Merge pull request #1899 from bobvanderlinden/pr-log

allow viewing live log during execution
This commit is contained in:
Adriaan de Groot 2022-03-14 14:19:43 +01:00 committed by GitHub
commit d89955f4b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 167 additions and 7 deletions

View file

@ -30,6 +30,7 @@ set( calamaresui_SOURCES
widgets/ErrorDialog.cpp
widgets/FixedAspectRatioLabel.cpp
widgets/PrettyRadioButton.cpp
widgets/LogWidget.cpp
widgets/TranslationFix.cpp
widgets/WaitingWidget.cpp
${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp

View file

@ -25,11 +25,19 @@
#include "utils/Dirs.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h"
#include "widgets/LogWidget.h"
#include <QDir>
#include <QLabel>
#include <QProgressBar>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QToolBar>
#include <QAction>
#include <QToolButton>
#include <QTabWidget>
#include <QPlainTextEdit>
#include <QTabBar>
static Calamares::Slideshow*
makeSlideshow( QWidget* parent )
@ -60,23 +68,40 @@ ExecutionViewStep::ExecutionViewStep( QObject* parent )
, m_progressBar( new QProgressBar )
, m_label( new QLabel )
, m_slideshow( makeSlideshow( m_widget ) )
, m_tab_widget( new QTabWidget )
, m_log_widget( new LogWidget )
{
m_widget->setObjectName( "slideshow" );
m_progressBar->setObjectName( "exec-progress" );
m_label->setObjectName( "exec-message" );
QVBoxLayout* layout = new QVBoxLayout( m_widget );
QVBoxLayout* innerLayout = new QVBoxLayout;
QVBoxLayout* bottomLayout = new QVBoxLayout;
QHBoxLayout* barLayout = new QHBoxLayout;
m_progressBar->setMaximum( 10000 );
layout->addWidget( m_slideshow->widget() );
CalamaresUtils::unmarginLayout( layout );
layout->addLayout( innerLayout );
m_tab_widget->addTab(m_slideshow->widget(), "Slideshow");
m_tab_widget->addTab(m_log_widget, "Log");
m_tab_widget->tabBar()->hide();
layout->addWidget( m_tab_widget );
CalamaresUtils::unmarginLayout( layout );
layout->addLayout( bottomLayout );
bottomLayout->addSpacing( CalamaresUtils::defaultFontHeight() / 2 );
bottomLayout->addLayout( barLayout );
bottomLayout->addWidget( m_label );
QToolBar* toolBar = new QToolBar;
auto toggleLogAction = toolBar->addAction(QIcon::fromTheme("utilities-terminal"), "Toggle log");
auto toggleLogButton = dynamic_cast<QToolButton*>(toolBar->widgetForAction(toggleLogAction));
connect( toggleLogButton, &QToolButton::clicked, this, &ExecutionViewStep::toggleLog );
barLayout->addWidget(m_progressBar);
barLayout->addWidget(toolBar);
innerLayout->addSpacing( CalamaresUtils::defaultFontHeight() / 2 );
innerLayout->addWidget( m_progressBar );
innerLayout->addWidget( m_label );
connect( JobQueue::instance(), &JobQueue::progress, this, &ExecutionViewStep::updateFromJobQueue );
}
@ -200,10 +225,18 @@ ExecutionViewStep::updateFromJobQueue( qreal percent, const QString& message )
}
}
void
ExecutionViewStep::toggleLog()
{
m_tab_widget->setCurrentIndex((m_tab_widget->currentIndex() + 1) % m_tab_widget->count());
}
void
ExecutionViewStep::onLeave()
{
m_slideshow->changeSlideShowState( Slideshow::Stop );
}
} // namespace Calamares

View file

@ -13,12 +13,14 @@
#include "ViewStep.h"
#include "modulesystem/InstanceKey.h"
#include "widgets/LogWidget.h"
#include <QStringList>
class QLabel;
class QObject;
class QProgressBar;
class QTabWidget;
namespace Calamares
{
@ -56,10 +58,14 @@ private:
QProgressBar* m_progressBar;
QLabel* m_label;
Slideshow* m_slideshow;
QTabWidget* m_tab_widget;
LogWidget* m_log_widget;
QList< ModuleSystem::InstanceKey > m_jobInstanceKeys;
void updateFromJobQueue( qreal percent, const QString& message );
void toggleLog();
};
} // namespace Calamares

View file

@ -0,0 +1,82 @@
#include "LogWidget.h"
#include <QStackedLayout>
#include "utils/Logger.h"
#include <QTextStream>
#include <QThread>
#include <QFile>
namespace Calamares
{
LogThread::LogThread(QObject *parent)
: QThread(parent) {
}
LogThread::~LogThread()
{
quit();
requestInterruption();
wait();
}
void LogThread::run()
{
auto filePath = Logger::logFile();
qint64 lastPosition = 0;
while (!QThread::currentThread()->isInterruptionRequested()) {
auto filePath = Logger::logFile();
QFile file(filePath);
qint64 fileSize = file.size();
// Check whether the file size has changed since last time
// we read the file.
if (lastPosition != fileSize && file.open(QFile::ReadOnly | QFile::Text)) {
// Start reading at the position we ended up last time we read the file.
file.seek(lastPosition);
QTextStream in(&file);
auto chunk = in.readAll();
qint64 newPosition = in.pos();
lastPosition = newPosition;
onLogChunk(chunk);
}
QThread::msleep(100);
}
}
LogWidget::LogWidget(QWidget *parent)
: QWidget(parent)
, m_text( new QPlainTextEdit )
, m_log_thread( this )
{
auto layout = new QStackedLayout(this);
setLayout(layout);
m_text->setReadOnly(true);
QFont monospaceFont("monospace");
monospaceFont.setStyleHint(QFont::Monospace);
m_text->setFont(monospaceFont);
layout->addWidget(m_text);
connect(&m_log_thread, &LogThread::onLogChunk, this, &LogWidget::handleLogChunk);
m_log_thread.start();
}
void
LogWidget::handleLogChunk(const QString &logChunk)
{
m_text->appendPlainText(logChunk);
m_text->moveCursor(QTextCursor::End);
m_text->ensureCursorVisible();
}
}

View file

@ -0,0 +1,38 @@
#ifndef LIBCALAMARESUI_LOGWIDGET_H
#define LIBCALAMARESUI_LOGWIDGET_H
#include <QWidget>
#include <QPlainTextEdit>
#include <QThread>
namespace Calamares
{
class LogThread : public QThread
{
Q_OBJECT
void run() override;
public:
explicit LogThread(QObject *parent = nullptr);
~LogThread() override;
signals:
void onLogChunk(const QString &logChunk);
};
class LogWidget : public QWidget
{
Q_OBJECT
QPlainTextEdit* m_text;
LogThread m_log_thread;
public:
explicit LogWidget(QWidget *parent = nullptr);
void handleLogChunk(const QString &logChunk);
};
}
#endif // LOGWIDGET_H