From cd24bcd64925816e0d809244d96ffbce7e8398e4 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Fri, 19 Apr 2024 13:11:07 +0200 Subject: [PATCH] fixes #1017 --- .../scripts/github-actions/build-windows.ps1 | 4 +- resources/text/CHANGELOG | 1 + src/librssguard/core/messagesmodel.cpp | 6 +- src/librssguard/core/messagesmodel.h | 2 +- .../gui/mediaplayer/libmpv/libmpvbackend.cpp | 2 +- src/librssguard/gui/messagesview.cpp | 53 ++++++++- src/librssguard/gui/messagesview.h | 19 ++++ .../gui/settings/settingsfeedsmessages.cpp | 47 ++++++++ .../gui/settings/settingsfeedsmessages.h | 3 + .../gui/settings/settingsfeedsmessages.ui | 101 +++++++++++------- src/librssguard/miscellaneous/settings.cpp | 6 ++ src/librssguard/miscellaneous/settings.h | 7 ++ 12 files changed, 204 insertions(+), 47 deletions(-) diff --git a/resources/scripts/github-actions/build-windows.ps1 b/resources/scripts/github-actions/build-windows.ps1 index e345e68ca..8c15b8994 100755 --- a/resources/scripts/github-actions/build-windows.ps1 +++ b/resources/scripts/github-actions/build-windows.ps1 @@ -48,8 +48,8 @@ $zlib_version = "1.3.1" $zlib_link = "https://github.com/madler/zlib/archive/refs/tags/v$zlib_version.zip" $zlib_output = "zlib.zip" -$libmpv_date = "2024-04-14" -$libmpv_commit = "6a8b130" +$libmpv_date = "2024-04-19" +$libmpv_commit = "1a49545" $libmpv_version = "{0}-git-{1}"-f $libmpv_date.Replace("-", ""), $libmpv_commit $libmpv_link = "https://github.com/zhongfly/mpv-winbuild/releases/download/$libmpv_date-$libmpv_commit/mpv-dev-x86_64-$libmpv_version.7z" $libmpv_output = "mpv.zip" diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG index ef84be995..59b58fd13 100644 --- a/resources/text/CHANGELOG +++ b/resources/text/CHANGELOG @@ -6,6 +6,7 @@ OK, dear users. Over recent releases, many features were added and as you can se Sole focus will be on fixing bugs and polish existing features and clean codebase. Added: +* Article now can be marked (upon selection) as read with delay or only manually. (#1017) * All RSS Guard plugins/services are now placed in their own library (DLL/SO/DYLIB) files and are loaded by main RSS Guard library dynamically. This means that unused services can now be removed from RSS Guard installation if not used by the user. Also it allows for a cleaner and slimmer common codebase. Refactoring of main RSS Guard library was also done and it is now more usable as regular dynamic-link library. I expect some regressions as this was HUGE change. Also, this change allows new potential interested people in writing new plugins easier as they now can just copy one of existing plugins and tweak for new service. * Application (Qt) style and icon theme now can be properly set to respect system style/icons and this setting is dynamic, meaning if you change system theme and restart RSS Guard, new theme is honored. (#1352) * Button to copy system/app information to "About..." dialog. (#1318) diff --git a/src/librssguard/core/messagesmodel.cpp b/src/librssguard/core/messagesmodel.cpp index 3d4f9221c..95914a8e3 100644 --- a/src/librssguard/core/messagesmodel.cpp +++ b/src/librssguard/core/messagesmodel.cpp @@ -159,9 +159,11 @@ void MessagesModel::repopulate() { << QUOTE_W_SPACE_DOT(selectStatement()); } -bool MessagesModel::setData(const QModelIndex& index, const QVariant& value, int role) { +bool MessagesModel::setData(const QModelIndex& idx, const QVariant& value, int role) { Q_UNUSED(role) - m_cache->setData(index, value); + m_cache->setData(idx, value); + + emit dataChanged(index(idx.row(), 0), index(idx.row(), MSG_DB_LABELS_IDS)); return true; } diff --git a/src/librssguard/core/messagesmodel.h b/src/librssguard/core/messagesmodel.h index 6964d1efc..c32a55f58 100644 --- a/src/librssguard/core/messagesmodel.h +++ b/src/librssguard/core/messagesmodel.h @@ -44,7 +44,7 @@ class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer { void repopulate(); // Model implementation. - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + bool setData(const QModelIndex& idx, const QVariant& value, int role = Qt::EditRole); QVariant data(const QModelIndex& idx, int role = Qt::DisplayRole) const; QVariant data(int row, int column, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; diff --git a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp index 1b78eca04..43973682c 100644 --- a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp +++ b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp @@ -62,7 +62,7 @@ LibMpvBackend::LibMpvBackend(Application* app, QWidget* parent) mpv_set_option_string(m_mpvHandle, "no-resume-playback", "yes"); #if !defined(NDEBUG) - // mpv_set_option_string(m_mpvHandle, "terminal", "yes"); + mpv_set_option_string(m_mpvHandle, "terminal", "yes"); #endif if (!m_customConfigFolder.isEmpty()) { diff --git a/src/librssguard/gui/messagesview.cpp b/src/librssguard/gui/messagesview.cpp index 4a2b36cc1..fb3db9a4e 100644 --- a/src/librssguard/gui/messagesview.cpp +++ b/src/librssguard/gui/messagesview.cpp @@ -40,12 +40,13 @@ MessagesView::MessagesView(QWidget* parent) createConnections(); setModel(m_proxyModel); setupAppearance(); + setupArticleMarkingPolicy(); header()->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); connect(header(), &QHeaderView::customContextMenuRequested, this, [=](QPoint point) { TreeViewColumnsMenu mm(header()); mm.exec(header()->mapToGlobal(point)); }); - + connect(&m_delayedArticleMarker, &QTimer::timeout, this, &MessagesView::markSelectedMessagesReadDelayed); reloadFontSettings(); } @@ -57,6 +58,16 @@ void MessagesView::reloadFontSettings() { m_sourceModel->setupFonts(); } +void MessagesView::setupArticleMarkingPolicy() { + m_articleMarkingPolicy = + ArticleMarkingPolicy(qApp->settings()->value(GROUP(Messages), SETTING(Messages::ArticleMarkOnSelection)).toInt()); + m_articleMarkingDelay = + qApp->settings()->value(GROUP(Messages), SETTING(Messages::ArticleMarkOnSelectionDelay)).toInt(); + + m_delayedArticleMarker.setSingleShot(true); + m_delayedArticleMarker.setInterval(m_articleMarkingDelay); +} + QByteArray MessagesView::saveHeaderState() const { QJsonObject obj; @@ -504,11 +515,25 @@ void MessagesView::selectionChanged(const QItemSelection& selected, const QItemS // Set this message as read only if current item // wasn't changed by "mark selected messages unread" action. if (!m_processingRightMouseButton) { - m_sourceModel->setMessageRead(mapped_current_index.row(), RootItem::ReadStatus::Read); - message.m_isRead = true; - } + if (!message.m_isRead) { + if (m_articleMarkingPolicy == ArticleMarkingPolicy::MarkImmediately) { + qDebugNN << LOGSEC_GUI << "Marking article as read immediately."; - emit currentMessageChanged(message, m_sourceModel->loadedItem()); + m_sourceModel->setMessageRead(mapped_current_index.row(), RootItem::ReadStatus::Read); + message.m_isRead = true; + } + else if (m_articleMarkingPolicy == ArticleMarkingPolicy::MarkWithDelay) { + qDebugNN << LOGSEC_GUI << "(Re)Starting timer to mark article as read with a delay."; + m_delayedArticleIndex = current_index; + m_delayedArticleMarker.start(); + } + else { + // NOTE: Article can only be marked as read manually, so just change. + } + } + + emit currentMessageChanged(message, m_sourceModel->loadedItem()); + } } else { emit currentMessageRemoved(m_sourceModel->loadedItem()); @@ -526,7 +551,25 @@ void MessagesView::selectionChanged(const QItemSelection& selected, const QItemS QTreeView::selectionChanged(selected, deselected); } +void MessagesView::markSelectedMessagesReadDelayed() { + qDebugNN << LOGSEC_GUI << "Delay has passed! Marking article as read NOW."; + const QModelIndexList selected_rows = selectionModel()->selectedRows(); + const QModelIndex current_index = m_delayedArticleIndex; + + if (selected_rows.size() == 1 && current_index.isValid() && !m_processingRightMouseButton && + m_articleMarkingPolicy == ArticleMarkingPolicy::MarkWithDelay) { + const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index); + Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()); + + m_sourceModel->setMessageRead(mapped_current_index.row(), RootItem::ReadStatus::Read); + message.m_isRead = true; + emit currentMessageChanged(message, m_sourceModel->loadedItem()); + } +} + void MessagesView::loadItem(RootItem* item) { + m_delayedArticleMarker.stop(); + const int col = header()->sortIndicatorSection(); const Qt::SortOrder ord = header()->sortIndicatorOrder(); diff --git a/src/librssguard/gui/messagesview.h b/src/librssguard/gui/messagesview.h index 85546ab03..b7dc31a83 100644 --- a/src/librssguard/gui/messagesview.h +++ b/src/librssguard/gui/messagesview.h @@ -10,6 +10,7 @@ #include "services/abstract/rootitem.h" #include +#include class MessagesProxyModel; @@ -17,6 +18,17 @@ class MessagesView : public BaseTreeView { Q_OBJECT public: + enum class ArticleMarkingPolicy { + // Article is marked as read right when selected. + MarkImmediately = 0, + + // Article is marked as read with some configured delay. + MarkWithDelay = 1, + + // Article is never marked as read on selection. + MarkOnlyManually = 2 + }; + explicit MessagesView(QWidget* parent = nullptr); virtual ~MessagesView(); @@ -24,6 +36,7 @@ class MessagesView : public BaseTreeView { MessagesModel* sourceModel() const; void reloadFontSettings(); + void setupArticleMarkingPolicy(); QByteArray saveHeaderState() const; void restoreHeaderState(const QByteArray& dta); @@ -82,6 +95,8 @@ class MessagesView : public BaseTreeView { // Changes resize mode for all columns. void adjustColumns(); + void markSelectedMessagesReadDelayed(); + // Saves current sort state. void onSortIndicatorChanged(int column, Qt::SortOrder order); @@ -130,6 +145,10 @@ class MessagesView : public BaseTreeView { bool m_columnsAdjusted; bool m_processingAnyMouseButton; bool m_processingRightMouseButton; + ArticleMarkingPolicy m_articleMarkingPolicy; + int m_articleMarkingDelay; + QTimer m_delayedArticleMarker; + QModelIndex m_delayedArticleIndex; }; inline MessagesProxyModel* MessagesView::model() const { diff --git a/src/librssguard/gui/settings/settingsfeedsmessages.cpp b/src/librssguard/gui/settings/settingsfeedsmessages.cpp index 651d62b2c..4fa00b441 100644 --- a/src/librssguard/gui/settings/settingsfeedsmessages.cpp +++ b/src/librssguard/gui/settings/settingsfeedsmessages.cpp @@ -46,6 +46,18 @@ SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent m_ui->m_cmbUnreadIconType->addItem(MessagesModel::descriptionOfUnreadIcon(en), int(en)); } + m_ui->m_cmbArticleMarkingPolicy->addItem(tr("immediately"), int(MessagesView::ArticleMarkingPolicy::MarkImmediately)); + m_ui->m_cmbArticleMarkingPolicy->addItem(tr("only manually"), + int(MessagesView::ArticleMarkingPolicy::MarkOnlyManually)); + m_ui->m_cmbArticleMarkingPolicy->addItem(tr("with delay"), int(MessagesView::ArticleMarkingPolicy::MarkWithDelay)); + + updateArticleMarkingPolicyDelay(); + + connect(m_ui->m_cmbArticleMarkingPolicy, + &QComboBox::currentIndexChanged, + this, + &SettingsFeedsMessages::updateArticleMarkingPolicyDelay); + connect(m_ui->m_cbShowEnclosuresDirectly, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_spinHeightImageAttachments, static_cast(&QSpinBox::valueChanged), @@ -70,6 +82,14 @@ SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent } }); + connect(m_ui->m_cmbArticleMarkingPolicy, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_spinArticleMarkingPolicy, + static_cast(&QSpinBox::valueChanged), + this, + &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_gbFeedListFont, &QGroupBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_gbArticleListFont, &QGroupBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_cbListsRestrictedShortcuts, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); @@ -261,6 +281,10 @@ void SettingsFeedsMessages::changeFont(QLabel& lbl) { } } +MessagesView::ArticleMarkingPolicy SettingsFeedsMessages::selectedArticleMarkingPolicy() const { + return m_ui->m_cmbArticleMarkingPolicy->currentData().value(); +} + void SettingsFeedsMessages::loadSettings() { onBeginLoadSettings(); @@ -268,6 +292,14 @@ void SettingsFeedsMessages::loadSettings() { m_ui->m_cbLegacyArticleFormatting->setVisible(false); } + m_ui->m_cmbArticleMarkingPolicy + ->setCurrentIndex(m_ui->m_cmbArticleMarkingPolicy->findData(settings() + ->value(GROUP(Messages), + SETTING(Messages::ArticleMarkOnSelection)) + .toInt())); + m_ui->m_spinArticleMarkingPolicy + ->setValue(settings()->value(GROUP(Messages), SETTING(Messages::ArticleMarkOnSelectionDelay)).toInt()); + m_ui->m_spinRelativeArticleTime ->setValue(settings()->value(GROUP(Messages), SETTING(Messages::RelativeTimeForNewerArticles)).toInt()); m_ui->m_spinPaddingRowsMessages @@ -376,6 +408,16 @@ void SettingsFeedsMessages::loadSettings() { void SettingsFeedsMessages::saveSettings() { onBeginSaveSettings(); + settings()->setValue(GROUP(Messages), + Messages::ArticleMarkOnSelection, + m_ui->m_cmbArticleMarkingPolicy->currentData().toInt()); + + settings()->setValue(GROUP(Messages), + Messages::ArticleMarkOnSelectionDelay, + m_ui->m_spinArticleMarkingPolicy->value()); + + qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesView()->setupArticleMarkingPolicy(); + settings()->setValue(GROUP(Messages), Messages::RelativeTimeForNewerArticles, m_ui->m_spinRelativeArticleTime->value()); @@ -506,3 +548,8 @@ void SettingsFeedsMessages::updateDateTimeTooltip() { } } } + +void SettingsFeedsMessages::updateArticleMarkingPolicyDelay() { + m_ui->m_spinArticleMarkingPolicy->setEnabled(selectedArticleMarkingPolicy() == + MessagesView::ArticleMarkingPolicy::MarkWithDelay); +} diff --git a/src/librssguard/gui/settings/settingsfeedsmessages.h b/src/librssguard/gui/settings/settingsfeedsmessages.h index 468064f77..7bcdca0fa 100644 --- a/src/librssguard/gui/settings/settingsfeedsmessages.h +++ b/src/librssguard/gui/settings/settingsfeedsmessages.h @@ -3,6 +3,7 @@ #ifndef SETTINGSFEEDSMESSAGES_H #define SETTINGSFEEDSMESSAGES_H +#include "gui/messagesview.h" #include "gui/settings/settingspanel.h" #include "ui_settingsfeedsmessages.h" @@ -21,9 +22,11 @@ class SettingsFeedsMessages : public SettingsPanel { private slots: void updateDateTimeTooltip(); + void updateArticleMarkingPolicyDelay(); private: void changeFont(QLabel& lbl); + MessagesView::ArticleMarkingPolicy selectedArticleMarkingPolicy() const; private: void initializeMessageDateFormats(); diff --git a/src/librssguard/gui/settings/settingsfeedsmessages.ui b/src/librssguard/gui/settings/settingsfeedsmessages.ui index c44c58982..a707b8078 100644 --- a/src/librssguard/gui/settings/settingsfeedsmessages.ui +++ b/src/librssguard/gui/settings/settingsfeedsmessages.ui @@ -441,21 +441,21 @@ - + Keep article selection in the middle of the article list viewport - + Enable multiline items - + @@ -465,7 +465,7 @@ - + Row height @@ -475,7 +475,7 @@ - + @@ -494,7 +494,7 @@ - + Top/bottom row padding @@ -504,7 +504,7 @@ - + @@ -523,7 +523,7 @@ - + Use custom date/time format @@ -536,7 +536,7 @@ - + @@ -550,9 +550,9 @@ - + - Custom date/time format for today's articles + Use custom date/time format for dates-only true @@ -563,7 +563,7 @@ - + 150 @@ -576,13 +576,39 @@ + + + Custom date/time format for today's articles + + + true + + + true + + + + + + + + 150 + 0 + + + + true + + + + Show relative time for articles not older than - + -1 @@ -592,7 +618,7 @@ - + Article list font @@ -624,29 +650,33 @@ - - - - - 150 - 0 - - - - true - - + + + + + + + + + ms + + + 100 + + + 15000 + + + 100 + + + + - - + + - Use custom date/time format for dates-only - - - true - - - true + Upon article selection, mark as read @@ -709,7 +739,6 @@ m_cmbMessagesTimeFormat m_spinRelativeArticleTime m_btnChangeMessageListFont - m_tabFeedsMessages m_gbFeedListFont m_gbArticleListFont diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index 68fa2cf0c..b0ae74c7d 100644 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -202,6 +202,12 @@ DVALUE(bool) Messages::UseCustomFormatForDatesOnlyDef = false; DKEY Messages::RelativeTimeForNewerArticles = "relative_time_for_new_articles"; DVALUE(int) Messages::RelativeTimeForNewerArticlesDef = -1; +DKEY Messages::ArticleMarkOnSelection = "mark_message_on_selected"; +DVALUE(int) Messages::ArticleMarkOnSelectionDef = int(MessagesView::ArticleMarkingPolicy::MarkImmediately); + +DKEY Messages::ArticleMarkOnSelectionDelay = "mark_message_on_selected_delay"; +DVALUE(int) Messages::ArticleMarkOnSelectionDelayDef = 3000; + DKEY Messages::ArticleListPadding = "article_list_padding"; DVALUE(int) Messages::ArticleListPaddingDef = -1; diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index e88d8d5ca..73ce17991 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -4,6 +4,7 @@ #define SETTINGS_H #include "definitions/definitions.h" +#include "gui/messagesview.h" #include "gui/notifications/toastnotificationsmanager.h" #include "miscellaneous/settingsproperties.h" #include "miscellaneous/textfactory.h" @@ -154,6 +155,12 @@ namespace Messages { KEY AvoidOldArticles; VALUE(bool) AvoidOldArticlesDef; + KEY ArticleMarkOnSelection; + VALUE(int) ArticleMarkOnSelectionDef; + + KEY ArticleMarkOnSelectionDelay; + VALUE(int) ArticleMarkOnSelectionDelayDef; + KEY DateTimeToAvoidArticle; VALUE(QDateTime) DateTimeToAvoidArticleDef;