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

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 "incidencecategories.h"
0009 
0010 #include "incidenceeditor_debug.h"
0011 #include "ui_dialogdesktop.h"
0012 
0013 #include <Akonadi/CalendarUtils>
0014 #include <Akonadi/TagAttribute>
0015 #include <Akonadi/TagCreateJob>
0016 #include <Akonadi/TagFetchJob>
0017 #include <Akonadi/TagFetchScope>
0018 
0019 using namespace IncidenceEditorNG;
0020 
0021 IncidenceCategories::IncidenceCategories(Ui::EventOrTodoDesktop *ui)
0022     : mUi(ui)
0023 {
0024     setObjectName(QLatin1StringView("IncidenceCategories"));
0025 
0026     connect(mUi->mTagWidget, &Akonadi::TagWidget::selectionChanged, this, &IncidenceCategories::onSelectionChanged);
0027 }
0028 
0029 void IncidenceCategories::onSelectionChanged(const Akonadi::Tag::List &list)
0030 {
0031     Q_UNUSED(list)
0032     mDirty = true;
0033     checkDirtyStatus();
0034 }
0035 
0036 void IncidenceCategories::load(const KCalendarCore::Incidence::Ptr &incidence)
0037 {
0038     Q_UNUSED(incidence)
0039     mDirty = false;
0040     mWasDirty = false;
0041 }
0042 
0043 void IncidenceCategories::load(const Akonadi::Item &item)
0044 {
0045     mLoadedIncidence = Akonadi::CalendarUtils::incidence(item);
0046     mDirty = false;
0047     mWasDirty = false;
0048 
0049     Q_ASSERT(mLoadedIncidence);
0050     if (mLoadedIncidence) {
0051         mMissingCategories = mLoadedIncidence->categories();
0052         const auto tags = item.tags();
0053         Akonadi::Tag::List selectedTags;
0054         selectedTags.reserve(mMissingCategories.count());
0055         for (const auto &tag : tags) {
0056             if (mMissingCategories.removeAll(tag.name()) > 0) {
0057                 selectedTags << tag;
0058             }
0059         }
0060         createMissingCategories();
0061         mUi->mTagWidget->blockSignals(true);
0062         mUi->mTagWidget->setSelection(selectedTags);
0063         mUi->mTagWidget->blockSignals(false);
0064     }
0065 }
0066 
0067 void IncidenceCategories::save(const KCalendarCore::Incidence::Ptr &incidence)
0068 {
0069     Q_ASSERT(incidence);
0070     if (mDirty) {
0071         incidence->setCategories(categories());
0072     }
0073 }
0074 
0075 void IncidenceCategories::save(Akonadi::Item &item)
0076 {
0077     const auto &selectedTags = mUi->mTagWidget->selection();
0078     if (mDirty) {
0079         item.setTags(selectedTags);
0080     }
0081 }
0082 
0083 QStringList IncidenceCategories::categories() const
0084 {
0085     QStringList list;
0086     const auto &selectedTags = mUi->mTagWidget->selection();
0087     list.reserve(selectedTags.count() + mMissingCategories.count());
0088     for (const Akonadi::Tag &tag : selectedTags) {
0089         list << tag.name();
0090     }
0091     list << mMissingCategories;
0092     return list;
0093 }
0094 
0095 void IncidenceCategories::createMissingCategories()
0096 {
0097     for (const QString &category : std::as_const(mMissingCategories)) {
0098         // Either the tag doesn't exist, or Akonadi doesn't have a tag <-> item
0099         // relation for this category and instance. Try to create a PLAIN tag.
0100         Akonadi::Tag missingTag = Akonadi::Tag(category);
0101         auto createJob = new Akonadi::TagCreateJob(missingTag, this);
0102         createJob->setMergeIfExisting(true);
0103         connect(createJob, &Akonadi::TagCreateJob::result, this, &IncidenceCategories::onMissingTagCreated);
0104     }
0105 }
0106 
0107 bool IncidenceCategories::isDirty() const
0108 {
0109     return mDirty;
0110 }
0111 
0112 void IncidenceCategories::printDebugInfo() const
0113 {
0114     qCDebug(INCIDENCEEDITOR_LOG) << "selected categories = " << categories();
0115     qCDebug(INCIDENCEEDITOR_LOG) << "mMissingCategories = " << mMissingCategories;
0116     qCDebug(INCIDENCEEDITOR_LOG) << "mLoadedIncidence->categories() = " << mLoadedIncidence->categories();
0117 }
0118 
0119 void IncidenceCategories::onMissingTagCreated(KJob *job)
0120 {
0121     if (job->error()) {
0122         qCWarning(INCIDENCEEDITOR_LOG) << "Failed to create tag " << job->errorString();
0123         return;
0124     }
0125     auto createJob = static_cast<Akonadi::TagCreateJob *>(job);
0126     int count = mMissingCategories.removeAll(createJob->tag().name());
0127 
0128     auto selectedTags{mUi->mTagWidget->selection()};
0129     selectedTags += createJob->tag();
0130 
0131     // If the created tag was one of the instance's missing categories,
0132     // adding it to the widget doesn't make it dirty.
0133     mUi->mTagWidget->blockSignals(count > 0);
0134     mUi->mTagWidget->setSelection(selectedTags);
0135     mUi->mTagWidget->blockSignals(false);
0136 }
0137 
0138 #include "moc_incidencecategories.cpp"