1 // Copyright (c) 2011-2018 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #ifndef BITCOIN_QT_GUIUTIL_H 6 #define BITCOIN_QT_GUIUTIL_H 7 8 #include <amount.h> 9 #include <fs.h> 10 11 #include <QEvent> 12 #include <QHeaderView> 13 #include <QItemDelegate> 14 #include <QMessageBox> 15 #include <QObject> 16 #include <QProgressBar> 17 #include <QString> 18 #include <QTableView> 19 #include <QLabel> 20 21 class QValidatedLineEdit; 22 class SendCoinsRecipient; 23 24 namespace interfaces 25 { 26 class Node; 27 } 28 29 QT_BEGIN_NAMESPACE 30 class QAbstractItemView; 31 class QDateTime; 32 class QFont; 33 class QLineEdit; 34 class QProgressDialog; 35 class QUrl; 36 class QWidget; 37 QT_END_NAMESPACE 38 39 /** Utility functions used by the Bitcoin Qt UI. 40 */ 41 namespace GUIUtil 42 { 43 // Create human-readable string from date 44 QString dateTimeStr(const QDateTime &datetime); 45 QString dateTimeStr(qint64 nTime); 46 47 // Return a monospace font 48 QFont fixedPitchFont(); 49 50 // Set up widget for address 51 void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); 52 53 // Parse "bitcoin:" URI into recipient object, return true on successful parsing 54 bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); 55 bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); 56 QString formatBitcoinURI(const SendCoinsRecipient &info); 57 58 // Returns true if given address+amount meets "dust" definition 59 bool isDust(interfaces::Node& node, const QString& address, const CAmount& amount); 60 61 // HTML escaping for rich text controls 62 QString HtmlEscape(const QString& str, bool fMultiLine=false); 63 QString HtmlEscape(const std::string& str, bool fMultiLine=false); 64 65 /** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing 66 is selected. 67 @param[in] column Data column to extract from the model 68 @param[in] role Data role to extract from the model 69 @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress 70 */ 71 void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole); 72 73 /** Return a field of the currently selected entry as a QString. Does nothing if nothing 74 is selected. 75 @param[in] column Data column to extract from the model 76 @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress 77 */ 78 QList<QModelIndex> getEntryData(QAbstractItemView *view, int column); 79 80 void setClipboard(const QString& str); 81 82 /** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix 83 when no suffix is provided by the user. 84 85 @param[in] parent Parent window (or 0) 86 @param[in] caption Window caption (or empty, for default) 87 @param[in] dir Starting directory (or empty, to default to documents directory) 88 @param[in] filter Filter specification such as "Comma Separated Files (*.csv)" 89 @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0). 90 Can be useful when choosing the save file format based on suffix. 91 */ 92 QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, 93 const QString &filter, 94 QString *selectedSuffixOut); 95 96 /** Get open filename, convenience wrapper for QFileDialog::getOpenFileName. 97 98 @param[in] parent Parent window (or 0) 99 @param[in] caption Window caption (or empty, for default) 100 @param[in] dir Starting directory (or empty, to default to documents directory) 101 @param[in] filter Filter specification such as "Comma Separated Files (*.csv)" 102 @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0). 103 Can be useful when choosing the save file format based on suffix. 104 */ 105 QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, 106 const QString &filter, 107 QString *selectedSuffixOut); 108 109 /** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking. 110 111 @returns If called from the GUI thread, return a Qt::DirectConnection. 112 If called from another thread, return a Qt::BlockingQueuedConnection. 113 */ 114 Qt::ConnectionType blockingGUIThreadConnection(); 115 116 // Determine whether a widget is hidden behind other windows 117 bool isObscured(QWidget *w); 118 119 // Activate, show and raise the widget 120 void bringToFront(QWidget* w); 121 122 // Open debug.log 123 void openDebugLogfile(); 124 125 // Open the config file 126 bool openBitcoinConf(); 127 128 /** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text 129 representation if needed. This assures that Qt can word-wrap long tooltip messages. 130 Tooltips longer than the provided size threshold (in characters) are wrapped. 131 */ 132 class ToolTipToRichTextFilter : public QObject 133 { 134 Q_OBJECT 135 136 public: 137 explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = nullptr); 138 139 protected: 140 bool eventFilter(QObject *obj, QEvent *evt); 141 142 private: 143 int size_threshold; 144 }; 145 146 /** 147 * Makes a QTableView last column feel as if it was being resized from its left border. 148 * Also makes sure the column widths are never larger than the table's viewport. 149 * In Qt, all columns are resizable from the right, but it's not intuitive resizing the last column from the right. 150 * Usually our second to last columns behave as if stretched, and when on stretch mode, columns aren't resizable 151 * interactively or programmatically. 152 * 153 * This helper object takes care of this issue. 154 * 155 */ 156 class TableViewLastColumnResizingFixer: public QObject 157 { 158 Q_OBJECT 159 160 public: 161 TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent); 162 void stretchColumnWidth(int column); 163 164 private: 165 QTableView* tableView; 166 int lastColumnMinimumWidth; 167 int allColumnsMinimumWidth; 168 int lastColumnIndex; 169 int columnCount; 170 int secondToLastColumnIndex; 171 172 void adjustTableColumnsWidth(); 173 int getAvailableWidthForColumn(int column); 174 int getColumnsWidth(); 175 void connectViewHeadersSignals(); 176 void disconnectViewHeadersSignals(); 177 void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); 178 void resizeColumn(int nColumnIndex, int width); 179 180 private Q_SLOTS: 181 void on_sectionResized(int logicalIndex, int oldSize, int newSize); 182 void on_geometriesChanged(); 183 }; 184 185 bool GetStartOnSystemStartup(); 186 bool SetStartOnSystemStartup(bool fAutoStart); 187 188 /* Convert QString to OS specific boost path through UTF-8 */ 189 fs::path qstringToBoostPath(const QString &path); 190 191 /* Convert OS specific boost path to QString through UTF-8 */ 192 QString boostPathToQString(const fs::path &path); 193 194 /* Convert seconds into a QString with days, hours, mins, secs */ 195 QString formatDurationStr(int secs); 196 197 /* Format CNodeStats.nServices bitmask into a user-readable string */ 198 QString formatServicesStr(quint64 mask); 199 200 /* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/ 201 QString formatPingTime(double dPingTime); 202 203 /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */ 204 QString formatTimeOffset(int64_t nTimeOffset); 205 206 QString formatNiceTimeOffset(qint64 secs); 207 208 QString formatBytes(uint64_t bytes); 209 210 qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize = 4, qreal startPointSize = 14); 211 212 class ClickableLabel : public QLabel 213 { 214 Q_OBJECT 215 216 Q_SIGNALS: 217 /** Emitted when the label is clicked. The relative mouse coordinates of the click are 218 * passed to the signal. 219 */ 220 void clicked(const QPoint& point); 221 protected: 222 void mouseReleaseEvent(QMouseEvent *event); 223 }; 224 225 class ClickableProgressBar : public QProgressBar 226 { 227 Q_OBJECT 228 229 Q_SIGNALS: 230 /** Emitted when the progressbar is clicked. The relative mouse coordinates of the click are 231 * passed to the signal. 232 */ 233 void clicked(const QPoint& point); 234 protected: 235 void mouseReleaseEvent(QMouseEvent *event); 236 }; 237 238 typedef ClickableProgressBar ProgressBar; 239 240 class ItemDelegate : public QItemDelegate 241 { 242 Q_OBJECT 243 public: ItemDelegate(QObject * parent)244 ItemDelegate(QObject* parent) : QItemDelegate(parent) {} 245 246 Q_SIGNALS: 247 void keyEscapePressed(); 248 249 private: 250 bool eventFilter(QObject *object, QEvent *event); 251 }; 252 253 // Fix known bugs in QProgressDialog class. 254 void PolishProgressDialog(QProgressDialog* dialog); 255 } // namespace GUIUtil 256 257 #endif // BITCOIN_QT_GUIUTIL_H 258