From c02e084dcfdb6a352cc7f83c2c9c37f60d208e84 Mon Sep 17 00:00:00 2001 From: dsc Date: Tue, 11 May 2021 01:56:04 +0200 Subject: [PATCH] Forum post widget showing latest from forum.wownero.com --- src/appcontext.cpp | 25 +++++++-- src/appcontext.h | 3 ++ src/mainwindow.cpp | 1 + src/mainwindow.h | 7 ++- src/mainwindow.ui | 32 ++++++++++- src/model/ForumModel.cpp | 104 ++++++++++++++++++++++++++++++++++++ src/model/ForumModel.h | 41 ++++++++++++++ src/utils/config.cpp | 2 +- src/widgets/ForumPost.h | 19 +++++++ src/widgets/forumwidget.cpp | 74 +++++++++++++++++++++++++ src/widgets/forumwidget.h | 42 +++++++++++++++ src/widgets/forumwidget.ui | 61 +++++++++++++++++++++ 12 files changed, 402 insertions(+), 9 deletions(-) create mode 100644 src/model/ForumModel.cpp create mode 100644 src/model/ForumModel.h create mode 100644 src/widgets/ForumPost.h create mode 100644 src/widgets/forumwidget.cpp create mode 100644 src/widgets/forumwidget.h create mode 100644 src/widgets/forumwidget.ui diff --git a/src/appcontext.cpp b/src/appcontext.cpp index 415c29f..122e5d9 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -433,7 +433,6 @@ void AppContext::onWSMessage(const QJsonObject &msg) { QJsonArray crypto_rates = msg.value("data").toArray(); AppContext::prices->cryptoPricesReceived(crypto_rates); } - else if(cmd == "fiat_rates") { QJsonObject fiat_rates = msg.value("data").toObject(); AppContext::prices->fiatPricesReceived(fiat_rates); @@ -442,17 +441,18 @@ void AppContext::onWSMessage(const QJsonObject &msg) { QJsonArray reddit_data = msg.value("data").toArray(); this->onWSReddit(reddit_data); } - + else if(cmd == "forum") { + QJsonArray forum_data = msg.value("data").toArray(); + this->onWSForum(forum_data); + } else if(cmd == "funding_proposals") { auto ccs_data = msg.value("data").toArray(); this->onWSCCS(ccs_data); } - else if(cmd == "suchwow") { QJsonArray such_data = msg.value("data").toArray(); emit suchWowUpdated(such_data); } - else if(cmd == "txFiatHistory") { auto txFiatHistory_data = msg.value("data").toObject(); AppContext::txFiatHistory->onWSData(txFiatHistory_data); @@ -507,6 +507,23 @@ void AppContext::onWSNodes(const QJsonArray &nodes) { this->nodes->onWSNodesReceived(l); } +void AppContext::onWSForum(const QJsonArray& forum_data) { + QList> l; + + for (auto &&entry: forum_data) { + auto obj = entry.toObject(); + auto forumPost = new ForumPost( + obj.value("title").toString(), + obj.value("author").toString(), + obj.value("permalink").toString(), + obj.value("comments").toInt()); + QSharedPointer r = QSharedPointer(forumPost); + l.append(r); + } + + emit forumUpdated(l); +} + void AppContext::onWSReddit(const QJsonArray& reddit_data) { QList> l; diff --git a/src/appcontext.h b/src/appcontext.h index d3b84a5..6419c40 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -19,6 +19,7 @@ #include "utils/txfiathistory.h" #include "utils/WowletSeed.h" #include "widgets/RedditPost.h" +#include "widgets/ForumPost.h" #include "widgets/CCSEntry.h" #include "utils/RestoreHeightLookup.h" #include "utils/nodes.h" @@ -160,6 +161,7 @@ private slots: void onWSMessage(const QJsonObject& msg); void onWSCCS(const QJsonArray &ccs_data); void onWSReddit(const QJsonArray& reddit_data); + void onWSForum(const QJsonArray& forum_data); void onMoneySpent(const QString &txId, quint64 amount); void onMoneyReceived(const QString &txId, quint64 amount); @@ -198,6 +200,7 @@ signals: void wsConnected(); void wsDisconnected(); void redditUpdated(QList> &posts); + void forumUpdated(QList> &posts); void nodesUpdated(QList> &nodes); void ccsUpdated(QList> &entries); void suchWowUpdated(const QJsonArray &such_data); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 34d7524..b497504 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -182,6 +182,7 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : connect(ui->ccsWidget, &CCSWidget::selected, this, &MainWindow::showSendScreen); connect(m_ctx, &AppContext::ccsUpdated, ui->ccsWidget->model(), &CCSModel::updateEntries); connect(m_ctx, &AppContext::redditUpdated, ui->redditWidget->model(), &RedditModel::updatePosts); + connect(m_ctx, &AppContext::forumUpdated, ui->forumWidget->model(), &ForumModel::updatePosts); connect(m_ctx, &AppContext::suchWowUpdated, ui->suchWowWidget, &SuchWowWidget::onWS); connect(ui->suchWowWidget, &SuchWowWidget::donate, this, &MainWindow::suchDonate); diff --git a/src/mainwindow.h b/src/mainwindow.h index b9e229f..62e33e0 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -25,6 +25,7 @@ #include "calcwindow.h" #include "widgets/ccswidget.h" #include "widgets/redditwidget.h" +#include "widgets/forumwidget.h" #include "widgets/tickerwidget.h" #include "widgets/xmrigwidget.h" #include "utils/networking.h" @@ -83,8 +84,10 @@ public: }; enum TabsHome { - CCS, - REDDIT + FORUM, + REDDIT, + SUCHWOW, + WFS }; public slots: diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 49fc6f3..20d9d21 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -101,9 +101,31 @@ true + + + Forum + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + - /r/Wownero + Reddit @@ -326,7 +348,7 @@ 0 0 1156 - 20 + 22 @@ -755,6 +777,12 @@
widgets/suchwowwidget.h
1 + + ForumWidget + QWidget +
widgets/forumwidget.h
+ 1 +
diff --git a/src/model/ForumModel.cpp b/src/model/ForumModel.cpp new file mode 100644 index 0000000..be32d11 --- /dev/null +++ b/src/model/ForumModel.cpp @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#include "ForumModel.h" + +ForumModel::ForumModel(QObject *parent) + : QAbstractTableModel(parent) +{ + +} + +void ForumModel::clear() { + beginResetModel(); + + m_posts.clear(); + + endResetModel(); +} + +void ForumModel::updatePosts(const QList>& posts) { + beginResetModel(); + + m_posts.clear(); + for (const auto& post : posts) { + m_posts.push_back(post); + } + + endResetModel(); +} + +int ForumModel::rowCount(const QModelIndex &parent) const{ + if (parent.isValid()) { + return 0; + } + return m_posts.count(); +} + +int ForumModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return ModelColumn::COUNT; +} + +QVariant ForumModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_posts.count()) + return QVariant(); + + QSharedPointer post = m_posts.at(index.row()); + + if(role == Qt::DisplayRole) { + switch(index.column()) { + case Title: + return post->title; + case Author: + return post->author; + case Comments: + return QString::number(post->comments); + default: + return QVariant(); + } + } + else if (role == Qt::TextAlignmentRole) { + switch(index.column()) { + case Comments: + return Qt::AlignRight; + default: + return QVariant(); + } + } + return QVariant(); +} + +QVariant ForumModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) { + return QVariant(); + } + if (orientation == Qt::Horizontal) + { + switch(section) { + case Title: + return QString("Forum Post"); + case Author: + return QString("Author"); + case Comments: + return QString("Comments"); + default: + return QVariant(); + } + } + return QVariant(); +} + +QSharedPointer ForumModel::post(int row) { + if (row < 0 || row >= m_posts.size()) { + qCritical("%s: no forum post for index %d", __FUNCTION__, row); + return QSharedPointer(); + } + + return m_posts.at(row); +} \ No newline at end of file diff --git a/src/model/ForumModel.h b/src/model/ForumModel.h new file mode 100644 index 0000000..9fe18b2 --- /dev/null +++ b/src/model/ForumModel.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#ifndef WOWLET_FORUMMODEL_H +#define WOWLET_FORUMMODEL_H + +#include +#include + +#include "widgets/ForumPost.h" + +class ForumModel : public QAbstractTableModel +{ +Q_OBJECT + +public: + enum ModelColumn + { + Title = 0, + Author, + Comments, + COUNT + }; + + explicit ForumModel(QObject *parent); + + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + void clear(); + void updatePosts(const QList>& posts); + + QSharedPointer post(int row); + +private: + QList> m_posts; +}; + +#endif //WOWLET_FORUMMODEL_H diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 432ce69..62dba69 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -22,7 +22,7 @@ static const QHash configStrings = { {Config::warnOnStagenet,{QS("warnOnStagenet"), true}}, {Config::warnOnTestnet,{QS("warnOnTestnet"), true}}, {Config::warnOnAlpha,{QS("warnOnAlpha"), true}}, - {Config::homeWidget,{QS("homeWidget"), "ccs"}}, + {Config::homeWidget,{QS("homeWidget"), 0}}, {Config::donateBeg,{QS("donateBeg"), 1}}, {Config::skin,{QS("skin"), "light"}}, {Config::openVRSkin,{QS("openVRSkin"), "default"}}, diff --git a/src/widgets/ForumPost.h b/src/widgets/ForumPost.h new file mode 100644 index 0000000..ca4f3ee --- /dev/null +++ b/src/widgets/ForumPost.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#ifndef WOWLET_FORUMPOST_H +#define WOWLET_FORUMPOST_H + +#include + +struct ForumPost { + ForumPost(const QString &title, const QString &author, const QString &permalink, int comments) + : title(title), author(author), permalink(permalink), comments(comments){}; + + QString title; + QString author; + QString permalink; + int comments; +}; + +#endif //WOWLET_FORUMPOST_H diff --git a/src/widgets/forumwidget.cpp b/src/widgets/forumwidget.cpp new file mode 100644 index 0000000..f11e6cc --- /dev/null +++ b/src/widgets/forumwidget.cpp @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#include +#include +#include + +#include "model/ForumModel.h" +#include "forumwidget.h" +#include "ui_forumwidget.h" +#include "utils/utils.h" +#include "utils/config.h" + +ForumWidget::ForumWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::ForumWidget), + m_model(new ForumModel(this)), + m_contextMenu(new QMenu(this)) +{ + ui->setupUi(this); + ui->tableView->setModel(m_model); + this->setupTable(); + + m_contextMenu->addAction("View thread", this, &ForumWidget::linkClicked); + m_contextMenu->addAction("Copy link", this, &ForumWidget::copyUrl); + connect(ui->tableView, &QHeaderView::customContextMenuRequested, this, &ForumWidget::showContextMenu); + + connect(ui->tableView, &QTableView::doubleClicked, this, &ForumWidget::linkClicked); + + ui->tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); +} + +ForumModel* ForumWidget::model() { + return m_model; +} + +void ForumWidget::linkClicked() { + QModelIndex index = ui->tableView->currentIndex(); + auto post = m_model->post(index.row()); + + if (post) + Utils::externalLinkWarning(this, post->permalink); +} + +void ForumWidget::copyUrl() { + QModelIndex index = ui->tableView->currentIndex(); + auto post = m_model->post(index.row()); + + if (post) { + Utils::copyToClipboard(post->permalink); + emit setStatusText("Link copied to clipboard", true, 1000); + } +} + +void ForumWidget::setupTable() { + ui->tableView->verticalHeader()->setVisible(false); + ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + + ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui->tableView->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch); +} + +void ForumWidget::showContextMenu(const QPoint &pos) { + QModelIndex index = ui->tableView->indexAt(pos); + if (!index.isValid()) { + return; + } + + m_contextMenu->exec(ui->tableView->viewport()->mapToGlobal(pos)); +} + +ForumWidget::~ForumWidget() { + delete ui; +} diff --git a/src/widgets/forumwidget.h b/src/widgets/forumwidget.h new file mode 100644 index 0000000..5ddc120 --- /dev/null +++ b/src/widgets/forumwidget.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#ifndef FORUMWIDGET_H +#define FORUMWIDGET_H + +#include +#include +#include + +#include "model/ForumModel.h" + +namespace Ui { + class ForumWidget; +} + +class ForumWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ForumWidget(QWidget *parent = nullptr); + ~ForumWidget(); + ForumModel* model(); + +public slots: + void linkClicked(); + +signals: + void setStatusText(const QString &msg, bool override, int timeout); + +private: + void setupTable(); + void showContextMenu(const QPoint &pos); + void copyUrl(); + + Ui::ForumWidget *ui; + ForumModel* const m_model; + QMenu *m_contextMenu; +}; + +#endif // FORUMWIDGET_H diff --git a/src/widgets/forumwidget.ui b/src/widgets/forumwidget.ui new file mode 100644 index 0000000..842b54d --- /dev/null +++ b/src/widgets/forumwidget.ui @@ -0,0 +1,61 @@ + + + ForumWidget + + + + 0 + 0 + 492 + 409 + + + + Form + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + false + + + + + + + + + linkClicked() + +