File indexing completed on 2024-05-12 16:16:00

0001 /*
0002    SPDX-FileCopyrightText: 2019-2023 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "grammarresulttextedit.h"
0008 #include "grammarresultutil.h"
0009 #include "textgrammarcheck_debug.h"
0010 #include <KStatefulBrush>
0011 
0012 #include <KLocalizedString>
0013 #include <KStandardAction>
0014 #include <QDesktopServices>
0015 
0016 #include <KColorScheme>
0017 #include <QAction>
0018 #include <QApplication>
0019 #include <QContextMenuEvent>
0020 #include <QMenu>
0021 #include <QPainter>
0022 using namespace TextGrammarCheck;
0023 GrammarResultTextEdit::GrammarResultTextEdit(QWidget *parent)
0024     : QTextEdit(parent)
0025 {
0026     setReadOnly(true);
0027     setAcceptRichText(false);
0028 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0029     connect(qApp, &QApplication::paletteChanged, this, &GrammarResultTextEdit::generalPaletteChanged);
0030 #endif
0031     generalPaletteChanged();
0032 }
0033 
0034 GrammarResultTextEdit::~GrammarResultTextEdit() = default;
0035 
0036 void GrammarResultTextEdit::paintEvent(QPaintEvent *event)
0037 {
0038     if (document()->isEmpty()) {
0039         const QString label = i18n("Any text to check.");
0040 
0041         QPainter p(viewport());
0042 
0043         QFont font = p.font();
0044         font.setItalic(true);
0045         p.setFont(font);
0046 
0047         if (!mTextColor.isValid()) {
0048             generalPaletteChanged();
0049         }
0050         p.setPen(mTextColor);
0051 
0052         p.drawText(QRect(0, 0, width(), height()), Qt::AlignCenter, label);
0053     } else {
0054         QTextEdit::paintEvent(event);
0055     }
0056 }
0057 
0058 bool GrammarResultTextEdit::event(QEvent *ev)
0059 {
0060 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0061     if (ev->type() == QEvent::ApplicationPaletteChange) {
0062         generalPaletteChanged();
0063     }
0064 #endif
0065     return QTextEdit::event(ev);
0066 }
0067 
0068 void GrammarResultTextEdit::generalPaletteChanged()
0069 {
0070     const QPalette palette = viewport()->palette();
0071     QColor color = palette.text().color();
0072     color.setAlpha(128);
0073     mTextColor = color;
0074     const KStatefulBrush bgBrush = KStatefulBrush(KColorScheme::View, KColorScheme::NegativeText);
0075     mNegativeTextColor = bgBrush.brush(palette).color();
0076 }
0077 
0078 void GrammarResultTextEdit::applyGrammarResult(const QVector<GrammarError> &infos)
0079 {
0080     GrammarResultUtil::applyGrammarResult(infos, document(), mNegativeTextColor);
0081 }
0082 
0083 void GrammarResultTextEdit::contextMenuEvent(QContextMenuEvent *event)
0084 {
0085     QMenu *popup = createStandardContextMenu();
0086     if (popup) {
0087         QTextCursor cursor = cursorForPosition(event->pos());
0088         if (cursor.charFormat().hasProperty(GrammarResultUtil::TextInfo::ReplaceFormatInfo)) {
0089             const auto act = cursor.charFormat().property(GrammarResultUtil::TextInfo::ReplaceFormatInfo).value<TextGrammarCheck::GrammarAction>();
0090             const QStringList sugg = act.suggestions();
0091             if (!sugg.isEmpty()) {
0092                 popup->addSeparator();
0093                 QMenu *popupReplacement = popup->addMenu(i18n("Replacement"));
0094                 for (const QString &str : sugg) {
0095                     QAction *actReplacement = popupReplacement->addAction(str);
0096                     connect(actReplacement, &QAction::triggered, this, [this, act, str]() {
0097                         slotReplaceWord(act, str);
0098                     });
0099                 }
0100                 const QStringList lst = act.infoUrls();
0101                 if (!lst.isEmpty()) {
0102                     QMenu *popupUrlInfo = popup->addMenu(i18n("Online Grammar Information"));
0103                     for (const QString &str : lst) {
0104                         QAction *actUrlInfo = popupUrlInfo->addAction(str);
0105                         connect(actUrlInfo, &QAction::triggered, this, [this, str]() {
0106                             slotOpenGrammarUrlInfo(str);
0107                         });
0108                     }
0109                 }
0110             } else {
0111                 qCDebug(TEXTGRAMMARCHECK_LOG) << " no suggestion " << act;
0112             }
0113         }
0114         popup->addSeparator();
0115         QAction *checkAgainAct = popup->addAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("Check Again"));
0116         connect(checkAgainAct, &QAction::triggered, this, &GrammarResultTextEdit::checkAgain);
0117         popup->addSeparator();
0118         QAction *configureAct = popup->addAction(QIcon::fromTheme(QStringLiteral("settings-configure")), i18n("Configure..."));
0119         connect(configureAct, &QAction::triggered, this, &GrammarResultTextEdit::configure);
0120         popup->addSeparator();
0121         QAction *closeAct = KStandardAction::close(this, &GrammarResultTextEdit::closeChecker, this);
0122         closeAct->setShortcut({});
0123         popup->addAction(closeAct);
0124         popup->exec(event->globalPos());
0125         delete popup;
0126     }
0127 }
0128 
0129 void GrammarResultTextEdit::slotOpenGrammarUrlInfo(const QString &url)
0130 {
0131     QDesktopServices::openUrl(QUrl(url));
0132 }
0133 
0134 void GrammarResultTextEdit::slotReplaceWord(const TextGrammarCheck::GrammarAction &act, const QString &replacementWord)
0135 {
0136     TextGrammarCheck::GrammarAction actWithReplacement = act;
0137     actWithReplacement.setReplacement(replacementWord);
0138     GrammarResultUtil::replaceWord(actWithReplacement, replacementWord, document());
0139     Q_EMIT replaceText(actWithReplacement);
0140 }
0141 
0142 #include "moc_grammarresulttextedit.cpp"