<commit_before>/*
 * Serve HTTP requests from another HTTP/AJP server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "handler.hxx"
#include "request.hxx"
#include "request_forward.hxx"
#include "http_server.hxx"
#include "http_cache.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "cgi_address.hxx"
#include "global.h"
#include "cookie_client.hxx"
#include "uri-extract.h"
#include "strref_pool.hxx"
#include "strmap.hxx"
#include "http_response.hxx"
#include "istream-impl.h"
#include "lhttp_address.hxx"

gcc_pure
static const char *
GetCookieHost(const request &r)
{
    const TranslateResponse &t = *r.translate.response;
    if (t.cookie_host != nullptr)
        return t.cookie_host;

    const struct resource_address &address = *r.translate.address;
    return resource_address_host_and_port(&address);
}

static void
proxy_collect_cookies(request &request2, const struct strmap *headers)
{
    const struct resource_address &address = *request2.translate.address;

    if (headers == nullptr)
        return;

    auto r = headers->EqualRange("set-cookie2");
    if (r.first == r.second) {
        r = headers->EqualRange("set-cookie");
        if (r.first == r.second)
            return;
    }

    const char *host_and_port = GetCookieHost(request2);
    if (host_and_port == nullptr)
        return;

    const char *path = resource_address_uri_path(&address);
    if (path == nullptr)
        return;

    struct session *session = request_make_session(request2);
    if (session == nullptr)
        return;

    for (auto i = r.first; i != r.second; ++i)
        cookie_jar_set_cookie2(session->cookies, i->value,
                               host_and_port, path);

    session_put(session);
}

static void
proxy_response(http_status_t status, struct strmap *headers,
               struct istream *body, void *ctx)
{
    request &request2 = *(request *)ctx;

#ifndef NDEBUG
    const struct resource_address &address = *request2.translate.address;
    assert(address.type == RESOURCE_ADDRESS_HTTP ||
           address.type == RESOURCE_ADDRESS_LHTTP ||
           address.type == RESOURCE_ADDRESS_AJP ||
           address.type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(&address));
#endif

    proxy_collect_cookies(request2, headers);

    response_handler.InvokeResponse(&request2, status, headers, body);
}

static void
proxy_abort(GError *error, void *ctx)
{
    request &request2 = *(request *)ctx;

    response_handler.InvokeAbort(&request2, error);
}

static const struct http_response_handler proxy_response_handler = {
    .response = proxy_response,
    .abort = proxy_abort,
};

void
proxy_handler(request &request2)
{
    struct http_server_request *request = request2.request;
    const TranslateResponse &tr = *request2.translate.response;
    const struct resource_address *address = request2.translate.address;

    assert(address->type == RESOURCE_ADDRESS_HTTP ||
           address->type == RESOURCE_ADDRESS_LHTTP ||
           address->type == RESOURCE_ADDRESS_AJP ||
           address->type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(address));

    const char *host_and_port = nullptr, *uri_p = nullptr;
    if (address->type == RESOURCE_ADDRESS_HTTP ||
        address->type == RESOURCE_ADDRESS_AJP) {
        host_and_port = address->u.http->host_and_port;
        uri_p = address->u.http->path;
    } else if (address->type == RESOURCE_ADDRESS_LHTTP) {
        host_and_port = address->u.lhttp->host_and_port;
        uri_p = address->u.lhttp->uri;
    }

    struct forward_request forward;
    request_forward(forward, request2,
                    tr.request_header_forward,
                    host_and_port, uri_p,
                    address->type == RESOURCE_ADDRESS_HTTP ||
                    address->type == RESOURCE_ADDRESS_LHTTP);

    if (request2.translate.response->transparent &&
        (!strref_is_empty(&request2.uri.args) ||
         !strref_is_empty(&request2.uri.path_info)))
        address = resource_address_insert_args(*request->pool, address,
                                               request2.uri.args.data,
                                               request2.uri.args.length,
                                               request2.uri.path_info.data,
                                               request2.uri.path_info.length);

    if (!request2.processor_focus)
        /* forward query string */
        address = resource_address_insert_query_string_from(*request->pool,
                                                            address,
                                                            request->uri);

    if (resource_address_is_cgi_alike(address) &&
        address->u.cgi->uri == nullptr) {
        struct resource_address *copy = resource_address_dup(*request->pool,
                                                             address);
        struct cgi_address *cgi = resource_address_get_cgi(copy);

        /* pass the "real" request URI to the CGI (but without the
           "args", unless the request is "transparent") */
        if (request2.translate.response->transparent ||
            strref_is_empty(&request2.uri.args))
            cgi->uri = request->uri;
        else if (strref_is_empty(&request2.uri.query))
            cgi->uri = strref_dup(request->pool, &request2.uri.base);
        else
            cgi->uri = p_strncat(request->pool,
                                 request2.uri.base.data,
                                 request2.uri.base.length,
                                 "?", (size_t)1,
                                 request2.uri.query.data,
                                 request2.uri.query.length,
                                 nullptr);

        address = copy;
    }

#ifdef SPLICE
    if (forward.body != nullptr)
        forward.body = istream_pipe_new(request->pool, forward.body,
                                        global_pipe_stock);
#endif

    for (const auto &i : tr.request_headers)
        forward.headers->Add(i.key, i.value);

    http_cache_request(*global_http_cache, *request->pool,
                       session_id_low(request2.session_id),
                       forward.method, *address,
                       forward.headers, forward.body,
                       proxy_response_handler, &request2,
                       request2.async_ref);
}
<commit_msg>proxy_handler: move code to GetCookieURI()<commit_after>/*
 * Serve HTTP requests from another HTTP/AJP server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "handler.hxx"
#include "request.hxx"
#include "request_forward.hxx"
#include "http_server.hxx"
#include "http_cache.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "cgi_address.hxx"
#include "global.h"
#include "cookie_client.hxx"
#include "uri-extract.h"
#include "strref_pool.hxx"
#include "strmap.hxx"
#include "http_response.hxx"
#include "istream-impl.h"
#include "lhttp_address.hxx"

gcc_pure
static const char *
GetCookieHost(const request &r)
{
    const TranslateResponse &t = *r.translate.response;
    if (t.cookie_host != nullptr)
        return t.cookie_host;

    const struct resource_address &address = *r.translate.address;
    return resource_address_host_and_port(&address);
}

gcc_pure
static const char *
GetCookieURI(const request &r)
{
    const struct resource_address &address = *r.translate.address;
    return resource_address_uri_path(&address);
}

static void
proxy_collect_cookies(request &request2, const struct strmap *headers)
{
    if (headers == nullptr)
        return;

    auto r = headers->EqualRange("set-cookie2");
    if (r.first == r.second) {
        r = headers->EqualRange("set-cookie");
        if (r.first == r.second)
            return;
    }

    const char *host_and_port = GetCookieHost(request2);
    if (host_and_port == nullptr)
        return;

    const char *path = GetCookieURI(request2);
    if (path == nullptr)
        return;

    struct session *session = request_make_session(request2);
    if (session == nullptr)
        return;

    for (auto i = r.first; i != r.second; ++i)
        cookie_jar_set_cookie2(session->cookies, i->value,
                               host_and_port, path);

    session_put(session);
}

static void
proxy_response(http_status_t status, struct strmap *headers,
               struct istream *body, void *ctx)
{
    request &request2 = *(request *)ctx;

#ifndef NDEBUG
    const struct resource_address &address = *request2.translate.address;
    assert(address.type == RESOURCE_ADDRESS_HTTP ||
           address.type == RESOURCE_ADDRESS_LHTTP ||
           address.type == RESOURCE_ADDRESS_AJP ||
           address.type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(&address));
#endif

    proxy_collect_cookies(request2, headers);

    response_handler.InvokeResponse(&request2, status, headers, body);
}

static void
proxy_abort(GError *error, void *ctx)
{
    request &request2 = *(request *)ctx;

    response_handler.InvokeAbort(&request2, error);
}

static const struct http_response_handler proxy_response_handler = {
    .response = proxy_response,
    .abort = proxy_abort,
};

void
proxy_handler(request &request2)
{
    struct http_server_request *request = request2.request;
    const TranslateResponse &tr = *request2.translate.response;
    const struct resource_address *address = request2.translate.address;

    assert(address->type == RESOURCE_ADDRESS_HTTP ||
           address->type == RESOURCE_ADDRESS_LHTTP ||
           address->type == RESOURCE_ADDRESS_AJP ||
           address->type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(address));

    const char *host_and_port = nullptr, *uri_p = nullptr;
    if (address->type == RESOURCE_ADDRESS_HTTP ||
        address->type == RESOURCE_ADDRESS_AJP) {
        host_and_port = address->u.http->host_and_port;
        uri_p = address->u.http->path;
    } else if (address->type == RESOURCE_ADDRESS_LHTTP) {
        host_and_port = address->u.lhttp->host_and_port;
        uri_p = address->u.lhttp->uri;
    }

    struct forward_request forward;
    request_forward(forward, request2,
                    tr.request_header_forward,
                    host_and_port, uri_p,
                    address->type == RESOURCE_ADDRESS_HTTP ||
                    address->type == RESOURCE_ADDRESS_LHTTP);

    if (request2.translate.response->transparent &&
        (!strref_is_empty(&request2.uri.args) ||
         !strref_is_empty(&request2.uri.path_info)))
        address = resource_address_insert_args(*request->pool, address,
                                               request2.uri.args.data,
                                               request2.uri.args.length,
                                               request2.uri.path_info.data,
                                               request2.uri.path_info.length);

    if (!request2.processor_focus)
        /* forward query string */
        address = resource_address_insert_query_string_from(*request->pool,
                                                            address,
                                                            request->uri);

    if (resource_address_is_cgi_alike(address) &&
        address->u.cgi->uri == nullptr) {
        struct resource_address *copy = resource_address_dup(*request->pool,
                                                             address);
        struct cgi_address *cgi = resource_address_get_cgi(copy);

        /* pass the "real" request URI to the CGI (but without the
           "args", unless the request is "transparent") */
        if (request2.translate.response->transparent ||
            strref_is_empty(&request2.uri.args))
            cgi->uri = request->uri;
        else if (strref_is_empty(&request2.uri.query))
            cgi->uri = strref_dup(request->pool, &request2.uri.base);
        else
            cgi->uri = p_strncat(request->pool,
                                 request2.uri.base.data,
                                 request2.uri.base.length,
                                 "?", (size_t)1,
                                 request2.uri.query.data,
                                 request2.uri.query.length,
                                 nullptr);

        address = copy;
    }

