File indexing completed on 2024-05-12 16:16:10

0001 /*
0002   SPDX-FileCopyrightText: 2022-2023 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "translatorengineloader.h"
0008 #include "texttranslator_debug.h"
0009 #include "translatorengineclient.h"
0010 #include <QCoreApplication>
0011 #include <QDir>
0012 #include <QPluginLoader>
0013 using namespace TextTranslator;
0014 class TextTranslator::TranslatorEngineLoaderPrivate
0015 {
0016 public:
0017     QSet<QString> loadedPlugins;
0018     QHash<QString, TranslatorEngineClient *> translatorClients;
0019 };
0020 
0021 TranslatorEngineLoader *TranslatorEngineLoader::self()
0022 {
0023     static TranslatorEngineLoader s_self;
0024     return &s_self;
0025 }
0026 
0027 TranslatorEngineLoader::TranslatorEngineLoader(QObject *parent)
0028     : QObject{parent}
0029     , d(new TextTranslator::TranslatorEngineLoaderPrivate)
0030 {
0031     loadPlugins();
0032 }
0033 
0034 TranslatorEngineLoader::~TranslatorEngineLoader() = default;
0035 
0036 void TranslatorEngineLoader::loadPlugins()
0037 {
0038     const QStringList libPaths = QCoreApplication::libraryPaths();
0039     const QString pathSuffix(QStringLiteral("/kf" QT_STRINGIFY(QT_VERSION_MAJOR)) + QStringLiteral("/translator/"));
0040     for (const QString &libPath : libPaths) {
0041         QDir dir(libPath + pathSuffix);
0042         if (!dir.exists()) {
0043             continue;
0044         }
0045         for (const QString &fileName : dir.entryList(QDir::Files)) {
0046             loadPlugin(dir.absoluteFilePath(fileName));
0047         }
0048     }
0049     if (d->loadedPlugins.isEmpty()) {
0050         qCWarning(TEXTTRANSLATOR_LOG) << "No translator plugins available!";
0051     }
0052 }
0053 
0054 void TranslatorEngineLoader::loadPlugin(const QString &pluginPath)
0055 {
0056     QPluginLoader plugin(pluginPath);
0057     const QString pluginIID = plugin.metaData()[QStringLiteral("IID")].toString();
0058     if (!pluginIID.isEmpty()) {
0059         if (d->loadedPlugins.contains(pluginIID)) {
0060             qCDebug(TEXTTRANSLATOR_LOG) << "Skipping already loaded" << pluginPath;
0061             return;
0062         }
0063         d->loadedPlugins.insert(pluginIID);
0064     }
0065 
0066     if (!plugin.load()) { // We do this separately for better error handling
0067         qCDebug(TEXTTRANSLATOR_LOG) << "Unable to load plugin" << pluginPath << "Error:" << plugin.errorString();
0068         d->loadedPlugins.remove(pluginIID);
0069         return;
0070     }
0071     TranslatorEngineClient *client = qobject_cast<TranslatorEngineClient *>(plugin.instance());
0072     if (!client) {
0073         qCWarning(TEXTTRANSLATOR_LOG) << "Invalid plugin loaded" << pluginPath;
0074         plugin.unload(); // don't leave it in memory
0075         return;
0076     }
0077     d->translatorClients.insert(client->name(), client);
0078 }
0079 
0080 TranslatorEngineClient *TranslatorEngineLoader::createTranslatorClient(const QString &clientName)
0081 {
0082     auto clientsItr = d->translatorClients.constFind(clientName);
0083     if (clientsItr == d->translatorClients.constEnd()) {
0084         qCWarning(TEXTTRANSLATOR_LOG) << "Client name not found: " << clientName;
0085         Q_EMIT loadingTranslatorFailed();
0086         return nullptr;
0087     }
0088     return (*clientsItr);
0089 }
0090 
0091 QString TranslatorEngineLoader::currentPluginName(const QString &key) const
0092 {
0093     auto clientsItr = d->translatorClients.constFind(key);
0094     if (clientsItr != d->translatorClients.constEnd()) {
0095         return (*clientsItr)->translatedName();
0096     }
0097     return {};
0098 }
0099 
0100 QMap<QString, QString> TranslatorEngineLoader::translatorEngineInfos() const
0101 {
0102     QMap<QString, QString> map;
0103     QHashIterator<QString, TranslatorEngineClient *> i(d->translatorClients);
0104     while (i.hasNext()) {
0105         i.next();
0106         map.insert(i.key(), i.value()->translatedName());
0107     }
0108     return map;
0109 }
0110 
0111 QMap<TextTranslator::TranslatorUtil::Language, QString> TranslatorEngineLoader::supportedFromLanguages(const QString &clientName) const
0112 {
0113     QMap<TranslatorUtil::Language, QString> supportedLanguages;
0114     auto clientsItr = d->translatorClients.constFind(clientName);
0115     if (clientsItr == d->translatorClients.constEnd()) {
0116         qCWarning(TEXTTRANSLATOR_LOG) << "Client name not found: " << clientName;
0117         return supportedLanguages;
0118     }
0119     (*clientsItr)->updateListLanguages();
0120     supportedLanguages = (*clientsItr)->supportedFromLanguages();
0121     return supportedLanguages;
0122 }
0123 
0124 QMap<TextTranslator::TranslatorUtil::Language, QString> TranslatorEngineLoader::supportedToLanguages(const QString &clientName) const
0125 {
0126     QMap<TranslatorUtil::Language, QString> supportedLanguages;
0127     auto clientsItr = d->translatorClients.constFind(clientName);
0128     if (clientsItr == d->translatorClients.constEnd()) {
0129         qCWarning(TEXTTRANSLATOR_LOG) << "Client name not found: " << clientName;
0130         return supportedLanguages;
0131     }
0132     (*clientsItr)->updateListLanguages();
0133     supportedLanguages = (*clientsItr)->supportedToLanguages();
0134     return supportedLanguages;
0135 }
0136 
0137 bool TranslatorEngineLoader::hasConfigurationDialog(const QString &clientName) const
0138 {
0139     auto clientsItr = d->translatorClients.constFind(clientName);
0140     if (clientsItr == d->translatorClients.constEnd()) {
0141         qCWarning(TEXTTRANSLATOR_LOG) << "Client name not found: " << clientName;
0142         return false;
0143     }
0144     return (*clientsItr)->hasConfigurationDialog();
0145 }
0146 
0147 bool TranslatorEngineLoader::showConfigureDialog(const QString &clientName, QWidget *parentWidget)
0148 {
0149     auto clientsItr = d->translatorClients.constFind(clientName);
0150     if (clientsItr == d->translatorClients.constEnd()) {
0151         qCWarning(TEXTTRANSLATOR_LOG) << "Client name not found: " << clientName;
0152         return false;
0153     }
0154     return (*clientsItr)->showConfigureDialog(parentWidget);
0155 }
0156 
0157 QString TranslatorEngineLoader::fallbackFirstEngine() const
0158 {
0159     if (!d->translatorClients.isEmpty()) {
0160         return *d->translatorClients.keyBegin();
0161     }
0162     qCWarning(TEXTTRANSLATOR_LOG) << "No plugin found ! ";
0163     return QString();
0164 }
0165 
0166 #include "moc_translatorengineloader.cpp"