Always keep log scrolled to the bottom
[frida/frida.git] / src / gui / widgets / LogDockAppender.cxx
1 #include "LogDockAppender.hxx"
2 #include "LogDock.hxx"
3
4 #include <log4cxx/patternlayout.h>
5 #include <QTimer>
6
7 using namespace log4cxx::helpers;
8
9 IMPLEMENT_LOG4CXX_OBJECT(LogDockAppender)
10
11 LogDockAppender::LogDockAppender()
12 : timeformat("%T") {
13 layout = new PatternLayout("%d{MMM dd yyyy HH:mm:ss,SSS} - %m %n");
14 }
15
16 void LogDockAppender::append(const spi::LoggingEventPtr& event, Pool& p) {
17 log4cxx::LogString message, timestamp;
18
19 if ( this->layout == NULL ) {
20 LOG4CXX_ENCODE_CHAR(nameStr, name);
21 std::string msg("No Layout set for the appender named [ ");
22 msg.append(nameStr);
23 msg.append(" ].");
24
25 LOG4CXX_DECODE_CHAR(msgL, msg);
26 errorHandler->error(msgL);
27 return;
28 }
29
30 layout->format(message, event, p);
31 timeformat.format(timestamp, event->getTimeStamp(), p);
32 LOG4CXX_ENCODE_CHAR(messageencode, message);
33 LOG4CXX_ENCODE_CHAR(timestampencode, timestamp);
34
35 QColor rowcolor(0xff, 0xff, 0xff, 0xff);
36 if (log4cxx::Level::getFatal() == event->getLevel()) {
37 rowcolor.setRgb(0xff, 0x00, 0x22);
38 } else if (log4cxx::Level::getError() == event->getLevel()) {
39 rowcolor.setRgb(0xff, 0x00, 0x00);
40 } else if (log4cxx::Level::getWarn() == event->getLevel()) {
41 rowcolor.setRgb(0x00, 0xff, 0xff);
42 } else if (log4cxx::Level::getTrace() == event->getLevel()) {
43 rowcolor.setRgb(0xee, 0xff, 0xee);
44 }
45
46 int rowcount = target->rowCount();
47 target->insertRow(rowcount);
48 target->setItem(rowcount, 0, new QTableWidgetItem(timestampencode.c_str()));
49 target->setItem(rowcount, 1, new QTableWidgetItem(event->getLevel()->toString().c_str()));
50 target->setItem(rowcount, 2, new QTableWidgetItem(messageencode.c_str()));
51 target->item(rowcount, 0)->setBackground(rowcolor);
52 target->item(rowcount, 1)->setBackground(rowcolor);
53 target->item(rowcount, 2)->setBackground(rowcolor);
54 target->resizeColumnsToContents();
55
56 QTimer *timer = new QTimer(target);
57 timer->setSingleShot(true);
58
59 QObject::connect(timer, &QTimer::timeout, [=]() {
60 target->scrollToItem(target->item(rowcount, 2), QAbstractItemView::PositionAtTop);
61 });
62 timer->start(10);
63 }
64
65 void LogDockAppender::setTarget(LogDock *target) {
66 this->target = target;
67 }
68
69 void LogDockAppender::close() {
70
71 }
72
73 bool LogDockAppender::requiresLayout() const {
74 return true;
75 }