#ifdef SPLICE
    if (forward.body != nullptr)
        forward.body = istream_pipe_new(request->pool, forward.body,
                                        global_pipe_stock);
#endif

    for (const auto &i : tr.request_headers)
        forward.headers->Add(i.key, i.value);

    http_cache_request(*global_http_cache, *request->pool,
                       session_id_low(request2.session_id),
                       forward.method, *address,
                       forward.headers, forward.body,
                       proxy_response_handler, &request2,
                       request2.async_ref);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Nikhil Marathe <nsm.nikhil@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "qhttpresponse.h"

#include "qhttpserver.h"
#include "qhttpconnection.h"
#include "HttpStatusCodes.h"

QHttpResponse::QHttpResponse(QHttpConnection *connection)
    : QObject(connection)
    , m_connection(connection)
    , m_headerWritten(false)
    , m_sentConnectionHeader(false)
    , m_sentContentLengthHeader(false)
    , m_sentTransferEncodingHeader(false)
    , m_keepAlive(true)
    , m_last(false)
    , m_useChunkedEncoding(false)
	, m_isDone(false)
{
}

QHttpResponse::~QHttpResponse()
{
}

void QHttpResponse::setHeader(const QString &field, const QString &value)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    m_headers[field] = value;
}

void QHttpResponse::writeHeaders()
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

	QHashIterator<QString, QString> headerIterator(m_headers);

	while( headerIterator.hasNext() )
    {
		headerIterator.next();
		const QString& name = headerIterator.key();
		const QString& value = headerIterator.value();

        if( name.compare("connection", Qt::CaseInsensitive) == 0 )
        {
            m_sentConnectionHeader = true;
            if( value == "close" )
                m_last = true;
            else
                m_keepAlive = true;
        }
        else if( name.compare("transfer-encoding", Qt::CaseInsensitive) == 0 )
        {
            m_sentTransferEncodingHeader = true;
            if( value == "chunked" )
                m_useChunkedEncoding = true;
        }
        else if( name.compare("content-length", Qt::CaseInsensitive) == 0 )
        {
            m_sentContentLengthHeader = true;
        }
        //TODO: Expect case

        m_connection->writeHeader(name.toAscii(), value.toAscii());
    }

    if( !m_sentConnectionHeader )
    {
        if( m_keepAlive &&
                ( m_sentContentLengthHeader || m_useChunkedEncoding ) )
        {
            m_connection->writeHeader("Connection", "keep-alive");
        }
        else
        {
            m_last = true;
            m_connection->writeHeader("Connection", "close");
       }
    }

    if( !m_sentContentLengthHeader && !m_sentTransferEncodingHeader )
    {
        if( m_useChunkedEncoding )
            m_connection->writeHeader("Transfer-Encoding", "chunked");
        else
            m_last = true;
    }
}

bool QHttpResponse::writeHead(int status)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    if( m_headerWritten )
	{
		return false;
	}

	const QHash<int, QString>& codes = HttpStatusCodes::codes();

	if( ! codes.contains(status) )
	{
		qDebug() << "Invalid status code"<<status;
		return false;
	}
    m_connection->write(QString("HTTP/1.1 %1 %2\r\n").arg(status).arg(codes.value(status)).toAscii());

    writeHeaders();

    m_connection->write("\r\n");
    m_headerWritten = true;
	return true;
}

bool QHttpResponse::write(const QByteArray &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    if( !m_headerWritten )
    {
        return false;
    }

	return m_connection->write(data);
}

bool QHttpResponse::write(const QString &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    return m_connection->write(data.toUtf8());
}

