File indexing completed on 2025-01-05 04:47:09
0001 /* 0002 SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org> 0003 SPDX-FileCopyrightText: 2008 Stephen Kelly <steveire@gmail.com> 0004 SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "entitylistview.h" 0010 0011 #include "dragdropmanager_p.h" 0012 0013 #include <QDragMoveEvent> 0014 #include <QMenu> 0015 0016 #include "akonadiwidgets_debug.h" 0017 #include <KXMLGUIClient> 0018 #include <KXMLGUIFactory> 0019 0020 #include "collection.h" 0021 #include "controlgui.h" 0022 #include "entitytreemodel.h" 0023 #include "item.h" 0024 #include "progressspinnerdelegate_p.h" 0025 0026 using namespace Akonadi; 0027 0028 /** 0029 * @internal 0030 */ 0031 class Akonadi::EntityListViewPrivate 0032 { 0033 public: 0034 explicit EntityListViewPrivate(EntityListView *parent) 0035 : mParent(parent) 0036 #ifndef QT_NO_DRAGANDDROP 0037 , mDragDropManager(new DragDropManager(mParent)) 0038 #endif 0039 { 0040 } 0041 0042 void init(); 0043 void itemClicked(const QModelIndex &index) const; 0044 void itemDoubleClicked(const QModelIndex &index) const; 0045 void itemCurrentChanged(const QModelIndex &index) const; 0046 0047 EntityListView *const mParent; 0048 DragDropManager *mDragDropManager = nullptr; 0049 KXMLGUIClient *mXmlGuiClient = nullptr; 0050 }; 0051 0052 void EntityListViewPrivate::init() 0053 { 0054 mParent->setEditTriggers(QAbstractItemView::EditKeyPressed); 0055 mParent->setAcceptDrops(true); 0056 #ifndef QT_NO_DRAGANDDROP 0057 mParent->setDropIndicatorShown(true); 0058 mParent->setDragDropMode(EntityListView::DragDrop); 0059 mParent->setDragEnabled(true); 0060 #endif 0061 mParent->connect(mParent, &QAbstractItemView::clicked, mParent, [this](const auto &index) { 0062 itemClicked(index); 0063 }); 0064 mParent->connect(mParent, &QAbstractItemView::doubleClicked, mParent, [this](const auto &index) { 0065 itemDoubleClicked(index); 0066 }); 0067 0068 auto animator = new DelegateAnimator(mParent); 0069 auto customDelegate = new ProgressSpinnerDelegate(animator, mParent); 0070 mParent->setItemDelegate(customDelegate); 0071 0072 ControlGui::widgetNeedsAkonadi(mParent); 0073 } 0074 0075 void EntityListViewPrivate::itemClicked(const QModelIndex &index) const 0076 { 0077 if (!index.isValid()) { 0078 return; 0079 } 0080 0081 const auto collection = index.model()->data(index, EntityTreeModel::CollectionRole).value<Collection>(); 0082 if (collection.isValid()) { 0083 Q_EMIT mParent->clicked(collection); 0084 } else { 0085 const Item item = index.model()->data(index, EntityTreeModel::ItemRole).value<Item>(); 0086 if (item.isValid()) { 0087 Q_EMIT mParent->clicked(item); 0088 } 0089 } 0090 } 0091 0092 void EntityListViewPrivate::itemDoubleClicked(const QModelIndex &index) const 0093 { 0094 if (!index.isValid()) { 0095 return; 0096 } 0097 0098 const auto collection = index.model()->data(index, EntityTreeModel::CollectionRole).value<Collection>(); 0099 if (collection.isValid()) { 0100 Q_EMIT mParent->doubleClicked(collection); 0101 } else { 0102 const Item item = index.model()->data(index, EntityTreeModel::ItemRole).value<Item>(); 0103 if (item.isValid()) { 0104 Q_EMIT mParent->doubleClicked(item); 0105 } 0106 } 0107 } 0108 0109 void EntityListViewPrivate::itemCurrentChanged(const QModelIndex &index) const 0110 { 0111 if (!index.isValid()) { 0112 return; 0113 } 0114 0115 const auto collection = index.model()->data(index, EntityTreeModel::CollectionRole).value<Collection>(); 0116 if (collection.isValid()) { 0117 Q_EMIT mParent->currentChanged(collection); 0118 } else { 0119 const Item item = index.model()->data(index, EntityTreeModel::ItemRole).value<Item>(); 0120 if (item.isValid()) { 0121 Q_EMIT mParent->currentChanged(item); 0122 } 0123 } 0124 } 0125 0126 EntityListView::EntityListView(QWidget *parent) 0127 : QListView(parent) 0128 , d(new EntityListViewPrivate(this)) 0129 { 0130 setSelectionMode(QAbstractItemView::SingleSelection); 0131 d->init(); 0132 } 0133 0134 EntityListView::EntityListView(KXMLGUIClient *xmlGuiClient, QWidget *parent) 0135 : QListView(parent) 0136 , d(new EntityListViewPrivate(this)) 0137 { 0138 d->mXmlGuiClient = xmlGuiClient; 0139 d->init(); 0140 } 0141 0142 EntityListView::~EntityListView() 0143 { 0144 delete d->mDragDropManager; 0145 } 0146 0147 void EntityListView::setModel(QAbstractItemModel *model) 0148 { 0149 if (selectionModel()) { 0150 disconnect(selectionModel(), &QItemSelectionModel::currentChanged, this, nullptr); 0151 } 0152 0153 QListView::setModel(model); 0154 0155 connect(selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex &index) { 0156 d->itemCurrentChanged(index); 0157 }); 0158 } 0159 0160 #ifndef QT_NO_DRAGANDDROP 0161 void EntityListView::dragMoveEvent(QDragMoveEvent *event) 0162 { 0163 if (d->mDragDropManager->dropAllowed(event)) { 0164 // All urls are supported. process the event. 0165 QListView::dragMoveEvent(event); 0166 return; 0167 } 0168 0169 event->setDropAction(Qt::IgnoreAction); 0170 } 0171 0172 void EntityListView::dropEvent(QDropEvent *event) 0173 { 0174 bool menuCanceled = false; 0175 if (d->mDragDropManager->processDropEvent(event, menuCanceled) && !menuCanceled) { 0176 QListView::dropEvent(event); 0177 } 0178 } 0179 #endif 0180 0181 #ifndef QT_NO_CONTEXTMENU 0182 void EntityListView::contextMenuEvent(QContextMenuEvent *event) 0183 { 0184 if (!d->mXmlGuiClient) { 0185 return; 0186 } 0187 0188 const QModelIndex index = indexAt(event->pos()); 0189 0190 QMenu *popup = nullptr; 0191 0192 // check if the index under the cursor is a collection or item 0193 const auto collection = model()->data(index, EntityTreeModel::CollectionRole).value<Collection>(); 0194 if (collection.isValid()) { 0195 popup = static_cast<QMenu *>(d->mXmlGuiClient->factory()->container(QStringLiteral("akonadi_favoriteview_contextmenu"), d->mXmlGuiClient)); 0196 } else { 0197 popup = 0198 static_cast<QMenu *>(d->mXmlGuiClient->factory()->container(QStringLiteral("akonadi_favoriteview_emptyselection_contextmenu"), d->mXmlGuiClient)); 0199 } 0200 0201 if (popup) { 0202 popup->exec(event->globalPos()); 0203 } 0204 } 0205 #endif 0206 0207 void EntityListView::setXmlGuiClient(KXMLGUIClient *xmlGuiClient) 0208 { 0209 d->mXmlGuiClient = xmlGuiClient; 0210 } 0211 0212 KXMLGUIClient *EntityListView::xmlGuiClient() const 0213 { 0214 return d->mXmlGuiClient; 0215 } 0216 0217 #ifndef QT_NO_DRAGANDDROP 0218 void EntityListView::startDrag(Qt::DropActions supportedActions) 0219 { 0220 d->mDragDropManager->startDrag(supportedActions); 0221 } 0222 #endif 0223 0224 void EntityListView::setDropActionMenuEnabled(bool enabled) 0225 { 0226 #ifndef QT_NO_DRAGANDDROP 0227 d->mDragDropManager->setShowDropActionMenu(enabled); 0228 #endif 0229 } 0230 0231 bool EntityListView::isDropActionMenuEnabled() const 0232 { 0233 #ifndef QT_NO_DRAGANDDROP 0234 return d->mDragDropManager->showDropActionMenu(); 0235 #else 0236 return false; 0237 #endif 0238 } 0239 0240 #include "moc_entitylistview.cpp"