File indexing completed on 2025-02-16 04:57:43

0001 /*
0002  * SPDX-FileCopyrightText: 2006 Dmitry Morozhnikov <dmiceman@mail.ru>
0003  * SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "templatesconfiguration.h"
0009 #include "globalsettings_templateparser.h"
0010 #include "templatesconfiguration_kfg.h"
0011 #include <TextCustomEditor/PlainTextEditor>
0012 
0013 #include "templateparser_debug.h"
0014 #include <KLocalizedString>
0015 #include <KMessageBox>
0016 
0017 #include <QWhatsThis>
0018 
0019 using namespace TemplateParser;
0020 class TemplateParser::TemplatesConfigurationPrivate
0021 {
0022 public:
0023     TemplatesConfigurationPrivate() = default;
0024 
0025     QString mHelpString;
0026 };
0027 
0028 TemplatesConfiguration::TemplatesConfiguration(QWidget *parent, const QString &name)
0029     : QWidget(parent)
0030     , d(new TemplateParser::TemplatesConfigurationPrivate)
0031 {
0032     setupUi(this);
0033     setObjectName(name);
0034 
0035     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0036     sizeHint();
0037 
0038     connect(textEdit_new->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0039     connect(textEdit_reply->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0040     connect(textEdit_reply_all->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0041     connect(textEdit_forward->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0042     connect(lineEdit_quote, &QLineEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0043 
0044     connect(mInsertCommand,
0045             qOverload<const QString &, int>(&TemplateParser::TemplatesInsertCommandPushButton::insertCommand),
0046             this,
0047             &TemplatesConfiguration::slotInsertCommand);
0048 
0049     d->mHelpString = i18n(
0050         "<p>Here you can create and manage templates to use when "
0051         "composing new messages, replies or forwarded messages.</p>"
0052         "<p>The message templates support substitution commands, "
0053         "either simply type them or select them from "
0054         "the <i>Insert command</i> menu.</p>");
0055     const QString templateConfigurationName(name);
0056     if (templateConfigurationName == QLatin1StringView("folder-templates")) {
0057         d->mHelpString += i18n(
0058             "<p>Templates specified here are folder-specific. "
0059             "They override both global templates and per-identity "
0060             "templates.</p>");
0061     } else if (templateConfigurationName == QLatin1StringView("identity-templates")) {
0062         d->mHelpString += i18n(
0063             "<p>Templates specified here are identity-specific. "
0064             "They override global templates, but can be overridden by "
0065             "per-folder templates if they are specified.</p>");
0066     } else {
0067         d->mHelpString += i18n(
0068             "<p>These are global (default) templates. They can be overridden "
0069             "by per-identity templates or per-folder templates "
0070             "if they are specified.</p>");
0071     }
0072 
0073     mHelp->setText(i18n("<a href=\"whatsthis\">How does this work?</a>"));
0074     connect(mHelp, &QLabel::linkActivated, this, &TemplatesConfiguration::slotHelpLinkClicked);
0075     mHelp->setContextMenuPolicy(Qt::NoContextMenu);
0076 }
0077 
0078 TemplatesConfiguration::~TemplatesConfiguration()
0079 {
0080     disconnect(textEdit_new->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0081     disconnect(textEdit_reply->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0082     disconnect(textEdit_reply_all->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0083     disconnect(textEdit_forward->editor(), &QPlainTextEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0084     disconnect(lineEdit_quote, &QLineEdit::textChanged, this, &TemplatesConfiguration::slotTextChanged);
0085 }
0086 
0087 void TemplatesConfiguration::slotHelpLinkClicked(const QString &)
0088 {
0089     QWhatsThis::showText(QCursor::pos(), d->mHelpString);
0090 }
0091 
0092 void TemplatesConfiguration::slotTextChanged()
0093 {
0094     Q_EMIT changed();
0095 }
0096 
0097 void TemplatesConfiguration::resetToDefault()
0098 {
0099     const int choice = KMessageBox::questionTwoActionsCancel(nullptr,
0100                                                              i18n("Do you want to reset current template or all templates to default?"),
0101                                                              i18nc("@title:window", "Reset to default"),
0102                                                              KGuiItem(i18n("Reset Current Template")),
0103                                                              KGuiItem(i18n("Reset All Templates")),
0104                                                              KStandardGuiItem::cancel());
0105 
0106     if (choice == KMessageBox::Cancel) {
0107         return;
0108     } else if (choice == KMessageBox::ButtonCode::PrimaryAction) {
0109         const int toolboxCurrentIndex(toolBox1->currentIndex());
0110         if (toolBox1->widget(toolboxCurrentIndex) == page_new) {
0111             textEdit_new->setPlainText(DefaultTemplates::defaultNewMessage());
0112         } else if (toolBox1->widget(toolboxCurrentIndex) == page_reply) {
0113             textEdit_reply->setPlainText(DefaultTemplates::defaultReply());
0114         } else if (toolBox1->widget(toolboxCurrentIndex) == page_reply_all) {
0115             textEdit_reply_all->setPlainText(DefaultTemplates::defaultReplyAll());
0116         } else if (toolBox1->widget(toolboxCurrentIndex) == page_forward) {
0117             textEdit_forward->setPlainText(DefaultTemplates::defaultForward());
0118         } else {
0119             qCDebug(TEMPLATEPARSER_LOG) << "Unknown current page in TemplatesConfiguration!";
0120         }
0121     } else {
0122         textEdit_new->setPlainText(DefaultTemplates::defaultNewMessage());
0123         textEdit_reply->setPlainText(DefaultTemplates::defaultReply());
0124         textEdit_reply_all->setPlainText(DefaultTemplates::defaultReplyAll());
0125         textEdit_forward->setPlainText(DefaultTemplates::defaultForward());
0126     }
0127     lineEdit_quote->setText(DefaultTemplates::defaultQuoteString());
0128 }
0129 
0130 QLabel *TemplatesConfiguration::helpLabel() const
0131 {
0132     return mHelp;
0133 }
0134 
0135 void TemplatesConfiguration::loadFromGlobal()
0136 {
0137     QString str;
0138     str = TemplateParserSettings::self()->templateNewMessage();
0139     if (str.isEmpty()) {
0140         textEdit_new->setPlainText(DefaultTemplates::defaultNewMessage());
0141     } else {
0142         textEdit_new->setPlainText(str);
0143     }
0144     str = TemplateParserSettings::self()->templateReply();
0145     if (str.isEmpty()) {
0146         textEdit_reply->setPlainText(DefaultTemplates::defaultReply());
0147     } else {
0148         textEdit_reply->setPlainText(str);
0149     }
0150     str = TemplateParserSettings::self()->templateReplyAll();
0151     if (str.isEmpty()) {
0152         textEdit_reply_all->setPlainText(DefaultTemplates::defaultReplyAll());
0153     } else {
0154         textEdit_reply_all->setPlainText(str);
0155     }
0156     str = TemplateParserSettings::self()->templateForward();
0157     if (str.isEmpty()) {
0158         textEdit_forward->setPlainText(DefaultTemplates::defaultForward());
0159     } else {
0160         textEdit_forward->setPlainText(str);
0161     }
0162     str = TemplateParserSettings::self()->quoteString();
0163     if (str.isEmpty()) {
0164         lineEdit_quote->setText(DefaultTemplates::defaultQuoteString());
0165     } else {
0166         lineEdit_quote->setText(str);
0167     }
0168 }
0169 
0170 void TemplatesConfiguration::saveToGlobal()
0171 {
0172     TemplateParserSettings::self()->setTemplateNewMessage(strOrBlank(textEdit_new->toPlainText()));
0173     TemplateParserSettings::self()->setTemplateReply(strOrBlank(textEdit_reply->toPlainText()));
0174     TemplateParserSettings::self()->setTemplateReplyAll(strOrBlank(textEdit_reply_all->toPlainText()));
0175     TemplateParserSettings::self()->setTemplateForward(strOrBlank(textEdit_forward->toPlainText()));
0176     TemplateParserSettings::self()->setQuoteString(lineEdit_quote->text());
0177     TemplateParserSettings::self()->save();
0178 }
0179 
0180 void TemplatesConfiguration::loadFromIdentity(uint id)
0181 {
0182     Templates t(configIdString(id));
0183 
0184     QString str;
0185 
0186     str = t.templateNewMessage();
0187     if (str.isEmpty()) {
0188         str = TemplateParserSettings::self()->templateNewMessage();
0189     }
0190     if (str.isEmpty()) {
0191         str = DefaultTemplates::defaultNewMessage();
0192     }
0193     textEdit_new->setPlainText(str);
0194 
0195     str = t.templateReply();
0196     if (str.isEmpty()) {
0197         str = TemplateParserSettings::self()->templateReply();
0198     }
0199     if (str.isEmpty()) {
0200         str = DefaultTemplates::defaultReply();
0201     }
0202     textEdit_reply->setPlainText(str);
0203 
0204     str = t.templateReplyAll();
0205     if (str.isEmpty()) {
0206         str = TemplateParserSettings::self()->templateReplyAll();
0207     }
0208     if (str.isEmpty()) {
0209         str = DefaultTemplates::defaultReplyAll();
0210     }
0211     textEdit_reply_all->setPlainText(str);
0212 
0213     str = t.templateForward();
0214     if (str.isEmpty()) {
0215         str = TemplateParserSettings::self()->templateForward();
0216     }
0217     if (str.isEmpty()) {
0218         str = DefaultTemplates::defaultForward();
0219     }
0220     textEdit_forward->setPlainText(str);
0221 
0222     str = t.quoteString();
0223     if (str.isEmpty()) {
0224         str = TemplateParserSettings::self()->quoteString();
0225     }
0226     if (str.isEmpty()) {
0227         str = DefaultTemplates::defaultQuoteString();
0228     }
0229     lineEdit_quote->setText(str);
0230 }
0231 
0232 void TemplatesConfiguration::saveToIdentity(uint id)
0233 {
0234     Templates t(configIdString(id));
0235     t.setTemplateNewMessage(strOrBlank(textEdit_new->toPlainText()));
0236     t.setTemplateReply(strOrBlank(textEdit_reply->toPlainText()));
0237     t.setTemplateReplyAll(strOrBlank(textEdit_reply_all->toPlainText()));
0238     t.setTemplateForward(strOrBlank(textEdit_forward->toPlainText()));
0239     t.setQuoteString(lineEdit_quote->text());
0240     t.save();
0241 }
0242 
0243 void TemplatesConfiguration::loadFromFolder(const QString &id, uint identity)
0244 {
0245     Templates t(id);
0246     Templates *tid = nullptr;
0247 
0248     if (identity) {
0249         tid = new Templates(configIdString(identity));
0250     }
0251 
0252     QString str;
0253 
0254     str = t.templateNewMessage();
0255     if (str.isEmpty() && tid) {
0256         str = tid->templateNewMessage();
0257     }
0258     if (str.isEmpty()) {
0259         str = TemplateParserSettings::self()->templateNewMessage();
0260         if (str.isEmpty()) {
0261             str = DefaultTemplates::defaultNewMessage();
0262         }
0263     }
0264     textEdit_new->setPlainText(str);
0265 
0266     str = t.templateReply();
0267     if (str.isEmpty() && tid) {
0268         str = tid->templateReply();
0269     }
0270     if (str.isEmpty()) {
0271         str = TemplateParserSettings::self()->templateReply();
0272         if (str.isEmpty()) {
0273             str = DefaultTemplates::defaultReply();
0274         }
0275     }
0276     textEdit_reply->setPlainText(str);
0277 
0278     str = t.templateReplyAll();
0279     if (str.isEmpty() && tid) {
0280         str = tid->templateReplyAll();
0281         if (str.isEmpty()) {
0282             str = TemplateParserSettings::self()->templateReplyAll();
0283         }
0284     }
0285     if (str.isEmpty()) {
0286         str = DefaultTemplates::defaultReplyAll();
0287     }
0288     textEdit_reply_all->setPlainText(str);
0289 
0290     str = t.templateForward();
0291     if (str.isEmpty() && tid) {
0292         str = tid->templateForward();
0293         if (str.isEmpty()) {
0294             str = TemplateParserSettings::self()->templateForward();
0295         }
0296     }
0297     if (str.isEmpty()) {
0298         str = DefaultTemplates::defaultForward();
0299     }
0300     textEdit_forward->setPlainText(str);
0301 
0302     str = t.quoteString();
0303     if (str.isEmpty() && tid) {
0304         str = tid->quoteString();
0305     }
0306     if (str.isEmpty()) {
0307         str = TemplateParserSettings::self()->quoteString();
0308         if (str.isEmpty()) {
0309             str = DefaultTemplates::defaultQuoteString();
0310         }
0311     }
0312     lineEdit_quote->setText(str);
0313 
0314     delete (tid);
0315 }
0316 
0317 void TemplatesConfiguration::saveToFolder(const QString &id)
0318 {
0319     Templates t(id);
0320 
0321     t.setTemplateNewMessage(strOrBlank(textEdit_new->toPlainText()));
0322     t.setTemplateReply(strOrBlank(textEdit_reply->toPlainText()));
0323     t.setTemplateReplyAll(strOrBlank(textEdit_reply_all->toPlainText()));
0324     t.setTemplateForward(strOrBlank(textEdit_forward->toPlainText()));
0325     t.setQuoteString(lineEdit_quote->text());
0326     t.save();
0327 }
0328 
0329 QPlainTextEdit *TemplatesConfiguration::currentTextEdit() const
0330 {
0331     QPlainTextEdit *edit = nullptr;
0332 
0333     const int toolboxCurrentIndex(toolBox1->currentIndex());
0334     if (toolBox1->widget(toolboxCurrentIndex) == page_new) {
0335         edit = textEdit_new->editor();
0336     } else if (toolBox1->widget(toolboxCurrentIndex) == page_reply) {
0337         edit = textEdit_reply->editor();
0338     } else if (toolBox1->widget(toolboxCurrentIndex) == page_reply_all) {
0339         edit = textEdit_reply_all->editor();
0340     } else if (toolBox1->widget(toolboxCurrentIndex) == page_forward) {
0341         edit = textEdit_forward->editor();
0342     } else {
0343         qCDebug(TEMPLATEPARSER_LOG) << "Unknown current page in TemplatesConfiguration!";
0344         edit = nullptr;
0345     }
0346     return edit;
0347 }
0348 
0349 void TemplatesConfiguration::slotInsertCommand(const QString &cmd, int adjustCursor)
0350 {
0351     QPlainTextEdit *edit = currentTextEdit();
0352     if (!edit) {
0353         return;
0354     }
0355 
0356     // qCDebug(TEMPLATEPARSER_LOG) << "Insert command:" << cmd;
0357     const QString editText(edit->toPlainText());
0358     if ((editText.contains(QLatin1StringView("%FORCEDPLAIN")) && (cmd == QLatin1StringView("%FORCEDHTML")))
0359         || (editText.contains(QLatin1StringView("%FORCEDHTML")) && (cmd == QLatin1StringView("%FORCEDPLAIN")))) {
0360         KMessageBox::error(this,
0361                            i18n("Use of \"Reply using plain text\" and \"Reply using HTML text\" in pairs"
0362                                 " is not correct. Use only one of the aforementioned commands with \" Reply as"
0363                                 " Quoted Message command\" as per your need\n"
0364                                 "(a)Reply using plain text for quotes to be strictly in plain text\n"
0365                                 "(b)Reply using HTML text for quotes being in HTML format if present"));
0366     } else {
0367         QTextCursor cursor = edit->textCursor();
0368         cursor.insertText(cmd);
0369         cursor.setPosition(cursor.position() + adjustCursor);
0370         edit->setTextCursor(cursor);
0371         edit->setFocus();
0372     }
0373 }
0374 
0375 QString TemplatesConfiguration::strOrBlank(const QString &str)
0376 {
0377     if (str.trimmed().isEmpty()) {
0378         return QStringLiteral("%BLANK");
0379     }
0380     return str;
0381 }
0382 
0383 QString TemplatesConfiguration::configIdString(uint id)
0384 {
0385     return QStringLiteral("IDENTITY_%1").arg(id);
0386 }
0387 
0388 #include "moc_templatesconfiguration.cpp"