void QHttpResponse::end(const QString &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    write(data);

	m_isDone = true;
    emit done();

    deleteLater();
    // TODO: end connection and delete ourselves
}
<commit_msg>Fixes compilation on release mode.<commit_after>/*
 * Copyright 2011 Nikhil Marathe <nsm.nikhil@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "qhttpresponse.h"

#include <QDebug>

#include "qhttpserver.h"
#include "qhttpconnection.h"
#include "HttpStatusCodes.h"

QHttpResponse::QHttpResponse(QHttpConnection *connection)
    : QObject(connection)
    , m_connection(connection)
    , m_headerWritten(false)
    , m_sentConnectionHeader(false)
    , m_sentContentLengthHeader(false)
    , m_sentTransferEncodingHeader(false)
    , m_keepAlive(true)
    , m_last(false)
    , m_useChunkedEncoding(false)
	, m_isDone(false)
{
}

QHttpResponse::~QHttpResponse()
{
}

void QHttpResponse::setHeader(const QString &field, const QString &value)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    m_headers[field] = value;
}

void QHttpResponse::writeHeaders()
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

	QHashIterator<QString, QString> headerIterator(m_headers);

	while( headerIterator.hasNext() )
    {
		headerIterator.next();
		const QString& name = headerIterator.key();
		const QString& value = headerIterator.value();

        if( name.compare("connection", Qt::CaseInsensitive) == 0 )
        {
            m_sentConnectionHeader = true;
            if( value == "close" )
                m_last = true;
            else
                m_keepAlive = true;
        }
        else if( name.compare("transfer-encoding", Qt::CaseInsensitive) == 0 )
        {
            m_sentTransferEncodingHeader = true;
            if( value == "chunked" )
                m_useChunkedEncoding = true;
        }
        else if( name.compare("content-length", Qt::CaseInsensitive) == 0 )
        {
            m_sentContentLengthHeader = true;
        }
        //TODO: Expect case

        m_connection->writeHeader(name.toAscii(), value.toAscii());
    }

    if( !m_sentConnectionHeader )
    {
        if( m_keepAlive &&
                ( m_sentContentLengthHeader || m_useChunkedEncoding ) )
        {
            m_connection->writeHeader("Connection", "keep-alive");
        }
        else
        {
            m_last = true;
            m_connection->writeHeader("Connection", "close");
       }
    }

    if( !m_sentContentLengthHeader && !m_sentTransferEncodingHeader )
    {
        if( m_useChunkedEncoding )
            m_connection->writeHeader("Transfer-Encoding", "chunked");
        else
            m_last = true;
    }
}

bool QHttpResponse::writeHead(int status)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    if( m_headerWritten )
	{
		return false;
	}

	const QHash<int, QString>& codes = HttpStatusCodes::codes();

	if( ! codes.contains(status) )
	{
		qDebug() << "Invalid status code"<<status;
		return false;
	}
    m_connection->write(QString("HTTP/1.1 %1 %2\r\n").arg(status).arg(codes.value(status)).toAscii());

    writeHeaders();

    m_connection->write("\r\n");
    m_headerWritten = true;
	return true;
}

bool QHttpResponse::write(const QByteArray &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    if( !m_headerWritten )
    {
        return false;
    }

	return m_connection->write(data);
}

bool QHttpResponse::write(const QString &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    return m_connection->write(data.toUtf8());
}

void QHttpResponse::end(const QString &data)
{
	Q_ASSERT(! m_isDone);
	Q_ASSERT(m_connection);

    write(data);

	m_isDone = true;
    emit done();

    deleteLater();
    // TODO: end connection and delete ourselves
}
<|endoftext|>


<commit_before>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookpage.h"
#include "sendcoinsdialog.h"
#include "optionsdialog.h"
#include "aboutdialog.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "guiutil.h"
#include "editaddressdialog.h"
#include "optionsmodel.h"
#include "transactiondescdialog.h"
#include "addresstablemodel.h"
#include "transactionview.h"
#include "overviewpage.h"

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QIcon>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QLocale>
#include <QMessageBox>
#include <QProgressBar>
#include <QStackedWidget>
#include <QDateTime>

#include <QDebug>

#include <iostream>

BitcoinGUI::BitcoinGUI(QWidget *parent):
    QMainWindow(parent),
    clientModel(0),
    walletModel(0),
    trayIcon(0)
{
    resize(850, 550);
    setWindowTitle(tr("Bitcoin Wallet"));
    setWindowIcon(QIcon(":icons/bitcoin"));

    createActions();

    // Menus
    QMenu *file = menuBar()->addMenu("&File");
    file->addAction(sendCoinsAction);
    file->addAction(receiveCoinsAction);
    file->addSeparator();
    file->addAction(quitAction);

    QMenu *settings = menuBar()->addMenu("&Settings");
    settings->addAction(optionsAction);

    QMenu *help = menuBar()->addMenu("&Help");
    help->addAction(aboutAction);

    // Toolbar
    QToolBar *toolbar = addToolBar("Main toolbar");
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar->addAction(overviewAction);
    toolbar->addAction(sendCoinsAction);
    toolbar->addAction(receiveCoinsAction);
    toolbar->addAction(historyAction);
    toolbar->addAction(addressBookAction);

    QToolBar *toolbar2 = addToolBar("Transactions toolbar");
    toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar2->addAction(exportAction);

    // Overview page
    overviewPage = new OverviewPage();
    QVBoxLayout *vbox = new QVBoxLayout();

    transactionView = new TransactionView(this);
    connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), transactionView, SLOT(transactionDetails()));
    vbox->addWidget(transactionView);

    transactionsPage = new QWidget(this);
    transactionsPage->setLayout(vbox);

    addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab);

    receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab);

    sendCoinsPage = new SendCoinsDialog(this);

    centralWidget = new QStackedWidget(this);
    centralWidget->addWidget(overviewPage);
    centralWidget->addWidget(transactionsPage);
    centralWidget->addWidget(addressBookPage);
    centralWidget->addWidget(receiveCoinsPage);
    centralWidget->addWidget(sendCoinsPage);
    setCentralWidget(centralWidget);

    // Create status bar
    statusBar();

    labelConnections = new QLabel();
    labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelConnections->setMinimumWidth(150);
    labelConnections->setMaximumWidth(150);
    labelConnections->setToolTip(tr("Number of connections to other clients"));

    labelBlocks = new QLabel();
    labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelBlocks->setMinimumWidth(150);
    labelBlocks->setMaximumWidth(150);
    labelBlocks->setToolTip(tr("Number of blocks in the block chain"));

    // Progress bar for blocks download
    progressBarLabel = new QLabel(tr("Synchronizing with network..."));
    progressBarLabel->setVisible(false);
    progressBar = new QProgressBar();
    progressBar->setToolTip(tr("Block chain synchronization in progress"));
    progressBar->setVisible(false);

    statusBar()->addWidget(progressBarLabel);
    statusBar()->addWidget(progressBar);
    statusBar()->addPermanentWidget(labelConnections);
    statusBar()->addPermanentWidget(labelBlocks);

    createTrayIcon();

    gotoOverviewPage();
}

void BitcoinGUI::createActions()
{
    QActionGroup *tabGroup = new QActionGroup(this);

    overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
    overviewAction->setCheckable(true);
    tabGroup->addAction(overviewAction);

    historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
    historyAction->setCheckable(true);
    tabGroup->addAction(historyAction);

    addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
    addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels"));
    addressBookAction->setCheckable(true);
    tabGroup->addAction(addressBookAction);

    receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
    receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments"));
    receiveCoinsAction->setCheckable(true);
    tabGroup->addAction(receiveCoinsAction);

    sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
    sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address"));
    sendCoinsAction->setCheckable(true);
    tabGroup->addAction(sendCoinsAction);

    connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
    connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
    connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
    connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
    connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));

    quitAction = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
    quitAction->setToolTip(tr("Quit application"));
    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
    aboutAction->setToolTip(tr("Show information about Bitcoin"));
    optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
    optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
    openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
    openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
    exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
    exportAction->setToolTip(tr("Export data in current view to a file"));

    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
    connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(show()));
}

void BitcoinGUI::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    if(clientModel->isTestNet())
    {
        QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
        setWindowTitle(title_testnet);
        setWindowIcon(QIcon(":icons/bitcoin_testnet"));
        if(trayIcon)
        {
            trayIcon->setToolTip(title_testnet);
            trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
        }
    }

    // Keep up to date with client
    setNumConnections(clientModel->getNumConnections());
    connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));

    setNumBlocks(clientModel->getNumBlocks());
    connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));

    // Report errors from network/worker thread
    connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
}

void BitcoinGUI::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Report errors from wallet thread
    connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));

    // Put transaction list in tabs
    transactionView->setModel(walletModel);

    overviewPage->setModel(walletModel);
    addressBookPage->setModel(walletModel->getAddressTableModel());
    receiveCoinsPage->setModel(walletModel->getAddressTableModel());
    sendCoinsPage->setModel(walletModel);

    // Balloon popup for new transaction
    connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
            this, SLOT(incomingTransaction(const QModelIndex &, int, int)));
}

void BitcoinGUI::createTrayIcon()
{
    QMenu *trayIconMenu = new QMenu(this);
    trayIconMenu->addAction(openBitcoinAction);
    trayIconMenu->addAction(sendCoinsAction);
    trayIconMenu->addAction(optionsAction);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quitAction);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);
    trayIcon->setToolTip("Bitcoin client");
    trayIcon->setIcon(QIcon(":/icons/toolbar"));
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
    trayIcon->show();
}

void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
    if(reason == QSystemTrayIcon::DoubleClick)
    {
        // Doubleclick on system tray icon triggers "open bitcoin"
        openBitcoinAction->trigger();
    }
}

void BitcoinGUI::optionsClicked()
{
    OptionsDialog dlg;
    dlg.setModel(clientModel->getOptionsModel());
    dlg.exec();
}

void BitcoinGUI::aboutClicked()
{
    AboutDialog dlg;
    dlg.setModel(clientModel);
    dlg.exec();
}

void BitcoinGUI::setNumConnections(int count)
{
    QString icon;
    switch(count)
    {
    case 0: icon = ":/icons/connect_0"; break;
    case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
    case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
    case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
    default: icon = ":/icons/connect_4"; break;
    }
    labelConnections->setTextFormat(Qt::RichText);
    labelConnections->setText(" " + tr("%n connection(s)", "", count));
}

void BitcoinGUI::setNumBlocks(int count)
{
    int total = clientModel->getTotalBlocksEstimate();
    if(count < total)
    {
        progressBarLabel->setVisible(true);
        progressBar->setVisible(true);
        progressBar->setMaximum(total);
        progressBar->setValue(count);
    }
    else
    {
        progressBarLabel->setVisible(false);
        progressBar->setVisible(false);
    }

    QDateTime now = QDateTime::currentDateTime();
    QDateTime lastBlockDate = clientModel->getLastBlockDate();
    int secs = lastBlockDate.secsTo(now);
    QString text;
    QString icon = ":/icons/notsynced";

    // "Up to date" icon, and outdated icon
    if(secs < 30*60)
    {
        text = "Up to date";
        icon = ":/icons/synced";
    }
    else if(secs < 60*60)
    {
        text = tr("%n minute(s) ago","",secs/60);
    }
    else if(secs < 24*60*60)
    {
        text = tr("%n hour(s) ago","",secs/(60*60));
    }
    else
    {
        text = tr("%n day(s) ago","",secs/(60*60*24));
    }

    labelBlocks->setText(" " + text);
    labelBlocks->setToolTip(tr("Downloaded %n block(s) of transaction history. Last block was generated %1.", "", count)
                            .arg(QLocale::system().toString(lastBlockDate)));
}

void BitcoinGUI::error(const QString &title, const QString &message)
{
    // Report errors from network/worker thread
    if(trayIcon->supportsMessages())
    {
        // Show as "balloon" message if possible
        trayIcon->showMessage(title, message, QSystemTrayIcon::Critical);
    }
    else
    {
        // Fall back to old fashioned popup dialog if not
        QMessageBox::critical(this, title,
            message,
            QMessageBox::Ok, QMessageBox::Ok);
    }
}

void BitcoinGUI::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::WindowStateChange)
    {
        if(clientModel->getOptionsModel()->getMinimizeToTray())
        {
            if (isMinimized())
            {
                hide();
                e->ignore();
            }
            else
            {
                e->accept();
            }
        }
    }
    QMainWindow::changeEvent(e);
}

void BitcoinGUI::closeEvent(QCloseEvent *event)
{
    if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
       !clientModel->getOptionsModel()->getMinimizeOnClose())
    {
        qApp->quit();
    }
    QMainWindow::closeEvent(event);
}

void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
{
    QString strMessage =
        tr("This transaction is over the size limit.  You can still send it for a fee of %1, "
          "which goes to the nodes that process your transaction and helps to support the network.  "
          "Do you want to pay the fee?").arg(GUIUtil::formatMoney(nFeeRequired));
    QMessageBox::StandardButton retval = QMessageBox::question(
          this, tr("Sending..."), strMessage,
          QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
    *payFee = (retval == QMessageBox::Yes);
}

void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end)
{
    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
                    .data(Qt::EditRole).toULongLong();
    if(amount>0 && !clientModel->inInitialBlockDownload())
    {
        // On incoming transaction, make an info balloon
        // Unless the initial block download is in progress, to prevent balloon-spam
        QString date = ttm->index(start, TransactionTableModel::Date, parent)
                        .data().toString();
        QString type = ttm->index(start, TransactionTableModel::Type, parent)
                        .data().toString();
        QString address = ttm->index(start, TransactionTableModel::ToAddress, parent)
                        .data().toString();

        trayIcon->showMessage(tr("Incoming transaction"),
                              tr("Date: ") + date + "\n" +
                              tr("Amount: ") + GUIUtil::formatMoney(amount, true) + "\n" +
                              tr("Type: ") + type + "\n" +
                              tr("Address: ") + address + "\n",
                              QSystemTrayIcon::Information);
    }
}

void BitcoinGUI::gotoOverviewPage()
{
    overviewAction->setChecked(true);
    centralWidget->setCurrentWidget(overviewPage);

    exportAction->setEnabled(false);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
}

void BitcoinGUI::gotoHistoryPage()
{
    historyAction->setChecked(true);
    centralWidget->setCurrentWidget(transactionsPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
}

void BitcoinGUI::gotoAddressBookPage()
{
    addressBookAction->setChecked(true);
    centralWidget->setCurrentWidget(addressBookPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
}

void BitcoinGUI::gotoReceiveCoinsPage()
{
    receiveCoinsAction->setChecked(true);
    centralWidget->setCurrentWidget(receiveCoinsPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
}

void BitcoinGUI::gotoSendCoinsPage()
{
    sendCoinsAction->setChecked(true);
    sendCoinsPage->clear();
    centralWidget->setCurrentWidget(sendCoinsPage);

    exportAction->setEnabled(false);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
}

<commit_msg>also show balloon on sent transaction, to notify when coins sent<commit_after>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookpage.h"
#include "sendcoinsdialog.h"
#include "optionsdialog.h"
#include "aboutdialog.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "guiutil.h"
#include "editaddressdialog.h"
#include "optionsmodel.h"
#include "transactiondescdialog.h"
#include "addresstablemodel.h"
#include "transactionview.h"
#include "overviewpage.h"

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QIcon>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QLocale>
#include <QMessageBox>
#include <QProgressBar>
#include <QStackedWidget>
#include <QDateTime>

#include <QDebug>

#include <iostream>

BitcoinGUI::BitcoinGUI(QWidget *parent):
    QMainWindow(parent),
    clientModel(0),
    walletModel(0),
    trayIcon(0)
{
    resize(850, 550);
    setWindowTitle(tr("Bitcoin Wallet"));
    setWindowIcon(QIcon(":icons/bitcoin"));

    createActions();

    // Menus
    QMenu *file = menuBar()->addMenu("&File");
    file->addAction(sendCoinsAction);
    file->addAction(receiveCoinsAction);
    file->addSeparator();
    file->addAction(quitAction);

    QMenu *settings = menuBar()->addMenu("&Settings");
    settings->addAction(optionsAction);

    QMenu *help = menuBar()->addMenu("&Help");
    help->addAction(aboutAction);

    // Toolbar
    QToolBar *toolbar = addToolBar("Main toolbar");
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar->addAction(overviewAction);
    toolbar->addAction(sendCoinsAction);
    toolbar->addAction(receiveCoinsAction);
    toolbar->addAction(historyAction);
    toolbar->addAction(addressBookAction);

    QToolBar *toolbar2 = addToolBar("Transactions toolbar");
    toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar2->addAction(exportAction);

    // Overview page
    overviewPage = new OverviewPage();
    QVBoxLayout *vbox = new QVBoxLayout();

    transactionView = new TransactionView(this);
    connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), transactionView, SLOT(transactionDetails()));
    vbox->addWidget(transactionView);

    transactionsPage = new QWidget(this);
    transactionsPage->setLayout(vbox);

    addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab);

    receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab);

    sendCoinsPage = new SendCoinsDialog(this);

    centralWidget = new QStackedWidget(this);
    centralWidget->addWidget(overviewPage);
    centralWidget->addWidget(transactionsPage);
    centralWidget->addWidget(addressBookPage);
    centralWidget->addWidget(receiveCoinsPage);
    centralWidget->addWidget(sendCoinsPage);
    setCentralWidget(centralWidget);

    // Create status bar
    statusBar();

    labelConnections = new QLabel();
    labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelConnections->setMinimumWidth(150);
    labelConnections->setMaximumWidth(150);
    labelConnections->setToolTip(tr("Number of connections to other clients"));

    labelBlocks = new QLabel();
    labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelBlocks->setMinimumWidth(150);
    labelBlocks->setMaximumWidth(150);
    labelBlocks->setToolTip(tr("Number of blocks in the block chain"));

    // Progress bar for blocks download
    progressBarLabel = new QLabel(tr("Synchronizing with network..."));
    progressBarLabel->setVisible(false);
    progressBar = new QProgressBar();
    progressBar->setToolTip(tr("Block chain synchronization in progress"));
    progressBar->setVisible(false);

    statusBar()->addWidget(progressBarLabel);
    statusBar()->addWidget(progressBar);
    statusBar()->addPermanentWidget(labelConnections);
    statusBar()->addPermanentWidget(labelBlocks);

    createTrayIcon();

    gotoOverviewPage();
}

void BitcoinGUI::createActions()
{
    QActionGroup *tabGroup = new QActionGroup(this);

    overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
    overviewAction->setCheckable(true);
    tabGroup->addAction(overviewAction);

    historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
    historyAction->setCheckable(true);
    tabGroup->addAction(historyAction);

    addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
    addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels"));
    addressBookAction->setCheckable(true);
    tabGroup->addAction(addressBookAction);

    receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
    receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments"));
    receiveCoinsAction->setCheckable(true);
    tabGroup->addAction(receiveCoinsAction);

    sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
    sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address"));
    sendCoinsAction->setCheckable(true);
    tabGroup->addAction(sendCoinsAction);

    connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
    connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
    connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
    connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
    connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));

    quitAction = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
    quitAction->setToolTip(tr("Quit application"));
    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
    aboutAction->setToolTip(tr("Show information about Bitcoin"));
    optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
    optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
    openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
    openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
    exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
    exportAction->setToolTip(tr("Export data in current view to a file"));

    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
    connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(show()));
}

void BitcoinGUI::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    if(clientModel->isTestNet())
    {
        QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
        setWindowTitle(title_testnet);
        setWindowIcon(QIcon(":icons/bitcoin_testnet"));
        if(trayIcon)
        {
            trayIcon->setToolTip(title_testnet);
            trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
        }
    }

    // Keep up to date with client
    setNumConnections(clientModel->getNumConnections());
    connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));

    setNumBlocks(clientModel->getNumBlocks());
    connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));

    // Report errors from network/worker thread
    connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
}

void BitcoinGUI::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Report errors from wallet thread
    connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));

    // Put transaction list in tabs
    transactionView->setModel(walletModel);

    overviewPage->setModel(walletModel);
    addressBookPage->setModel(walletModel->getAddressTableModel());
    receiveCoinsPage->setModel(walletModel->getAddressTableModel());
    sendCoinsPage->setModel(walletModel);

    // Balloon popup for new transaction
    connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
            this, SLOT(incomingTransaction(const QModelIndex &, int, int)));
}

void BitcoinGUI::createTrayIcon()
{
    QMenu *trayIconMenu = new QMenu(this);
    trayIconMenu->addAction(openBitcoinAction);
    trayIconMenu->addAction(sendCoinsAction);
    trayIconMenu->addAction(optionsAction);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quitAction);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);
    trayIcon->setToolTip("Bitcoin client");
    trayIcon->setIcon(QIcon(":/icons/toolbar"));
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
    trayIcon->show();
}

void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
    if(reason == QSystemTrayIcon::DoubleClick)
    {
        // Doubleclick on system tray icon triggers "open bitcoin"
        openBitcoinAction->trigger();
    }
}

void BitcoinGUI::optionsClicked()
{
    OptionsDialog dlg;
    dlg.setModel(clientModel->getOptionsModel());
    dlg.exec();
}

void BitcoinGUI::aboutClicked()
{
    AboutDialog dlg;
    dlg.setModel(clientModel);
    dlg.exec();
}

void BitcoinGUI::setNumConnections(int count)
{
    QString icon;
    switch(count)
    {
    case 0: icon = ":/icons/connect_0"; break;
    case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
    case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
    case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
    default: icon = ":/icons/connect_4"; break;
    }
    labelConnections->setTextFormat(Qt::RichText);
    labelConnections->setText(" " + tr("%n connection(s)", "", count));
}

void BitcoinGUI::setNumBlocks(int count)
{
    int total = clientModel->getTotalBlocksEstimate();
    if(count < total)
    {
        progressBarLabel->setVisible(true);
        progressBar->setVisible(true);
        progressBar->setMaximum(total);
        progressBar->setValue(count);
    }
    else
    {
        progressBarLabel->setVisible(false);
        progressBar->setVisible(false);
    }

    QDateTime now = QDateTime::currentDateTime();
    QDateTime lastBlockDate = clientModel->getLastBlockDate();
    int secs = lastBlockDate.secsTo(now);
    QString text;
    QString icon = ":/icons/notsynced";

    // "Up to date" icon, and outdated icon
    if(secs < 30*60)
    {
        text = "Up to date";
        icon = ":/icons/synced";
    }
    else if(secs < 60*60)
    {
        text = tr("%n minute(s) ago","",secs/60);
    }
    else if(secs < 24*60*60)
    {
        text = tr("%n hour(s) ago","",secs/(60*60));
    }
    else
    {
        text = tr("%n day(s) ago","",secs/(60*60*24));
    }

    labelBlocks->setText(" " + text);
    labelBlocks->setToolTip(tr("Downloaded %n block(s) of transaction history. Last block was generated %1.", "", count)
                            .arg(QLocale::system().toString(lastBlockDate)));
}

void BitcoinGUI::error(const QString &title, const QString &message)
{
    // Report errors from network/worker thread
    if(trayIcon->supportsMessages())
    {
        // Show as "balloon" message if possible
        trayIcon->showMessage(title, message, QSystemTrayIcon::Critical);
    }
    else
    {
        // Fall back to old fashioned popup dialog if not
        QMessageBox::critical(this, title,
            message,
            QMessageBox::Ok, QMessageBox::Ok);
    }
}

void BitcoinGUI::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::WindowStateChange)
    {
        if(clientModel->getOptionsModel()->getMinimizeToTray())
        {
            if (isMinimized())
            {
                hide();
                e->ignore();
            }
            else
            {
                e->accept();
            }
        }
    }
    QMainWindow::changeEvent(e);
}

void BitcoinGUI::closeEvent(QCloseEvent *event)
{
    if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
       !clientModel->getOptionsModel()->getMinimizeOnClose())
    {
        qApp->quit();
    }
    QMainWindow::closeEvent(event);
}

void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
{
    QString strMessage =
        tr("This transaction is over the size limit.  You can still send it for a fee of %1, "
          "which goes to the nodes that process your transaction and helps to support the network.  "
          "Do you want to pay the fee?").arg(GUIUtil::formatMoney(nFeeRequired));
    QMessageBox::StandardButton retval = QMessageBox::question(
          this, tr("Sending..."), strMessage,
          QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
    *payFee = (retval == QMessageBox::Yes);
}

void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end)
{
    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
                    .data(Qt::EditRole).toULongLong();
    if(!clientModel->inInitialBlockDownload())
    {
        // On incoming transaction, make an info balloon
        // Unless the initial block download is in progress, to prevent balloon-spam
        QString date = ttm->index(start, TransactionTableModel::Date, parent)
                        .data().toString();
        QString type = ttm->index(start, TransactionTableModel::Type, parent)
                        .data().toString();
        QString address = ttm->index(start, TransactionTableModel::ToAddress, parent)
                        .data().toString();

        trayIcon->showMessage((amount)<0 ? tr("Sent transaction") :
                                           tr("Incoming transaction"),
                              tr("Date: ") + date + "\n" +
                              tr("Amount: ") + GUIUtil::formatMoney(amount, true) + "\n" +
                              tr("Type: ") + type + "\n" +
                              tr("Address: ") + address + "\n",
                              QSystemTrayIcon::Information);
    }
}

void BitcoinGUI::gotoOverviewPage()
{
    overviewAction->setChecked(true);
    centralWidget->setCurrentWidget(overviewPage);

    exportAction->setEnabled(false);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
}

void BitcoinGUI::gotoHistoryPage()
{
    historyAction->setChecked(true);
    centralWidget->setCurrentWidget(transactionsPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
}

void BitcoinGUI::gotoAddressBookPage()
{
    addressBookAction->setChecked(true);
    centralWidget->setCurrentWidget(addressBookPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
}

void BitcoinGUI::gotoReceiveCoinsPage()
{
    receiveCoinsAction->setChecked(true);
    centralWidget->setCurrentWidget(receiveCoinsPage);

    exportAction->setEnabled(true);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
    connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
}

void BitcoinGUI::gotoSendCoinsPage()
{
    sendCoinsAction->setChecked(true);
    sendCoinsPage->clear();
    centralWidget->setCurrentWidget(sendCoinsPage);

    exportAction->setEnabled(false);
    disconnect(exportAction, SIGNAL(triggered()), 0, 0);
}

<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "miningpage.h"
#include "ui_miningpage.h"

#include "clientmodel.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "optionsmodel.h"
#include "transactiontablemodel.h"
#include "transactionfilterproxy.h"
#include "guiutil.h"
#include "guiconstants.h"

#include <QAbstractItemDelegate>
#include <QPainter>

extern int nCurrentNFactor;
extern int nBestHeight;
extern CWallet* pwalletMain;
extern void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
extern bool SoftSetBoolArg(const std::string& strArg, bool fValue);

class MPExecutor : public QThread
{
     Q_OBJECT

  public:
    void setThreadRunning(int state)
    {
        threadRunning = state;
    }

    void cleanup()
    {
        threadRunning = 0;
        exit();
    }

  public slots:
     void run()
     {
         while(threadRunning != 0)
         {
             QString result = "Current NFactor: " + QString::number(nCurrentNFactor+1) +
                 "\nCurrent Block Height: " + QString::number(nBestHeight);
             emit resultReady(result);
             msleep(800);
         }
     }

  signals:
     void resultReady(const QString &result);

  private:
     int threadRunning;
};
#include "miningpage.moc"

MiningPage::MiningPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MiningPage),
    clientModel(0),
    walletModel(0)
{
    ui->setupUi(this);
    mpe = new MPExecutor();
    connect(mpe, SIGNAL(resultReady(QString)), this, SLOT(refreshMiningData(QString)));
}

MiningPage::~MiningPage()
{
    mpe->cleanup();
    mpe->wait(1000);
    delete ui;
    delete mpe;
}

void MiningPage::setClientModel(ClientModel *model)
{
    this->clientModel = model;
}

void MiningPage::setWalletModel(WalletModel *model)
{
    this->walletModel = model;
}

void MiningPage::startMining()
{
    if (pwalletMain)
    {
        bool status = true;
        SoftSetBoolArg("-gen", status);
        GenerateBitcoins(status, pwalletMain);

        QPixmap image(":/images/mining_active");
        ui->miningStatus->setPixmap(image);
        ui->miningStatus->repaint();
        ui->miningStart->setEnabled(false);
        ui->miningStop->setEnabled(true);

        ui->miningData->setText("Aptcoin Miner\nMining is active.");
        mpe->setThreadRunning(1);
        mpe->start();
    }
    else
    {
        QMessageBox::information(NULL, "Mining Status Error", "Failed to start the internal miner.  Possible wallet error detected.");
    }
}

void MiningPage::stopMining()
{
    if (pwalletMain)
    {
        bool status = false;
        SoftSetBoolArg("-gen", status);
        GenerateBitcoins(status, pwalletMain);

        QPixmap image(":/images/mining_inactive");
        ui->miningStatus->setPixmap(image);
        ui->miningStatus->repaint();
        ui->miningStart->setEnabled(true);
        ui->miningStop->setEnabled(false);

        ui->miningData->setText("Aptcoin Miner\nMining is not active.");
        mpe->setThreadRunning(0);
        ui->miningInfo->setText("");
    }
    else
    {
        QMessageBox::information(NULL, "Mining Status Error", "Failed to stop the internal miner.  Possible wallet error detected.");
    }
}

void MiningPage::refreshMiningData(const QString& data)
{
    ui->miningInfo->setText(data);
}
<commit_msg>- display the current hashrate in khash/s on the mining page<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "miningpage.h"
#include "ui_miningpage.h"

#include "clientmodel.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "optionsmodel.h"
#include "transactiontablemodel.h"
#include "transactionfilterproxy.h"
#include "guiutil.h"
#include "guiconstants.h"

#include <QAbstractItemDelegate>
#include <QPainter>

extern int nCurrentNFactor;
extern int nBestHeight;
extern double dHashesPerSec;
extern CWallet* pwalletMain;
extern void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
extern bool SoftSetBoolArg(const std::string& strArg, bool fValue);

class MPExecutor : public QThread
{
     Q_OBJECT

  public:
    void setThreadRunning(int state)
    {
        threadRunning = state;
    }

    void cleanup()
    {
        threadRunning = 0;
        exit();
    }

  public slots:
     void run()
     {
         while(threadRunning != 0)
         {
             QString result = "Current NFactor: " + QString::number(nCurrentNFactor+1) +
                 "\nCurrent Block Height: " + QString::number(nBestHeight) +
                 "\nCurrent Hashrate (khash/s): " + QString::number(dHashesPerSec/1000.0);
             emit resultReady(result);
             msleep(800);
         }
     }

  signals:
     void resultReady(const QString &result);

  private:
     int threadRunning;
};
#include "miningpage.moc"

MiningPage::MiningPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MiningPage),
    clientModel(0),
    walletModel(0)
{
    ui->setupUi(this);
    mpe = new MPExecutor();
    connect(mpe, SIGNAL(resultReady(QString)), this, SLOT(refreshMiningData(QString)));
}

MiningPage::~MiningPage()
{
    mpe->cleanup();
    mpe->wait(1000);
    delete ui;
    delete mpe;
}

void MiningPage::setClientModel(ClientModel *model)
{
    this->clientModel = model;
}

void MiningPage::setWalletModel(WalletModel *model)
{
    this->walletModel = model;
}

void MiningPage::startMining()
{
    if (pwalletMain)
    {
        bool status = true;
        SoftSetBoolArg("-gen", status);
        GenerateBitcoins(status, pwalletMain);

        QPixmap image(":/images/mining_active");
        ui->miningStatus->setPixmap(image);
        ui->miningStatus->repaint();
        ui->miningStart->setEnabled(false);
        ui->miningStop->setEnabled(true);

        ui->miningData->setText("Aptcoin Miner\nMining is active.");
        mpe->setThreadRunning(1);
        mpe->start();
    }
    else
    {
        QMessageBox::information(NULL, "Mining Status Error", "Failed to start the internal miner.  Possible wallet error detected.");
    }
}

void MiningPage::stopMining()
{
    if (pwalletMain)
    {
        bool status = false;
        SoftSetBoolArg("-gen", status);
        GenerateBitcoins(status, pwalletMain);

        QPixmap image(":/images/mining_inactive");
        ui->miningStatus->setPixmap(image);
        ui->miningStatus->repaint();
        ui->miningStart->setEnabled(true);
        ui->miningStop->setEnabled(false);

        ui->miningData->setText("Aptcoin Miner\nMining is not active.");
        mpe->setThreadRunning(0);
        ui->miningInfo->setText("");
    }
    else
    {
        QMessageBox::information(NULL, "Mining Status Error", "Failed to stop the internal miner.  Possible wallet error detected.");
    }
}

void MiningPage::refreshMiningData(const QString& data)
{
    ui->miningInfo->setText(data);
}
<|endoftext|>


<commit_before>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_plot_item.h"
#include "qwt_text.h"
#include "qwt_plot.h"
#include "qwt_legend_data.h"
#include "qwt_scale_div.h"
#include "qwt_graphic.h"
#include <qpainter.h>

class QwtPlotItem::PrivateData
{
public:
    PrivateData():
        plot( NULL ),
        isVisible( true ),
        attributes( 0 ),
        interests( 0 ),
        renderHints( 0 ),
        z( 0.0 ),
        xAxis( QwtPlot::xBottom ),
        yAxis( QwtPlot::yLeft ),
        legendIconSize( 8, 8 )
    {
    }

    mutable QwtPlot *plot;

    bool isVisible;
    QwtPlotItem::ItemAttributes attributes;
    QwtPlotItem::ItemInterests interests;
    QwtPlotItem::RenderHints renderHints;
    double z;

    int xAxis;
    int yAxis;

    QwtText title;
    QSize legendIconSize;
};

/*!
   Constructor
   \param title Title of the item
*/
QwtPlotItem::QwtPlotItem( const QwtText &title )
{
    d_data = new PrivateData;
    d_data->title = title;
}

