diff --git a/PdfForQtViewer/PdfForQtViewer.pro b/PdfForQtViewer/PdfForQtViewer.pro index c737b8d..00750f3 100644 --- a/PdfForQtViewer/PdfForQtViewer.pro +++ b/PdfForQtViewer/PdfForQtViewer.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui winextras printsupport +QT += core gui winextras printsupport texttospeech greaterThan(QT_MAJOR_VERSION, 4): QT += widgets diff --git a/PdfForQtViewer/pdfforqtviewer.qrc b/PdfForQtViewer/pdfforqtviewer.qrc index 9d30a24..8f5b6d2 100644 --- a/PdfForQtViewer/pdfforqtviewer.qrc +++ b/PdfForQtViewer/pdfforqtviewer.qrc @@ -36,5 +36,6 @@ resources/rotate-left.svg resources/rotate-right.svg resources/print.svg + resources/speech.svg diff --git a/PdfForQtViewer/pdfviewersettings.cpp b/PdfForQtViewer/pdfviewersettings.cpp index c02c2ae..5e6724e 100644 --- a/PdfForQtViewer/pdfviewersettings.cpp +++ b/PdfForQtViewer/pdfviewersettings.cpp @@ -69,6 +69,15 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti m_colorManagementSystemSettings.profileDirectory = settings.value("profileDirectory", defaultCMSSettings.profileDirectory).toString(); settings.endGroup(); + settings.beginGroup("SpeechSettings"); + m_settings.m_speechEngine = settings.value("speechEngine", defaultSettings.m_speechEngine).toString(); + m_settings.m_speechLocale = settings.value("speechLocale", defaultSettings.m_speechLocale).toString(); + m_settings.m_speechVoice = settings.value("speechVoice", defaultSettings.m_speechVoice).toString(); + m_settings.m_speechRate = settings.value("speechRate", defaultSettings.m_speechRate).toDouble(); + m_settings.m_speechPitch = settings.value("speechPitch", defaultSettings.m_speechPitch).toDouble(); + m_settings.m_speechVolume = settings.value("speechVolume", defaultSettings.m_speechVolume).toDouble(); + settings.endGroup(); + emit settingsChanged(); } @@ -105,6 +114,15 @@ void PDFViewerSettings::writeSettings(QSettings& settings) settings.setValue("deviceCMYK", m_colorManagementSystemSettings.deviceCMYK); settings.setValue("profileDirectory", m_colorManagementSystemSettings.profileDirectory); settings.endGroup(); + + settings.beginGroup("SpeechSettings"); + settings.setValue("speechEngine", m_settings.m_speechEngine); + settings.setValue("speechLocale", m_settings.m_speechLocale); + settings.setValue("speechVoice", m_settings.m_speechVoice); + settings.setValue("speechRate", m_settings.m_speechRate); + settings.setValue("speechPitch", m_settings.m_speechPitch); + settings.setValue("speechVolume", m_settings.m_speechVolume); + settings.endGroup(); } QString PDFViewerSettings::getDirectory() const @@ -205,7 +223,10 @@ PDFViewerSettings::Settings::Settings() : m_thumbnailsCacheLimit(PIXMAP_CACHE_LIMIT), m_fontCacheLimit(pdf::DEFAULT_FONT_CACHE_LIMIT), m_instancedFontCacheLimit(pdf::DEFAULT_REALIZED_FONT_CACHE_LIMIT), - m_multithreadingStrategy(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded) + m_multithreadingStrategy(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded), + m_speechRate(0.0), + m_speechPitch(0.0), + m_speechVolume(1.0) { } diff --git a/PdfForQtViewer/pdfviewersettings.h b/PdfForQtViewer/pdfviewersettings.h index f4331de..81bd885 100644 --- a/PdfForQtViewer/pdfviewersettings.h +++ b/PdfForQtViewer/pdfviewersettings.h @@ -63,6 +63,14 @@ public: int m_thumbnailsCacheLimit; int m_fontCacheLimit; int m_instancedFontCacheLimit; + + // Speech settings + QString m_speechEngine; + QString m_speechLocale; + QString m_speechVoice; + double m_speechRate; + double m_speechPitch; + double m_speechVolume; }; const Settings& getSettings() const { return m_settings; } diff --git a/PdfForQtViewer/pdfviewersettingsdialog.cpp b/PdfForQtViewer/pdfviewersettingsdialog.cpp index 9f2ffe9..02cb2af 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.cpp +++ b/PdfForQtViewer/pdfviewersettingsdialog.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace pdfviewer { @@ -46,6 +47,8 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin { ui->setupUi(this); + m_textToSpeechEngines = QTextToSpeech::availableEngines(); + new QListWidgetItem(QIcon(":/resources/engine.svg"), tr("Engine"), ui->optionsPagesWidget, EngineSettings); new QListWidgetItem(QIcon(":/resources/rendering.svg"), tr("Rendering"), ui->optionsPagesWidget, RenderingSettings); new QListWidgetItem(QIcon(":/resources/shading.svg"), tr("Shading"), ui->optionsPagesWidget, ShadingSettings); @@ -54,6 +57,7 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin new QListWidgetItem(QIcon(":/resources/cms.svg"), tr("Colors"), ui->optionsPagesWidget, ColorManagementSystemSettings); new QListWidgetItem(QIcon(":/resources/security.svg"), tr("Security"), ui->optionsPagesWidget, SecuritySettings); new QListWidgetItem(QIcon(":/resources/ui.svg"), tr("UI"), ui->optionsPagesWidget, UISettings); + new QListWidgetItem(QIcon(":/resources/speech.svg"), tr("Speech"), ui->optionsPagesWidget, SpeechSettings); ui->renderingEngineComboBox->addItem(tr("Software"), static_cast(pdf::RendererEngine::Software)); ui->renderingEngineComboBox->addItem(tr("Hardware accelerated (OpenGL)"), static_cast(pdf::RendererEngine::OpenGL)); @@ -130,6 +134,12 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin } } + // Text to speech + for (const QString& engine : m_textToSpeechEngines) + { + ui->speechEnginesComboBox->addItem(engine, engine); + } + ui->optionsPagesWidget->setCurrentRow(0); adjustSize(); loadData(); @@ -179,6 +189,10 @@ void PDFViewerSettingsDialog::on_optionsPagesWidget_currentItemChanged(QListWidg ui->stackedWidget->setCurrentWidget(ui->uiPage); break; + case SpeechSettings: + ui->stackedWidget->setCurrentWidget(ui->speechPage); + break; + default: Q_ASSERT(false); break; @@ -289,6 +303,16 @@ void PDFViewerSettingsDialog::loadData() ui->cmsProfileDirectoryEdit->setEnabled(false); ui->cmsProfileDirectoryEdit->setText(QString()); } + + // Text-to-speech + ui->speechEnginesComboBox->setCurrentIndex(ui->speechEnginesComboBox->findData(m_settings.m_speechEngine)); + QString speechEngine = ui->speechEnginesComboBox->currentData().toString(); + setSpeechEngine(speechEngine); + ui->speechLocaleComboBox->setCurrentIndex(ui->speechLocaleComboBox->findData(m_settings.m_speechLocale)); + ui->speechVoiceComboBox->setCurrentIndex(ui->speechVoiceComboBox->findData(m_settings.m_speechVoice)); + ui->speechRateEdit->setValue(m_settings.m_speechRate); + ui->speechPitchEdit->setValue(m_settings.m_speechPitch); + ui->speechVolumeEdit->setValue(m_settings.m_speechVolume); } void PDFViewerSettingsDialog::saveData() @@ -424,8 +448,36 @@ void PDFViewerSettingsDialog::saveData() { m_otherSettings.maximumRecentFileCount = ui->maximumRecentFileCountEdit->value(); } + else if (sender == ui->speechEnginesComboBox) + { + m_settings.m_speechEngine = ui->speechEnginesComboBox->currentData().toString(); + } + else if (sender == ui->speechLocaleComboBox) + { + m_settings.m_speechLocale = ui->speechLocaleComboBox->currentData().toString(); + } + else if (sender == ui->speechVoiceComboBox) + { + m_settings.m_speechVoice = ui->speechVoiceComboBox->currentData().toString(); + } + else if (sender == ui->speechRateEdit) + { + m_settings.m_speechRate = ui->speechRateEdit->value(); + } + else if (sender == ui->speechPitchEdit) + { + m_settings.m_speechPitch = ui->speechPitchEdit->value(); + } + else if (sender == ui->speechVolumeEdit) + { + m_settings.m_speechVolume = ui->speechVolumeEdit->value(); + } - loadData(); + const bool loadData = !qobject_cast(sender) && !qobject_cast(sender); + if (loadData) + { + this->loadData(); + } } void PDFViewerSettingsDialog::loadActionShortcutsTable() @@ -480,6 +532,35 @@ bool PDFViewerSettingsDialog::saveActionShortcutsTable() return true; } +void PDFViewerSettingsDialog::setSpeechEngine(const QString& engine) +{ + if (m_currentSpeechEngine == engine) + { + return; + } + + m_currentSpeechEngine = engine; + QTextToSpeech textToSpeech(engine, nullptr); + + QVector locales = textToSpeech.availableLocales(); + ui->speechLocaleComboBox->setUpdatesEnabled(false); + ui->speechLocaleComboBox->clear(); + for (const QLocale& locale : locales) + { + ui->speechLocaleComboBox->addItem(QString("%1 (%2)").arg(locale.nativeLanguageName(), locale.nativeCountryName()), locale.name()); + } + ui->speechLocaleComboBox->setUpdatesEnabled(true); + + QVector voices = textToSpeech.availableVoices(); + ui->speechVoiceComboBox->setUpdatesEnabled(false); + ui->speechVoiceComboBox->clear(); + for (const QVoice& voice : voices) + { + ui->speechVoiceComboBox->addItem(QString("%1 (%2, %3)").arg(voice.name(), QVoice::genderName(voice.gender()), QVoice::ageName(voice.age())), voice.name()); + } + ui->speechVoiceComboBox->setUpdatesEnabled(true); +} + void PDFViewerSettingsDialog::accept() { if (saveActionShortcutsTable()) diff --git a/PdfForQtViewer/pdfviewersettingsdialog.h b/PdfForQtViewer/pdfviewersettingsdialog.h index ec1564c..a750458 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.h +++ b/PdfForQtViewer/pdfviewersettingsdialog.h @@ -69,7 +69,8 @@ public: ShortcutSettings, ColorManagementSystemSettings, SecuritySettings, - UISettings + UISettings, + SpeechSettings }; const PDFViewerSettings::Settings& getSettings() const { return m_settings; } @@ -78,7 +79,6 @@ public: private slots: void on_optionsPagesWidget_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous); - void on_cmsProfileDirectoryButton_clicked(); private: @@ -88,12 +88,16 @@ private: void loadActionShortcutsTable(); bool saveActionShortcutsTable(); + void setSpeechEngine(const QString& engine); + Ui::PDFViewerSettingsDialog* ui; PDFViewerSettings::Settings m_settings; pdf::PDFCMSSettings m_cmsSettings; OtherSettings m_otherSettings; QList m_actions; bool m_isLoadingData; + QStringList m_textToSpeechEngines; + QString m_currentSpeechEngine; }; } // namespace pdfviewer diff --git a/PdfForQtViewer/pdfviewersettingsdialog.ui b/PdfForQtViewer/pdfviewersettingsdialog.ui index 862f7c6..8fbea75 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.ui +++ b/PdfForQtViewer/pdfviewersettingsdialog.ui @@ -26,7 +26,7 @@ - 7 + 8 @@ -887,6 +887,136 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Speech Settings + + + + + + + + Voice + + + + + + + Pitch + + + + + + + Volume + + + + + + + Rate + + + + + + + Voice synthetiser + + + + + + + Locale + + + + + + + + + + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + + + + + 1.000000000000000 + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + + + + + + + <html><head/><body><p>Set speech settings to enable document reading. These settings are default settings for text to speech functionality, but some can be changed later. Pitch can have values from -1.0 to 1.0 and 0.0 is default. Rate can also have values ranging from -1.0 to 1.0, while 0.0 is normal speech flow. Volume can have values from 0.0 to 1.0.</p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 288 + + + + + + + + + diff --git a/PdfForQtViewer/resources/speech.svg b/PdfForQtViewer/resources/speech.svg new file mode 100644 index 0000000..cdc6e6f --- /dev/null +++ b/PdfForQtViewer/resources/speech.svg @@ -0,0 +1,178 @@ + + + + + + + + + + image/svg+xml + + + + + Jakub Melka + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +