File indexing completed on 2023-05-30 10:40:15
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com> 0004 */ 0005 0006 #include <vector> 0007 0008 #include "backend.h" 0009 #include "extension.h" 0010 0011 #include <QCoreApplication> 0012 #include <QDir> 0013 #include <QPluginLoader> 0014 #include <QProcess> 0015 #include <QRegularExpression> 0016 #include <QStandardPaths> 0017 #include <QUrl> 0018 0019 #include <KPluginFactory> 0020 #include <KPluginMetaData> 0021 #include <KPluginFactory> 0022 #include <KLocalizedString> 0023 0024 using namespace Cantor; 0025 0026 class Cantor::BackendPrivate 0027 { 0028 public: 0029 QString name; 0030 QString comment; 0031 QString icon; 0032 QString url; 0033 bool enabled{true}; 0034 QList<GraphicPackage> supportedGraphicPackagesCache; 0035 }; 0036 0037 Backend::Backend(QObject* parent, const QList<QVariant>& args) : QObject(parent), 0038 d(new BackendPrivate) 0039 { 0040 Q_UNUSED(args) 0041 } 0042 0043 Backend::~Backend() 0044 { 0045 delete d; 0046 } 0047 0048 QString Backend::name() const 0049 { 0050 return d->name; 0051 } 0052 0053 QString Backend::comment() const 0054 { 0055 return d->comment; 0056 } 0057 0058 QString Backend::description() const 0059 { 0060 return comment(); 0061 } 0062 0063 QString Backend::icon() const 0064 { 0065 return d->icon; 0066 } 0067 0068 QString Backend::url() const 0069 { 0070 return d->url; 0071 } 0072 0073 QString Backend::defaultHelp() const 0074 { 0075 return QString(); 0076 } 0077 0078 bool Backend::isEnabled() const 0079 { 0080 return d->enabled && requirementsFullfilled(); 0081 } 0082 0083 void Backend::setEnabled(bool enabled) 0084 { 0085 d->enabled = enabled; 0086 } 0087 0088 QStringList Backend::listAvailableBackends() 0089 { 0090 QStringList l; 0091 for (Backend* b : availableBackends()) 0092 { 0093 if(b->isEnabled()) 0094 l<<b->name(); 0095 } 0096 0097 return l; 0098 } 0099 0100 QList<Backend*> Backend::availableBackends() 0101 { 0102 static QList<Backend*> backendCache; 0103 //if we already have all backends Cached, just return the cache. 0104 //otherwise create the available backends 0105 if(!backendCache.isEmpty()) 0106 { 0107 return backendCache; 0108 } 0109 0110 const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("cantor/backends")); 0111 0112 for (const KPluginMetaData &plugin : plugins) { 0113 0114 const auto result = KPluginFactory::instantiatePlugin<Backend>(plugin, QCoreApplication::instance()); 0115 0116 if (!result) { 0117 qDebug() << "Error while loading backend: " << result.errorText; 0118 continue; 0119 } 0120 0121 Backend *backend = result.plugin; 0122 0123 backend->d->name = plugin.name(); 0124 backend->d->comment = plugin.description(); 0125 backend->d->icon = plugin.iconName(); 0126 backend->d->url = plugin.website(); 0127 backendCache << backend; 0128 } 0129 0130 return backendCache; 0131 } 0132 0133 Backend* Backend::getBackend(const QString& name) 0134 { 0135 for (Backend* b : availableBackends()) 0136 { 0137 if(b->name().toLower()==name.toLower() || b->id().toLower()==name.toLower()) 0138 return b; 0139 } 0140 0141 return nullptr; 0142 } 0143 0144 QStringList Backend::extensions() const 0145 { 0146 QList<Extension*> extensions = findChildren<Extension*>(QRegularExpression(QLatin1String(".*Extension"))); 0147 QStringList names; 0148 for (Extension* e : extensions) 0149 names << e->objectName(); 0150 return names; 0151 } 0152 0153 Extension* Backend::extension(const QString& name) const 0154 { 0155 return findChild<Extension*>(name); 0156 } 0157 0158 bool Backend::checkExecutable(const QString& name, const QString& path, QString* reason) 0159 { 0160 if (path.isEmpty()) 0161 { 0162 if (reason) 0163 *reason = i18n("No path for the %1 executable specified. " 0164 "Please provide the correct path in the application settings and try again.", 0165 name); 0166 return false; 0167 } 0168 0169 QFileInfo info(path); 0170 if (!info.exists()) 0171 { 0172 if (reason) 0173 *reason = i18n("The specified file '%1' for the %2 executable doesn't exist. " 0174 "Please provide the correct path in the application settings and try again.", 0175 path, name); 0176 return false; 0177 } 0178 0179 if (!info.isExecutable()) 0180 { 0181 if (reason) 0182 *reason = i18n("The specified file '%1' doesn't point to an executable. " 0183 "Please provide the correct path in the application settings and try again.", 0184 path); 0185 return false; 0186 } 0187 0188 return true; 0189 } 0190 0191 bool Cantor::Backend::testProgramWritable(const QString& program, const QStringList& args, const QString& filename, const QString& expectedContent, QString* reason, int timeOut) 0192 { 0193 QProcess process; 0194 process.setProgram(program); 0195 process.setArguments(args); 0196 process.start(); 0197 0198 if (process.waitForFinished(timeOut) == false) 0199 { 0200 if (reason) 0201 *reason = i18n("The program %1 didn't finish the execution after %2 milliseconds during the plot integration test.", QFileInfo(program).fileName(), timeOut); 0202 0203 return false; 0204 } 0205 0206 QFile file(filename); 0207 if (!file.open(QIODevice::ReadOnly)) 0208 { 0209 if (reason) 0210 *reason = i18n("Failed to open the file %1 during the plot integration test.", filename); 0211 return false; 0212 } 0213 0214 QString fileContent = QString::fromLocal8Bit(file.readAll()); 0215 if (fileContent.trimmed() != expectedContent) 0216 { 0217 if (reason) 0218 *reason = i18n("Failed to parse the result during the plot integration test."); 0219 return false; 0220 } 0221 0222 file.close(); 0223 file.remove(); 0224 0225 return true; 0226 } 0227 0228 QList<GraphicPackage> Backend::availableGraphicPackages() const 0229 { 0230 if (d->supportedGraphicPackagesCache.size() != 0) 0231 return d->supportedGraphicPackagesCache; 0232 0233 if (!(capabilities() & Capability::IntegratedPlots)) 0234 return QList<GraphicPackage>(); // because this cache is empty 0235 0236 QString packagesFile = id() + QLatin1String("/graphic_packages.xml"); 0237 QString filename = QStandardPaths::locate(QStandardPaths::AppDataLocation, packagesFile, QStandardPaths::LocateFile); 0238 0239 if (filename.isEmpty()) 0240 filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("cantor/") + packagesFile, QStandardPaths::LocateFile); 0241 0242 if (filename.isEmpty()) 0243 return QList<GraphicPackage>(); 0244 0245 d->supportedGraphicPackagesCache = GraphicPackage::loadFromFile(filename); 0246 0247 return d->supportedGraphicPackagesCache; 0248 }