File indexing completed on 2025-01-05 03:57:57

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2021-09-27
0007  * Description : Showfoto stack view favorites list
0008  *
0009  * SPDX-FileCopyrightText: 2021-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 "showfotostackviewfavoritelist.h"
0016 
0017 // Qt includes
0018 
0019 #include <QHeaderView>
0020 #include <QMimeData>
0021 #include <QFileInfo>
0022 #include <QDir>
0023 #include <QDrag>
0024 #include <QMenu>
0025 #include <QMimeType>
0026 #include <QMimeDatabase>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 
0032 // Local include
0033 
0034 #include "digikam_debug.h"
0035 #include "digikam_globals.h"
0036 #include "showfotostackviewfavorites.h"
0037 #include "showfotostackviewfavoriteitem.h"
0038 #include "dfileoperations.h"
0039 #include "drawdecoder.h"
0040 
0041 using namespace Digikam;
0042 
0043 namespace ShowFoto
0044 {
0045 
0046 class Q_DECL_HIDDEN ShowfotoStackViewFavoriteList::Private
0047 {
0048 public:
0049 
0050     explicit Private()
0051         : parent     (nullptr),
0052           draggedItem(nullptr)
0053     {
0054     }
0055 
0056 public:
0057 
0058     ShowfotoStackViewFavorites* parent;
0059     QTreeWidgetItem*            draggedItem;
0060     QString                     filter;
0061 };
0062 
0063 ShowfotoStackViewFavoriteList::ShowfotoStackViewFavoriteList(ShowfotoStackViewFavorites* const parent)
0064     : QTreeWidget(parent),
0065       d          (new Private)
0066 {
0067     d->parent = parent;
0068 
0069     setWhatsThis(i18nc("@info", "You can add or remove favorite stacks here."));
0070     setAlternatingRowColors(true);
0071     setColumnCount(1);
0072     setSortingEnabled(true);
0073     setUniformRowHeights(true);
0074     setAllColumnsShowFocus(true);
0075     sortByColumn(0, Qt::AscendingOrder);
0076     setSelectionMode(QAbstractItemView::SingleSelection);
0077     setHeaderHidden(true);
0078     header()->setSectionResizeMode(QHeaderView::Stretch);
0079     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0080     setContextMenuPolicy(Qt::CustomContextMenu);
0081 
0082     setAcceptDrops(true);
0083     setDragEnabled(true);
0084     setDragDropMode(QAbstractItemView::InternalMove);
0085     setDropIndicatorShown(true);
0086     viewport()->setAcceptDrops(true);
0087     viewport()->setMouseTracking(true);
0088 
0089     connect(this, SIGNAL(customContextMenuRequested(QPoint)),
0090             this, SLOT(slotContextMenu(QPoint)));
0091 }
0092 
0093 ShowfotoStackViewFavoriteList::~ShowfotoStackViewFavoriteList()
0094 {
0095     delete d;
0096 }
0097 
0098 void ShowfotoStackViewFavoriteList::slotOpenInFileManager()
0099 {
0100     ShowfotoStackViewFavoriteItem* const fvitem = dynamic_cast<ShowfotoStackViewFavoriteItem*>(currentItem());
0101 
0102     if (fvitem)
0103     {
0104         DFileOperations::openInFileManager(fvitem->urls());
0105     }
0106 }
0107 
0108 void ShowfotoStackViewFavoriteList::slotLoadContents()
0109 {
0110     ShowfotoStackViewFavoriteItem* const fvitem = dynamic_cast<ShowfotoStackViewFavoriteItem*>(currentItem());
0111 
0112     if (fvitem)
0113     {
0114         Q_EMIT signalLoadContentsFromFiles(fvitem->urlsToPaths(), fvitem->currentUrl().toLocalFile());
0115     }
0116 }
0117 
0118 void ShowfotoStackViewFavoriteList::slotContextMenu(const QPoint& pos)
0119 {
0120     QMenu* const ctxmenu        = new QMenu(this);
0121     ctxmenu->setTitle(i18nc("@title", "Favorites"));
0122     ctxmenu->addAction(d->parent->toolBarAction(QLatin1String("AddFavorite")));
0123     ctxmenu->addAction(d->parent->toolBarAction(QLatin1String("AddFolder")));
0124 
0125     ShowfotoStackViewFavoriteItem* const fvitem = dynamic_cast<ShowfotoStackViewFavoriteItem*>(itemAt(pos));
0126 
0127     if (fvitem)
0128     {
0129         if (fvitem->favoriteType() != ShowfotoStackViewFavoriteItem::FavoriteRoot)
0130         {
0131             ctxmenu->addAction(d->parent->toolBarAction(QLatin1String("DelItem")));
0132             ctxmenu->addAction(d->parent->toolBarAction(QLatin1String("EditItem")));
0133         }
0134 
0135         ctxmenu->addSeparator();
0136 
0137         if (fvitem->favoriteType() == ShowfotoStackViewFavoriteItem::FavoriteItem)
0138         {
0139             ctxmenu->addActions(d->parent->pluginActions());
0140             ctxmenu->addSeparator();
0141 
0142             QAction* const loadContents = new QAction(QIcon::fromTheme(QLatin1String("media-playlist-normal")),
0143                                                       i18nc("@action: context menu", "Load Contents"), ctxmenu);
0144             ctxmenu->addAction(loadContents);
0145 
0146             connect(loadContents, SIGNAL(triggered()),
0147                     this, SLOT(slotLoadContents()));
0148 
0149             QAction* const openFileMngr = new QAction(QIcon::fromTheme(QLatin1String("folder-open")),
0150                                                       i18nc("@action: context menu", "Open in File Manager"), ctxmenu);
0151             ctxmenu->addAction(openFileMngr);
0152 
0153             connect(openFileMngr, SIGNAL(triggered()),
0154                     this, SLOT(slotOpenInFileManager()));
0155         }
0156     }
0157 
0158     ctxmenu->exec(mapToGlobal(pos));
0159 
0160     delete ctxmenu;
0161 }
0162 
0163 QStringList ShowfotoStackViewFavoriteList::mimeTypes() const
0164 {
0165     return QStringList(QLatin1String("text/uri-list"));
0166 }
0167 
0168 Qt::DropActions ShowfotoStackViewFavoriteList::supportedDropActions() const
0169 {
0170     return (Qt::CopyAction | Qt::MoveAction);
0171 }
0172 
0173 void ShowfotoStackViewFavoriteList::startDrag(Qt::DropActions /*supportedActions*/)
0174 {
0175     QList<QTreeWidgetItem*> items = selectedItems();
0176 
0177     if (items.isEmpty())
0178     {
0179         return;
0180     }
0181 
0182     d->draggedItem    = items.first();
0183 
0184     QDrag* const drag = new QDrag(this);
0185     drag->setMimeData(mimeData(items));
0186     drag->exec();
0187 }
0188 
0189 void ShowfotoStackViewFavoriteList::dragEnterEvent(QDragEnterEvent* e)
0190 {
0191     QTreeWidget::dragEnterEvent(e);
0192     e->accept();
0193 }
0194 
0195 void ShowfotoStackViewFavoriteList::dragMoveEvent(QDragMoveEvent* e)
0196 {
0197     if ((e->source() == this) &&
0198 
0199 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0200 
0201         (dynamic_cast<ShowfotoStackViewFavoriteItem*>(itemAt(e->position().toPoint())) != d->parent->topFavoritesItem()))
0202 
0203 #else
0204 
0205         (dynamic_cast<ShowfotoStackViewFavoriteItem*>(itemAt(e->pos())) != d->parent->topFavoritesItem()))
0206 
0207 #endif
0208 
0209     {
0210         QTreeWidget::dragMoveEvent(e);
0211         e->accept();
0212 
0213         return;
0214     }
0215 
0216     if (e->mimeData()->hasUrls())
0217     {
0218         QList<QUrl> mimeurls = e->mimeData()->urls();
0219         QList<QUrl> urls;
0220 
0221         Q_FOREACH (const QUrl& url, mimeurls)
0222         {
0223             if (isReadableImageFile(url.toLocalFile()))
0224             {
0225                 urls << url;
0226             }
0227         }
0228 
0229         if (!urls.isEmpty())
0230         {
0231             QTreeWidget::dragMoveEvent(e);
0232             e->accept();
0233             return;
0234         }
0235     }
0236 
0237     e->ignore();
0238 }
0239 
0240 void ShowfotoStackViewFavoriteList::dropEvent(QDropEvent* e)
0241 {
0242     if (e->source() == this)
0243     {
0244         ShowfotoStackViewFavoriteItem* const src = dynamic_cast<ShowfotoStackViewFavoriteItem*>(d->draggedItem);
0245 
0246         if (!src)
0247         {
0248             return;
0249         }
0250 
0251 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0252 
0253         ShowfotoStackViewFavoriteItem* const tgt = dynamic_cast<ShowfotoStackViewFavoriteItem*>(itemAt(e->position().toPoint()));
0254 
0255 #else
0256 
0257         ShowfotoStackViewFavoriteItem* const tgt = dynamic_cast<ShowfotoStackViewFavoriteItem*>(itemAt(e->pos()));
0258 
0259 #endif
0260 
0261         if (!tgt)
0262         {
0263             return;
0264         }
0265 
0266         for (int i = 0 ; i < tgt->childCount() ; ++i)
0267         {
0268             ShowfotoStackViewFavoriteItem* const chl = dynamic_cast<ShowfotoStackViewFavoriteItem*>(tgt->child(i));
0269 
0270             if (chl && (chl->name() == src->name()))
0271             {
0272                 // Ignore event if a target child item with same name than source already exist.
0273                 return;
0274             }
0275         }
0276 
0277         QTreeWidget::dropEvent(e);
0278         e->acceptProposedAction();
0279 
0280         rebaseHierarchy(tgt);
0281         d->draggedItem = nullptr;
0282 
0283         return;
0284     }
0285 
0286     if (e->mimeData()->hasUrls())
0287     {
0288         QList<QUrl> mimeurls = e->mimeData()->urls();
0289         QList<QUrl> urls;
0290 
0291         Q_FOREACH (const QUrl& url, mimeurls)
0292         {
0293             if (isReadableImageFile(url.toLocalFile()))
0294             {
0295                 urls << url;
0296             }
0297         }
0298 
0299         if (!urls.isEmpty())
0300         {
0301             QTreeWidget::dropEvent(e);
0302 
0303             Q_EMIT signalAddFavorite(urls, urls.first());
0304 
0305             e->acceptProposedAction();
0306             return;
0307         }
0308     }
0309 
0310     e->ignore();
0311 }
0312 
0313 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0314 
0315 QMimeData* ShowfotoStackViewFavoriteList::mimeData(const QList<QTreeWidgetItem*>& items) const
0316 
0317 #else
0318 // cppcheck-suppress passedByValue
0319 QMimeData* ShowfotoStackViewFavoriteList::mimeData(const QList<QTreeWidgetItem*> items) const     // clazy:exclude=function-args-by-ref
0320 
0321 #endif
0322 
0323 {
0324     QList<QUrl> urls;
0325 
0326     Q_FOREACH (QTreeWidgetItem* const itm, items)
0327     {
0328         ShowfotoStackViewFavoriteItem* const vitem = dynamic_cast<ShowfotoStackViewFavoriteItem*>(itm);
0329 
0330         if (vitem)
0331         {
0332             urls.append(vitem->urls());
0333         }
0334     }
0335 
0336     QMimeData* const data = new QMimeData;
0337     data->setUrls(urls);
0338 
0339     return data;
0340 }
0341 
0342 
0343 ShowfotoStackViewFavoriteItem* ShowfotoStackViewFavoriteList::findFavoriteByHierarchy(const QString& hierarchy)
0344 {
0345     ShowfotoStackViewFavoriteItem* item = nullptr;
0346     QTreeWidgetItemIterator it(this);
0347 
0348     while (*it)
0349     {
0350         item = dynamic_cast<ShowfotoStackViewFavoriteItem*>(*it);
0351 
0352         if (item && (hierarchy == item->hierarchy()))
0353         {
0354             return item;
0355         }
0356 
0357         ++it;
0358     }
0359 
0360     return nullptr;
0361 }
0362 
0363 void ShowfotoStackViewFavoriteList::rebaseHierarchy(ShowfotoStackViewFavoriteItem* const parent)
0364 {
0365     if (parent)
0366     {
0367         QTreeWidgetItemIterator it(parent);
0368 
0369         while (*it)
0370         {
0371             ShowfotoStackViewFavoriteItem* const item = dynamic_cast<ShowfotoStackViewFavoriteItem*>(*it);
0372 
0373             if (item)
0374             {
0375                 item->setName(item->name());
0376             }
0377 
0378             ++it;
0379         }
0380     }
0381 }
0382 
0383 void ShowfotoStackViewFavoriteList::setFilter(const QString& filter, Qt::CaseSensitivity cs)
0384 {
0385     d->filter                            = filter;
0386     int query                            = 0;
0387     ShowfotoStackViewFavoriteItem* fitem = nullptr;
0388     QTreeWidgetItemIterator it(this);
0389 
0390     while (*it)
0391     {
0392         fitem = dynamic_cast<ShowfotoStackViewFavoriteItem*>(*it);
0393 
0394         if (fitem)
0395         {
0396             if (fitem->name().contains(filter, cs))
0397             {
0398                 query++;
0399 
0400                 QTreeWidgetItem* item = *it;
0401 
0402                 do
0403                 {
0404                     item->setHidden(false);
0405                     item = item->parent();
0406                 }
0407                 while (item);
0408             }
0409             else
0410             {
0411                 fitem->setHidden(true);
0412             }
0413         }
0414 
0415         ++it;
0416     }
0417 
0418     Q_EMIT signalSearchResult(query);
0419 }
0420 
0421 QString ShowfotoStackViewFavoriteList::filter() const
0422 {
0423     return d->filter;
0424 }
0425 
0426 } // namespace ShowFoto
0427 
0428 #include "moc_showfotostackviewfavoritelist.cpp"