aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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>