15 #include "validation.h" 25 #define _WIN32_WINNT 0x0501 29 #define _WIN32_IE 0x0501 30 #define WIN32_LEAN_AND_MEAN 1 39 #include <boost/filesystem.hpp> 40 #include <boost/filesystem/fstream.hpp> 41 #if BOOST_FILESYSTEM_VERSION >= 3 42 #include <boost/filesystem/detail/utf8_codecvt_facet.hpp> 44 #include <boost/scoped_array.hpp> 46 #include <QAbstractItemView> 47 #include <QApplication> 50 #include <QDesktopServices> 51 #include <QDesktopWidget> 52 #include <QDoubleValidator> 53 #include <QFileDialog> 57 #include <QTextDocument> 59 #include <QMouseEvent> 61 #if QT_VERSION < 0x050000 67 #if QT_VERSION >= 0x50200 68 #include <QFontDatabase> 71 #if BOOST_FILESYSTEM_VERSION >= 3 72 static boost::filesystem::detail::utf8_codecvt_facet utf8;
76 extern double NSAppKitVersionNumber;
77 #if !defined(NSAppKitVersionNumber10_8) 78 #define NSAppKitVersionNumber10_8 1187 80 #if !defined(NSAppKitVersionNumber10_9) 81 #define NSAppKitVersionNumber10_9 1265 89 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm");
94 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
99 #if QT_VERSION >= 0x50200 100 return QFontDatabase::systemFont(QFontDatabase::FixedFont);
102 QFont font(
"Monospace");
103 #if QT_VERSION >= 0x040800 104 font.setStyleHint(QFont::Monospace);
106 font.setStyleHint(QFont::TypeWriter);
114 parent->setFocusProxy(widget);
117 #if QT_VERSION >= 0x040700 120 widget->setPlaceholderText(QObject::tr(
"Enter a Dash address (e.g. %1)").arg(
"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg"));
128 QDoubleValidator *amountValidator =
new QDoubleValidator(parent);
129 amountValidator->setDecimals(8);
130 amountValidator->setBottom(0.0);
131 widget->setValidator(amountValidator);
132 widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
138 if(!uri.isValid() || uri.scheme() != QString(
"dash"))
144 if (rv.
address.endsWith(
"/")) {
149 #if QT_VERSION < 0x050000 150 QList<QPair<QString, QString> > items = uri.queryItems();
152 QUrlQuery uriQuery(uri);
153 QList<QPair<QString, QString> > items = uriQuery.queryItems();
157 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
159 bool fShouldReturnFalse =
false;
160 if (i->first.startsWith(
"req-"))
162 i->first.remove(0, 4);
163 fShouldReturnFalse =
true;
166 if (i->first ==
"label")
168 rv.
label = i->second;
169 fShouldReturnFalse =
false;
171 if (i->first ==
"IS")
173 if(i->second.compare(QString(
"1")) == 0)
176 fShouldReturnFalse =
false;
178 if (i->first ==
"message")
181 fShouldReturnFalse =
false;
183 else if (i->first ==
"amount")
185 if(!i->second.isEmpty())
192 fShouldReturnFalse =
false;
195 if (fShouldReturnFalse)
211 if(uri.startsWith(
"dash://", Qt::CaseInsensitive))
213 uri.replace(0, 7,
"dash:");
215 QUrl uriInstance(uri);
221 QString ret = QString(
"dash:%1").arg(info.
address);
230 if (!info.
label.isEmpty())
232 QString lbl(QUrl::toPercentEncoding(info.
label));
233 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
239 QString
msg(QUrl::toPercentEncoding(info.
message));
240 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(
msg);
246 ret += QString(
"%1IS=1").arg(paramCount == 0 ?
"?" :
"&");
257 CTxOut txOut(amount, script);
263 #if QT_VERSION < 0x050000 264 QString escaped = Qt::escape(str);
266 QString escaped = str.toHtmlEscaped();
268 escaped = escaped.replace(
" ",
" ");
271 escaped = escaped.replace(
"\n",
"<br>\n");
278 return HtmlEscape(QString::fromStdString(str), fMultiLine);
283 if(!view || !view->selectionModel())
285 QModelIndexList selection = view->selectionModel()->selectedRows(column);
287 if(!selection.isEmpty())
296 if(!view || !view->selectionModel())
297 return QList<QModelIndex>();
298 return view->selectionModel()->selectedRows(column);
302 const QString &filter,
303 QString *selectedSuffixOut)
305 QString selectedFilter;
309 #if QT_VERSION < 0x050000 310 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
312 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
323 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
324 QString selectedSuffix;
325 if(filter_re.exactMatch(selectedFilter))
327 selectedSuffix = filter_re.cap(1);
334 if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
339 result.append(selectedSuffix);
344 if(selectedSuffixOut)
346 *selectedSuffixOut = selectedSuffix;
352 const QString &filter,
353 QString *selectedSuffixOut)
355 QString selectedFilter;
359 #if QT_VERSION < 0x050000 360 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
362 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
372 if(selectedSuffixOut)
375 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
376 QString selectedSuffix;
377 if(filter_re.exactMatch(selectedFilter))
379 selectedSuffix = filter_re.cap(1);
381 *selectedSuffixOut = selectedSuffix;
388 if(QThread::currentThread() != qApp->thread())
390 return Qt::BlockingQueuedConnection;
394 return Qt::DirectConnection;
400 QWidget *atW = QApplication::widgetAt(w->mapToGlobal(
p));
401 if (!atW)
return false;
402 return atW->topLevelWidget() == w;
410 &&
checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
411 &&
checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
416 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
419 if (boost::filesystem::exists(pathDebug))
428 if (boost::filesystem::exists(pathConfig))
437 if (boost::filesystem::exists(pathConfig))
446 if (boost::filesystem::exists(backupsDir))
452 #if defined(Q_OS_MAC) 465 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 466 if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_8)
468 if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
470 QFont::insertSubstitution(
".Lucida Grande UI",
"Lucida Grande");
474 if (language ==
"zh_CN" || language ==
"zh_TW" || language ==
"zh_HK")
475 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Heiti SC");
476 else if (language ==
"ja")
477 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Songti SC");
479 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Lucida Grande");
488 size_threshold(size_threshold)
495 if(evt->type() == QEvent::ToolTipChange)
497 QWidget *widget =
static_cast<QWidget*
>(obj);
498 QString tooltip = widget->toolTip();
502 if(!Qt::mightBeRichText(tooltip))
506 tooltip =
"<qt style='white-space:pre'>" + tooltip +
"</qt>";
507 widget->setToolTip(tooltip);
511 return QObject::eventFilter(obj, evt);
531 #if QT_VERSION < 0x050000 532 tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
534 tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
540 tableView->setColumnWidth(nColumnIndex, width);
541 tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
546 int nColumnsWidthSum = 0;
549 nColumnsWidthSum +=
tableView->horizontalHeader()->sectionSize(i);
551 return nColumnsWidthSum;
557 int nTableWidth =
tableView->horizontalHeader()->width();
562 nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
575 int nTableWidth =
tableView->horizontalHeader()->width();
577 if (nColsWidth > nTableWidth)
596 if (newSize > remainingWidth)
621 lastColumnMinimumWidth(lastColMinimumWidth),
622 allColumnsMinimumWidth(allColsMinimumWidth)
633 boost::filesystem::path
static StartupShortcutPath()
637 return GetSpecialFolderPath(CSIDL_STARTUP) /
"Dash Core.lnk";
639 return GetSpecialFolderPath(CSIDL_STARTUP) /
"Dash Core (testnet).lnk";
640 return GetSpecialFolderPath(CSIDL_STARTUP) /
strprintf(
"Dash Core (%s).lnk", chain);
646 return boost::filesystem::exists(StartupShortcutPath());
652 boost::filesystem::remove(StartupShortcutPath());
659 IShellLink* psl = NULL;
660 HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
661 CLSCTX_INPROC_SERVER, IID_IShellLink,
662 reinterpret_cast<void**>(&psl));
668 GetModuleFileName(NULL, pszExePath,
sizeof(pszExePath));
671 QString strArgs =
"-min";
676 boost::scoped_array<TCHAR> args(
new TCHAR[strArgs.length() + 1]);
678 strArgs.toWCharArray(args.get());
680 args[strArgs.length()] =
'\0';
684 psl->SetPath(pszExePath);
685 PathRemoveFileSpec(pszExePath);
686 psl->SetWorkingDirectory(pszExePath);
687 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
689 psl->SetArguments(strArgs.toStdString().c_str());
691 psl->SetArguments(args.get());
696 IPersistFile* ppf = NULL;
697 hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
702 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().
string().c_str(), -1, pwsz,
MAX_PATH);
704 hres = ppf->Save(pwsz, TRUE);
717 #elif defined(Q_OS_LINUX) 722 boost::filesystem::path
static GetAutostartDir()
724 namespace fs = boost::filesystem;
726 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
727 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
728 char* pszHome = getenv(
"HOME");
729 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
733 boost::filesystem::path
static GetAutostartFilePath()
737 return GetAutostartDir() /
"dashcore.desktop";
738 return GetAutostartDir() /
strprintf(
"dashcore-%s.lnk", chain);
743 boost::filesystem::ifstream optionFile(GetAutostartFilePath());
744 if (!optionFile.good())
748 while (!optionFile.eof())
750 getline(optionFile, line);
751 if (line.find(
"Hidden") != std::string::npos &&
752 line.find(
"true") != std::string::npos)
763 boost::filesystem::remove(GetAutostartFilePath());
767 memset(pszExePath, 0,
sizeof(pszExePath));
768 if (readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath)-1) == -1)
771 boost::filesystem::create_directories(GetAutostartDir());
773 boost::filesystem::ofstream optionFile(GetAutostartFilePath(),
std::ios_base::out|std::ios_base::trunc);
774 if (!optionFile.good())
778 optionFile <<
"[Desktop Entry]\n";
779 optionFile <<
"Type=Application\n";
781 optionFile <<
"Name=Dash Core\n";
783 optionFile <<
strprintf(
"Name=Dash Core (%s)\n", chain);
784 optionFile <<
"Exec=" << pszExePath <<
strprintf(
" -min -testnet=%d -regtest=%d\n",
GetBoolArg(
"-testnet",
false),
GetBoolArg(
"-regtest",
false));
785 optionFile <<
"Terminal=false\n";
786 optionFile <<
"Hidden=false\n";
793 #elif defined(Q_OS_MAC) 796 #include <CoreFoundation/CoreFoundation.h> 797 #include <CoreServices/CoreServices.h> 799 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
800 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
803 CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, NULL);
804 for(
int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
805 LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
806 UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
807 CFURLRef currentItemURL = NULL;
809 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 810 if(&LSSharedFileListItemCopyResolvedURL)
811 currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL);
812 #if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100 814 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
817 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
820 if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
822 CFRelease(currentItemURL);
826 CFRelease(currentItemURL);
834 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
835 LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
836 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
842 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
843 LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
844 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
846 if(fAutoStart && !foundItem) {
848 LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, bitcoinAppUrl, NULL, NULL);
850 else if(!fAutoStart && foundItem) {
852 LSSharedFileListItemRemove(loginItems, foundItem);
867 if(!
settings.value(
"fMigrationDone121",
false).toBool()) {
871 settings.setValue(
"fMigrationDone121",
true);
878 settings.setValue(strSetting +
"Pos", parent->pos());
879 settings.setValue(strSetting +
"Size", parent->size());
885 QPoint pos =
settings.value(strSetting +
"Pos").toPoint();
886 QSize size =
settings.value(strSetting +
"Size", defaultSize).toSize();
888 parent->resize(size);
891 if ((!pos.x() && !pos.y()) || (QApplication::desktop()->screenNumber(parent) == -1))
893 QRect screen = QApplication::desktop()->screenGeometry();
894 QPoint defaultPos = screen.center() -
895 QPoint(defaultSize.width() / 2, defaultSize.height() / 2);
896 parent->resize(defaultSize);
897 parent->move(defaultPos);
905 QString theme =
settings.value(
"theme",
"").toString();
907 if(!theme.isEmpty()){
910 return QString(
"light");
919 QString theme =
settings.value(
"theme",
"").toString();
921 if(!theme.isEmpty()){
922 cssName = QString(
":/css/") + theme;
925 cssName = QString(
":/css/light");
926 settings.setValue(
"theme",
"light");
929 QFile qFile(cssName);
930 if (qFile.open(QFile::ReadOnly)) {
931 styleSheet = QLatin1String(qFile.readAll());
939 QApplication::clipboard()->setText(str, QClipboard::Clipboard);
940 QApplication::clipboard()->setText(str, QClipboard::Selection);
943 #if BOOST_FILESYSTEM_VERSION >= 3 946 return boost::filesystem::path(path.toStdString(), utf8);
951 return QString::fromStdString(path.string(utf8));
954 #warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older 957 return boost::filesystem::path(path.toStdString());
962 return QString::fromStdString(path.string());
969 int days = secs / 86400;
970 int hours = (secs % 86400) / 3600;
971 int mins = (secs % 3600) / 60;
972 int seconds = secs % 60;
975 strList.append(QString(QObject::tr(
"%1 d")).arg(days));
977 strList.append(QString(QObject::tr(
"%1 h")).arg(hours));
979 strList.append(QString(QObject::tr(
"%1 m")).arg(mins));
980 if (seconds || (!days && !hours && !mins))
981 strList.append(QString(QObject::tr(
"%1 s")).arg(seconds));
983 return strList.join(
" ");
991 for (
int i = 0; i < 8; i++) {
992 uint64_t check = 1 << i;
998 strList.append(
"NETWORK");
1001 strList.append(
"GETUTXO");
1004 strList.append(
"BLOOM");
1007 strList.append(QString(
"%1[%2]").arg(
"UNKNOWN").arg(check));
1013 return strList.join(
" & ");
1015 return QObject::tr(
"None");
1020 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));
1025 return QString(QObject::tr(
"%1 s")).arg(QString::number((
int)
nTimeOffset, 10));
1031 QString timeBehindText;
1032 const int HOUR_IN_SECONDS = 60*60;
1033 const int DAY_IN_SECONDS = 24*60*60;
1034 const int WEEK_IN_SECONDS = 7*24*60*60;
1035 const int YEAR_IN_SECONDS = 31556952;
1038 timeBehindText = QObject::tr(
"%n second(s)",
"",secs);
1040 else if(secs < 2*HOUR_IN_SECONDS)
1042 timeBehindText = QObject::tr(
"%n minute(s)",
"",secs/60);
1044 else if(secs < 2*DAY_IN_SECONDS)
1046 timeBehindText = QObject::tr(
"%n hour(s)",
"",secs/HOUR_IN_SECONDS);
1048 else if(secs < 2*WEEK_IN_SECONDS)
1050 timeBehindText = QObject::tr(
"%n day(s)",
"",secs/DAY_IN_SECONDS);
1052 else if(secs < YEAR_IN_SECONDS)
1054 timeBehindText = QObject::tr(
"%n week(s)",
"",secs/WEEK_IN_SECONDS);
1058 qint64 years = secs / YEAR_IN_SECONDS;
1059 qint64 remainder = secs % YEAR_IN_SECONDS;
1060 timeBehindText = QObject::tr(
"%1 and %2").arg(QObject::tr(
"%n year(s)",
"", years)).arg(QObject::tr(
"%n week(s)",
"", remainder/WEEK_IN_SECONDS));
1062 return timeBehindText;
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
void SubstituteFonts(const QString &language)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
void mouseReleaseEvent(QMouseEvent *event)
void on_sectionResized(int logicalIndex, int oldSize, int newSize)
void mouseReleaseEvent(QMouseEvent *event)
bool isObscured(QWidget *w)
QString boostPathToQString(const boost::filesystem::path &path)
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
static const std::string TESTNET
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
static int64_t nTimeOffset
bool eventFilter(QObject *obj, QEvent *evt)
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
Qt::ConnectionType blockingGUIThreadConnection()
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
void copyEntryData(QAbstractItemView *view, int column, int role)
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
bool GetBoolArg(const std::string &strArg, bool fDefault)
void setClipboard(const QString &str)
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
void resizeColumn(int nColumnIndex, int width)
void adjustTableColumnsWidth()
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
QString formatTimeOffset(int64_t nTimeOffset)
void disconnectViewHeadersSignals()
QString HtmlEscape(const QString &str, bool fMultiLine)
bool isDust(const QString &address, const CAmount &amount)
void setCheckValidator(const QValidator *v)
int lastColumnMinimumWidth
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
CScript GetScriptForDestination(const CTxDestination &dest)
QString formatBitcoinURI(const SendCoinsRecipient &info)
void stretchColumnWidth(int column)
QString formatNiceTimeOffset(qint64 secs)
bool GetStartOnSystemStartup()
bool SetStartOnSystemStartup(bool fAutoStart)
const boost::filesystem::path & GetBackupsDir()
bool IsDust(const CFeeRate &minRelayTxFee) const
void clicked(const QPoint &point)
void clicked(const QPoint &point)
void connectViewHeadersSignals()
int getAvailableWidthForColumn(int column)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
void on_geometriesChanged()
std::string ChainNameFromCommandLine()
QList< QModelIndex > getEntryData(QAbstractItemView *view, int column)
QString formatServicesStr(quint64 mask)
boost::filesystem::path GetMasternodeConfigFile()
int secondToLastColumnIndex
static const std::string MAIN
QString formatPingTime(double dPingTime)
QString formatDurationStr(int secs)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
bool checkPoint(const QPoint &p, const QWidget *w)
boost::filesystem::path qstringToBoostPath(const QString &path)
TableViewLastColumnResizingFixer(QTableView *table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent)
int allColumnsMinimumWidth
boost::filesystem::path GetConfigFile()
QString dateTimeStr(const QDateTime &date)