Browse Source

qt log viewer now works

pull/1184/head
mewmew@i2p 7 years ago
parent
commit
ed2818eaa2
  1. 11
      daemon/Daemon.cpp
  2. 2
      daemon/Daemon.h
  3. 16
      libi2pd/Log.cpp
  4. 27
      qt/i2pd_qt/DaemonQT.cpp
  5. 2
      qt/i2pd_qt/DaemonQT.h
  6. 2
      qt/i2pd_qt/SignatureTypeComboboxFactory.h
  7. 6
      qt/i2pd_qt/i2pd_qt.pro
  8. 45
      qt/i2pd_qt/logviewermanager.cpp
  9. 130
      qt/i2pd_qt/logviewermanager.h
  10. 24
      qt/i2pd_qt/mainwindow.cpp
  11. 24
      qt/i2pd_qt/mainwindow.h
  12. 80
      qt/i2pd_qt/mainwindow.ui

11
daemon/Daemon.cpp

@ -60,7 +60,11 @@ namespace i2p
return service; return service;
} }
bool Daemon_Singleton::init(int argc, char* argv[]) bool Daemon_Singleton::init(int argc, char* argv[]) {
return init(argc, argv, nullptr);
}
bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
{ {
i2p::config::Init(); i2p::config::Init();
i2p::config::ParseCmdline(argc, argv); i2p::config::ParseCmdline(argc, argv);
@ -104,7 +108,10 @@ namespace i2p
logs = "file"; logs = "file";
i2p::log::Logger().SetLogLevel(loglevel); i2p::log::Logger().SetLogLevel(loglevel);
if (logs == "file") { if (logstream) {
LogPrint(eLogInfo, "Log: will send messages to std::ostream");
i2p::log::Logger().SendTo (logstream);
} else if (logs == "file") {
if (logfile == "") if (logfile == "")
logfile = i2p::fs::DataDirPath("i2pd.log"); logfile = i2p::fs::DataDirPath("i2pd.log");
LogPrint(eLogInfo, "Log: will send messages to ", logfile); LogPrint(eLogInfo, "Log: will send messages to ", logfile);

2
daemon/Daemon.h

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <ostream>
namespace i2p namespace i2p
{ {
@ -12,6 +13,7 @@ namespace util
class Daemon_Singleton class Daemon_Singleton
{ {
public: public:
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init(int argc, char* argv[]); virtual bool init(int argc, char* argv[]);
virtual bool start(); virtual bool start();
virtual bool stop(); virtual bool stop();

16
libi2pd/Log.cpp

@ -8,6 +8,9 @@
#include "Log.h" #include "Log.h"
//for std::transform
#include <algorithm>
namespace i2p { namespace i2p {
namespace log { namespace log {
static Log logger; static Log logger;
@ -107,7 +110,18 @@ namespace log {
} }
} }
void Log::SetLogLevel (const std::string& level) { std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct
);
return s;
}
void Log::SetLogLevel (const std::string& level_) {
std::string level=str_tolower(level_);
if (level == "none") { m_MinLevel = eLogNone; } if (level == "none") { m_MinLevel = eLogNone; }
else if (level == "error") { m_MinLevel = eLogError; } else if (level == "error") { m_MinLevel = eLogError; }
else if (level == "warn") { m_MinLevel = eLogWarning; } else if (level == "warn") { m_MinLevel = eLogWarning; }

27
qt/i2pd_qt/DaemonQT.cpp

@ -1,6 +1,11 @@
#include <memory>
#include "DaemonQT.h" #include "DaemonQT.h"
#include "Daemon.h" #include "Daemon.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "Log.h"
#include <QMessageBox> #include <QMessageBox>
#include <QApplication> #include <QApplication>
#include <QMutexLocker> #include <QMutexLocker>
@ -90,12 +95,12 @@ namespace qt
delete mutex; delete mutex;
} }
bool DaemonQTImpl::init(int argc, char* argv[]) bool DaemonQTImpl::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
{ {
mutex=new QMutex(QMutex::Recursive); mutex=new QMutex(QMutex::Recursive);
setRunningCallback(0); setRunningCallback(0);
m_IsRunning=false; m_IsRunning=false;
return Daemon.init(argc,argv); return Daemon.init(argc,argv,logstream);
} }
void DaemonQTImpl::start() void DaemonQTImpl::start()
@ -146,33 +151,35 @@ namespace qt
int result; int result;
{ {
std::shared_ptr<std::iostream> logstreamptr=std::make_shared<std::stringstream>();
//TODO move daemon init deinit to a bg thread
DaemonQTImpl daemon; DaemonQTImpl daemon;
qDebug("Initialising the daemon..."); (*logstreamptr) << "Initialising the daemon..." << std::endl;
bool daemonInitSuccess = daemon.init(argc, argv); bool daemonInitSuccess = daemon.init(argc, argv, logstreamptr);
if(!daemonInitSuccess) if(!daemonInitSuccess)
{ {
QMessageBox::critical(0, "Error", "Daemon init failed"); QMessageBox::critical(0, "Error", "Daemon init failed");
return 1; return 1;
} }
qDebug("Initialised, creating the main window..."); LogPrint(eLogDebug, "Initialised, creating the main window...");
MainWindow w; MainWindow w(logstreamptr);
qDebug("Before main window.show()..."); LogPrint(eLogDebug, "Before main window.show()...");
w.show (); w.show ();
{ {
i2p::qt::Controller daemonQtController(daemon); i2p::qt::Controller daemonQtController(daemon);
w.setI2PController(&daemonQtController); w.setI2PController(&daemonQtController);
qDebug("Starting the daemon..."); LogPrint(eLogDebug, "Starting the daemon...");
emit daemonQtController.startDaemon(); emit daemonQtController.startDaemon();
//daemon.start (); //daemon.start ();
qDebug("Starting GUI event loop..."); LogPrint(eLogDebug, "Starting GUI event loop...");
result = app.exec(); result = app.exec();
//daemon.stop (); //daemon.stop ();
} }
} }
//QMessageBox::information(&w, "Debug", "demon stopped"); //QMessageBox::information(&w, "Debug", "demon stopped");
qDebug("Exiting the application"); LogPrint(eLogDebug, "Exiting the application");
return result; return result;
} }
} }

2
qt/i2pd_qt/DaemonQT.h

@ -25,7 +25,7 @@ namespace qt
* @param argv * @param argv
* @return success * @return success
*/ */
bool init(int argc, char* argv[]); bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
void start(); void start();
void stop(); void stop();
void restart(); void restart();

2
qt/i2pd_qt/SignatureTypeComboboxFactory.h

@ -18,7 +18,7 @@ class SignatureTypeComboBoxFactory
} }
public: public:
static const uint16_t getSigType(const QVariant& var) { static uint16_t getSigType(const QVariant& var) {
return (uint16_t)var.toInt(); return (uint16_t)var.toInt();
} }

6
qt/i2pd_qt/i2pd_qt.pro

@ -93,7 +93,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
textbrowsertweaked1.cpp \ textbrowsertweaked1.cpp \
pagewithbackbutton.cpp \ pagewithbackbutton.cpp \
widgetlock.cpp \ widgetlock.cpp \
widgetlockregistry.cpp widgetlockregistry.cpp \
logviewermanager.cpp
#qt creator does not handle this well #qt creator does not handle this well
#SOURCES += $$files(../../libi2pd/*.cpp) #SOURCES += $$files(../../libi2pd/*.cpp)
@ -179,7 +180,8 @@ HEADERS += DaemonQT.h mainwindow.h \
widgetlock.h \ widgetlock.h \
widgetlockregistry.h \ widgetlockregistry.h \
i2pd.rc \ i2pd.rc \
i2pd.rc i2pd.rc \
logviewermanager.h
INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd
INCLUDEPATH += ../../libi2pd_client INCLUDEPATH += ../../libi2pd_client

45
qt/i2pd_qt/logviewermanager.cpp

@ -0,0 +1,45 @@
#include "logviewermanager.h"
LogViewerManager::LogViewerManager(std::shared_ptr<std::iostream> logStream_,
QPlainTextEdit* logTextEdit_,
QObject *parent) :
QObject(parent),
logStream(logStream_),
logTextEdit(logTextEdit_),
controllerForBgThread(nullptr)
{
assert(logTextEdit!=nullptr);
controllerForBgThread=new i2pd::qt::logviewer::Controller(*this);
}
namespace i2pd {
namespace qt {
namespace logviewer {
QString Worker::pollAndShootATimerForInfiniteRetries() {
std::shared_ptr<std::iostream> logStream=logViewerManager.getLogStream();
assert(logStream!=nullptr);
std::streamsize MAX_SZ=64*1024;
char*buf=(char*)malloc(MAX_SZ*sizeof(char));
if(buf==nullptr)return "";
std::streamsize read=logStream->readsome(buf, MAX_SZ);
if(read<0)read=0;
QString ret=QString::fromUtf8(buf, read);
free(buf);
return ret;
}
Controller::Controller(LogViewerManager &parameter1):logViewerManager(parameter1) {
Worker *worker = new Worker(parameter1);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate1, worker, &Worker::doWork1);
connect(worker, &Worker::resultReady,
&parameter1, &LogViewerManager::appendPlainText_atGuiThread);
workerThread.start();
timerId=startTimer(100/*millis*/);
}
}
}
}

