File indexing completed on 2024-04-28 05:11:34

0001 /*
0002   SPDX-FileCopyrightText: 2010 Bertjan Broeksema <broeksema@kde.org>
0003   SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0004 
0005   SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "incidencedescription.h"
0009 #include "ui_dialogdesktop.h"
0010 #include <KPIMTextEdit/RichTextComposer>
0011 
0012 #include "incidenceeditor_debug.h"
0013 #include <KActionCollection>
0014 #include <KLocalizedString>
0015 #include <KToolBar>
0016 
0017 using namespace IncidenceEditorNG;
0018 
0019 namespace IncidenceEditorNG
0020 {
0021 class IncidenceDescriptionPrivate
0022 {
0023 public:
0024     IncidenceDescriptionPrivate() = default;
0025 
0026     QString mRealOriginalDescriptionEditContents;
0027     bool mRichTextEnabled = false;
0028 };
0029 }
0030 
0031 IncidenceDescription::IncidenceDescription(Ui::EventOrTodoDesktop *ui)
0032     : IncidenceEditor(nullptr)
0033     , mUi(ui)
0034     , d(new IncidenceDescriptionPrivate())
0035 {
0036     setObjectName(QLatin1StringView("IncidenceDescription"));
0037     mUi->mRichTextLabel->setContextMenuPolicy(Qt::NoContextMenu);
0038     setupToolBar();
0039     connect(mUi->mRichTextLabel, &QLabel::linkActivated, this, &IncidenceDescription::toggleRichTextDescription);
0040     connect(mUi->mDescriptionEdit->richTextComposer(), &KPIMTextEdit::RichTextComposer::textChanged, this, &IncidenceDescription::checkDirtyStatus);
0041 }
0042 
0043 IncidenceDescription::~IncidenceDescription() = default;
0044 
0045 void IncidenceDescription::load(const KCalendarCore::Incidence::Ptr &incidence)
0046 {
0047     mLoadedIncidence = incidence;
0048 
0049     d->mRealOriginalDescriptionEditContents.clear();
0050 
0051     if (incidence) {
0052         enableRichTextDescription(incidence->descriptionIsRich());
0053         if (incidence->descriptionIsRich()) {
0054             mUi->mDescriptionEdit->richTextComposer()->setHtml(incidence->richDescription());
0055             d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml();
0056         } else {
0057             mUi->mDescriptionEdit->richTextComposer()->setPlainText(incidence->description());
0058             d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText();
0059         }
0060     } else {
0061         enableRichTextDescription(false);
0062         mUi->mDescriptionEdit->richTextComposer()->clear();
0063     }
0064 
0065     mWasDirty = false;
0066 }
0067 
0068 void IncidenceDescription::save(const KCalendarCore::Incidence::Ptr &incidence)
0069 {
0070     if (d->mRichTextEnabled) {
0071         incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toHtml(), true);
0072     } else {
0073         incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toPlainText(), false);
0074     }
0075 }
0076 
0077 bool IncidenceDescription::isDirty() const
0078 {
0079     /* Sometimes, what you put in a KRichTextWidget isn't the same as what you get out.
0080        Line terminators (cr,lf) for example can be converted.
0081 
0082        So, to see if the user changed something, we can't compare the original incidence
0083        with the new editor content.
0084 
0085        Instead we compare the new editor content, with the original editor content, this way
0086        any transformation regarding non-printable chars will be irrelevant.
0087     */
0088     if (d->mRichTextEnabled) {
0089         return !mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toHtml();
0090     } else {
0091         return mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toPlainText();
0092     }
0093 }
0094 
0095 void IncidenceDescription::enableRichTextDescription(bool enable)
0096 {
0097     d->mRichTextEnabled = enable;
0098 
0099     QString rt(i18nc("@action Enable or disable rich text editing", "Enable rich text"));
0100     QString placeholder(QStringLiteral("<a href=\"show\">%1 &gt;&gt;</a>"));
0101 
0102     if (enable) {
0103         rt = i18nc("@action Enable or disable rich text editing", "Disable rich text");
0104         placeholder = QStringLiteral("<a href=\"show\">&lt;&lt; %1</a>");
0105         mUi->mDescriptionEdit->richTextComposer()->activateRichText();
0106         d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml();
0107     } else {
0108         mUi->mDescriptionEdit->richTextComposer()->switchToPlainText();
0109         d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText();
0110     }
0111 
0112     placeholder = placeholder.arg(rt);
0113     mUi->mRichTextLabel->setText(placeholder);
0114     mUi->mDescriptionEdit->richTextComposer()->setEnableActions(enable);
0115     mUi->mEditToolBarPlaceHolder->setVisible(enable);
0116     checkDirtyStatus();
0117 }
0118 
0119 void IncidenceDescription::toggleRichTextDescription()
0120 {
0121     enableRichTextDescription(!d->mRichTextEnabled);
0122 }
0123 
0124 void IncidenceDescription::setupToolBar()
0125 {
0126 #ifndef QT_NO_TOOLBAR
0127     auto collection = new KActionCollection(this);
0128     mUi->mDescriptionEdit->richTextComposer()->createActions(collection);
0129 
0130     auto mEditToolBar = new KToolBar(mUi->mEditToolBarPlaceHolder);
0131     mEditToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
0132     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_bold")));
0133     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_italic")));
0134     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_underline")));
0135     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_strikeout")));
0136     mEditToolBar->addSeparator();
0137 
0138     mEditToolBar->addAction(collection->action(QStringLiteral("format_font_family")));
0139     mEditToolBar->addAction(collection->action(QStringLiteral("format_font_size")));
0140     mEditToolBar->addSeparator();
0141 
0142     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_foreground_color")));
0143     mEditToolBar->addAction(collection->action(QStringLiteral("format_text_background_color")));
0144     mEditToolBar->addSeparator();
0145 
0146     mEditToolBar->addAction(collection->action(QStringLiteral("format_list_style")));
0147     mEditToolBar->addSeparator();
0148 
0149     mEditToolBar->addAction(collection->action(QStringLiteral("format_align_left")));
0150     mEditToolBar->addAction(collection->action(QStringLiteral("format_align_center")));
0151     mEditToolBar->addAction(collection->action(QStringLiteral("format_align_right")));
0152     mEditToolBar->addAction(collection->action(QStringLiteral("format_align_justify")));
0153     mEditToolBar->addSeparator();
0154 
0155     mEditToolBar->addAction(collection->action(QStringLiteral("format_painter")));
0156     mEditToolBar->addSeparator();
0157     mEditToolBar->addAction(collection->action(QStringLiteral("manage_link")));
0158     mUi->mDescriptionEdit->richTextComposer()->setEnableActions(false);
0159 
0160     auto layout = new QGridLayout(mUi->mEditToolBarPlaceHolder);
0161     layout->addWidget(mEditToolBar);
0162 #endif
0163 
0164     // By default we don't show the rich text toolbar.
0165     mUi->mEditToolBarPlaceHolder->setVisible(false);
0166     d->mRichTextEnabled = false;
0167 }
0168 
0169 void IncidenceDescription::printDebugInfo() const
0170 {
0171     // We're going to crash
0172     qCDebug(INCIDENCEEDITOR_LOG) << "RichText enabled " << d->mRichTextEnabled;
0173 
0174     if (mLoadedIncidence) {
0175         qCDebug(INCIDENCEEDITOR_LOG) << "Incidence description is rich " << mLoadedIncidence->descriptionIsRich();
0176 
0177         if (mLoadedIncidence->descriptionIsRich()) {
0178             qCDebug(INCIDENCEEDITOR_LOG) << "desc is rich, and it is <desc>" << mLoadedIncidence->richDescription() << "</desc>; "
0179                                          << "widget has <desc>" << mUi->mDescriptionEdit->richTextComposer()->toHtml() << "</desc>; "
0180                                          << "expr mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->toHtml() is "
0181                                          << (mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->richTextComposer()->toHtml());
0182         } else {
0183             qCDebug(INCIDENCEEDITOR_LOG) << "desc is not rich, and it is <desc>" << mLoadedIncidence->description() << "</desc>; "
0184                                          << "widget has <desc>" << mUi->mDescriptionEdit->richTextComposer()->toPlainText() << "</desc>; "
0185                                          << "expr mLoadedIncidence->description() != mUi->mDescriptionEdit->toPlainText() is "
0186                                          << (mLoadedIncidence->description() != mUi->mDescriptionEdit->richTextComposer()->toPlainText());
0187         }
0188     } else {
0189         qCDebug(INCIDENCEEDITOR_LOG) << "Incidence is invalid";
0190     }
0191 }
0192 
0193 #include "moc_incidencedescription.cpp"