diff --git a/resources/desktop/io.github.martinrotter.rssguard.metainfo.xml b/resources/desktop/io.github.martinrotter.rssguard.metainfo.xml
index 63403b755..c55e4b284 100644
--- a/resources/desktop/io.github.martinrotter.rssguard.metainfo.xml
+++ b/resources/desktop/io.github.martinrotter.rssguard.metainfo.xml
@@ -60,7 +60,7 @@
-
+
rssguard
diff --git a/resources/docs/Documentation.md b/resources/docs/Documentation.md
index 406cf4de9..a954acaab 100644
--- a/resources/docs/Documentation.md
+++ b/resources/docs/Documentation.md
@@ -604,6 +604,8 @@ Please report all issues/bugs/ideas to [Issues](https://github.com/martinrotter/
If you report any bug, you must provide application debug log. So make sure to start RSS Guard from command line (`cmd.exe` on Windows) with `--log` switch and path where you want to store log file, for example `rssguard.exe --log '.\rssguard.log'` which will save log file into your RSS Guard folder. After you've started RSS Guard this way, then reproduce your problem and upload log file to the ticket.
+You can also display application log directly in RSS Guard, see `Application log` menu item in `Help` menu. Note that log messages are only pumped into the dialog when the dialog is opened (can be minimized).
+
Also, for some broader questions or general ideas, use [discussions](https://github.com/martinrotter/rssguard/discussions) rather than [issues](https://github.com/martinrotter/rssguard/issues).
### Localization
diff --git a/resources/rssguard.qrc b/resources/rssguard.qrc
index 6b0b53f60..6d00794d1 100644
--- a/resources/rssguard.qrc
+++ b/resources/rssguard.qrc
@@ -22,6 +22,7 @@
scripts/filters/blacklist.js
scripts/filters/whitelist.js
+ scripts/filters/no-duplicates.js
graphics/rssguard.ico
diff --git a/resources/scripts/filters/no-duplicates.js b/resources/scripts/filters/no-duplicates.js
new file mode 100755
index 000000000..3c249e92e
--- /dev/null
+++ b/resources/scripts/filters/no-duplicates.js
@@ -0,0 +1,14 @@
+// This filter ensures that there are no duplicate
+// articles received across all feeds
+//
+// Remember you have to assign this filter to all your feeds
+// you want to de-duplicate.
+
+function filterMessage() {
+ if (msg.isAlreadyInDatabase(MessageObject.SameTitle | MessageObject.AllFeedsSameAccount)) {
+ return MessageObject.Ignore;
+ }
+ else {
+ return MessageObject.Accept;
+ }
+}
\ No newline at end of file
diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt
index 6a7ea25f4..d1a4d250f 100644
--- a/src/librssguard/CMakeLists.txt
+++ b/src/librssguard/CMakeLists.txt
@@ -68,7 +68,9 @@ set(SOURCES
gui/dialogs/formdatabasecleanup.cpp
gui/dialogs/formdatabasecleanup.h
gui/dialogs/formmain.cpp
- gui/dialogs/formmain.h
+ gui/dialogs/formmain.h
+ gui/dialogs/formlog.cpp
+ gui/dialogs/formlog.h
gui/dialogs/formmessagefiltersmanager.cpp
gui/dialogs/formmessagefiltersmanager.h
gui/dialogs/formrestoredatabasesettings.cpp
@@ -438,6 +440,7 @@ set(UI_FILES
gui/dialogs/formbackupdatabasesettings.ui
gui/dialogs/formdatabasecleanup.ui
gui/dialogs/formmain.ui
+ gui/dialogs/formlog.ui
gui/dialogs/formmessagefiltersmanager.ui
gui/dialogs/formrestoredatabasesettings.ui
gui/dialogs/formsettings.ui
diff --git a/src/librssguard/gui/dialogs/formlog.cpp b/src/librssguard/gui/dialogs/formlog.cpp
new file mode 100755
index 000000000..35f740ef3
--- /dev/null
+++ b/src/librssguard/gui/dialogs/formlog.cpp
@@ -0,0 +1,26 @@
+// For license of this file, see /LICENSE.md.
+
+#include "gui/dialogs/formlog.h"
+
+#include "gui/guiutilities.h"
+#include "miscellaneous/application.h"
+#include "miscellaneous/iconfactory.h"
+
+#include
+
+FormLog::FormLog(QWidget* parent) : QDialog(parent) {
+ m_ui.setupUi(this);
+
+ GuiUtilities::applyDialogProperties(*this,
+ qApp->icons()->fromTheme(QSL("dialog-information")),
+ tr("Application log"));
+
+ setWindowFlags(Qt::WindowType::WindowMinimizeButtonHint | windowFlags());
+}
+
+FormLog::~FormLog() {}
+
+void FormLog::appendLogMessage(const QString& message) {
+ m_ui.m_txtLog->appendPlainText(message);
+ m_ui.m_txtLog->verticalScrollBar()->setValue(m_ui.m_txtLog->verticalScrollBar()->maximum());
+}
diff --git a/src/librssguard/gui/dialogs/formlog.h b/src/librssguard/gui/dialogs/formlog.h
new file mode 100755
index 000000000..7d49d384b
--- /dev/null
+++ b/src/librssguard/gui/dialogs/formlog.h
@@ -0,0 +1,24 @@
+// For license of this file, see /LICENSE.md.
+
+#ifndef FORMLOG_H
+#define FORMLOG_H
+
+#include
+
+#include "ui_formlog.h"
+
+class FormLog : public QDialog {
+ Q_OBJECT
+
+ public:
+ explicit FormLog(QWidget* parent = nullptr);
+ virtual ~FormLog();
+
+ public slots:
+ void appendLogMessage(const QString& message);
+
+ private:
+ Ui::FormLog m_ui;
+};
+
+#endif // FORMLOG_H
diff --git a/src/librssguard/gui/dialogs/formlog.ui b/src/librssguard/gui/dialogs/formlog.ui
new file mode 100755
index 000000000..3593a8591
--- /dev/null
+++ b/src/librssguard/gui/dialogs/formlog.ui
@@ -0,0 +1,71 @@
+
+
+ FormLog
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close
+
+
+
+ -
+
+
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+ m_btnBox
+ accepted()
+ FormLog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ m_btnBox
+ rejected()
+ FormLog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/librssguard/gui/dialogs/formmain.cpp b/src/librssguard/gui/dialogs/formmain.cpp
index fdf6b19ba..c0c0f669d 100644
--- a/src/librssguard/gui/dialogs/formmain.cpp
+++ b/src/librssguard/gui/dialogs/formmain.cpp
@@ -551,6 +551,7 @@ void FormMain::setupIcons() {
m_ui->m_actionBackupDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-export")));
m_ui->m_actionRestoreDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-import")));
m_ui->m_actionDonate->setIcon(icon_theme_factory->fromTheme(QSL("applications-office")));
+ m_ui->m_actionApplicationLog->setIcon(icon_theme_factory->fromTheme(QSL("dialog-information")));
m_ui->m_actionDisplayDocs->setIcon(icon_theme_factory->fromTheme(QSL("applications-science")));
// View.
@@ -751,6 +752,7 @@ void FormMain::createConnections() {
});
connect(m_ui->m_actionReportBug, &QAction::triggered, this, &FormMain::reportABug);
connect(m_ui->m_actionDonate, &QAction::triggered, this, &FormMain::donate);
+ connect(m_ui->m_actionApplicationLog, &QAction::triggered, qApp, &Application::displayLog);
connect(m_ui->m_actionDisplayDocs, &QAction::triggered, this, &FormMain::showDocs);
// Tab widget connections.
diff --git a/src/librssguard/gui/dialogs/formmain.ui b/src/librssguard/gui/dialogs/formmain.ui
index d954191af..c83f1fcd2 100644
--- a/src/librssguard/gui/dialogs/formmain.ui
+++ b/src/librssguard/gui/dialogs/formmain.ui
@@ -64,6 +64,7 @@
+
@@ -884,6 +885,11 @@
Move to &bottom
+
+
+ Display application &log
+
+
diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp
index a3e250b63..2d494c131 100644
--- a/src/librssguard/miscellaneous/application.cpp
+++ b/src/librssguard/miscellaneous/application.cpp
@@ -6,12 +6,13 @@
#include "dynamic-shortcuts/dynamicshortcuts.h"
#include "exceptions/applicationexception.h"
#include "gui/dialogs/formabout.h"
+#include "gui/dialogs/formlog.h"
#include "gui/dialogs/formmain.h"
#include "gui/feedmessageviewer.h"
#include "gui/feedsview.h"
#include "gui/messagebox.h"
#include "gui/toolbars/statusbar.h"
-#include "gui/webviewers/qtextbrowser/textbrowserviewer.h" // QTextBrowser-based web browsing.
+#include "gui/webviewers/qtextbrowser/textbrowserviewer.h"
#include "miscellaneous/feedreader.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/iofactory.h"
@@ -68,6 +69,7 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
m_feedReader = nullptr;
m_quitLogicDone = false;
m_mainForm = nullptr;
+ m_logForm = nullptr;
m_trayIcon = nullptr;
m_settings = Settings::setupSettings(this);
@@ -237,6 +239,8 @@ void Application::performLogging(QtMsgType type, const QMessageLogContext& conte
}
}
+ qApp->displayLogMessageInDialog(console_message);
+
if (type == QtMsgType::QtFatalMsg) {
qApp->exit(EXIT_FAILURE);
}
@@ -363,6 +367,12 @@ void Application::eliminateFirstRuns() {
settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + APP_VERSION, false);
}
+void Application::displayLogMessageInDialog(const QString& message) {
+ if (m_logForm != nullptr && m_logForm->isVisible()) {
+ m_logForm->appendLogMessage(message);
+ }
+}
+
int Application::customAdblockPort() const {
return m_customAdblockPort;
}
@@ -1059,6 +1069,14 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_arg
}
}
+void Application::displayLog() {
+ if (m_logForm == nullptr) {
+ m_logForm = new FormLog(m_mainForm);
+ }
+
+ m_logForm->show();
+}
+
void Application::fillCmdArgumentsParser(QCommandLineParser& parser) {
QCommandLineOption help({QSL(CLI_HELP_SHORT), QSL(CLI_HELP_LONG)}, QSL("Displays overview of CLI."));
QCommandLineOption version({QSL(CLI_VER_SHORT), QSL(CLI_VER_LONG)}, QSL("Displays version of the application."));
diff --git a/src/librssguard/miscellaneous/application.h b/src/librssguard/miscellaneous/application.h
index f467c9375..38624099a 100644
--- a/src/librssguard/miscellaneous/application.h
+++ b/src/librssguard/miscellaneous/application.h
@@ -31,6 +31,7 @@
#define qApp (Application::instance())
class FormMain;
+class FormLog;
class IconFactory;
class QAction;
class Mutex;
@@ -188,6 +189,8 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication {
void parseCmdArgumentsFromOtherInstance(const QString& message);
void parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_args);
+ void displayLog();
+
private slots:
void fillCmdArgumentsParser(QCommandLineParser& parser);
@@ -219,6 +222,7 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication {
void setupCustomDataFolder(const QString& data_folder);
void determineFirstRuns();
void eliminateFirstRuns();
+ void displayLogMessageInDialog(const QString& message);
private:
QStringList m_rawCliArgs;
@@ -243,6 +247,7 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication {
QList m_userActions;
FormMain* m_mainForm;
+ FormLog* m_logForm;
SystemTrayIcon* m_trayIcon;
Settings* m_settings;
WebFactory* m_webFactory;