//! Destroy the QwtPlotItem
QwtPlotItem::~QwtPlotItem()
{
    attach( NULL );
    delete d_data;
}

/*!
  \brief Attach the item to a plot.

  This method will attach a QwtPlotItem to the QwtPlot argument. It will first
  detach the QwtPlotItem from any plot from a previous call to attach (if
  necessary). If a NULL argument is passed, it will detach from any QwtPlot it
  was attached to.

  \param plot Plot widget
  \sa detach()
*/
void QwtPlotItem::attach( QwtPlot *plot )
{
    if ( plot == d_data->plot )
        return;

    if ( d_data->plot )
        d_data->plot->attachItem( this, false );

    d_data->plot = plot;

    if ( d_data->plot )
        d_data->plot->attachItem( this, true );
}

/*!
   \brief This method detaches a QwtPlotItem from any
          QwtPlot it has been associated with.

   detach() is equivalent to calling attach( NULL )
   \sa attach()
*/
void QwtPlotItem::detach()
{
    attach( NULL );
}

/*!
   Return rtti for the specific class represented. QwtPlotItem is simply
   a virtual interface class, and base classes will implement this method
   with specific rtti values so a user can differentiate them.

   The rtti value is useful for environments, where the
   runtime type information is disabled and it is not possible
   to do a dynamic_cast<...>.

   \return rtti value
   \sa RttiValues
*/
int QwtPlotItem::rtti() const
{
    return Rtti_PlotItem;
}

