From 5befd0666aef0b96e3e4bd41ed704ccaa3ace5d5 Mon Sep 17 00:00:00 2001 From: ConfuSomu Date: Mon, 10 Jul 2023 13:27:34 +0200 Subject: Implement basic multithreading support A few CPU heavy operations, which are opening an archive and displaying a selected Activity, have been moved to another thread to avoid having long-running operations on the main thread. --- src/archive_parser.cpp | 6 +++--- src/archive_parser.h | 6 +++--- src/list_item.cpp | 2 +- src/list_item.h | 2 +- src/mainwindow.cpp | 40 ++++++++++++++++++++++++++++++++++------ src/mainwindow.h | 9 +++++++++ 6 files changed, 51 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/archive_parser.cpp b/src/archive_parser.cpp index 77d3ec0..96df1ec 100644 --- a/src/archive_parser.cpp +++ b/src/archive_parser.cpp @@ -19,7 +19,7 @@ Archive::Archive(QString outbox_filename, ArchiveType archive_type) : outbox_filename(outbox_filename), archive_type(archive_type) {} -Archive::InitError Archive::init() { +std::variant Archive::init() { QFile outbox_file(outbox_filename); if (!outbox_file.open(QIODevice::ReadOnly | QIODevice::Text)) @@ -233,7 +233,7 @@ std::vector Archive::get_status_attachments_list(QJsonValueR } // status_index is assumed to be a valid index -QString Archive::get_html_status_info(int status_index, int text_zone_width, StatusType status_type, QLocale* locale) { +const QString Archive::get_html_status_info(int status_index, int text_zone_width, StatusType status_type, QLocale* locale) { // the JSON AP Activity (TODO: fix misleading name) QJsonObject obj = outbox_items->at(status_index).toObject(); @@ -303,7 +303,7 @@ QString Archive::get_html_status_info(int status_index, int text_zone_width, Sta } // TODO: make this use an APActivity object that will be present as an StatusListItem member. -QString Archive::get_html_status_text(int status_index) { +const QString Archive::get_html_status_text(int status_index) { QString text(""); QJsonObject obj = outbox_items->at(status_index).toObject(); diff --git a/src/archive_parser.h b/src/archive_parser.h index c206087..7377120 100644 --- a/src/archive_parser.h +++ b/src/archive_parser.h @@ -28,11 +28,11 @@ public: Archive(QString outbox_filename, ArchiveType archive_type); ~Archive(); - InitError init(); + std::variant init(); void update_status_list(ViewStatusTypes allowed_types, QListWidget *parent); - QString get_html_status_info(int status_index, int text_zone_width, StatusType status_type, QLocale* locale); - QString get_html_status_text(int status_index); + const QString get_html_status_info(int status_index, int text_zone_width, StatusType status_type, QLocale* locale); + const QString get_html_status_text(int status_index); private: QString outbox_filename; QDir archive_root_dir; diff --git a/src/list_item.cpp b/src/list_item.cpp index c74fa39..020ccde 100644 --- a/src/list_item.cpp +++ b/src/list_item.cpp @@ -39,6 +39,6 @@ StatusType StatusListItem::get_status_type() { return status_type; } -QString StatusListItem::get_info_html(int text_zone_width, QLocale* locale) { +const QString StatusListItem::get_info_html(int text_zone_width, QLocale* locale) { return data_archive->get_html_status_info(status_index, text_zone_width, status_type, locale); } diff --git a/src/list_item.h b/src/list_item.h index 9ca0aac..4514903 100644 --- a/src/list_item.h +++ b/src/list_item.h @@ -13,7 +13,7 @@ public: StatusListItem(const QString &text, StatusType status_type, bool has_attachement, Archive* data_archive, QListWidget *parent = nullptr, int index = 0); int get_status_index(); StatusType get_status_type(); - QString get_info_html(int text_zone_width, QLocale* locale); + const QString get_info_html(int text_zone_width, QLocale* locale); private: int status_index; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ede24f8..363f2b1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -17,6 +18,7 @@ MainWindow::MainWindow(QWidget *parent) ui->setupUi(this); connect(ui->buttonCopy, &QPushButton::clicked, ui->actionCopy_status, &QAction::trigger); connect(ui->buttonRandom, &QPushButton::clicked, ui->actionRandom_status, &QAction::trigger); + connect(&archive_thread_watcher, &QFutureWatcher>::finished, this, &MainWindow::archive_thread_watcher_done); } MainWindow::~MainWindow() @@ -60,15 +62,22 @@ void MainWindow::on_actionAbout_triggered(bool checked) { QMessageBox::information(this, "title", "text"); } +std::variant start_listWidget_itemActivated(StatusListItem* status, int text_zone_width, QLocale* locale) { + return (QString)status->get_info_html(text_zone_width, locale); +} + void MainWindow::on_listWidget_itemActivated(QListWidgetItem *item) { StatusListItem* status = dynamic_cast(item); if (status != nullptr) { - // TODO: do this in another thread - QString status_info = status->get_info_html(ui->statusInfoText->width(), &locale_context); - ui->statusInfoText->setHtml(status_info); + const QFuture> status_info = QtConcurrent::run(start_listWidget_itemActivated, status, ui->statusInfoText->width(), &locale_context); + archive_thread_watcher.setFuture(status_info); } } +void MainWindow::finish_listWidget_itemActivated(const QString& status_info) { + ui->statusInfoText->setHtml(status_info); +} + void MainWindow::on_actionRandom_status_triggered(bool checked) { if (data_archive == nullptr) return; // No archive open, avoids crashing @@ -201,14 +210,19 @@ void MainWindow::open_file(const QString &filename) { data_archive = nullptr; } - // TODO: Do this in another thread + open_file_filename = filename; + QApplication::setOverrideCursor(Qt::WaitCursor); data_archive = new Archive(filename, ArchiveType::MASTODON); - auto parse_error = data_archive->init(); + QFuture> parse_error = QtConcurrent::run(data_archive, &Archive::init); + archive_thread_watcher.setFuture(parse_error); +} + +void MainWindow::finish_open_file(const Archive::InitError& parse_error) { switch (parse_error) { case Archive::FailedOpeningFile: - QMessageBox::warning(this, tr("Archive Parser"), tr("Failed opening file %1").arg(filename)); break; + QMessageBox::warning(this, tr("Archive Parser"), tr("Failed opening file %1").arg(open_file_filename)); break; case Archive::JsonParseError: QMessageBox::warning(this, tr("Archive Parser"), tr("Failed parsing outbox JSON.")); break; case Archive::JsonEmpty: @@ -228,3 +242,17 @@ void MainWindow::open_file(const QString &filename) { QApplication::restoreOverrideCursor(); } + +void MainWindow::archive_thread_watcher_done() { + std::variant result = archive_thread_watcher.result(); + + // For MainWindow::on_listWidget_itemActivated + if (const QString* status_info = std::get_if(&result)) { + finish_listWidget_itemActivated(*status_info); + } else + // For MainWindow::open_file + if (const Archive::InitError* parse_error = std::get_if(&result)) { + finish_open_file(*parse_error); + } else + qDebug() << "What, the variant is weird"; +} diff --git a/src/mainwindow.h b/src/mainwindow.h index f1de2d7..abf9acc 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "archive_parser.h" #include "types.h" @@ -47,6 +49,12 @@ private: void reset_view_filters(); void relist_statuses(); void open_file(const QString &filename); + void archive_thread_watcher_done(); + + void finish_listWidget_itemActivated(const QString& status_info); + void finish_open_file(const Archive::InitError& parse_error); + + QString open_file_filename; Ui::MainWindow *ui; @@ -54,6 +62,7 @@ private: bool view_filters_changed = false; Archive *data_archive = nullptr; + QFutureWatcher> archive_thread_watcher; QLocale locale_context; }; -- cgit v1.2.3-54-g00ecf