SVN_SILENT made messages (.desktop file) - always resolve ours
[kdepim.git] / akonadiconsole / browserwidget.cpp
blob8e08fbda83365203e121068c3ccd02d9e6b2deb1
1 /*
2 Copyright (c) 2007 Volker Krause <vkrause@kde.org>
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
20 #include "browserwidget.h"
22 #include "collectionattributespage.h"
23 #include "collectioninternalspage.h"
24 #include "collectionaclpage.h"
25 #include "dbaccess.h"
26 #include "akonadibrowsermodel.h"
27 #include "tagpropertiesdialog.h"
29 #include <AkonadiCore/attributefactory.h>
30 #include <AkonadiCore/changerecorder.h>
31 #include <AkonadiWidgets/controlgui.h>
32 #include <AkonadiCore/entitymimetypefiltermodel.h>
33 #include <AkonadiCore/item.h>
34 #include <AkonadiCore/itemfetchjob.h>
35 #include <AkonadiCore/itemfetchscope.h>
36 #include <AkonadiCore/itemmodifyjob.h>
37 #include <AkonadiCore/job.h>
38 #include <AkonadiCore/collectionfilterproxymodel.h>
39 #include <AkonadiWidgets/collectionpropertiesdialog.h>
40 #include <AkonadiCore/selectionproxymodel.h>
41 #include <AkonadiCore/session.h>
42 #include <AkonadiWidgets/standardactionmanager.h>
43 #include <AkonadiWidgets/entitylistview.h>
44 #include <AkonadiWidgets/entitytreeview.h>
45 #include <AkonadiWidgets/etmviewstatesaver.h>
46 #include <AkonadiCore/favoritecollectionsmodel.h>
47 #include <AkonadiCore/quotacolorproxymodel.h>
48 #include <AkonadiCore/tagmodel.h>
49 #include <AkonadiCore/statisticsproxymodel.h>
50 #include <AkonadiCore/tagdeletejob.h>
51 #include <kviewstatemaintainer.h>
53 #include <kcontacts/addressee.h>
54 #include <kcontacts/contactgroup.h>
55 #include <KCalCore/Incidence>
57 #include "akonadiconsole_debug.h"
58 #include <kconfig.h>
59 #include <kconfiggroup.h>
60 #include <kmessagebox.h>
61 #include <kxmlguiwindow.h>
62 #include <KToggleAction>
63 #include <KActionCollection>
64 #include <AkonadiCore/tagmodifyjob.h>
65 #include <AkonadiCore/tagcreatejob.h>
67 #include <KLocalizedString>
69 #include <QSplitter>
70 #include <QVBoxLayout>
71 #include <QStandardItemModel>
72 #include <QSqlQuery>
73 #include <QTimer>
74 #include <QSqlError>
75 #include <KSharedConfig>
76 #include <QMenu>
77 #include <QFileDialog>
79 using namespace Akonadi;
81 AKONADI_COLLECTION_PROPERTIES_PAGE_FACTORY(CollectionAttributePageFactory, CollectionAttributePage)
82 AKONADI_COLLECTION_PROPERTIES_PAGE_FACTORY(CollectionInternalsPageFactory, CollectionInternalsPage)
83 AKONADI_COLLECTION_PROPERTIES_PAGE_FACTORY(CollectionAclPageFactory, CollectionAclPage)
85 Q_DECLARE_METATYPE(QSet<QByteArray>)
87 BrowserWidget::BrowserWidget(KXmlGuiWindow *xmlGuiWindow, QWidget *parent) :
88 QWidget(parent),
89 mAttrModel(Q_NULLPTR),
90 mStdActionManager(Q_NULLPTR),
91 mMonitor(Q_NULLPTR),
92 mCacheOnlyAction(Q_NULLPTR)
94 Q_ASSERT(xmlGuiWindow);
95 QVBoxLayout *layout = new QVBoxLayout(this);
97 QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
98 splitter->setObjectName(QStringLiteral("collectionSplitter"));
99 layout->addWidget(splitter);
101 QSplitter *splitter2 = new QSplitter(Qt::Vertical, this);
102 splitter2->setObjectName(QStringLiteral("ffvSplitter"));
104 mCollectionView = new Akonadi::EntityTreeView(xmlGuiWindow, this);
105 mCollectionView->setObjectName(QStringLiteral("CollectionView"));
106 mCollectionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
107 splitter2->addWidget(mCollectionView);
109 EntityListView *favoritesView = new EntityListView(xmlGuiWindow, this);
110 //favoritesView->setViewMode( QListView::IconMode );
111 splitter2->addWidget(favoritesView);
113 splitter->addWidget(splitter2);
115 ChangeRecorder *tagRecorder = new ChangeRecorder(this);
116 tagRecorder->setTypeMonitored(Monitor::Tags);
117 tagRecorder->setChangeRecordingEnabled(false);
118 mTagView = new QTreeView(this);
119 mTagModel = new Akonadi::TagModel(tagRecorder, this);
120 mTagView->setModel(mTagModel);
121 splitter2->addWidget(mTagView);
123 mTagView->setContextMenuPolicy(Qt::CustomContextMenu);
124 connect(mTagView, &QTreeView::customContextMenuRequested, this, &BrowserWidget::tagViewContextMenuRequested);
125 connect(mTagView, &QTreeView::doubleClicked, this, &BrowserWidget::tagViewDoubleClicked);
127 Session *session = new Session(("AkonadiConsole Browser Widget"), this);
129 // monitor collection changes
130 mBrowserMonitor = new ChangeRecorder(this);
131 mBrowserMonitor->setSession(session);
132 mBrowserMonitor->setCollectionMonitored(Collection::root());
133 mBrowserMonitor->fetchCollection(true);
134 mBrowserMonitor->setAllMonitored(true);
135 // TODO: Only fetch the envelope etc if possible.
136 mBrowserMonitor->itemFetchScope().fetchFullPayload(true);
137 mBrowserMonitor->itemFetchScope().setCacheOnly(true);
139 mBrowserModel = new AkonadiBrowserModel(mBrowserMonitor, this);
140 mBrowserModel->setItemPopulationStrategy(EntityTreeModel::LazyPopulation);
141 mBrowserModel->setShowSystemEntities(true);
142 mBrowserModel->setListFilter(CollectionFetchScope::Display);
144 // new ModelTest( mBrowserModel );
146 EntityMimeTypeFilterModel *collectionFilter = new EntityMimeTypeFilterModel(this);
147 collectionFilter->setSourceModel(mBrowserModel);
148 collectionFilter->addMimeTypeInclusionFilter(Collection::mimeType());
149 collectionFilter->setHeaderGroup(EntityTreeModel::CollectionTreeHeaders);
150 collectionFilter->setDynamicSortFilter(true);
151 collectionFilter->setSortCaseSensitivity(Qt::CaseInsensitive);
153 statisticsProxyModel = new Akonadi::StatisticsProxyModel(this);
154 statisticsProxyModel->setToolTipEnabled(true);
155 statisticsProxyModel->setSourceModel(collectionFilter);
157 Akonadi::QuotaColorProxyModel *quotaProxyModel = new Akonadi::QuotaColorProxyModel(this);
158 quotaProxyModel->setWarningThreshold(50.0);
159 quotaProxyModel->setSourceModel(statisticsProxyModel);
161 mCollectionView->setModel(quotaProxyModel);
163 Akonadi::SelectionProxyModel *selectionProxyModel = new Akonadi::SelectionProxyModel(mCollectionView->selectionModel(), this);
164 selectionProxyModel->setSourceModel(mBrowserModel);
165 selectionProxyModel->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection);
167 EntityMimeTypeFilterModel *itemFilter = new EntityMimeTypeFilterModel(this);
168 itemFilter->setSourceModel(selectionProxyModel);
169 itemFilter->addMimeTypeExclusionFilter(Collection::mimeType());
170 itemFilter->setHeaderGroup(EntityTreeModel::ItemListHeaders);
172 const KConfigGroup group = KSharedConfig::openConfig()->group("FavoriteCollectionsModel");
173 connect(mBrowserModel, &AkonadiBrowserModel::columnsChanged, itemFilter, &EntityMimeTypeFilterModel::invalidate);
174 AkonadiBrowserSortModel *sortModel = new AkonadiBrowserSortModel(mBrowserModel, this);
175 sortModel->setDynamicSortFilter(true);
176 sortModel->setSourceModel(itemFilter);
177 FavoriteCollectionsModel *favoritesModel = new FavoriteCollectionsModel(mBrowserModel, group, this);
178 favoritesView->setModel(favoritesModel);
180 QSplitter *splitter3 = new QSplitter(Qt::Vertical, this);
181 splitter3->setObjectName(QStringLiteral("itemSplitter"));
182 splitter->addWidget(splitter3);
184 QWidget *itemViewParent = new QWidget(this);
185 itemUi.setupUi(itemViewParent);
187 itemUi.modelBox->addItem(QStringLiteral("Generic"));
188 itemUi.modelBox->addItem(QStringLiteral("Mail"));
189 itemUi.modelBox->addItem(QStringLiteral("Contacts"));
190 itemUi.modelBox->addItem(QStringLiteral("Calendar"));
191 itemUi.modelBox->addItem(QStringLiteral("Calendar/Tasks"));
192 connect(itemUi.modelBox, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), this, &BrowserWidget::modelChanged);
193 QTimer::singleShot(0, this, SLOT(modelChanged()));
195 itemUi.itemView->setXmlGuiClient(xmlGuiWindow);
196 itemUi.itemView->setModel(sortModel);
197 itemUi.itemView->setSelectionMode(QAbstractItemView::ExtendedSelection);
198 connect(itemUi.itemView, &Akonadi::EntityTreeView::activated, this, &BrowserWidget::itemActivated);
199 connect(itemUi.itemView, SIGNAL(clicked(QModelIndex)), SLOT(itemActivated(QModelIndex)));
201 splitter3->addWidget(itemViewParent);
202 itemViewParent->layout()->setMargin(0);
204 QWidget *contentViewParent = new QWidget(this);
205 contentUi.setupUi(contentViewParent);
206 contentUi.saveButton->setEnabled(false);
207 connect(contentUi.saveButton, &QPushButton::clicked, this, &BrowserWidget::save);
208 splitter3->addWidget(contentViewParent);
210 connect(contentUi.attrAddButton, &QPushButton::clicked, this, &BrowserWidget::addAttribute);
211 connect(contentUi.attrDeleteButton, &QPushButton::clicked, this, &BrowserWidget::delAttribute);
212 connect(contentUi.flags, &KEditListWidget::changed, this, &BrowserWidget::contentViewChanged);
213 connect(contentUi.tags, &KEditListWidget::changed, this, &BrowserWidget::contentViewChanged);
214 connect(contentUi.remoteId, &QLineEdit::textChanged, this, &BrowserWidget::contentViewChanged);
216 CollectionPropertiesDialog::registerPage(new CollectionAclPageFactory());
217 CollectionPropertiesDialog::registerPage(new CollectionAttributePageFactory());
218 CollectionPropertiesDialog::registerPage(new CollectionInternalsPageFactory());
220 ControlGui::widgetNeedsAkonadi(this);
222 mStdActionManager = new StandardActionManager(xmlGuiWindow->actionCollection(), xmlGuiWindow);
223 mStdActionManager->setCollectionSelectionModel(mCollectionView->selectionModel());
224 mStdActionManager->setItemSelectionModel(itemUi.itemView->selectionModel());
225 mStdActionManager->setFavoriteCollectionsModel(favoritesModel);
226 mStdActionManager->setFavoriteSelectionModel(favoritesView->selectionModel());
227 mStdActionManager->createAllActions();
229 mCacheOnlyAction = new KToggleAction(QStringLiteral("Cache only retrieval"), xmlGuiWindow);
230 mCacheOnlyAction->setChecked(true);
231 xmlGuiWindow->actionCollection()->addAction(QStringLiteral("akonadiconsole_cacheonly"), mCacheOnlyAction);
232 connect(mCacheOnlyAction, &KToggleAction::toggled, this, &BrowserWidget::updateItemFetchScope);
234 m_stateMaintainer = new KViewStateMaintainer<ETMViewStateSaver>(KSharedConfig::openConfig()->group("CollectionViewState"), this);
235 m_stateMaintainer->setView(mCollectionView);
237 m_stateMaintainer->restoreState();
240 BrowserWidget::~BrowserWidget()
242 m_stateMaintainer->saveState();
245 void BrowserWidget::clear()
247 contentUi.stack->setCurrentWidget(contentUi.unsupportedTypePage);
248 contentUi.dataView->clear();
249 contentUi.id->clear();
250 contentUi.remoteId->clear();
251 contentUi.mimeType->clear();
252 contentUi.revision->clear();
253 contentUi.size->clear();
254 contentUi.modificationtime->clear();
255 contentUi.flags->clear();
256 contentUi.tags->clear();
257 contentUi.attrView->setModel(Q_NULLPTR);
260 void BrowserWidget::itemActivated(const QModelIndex &index)
262 const Item item = index.sibling(index.row(), 0).data(EntityTreeModel::ItemRole).value< Item >();
263 if (!item.isValid()) {
264 clear();
265 return;
268 ItemFetchJob *job = new ItemFetchJob(item, this);
269 job->fetchScope().fetchFullPayload();
270 job->fetchScope().fetchAllAttributes();
271 job->fetchScope().setFetchTags(true);
272 connect(job, &ItemFetchJob::result, this, &BrowserWidget::itemFetchDone);
275 void BrowserWidget::itemFetchDone(KJob *job)
277 ItemFetchJob *fetch = static_cast<ItemFetchJob *>(job);
278 if (job->error()) {
279 qCWarning(AKONADICONSOLE_LOG) << "Item fetch failed: " << job->errorString();
280 } else if (fetch->items().isEmpty()) {
281 qCWarning(AKONADICONSOLE_LOG) << "No item found!";
282 } else {
283 const Item item = fetch->items().first();
284 setItem(item);
288 void BrowserWidget::contentViewChanged()
290 contentUi.saveButton->setEnabled(true);
293 void BrowserWidget::setItem(const Akonadi::Item &item)
295 mCurrentItem = item;
296 if (item.hasPayload<KContacts::Addressee>()) {
297 contentUi.contactView->setItem(item);
298 contentUi.stack->setCurrentWidget(contentUi.contactViewPage);
299 } else if (item.hasPayload<KContacts::ContactGroup>()) {
300 contentUi.contactGroupView->setItem(item);
301 contentUi.stack->setCurrentWidget(contentUi.contactGroupViewPage);
302 } else if (item.hasPayload<KCalCore::Incidence::Ptr>()) {
303 contentUi.incidenceView->setItem(item);
304 contentUi.stack->setCurrentWidget(contentUi.incidenceViewPage);
305 } else if (item.mimeType() == QLatin1String("message/rfc822")
306 || item.mimeType() == QLatin1String("message/news")) {
307 contentUi.mailView->setMessageItem(item, MessageViewer::Viewer::Force);
308 contentUi.stack->setCurrentWidget(contentUi.mailViewPage);
309 } else if (item.hasPayload<QPixmap>()) {
310 contentUi.imageView->setPixmap(item.payload<QPixmap>());
311 contentUi.stack->setCurrentWidget(contentUi.imageViewPage);
312 } else {
313 contentUi.stack->setCurrentWidget(contentUi.unsupportedTypePage);
316 contentUi.saveButton->setEnabled(false);
318 QByteArray data = item.payloadData();
319 contentUi.dataView->setPlainText(QString::fromLatin1(data));
321 contentUi.id->setText(QString::number(item.id()));
322 contentUi.remoteId->setText(item.remoteId());
323 contentUi.mimeType->setText(item.mimeType());
324 contentUi.revision->setText(QString::number(item.revision()));
325 contentUi.size->setText(QString::number(item.size()));
326 contentUi.modificationtime->setText(item.modificationTime().toString() + QStringLiteral(" UTC"));
327 QStringList flags;
328 foreach (const Item::Flag &f, item.flags()) {
329 flags << QString::fromUtf8(f);
331 contentUi.flags->setItems(flags);
333 QStringList tags;
334 foreach (const Tag &tag, item.tags()) {
335 tags << QLatin1String(tag.gid());
337 contentUi.tags->setItems(tags);
339 Attribute::List list = item.attributes();
340 delete mAttrModel;
341 mAttrModel = new QStandardItemModel(list.count(), 2);
342 QStringList labels;
343 labels << QStringLiteral("Attribute") << QStringLiteral("Value");
344 mAttrModel->setHorizontalHeaderLabels(labels);
345 for (int i = 0; i < list.count(); ++i) {
346 QModelIndex index = mAttrModel->index(i, 0);
347 Q_ASSERT(index.isValid());
348 mAttrModel->setData(index, QString::fromLatin1(list[i]->type()));
349 index = mAttrModel->index(i, 1);
350 Q_ASSERT(index.isValid());
351 mAttrModel->setData(index, QString::fromLatin1(list[i]->serialized()));
352 mAttrModel->itemFromIndex(index)->setFlags(Qt::ItemIsEditable | mAttrModel->flags(index));
354 contentUi.attrView->setModel(mAttrModel);
356 if (mMonitor) {
357 mMonitor->deleteLater(); // might be the one calling us
359 mMonitor = new Monitor(this);
360 mMonitor->setItemMonitored(item);
361 mMonitor->itemFetchScope().fetchFullPayload();
362 mMonitor->itemFetchScope().fetchAllAttributes();
363 qRegisterMetaType<QSet<QByteArray> >();
364 connect(mMonitor, &Akonadi::Monitor::itemChanged, this, &BrowserWidget::setItem, Qt::QueuedConnection);
365 contentUi.saveButton->setEnabled(false);
368 void BrowserWidget::modelChanged()
370 switch (itemUi.modelBox->currentIndex()) {
371 case 1:
372 mBrowserModel->setItemDisplayMode(AkonadiBrowserModel::MailMode);
373 break;
374 case 2:
375 mBrowserModel->setItemDisplayMode(AkonadiBrowserModel::ContactsMode);
376 break;
377 case 3:
378 mBrowserModel->setItemDisplayMode(AkonadiBrowserModel::CalendarMode);
379 break;
380 default:
381 mBrowserModel->setItemDisplayMode(AkonadiBrowserModel::GenericMode);
385 void BrowserWidget::save()
387 Q_ASSERT(mAttrModel);
389 const QByteArray data = contentUi.dataView->toPlainText().toUtf8();
390 Item item = mCurrentItem;
391 item.setRemoteId(contentUi.remoteId->text());
392 foreach (const Item::Flag &f, mCurrentItem.flags()) {
393 item.clearFlag(f);
395 foreach (const QString &s, contentUi.flags->items()) {
396 item.setFlag(s.toUtf8());
398 foreach (const Tag &tag, mCurrentItem.tags()) {
399 item.clearTag(tag);
401 foreach (const QString &s, contentUi.tags->items()) {
402 Tag tag;
403 tag.setGid(s.toLatin1());
404 item.setTag(tag);
406 item.setPayloadFromData(data);
408 item.clearAttributes();
409 for (int i = 0; i < mAttrModel->rowCount(); ++i) {
410 const QModelIndex typeIndex = mAttrModel->index(i, 0);
411 Q_ASSERT(typeIndex.isValid());
412 const QModelIndex valueIndex = mAttrModel->index(i, 1);
413 Q_ASSERT(valueIndex.isValid());
414 Attribute *attr = AttributeFactory::createAttribute(mAttrModel->data(typeIndex).toString().toLatin1());
415 Q_ASSERT(attr);
416 attr->deserialize(mAttrModel->data(valueIndex).toString().toLatin1());
417 item.addAttribute(attr);
420 ItemModifyJob *store = new ItemModifyJob(item, this);
421 connect(store, &ItemModifyJob::result, this, &BrowserWidget::saveResult);
424 void BrowserWidget::saveResult(KJob *job)
426 if (job->error()) {
427 KMessageBox::error(this, QStringLiteral("Failed to save changes: %1").arg(job->errorString()));
428 } else {
429 contentUi.saveButton->setEnabled(false);
433 void BrowserWidget::addAttribute()
435 if (!mAttrModel || contentUi.attrName->text().isEmpty()) {
436 return;
438 const int row = mAttrModel->rowCount();
439 mAttrModel->insertRow(row);
440 QModelIndex index = mAttrModel->index(row, 0);
441 Q_ASSERT(index.isValid());
442 mAttrModel->setData(index, contentUi.attrName->text());
443 contentUi.attrName->clear();
444 contentUi.saveButton->setEnabled(true);
447 void BrowserWidget::delAttribute()
449 if (!mAttrModel) {
450 return;
452 QModelIndexList selection = contentUi.attrView->selectionModel()->selectedRows();
453 if (selection.count() != 1) {
454 return;
456 mAttrModel->removeRow(selection.first().row());
457 if (mAttrModel->rowCount() == 0) {
458 contentUi.saveButton->setEnabled(false);
462 void BrowserWidget::dumpToXml()
464 const Collection root = currentCollection();
465 if (!root.isValid()) {
466 return;
468 const QString fileName = QFileDialog::getSaveFileName(this, QStringLiteral("Select XML file"), QString(), QStringLiteral("*.xml"));
469 if (fileName.isEmpty()) {
470 return;
472 #if 0 // TODO: port me, can't use XmlWriteJob here, it's in runtime, call the akonadi2xml cli tool instead
473 XmlWriteJob *job = new XmlWriteJob(root, fileName, this);
474 connect(job, &XmlWriteJob::result, this, &BrowserWidget::dumpToXmlResult);
475 #endif
478 void BrowserWidget::dumpToXmlResult(KJob *job)
480 if (job->error()) {
481 KMessageBox::error(this, job->errorString());
485 void BrowserWidget::clearCache()
487 const Collection coll = currentCollection();
488 if (!coll.isValid()) {
489 return;
491 QString str = QStringLiteral("DELETE FROM PimItemTable WHERE collectionId=%1").arg(coll.id());
492 qCDebug(AKONADICONSOLE_LOG) << str;
493 QSqlQuery query(str, DbAccess::database());
494 if (query.exec()) {
495 if (query.lastError().isValid()) {
496 qCDebug(AKONADICONSOLE_LOG) << query.lastError();
497 KMessageBox::error(this, query.lastError().text());
502 Akonadi::Collection BrowserWidget::currentCollection() const
504 return mCollectionView->currentIndex().data(EntityTreeModel::CollectionRole).value<Collection>();
507 void BrowserWidget::updateItemFetchScope()
509 mBrowserMonitor->itemFetchScope().setCacheOnly(mCacheOnlyAction->isChecked());
512 void BrowserWidget::tagViewContextMenuRequested(const QPoint &pos)
514 const QModelIndex index = mTagView->indexAt(pos);
515 QMenu *menu = new QMenu(this);
516 connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater);
517 menu->addAction(QIcon::fromTheme(QStringLiteral("list-add")), QStringLiteral("&Add tag..."), this, SLOT(addTagRequested()));
518 if (index.isValid()) {
519 menu->addAction(QStringLiteral("Add &subtag..."), this, SLOT(addSubTagRequested()));
520 menu->addAction(QIcon::fromTheme(QStringLiteral("document-edit")), QStringLiteral("&Edit tag..."), this, SLOT(editTagRequested()), QKeySequence(Qt::Key_Return));
521 menu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), QStringLiteral("&Delete tag..."), this, SLOT(removeTagRequested()), QKeySequence::Delete);
522 menu->setProperty("Tag", index.data(TagModel::TagRole));
525 menu->popup(mTagView->mapToGlobal(pos));
528 void BrowserWidget::addTagRequested()
530 TagPropertiesDialog *dlg = new TagPropertiesDialog(this);
531 connect(dlg, &TagPropertiesDialog::accepted, this, &BrowserWidget::createTag);
532 connect(dlg, &TagPropertiesDialog::rejected, dlg, &TagPropertiesDialog::deleteLater);
533 dlg->show();
536 void BrowserWidget::addSubTagRequested()
538 QAction *action = qobject_cast<QAction *>(sender());
539 const Akonadi::Tag parentTag = action->parent()->property("Tag").value<Akonadi::Tag>();
541 Akonadi::Tag tag;
542 tag.setParent(parentTag);
544 TagPropertiesDialog *dlg = new TagPropertiesDialog(tag, this);
545 connect(dlg, &TagPropertiesDialog::accepted, this, &BrowserWidget::createTag);
546 connect(dlg, &TagPropertiesDialog::rejected, dlg, &TagPropertiesDialog::deleteLater);
547 dlg->show();
550 void BrowserWidget::editTagRequested()
552 QAction *action = qobject_cast<QAction *>(sender());
553 const Akonadi::Tag tag = action->parent()->property("Tag").value<Akonadi::Tag>();
554 TagPropertiesDialog *dlg = new TagPropertiesDialog(tag, this);
555 connect(dlg, &TagPropertiesDialog::accepted, this, &BrowserWidget::modifyTag);
556 connect(dlg, &TagPropertiesDialog::rejected, dlg, &TagPropertiesDialog::deleteLater);
557 dlg->show();
560 void BrowserWidget::tagViewDoubleClicked(const QModelIndex &index)
562 if (!index.isValid()) {
563 addTagRequested();
564 return;
567 const Akonadi::Tag tag = mTagModel->data(index, TagModel::TagRole).value<Akonadi::Tag>();
568 Q_ASSERT(tag.isValid());
570 TagPropertiesDialog *dlg = new TagPropertiesDialog(tag, this);
571 connect(dlg, &TagPropertiesDialog::accepted, this, &BrowserWidget::modifyTag);
572 connect(dlg, &TagPropertiesDialog::rejected, dlg, &TagPropertiesDialog::deleteLater);
573 dlg->show();
576 void BrowserWidget::removeTagRequested()
578 if (KMessageBox::questionYesNo(this, QStringLiteral("Do you really want to remove selected tag?"),
579 QStringLiteral("Delete tag?"), KStandardGuiItem::del(), KStandardGuiItem::cancel(),
580 QString(), KMessageBox::Dangerous) == KMessageBox::No) {
581 return;
584 QAction *action = qobject_cast<QAction *>(sender());
585 const Akonadi::Tag tag = action->parent()->property("Tag").value<Akonadi::Tag>();
586 new Akonadi::TagDeleteJob(tag, this);
589 void BrowserWidget::createTag()
591 TagPropertiesDialog *dlg = qobject_cast<TagPropertiesDialog *>(sender());
592 Q_ASSERT(dlg);
594 if (dlg->changed()) {
595 new TagCreateJob(dlg->tag(), this);
599 void BrowserWidget::modifyTag()
601 TagPropertiesDialog *dlg = qobject_cast<TagPropertiesDialog *>(sender());
602 Q_ASSERT(dlg);
604 if (dlg->changed()) {
605 new TagModifyJob(dlg->tag(), this);