//! Return attached plot
QwtPlot *QwtPlotItem::plot() const
{
    return d_data->plot;
}

/*!
   Plot items are painted in increasing z-order.

   \return setZ(), QwtPlotDict::itemList()
*/
double QwtPlotItem::z() const
{
    return d_data->z;
}

/*!
   \brief Set the z value

   Plot items are painted in increasing z-order.

   \param z Z-value
   \sa z(), QwtPlotDict::itemList()
*/
void QwtPlotItem::setZ( double z )
{
    if ( d_data->z != z )
    {
        if ( d_data->plot ) // update the z order
            d_data->plot->attachItem( this, false );

        d_data->z = z;

        if ( d_data->plot )
            d_data->plot->attachItem( this, true );

        itemChanged();
    }
}

/*!
   Set a new title

   \param title Title
   \sa title()
*/
void QwtPlotItem::setTitle( const QString &title )
{
    setTitle( QwtText( title ) );
}

/*!
   Set a new title

   \param title Title
   \sa title()
*/
void QwtPlotItem::setTitle( const QwtText &title )
{
    if ( d_data->title != title )
    {
        d_data->title = title;

        legendChanged();
#if 0
        itemChanged();
#endif
    }
}

/*!
   \return Title of the item
   \sa setTitle()
*/
const QwtText &QwtPlotItem::title() const
{
    return d_data->title;
}

/*!
   Toggle an item attribute

   \param attribute Attribute type
   \param on true/false

   \sa testItemAttribute(), ItemInterest
*/
void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on )
{
    if ( d_data->attributes.testFlag( attribute ) != on )
    {
        if ( on )
            d_data->attributes |= attribute;
        else
            d_data->attributes &= ~attribute;

        if ( attribute == QwtPlotItem::Legend )
            legendChanged();

        itemChanged();
    }
}

/*!
   Test an item attribute

   \param attribute Attribute type
   \return true/false
   \sa setItemAttribute(), ItemInterest
*/
bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const
{
    return d_data->attributes.testFlag( attribute );
}

