diff --git a/resources/desktop/com.github.rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml index 3c5eb5c37..83f988c6b 100644 --- a/resources/desktop/com.github.rssguard.appdata.xml +++ b/resources/desktop/com.github.rssguard.appdata.xml @@ -26,7 +26,7 @@ https://github.com/sponsors/martinrotter - + none diff --git a/src/librssguard/core/messageobject.cpp b/src/librssguard/core/messageobject.cpp index 8d9603c4c..e99bed915 100644 --- a/src/librssguard/core/messageobject.cpp +++ b/src/librssguard/core/messageobject.cpp @@ -3,6 +3,7 @@ #include "core/messageobject.h" #include "3rd-party/boolinq/boolinq.h" +#include "database/databasefactory.h" #include #include @@ -65,9 +66,8 @@ bool MessageObject::isDuplicateWithAttribute(MessageObject::DuplicationAttribute QString full_query = QSL("SELECT COUNT(*) FROM Messages WHERE ") + where_clauses.join(QSL(" AND ")) + QSL(";"); qDebugNN << LOGSEC_MESSAGEMODEL - << "Query for MSG duplicate identification is: '" - << full_query - << "'."; + << "Prepared query for MSG duplicate identification is:" + << QUOTE_W_SPACE_DOT(full_query); q.setForwardOnly(true); q.prepare(full_query); @@ -77,20 +77,23 @@ bool MessageObject::isDuplicateWithAttribute(MessageObject::DuplicationAttribute } if (q.exec() && q.next()) { + qDebugNN << LOGSEC_DB + << "Executed SQL for message duplicates check:" + << QUOTE_W_SPACE_DOT(DatabaseFactory::lastExecutedQuery(q)); + if (q.record().value(0).toInt() > 0) { // Whoops, we have the "same" message in database. - qDebugNN << LOGSEC_MESSAGEMODEL - << "Message '" - << title() - << "' was identified as duplicate by filter script."; + qDebugNN << LOGSEC_CORE + << "Message" + << QUOTE_W_SPACE(title()) + << "was identified as duplicate by filter script."; return true; } } else if (q.lastError().isValid()) { - qWarningNN << LOGSEC_MESSAGEMODEL - << "Error when checking for duplicate messages via filtering system, error: '" - << q.lastError().text() - << "'."; + qWarningNN << LOGSEC_CORE + << "Error when checking for duplicate messages via filtering system, error:" + << QUOTE_W_SPACE_DOT(q.lastError().text()); } return false; diff --git a/src/librssguard/database/databasefactory.cpp b/src/librssguard/database/databasefactory.cpp index 98bd56311..3e6ab929f 100644 --- a/src/librssguard/database/databasefactory.cpp +++ b/src/librssguard/database/databasefactory.cpp @@ -12,7 +12,9 @@ #include "miscellaneous/textfactory.h" #include +#include #include +#include #include #include @@ -78,6 +80,25 @@ DatabaseDriver* DatabaseFactory::driverForType(DatabaseDriver::DriverType d) con }); } +QString DatabaseFactory::lastExecutedQuery(const QSqlQuery& query) { + QString str = query.lastQuery(); + QMapIterator it(query.boundValues()); + + while (it.hasNext()) { + it.next(); + + if (it.value().type() == QVariant::Type::Char || + it.value().type() == QVariant::Type::String) { + str.replace(it.key(), QSL("'%1'").arg(it.value().toString())); + } + else { + str.replace(it.key(), it.value().toString()); + } + } + + return str; +} + QString DatabaseFactory::escapeQuery(const QString& query) { return QString(query) .replace(QSL("'"), QSL("''")); diff --git a/src/librssguard/database/databasefactory.h b/src/librssguard/database/databasefactory.h index 2c24c6bbe..726f50cf5 100644 --- a/src/librssguard/database/databasefactory.h +++ b/src/librssguard/database/databasefactory.h @@ -24,6 +24,7 @@ class DatabaseFactory : public QObject { DatabaseDriver* driver() const; DatabaseDriver* driverForType(DatabaseDriver::DriverType d) const; + static QString lastExecutedQuery(const QSqlQuery& query); static QString escapeQuery(const QString& query); private: diff --git a/src/librssguard/gui/dialogs/formmain.cpp b/src/librssguard/gui/dialogs/formmain.cpp index 5c1ff8131..43824495b 100644 --- a/src/librssguard/gui/dialogs/formmain.cpp +++ b/src/librssguard/gui/dialogs/formmain.cpp @@ -804,7 +804,9 @@ void FormMain::createConnections() { connect(m_ui->m_actionSelectPreviousMessage, &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::selectPreviousItem); connect(m_ui->m_actionSwitchMessageListOrientation, &QAction::triggered, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::switchMessageSplitterOrientation); + tabWidget()->feedMessageViewer(), [this]() { + tabWidget()->feedMessageViewer()->switchMessageSplitterOrientation(true); + }); connect(m_ui->m_actionShowOnlyUnreadItems, &QAction::toggled, tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadFeeds); connect(m_ui->m_actionShowTreeBranches, &QAction::toggled, diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp index 3d0193a51..27908a3f3 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp @@ -596,6 +596,7 @@ Message FormMessageFiltersManager::testingMessage() const { msg.m_feedId = NO_PARENT_CATEGORY; msg.m_url = m_ui.m_txtSampleUrl->text(); + msg.m_customId = m_ui.m_txtSampleUrl->text(); msg.m_title = m_ui.m_txtSampleTitle->text(); msg.m_author = m_ui.m_txtSampleAuthor->text(); msg.m_isRead = m_ui.m_cbSampleRead->isChecked(); diff --git a/src/librssguard/gui/feedmessageviewer.cpp b/src/librssguard/gui/feedmessageviewer.cpp index 5c7343fb7..70e78e450 100644 --- a/src/librssguard/gui/feedmessageviewer.cpp +++ b/src/librssguard/gui/feedmessageviewer.cpp @@ -2,6 +2,7 @@ #include "gui/feedmessageviewer.h" +#include "3rd-party/boolinq/boolinq.h" #include "core/feeddownloader.h" #include "core/feedsproxymodel.h" #include "core/messagesproxymodel.h" @@ -23,6 +24,7 @@ #include "miscellaneous/mutex.h" #include "miscellaneous/settings.h" #include "miscellaneous/systemfactory.h" +#include "miscellaneous/templates.h" #include "services/standard/standardfeed.h" #include "services/standard/standardfeedsimportexportmodel.h" #include "services/standard/standardserviceroot.h" @@ -87,8 +89,19 @@ void FeedMessageViewer::saveSize() { m_feedsView->saveAllExpandStates(); // Store offsets of splitters. - settings->setValue(GROUP(GUI), GUI::SplitterFeeds, QString(m_feedSplitter->saveState().toBase64())); - settings->setValue(GROUP(GUI), GUI::SplitterMessages, QString(m_messageSplitter->saveState().toBase64())); + settings->setValue(GROUP(GUI), GUI::SplitterFeeds, toVariant(m_feedSplitter->sizes())); + + if (!settings->value(GROUP(GUI), SETTING(GUI::SplitterMessagesIsVertical)).toBool()) { + settings->setValue(GROUP(GUI), + GUI::SplitterMessagesHorizontal, + toVariant(m_messageSplitter->sizes())); + } + else { + settings->setValue(GROUP(GUI), + GUI::SplitterMessagesVertical, + toVariant(m_messageSplitter->sizes())); + } + settings->setValue(GROUP(GUI), GUI::MessageViewState, QString(m_messagesView->saveHeaderState().toBase64())); // Store "visibility" of toolbars and list headers. @@ -100,9 +113,19 @@ void FeedMessageViewer::loadSize() { const Settings* settings = qApp->settings(); // Restore offsets of splitters. - m_feedSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterFeeds)).toString().toLocal8Bit())); - m_messageSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), - SETTING(GUI::SplitterMessages)).toString().toLocal8Bit())); + m_feedSplitter->setSizes(toList(settings->value(GROUP(GUI), + SETTING(GUI::SplitterFeeds)))); + + if (!settings->value(GROUP(GUI), SETTING(GUI::SplitterMessagesIsVertical)).toBool()) { + switchMessageSplitterOrientation(false); + m_messageSplitter->setSizes(toList(settings->value(GROUP(GUI), + SETTING(GUI::SplitterMessagesHorizontal)))); + } + else { + m_messageSplitter->setSizes(toList(settings->value(GROUP(GUI), + SETTING(GUI::SplitterMessagesVertical)))); + + } QString settings_msg_header = settings->value(GROUP(GUI), SETTING(GUI::MessageViewState)).toString(); @@ -125,13 +148,33 @@ bool FeedMessageViewer::areListHeadersEnabled() const { return m_listHeadersEnabled; } -void FeedMessageViewer::switchMessageSplitterOrientation() { +void FeedMessageViewer::switchMessageSplitterOrientation(bool save_settings) { if (m_messageSplitter->orientation() == Qt::Orientation::Vertical) { + if (save_settings) { + qApp->settings()->setValue(GROUP(GUI), + GUI::SplitterMessagesVertical, + toVariant(m_messageSplitter->sizes())); + } + m_messageSplitter->setOrientation(Qt::Orientation::Horizontal); + m_messageSplitter->setSizes(toList(qApp->settings()->value(GROUP(GUI), + SETTING(GUI::SplitterMessagesHorizontal)))); } else { + if (save_settings) { + qApp->settings()->setValue(GROUP(GUI), + GUI::SplitterMessagesHorizontal, + toVariant(m_messageSplitter->sizes())); + } + m_messageSplitter->setOrientation(Qt::Orientation::Vertical); + m_messageSplitter->setSizes(toList(qApp->settings()->value(GROUP(GUI), + SETTING(GUI::SplitterMessagesVertical)))); } + + qApp->settings()->setValue(GROUP(GUI), + GUI::SplitterMessagesIsVertical, + m_messageSplitter->orientation() == Qt::Orientation::Vertical); } void FeedMessageViewer::setToolBarsEnabled(bool enable) { diff --git a/src/librssguard/gui/feedmessageviewer.h b/src/librssguard/gui/feedmessageviewer.h index 26caa3f84..2343ced02 100644 --- a/src/librssguard/gui/feedmessageviewer.h +++ b/src/librssguard/gui/feedmessageviewer.h @@ -51,7 +51,7 @@ class RSSGUARD_DLLSPEC FeedMessageViewer : public TabContent { void loadMessageViewerFonts(); // Switches orientation horizontal/vertical. - void switchMessageSplitterOrientation(); + void switchMessageSplitterOrientation(bool save_settings); // Enables/disables main toolbars or list headers. void setToolBarsEnabled(bool enable); diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index c89d59b00..798beb93d 100644 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -135,10 +135,16 @@ DKEY GUI::MessageViewState = "msg_view_state"; DVALUE(QString) GUI::MessageViewStateDef = QString(); DKEY GUI::SplitterFeeds = "splitter_feeds"; -DVALUE(char*) GUI::SplitterFeedsDef = ""; +DVALUE(QList) GUI::SplitterFeedsDef = {}; -DKEY GUI::SplitterMessages = "splitter_messages"; -DVALUE(char*) GUI::SplitterMessagesDef = ""; +DKEY GUI::SplitterMessagesIsVertical = "splitter_messages_is_vertical"; +DVALUE(bool) GUI::SplitterMessagesIsVerticalDef = true; + +DKEY GUI::SplitterMessagesVertical = "splitter_messages_vertical"; +DVALUE(QList) GUI::SplitterMessagesVerticalDef = {}; + +DKEY GUI::SplitterMessagesHorizontal = "splitter_messages_horizontal"; +DVALUE(QList) GUI::SplitterMessagesHorizontalDef = {}; DKEY GUI::ToolbarStyle = "toolbar_style"; DVALUE(Qt::ToolButtonStyle) GUI::ToolbarStyleDef = Qt::ToolButtonIconOnly; diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index 47b8670f2..30bf883db 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -157,10 +157,16 @@ namespace GUI { VALUE(QString) MessageViewStateDef; KEY SplitterFeeds; - VALUE(char*) SplitterFeedsDef; + VALUE(QList) SplitterFeedsDef; - KEY SplitterMessages; - VALUE(char*) SplitterMessagesDef; + KEY SplitterMessagesIsVertical; + VALUE(bool) SplitterMessagesIsVerticalDef; + + KEY SplitterMessagesVertical; + VALUE(QList) SplitterMessagesVerticalDef; + + KEY SplitterMessagesHorizontal; + VALUE(QList) SplitterMessagesHorizontalDef; KEY ToolbarStyle; VALUE(Qt::ToolButtonStyle) ToolbarStyleDef; diff --git a/src/librssguard/miscellaneous/skinfactory.cpp b/src/librssguard/miscellaneous/skinfactory.cpp index 96c4d3cc1..3fb863d98 100644 --- a/src/librssguard/miscellaneous/skinfactory.cpp +++ b/src/librssguard/miscellaneous/skinfactory.cpp @@ -156,7 +156,7 @@ Skin SkinFactory::skinInfo(const QString& skin_name, bool* ok) const { skin.m_layoutMarkupWrapper = skin.m_layoutMarkupWrapper.replace(QSL(SKIN_STYLE_PLACEHOLDER), QString::fromUtf8(custom_css)); } - catch (const IOException& ex) { + catch (...) { qWarningNN << "Skin" << QUOTE_W_SPACE(skin_name) << "does not support separated custom CSS."; diff --git a/src/librssguard/miscellaneous/templates.h b/src/librssguard/miscellaneous/templates.h index 323dc9d15..406adb53a 100644 --- a/src/librssguard/miscellaneous/templates.h +++ b/src/librssguard/miscellaneous/templates.h @@ -1,4 +1,28 @@ +// For license of this file, see /LICENSE.md. + #ifndef TEMPLATES_H #define TEMPLATES_H +#include + +template static QVariant toVariant(const QList& list) { + QVariantList variant_list; variant_list.reserve(list.size()); + + for (const auto& v : list) { + variant_list.append(v); + } + + return variant_list; +} + +template static QList toList(const QVariant& qv) { + QList data_list; + + foreach(QVariant v, qv.value()) { + data_list << v.value(); + } + + return data_list; +} + #endif // TEMPLATES_H