aboutsummaryrefslogtreecommitdiffstats
path: root/src/widgets/status_info.cpp
blob: 847aec4dec300a1246a9f4a3164a267d3eb28a39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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);
}