File indexing completed on 2025-03-09 03:58:51
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2008-11-21 0007 * Description : Batch Queue Manager items list. 0008 * 0009 * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #define ICONSIZE 32 0016 0017 #include "assignedlist.h" 0018 0019 // Qt includes 0020 0021 #include <QDragEnterEvent> 0022 #include <QFileInfo> 0023 #include <QHeaderView> 0024 #include <QPainter> 0025 #include <QUrl> 0026 #include <QMimeData> 0027 #include <QAction> 0028 #include <QMenu> 0029 0030 // KDE includes 0031 0032 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU) 0033 # pragma GCC diagnostic push 0034 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 0035 #endif 0036 0037 #if defined(Q_CC_CLANG) 0038 # pragma clang diagnostic push 0039 # pragma clang diagnostic ignored "-Wdeprecated-declarations" 0040 #endif 0041 0042 #include <kactioncollection.h> 0043 #include <klocalizedstring.h> 0044 0045 // Restore warnings 0046 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU) 0047 # pragma GCC diagnostic pop 0048 #endif 0049 0050 #if defined(Q_CC_CLANG) 0051 # pragma clang diagnostic pop 0052 #endif 0053 0054 // Local includes 0055 0056 #include "digikam_debug.h" 0057 #include "queuemgrwindow.h" 0058 #include "queuesettingsview.h" 0059 #include "toolslistview.h" 0060 #include "batchtoolsfactory.h" 0061 0062 namespace Digikam 0063 { 0064 0065 AssignedListViewItem::AssignedListViewItem(QTreeWidget* const parent) 0066 : QTreeWidgetItem(parent) 0067 { 0068 setFlags(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | flags()); 0069 } 0070 0071 AssignedListViewItem::AssignedListViewItem(QTreeWidget* const parent, QTreeWidgetItem* const preceding) 0072 : QTreeWidgetItem(parent, preceding) 0073 { 0074 setFlags(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | flags()); 0075 } 0076 0077 AssignedListViewItem::~AssignedListViewItem() 0078 { 0079 } 0080 0081 void AssignedListViewItem::setToolSet(const BatchToolSet& set) 0082 { 0083 m_set = set; 0084 setIndex(m_set.index); 0085 0086 BatchTool* const tool = BatchToolsFactory::instance()->findTool(m_set.name, m_set.group); 0087 0088 if (tool) 0089 { 0090 setIcon(1, tool->toolIcon()); 0091 setText(1, tool->toolTitle()); 0092 } 0093 } 0094 0095 BatchToolSet AssignedListViewItem::toolSet() 0096 { 0097 return m_set; 0098 } 0099 0100 void AssignedListViewItem::setIndex(int index) 0101 { 0102 m_set.index = index; 0103 setText(0, QString::fromUtf8("%1").arg(m_set.index + 1)); 0104 } 0105 0106 // --------------------------------------------------------------------------- 0107 0108 AssignedListView::AssignedListView(QWidget* const parent) 0109 : QTreeWidget(parent) 0110 { 0111 setSelectionMode(QAbstractItemView::SingleSelection); 0112 setWhatsThis(i18n("This is the list of batch tools assigned.")); 0113 setIconSize(QSize(ICONSIZE, ICONSIZE)); 0114 0115 setDragEnabled(true); 0116 setAcceptDrops(true); 0117 viewport()->setAcceptDrops(true); 0118 setDropIndicatorShown(true); 0119 0120 setContextMenuPolicy(Qt::CustomContextMenu); 0121 setSortingEnabled(false); 0122 setRootIsDecorated(false); 0123 setUniformRowHeights(true); 0124 setAllColumnsShowFocus(true); 0125 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0126 setColumnCount(2); 0127 setHeaderHidden(true); 0128 header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0129 0130 connect(this, SIGNAL(itemSelectionChanged()), 0131 this, SLOT(slotSelectionChanged())); 0132 0133 connect(this, SIGNAL(customContextMenuRequested(QPoint)), 0134 this, SLOT(slotContextMenu())); 0135 } 0136 0137 AssignedListView::~AssignedListView() 0138 { 0139 } 0140 0141 void AssignedListView::keyPressEvent(QKeyEvent* e) 0142 { 0143 if (e->key() == Qt::Key_Delete) 0144 { 0145 slotRemoveCurrentTool(); 0146 } 0147 else 0148 { 0149 QTreeWidget::keyPressEvent(e); 0150 } 0151 } 0152 0153 void AssignedListView::setBusy(bool b) 0154 { 0155 viewport()->setEnabled(!b); 0156 } 0157 0158 AssignedBatchTools AssignedListView::assignedList() 0159 { 0160 BatchSetList list; 0161 QTreeWidgetItemIterator it(this); 0162 0163 while (*it) 0164 { 0165 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(*it); 0166 0167 if (item) 0168 { 0169 list.append(item->toolSet()); 0170 } 0171 0172 ++it; 0173 } 0174 0175 AssignedBatchTools tools; 0176 tools.m_toolsList = list; 0177 0178 return tools; 0179 } 0180 0181 int AssignedListView::assignedCount() 0182 { 0183 return assignedList().m_toolsList.count(); 0184 } 0185 0186 void AssignedListView::slotRemoveCurrentTool() 0187 { 0188 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(currentItem()); 0189 0190 if (item) 0191 { 0192 delete item; 0193 refreshIndex(); 0194 Q_EMIT signalAssignedToolsChanged(assignedList()); 0195 } 0196 0197 if (assignedCount() == 0) 0198 { 0199 Q_EMIT signalToolSelected(BatchToolSet()); 0200 } 0201 } 0202 0203 void AssignedListView::slotClearToolsList() 0204 { 0205 clear(); 0206 Q_EMIT signalAssignedToolsChanged(assignedList()); 0207 Q_EMIT signalToolSelected(BatchToolSet()); 0208 } 0209 0210 void AssignedListView::slotMoveCurrentToolUp() 0211 { 0212 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(currentItem()); 0213 0214 if (item) 0215 { 0216 AssignedListViewItem* const iabove = dynamic_cast<AssignedListViewItem*>(itemAbove(item)); 0217 0218 if (iabove) 0219 { 0220 moveTool(item, iabove->toolSet()); 0221 setCurrentItem(item); 0222 } 0223 } 0224 } 0225 0226 void AssignedListView::slotMoveCurrentToolDown() 0227 { 0228 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(currentItem()); 0229 0230 if (item) 0231 { 0232 AssignedListViewItem* const ibelow = dynamic_cast<AssignedListViewItem*>(itemBelow(item)); 0233 0234 if (ibelow) 0235 { 0236 AssignedListViewItem* const nitem = moveTool(ibelow, item->toolSet()); 0237 setCurrentItem(nitem); 0238 } 0239 } 0240 } 0241 0242 AssignedListViewItem* AssignedListView::moveTool(AssignedListViewItem* const preceding, const BatchToolSet& set) 0243 { 0244 BatchTool* const tool = BatchToolsFactory::instance()->findTool(set.name, set.group); 0245 0246 if (!tool) 0247 { 0248 return nullptr; 0249 } 0250 0251 removeTool(set); 0252 AssignedListViewItem* const item = insertTool(preceding, set); 0253 refreshIndex(); 0254 0255 Q_EMIT signalAssignedToolsChanged(assignedList()); 0256 0257 return item; 0258 } 0259 0260 AssignedListViewItem* AssignedListView::insertTool(AssignedListViewItem* const preceding, const BatchToolSet& set) 0261 { 0262 AssignedListViewItem* item = nullptr; 0263 0264 if (preceding) 0265 { 0266 item = new AssignedListViewItem(this, preceding); 0267 } 0268 else 0269 { 0270 item = new AssignedListViewItem(this); 0271 } 0272 0273 BatchTool* const tool = BatchToolsFactory::instance()->findTool(set.name, set.group); 0274 0275 // NOTE: Only now create the settings widget when needed. 0276 0277 if (tool && !tool->settingsWidget()) 0278 { 0279 tool->registerSettingsWidget(); 0280 } 0281 0282 item->setToolSet(set); 0283 refreshIndex(); 0284 0285 Q_EMIT signalAssignedToolsChanged(assignedList()); 0286 0287 return item; 0288 } 0289 0290 AssignedListViewItem* AssignedListView::addTool(const BatchToolSet& set) 0291 { 0292 return insertTool(nullptr, set); 0293 } 0294 0295 bool AssignedListView::removeTool(const BatchToolSet& set) 0296 { 0297 QTreeWidgetItemIterator it(this); 0298 0299 while (*it) 0300 { 0301 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(*it); 0302 0303 if (item && (item->toolSet() == set)) 0304 { 0305 delete item; 0306 refreshIndex(); 0307 return true; 0308 } 0309 0310 ++it; 0311 } 0312 0313 return false; 0314 } 0315 0316 AssignedListViewItem* AssignedListView::findTool(const BatchToolSet& set) 0317 { 0318 QTreeWidgetItemIterator it(this); 0319 0320 while (*it) 0321 { 0322 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(*it); 0323 0324 if (item && (item->toolSet() == set)) 0325 { 0326 return item; 0327 } 0328 0329 ++it; 0330 } 0331 0332 return nullptr; 0333 } 0334 0335 Qt::DropActions AssignedListView::supportedDropActions() const 0336 { 0337 return (Qt::CopyAction | Qt::MoveAction); 0338 } 0339 0340 QStringList AssignedListView::mimeTypes() const 0341 { 0342 QStringList types; 0343 types << QLatin1String("digikam/assignedbatchtool"); 0344 0345 return types; 0346 } 0347 0348 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0349 0350 QMimeData* AssignedListView::mimeData(const QList<QTreeWidgetItem*>& items) const 0351 0352 #else 0353 0354 // cppcheck-suppress passedByValue 0355 QMimeData* AssignedListView::mimeData(const QList<QTreeWidgetItem*> items) const // clazy:exclude=function-args-by-ref 0356 0357 #endif 0358 0359 { 0360 QMimeData* const mimeData = new QMimeData(); 0361 QByteArray encodedData; 0362 0363 QDataStream stream(&encodedData, QIODevice::WriteOnly); 0364 stream << items.count(); 0365 0366 Q_FOREACH (QTreeWidgetItem* const itm, items) 0367 { 0368 AssignedListViewItem* const alwi = dynamic_cast<AssignedListViewItem*>(itm); 0369 0370 if (alwi) 0371 { 0372 stream << (int)(alwi->toolSet().group); 0373 stream << alwi->toolSet().name; 0374 stream << alwi->toolSet().index; 0375 stream << alwi->toolSet().version; 0376 stream << alwi->toolSet().settings; 0377 } 0378 } 0379 0380 mimeData->setData(QLatin1String("digikam/assignedbatchtool"), encodedData); 0381 0382 return mimeData; 0383 } 0384 0385 void AssignedListView::dragEnterEvent(QDragEnterEvent* e) 0386 { 0387 QTreeWidget::dragEnterEvent(e); 0388 e->accept(); 0389 } 0390 0391 void AssignedListView::dragMoveEvent(QDragMoveEvent* e) 0392 { 0393 if (e->mimeData()->formats().contains(QLatin1String("digikam/batchtoolslist")) || 0394 e->mimeData()->formats().contains(QLatin1String("digikam/assignedbatchtool"))) 0395 { 0396 QTreeWidget::dragMoveEvent(e); 0397 e->accept(); 0398 0399 return; 0400 } 0401 0402 e->ignore(); 0403 } 0404 0405 void AssignedListView::dropEvent(QDropEvent* e) 0406 { 0407 if (e->mimeData()->formats().contains(QLatin1String("digikam/batchtoolslist"))) 0408 { 0409 QByteArray ba = e->mimeData()->data(QLatin1String("digikam/batchtoolslist")); 0410 0411 if (ba.size()) 0412 { 0413 QDataStream ds(ba); 0414 QMultiMap<int, QString> map; 0415 ds >> map; 0416 0417 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0418 0419 AssignedListViewItem* const preceding = dynamic_cast<AssignedListViewItem*>(itemAt(e->position().toPoint())); 0420 0421 #else 0422 0423 AssignedListViewItem* const preceding = dynamic_cast<AssignedListViewItem*>(itemAt(e->pos())); 0424 0425 #endif 0426 0427 assignTools(map, preceding); 0428 } 0429 0430 e->acceptProposedAction(); 0431 } 0432 else if (e->mimeData()->formats().contains(QLatin1String("digikam/assignedbatchtool"))) 0433 { 0434 QByteArray ba = e->mimeData()->data(QLatin1String("digikam/assignedbatchtool")); 0435 0436 if (ba.size()) 0437 { 0438 int count; 0439 QDataStream ds(ba); 0440 ds >> count; 0441 0442 for (int i = 0 ; i < count ; ++i) 0443 { 0444 int group, index, version; 0445 QString name; 0446 BatchToolSettings settings; 0447 0448 ds >> group; 0449 ds >> name; 0450 ds >> index; 0451 ds >> version; 0452 ds >> settings; 0453 0454 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0455 0456 AssignedListViewItem* const preceding = dynamic_cast<AssignedListViewItem*>(itemAt(e->position().toPoint())); 0457 0458 #else 0459 0460 AssignedListViewItem* const preceding = dynamic_cast<AssignedListViewItem*>(itemAt(e->pos())); 0461 0462 #endif 0463 0464 BatchToolSet set; 0465 set.name = name; 0466 set.group = (BatchTool::BatchToolGroup)group; 0467 set.index = index; 0468 set.version = version; 0469 set.settings = settings; 0470 AssignedListViewItem* const item = moveTool(preceding, set); 0471 setCurrentItem(item); 0472 } 0473 } 0474 0475 e->acceptProposedAction(); 0476 } 0477 else 0478 { 0479 e->ignore(); 0480 } 0481 } 0482 0483 void AssignedListView::slotSelectionChanged() 0484 { 0485 QList<QTreeWidgetItem*> list = selectedItems(); 0486 0487 if (list.isEmpty()) 0488 { 0489 return; 0490 } 0491 0492 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(list.first()); 0493 0494 if (item) 0495 { 0496 BatchToolSet set = item->toolSet(); 0497 Q_EMIT signalToolSelected(set); 0498 } 0499 else 0500 { 0501 Q_EMIT signalToolSelected(BatchToolSet()); 0502 } 0503 } 0504 0505 void AssignedListView::slotQueueSelected(int, const QueueSettings&, const AssignedBatchTools& tools) 0506 { 0507 // Clear assigned tools list and tool settings view. 0508 0509 clear(); 0510 Q_EMIT signalToolSelected(BatchToolSet()); 0511 0512 if (!tools.m_toolsList.isEmpty()) 0513 { 0514 blockSignals(true); 0515 0516 Q_FOREACH (const BatchToolSet& set, tools.m_toolsList) 0517 { 0518 addTool(set); 0519 } 0520 0521 blockSignals(false); 0522 } 0523 } 0524 0525 void AssignedListView::slotSettingsChanged(const BatchToolSet& set) 0526 { 0527 AssignedListViewItem* const item = findTool(set); 0528 0529 if (item) 0530 { 0531 item->setToolSet(set); 0532 Q_EMIT signalAssignedToolsChanged(assignedList()); 0533 } 0534 } 0535 0536 void AssignedListView::slotAssignTools(const QMultiMap<int, QString>& map) 0537 { 0538 if (map.isEmpty()) 0539 { 0540 return; 0541 } 0542 0543 assignTools(map, nullptr); 0544 } 0545 0546 void AssignedListView::assignTools(const QMultiMap<int, QString>& map, AssignedListViewItem* const preceding) 0547 { 0548 // We pop all items in reverse order to have same order than selection from Batch Tools list. 0549 0550 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0551 0552 QMultiMapIterator<int, QString> it(map); 0553 0554 #else 0555 0556 QMapIterator<int, QString> it(map); 0557 0558 #endif 0559 0560 it.toBack(); 0561 0562 while (it.hasPrevious()) 0563 { 0564 it.previous(); 0565 BatchTool::BatchToolGroup group = (BatchTool::BatchToolGroup)(it.key()); 0566 QString name = it.value(); 0567 BatchTool* const tool = BatchToolsFactory::instance()->findTool(name, group); 0568 0569 if (tool) 0570 { 0571 // NOTE: Only now create the settings widget when needed. 0572 0573 if (!tool->settingsWidget()) 0574 { 0575 tool->registerSettingsWidget(); 0576 } 0577 0578 BatchToolSet set; 0579 set.name = tool->objectName(); 0580 set.group = tool->toolGroup(); 0581 set.version = tool->toolVersion(); 0582 set.settings = tool->defaultSettings(); 0583 AssignedListViewItem* const item = insertTool(preceding, set); 0584 setCurrentItem(item); 0585 } 0586 } 0587 } 0588 0589 void AssignedListView::slotContextMenu() 0590 { 0591 if (!viewport()->isEnabled()) 0592 { 0593 return; 0594 } 0595 0596 KActionCollection* const acol = QueueMgrWindow::queueManagerWindow()->actionCollection(); 0597 QMenu popmenu(this); 0598 popmenu.addAction(acol->action(QLatin1String("queuemgr_toolup"))); 0599 popmenu.addAction(acol->action(QLatin1String("queuemgr_tooldown"))); 0600 popmenu.addAction(acol->action(QLatin1String("queuemgr_toolremove"))); 0601 popmenu.addSeparator(); 0602 popmenu.addAction(acol->action(QLatin1String("queuemgr_savequeue"))); 0603 popmenu.addAction(acol->action(QLatin1String("queuemgr_toolsclear"))); 0604 popmenu.exec(QCursor::pos()); 0605 } 0606 0607 void AssignedListView::refreshIndex() 0608 { 0609 QTreeWidgetItemIterator it(this); 0610 0611 while (*it) 0612 { 0613 AssignedListViewItem* const item = dynamic_cast<AssignedListViewItem*>(*it); 0614 0615 if (item) 0616 { 0617 item->setIndex(indexOfTopLevelItem(item)); 0618 } 0619 0620 ++it; 0621 } 0622 } 0623 0624 } // namespace Digikam 0625 0626 #include "moc_assignedlist.cpp"