diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index d9d37c88a..afffd8b6f 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1,1001 +1,967 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "guiutil.h" #include "bitcoinaddressvalidator.h" #include "bitcoinunits.h" #include "qvalidatedlineedit.h" #include "walletmodel.h" -#include "primitives/transaction.h" #include "init.h" #include "policy/policy.h" +#include "primitives/transaction.h" #include "protocol.h" #include "script/script.h" #include "script/standard.h" #include "util.h" #ifdef WIN32 #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif #define _WIN32_WINNT 0x0501 #ifdef _WIN32_IE #undef _WIN32_IE #endif #define _WIN32_IE 0x0501 #define WIN32_LEAN_AND_MEAN 1 #ifndef NOMINMAX #define NOMINMAX #endif #include "shellapi.h" #include "shlobj.h" #include "shlwapi.h" #endif #include #include #if BOOST_FILESYSTEM_VERSION >= 3 #include #endif #include #include #include #include #include #include #include #include #include #include #include +#include #include #include // for Qt::mightBeRichText #include -#include #if QT_VERSION < 0x050000 #include #else #include #endif #if QT_VERSION >= 0x50200 #include #endif #if BOOST_FILESYSTEM_VERSION >= 3 static boost::filesystem::detail::utf8_codecvt_facet utf8; #endif #if defined(Q_OS_MAC) extern double NSAppKitVersionNumber; #if !defined(NSAppKitVersionNumber10_8) #define NSAppKitVersionNumber10_8 1187 #endif #if !defined(NSAppKitVersionNumber10_9) #define NSAppKitVersionNumber10_9 1265 #endif #endif namespace GUIUtil { -QString dateTimeStr(const QDateTime &date) -{ - return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm"); +QString dateTimeStr(const QDateTime &date) { + return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + + date.toString("hh:mm"); } -QString dateTimeStr(qint64 nTime) -{ +QString dateTimeStr(qint64 nTime) { return dateTimeStr(QDateTime::fromTime_t((qint32)nTime)); } -QFont fixedPitchFont() -{ +QFont fixedPitchFont() { #if QT_VERSION >= 0x50200 return QFontDatabase::systemFont(QFontDatabase::FixedFont); #else QFont font("Monospace"); #if QT_VERSION >= 0x040800 font.setStyleHint(QFont::Monospace); #else font.setStyleHint(QFont::TypeWriter); #endif return font; #endif } -// Just some dummy data to generate an convincing random-looking (but consistent) address -static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47}; +// Just some dummy data to generate an convincing random-looking (but +// consistent) address +static const uint8_t dummydata[] = { + 0xeb, 0x15, 0x23, 0x1d, 0xfc, 0xeb, 0x60, 0x92, 0x58, 0x86, 0xb6, 0x7d, + 0x06, 0x52, 0x99, 0x92, 0x59, 0x15, 0xae, 0xb1, 0x72, 0xc0, 0x66, 0x47}; // Generate a dummy address with invalid CRC, starting with the network prefix. -static std::string DummyAddress(const CChainParams ¶ms) -{ - std::vector sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); - sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata)); - for(int i=0; i<256; ++i) { // Try every trailing byte - std::string s = EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()); - if (!CBitcoinAddress(s).IsValid()) - return s; - sourcedata[sourcedata.size()-1] += 1; +static std::string DummyAddress(const CChainParams ¶ms) { + std::vector sourcedata = + params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); + sourcedata.insert(sourcedata.end(), dummydata, + dummydata + sizeof(dummydata)); + for (int i = 0; i < 256; ++i) { // Try every trailing byte + std::string s = EncodeBase58(sourcedata.data(), + sourcedata.data() + sourcedata.size()); + if (!CBitcoinAddress(s).IsValid()) return s; + sourcedata[sourcedata.size() - 1] += 1; } return ""; } -void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) -{ +void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) { parent->setFocusProxy(widget); widget->setFont(fixedPitchFont()); #if QT_VERSION >= 0x040700 // We don't want translators to use own addresses in translations // and this is the only place, where this address is supplied. - widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg( - QString::fromStdString(DummyAddress(Params())))); + widget->setPlaceholderText( + QObject::tr("Enter a Bitcoin address (e.g. %1)") + .arg(QString::fromStdString(DummyAddress(Params())))); #endif widget->setValidator(new BitcoinAddressEntryValidator(parent)); widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); } -void setupAmountWidget(QLineEdit *widget, QWidget *parent) -{ +void setupAmountWidget(QLineEdit *widget, QWidget *parent) { QDoubleValidator *amountValidator = new QDoubleValidator(parent); amountValidator->setDecimals(8); amountValidator->setBottom(0.0); widget->setValidator(amountValidator); - widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + widget->setAlignment(Qt::AlignRight | Qt::AlignVCenter); } -bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) -{ +bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) { // return if URI is not valid or is no bitcoin: URI - if(!uri.isValid() || uri.scheme() != QString("bitcoin")) - return false; + if (!uri.isValid() || uri.scheme() != QString("bitcoin")) return false; SendCoinsRecipient rv; rv.address = uri.path(); // Trim any following forward slash which may have been added by the OS if (rv.address.endsWith("/")) { rv.address.truncate(rv.address.length() - 1); } rv.amount = 0; #if QT_VERSION < 0x050000 - QList > items = uri.queryItems(); + QList> items = uri.queryItems(); #else QUrlQuery uriQuery(uri); - QList > items = uriQuery.queryItems(); + QList> items = uriQuery.queryItems(); #endif - for (QList >::iterator i = items.begin(); i != items.end(); i++) - { + for (QList>::iterator i = items.begin(); + i != items.end(); i++) { bool fShouldReturnFalse = false; - if (i->first.startsWith("req-")) - { + if (i->first.startsWith("req-")) { i->first.remove(0, 4); fShouldReturnFalse = true; } - if (i->first == "label") - { + if (i->first == "label") { rv.label = i->second; fShouldReturnFalse = false; } - if (i->first == "message") - { + if (i->first == "message") { rv.message = i->second; fShouldReturnFalse = false; - } - else if (i->first == "amount") - { - if(!i->second.isEmpty()) - { - if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount)) - { + } else if (i->first == "amount") { + if (!i->second.isEmpty()) { + if (!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, + &rv.amount)) { return false; } } fShouldReturnFalse = false; } - if (fShouldReturnFalse) - return false; + if (fShouldReturnFalse) return false; } - if(out) - { + if (out) { *out = rv; } return true; } -bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) -{ +bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) { // Convert bitcoin:// to bitcoin: // - // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host, + // Cannot handle this later, because bitcoin:// + // will cause Qt to see the part after // as host, // which will lower-case it (and thus invalidate the address). - if(uri.startsWith("bitcoin://", Qt::CaseInsensitive)) - { + if (uri.startsWith("bitcoin://", Qt::CaseInsensitive)) { uri.replace(0, 10, "bitcoin:"); } QUrl uriInstance(uri); return parseBitcoinURI(uriInstance, out); } -QString formatBitcoinURI(const SendCoinsRecipient &info) -{ +QString formatBitcoinURI(const SendCoinsRecipient &info) { QString ret = QString("bitcoin:%1").arg(info.address); int paramCount = 0; - if (info.amount) - { - ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount, false, BitcoinUnits::separatorNever)); + if (info.amount) { + ret += + QString("?amount=%1") + .arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount, false, + BitcoinUnits::separatorNever)); paramCount++; } - if (!info.label.isEmpty()) - { + if (!info.label.isEmpty()) { QString lbl(QUrl::toPercentEncoding(info.label)); ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl); paramCount++; } - if (!info.message.isEmpty()) - { + if (!info.message.isEmpty()) { QString msg(QUrl::toPercentEncoding(info.message)); - ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); + ret += + QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); paramCount++; } return ret; } -bool isDust(const QString& address, const CAmount& amount) -{ +bool isDust(const QString &address, const CAmount &amount) { CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script = GetScriptForDestination(dest); CTxOut txOut(amount, script); return txOut.IsDust(dustRelayFee); } -QString HtmlEscape(const QString& str, bool fMultiLine) -{ +QString HtmlEscape(const QString &str, bool fMultiLine) { #if QT_VERSION < 0x050000 QString escaped = Qt::escape(str); #else QString escaped = str.toHtmlEscaped(); #endif - if(fMultiLine) - { + if (fMultiLine) { escaped = escaped.replace("\n", "
\n"); } return escaped; } -QString HtmlEscape(const std::string& str, bool fMultiLine) -{ +QString HtmlEscape(const std::string &str, bool fMultiLine) { return HtmlEscape(QString::fromStdString(str), fMultiLine); } -void copyEntryData(QAbstractItemView *view, int column, int role) -{ - if(!view || !view->selectionModel()) - return; +void copyEntryData(QAbstractItemView *view, int column, int role) { + if (!view || !view->selectionModel()) return; QModelIndexList selection = view->selectionModel()->selectedRows(column); - if(!selection.isEmpty()) - { + if (!selection.isEmpty()) { // Copy first item setClipboard(selection.at(0).data(role).toString()); } } -QList getEntryData(QAbstractItemView *view, int column) -{ - if(!view || !view->selectionModel()) - return QList(); +QList getEntryData(QAbstractItemView *view, int column) { + if (!view || !view->selectionModel()) return QList(); return view->selectionModel()->selectedRows(column); } -QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, - const QString &filter, - QString *selectedSuffixOut) -{ +QString getSaveFileName(QWidget *parent, const QString &caption, + const QString &dir, const QString &filter, + QString *selectedSuffixOut) { QString selectedFilter; QString myDir; - if(dir.isEmpty()) // Default to user documents location - { + // Default to user documents location + if (dir.isEmpty()) { #if QT_VERSION < 0x050000 - myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + myDir = QDesktopServices::storageLocation( + QDesktopServices::DocumentsLocation); #else - myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + myDir = + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); #endif - } - else - { + } else { myDir = dir; } /* Directly convert path to native OS path separators */ - QString result = QDir::toNativeSeparators(QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter)); + QString result = QDir::toNativeSeparators(QFileDialog::getSaveFileName( + parent, caption, myDir, filter, &selectedFilter)); - /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */ + /* Extract first suffix from filter pattern "Description (*.foo)" or + * "Description (*.foo *.bar ...) */ QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]"); QString selectedSuffix; - if(filter_re.exactMatch(selectedFilter)) - { + if (filter_re.exactMatch(selectedFilter)) { selectedSuffix = filter_re.cap(1); } /* Add suffix if needed */ QFileInfo info(result); - if(!result.isEmpty()) - { - if(info.suffix().isEmpty() && !selectedSuffix.isEmpty()) - { + if (!result.isEmpty()) { + if (info.suffix().isEmpty() && !selectedSuffix.isEmpty()) { /* No suffix specified, add selected suffix */ - if(!result.endsWith(".")) - result.append("."); + if (!result.endsWith(".")) result.append("."); result.append(selectedSuffix); } } /* Return selected suffix if asked to */ - if(selectedSuffixOut) - { + if (selectedSuffixOut) { *selectedSuffixOut = selectedSuffix; } return result; } -QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, - const QString &filter, - QString *selectedSuffixOut) -{ +QString getOpenFileName(QWidget *parent, const QString &caption, + const QString &dir, const QString &filter, + QString *selectedSuffixOut) { QString selectedFilter; QString myDir; - if(dir.isEmpty()) // Default to user documents location + if (dir.isEmpty()) // Default to user documents location { #if QT_VERSION < 0x050000 - myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + myDir = QDesktopServices::storageLocation( + QDesktopServices::DocumentsLocation); #else - myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + myDir = + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); #endif - } - else - { + } else { myDir = dir; } /* Directly convert path to native OS path separators */ - QString result = QDir::toNativeSeparators(QFileDialog::getOpenFileName(parent, caption, myDir, filter, &selectedFilter)); + QString result = QDir::toNativeSeparators(QFileDialog::getOpenFileName( + parent, caption, myDir, filter, &selectedFilter)); - if(selectedSuffixOut) - { - /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */ + if (selectedSuffixOut) { + /* Extract first suffix from filter pattern "Description (*.foo)" or + * "Description (*.foo *.bar ...) */ QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]"); QString selectedSuffix; - if(filter_re.exactMatch(selectedFilter)) - { + if (filter_re.exactMatch(selectedFilter)) { selectedSuffix = filter_re.cap(1); } *selectedSuffixOut = selectedSuffix; } return result; } -Qt::ConnectionType blockingGUIThreadConnection() -{ - if(QThread::currentThread() != qApp->thread()) - { +Qt::ConnectionType blockingGUIThreadConnection() { + if (QThread::currentThread() != qApp->thread()) { return Qt::BlockingQueuedConnection; - } - else - { + } else { return Qt::DirectConnection; } } -bool checkPoint(const QPoint &p, const QWidget *w) -{ +bool checkPoint(const QPoint &p, const QWidget *w) { QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p)); if (!atW) return false; return atW->topLevelWidget() == w; } -bool isObscured(QWidget *w) -{ - return !(checkPoint(QPoint(0, 0), w) - && checkPoint(QPoint(w->width() - 1, 0), w) - && checkPoint(QPoint(0, w->height() - 1), w) - && checkPoint(QPoint(w->width() - 1, w->height() - 1), w) - && checkPoint(QPoint(w->width() / 2, w->height() / 2), w)); +bool isObscured(QWidget *w) { + return !(checkPoint(QPoint(0, 0), w) && + checkPoint(QPoint(w->width() - 1, 0), w) && + checkPoint(QPoint(0, w->height() - 1), w) && + checkPoint(QPoint(w->width() - 1, w->height() - 1), w) && + checkPoint(QPoint(w->width() / 2, w->height() / 2), w)); } -void openDebugLogfile() -{ +void openDebugLogfile() { boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; /* Open debug.log with the associated application */ if (boost::filesystem::exists(pathDebug)) - QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathDebug))); + QDesktopServices::openUrl( + QUrl::fromLocalFile(boostPathToQString(pathDebug))); } -void SubstituteFonts(const QString& language) -{ +void SubstituteFonts(const QString &language) { #if defined(Q_OS_MAC) // Background: // OSX's default font changed in 10.9 and Qt is unable to find it with its // usual fallback methods when building against the 10.7 sdk or lower. // The 10.8 SDK added a function to let it find the correct fallback font. // If this fallback is not properly loaded, some characters may fail to // render correctly. // -// The same thing happened with 10.10. .Helvetica Neue DeskInterface is now default. +// The same thing happened with 10.10. .Helvetica Neue DeskInterface is now +// default. // // Solution: If building with the 10.7 SDK or lower and the user's platform // is 10.9 or higher at runtime, substitute the correct font. This needs to // happen before the QApplication is created. -#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 - if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_8) - { +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 + if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_8) { if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9) /* On a 10.9 - 10.9.x system */ QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande"); - else - { + else { /* 10.10 or later system */ - if (language == "zh_CN" || language == "zh_TW" || language == "zh_HK") // traditional or simplified Chinese - QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Heiti SC"); + if (language == "zh_CN" || language == "zh_TW" || + language == "zh_HK") // traditional or simplified Chinese + QFont::insertSubstitution(".Helvetica Neue DeskInterface", + "Heiti SC"); else if (language == "ja") // Japanesee - QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Songti SC"); + QFont::insertSubstitution(".Helvetica Neue DeskInterface", + "Songti SC"); else - QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Lucida Grande"); + QFont::insertSubstitution(".Helvetica Neue DeskInterface", + "Lucida Grande"); } } #endif #endif } -ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, QObject *parent) : - QObject(parent), - size_threshold(_size_threshold) -{ +ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, + QObject *parent) + : QObject(parent), size_threshold(_size_threshold) {} -} - -bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt) -{ - if(evt->type() == QEvent::ToolTipChange) - { - QWidget *widget = static_cast(obj); +bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt) { + if (evt->type() == QEvent::ToolTipChange) { + QWidget *widget = static_cast(obj); QString tooltip = widget->toolTip(); - if(tooltip.size() > size_threshold && !tooltip.startsWith(" size_threshold && !tooltip.startsWith(" to make sure Qt detects this as rich text // Escape the current message as HTML and replace \n by
tooltip = "" + HtmlEscape(tooltip, true) + ""; widget->setToolTip(tooltip); return true; } } return QObject::eventFilter(obj, evt); } -void TableViewLastColumnResizingFixer::connectViewHeadersSignals() -{ - connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int))); - connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged())); +void TableViewLastColumnResizingFixer::connectViewHeadersSignals() { + connect(tableView->horizontalHeader(), + SIGNAL(sectionResized(int, int, int)), this, + SLOT(on_sectionResized(int, int, int))); + connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, + SLOT(on_geometriesChanged())); } -// We need to disconnect these while handling the resize events, otherwise we can enter infinite loops. -void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals() -{ - disconnect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int))); - disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged())); +// We need to disconnect these while handling the resize events, otherwise we +// can enter infinite loops. +void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals() { + disconnect(tableView->horizontalHeader(), + SIGNAL(sectionResized(int, int, int)), this, + SLOT(on_sectionResized(int, int, int))); + disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, + SLOT(on_geometriesChanged())); } -// Setup the resize mode, handles compatibility for Qt5 and below as the method signatures changed. +// Setup the resize mode, handles compatibility for Qt5 and below as the method +// signatures changed. // Refactored here for readability. -void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode) -{ +void TableViewLastColumnResizingFixer::setViewHeaderResizeMode( + int logicalIndex, QHeaderView::ResizeMode resizeMode) { #if QT_VERSION < 0x050000 tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode); #else - tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode); + tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, + resizeMode); #endif } -void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width) -{ +void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, + int width) { tableView->setColumnWidth(nColumnIndex, width); tableView->horizontalHeader()->resizeSection(nColumnIndex, width); } -int TableViewLastColumnResizingFixer::getColumnsWidth() -{ +int TableViewLastColumnResizingFixer::getColumnsWidth() { int nColumnsWidthSum = 0; - for (int i = 0; i < columnCount; i++) - { + for (int i = 0; i < columnCount; i++) { nColumnsWidthSum += tableView->horizontalHeader()->sectionSize(i); } return nColumnsWidthSum; } -int TableViewLastColumnResizingFixer::getAvailableWidthForColumn(int column) -{ +int TableViewLastColumnResizingFixer::getAvailableWidthForColumn(int column) { int nResult = lastColumnMinimumWidth; int nTableWidth = tableView->horizontalHeader()->width(); - if (nTableWidth > 0) - { - int nOtherColsWidth = getColumnsWidth() - tableView->horizontalHeader()->sectionSize(column); + if (nTableWidth > 0) { + int nOtherColsWidth = + getColumnsWidth() - + tableView->horizontalHeader()->sectionSize(column); nResult = std::max(nResult, nTableWidth - nOtherColsWidth); } return nResult; } // Make sure we don't make the columns wider than the table's viewport width. -void TableViewLastColumnResizingFixer::adjustTableColumnsWidth() -{ +void TableViewLastColumnResizingFixer::adjustTableColumnsWidth() { disconnectViewHeadersSignals(); resizeColumn(lastColumnIndex, getAvailableWidthForColumn(lastColumnIndex)); connectViewHeadersSignals(); int nTableWidth = tableView->horizontalHeader()->width(); int nColsWidth = getColumnsWidth(); - if (nColsWidth > nTableWidth) - { - resizeColumn(secondToLastColumnIndex,getAvailableWidthForColumn(secondToLastColumnIndex)); + if (nColsWidth > nTableWidth) { + resizeColumn(secondToLastColumnIndex, + getAvailableWidthForColumn(secondToLastColumnIndex)); } } // Make column use all the space available, useful during window resizing. -void TableViewLastColumnResizingFixer::stretchColumnWidth(int column) -{ +void TableViewLastColumnResizingFixer::stretchColumnWidth(int column) { disconnectViewHeadersSignals(); resizeColumn(column, getAvailableWidthForColumn(column)); connectViewHeadersSignals(); } // When a section is resized this is a slot-proxy for ajustAmountColumnWidth(). -void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int oldSize, int newSize) -{ +void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, + int oldSize, + int newSize) { adjustTableColumnsWidth(); int remainingWidth = getAvailableWidthForColumn(logicalIndex); - if (newSize > remainingWidth) - { - resizeColumn(logicalIndex, remainingWidth); + if (newSize > remainingWidth) { + resizeColumn(logicalIndex, remainingWidth); } } -// When the table's geometry is ready, we manually perform the stretch of the "Message" column, +// When the table's geometry is ready, we manually perform the stretch of the +// "Message" column, // as the "Stretch" resize mode does not allow for interactive resizing. -void TableViewLastColumnResizingFixer::on_geometriesChanged() -{ - if ((getColumnsWidth() - this->tableView->horizontalHeader()->width()) != 0) - { +void TableViewLastColumnResizingFixer::on_geometriesChanged() { + if ((getColumnsWidth() - this->tableView->horizontalHeader()->width()) != + 0) { disconnectViewHeadersSignals(); - resizeColumn(secondToLastColumnIndex, getAvailableWidthForColumn(secondToLastColumnIndex)); + resizeColumn(secondToLastColumnIndex, + getAvailableWidthForColumn(secondToLastColumnIndex)); connectViewHeadersSignals(); } } /** * Initializes all internal variables and prepares the * the resize modes of the last 2 columns of the table and */ -TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent) : - QObject(parent), - tableView(table), - lastColumnMinimumWidth(lastColMinimumWidth), - allColumnsMinimumWidth(allColsMinimumWidth) -{ +TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer( + QTableView *table, int lastColMinimumWidth, int allColsMinimumWidth, + QObject *parent) + : QObject(parent), tableView(table), + lastColumnMinimumWidth(lastColMinimumWidth), + allColumnsMinimumWidth(allColsMinimumWidth) { columnCount = tableView->horizontalHeader()->count(); lastColumnIndex = columnCount - 1; secondToLastColumnIndex = columnCount - 2; - tableView->horizontalHeader()->setMinimumSectionSize(allColumnsMinimumWidth); + tableView->horizontalHeader()->setMinimumSectionSize( + allColumnsMinimumWidth); setViewHeaderResizeMode(secondToLastColumnIndex, QHeaderView::Interactive); setViewHeaderResizeMode(lastColumnIndex, QHeaderView::Interactive); } #ifdef WIN32 -boost::filesystem::path static StartupShortcutPath() -{ +boost::filesystem::path static StartupShortcutPath() { std::string chain = ChainNameFromCommandLine(); if (chain == CBaseChainParams::MAIN) return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk"; - if (chain == CBaseChainParams::TESTNET) // Remove this special case when CBaseChainParams::TESTNET = "testnet4" + // Remove this special case when CBaseChainParams::TESTNET = "testnet4" + if (chain == CBaseChainParams::TESTNET) return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (testnet).lnk"; - return GetSpecialFolderPath(CSIDL_STARTUP) / strprintf("Bitcoin (%s).lnk", chain); + return GetSpecialFolderPath(CSIDL_STARTUP) / + strprintf("Bitcoin (%s).lnk", chain); } -bool GetStartOnSystemStartup() -{ +bool GetStartOnSystemStartup() { // check for Bitcoin*.lnk return boost::filesystem::exists(StartupShortcutPath()); } -bool SetStartOnSystemStartup(bool fAutoStart) -{ +bool SetStartOnSystemStartup(bool fAutoStart) { // If the shortcut exists already, remove it for updating boost::filesystem::remove(StartupShortcutPath()); - if (fAutoStart) - { + if (fAutoStart) { CoInitialize(NULL); // Get a pointer to the IShellLink interface. - IShellLink* psl = NULL; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, - CLSCTX_INPROC_SERVER, IID_IShellLink, - reinterpret_cast(&psl)); + IShellLink *psl = NULL; + HRESULT hres = + CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, reinterpret_cast(&psl)); - if (SUCCEEDED(hres)) - { + if (SUCCEEDED(hres)) { // Get the current executable path TCHAR pszExePath[MAX_PATH]; GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); // Start client minimized QString strArgs = "-min"; // Set -testnet /-regtest options - strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false))); + strArgs += QString::fromStdString(strprintf( + " -testnet=%d -regtest=%d", GetBoolArg("-testnet", false), + GetBoolArg("-regtest", false))); #ifdef UNICODE boost::scoped_array args(new TCHAR[strArgs.length() + 1]); // Convert the QString to TCHAR* strArgs.toWCharArray(args.get()); // Add missing '\0'-termination to string args[strArgs.length()] = '\0'; #endif // Set the path to the shortcut target psl->SetPath(pszExePath); PathRemoveFileSpec(pszExePath); psl->SetWorkingDirectory(pszExePath); psl->SetShowCmd(SW_SHOWMINNOACTIVE); #ifndef UNICODE psl->SetArguments(strArgs.toStdString().c_str()); #else psl->SetArguments(args.get()); #endif // Query IShellLink for the IPersistFile interface for // saving the shortcut in persistent storage. - IPersistFile* ppf = NULL; - hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast(&ppf)); - if (SUCCEEDED(hres)) - { + IPersistFile *ppf = NULL; + hres = psl->QueryInterface(IID_IPersistFile, + reinterpret_cast(&ppf)); + if (SUCCEEDED(hres)) { WCHAR pwsz[MAX_PATH]; // Ensure that the string is ANSI. - MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH); + MultiByteToWideChar(CP_ACP, 0, + StartupShortcutPath().string().c_str(), -1, + pwsz, MAX_PATH); // Save the link by calling IPersistFile::Save. hres = ppf->Save(pwsz, TRUE); ppf->Release(); psl->Release(); CoUninitialize(); return true; } psl->Release(); } CoUninitialize(); return false; } return true; } #elif defined(Q_OS_LINUX) // Follow the Desktop Application Autostart Spec: // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html -boost::filesystem::path static GetAutostartDir() -{ +boost::filesystem::path static GetAutostartDir() { namespace fs = boost::filesystem; - char* pszConfigHome = getenv("XDG_CONFIG_HOME"); + char *pszConfigHome = getenv("XDG_CONFIG_HOME"); if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; - char* pszHome = getenv("HOME"); + char *pszHome = getenv("HOME"); if (pszHome) return fs::path(pszHome) / ".config" / "autostart"; return fs::path(); } -boost::filesystem::path static GetAutostartFilePath() -{ +boost::filesystem::path static GetAutostartFilePath() { std::string chain = ChainNameFromCommandLine(); if (chain == CBaseChainParams::MAIN) return GetAutostartDir() / "bitcoin.desktop"; return GetAutostartDir() / strprintf("bitcoin-%s.lnk", chain); } -bool GetStartOnSystemStartup() -{ +bool GetStartOnSystemStartup() { boost::filesystem::ifstream optionFile(GetAutostartFilePath()); - if (!optionFile.good()) - return false; + if (!optionFile.good()) return false; // Scan through file for "Hidden=true": std::string line; - while (!optionFile.eof()) - { + while (!optionFile.eof()) { getline(optionFile, line); if (line.find("Hidden") != std::string::npos && line.find("true") != std::string::npos) return false; } optionFile.close(); return true; } -bool SetStartOnSystemStartup(bool fAutoStart) -{ +bool SetStartOnSystemStartup(bool fAutoStart) { if (!fAutoStart) boost::filesystem::remove(GetAutostartFilePath()); - else - { - char pszExePath[MAX_PATH+1]; + else { + char pszExePath[MAX_PATH + 1]; memset(pszExePath, 0, sizeof(pszExePath)); - if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1) + if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath) - 1) == + -1) return false; boost::filesystem::create_directories(GetAutostartDir()); - boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); - if (!optionFile.good()) - return false; + boost::filesystem::ofstream optionFile( + GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc); + if (!optionFile.good()) return false; std::string chain = ChainNameFromCommandLine(); // Write a bitcoin.desktop file to the autostart directory: optionFile << "[Desktop Entry]\n"; optionFile << "Type=Application\n"; if (chain == CBaseChainParams::MAIN) optionFile << "Name=Bitcoin\n"; else optionFile << strprintf("Name=Bitcoin (%s)\n", chain); - optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false)); + optionFile << "Exec=" << pszExePath + << strprintf(" -min -testnet=%d -regtest=%d\n", + GetBoolArg("-testnet", false), + GetBoolArg("-regtest", false)); optionFile << "Terminal=false\n"; optionFile << "Hidden=false\n"; optionFile.close(); } return true; } - #elif defined(Q_OS_MAC) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -// based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m +// based on: +// https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m #include #include -LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl); -LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl) -{ +LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, + CFURLRef findUrl); +LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, + CFURLRef findUrl) { // loop through the list of startup items and try to find the bitcoin app CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, NULL); - for(int i = 0; i < CFArrayGetCount(listSnapshot); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i); - UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; + for (int i = 0; i < CFArrayGetCount(listSnapshot); i++) { + LSSharedFileListItemRef item = + (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i); + UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | + kLSSharedFileListDoNotMountVolumes; CFURLRef currentItemURL = NULL; -#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 - if(&LSSharedFileListItemCopyResolvedURL) - currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL); -#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100 - else - LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL); +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 + if (&LSSharedFileListItemCopyResolvedURL) + currentItemURL = LSSharedFileListItemCopyResolvedURL( + item, resolutionFlags, NULL); +#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < 10100 + else + LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, + NULL); #endif #else - LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL); + LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, + NULL); #endif - if(currentItemURL && CFEqual(currentItemURL, findUrl)) { + if (currentItemURL && CFEqual(currentItemURL, findUrl)) { // found CFRelease(currentItemURL); return item; } - if(currentItemURL) { + if (currentItemURL) { CFRelease(currentItemURL); } } return NULL; } -bool GetStartOnSystemStartup() -{ +bool GetStartOnSystemStartup() { CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); - LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl); + LSSharedFileListRef loginItems = + LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + LSSharedFileListItemRef foundItem = + findStartupItemInList(loginItems, bitcoinAppUrl); return !!foundItem; // return boolified object } -bool SetStartOnSystemStartup(bool fAutoStart) -{ +bool SetStartOnSystemStartup(bool fAutoStart) { CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); - LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl); + LSSharedFileListRef loginItems = + LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + LSSharedFileListItemRef foundItem = + findStartupItemInList(loginItems, bitcoinAppUrl); - if(fAutoStart && !foundItem) { + if (fAutoStart && !foundItem) { // add bitcoin app to startup item list - LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, bitcoinAppUrl, NULL, NULL); - } - else if(!fAutoStart && foundItem) { + LSSharedFileListInsertItemURL(loginItems, + kLSSharedFileListItemBeforeFirst, NULL, + NULL, bitcoinAppUrl, NULL, NULL); + } else if (!fAutoStart && foundItem) { // remove item LSSharedFileListItemRemove(loginItems, foundItem); } return true; } #pragma GCC diagnostic pop #else -bool GetStartOnSystemStartup() { return false; } -bool SetStartOnSystemStartup(bool fAutoStart) { return false; } +bool GetStartOnSystemStartup() { + return false; +} +bool SetStartOnSystemStartup(bool fAutoStart) { + return false; +} #endif -void saveWindowGeometry(const QString& strSetting, QWidget *parent) -{ +void saveWindowGeometry(const QString &strSetting, QWidget *parent) { QSettings settings; settings.setValue(strSetting + "Pos", parent->pos()); settings.setValue(strSetting + "Size", parent->size()); } -void restoreWindowGeometry(const QString& strSetting, const QSize& defaultSize, QWidget *parent) -{ +void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, + QWidget *parent) { QSettings settings; QPoint pos = settings.value(strSetting + "Pos").toPoint(); QSize size = settings.value(strSetting + "Size", defaultSize).toSize(); if (!pos.x() && !pos.y()) { QRect screen = QApplication::desktop()->screenGeometry(); pos.setX((screen.width() - size.width()) / 2); pos.setY((screen.height() - size.height()) / 2); } parent->resize(size); parent->move(pos); } -void setClipboard(const QString& str) -{ +void setClipboard(const QString &str) { QApplication::clipboard()->setText(str, QClipboard::Clipboard); QApplication::clipboard()->setText(str, QClipboard::Selection); } #if BOOST_FILESYSTEM_VERSION >= 3 -boost::filesystem::path qstringToBoostPath(const QString &path) -{ +boost::filesystem::path qstringToBoostPath(const QString &path) { return boost::filesystem::path(path.toStdString(), utf8); } -QString boostPathToQString(const boost::filesystem::path &path) -{ +QString boostPathToQString(const boost::filesystem::path &path) { return QString::fromStdString(path.string(utf8)); } #else #warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older -boost::filesystem::path qstringToBoostPath(const QString &path) -{ +boost::filesystem::path qstringToBoostPath(const QString &path) { return boost::filesystem::path(path.toStdString()); } -QString boostPathToQString(const boost::filesystem::path &path) -{ +QString boostPathToQString(const boost::filesystem::path &path) { return QString::fromStdString(path.string()); } #endif -QString formatDurationStr(int secs) -{ +QString formatDurationStr(int secs) { QStringList strList; int days = secs / 86400; int hours = (secs % 86400) / 3600; int mins = (secs % 3600) / 60; int seconds = secs % 60; - if (days) - strList.append(QString(QObject::tr("%1 d")).arg(days)); - if (hours) - strList.append(QString(QObject::tr("%1 h")).arg(hours)); - if (mins) - strList.append(QString(QObject::tr("%1 m")).arg(mins)); + if (days) strList.append(QString(QObject::tr("%1 d")).arg(days)); + if (hours) strList.append(QString(QObject::tr("%1 h")).arg(hours)); + if (mins) strList.append(QString(QObject::tr("%1 m")).arg(mins)); if (seconds || (!days && !hours && !mins)) strList.append(QString(QObject::tr("%1 s")).arg(seconds)); return strList.join(" "); } -QString formatServicesStr(quint64 mask) -{ +QString formatServicesStr(quint64 mask) { QStringList strList; // Just scan the last 8 bits for now. for (int i = 0; i < 8; i++) { uint64_t check = 1 << i; - if (mask & check) - { - switch (check) - { - case NODE_NETWORK: - strList.append("NETWORK"); - break; - case NODE_GETUTXO: - strList.append("GETUTXO"); - break; - case NODE_BLOOM: - strList.append("BLOOM"); - break; - case NODE_XTHIN: - strList.append("XTHIN"); - break; - default: - strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check)); + if (mask & check) { + switch (check) { + case NODE_NETWORK: + strList.append("NETWORK"); + break; + case NODE_GETUTXO: + strList.append("GETUTXO"); + break; + case NODE_BLOOM: + strList.append("BLOOM"); + break; + case NODE_XTHIN: + strList.append("XTHIN"); + break; + default: + strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check)); } } } if (strList.size()) return strList.join(" & "); else return QObject::tr("None"); } -QString formatPingTime(double dPingTime) -{ - return (dPingTime == std::numeric_limits::max()/1e6 || dPingTime == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10)); +QString formatPingTime(double dPingTime) { + return (dPingTime == std::numeric_limits::max() / 1e6 || + dPingTime == 0) + ? QObject::tr("N/A") + : QString(QObject::tr("%1 ms")) + .arg(QString::number((int)(dPingTime * 1000), 10)); } -QString formatTimeOffset(int64_t nTimeOffset) -{ - return QString(QObject::tr("%1 s")).arg(QString::number((int)nTimeOffset, 10)); +QString formatTimeOffset(int64_t nTimeOffset) { + return QString(QObject::tr("%1 s")) + .arg(QString::number((int)nTimeOffset, 10)); } -QString formatNiceTimeOffset(qint64 secs) -{ +QString formatNiceTimeOffset(qint64 secs) { // Represent time from last generated block in human readable text QString timeBehindText; - const int HOUR_IN_SECONDS = 60*60; - const int DAY_IN_SECONDS = 24*60*60; - const int WEEK_IN_SECONDS = 7*24*60*60; - const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar - if(secs < 60) - { - timeBehindText = QObject::tr("%n second(s)","",secs); - } - else if(secs < 2*HOUR_IN_SECONDS) - { - timeBehindText = QObject::tr("%n minute(s)","",secs/60); - } - else if(secs < 2*DAY_IN_SECONDS) - { - timeBehindText = QObject::tr("%n hour(s)","",secs/HOUR_IN_SECONDS); - } - else if(secs < 2*WEEK_IN_SECONDS) - { - timeBehindText = QObject::tr("%n day(s)","",secs/DAY_IN_SECONDS); - } - else if(secs < YEAR_IN_SECONDS) - { - timeBehindText = QObject::tr("%n week(s)","",secs/WEEK_IN_SECONDS); - } - else - { + const int HOUR_IN_SECONDS = 60 * 60; + const int DAY_IN_SECONDS = 24 * 60 * 60; + const int WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + // Average length of year in Gregorian calendar + const int YEAR_IN_SECONDS = 31556952; + if (secs < 60) { + timeBehindText = QObject::tr("%n second(s)", "", secs); + } else if (secs < 2 * HOUR_IN_SECONDS) { + timeBehindText = QObject::tr("%n minute(s)", "", secs / 60); + } else if (secs < 2 * DAY_IN_SECONDS) { + timeBehindText = QObject::tr("%n hour(s)", "", secs / HOUR_IN_SECONDS); + } else if (secs < 2 * WEEK_IN_SECONDS) { + timeBehindText = QObject::tr("%n day(s)", "", secs / DAY_IN_SECONDS); + } else if (secs < YEAR_IN_SECONDS) { + timeBehindText = QObject::tr("%n week(s)", "", secs / WEEK_IN_SECONDS); + } else { qint64 years = secs / YEAR_IN_SECONDS; qint64 remainder = secs % YEAR_IN_SECONDS; - timeBehindText = QObject::tr("%1 and %2").arg(QObject::tr("%n year(s)", "", years)).arg(QObject::tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); + timeBehindText = QObject::tr("%1 and %2") + .arg(QObject::tr("%n year(s)", "", years)) + .arg(QObject::tr("%n week(s)", "", + remainder / WEEK_IN_SECONDS)); } return timeBehindText; } -void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) -{ +void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) { Q_EMIT clicked(event->pos()); } - -void ClickableProgressBar::mouseReleaseEvent(QMouseEvent *event) -{ + +void ClickableProgressBar::mouseReleaseEvent(QMouseEvent *event) { Q_EMIT clicked(event->pos()); } } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 913aa5e24..758c4bb95 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -1,247 +1,266 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_QT_GUIUTIL_H #define BITCOIN_QT_GUIUTIL_H #include "amount.h" #include #include +#include #include #include #include #include #include -#include #include class QValidatedLineEdit; class SendCoinsRecipient; QT_BEGIN_NAMESPACE class QAbstractItemView; class QDateTime; class QFont; class QLineEdit; class QUrl; class QWidget; QT_END_NAMESPACE /** Utility functions used by the Bitcoin Qt UI. */ -namespace GUIUtil -{ - // Create human-readable string from date - QString dateTimeStr(const QDateTime &datetime); - QString dateTimeStr(qint64 nTime); - - // Return a monospace font - QFont fixedPitchFont(); - - // Set up widgets for address and amounts - void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); - void setupAmountWidget(QLineEdit *widget, QWidget *parent); - - // Parse "bitcoin:" URI into recipient object, return true on successful parsing - bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); - bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); - QString formatBitcoinURI(const SendCoinsRecipient &info); - - // Returns true if given address+amount meets "dust" definition - bool isDust(const QString& address, const CAmount& amount); - - // HTML escaping for rich text controls - QString HtmlEscape(const QString& str, bool fMultiLine=false); - QString HtmlEscape(const std::string& str, bool fMultiLine=false); - - /** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing - is selected. - @param[in] column Data column to extract from the model - @param[in] role Data role to extract from the model - @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress - */ - void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole); - - /** Return a field of the currently selected entry as a QString. Does nothing if nothing - is selected. - @param[in] column Data column to extract from the model - @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress - */ - QList getEntryData(QAbstractItemView *view, int column); +namespace GUIUtil { +// Create human-readable string from date +QString dateTimeStr(const QDateTime &datetime); +QString dateTimeStr(qint64 nTime); + +// Return a monospace font +QFont fixedPitchFont(); + +// Set up widgets for address and amounts +void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); +void setupAmountWidget(QLineEdit *widget, QWidget *parent); + +// Parse "bitcoin:" URI into recipient object, return true on successful parsing +bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); +bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); +QString formatBitcoinURI(const SendCoinsRecipient &info); + +// Returns true if given address+amount meets "dust" definition +bool isDust(const QString &address, const CAmount &amount); + +// HTML escaping for rich text controls +QString HtmlEscape(const QString &str, bool fMultiLine = false); +QString HtmlEscape(const std::string &str, bool fMultiLine = false); + +/** Copy a field of the currently selected entry of a view to the clipboard. + Does nothing if nothing + is selected. + @param[in] column Data column to extract from the model + @param[in] role Data role to extract from the model + @see TransactionView::copyLabel, TransactionView::copyAmount, + TransactionView::copyAddress + */ +void copyEntryData(QAbstractItemView *view, int column, + int role = Qt::EditRole); + +/** Return a field of the currently selected entry as a QString. Does nothing if + nothing + is selected. + @param[in] column Data column to extract from the model + @see TransactionView::copyLabel, TransactionView::copyAmount, + TransactionView::copyAddress + */ +QList getEntryData(QAbstractItemView *view, int column); + +void setClipboard(const QString &str); + +/** Get save filename, mimics QFileDialog::getSaveFileName, except that it + appends a default suffix + when no suffix is provided by the user. + + @param[in] parent Parent window (or 0) + @param[in] caption Window caption (or empty, for default) + @param[in] dir Starting directory (or empty, to default to documents + directory) + @param[in] filter Filter specification such as "Comma Separated Files + (*.csv)" + @param[out] selectedSuffixOut Pointer to return the suffix (file type) that + was selected (or 0). + Can be useful when choosing the save file format based on suffix. + */ +QString getSaveFileName(QWidget *parent, const QString &caption, + const QString &dir, const QString &filter, + QString *selectedSuffixOut); + +/** Get open filename, convenience wrapper for QFileDialog::getOpenFileName. + + @param[in] parent Parent window (or 0) + @param[in] caption Window caption (or empty, for default) + @param[in] dir Starting directory (or empty, to default to documents + directory) + @param[in] filter Filter specification such as "Comma Separated Files + (*.csv)" + @param[out] selectedSuffixOut Pointer to return the suffix (file type) that + was selected (or 0). + Can be useful when choosing the save file format based on suffix. + */ +QString getOpenFileName(QWidget *parent, const QString &caption, + const QString &dir, const QString &filter, + QString *selectedSuffixOut); - void setClipboard(const QString& str); +/** Get connection type to call object slot in GUI thread with invokeMethod. The + call will be blocking. - /** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix - when no suffix is provided by the user. + @returns If called from the GUI thread, return a Qt::DirectConnection. + If called from another thread, return a + Qt::BlockingQueuedConnection. +*/ +Qt::ConnectionType blockingGUIThreadConnection(); - @param[in] parent Parent window (or 0) - @param[in] caption Window caption (or empty, for default) - @param[in] dir Starting directory (or empty, to default to documents directory) - @param[in] filter Filter specification such as "Comma Separated Files (*.csv)" - @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0). - Can be useful when choosing the save file format based on suffix. - */ - QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, - const QString &filter, - QString *selectedSuffixOut); - - /** Get open filename, convenience wrapper for QFileDialog::getOpenFileName. - - @param[in] parent Parent window (or 0) - @param[in] caption Window caption (or empty, for default) - @param[in] dir Starting directory (or empty, to default to documents directory) - @param[in] filter Filter specification such as "Comma Separated Files (*.csv)" - @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0). - Can be useful when choosing the save file format based on suffix. - */ - QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, - const QString &filter, - QString *selectedSuffixOut); +// Determine whether a widget is hidden behind other windows +bool isObscured(QWidget *w); - /** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking. +// Open debug.log +void openDebugLogfile(); - @returns If called from the GUI thread, return a Qt::DirectConnection. - If called from another thread, return a Qt::BlockingQueuedConnection. - */ - Qt::ConnectionType blockingGUIThreadConnection(); +// Replace invalid default fonts with known good ones +void SubstituteFonts(const QString &language); - // Determine whether a widget is hidden behind other windows - bool isObscured(QWidget *w); +/** Qt event filter that intercepts ToolTipChange events, and replaces the + * tooltip with a rich text representation if needed. This assures that Qt can + * word-wrap long tooltip messages. Tooltips longer than the provided size + * threshold (in characters) are wrapped. + */ +class ToolTipToRichTextFilter : public QObject { + Q_OBJECT + +public: + explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0); + +protected: + bool eventFilter(QObject *obj, QEvent *evt); + +private: + int size_threshold; +}; + +/** + * Makes a QTableView last column feel as if it was being resized from its left + * border. + * Also makes sure the column widths are never larger than the table's viewport. + * In Qt, all columns are resizable from the right, but it's not intuitive + * resizing the last column from the right. + * Usually our second to last columns behave as if stretched, and when on strech + * mode, columns aren't resizable interactively or programmatically. + * + * This helper object takes care of this issue. + * + */ +class TableViewLastColumnResizingFixer : public QObject { + Q_OBJECT + +public: + TableViewLastColumnResizingFixer(QTableView *table, int lastColMinimumWidth, + int allColsMinimumWidth, QObject *parent); + void stretchColumnWidth(int column); + +private: + QTableView *tableView; + int lastColumnMinimumWidth; + int allColumnsMinimumWidth; + int lastColumnIndex; + int columnCount; + int secondToLastColumnIndex; + + void adjustTableColumnsWidth(); + int getAvailableWidthForColumn(int column); + int getColumnsWidth(); + void connectViewHeadersSignals(); + void disconnectViewHeadersSignals(); + void setViewHeaderResizeMode(int logicalIndex, + QHeaderView::ResizeMode resizeMode); + void resizeColumn(int nColumnIndex, int width); + +private Q_SLOTS: + void on_sectionResized(int logicalIndex, int oldSize, int newSize); + void on_geometriesChanged(); +}; + +bool GetStartOnSystemStartup(); +bool SetStartOnSystemStartup(bool fAutoStart); + +/** Save window size and position */ +void saveWindowGeometry(const QString &strSetting, QWidget *parent); +/** Restore window size and position */ +void restoreWindowGeometry(const QString &strSetting, + const QSize &defaultSizeIn, QWidget *parent); + +/* Convert QString to OS specific boost path through UTF-8 */ +boost::filesystem::path qstringToBoostPath(const QString &path); + +/* Convert OS specific boost path to QString through UTF-8 */ +QString boostPathToQString(const boost::filesystem::path &path); + +/* Convert seconds into a QString with days, hours, mins, secs */ +QString formatDurationStr(int secs); + +/* Format CNodeStats.nServices bitmask into a user-readable string */ +QString formatServicesStr(quint64 mask); + +/* Format a CNodeCombinedStats.dPingTime into a user-readable string or display + * N/A, if 0*/ +QString formatPingTime(double dPingTime); + +/* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */ +QString formatTimeOffset(int64_t nTimeOffset); + +QString formatNiceTimeOffset(qint64 secs); + +class ClickableLabel : public QLabel { + Q_OBJECT + +Q_SIGNALS: + /** Emitted when the label is clicked. The relative mouse coordinates of the + * click are passed to the signal. + */ + void clicked(const QPoint &point); - // Open debug.log - void openDebugLogfile(); +protected: + void mouseReleaseEvent(QMouseEvent *event); +}; - // Replace invalid default fonts with known good ones - void SubstituteFonts(const QString& language); +class ClickableProgressBar : public QProgressBar { + Q_OBJECT - /** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text - representation if needed. This assures that Qt can word-wrap long tooltip messages. - Tooltips longer than the provided size threshold (in characters) are wrapped. +Q_SIGNALS: + /** Emitted when the progressbar is clicked. The relative mouse coordinates + * of the click are passed to the signal. */ - class ToolTipToRichTextFilter : public QObject - { - Q_OBJECT - - public: - explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0); - - protected: - bool eventFilter(QObject *obj, QEvent *evt); - - private: - int size_threshold; - }; - - /** - * Makes a QTableView last column feel as if it was being resized from its left border. - * Also makes sure the column widths are never larger than the table's viewport. - * In Qt, all columns are resizable from the right, but it's not intuitive resizing the last column from the right. - * Usually our second to last columns behave as if stretched, and when on strech mode, columns aren't resizable - * interactively or programmatically. - * - * This helper object takes care of this issue. - * - */ - class TableViewLastColumnResizingFixer: public QObject - { - Q_OBJECT - - public: - TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent); - void stretchColumnWidth(int column); - - private: - QTableView* tableView; - int lastColumnMinimumWidth; - int allColumnsMinimumWidth; - int lastColumnIndex; - int columnCount; - int secondToLastColumnIndex; - - void adjustTableColumnsWidth(); - int getAvailableWidthForColumn(int column); - int getColumnsWidth(); - void connectViewHeadersSignals(); - void disconnectViewHeadersSignals(); - void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); - void resizeColumn(int nColumnIndex, int width); - - private Q_SLOTS: - void on_sectionResized(int logicalIndex, int oldSize, int newSize); - void on_geometriesChanged(); - }; - - bool GetStartOnSystemStartup(); - bool SetStartOnSystemStartup(bool fAutoStart); - - /** Save window size and position */ - void saveWindowGeometry(const QString& strSetting, QWidget *parent); - /** Restore window size and position */ - void restoreWindowGeometry(const QString& strSetting, const QSize &defaultSizeIn, QWidget *parent); - - /* Convert QString to OS specific boost path through UTF-8 */ - boost::filesystem::path qstringToBoostPath(const QString &path); - - /* Convert OS specific boost path to QString through UTF-8 */ - QString boostPathToQString(const boost::filesystem::path &path); - - /* Convert seconds into a QString with days, hours, mins, secs */ - QString formatDurationStr(int secs); - - /* Format CNodeStats.nServices bitmask into a user-readable string */ - QString formatServicesStr(quint64 mask); - - /* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/ - QString formatPingTime(double dPingTime); - - /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */ - QString formatTimeOffset(int64_t nTimeOffset); - - QString formatNiceTimeOffset(qint64 secs); - - class ClickableLabel : public QLabel - { - Q_OBJECT - - Q_SIGNALS: - /** Emitted when the label is clicked. The relative mouse coordinates of the click are - * passed to the signal. - */ - void clicked(const QPoint& point); - protected: - void mouseReleaseEvent(QMouseEvent *event); - }; - - class ClickableProgressBar : public QProgressBar - { - Q_OBJECT - - Q_SIGNALS: - /** Emitted when the progressbar is clicked. The relative mouse coordinates of the click are - * passed to the signal. - */ - void clicked(const QPoint& point); - protected: - void mouseReleaseEvent(QMouseEvent *event); - }; + void clicked(const QPoint &point); + +protected: + void mouseReleaseEvent(QMouseEvent *event); +}; #if defined(Q_OS_MAC) && QT_VERSION >= 0x050000 - // workaround for Qt OSX Bug: - // https://bugreports.qt-project.org/browse/QTBUG-15631 - // QProgressBar uses around 10% CPU even when app is in background - class ProgressBar : public ClickableProgressBar - { - bool event(QEvent *e) { - return (e->type() != QEvent::StyleAnimationUpdate) ? QProgressBar::event(e) : false; - } - }; +// workaround for Qt OSX Bug: +// https://bugreports.qt-project.org/browse/QTBUG-15631 +// QProgressBar uses around 10% CPU even when app is in background +class ProgressBar : public ClickableProgressBar { + bool event(QEvent *e) { + return (e->type() != QEvent::StyleAnimationUpdate) + ? QProgressBar::event(e) + : false; + } +}; #else - typedef ClickableProgressBar ProgressBar; +typedef ClickableProgressBar ProgressBar; #endif } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H