/*!
   Toggle an item interest

   \param interest Interest type
   \param on true/false

   \sa testItemInterest(), ItemAttribute
*/
void QwtPlotItem::setItemInterest( ItemInterest interest, bool on )
{
    if ( d_data->interests.testFlag( interest ) != on )
    {
        if ( on )
            d_data->interests |= interest;
        else
            d_data->interests &= ~interest;

        itemChanged();
    }
}

/*!
   Test an item interest

   \param interest Interest type
   \return true/false
   \sa setItemInterest(), ItemAttribute
*/
bool QwtPlotItem::testItemInterest( ItemInterest interest ) const
{
    return d_data->interests.testFlag( interest );
}

/*!
   Toggle an render hint

   \param hint Render hint
   \param on true/false

   \sa testRenderHint(), RenderHint
*/
void QwtPlotItem::setRenderHint( RenderHint hint, bool on )
{
    if ( d_data->renderHints.testFlag( hint ) != on )
    {
        if ( on )
            d_data->renderHints |= hint;
        else
            d_data->renderHints &= ~hint;

        itemChanged();
    }
}

/*!
   Test a render hint

   \param hint Render hint
   \return true/false
   \sa setRenderHint(), RenderHint
*/
bool QwtPlotItem::testRenderHint( RenderHint hint ) const
{
    return d_data->renderHints.testFlag( hint );
}

/*!
   Set the size of the legend icon

   The default setting is 8x8 pixels

   \param size Size
   \sa legendIconSize(), legendIcon()
*/
void QwtPlotItem::setLegendIconSize( const QSize &size )
{
    d_data->legendIconSize = size;
}

/*!
   \return Legend icon size
   \sa setLegendIconSize(), legendIcon()
*/
QSize QwtPlotItem::legendIconSize() const
{
    return d_data->legendIconSize;
}

/*!
   \return Icon representing the item on the legend

   The default implementation returns an invalid icon

   \param index Index of the legend entry
                ( usually there is only one )
   \param size Icon size

   \sa setLegendIconSize(), legendData()
 */
QwtGraphic QwtPlotItem::legendIcon(
    int index, const QSizeF &size ) const
{
    Q_UNUSED( index )
    Q_UNUSED( size )

    return QwtGraphic();
}

/*!
   \brief Return a default icon from a brush

   The default icon is a filled rectangle used
   in several derived classes as legendIcon().

   \param brush Fill brush
   \param size Icon size

   \return A filled rectangle
 */
QwtGraphic QwtPlotItem::defaultIcon(
    const QBrush &brush, const QSizeF &size ) const
{
    QwtGraphic icon;
    if ( !size.isEmpty() )
    {
        icon.setDefaultSize( size );

        QRectF r( 0, 0, size.width(), size.height() );

        QPainter painter( &icon );
        painter.fillRect( r, brush );
    }

    return icon;
}

//! Show the item
void QwtPlotItem::show()
{
    setVisible( true );
}

//! Hide the item
void QwtPlotItem::hide()
{
    setVisible( false );
}

/*!
    Show/Hide the item

    \param on Show if true, otherwise hide
    \sa isVisible(), show(), hide()
*/
void QwtPlotItem::setVisible( bool on )
{
    if ( on != d_data->isVisible )
    {
        d_data->isVisible = on;
        itemChanged();
    }
}

/*!
    \return true if visible
    \sa setVisible(), show(), hide()
*/
bool QwtPlotItem::isVisible() const
{
    return d_data->isVisible;
}

/*!
   Update the legend and call QwtPlot::autoRefresh for the
   parent plot.

   \sa QwtPlot::legendChanged(), QwtPlot::autoRefresh()
*/
void QwtPlotItem::itemChanged()
{
    if ( d_data->plot )
        d_data->plot->autoRefresh();
}

/*!
   Update the legend of the parent plot.
   \sa QwtPlot::updateLegend(), itemChanged()
*/
void QwtPlotItem::legendChanged()
{
    if ( testItemAttribute( QwtPlotItem::Legend ) && d_data->plot )
        d_data->plot->updateLegend( this );
}

/*!
   Set X and Y axis

   The item will painted according to the coordinates its Axes.

   \param xAxis X Axis
   \param yAxis Y Axis

   \sa setXAxis(), setYAxis(), xAxis(), yAxis()
*/
void QwtPlotItem::setAxes( int xAxis, int yAxis )
{
    if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop )
        d_data->xAxis = xAxis;

    if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight )
        d_data->yAxis = yAxis;

    itemChanged();
}

/*!
   Set the X axis

   The item will painted according to the coordinates its Axes.

   \param axis X Axis
   \sa setAxes(), setYAxis(), xAxis()
*/
void QwtPlotItem::setXAxis( int axis )
{
    if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop )
    {
        d_data->xAxis = axis;
        itemChanged();
    }
}

/*!
   Set the Y axis

   The item will painted according to the coordinates its Axes.

   \param axis Y Axis
   \sa setAxes(), setXAxis(), yAxis()
*/
void QwtPlotItem::setYAxis( int axis )
{
    if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight )
    {
        d_data->yAxis = axis;
        itemChanged();
    }
}

//! Return xAxis
int QwtPlotItem::xAxis() const
{
    return d_data->xAxis;
}

//! Return yAxis
int QwtPlotItem::yAxis() const
{
    return d_data->yAxis;
}

/*!
   \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0)
*/
QRectF QwtPlotItem::boundingRect() const
{
    return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid
}

/*!
   \brief Calculate a hint for the canvas margin

   When the QwtPlotItem::Margins flag is enabled the plot item
   indicates, that it needs some margins at the borders of the canvas.
   This is f.e. used by bar charts to reserve space for displaying
   the bars.

   The margins are in target device coordinates ( pixels on screen )

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.
   \param canvasRect Contents rect of the canvas in painter coordinates
   \param left Returns the left margin
   \param top Returns the top margin
   \param right Returns the right margin
   \param bottom Returns the bottom margin

   \return The default implementation returns 0 for all margins

   \sa QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins()
 */
void QwtPlotItem::getCanvasMarginHint( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap, const QRectF &canvasRect,
    double &left, double &top, double &right, double &bottom ) const
{
    Q_UNUSED( xMap );
    Q_UNUSED( yMap );
    Q_UNUSED( canvasRect );

    // use QMargins, when we don't need to support Qt < 4.6 anymore
    left = top = right = bottom = 0.0;
}

/*!
   \brief Return all information, that is needed to represent
          the item on the legend

   Most items are represented by one entry on the legend
   showing an icon and a text, but f.e. QwtPlotMultiBarChart
   displays one entry for each bar.

   QwtLegendData is basically a list of QVariants that makes it
   possible to overload and reimplement legendData() to
   return almost any type of information, that is understood
   by the receiver that acts as the legend.

   The default implementation returns one entry with
   the title() of the item and the legendIcon().

   \sa title(), legendIcon(), QwtLegend, QwtPlotLegendItem
 */
QList<QwtLegendData> QwtPlotItem::legendData() const
{
    QwtLegendData data;

    QVariant titleValue;
    qVariantSetValue( titleValue, title() );
    data.setValue( QwtLegendData::TitleRole, titleValue );

    const QwtGraphic graphic = legendIcon( 0, legendIconSize() );
    if ( !graphic.isNull() )
    {
        QVariant iconValue;
        qVariantSetValue( iconValue, graphic );
        data.setValue( QwtLegendData::IconRole, iconValue );
    }

    QList<QwtLegendData> list;
    list += data;

    return list;
}

/*!
   \brief Update the item to changes of the axes scale division

   Update the item, when the axes of plot have changed.
   The default implementation does nothing, but items that depend
   on the scale division (like QwtPlotGrid()) have to reimplement
   updateScaleDiv()

   updateScaleDiv() is only called when the ScaleInterest interest
   is enabled. The default implemention does nothing.

   \param xScaleDiv Scale division of the x-axis
   \param yScaleDiv Scale division of the y-axis

   \sa QwtPlot::updateAxes(), ScaleInterest
*/
void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &xScaleDiv,
    const QwtScaleDiv &yScaleDiv )
{
    Q_UNUSED( xScaleDiv );
    Q_UNUSED( yScaleDiv );
}

/*!
   \brief Update the item to changes of the legend info

   Plot items that want to display a legend ( not those, that want to
   be displayed on a legend ! ) will have to implement updateLegend().

   updateLegend() is only called when the LegendInterest interest
   is enabled. The default implemention does nothing.

   \param item Plot item to be displayed on a legend
   \param data Attributes how to display item on the legend

   \note Plot items, that want to be displayed on a legend
         need to enable the QwtPlotItem::Legend flag and to implement
         legendData() and legendIcon()
 */
void QwtPlotItem::updateLegend( const QwtPlotItem *item,
    const QList<QwtLegendData> &data )
{
    Q_UNUSED( item );
    Q_UNUSED( data );
}

/*!
   \brief Calculate the bounding scale rect of 2 maps

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.

   \return Bounding scale rect of the scale maps, not normalized
*/
QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap ) const
{
    return QRectF( xMap.s1(), yMap.s1(),
        xMap.sDist(), yMap.sDist() );
}

/*!
   \brief Calculate the bounding paint rect of 2 maps

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.

   \return Bounding paint rect of the scale maps, not normalized
*/
QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap ) const
{
    const QRectF rect( xMap.p1(), yMap.p1(),
        xMap.pDist(), yMap.pDist() );

    return rect;
}
<commit_msg>legendChanged() in setLegendIconSize<commit_after>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_plot_item.h"
#include "qwt_text.h"
#include "qwt_plot.h"
#include "qwt_legend_data.h"
#include "qwt_scale_div.h"
#include "qwt_graphic.h"
#include <qpainter.h>

class QwtPlotItem::PrivateData
{
public:
    PrivateData():
        plot( NULL ),
        isVisible( true ),
        attributes( 0 ),
        interests( 0 ),
        renderHints( 0 ),
        z( 0.0 ),
        xAxis( QwtPlot::xBottom ),
        yAxis( QwtPlot::yLeft ),
        legendIconSize( 8, 8 )
    {
    }

    mutable QwtPlot *plot;

    bool isVisible;
    QwtPlotItem::ItemAttributes attributes;
    QwtPlotItem::ItemInterests interests;
    QwtPlotItem::RenderHints renderHints;
    double z;

    int xAxis;
    int yAxis;

    QwtText title;
    QSize legendIconSize;
};

