Line data Source code
1 : // Copyright (c) 2011-2020 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 QAction;
32 : class QDateTime;
33 : class QFont;
34 : class QLineEdit;
35 : class QMenu;
36 : class QPoint;
37 : class QProgressDialog;
38 : class QUrl;
39 : class QWidget;
40 : QT_END_NAMESPACE
41 :
42 : /** Utility functions used by the Bitcoin Qt UI.
43 : */
44 : namespace GUIUtil
45 : {
46 : // Create human-readable string from date
47 : QString dateTimeStr(const QDateTime &datetime);
48 : QString dateTimeStr(qint64 nTime);
49 :
50 : // Return a monospace font
51 : QFont fixedPitchFont();
52 :
53 : // Set up widget for address
54 : void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent);
55 :
56 : // Parse "bitcoin:" URI into recipient object, return true on successful parsing
57 : bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out);
58 : bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
59 : QString formatBitcoinURI(const SendCoinsRecipient &info);
60 :
61 : // Returns true if given address+amount meets "dust" definition
62 : bool isDust(interfaces::Node& node, const QString& address, const CAmount& amount);
63 :
64 : // HTML escaping for rich text controls
65 : QString HtmlEscape(const QString& str, bool fMultiLine=false);
66 : QString HtmlEscape(const std::string& str, bool fMultiLine=false);
67 :
68 : /** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing
69 : is selected.
70 : @param[in] column Data column to extract from the model
71 : @param[in] role Data role to extract from the model
72 : @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
73 : */
74 : void copyEntryData(const QAbstractItemView *view, int column, int role=Qt::EditRole);
75 :
76 : /** Return a field of the currently selected entry as a QString. Does nothing if nothing
77 : is selected.
78 : @param[in] column Data column to extract from the model
79 : @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
80 : */
81 : QList<QModelIndex> getEntryData(const QAbstractItemView *view, int column);
82 :
83 : /** Returns true if the specified field of the currently selected view entry is not empty.
84 : @param[in] column Data column to extract from the model
85 : @param[in] role Data role to extract from the model
86 : @see TransactionView::contextualMenu
87 : */
88 : bool hasEntryData(const QAbstractItemView *view, int column, int role);
89 :
90 : void setClipboard(const QString& str);
91 :
92 : /**
93 : * Determine default data directory for operating system.
94 : */
95 : QString getDefaultDataDirectory();
96 :
97 : /** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
98 : when no suffix is provided by the user.
99 :
100 : @param[in] parent Parent window (or 0)
101 : @param[in] caption Window caption (or empty, for default)
102 : @param[in] dir Starting directory (or empty, to default to documents directory)
103 : @param[in] filter Filter specification such as "Comma Separated Files (*.csv)"
104 : @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0).
105 : Can be useful when choosing the save file format based on suffix.
106 : */
107 : QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
108 : const QString &filter,
109 : QString *selectedSuffixOut);
110 :
111 : /** Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
112 :
113 : @param[in] parent Parent window (or 0)
114 : @param[in] caption Window caption (or empty, for default)
115 : @param[in] dir Starting directory (or empty, to default to documents directory)
116 : @param[in] filter Filter specification such as "Comma Separated Files (*.csv)"
117 : @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0).
118 : Can be useful when choosing the save file format based on suffix.
119 : */
120 : QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
121 : const QString &filter,
122 : QString *selectedSuffixOut);
123 :
124 : /** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking.
125 :
126 : @returns If called from the GUI thread, return a Qt::DirectConnection.
127 : If called from another thread, return a Qt::BlockingQueuedConnection.
128 : */
129 : Qt::ConnectionType blockingGUIThreadConnection();
130 :
131 : // Determine whether a widget is hidden behind other windows
132 : bool isObscured(QWidget *w);
133 :
134 : // Activate, show and raise the widget
135 : void bringToFront(QWidget* w);
136 :
137 : // Set shortcut to close window
138 : void handleCloseWindowShortcut(QWidget* w);
139 :
140 : // Open debug.log
141 : void openDebugLogfile();
142 :
143 : // Open the config file
144 : bool openBitcoinConf();
145 :
146 : /** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text
147 : representation if needed. This assures that Qt can word-wrap long tooltip messages.
148 : Tooltips longer than the provided size threshold (in characters) are wrapped.
149 : */
150 0 : class ToolTipToRichTextFilter : public QObject
151 : {
152 : Q_OBJECT
153 :
154 : public:
155 : explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = nullptr);
156 :
157 : protected:
158 : bool eventFilter(QObject *obj, QEvent *evt) override;
159 :
160 : private:
161 : int size_threshold;
162 : };
163 :
164 : /**
165 : * Qt event filter that intercepts QEvent::FocusOut events for QLabel objects, and
166 : * resets their `textInteractionFlags' property to get rid of the visible cursor.
167 : *
168 : * This is a temporary fix of QTBUG-59514.
169 : */
170 0 : class LabelOutOfFocusEventFilter : public QObject
171 : {
172 : Q_OBJECT
173 :
174 : public:
175 : explicit LabelOutOfFocusEventFilter(QObject* parent);
176 : bool eventFilter(QObject* watched, QEvent* event) override;
177 : };
178 :
179 : /**
180 : * Makes a QTableView last column feel as if it was being resized from its left border.
181 : * Also makes sure the column widths are never larger than the table's viewport.
182 : * In Qt, all columns are resizable from the right, but it's not intuitive resizing the last column from the right.
183 : * Usually our second to last columns behave as if stretched, and when on stretch mode, columns aren't resizable
184 : * interactively or programmatically.
185 : *
186 : * This helper object takes care of this issue.
187 : *
188 : */
189 0 : class TableViewLastColumnResizingFixer: public QObject
190 : {
191 : Q_OBJECT
192 :
193 : public:
194 : TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent);
195 : void stretchColumnWidth(int column);
196 :
197 : private:
198 : QTableView* tableView;
199 : int lastColumnMinimumWidth;
200 : int allColumnsMinimumWidth;
201 : int lastColumnIndex;
202 : int columnCount;
203 : int secondToLastColumnIndex;
204 :
205 : void adjustTableColumnsWidth();
206 : int getAvailableWidthForColumn(int column);
207 : int getColumnsWidth();
208 : void connectViewHeadersSignals();
209 : void disconnectViewHeadersSignals();
210 : void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode);
211 : void resizeColumn(int nColumnIndex, int width);
212 :
213 : private Q_SLOTS:
214 : void on_sectionResized(int logicalIndex, int oldSize, int newSize);
215 : void on_geometriesChanged();
216 : };
217 :
218 : bool GetStartOnSystemStartup();
219 : bool SetStartOnSystemStartup(bool fAutoStart);
220 :
221 : /* Convert QString to OS specific boost path through UTF-8 */
222 : fs::path qstringToBoostPath(const QString &path);
223 :
224 : /* Convert OS specific boost path to QString through UTF-8 */
225 : QString boostPathToQString(const fs::path &path);
226 :
227 : /* Convert seconds into a QString with days, hours, mins, secs */
228 : QString formatDurationStr(int secs);
229 :
230 : /* Format CNodeStats.nServices bitmask into a user-readable string */
231 : QString formatServicesStr(quint64 mask);
232 :
233 : /* Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0*/
234 : QString formatPingTime(int64_t ping_usec);
235 :
236 : /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */
237 : QString formatTimeOffset(int64_t nTimeOffset);
238 :
239 : QString formatNiceTimeOffset(qint64 secs);
240 :
241 : QString formatBytes(uint64_t bytes);
242 :
243 : qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize = 4, qreal startPointSize = 14);
244 :
245 0 : class ClickableLabel : public QLabel
246 : {
247 : Q_OBJECT
248 :
249 : Q_SIGNALS:
250 : /** Emitted when the label is clicked. The relative mouse coordinates of the click are
251 : * passed to the signal.
252 : */
253 : void clicked(const QPoint& point);
254 : protected:
255 : void mouseReleaseEvent(QMouseEvent *event) override;
256 : };
257 :
258 0 : class ClickableProgressBar : public QProgressBar
259 : {
260 : Q_OBJECT
261 :
262 : Q_SIGNALS:
263 : /** Emitted when the progressbar is clicked. The relative mouse coordinates of the click are
264 : * passed to the signal.
265 : */
266 : void clicked(const QPoint& point);
267 : protected:
268 : void mouseReleaseEvent(QMouseEvent *event) override;
269 : };
270 :
271 : typedef ClickableProgressBar ProgressBar;
272 :
273 0 : class ItemDelegate : public QItemDelegate
274 : {
275 : Q_OBJECT
276 : public:
277 0 : ItemDelegate(QObject* parent) : QItemDelegate(parent) {}
278 :
279 : Q_SIGNALS:
280 : void keyEscapePressed();
281 :
282 : private:
283 : bool eventFilter(QObject *object, QEvent *event) override;
284 : };
285 :
286 : // Fix known bugs in QProgressDialog class.
287 : void PolishProgressDialog(QProgressDialog* dialog);
288 :
289 : /**
290 : * Returns the distance in pixels appropriate for drawing a subsequent character after text.
291 : *
292 : * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 13.0.
293 : * In Qt 5.11 the QFontMetrics::horizontalAdvance() was introduced.
294 : */
295 : int TextWidth(const QFontMetrics& fm, const QString& text);
296 :
297 : /**
298 : * Writes to debug.log short info about the used Qt and the host system.
299 : */
300 : void LogQtInfo();
301 :
302 : /**
303 : * Call QMenu::popup() only on supported QT_QPA_PLATFORM.
304 : */
305 : void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action = nullptr);
306 : } // namespace GUIUtil
307 :
308 : #endif // BITCOIN_QT_GUIUTIL_H
|