130
qt/i2pd_qt/logviewermanager.h

@ -0,0 +1,130 @@
#ifndef LOGVIEWERMANAGER_H
#define LOGVIEWERMANAGER_H
#include <QObject>
#include <QString>
#include <QPlainTextEdit>
#include <QScrollBar>
#include <QComboBox>
#include <QTimer>
#include <QThread>
#include <assert.h>
#include <string>
#include "FS.h"
#include "Log.h"
class LogViewerManager;
namespace i2pd {
namespace qt {
namespace logviewer {
class Worker : public QObject
{
Q_OBJECT
private:
LogViewerManager &logViewerManager;
public:
Worker(LogViewerManager &parameter1):logViewerManager(parameter1){}
private:
QString pollAndShootATimerForInfiniteRetries();
public slots:
void doWork1() {
/* ... here is the expensive or blocking operation ... */
QString read=pollAndShootATimerForInfiniteRetries();
emit resultReady(read);
}
signals:
void resultReady(QString read);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
LogViewerManager& logViewerManager;
int timerId;
public:
Controller(LogViewerManager &parameter1);
~Controller() {
if(timerId!=0)killTimer(timerId);
workerThread.quit();
workerThread.wait();
}
signals:
void operate1();
protected:
void timerEvent(QTimerEvent */*event*/) {
emit operate1();
}
};
}
}
}
class LogViewerManager : public QObject
{
Q_OBJECT
private:
std::shared_ptr<std::iostream> logStream;
QPlainTextEdit* logTextEdit;
i2pd::qt::logviewer::Controller* controllerForBgThread;
public:
//also starts a bg thread (QTimer) polling logStream->readsome(buf, n)
explicit LogViewerManager(std::shared_ptr<std::iostream> logStream_,
QPlainTextEdit* logTextEdit_,
QObject *parent);
//also deallocs the bg thread (QTimer)
virtual ~LogViewerManager(){}
const i2pd::qt::logviewer::Controller& getControllerForBgThread() {
assert(controllerForBgThread!=nullptr);
return *controllerForBgThread;
}
const QPlainTextEdit* getLogTextEdit(){ return logTextEdit; }
const std::shared_ptr<std::iostream> getLogStream(){ return logStream; }
signals:
public slots:
//void appendFromNonGuiThread(std::string read) {
//}
public slots:
void appendPlainText_atGuiThread(QString plainText) {
if(plainText.length()==0)return;
assert(logTextEdit!=nullptr);
int scrollPosVert =logTextEdit->verticalScrollBar()->value();
int scrollPosHoriz=logTextEdit->horizontalScrollBar()->value();
int scrollPosVertMax =logTextEdit->verticalScrollBar()->maximum();
const int MAX_LINES=10*1024;
logTextEdit->setMaximumBlockCount(MAX_LINES);
//logTextEdit->appendPlainText(plainText);
//navigate the window to the end
//QTextCursor cursor = logTextEdit->textCursor();
//cursor.movePosition(QTextCursor::MoveOperation::End);
//logTextEdit->setTextCursor(cursor);
//QTextCursor prev_cursor = logTextEdit->textCursor();
logTextEdit->moveCursor(QTextCursor::End);
logTextEdit->insertPlainText(plainText);
if(/*prev_cursor.atEnd()*/scrollPosVert==scrollPosVertMax){
//logTextEdit->moveCursor(QTextCursor::End);
scrollPosVert =logTextEdit->verticalScrollBar()->maximum();
scrollPosHoriz=logTextEdit->horizontalScrollBar()->minimum();
}
//else
// logTextEdit->setTextCursor(prev_cursor);
logTextEdit->verticalScrollBar()->setValue(scrollPosVert);
logTextEdit->horizontalScrollBar()->setValue(scrollPosHoriz);
}
/*
void replaceText_atGuiThread() {
assert(logTextEdit!=nullptr);
logTextEdit->setText(QString::fromStdString(nav.getContent()));
}
*/
};
#endif // LOGVIEWERMANAGER_H