/*!
   Constructor
   \param title Title of the item
*/
QwtPlotItem::QwtPlotItem( const QwtText &title )
{
    d_data = new PrivateData;
    d_data->title = title;
}

//! Destroy the QwtPlotItem
QwtPlotItem::~QwtPlotItem()
{
    attach( NULL );
    delete d_data;
}

/*!
  \brief Attach the item to a plot.

  This method will attach a QwtPlotItem to the QwtPlot argument. It will first
  detach the QwtPlotItem from any plot from a previous call to attach (if
  necessary). If a NULL argument is passed, it will detach from any QwtPlot it
  was attached to.

  \param plot Plot widget
  \sa detach()
*/
void QwtPlotItem::attach( QwtPlot *plot )
{
    if ( plot == d_data->plot )
        return;

    if ( d_data->plot )
        d_data->plot->attachItem( this, false );

    d_data->plot = plot;

    if ( d_data->plot )
        d_data->plot->attachItem( this, true );
}

/*!
   \brief This method detaches a QwtPlotItem from any
          QwtPlot it has been associated with.

   detach() is equivalent to calling attach( NULL )
   \sa attach()
*/
void QwtPlotItem::detach()
{
    attach( NULL );
}

/*!
   Return rtti for the specific class represented. QwtPlotItem is simply
   a virtual interface class, and base classes will implement this method
   with specific rtti values so a user can differentiate them.

   The rtti value is useful for environments, where the
   runtime type information is disabled and it is not possible
   to do a dynamic_cast<...>.

   \return rtti value
   \sa RttiValues
*/
int QwtPlotItem::rtti() const
{
    return Rtti_PlotItem;
}

//! Return attached plot
QwtPlot *QwtPlotItem::plot() const
{
    return d_data->plot;
}

/*!
   Plot items are painted in increasing z-order.

   \return setZ(), QwtPlotDict::itemList()
*/
double QwtPlotItem::z() const
{
    return d_data->z;
}

/*!
   \brief Set the z value

   Plot items are painted in increasing z-order.

   \param z Z-value
   \sa z(), QwtPlotDict::itemList()
*/
void QwtPlotItem::setZ( double z )
{
    if ( d_data->z != z )
    {
        if ( d_data->plot ) // update the z order
            d_data->plot->attachItem( this, false );

        d_data->z = z;

        if ( d_data->plot )
            d_data->plot->attachItem( this, true );

        itemChanged();
    }
}

/*!
   Set a new title

   \param title Title
   \sa title()
*/
void QwtPlotItem::setTitle( const QString &title )
{
    setTitle( QwtText( title ) );
}

/*!
   Set a new title

   \param title Title
   \sa title()
*/
void QwtPlotItem::setTitle( const QwtText &title )
{
    if ( d_data->title != title )
    {
        d_data->title = title;

        legendChanged();
#if 0
        itemChanged();
#endif
    }
}

/*!
   \return Title of the item
   \sa setTitle()
*/
const QwtText &QwtPlotItem::title() const
{
    return d_data->title;
}

/*!
   Toggle an item attribute

   \param attribute Attribute type
   \param on true/false

   \sa testItemAttribute(), ItemInterest
*/
void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on )
{
    if ( d_data->attributes.testFlag( attribute ) != on )
    {
        if ( on )
            d_data->attributes |= attribute;
        else
            d_data->attributes &= ~attribute;

        if ( attribute == QwtPlotItem::Legend )
            legendChanged();

        itemChanged();
    }
}

/*!
   Test an item attribute

   \param attribute Attribute type
   \return true/false
   \sa setItemAttribute(), ItemInterest
*/
bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const
{
    return d_data->attributes.testFlag( attribute );
}

/*!
   Toggle an item interest

   \param interest Interest type
   \param on true/false

   \sa testItemInterest(), ItemAttribute
*/
void QwtPlotItem::setItemInterest( ItemInterest interest, bool on )
{
    if ( d_data->interests.testFlag( interest ) != on )
    {
        if ( on )
            d_data->interests |= interest;
        else
            d_data->interests &= ~interest;

        itemChanged();
    }
}

/*!
   Test an item interest

   \param interest Interest type
   \return true/false
   \sa setItemInterest(), ItemAttribute
*/
bool QwtPlotItem::testItemInterest( ItemInterest interest ) const
{
    return d_data->interests.testFlag( interest );
}

/*!
   Toggle an render hint

   \param hint Render hint
   \param on true/false

   \sa testRenderHint(), RenderHint
*/
void QwtPlotItem::setRenderHint( RenderHint hint, bool on )
{
    if ( d_data->renderHints.testFlag( hint ) != on )
    {
        if ( on )
            d_data->renderHints |= hint;
        else
            d_data->renderHints &= ~hint;

        itemChanged();
    }
}

/*!
   Test a render hint

   \param hint Render hint
   \return true/false
   \sa setRenderHint(), RenderHint
*/
bool QwtPlotItem::testRenderHint( RenderHint hint ) const
{
    return d_data->renderHints.testFlag( hint );
}

/*!
   Set the size of the legend icon

   The default setting is 8x8 pixels

   \param size Size
   \sa legendIconSize(), legendIcon()
*/
void QwtPlotItem::setLegendIconSize( const QSize &size )
{
    if ( d_data->legendIconSize != size )
    {
        d_data->legendIconSize = size;
        legendChanged();
    }
}

/*!
   \return Legend icon size
   \sa setLegendIconSize(), legendIcon()
*/
QSize QwtPlotItem::legendIconSize() const
{
    return d_data->legendIconSize;
}

/*!
   \return Icon representing the item on the legend

   The default implementation returns an invalid icon

   \param index Index of the legend entry
                ( usually there is only one )
   \param size Icon size

   \sa setLegendIconSize(), legendData()
 */
QwtGraphic QwtPlotItem::legendIcon(
    int index, const QSizeF &size ) const
{
    Q_UNUSED( index )
    Q_UNUSED( size )

    return QwtGraphic();
}

/*!
   \brief Return a default icon from a brush

   The default icon is a filled rectangle used
   in several derived classes as legendIcon().

   \param brush Fill brush
   \param size Icon size

   \return A filled rectangle
 */
QwtGraphic QwtPlotItem::defaultIcon(
    const QBrush &brush, const QSizeF &size ) const
{
    QwtGraphic icon;
    if ( !size.isEmpty() )
    {
        icon.setDefaultSize( size );

        QRectF r( 0, 0, size.width(), size.height() );

        QPainter painter( &icon );
        painter.fillRect( r, brush );
    }

    return icon;
}

//! Show the item
void QwtPlotItem::show()
{
    setVisible( true );
}

//! Hide the item
void QwtPlotItem::hide()
{
    setVisible( false );
}

/*!
    Show/Hide the item

    \param on Show if true, otherwise hide
    \sa isVisible(), show(), hide()
*/
void QwtPlotItem::setVisible( bool on )
{
    if ( on != d_data->isVisible )
    {
        d_data->isVisible = on;
        itemChanged();
    }
}

/*!
    \return true if visible
    \sa setVisible(), show(), hide()
*/
bool QwtPlotItem::isVisible() const
{
    return d_data->isVisible;
}

/*!
   Update the legend and call QwtPlot::autoRefresh for the
   parent plot.

   \sa QwtPlot::legendChanged(), QwtPlot::autoRefresh()
*/
void QwtPlotItem::itemChanged()
{
    if ( d_data->plot )
        d_data->plot->autoRefresh();
}

/*!
   Update the legend of the parent plot.
   \sa QwtPlot::updateLegend(), itemChanged()
*/
void QwtPlotItem::legendChanged()
{
    if ( testItemAttribute( QwtPlotItem::Legend ) && d_data->plot )
        d_data->plot->updateLegend( this );
}

/*!
   Set X and Y axis

   The item will painted according to the coordinates its Axes.

   \param xAxis X Axis
   \param yAxis Y Axis

   \sa setXAxis(), setYAxis(), xAxis(), yAxis()
*/
void QwtPlotItem::setAxes( int xAxis, int yAxis )
{
    if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop )
        d_data->xAxis = xAxis;

    if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight )
        d_data->yAxis = yAxis;

    itemChanged();
}

/*!
   Set the X axis

   The item will painted according to the coordinates its Axes.

   \param axis X Axis
   \sa setAxes(), setYAxis(), xAxis()
*/
void QwtPlotItem::setXAxis( int axis )
{
    if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop )
    {
        d_data->xAxis = axis;
        itemChanged();
    }
}

/*!
   Set the Y axis

   The item will painted according to the coordinates its Axes.

   \param axis Y Axis
   \sa setAxes(), setXAxis(), yAxis()
*/
void QwtPlotItem::setYAxis( int axis )
{
    if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight )
    {
        d_data->yAxis = axis;
        itemChanged();
    }
}

//! Return xAxis
int QwtPlotItem::xAxis() const
{
    return d_data->xAxis;
}

//! Return yAxis
int QwtPlotItem::yAxis() const
{
    return d_data->yAxis;
}

/*!
   \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0)
*/
QRectF QwtPlotItem::boundingRect() const
{
    return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid
}

/*!
   \brief Calculate a hint for the canvas margin

   When the QwtPlotItem::Margins flag is enabled the plot item
   indicates, that it needs some margins at the borders of the canvas.
   This is f.e. used by bar charts to reserve space for displaying
   the bars.

   The margins are in target device coordinates ( pixels on screen )

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.
   \param canvasRect Contents rect of the canvas in painter coordinates
   \param left Returns the left margin
   \param top Returns the top margin
   \param right Returns the right margin
   \param bottom Returns the bottom margin

   \return The default implementation returns 0 for all margins

   \sa QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins()
 */
void QwtPlotItem::getCanvasMarginHint( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap, const QRectF &canvasRect,
    double &left, double &top, double &right, double &bottom ) const
{
    Q_UNUSED( xMap );
    Q_UNUSED( yMap );
    Q_UNUSED( canvasRect );

    // use QMargins, when we don't need to support Qt < 4.6 anymore
    left = top = right = bottom = 0.0;
}

/*!
   \brief Return all information, that is needed to represent
          the item on the legend

   Most items are represented by one entry on the legend
   showing an icon and a text, but f.e. QwtPlotMultiBarChart
   displays one entry for each bar.

   QwtLegendData is basically a list of QVariants that makes it
   possible to overload and reimplement legendData() to
   return almost any type of information, that is understood
   by the receiver that acts as the legend.

   The default implementation returns one entry with
   the title() of the item and the legendIcon().

   \sa title(), legendIcon(), QwtLegend, QwtPlotLegendItem
 */
