aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConfuSomu2023-11-12 00:16:02 -0500
committerConfuSomu2023-11-12 00:16:02 -0500
commit8ee7a379bbd8c1e2d7831208308bf11eabcdc79d (patch)
tree601b9d6e453d0be1acc7a56a3df6f233cc4a73da
parent80a658f062328ab8b47dc6b2557d274f51278b3a (diff)
downloadActorViewer-8ee7a379bbd8c1e2d7831208308bf11eabcdc79d.tar
ActorViewer-8ee7a379bbd8c1e2d7831208308bf11eabcdc79d.tar.gz
ActorViewer-8ee7a379bbd8c1e2d7831208308bf11eabcdc79d.zip
Move status info widget to its own widget
It is responsable of processing list items which are given to it, via signals, and then displaying them on the interface. Making this widget separate and modular will allow creating more advanced status views that aren't only HTML-based and that are more intuitive to use.
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/list_item.cpp4
-rw-r--r--src/list_item.h2
-rw-r--r--src/mainwindow.cpp25
-rw-r--r--src/mainwindow.h5
-rw-r--r--src/widgets/status_info.cpp82
-rw-r--r--src/widgets/status_info.h56
-rw-r--r--src/widgets/status_info.ui44
8 files changed, 203 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15486f5..8aa19f2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,9 @@ set(PROJECT_SOURCES
src/settingsdialog.ui
src/settings_interface.cpp
src/settings_interface.h
+ src/widgets/status_info.cpp
+ src/widgets/status_info.h
+ src/widgets/status_info.ui
src/archive/base_archive.cpp
src/archive/base_archive.h
src/archive/mastodon.cpp
diff --git a/src/list_item.cpp b/src/list_item.cpp
index deead65..b4e7e84 100644
--- a/src/list_item.cpp
+++ b/src/list_item.cpp
@@ -50,6 +50,10 @@ StatusType StatusListItem::get_status_type() {
return status_type;
}
+APActivity* StatusListItem::get_activity() {
+ return data_archive->get_activity(status_index, {status_type});
+}
+
const QString StatusListItem::get_info_html(int text_zone_width, QLocale* locale) {
APActivity* activity = data_archive->get_activity(status_index, {status_type});
QString html = activity->get_html_render({text_zone_width, locale});
diff --git a/src/list_item.h b/src/list_item.h
index d730551..22debe7 100644
--- a/src/list_item.h
+++ b/src/list_item.h
@@ -1,6 +1,7 @@
#pragma once
#include <QListWidgetItem>
+#include "src/activitypub/apactivity.h"
#include "src/archive/base_archive.h"
#include "types.h"
@@ -13,6 +14,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();
+ APActivity* get_activity();
const QString get_info_html(int text_zone_width, QLocale* locale);
private:
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 4ab0bb2..8f72f23 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -21,6 +21,8 @@ MainWindow::MainWindow(QWidget *parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
+ status_info_widget = new StatusInfoWidget(this);
+ ui->gridLayout->addWidget(status_info_widget, 1, 1);
connect(ui->buttonCopy, &QPushButton::clicked, ui->actionCopy_status, &QAction::trigger);
connect(ui->buttonRandom, &QPushButton::clicked, ui->actionRandom_status, &QAction::trigger);
connect(ui->buttonSearch, &QPushButton::clicked, ui->actionFind, &QAction::trigger);
@@ -85,22 +87,13 @@ void MainWindow::on_actionAbout_triggered(bool checked) {
QMessageBox::information(this, "title", "text");
}
-std::variant<QString, Archive::InitError> 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<StatusListItem*>(item);
if (status != nullptr) {
- const QFuture<std::variant<QString, Archive::InitError>> status_info = QtConcurrent::run(start_listWidget_itemActivated, status, ui->statusInfoText->width(), &locale_context);
- archive_thread_watcher.setFuture(status_info);
+ status_info_widget->show_list_item(status);
}
}
-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
@@ -291,12 +284,10 @@ void MainWindow::archive_thread_watcher_done() {
std::variant<QString, Archive::InitError> result = archive_thread_watcher.result();
// For MainWindow::on_listWidget_itemActivated
- if (const QString* status_info = std::get_if<QString>(&result)) {
- finish_listWidget_itemActivated(*status_info);
- } else
- // For MainWindow::open_file
- if (const Archive::InitError* parse_error = std::get_if<Archive::InitError>(&result)) {
- finish_open_file(*parse_error);
- } else
+ if (std::get_if<Archive::InitError>(&result)) {
+ // For MainWindow::open_file
+ if (const Archive::InitError* parse_error = std::get_if<Archive::InitError>(&result))
+ finish_open_file(*parse_error);
+ } else if (not std::get_if<QString>(&result))
qDebug() << "What, the variant is weird";
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 24bc970..22f5b29 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -7,7 +7,9 @@
#include <variant>
#include "archive/base_archive.h"
+#include "src/list_item.h"
#include "src/settingsdialog.h"
+#include "src/widgets/status_info.h"
#include "types.h"
#include "command_line.h"
#include "finddialog.h"
@@ -63,12 +65,13 @@ private:
void open_file(const QString &filename);
void archive_thread_watcher_done();
- void finish_listWidget_itemActivated(const QString& status_info);
+ std::variant<QString, Archive::InitError> start_listWidget_itemActivated(StatusListItem* status);
void finish_open_file(const Archive::InitError& parse_error);
void settingsDialog_done(int result);
FindDialog* find_dialog = nullptr;
SettingsDialog* settings_dialog = nullptr;
+ StatusInfoWidget* status_info_widget = nullptr;
QString open_file_filename;
diff --git a/src/widgets/status_info.cpp b/src/widgets/status_info.cpp
new file mode 100644
index 0000000..847aec4
--- /dev/null
+++ b/src/widgets/status_info.cpp
@@ -0,0 +1,82 @@
+#include "status_info.h"
+#include "src/list_item.h"
+#include <QTimer>
+#include <QDebug>
+#include <QCloseEvent>
+
+StatusInfoWidget::StatusInfoWidget(QWidget* parent)
+ : QWidget(parent), ui(new Ui::StatusInfo)
+{
+ ui->setupUi(this);
+
+ worker.moveToThread(&worker_thread);
+ connect(this, &StatusInfoWidget::do_process_item, &worker, &StatusInfoWidgetWorker::process_item, Qt::QueuedConnection);
+ connect(this, &StatusInfoWidget::do_process_activity, &worker, &StatusInfoWidgetWorker::process_activity, Qt::QueuedConnection);
+ connect(&worker, &StatusInfoWidgetWorker::itemProcessed, this, &StatusInfoWidget::postProcess, Qt::QueuedConnection);
+ worker_thread.start();
+
+ worker.set_text_zone_width(ui->statusInfoText->width());
+}
+
+StatusInfoWidget::~StatusInfoWidget() {
+ worker_thread.quit();
+ worker_thread.wait();
+
+ delete displayed_activity;
+ delete ui;
+}
+
+void StatusInfoWidget::resizeEvent(QResizeEvent* event) {
+ // TODO: probably create a template, define or inline function for this
+ static QTimer* differed_resize = new QTimer(this);
+ if (static bool timer_init_done = false; not timer_init_done) {
+ differed_resize->setTimerType(Qt::CoarseTimer);
+ differed_resize->setSingleShot(true);
+ differed_resize->setInterval(150);
+ connect(differed_resize, &QTimer::timeout, this, [=]() {
+ worker.set_text_zone_width(ui->statusInfoText->width());
+ if (displayed_activity)
+ emit do_process_activity(displayed_activity);
+ });
+ }
+ differed_resize->start();
+ QWidget::resizeEvent(event);
+}
+
+void StatusInfoWidget::show_list_item(StatusListItem* new_item) {
+ qDebug() << "got item" << new_item << "old is" << displayed_item << displayed_activity;
+ if (new_item != displayed_item) {
+ delete displayed_activity; displayed_activity = nullptr;
+ displayed_item = new_item;
+ emit do_process_item(new_item);
+ }
+}
+
+// Update the GUI with the displayed Activity.
+// Has to be done on the GUI thread, no other way in Qt
+void StatusInfoWidget::postProcess(const QString &html, APActivity* activity) {
+ // Make sure to not delete the displayed_activity if we are reprocessing it after a resize event, else you get a crash that requires nasty debugging (don't ask how i found out ;)
+ if (activity != displayed_activity) {
+ // We are doing "double" deletion of old displayed_activity but sometimes that's important when really scrubbing the search results bar very quickly (we sometimes do reach that code and it hopefully helps against memory leaks)
+ if (displayed_activity)
+ delete displayed_activity;
+ displayed_activity = activity;
+ }
+ ui->statusInfoText->setHtml(html);
+}
+
+/*
+ * ----------------
+ * Worker functions. Ran on non-main, non-GUI, thread
+ * ----------------
+ */
+
+void StatusInfoWidgetWorker::process_item(StatusListItem* item) {
+ APActivity* activity = item->get_activity();
+ process_activity(activity);
+}
+
+void StatusInfoWidgetWorker::process_activity(APActivity* activity) {
+ QString html = activity->get_html_render(render_info);
+ emit itemProcessed(html, activity);
+}
diff --git a/src/widgets/status_info.h b/src/widgets/status_info.h
new file mode 100644
index 0000000..988f930
--- /dev/null
+++ b/src/widgets/status_info.h
@@ -0,0 +1,56 @@
+#pragma once
+#include <QWidget>
+#include <QLocale>
+#include <QThread>
+#include "./ui_status_info.h"
+#include "src/activitypub/apactivity.h"
+#include "src/activitypub/apbase.h"
+#include "src/list_item.h"
+
+class StatusInfoWidgetWorker : public QObject {
+ Q_OBJECT
+
+public slots:
+ void process_item(StatusListItem* item);
+ void process_activity(APActivity* activity);
+ void set_text_zone_width(int width) {render_info.text_zone_width = width;}
+
+signals:
+ void itemProcessed(const QString &html, APActivity* activity = nullptr);
+
+private:
+ QLocale locale_context;
+ HtmlRenderDetails render_info = {0, &locale_context};
+};
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class StatusInfo; }
+QT_END_NAMESPACE
+
+class StatusInfoWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ StatusInfoWidget(QWidget *parent = nullptr);
+ ~StatusInfoWidget();
+
+ void resizeEvent(QResizeEvent* event);
+
+public slots:
+ void show_list_item(StatusListItem* status); // Call from GUI thread
+ void postProcess(const QString &html, APActivity* activity);
+
+signals:
+ // These signals are called privetely by StatusInfoWidget
+ void do_process_item(StatusListItem* item);
+ void do_process_activity(APActivity* activity);
+
+private:
+ Ui::StatusInfo* ui;
+ QThread worker_thread;
+ StatusInfoWidgetWorker worker;
+
+ // Used for determining if we are dealing with a new list item or not
+ StatusListItem* displayed_item = nullptr;
+ APActivity* displayed_activity = nullptr;
+};
diff --git a/src/widgets/status_info.ui b/src/widgets/status_info.ui
new file mode 100644
index 0000000..b8b2586
--- /dev/null
+++ b/src/widgets/status_info.ui
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StatusInfo</class>
+ <widget class="QWidget" name="StatusInfo">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QTextEdit" name="statusInfoText">
+ <property name="cursor" stdset="0">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="undoRedoEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Select Status to display from list.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::TextBrowserInteraction</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>