File indexing completed on 2025-03-09 03:58:53

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-11-24
0007  * Description : Available batch tools 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 #include "toolslistview.h"
0016 
0017 // Qt includes
0018 
0019 #include <QDrag>
0020 #include <QHeaderView>
0021 #include <QMimeData>
0022 #include <QPainter>
0023 #include <QAction>
0024 #include <QMenu>
0025 #include <QIcon>
0026 
0027 // KDE includes
0028 
0029 #include <klocalizedstring.h>
0030 
0031 // Local includes
0032 
0033 #include "dpluginbqm.h"
0034 
0035 namespace Digikam
0036 {
0037 
0038 ToolListViewGroup::ToolListViewGroup(QTreeWidget* const parent, BatchTool::BatchToolGroup group)
0039     : QTreeWidgetItem(parent)
0040 {
0041     setFlags(Qt::ItemIsEnabled);
0042 
0043     setExpanded(true);
0044     setDisabled(false);
0045 
0046     m_group = group;
0047 
0048     switch (m_group)
0049     {
0050         case BatchTool::ColorTool:
0051         {
0052             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0053             setText(0, i18nc("@title: color tools category", "Color"));
0054             break;
0055         }
0056 
0057         case BatchTool::EnhanceTool:
0058         {
0059             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0060             setText(0, i18nc("@title: enhance tools category", "Enhance"));
0061             break;
0062         }
0063 
0064         case BatchTool::TransformTool:
0065         {
0066             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0067             setText(0, i18nc("@title: transform tools category", "Transform"));
0068             break;
0069         }
0070 
0071         case BatchTool::DecorateTool:
0072         {
0073             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0074             setText(0, i18nc("@title: decorate tools category", "Decorate"));
0075             break;
0076         }
0077 
0078         case BatchTool::FiltersTool:
0079         {
0080             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0081             setText(0, i18nc("@title: filters tools category", "Filters"));
0082             break;
0083         }
0084 
0085         case BatchTool::ConvertTool:
0086         {
0087             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0088             setText(0, i18nc("@title: convert tools category", "Convert"));
0089             break;
0090         }
0091 
0092         case BatchTool::MetadataTool:
0093         {
0094             setIcon(0, QIcon::fromTheme(QLatin1String("digikam")));
0095             setText(0, i18nc("@title: metadata tools category", "Metadata"));
0096             break;
0097         }
0098 
0099         default:      // User customized tools.
0100         {
0101             setIcon(0, QIcon::fromTheme(QLatin1String("user-properties")));
0102             setText(0, i18nc("@title: custom tools category", "Custom Tools"));
0103             break;
0104         }
0105     }
0106 }
0107 
0108 ToolListViewGroup::~ToolListViewGroup()
0109 {
0110 }
0111 
0112 BatchTool::BatchToolGroup ToolListViewGroup::toolGroup() const
0113 {
0114     return m_group;
0115 }
0116 
0117 // ---------------------------------------------------------------------------
0118 
0119 ToolListViewItem::ToolListViewItem(ToolListViewGroup* const parent, BatchTool* const tool)
0120     : QTreeWidgetItem(parent)
0121 {
0122     setDisabled(false);
0123     setSelected(false);
0124 
0125     m_tool = tool;
0126 
0127     if (m_tool)
0128     {
0129         setIcon(0, m_tool->toolIcon());
0130         setText(0, m_tool->toolTitle());
0131         setText(1, m_tool->toolDescription());
0132     }
0133 }
0134 
0135 ToolListViewItem::~ToolListViewItem()
0136 {
0137 }
0138 
0139 BatchTool* ToolListViewItem::tool() const
0140 {
0141     return m_tool;
0142 }
0143 
0144 // ---------------------------------------------------------------------------
0145 
0146 ToolsListView::ToolsListView(QWidget* const parent)
0147     : QTreeWidget(parent)
0148 {
0149     setContextMenuPolicy(Qt::CustomContextMenu);
0150     setIconSize(QSize(22, 22));
0151     setSelectionMode(QAbstractItemView::ExtendedSelection);
0152     setSortingEnabled(false);
0153     setUniformRowHeights(true);
0154     setAllColumnsShowFocus(true);
0155     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0156     setColumnCount(2);
0157     setHeaderHidden(true);
0158     setDragEnabled(true);
0159     header()->setSectionResizeMode(QHeaderView::Stretch);
0160 
0161     connect(this, SIGNAL(customContextMenuRequested(QPoint)),
0162             this, SLOT(slotContextMenu()));
0163 }
0164 
0165 ToolsListView::~ToolsListView()
0166 {
0167 }
0168 
0169 BatchToolsList ToolsListView::toolsList()
0170 {
0171     BatchToolsList list;
0172 
0173     QTreeWidgetItemIterator it(this);
0174 
0175     while (*it)
0176     {
0177         ToolListViewItem* const item = dynamic_cast<ToolListViewItem*>(*it);
0178 
0179         if (item)
0180         {
0181             list.append(item->tool());
0182         }
0183 
0184         ++it;
0185     }
0186 
0187     return list;
0188 }
0189 
0190 void ToolsListView::addTool(BatchTool* const tool)
0191 {
0192     if (!tool)
0193     {
0194         return;
0195     }
0196 
0197     ToolListViewGroup* const parent = findToolGroup(tool->toolGroup());
0198 
0199     if (parent)
0200     {
0201         ToolListViewItem* const item = new ToolListViewItem(parent, tool);
0202 
0203         connect(tool, SIGNAL(signalVisible(bool)),
0204                 this, SLOT(slotToolVisible(bool)));
0205 
0206         item->setHidden(!tool->plugin()->shouldLoaded());
0207     }
0208 }
0209 
0210 void ToolsListView::slotToolVisible(bool b)
0211 {
0212     BatchTool* const tool = dynamic_cast<BatchTool*>(sender());
0213 
0214     if (tool)
0215     {
0216         ToolListViewItem* const item = findTool(tool);
0217 
0218         if (item)
0219         {
0220             item->setHidden(!b);
0221         }
0222     }
0223 }
0224 
0225 bool ToolsListView::removeTool(BatchTool* const tool)
0226 {
0227     QTreeWidgetItemIterator it(this);
0228 
0229     while (*it)
0230     {
0231         ToolListViewItem* const item = dynamic_cast<ToolListViewItem*>(*it);
0232 
0233         if (item && (item->tool() == tool))
0234         {
0235             delete item;
0236 
0237             return true;
0238         }
0239 
0240         ++it;
0241     }
0242 
0243     return false;
0244 }
0245 
0246 ToolListViewGroup* ToolsListView::findToolGroup(BatchTool::BatchToolGroup group)
0247 {
0248     QTreeWidgetItemIterator it(this);
0249 
0250     while (*it)
0251     {
0252         ToolListViewGroup* const item = dynamic_cast<ToolListViewGroup*>(*it);
0253 
0254         if (item && (item->toolGroup() == group))
0255         {
0256             return item;
0257         }
0258 
0259         ++it;
0260     }
0261 
0262     return nullptr;
0263 }
0264 
0265 bool ToolsListView::hasTool(BatchTool* const tool)
0266 {
0267     return (findTool(tool) ? true : false);
0268 }
0269 
0270 ToolListViewItem* ToolsListView::findTool(BatchTool* const tool)
0271 {
0272     QTreeWidgetItemIterator it(this);
0273 
0274     while (*it)
0275     {
0276         ToolListViewItem* const item = dynamic_cast<ToolListViewItem*>(*it);
0277 
0278         if (item && (item->tool() == tool))
0279         {
0280             return item;
0281         }
0282 
0283         ++it;
0284     }
0285 
0286     return nullptr;
0287 }
0288 
0289 void ToolsListView::startDrag(Qt::DropActions /*supportedActions*/)
0290 {
0291     QList<QTreeWidgetItem*> items = selectedItems();
0292 
0293     if (items.isEmpty())
0294     {
0295         return;
0296     }
0297 
0298     QPixmap icon(QIcon::fromTheme(QLatin1String("system-run")).pixmap(48));
0299     int w = icon.width();
0300     int h = icon.height();
0301 
0302     QPixmap pix(w + 4, h + 4);
0303     QString text(QString::number(items.count()));
0304 
0305     QPainter p(&pix);
0306     p.fillRect(0, 0, pix.width() - 1, pix.height() - 1, QColor(Qt::white));
0307     p.setPen(QPen(Qt::black, 1));
0308     p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
0309     p.drawPixmap(2, 2, icon);
0310     QRect r     = p.boundingRect(2, 2, w, h, Qt::AlignLeft | Qt::AlignTop, text);
0311     r.setWidth(qMax(r.width(), r.height()));
0312     r.setHeight(qMax(r.width(), r.height()));
0313     p.fillRect(r, QColor(0, 80, 0));
0314     p.setPen(Qt::white);
0315     QFont f(font());
0316     f.setBold(true);
0317     p.setFont(f);
0318     p.drawText(r, Qt::AlignCenter, text);
0319     p.end();
0320 
0321     QDrag* drag = new QDrag(this);
0322     drag->setMimeData(mimeData(items));
0323     drag->setPixmap(pix);
0324     drag->exec();
0325 }
0326 
0327 QStringList ToolsListView::mimeTypes() const
0328 {
0329     QStringList types;
0330     types << QLatin1String("digikam/batchtoolslist");
0331 
0332     return types;
0333 }
0334 
0335 void ToolsListView::mouseDoubleClickEvent(QMouseEvent*)
0336 {
0337     if (viewport()->isEnabled())
0338     {
0339         slotAssignTools();
0340     }
0341 }
0342 
0343 void ToolsListView::slotAssignTools()
0344 {
0345     QList<QTreeWidgetItem*> items = selectedItems();
0346 
0347     if (items.isEmpty())
0348     {
0349         return;
0350     }
0351 
0352     QMultiMap<int, QString> map = itemsToMap(items);
0353 
0354     Q_EMIT signalAssignTools(map);
0355 }
0356 
0357 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0358 
0359 QMimeData* ToolsListView::mimeData(const QList<QTreeWidgetItem*>& items) const
0360 
0361 #else
0362 
0363 // cppcheck-suppress passedByValue
0364 QMimeData* ToolsListView::mimeData(const QList<QTreeWidgetItem*> items) const    // clazy:exclude=function-args-by-ref
0365 
0366 #endif
0367 
0368 {
0369     QMimeData* const mimeData   = new QMimeData();
0370     QByteArray encodedData;
0371 
0372     QDataStream stream(&encodedData, QIODevice::WriteOnly);
0373     QMultiMap<int, QString> map = itemsToMap(items);
0374     stream << map;
0375 
0376     mimeData->setData(QLatin1String("digikam/batchtoolslist"), encodedData);
0377 
0378     return mimeData;
0379 }
0380 
0381 QMultiMap<int, QString> ToolsListView::itemsToMap(const QList<QTreeWidgetItem*>& items) const
0382 {
0383     QMultiMap<int, QString> map;
0384 
0385     Q_FOREACH (QTreeWidgetItem* const itm, items)
0386     {
0387         ToolListViewItem* const tlwi = dynamic_cast<ToolListViewItem*>(itm);
0388 
0389         if (tlwi)
0390         {
0391             map.insert((int)(tlwi->tool()->toolGroup()), tlwi->tool()->objectName());
0392         }
0393     }
0394 
0395     return map;
0396 }
0397 
0398 void ToolsListView::slotContextMenu()
0399 {
0400     QMenu popmenu(this);
0401     QAction* const action = new QAction(QIcon::fromTheme(QLatin1String("list-add")), i18nc("@action", "Assign tools"), this);
0402 
0403     connect(action, SIGNAL(triggered(bool)),
0404             this, SLOT(slotAssignTools()));
0405 
0406     popmenu.addAction(action);
0407     popmenu.exec(QCursor::pos());
0408 }
0409 
0410 } // namespace Digikam
0411 
0412 #include "moc_toolslistview.cpp"