File indexing completed on 2024-06-09 04:53:12

0001 /*
0002     SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar>
0003     SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "speller.h"
0009 #include "application.h"
0010 #include "core/richtext/richdocument.h"
0011 #include "core/subtitleiterator.h"
0012 
0013 #include <QDebug>
0014 
0015 #include <KMessageBox>
0016 #include <KLocalizedString>
0017 
0018 #include <sonnet_version.h>
0019 #include <sonnet/dialog.h>
0020 #include <sonnet/backgroundchecker.h>
0021 
0022 using namespace SubtitleComposer;
0023 
0024 Speller::Speller(QWidget *parent) :
0025     QObject(parent),
0026     m_subtitle(0),
0027     m_translationMode(false),
0028     m_useTranslation(false),
0029     m_sonnetDialog(0),
0030     m_iterator(0)
0031 {
0032     connect(SCConfig::self(), &KCoreConfigSkeleton::configChanged, this, &Speller::onConfigChanged);
0033 }
0034 
0035 Speller::~Speller()
0036 {
0037     setSubtitle(0);
0038 }
0039 
0040 void
0041 Speller::invalidate()
0042 {
0043     delete m_iterator;
0044     m_iterator = 0;
0045 }
0046 
0047 QWidget *
0048 Speller::parentWidget()
0049 {
0050     return static_cast<QWidget *>(parent());
0051 }
0052 
0053 void
0054 Speller::setSubtitle(Subtitle *subtitle)
0055 {
0056     m_subtitle = subtitle;
0057 
0058     invalidate();
0059 }
0060 
0061 void
0062 Speller::setTranslationMode(bool enabled)
0063 {
0064     m_translationMode = enabled;
0065 
0066     if(!enabled)
0067         m_useTranslation = false;
0068 }
0069 
0070 void
0071 Speller::setUseTranslation(bool useTranslation)
0072 {
0073     if(m_useTranslation != useTranslation) {
0074         m_useTranslation = useTranslation;
0075         updateBuffer();
0076     }
0077 }
0078 
0079 void
0080 Speller::updateBuffer()
0081 {
0082     if(m_iterator)
0083         m_sonnetDialog->setBuffer((m_useTranslation ? m_iterator->current()->secondaryDoc() : m_iterator->current()->primaryDoc())->toPlainText());
0084 }
0085 
0086 void
0087 Speller::spellCheck(int currentIndex)
0088 {
0089     invalidate();
0090 
0091     if(!m_subtitle || !m_subtitle->linesCount())
0092         return;
0093 
0094     m_iterator = new SubtitleIterator(*m_subtitle);
0095     m_iterator->toIndex(currentIndex < 0 ? 0 : currentIndex);
0096     m_firstIndex = m_iterator->index();
0097 
0098     if(!m_sonnetDialog) {
0099         m_sonnetDialog = new Sonnet::Dialog(new Sonnet::BackgroundChecker(this), parentWidget());
0100 
0101 #if SONNET_VERSION < QT_VERSION_CHECK(5, 65, 0)
0102         connect(m_sonnetDialog, QOverload<const QString &>::of(&Sonnet::Dialog::done), this, &Speller::onBufferDone);
0103 #else
0104         connect(m_sonnetDialog, &Sonnet::Dialog::spellCheckDone, this, &Speller::onBufferDone);
0105 #endif
0106 
0107         connect(m_sonnetDialog, &Sonnet::Dialog::replace, this, &Speller::onCorrected);
0108 
0109         connect(m_sonnetDialog, &Sonnet::Dialog::misspelling, this, &Speller::onMisspelling);
0110     }
0111 
0112     updateBuffer();
0113     m_sonnetDialog->show();
0114 }
0115 
0116 void
0117 Speller::onBufferDone()
0118 {
0119     // NOTE: not setting the buffer in this slots closes the dialog
0120     if(advance())
0121         updateBuffer();
0122 }
0123 
0124 bool
0125 Speller::advance()
0126 {
0127     ++(*m_iterator);
0128 
0129     if((m_firstIndex == m_iterator->index()) || (m_firstIndex == m_iterator->firstIndex() && m_iterator->index() == SubtitleIterator::AfterLast))
0130         return false;
0131 
0132     if(m_iterator->index() < 0) {
0133         m_iterator->toFirst();
0134 
0135         if(KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(), i18n("End of subtitle reached.\nContinue from the beginning?"), i18n("Spell Checking")))
0136             return false;
0137     }
0138 
0139     return true;
0140 }
0141 
0142 void
0143 Speller::onMisspelling(const QString &before, int pos)
0144 {
0145     emit misspelled(m_iterator->current(), !m_useTranslation, pos, pos + before.length() - 1);
0146 }
0147 
0148 void
0149 Speller::onCorrected(const QString &before, int pos, const QString &after)
0150 {
0151     if(before == after)
0152         return;
0153 
0154     if(m_useTranslation)
0155         m_iterator->current()->secondaryDoc()->replace(pos, before.length(), after);
0156     else
0157         m_iterator->current()->primaryDoc()->replace(pos, before.length(), after);
0158 }
0159 
0160 void
0161 Speller::onConfigChanged()
0162 {
0163     if(m_sonnetDialog) {
0164         invalidate();
0165 
0166         m_sonnetDialog->deleteLater();
0167         m_sonnetDialog = nullptr;
0168     }
0169 }
0170 
0171