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