KTextAddons

voskenginelanguagewidget.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 "voskenginelanguagewidget.h"
8#include "libvoskspeechtotext_debug.h"
9#include "voskspeechtotextmodel.h"
10#include "voskspeechtotextproxymodel.h"
11
12#include <KLocalizedString>
13#include <KMessageBox>
14#include <QLabel>
15#include <QLineEdit>
16#include <QProgressBar>
17#include <QPushButton>
18#include <QTreeView>
19#include <QVBoxLayout>
20
21#include <KLineEditEventHandler>
22
23VoskEngineLanguageWidget::VoskEngineLanguageWidget(QWidget *parent)
24 : QWidget{parent}
25 , mTreeView(new QTreeView(this))
26 , mSearchLineEdit(new QLineEdit(this))
27 , mVoskSpeechToTextModel(new VoskSpeechToTextModel(this))
28 , mVoskSpeechToTextProxyModel(new VoskSpeechToTextProxyModel(this))
29 , mProgressBar(new QProgressBar(this))
30 , mProgressBarLabel(new QLabel(this))
31 , mProgressBarWidget(new QWidget(this))
32{
33 auto mainLayout = new QVBoxLayout(this);
34 mainLayout->setObjectName(QStringLiteral("mainLayout"));
35 mainLayout->setContentsMargins({});
36
37 auto hboxLayout = new QHBoxLayout;
38 hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
39 hboxLayout->setContentsMargins({});
40 mainLayout->addLayout(hboxLayout);
41
42 auto vboxLayout = new QVBoxLayout;
43 vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
44 vboxLayout->setContentsMargins({});
45
46 mSearchLineEdit->setObjectName(QStringLiteral("mSearchLineEdit"));
47 vboxLayout->addWidget(mSearchLineEdit);
48 mSearchLineEdit->setPlaceholderText(i18nc("@info:placeholder", "Search…"));
49 mSearchLineEdit->setClearButtonEnabled(true);
50
52
53 mTreeView->setObjectName(QStringLiteral("mTreeView"));
54 connect(ManagerModelVoskSpeechToText::self(), &ManagerModelVoskSpeechToText::errorText, this, &VoskEngineLanguageWidget::slotError);
55 connect(ManagerModelVoskSpeechToText::self(), &ManagerModelVoskSpeechToText::progress, this, &VoskEngineLanguageWidget::slotProgressInfo);
56 connect(ManagerModelVoskSpeechToText::self(),
57 &ManagerModelVoskSpeechToText::extractDone,
58 mVoskSpeechToTextModel,
59 &VoskSpeechToTextModel::updateInstalledLanguage);
60 connect(ManagerModelVoskSpeechToText::self(), &ManagerModelVoskSpeechToText::downLoadModelListDone, this, &VoskEngineLanguageWidget::updateListModel);
61
62 // TODO store list on local.
63 if (ManagerModelVoskSpeechToText::self()->needDownloadModelList()) {
64 ManagerModelVoskSpeechToText::self()->downloadListModels();
65 } else {
66 mVoskSpeechToTextModel->setSpeechToTextInfos(ManagerModelVoskSpeechToText::self()->speechToTextInfos());
67 }
68
69 mVoskSpeechToTextProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
70 mVoskSpeechToTextProxyModel->setSourceModel(mVoskSpeechToTextModel);
71 mTreeView->setModel(mVoskSpeechToTextProxyModel);
72 mTreeView->setRootIsDecorated(false);
73 mTreeView->setSortingEnabled(true);
74 vboxLayout->addWidget(mTreeView);
75
76 hboxLayout->addLayout(vboxLayout);
77
78 auto buttonLayout = new QVBoxLayout;
79 buttonLayout->setObjectName(QStringLiteral("buttonLayout"));
80 hboxLayout->addLayout(buttonLayout);
81
82 auto downLoadLanguage = new QPushButton(QIcon::fromTheme(QStringLiteral("download-symbolic")), i18n("Download"), this);
83 downLoadLanguage->setObjectName(QStringLiteral("downLoadLanguage"));
84 buttonLayout->addWidget(downLoadLanguage);
85 connect(downLoadLanguage, &QPushButton::clicked, this, [this]() {
86 const auto currentlySelectedIndex = mVoskSpeechToTextProxyModel->mapToSource(mTreeView->selectionModel()->currentIndex());
87 const QModelIndex modelIndex = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::Url);
88 const QModelIndex modelIndexCheckSum = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::CheckSum);
89 const QModelIndex modelIndexName = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::Name);
90 const QModelIndex modelIndexVersion = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::AvailableVersion);
91
92 const QString url = modelIndex.data().toString();
93 const QString checkSum = modelIndexCheckSum.data().toString();
94 qCDebug(LIBVOSKSPEECHTOTEXT_LOG) << " url " << url << " checksum " << checkSum;
95 VoskDownloadLanguageJob::DownloadLanguageInfo info;
96 info.checksum = modelIndexCheckSum.data().toString();
97 info.url = QUrl(modelIndex.data().toString());
98 info.name = modelIndexName.data().toString();
99 info.version = modelIndexVersion.data().toString();
100 slotDownLoad(info);
101 });
102
103 auto deleteLanguage = new QPushButton(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete"), this);
104 deleteLanguage->setObjectName(QStringLiteral("downLoadLanguage"));
105 buttonLayout->addWidget(deleteLanguage);
106
107 auto updateListLanguage = new QPushButton(i18nc("@action:button", "Update List"), this);
108 updateListLanguage->setToolTip(i18nc("@info:tooltip", "Update list of languages from network"));
109 updateListLanguage->setObjectName(QStringLiteral("updateListLanguage"));
110 buttonLayout->addWidget(updateListLanguage);
111 buttonLayout->addStretch(1); // spacer
112 connect(updateListLanguage, &QPushButton::clicked, this, &VoskEngineLanguageWidget::slotUpdateListLanguage);
113
114 connect(mSearchLineEdit, &QLineEdit::textChanged, this, &VoskEngineLanguageWidget::slotTextChanged);
115
116 auto progressBarLayout = new QHBoxLayout;
117 progressBarLayout->setObjectName(QStringLiteral("progressBarLayout"));
118
119 mProgressBarLabel->setObjectName(QStringLiteral("mProgressBarLabel"));
120 progressBarLayout->addWidget(mProgressBarLabel);
121
122 mProgressBar->setObjectName(QStringLiteral("mProgressBar"));
123 progressBarLayout->addWidget(mProgressBar);
124
125 mProgressBarWidget->setObjectName(QStringLiteral("mProgressBarWidget"));
126 mProgressBarWidget->setLayout(progressBarLayout);
127
128 mainLayout->addWidget(mProgressBarWidget);
129 mProgressBarWidget->setVisible(false);
130
131 mTreeView->setColumnHidden(VoskSpeechToTextModel::Url, true);
132 mTreeView->setColumnHidden(VoskSpeechToTextModel::CheckSum, true);
133 mTreeView->setColumnHidden(VoskSpeechToTextModel::Identifier, true);
134 mTreeView->setColumnHidden(VoskSpeechToTextModel::NeedToUpdateLanguage, true);
135 mTreeView->setColumnHidden(VoskSpeechToTextModel::Name, true);
136 mTreeView->setColumnHidden(VoskSpeechToTextModel::SizeByte, true);
137 auto updateButton = [this, downLoadLanguage, deleteLanguage]() {
138 const bool hasSelectedItem = mTreeView->currentIndex().isValid();
139 const auto currentlySelectedIndex = mVoskSpeechToTextProxyModel->mapToSource(mTreeView->selectionModel()->currentIndex());
140 const QModelIndex modelIndex = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::Installed);
141 const QModelIndex modelIndexNeedToUpdate = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::NeedToUpdateLanguage);
142 const bool isInstalled = modelIndex.data().toBool();
143 const bool needToUpdate = modelIndexNeedToUpdate.data().toBool();
144
145 if (needToUpdate) {
146 downLoadLanguage->setEnabled(hasSelectedItem && needToUpdate);
147 } else {
148 downLoadLanguage->setEnabled(hasSelectedItem && !isInstalled);
149 }
150 deleteLanguage->setEnabled(hasSelectedItem && isInstalled);
151 };
152
153 connect(deleteLanguage, &QPushButton::clicked, this, [this, updateButton]() {
154 const auto currentlySelectedIndex = mVoskSpeechToTextProxyModel->mapToSource(mTreeView->selectionModel()->currentIndex());
155 const QModelIndex modelIndex = mVoskSpeechToTextModel->index(currentlySelectedIndex.row(), VoskSpeechToTextModel::Name);
156 const QString identifier = modelIndex.data().toString();
157 slotDelete(identifier);
158 updateButton();
159 });
160
161 connect(mTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [updateButton]() {
162 updateButton();
163 });
164 downLoadLanguage->setEnabled(false);
165 deleteLanguage->setEnabled(false);
166}
167
168VoskEngineLanguageWidget::~VoskEngineLanguageWidget() = default;
169
170void VoskEngineLanguageWidget::slotProgressInfo(const ManagerModelVoskSpeechToText::ProgressInfo &info)
171{
172 if (info.bytesReceived != info.bytesTotal) {
173 mProgressBarWidget->setVisible(true);
174 } else {
175 mProgressBarWidget->setVisible(false);
176 }
177 mProgressBarLabel->setText(info.languageName);
178 mProgressBar->setRange(0, 100);
179 mProgressBar->setValue((info.bytesReceived * 100) / info.bytesTotal);
180}
181
182void VoskEngineLanguageWidget::slotError(const QString &str)
183{
184 KMessageBox::error(this, i18n("Error: %1", str), i18n("Vosk"));
185}
186
187void VoskEngineLanguageWidget::slotTextChanged(const QString &str)
188{
189 mVoskSpeechToTextProxyModel->setSearchString(str);
190}
191
192void VoskEngineLanguageWidget::slotDownLoad(const VoskDownloadLanguageJob::DownloadLanguageInfo &info)
193{
194 ManagerModelVoskSpeechToText::self()->downloadLanguage(info);
195}
196
197void VoskEngineLanguageWidget::slotDelete(const QString &name)
198{
199 mVoskSpeechToTextModel->removeLanguage(name);
200}
201
202void VoskEngineLanguageWidget::slotUpdateListLanguage()
203{
204 ManagerModelVoskSpeechToText::self()->downloadListModels();
205}
206
207void VoskEngineLanguageWidget::updateListModel()
208{
209 mVoskSpeechToTextModel->setSpeechToTextInfos(ManagerModelVoskSpeechToText::self()->speechToTextInfos());
210}
211
212#include "moc_voskenginelanguagewidget.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void catchReturnKey(QObject *lineEdit)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
void clicked(bool checked)
QIcon fromTheme(const QString &name)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void setText(const QString &)
void textChanged(const QString &text)
QVariant data(int role) const const
void setObjectName(QAnyStringView name)
void setRange(int minimum, int maximum)
void setValue(int value)
CaseInsensitive
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool toBool() const const
QString toString() const const
virtual void setVisible(bool visible)
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.