27 #define _WIN32_WINNT 0x0501 31 #define _WIN32_IE 0x0501 32 #define WIN32_LEAN_AND_MEAN 1 41 #include <QAbstractItemView> 42 #include <QApplication> 45 #include <QDesktopServices> 46 #include <QDesktopWidget> 47 #include <QDoubleValidator> 48 #include <QFileDialog> 53 #include <QTextDocument> 56 #include <QMouseEvent> 59 #if QT_VERSION >= 0x50200 60 #include <QFontDatabase> 67 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm");
72 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
77 #if QT_VERSION >= 0x50200 78 return QFontDatabase::systemFont(QFontDatabase::FixedFont);
80 QFont font(
"Monospace");
81 font.setStyleHint(QFont::Monospace);
87 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};
90 static std::string DummyAddress(
const CChainParams ¶ms)
93 sourcedata.insert(sourcedata.end(), dummydata, dummydata +
sizeof(dummydata));
94 for(
int i=0; i<256; ++i) {
95 std::string s =
EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size());
99 sourcedata[sourcedata.size()-1] += 1;
106 parent->setFocusProxy(widget);
111 widget->setPlaceholderText(QObject::tr(
"Enter a BSHA3 address (e.g. %1)").arg(
112 QString::fromStdString(DummyAddress(
Params()))));
120 if(!uri.isValid() || uri.scheme() != QString(
"bitcoin"))
126 if (rv.
address.endsWith(
"/")) {
131 QUrlQuery uriQuery(uri);
132 QList<QPair<QString, QString> > items = uriQuery.queryItems();
133 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
135 bool fShouldReturnFalse =
false;
136 if (i->first.startsWith(
"req-"))
138 i->first.remove(0, 4);
139 fShouldReturnFalse =
true;
142 if (i->first ==
"label")
144 rv.
label = i->second;
145 fShouldReturnFalse =
false;
147 if (i->first ==
"message")
150 fShouldReturnFalse =
false;
152 else if (i->first ==
"amount")
154 if(!i->second.isEmpty())
161 fShouldReturnFalse =
false;
164 if (fShouldReturnFalse)
176 QUrl uriInstance(uri);
182 QString
ret = QString(
"bitcoin:%1").arg(info.
address);
191 if (!info.
label.isEmpty())
193 QString lbl(QUrl::toPercentEncoding(info.
label));
194 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
200 QString msg(QUrl::toPercentEncoding(info.
message));
201 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(msg);
212 CTxOut txOut(amount, script);
218 QString escaped = str.toHtmlEscaped();
221 escaped = escaped.replace(
"\n",
"<br>\n");
228 return HtmlEscape(QString::fromStdString(str), fMultiLine);
233 if(!view || !view->selectionModel())
235 QModelIndexList selection = view->selectionModel()->selectedRows(column);
237 if(!selection.isEmpty())
246 if(!view || !view->selectionModel())
247 return QList<QModelIndex>();
248 return view->selectionModel()->selectedRows(column);
253 QString *selectedSuffixOut)
255 QString selectedFilter;
259 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
269 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
270 QString selectedSuffix;
271 if(filter_re.exactMatch(selectedFilter))
273 selectedSuffix = filter_re.cap(1);
277 QFileInfo info(result);
278 if(!result.isEmpty())
280 if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
283 if(!result.endsWith(
"."))
285 result.append(selectedSuffix);
290 if(selectedSuffixOut)
292 *selectedSuffixOut = selectedSuffix;
299 QString *selectedSuffixOut)
301 QString selectedFilter;
305 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
314 if(selectedSuffixOut)
317 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
318 QString selectedSuffix;
319 if(filter_re.exactMatch(selectedFilter))
321 selectedSuffix = filter_re.cap(1);
323 *selectedSuffixOut = selectedSuffix;
330 if(QThread::currentThread() != qApp->thread())
332 return Qt::BlockingQueuedConnection;
336 return Qt::DirectConnection;
342 QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
343 if (!atW)
return false;
344 return atW->topLevelWidget() == w;
352 &&
checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
353 &&
checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
358 fs::path pathDebug =
GetDataDir() /
"debug.log";
361 if (fs::exists(pathDebug))
372 if (!configFile.good())
378 return QDesktopServices::openUrl(QUrl::fromLocalFile(
boostPathToQString(pathConfig)));
383 size_threshold(_size_threshold)
390 if(evt->type() == QEvent::ToolTipChange)
392 QWidget *widget =
static_cast<QWidget*
>(obj);
393 QString tooltip = widget->toolTip();
394 if(tooltip.size() >
size_threshold && !tooltip.startsWith(
"<qt") && !Qt::mightBeRichText(tooltip))
398 tooltip =
"<qt>" +
HtmlEscape(tooltip,
true) +
"</qt>";
399 widget->setToolTip(tooltip);
403 return QObject::eventFilter(obj, evt);
423 tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
428 tableView->setColumnWidth(nColumnIndex, width);
429 tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
434 int nColumnsWidthSum = 0;
437 nColumnsWidthSum +=
tableView->horizontalHeader()->sectionSize(i);
439 return nColumnsWidthSum;
445 int nTableWidth =
tableView->horizontalHeader()->width();
450 nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
463 int nTableWidth =
tableView->horizontalHeader()->width();
465 if (nColsWidth > nTableWidth)
484 if (newSize > remainingWidth)
509 lastColumnMinimumWidth(lastColMinimumWidth),
510 allColumnsMinimumWidth(allColsMinimumWidth)
521 fs::path
static StartupShortcutPath()
525 return GetSpecialFolderPath(CSIDL_STARTUP) /
"BSHA3.lnk";
527 return GetSpecialFolderPath(CSIDL_STARTUP) /
"BSHA3 (testnet).lnk";
528 return GetSpecialFolderPath(CSIDL_STARTUP) /
strprintf(
"BSHA3 (%s).lnk", chain);
534 return fs::exists(StartupShortcutPath());
540 fs::remove(StartupShortcutPath());
544 CoInitialize(
nullptr);
547 IShellLinkW* psl =
nullptr;
548 HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
549 CLSCTX_INPROC_SERVER, IID_IShellLinkW,
550 reinterpret_cast<void**>(&psl));
556 GetModuleFileNameW(
nullptr, pszExePath, ARRAYSIZE(pszExePath));
559 QString strArgs =
"-min";
564 psl->SetPath(pszExePath);
565 PathRemoveFileSpecW(pszExePath);
566 psl->SetWorkingDirectory(pszExePath);
567 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
568 psl->SetArguments(strArgs.toStdWString().c_str());
572 IPersistFile* ppf =
nullptr;
573 hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
577 hres = ppf->Save(StartupShortcutPath().wstring().c_str(), TRUE);
590 #elif defined(Q_OS_LINUX) 595 fs::path
static GetAutostartDir()
597 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
598 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
599 char* pszHome = getenv(
"HOME");
600 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
604 fs::path
static GetAutostartFilePath()
608 return GetAutostartDir() /
"bitcoin.desktop";
609 return GetAutostartDir() /
strprintf(
"bitcoin-%s.lnk", chain);
615 if (!optionFile.good())
619 while (!optionFile.eof())
621 getline(optionFile, line);
622 if (line.find(
"Hidden") != std::string::npos &&
623 line.find(
"true") != std::string::npos)
634 fs::remove(GetAutostartFilePath());
638 ssize_t r = readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath) - 1);
641 pszExePath[r] =
'\0';
643 fs::create_directories(GetAutostartDir());
645 fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc);
646 if (!optionFile.good())
650 optionFile <<
"[Desktop Entry]\n";
651 optionFile <<
"Type=Application\n";
653 optionFile <<
"Name=Bitcoin\n";
655 optionFile <<
strprintf(
"Name=Bitcoin (%s)\n", chain);
657 optionFile <<
"Terminal=false\n";
658 optionFile <<
"Hidden=false\n";
665 #elif defined(Q_OS_MAC) 666 #pragma GCC diagnostic push 667 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 670 #include <CoreFoundation/CoreFoundation.h> 671 #include <CoreServices/CoreServices.h> 673 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
674 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
676 CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list,
nullptr);
677 if (listSnapshot ==
nullptr) {
682 for(
int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
683 LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
684 UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
685 CFURLRef currentItemURL =
nullptr;
687 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 688 if(&LSSharedFileListItemCopyResolvedURL)
689 currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags,
nullptr);
690 #if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100 692 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL,
nullptr);
695 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL,
nullptr);
699 if (CFEqual(currentItemURL, findUrl)) {
701 CFRelease(listSnapshot);
702 CFRelease(currentItemURL);
705 CFRelease(currentItemURL);
709 CFRelease(listSnapshot);
715 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
716 if (bitcoinAppUrl ==
nullptr) {
720 LSSharedFileListRef loginItems = LSSharedFileListCreate(
nullptr, kLSSharedFileListSessionLoginItems,
nullptr);
721 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
723 CFRelease(bitcoinAppUrl);
729 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
730 if (bitcoinAppUrl ==
nullptr) {
734 LSSharedFileListRef loginItems = LSSharedFileListCreate(
nullptr, kLSSharedFileListSessionLoginItems,
nullptr);
735 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
737 if(fAutoStart && !foundItem) {
739 LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
nullptr,
nullptr, bitcoinAppUrl,
nullptr,
nullptr);
741 else if(!fAutoStart && foundItem) {
743 LSSharedFileListItemRemove(loginItems, foundItem);
746 CFRelease(bitcoinAppUrl);
749 #pragma GCC diagnostic pop 759 QApplication::clipboard()->setText(str, QClipboard::Clipboard);
760 QApplication::clipboard()->setText(str, QClipboard::Selection);
765 return fs::path(path.toStdString());
770 return QString::fromStdString(path.string());
776 int days = secs / 86400;
777 int hours = (secs % 86400) / 3600;
778 int mins = (secs % 3600) / 60;
779 int seconds = secs % 60;
782 strList.append(QString(QObject::tr(
"%1 d")).arg(days));
784 strList.append(QString(QObject::tr(
"%1 h")).arg(hours));
786 strList.append(QString(QObject::tr(
"%1 m")).arg(mins));
787 if (seconds || (!days && !hours && !mins))
788 strList.append(QString(QObject::tr(
"%1 s")).arg(seconds));
790 return strList.join(
" ");
798 for (
int i = 0; i < 8; i++) {
799 uint64_t check = 1 << i;
805 strList.append(
"NETWORK");
808 strList.append(
"GETUTXO");
811 strList.append(
"BLOOM");
814 strList.append(
"WITNESS");
817 strList.append(
"XTHIN");
820 strList.append(QString(
"%1[%2]").arg(
"UNKNOWN").arg(check));
826 return strList.join(
" & ");
828 return QObject::tr(
"None");
833 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));
838 return QString(QObject::tr(
"%1 s")).arg(QString::number((
int)nTimeOffset, 10));
844 QString timeBehindText;
845 const int HOUR_IN_SECONDS = 60*60;
846 const int DAY_IN_SECONDS = 24*60*60;
847 const int WEEK_IN_SECONDS = 7*24*60*60;
848 const int YEAR_IN_SECONDS = 31556952;
851 timeBehindText = QObject::tr(
"%n second(s)",
"",secs);
853 else if(secs < 2*HOUR_IN_SECONDS)
855 timeBehindText = QObject::tr(
"%n minute(s)",
"",secs/60);
857 else if(secs < 2*DAY_IN_SECONDS)
859 timeBehindText = QObject::tr(
"%n hour(s)",
"",secs/HOUR_IN_SECONDS);
861 else if(secs < 2*WEEK_IN_SECONDS)
863 timeBehindText = QObject::tr(
"%n day(s)",
"",secs/DAY_IN_SECONDS);
865 else if(secs < YEAR_IN_SECONDS)
867 timeBehindText = QObject::tr(
"%n week(s)",
"",secs/WEEK_IN_SECONDS);
871 qint64 years = secs / YEAR_IN_SECONDS;
872 qint64 remainder = secs % YEAR_IN_SECONDS;
873 timeBehindText = QObject::tr(
"%1 and %2").arg(QObject::tr(
"%n year(s)",
"", years)).arg(QObject::tr(
"%n week(s)",
"", remainder/WEEK_IN_SECONDS));
875 return timeBehindText;
881 return QString(QObject::tr(
"%1 B")).arg(bytes);
882 if(bytes < 1024 * 1024)
883 return QString(QObject::tr(
"%1 KB")).arg(bytes / 1024);
884 if(bytes < 1024 * 1024 * 1024)
885 return QString(QObject::tr(
"%1 MB")).arg(bytes / 1024 / 1024);
887 return QString(QObject::tr(
"%1 GB")).arg(bytes / 1024 / 1024 / 1024);
891 while(font_size >= minPointSize) {
892 font.setPointSizeF(font_size);
893 QFontMetrics fm(font);
894 if (fm.width(text) < width) {
914 if (event->type() == QEvent::KeyPress) {
915 if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
919 return QItemDelegate::eventFilter(
object, event);
void stretchColumnWidth(int column)
Utility functions used by the Bitcoin Qt UI.
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.
const char *const BITCOIN_CONF_FILENAME
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
bool IsValidDestinationString(const std::string &str, const CChainParams ¶ms)
void on_geometriesChanged()
bool isDust(interfaces::Node &node, const QString &address, const CAmount &amount)
int secondToLastColumnIndex
UniValue ret(UniValue::VARR)
QString dateTimeStr(const QDateTime &date)
std::string EncodeBase58(const unsigned char *pbegin, const unsigned char *pend)
Why base-58 instead of standard base-64 encoding?
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)
bool GetStartOnSystemStartup()
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
QString HtmlEscape(const QString &str, bool fMultiLine)
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.
int getAvailableWidthForColumn(int column)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
virtual CFeeRate getDustRelayFee()=0
Get dust relay fee.
QString formatBitcoinURI(const SendCoinsRecipient &info)
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
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...
int64_t CAmount
Amount in satoshis (Can be negative)
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
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)
boost::variant< CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
int lastColumnMinimumWidth
void clicked(const QPoint &point)
Emitted when the label is clicked.
Base58 entry widget validator, checks for valid characters and removes some whitespace.
An output of a transaction.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
bool eventFilter(QObject *object, QEvent *event)
QString formatPingTime(double dPingTime)
void on_sectionResized(int logicalIndex, int oldSize, int newSize)
void mouseReleaseEvent(QMouseEvent *event)
CTxDestination DecodeDestination(const std::string &str)
void disconnectViewHeadersSignals()
int allColumnsMinimumWidth
void mouseReleaseEvent(QMouseEvent *event)
fs::path qstringToBoostPath(const QString &path)
const CChainParams & Params()
Return the currently selected parameters.
fs::path GetConfigFile(const std::string &confPath)
Serialized script, used inside transaction inputs and outputs.
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 ...
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
void adjustTableColumnsWidth()
bool checkPoint(const QPoint &p, const QWidget *w)
void setCheckValidator(const QValidator *v)
static const std::string TESTNET
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
bool SetStartOnSystemStartup(bool fAutoStart)
const fs::path & GetDataDir(bool fNetSpecific)
void clicked(const QPoint &point)
Emitted when the progressbar is clicked.
QString formatNiceTimeOffset(qint64 secs)
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)
BSHA3 address widget validator, checks for a valid bitcoin address.
Top-level interface for a bitcoin node (bsha3d process).
void resizeColumn(int nColumnIndex, int width)
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const