aboutsummaryrefslogtreecommitdiff
path: root/src/qt/guiutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/guiutil.cpp')
-rw-r--r--src/qt/guiutil.cpp150
1 files changed, 118 insertions, 32 deletions
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 13fd63274..6912b9312 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2013 The Bitcoin Core developers
+// 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.
@@ -11,7 +11,7 @@
#include "primitives/transaction.h"
#include "init.h"
-#include "main.h"
+#include "policy/policy.h"
#include "protocol.h"
#include "script/script.h"
#include "script/standard.h"
@@ -55,6 +55,7 @@
#include <QSettings>
#include <QTextDocument> // for Qt::mightBeRichText
#include <QThread>
+#include <QMouseEvent>
#if QT_VERSION < 0x050000
#include <QUrl>
@@ -62,6 +63,10 @@
#include <QUrlQuery>
#endif
+#if QT_VERSION >= 0x50200
+#include <QFontDatabase>
+#endif
+
#if BOOST_FILESYSTEM_VERSION >= 3
static boost::filesystem::detail::utf8_codecvt_facet utf8;
#endif
@@ -88,22 +93,40 @@ QString dateTimeStr(qint64 nTime)
return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
}
-QFont bitcoinAddressFont()
+QFont fixedPitchFont()
{
QFont font("Cursive");
font.setFamily("Comic Sans MS");
return font;
}
+// 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 &params)
+{
+ std::vector<unsigned char> 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)
{
parent->setFocusProxy(widget);
- widget->setFont(bitcoinAddressFont());
+ 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 Dogecoin address (e.g. %1)").arg("DEaT9KZM6b6oDZMr8pj7pWTLZSdtYZFAx8"));
+ widget->setPlaceholderText(QObject::tr("Enter a Dogecoin address (e.g. %1)").arg(
+ QString::fromStdString(DummyAddress(Params()))));
#endif
widget->setValidator(new BitcoinAddressEntryValidator(parent));
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
@@ -120,7 +143,7 @@ void setupAmountWidget(QLineEdit *widget, QWidget *parent)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
- // return if URI is not valid or is no bitcoin: URI
+ // return if URI is not valid or is no dogecoin: URI
if(!uri.isValid() || uri.scheme() != QString("dogecoin"))
return false;
@@ -161,10 +184,7 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
if(!i->second.isEmpty())
{
- // Parse amount in C locale with no number separators
- QLocale locale(QLocale::c());
- locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
- if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount, locale))
+ if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
{
return false;
}
@@ -184,9 +204,9 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
{
- // Convert bitcoin:// to bitcoin:
+ // Convert dogecoin:// to dogecoin:
//
- // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
+ // Cannot handle this later, because dogecoin:// will cause Qt to see the part after // as host,
// which will lower-case it (and thus invalidate the address).
if(uri.startsWith("dogecoin://", Qt::CaseInsensitive))
{
@@ -216,7 +236,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
if (!info.message.isEmpty())
{
- QString msg(QUrl::toPercentEncoding(info.message));;
+ QString msg(QUrl::toPercentEncoding(info.message));
ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg);
paramCount++;
}
@@ -229,7 +249,7 @@ 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(::minRelayTxFee);
+ return txOut.IsDust(dustRelayFee);
}
QString HtmlEscape(const QString& str, bool fMultiLine)
@@ -264,6 +284,13 @@ void copyEntryData(QAbstractItemView *view, int column, int role)
}
}
+QList<QModelIndex> getEntryData(QAbstractItemView *view, int column)
+{
+ if(!view || !view->selectionModel())
+ return QList<QModelIndex>();
+ return view->selectionModel()->selectedRows(column);
+}
+
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
@@ -390,7 +417,7 @@ 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
+// 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
@@ -422,9 +449,9 @@ void SubstituteFonts(const QString& language)
#endif
}
-ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) :
+ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, QObject *parent) :
QObject(parent),
- size_threshold(size_threshold)
+ size_threshold(_size_threshold)
{
}
@@ -501,7 +528,7 @@ int TableViewLastColumnResizingFixer::getAvailableWidthForColumn(int column)
return nResult;
}
-// Make sure we don't make the columns wider than the tables viewport width.
+// Make sure we don't make the columns wider than the table's viewport width.
void TableViewLastColumnResizingFixer::adjustTableColumnsWidth()
{
disconnectViewHeadersSignals();
@@ -535,7 +562,7 @@ void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int o
}
}
-// When the tabless 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()
{
@@ -551,7 +578,8 @@ void TableViewLastColumnResizingFixer::on_geometriesChanged()
* 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) :
+TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent) :
+ QObject(parent),
tableView(table),
lastColumnMinimumWidth(lastColMinimumWidth),
allColumnsMinimumWidth(allColsMinimumWidth)
@@ -567,12 +595,12 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t
#ifdef WIN32
boost::filesystem::path static StartupShortcutPath()
{
- if (GetBoolArg("-testnet", false))
+ std::string chain = ChainNameFromCommandLine();
+ if (chain == CBaseChainParams::MAIN)
+ return GetSpecialFolderPath(CSIDL_STARTUP) / "Dogecoin.lnk";
+ if (chain == CBaseChainParams::TESTNET) // Remove this special case when CBaseChainParams::TESTNET = "testnet4"
return GetSpecialFolderPath(CSIDL_STARTUP) / "Dogecoin (testnet).lnk";
- else if (GetBoolArg("-regtest", false))
- return GetSpecialFolderPath(CSIDL_STARTUP) / "Dogecoin (regtest).lnk";
-
- return GetSpecialFolderPath(CSIDL_STARTUP) / "Dogecoin.lnk";
+ return GetSpecialFolderPath(CSIDL_STARTUP) / strprintf("Dogecoin (%s).lnk", chain);
}
bool GetStartOnSystemStartup()
@@ -667,7 +695,10 @@ boost::filesystem::path static GetAutostartDir()
boost::filesystem::path static GetAutostartFilePath()
{
- return GetAutostartDir() / "dogecoin.desktop";
+ std::string chain = ChainNameFromCommandLine();
+ if (chain == CBaseChainParams::MAIN)
+ return GetAutostartDir() / "bitcoin.desktop";
+ return GetAutostartDir() / strprintf("bitcoin-%s.lnk", chain);
}
bool GetStartOnSystemStartup()
@@ -705,15 +736,14 @@ bool SetStartOnSystemStartup(bool fAutoStart)
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 (GetBoolArg("-testnet", false))
- optionFile << "Name=Dogecoin (testnet)\n";
- else if (GetBoolArg("-regtest", false))
- optionFile << "Name=Dogecoin (regtest)\n";
- else
+ if (chain == CBaseChainParams::MAIN)
optionFile << "Name=Dogecoin\n";
+ else
+ optionFile << strprintf("Name=Dogecoin (%s)\n", chain);
optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false));
optionFile << "Terminal=false\n";
optionFile << "Hidden=false\n";
@@ -724,6 +754,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
#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
#include <CoreFoundation/CoreFoundation.h>
@@ -786,6 +818,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
return true;
}
+#pragma GCC diagnostic pop
#else
bool GetStartOnSystemStartup() { return false; }
@@ -885,6 +918,12 @@ QString formatServicesStr(quint64 mask)
case NODE_BLOOM:
strList.append("BLOOM");
break;
+ case NODE_WITNESS:
+ strList.append("WITNESS");
+ break;
+ case NODE_XTHIN:
+ strList.append("XTHIN");
+ break;
default:
strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
}
@@ -899,7 +938,7 @@ QString formatServicesStr(quint64 mask)
QString formatPingTime(double dPingTime)
{
- return dPingTime == 0 ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10));
+ return (dPingTime == std::numeric_limits<int64_t>::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)
@@ -907,4 +946,51 @@ QString formatTimeOffset(int64_t nTimeOffset)
return QString(QObject::tr("%1 s")).arg(QString::number((int)nTimeOffset, 10));
}
+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
+ {
+ 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));
+ }
+ return timeBehindText;
+}
+
+void ClickableLabel::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_EMIT clicked(event->pos());
+}
+
+void ClickableProgressBar::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_EMIT clicked(event->pos());
+}
+
} // namespace GUIUtil