QList<QwtLegendData> QwtPlotItem::legendData() const
{
    QwtLegendData data;

    QVariant titleValue;
    qVariantSetValue( titleValue, title() );
    data.setValue( QwtLegendData::TitleRole, titleValue );

    const QwtGraphic graphic = legendIcon( 0, legendIconSize() );
    if ( !graphic.isNull() )
    {
        QVariant iconValue;
        qVariantSetValue( iconValue, graphic );
        data.setValue( QwtLegendData::IconRole, iconValue );
    }

    QList<QwtLegendData> list;
    list += data;

    return list;
}

/*!
   \brief Update the item to changes of the axes scale division

   Update the item, when the axes of plot have changed.
   The default implementation does nothing, but items that depend
   on the scale division (like QwtPlotGrid()) have to reimplement
   updateScaleDiv()

   updateScaleDiv() is only called when the ScaleInterest interest
   is enabled. The default implemention does nothing.

   \param xScaleDiv Scale division of the x-axis
   \param yScaleDiv Scale division of the y-axis

   \sa QwtPlot::updateAxes(), ScaleInterest
*/
void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &xScaleDiv,
    const QwtScaleDiv &yScaleDiv )
{
    Q_UNUSED( xScaleDiv );
    Q_UNUSED( yScaleDiv );
}

/*!
   \brief Update the item to changes of the legend info

   Plot items that want to display a legend ( not those, that want to
   be displayed on a legend ! ) will have to implement updateLegend().

   updateLegend() is only called when the LegendInterest interest
   is enabled. The default implemention does nothing.

   \param item Plot item to be displayed on a legend
   \param data Attributes how to display item on the legend

   \note Plot items, that want to be displayed on a legend
         need to enable the QwtPlotItem::Legend flag and to implement
         legendData() and legendIcon()
 */
void QwtPlotItem::updateLegend( const QwtPlotItem *item,
    const QList<QwtLegendData> &data )
{
    Q_UNUSED( item );
    Q_UNUSED( data );
}

/*!
   \brief Calculate the bounding scale rect of 2 maps

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.

   \return Bounding scale rect of the scale maps, not normalized
*/
QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap ) const
{
    return QRectF( xMap.s1(), yMap.s1(),
        xMap.sDist(), yMap.sDist() );
}

/*!
   \brief Calculate the bounding paint rect of 2 maps

   \param xMap Maps x-values into pixel coordinates.
   \param yMap Maps y-values into pixel coordinates.

   \return Bounding paint rect of the scale maps, not normalized
*/
QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap,
    const QwtScaleMap &yMap ) const
{
    const QRectF rect( xMap.p1(), yMap.p1(),
        xMap.pDist(), yMap.pDist() );

    return rect;
}
<|endoftext|>


<commit_before>#ifndef _DIRS_CXX_
#define _DIRS_CXX_

#include "Dirs.hpp"
#include <iostream>
#include <stdlib.h>
#include "ProjectRootDir.h"
#include "Parameters.hpp"

string Dirs::_dataSet = "";
string Dirs::_outputDirName = "";
string Dirs::_paramsFile = ConfigDir() + _dataSet + "/registration_parameters.yml";

string Dirs::GetDataSet()
{
  CheckDataSet();
  return _dataSet;
}

void Dirs::SetDataSet(const string dataSet)
{
  _dataSet = dataSet;
}

void Dirs::SetOutputDirName(const string outputDirName)
{
  _outputDirName = outputDirName;
}

void Dirs::SetParamsFile(string paramsFile)
{
  _paramsFile = paramsFile;
}

void Dirs::CheckDataSet()
{
  if ( _dataSet.empty())
  {
    cerr << "Dirs::dataSet not set!\n";
    exit(1);
  }
}

void Dirs::CheckOutputDirName()
{
  if ( _outputDirName.empty())
  {
    cerr << "Dirs::outputDirName not set!\n";
    exit(1);
  }
}

string Dirs::ProjectRootDir()
{
  return PROJECT_ROOT_DIR;
}

string Dirs::ImagesDir()
{
  CheckDataSet();
  return ProjectRootDir() + "images/" + _dataSet + "/";
}

string Dirs::ResultsDir()
{
  CheckDataSet();
  return ProjectRootDir() + "results/" + _dataSet + "/" + _outputDirName + "/";
}

string Dirs::LoResTransformsDir()
{
  // read transforms from directories labeled by both ds ratios
  return ResultsDir() + "LoResTransforms_" + DownsampleSuffix();
}

string Dirs::HiResTransformsDir()
{
  // read transforms from directories labeled by both ds ratios
  return ResultsDir() + "HiResTransforms_" + DownsampleSuffix();
}

string Dirs::ColourDir()
{
  return Dirs::ResultsDir() + "ColourResamples_" + DownsampleSuffix();
}

string Dirs::BlockDir()
{
  CheckDataSet();
  string ratio;
  boost::shared_ptr<YAML::Node> downsample_ratios = config(_dataSet + "/downsample_ratios.yml");
  (*(downsample_ratios.get()))["LoRes"] >> ratio;
  return ImagesDir() + "LoRes_rgb/downsamples_" + ratio + "/";
}

string Dirs::SliceDir()
{
  CheckDataSet();
  string ratio;
  boost::shared_ptr<YAML::Node> downsample_ratios = config(_dataSet + "/downsample_ratios.yml");
  (*(downsample_ratios.get()))["HiRes"] >> ratio;
  return ImagesDir() + "HiRes/downsamples_" + ratio + "/";
}

string Dirs::ConfigDir()
{
  return ProjectRootDir() + "config/";
}

string Dirs::ParamsFile()
{
  CheckDataSet();
  return _paramsFile;
}

string Dirs::SliceFile()
{
  return ConfigDir() + _dataSet + "/image_lists/image_list.txt";
}

string Dirs::TestDir()
{
  return ProjectRootDir() + "itk_source/test/";
}

string Dirs::DownsampleSuffix()
{
  // get downsample ratios
  boost::shared_ptr<YAML::Node> downsample_ratios = config(Dirs::GetDataSet() + "/downsample_ratios.yml");
  string LoResDownsampleRatio, HiResDownsampleRatio;
  (*downsample_ratios)["LoRes"] >> LoResDownsampleRatio;
  (*downsample_ratios)["HiRes"] >> HiResDownsampleRatio;

  // read transforms from directories labeled by both ds ratios
  return LoResDownsampleRatio + "_" + HiResDownsampleRatio;
}

// Constructor
Dirs::Dirs() {}

#endif

<commit_msg>Fixed paramsFile bug.<commit_after>#ifndef _DIRS_CXX_
#define _DIRS_CXX_

#include "Dirs.hpp"
#include <iostream>
#include <stdlib.h>
#include "ProjectRootDir.h"
#include "Parameters.hpp"

string Dirs::_dataSet = "";
string Dirs::_outputDirName = "";
string Dirs::_paramsFile = "";

string Dirs::GetDataSet()
{
  CheckDataSet();
  return _dataSet;
}

void Dirs::SetDataSet(const string dataSet)
{
  _dataSet = dataSet;
}

void Dirs::SetOutputDirName(const string outputDirName)
{
  _outputDirName = outputDirName;
}

void Dirs::SetParamsFile(string paramsFile)
{
  _paramsFile = paramsFile;
}

void Dirs::CheckDataSet()
{
  if ( _dataSet.empty())
  {
    cerr << "Dirs::dataSet not set!\n";
    exit(1);
  }
}

void Dirs::CheckOutputDirName()
{
  if ( _outputDirName.empty())
  {
    cerr << "Dirs::outputDirName not set!\n";
    exit(1);
  }
}

string Dirs::ProjectRootDir()
{
  return PROJECT_ROOT_DIR;
}

string Dirs::ImagesDir()
{
  CheckDataSet();
  return ProjectRootDir() + "images/" + _dataSet + "/";
}

string Dirs::ResultsDir()
{
  CheckDataSet();
  return ProjectRootDir() + "results/" + _dataSet + "/" + _outputDirName + "/";
}

string Dirs::LoResTransformsDir()
{
  // read transforms from directories labeled by both ds ratios
  return ResultsDir() + "LoResTransforms_" + DownsampleSuffix();
}

string Dirs::HiResTransformsDir()
{
  // read transforms from directories labeled by both ds ratios
  return ResultsDir() + "HiResTransforms_" + DownsampleSuffix();
}

string Dirs::ColourDir()
{
  return Dirs::ResultsDir() + "ColourResamples_" + DownsampleSuffix();
}

string Dirs::BlockDir()
{
  CheckDataSet();
  string ratio;
  boost::shared_ptr<YAML::Node> downsample_ratios = config(_dataSet + "/downsample_ratios.yml");
  (*(downsample_ratios.get()))["LoRes"] >> ratio;
  return ImagesDir() + "LoRes_rgb/downsamples_" + ratio + "/";
}

string Dirs::SliceDir()
{
  CheckDataSet();
  string ratio;
  boost::shared_ptr<YAML::Node> downsample_ratios = config(_dataSet + "/downsample_ratios.yml");
  (*(downsample_ratios.get()))["HiRes"] >> ratio;
  return ImagesDir() + "HiRes/downsamples_" + ratio + "/";
}

string Dirs::ConfigDir()
{
  return ProjectRootDir() + "config/";
}

string Dirs::ParamsFile()
{
  if(!_paramsFile.empty()) return _paramsFile;
  CheckDataSet();
  return ConfigDir() + _dataSet + "/registration_parameters.yml";
}

string Dirs::SliceFile()
{
  return ConfigDir() + _dataSet + "/image_lists/image_list.txt";
}

string Dirs::TestDir()
{
  return ProjectRootDir() + "itk_source/test/";
}

string Dirs::DownsampleSuffix()
{
  // get downsample ratios
  boost::shared_ptr<YAML::Node> downsample_ratios = config(Dirs::GetDataSet() + "/downsample_ratios.yml");
  string LoResDownsampleRatio, HiResDownsampleRatio;
  (*downsample_ratios)["LoRes"] >> LoResDownsampleRatio;
  (*downsample_ratios)["HiRes"] >> HiResDownsampleRatio;

  // read transforms from directories labeled by both ds ratios
  return LoResDownsampleRatio + "_" + HiResDownsampleRatio;
}

// Constructor
Dirs::Dirs() {}

#endif

<|endoftext|>