File indexing completed on 2024-12-22 04:28:23

0001 /*
0002   SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "voskspeechtotextmodel.h"
0008 #include "libvoskspeechtotext_debug.h"
0009 #include <KIO/Global>
0010 #include <KLocalizedString>
0011 #include <QColor>
0012 #include <QDir>
0013 
0014 VoskSpeechToTextModel::VoskSpeechToTextModel(QObject *parent)
0015     : QAbstractListModel{parent}
0016 {
0017     updateInstalledLanguage();
0018 }
0019 
0020 VoskSpeechToTextModel::~VoskSpeechToTextModel() = default;
0021 
0022 int VoskSpeechToTextModel::rowCount(const QModelIndex &parent) const
0023 {
0024     Q_UNUSED(parent);
0025     return mSpeechToTextInfos.count();
0026 }
0027 
0028 QVariant VoskSpeechToTextModel::headerData(int section, Qt::Orientation orientation, int role) const
0029 {
0030     if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
0031         switch (static_cast<VoskRoles>(section)) {
0032         case VoskRoles::Identifier:
0033         case VoskRoles::SizeByte:
0034         case VoskRoles::Url:
0035         case VoskRoles::Name:
0036         case VoskRoles::NeedToUpdateLanguage:
0037         case VoskRoles::CheckSum:
0038             return {};
0039         case VoskRoles::LangText:
0040             return i18n("Language");
0041         case VoskRoles::Installed:
0042             return i18n("Installed");
0043         case VoskRoles::InstalledVersion:
0044             return i18n("Installed Version");
0045         case VoskRoles::AvailableVersion:
0046             return i18n("Available Version");
0047         case VoskRoles::Size:
0048             return i18n("Size");
0049         }
0050     }
0051     return {};
0052 }
0053 
0054 QVariant VoskSpeechToTextModel::data(const QModelIndex &index, int role) const
0055 {
0056     if (index.row() < 0 || index.row() >= mSpeechToTextInfos.count()) {
0057         return {};
0058     }
0059     const auto speechToTextInfo = mSpeechToTextInfos.at(index.row());
0060     const int col = index.column();
0061     if (role == Qt::BackgroundRole) {
0062         if (needToUpdateLanguageModel(speechToTextInfo)) {
0063             if (static_cast<VoskRoles>(col) == VoskRoles::InstalledVersion) {
0064                 return QColor(Qt::red);
0065             }
0066         }
0067         return {};
0068     } else if (role == Qt::DisplayRole) {
0069         switch (static_cast<VoskRoles>(col)) {
0070         case VoskRoles::InstalledVersion: {
0071             const QString name{speechToTextInfo.name()};
0072             if (isInstalled(name)) {
0073                 return versionInstalled(name);
0074             }
0075             return {};
0076         }
0077         case VoskRoles::AvailableVersion: {
0078             return speechToTextInfo.version();
0079         }
0080         case VoskRoles::NeedToUpdateLanguage: {
0081             return needToUpdateLanguageModel(speechToTextInfo);
0082         }
0083         case VoskRoles::Installed: {
0084             if (isInstalled(speechToTextInfo.name())) {
0085                 return i18n("Installed");
0086             }
0087             return {};
0088         }
0089         case VoskRoles::Identifier: {
0090             return speechToTextInfo.identifier();
0091         }
0092         case VoskRoles::LangText: {
0093             return speechToTextInfo.langText();
0094         }
0095         case VoskRoles::Size: {
0096             return KIO::convertSize(speechToTextInfo.size());
0097         }
0098         case VoskRoles::SizeByte: {
0099             return speechToTextInfo.size();
0100         }
0101         case VoskRoles::Url: {
0102             return speechToTextInfo.url();
0103         }
0104         case VoskRoles::CheckSum: {
0105             return speechToTextInfo.md5();
0106         }
0107         case VoskRoles::Name: {
0108             return speechToTextInfo.name();
0109         }
0110         }
0111     }
0112     return {};
0113 }
0114 
0115 bool VoskSpeechToTextModel::needToUpdateLanguageModel(const VoskSpeechToTextInfo &language) const
0116 {
0117     const QString shortName{language.identifier()};
0118     if (isInstalled(shortName)) {
0119         if (versionInstalled(shortName) != language.version()) {
0120             return true;
0121         }
0122     }
0123     return false;
0124 }
0125 
0126 void VoskSpeechToTextModel::clear()
0127 {
0128     if (rowCount() != 0) {
0129         beginResetModel();
0130         mSpeechToTextInfos.clear();
0131         endResetModel();
0132     }
0133     updateInstalledLanguage();
0134 }
0135 
0136 void VoskSpeechToTextModel::updateInstalledLanguage()
0137 {
0138     mLanguageInstalled = VoskEngineUtils::languageLocallyStored();
0139     qCDebug(LIBVOSKSPEECHTOTEXT_LOG) << "mLanguageInstalled " << mLanguageInstalled;
0140 }
0141 
0142 void VoskSpeechToTextModel::removeLanguage(const QString &name)
0143 {
0144     auto index = std::find_if(mLanguageInstalled.begin(), mLanguageInstalled.end(), [name](const VoskEngineUtils::LanguageInstalled &installed) {
0145         return (name == installed.name);
0146     });
0147     if (index != mLanguageInstalled.end()) {
0148         const QString absoluteLanguageModelPath = (*index).absoluteLanguageModelPath;
0149         if (!QDir(absoluteLanguageModelPath).removeRecursively()) {
0150             qCDebug(LIBVOSKSPEECHTOTEXT_LOG) << "Impossible to delete " << absoluteLanguageModelPath;
0151             return;
0152         }
0153         mLanguageInstalled.removeAll(*index);
0154         beginResetModel();
0155         endResetModel();
0156     }
0157     updateInstalledLanguage();
0158 }
0159 
0160 QVector<VoskSpeechToTextInfo> VoskSpeechToTextModel::speechToTextInfos() const
0161 {
0162     return mSpeechToTextInfos;
0163 }
0164 
0165 void VoskSpeechToTextModel::setSpeechToTextInfos(const QVector<VoskSpeechToTextInfo> &newSpeechToTextInfo)
0166 {
0167     if (rowCount() != 0) {
0168         beginResetModel();
0169         mSpeechToTextInfos.clear();
0170         endResetModel();
0171     }
0172     if (!newSpeechToTextInfo.isEmpty()) {
0173         beginInsertRows(QModelIndex(), 0, newSpeechToTextInfo.count() - 1);
0174         mSpeechToTextInfos = newSpeechToTextInfo;
0175         endInsertRows();
0176     }
0177     updateInstalledLanguage();
0178 }
0179 
0180 int VoskSpeechToTextModel::columnCount(const QModelIndex &parent) const
0181 {
0182     Q_UNUSED(parent)
0183     return static_cast<int>(VoskRoles::LastColumn) + 1;
0184 }
0185 
0186 bool VoskSpeechToTextModel::isInstalled(const QString &name) const
0187 {
0188     for (const auto &lang : std::as_const(mLanguageInstalled)) {
0189         if (lang.name == name) {
0190             return true;
0191         }
0192     }
0193     return false;
0194 }
0195 
0196 QString VoskSpeechToTextModel::versionInstalled(const QString &shortName) const
0197 {
0198     for (const auto &lang : std::as_const(mLanguageInstalled)) {
0199         if (lang.name == shortName) {
0200             return lang.versionStr;
0201         }
0202     }
0203     return {};
0204 }
0205 
0206 #include "moc_voskspeechtotextmodel.cpp"