diff --git a/conf/dlgaccessibility.cpp b/conf/dlgaccessibility.cpp --- a/conf/dlgaccessibility.cpp +++ b/conf/dlgaccessibility.cpp @@ -11,6 +11,10 @@ #include "ui_dlgaccessibilitybase.h" +#include "settings.h" + +#include + DlgAccessibility::DlgAccessibility( QWidget * parent ) : QWidget( parent ), m_selected( 0 ) { @@ -28,6 +32,13 @@ page->hide(); m_color_pages[ m_selected ]->show(); + // Populate tts engines + const QStringList engines = QTextToSpeech::availableEngines(); + for (const QString &engine: engines) { + m_dlg->kcfg_ttsEngine->addItem (engine); + } + m_dlg->kcfg_ttsEngine->setProperty("kcfg_property", QByteArray("currentText")); + connect(m_dlg->kcfg_RenderMode, static_cast(&KComboBox::currentIndexChanged), this, &DlgAccessibility::slotColorMode); } diff --git a/conf/dlgaccessibilitybase.ui b/conf/dlgaccessibilitybase.ui --- a/conf/dlgaccessibilitybase.ui +++ b/conf/dlgaccessibilitybase.ui @@ -1,106 +1,107 @@ - + + DlgAccessibilityBase - - + + 0 0 374 - 327 + 479 - - + + 0 - + 0 - + 0 - + 0 - - + + Draw border around &Images - - + + Draw border around &Links - - + + true - + Change &colors - + true - + false - + - - - + + + 0 0 - + Warning: these options can badly affect drawing speed. - + Qt::PlainText - + true - + - - + + Color mode: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + Invert Colors - + Change Paper Color - + Change Dark & Light Colors - + Convert to Black & White @@ -110,235 +111,235 @@ - + Qt::Vertical - + QSizePolicy::Fixed - + 20 8 - + - - - + + + 0 - + 0 - + 0 - + 0 - - + + 6 - + 0 - + 0 - + 0 - + 0 - - + + Paper color: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + kcfg_PaperColor - + - - - + + + 0 - + 0 - + 0 - + 0 - - + + 6 - + 0 - + 0 - + 0 - + 0 - - + + Dark color: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - - + + 6 - + 0 - + 0 - + 0 - + 0 - - + + Light color: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - - - + + + 0 - + 0 - + 0 - + 0 - - - - - + + + + + 0 0 - + Threshold: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + + + + 0 0 - + 16 - + Qt::Horizontal - - - - + + + + 0 0 - + Contrast: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + + + + 0 0 - + 1 - + Qt::Horizontal @@ -351,15 +352,34 @@ + + + + Speech + + + + + + Engine + + + + + + + + + - + Qt::Vertical - + QSizePolicy::Expanding - + 20 20 @@ -369,17 +389,17 @@ - - - KColorButton - QPushButton -
kcolorbutton.h
-
+ KComboBox QComboBox
kcombobox.h
+ + KColorButton + QPushButton +
kcolorbutton.h
+
diff --git a/conf/okular.kcfg b/conf/okular.kcfg --- a/conf/okular.kcfg +++ b/conf/okular.kcfg @@ -145,6 +145,9 @@ + + speechd + true diff --git a/part.rc b/part.rc --- a/part.rc +++ b/part.rc @@ -1,5 +1,5 @@ - + &File @@ -84,6 +84,7 @@ + &Settings diff --git a/ui/pageview.h b/ui/pageview.h --- a/ui/pageview.h +++ b/ui/pageview.h @@ -272,6 +272,7 @@ void slotSpeakDocument(); void slotSpeakCurrentPage(); void slotStopSpeaks(); + void slotPauseResumeSpeech(); #endif void slotAction( Okular::Action *action ); void externalKeyPressEvent( QKeyEvent *e ); diff --git a/ui/pageview.cpp b/ui/pageview.cpp --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -241,6 +241,7 @@ QAction * aSpeakDoc; QAction * aSpeakPage; QAction * aSpeakStop; + QAction * aSpeakPauseResume; KActionCollection * actionCollection; QActionGroup * mouseModeActionGroup; QAction * aFitWindowToPage; @@ -300,9 +301,15 @@ m_tts = new OkularTTS( q ); if ( aSpeakStop ) { - QObject::connect( m_tts, &OkularTTS::isSpeaking, + QObject::connect( m_tts, &OkularTTS::canPauseOrResume, aSpeakStop, &QAction::setEnabled ); } + + if ( aSpeakPauseResume ) + { + QObject::connect( m_tts, &OkularTTS::canPauseOrResume, + aSpeakPauseResume, &QAction::setEnabled ); + } } return m_tts; @@ -379,6 +386,7 @@ d->aSpeakDoc = nullptr; d->aSpeakPage = nullptr; d->aSpeakStop = nullptr; + d->aSpeakPauseResume = nullptr; d->actionCollection = nullptr; d->aPageSizes=nullptr; d->setting_viewCols = Okular::Settings::viewColumns(); @@ -705,10 +713,16 @@ ac->addAction( QStringLiteral("speak_stop_all"), d->aSpeakStop ); d->aSpeakStop->setEnabled( false ); connect( d->aSpeakStop, &QAction::triggered, this, &PageView::slotStopSpeaks ); + + d->aSpeakPauseResume = new QAction( QIcon::fromTheme( QStringLiteral("media-playback-pause") ), i18n( "Pause/Resume Speaking" ), this ); + ac->addAction( QStringLiteral("speak_pause_resume"), d->aSpeakPauseResume ); + d->aSpeakPauseResume->setEnabled( false ); + connect( d->aSpeakPauseResume, &QAction::triggered, this, &PageView::slotPauseResumeSpeech ); #else d->aSpeakDoc = 0; d->aSpeakPage = 0; d->aSpeakStop = 0; + d->aSpeakPauseResume = 0; #endif // Other actions @@ -5492,6 +5506,15 @@ d->m_tts->stopAllSpeechs(); } + +void PageView::slotPauseResumeSpeech() +{ + if ( !d->m_tts ) + return; + + d->m_tts->pauseResumeSpeech(); +} + #endif void PageView::slotAction( Okular::Action *action ) diff --git a/ui/tts.h b/ui/tts.h --- a/ui/tts.h +++ b/ui/tts.h @@ -22,12 +22,15 @@ void say( const QString &text ); void stopAllSpeechs(); + void pauseResumeSpeech(); public slots: void slotSpeechStateChanged(QTextToSpeech::State state); + void slotConfigChanged(); signals: void isSpeaking( bool speaking ); + void canPauseOrResume( bool speakingOrPaused ); private: // private storage diff --git a/ui/tts.cpp b/ui/tts.cpp --- a/ui/tts.cpp +++ b/ui/tts.cpp @@ -14,12 +14,14 @@ #include +#include "settings.h" + /* Private storage. */ class OkularTTS::Private { public: Private( OkularTTS *qq ) - : q( qq ), speech( new QTextToSpeech ) + : q( qq ), speech( new QTextToSpeech( Okular::Settings::ttsEngine() ) ) { } @@ -31,12 +33,19 @@ OkularTTS *q; QTextToSpeech *speech; + // Which speech engine was used when above object was created. + // When the setting changes, we need to stop speaking and recreate. + QString speechEngine; }; OkularTTS::OkularTTS( QObject *parent ) : QObject( parent ), d( new Private( this ) ) { + // 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); } OkularTTS::~OkularTTS() @@ -60,12 +69,45 @@ d->speech->stop(); } +void OkularTTS::pauseResumeSpeech() +{ + if ( !d->speech ) + return; + + if ( d->speech->state() == QTextToSpeech::Speaking ) + d->speech->pause(); + else + d->speech->resume(); +} + void OkularTTS::slotSpeechStateChanged(QTextToSpeech::State state) { if (state == QTextToSpeech::Speaking) + { emit isSpeaking(true); + emit canPauseOrResume(true); + } else + { emit isSpeaking(false); + if (state == QTextToSpeech::Paused) + emit canPauseOrResume(true); + else + emit canPauseOrResume(false); + } +} + +void OkularTTS::slotConfigChanged() +{ + const QString engine = Okular::Settings::ttsEngine(); + if (engine != d->speechEngine) + { + d->speech->stop(); + delete d->speech; + d->speech = new QTextToSpeech(engine); + connect( d->speech, &QTextToSpeech::stateChanged, this, &OkularTTS::slotSpeechStateChanged); + d->speechEngine = engine; + } } #include "moc_tts.cpp"