10
10
#include < QThread>
11
11
#include < QTextEdit>
12
12
#include < QKeyEvent>
13
+ #include < QUrl>
13
14
14
15
#include < boost/tokenizer.hpp>
15
16
19
20
const int CONSOLE_SCROLLBACK = 50 ;
20
21
const int CONSOLE_HISTORY = 50 ;
21
22
23
+ const QSize ICON_SIZE (24 , 24 );
24
+
25
+ const struct {
26
+ const char *url;
27
+ const char *source;
28
+ } ICON_MAPPING[] = {
29
+ {" cmd-request" , " :/icons/tx_input" },
30
+ {" cmd-reply" , " :/icons/tx_output" },
31
+ {" cmd-error" , " :/icons/tx_output" },
32
+ {" misc" , " :/icons/tx_inout" },
33
+ {NULL , NULL }
34
+ };
35
+
22
36
/* Object for executing console RPC commands in a separate thread.
23
37
*/
24
38
class RPCExecutor : public QObject
@@ -83,12 +97,9 @@ void RPCExecutor::request(const QString &command)
83
97
RPCConsole::RPCConsole (QWidget *parent) :
84
98
QDialog(parent),
85
99
ui(new Ui::RPCConsole),
86
- firstLayout(true ),
87
100
historyPtr(0 )
88
101
{
89
102
ui->setupUi (this );
90
- ui->messagesWidget ->horizontalHeader ()->setResizeMode (1 , QHeaderView::Stretch);
91
- ui->messagesWidget ->setContextMenuPolicy (Qt::ActionsContextMenu);
92
103
93
104
#ifndef WIN32
94
105
// Show Debug logfile label and Open button only for Windows
@@ -99,13 +110,6 @@ RPCConsole::RPCConsole(QWidget *parent) :
99
110
// Install event filter for up and down arrow
100
111
ui->lineEdit ->installEventFilter (this );
101
112
102
- // Add "Copy message" to context menu explicitly
103
- QAction *copyMessageAction = new QAction (tr (" &Copy" ), this );
104
- copyMessageAction->setShortcut (QKeySequence (Qt::CTRL | Qt::Key_C));
105
- copyMessageAction->setShortcutContext (Qt::WidgetShortcut);
106
- connect (copyMessageAction, SIGNAL (triggered ()), this , SLOT (copyMessage ()));
107
- ui->messagesWidget ->addAction (copyMessageAction);
108
-
109
113
connect (ui->clearButton , SIGNAL (clicked ()), this , SLOT (clear ()));
110
114
connect (ui->openDebugLogfileButton , SIGNAL (clicked ()), this , SLOT (on_openDebugLogfileButton_clicked ()));
111
115
@@ -159,68 +163,62 @@ void RPCConsole::setClientModel(ClientModel *model)
159
163
}
160
164
}
161
165
162
- static QColor categoryColor (int category)
166
+ static QString categoryClass (int category)
163
167
{
164
168
switch (category)
165
169
{
166
- case RPCConsole::MC_ERROR: return QColor (255 ,0 ,0 ); break ;
167
- case RPCConsole::MC_DEBUG: return QColor (192 ,192 ,192 ); break ;
168
- case RPCConsole::CMD_REQUEST: return QColor (128 ,128 ,128 ); break ;
169
- case RPCConsole::CMD_REPLY: return QColor (128 ,255 ,128 ); break ;
170
- case RPCConsole::CMD_ERROR: return QColor (255 ,128 ,128 ); break ;
171
- default : return QColor (0 ,0 ,0 );
170
+ case RPCConsole::CMD_REQUEST: return " cmd-request" ; break ;
171
+ case RPCConsole::CMD_REPLY: return " cmd-reply" ; break ;
172
+ case RPCConsole::CMD_ERROR: return " cmd-error" ; break ;
173
+ default : return " misc" ;
172
174
}
173
175
}
174
176
175
177
void RPCConsole::clear ()
176
178
{
177
179
ui->messagesWidget ->clear ();
178
- ui->messagesWidget ->setRowCount (0 );
179
180
ui->lineEdit ->clear ();
180
181
ui->lineEdit ->setFocus ();
181
182
182
- message (CMD_REPLY, tr (" Welcome to the bitcoin RPC console." )+" \n " +
183
- tr (" Use up and down arrows to navigate history, and Ctrl-L to clear screen." )+" \n " +
184
- tr (" Type \" help\" for an overview of available commands." ));
183
+ // Add smoothly scaled icon images.
184
+ // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
185
+ for (int i=0 ; ICON_MAPPING[i].url ; ++i)
186
+ {
187
+ ui->messagesWidget ->document ()->addResource (
188
+ QTextDocument::ImageResource,
189
+ QUrl (ICON_MAPPING[i].url ),
190
+ QImage (ICON_MAPPING[i].source ).scaled (ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
191
+ }
192
+
193
+ // Set default style sheet
194
+ ui->messagesWidget ->document ()->setDefaultStyleSheet (
195
+ " table { }"
196
+ " td.time { color: #808080; padding-top: 3px; } "
197
+ " td.message { font-family: Monospace; font-size: 12px; } "
198
+ " td.cmd-request { color: #006060; } "
199
+ " td.cmd-error { color: red; } "
200
+ " b { color: #006060; } "
201
+ );
202
+
203
+ message (CMD_REPLY, tr (" Welcome to the Bitcoin RPC console.<br>"
204
+ " Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen.<br>"
205
+ " Type <b>help</b> for an overview of available commands." ), true );
185
206
}
186
207
187
- void RPCConsole::message (int category, const QString &message)
208
+ void RPCConsole::message (int category, const QString &message, bool html )
188
209
{
189
- // Add row to messages widget
190
- int row = ui->messagesWidget ->rowCount ();
191
- ui->messagesWidget ->setRowCount (row+1 );
192
-
193
210
QTime time = QTime::currentTime ();
194
- QTableWidgetItem *newTime = new QTableWidgetItem (time.toString ());
195
- newTime->setData (Qt::DecorationRole, categoryColor (category));
196
- newTime->setForeground (QColor (128 ,128 ,128 ));
197
- newTime->setFlags (Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
198
-
199
- int numLines = message.count (" \n " ) + 1 ;
200
- // As Qt doesn't like very tall cells (they break scrolling) keep only short messages in
201
- // the cell text, longer messages trigger a display widget with scroll bar
202
- if (numLines < 5 )
203
- {
204
- QTableWidgetItem *newItem = new QTableWidgetItem (message);
205
- newItem->setFlags (Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
206
- if (category == CMD_ERROR) // Coloring error messages in red
207
- newItem->setForeground (QColor (255 ,16 ,16 ));
208
- ui->messagesWidget ->setItem (row, 1 , newItem);
209
- } else {
210
- QTextEdit *newWidget = new QTextEdit;
211
- newWidget->setText (message);
212
- newWidget->setMaximumHeight (100 );
213
- newWidget->setReadOnly (true );
214
- ui->messagesWidget ->setCellWidget (row, 1 , newWidget);
215
- }
216
-
217
- ui->messagesWidget ->setItem (row, 0 , newTime);
218
- ui->messagesWidget ->resizeRowToContents (row);
219
- // Preserve only limited scrollback buffer
220
- while (ui->messagesWidget ->rowCount () > CONSOLE_SCROLLBACK)
221
- ui->messagesWidget ->removeRow (0 );
222
- // Scroll to bottom after table is updated
223
- QTimer::singleShot (0 , ui->messagesWidget , SLOT (scrollToBottom ()));
211
+ QString timeString = time.toString ();
212
+ QString out;
213
+ out += " <table><tr><td class=\" time\" width=\" 65\" >" + timeString + " </td>" ;
214
+ out += " <td class=\" icon\" width=\" 32\" ><img src=\" " + categoryClass (category) + " \" ></td>" ;
215
+ out += " <td class=\" message " + categoryClass (category) + " \" valign=\" middle\" >" ;
216
+ if (html)
217
+ out += message;
218
+ else
219
+ out += GUIUtil::HtmlEscape (message, true );
220
+ out += " </td></tr></table>" ;
221
+ ui->messagesWidget ->append (out);
224
222
}
225
223
226
224
void RPCConsole::setNumConnections (int count)
@@ -298,24 +296,10 @@ void RPCConsole::startExecutor()
298
296
thread->start ();
299
297
}
300
298
301
- void RPCConsole::copyMessage ()
302
- {
303
- GUIUtil::copyEntryData (ui->messagesWidget , 1 , Qt::EditRole);
304
- }
305
-
306
299
void RPCConsole::on_tabWidget_currentChanged (int index)
307
300
{
308
301
if (ui->tabWidget ->widget (index) == ui->tab_console )
309
302
{
310
- if (firstLayout)
311
- {
312
- // Work around QTableWidget issue:
313
- // Call resizeRowsToContents on first Layout request with widget visible,
314
- // to make sure multiline messages that were added before the console was shown
315
- // have the right height.
316
- firstLayout = false ;
317
- ui->messagesWidget ->resizeRowsToContents ();
318
- }
319
303
ui->lineEdit ->setFocus ();
320
304
}
321
305
}
0 commit comments