25 #define _WIN32_WINNT 0x0501
29 #define _WIN32_IE 0x0501
30 #define WIN32_LEAN_AND_MEAN 1
39 #include <QAbstractItemView>
40 #include <QApplication>
43 #include <QDesktopServices>
44 #include <QDesktopWidget>
46 #include <QRegularExpression>
47 #include <QRegularExpressionValidator>
48 #include <QFileDialog>
53 #include <QTextDocument>
56 #include <QMouseEvent>
58 #define URI_SCHEME "pivx"
71 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm");
76 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm:ss");
81 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
86 QFont font(
"Monospace");
87 font.setStyleHint(QFont::Monospace);
96 static CAmount parseValue(
const QString& text,
int displayUnit,
bool* valid_out)
106 return valid ? val : 0;
112 CAmount parseValue(
const QString& amount,
int displayUnit)
114 bool isValid =
false;
115 CAmount value = GUIUtil::parseValue(amount, displayUnit, &isValid);
116 return isValid ? value : 0;
131 parent->setFocusProxy(widget);
136 widget->setPlaceholderText(QObject::tr(
"Enter PIVX address (e.g. %1)").arg(
"D7VFR83SQbiezrW72hjcWJtcfip5krte2Z"));
143 QRegularExpression rx(
"^(\\d{0,8})((\\.|,)\\d{1,8})?$");
144 QValidator *validator =
new QRegularExpressionValidator(rx, widget);
145 widget->setValidator(validator);
150 const int cpos = widget->cursorPosition();
151 widget->setText(str);
152 if (cpos > str.size())
return;
153 widget->setCursorPosition(cpos);
159 if (!uri.isValid() || uri.scheme() != QString(
URI_SCHEME))
165 if (rv.
address.endsWith(
"/")) {
170 QUrlQuery uriQuery(uri);
171 QList<QPair<QString, QString> > items = uriQuery.queryItems();
172 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
174 bool fShouldReturnFalse =
false;
175 if (i->first.startsWith(
"req-")) {
176 i->first.remove(0, 4);
177 fShouldReturnFalse =
true;
180 if (i->first ==
"label") {
181 rv.
label = i->second;
182 fShouldReturnFalse =
false;
184 if (i->first ==
"message") {
186 fShouldReturnFalse =
false;
187 }
else if (i->first ==
"amount") {
188 if (!i->second.isEmpty()) {
193 fShouldReturnFalse =
false;
196 if (fShouldReturnFalse)
211 if (uri.startsWith(
URI_SCHEME "://", Qt::CaseInsensitive)) {
214 QUrl uriInstance(uri);
228 if (!info.
label.isEmpty()) {
229 QString lbl(QUrl::toPercentEncoding(info.
label));
230 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
235 QString msg(QUrl::toPercentEncoding(info.
message));
236 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(msg);
247 CTxOut txOut(amount, script);
253 QString escaped = str.toHtmlEscaped();
254 escaped = escaped.replace(
" ",
" ");
256 escaped = escaped.replace(
"\n",
"<br>\n");
263 return HtmlEscape(QString::fromStdString(str), fMultiLine);
268 if (!view || !view->selectionModel())
270 QModelIndexList selection = view->selectionModel()->selectedRows(column);
272 if (!selection.isEmpty()) {
280 if (!view || !view->selectionModel())
282 QModelIndexList selection = view->selectionModel()->selectedRows(column);
284 if (!selection.isEmpty()) {
286 return (selection.at(0).data(role));
291 QString
getSaveFileName(QWidget* parent,
const QString& caption,
const QString& dir,
const QString& filter, QString* selectedSuffixOut)
293 QString selectedFilter;
297 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
307 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
308 QString selectedSuffix;
309 if (filter_re.exactMatch(selectedFilter)) {
310 selectedSuffix = filter_re.cap(1);
314 QFileInfo info(result);
315 if (!result.isEmpty()) {
316 if (info.suffix().isEmpty() && !selectedSuffix.isEmpty()) {
318 if (!result.endsWith(
"."))
320 result.append(selectedSuffix);
325 if (selectedSuffixOut) {
326 *selectedSuffixOut = selectedSuffix;
331 QString
getOpenFileName(QWidget* parent,
const QString& caption,
const QString& dir,
const QString& filter, QString* selectedSuffixOut)
333 QString selectedFilter;
337 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
346 if (selectedSuffixOut) {
348 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
349 QString selectedSuffix;
350 if (filter_re.exactMatch(selectedFilter)) {
351 selectedSuffix = filter_re.cap(1);
353 *selectedSuffixOut = selectedSuffix;
360 if (QThread::currentThread() != qApp->thread()) {
361 return Qt::BlockingQueuedConnection;
363 return Qt::DirectConnection;
369 QWidget* atW = QApplication::widgetAt(w->mapToGlobal(p));
370 if (!atW)
return false;
371 return atW->window() == w;
376 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));
387 if (w->isMinimized()) {
401 if (fs::exists(path)) {
405 if (isTextFile && !ret) {
406 ret = QProcess::startDetached(
"/usr/bin/open", QStringList{
"-t",
boostPathToQString(path)});
434 size_threshold(size_threshold)
440 if (evt->type() == QEvent::ToolTipChange) {
441 QWidget* widget =
static_cast<QWidget*
>(obj);
442 QString tooltip = widget->toolTip();
443 if (tooltip.size() >
size_threshold && !tooltip.startsWith(
"<qt")) {
445 if (!Qt::mightBeRichText(tooltip))
449 tooltip =
"<qt style='white-space:pre'>" + tooltip +
"</qt>";
450 widget->setToolTip(tooltip);
454 return QObject::eventFilter(obj, evt);
458 fs::path
static StartupShortcutPath()
462 return GetSpecialFolderPath(CSIDL_STARTUP) /
"PIVX (testnet).lnk";
464 return GetSpecialFolderPath(CSIDL_STARTUP) /
"PIVX (regtest).lnk";
466 return GetSpecialFolderPath(CSIDL_STARTUP) /
"PIVX.lnk";
472 return fs::exists(StartupShortcutPath());
478 fs::remove(StartupShortcutPath());
481 CoInitialize(
nullptr);
484 IShellLinkW* psl =
nullptr;
485 HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
486 CLSCTX_INPROC_SERVER, IID_IShellLinkW,
487 reinterpret_cast<void**
>(&psl));
492 GetModuleFileNameW(
nullptr, pszExePath, ARRAYSIZE(pszExePath));
495 QString strArgs =
"-min";
500 psl->SetPath(pszExePath);
501 PathRemoveFileSpecW(pszExePath);
502 psl->SetWorkingDirectory(pszExePath);
503 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
504 psl->SetArguments(strArgs.toStdWString().c_str());
508 IPersistFile* ppf =
nullptr;
509 hres = psl->QueryInterface(IID_IPersistFile,
reinterpret_cast<void**
>(&ppf));
512 hres = ppf->Save(StartupShortcutPath().wstring().c_str(), TRUE);
526 #elif defined(Q_OS_LINUX)
531 fs::path
static GetAutostartDir()
533 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
534 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
535 char* pszHome = getenv(
"HOME");
536 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
540 fs::path
static GetAutostartFilePath()
542 return GetAutostartDir() /
"pivx.desktop";
548 if (!optionFile.good())
552 while (!optionFile.eof()) {
553 getline(optionFile, line);
554 if (line.find(
"Hidden") != std::string::npos &&
555 line.find(
"true") != std::string::npos)
566 fs::remove(GetAutostartFilePath());
569 ssize_t r = readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath) - 1);
572 pszExePath[r] =
'\0';
574 fs::create_directories(GetAutostartDir());
576 fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc);
577 if (!optionFile.good())
580 optionFile <<
"[Desktop Entry]\n";
581 optionFile <<
"Type=Application\n";
583 optionFile <<
"Name=PIVX (testnet)\n";
585 optionFile <<
"Name=PIVX (regtest)\n";
587 optionFile <<
"Name=PIVX\n";
589 optionFile <<
"Terminal=false\n";
590 optionFile <<
"Hidden=false\n";
609 settings.setValue(strSetting +
"Pos", parent->pos());
610 settings.setValue(strSetting +
"Size", parent->size());
616 QPoint pos =
settings.value(strSetting +
"Pos").toPoint();
617 QSize size =
settings.value(strSetting +
"Size", defaultSize).toSize();
619 if (!pos.x() && !pos.y()) {
620 QRect screen = QGuiApplication::primaryScreen()->geometry();
621 pos.setX((screen.width() - size.width()) / 2);
622 pos.setY((screen.height() - size.height()) / 2);
625 parent->resize(size);
635 return (theme.operator!=(
"default") && theme.operator!=(
"default-dark"));
644 QString theme =
settings.value(
"theme",
"").toString();
648 settings.setValue(
"fCSSexternal",
true);
650 cssName = pathAddr.string().c_str() + theme +
"/css/theme.css";
653 settings.setValue(
"fCSSexternal",
false);
654 if (!theme.isEmpty()) {
655 cssName = QString(
":/css/") + theme;
657 cssName = QString(
":/css/default");
658 settings.setValue(
"theme",
"default");
662 QFile qFile(cssName);
663 if (qFile.open(QFile::ReadOnly)) {
664 styleSheet = QLatin1String(qFile.readAll());
672 QApplication::clipboard()->setText(str, QClipboard::Clipboard);
673 QApplication::clipboard()->setText(str, QClipboard::Selection);
678 return fs::path(path.toStdString());
683 return QString::fromStdString(path.string());
689 int days = secs / 86400;
690 int hours = (secs % 86400) / 3600;
691 int mins = (secs % 3600) / 60;
692 int seconds = secs % 60;
695 strList.append(QString(QObject::tr(
"%1 d")).arg(days));
697 strList.append(QString(QObject::tr(
"%1 h")).arg(hours));
699 strList.append(QString(QObject::tr(
"%1 m")).arg(mins));
700 if (seconds || (!days && !hours && !mins))
701 strList.append(QString(QObject::tr(
"%1 s")).arg(seconds));
703 return strList.join(
" ");
711 for (
int i = 0; i < 8; i++) {
712 uint64_t check = 1 << i;
716 strList.append(QObject::tr(
"NETWORK"));
720 strList.append(QObject::tr(
"BLOOM"));
723 strList.append(QString(
"%1[%2]").arg(QObject::tr(
"UNKNOWN")).arg(check));
729 return strList.join(
" & ");
731 return QObject::tr(
"None");
736 return dPingTime == 0 ? QObject::tr(
"N/A") : QString(QObject::tr(
"%1 ms")).arg(QString::number((
int)(dPingTime * 1000), 10));
741 return QString(QObject::tr(
"%1 s")).arg(QString::number((
int)nTimeOffset, 10));
int64_t CAmount
Amount in PIV (Can be negative)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Bitcoin address widget validator, checks for a valid bitcoin address.
Base58 entry widget validator, checks for valid characters and removes some whitespace.
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
static CAmount maxMoney()
Return maximum number of base units (Satoshis)
static QString floorHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, bool cleanRemainderZeros=false, bool isZPIV=false)
static QString floorWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, bool cleanRemainderZeros=false, bool isZPIV=false)
Format as string (with unit) but floor value up to "digits" settings.
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, bool cleanRemainderZeros=true)
Format as string.
static QString name(int unit, bool isZpiv=false)
Short name.
static const std::string REGTEST
static const std::string TESTNET
Serialized script, used inside transaction inputs and outputs.
An output of a transaction.
bool eventFilter(QObject *obj, QEvent *evt)
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
Line edit that can be marked as "invalid" to show input validation feedback.
void setCheckValidator(const QValidator *v)
void ForceActivation()
Force application activation on macOS.
Utility functions used by the PIVX Qt UI.
fs::path qstringToBoostPath(const QString &path)
bool isObscured(QWidget *w)
QString formatBalanceWithoutHtml(CAmount amount, int nDisplayUnit, bool isZpiv)
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
void updateWidgetTextAndCursorPosition(QLineEdit *widget, const QString &str)
QString HtmlEscape(const QString &str, bool fMultiLine)
bool isExternal(QString theme)
Check whether a theme is not built-in.
QString loadStyleSheet()
Load global CSS theme.
QString formatPingTime(double dPingTime)
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
Save window size and position.
QString dateTimeStrWithSeconds(const QDateTime &date)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
QFont bitcoinAddressFont()
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
QString boostPathToQString(const fs::path &path)
bool SetStartOnSystemStartup(bool fAutoStart)
void bringToFront(QWidget *w)
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
Restore window size and position.
QString dateTimeStr(const QDateTime &date)
QString formatDurationStr(int secs)
QVariant getEntryData(QAbstractItemView *view, int column, int role)
Return a field of the currently selected entry as a QString.
bool checkPoint(const QPoint &p, const QWidget *w)
QString formatBitcoinURI(const SendCoinsRecipient &info)
QString formatTimeOffset(int64_t nTimeOffset)
QString formatServicesStr(quint64 mask)
bool openFile(fs::path path, bool isTextFile)
QString formatBalance(CAmount amount, int nDisplayUnit, bool isZpiv)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
bool GetStartOnSystemStartup()
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
void setClipboard(const QString &str)
bool isDust(const QString &address, const CAmount &amount)
CWDestination DecodeDestination(const std::string &strAddress)
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
const char *const PIVX_CONF_FILENAME
const fs::path & GetDataDir(bool fNetSpecific)
fs::path GetConfigFile(const std::string &confPath)
fs::path GetMasternodeConfigFile()