KTextAddons

speechtotextengineloader.cpp
1/*
2 SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "speechtotextengineloader.h"
8using namespace Qt::Literals::StringLiterals;
9
10#include "speechtotextclient.h"
11#include "textspeechtotext_debug.h"
12#include <QCoreApplication>
13#include <QDir>
14#include <QPluginLoader>
15using namespace TextSpeechToText;
16class TextSpeechToText::SpeechToTextEngineLoaderPrivate
17{
18public:
19 QSet<QString> loadedPlugins;
20 QHash<QString, SpeechToTextClient *> speechToTextClients;
21};
22
23SpeechToTextEngineLoader *SpeechToTextEngineLoader::self()
24{
25 static SpeechToTextEngineLoader s_self;
26 return &s_self;
27}
28
29SpeechToTextEngineLoader::SpeechToTextEngineLoader(QObject *parent)
30 : QObject{parent}
31 , d(new TextSpeechToText::SpeechToTextEngineLoaderPrivate)
32{
33 loadPlugins();
34}
35
36SpeechToTextEngineLoader::~SpeechToTextEngineLoader() = default;
37
38void SpeechToTextEngineLoader::loadPlugins()
39{
41 const QString pathSuffix(QStringLiteral("/kf6/speechtotext/"));
42 for (const QString &libPath : libPaths) {
43 const QDir dir(libPath + pathSuffix);
44 if (!dir.exists()) {
45 continue;
46 }
47 for (const QString &fileName : dir.entryList(QDir::Files)) {
48 loadPlugin(dir.absoluteFilePath(fileName));
49 }
50 }
51 if (d->loadedPlugins.isEmpty()) {
52 qCWarning(TEXTSPEECHTOTEXT_LOG) << "No speechtotext plugins available!";
53 Q_EMIT noPluginsFound();
54 }
55}
56
57void SpeechToTextEngineLoader::loadPlugin(const QString &pluginPath)
58{
59 QPluginLoader plugin(pluginPath);
60 const QString pluginIID = plugin.metaData()["IID"_L1].toString();
61 if (!pluginIID.isEmpty()) {
62 if (d->loadedPlugins.contains(pluginIID)) {
63 qCDebug(TEXTSPEECHTOTEXT_LOG) << "Skipping already loaded" << pluginPath;
64 return;
65 }
66 d->loadedPlugins.insert(pluginIID);
67 }
68
69 if (!plugin.load()) { // We do this separately for better error handling
70 qCDebug(TEXTSPEECHTOTEXT_LOG) << "Unable to load plugin" << pluginPath << "Error:" << plugin.errorString();
71 d->loadedPlugins.remove(pluginIID);
72 return;
73 }
74 SpeechToTextClient *client = qobject_cast<SpeechToTextClient *>(plugin.instance());
75 if (!client) {
76 qCWarning(TEXTSPEECHTOTEXT_LOG) << "Invalid plugin loaded" << pluginPath;
77 plugin.unload(); // don't leave it in memory
78 return;
79 }
80 d->speechToTextClients.insert(client->name(), client);
81}
82
83SpeechToTextClient *SpeechToTextEngineLoader::createSpeechToTextClient(const QString &clientName)
84{
85 auto clientsItr = d->speechToTextClients.constFind(clientName);
86 if (clientsItr == d->speechToTextClients.constEnd()) {
87 qCWarning(TEXTSPEECHTOTEXT_LOG) << "Client name not found: " << clientName;
88 Q_EMIT loadingSpeechToTextFailed();
89 return nullptr;
90 }
91 return (*clientsItr);
92}
93
94bool SpeechToTextEngineLoader::hasConfigurationDialog(const QString &clientName) const
95{
96 auto clientsItr = d->speechToTextClients.constFind(clientName);
97 if (clientsItr == d->speechToTextClients.constEnd()) {
98 qCWarning(TEXTSPEECHTOTEXT_LOG) << "Client name not found: " << clientName;
99 return false;
100 }
101 return (*clientsItr)->hasConfigurationDialog();
102}
103
104bool SpeechToTextEngineLoader::showConfigureDialog(const QString &clientName, QWidget *parentWidget)
105{
106 auto clientsItr = d->speechToTextClients.constFind(clientName);
107 if (clientsItr == d->speechToTextClients.constEnd()) {
108 qCWarning(TEXTSPEECHTOTEXT_LOG) << "Client name not found: " << clientName;
109 return false;
110 }
111 return (*clientsItr)->showConfigureDialog(parentWidget);
112}
113
114QMap<QString, QString> SpeechToTextEngineLoader::speechToTextEngineInfos() const
115{
117 QHashIterator<QString, SpeechToTextClient *> i(d->speechToTextClients);
118 while (i.hasNext()) {
119 i.next();
120 map.insert(i.key(), i.value()->translatedName());
121 }
122 return map;
123}
124
125QString SpeechToTextEngineLoader::fallbackFirstEngine() const
126{
127 if (!d->speechToTextClients.isEmpty()) {
128 return *d->speechToTextClients.keyBegin();
129 }
130 qCWarning(TEXTSPEECHTOTEXT_LOG) << "No plugin found ! ";
131 return QString();
132}
133
134bool SpeechToTextEngineLoader::hasEngine() const
135{
136 return !d->speechToTextClients.isEmpty();
137}
138
139#include "moc_speechtotextengineloader.cpp"
The SpeechToTextClient class.
virtual QString name() const =0
KIOCORE_EXPORT QString dir(const QString &fileClass)
QStringList libraryPaths()
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
bool isEmpty() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:29:59 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.