From c360450e62a606d71e0f763c7ab6e0b388ae5e82 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Wed, 2 Feb 2022 10:06:45 +0100 Subject: [PATCH] some work on nodejs integration --- src/librssguard/CMakeLists.txt | 2 + src/librssguard/core/filterutils.cpp | 8 ++- src/librssguard/definitions/definitions.h | 2 +- .../exceptions/processexception.cpp | 14 +++++ src/librssguard/exceptions/processexception.h | 22 ++++++++ .../gui/settings/settingsnodejs.cpp | 51 ++++++++++++++++++- src/librssguard/gui/settings/settingsnodejs.h | 5 ++ .../gui/settings/settingsnodejs.ui | 21 +++++--- src/librssguard/miscellaneous/application.cpp | 2 +- src/librssguard/miscellaneous/iofactory.cpp | 5 +- src/librssguard/miscellaneous/nodejs.cpp | 46 ++++++++++++++++- src/librssguard/miscellaneous/nodejs.h | 19 ++++++- src/librssguard/miscellaneous/settings.cpp | 24 +++++++++ src/librssguard/miscellaneous/settings.h | 17 ++++++- .../network-web/adblock/adblockmanager.cpp | 19 ++++--- 15 files changed, 233 insertions(+), 24 deletions(-) create mode 100755 src/librssguard/exceptions/processexception.cpp create mode 100755 src/librssguard/exceptions/processexception.h diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt index 83d918d81..4fdd60250 100644 --- a/src/librssguard/CMakeLists.txt +++ b/src/librssguard/CMakeLists.txt @@ -55,6 +55,8 @@ set(SOURCES exceptions/networkexception.h exceptions/scriptexception.cpp exceptions/scriptexception.h + exceptions/processexception.cpp + exceptions/processexception.h gui/dialogs/formabout.cpp gui/dialogs/formabout.h gui/dialogs/formaddaccount.cpp diff --git a/src/librssguard/core/filterutils.cpp b/src/librssguard/core/filterutils.cpp index e2e19fd9b..4f38543fc 100644 --- a/src/librssguard/core/filterutils.cpp +++ b/src/librssguard/core/filterutils.cpp @@ -3,6 +3,7 @@ #include "core/filterutils.h" #include "definitions/definitions.h" +#include "exceptions/applicationexception.h" #include "miscellaneous/iofactory.h" #include "miscellaneous/textfactory.h" @@ -88,5 +89,10 @@ QDateTime FilterUtils::parseDateTime(const QString& dat) const { } QString FilterUtils::runExecutableGetOutput(const QString& executable, const QStringList& arguments) const { - return IOFactory::startProcessGetOutput(executable, arguments); + try { + return IOFactory::startProcessGetOutput(executable, arguments); + } + catch (const ApplicationException& ex) { + return ex.message(); + } } diff --git a/src/librssguard/definitions/definitions.h b/src/librssguard/definitions/definitions.h index 015358561..de6a65c15 100644 --- a/src/librssguard/definitions/definitions.h +++ b/src/librssguard/definitions/definitions.h @@ -275,7 +275,7 @@ #elif defined(Q_OS_OPENBSD) #define OS_ID "OpenBSD" #elif defined(Q_OS_OS2) -#define OS_ID "OS/2" +#define OS_ID "OS2" #elif defined(Q_OS_OSX) #define OS_ID "macOS" #elif defined(Q_OS_WIN) diff --git a/src/librssguard/exceptions/processexception.cpp b/src/librssguard/exceptions/processexception.cpp new file mode 100755 index 000000000..e5af636b6 --- /dev/null +++ b/src/librssguard/exceptions/processexception.cpp @@ -0,0 +1,14 @@ +// For license of this file, see /LICENSE.md. + +#include "exceptions/processexception.h" + +ProcessException::ProcessException(int exit_code, QProcess::ExitStatus exit_status, const QString& message) + : ApplicationException(message), m_exitStatus(exit_status), m_exitCode(exit_code) {} + +QProcess::ExitStatus ProcessException::exitStatus() const { + return m_exitStatus; +} + +int ProcessException::exitCode() const { + return m_exitCode; +} diff --git a/src/librssguard/exceptions/processexception.h b/src/librssguard/exceptions/processexception.h new file mode 100755 index 000000000..bf55547de --- /dev/null +++ b/src/librssguard/exceptions/processexception.h @@ -0,0 +1,22 @@ +// For license of this file, see /LICENSE.md. + +#ifndef PROCESSEXCEPTION_H +#define PROCESSEXCEPTION_H + +#include "exceptions/applicationexception.h" + +#include + +class ProcessException : public ApplicationException { + public: + ProcessException(int exit_code, QProcess::ExitStatus exit_status, const QString& message = QString()); + + QProcess::ExitStatus exitStatus() const; + int exitCode() const; + + private: + QProcess::ExitStatus m_exitStatus; + int m_exitCode; +}; + +#endif // PROCESSEXCEPTION_H diff --git a/src/librssguard/gui/settings/settingsnodejs.cpp b/src/librssguard/gui/settings/settingsnodejs.cpp index c144ead66..4dbbc545c 100644 --- a/src/librssguard/gui/settings/settingsnodejs.cpp +++ b/src/librssguard/gui/settings/settingsnodejs.cpp @@ -3,9 +3,12 @@ #include "gui/settings/settingsnodejs.h" #include "definitions/definitions.h" +#include "exceptions/applicationexception.h" #include "miscellaneous/application.h" #include "miscellaneous/nodejs.h" +#include + SettingsNodejs::SettingsNodejs(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent) { m_ui.setupUi(this); @@ -22,6 +25,13 @@ SettingsNodejs::SettingsNodejs(Settings* settings, QWidget* parent) : SettingsPa "it uses subfolder placed in your \"user data\" folder.").arg(APP_NAME), false); + connect(m_ui.m_tbNodeExecutable->lineEdit(), &BaseLineEdit::textChanged, + this, &SettingsNodejs::testNodejs); + connect(m_ui.m_tbNpmExecutable->lineEdit(), &BaseLineEdit::textChanged, + this, &SettingsNodejs::testNpm); + connect(m_ui.m_tbPackageFolder->lineEdit(), &BaseLineEdit::textChanged, + this, &SettingsNodejs::testPackageFolder); + // FOR ME: npm install --prefix "složka" // NODE_PATH="složka" node.exe.... } @@ -30,6 +40,45 @@ QString SettingsNodejs::title() const { return QSL("Node.js"); } -void SettingsNodejs::loadSettings() {} +void SettingsNodejs::loadSettings() { + m_ui.m_tbNodeExecutable->lineEdit()->setText(qApp->nodejs()->nodeJsExecutable()); + m_ui.m_tbNpmExecutable->lineEdit()->setText(qApp->nodejs()->npmExecutable()); + m_ui.m_tbPackageFolder->lineEdit()->setText(qApp->nodejs()->packageFolder()); +} void SettingsNodejs::saveSettings() {} + +void SettingsNodejs::testNodejs() { + try { + QString node_version = qApp->nodejs()->nodejsVersion(m_ui.m_tbNodeExecutable->lineEdit()->text()); + + m_ui.m_tbNodeExecutable->setStatus(WidgetWithStatus::StatusType::Ok, + tr("Node.js has version %1.").arg(node_version)); + } + catch (const ApplicationException& ex) { + m_ui.m_tbNodeExecutable->setStatus(WidgetWithStatus::StatusType::Error, + tr("Node.js: %1.").arg(ex.message())); + } +} + +void SettingsNodejs::testNpm() { + try { + QString npm_version = qApp->nodejs()->npmVersion(m_ui.m_tbNpmExecutable->lineEdit()->text()); + + m_ui.m_tbNpmExecutable->setStatus(WidgetWithStatus::StatusType::Ok, + tr("NPM has version %1.").arg(npm_version)); + } + catch (const ApplicationException& ex) { + m_ui.m_tbNpmExecutable->setStatus(WidgetWithStatus::StatusType::Error, + tr("NPM: %1.").arg(ex.message())); + } +} + +void SettingsNodejs::testPackageFolder() { + QString folder = qApp->replaceDataUserDataFolderPlaceholder(m_ui.m_tbPackageFolder->lineEdit()->text()); + + m_ui.m_tbPackageFolder->setStatus(WidgetWithStatus::StatusType::Ok, + QDir().exists(folder) + ? tr("Package folder is OK.") + : tr("Package folder will be created!")); +} diff --git a/src/librssguard/gui/settings/settingsnodejs.h b/src/librssguard/gui/settings/settingsnodejs.h index 50a9b4152..22a2ecc36 100644 --- a/src/librssguard/gui/settings/settingsnodejs.h +++ b/src/librssguard/gui/settings/settingsnodejs.h @@ -17,6 +17,11 @@ class SettingsNodejs : public SettingsPanel { virtual void loadSettings(); virtual void saveSettings(); + private slots: + void testNodejs(); + void testNpm(); + void testPackageFolder(); + private: Ui::SettingsNodejs m_ui; }; diff --git a/src/librssguard/gui/settings/settingsnodejs.ui b/src/librssguard/gui/settings/settingsnodejs.ui index 241bba097..3522b627c 100644 --- a/src/librssguard/gui/settings/settingsnodejs.ui +++ b/src/librssguard/gui/settings/settingsnodejs.ui @@ -22,15 +22,18 @@ Node.js executable + + m_tbNodeExecutable + - + - + 0 @@ -49,15 +52,18 @@ NPM executable + + m_tbNpmExecutable + - + - + 0 @@ -76,15 +82,18 @@ Package folder + + m_tbPackageFolder + - + - + 0 diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index 4b67cabd5..83db3db54 100644 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -68,7 +68,7 @@ Application::Application(const QString& id, int& argc, char** argv) m_database = new DatabaseFactory(this); m_downloadManager = nullptr; m_notifications = new NotificationFactory(this); - m_nodejs = new NodeJs(this); + m_nodejs = new NodeJs(m_settings, this); m_shouldRestart = false; determineFirstRuns(); diff --git a/src/librssguard/miscellaneous/iofactory.cpp b/src/librssguard/miscellaneous/iofactory.cpp index 34fe0211e..bb3b926fe 100644 --- a/src/librssguard/miscellaneous/iofactory.cpp +++ b/src/librssguard/miscellaneous/iofactory.cpp @@ -4,6 +4,7 @@ #include "definitions/definitions.h" #include "exceptions/ioexception.h" +#include "exceptions/processexception.h" #include #include @@ -113,9 +114,7 @@ QString IOFactory::startProcessGetOutput(const QString& executable, return proc.readAllStandardOutput(); } else { - QString err = proc.readAllStandardError().simplified(); - - return err; + throw ProcessException(proc.exitCode(), proc.exitStatus(), proc.readAllStandardError().simplified()); } } diff --git a/src/librssguard/miscellaneous/nodejs.cpp b/src/librssguard/miscellaneous/nodejs.cpp index 52bd2dc69..5f0c638c5 100644 --- a/src/librssguard/miscellaneous/nodejs.cpp +++ b/src/librssguard/miscellaneous/nodejs.cpp @@ -2,4 +2,48 @@ #include "miscellaneous/nodejs.h" -NodeJs::NodeJs(QObject* parent) : QObject{parent} {} +#include "exceptions/applicationexception.h" +#include "miscellaneous/iofactory.h" +#include "miscellaneous/settings.h" + +#include + +NodeJs::NodeJs(Settings* settings, QObject* parent) : QObject(parent), m_settings(settings) {} + +QString NodeJs::nodeJsExecutable() const { + return QDir::toNativeSeparators(m_settings->value(GROUP(Node), SETTING(Node::NodeJsExecutable)).toString()); +} + +void NodeJs::setNodeJsExecutable(const QString& exe) const { + m_settings->setValue(GROUP(Node), Node::NodeJsExecutable, exe); +} + +QString NodeJs::npmExecutable() const { + return QDir::toNativeSeparators(m_settings->value(GROUP(Node), SETTING(Node::NpmExecutable)).toString()); +} + +void NodeJs::setNpmExecutable(const QString& exe) const { + m_settings->setValue(GROUP(Node), Node::NpmExecutable, exe); +} + +QString NodeJs::packageFolder() const { + return QDir::toNativeSeparators(m_settings->value(GROUP(Node), SETTING(Node::PackageFolder)).toString()); +} + +void NodeJs::setPackageFolder(const QString& path) {} + +QString NodeJs::nodejsVersion(const QString& nodejs_exe) const { + if (nodejs_exe.simplified().isEmpty()) { + throw ApplicationException(tr("file not found")); + } + + return IOFactory::startProcessGetOutput(nodejs_exe, { QSL("--version") }).simplified(); +} + +QString NodeJs::npmVersion(const QString& npm_exe) const { + if (npm_exe.simplified().isEmpty()) { + throw ApplicationException(tr("file not found")); + } + + return IOFactory::startProcessGetOutput(npm_exe, { QSL("--version") }).simplified(); +} diff --git a/src/librssguard/miscellaneous/nodejs.h b/src/librssguard/miscellaneous/nodejs.h index ede73475f..ed3202c04 100644 --- a/src/librssguard/miscellaneous/nodejs.h +++ b/src/librssguard/miscellaneous/nodejs.h @@ -5,11 +5,28 @@ #include +class Settings; + class NodeJs : public QObject { Q_OBJECT public: - explicit NodeJs(QObject* parent = nullptr); + explicit NodeJs(Settings* settings, QObject* parent = nullptr); + + QString nodeJsExecutable() const; + void setNodeJsExecutable(const QString& exe) const; + + QString npmExecutable() const; + void setNpmExecutable(const QString& exe) const; + + QString packageFolder() const; + void setPackageFolder(const QString& path); + + QString nodejsVersion(const QString& nodejs_exe) const; + QString npmVersion(const QString& npm_exe) const; + + private: + Settings* m_settings; }; #endif // NODEJS_H diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index 787947879..c04a7613e 100644 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -15,6 +15,30 @@ DKEY WebEngineAttributes::ID = "web_engine_attributes"; #endif +// Node.js. +DKEY Node::ID = "nodejs"; + +DKEY Node::NodeJsExecutable = QSL("nodejs_executable_") + OS_ID; + +#if defined(Q_OS_WIN) || defined(Q_OS_OS2) +DVALUE(QString) Node::NodeJsExecutableDef = "node.exe"; +#else +DVALUE(QString) Node::NodeJsExecutableDef = "node"; +#endif + +DKEY Node::NpmExecutable = QSL("npm_executable_") + OS_ID; + +#if defined(Q_OS_WIN) +DVALUE(QString) Node::NpmExecutableDef = "npm.cmd"; +#elif defined(Q_OS_OS2) +DVALUE(QString) Node::NpmExecutableDef = "npm.exe"; +#else +DVALUE(QString) Node::NpmExecutableDef = "npm"; +#endif + +DKEY Node::PackageFolder = QSL("package_folder") + OS_ID; +DVALUE(QString) Node::PackageFolderDef = QSL(USER_DATA_PLACEHOLDER) + "/node-packages-" + OS_ID; + // Cookies. DKEY Cookies::ID = "cookies"; diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index d03c2eddc..d1e9a840a 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -16,8 +16,8 @@ #include #include -#define KEY extern const char* -#define DKEY const char* +#define KEY extern const QString +#define DKEY const QString #define VALUE(x) extern const x #define NON_CONST_VALUE(x) extern x #define DVALUE(x) const x @@ -36,6 +36,19 @@ namespace Cookies { KEY ID; } +namespace Node { + KEY ID; + + KEY NodeJsExecutable; + VALUE(QString) NodeJsExecutableDef; + + KEY NpmExecutable; + VALUE(QString) NpmExecutableDef; + + KEY PackageFolder; + VALUE(QString) PackageFolderDef; +} + namespace AdBlock { KEY ID; diff --git a/src/librssguard/network-web/adblock/adblockmanager.cpp b/src/librssguard/network-web/adblock/adblockmanager.cpp index d542972f6..ef3aea4c9 100644 --- a/src/librssguard/network-web/adblock/adblockmanager.cpp +++ b/src/librssguard/network-web/adblock/adblockmanager.cpp @@ -298,17 +298,22 @@ QProcess* AdBlockManager::startServer(int port) { auto pe = proc->processEnvironment(); if (!pe.contains(QSL("NODE_PATH"))) { - const QString system_node_prefix = IOFactory::startProcessGetOutput( + try { + const QString system_node_prefix = IOFactory::startProcessGetOutput( #if defined(Q_OS_WIN) - QSL("npm.cmd") + QSL("npm.cmd") #else - QSL("npm") + QSL("npm") #endif - , { QSL("root"), QSL("--quiet"), QSL("-g") } - ); + , { QSL("root"), QSL("--quiet"), QSL("-g") } + ); - if (!system_node_prefix.isEmpty()) { - pe.insert(QSL("NODE_PATH"), system_node_prefix.simplified()); + if (!system_node_prefix.isEmpty()) { + pe.insert(QSL("NODE_PATH"), system_node_prefix.simplified()); + } + } + catch (const ApplicationException& ex) { + qWarningNN << LOGSEC_ADBLOCK << "Failed to get NPM root path:" << QUOTE_W_SPACE_DOT(ex.message()); } }