20 #define _WIN32_WINNT 0x0501
24 #define _WIN32_IE 0x0501
25 #define WIN32_LEAN_AND_MEAN 1
34 #include <boost/filesystem.hpp>
35 #include <boost/filesystem/fstream.hpp>
36 #if BOOST_FILESYSTEM_VERSION >= 3
37 #include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
40 #include <QAbstractItemView>
41 #include <QApplication>
44 #include <QDesktopServices>
45 #include <QDesktopWidget>
46 #include <QDoubleValidator>
47 #include <QFileDialog>
51 #include <QTextDocument>
54 #if QT_VERSION < 0x050000
60 #if BOOST_FILESYSTEM_VERSION >= 3
61 static boost::filesystem::detail::utf8_codecvt_facet utf8;
65 extern double NSAppKitVersionNumber;
66 #if !defined(NSAppKitVersionNumber10_9)
67 #define NSAppKitVersionNumber10_9 1265
75 return date.date().toString(Qt::SystemLocaleShortDate) + QString(
" ") + date.toString(
"hh:mm");
80 return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
85 QFont font(
"Monospace");
86 #if QT_VERSION >= 0x040800
87 font.setStyleHint(QFont::Monospace);
89 font.setStyleHint(QFont::TypeWriter);
96 parent->setFocusProxy(widget);
99 #if QT_VERSION >= 0x040700
100 widget->setPlaceholderText(QObject::tr(
"Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
108 QDoubleValidator *amountValidator =
new QDoubleValidator(parent);
109 amountValidator->setDecimals(8);
110 amountValidator->setBottom(0.0);
111 widget->setValidator(amountValidator);
112 widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
118 if(!uri.isValid() || uri.scheme() != QString(
"bitcoin"))
125 #if QT_VERSION < 0x050000
126 QList<QPair<QString, QString> > items = uri.queryItems();
128 QUrlQuery uriQuery(uri);
129 QList<QPair<QString, QString> > items = uriQuery.queryItems();
131 for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
133 bool fShouldReturnFalse =
false;
134 if (i->first.startsWith(
"req-"))
136 i->first.remove(0, 4);
137 fShouldReturnFalse =
true;
140 if (i->first ==
"label")
142 rv.
label = i->second;
143 fShouldReturnFalse =
false;
145 if (i->first ==
"message")
148 fShouldReturnFalse =
false;
150 else if (i->first ==
"amount")
152 if(!i->second.isEmpty())
159 fShouldReturnFalse =
false;
162 if (fShouldReturnFalse)
178 if(uri.startsWith(
"bitcoin://", Qt::CaseInsensitive))
180 uri.replace(0, 10,
"bitcoin:");
182 QUrl uriInstance(uri);
188 QString ret = QString(
"bitcoin:%1").arg(info.
address);
197 if (!info.
label.isEmpty())
199 QString lbl(QUrl::toPercentEncoding(info.
label));
200 ret += QString(
"%1label=%2").arg(paramCount == 0 ?
"?" :
"&").arg(lbl);
206 QString msg(QUrl::toPercentEncoding(info.
message));;
207 ret += QString(
"%1message=%2").arg(paramCount == 0 ?
"?" :
"&").arg(msg);
214 bool isDust(
const QString& address, qint64 amount)
218 CTxOut txOut(amount, script);
224 #if QT_VERSION < 0x050000
225 QString escaped = Qt::escape(str);
227 QString escaped = str.toHtmlEscaped();
231 escaped = escaped.replace(
"\n",
"<br>\n");
238 return HtmlEscape(QString::fromStdString(str), fMultiLine);
243 if(!view || !view->selectionModel())
245 QModelIndexList selection = view->selectionModel()->selectedRows(column);
247 if(!selection.isEmpty())
255 const QString &filter,
256 QString *selectedSuffixOut)
258 QString selectedFilter;
262 #if QT_VERSION < 0x050000
263 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
265 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
276 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
277 QString selectedSuffix;
278 if(filter_re.exactMatch(selectedFilter))
280 selectedSuffix = filter_re.cap(1);
284 QFileInfo info(result);
285 if(!result.isEmpty())
287 if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
290 if(!result.endsWith(
"."))
292 result.append(selectedSuffix);
297 if(selectedSuffixOut)
299 *selectedSuffixOut = selectedSuffix;
305 const QString &filter,
306 QString *selectedSuffixOut)
308 QString selectedFilter;
312 #if QT_VERSION < 0x050000
313 myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
315 myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
325 if(selectedSuffixOut)
328 QRegExp filter_re(
".* \\(\\*\\.(.*)[ \\)]");
329 QString selectedSuffix;
330 if(filter_re.exactMatch(selectedFilter))
332 selectedSuffix = filter_re.cap(1);
334 *selectedSuffixOut = selectedSuffix;
341 if(QThread::currentThread() != qApp->thread())
343 return Qt::BlockingQueuedConnection;
347 return Qt::DirectConnection;
353 QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
354 if (!atW)
return false;
355 return atW->topLevelWidget() == w;
363 &&
checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
364 &&
checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
369 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
372 if (boost::filesystem::exists(pathDebug))
377 QObject(parent), size_threshold(size_threshold)
384 #if defined(Q_OS_MAC)
395 #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
396 if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_9)
397 QFont::insertSubstitution(
".Lucida Grande UI",
"Lucida Grande");
404 if(evt->type() == QEvent::ToolTipChange)
407 QString tooltip = widget->toolTip();
408 if(tooltip.size() >
size_threshold && !tooltip.startsWith(
"<qt") && !Qt::mightBeRichText(tooltip))
412 tooltip =
"<qt>" +
HtmlEscape(tooltip,
true) +
"</qt>";
413 widget->setToolTip(tooltip);
417 return QObject::eventFilter(obj, evt);
437 #if QT_VERSION < 0x050000
438 tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
440 tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
446 tableView->setColumnWidth(nColumnIndex, width);
447 tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
452 int nColumnsWidthSum = 0;
455 nColumnsWidthSum +=
tableView->horizontalHeader()->sectionSize(i);
457 return nColumnsWidthSum;
463 int nTableWidth =
tableView->horizontalHeader()->width();
468 nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
481 int nTableWidth =
tableView->horizontalHeader()->width();
483 if (nColsWidth > nTableWidth)
502 if (newSize > remainingWidth)
526 lastColumnMinimumWidth(lastColMinimumWidth),
527 allColumnsMinimumWidth(allColsMinimumWidth)
538 boost::filesystem::path
static StartupShortcutPath()
540 return GetSpecialFolderPath(CSIDL_STARTUP) /
"Bitcoin.lnk";
546 return boost::filesystem::exists(StartupShortcutPath());
552 boost::filesystem::remove(StartupShortcutPath());
559 IShellLink* psl = NULL;
560 HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
561 CLSCTX_INPROC_SERVER, IID_IShellLink,
562 reinterpret_cast<void**>(&psl));
568 GetModuleFileName(NULL, pszExePath,
sizeof(pszExePath));
570 TCHAR pszArgs[5] = TEXT(
"-min");
573 psl->SetPath(pszExePath);
574 PathRemoveFileSpec(pszExePath);
575 psl->SetWorkingDirectory(pszExePath);
576 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
577 psl->SetArguments(pszArgs);
581 IPersistFile* ppf = NULL;
582 hres = psl->QueryInterface(IID_IPersistFile,
583 reinterpret_cast<void**>(&ppf));
588 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().
string().c_str(), -1, pwsz,
MAX_PATH);
590 hres = ppf->Save(pwsz, TRUE);
604 #elif defined(Q_OS_LINUX)
609 boost::filesystem::path
static GetAutostartDir()
611 namespace fs = boost::filesystem;
613 char* pszConfigHome = getenv(
"XDG_CONFIG_HOME");
614 if (pszConfigHome)
return fs::path(pszConfigHome) /
"autostart";
615 char* pszHome = getenv(
"HOME");
616 if (pszHome)
return fs::path(pszHome) /
".config" /
"autostart";
620 boost::filesystem::path
static GetAutostartFilePath()
622 return GetAutostartDir() /
"bitcoin.desktop";
627 boost::filesystem::ifstream optionFile(GetAutostartFilePath());
628 if (!optionFile.good())
632 while (!optionFile.eof())
634 getline(optionFile, line);
635 if (line.find(
"Hidden") != std::string::npos &&
636 line.find(
"true") != std::string::npos)
647 boost::filesystem::remove(GetAutostartFilePath());
651 memset(pszExePath, 0,
sizeof(pszExePath));
652 if (readlink(
"/proc/self/exe", pszExePath,
sizeof(pszExePath)-1) == -1)
655 boost::filesystem::create_directories(GetAutostartDir());
657 boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
658 if (!optionFile.good())
661 optionFile <<
"[Desktop Entry]\n";
662 optionFile <<
"Type=Application\n";
663 optionFile <<
"Name=Bitcoin\n";
664 optionFile <<
"Exec=" << pszExePath <<
" -min\n";
665 optionFile <<
"Terminal=false\n";
666 optionFile <<
"Hidden=false\n";
673 #elif defined(Q_OS_MAC)
676 #include <CoreFoundation/CoreFoundation.h>
677 #include <CoreServices/CoreServices.h>
679 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
680 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
683 CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, NULL);
684 for(
int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
685 LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
686 UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
687 CFURLRef currentItemURL = NULL;
688 LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
689 if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
691 CFRelease(currentItemURL);
695 CFRelease(currentItemURL);
703 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
704 LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
705 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
711 CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
712 LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
713 LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
715 if(fAutoStart && !foundItem) {
717 LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, bitcoinAppUrl, NULL, NULL);
719 else if(!fAutoStart && foundItem) {
721 LSSharedFileListItemRemove(loginItems, foundItem);
735 settings.setValue(strSetting +
"Pos", parent->pos());
736 settings.setValue(strSetting +
"Size", parent->size());
742 QPoint pos = settings.value(strSetting +
"Pos").toPoint();
743 QSize size = settings.value(strSetting +
"Size", defaultSize).toSize();
745 if (!pos.x() && !pos.y()) {
746 QRect screen = QApplication::desktop()->screenGeometry();
747 pos.setX((screen.width() - size.width()) / 2);
748 pos.setY((screen.height() - size.height()) / 2);
751 parent->resize(size);
757 QApplication::clipboard()->setText(str, QClipboard::Clipboard);
758 QApplication::clipboard()->setText(str, QClipboard::Selection);
761 #if BOOST_FILESYSTEM_VERSION >= 3
764 return boost::filesystem::path(path.toStdString(), utf8);
769 return QString::fromStdString(path.string(utf8));
772 #warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older
775 return boost::filesystem::path(path.toStdString());
780 return QString::fromStdString(path.string());
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
void stretchColumnWidth(int column)
bool IsDust(int64_t nMinRelayTxFee) const
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.
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
TableViewLastColumnResizingFixer(QTableView *table, int lastColMinimumWidth, int allColsMinimumWidth)
Initializes all internal variables and prepares the the resize modes of the last 2 columns of the tab...
void on_geometriesChanged()
int secondToLastColumnIndex
QString dateTimeStr(const QDateTime &date)
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
bool GetStartOnSystemStartup()
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
QString HtmlEscape(const QString &str, bool fMultiLine)
boost::filesystem::path qstringToBoostPath(const QString &path)
void connectViewHeadersSignals()
base58-encoded Bitcoin addresses.
Line edit that can be marked as "invalid" to show input validation feedback.
int getAvailableWidthForColumn(int column)
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
QString formatBitcoinURI(const SendCoinsRecipient &info)
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
Save window size and position.
void SetDestination(const CTxDestination &address)
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
void SubstituteFonts()
Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text repre...
bool isObscured(QWidget *w)
bool eventFilter(QObject *obj, QEvent *evt)
void setClipboard(const QString &str)
int lastColumnMinimumWidth
bool isDust(const QString &address, qint64 amount)
Base58 entry widget validator, checks for valid characters and removes some whitespace.
An output of a transaction.
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
Restore window size and position.
void on_sectionResized(int logicalIndex, int oldSize, int newSize)
void disconnectViewHeadersSignals()
int allColumnsMinimumWidth
Serialized script, used inside transaction inputs and outputs.
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 bool parse(int unit, const QString &value, qint64 *val_out)
Parse string to coin amount.
void adjustTableColumnsWidth()
bool checkPoint(const QPoint &p, const QWidget *w)
void setCheckValidator(const QValidator *v)
static int64_t nMinRelayTxFee
Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) ...
bool SetStartOnSystemStartup(bool fAutoStart)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
QString boostPathToQString(const boost::filesystem::path &path)
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Bitcoin address widget validator, checks for a valid bitcoin address.
static QString format(int unit, qint64 amount, bool plussign=false)
Format as string.
void resizeColumn(int nColumnIndex, int width)
QFont bitcoinAddressFont()