diff --git a/pri/install.pri b/pri/install.pri index 1948f8d36..ed4c9d604 100644 --- a/pri/install.pri +++ b/pri/install.pri @@ -175,7 +175,10 @@ win32 { lib.path = $$PREFIX lib.CONFIG = no_check_exist - INSTALLS += target lib + clng.files = ../../resources/scripts/clang-format/clang-format.exe + clng.path = $$PREFIX + + INSTALLS += target lib clng INSTALL_HEADERS_PREFIX = $$quote($$PREFIX/include/librssguard) } diff --git a/resources/scripts/clang-format/clang-format.exe b/resources/scripts/clang-format/clang-format.exe new file mode 100755 index 000000000..cc26d5b09 Binary files /dev/null and b/resources/scripts/clang-format/clang-format.exe differ diff --git a/src/librssguard/core/feeddownloader.cpp b/src/librssguard/core/feeddownloader.cpp index 25a8d2dc8..6f7d659ad 100644 --- a/src/librssguard/core/feeddownloader.cpp +++ b/src/librssguard/core/feeddownloader.cpp @@ -4,6 +4,7 @@ #include "core/messagefilter.h" #include "definitions/definitions.h" +#include "exceptions/filteringexception.h" #include "miscellaneous/application.h" #include "services/abstract/cacheforserviceroot.h" #include "services/abstract/feed.h" @@ -147,23 +148,31 @@ void FeedDownloader::updateOneFeed(Feed* feed) { tmr.restart(); - FilteringAction decision = msg_filter->filterMessage(&filter_engine); + try { + FilteringAction decision = msg_filter->filterMessage(&filter_engine); - qDebug().nospace() << "Running filter script, it took " << tmr.nsecsElapsed() / 1000 << " microseconds."; + qDebug().nospace() << "Running filter script, it took " << tmr.nsecsElapsed() / 1000 << " microseconds."; - switch (decision) { - case FilteringAction::Accept: + switch (decision) { + case FilteringAction::Accept: - // Message is normally accepted, it could be tweaked by the filter. - continue; + // Message is normally accepted, it could be tweaked by the filter. + continue; - case FilteringAction::Ignore: + case FilteringAction::Ignore: - // Remove the message, we do not want it. - msgs.removeAt(i--); - break; + // Remove the message, we do not want it. + msgs.removeAt(i--); + break; + } + } + catch (const FilteringException& ex) { + qCritical("Error when evaluating filtering JS function: '%s'. Accepting message.", qPrintable(ex.message())); + continue; } + // If we reach this point. Then we ignore the message which is by now + // already removed, go to next message. break; } } diff --git a/src/librssguard/core/messagefilter.cpp b/src/librssguard/core/messagefilter.cpp index 966e43f08..8b01d0e0b 100755 --- a/src/librssguard/core/messagefilter.cpp +++ b/src/librssguard/core/messagefilter.cpp @@ -3,6 +3,7 @@ #include "core/messagefilter.h" #include "core/message.h" +#include "exceptions/filteringexception.h" #include @@ -43,15 +44,19 @@ FilteringAction MessageFilter::filterMessage(QJSEngine* engine) { QJSValue filter_func = engine->evaluate(m_script); if (filter_func.isError()) { - qCritical("Error when evaluating script from filter '%d'. Error is: '%s'", id(), qPrintable(filter_func.toString())); - return FilteringAction::Accept; + QJSValue::ErrorType error = filter_func.errorType(); + QString message = filter_func.toString(); + + throw FilteringException(error, message); } auto filter_output = engine->evaluate(QSL("filterMessage()")); if (filter_output.isError()) { - qCritical("Error when calling filtering function '%d'. Error is: '%s'", id(), qPrintable(filter_output.toString())); - return FilteringAction::Accept; + QJSValue::ErrorType error = filter_output.errorType(); + QString message = filter_output.toString(); + + throw FilteringException(error, message); } return FilteringAction(filter_output.toInt()); diff --git a/src/librssguard/exceptions/applicationexception.h b/src/librssguard/exceptions/applicationexception.h index 982f606fa..f3e89a199 100644 --- a/src/librssguard/exceptions/applicationexception.h +++ b/src/librssguard/exceptions/applicationexception.h @@ -8,7 +8,6 @@ class ApplicationException { public: explicit ApplicationException(QString message = QString()); - virtual ~ApplicationException() = default; QString message() const; diff --git a/src/librssguard/exceptions/filteringexception.cpp b/src/librssguard/exceptions/filteringexception.cpp new file mode 100755 index 000000000..d061e1d51 --- /dev/null +++ b/src/librssguard/exceptions/filteringexception.cpp @@ -0,0 +1,6 @@ +// For license of this file, see /LICENSE.md. + +#include "exceptions/filteringexception.h" + +FilteringException::FilteringException(QJSValue::ErrorType js_error, QString message) + : ApplicationException(message), m_errorType(js_error) {} diff --git a/src/librssguard/exceptions/filteringexception.h b/src/librssguard/exceptions/filteringexception.h new file mode 100755 index 000000000..493220da5 --- /dev/null +++ b/src/librssguard/exceptions/filteringexception.h @@ -0,0 +1,18 @@ +// For license of this file, see /LICENSE.md. + +#ifndef FILTERINGEXCEPTION_H +#define FILTERINGEXCEPTION_H + +#include "exceptions/applicationexception.h" + +#include + +class FilteringException : public ApplicationException { + public: + explicit FilteringException(QJSValue::ErrorType js_error, QString message = QString()); + + private: + QJSValue::ErrorType m_errorType; +}; + +#endif // FILTERINGEXCEPTION_H diff --git a/src/librssguard/exceptions/ioexception.h b/src/librssguard/exceptions/ioexception.h index 4d3bf1a2a..42fedde6e 100644 --- a/src/librssguard/exceptions/ioexception.h +++ b/src/librssguard/exceptions/ioexception.h @@ -8,7 +8,6 @@ class IOException : public ApplicationException { public: explicit IOException(const QString& message = QString()); - virtual ~IOException() = default; }; #endif // IOEXCEPTION_H diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp index 8ed317fa4..a8baaaa0b 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp @@ -6,6 +6,7 @@ #include "gui/dialogs/formmessagefiltersmanager.h" #include "core/messagefilter.h" +#include "exceptions/filteringexception.h" #include "gui/guiutilities.h" #include "miscellaneous/application.h" #include "miscellaneous/feedreader.h" @@ -38,6 +39,7 @@ FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const Q connect(m_ui.m_btnTest, &QPushButton::clicked, this, &FormMessageFiltersManager::testFilter); initializeTestingMessage(); + loadFilter(); } FormMessageFiltersManager::~FormMessageFiltersManager() { @@ -95,6 +97,12 @@ void FormMessageFiltersManager::loadFilter() { } void FormMessageFiltersManager::testFilter() { + // TODO: Add button to beautify JavaScript code, call clang-format and distribute + // it under windows. On other platforms, just try to call and raise messagebox + // error with "install clang-format" if not found. + // then call like this with qt process api. + // echo "script-code" | ./clang-format.exe --assume-filename="script.js" --style="Chromium" + // Perform per-message filtering. QJSEngine filter_engine; QSqlDatabase database = qApp->database()->connection(metaObject()->className()); @@ -113,8 +121,37 @@ void FormMessageFiltersManager::testFilter() { msg_obj.setMessage(&msg); auto* fltr = selectedFilter(); - FilteringAction decision = fltr->filterMessage(&filter_engine); - int aa = 5; + + try { + FilteringAction decision = fltr->filterMessage(&filter_engine); + + m_ui.m_txtErrors->setTextColor(decision == FilteringAction::Accept ? Qt::GlobalColor::darkGreen : Qt::GlobalColor::red); + + QString answer = tr("Message will be %1.\n").arg(decision == FilteringAction::Accept + ? tr("accepted") + : tr("rejected")); + + answer += tr("Output (modified) message is:\n" + " Title = '%1'\n" + " URL = '%2'\n" + " Author = '%3'\n" + " Is read/important = '%4/%5'\n" + " Created on = '%6'\n" + " Contents = '%7'").arg(msg.m_title, msg.m_url, msg.m_author, + msg.m_isRead ? tr("yes") : tr("no"), + msg.m_isImportant ? tr("yes") : tr("no"), + QString::number(msg.m_created.toMSecsSinceEpoch()), + msg.m_contents); + + m_ui.m_txtErrors->setPlainText(answer); + } + catch (const FilteringException& ex) { + m_ui.m_txtErrors->setTextColor(Qt::GlobalColor::red); + m_ui.m_txtErrors->setPlainText(tr("JavaScript-based filter contains errors: '%1'.").arg(ex.message())); + } + + // See output. + m_ui.m_tcMessage->setCurrentIndex(1); } void FormMessageFiltersManager::showFilter(MessageFilter* filter) { @@ -131,6 +168,8 @@ void FormMessageFiltersManager::showFilter(MessageFilter* filter) { m_ui.m_gbDetails->setEnabled(true); } + // See message. + m_ui.m_tcMessage->setCurrentIndex(0); m_loadingFilter = false; } diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.ui b/src/librssguard/gui/dialogs/formmessagefiltersmanager.ui index f185faf8b..ef4036be7 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.ui +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.ui @@ -50,19 +50,6 @@ - - - - - 0 - 150 - - - - - - - @@ -73,6 +60,54 @@ + + + + + + + + + + 0 + 150 + + + + + + + + + + &Check all + + + + + + + &Uncheck all + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + @@ -147,108 +182,154 @@ - - - Sample message + + + 0 - - - - - - - Read - - - - - - - Important - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Title - - - m_txtSampleTitle - - - - - - - - - - URL - - - m_txtSampleUrl - - - - - - - - - - Author - - - m_txtSampleAuthor - - - - - - - - - - Created on - - - m_txtSampleCreatedOn - - - - - - - - - - Contents - - - m_txtSampleContents - - - - - - - + + + Sample message + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + + Read + + + + + + + Important + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Title + + + m_txtSampleTitle + + + + + + + + + + URL + + + m_txtSampleUrl + + + + + + + + + + Author + + + m_txtSampleAuthor + + + + + + + + + + Created on + + + m_txtSampleCreatedOn + + + + + + + + + + Contents + + + m_txtSampleContents + + + + + + + + + + + Script output + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 1 + + + + + + @@ -265,7 +346,7 @@ - &Detailed &help + Detailed &help @@ -284,32 +365,6 @@ - - - - Test output - - - m_txtErrors - - - - - - - false - - - - 0 - 1 - - - - false - - - @@ -334,10 +389,13 @@ m_btnRemoveSelected comboBox m_treeFeeds + pushButton + pushButton_2 m_txtTitle m_txtScript m_btnTest m_btnDetailedHelp + m_tcMessage m_cbSampleRead m_cbSampleImportant m_txtSampleTitle diff --git a/src/librssguard/librssguard.pro b/src/librssguard/librssguard.pro index b4d76d751..3ba224694 100644 --- a/src/librssguard/librssguard.pro +++ b/src/librssguard/librssguard.pro @@ -44,6 +44,7 @@ HEADERS += core/feeddownloader.h \ dynamic-shortcuts/shortcutbutton.h \ dynamic-shortcuts/shortcutcatcher.h \ exceptions/applicationexception.h \ + exceptions/filteringexception.h \ exceptions/ioexception.h \ gui/baselineedit.h \ gui/basetoolbar.h \ @@ -189,6 +190,7 @@ SOURCES += core/feeddownloader.cpp \ dynamic-shortcuts/shortcutbutton.cpp \ dynamic-shortcuts/shortcutcatcher.cpp \ exceptions/applicationexception.cpp \ + exceptions/filteringexception.cpp \ exceptions/ioexception.cpp \ gui/baselineedit.cpp \ gui/basetoolbar.cpp \