KTextAddons

voskspeechtotextmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2023-2025 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "voskspeechtotextmodel.h"
8#include "libvoskspeechtotext_debug.h"
9#include <KFormat>
10#include <KLocalizedString>
11#include <QColor>
12#include <QDir>
13
14VoskSpeechToTextModel::VoskSpeechToTextModel(QObject *parent)
15 : QAbstractListModel{parent}
16{
17 updateInstalledLanguage();
18}
19
20VoskSpeechToTextModel::~VoskSpeechToTextModel() = default;
21
22int VoskSpeechToTextModel::rowCount(const QModelIndex &parent) const
23{
24 if (parent.isValid()) // flat model
25 return 0;
26 return mSpeechToTextInfos.count();
27}
28
29QVariant VoskSpeechToTextModel::headerData(int section, Qt::Orientation orientation, int role) const
30{
31 if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
32 switch (static_cast<VoskRoles>(section)) {
33 case VoskRoles::Identifier:
34 case VoskRoles::SizeByte:
35 case VoskRoles::Url:
36 case VoskRoles::Name:
37 case VoskRoles::NeedToUpdateLanguage:
38 case VoskRoles::CheckSum:
39 return {};
40 case VoskRoles::LangText:
41 return i18n("Language");
42 case VoskRoles::Installed:
43 return i18n("Installed");
44 case VoskRoles::InstalledVersion:
45 return i18n("Installed Version");
46 case VoskRoles::AvailableVersion:
47 return i18n("Available Version");
48 case VoskRoles::Size:
49 return i18n("Size");
50 }
51 }
52 return {};
53}
54
55QVariant VoskSpeechToTextModel::data(const QModelIndex &index, int role) const
56{
57 if (index.row() < 0 || index.row() >= mSpeechToTextInfos.count()) {
58 return {};
59 }
60 const auto speechToTextInfo = mSpeechToTextInfos.at(index.row());
61 const int col = index.column();
62 if (role == Qt::BackgroundRole) {
63 if (needToUpdateLanguageModel(speechToTextInfo)) {
64 if (static_cast<VoskRoles>(col) == VoskRoles::InstalledVersion) {
65 return QColor(Qt::red);
66 }
67 }
68 return {};
69 } else if (role == Qt::DisplayRole) {
70 switch (static_cast<VoskRoles>(col)) {
71 case VoskRoles::InstalledVersion: {
72 const QString name{speechToTextInfo.name()};
73 if (isInstalled(name)) {
74 return versionInstalled(name);
75 }
76 return {};
77 }
78 case VoskRoles::AvailableVersion: {
79 return speechToTextInfo.version();
80 }
81 case VoskRoles::NeedToUpdateLanguage: {
82 return needToUpdateLanguageModel(speechToTextInfo);
83 }
84 case VoskRoles::Installed: {
85 if (isInstalled(speechToTextInfo.name())) {
86 return i18n("Installed");
87 }
88 return {};
89 }
90 case VoskRoles::Identifier: {
91 return speechToTextInfo.identifier();
92 }
93 case VoskRoles::LangText: {
94 return speechToTextInfo.langText();
95 }
96 case VoskRoles::Size: {
97 KFormat format;
98 return format.formatByteSize(speechToTextInfo.size());
99 }
100 case VoskRoles::SizeByte: {
101 return speechToTextInfo.size();
102 }
103 case VoskRoles::Url: {
104 return speechToTextInfo.url();
105 }
106 case VoskRoles::CheckSum: {
107 return speechToTextInfo.md5();
108 }
109 case VoskRoles::Name: {
110 return speechToTextInfo.name();
111 }
112 }
113 }
114 return {};
115}
116
117bool VoskSpeechToTextModel::needToUpdateLanguageModel(const VoskSpeechToTextInfo &language) const
118{
119 const QString shortName{language.identifier()};
120 if (isInstalled(shortName)) {
121 if (versionInstalled(shortName) != language.version()) {
122 return true;
123 }
124 }
125 return false;
126}
127
128void VoskSpeechToTextModel::clear()
129{
130 if (rowCount() != 0) {
132 mSpeechToTextInfos.clear();
134 }
135 updateInstalledLanguage();
136}
137
138void VoskSpeechToTextModel::updateInstalledLanguage()
139{
140 mLanguageInstalled = VoskEngineUtils::languageLocallyStored();
141 qCDebug(LIBVOSKSPEECHTOTEXT_LOG) << "mLanguageInstalled " << mLanguageInstalled;
142}
143
144void VoskSpeechToTextModel::removeLanguage(const QString &name)
145{
146 auto index = std::find_if(mLanguageInstalled.begin(), mLanguageInstalled.end(), [name](const VoskEngineUtils::LanguageInstalled &installed) {
147 return (name == installed.name);
148 });
149 if (index != mLanguageInstalled.end()) {
150 const QString absoluteLanguageModelPath = (*index).absoluteLanguageModelPath;
151 if (!QDir(absoluteLanguageModelPath).removeRecursively()) {
152 qCDebug(LIBVOSKSPEECHTOTEXT_LOG) << "Impossible to delete " << absoluteLanguageModelPath;
153 return;
154 }
155 mLanguageInstalled.removeAll(*index);
158 }
159 updateInstalledLanguage();
160}
161
162QVector<VoskSpeechToTextInfo> VoskSpeechToTextModel::speechToTextInfos() const
163{
164 return mSpeechToTextInfos;
165}
166
167void VoskSpeechToTextModel::setSpeechToTextInfos(const QVector<VoskSpeechToTextInfo> &newSpeechToTextInfo)
168{
169 if (rowCount() != 0) {
171 mSpeechToTextInfos.clear();
173 }
174 if (!newSpeechToTextInfo.isEmpty()) {
175 beginInsertRows(QModelIndex(), 0, newSpeechToTextInfo.count() - 1);
176 mSpeechToTextInfos = newSpeechToTextInfo;
178 }
179 updateInstalledLanguage();
180}
181
182int VoskSpeechToTextModel::columnCount(const QModelIndex &parent) const
183{
184 Q_UNUSED(parent)
185 return static_cast<int>(VoskRoles::LastColumn) + 1;
186}
187
188bool VoskSpeechToTextModel::isInstalled(const QString &name) const
189{
190 for (const auto &lang : std::as_const(mLanguageInstalled)) {
191 if (lang.name == name) {
192 return true;
193 }
194 }
195 return false;
196}
197
198QString VoskSpeechToTextModel::versionInstalled(const QString &shortName) const
199{
200 for (const auto &lang : std::as_const(mLanguageInstalled)) {
201 if (lang.name == shortName) {
202 return lang.versionStr;
203 }
204 }
205 return {};
206}
207
208#include "moc_voskspeechtotextmodel.cpp"
QString formatByteSize(double size, int precision=1, KFormat::BinaryUnitDialect dialect=KFormat::DefaultBinaryDialect, KFormat::BinarySizeUnits units=KFormat::DefaultBinaryUnits) const
QString i18n(const char *text, const TYPE &arg...)
QString name(const QVariant &location)
void beginInsertRows(const QModelIndex &parent, int first, int last)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QModelIndex parent(const QModelIndex &index) const const=0
qsizetype count() const const
bool isEmpty() const const
DisplayRole
Orientation
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:48:40 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.