24
qt/i2pd_qt/mainwindow.cpp

@ -27,15 +27,19 @@
#include "DaemonQT.h" #include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h" #include "SignatureTypeComboboxFactory.h"
#include "logviewermanager.h"
std::string programOptionsWriterCurrentSection; std::string programOptionsWriterCurrentSection;
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent) :
QMainWindow(parent) QMainWindow(parent)
,logStream(logStream_)
#ifndef ANDROID #ifndef ANDROID
,quitting(false) ,quitting(false)
#endif #endif
,wasSelectingAtStatusMainPage(false) ,wasSelectingAtStatusMainPage(false)
,showHiddenInfoStatusMainPage(false) ,showHiddenInfoStatusMainPage(false)
,logViewerManagerPtr(nullptr)
,ui(new Ui::MainWindow) ,ui(new Ui::MainWindow)
,statusButtonsUI(new Ui::StatusButtonsForm) ,statusButtonsUI(new Ui::StatusButtonsForm)
,routerCommandsUI(new Ui::routerCommandsWidget) ,routerCommandsUI(new Ui::routerCommandsWidget)
@ -132,6 +136,8 @@ MainWindow::MainWindow(QWidget *parent) :
QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit())); QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit()));
QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit())); QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit()));
QObject::connect(ui->logViewerPushButton, SIGNAL(released()), this, SLOT(showLogViewerPage()));
QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage())); QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage()));
QObject::connect(ui->tunnelsPagePushButton, SIGNAL(released()), this, SLOT(showTunnelsPage())); QObject::connect(ui->tunnelsPagePushButton, SIGNAL(released()), this, SLOT(showTunnelsPage()));
@ -299,6 +305,9 @@ MainWindow::MainWindow(QWidget *parent) :
trayIcon->show(); trayIcon->show();
#endif #endif
logViewerManagerPtr=new LogViewerManager(logStream_,ui->logViewerTextEdit,this);
assert(logViewerManagerPtr!=nullptr);
onLoggingOptionsChange();
//QMetaObject::connectSlotsByName(this); //QMetaObject::connectSlotsByName(this);
} }
@ -333,10 +342,11 @@ void MainWindow::showStatusPage(StatusPage newStatusPage){
} }
wasSelectingAtStatusMainPage=false; wasSelectingAtStatusMainPage=false;
} }
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);} void MainWindow::showLogViewerPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);}
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);} void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);}
void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);} void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);}
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(4);setStatusButtonsVisible(false);} void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(4);setStatusButtonsVisible(false);}
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(5);setStatusButtonsVisible(false);}
void MainWindow::setStatusButtonsVisible(bool visible) { void MainWindow::setStatusButtonsVisible(bool visible) {
ui->statusButtonsPane->setVisible(visible); ui->statusButtonsPane->setVisible(visible);
@ -631,6 +641,8 @@ void MainWindow::loadAllConfigs(){
} }
ReadTunnelsConfig(); ReadTunnelsConfig();
onLoggingOptionsChange();
} }
/** returns false iff not valid items present and save was aborted */ /** returns false iff not valid items present and save was aborted */
bool MainWindow::saveAllConfigs(){ bool MainWindow::saveAllConfigs(){
@ -668,6 +680,8 @@ bool MainWindow::saveAllConfigs(){
SaveTunnelsConfig(); SaveTunnelsConfig();
onLoggingOptionsChange();
return true; return true;
} }

24
qt/i2pd_qt/mainwindow.h

@ -62,6 +62,8 @@
#include "widgetlockregistry.h" #include "widgetlockregistry.h"
#include "widgetlock.h" #include "widgetlock.h"
class LogViewerManager;
template<typename ValueType> template<typename ValueType>
bool isType(boost::any& a) { bool isType(boost::any& a) {
return return
@ -215,7 +217,8 @@ public:
}; };
class LogDestinationComboBoxItem : public ComboBoxItem { class LogDestinationComboBoxItem : public ComboBoxItem {
public: public:
LogDestinationComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}; LogDestinationComboBoxItem(ConfigOption option_, QComboBox* comboBox_) :
ComboBoxItem(option_, comboBox_) {}
virtual ~LogDestinationComboBoxItem(){} virtual ~LogDestinationComboBoxItem(){}
virtual void loadFromConfigOption(){ virtual void loadFromConfigOption(){
MainWindowItem::loadFromConfigOption(); MainWindowItem::loadFromConfigOption();
@ -228,6 +231,8 @@ public:
MainWindowItem::saveToStringStream(out); MainWindowItem::saveToStringStream(out);
} }
virtual bool isValid() { return true; } virtual bool isValid() { return true; }
Q_OBJECT
}; };
class LogLevelComboBoxItem : public ComboBoxItem { class LogLevelComboBoxItem : public ComboBoxItem {
public: public:
@ -370,9 +375,10 @@ class Controller;
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
private:
std::shared_ptr<std::iostream> logStream;
public: public:
explicit MainWindow(QWidget *parent=0); explicit MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent=nullptr);
~MainWindow(); ~MainWindow();
void setI2PController(i2p::qt::Controller* controller_); void setI2PController(i2p::qt::Controller* controller_);
@ -419,6 +425,7 @@ public slots:
void showStatus_i2p_tunnels_Page(); void showStatus_i2p_tunnels_Page();
void showStatus_sam_sessions_Page(); void showStatus_sam_sessions_Page();
void showLogViewerPage();
void showSettingsPage(); void showSettingsPage();
void showTunnelsPage(); void showTunnelsPage();
void showRestartPage(); void showRestartPage();
@ -430,6 +437,8 @@ private:
bool wasSelectingAtStatusMainPage; bool wasSelectingAtStatusMainPage;
bool showHiddenInfoStatusMainPage; bool showHiddenInfoStatusMainPage;
LogViewerManager *logViewerManagerPtr;
void showStatusPage(StatusPage newStatusPage); void showStatusPage(StatusPage newStatusPage);
#ifndef ANDROID #ifndef ANDROID
void createActions(); void createActions();
@ -522,13 +531,6 @@ private:
void appendTunnelForms(std::string tunnelNameToFocus); void appendTunnelForms(std::string tunnelNameToFocus);
void deleteTunnelForms(); void deleteTunnelForms();
/*
TODO signaturetype
*/
template<typename Section, typename Type> template<typename Section, typename Type>
std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
{ {
@ -790,6 +792,8 @@ private:
}; };
TunnelsPageUpdateListenerMainWindowImpl tunnelsPageUpdateListener; TunnelsPageUpdateListenerMainWindowImpl tunnelsPageUpdateListener;
void onLoggingOptionsChange() {}
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

80
qt/i2pd_qt/mainwindow.ui

@ -58,7 +58,7 @@
<enum>QLayout::SetMaximumSize</enum> <enum>QLayout::SetMaximumSize</enum>
</property> </property>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0"> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0,0">
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum> <enum>QLayout::SetMinimumSize</enum>
</property> </property>
@ -96,6 +96,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="logViewerPushButton">
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="settingsPagePushButton"> <widget class="QPushButton" name="settingsPagePushButton">
<property name="enabled"> <property name="enabled">
@ -596,7 +603,7 @@
</palette> </palette>
</property> </property>
<property name="text"> <property name="text">
<string>TextLabel</string> <string>wrongInputMessageLabel</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -627,7 +634,7 @@
</size> </size>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="statusPage"> <widget class="QWidget" name="statusPage">
<property name="sizePolicy"> <property name="sizePolicy">
@ -671,6 +678,69 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="logViewerPage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="verticalLayoutWidget_4_logViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>711</width>
<height>531</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4_logViewer">
<property name="sizeConstraint">
<enum>QLayout::SetMinAndMaxSize</enum>
</property>
<item>
<widget class="QLabel" name="logViewerTitleLabel">
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="logViewerTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<property name="maximumBlockCount">
<number>10000</number>
</property>
<property name="acceptRichText" stdset="0">
<bool>false</bool>
</property>
<property name="widgetResizable" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="settingsPage"> <widget class="QWidget" name="settingsPage">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -728,8 +798,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>689</width> <width>81</width>
<height>496</height> <height>28</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">

Loading…
Cancel
Save