File indexing completed on 2024-04-28 16:00:59

0001 /*
0002    SPDX-FileCopyrightText: 2014-2023 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "texttospeechwidget.h"
0008 #include "texttospeechactions.h"
0009 #include "texttospeechconfigdialog.h"
0010 #include "texttospeechinterface.h"
0011 #include "texttospeechsliderwidget.h"
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <QHBoxLayout>
0015 #include <QLabel>
0016 #include <QPointer>
0017 #include <QTimer>
0018 #include <QToolButton>
0019 
0020 using namespace std::chrono_literals;
0021 #include <chrono>
0022 
0023 using namespace TextEditTextToSpeech;
0024 
0025 class Q_DECL_HIDDEN TextEditTextToSpeech::TextToSpeechWidgetPrivate
0026 {
0027 public:
0028     TextToSpeechWidgetPrivate() = default;
0029 
0030     QPointer<TextEditTextToSpeech::TextToSpeechConfigDialog> mConfigDialog;
0031     QToolButton *mStopButton = nullptr;
0032     QToolButton *mPlayPauseButton = nullptr;
0033     QToolButton *mConfigureButton = nullptr;
0034     TextToSpeechInterface *mTextToSpeechInterface = nullptr;
0035     TextToSpeechActions *mTextToSpeechActions = nullptr;
0036     TextToSpeechSliderWidget *mVolume = nullptr;
0037     bool mNeedToHide = false;
0038 };
0039 
0040 TextToSpeechWidget::TextToSpeechWidget(QWidget *parent)
0041     : QWidget(parent)
0042     , d(new TextEditTextToSpeech::TextToSpeechWidgetPrivate)
0043 {
0044     auto hbox = new QHBoxLayout(this);
0045     hbox->setObjectName(QStringLiteral("hbox"));
0046     hbox->setContentsMargins(QMargins{});
0047 
0048     d->mTextToSpeechActions = new TextToSpeechActions(this);
0049     connect(d->mTextToSpeechActions, &TextToSpeechActions::stateChanged, this, &TextToSpeechWidget::stateChanged);
0050 
0051     auto close = new QToolButton(this);
0052     close->setObjectName(QStringLiteral("close-button"));
0053     close->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
0054     close->setToolTip(i18n("Close"));
0055     connect(close, &QToolButton::clicked, this, &TextToSpeechWidget::slotCloseTextToSpeechWidget);
0056     hbox->addWidget(close);
0057     hbox->addStretch(0);
0058 
0059     auto volume = new QLabel(i18n("Volume:"), this);
0060     hbox->addWidget(volume);
0061     d->mVolume = new TextToSpeechSliderWidget(QStringLiteral("%1 %"), this);
0062     d->mVolume->setMinimumWidth(100);
0063     d->mVolume->setObjectName(QStringLiteral("volumeslider"));
0064     d->mVolume->setRange(0, 100);
0065     connect(d->mVolume, &TextToSpeechSliderWidget::valueChanged, this, &TextToSpeechWidget::slotVolumeChanged);
0066     hbox->addWidget(d->mVolume);
0067 
0068     d->mStopButton = new QToolButton(this);
0069     d->mStopButton->setObjectName(QStringLiteral("stopbutton"));
0070     d->mStopButton->setDefaultAction(d->mTextToSpeechActions->stopAction());
0071     hbox->addWidget(d->mStopButton);
0072 
0073     d->mPlayPauseButton = new QToolButton(this);
0074     d->mPlayPauseButton->setObjectName(QStringLiteral("playpausebutton"));
0075     d->mPlayPauseButton->setDefaultAction(d->mTextToSpeechActions->playPauseAction());
0076     hbox->addWidget(d->mPlayPauseButton);
0077 
0078     d->mConfigureButton = new QToolButton(this);
0079     d->mConfigureButton->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
0080     d->mConfigureButton->setToolTip(i18n("Configure..."));
0081     d->mConfigureButton->setObjectName(QStringLiteral("configurebutton"));
0082     connect(d->mConfigureButton, &QToolButton::clicked, this, &TextToSpeechWidget::slotConfigure);
0083     hbox->addWidget(d->mConfigureButton);
0084 
0085     d->mTextToSpeechInterface = new TextToSpeechInterface(this, this);
0086     applyVolume();
0087     setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
0088     hideWidget();
0089 }
0090 
0091 TextToSpeechWidget::~TextToSpeechWidget() = default;
0092 
0093 void TextToSpeechWidget::slotCloseTextToSpeechWidget()
0094 {
0095     d->mTextToSpeechActions->slotStop();
0096     hideWidget();
0097 }
0098 
0099 void TextToSpeechWidget::slotConfigure()
0100 {
0101     if (!d->mConfigDialog.data()) {
0102         d->mNeedToHide = false;
0103         d->mConfigDialog = new TextToSpeechConfigDialog(this);
0104         if (d->mConfigDialog->exec()) {
0105             d->mTextToSpeechInterface->reloadSettings();
0106             applyVolume();
0107         }
0108         delete d->mConfigDialog;
0109         if (d->mNeedToHide) {
0110             hideWidget();
0111             d->mNeedToHide = false;
0112         }
0113     }
0114 }
0115 
0116 void TextToSpeechWidget::slotVolumeChanged(int value)
0117 {
0118     d->mTextToSpeechInterface->setVolume(value / 100.0);
0119 }
0120 
0121 bool TextToSpeechWidget::isReady() const
0122 {
0123     return d->mTextToSpeechInterface->isReady();
0124 }
0125 
0126 void TextToSpeechWidget::say(const QString &text)
0127 {
0128     if (!text.isEmpty()) {
0129         if (d->mTextToSpeechInterface->isReady()) {
0130             d->mTextToSpeechInterface->say(text);
0131         } else {
0132             KMessageBox::error(this, i18n("Engine has a problem."), i18n("Text To Speech"));
0133         }
0134     }
0135 }
0136 
0137 TextToSpeechWidget::State TextToSpeechWidget::state() const
0138 {
0139     return d->mTextToSpeechActions->state();
0140 }
0141 
0142 void TextToSpeechWidget::slotStateChanged(TextEditTextToSpeech::TextToSpeech::State state)
0143 {
0144     switch (state) {
0145     case TextEditTextToSpeech::TextToSpeech::Ready:
0146         if (state == TextEditTextToSpeech::TextToSpeech::Ready) {
0147             d->mTextToSpeechActions->setState(TextToSpeechWidget::Stop);
0148             if (d->mConfigDialog) {
0149                 d->mNeedToHide = true;
0150             } else {
0151                 QTimer::singleShot(2s, this, &TextToSpeechWidget::hideWidget);
0152             }
0153         }
0154         break;
0155     default:
0156         // TODO
0157         break;
0158     }
0159 }
0160 
0161 void TextToSpeechWidget::showWidget()
0162 {
0163     show();
0164     Q_EMIT changeVisibility(true);
0165 }
0166 
0167 void TextToSpeechWidget::hideWidget()
0168 {
0169     hide();
0170     Q_EMIT changeVisibility(false);
0171 }
0172 
0173 void TextToSpeechWidget::setState(TextToSpeechWidget::State state)
0174 {
0175     d->mTextToSpeechActions->setState(state);
0176 }
0177 
0178 void TextToSpeechWidget::setTextToSpeechInterface(TextToSpeechInterface *interface)
0179 {
0180     delete d->mTextToSpeechInterface;
0181     d->mTextToSpeechInterface = interface;
0182     // Update volume value
0183     if (d->mTextToSpeechInterface) {
0184         d->mTextToSpeechInterface->reloadSettings();
0185         applyVolume();
0186     }
0187 }
0188 
0189 void TextToSpeechWidget::applyVolume()
0190 {
0191     // Api return volume between 0.0 -> 1.0
0192     // We want display between 0 -> 100
0193     d->mVolume->setValue(d->mTextToSpeechInterface->volume() * 100);
0194 }
0195 
0196 #include "moc_texttospeechwidget.cpp"