1212#include " bantablemodel.h"
1313#include " clientmodel.h"
1414#include " guiutil.h"
15+ #include " guiconstants.h"
1516#include " platformstyle.h"
1617#include " bantablemodel.h"
1718
2829#include < db_cxx.h>
2930#endif
3031
32+ #include < QFile>
3133#include < QKeyEvent>
3234#include < QMenu>
3335#include < QScrollBar>
3436#include < QSettings>
3537#include < QSignalMapper>
38+
39+ #include < QString>
3640#include < QStringList>
41+ #include < QTextStream>
42+ #include < QTextCursor>
3743#include < QThread>
3844#include < QTime>
3945#include < QTimer>
4046
47+ #if QT_VERSION < 0x050000
48+ #include < QUrl>
49+ #endif
50+
4151// TODO: add a scrollback limit, as there is currently none
4252// TODO: make it possible to filter out categories (esp debug messages when implemented)
4353// TODO: receive errors and debug messages through ClientModel
@@ -290,6 +300,11 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
290300 ui->detailWidget ->hide ();
291301 ui->peerHeading ->setText (tr (" Select a peer to view detailed information." ));
292302
303+ // set up timer for auto refresh for error log
304+ errorLogTimer = new QTimer ();
305+ connect (errorLogTimer, SIGNAL (timeout ()), SLOT (errorLogRefresh ()));
306+ errorLogTimer->setInterval (ERROR_LOG_UPDATE_DELAY );
307+
293308 QSettings settings;
294309 consoleFontSize = settings.value (fontSizeSettingsKey, QFontInfo (QFont ()).pointSize ()).toInt ();
295310 clear ();
@@ -300,10 +315,115 @@ RPCConsole::~RPCConsole()
300315 GUIUtil::saveWindowGeometry (" nRPCConsoleWindow" , this );
301316 Q_EMIT stopExecutor ();
302317 RPCUnsetTimerInterface (rpcTimerInterface);
318+ errorLogFile->close ();
303319 delete rpcTimerInterface;
304320 delete ui;
305321}
306322
323+ void RPCConsole::errorLogInitPos ()
324+ {
325+ // Check if we already have the file
326+ if (errorLogFile != NULL ) {
327+ // Get a QFile instance
328+ errorLogFile = new QFile (QString::fromStdString (GetErrorLogPath ().string ()));
329+ }
330+
331+ // Try to open file
332+ if (!errorLogFile->open (QFile::ReadOnly | QFile::Text))
333+ return ;
334+
335+ // Seek to the end of file
336+ errorLogFile->seek (errorLogFile->size () - 1 );
337+
338+ // We need to move the file pos back by ERROR_LOG_INITIAL_COUNT lines
339+ QString ch;
340+ int lineCount = 0 ;
341+ while ((lineCount < ERROR_LOG_INITIAL_COUNT ) && (errorLogFile->pos () > 0 ))
342+ {
343+ // Load the current character
344+ ch = errorLogFile->read (1 );
345+
346+ // Move pos back by 2 spaces
347+ errorLogFile->seek (errorLogFile->pos () - 2 );
348+
349+ // Check if we have a newline
350+ if (ch == " \n " )
351+ lineCount++; // Count it
352+ }
353+
354+ // Move pos forward by 2 spaces
355+ errorLogFile->seek (errorLogFile->pos () + 2 );
356+
357+ // Clear the textarea
358+ ui->errorLogTextBrowser ->setText (" " );
359+
360+ // Mark init as done
361+ errorLogInitPosDone = true ;
362+ }
363+
364+ void RPCConsole::errorLogRefresh ()
365+ {
366+ // Check if we are still refreshing
367+ if (errorLogRefreshing)
368+ return ;
369+
370+ // Set to refreshing
371+ errorLogRefreshing = true ;
372+
373+ // Check if we have initialized debug log already
374+ if (!errorLogInitPosDone)
375+ errorLogInitPos ();
376+
377+ // Load the stream
378+ QTextStream in (errorLogFile);
379+
380+ // Load up the lines
381+ QString logLines = " " ;
382+ while (!in.atEnd ()) {
383+ // Load the next line
384+ logLines += in.readLine () + " \n " ;
385+ }
386+
387+ // Check if we have lines
388+ if (logLines != " " ) {
389+ // Add the new lines, purpose of duplicate moveCursor calls is
390+ // to auto scroll to the end of the log instead of sticking to the
391+ // top of the text area
392+ ui->errorLogTextBrowser ->moveCursor (QTextCursor::End);
393+ ui->errorLogTextBrowser ->textCursor ().insertText (logLines);
394+ ui->errorLogTextBrowser ->moveCursor (QTextCursor::End);
395+ }
396+
397+ // Count the lines in the UI textarea
398+ int uiLineCount = ui->errorLogTextBrowser ->document ()->lineCount ();
399+
400+ // Check if lines are more than ERROR_LOG_INITIAL_COUNT
401+ if (uiLineCount > ERROR_LOG_INITIAL_COUNT ) {
402+ // Count how many to remove
403+ int lineCountDiff = uiLineCount - ERROR_LOG_INITIAL_COUNT ;
404+
405+ // Get our cursor
406+ QTextCursor cursor = ui->errorLogTextBrowser ->textCursor ();
407+
408+ // REMOVE THEM
409+ for (int i = 0 ; i < lineCountDiff; i++) {
410+ cursor.movePosition (QTextCursor::Start);
411+ cursor.select (QTextCursor::LineUnderCursor);
412+ cursor.deleteChar (); // Remove the selected text
413+ cursor.deleteChar (); // This is by design, this removes the \n
414+ }
415+
416+ // Replace the cursor
417+ ui->errorLogTextBrowser ->setTextCursor (cursor);
418+
419+ // Move cursor back to the end
420+ ui->errorLogTextBrowser ->moveCursor (QTextCursor::End);
421+ }
422+
423+ // Mark as done
424+ errorLogRefreshing = false ;
425+ }
426+
307427bool RPCConsole::eventFilter (QObject* obj, QEvent *event)
308428{
309429 if (event->type () == QEvent::KeyPress) // Special key handling
@@ -672,6 +792,11 @@ void RPCConsole::on_tabWidget_currentChanged(int index)
672792 clearSelectedNode ();
673793}
674794
795+ void RPCConsole::on_errorLogCopyClipboardButton_clicked ()
796+ {
797+ GUIUtil::setClipboard (ui->errorLogTextBrowser ->toPlainText ());
798+ }
799+
675800void RPCConsole::on_openDebugLogfileButton_clicked ()
676801{
677802 GUIUtil::openDebugLogfile ();
@@ -837,6 +962,15 @@ void RPCConsole::showEvent(QShowEvent *event)
837962{
838963 QWidget::showEvent (event);
839964
965+ // Mark init as not done
966+ errorLogInitPosDone = false ;
967+
968+ // Load error log initial data
969+ errorLogRefresh ();
970+
971+ // Start the error log timer
972+ errorLogTimer->start ();
973+
840974 if (!clientModel || !clientModel->getPeerTableModel ())
841975 return ;
842976
@@ -848,6 +982,9 @@ void RPCConsole::hideEvent(QHideEvent *event)
848982{
849983 QWidget::hideEvent (event);
850984
985+ // Stop the error log timer
986+ errorLogTimer->stop ();
987+
851988 if (!clientModel || !clientModel->getPeerTableModel ())
852989 return ;
853990
0 commit comments