32 #include <QAbstractItemView>
33 #include <QAbstractButton>
34 #include <QApplication>
35 #include <QCalendarWidget>
39 #include <QDesktopServices>
40 #include <QDesktopWidget>
41 #include <QDoubleValidator>
42 #include <QFileDialog>
44 #include <QFontDatabase>
48 #include <QSizePolicy>
49 #include <QTextDocument>
51 #include <QTextStream>
53 #include <QMouseEvent>
57 static fs::detail::utf8_codecvt_facet utf8;
59 #define URI_SCHEME "prcycoin"
72 QString
format =
"MM/dd/yy HH:mm:ss";
73 return date.toString(
format);
78 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
83 return QFontDatabase::systemFont(QFontDatabase::FixedFont);
88 parent->setFocusProxy(widget);
97 QDoubleValidator* amountValidator =
new QDoubleValidator(parent);
98 amountValidator->setDecimals(8);
99 amountValidator->setBottom(0.0);
100 widget->setValidator(amountValidator);
101 widget->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
107 if (!uri.isValid() || uri.scheme() != QString(
URI_SCHEME))
113 if (rv.
address.endsWith(
"/")) {
118 QUrlQuery uriQuery(uri);
119 QList<QPair<QString, QString> > items = uriQuery.queryItems();
121 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
123 bool fShouldReturnFalse =
false;
124 if (i->first.startsWith(
"req-")) {
125 i->first.remove(0, 4);
126 fShouldReturnFalse =
true;
129 if (i->first ==
"label") {
130 rv.
label = i->second;
131 fShouldReturnFalse =
false;
133 if (i->first ==
"message") {
135 fShouldReturnFalse =
false;
136 }
else if (i->first ==
"amount") {
137 if (!i->second.isEmpty()) {
142 fShouldReturnFalse =
false;
145 if (fShouldReturnFalse)
160 if (uri.startsWith(
URI_SCHEME "://", Qt::CaseInsensitive)) {
163 QUrl uriInstance(uri);
177 if (!info.
label.isEmpty()) {
178 QString lbl(QUrl::toPercentEncoding(info.
label));
179 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
184 QString msg(QUrl::toPercentEncoding(info.
message));
185 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(msg);
196 CTxOut txOut(amount, script);
202 QString escaped = str.toHtmlEscaped();
203 escaped = escaped.replace(
" ",
" ");
205 escaped = escaped.replace(
"\n",
"<br>\n");
212 return HtmlEscape(QString::fromStdString(str), fMultiLine);
217 if (!view || !view->selectionModel())
219 QModelIndexList selection = view->selectionModel()->selectedRows(column);
221 if (!selection.isEmpty()) {
229 if(!view || !view->selectionModel())
231 QModelIndexList selection = view->selectionModel()->selectedRows(column);
232 if(!selection.isEmpty()) {
234 return (selection.at(0).data(role));
239 QString
getSaveFileName(QWidget* parent,
const QString& caption,
const QString& dir,
const QString& filter, QString* selectedSuffixOut)
241 QString selectedFilter;
245 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
253 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
254 QString selectedSuffix;
255 if (filter_re.exactMatch(selectedFilter)) {
256 selectedSuffix = filter_re.cap(1);
260 QFileInfo info(result);
261 if (!result.isEmpty()) {
262 if (info.suffix().isEmpty() && !selectedSuffix.isEmpty()) {
264 if (!result.endsWith(
"."))
266 result.append(selectedSuffix);
271 if (selectedSuffixOut) {
272 *selectedSuffixOut = selectedSuffix;
277 QString
getOpenFileName(QWidget* parent,
const QString& caption,
const QString& dir,
const QString& filter, QString* selectedSuffixOut)
279 QString selectedFilter;
283 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
292 if (selectedSuffixOut) {
294 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
295 QString selectedSuffix;
296 if (filter_re.exactMatch(selectedFilter)) {
297 selectedSuffix = filter_re.cap(1);
299 *selectedSuffixOut = selectedSuffix;
306 if (QThread::currentThread() != qApp->thread()) {
307 return Qt::BlockingQueuedConnection;
309 return Qt::DirectConnection;
315 QWidget* atW = QApplication::widgetAt(w->mapToGlobal(p));
316 if (!atW)
return false;
317 return atW->window() == w;
322 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));
333 if (w->isMinimized()) {
347 if (fs::exists(path)) {
351 if (isTextFile && !ret) {
352 ret = QProcess::startDetached(
"/usr/bin/open", QStringList{
"-t",
boostPathToQString(path)});
379 if (fs::exists(pathDataDir))
380 return QDesktopServices::openUrl(QUrl::fromLocalFile(
boostPathToQString(pathDataDir)));
386 QString pathQt = QCoreApplication::applicationDirPath();
387 QDesktopServices::openUrl(QUrl(pathQt, QUrl::TolerantMode));
396 size_threshold(size_threshold)
402 if (evt->type() == QEvent::ToolTipChange) {
403 QWidget* widget =
static_cast<QWidget*
>(obj);
404 QString tooltip = widget->toolTip();
405 if (tooltip.size() >
size_threshold && !tooltip.startsWith(
"<qt")) {
407 if (!Qt::mightBeRichText(tooltip))
411 tooltip =
"<qt style='white-space:pre'>" + tooltip +
"</qt>";
412 widget->setToolTip(tooltip);
416 return QObject::eventFilter(obj, evt);
428 disconnect(
tableView->horizontalHeader(), SIGNAL(sectionResized(
int,
int,
int)),
this, SLOT(
on_sectionResized(
int,
int,
int)));
436 tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
441 tableView->setColumnWidth(nColumnIndex, width);
442 tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
447 int nColumnsWidthSum = 0;
449 nColumnsWidthSum +=
tableView->horizontalHeader()->sectionSize(i);
451 return nColumnsWidthSum;
457 int nTableWidth =
tableView->horizontalHeader()->width();
459 if (nTableWidth > 0) {
461 nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
474 int nTableWidth =
tableView->horizontalHeader()->width();
476 if (nColsWidth > nTableWidth) {
494 if (newSize > remainingWidth) {
515 lastColumnMinimumWidth(lastColMinimumWidth),
516 allColumnsMinimumWidth(allColsMinimumWidth)
554 fs::path
static StartupShortcutPath()
556 return GetSpecialFolderPath(CSIDL_STARTUP) /
"PRCYcoin.lnk";
562 return fs::exists(StartupShortcutPath());
568 fs::remove(StartupShortcutPath());
571 CoInitialize(
nullptr);
574 IShellLink* psl =
nullptr;
575 HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
576 CLSCTX_INPROC_SERVER, IID_IShellLink,
577 reinterpret_cast<void**
>(&psl));
579 if (SUCCEEDED(hres)) {
582 GetModuleFileName(
nullptr, pszExePath,
sizeof(pszExePath));
584 TCHAR pszArgs[5] = TEXT(
"-min");
587 psl->SetPath(pszExePath);
588 PathRemoveFileSpec(pszExePath);
589 psl->SetWorkingDirectory(pszExePath);
590 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
591 psl->SetArguments(pszArgs);
595 IPersistFile* ppf =
nullptr;
596 hres = psl->QueryInterface(IID_IPersistFile,
597 reinterpret_cast<void**
>(&ppf));
598 if (SUCCEEDED(hres)) {
601 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().
string().c_str(), -1, pwsz,
MAX_PATH);
603 hres = ppf->Save(pwsz, TRUE);
617 #elif defined(Q_OS_LINUX)
622 fs::path
static GetAutostartDir()
624 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
625 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
626 char* pszHome = getenv(
"HOME");
627 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
631 fs::path
static GetAutostartFilePath()
633 return GetAutostartDir() /
"prcycoin.desktop";
638 fs::ifstream optionFile(GetAutostartFilePath());
639 if (!optionFile.good())
643 while (!optionFile.eof()) {
644 getline(optionFile, line);
645 if (line.find(
"Hidden") != std::string::npos &&
646 line.find(
"true") != std::string::npos)
657 fs::remove(GetAutostartFilePath());
660 memset(pszExePath, 0,
sizeof(pszExePath));
661 if (readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath) - 1) == -1)
664 fs::create_directories(GetAutostartDir());
666 fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc);
667 if (!optionFile.good())
670 optionFile <<
"[Desktop Entry]\n";
671 optionFile <<
"Type=Application\n";
672 optionFile <<
"Name=PRCYcoin\n";
673 optionFile <<
"Exec=" << pszExePath <<
" -min\n";
674 optionFile <<
"Terminal=false\n";
675 optionFile <<
"Hidden=false\n";
694 settings.setValue(strSetting +
"Pos", parent->pos());
695 settings.setValue(strSetting +
"Size", parent->size());
699 auto hide = []( QWidget* widget) { widget->setVisible(
false); };
700 std::for_each (widgets.begin(), widgets.end(), hide);
707 QPoint pos = settings.value(strSetting +
"Pos").toPoint();
708 QSize size = settings.value(strSetting +
"Size", defaultSize).toSize();
710 if (!pos.x() && !pos.y()) {
711 QRect screen = QApplication::desktop()->screenGeometry();
712 pos.setX((screen.width() - size.width()) / 2);
713 pos.setY((screen.height() - size.height()) / 2);
716 parent->resize(size);
725 QVariant theme = settings.value(
"theme");
726 QString cssName = QString(
":/css/" + theme.toString());
729 settings.setValue(
"fCSSexternal",
false);
731 QFile qFile(cssName);
732 if (!qFile.exists()){
733 QTextStream qout(stdout);
734 qout <<
"Error: " << cssName <<
" not found. Please check qrc." <<endl;
735 }
else if (qFile.open(QFile::ReadOnly)) {
736 styleSheet = QLatin1String(qFile.readAll());
744 Q_FOREACH (QWidget *widget, QApplication::topLevelWidgets()){
751 widget->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
752 widget->setAttribute(Qt::WA_NoSystemBackground,
true);
753 widget->setAttribute(Qt::WA_TranslucentBackground,
true);
754 widget->setAttribute(Qt::WA_OpaquePaintEvent,
false);
762 QMessageBox* errorPrompt =
new QMessageBox();
765 errorPrompt->setText(message);
767 errorPrompt->deleteLater();
772 QTextCharFormat
format = widget->weekdayTextFormat(Qt::Saturday);
773 format.setForeground(QBrush(color, Qt::SolidPattern));
774 widget->setWeekdayTextFormat(Qt::Saturday,
format);
775 format = widget->weekdayTextFormat(Qt::Sunday);
776 format.setForeground(QBrush(color, Qt::SolidPattern));
777 widget->setWeekdayTextFormat(Qt::Sunday,
format);
778 widget->parentWidget()->resize(300,300);
779 widget->findChild<QWidget*>(
"qt_calendar_navigationbar")->setMinimumHeight(65);
780 widget->findChild<QWidget*>(
"qt_calendar_calendarview")->setStyleSheet(
"padding:5px; margin:0;");
781 widget->findChild<QAbstractButton*>(
"qt_calendar_prevmonth")->setIcon(QIcon(
":/images/leftArrow_small"));
782 widget->findChild<QAbstractButton*>(
"qt_calendar_nextmonth")->setIcon(QIcon(
":/images/rightArrow_small"));
787 QClipboard* clipboard = QApplication::clipboard();
788 clipboard->setText(str, QClipboard::Clipboard);
789 if (clipboard->supportsSelection()) {
790 clipboard->setText(str, QClipboard::Selection);
796 return fs::path(path.toStdString(), utf8);
801 return QString::fromStdString(path.string(utf8));
807 int days = secs / 86400;
808 int hours = (secs % 86400) / 3600;
809 int mins = (secs % 3600) / 60;
810 int seconds = secs % 60;
813 strList.append(QString(QObject::tr(
"%1 d")).arg(days));
815 strList.append(QString(QObject::tr(
"%1 h")).arg(hours));
817 strList.append(QString(QObject::tr(
"%1 m")).arg(mins));
818 if (seconds || (!days && !hours && !mins))
819 strList.append(QString(QObject::tr(
"%1 s")).arg(seconds));
821 return strList.join(
" ");
829 for (
int i = 0; i < 8; i++) {
830 uint64_t check = 1 << i;
834 strList.append(QObject::tr(
"NETWORK"));
838 strList.append(QObject::tr(
"BLOOM"));
841 strList.append(QString(
"%1[%2]").arg(QObject::tr(
"UNKNOWN")).arg(check));
847 return strList.join(
" & ");
849 return QObject::tr(
"None");
854 return dPingTime == 0 ? QObject::tr(
"N/A") : QString(QObject::tr(
"%1 ms")).arg(QString::number((
int)(dPingTime * 1000), 10));
859 return QString(QObject::tr(
"%1 s")).arg(QString::number((
int)nTimeOffset, 10));
865 return QString(QObject::tr(
"%1 B")).arg(bytes);
866 if(bytes < 1024 * 1024)
867 return QString(QObject::tr(
"%1 KB")).arg(bytes / 1024);
868 if(bytes < 1024 * 1024 * 1024)
869 return QString(QObject::tr(
"%1 MB")).arg(bytes / 1024 / 1024);
871 return QString(QObject::tr(
"%1 GB")).arg(bytes / 1024 / 1024 / 1024);