diff --git a/conf/okular.kcfg b/conf/okular.kcfg index 66d667571..172e4780f 100644 --- a/conf/okular.kcfg +++ b/conf/okular.kcfg @@ -207,6 +207,9 @@ speechd + + + true diff --git a/part/dlgaccessibility.cpp b/part/dlgaccessibility.cpp index 46ab63209..67b70dcc5 100644 --- a/part/dlgaccessibility.cpp +++ b/part/dlgaccessibility.cpp @@ -147,19 +147,42 @@ DlgAccessibility::DlgAccessibility(QWidget *parent) layout->addRow(new QLabel(this)); // BEGIN Text-to-speech section - QComboBox *ttsEngine = new QComboBox(this); + m_ttsEngineBox = new QComboBox(this); // Populate tts engines and use their names directly as key and item text: const QStringList engines = QTextToSpeech::availableEngines(); for (const QString &engine : engines) { - ttsEngine->addItem(engine); + m_ttsEngineBox->addItem(engine); } - ttsEngine->setProperty("kcfg_property", QByteArray("currentText")); - ttsEngine->setObjectName(QStringLiteral("kcfg_ttsEngine")); - layout->addRow(i18nc("@label:listbox Config dialog, accessibility page", "Text-to-speech engine:"), ttsEngine); + m_ttsEngineBox->setProperty("kcfg_property", QByteArray("currentText")); + m_ttsEngineBox->setObjectName(QStringLiteral("kcfg_ttsEngine")); + layout->addRow(i18nc("@label:listbox Config dialog, accessibility page", "Text-to-speech engine:"), m_ttsEngineBox); + + connect(m_ttsEngineBox, qOverload(&QComboBox::currentIndexChanged), this, &DlgAccessibility::slotTTSEngineChanged); + + m_ttsVoiceBox = new QComboBox(this); + m_ttsVoiceBox->setProperty("kcfg_property", QByteArray("currentText")); + m_ttsVoiceBox->setObjectName(QStringLiteral("kcfg_ttsVoice")); + layout->addRow(i18nc("&label:listbox Config dialog, accessibility page", "Text-to-speech voice:"), m_ttsVoiceBox); + + slotTTSEngineChanged(); // END Text-to-speech section #endif } +#ifdef HAVE_SPEECH +void DlgAccessibility::slotTTSEngineChanged() +{ + QString engine = m_ttsEngineBox->currentText(); + QTextToSpeech *ttsEngine = new QTextToSpeech(engine); + const QVector voices = ttsEngine->availableVoices(); + m_ttsVoiceBox->clear(); + for (const QVoice &voice : voices) { + m_ttsVoiceBox->addItem(voice.name()); + } + delete ttsEngine; +} +#endif + void DlgAccessibility::slotColorModeSelected(int mode) { if (mode == Okular::Settings::EnumRenderMode::Paper) { diff --git a/part/dlgaccessibility.h b/part/dlgaccessibility.h index 302475869..8789a7a79 100644 --- a/part/dlgaccessibility.h +++ b/part/dlgaccessibility.h @@ -9,6 +9,7 @@ #include +class QComboBox; class QStackedWidget; class DlgAccessibility : public QWidget @@ -20,9 +21,16 @@ public: protected Q_SLOTS: void slotColorModeSelected(int mode); +#ifdef HAVE_SPEECH + void slotTTSEngineChanged(); +#endif protected: QStackedWidget *m_colorModeConfigStack; +#ifdef HAVE_SPEECH + QComboBox *m_ttsEngineBox; + QComboBox *m_ttsVoiceBox; +#endif }; #endif diff --git a/part/tts.cpp b/part/tts.cpp index 6357c70ef..11b4376ab 100644 --- a/part/tts.cpp +++ b/part/tts.cpp @@ -20,6 +20,13 @@ public: : q(qq) , speech(new QTextToSpeech(Okular::Settings::ttsEngine())) { + const QVector voices = speech->availableVoices(); + QString voiceName = Okular::Settings::ttsVoice(); + for (const QVoice &voice : voices) { + if (voice.name() == voiceName) { + speech->setVoice(voice); + } + } } ~Private() @@ -42,7 +49,7 @@ OkularTTS::OkularTTS(QObject *parent) // Initialize speechEngine so we can reinitialize if it changes. d->speechEngine = Okular::Settings::ttsEngine(); connect(d->speech, &QTextToSpeech::stateChanged, this, &OkularTTS::slotSpeechStateChanged); - connect(Okular::Settings::self(), &KConfigSkeleton::configChanged, this, &OkularTTS::slotConfigChanged); + connect(Okular::Settings::self(), &KCoreConfigSkeleton::configChanged, this, &OkularTTS::slotConfigChanged); } OkularTTS::~OkularTTS() @@ -94,6 +101,7 @@ void OkularTTS::slotSpeechStateChanged(QTextToSpeech::State state) void OkularTTS::slotConfigChanged() { const QString engine = Okular::Settings::ttsEngine(); + const QString voiceName = Okular::Settings::ttsVoice(); if (engine != d->speechEngine) { d->speech->stop(); delete d->speech; @@ -101,4 +109,12 @@ void OkularTTS::slotConfigChanged() connect(d->speech, &QTextToSpeech::stateChanged, this, &OkularTTS::slotSpeechStateChanged); d->speechEngine = engine; } + + const QVector voices = d->speech->availableVoices(); + for (const QVoice &voice : voices) { + if (voice.name() == voiceName) { + d->speech->setVoice(voice); + break; + } + } }