File indexing completed on 2025-01-19 04:51:21
0001 /* 0002 This file is part of Kontact. 0003 0004 SPDX-FileCopyrightText: 2003 Tobias Koenig <tokoe@kde.org> 0005 SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0008 */ 0009 0010 #include "summarywidget.h" 0011 #include "akonadi/notesakonaditreemodel.h" 0012 #include "akonadi/noteschangerecorder.h" 0013 #include "knotesinterface.h" 0014 0015 #include <Akonadi/ChangeRecorder> 0016 #include <Akonadi/ETMViewStateSaver> 0017 #include <Akonadi/Session> 0018 0019 #include <KontactInterface/Core> 0020 #include <KontactInterface/Plugin> 0021 0022 #include <KCheckableProxyModel> 0023 #include <KLocalizedString> 0024 #include <KMime/Message> 0025 #include <KSharedConfig> 0026 #include <KUrlLabel> 0027 0028 #include <QItemSelectionModel> 0029 #include <QLabel> 0030 #include <QMenu> 0031 #include <QVBoxLayout> 0032 0033 KNotesSummaryWidget::KNotesSummaryWidget(KontactInterface::Plugin *plugin, QWidget *parent) 0034 : KontactInterface::Summary(parent) 0035 , mPlugin(plugin) 0036 { 0037 auto mainLayout = new QVBoxLayout(this); 0038 mainLayout->setSpacing(3); 0039 mainLayout->setContentsMargins(3, 3, 3, 3); 0040 0041 QWidget *header = createHeader(this, QStringLiteral("view-pim-notes"), i18n("Popup Notes")); 0042 mainLayout->addWidget(header); 0043 0044 mLayout = new QGridLayout(); 0045 mainLayout->addLayout(mLayout); 0046 mLayout->setSpacing(3); 0047 mLayout->setRowStretch(6, 1); 0048 0049 auto session = new Akonadi::Session("KNotes Session", this); 0050 mNoteRecorder = new NoteShared::NotesChangeRecorder(this); 0051 mNoteRecorder->changeRecorder()->setSession(session); 0052 mNoteTreeModel = new NoteShared::NotesAkonadiTreeModel(mNoteRecorder->changeRecorder(), this); 0053 0054 connect(mNoteTreeModel, &NoteShared::NotesAkonadiTreeModel::rowsInserted, this, &KNotesSummaryWidget::updateFolderList); 0055 0056 connect(mNoteRecorder->changeRecorder(), &Akonadi::Monitor::itemChanged, this, &KNotesSummaryWidget::updateFolderList); 0057 0058 connect(mNoteRecorder->changeRecorder(), &Akonadi::Monitor::itemRemoved, this, &KNotesSummaryWidget::updateFolderList); 0059 0060 mSelectionModel = new QItemSelectionModel(mNoteTreeModel); 0061 mModelProxy = new KCheckableProxyModel(this); 0062 mModelProxy->setSelectionModel(mSelectionModel); 0063 mModelProxy->setSourceModel(mNoteTreeModel); 0064 0065 KSharedConfigPtr _config = KSharedConfig::openConfig(QStringLiteral("kcmknotessummaryrc")); 0066 0067 mModelState = new KViewStateMaintainer<Akonadi::ETMViewStateSaver>(_config->group(QStringLiteral("CheckState")), this); 0068 mModelState->setSelectionModel(mSelectionModel); 0069 } 0070 0071 KNotesSummaryWidget::~KNotesSummaryWidget() = default; 0072 0073 void KNotesSummaryWidget::updateFolderList() 0074 { 0075 if (mInProgress) { 0076 return; 0077 } 0078 mInProgress = true; 0079 qDeleteAll(mLabels); 0080 mLabels.clear(); 0081 int counter = 0; 0082 0083 mModelState->restoreState(); 0084 displayNotes(QModelIndex(), counter); 0085 mInProgress = false; 0086 0087 if (counter == 0) { 0088 auto label = new QLabel(i18n("No notes found"), this); 0089 label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 0090 mLayout->addWidget(label, 0, 0); 0091 mLabels.append(label); 0092 } 0093 QList<QLabel *>::const_iterator lit; 0094 QList<QLabel *>::const_iterator lend(mLabels.constEnd()); 0095 for (lit = mLabels.constBegin(); lit != lend; ++lit) { 0096 (*lit)->show(); 0097 } 0098 } 0099 0100 void KNotesSummaryWidget::displayNotes(const QModelIndex &parent, int &counter) 0101 { 0102 const int nbCol = mModelProxy->rowCount(parent); 0103 for (int i = 0; i < nbCol; ++i) { 0104 const QModelIndex child = mModelProxy->index(i, 0, parent); 0105 const auto item = mModelProxy->data(child, Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>(); 0106 if (item.isValid()) { 0107 createNote(item, counter); 0108 ++counter; 0109 } 0110 displayNotes(child, counter); 0111 } 0112 } 0113 0114 void KNotesSummaryWidget::slotPopupMenu(const QString ¬e) 0115 { 0116 QMenu popup(this); 0117 const QAction *modifyNoteAction = popup.addAction(QIcon::fromTheme(QStringLiteral("document-edit")), i18n("Modify Note...")); 0118 popup.addSeparator(); 0119 const QAction *deleteNoteAction = popup.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete Note...")); 0120 0121 const QAction *ret = popup.exec(QCursor::pos()); 0122 if (ret == deleteNoteAction) { 0123 deleteNote(note); 0124 } else if (ret == modifyNoteAction) { 0125 slotSelectNote(note); 0126 } 0127 } 0128 0129 void KNotesSummaryWidget::deleteNote(const QString ¬e) 0130 { 0131 org::kde::kontact::KNotes knotes(QStringLiteral("org.kde.kontact"), QStringLiteral("/KNotes"), QDBusConnection::sessionBus()); 0132 knotes.killNote(note.toLongLong()); 0133 } 0134 0135 void KNotesSummaryWidget::createNote(const Akonadi::Item &item, int counter) 0136 { 0137 if (!item.hasPayload<KMime::Message::Ptr>()) { 0138 return; 0139 } 0140 0141 auto noteMessage = item.payload<KMime::Message::Ptr>(); 0142 if (!noteMessage) { 0143 return; 0144 } 0145 const KMime::Headers::Subject *const subject = noteMessage->subject(false); 0146 const QString subStr = subject ? subject->asUnicodeString() : QString(); 0147 auto urlLabel = new KUrlLabel(QString::number(item.id()), subStr, this); 0148 0149 urlLabel->installEventFilter(this); 0150 urlLabel->setAlignment(Qt::AlignLeft); 0151 urlLabel->setWordWrap(true); 0152 connect(urlLabel, &KUrlLabel::leftClickedUrl, this, [this, urlLabel]() { 0153 slotSelectNote(urlLabel->url()); 0154 }); 0155 0156 connect(urlLabel, &KUrlLabel::rightClickedUrl, this, [this, urlLabel]() { 0157 slotPopupMenu(urlLabel->url()); 0158 }); 0159 mLayout->addWidget(urlLabel, counter, 1); 0160 0161 auto label = new QLabel(this); 0162 label->setAlignment(Qt::AlignVCenter); 0163 QIcon icon = QIcon::fromTheme(QStringLiteral("note")); 0164 label->setPixmap(icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); 0165 label->setMaximumWidth(label->minimumSizeHint().width()); 0166 mLayout->addWidget(label, counter, 0); 0167 mLabels.append(label); 0168 mLabels.append(urlLabel); 0169 } 0170 0171 void KNotesSummaryWidget::updateSummary(bool force) 0172 { 0173 Q_UNUSED(force) 0174 updateFolderList(); 0175 } 0176 0177 void KNotesSummaryWidget::slotSelectNote(const QString ¬e) 0178 { 0179 if (!mPlugin->isRunningStandalone()) { 0180 mPlugin->core()->selectPlugin(mPlugin); 0181 } else { 0182 mPlugin->bringToForeground(); 0183 } 0184 0185 org::kde::kontact::KNotes knotes(QStringLiteral("org.kde.kontact"), QStringLiteral("/KNotes"), QDBusConnection::sessionBus()); 0186 knotes.editNote(note.toLongLong()); 0187 } 0188 0189 bool KNotesSummaryWidget::eventFilter(QObject *obj, QEvent *e) 0190 { 0191 if (obj->inherits("KUrlLabel")) { 0192 auto label = static_cast<KUrlLabel *>(obj); 0193 if (e->type() == QEvent::Enter) { 0194 Q_EMIT message(i18n("Read Popup Note: \"%1\"", label->text())); 0195 } else if (e->type() == QEvent::Leave) { 0196 Q_EMIT message(QString()); 0197 } 0198 } 0199 0200 return KontactInterface::Summary::eventFilter(obj, e); 0201 } 0202 0203 QStringList KNotesSummaryWidget::configModules() const 0204 { 0205 return QStringList() << QStringLiteral("kcmknotessummary.desktop"); 0206 } 0207 0208 #include "moc_summarywidget.cpp"