rpcconsole.h raw
1 // Copyright (c) 2011-2022 The Limenka 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 LIMENKA_QT_RPCCONSOLE_H
6 #define LIMENKA_QT_RPCCONSOLE_H
7
8 #include <limenka-build-config.h> // IWYU pragma: keep
9
10 #include <qt/clientmodel.h>
11 #include <qt/guiutil.h>
12 #include <qt/peertablemodel.h>
13
14 #include <net.h>
15
16 #include <QByteArray>
17 #include <QCompleter>
18 #include <QMimeData>
19 #include <QTextDocumentFragment>
20 #include <QTextEdit>
21 #include <QThread>
22 #include <QWidget>
23
24 class GuiNetWatch;
25 class PairingPage;
26 class PlatformStyle;
27 class RPCExecutor;
28 class RPCTimerInterface;
29 class WalletModel;
30
31 namespace interfaces {
32 class Node;
33 }
34
35 namespace Ui {
36 class RPCConsole;
37 }
38
39 QT_BEGIN_NAMESPACE
40 class QColor;
41 class QEvent;
42 class QDateTime;
43 class QLabel;
44 class QMenu;
45 class QItemSelection;
46 QT_END_NAMESPACE
47
48 /** Local Limenka RPC console. */
49 class RPCConsole: public QWidget
50 {
51 Q_OBJECT
52
53 public:
54 struct ThemeColors {
55 QColor warning;
56 QColor userinput;
57 };
58 explicit RPCConsole(interfaces::Node& node, const PlatformStyle *platformStyle, QWidget *parent);
59 ~RPCConsole();
60
61 static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr);
62 static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr) {
63 return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model);
64 }
65
66 void setClientModel(ClientModel *model = nullptr, int bestblock_height = 0, int64_t bestblock_date = 0, double verification_progress = 0.0);
67 void addPairingTab();
68
69 #ifdef ENABLE_WALLET
70 void addWallet(WalletModel* const walletModel);
71 void removeWallet(WalletModel* const walletModel);
72 #endif // ENABLE_WALLET
73
74 enum MessageClass {
75 MC_ERROR,
76 MC_DEBUG,
77 CMD_REQUEST,
78 CMD_REPLY,
79 CMD_ERROR
80 };
81
82 enum class TabTypes {
83 INFO,
84 CONSOLE,
85 GRAPH,
86 PEERS,
87 PAIRING,
88 };
89
90 std::vector<TabTypes> tabs() const;
91
92 QString tabTitle(TabTypes tab_type) const;
93 QKeySequence tabShortcut(TabTypes tab_type) const;
94
95
96 protected:
97 virtual bool eventFilter(QObject* obj, QEvent *event) override;
98 void keyPressEvent(QKeyEvent *) override;
99 void changeEvent(QEvent* e) override;
100
101 private Q_SLOTS:
102 void on_lineEdit_returnPressed();
103 void on_tabWidget_currentChanged(int index);
104 /** open the debug.log from the current datadir */
105 void on_openDebugLogfileButton_clicked();
106 /** change the time range of the network traffic graph */
107 void on_sldGraphRange_valueChanged(int value);
108 /** update traffic statistics */
109 void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut);
110 void resizeEvent(QResizeEvent *event) override;
111 void showEvent(QShowEvent *event) override;
112 void hideEvent(QHideEvent *event) override;
113 /** Show custom context menu on Peers tab */
114 void showPeersTableContextMenu(const QPoint& point);
115 /** Show custom context menu on Bans tab */
116 void showBanTableContextMenu(const QPoint& point);
117 /** Hides ban table if no bans are present */
118 void showOrHideBanTableIfRequired();
119 /** clear the selected node */
120 void clearSelectedNode();
121 /** reset all fields in UI detailed information to N/A */
122 void resetDetailWidget();
123 /** show detailed information on ui about selected node */
124 void updateDetailWidget();
125
126 public Q_SLOTS:
127 void clear(bool keep_prompt = false);
128 void fontBigger();
129 void fontSmaller();
130 void setFontSize(int newSize);
131 /** Append the message to the message widget */
132 void message(int category, const QString &msg) { message(category, msg, false); }
133 void message(int category, const QString &message, bool html);
134 /** Set number of connections shown in the UI */
135 void setNumConnections(int count);
136 /** Set network state shown in the UI */
137 void setNetworkActive(bool networkActive);
138 /** Set number of blocks and last block date shown in the UI */
139 void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype);
140 /** Set size (number of transactions and memory usage) of the mempool in the UI */
141 void setMempoolSize(long numberOfTxs, size_t dynUsage, size_t maxUsage);
142 /** Go forward or back in history */
143 void browseHistory(int offset);
144 /** Scroll console view to end */
145 void scrollToEnd();
146 /** Disconnect a selected node on the Peers tab */
147 void disconnectSelectedNode();
148 /** Ban a selected node on the Peers tab */
149 void banSelectedNode(int bantime);
150 /** Unban a selected node on the Bans tab */
151 void unbanSelectedNode();
152 /** set which tab has the focus (is visible) */
153 void setTabFocus(enum TabTypes tabType);
154 #ifdef ENABLE_WALLET
155 /** Set the current (ie - active) wallet */
156 void setCurrentWallet(WalletModel* const wallet_model);
157 #endif // ENABLE_WALLET
158
159 private:
160 struct TranslatedStrings {
161 const QString yes{tr("Yes")}, no{tr("No")}, to{tr("To")}, from{tr("From")},
162 ban_for{tr("Ban for")}, na{tr("N/A")}, unknown{tr("Unknown")}, no_permissions{tr("None")};
163 } const ts;
164
165 void startExecutor();
166 void setTrafficGraphRange(int mins);
167 void WriteCommandHistory();
168 void ClearCommandHistory();
169
170 enum ColumnWidths
171 {
172 DIRECTION_COLUMN_WIDTH = 32,
173 ADDRESS_COLUMN_WIDTH = 200,
174 SUBVERSION_COLUMN_WIDTH = 150,
175 PING_COLUMN_WIDTH = 80,
176 BANSUBNET_COLUMN_WIDTH = 200,
177 BANTIME_COLUMN_WIDTH = 250
178
179 };
180
181 interfaces::Node& m_node;
182 Ui::RPCConsole* const ui;
183 ClientModel *clientModel = nullptr;
184 std::map<TabTypes, QWidget*> m_tabs;
185 PairingPage *m_tab_pairing{nullptr};
186 GuiNetWatch *netwatch = nullptr;
187 QStringList history;
188 int historyPtr = 0;
189 QString cmdBeforeBrowsing;
190 QList<NodeId> cachedNodeids;
191 const PlatformStyle* const platformStyle;
192 RPCTimerInterface *rpcTimerInterface = nullptr;
193 QMenu *peersTableContextMenu = nullptr;
194 QMenu *banTableContextMenu = nullptr;
195 int consoleFontSize = 0;
196 QCompleter *autoCompleter = nullptr;
197 QThread thread;
198 RPCExecutor* m_executor{nullptr};
199 WalletModel* m_last_wallet_model{nullptr};
200 bool m_is_executing{false};
201 QByteArray m_peer_widget_header_state;
202 QByteArray m_banlist_widget_header_state;
203 bool m_alternating_row_colors{false};
204
205 // Theme Colors
206 const ThemeColors *m_theme_colors;
207
208 /** Update UI with latest network info from model. */
209 void updateNetworkState();
210
211 /** Helper for the output of a time duration field. Inputs are UNIX epoch times. */
212 QString TimeDurationField(std::chrono::seconds time_now, std::chrono::seconds time_at_event) const
213 {
214 return time_at_event.count() ? GUIUtil::formatDurationStr(time_now - time_at_event) : tr("Never");
215 }
216
217 void updateWindowTitle();
218 void updateThemeColors();
219 void updateConsoleStyleSheet();
220
221 private Q_SLOTS:
222 void updateAlerts(const QString& warnings);
223 };
224
225 /**
226 * A version of QTextEdit that only populates plaintext mime data from a
227 * selection, this avoids some bad behavior in QT's HTML->Markdown conversion.
228 */
229 class PlainCopyTextEdit : public QTextEdit {
230 Q_OBJECT
231 public:
232 using QTextEdit::QTextEdit;
233 protected:
234 QMimeData* createMimeDataFromSelection() const override {
235 auto md = new QMimeData();
236 md->setText(textCursor().selection().toPlainText());
237 return md;
238 }
239 };
240
241 #endif // LIMENKA_QT_RPCCONSOLE_H
242