diff --git a/src/librssguard/database/databasequeries.cpp b/src/librssguard/database/databasequeries.cpp index 28a96204a..94aac33b2 100644 --- a/src/librssguard/database/databasequeries.cpp +++ b/src/librssguard/database/databasequeries.cpp @@ -1075,7 +1075,7 @@ QHash DatabaseQueries::bagsOfMessages(const QSqlDatabase& return ids; } -QPair DatabaseQueries::updateMessages(const QSqlDatabase &db, +QPair DatabaseQueries::updateMessages(const QSqlDatabase& db, QList& messages, Feed* feed, bool force_update, @@ -1801,13 +1801,18 @@ void DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro } } -QStringList DatabaseQueries::customIdsOfMessagesFromAccount(const QSqlDatabase& db, int account_id, bool* ok) { +QStringList DatabaseQueries::customIdsOfMessagesFromAccount(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok) { QSqlQuery q(db); QStringList ids; q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_pdeleted = 0 AND account_id = :account_id;")); + q.prepare(QSL("SELECT custom_id FROM Messages " + "WHERE is_read = :read AND is_pdeleted = 0 AND account_id = :account_id;")); q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1); if (ok != nullptr) { *ok = q.exec(); @@ -1823,13 +1828,17 @@ QStringList DatabaseQueries::customIdsOfMessagesFromAccount(const QSqlDatabase& return ids; } -QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db, Label* label, bool* ok) { +QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db, + Label* label, + RootItem::ReadStatus target_read, + bool* ok) { QSqlQuery q(db); QStringList ids; q.setForwardOnly(true); q.prepare(QSL("SELECT custom_id FROM Messages " "WHERE " + " is_read = :read AND " " is_deleted = 0 AND " " is_pdeleted = 0 AND " " account_id = :account_id AND " @@ -1838,6 +1847,7 @@ QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db "LabelsInMessages.message);")); q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId()); q.bindValue(QSL(":label"), label->customId()); + q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1); if (ok != nullptr) { *ok = q.exec(); @@ -1853,14 +1863,20 @@ QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db return ids; } -QStringList DatabaseQueries::customIdsOfImportantMessages(const QSqlDatabase& db, int account_id, bool* ok) { +QStringList DatabaseQueries::customIdsOfImportantMessages(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok) { QSqlQuery q(db); QStringList ids; q.setForwardOnly(true); q.prepare(QSL("SELECT custom_id FROM Messages " - "WHERE is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")); + "WHERE " + "is_read = :read AND is_important = 1 AND is_deleted = 0 AND " + "is_pdeleted = 0 AND account_id = :account_id;")); q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1); if (ok != nullptr) { *ok = q.exec(); @@ -1899,14 +1915,18 @@ QStringList DatabaseQueries::customIdsOfUnreadMessages(const QSqlDatabase& db, i return ids; } -QStringList DatabaseQueries::customIdsOfMessagesFromBin(const QSqlDatabase& db, int account_id, bool* ok) { +QStringList DatabaseQueries::customIdsOfMessagesFromBin(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok) { QSqlQuery q(db); QStringList ids; q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = " - ":account_id;")); + q.prepare(QSL("SELECT custom_id FROM Messages " + "WHERE is_read = :read AND is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")); q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1); if (ok != nullptr) { *ok = q.exec(); @@ -1924,16 +1944,19 @@ QStringList DatabaseQueries::customIdsOfMessagesFromBin(const QSqlDatabase& db, QStringList DatabaseQueries::customIdsOfMessagesFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, + RootItem::ReadStatus target_read, int account_id, bool* ok) { QSqlQuery q(db); QStringList ids; q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND " - "account_id = :account_id;")); + q.prepare(QSL("SELECT custom_id FROM Messages " + "WHERE is_read = :read AND is_deleted = 0 AND " + "is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;")); q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1); if (ok != nullptr) { *ok = q.exec(); diff --git a/src/librssguard/database/databasequeries.h b/src/librssguard/database/databasequeries.h index 49eb16914..ddfbc54df 100644 --- a/src/librssguard/database/databasequeries.h +++ b/src/librssguard/database/databasequeries.h @@ -117,13 +117,28 @@ class DatabaseQueries { // Custom ID accumulators. static QStringList bagOfMessages(const QSqlDatabase& db, ServiceRoot::BagOfMessages bag, const Feed* feed); static QHash bagsOfMessages(const QSqlDatabase& db, const QList& labels); - static QStringList customIdsOfMessagesFromLabel(const QSqlDatabase& db, Label* label, bool* ok = nullptr); - static QStringList customIdsOfImportantMessages(const QSqlDatabase& db, int account_id, bool* ok = nullptr); - static QStringList customIdsOfUnreadMessages(const QSqlDatabase& db, int account_id, bool* ok = nullptr); - static QStringList customIdsOfMessagesFromAccount(const QSqlDatabase& db, int account_id, bool* ok = nullptr); - static QStringList customIdsOfMessagesFromBin(const QSqlDatabase& db, int account_id, bool* ok = nullptr); + static QStringList customIdsOfMessagesFromLabel(const QSqlDatabase& db, + Label* label, + RootItem::ReadStatus target_read, + bool* ok = nullptr); + static QStringList customIdsOfImportantMessages(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok = nullptr); + static QStringList customIdsOfUnreadMessages(const QSqlDatabase& db, + int account_id, + bool* ok = nullptr); + static QStringList customIdsOfMessagesFromAccount(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok = nullptr); + static QStringList customIdsOfMessagesFromBin(const QSqlDatabase& db, + RootItem::ReadStatus target_read, + int account_id, + bool* ok = nullptr); static QStringList customIdsOfMessagesFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, + RootItem::ReadStatus target_read, int account_id, bool* ok = nullptr); @@ -136,7 +151,7 @@ class DatabaseQueries { static void createOverwriteAccount(const QSqlDatabase& db, ServiceRoot* account); // Returns counts of updated messages . - static QPair updateMessages(const QSqlDatabase &db, + static QPair updateMessages(const QSqlDatabase& db, QList& messages, Feed* feed, bool force_update, diff --git a/src/librssguard/gui/settings/settingsgui.cpp b/src/librssguard/gui/settings/settingsgui.cpp index 4eb4daacc..849950145 100644 --- a/src/librssguard/gui/settings/settingsgui.cpp +++ b/src/librssguard/gui/settings/settingsgui.cpp @@ -22,7 +22,8 @@ #include #include -SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) { +SettingsGui::SettingsGui(Settings* settings, QWidget* parent) + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) { m_ui->setupUi(this); m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this); m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this); @@ -30,7 +31,7 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this); m_ui->m_treeSkins->setColumnCount(4); m_ui->m_treeSkins->setHeaderHidden(false); - m_ui->m_treeSkins->setHeaderLabels({ tr("Name"), tr("Author"), tr("Forced style"), tr("Forced skin colors") }); + m_ui->m_treeSkins->setHeaderLabels({tr("Name"), tr("Author"), tr("Forced style"), tr("Forced skin colors")}); m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) @@ -40,7 +41,8 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se #endif m_ui->m_helpCustomSkinColors->setHelpText(tr("You can override some colors defined by your skin here. " - "Some colors are used dynamically throughout the application."), false); + "Some colors are used dynamically throughout the application."), + false); // Setup skins. m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); @@ -50,9 +52,13 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se connect(m_ui->m_cmbStyles, &QComboBox::currentTextChanged, this, &SettingsGui::updateSkinOptions); - connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), - this, &SettingsGui::requireRestart); - connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), this, + connect(m_ui->m_cmbIconTheme, + static_cast(&QComboBox::currentIndexChanged), + this, + &SettingsGui::requireRestart); + connect(m_ui->m_cmbIconTheme, + static_cast(&QComboBox::currentIndexChanged), + this, &SettingsGui::dirtifySettings); connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::updateSkinOptions); @@ -68,17 +74,27 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_cmbToolbarButtonStyle, static_cast(&QComboBox::currentIndexChanged), this, + connect(m_ui->m_cmbToolbarButtonStyle, + static_cast(&QComboBox::currentIndexChanged), + this, &SettingsGui::dirtifySettings); connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::requireRestart); - connect(m_ui->m_cmbStyles, static_cast(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings); - connect(m_ui->m_cmbSelectToolBar, static_cast(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars, + connect(m_ui->m_cmbStyles, + static_cast(&QComboBox::currentIndexChanged), + this, + &SettingsGui::dirtifySettings); + connect(m_ui->m_cmbSelectToolBar, + static_cast(&QComboBox::currentIndexChanged), + m_ui->m_stackedToolbars, &QStackedWidget::setCurrentIndex); connect(m_ui->m_gbCustomSkinColors, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_spinToolbarIconSize, QOverload::of(&QSpinBox::valueChanged), this, &SettingsGui::dirtifySettings); + connect(m_ui->m_spinToolbarIconSize, + QOverload::of(&QSpinBox::valueChanged), + this, + &SettingsGui::dirtifySettings); connect(m_ui->m_displayUnreadMessageCountOnTaskBar, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); connect(m_ui->m_spinToolbarIconSize, QOverload::of(&QSpinBox::valueChanged), this, [=](int value) { @@ -137,12 +153,14 @@ void SettingsGui::loadSettings() { m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool()); if (!SystemTrayIcon::isSystemTrayAreaAvailable()) { - m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Your OS does not support tray icons at the moment.)")); + m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + + tr("(Your OS does not support tray icons at the moment.)")); m_ui->m_grpTray->setEnabled(false); } m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool()); - m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); + m_ui->m_checkHideWhenMinimized + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); // Load settings of icon theme. const QString current_theme = qApp->icons()->currentIconTheme(); @@ -164,10 +182,12 @@ void SettingsGui::loadSettings() { } m_ui->m_checkMonochromeIcons->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()); - m_ui->m_checkCountUnreadMessages->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersInTrayIcon)).toBool()); + m_ui->m_checkCountUnreadMessages + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersInTrayIcon)).toBool()); #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) - m_ui->m_displayUnreadMessageCountOnTaskBar->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool()); + m_ui->m_displayUnreadMessageCountOnTaskBar + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool()); #endif // Mark active icon theme. @@ -192,24 +212,27 @@ void SettingsGui::loadSettings() { m_ui->m_cmbStyles->setCurrentIndex(item_style); } - m_ui->m_checkForceAlternativePalette->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::ForcedSkinColors)).toBool()); + m_ui->m_checkForceAlternativePalette + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::ForcedSkinColors)).toBool()); // Load skin. const QString selected_skin = qApp->skins()->selectedSkinName(); auto skins = qApp->skins()->installedSkins(); for (const Skin& skin : qAsConst(skins)) { - QTreeWidgetItem* new_item = new QTreeWidgetItem({ - skin.m_visibleName, - skin.m_author, - skin.m_forcedStyles.isEmpty() ? QString() : skin.m_forcedStyles.join(QSL(", ")), - QString() }); + QTreeWidgetItem* new_item = + new QTreeWidgetItem({skin.m_visibleName, + skin.m_author, + skin.m_forcedStyles.isEmpty() ? QString() : skin.m_forcedStyles.join(QSL(", ")), + QString()}); - new_item->setToolTip(0, tr("%1\n\n" - "Version: %2\n" - "Description: %3").arg(skin.m_visibleName, - skin.m_version, - skin.m_description.isEmpty() ? QSL("-") : skin.m_description)); + new_item->setToolTip(0, + tr("%1\n\n" + "Version: %2\n" + "Description: %3") + .arg(skin.m_visibleName, + skin.m_version, + skin.m_description.isEmpty() ? QSL("-") : skin.m_description)); for (int i = 1; i < m_ui->m_treeSkins->columnCount(); i++) { new_item->setToolTip(i, new_item->toolTip(0)); @@ -219,9 +242,9 @@ void SettingsGui::loadSettings() { new_item->setIcon(2, qApp->icons()->fromTheme(QSL("dialog-cancel"), QSL("gtk-cancel"))); } - new_item->setIcon(3, skin.m_forcedSkinColors - ? qApp->icons()->fromTheme(QSL("dialog-yes"), QSL("dialog-ok")) - : qApp->icons()->fromTheme(QSL("dialog-cancel"), QSL("gtk-cancel"))); + new_item->setIcon(3, + skin.m_forcedSkinColors ? qApp->icons()->fromTheme(QSL("dialog-yes"), QSL("dialog-ok")) + : qApp->icons()->fromTheme(QSL("dialog-cancel"), QSL("gtk-cancel"))); new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin)); @@ -233,18 +256,20 @@ void SettingsGui::loadSettings() { } } - if (m_ui->m_treeSkins->currentItem() == nullptr && - m_ui->m_treeSkins->topLevelItemCount() > 0) { + if (m_ui->m_treeSkins->currentItem() == nullptr && m_ui->m_treeSkins->topLevelItemCount() > 0) { // Currently active skin is NOT available, select another one as selected // if possible. m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0)); } // Load tab settings. - m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); - m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); + m_ui->m_checkCloseTabsMiddleClick + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); + m_ui->m_checkCloseTabsDoubleClick + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool()); - m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool()); + m_ui->m_checkHideTabBarIfOneTabVisible + ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool()); // Load toolbar button style. m_ui->m_spinToolbarIconSize->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToolbarIconSize)).toInt()); @@ -253,9 +278,9 @@ void SettingsGui::loadSettings() { m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonStyle::ToolButtonTextBesideIcon); m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonStyle::ToolButtonTextUnderIcon); m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonStyle::ToolButtonFollowStyle); - m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI), - SETTING( - GUI::ToolbarStyle)).toInt())); + m_ui->m_cmbToolbarButtonStyle + ->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle + ->findData(settings()->value(GROUP(GUI), SETTING(GUI::ToolbarStyle)).toInt())); // Load toolbars. m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar()); @@ -263,8 +288,8 @@ void SettingsGui::loadSettings() { m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar()); // Load custom colors. - m_ui->m_gbCustomSkinColors->setChecked(settings()->value(GROUP(CustomSkinColors), - SETTING(CustomSkinColors::Enabled)).toBool()); + m_ui->m_gbCustomSkinColors + ->setChecked(settings()->value(GROUP(CustomSkinColors), SETTING(CustomSkinColors::Enabled)).toBool()); const QMetaObject& mo = SkinEnums::staticMetaObject; QMetaEnum enumer = mo.enumerator(mo.indexOfEnumerator(QSL("PaletteColors").toLocal8Bit().constData())); @@ -297,14 +322,14 @@ void SettingsGui::loadSettings() { lay->addWidget(clr_btn); lay->addWidget(rst_btn); - m_ui->m_layoutCustomColors->setWidget(row, - QFormLayout::ItemRole::LabelRole, - new QLabel( - TextFactory::capitalizeFirstLetter(SkinEnums::palleteColorText(SkinEnums::PaletteColors(enumer.value(i)))), - this)); - m_ui->m_layoutCustomColors->setLayout(row, - QFormLayout::ItemRole::FieldRole, - lay); + m_ui->m_layoutCustomColors + ->setWidget(row, + QFormLayout::ItemRole::LabelRole, + new QLabel(TextFactory:: + capitalizeFirstLetter(SkinEnums:: + palleteColorText(SkinEnums::PaletteColors(enumer.value(i)))), + this)); + m_ui->m_layoutCustomColors->setLayout(row, QFormLayout::ItemRole::FieldRole, lay); } onEndLoadSettings(); @@ -328,15 +353,13 @@ void SettingsGui::saveSettings() { auto children = m_ui->m_gbCustomSkinColors->findChildren(); for (const ColorToolButton* clr : children) { - settings()->setValue(GROUP(CustomSkinColors), - enumer.valueToKey(clr->objectName().toInt()), - clr->color().name()); + settings()->setValue(GROUP(CustomSkinColors), enumer.valueToKey(clr->objectName().toInt()), clr->color().name()); } // Save toolbar. settings()->setValue(GROUP(GUI), GUI::ToolbarIconSize, m_ui->m_spinToolbarIconSize->value()); - - settings()->setValue(GROUP(GUI), GUI::ToolbarStyle, + settings()->setValue(GROUP(GUI), + GUI::ToolbarStyle, m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex())); // Save tray icon. @@ -363,7 +386,9 @@ void SettingsGui::saveSettings() { settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked()); #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) - settings()->setValue(GROUP(GUI), GUI::UnreadNumbersOnTaskBar, m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked()); + settings()->setValue(GROUP(GUI), + GUI::UnreadNumbersOnTaskBar, + m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked()); #endif // Make sure that number of unread messages is shown in tray icon as requested. diff --git a/src/librssguard/gui/toolbars/messagestoolbar.cpp b/src/librssguard/gui/toolbars/messagestoolbar.cpp index 0d4d6a878..8a45f82ae 100644 --- a/src/librssguard/gui/toolbars/messagestoolbar.cpp +++ b/src/librssguard/gui/toolbars/messagestoolbar.cpp @@ -182,6 +182,7 @@ void MessagesToolBar::addActionToMenu(QMenu* menu, void MessagesToolBar::initializeHighlighter() { m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting articles"), this); + addActionToMenu(m_menuMessageHighlighter, qApp->icons()->fromTheme(QSL("mail-mark-read")), tr("No extra highlighting"), @@ -199,6 +200,7 @@ void MessagesToolBar::initializeHighlighter() { "highlight_important"); m_menuMessageFilter = new QMenu(tr("Menu for filtering articles"), this); + addActionToMenu(m_menuMessageFilter, qApp->icons()->fromTheme(QSL("mail-mark-read")), tr("No extra filtering"), @@ -261,17 +263,20 @@ void MessagesToolBar::initializeHighlighter() { m_btnMessageHighlighter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup); m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); m_btnMessageHighlighter->setDefaultAction(m_menuMessageHighlighter->actions().constFirst()); + m_btnMessageFilter = new QToolButton(this); m_btnMessageFilter->setToolTip(tr("Display all articles")); m_btnMessageFilter->setMenu(m_menuMessageFilter); m_btnMessageFilter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup); m_btnMessageFilter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); m_btnMessageFilter->setDefaultAction(m_menuMessageFilter->actions().constFirst()); + m_actionMessageHighlighter = new QWidgetAction(this); m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter); m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon()); m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME); m_actionMessageHighlighter->setProperty("name", tr("Article highlighter")); + m_actionMessageFilter = new QWidgetAction(this); m_actionMessageFilter->setDefaultWidget(m_btnMessageFilter); m_actionMessageFilter->setIcon(m_btnMessageFilter->icon()); @@ -280,6 +285,11 @@ void MessagesToolBar::initializeHighlighter() { connect(m_menuMessageHighlighter, &QMenu::triggered, this, &MessagesToolBar::handleMessageHighlighterChange); connect(m_menuMessageFilter, &QMenu::triggered, this, &MessagesToolBar::handleMessageFilterChange); + + connect(this, &MessagesToolBar::toolButtonStyleChanged, this, [=](Qt::ToolButtonStyle style) { + m_btnMessageHighlighter->setToolButtonStyle(style); + m_btnMessageFilter->setToolButtonStyle(style); + }); } void MessagesToolBar::saveToolButtonSelection(const QString& button_name, const QList& actions) const { diff --git a/src/librssguard/services/abstract/cacheforserviceroot.cpp b/src/librssguard/services/abstract/cacheforserviceroot.cpp index 24d605f46..9487d0d9b 100644 --- a/src/librssguard/services/abstract/cacheforserviceroot.cpp +++ b/src/librssguard/services/abstract/cacheforserviceroot.cpp @@ -17,6 +17,10 @@ CacheForServiceRoot::~CacheForServiceRoot() {} void CacheForServiceRoot::addLabelsAssignmentsToCache(const QStringList& ids_of_messages, const QString& lbl_custom_id, bool assign) { + if (ids_of_messages.isEmpty()) { + return; + } + if (assign) { for (const QString& custom_id : ids_of_messages) { if (m_cachedLabelDeassignments[lbl_custom_id].contains(custom_id)) { @@ -51,12 +55,17 @@ void CacheForServiceRoot::addLabelsAssignmentsToCache(const QList& ids_ addLabelsAssignmentsToCache(custom_ids, lbl->customId(), assign); } -void CacheForServiceRoot::addMessageStatesToCache(const QList& ids_of_messages, RootItem::Importance importance) { +void CacheForServiceRoot::addMessageStatesToCache(const QList& ids_of_messages, + RootItem::Importance importance) { + if (ids_of_messages.isEmpty()) { + return; + } + QMutexLocker lck(m_cacheSaveMutex.data()); QList& list_act = m_cachedStatesImportant[importance]; - QList& list_other = m_cachedStatesImportant[importance == RootItem::Importance::Important - ? RootItem::Importance::NotImportant - : RootItem::Importance::Important]; + QList& list_other = + m_cachedStatesImportant[importance == RootItem::Importance::Important ? RootItem::Importance::NotImportant + : RootItem::Importance::Important]; // Store changes, they will be sent to server later. list_act.append(ids_of_messages); @@ -80,11 +89,14 @@ void CacheForServiceRoot::addMessageStatesToCache(const QList& ids_of_m } void CacheForServiceRoot::addMessageStatesToCache(const QStringList& ids_of_messages, RootItem::ReadStatus read) { + if (ids_of_messages.isEmpty()) { + return; + } + QMutexLocker lck(m_cacheSaveMutex.data()); QStringList& list_act = m_cachedStatesRead[read]; - QStringList& list_other = m_cachedStatesRead[read == RootItem::ReadStatus::Read - ? RootItem::ReadStatus::Unread - : RootItem::ReadStatus::Read]; + QStringList& list_other = + m_cachedStatesRead[read == RootItem::ReadStatus::Read ? RootItem::ReadStatus::Unread : RootItem::ReadStatus::Read]; // Store changes, they will be sent to server later. list_act.append(ids_of_messages); @@ -109,7 +121,8 @@ void CacheForServiceRoot::addMessageStatesToCache(const QStringList& ids_of_mess void CacheForServiceRoot::saveCacheToFile() { // Save to file. - const QString file_cache = qApp->userDataFolder() + QDir::separator() + QString::number(m_uniqueId) + "-cached-msgs.dat"; + const QString file_cache = + qApp->userDataFolder() + QDir::separator() + QString::number(m_uniqueId) + "-cached-msgs.dat"; if (isEmpty()) { QFile::remove(file_cache); @@ -140,7 +153,8 @@ void CacheForServiceRoot::loadCacheFromFile() { clearCache(); // Load from file. - const QString file_cache = qApp->userDataFolder() + QDir::separator() + QString::number(m_uniqueId) + "-cached-msgs.dat"; + const QString file_cache = + qApp->userDataFolder() + QDir::separator() + QString::number(m_uniqueId) + "-cached-msgs.dat"; QFile file(file_cache); if (file.exists()) { @@ -189,6 +203,6 @@ CacheSnapshot CacheForServiceRoot::takeMessageCache() { } bool CacheForServiceRoot::isEmpty() const { - return m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty() && - m_cachedLabelAssignments.isEmpty() && m_cachedLabelDeassignments.isEmpty(); + return m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty() && m_cachedLabelAssignments.isEmpty() && + m_cachedLabelDeassignments.isEmpty(); } diff --git a/src/librssguard/services/abstract/category.cpp b/src/librssguard/services/abstract/category.cpp index 5bb8368fd..024218815 100644 --- a/src/librssguard/services/abstract/category.cpp +++ b/src/librssguard/services/abstract/category.cpp @@ -37,11 +37,12 @@ void Category::updateCounts(bool including_total_count) { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); bool ok; - QMap> counts = DatabaseQueries::getMessageCountsForCategory(database, - customId(), - getParentServiceRoot()->accountId(), - including_total_count, - &ok); + QMap> counts = + DatabaseQueries::getMessageCountsForCategory(database, + customId(), + getParentServiceRoot()->accountId(), + including_total_count, + &ok); if (ok) { for (Feed* feed : feeds) { @@ -65,7 +66,7 @@ bool Category::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } return service->markFeedsReadUnread(getSubTreeFeeds(), status); diff --git a/src/librssguard/services/abstract/feed.cpp b/src/librssguard/services/abstract/feed.cpp index 56b062cc2..0f1019fd5 100644 --- a/src/librssguard/services/abstract/feed.cpp +++ b/src/librssguard/services/abstract/feed.cpp @@ -213,10 +213,10 @@ bool Feed::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } - return service->markFeedsReadUnread(QList() << this, status); + return service->markFeedsReadUnread({this}, status); } QString Feed::getAutoUpdateStatusDescription() const { diff --git a/src/librssguard/services/abstract/importantnode.cpp b/src/librssguard/services/abstract/importantnode.cpp index 0c1a3d078..9d5ae3708 100644 --- a/src/librssguard/services/abstract/importantnode.cpp +++ b/src/librssguard/services/abstract/importantnode.cpp @@ -53,7 +53,7 @@ bool ImportantNode::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); diff --git a/src/librssguard/services/abstract/label.cpp b/src/librssguard/services/abstract/label.cpp index cd83d52f1..30d4a5798 100644 --- a/src/librssguard/services/abstract/label.cpp +++ b/src/librssguard/services/abstract/label.cpp @@ -153,7 +153,7 @@ bool Label::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); diff --git a/src/librssguard/services/abstract/recyclebin.cpp b/src/librssguard/services/abstract/recyclebin.cpp index fdb822c41..65742d97e 100644 --- a/src/librssguard/services/abstract/recyclebin.cpp +++ b/src/librssguard/services/abstract/recyclebin.cpp @@ -64,17 +64,17 @@ QList RecycleBin::undeletedMessages() const { bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - ServiceRoot* parent_root = getParentServiceRoot(); - auto* cache = dynamic_cast(parent_root); + ServiceRoot* service = getParentServiceRoot(); + auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(parent_root->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } - if (DatabaseQueries::markBinReadUnread(database, parent_root->accountId(), status)) { + if (DatabaseQueries::markBinReadUnread(database, service->accountId(), status)) { updateCounts(false); - parent_root->itemChanged(QList() << this); - parent_root->requestReloadMessageList(status == RootItem::ReadStatus::Read); + service->itemChanged(QList() << this); + service->requestReloadMessageList(status == RootItem::ReadStatus::Read); return true; } else { diff --git a/src/librssguard/services/abstract/rootitem.h b/src/librssguard/services/abstract/rootitem.h index 7085ae014..de0fdf681 100644 --- a/src/librssguard/services/abstract/rootitem.h +++ b/src/librssguard/services/abstract/rootitem.h @@ -27,11 +27,11 @@ class RSSGUARD_DLLSPEC RootItem : public QObject { Q_PROPERTY(QString customId READ customId) public: - enum class ReadStatus { Unread = 0, Read = 1 }; + enum class ReadStatus { Unread = 0, Read = 1, Unknown = 256 }; // Holds statuses for messages // to be switched importance (starred). - enum class Importance { NotImportant = 0, Important = 1 }; + enum class Importance { NotImportant = 0, Important = 1, Unknown = 256 }; // Describes the kind of the item. enum class Kind { @@ -142,7 +142,7 @@ class RSSGUARD_DLLSPEC RootItem : public QObject { QHash getSubTreeCategoriesForAssemble() const; // Returns list of categories complemented by their own string CUSTOM ID. - QHash getHashedSubTreeCategories() const; + QHash getHashedSubTreeCategories() const; // Returns list of feeds complemented by their own string CUSTOM ID. QHash getHashedSubTreeFeeds() const; diff --git a/src/librssguard/services/abstract/serviceroot.cpp b/src/librssguard/services/abstract/serviceroot.cpp index 1c8845dc8..adad5e240 100644 --- a/src/librssguard/services/abstract/serviceroot.cpp +++ b/src/librssguard/services/abstract/serviceroot.cpp @@ -46,7 +46,7 @@ bool ServiceRoot::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(this); if (cache != nullptr) { - cache->addMessageStatesToCache(customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(customIDSOfMessagesForItem(this, status), status); } QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); @@ -559,7 +559,7 @@ RootItem* ServiceRoot::obtainNewTreeForSyncIn() const { return nullptr; } -QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) { +QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item, ReadStatus target_read) { if (item->getParentServiceRoot() != this) { // Not item from this account. return {}; @@ -573,7 +573,7 @@ QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) { auto chi = item->childItems(); for (RootItem* child : qAsConst(chi)) { - list.append(customIDSOfMessagesForItem(child)); + list.append(customIDSOfMessagesForItem(child, target_read)); } return list; @@ -582,35 +582,35 @@ QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) { case RootItem::Kind::Label: { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - list = DatabaseQueries::customIdsOfMessagesFromLabel(database, item->toLabel()); + list = DatabaseQueries::customIdsOfMessagesFromLabel(database, item->toLabel(), target_read); break; } case RootItem::Kind::ServiceRoot: { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - list = DatabaseQueries::customIdsOfMessagesFromAccount(database, accountId()); + list = DatabaseQueries::customIdsOfMessagesFromAccount(database, target_read, accountId()); break; } case RootItem::Kind::Bin: { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - list = DatabaseQueries::customIdsOfMessagesFromBin(database, accountId()); + list = DatabaseQueries::customIdsOfMessagesFromBin(database, target_read, accountId()); break; } case RootItem::Kind::Feed: { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), accountId()); + list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), target_read, accountId()); break; } case RootItem::Kind::Important: { QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - list = DatabaseQueries::customIdsOfImportantMessages(database, accountId()); + list = DatabaseQueries::customIdsOfImportantMessages(database, target_read, accountId()); break; } diff --git a/src/librssguard/services/abstract/serviceroot.h b/src/librssguard/services/abstract/serviceroot.h index 3f5f9c68c..86003c175 100644 --- a/src/librssguard/services/abstract/serviceroot.h +++ b/src/librssguard/services/abstract/serviceroot.h @@ -222,7 +222,15 @@ class ServiceRoot : public RootItem { QStringList textualFeedIds(const QList& feeds) const; QStringList customIDsOfMessages(const QList& changes); QStringList customIDsOfMessages(const QList& messages); - QStringList customIDSOfMessagesForItem(RootItem* item); + + // Returns list of article IDs depending on what target operation is. + // NOTE: So if we want to mark some articles as read, + // then we only return UNREAD IDs here to really return + // only IDs when the change makes sense. + // NOTE: Importance is not dealt here because it was not needed + // yet. + QStringList customIDSOfMessagesForItem(RootItem* item, + RootItem::ReadStatus target_read = RootItem::ReadStatus::Unknown); void performInitialAssembly(const Assignment& categories, const Assignment& feeds, const QList& labels); diff --git a/src/librssguard/services/abstract/unreadnode.cpp b/src/librssguard/services/abstract/unreadnode.cpp index 55d55785e..ae83ed036 100644 --- a/src/librssguard/services/abstract/unreadnode.cpp +++ b/src/librssguard/services/abstract/unreadnode.cpp @@ -58,7 +58,7 @@ bool UnreadNode::markAsReadUnread(RootItem::ReadStatus status) { auto* cache = dynamic_cast(service); if (cache != nullptr) { - cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status); + cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this, status), status); } QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); diff --git a/src/librssguard/services/feedly/feedlyserviceroot.cpp b/src/librssguard/services/feedly/feedlyserviceroot.cpp index b82a0554a..279e6acb0 100644 --- a/src/librssguard/services/feedly/feedlyserviceroot.cpp +++ b/src/librssguard/services/feedly/feedlyserviceroot.cpp @@ -152,11 +152,7 @@ void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) { QList messages = j.value(); if (!messages.isEmpty()) { - QStringList ids; - - for (const Message& msg : messages) { - ids.append(msg.m_customId); - } + QStringList ids = customIDsOfMessages(messages); try { network()->markers(key == RootItem::Importance::Important ? FEEDLY_MARKERS_IMPORTANT diff --git a/src/librssguard/services/gmail/gmailserviceroot.cpp b/src/librssguard/services/gmail/gmailserviceroot.cpp index fb58cd5fb..29d415e36 100644 --- a/src/librssguard/services/gmail/gmailserviceroot.cpp +++ b/src/librssguard/services/gmail/gmailserviceroot.cpp @@ -236,12 +236,7 @@ void GmailServiceRoot::saveAllCachedData(bool ignore_errors) { QList messages = j.value(); if (!messages.isEmpty()) { - QStringList custom_ids; - custom_ids.reserve(messages.size()); - - for (const Message& msg : messages) { - custom_ids.append(msg.m_customId); - } + QStringList custom_ids = customIDsOfMessages(messages); if (network()->markMessagesStarred(key, custom_ids, networkProxy()) != QNetworkReply::NetworkError::NoError && !ignore_errors) { diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp index 4d64ee1eb..b06a66fbb 100644 --- a/src/librssguard/services/greader/greaderserviceroot.cpp +++ b/src/librssguard/services/greader/greaderserviceroot.cpp @@ -201,12 +201,7 @@ void GreaderServiceRoot::saveAllCachedData(bool ignore_errors) { QList messages = j.value(); if (!messages.isEmpty()) { - QStringList custom_ids; - custom_ids.reserve(messages.size()); - - for (const Message& msg : messages) { - custom_ids.append(msg.m_customId); - } + QStringList custom_ids = customIDsOfMessages(messages); if (network()->markMessagesStarred(key, custom_ids, networkProxy()) != QNetworkReply::NetworkError::NoError && !ignore_errors) {