diff --git a/src/backends/julia/juliabackend.cpp b/src/backends/julia/juliabackend.cpp index 73799318..caac5f87 100644 --- a/src/backends/julia/juliabackend.cpp +++ b/src/backends/julia/juliabackend.cpp @@ -1,169 +1,169 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2016 Ivan Lakhtanov Copyright (C) 2019 Alexander Semke */ #include "juliabackend.h" #include "juliaextensions.h" #include "juliasession.h" #include "settings.h" #include "ui_settings.h" #include #include JuliaBackend::JuliaBackend(QObject *parent, const QList &args) : Cantor::Backend(parent, args) { setEnabled(true); new JuliaVariableManagementExtension(this); new JuliaPackagingExtension(this); new JuliaPlotExtension(this); new JuliaScriptExtension(this); new JuliaLinearAlgebraExtension(this); } QString JuliaBackend::id() const { return QLatin1String("julia"); } QString JuliaBackend::version() const { return QLatin1String("1.0.0"); } Cantor::Session *JuliaBackend::createSession() { return new JuliaSession(this); } Cantor::Backend::Capabilities JuliaBackend::capabilities() const { Cantor::Backend::Capabilities cap = SyntaxHighlighting | Completion; if (JuliaSettings::variableManagement()) cap |= VariableManagement; return cap; } QString JuliaBackend::description() const { return i18n( "Julia is a high-level, high-performance dynamic programming " "language for technical computing, with syntax that is familiar to " "users of other technical computing environments. It provides a " "sophisticated compiler, distributed parallel execution, numerical " "accuracy, and an extensive mathematical function library." ); } QUrl JuliaBackend::helpUrl() const { return QUrl(i18nc( "The url to the documentation of Julia, please check if there is a" " translated version and use the correct url", "https://docs.julialang.org/en/latest/" )); } bool JuliaBackend::requirementsFullfilled(QString* const reason) const { const QString& path = JuliaSettings::self()->replPath().toLocalFile(); bool valid = Cantor::Backend::checkExecutable(QLatin1String("Julia"), path, reason); if (!valid) return false; QFileInfo info(path); if (info.isSymLink()) { if (reason) - *reason = i18n("The path to Julia specified in the application settings must point directly to the executable. Symlinks are not allowed." + *reason = i18n("The path to Julia specified in the application settings must point directly to the executable. Symlinks are not allowed. " "Please provide the correct path in the application settings and try again."); return false; } // Julia because of C API can handle only MAJOR.MINOR.* versions corresponding to // version, which used to build cantor_juliaserver // So check it and print info about it to user, if versions don't match QProcess getJuliaVersionProcess; getJuliaVersionProcess.setProgram(path); getJuliaVersionProcess.setArguments(QStringList() << QLatin1String("-v")); getJuliaVersionProcess.start(); if (getJuliaVersionProcess.waitForFinished(1000) == false) { if (reason) *reason = i18n("Сantor couldn’t determine the version of Julia for %1. " "Please specify the correct path to Julia executable (no symlinks allowed) and try again.", path); return false; } QRegularExpression versionExp(QLatin1String("julia version (\\d+)\\.(\\d+).(\\d+)")); QString versionString = QString::fromLocal8Bit(getJuliaVersionProcess.readLine()); QRegularExpressionMatch match = versionExp.match(versionString); if (getJuliaVersionProcess.state() != QProcess::NotRunning || !match.hasMatch()) { if (reason) *reason = i18n("Сantor couldn’t determine the version of Julia for %1. " "Please specify the correct path to Julia executable (no symlinks allowed) and try again.", path); return false; } int juliaMajor = match.captured(1).toInt(); int juliaMinor = match.captured(2).toInt(); int juliaPatch = match.captured(3).toInt(); if (QT_VERSION_CHECK(juliaMajor, juliaMinor, juliaPatch) != QT_VERSION_CHECK(JULIA_VERSION_MAJOR, JULIA_VERSION_MINOR, JULIA_VERSION_PATCH)) { if (reason) *reason = i18n("You are trying to use Cantor with Julia v%1.%2.%3. " "This version of Cantor was compiled with the support of Julia v%4.%5.%6. " "Please point to this version of Julia or recompile Cantor using the version %1.%2.%3.", juliaMajor, juliaMinor, juliaPatch, JULIA_VERSION_MAJOR, JULIA_VERSION_MINOR, JULIA_VERSION_PATCH); return false; } return true; } QWidget* JuliaBackend::settingsWidget(QWidget *parent) const { QWidget* widget = new QWidget(parent); Ui::JuliaSettingsBase s; s.setupUi(widget); return widget; } KConfigSkeleton* JuliaBackend::config() const { return JuliaSettings::self(); } K_PLUGIN_FACTORY_WITH_JSON( juliabackend, "juliabackend.json", registerPlugin(); ) #include "juliabackend.moc" diff --git a/src/lib/backend.cpp b/src/lib/backend.cpp index 251f5269..04c997c2 100644 --- a/src/lib/backend.cpp +++ b/src/lib/backend.cpp @@ -1,206 +1,206 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2009 Alexander Rieder */ #include "backend.h" #include "extension.h" #include #include #include #include #include using namespace Cantor; class Cantor::BackendPrivate { public: QString name; QString comment; QString icon; QString url; bool enabled{true}; }; Backend::Backend(QObject* parent, const QList& args) : QObject(parent), d(new BackendPrivate) { Q_UNUSED(args) } Backend::~Backend() { delete d; } QString Backend::name() const { return d->name; } QString Backend::comment() const { return d->comment; } QString Backend::description() const { return comment(); } QString Backend::icon() const { return d->icon; } QString Backend::url() const { return d->url; } bool Backend::isEnabled() const { return d->enabled && requirementsFullfilled(); } void Backend::setEnabled(bool enabled) { d->enabled = enabled; } QStringList Backend::listAvailableBackends() { QStringList l; for (Backend* b : availableBackends()) { if(b->isEnabled()) l<name(); } return l; } QList Backend::availableBackends() { static QList backendCache; //if we already have all backends Cached, just return the cache. //otherwise create the available backends if(!backendCache.isEmpty()) { return backendCache; } QStringList pluginDirs; for (const QString& dir : QCoreApplication::libraryPaths()){ pluginDirs << dir + QDir::separator() + QLatin1String("cantor/backends"); } QPluginLoader loader; for (const QString &dir : pluginDirs){ qDebug() << "dir: " << dir; QStringList plugins; QDir pluginDir = QDir(dir); plugins = pluginDir.entryList(); for (const QString &plugin : plugins){ if (plugin==QLatin1String(".") || plugin==QLatin1String("..")) continue; loader.setFileName(dir + QDir::separator() + plugin); if (!loader.load()){ qDebug() << "Error while loading plugin: " << plugin; continue; } KPluginFactory* factory = KPluginLoader(loader.fileName()).factory(); Backend* backend = factory->create(QCoreApplication::instance()); KPluginMetaData info(loader); backend->d->name=info.name(); backend->d->comment=info.description(); backend->d->icon=info.iconName(); backend->d->url=info.website(); backendCache<name().toLower()==name.toLower() || b->id().toLower()==name.toLower()) return b; } return nullptr; } QStringList Backend::extensions() const { QList extensions = findChildren(QRegularExpression(QLatin1String(".*Extension"))); QStringList names; for (Extension* e : extensions) names << e->objectName(); return names; } Extension* Backend::extension(const QString& name) const { return findChild(name); } bool Backend::checkExecutable(const QString& name, const QString& path, QString* reason) { if (path.isEmpty()) { if (reason) *reason = i18n("No path for the %1 executable specified. " "Please provide the correct path in the application settings and try again.", name); return false; } QFileInfo info(path); if (!info.exists()) { if (reason) *reason = i18n("The specified file '%1' for the %2 executable doesn't exist. " "Please provide the correct path in the application settings and try again.", path, name); return false; } if (!info.isExecutable()) { if (reason) - *reason = i18n("The specified file '%1' doesn't point to an executable." + *reason = i18n("The specified file '%1' doesn't point to an executable. " "Please provide the correct path in the application settings and try again.", path, name); return false; } return true; }