Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
guiutil.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2013 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "guiutil.h"
6 
8 #include "bitcoinunits.h"
9 #include "qvalidatedlineedit.h"
10 #include "walletmodel.h"
11 
12 #include "core.h"
13 #include "init.h"
14 #include "util.h"
15 
16 #ifdef WIN32
17 #ifdef _WIN32_WINNT
18 #undef _WIN32_WINNT
19 #endif
20 #define _WIN32_WINNT 0x0501
21 #ifdef _WIN32_IE
22 #undef _WIN32_IE
23 #endif
24 #define _WIN32_IE 0x0501
25 #define WIN32_LEAN_AND_MEAN 1
26 #ifndef NOMINMAX
27 #define NOMINMAX
28 #endif
29 #include "shellapi.h"
30 #include "shlobj.h"
31 #include "shlwapi.h"
32 #endif
33 
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>
38 #endif
39 
40 #include <QAbstractItemView>
41 #include <QApplication>
42 #include <QClipboard>
43 #include <QDateTime>
44 #include <QDesktopServices>
45 #include <QDesktopWidget>
46 #include <QDoubleValidator>
47 #include <QFileDialog>
48 #include <QFont>
49 #include <QLineEdit>
50 #include <QSettings>
51 #include <QTextDocument> // for Qt::mightBeRichText
52 #include <QThread>
53 
54 #if QT_VERSION < 0x050000
55 #include <QUrl>
56 #else
57 #include <QUrlQuery>
58 #endif
59 
60 #if BOOST_FILESYSTEM_VERSION >= 3
61 static boost::filesystem::detail::utf8_codecvt_facet utf8;
62 #endif
63 
64 #if defined(Q_OS_MAC)
65 extern double NSAppKitVersionNumber;
66 #if !defined(NSAppKitVersionNumber10_9)
67 #define NSAppKitVersionNumber10_9 1265
68 #endif
69 #endif
70 
71 namespace GUIUtil {
72 
73 QString dateTimeStr(const QDateTime &date)
74 {
75  return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
76 }
77 
78 QString dateTimeStr(qint64 nTime)
79 {
80  return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
81 }
82 
84 {
85  QFont font("Monospace");
86 #if QT_VERSION >= 0x040800
87  font.setStyleHint(QFont::Monospace);
88 #else
89  font.setStyleHint(QFont::TypeWriter);
90 #endif
91  return font;
92 }
93 
95 {
96  parent->setFocusProxy(widget);
97 
98  widget->setFont(bitcoinAddressFont());
99 #if QT_VERSION >= 0x040700
100  widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
101 #endif
102  widget->setValidator(new BitcoinAddressEntryValidator(parent));
103  widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
104 }
105 
106 void setupAmountWidget(QLineEdit *widget, QWidget *parent)
107 {
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);
113 }
114 
115 bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
116 {
117  // return if URI is not valid or is no bitcoin: URI
118  if(!uri.isValid() || uri.scheme() != QString("bitcoin"))
119  return false;
120 
122  rv.address = uri.path();
123  rv.amount = 0;
124 
125 #if QT_VERSION < 0x050000
126  QList<QPair<QString, QString> > items = uri.queryItems();
127 #else
128  QUrlQuery uriQuery(uri);
129  QList<QPair<QString, QString> > items = uriQuery.queryItems();
130 #endif
131  for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
132  {
133  bool fShouldReturnFalse = false;
134  if (i->first.startsWith("req-"))
135  {
136  i->first.remove(0, 4);
137  fShouldReturnFalse = true;
138  }
139 
140  if (i->first == "label")
141  {
142  rv.label = i->second;
143  fShouldReturnFalse = false;
144  }
145  if (i->first == "message")
146  {
147  rv.message = i->second;
148  fShouldReturnFalse = false;
149  }
150  else if (i->first == "amount")
151  {
152  if(!i->second.isEmpty())
153  {
154  if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
155  {
156  return false;
157  }
158  }
159  fShouldReturnFalse = false;
160  }
161 
162  if (fShouldReturnFalse)
163  return false;
164  }
165  if(out)
166  {
167  *out = rv;
168  }
169  return true;
170 }
171 
172 bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
173 {
174  // Convert bitcoin:// to bitcoin:
175  //
176  // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
177  // which will lower-case it (and thus invalidate the address).
178  if(uri.startsWith("bitcoin://", Qt::CaseInsensitive))
179  {
180  uri.replace(0, 10, "bitcoin:");
181  }
182  QUrl uriInstance(uri);
183  return parseBitcoinURI(uriInstance, out);
184 }
185 
187 {
188  QString ret = QString("bitcoin:%1").arg(info.address);
189  int paramCount = 0;
190 
191  if (info.amount)
192  {
193  ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount));
194  paramCount++;
195  }
196 
197  if (!info.label.isEmpty())
198  {
199  QString lbl(QUrl::toPercentEncoding(info.label));
200  ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl);
201  paramCount++;
202  }
203 
204  if (!info.message.isEmpty())
205  {
206  QString msg(QUrl::toPercentEncoding(info.message));;
207  ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg);
208  paramCount++;
209  }
210 
211  return ret;
212 }
213 
214 bool isDust(const QString& address, qint64 amount)
215 {
216  CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
217  CScript script; script.SetDestination(dest);
218  CTxOut txOut(amount, script);
219  return txOut.IsDust(CTransaction::nMinRelayTxFee);
220 }
221 
222 QString HtmlEscape(const QString& str, bool fMultiLine)
223 {
224 #if QT_VERSION < 0x050000
225  QString escaped = Qt::escape(str);
226 #else
227  QString escaped = str.toHtmlEscaped();
228 #endif
229  if(fMultiLine)
230  {
231  escaped = escaped.replace("\n", "<br>\n");
232  }
233  return escaped;
234 }
235 
236 QString HtmlEscape(const std::string& str, bool fMultiLine)
237 {
238  return HtmlEscape(QString::fromStdString(str), fMultiLine);
239 }
240 
241 void copyEntryData(QAbstractItemView *view, int column, int role)
242 {
243  if(!view || !view->selectionModel())
244  return;
245  QModelIndexList selection = view->selectionModel()->selectedRows(column);
246 
247  if(!selection.isEmpty())
248  {
249  // Copy first item
250  setClipboard(selection.at(0).data(role).toString());
251  }
252 }
253 
254 QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
255  const QString &filter,
256  QString *selectedSuffixOut)
257 {
258  QString selectedFilter;
259  QString myDir;
260  if(dir.isEmpty()) // Default to user documents location
261  {
262 #if QT_VERSION < 0x050000
263  myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
264 #else
265  myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
266 #endif
267  }
268  else
269  {
270  myDir = dir;
271  }
272  /* Directly convert path to native OS path separators */
273  QString result = QDir::toNativeSeparators(QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter));
274 
275  /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
276  QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
277  QString selectedSuffix;
278  if(filter_re.exactMatch(selectedFilter))
279  {
280  selectedSuffix = filter_re.cap(1);
281  }
282 
283  /* Add suffix if needed */
284  QFileInfo info(result);
285  if(!result.isEmpty())
286  {
287  if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
288  {
289  /* No suffix specified, add selected suffix */
290  if(!result.endsWith("."))
291  result.append(".");
292  result.append(selectedSuffix);
293  }
294  }
295 
296  /* Return selected suffix if asked to */
297  if(selectedSuffixOut)
298  {
299  *selectedSuffixOut = selectedSuffix;
300  }
301  return result;
302 }
303 
304 QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
305  const QString &filter,
306  QString *selectedSuffixOut)
307 {
308  QString selectedFilter;
309  QString myDir;
310  if(dir.isEmpty()) // Default to user documents location
311  {
312 #if QT_VERSION < 0x050000
313  myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
314 #else
315  myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
316 #endif
317  }
318  else
319  {
320  myDir = dir;
321  }
322  /* Directly convert path to native OS path separators */
323  QString result = QDir::toNativeSeparators(QFileDialog::getOpenFileName(parent, caption, myDir, filter, &selectedFilter));
324 
325  if(selectedSuffixOut)
326  {
327  /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
328  QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
329  QString selectedSuffix;
330  if(filter_re.exactMatch(selectedFilter))
331  {
332  selectedSuffix = filter_re.cap(1);
333  }
334  *selectedSuffixOut = selectedSuffix;
335  }
336  return result;
337 }
338 
339 Qt::ConnectionType blockingGUIThreadConnection()
340 {
341  if(QThread::currentThread() != qApp->thread())
342  {
343  return Qt::BlockingQueuedConnection;
344  }
345  else
346  {
347  return Qt::DirectConnection;
348  }
349 }
350 
351 bool checkPoint(const QPoint &p, const QWidget *w)
352 {
353  QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
354  if (!atW) return false;
355  return atW->topLevelWidget() == w;
356 }
357 
359 {
360  return !(checkPoint(QPoint(0, 0), w)
361  && checkPoint(QPoint(w->width() - 1, 0), w)
362  && checkPoint(QPoint(0, w->height() - 1), w)
363  && checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
364  && checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
365 }
366 
368 {
369  boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
370 
371  /* Open debug.log with the associated application */
372  if (boost::filesystem::exists(pathDebug))
373  QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathDebug)));
374 }
375 
377  QObject(parent), size_threshold(size_threshold)
378 {
379 
380 }
381 
383 {
384 #if defined(Q_OS_MAC)
385 // Background:
386 // OSX's default font changed in 10.9 and QT is unable to find it with its
387 // usual fallback methods when building against the 10.7 sdk or lower.
388 // The 10.8 SDK added a function to let it find the correct fallback font.
389 // If this fallback is not properly loaded, some characters may fail to
390 // render correctly.
391 //
392 // Solution: If building with the 10.7 SDK or lower and the user's platform
393 // is 10.9 or higher at runtime, substitute the correct font. This needs to
394 // happen before the QApplication is created.
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");
398 #endif
399 #endif
400 }
401 
403 {
404  if(evt->type() == QEvent::ToolTipChange)
405  {
406  QWidget *widget = static_cast<QWidget*>(obj);
407  QString tooltip = widget->toolTip();
408  if(tooltip.size() > size_threshold && !tooltip.startsWith("<qt") && !Qt::mightBeRichText(tooltip))
409  {
410  // Envelop with <qt></qt> to make sure Qt detects this as rich text
411  // Escape the current message as HTML and replace \n by <br>
412  tooltip = "<qt>" + HtmlEscape(tooltip, true) + "</qt>";
413  widget->setToolTip(tooltip);
414  return true;
415  }
416  }
417  return QObject::eventFilter(obj, evt);
418 }
419 
421 {
422  connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
423  connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
424 }
425 
426 // We need to disconnect these while handling the resize events, otherwise we can enter infinite loops.
428 {
429  disconnect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
430  disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
431 }
432 
433 // Setup the resize mode, handles compatibility for Qt5 and below as the method signatures changed.
434 // Refactored here for readability.
435 void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
436 {
437 #if QT_VERSION < 0x050000
438  tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
439 #else
440  tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
441 #endif
442 }
443 
444 void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width)
445 {
446  tableView->setColumnWidth(nColumnIndex, width);
447  tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
448 }
449 
451 {
452  int nColumnsWidthSum = 0;
453  for (int i = 0; i < columnCount; i++)
454  {
455  nColumnsWidthSum += tableView->horizontalHeader()->sectionSize(i);
456  }
457  return nColumnsWidthSum;
458 }
459 
461 {
462  int nResult = lastColumnMinimumWidth;
463  int nTableWidth = tableView->horizontalHeader()->width();
464 
465  if (nTableWidth > 0)
466  {
467  int nOtherColsWidth = getColumnsWidth() - tableView->horizontalHeader()->sectionSize(column);
468  nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
469  }
470 
471  return nResult;
472 }
473 
474 // Make sure we don't make the columns wider than the tables viewport width.
476 {
480 
481  int nTableWidth = tableView->horizontalHeader()->width();
482  int nColsWidth = getColumnsWidth();
483  if (nColsWidth > nTableWidth)
484  {
486  }
487 }
488 
489 // Make column use all the space available, useful during window resizing.
491 {
493  resizeColumn(column, getAvailableWidthForColumn(column));
495 }
496 
497 // When a section is resized this is a slot-proxy for ajustAmountColumnWidth().
498 void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int oldSize, int newSize)
499 {
501  int remainingWidth = getAvailableWidthForColumn(logicalIndex);
502  if (newSize > remainingWidth)
503  {
504  resizeColumn(logicalIndex, remainingWidth);
505  }
506 }
507 
508 // When the tabless geometry is ready, we manually perform the stretch of the "Message" column,
509 // as the "Stretch" resize mode does not allow for interactive resizing.
511 {
512  if ((getColumnsWidth() - this->tableView->horizontalHeader()->width()) != 0)
513  {
517  }
518 }
519 
524 TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth) :
525  tableView(table),
526  lastColumnMinimumWidth(lastColMinimumWidth),
527  allColumnsMinimumWidth(allColsMinimumWidth)
528 {
529  columnCount = tableView->horizontalHeader()->count();
532  tableView->horizontalHeader()->setMinimumSectionSize(allColumnsMinimumWidth);
533  setViewHeaderResizeMode(secondToLastColumnIndex, QHeaderView::Interactive);
534  setViewHeaderResizeMode(lastColumnIndex, QHeaderView::Interactive);
535 }
536 
537 #ifdef WIN32
538 boost::filesystem::path static StartupShortcutPath()
539 {
540  return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
541 }
542 
544 {
545  // check for Bitcoin.lnk
546  return boost::filesystem::exists(StartupShortcutPath());
547 }
548 
549 bool SetStartOnSystemStartup(bool fAutoStart)
550 {
551  // If the shortcut exists already, remove it for updating
552  boost::filesystem::remove(StartupShortcutPath());
553 
554  if (fAutoStart)
555  {
556  CoInitialize(NULL);
557 
558  // Get a pointer to the IShellLink interface.
559  IShellLink* psl = NULL;
560  HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
561  CLSCTX_INPROC_SERVER, IID_IShellLink,
562  reinterpret_cast<void**>(&psl));
563 
564  if (SUCCEEDED(hres))
565  {
566  // Get the current executable path
567  TCHAR pszExePath[MAX_PATH];
568  GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
569 
570  TCHAR pszArgs[5] = TEXT("-min");
571 
572  // Set the path to the shortcut target
573  psl->SetPath(pszExePath);
574  PathRemoveFileSpec(pszExePath);
575  psl->SetWorkingDirectory(pszExePath);
576  psl->SetShowCmd(SW_SHOWMINNOACTIVE);
577  psl->SetArguments(pszArgs);
578 
579  // Query IShellLink for the IPersistFile interface for
580  // saving the shortcut in persistent storage.
581  IPersistFile* ppf = NULL;
582  hres = psl->QueryInterface(IID_IPersistFile,
583  reinterpret_cast<void**>(&ppf));
584  if (SUCCEEDED(hres))
585  {
586  WCHAR pwsz[MAX_PATH];
587  // Ensure that the string is ANSI.
588  MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
589  // Save the link by calling IPersistFile::Save.
590  hres = ppf->Save(pwsz, TRUE);
591  ppf->Release();
592  psl->Release();
593  CoUninitialize();
594  return true;
595  }
596  psl->Release();
597  }
598  CoUninitialize();
599  return false;
600  }
601  return true;
602 }
603 
604 #elif defined(Q_OS_LINUX)
605 
606 // Follow the Desktop Application Autostart Spec:
607 // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
608 
609 boost::filesystem::path static GetAutostartDir()
610 {
611  namespace fs = boost::filesystem;
612 
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";
617  return fs::path();
618 }
619 
620 boost::filesystem::path static GetAutostartFilePath()
621 {
622  return GetAutostartDir() / "bitcoin.desktop";
623 }
624 
626 {
627  boost::filesystem::ifstream optionFile(GetAutostartFilePath());
628  if (!optionFile.good())
629  return false;
630  // Scan through file for "Hidden=true":
631  std::string line;
632  while (!optionFile.eof())
633  {
634  getline(optionFile, line);
635  if (line.find("Hidden") != std::string::npos &&
636  line.find("true") != std::string::npos)
637  return false;
638  }
639  optionFile.close();
640 
641  return true;
642 }
643 
644 bool SetStartOnSystemStartup(bool fAutoStart)
645 {
646  if (!fAutoStart)
647  boost::filesystem::remove(GetAutostartFilePath());
648  else
649  {
650  char pszExePath[MAX_PATH+1];
651  memset(pszExePath, 0, sizeof(pszExePath));
652  if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
653  return false;
654 
655  boost::filesystem::create_directories(GetAutostartDir());
656 
657  boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
658  if (!optionFile.good())
659  return false;
660  // Write a bitcoin.desktop file to the autostart directory:
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";
667  optionFile.close();
668  }
669  return true;
670 }
671 
672 
673 #elif defined(Q_OS_MAC)
674 // based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m
675 
676 #include <CoreFoundation/CoreFoundation.h>
677 #include <CoreServices/CoreServices.h>
678 
679 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
680 LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
681 {
682  // loop through the list of startup items and try to find the bitcoin app
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, &currentItemURL, NULL);
689  if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
690  // found
691  CFRelease(currentItemURL);
692  return item;
693  }
694  if(currentItemURL) {
695  CFRelease(currentItemURL);
696  }
697  }
698  return NULL;
699 }
700 
702 {
703  CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
704  LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
705  LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
706  return !!foundItem; // return boolified object
707 }
708 
709 bool SetStartOnSystemStartup(bool fAutoStart)
710 {
711  CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
712  LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
713  LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
714 
715  if(fAutoStart && !foundItem) {
716  // add bitcoin app to startup item list
717  LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, bitcoinAppUrl, NULL, NULL);
718  }
719  else if(!fAutoStart && foundItem) {
720  // remove item
721  LSSharedFileListItemRemove(loginItems, foundItem);
722  }
723  return true;
724 }
725 #else
726 
727 bool GetStartOnSystemStartup() { return false; }
728 bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
729 
730 #endif
731 
732 void saveWindowGeometry(const QString& strSetting, QWidget *parent)
733 {
734  QSettings settings;
735  settings.setValue(strSetting + "Pos", parent->pos());
736  settings.setValue(strSetting + "Size", parent->size());
737 }
738 
739 void restoreWindowGeometry(const QString& strSetting, const QSize& defaultSize, QWidget *parent)
740 {
741  QSettings settings;
742  QPoint pos = settings.value(strSetting + "Pos").toPoint();
743  QSize size = settings.value(strSetting + "Size", defaultSize).toSize();
744 
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);
749  }
750 
751  parent->resize(size);
752  parent->move(pos);
753 }
754 
755 void setClipboard(const QString& str)
756 {
757  QApplication::clipboard()->setText(str, QClipboard::Clipboard);
758  QApplication::clipboard()->setText(str, QClipboard::Selection);
759 }
760 
761 #if BOOST_FILESYSTEM_VERSION >= 3
762 boost::filesystem::path qstringToBoostPath(const QString &path)
763 {
764  return boost::filesystem::path(path.toStdString(), utf8);
765 }
766 
767 QString boostPathToQString(const boost::filesystem::path &path)
768 {
769  return QString::fromStdString(path.string(utf8));
770 }
771 #else
772 #warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older
773 boost::filesystem::path qstringToBoostPath(const QString &path)
774 {
775  return boost::filesystem::path(path.toStdString());
776 }
777 
778 QString boostPathToQString(const boost::filesystem::path &path)
779 {
780  return QString::fromStdString(path.string());
781 }
782 #endif
783 
784 } // namespace GUIUtil
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:973
void openDebugLogfile()
Definition: guiutil.cpp:367
bool IsDust(int64_t nMinRelayTxFee) const
Definition: core.h:151
Utility functions used by the Bitcoin Qt UI.
Definition: guiutil.cpp:71
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
Definition: guiutil.cpp:304
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:106
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
Definition: guiutil.cpp:435
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...
Definition: guiutil.cpp:524
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:73
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:339
bool GetStartOnSystemStartup()
Definition: guiutil.cpp:727
ToolTipToRichTextFilter(int size_threshold, QObject *parent=0)
Definition: guiutil.cpp:376
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:222
boost::filesystem::path qstringToBoostPath(const QString &path)
Definition: guiutil.cpp:773
base58-encoded Bitcoin addresses.
Definition: base58.h:101
Line edit that can be marked as "invalid" to show input validation feedback.
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
Definition: guiutil.cpp:115
QString formatBitcoinURI(const SendCoinsRecipient &info)
Definition: guiutil.cpp:186
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
Save window size and position.
Definition: guiutil.cpp:732
void SetDestination(const CTxDestination &address)
Definition: script.cpp:1925
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:94
void SubstituteFonts()
Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text repre...
Definition: guiutil.cpp:382
bool isObscured(QWidget *w)
Definition: guiutil.cpp:358
bool eventFilter(QObject *obj, QEvent *evt)
Definition: guiutil.cpp:402
void setClipboard(const QString &str)
Definition: guiutil.cpp:755
bool isDust(const QString &address, qint64 amount)
Definition: guiutil.cpp:214
Base58 entry widget validator, checks for valid characters and removes some whitespace.
An output of a transaction.
Definition: core.h:119
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
Restore window size and position.
Definition: guiutil.cpp:739
#define MAX_PATH
Definition: util.h:72
void on_sectionResized(int logicalIndex, int oldSize, int newSize)
Definition: guiutil.cpp:498
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:401
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 ...
Definition: guiutil.cpp:254
static bool parse(int unit, const QString &value, qint64 *val_out)
Parse string to coin amount.
bool checkPoint(const QPoint &p, const QWidget *w)
Definition: guiutil.cpp:351
void setCheckValidator(const QValidator *v)
static int64_t nMinRelayTxFee
Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) ...
Definition: core.h:187
bool SetStartOnSystemStartup(bool fAutoStart)
Definition: guiutil.cpp:728
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:218
QString boostPathToQString(const boost::filesystem::path &path)
Definition: guiutil.cpp:778
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Definition: guiutil.cpp:241
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)
Definition: guiutil.cpp:444
QFont bitcoinAddressFont()
Definition: guiutil.cpp:83