29 #define _WIN32_WINNT 0x0501 33 #define _WIN32_IE 0x0501 34 #define WIN32_LEAN_AND_MEAN 1 43 #include <boost/scoped_array.hpp> 45 #include <QAbstractButton> 46 #include <QAbstractItemView> 47 #include <QApplication> 51 #include <QDesktopServices> 52 #include <QDesktopWidget> 53 #include <QDialogButtonBox> 54 #include <QDoubleValidator> 55 #include <QFileDialog> 59 #include <QTextDocument> 62 #include <QMouseEvent> 63 #include <QVBoxLayout> 65 #if QT_VERSION < 0x050000 71 #if QT_VERSION >= 0x50200 72 #include <QFontDatabase> 75 static fs::detail::utf8_codecvt_facet
utf8;
78 extern double NSAppKitVersionNumber;
79 #if !defined(NSAppKitVersionNumber10_8) 80 #define NSAppKitVersionNumber10_8 1187 82 #if !defined(NSAppKitVersionNumber10_9) 83 #define NSAppKitVersionNumber10_9 1265 86 #pragma GCC diagnostic push 87 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 89 #include <CoreServices/CoreServices.h> 111 {
"dark.css",
"Dark"},
112 {
"light.css",
"Light"},
113 {
"traditional.css",
"Traditional"}
149 static std::set<QWidget*> setRectsDisabled;
206 QString theme = QSettings().value(
"theme",
"").toString();
212 QString theme = QSettings().value(
"theme",
"").toString();
220 QIcon icon(strIconPath + strIcon);
222 for (
const QSize& size : icon.availableSizes()) {
223 QImage image(icon.pixmap(size).toImage());
224 image = image.convertToFormat(QImage::Format_ARGB32);
225 for (
int x = 0; x < image.width(); ++x) {
226 for (
int y = 0; y < image.height(); ++y) {
227 const QRgb rgb = image.pixel(x, y);
232 pColor = &qcolorAlternative;
234 image.setPixel(x, y, qRgba(pColor->red(), pColor->green(), pColor->blue(), qAlpha(rgb)));
237 themedIcon.addPixmap(QPixmap::fromImage(image));
249 button->setIcon(
getIcon(strIcon, color, colorAlternative));
250 button->setIconSize(size);
253 void setIcon(QAbstractButton* button,
const QString& strIcon,
const ThemedColor color,
const QSize& size)
260 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm");
265 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
269 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};
276 for(
int i=0; i<256; ++i) {
277 std::string s =
EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size());
281 sourcedata[sourcedata.size()-1] += 1;
288 parent->setFocusProxy(widget);
290 #if QT_VERSION >= 0x040700 293 widget->setPlaceholderText(QObject::tr(
"Enter a Dash address (e.g. %1)").arg(
302 QDoubleValidator *amountValidator =
new QDoubleValidator(parent);
303 amountValidator->setDecimals(8);
304 amountValidator->setBottom(0.0);
305 widget->setValidator(amountValidator);
306 widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
311 if (!QSettings().value(
"fAppearanceSetupDone",
false).toBool()) {
321 dlg.setObjectName(
"AppearanceSetup");
322 dlg.setWindowTitle(QObject::tr(
"Appearance Setup"));
323 dlg.setWindowIcon(QIcon(
":icons/bitcoin"));
325 QLabel lblHeading(QObject::tr(
"Please choose your preferred settings for the appearance of %1").arg(QObject::tr(PACKAGE_NAME)), &dlg);
326 lblHeading.setObjectName(
"lblHeading");
327 lblHeading.setWordWrap(
true);
328 QLabel lblSubHeading(QObject::tr(
"This can also be adjusted later in the \"Appearance\" tab of the preferences."), &dlg);
329 lblSubHeading.setObjectName(
"lblSubHeading");
330 lblSubHeading.setWordWrap(
true);
334 line.setFrameShape(QFrame::HLine);
335 QDialogButtonBox buttonBox(QDialogButtonBox::Save);
338 layout.addWidget(&lblHeading);
339 layout.addWidget(&lblSubHeading);
340 layout.addWidget(&line);
341 layout.addWidget(&appearance);
342 layout.addWidget(&buttonBox);
343 dlg.setLayout(&layout);
348 QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() {
349 QSettings().setValue(
"fAppearanceSetupDone",
true);
361 if(!uri.isValid() || uri.scheme() != QString(
"dash"))
367 if (rv.
address.endsWith(
"/")) {
372 #if QT_VERSION < 0x050000 373 QList<QPair<QString, QString> > items = uri.queryItems();
375 QUrlQuery uriQuery(uri);
376 QList<QPair<QString, QString> > items = uriQuery.queryItems();
379 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
381 bool fShouldReturnFalse =
false;
382 if (i->first.startsWith(
"req-"))
384 i->first.remove(0, 4);
385 fShouldReturnFalse =
true;
388 if (i->first ==
"label")
390 rv.
label = i->second;
391 fShouldReturnFalse =
false;
393 if (i->first ==
"IS")
396 fShouldReturnFalse =
false;
398 if (i->first ==
"message")
401 fShouldReturnFalse =
false;
403 else if (i->first ==
"amount")
405 if(!i->second.isEmpty())
412 fShouldReturnFalse =
false;
415 if (fShouldReturnFalse)
431 if(uri.startsWith(
"dash://", Qt::CaseInsensitive))
433 uri.replace(0, 7,
"dash:");
435 QUrl uriInstance(uri);
447 QString ret = QString(
"dash:%1").arg(info.
address);
456 if (!info.
label.isEmpty())
458 QString lbl(QUrl::toPercentEncoding(info.
label));
459 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
465 QString msg(QUrl::toPercentEncoding(info.
message));
466 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(msg);
477 CTxOut txOut(amount, script);
483 #if QT_VERSION < 0x050000 484 QString escaped = Qt::escape(str);
486 QString escaped = str.toHtmlEscaped();
488 escaped = escaped.replace(
" ",
" ");
491 escaped = escaped.replace(
"\n",
"<br>\n");
498 return HtmlEscape(QString::fromStdString(str), fMultiLine);
503 if(!view || !view->selectionModel())
505 QModelIndexList selection = view->selectionModel()->selectedRows(column);
507 if(!selection.isEmpty())
516 if(!view || !view->selectionModel())
517 return QList<QModelIndex>();
518 return view->selectionModel()->selectedRows(column);
522 const QString &filter,
523 QString *selectedSuffixOut)
525 QString selectedFilter;
529 #if QT_VERSION < 0x050000 530 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
532 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
543 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
544 QString selectedSuffix;
545 if(filter_re.exactMatch(selectedFilter))
547 selectedSuffix = filter_re.cap(1);
551 QFileInfo info(result);
552 if(!result.isEmpty())
554 if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
557 if(!result.endsWith(
"."))
559 result.append(selectedSuffix);
564 if(selectedSuffixOut)
566 *selectedSuffixOut = selectedSuffix;
572 const QString &filter,
573 QString *selectedSuffixOut)
575 QString selectedFilter;
579 #if QT_VERSION < 0x050000 580 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
582 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
592 if(selectedSuffixOut)
595 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
596 QString selectedSuffix;
597 if(filter_re.exactMatch(selectedFilter))
599 selectedSuffix = filter_re.cap(1);
601 *selectedSuffixOut = selectedSuffix;
608 if(QThread::currentThread() != qApp->thread())
610 return Qt::BlockingQueuedConnection;
614 return Qt::DirectConnection;
620 QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
621 if (!atW)
return false;
622 return atW->topLevelWidget() == w;
630 &&
checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
631 &&
checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
642 if (w->isMinimized()) {
654 fs::path pathDebug =
GetDataDir() /
"debug.log";
657 if (fs::exists(pathDebug))
666 if (fs::exists(pathConfig))
675 if (fs::exists(backupsDir))
681 #if defined(Q_OS_MAC) 694 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 695 if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_8)
697 if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
699 QFont::insertSubstitution(
".Lucida Grande UI",
"Lucida Grande");
703 if (language ==
"zh_CN" || language ==
"zh_TW" || language ==
"zh_HK")
704 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Heiti SC");
705 else if (language ==
"ja")
706 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Songti SC");
708 QFont::insertSubstitution(
".Helvetica Neue DeskInterface",
"Lucida Grande");
717 size_threshold(_size_threshold)
724 if(evt->type() == QEvent::ToolTipChange)
726 QWidget *widget =
static_cast<QWidget*
>(obj);
727 QString tooltip = widget->toolTip();
731 if(!Qt::mightBeRichText(tooltip))
735 tooltip =
"<qt style='white-space:pre'>" + tooltip +
"</qt>";
736 widget->setToolTip(tooltip);
740 return QObject::eventFilter(obj, evt);
760 #if QT_VERSION < 0x050000 761 tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
763 tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
769 tableView->setColumnWidth(nColumnIndex, width);
770 tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
775 int nColumnsWidthSum = 0;
778 nColumnsWidthSum +=
tableView->horizontalHeader()->sectionSize(i);
780 return nColumnsWidthSum;
786 int nTableWidth =
tableView->horizontalHeader()->width();
791 nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
804 int nTableWidth =
tableView->horizontalHeader()->width();
806 if (nColsWidth > nTableWidth)
825 if (newSize > remainingWidth)
850 lastColumnMinimumWidth(lastColMinimumWidth),
851 allColumnsMinimumWidth(allColsMinimumWidth)
862 fs::path
static StartupShortcutPath()
866 return GetSpecialFolderPath(CSIDL_STARTUP) /
"Dash Core.lnk";
868 return GetSpecialFolderPath(CSIDL_STARTUP) /
"Dash Core (testnet).lnk";
869 return GetSpecialFolderPath(CSIDL_STARTUP) /
strprintf(
"Dash Core (%s).lnk", chain);
875 return fs::exists(StartupShortcutPath());
881 fs::remove(StartupShortcutPath());
885 CoInitialize(
nullptr);
888 IShellLink* psl =
nullptr;
889 HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
890 CLSCTX_INPROC_SERVER, IID_IShellLink,
891 reinterpret_cast<void**>(&psl));
897 GetModuleFileName(
nullptr, pszExePath,
sizeof(pszExePath));
900 QString strArgs =
"-min";
905 boost::scoped_array<TCHAR> args(
new TCHAR[strArgs.length() + 1]);
907 strArgs.toWCharArray(args.get());
909 args[strArgs.length()] =
'\0';
913 psl->SetPath(pszExePath);
914 PathRemoveFileSpec(pszExePath);
915 psl->SetWorkingDirectory(pszExePath);
916 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
918 psl->SetArguments(strArgs.toStdString().c_str());
920 psl->SetArguments(args.get());
925 IPersistFile* ppf =
nullptr;
926 hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
931 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().
string().c_str(), -1, pwsz,
MAX_PATH);
933 hres = ppf->Save(pwsz, TRUE);
946 #elif defined(Q_OS_LINUX) 951 fs::path
static GetAutostartDir()
953 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
954 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
955 char* pszHome = getenv(
"HOME");
956 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
960 fs::path
static GetAutostartFilePath()
964 return GetAutostartDir() /
"dashcore.desktop";
965 return GetAutostartDir() /
strprintf(
"dashcore-%s.lnk", chain);
970 fs::ifstream optionFile(GetAutostartFilePath());
971 if (!optionFile.good())
975 while (!optionFile.eof())
977 getline(optionFile, line);
978 if (line.find(
"Hidden") != std::string::npos &&
979 line.find(
"true") != std::string::npos)
990 fs::remove(GetAutostartFilePath());
994 ssize_t r = readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath) - 1);
997 pszExePath[r] =
'\0';
999 fs::create_directories(GetAutostartDir());
1001 fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
1002 if (!optionFile.good())
1006 optionFile <<
"[Desktop Entry]\n";
1007 optionFile <<
"Type=Application\n";
1009 optionFile <<
"Name=Dash Core\n";
1011 optionFile <<
strprintf(
"Name=Dash Core (%s)\n", chain);
1013 optionFile <<
"Terminal=false\n";
1014 optionFile <<
"Hidden=false\n";
1021 #elif defined(Q_OS_MAC) 1024 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
1025 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
1027 CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list,
nullptr);
1028 if (listSnapshot ==
nullptr) {
1033 for(
int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
1034 LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
1035 UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
1036 CFURLRef currentItemURL =
nullptr;
1038 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 1039 if(&LSSharedFileListItemCopyResolvedURL)
1040 currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags,
nullptr);
1041 #if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100 1043 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL,
nullptr);
1046 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL,
nullptr);
1049 if(currentItemURL) {
1050 if (CFEqual(currentItemURL, findUrl)) {
1052 CFRelease(listSnapshot);
1053 CFRelease(currentItemURL);
1056 CFRelease(currentItemURL);
1060 CFRelease(listSnapshot);
1066 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
1067 if (bitcoinAppUrl ==
nullptr) {
1071 LSSharedFileListRef loginItems = LSSharedFileListCreate(
nullptr, kLSSharedFileListSessionLoginItems,
nullptr);
1072 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
1074 CFRelease(bitcoinAppUrl);
1080 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
1081 if (bitcoinAppUrl ==
nullptr) {
1085 LSSharedFileListRef loginItems = LSSharedFileListCreate(
nullptr, kLSSharedFileListSessionLoginItems,
nullptr);
1086 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
1088 if(fAutoStart && !foundItem) {
1090 LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
nullptr,
nullptr, bitcoinAppUrl,
nullptr,
nullptr);
1092 else if(!fAutoStart && foundItem) {
1094 LSSharedFileListItemRemove(loginItems, foundItem);
1097 CFRelease(bitcoinAppUrl);
1100 #pragma GCC diagnostic pop 1112 if(!settings.value(
"fMigrationDone121",
false).toBool()) {
1113 settings.remove(
"theme");
1114 settings.remove(
"nWindowPos");
1115 settings.remove(
"nWindowSize");
1116 settings.setValue(
"fMigrationDone121",
true);
1132 std::vector<QString> vecStylesheets;
1134 vecStylesheets.push_back(it.first);
1136 return vecStylesheets;
1141 std::vector<QString> vecThemes;
1143 if (!it.second.isEmpty()) {
1144 vecThemes.push_back(it.second);
1160 static std::unique_ptr<QString> stylesheet;
1161 static std::set<QWidget*> setWidgets;
1164 bool fStyleSheetChanged =
false;
1166 if (stylesheet ==
nullptr || fForceUpdate || fDebugCustomStyleSheets) {
1167 auto hasModified = [](
const std::vector<QString>& vecFiles) ->
bool {
1168 static std::map<const QString, QDateTime> mapLastModified;
1170 bool fModified =
false;
1171 for (
auto file = vecFiles.begin(); file != vecFiles.end() && !fModified; ++file) {
1172 QFileInfo info(*file);
1173 QDateTime lastModified = info.lastModified(), prevLastModified;
1174 auto it = mapLastModified.emplace(std::make_pair(*file, lastModified));
1175 prevLastModified = it.second ? QDateTime() : it.first->second;
1176 it.first->second = lastModified;
1177 fModified = prevLastModified != lastModified;
1182 auto loadFiles = [&](
const std::vector<QString>& vecFiles) ->
bool {
1183 if (!fForceUpdate && fDebugCustomStyleSheets && !hasModified(vecFiles)) {
1188 stylesheet = std::make_unique<QString>();
1190 for (
const auto& file : vecFiles) {
1192 if (!qFile.open(QFile::ReadOnly)) {
1193 throw std::runtime_error(
strprintf(
"%s: Failed to open file: %s", __func__, file.toStdString()));
1196 QString strStyle = QLatin1String(qFile.readAll());
1198 QRegularExpressionMatch osStyleMatch;
1199 QRegularExpression osStyleExp(
1201 "(<os=(?:'|\").+(?:'|\")>)" 1205 osStyleExp.setPatternOptions(QRegularExpression::MultilineOption);
1206 QRegularExpressionMatchIterator it = osStyleExp.globalMatch(strStyle);
1209 while (it.hasNext() && (osStyleMatch = it.next()).isValid()) {
1210 QStringList listMatches = osStyleMatch.capturedTexts();
1213 if (listMatches.size() % 4) {
1214 throw std::runtime_error(
strprintf(
"%s: Invalid <os=...></os> section in file %s", __func__, file.toStdString()));
1217 for (
int i = 0; i < listMatches.size(); i += 4) {
1218 if (!listMatches[i + 1].contains(QString::fromStdString(platformName))) {
1221 strStyle.replace(listMatches[i],
"");
1224 strStyle.replace(listMatches[i + 1],
"");
1225 strStyle.replace(listMatches[i + 3],
"");
1229 stylesheet->append(strStyle);
1234 auto pathToFile = [&](
const QString& file) -> QString {
1238 std::vector<QString> vecFiles;
1241 vecFiles.push_back(pathToFile(
"general"));
1245 fStyleSheetChanged = loadFiles(vecFiles);
1248 bool fUpdateStyleSheet = fForceUpdate || (fDebugCustomStyleSheets && fStyleSheetChanged);
1251 setWidgets.insert(widget);
1252 widget->setStyleSheet(*stylesheet);
1255 QWidgetList allWidgets = QApplication::allWidgets();
1256 auto it = setWidgets.begin();
1257 while (it != setWidgets.end()) {
1258 if (!allWidgets.contains(*it)) {
1259 it = setWidgets.erase(it);
1262 if (fUpdateStyleSheet && *it != widget) {
1263 (*it)->setStyleSheet(*stylesheet);
1275 if (strFamily ==
"SystemDefault") {
1278 if (strFamily ==
"Montserrat") {
1281 throw std::invalid_argument(
strprintf(
"Invalid font-family: %s", strFamily.toStdString()));
1288 return "SystemDefault";
1290 return "Montserrat";
1315 const std::map<int, QFont::Weight> mapWeight{
1317 {1, QFont::ExtraLight},
1321 {5, QFont::DemiBold},
1323 {7, QFont::ExtraBold},
1326 auto it = mapWeight.find(nArg);
1327 if (it == mapWeight.end()) {
1330 weight = it->second;
1336 const std::map<QFont::Weight, int> mapWeight{
1338 {QFont::ExtraLight, 1},
1342 {QFont::DemiBold, 5},
1344 {QFont::ExtraBold, 7},
1347 assert(mapWeight.count(weight));
1348 return mapWeight.find(weight)->second;
1412 osDefaultFont = std::make_unique<QFont>(QApplication::font());
1415 QString italic =
"Italic";
1417 std::map<QString, bool> mapStyles{
1419 {
"ExtraLight",
true},
1426 {
"ExtraBold",
true},
1430 QFontDatabase database;
1431 std::vector<int> vecFontIds;
1433 for (
const auto& it : mapStyles) {
1434 QString font =
":fonts/" + family +
"-" + it.first;
1435 vecFontIds.push_back(QFontDatabase::addApplicationFont(font));
1436 qDebug() << __func__ <<
": " << font <<
" loaded with id " << vecFontIds.back();
1438 vecFontIds.push_back(QFontDatabase::addApplicationFont(font + italic));
1439 qDebug() << __func__ <<
": " << font + italic <<
" loaded with id " << vecFontIds.back();
1444 if (std::find(vecFontIds.begin(), vecFontIds.end(), -1) != vecFontIds.end()) {
1449 for (
const auto& i : vecFontIds) {
1450 auto families = QFontDatabase::applicationFontFamilies(i);
1451 for (
const QString& f : families) {
1452 qDebug() << __func__ <<
": - Font id " << i <<
" is family: " << f;
1453 const QStringList fontStyles = database.styles(f);
1454 for (
const QString& style : fontStyles) {
1455 qDebug() << __func__ <<
": Style for family " << f <<
" with id: " << i <<
": " << style;
1460 const QStringList fontFamilies = database.families();
1461 for (
const QString& f : fontFamilies) {
1462 if (f.contains(family)) {
1463 const QStringList fontStyles = database.styles(f);
1464 for (
const QString& style : fontStyles) {
1465 qDebug() << __func__ <<
": Family: " << f <<
", Style: " << style;
1472 QFont::Weight weight;
1479 fontScale = settings.value(
"fontScale").toInt();
1494 auto supportedWeights = [](
FontFamily family) -> std::vector<QFont::Weight> {
1495 auto getTestWidth = [&](QFont::Weight weight) ->
int {
1497 return QFontMetrics(font).width(
"Check the width of this text to see if the weight change has an impact!");
1499 std::vector<QFont::Weight> vecWeights{QFont::Thin, QFont::ExtraLight, QFont::Light,
1502 std::vector<QFont::Weight> vecSupported;
1503 QFont::Weight prevWeight = vecWeights.front();
1504 for (
auto weight = vecWeights.begin() + 1; weight != vecWeights.end(); ++weight) {
1505 if (getTestWidth(prevWeight) != getTestWidth(*weight)) {
1506 if (vecSupported.empty()) {
1507 vecSupported.push_back(prevWeight);
1509 vecSupported.push_back(*weight);
1511 prevWeight = *weight;
1513 return vecSupported;
1524 std::unique_ptr<QFont> font;
1532 font = std::make_unique<QFont>(family);
1536 font = std::make_unique<QFont>(family);
1540 font = std::make_unique<QFont>(*osDefaultFont);
1544 qApp->setFont(*font);
1546 qDebug() << __func__ <<
": " << qApp->font().toString() <<
1547 " family: " << qApp->font().family() <<
1548 ", style: " << qApp->font().styleName() <<
1549 " match: " << qApp->font().exactMatch();
1552 void setFont(
const std::vector<QWidget*>& vecWidgets,
FontWeight weight,
int nPointSize,
bool fItalic)
1554 for (
auto it : vecWidgets) {
1555 auto fontAttributes = std::make_tuple(weight, fItalic, nPointSize);
1557 if (!itFontUpdate.second) {
1558 itFontUpdate.first->second = fontAttributes;
1570 static std::map<QWidget*, int> mapWidgetDefaultFontSizes;
1571 static std::map<QString, int> mapClassDefaultFontSizes;
1572 std::map<QWidget*, std::pair<QFont, bool>> mapWidgetFonts;
1574 for (QWidget* w : qApp->allWidgets()) {
1575 std::vector<QString> vecIgnore{
1576 "QWidget",
"QDialog",
"QFrame",
"QStackedWidget",
"QDesktopWidget",
"QDesktopScreenWidget",
1577 "QTipLabel",
"QMessageBox",
"QMenu",
"QComboBoxPrivateScroller",
"QComboBoxPrivateContainer",
1578 "QScrollBar",
"QListView",
"BitcoinGUI",
"WalletView",
"WalletFrame" 1580 if (std::find(vecIgnore.begin(), vecIgnore.end(), w->metaObject()->className()) != vecIgnore.end()) {
1583 QFont font = w->font();
1584 font.setFamily(qApp->font().family());
1586 font.setStyleName(qApp->font().styleName());
1587 font.setStyle(qApp->font().style());
1589 bool fAdded =
false;
1590 if (!mapWidgetDefaultFontSizes.count(w)) {
1591 mapWidgetDefaultFontSizes.emplace(std::make_pair(w, font.pointSize() > 0 ? font.pointSize() :
defaultFontSize));
1596 mapWidgetFonts.emplace(w, std::make_pair(font, fUpdateRequired));
1601 auto itw = mapWidgetFonts.find(itn->first);
1602 if (itw != mapWidgetFonts.end()) {
1603 int nSize = std::get<2>(itn->second);
1605 nSize = mapWidgetDefaultFontSizes[itn->first];
1607 QFont&& font =
getFont(std::get<0>(itn->second), std::get<1>(itn->second), nSize);
1608 if (itn->first->font() != font) {
1609 itw->second.first = font;
1610 itw->second.second =
true;
1618 for (
auto it : mapWidgetFonts) {
1619 if (it.second.second) {
1620 it.first->setFont(it.second.first);
1625 auto itd = mapWidgetDefaultFontSizes.begin();
1626 while (itd != mapWidgetDefaultFontSizes.end()) {
1627 if (qApp->allWidgets().contains(itd->first)) {
1630 itd = mapWidgetDefaultFontSizes.erase(itd);
1635 QFont fontToolTip = qApp->font(
"QTipLabel");
1636 QFont fontMenu = qApp->font(
"QMenu");
1637 QFont fontMessageBox = qApp->font(
"QMessageBox");
1639 if (!mapClassDefaultFontSizes.count(
"QTipLabel")) {
1640 mapClassDefaultFontSizes.emplace(
"QTipLabel", fontToolTip.pointSize());
1642 if (!mapClassDefaultFontSizes.count(
"QMenu")) {
1643 mapClassDefaultFontSizes.emplace(
"QMenu", fontMenu.pointSize());
1645 if (!mapClassDefaultFontSizes.count(
"QMessageBox")) {
1646 mapClassDefaultFontSizes.emplace(
"QMessageBox", fontMessageBox.pointSize());
1650 if (fontToolTip.pointSizeF() != dSize) {
1651 fontToolTip.setPointSizeF(dSize);
1652 qApp->setFont(fontToolTip,
"QTipLabel");
1655 if (fontMenu.pointSizeF() != dSize) {
1656 fontMenu.setPointSizeF(dSize);
1657 qApp->setFont(fontMenu,
"QMenu");
1660 if (fontMessageBox.pointSizeF() != dSize) {
1661 fontMessageBox.setPointSizeF(dSize);
1662 qApp->setFont(fontMessageBox,
"QMessageBox");
1671 static std::map<QFont::Weight, QString> mapMontserratMapping{
1672 {QFont::Thin,
"Thin"},
1673 {QFont::ExtraLight,
"ExtraLight"},
1674 {QFont::Light,
"Light"},
1675 {QFont::Medium,
"Medium"},
1676 {QFont::DemiBold,
"SemiBold"},
1677 {QFont::ExtraBold,
"ExtraBold"},
1678 {QFont::Black,
"Black"},
1688 assert(mapMontserratMapping.count(qWeight));
1692 QString styleName = mapMontserratMapping[qWeight];
1695 if (styleName ==
"Regular") {
1696 styleName =
"Italic";
1698 styleName +=
" Italic";
1703 font.setStyleName(styleName);
1706 font.setWeight(qWeight);
1707 font.setStyle(fItalic ? QFont::StyleItalic : QFont::StyleNormal);
1711 font.setWeight(qWeight);
1712 font.setStyle(fItalic ? QFont::StyleItalic : QFont::StyleNormal);
1715 if (nPointSize != -1) {
1720 qDebug() << __func__ <<
": font size: " << font.pointSizeF() <<
" family: " << font.family() <<
", style: " << font.styleName() <<
", weight:" << font.weight() <<
" match: " << font.exactMatch();
1726 QFont
getFont(QFont::Weight qWeight,
bool fItalic,
int nPointSize)
1754 assert(vecWeights.size() > nIndex);
1755 return vecWeights[nIndex];
1761 for (
int index = 0; index < vecWeights.size(); ++index) {
1762 if (weight == vecWeights[index]) {
1772 return settings.value(
"theme",
defaultTheme).toString();
1778 QString theme = settings.value(
"theme",
"").toString();
1792 for (
const auto& c : w->findChildren<QWidget*>()) {
1793 if (c->testAttribute(Qt::WA_MacShowFocusRect)) {
1795 setRectsDisabled.emplace(c);
1804 QWidgetList allWidgets = QApplication::allWidgets();
1805 auto it = setRectsDisabled.begin();
1806 while (it != setRectsDisabled.end()) {
1807 if (allWidgets.contains(*it)) {
1811 it = setRectsDisabled.erase(it);
1819 QApplication::clipboard()->setText(str, QClipboard::Clipboard);
1820 QApplication::clipboard()->setText(str, QClipboard::Selection);
1825 return fs::path(path.toStdString(),
utf8);
1830 return QString::fromStdString(path.string(
utf8));
1835 QStringList strList;
1836 int days = secs / 86400;
1837 int hours = (secs % 86400) / 3600;
1838 int mins = (secs % 3600) / 60;
1839 int seconds = secs % 60;
1842 strList.append(QString(QObject::tr(
"%1 d")).arg(days));
1844 strList.append(QString(QObject::tr(
"%1 h")).arg(hours));
1846 strList.append(QString(QObject::tr(
"%1 m")).arg(mins));
1847 if (seconds || (!days && !hours && !mins))
1848 strList.append(QString(QObject::tr(
"%1 s")).arg(seconds));
1850 return strList.join(
" ");
1855 QStringList strList;
1858 for (
int i = 0; i < 8; i++) {
1859 uint64_t check = 1 << i;
1865 strList.append(
"NETWORK");
1868 strList.append(
"GETUTXO");
1871 strList.append(
"BLOOM");
1874 strList.append(
"XTHIN");
1877 strList.append(QString(
"%1[%2]").arg(
"UNKNOWN").arg(check));
1883 return strList.join(
" & ");
1885 return QObject::tr(
"None");
1890 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));
1895 return QString(QObject::tr(
"%1 s")).arg(QString::number((
int)
nTimeOffset, 10));
1901 QString timeBehindText;
1902 const int HOUR_IN_SECONDS = 60*60;
1903 const int DAY_IN_SECONDS = 24*60*60;
1904 const int WEEK_IN_SECONDS = 7*24*60*60;
1905 const int YEAR_IN_SECONDS = 31556952;
1908 timeBehindText = QObject::tr(
"%n second(s)",
"",secs);
1910 else if(secs < 2*HOUR_IN_SECONDS)
1912 timeBehindText = QObject::tr(
"%n minute(s)",
"",secs/60);
1914 else if(secs < 2*DAY_IN_SECONDS)
1916 timeBehindText = QObject::tr(
"%n hour(s)",
"",secs/HOUR_IN_SECONDS);
1918 else if(secs < 2*WEEK_IN_SECONDS)
1920 timeBehindText = QObject::tr(
"%n day(s)",
"",secs/DAY_IN_SECONDS);
1922 else if(secs < YEAR_IN_SECONDS)
1924 timeBehindText = QObject::tr(
"%n week(s)",
"",secs/WEEK_IN_SECONDS);
1928 qint64 years = secs / YEAR_IN_SECONDS;
1929 qint64 remainder = secs % YEAR_IN_SECONDS;
1930 timeBehindText = QObject::tr(
"%1 and %2").arg(QObject::tr(
"%n year(s)",
"", years)).arg(QObject::tr(
"%n week(s)",
"", remainder/WEEK_IN_SECONDS));
1932 return timeBehindText;
1938 return QString(QObject::tr(
"%1 B")).arg(bytes);
1939 if(bytes < 1024 * 1024)
1940 return QString(QObject::tr(
"%1 KB")).arg(bytes / 1024);
1941 if(bytes < 1024 * 1024 * 1024)
1942 return QString(QObject::tr(
"%1 MB")).arg(bytes / 1024 / 1024);
1944 return QString(QObject::tr(
"%1 GB")).arg(bytes / 1024 / 1024 / 1024);
1948 while(font_size >= minPointSize) {
1949 font.setPointSizeF(font_size);
1950 QFontMetrics fm(font);
1951 if (fm.width(text) < width) {
void SubstituteFonts(const QString &language)
void stretchColumnWidth(int column)
bool isDust(const QString &address, const CAmount &amount)
double getScaledFontSize(int nSize)
get font size with GUIUtil::fontScale applied
static std::map< FontFamily, std::vector< QFont::Weight > > mapSupportedWeights
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
const std::vector< QString > listThemes()
Return a list of all theme css files.
bool weightFromArg(int nArg, QFont::Weight &weight)
Convert weight value from args (0-8) to QFont::Weight.
QFont::Weight getFontWeightNormal()
FontFamily getFontFamilyDefault()
set/get font family: GUIUtil::fontFamily
static CCriticalSection cs_css
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
void setFontWeightBold(QFont::Weight weight)
QFont getFont(FontFamily family, QFont::Weight qWeight, bool fItalic, int nPointSize)
Get a properly weighted QFont object with the selected font.
Utility functions used by the Dash Qt UI.
int weightToArg(const QFont::Weight weight)
Convert QFont::Weight to an arg value (0-8)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
QList< QModelIndex > getEntryData(QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
QFont::Weight supportedWeightFromIndex(int nIndex)
Convert an index to a weight in the supported weights vector.
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
const char *const BITCOIN_CONF_FILENAME
void setFont(const std::vector< QWidget *> &vecWidgets, FontWeight weight, int nPointSize, bool fItalic)
Workaround to set correct font styles in all themes since there is a bug in macOS which leads to issu...
FontFamily fontFamilyFromString(const QString &strFamily)
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
#define RGB_HALF
Defines the half in RGB space, basically a grey in the middle between black and white.
void on_geometriesChanged()
bool dashThemeActive()
Check if a dash specific theme is activated (light/dark).
int secondToLastColumnIndex
static const QString darkThemePrefix
QColor getThemedQColor(ThemedColor color)
Helper to get colors for various themes which can't be applied via css for some reason.
void setFontWeightNormal(QFont::Weight weight)
QFont getFontNormal()
Get the default normal QFont.
CTxDestination DecodeDestination(const std::string &str)
QString dateTimeStr(const QDateTime &date)
void loadTheme(QWidget *widget, bool fForce)
Load the theme and update all UI elements according to the appearance settings.
FontFamily getFontFamily()
QFont::Weight getFontWeightNormalDefault()
set/get normal font weight: GUIUtil::fontWeightNormal
std::string EncodeBase58(const unsigned char *pbegin, const unsigned char *pend)
Why base-58 instead of standard base-64 encoding?
const std::vector< QString > listStyleSheets()
Return a list of all required css files.
static int64_t nTimeOffset
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
QString formatBytes(uint64_t bytes)
QString formatTimeOffset(int64_t nTimeOffset)
static const int defaultFontScale
static const std::map< ThemedColor, QColor > themedDarkColors
bool GetStartOnSystemStartup()
static const double fontScaleSteps
static const std::map< ThemedColor, QColor > themedColors
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent, bool fAllowURI)
CChainParams defines various tweakable parameters of a given instance of the Dash system...
QString HtmlEscape(const QString &str, bool fMultiLine)
QFont::Weight getFontWeightBoldDefault()
set/get bold font weight: GUIUtil::fontWeightBold
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void connectViewHeadersSignals()
Line edit that can be marked as "invalid" to show input validation feedback.
void migrateQtSettings()
Modify Qt network specific settings on migration.
static fs::detail::utf8_codecvt_facet utf8
int getAvailableWidthForColumn(int column)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
void setupAppearance(QWidget *parent, OptionsModel *model)
static const QString defaultStylesheetDirectory
QString formatBitcoinURI(const SendCoinsRecipient &info)
QFont::Weight toQFontWeight(FontWeight weight)
Convert GUIUtil::FontWeight to QFont::Weight.
const QString getDefaultTheme()
Return the name of the default theme `.
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
void bringToFront(QWidget *w)
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
static const QFont::Weight defaultFontWeightNormal
TableViewLastColumnResizingFixer(QTableView *table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent)
Initializes all internal variables and prepares the the resize modes of the last 2 columns of the tab...
static const QString defaultTheme
void updateMacFocusRects()
Enable/Disable the macOS focus rects depending on the current theme.
int64_t CAmount
Amount in satoshis (Can be negative)
bool isStyleSheetDirectoryCustom()
Check if a custom css directory has been set with -custom-css-dir.
QFont::Weight getFontWeightBold()
void updateFonts()
Update the font of all widgets where a custom font has been set with GUIUtil::setFont.
bool IsValidDestinationString(const std::string &str, const CChainParams ¶ms)
bool isObscured(QWidget *w)
bool eventFilter(QObject *obj, QEvent *evt)
qreal calculateIdealFontSize(int width, const QString &text, QFont font, qreal minPointSize, qreal font_size)
QString formatDurationStr(int secs)
void setClipboard(const QString &str)
int lastColumnMinimumWidth
QString fontFamilyToString(FontFamily family)
QIcon getIcon(const QString &strIcon, const ThemedColor color, const ThemedColor colorAlternative, const QString &strIconPath)
Helper to get an icon colorized with the given color (replaces black) and colorAlternative (replaces ...
bool validateBitcoinURI(const QString &uri)
static const int defaultFontSize
static std::unique_ptr< QFont > osDefaultFont
loadFonts stores the SystemDefault font in osDefaultFont to be able to reference it later again ...
int supportedWeightToIndex(QFont::Weight weight)
Convert a weight to an index in the supported weights vector.
void clicked(const QPoint &point)
Emitted when the label is clicked.
Base58 entry widget validator, checks for valid characters and removes some whitespace.
std::vector< QFont::Weight > getSupportedWeights()
Return supported weights for the current font family.
An output of a transaction.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
QString getActiveTheme()
Return the name of the currently active theme.
QString formatPingTime(double dPingTime)
void disableMacFocusRect(const QWidget *w)
Disable the OS default focus rect for macOS because we have custom focus rects set in the css files...
void on_sectionResized(int logicalIndex, int oldSize, int newSize)
void setStyleSheetDirectory(const QString &path)
Change the stylesheet directory.
void mouseReleaseEvent(QMouseEvent *event)
static QString stylesheetDirectory
bool loadFonts()
Load dash specific appliciation fonts.
static const std::map< ThemedStyle, QString > themedStyles
void disconnectViewHeadersSignals()
QFont getFontBold()
Get the default bold QFont.
int allColumnsMinimumWidth
void mouseReleaseEvent(QMouseEvent *event)
fs::path qstringToBoostPath(const QString &path)
Interface from Qt to configuration data structure for Bitcoin client.
const CChainParams & Params()
Return the currently selected parameters.
fs::path GetConfigFile(const std::string &confPath)
Serialized script, used inside transaction inputs and outputs.
int getFontScaleDefault()
set/get font scale: GUIUtil::fontScale
QString formatServicesStr(quint64 mask)
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 ...
static std::string DummyAddress(const CChainParams ¶ms)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
static const std::map< QString, QString > mapStyleToTheme
void ForceActivation()
Force application activation on macOS.
QString getThemedStyleQString(ThemedStyle style)
Helper to get css style strings which are injected into rich text through qt.
void adjustTableColumnsWidth()
bool checkPoint(const QPoint &p, const QWidget *w)
void setCheckValidator(const QValidator *v)
#define AssertLockNotHeld(cs)
void setIcon(QAbstractButton *button, const QString &strIcon, const ThemedColor color, const ThemedColor colorAlternative, const QSize &size)
Helper to set an icon for a button with the given color (replaces black) and colorAlternative (replac...
void setFontScale(int nScale)
static const std::string TESTNET
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
static const std::map< ThemedStyle, QString > themedDarkStyles
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
bool SetStartOnSystemStartup(bool fAutoStart)
static std::map< QWidget *, std::tuple< FontWeight, bool, int > > mapNormalFontUpdates
const fs::path & GetDataDir(bool fNetSpecific)
static QFont::Weight fontWeightNormal
void clicked(const QPoint &point)
Emitted when the progressbar is clicked.
QString formatNiceTimeOffset(qint64 secs)
void loadStyleSheet(QWidget *widget, bool fForceUpdate)
Updates the widgets stylesheet and adds it to the list of ui debug elements.
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
QString boostPathToQString(const fs::path &path)
void setFontFamily(FontFamily family)
static const std::string DEFAULT_UIPLATFORM
Bitcoin address widget validator, checks for a valid bitcoin address.
static FontFamily fontFamily
Font related variables.
static const uint8_t dummydata[]
static const QFont::Weight defaultFontWeightBold
static QFont::Weight fontWeightBold
void setApplicationFont()
Set an application wide default font, depends on the selected theme.
void resizeColumn(int nColumnIndex, int width)
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
Wrapped mutex: supports recursive locking, but no waiting TODO: We should move away from using the re...
static const QString traditionalTheme
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
static const FontFamily defaultFontFamily
Font related default values.