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
20 #include "browserwidget.h"
22 #include "collectionattributespage.h"
23 #include "collectioninternalspage.h"
24 #include "collectionaclpage.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"
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>
70 #include <QVBoxLayout>
71 #include <QStandardItemModel>
75 #include <KSharedConfig>
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
) :
89 mAttrModel(Q_NULLPTR
),
90 mStdActionManager(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()) {
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
);
279 qCWarning(AKONADICONSOLE_LOG
) << "Item fetch failed: " << job
->errorString();
280 } else if (fetch
->items().isEmpty()) {
281 qCWarning(AKONADICONSOLE_LOG
) << "No item found!";
283 const Item item
= fetch
->items().first();
288 void BrowserWidget::contentViewChanged()
290 contentUi
.saveButton
->setEnabled(true);
293 void BrowserWidget::setItem(const Akonadi::Item
&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
);
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"));
328 foreach (const Item::Flag
&f
, item
.flags()) {
329 flags
<< QString::fromUtf8(f
);
331 contentUi
.flags
->setItems(flags
);
334 foreach (const Tag
&tag
, item
.tags()) {
335 tags
<< QLatin1String(tag
.gid());
337 contentUi
.tags
->setItems(tags
);
339 Attribute::List list
= item
.attributes();
341 mAttrModel
= new QStandardItemModel(list
.count(), 2);
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
);
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()) {
372 mBrowserModel
->setItemDisplayMode(AkonadiBrowserModel::MailMode
);
375 mBrowserModel
->setItemDisplayMode(AkonadiBrowserModel::ContactsMode
);
378 mBrowserModel
->setItemDisplayMode(AkonadiBrowserModel::CalendarMode
);
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()) {
395 foreach (const QString
&s
, contentUi
.flags
->items()) {
396 item
.setFlag(s
.toUtf8());
398 foreach (const Tag
&tag
, mCurrentItem
.tags()) {
401 foreach (const QString
&s
, contentUi
.tags
->items()) {
403 tag
.setGid(s
.toLatin1());
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());
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
)
427 KMessageBox::error(this, QStringLiteral("Failed to save changes: %1").arg(job
->errorString()));
429 contentUi
.saveButton
->setEnabled(false);
433 void BrowserWidget::addAttribute()
435 if (!mAttrModel
|| contentUi
.attrName
->text().isEmpty()) {
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()
452 QModelIndexList selection
= contentUi
.attrView
->selectionModel()->selectedRows();
453 if (selection
.count() != 1) {
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()) {
468 const QString fileName
= QFileDialog::getSaveFileName(this, QStringLiteral("Select XML file"), QString(), QStringLiteral("*.xml"));
469 if (fileName
.isEmpty()) {
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
);
478 void BrowserWidget::dumpToXmlResult(KJob
*job
)
481 KMessageBox::error(this, job
->errorString());
485 void BrowserWidget::clearCache()
487 const Collection coll
= currentCollection();
488 if (!coll
.isValid()) {
491 QString str
= QStringLiteral("DELETE FROM PimItemTable WHERE collectionId=%1").arg(coll
.id());
492 qCDebug(AKONADICONSOLE_LOG
) << str
;
493 QSqlQuery
query(str
, DbAccess::database());
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
);
536 void BrowserWidget::addSubTagRequested()
538 QAction
*action
= qobject_cast
<QAction
*>(sender());
539 const Akonadi::Tag parentTag
= action
->parent()->property("Tag").value
<Akonadi::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
);
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
);
560 void BrowserWidget::tagViewDoubleClicked(const QModelIndex
&index
)
562 if (!index
.isValid()) {
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
);
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
) {
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());
594 if (dlg
->changed()) {
595 new TagCreateJob(dlg
->tag(), this);
599 void BrowserWidget::modifyTag()
601 TagPropertiesDialog
*dlg
= qobject_cast
<TagPropertiesDialog
*>(sender());
604 if (dlg
->changed()) {
605 new TagModifyJob(dlg
->tag(), this);