diff --git a/core/utilities/import/models/importimagemodel.cpp b/core/utilities/import/models/importimagemodel.cpp index 03233f5e18..273fb17755 100644 --- a/core/utilities/import/models/importimagemodel.cpp +++ b/core/utilities/import/models/importimagemodel.cpp @@ -1,1100 +1,1100 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-05-22 * Description : Qt item model for camera entries * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "importimagemodel.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "coredbdownloadhistory.h" #include "cameracontroller.h" namespace Digikam { class Q_DECL_HIDDEN ImportItemModel::Private { public: explicit Private() : controller(nullptr), keepFileUrlCache(false), refreshing(false), reAdding(false), incrementalRefreshRequested(false), sendRemovalSignals(false), incrementalUpdater(nullptr) { } inline bool isValid(const QModelIndex& index) { return ( index.isValid() && (index.row() >= 0) && (index.row() < infos.size()) ); } public: CameraController* controller; CamItemInfoList infos; CamItemInfo camItemInfo; QHash idHash; QHash fileUrlHash; bool keepFileUrlCache; bool refreshing; bool reAdding; bool incrementalRefreshRequested; bool sendRemovalSignals; class ImportItemModelIncrementalUpdater* incrementalUpdater; }; // ---------------------------------------------------------------------------------------------------- typedef QPair IntPair; typedef QList IntPairList; class Q_DECL_HIDDEN ImportItemModelIncrementalUpdater { public: explicit ImportItemModelIncrementalUpdater(ImportItemModel::Private* const d); void appendInfos(const QList& infos); void aboutToBeRemovedInModel(const IntPairList& aboutToBeRemoved); QList oldIndexes(); static QList toContiguousPairs(const QList& ids); public: QHash oldIds; QList newInfos; QList modelRemovals; }; // ---------------------------------------------------------------------------------------------------- ImportItemModel::ImportItemModel(QObject* const parent) : QAbstractListModel(parent), d(new Private) { } ImportItemModel::~ImportItemModel() { delete d; } void ImportItemModel::setCameraThumbsController(CameraThumbsCtrl* const thumbsCtrl) { d->controller = thumbsCtrl->cameraController(); connect(d->controller, SIGNAL(signalFileList(CamItemInfoList)), SLOT(addCamItemInfos(CamItemInfoList))); connect(d->controller, SIGNAL(signalDeleted(QString,QString,bool)), SLOT(slotFileDeleted(QString,QString,bool))); connect(d->controller, SIGNAL(signalUploaded(CamItemInfo)), SLOT(slotFileUploaded(CamItemInfo))); } void ImportItemModel::setKeepsFileUrlCache(bool keepCache) { d->keepFileUrlCache = keepCache; } bool ImportItemModel::keepsFileUrlCache() const { return d->keepFileUrlCache; } bool ImportItemModel::isEmpty() const { return d->infos.isEmpty(); } CamItemInfo ImportItemModel::camItemInfo(const QModelIndex& index) const { if (!d->isValid(index)) { return CamItemInfo(); } return d->infos.at(index.row()); } CamItemInfo& ImportItemModel::camItemInfoRef(const QModelIndex& index) const { if (!d->isValid(index)) { return d->camItemInfo; } return d->infos[index.row()]; } qlonglong ImportItemModel::camItemId(const QModelIndex& index) const { if (!d->isValid(index)) { return -1; } return d->infos.at(index.row()).id; } QList ImportItemModel::camItemInfos(const QList& indexes) const { QList infos; foreach (const QModelIndex& index, indexes) { infos << camItemInfo(index); } return infos; } QList ImportItemModel::camItemIds(const QList& indexes) const { QList ids; foreach (const QModelIndex& index, indexes) { ids << camItemId(index); } return ids; } CamItemInfo ImportItemModel::camItemInfo(int row) const { if ((row < 0) || (row >= d->infos.size())) { return CamItemInfo(); } return d->infos.at(row); } CamItemInfo& ImportItemModel::camItemInfoRef(int row) const { if ((row < 0) || (row >= d->infos.size())) { return d->camItemInfo; } return d->infos[row]; } qlonglong ImportItemModel::camItemId(int row) const { if ((row < 0) || (row >= d->infos.size())) { return -1; } return d->infos.at(row).id; } QModelIndex ImportItemModel::indexForCamItemInfo(const CamItemInfo& info) const { return indexForCamItemId(info.id); } QList ImportItemModel::indexesForCamItemInfo(const CamItemInfo& info) const { return indexesForCamItemId(info.id); } QModelIndex ImportItemModel::indexForCamItemId(qlonglong id) const { int index = d->idHash.value(id, -1); if (index == -1) { return QModelIndex(); } return createIndex(index, 0); } QList ImportItemModel::indexesForCamItemId(qlonglong id) const { QList indexes; QHash::const_iterator it; for (it = d->idHash.constFind(id) ; it != d->idHash.constEnd() && it.key() == id ; ++it) { indexes << createIndex(it.value(), 0); } return indexes; } int ImportItemModel::numberOfIndexesForCamItemInfo(const CamItemInfo& info) const { return numberOfIndexesForCamItemId(info.id); } int ImportItemModel::numberOfIndexesForCamItemId(qlonglong id) const { int count = 0; QHash::const_iterator it; for (it = d->idHash.constFind(id) ; it != d->idHash.constEnd() && it.key() == id ; ++it) { ++count; } return count; } // static method CamItemInfo ImportItemModel::retrieveCamItemInfo(const QModelIndex& index) { if (!index.isValid()) { return CamItemInfo(); } ImportItemModel* const model = index.data(ImportItemModelPointerRole).value(); int row = index.data(ImportItemModelInternalId).toInt(); if (!model) { return CamItemInfo(); } return model->camItemInfo(row); } // static method qlonglong ImportItemModel::retrieveCamItemId(const QModelIndex& index) { if (!index.isValid()) { return -1; } ImportItemModel* const model = index.data(ImportItemModelPointerRole).value(); int row = index.data(ImportItemModelInternalId).toInt(); if (!model) { return -1; } return model->camItemId(row); } QModelIndex ImportItemModel::indexForUrl(const QUrl& fileUrl) const { if (d->keepFileUrlCache) { return indexForCamItemId(d->fileUrlHash.value(fileUrl.toLocalFile())); } else { const int size = d->infos.size(); for (int i = 0 ; i < size ; ++i) { if (d->infos.at(i).url() == fileUrl) { return createIndex(i, 0); } } } return QModelIndex(); } QList ImportItemModel::indexesForUrl(const QUrl& fileUrl) const { if (d->keepFileUrlCache) { return indexesForCamItemId(d->fileUrlHash.value(fileUrl.toLocalFile())); } else { QList indexes; const int size = d->infos.size(); for (int i = 0 ; i < size ; ++i) { if (d->infos.at(i).url() == fileUrl) { indexes << createIndex(i, 0); } } return indexes; } } CamItemInfo ImportItemModel::camItemInfo(const QUrl& fileUrl) const { if (d->keepFileUrlCache) { qlonglong id = d->fileUrlHash.value(fileUrl.toLocalFile()); if (id) { int index = d->idHash.value(id, -1); if (index != -1) { return d->infos.at(index); } } } else { foreach (const CamItemInfo& info, d->infos) { if (info.url() == fileUrl) { return info; } } } return CamItemInfo(); } QList ImportItemModel::camItemInfos(const QUrl& fileUrl) const { QList infos; if (d->keepFileUrlCache) { qlonglong id = d->fileUrlHash.value(fileUrl.toLocalFile()); if (id) { foreach (int index, d->idHash.values(id)) { infos << d->infos.at(index); } } } else { foreach (const CamItemInfo& info, d->infos) { if (info.url() == fileUrl) { infos << info; } } } return infos; } void ImportItemModel::addCamItemInfo(const CamItemInfo& info) { addCamItemInfos(QList() << info); } void ImportItemModel::addCamItemInfos(const CamItemInfoList& infos) { if (infos.isEmpty()) { return; } if (d->incrementalUpdater) { d->incrementalUpdater->appendInfos(infos); } else { appendInfos(infos); } } void ImportItemModel::addCamItemInfoSynchronously(const CamItemInfo& info) { addCamItemInfosSynchronously(QList() << info); } void ImportItemModel::addCamItemInfosSynchronously(const CamItemInfoList& infos) { if (infos.isEmpty()) { return; } publiciseInfos(infos); emit processAdded(infos); } void ImportItemModel::clearCamItemInfos() { beginResetModel(); d->infos.clear(); d->idHash.clear(); d->fileUrlHash.clear(); delete d->incrementalUpdater; d->incrementalUpdater = nullptr; d->reAdding = false; d->refreshing = false; d->incrementalRefreshRequested = false; camItemInfosCleared(); endResetModel(); } // TODO unused void ImportItemModel::setCamItemInfos(const CamItemInfoList& infos) { clearCamItemInfos(); addCamItemInfos(infos); } QList ImportItemModel::camItemInfos() const { return d->infos; } QList ImportItemModel::camItemIds() const { return d->idHash.keys(); } QList ImportItemModel::uniqueCamItemInfos() const { QList uniqueInfos; const int size = d->infos.size(); for (int i = 0 ; i < size ; ++i) { const CamItemInfo& info = d->infos.at(i); if (d->idHash.value(info.id) == i) { uniqueInfos << info; } } return uniqueInfos; } bool ImportItemModel::hasImage(qlonglong id) const { return d->idHash.contains(id); } bool ImportItemModel::hasImage(const CamItemInfo& info) const { return d->fileUrlHash.contains(info.url().toLocalFile()); } void ImportItemModel::emitDataChangedForAll() { if (d->infos.isEmpty()) { return; } QModelIndex first = createIndex(0, 0); QModelIndex last = createIndex(d->infos.size() - 1, 0); emit dataChanged(first, last); } void ImportItemModel::emitDataChangedForSelections(const QItemSelection& selection) { if (!selection.isEmpty()) { foreach (const QItemSelectionRange& range, selection) { emit dataChanged(range.topLeft(), range.bottomRight()); } } } void ImportItemModel::appendInfos(const CamItemInfoList& infos) { if (infos.isEmpty()) { return; } publiciseInfos(infos); } void ImportItemModel::reAddCamItemInfos(const CamItemInfoList& infos) { publiciseInfos(infos); } void ImportItemModel::reAddingFinished() { d->reAdding = false; cleanSituationChecks(); } void ImportItemModel::slotFileDeleted(const QString& folder, const QString& file, bool status) { Q_UNUSED(status) QUrl url = QUrl::fromLocalFile(folder); url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + file); CamItemInfo info = camItemInfo(url); removeCamItemInfo(info); } void ImportItemModel::slotFileUploaded(const CamItemInfo& info) { addCamItemInfo(info); } void ImportItemModel::startRefresh() { d->refreshing = true; } void ImportItemModel::finishRefresh() { d->refreshing = false; cleanSituationChecks(); } bool ImportItemModel::isRefreshing() const { return d->refreshing; } void ImportItemModel::cleanSituationChecks() { // For starting an incremental refresh we want a clear situation: // Any remaining batches from non-incremental refreshing subclasses have been received in appendInfos(), // any batches sent to preprocessor for re-adding have been re-added. if (d->refreshing || d->reAdding) { return; } if (d->incrementalRefreshRequested) { d->incrementalRefreshRequested = false; emit readyForIncrementalRefresh(); } else { emit allRefreshingFinished(); } } void ImportItemModel::publiciseInfos(const CamItemInfoList& infos) { if (infos.isEmpty()) { return; } emit itemInfosAboutToBeAdded(infos); const int firstNewIndex = d->infos.size(); const int lastNewIndex = d->infos.size() + infos.size() -1; beginInsertRows(QModelIndex(), firstNewIndex, lastNewIndex); d->infos << infos; for (int i = firstNewIndex ; i <= lastNewIndex ; ++i) { CamItemInfo& info = d->infos[i]; // TODO move this to a separate thread, see CameraHistoryUpdater // TODO can we/do we want to differentiate at all between whether the status is unknown and not downloaded? info.downloaded = CoreDbDownloadHistory::status(QString::fromUtf8(d->controller->cameraMD5ID()), info.name, info.size, info.ctime); // TODO is this safe? if so, is there a need to store this inside idHash separately? info.id = i; qlonglong id = info.id; d->idHash.insertMulti(id, i); if (d->keepFileUrlCache) { d->fileUrlHash[info.url().toLocalFile()] = id; } } endInsertRows(); emit processAdded(infos); emit itemInfosAdded(infos); } void ImportItemModel::requestIncrementalRefresh() { if (d->reAdding) { d->incrementalRefreshRequested = true; } else { emit readyForIncrementalRefresh(); } } bool ImportItemModel::hasIncrementalRefreshPending() const { return d->incrementalRefreshRequested; } void ImportItemModel::startIncrementalRefresh() { delete d->incrementalUpdater; d->incrementalUpdater = new ImportItemModelIncrementalUpdater(d); } void ImportItemModel::finishIncrementalRefresh() { if (!d->incrementalUpdater) { return; } // remove old entries QList > pairs = d->incrementalUpdater->oldIndexes(); removeRowPairs(pairs); // add new indexes appendInfos(d->incrementalUpdater->newInfos); delete d->incrementalUpdater; d->incrementalUpdater = nullptr; } template static bool pairsContain(const List& list, T value) { typename List::const_iterator middle; typename List::const_iterator begin = list.begin(); typename List::const_iterator end = list.end(); int n = int(end - begin); while (n > 0) { int half = (n >> 1); middle = begin + half; if ((middle->first <= value) && (middle->second >= value)) { return true; } else if (middle->second < value) { begin = middle + 1; n -= half + 1; } else { n = half; } } return false; } void ImportItemModel::removeIndex(const QModelIndex& index) { removeIndexs(QList() << index); } void ImportItemModel::removeIndexs(const QList& indexes) { QList indexesList; foreach (const QModelIndex& index, indexes) { if (d->isValid(index)) { indexesList << index.row(); } } if (indexesList.isEmpty()) { return; } removeRowPairsWithCheck(ImportItemModelIncrementalUpdater::toContiguousPairs(indexesList)); } void ImportItemModel::removeCamItemInfo(const CamItemInfo& info) { removeCamItemInfos(QList() << info); } void ImportItemModel::removeCamItemInfos(const QList& infos) { QList indexesList; foreach (const CamItemInfo& info, infos) { QModelIndex index = indexForCamItemId(info.id); if (index.isValid()) { indexesList << index.row(); } } removeRowPairsWithCheck(ImportItemModelIncrementalUpdater::toContiguousPairs(indexesList)); } void ImportItemModel::setSendRemovalSignals(bool send) { d->sendRemovalSignals = send; } void ImportItemModel::removeRowPairsWithCheck(const QList >& toRemove) { if (d->incrementalUpdater) { d->incrementalUpdater->aboutToBeRemovedInModel(toRemove); } removeRowPairs(toRemove); } void ImportItemModel::removeRowPairs(const QList >& toRemove) { if (toRemove.isEmpty()) { return; } // Remove old indexes // Keep in mind that when calling beginRemoveRows all structures announced to be removed // must still be valid, and this includes our hashes as well, which limits what we can optimize int removedRows = 0; int offset = 0; foreach (const IntPair& pair, toRemove) { const int begin = pair.first - offset; const int end = pair.second - offset; removedRows = end - begin + 1; // when removing from the list, all subsequent indexes are affected offset += removedRows; QList removedInfos; if (d->sendRemovalSignals) { std::copy(d->infos.begin() + begin, d->infos.begin() + end, removedInfos.begin()); emit itemInfosAboutToBeRemoved(removedInfos); } itemInfosAboutToBeRemoved(begin, end); beginRemoveRows(QModelIndex(), begin, end); // update idHash - which points to indexes of d->infos QHash::iterator it; for (it = d->idHash.begin() ; it != d->idHash.end() ; ) { if (it.value() >= begin) { if (it.value() > end) { // after the removed interval, adjust index it.value() -= removedRows; } else { // in the removed interval it = d->idHash.erase(it); continue; } } ++it; } // remove from list d->infos.erase(d->infos.begin() + begin, d->infos.begin() + (end + 1)); endRemoveRows(); if (d->sendRemovalSignals) { emit itemInfosRemoved(removedInfos); } } // tidy up: remove old indexes from file path hash now if (d->keepFileUrlCache) { QHash::iterator it; for (it = d->fileUrlHash.begin() ; it!= d->fileUrlHash.end() ; ) { if (pairsContain(toRemove, it.value())) { it = d->fileUrlHash.erase(it); } else { ++it; } } } } // ------------ ImportItemModelIncrementalUpdater ------------ ImportItemModelIncrementalUpdater::ImportItemModelIncrementalUpdater(ImportItemModel::Private* const d) + : oldIds(d->idHash) { - oldIds = d->idHash; } void ImportItemModelIncrementalUpdater::aboutToBeRemovedInModel(const IntPairList& toRemove) { modelRemovals << toRemove; } void ImportItemModelIncrementalUpdater::appendInfos(const QList& infos) { for (int i = 0 ; i < infos.size() ; ++i) { const CamItemInfo& info = infos.at(i); bool found = false; QHash::iterator it; for (it = oldIds.find(info.id) ; it != oldIds.end() ; ++it) { if (it.key() == info.id) { found = true; break; } } if (found) { oldIds.erase(it); } else { newInfos << info; } } } QList > ImportItemModelIncrementalUpdater::toContiguousPairs(const QList& unsorted) { // Take the given indices and return them as contiguous pairs [begin, end] QList > pairs; if (unsorted.isEmpty()) { return pairs; } QList indices(unsorted); std::sort(indices.begin(), indices.end()); QPair pair(indices.first(), indices.first()); for (int i = 1 ; i < indices.size() ; ++i) { const int &index = indices.at(i); if (index == pair.second + 1) { pair.second = index; continue; } pairs << pair; // insert last pair pair.first = index; pair.second = index; } pairs << pair; return pairs; } QList > ImportItemModelIncrementalUpdater::oldIndexes() { // first, apply all changes to indexes by direct removal in model // while the updater was active foreach (const IntPairList& list, modelRemovals) { int removedRows = 0; int offset = 0; foreach (const IntPair& pair, list) { const int begin = pair.first - offset; const int end = pair.second - offset; // inclusive removedRows = end - begin + 1; // when removing from the list, all subsequent indexes are affected offset += removedRows; // update idHash - which points to indexes of d->infos, and these change now! QHash::iterator it; for (it = oldIds.begin() ; it != oldIds.end() ; ) { if (it.value() >= begin) { if (it.value() > end) { // after the removed interval: adjust index it.value() -= removedRows; } else { // in the removed interval it = oldIds.erase(it); continue; } } ++it; } } } modelRemovals.clear(); return toContiguousPairs(oldIds.values()); } // ------------ QAbstractItemModel implementation ------------- QVariant ImportItemModel::data(const QModelIndex& index, int role) const { if (!d->isValid(index)) { return QVariant(); } switch(role) { case Qt::DisplayRole: case Qt::ToolTipRole: return d->infos.at(index.row()).name; break; case ImportItemModelPointerRole: return QVariant::fromValue(const_cast(this)); break; case ImportItemModelInternalId: return index.row(); break; } return QVariant(); } QVariant ImportItemModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(section) Q_UNUSED(orientation) Q_UNUSED(role) return QVariant(); } int ImportItemModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } return d->infos.size(); } Qt::ItemFlags ImportItemModel::flags(const QModelIndex& index) const { if (!d->isValid(index)) { return nullptr; } Qt::ItemFlags f = Qt::ItemIsSelectable | Qt::ItemIsEnabled; f |= dragDropFlags(index); return f; } QModelIndex ImportItemModel::index(int row, int column, const QModelIndex& parent) const { if ((column != 0) || (row < 0) || parent.isValid() || (row >= d->infos.size())) { return QModelIndex(); } return createIndex(row, 0); } } // namespace Digikam diff --git a/core/utilities/import/views/camerafolderview.cpp b/core/utilities/import/views/camerafolderview.cpp index 2c06cb5ab5..e6a2379160 100644 --- a/core/utilities/import/views/camerafolderview.cpp +++ b/core/utilities/import/views/camerafolderview.cpp @@ -1,193 +1,197 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2003-01-23 * Description : A widget to display a list of camera folders. * * Copyright (C) 2003-2005 by Renchi Raju * Copyright (C) 2006-2020 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "camerafolderview.h" // KDE includes #include // Local includes #include "digikam_debug.h" #include "camerafolderitem.h" namespace Digikam { class Q_DECL_HIDDEN CameraFolderView::Private { public: explicit Private() : cameraName(QLatin1String("Camera")), virtualFolder(nullptr), rootFolder(nullptr) { } QString cameraName; CameraFolderItem* virtualFolder; CameraFolderItem* rootFolder; }; CameraFolderView::CameraFolderView(QWidget* const parent) : QTreeWidget(parent), d(new Private) { setColumnCount(1); setRootIsDecorated(false); setSelectionMode(QAbstractItemView::SingleSelection); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setAllColumnsShowFocus(true); setDragEnabled(false); setDropIndicatorShown(false); setAcceptDrops(false); setHeaderLabels(QStringList() << i18n("Camera Folders")); connect(this, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(slotCurrentChanged(QTreeWidgetItem*,int))); connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(slotCurrentChanged(QTreeWidgetItem*,int))); } CameraFolderView::~CameraFolderView() { delete d; } void CameraFolderView::addVirtualFolder(const QString& name, const QIcon& icon) { d->cameraName = name; d->virtualFolder = new CameraFolderItem(this, d->cameraName, icon); d->virtualFolder->setExpanded(true); d->virtualFolder->setSelected(false); + // item is not selectable. + d->virtualFolder->setFlags(d->virtualFolder->flags() & (int)!Qt::ItemIsSelectable); d->virtualFolder->setDisabled(false); } void CameraFolderView::addRootFolder(const QString& folder, int nbItems, const QIcon &icon) { d->rootFolder = new CameraFolderItem(d->virtualFolder, folder, folder, icon); d->rootFolder->setExpanded(true); if (nbItems != -1) { d->rootFolder->setCount(nbItems); } } CameraFolderItem* CameraFolderView::addFolder(const QString& folder, const QString& subFolder, int nbItems, const QIcon &icon) { CameraFolderItem* const parentItem = findFolder(folder); if (parentItem) { QString path(folder); if (!folder.endsWith(QLatin1Char('/'))) { path += QLatin1Char('/'); } path += subFolder + QLatin1Char('/'); if (!findFolder(path)) { CameraFolderItem* item = new CameraFolderItem(parentItem, subFolder, path, icon); qCDebug(DIGIKAM_IMPORTUI_LOG) << "Adding subfolder:" << subFolder << "Folder path:" << item->folderPath(); item->setCount(nbItems); item->setExpanded(true); + return item; } else { return nullptr; } } else { qCWarning(DIGIKAM_IMPORTUI_LOG) << "Could not find parent for subfolder" << subFolder << "of folder" << folder; return nullptr; } } CameraFolderItem* CameraFolderView::findFolder(const QString& folderPath) { QTreeWidgetItemIterator it(this); while (*it) { CameraFolderItem* const lvItem = dynamic_cast(*it); - if (lvItem && lvItem->folderPath() == folderPath) + if (lvItem && (lvItem->folderPath() == folderPath)) { return lvItem; } ++it; } return nullptr; } void CameraFolderView::slotCurrentChanged(QTreeWidgetItem* item, int) { if (!item) { emit signalFolderChanged(nullptr); } else { emit signalFolderChanged(dynamic_cast(item)); } } CameraFolderItem* CameraFolderView::virtualFolder() const { return d->virtualFolder; } CameraFolderItem* CameraFolderView::rootFolder() const { return d->rootFolder; } void CameraFolderView::clear() { QTreeWidget::clear(); d->virtualFolder = nullptr; d->rootFolder = nullptr; + emit signalCleared(); } } // namespace Digikam diff --git a/core/utilities/import/views/camerafolderview.h b/core/utilities/import/views/camerafolderview.h index d824c90405..e4303f54fe 100644 --- a/core/utilities/import/views/camerafolderview.h +++ b/core/utilities/import/views/camerafolderview.h @@ -1,79 +1,79 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2003-01-23 * Description : A widget to display a list of camera folders. * * Copyright (C) 2003-2005 by Renchi Raju * Copyright (C) 2006-2020 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_CAMERA_FOLDER_VIEW_H #define DIGIKAM_CAMERA_FOLDER_VIEW_H // Qt includes #include #include #include #include namespace Digikam { class CameraFolderItem; class CameraFolderView : public QTreeWidget { Q_OBJECT public: explicit CameraFolderView(QWidget* const parent); ~CameraFolderView(); void addVirtualFolder(const QString& name, const QIcon &icon = QIcon::fromTheme(QLatin1String("camera-photo"))); void addRootFolder(const QString& folder, int nbItems = -1, const QIcon& icon = QIcon::fromTheme(QLatin1String("folder"))); CameraFolderItem* addFolder(const QString& folder, const QString& subFolder, int nbItems, const QIcon& icon = QIcon::fromTheme(QLatin1String("folder"))); CameraFolderItem* findFolder(const QString& folderPath); CameraFolderItem* virtualFolder() const; - CameraFolderItem* rootFolder() const; + CameraFolderItem* rootFolder() const; virtual void clear(); Q_SIGNALS: void signalFolderChanged(CameraFolderItem*); void signalCleared(); private Q_SLOTS: void slotCurrentChanged(QTreeWidgetItem*, int); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_CAMERA_FOLDER_VIEW_H diff --git a/core/utilities/import/views/cameranamehelper.cpp b/core/utilities/import/views/cameranamehelper.cpp index 9a54b67243..25e7c55df9 100644 --- a/core/utilities/import/views/cameranamehelper.cpp +++ b/core/utilities/import/views/cameranamehelper.cpp @@ -1,178 +1,181 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-08-01 * Description : camera name helper class * * Copyright (C) 2009-2012 by Andi Clemens * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "cameranamehelper.h" // Qt includes #include namespace { static const QString STR_AUTO_DETECTED(QLatin1String("auto-detected")); static QRegExp REGEXP_CAMERA_NAME(QLatin1String("^(.*)\\s*\\((.*)\\)\\s*$"), Qt::CaseInsensitive); static QRegExp REGEXP_MODES(QLatin1String("^(ptp|normal|mtp)(\\s+mode)?$"), Qt::CaseInsensitive); static QRegExp REGEXP_AUTODETECTED(QString::fromUtf8("(%1|, %1)").arg(STR_AUTO_DETECTED)); } namespace Digikam { QString CameraNameHelper::createCameraName(const QString& vendor, const QString& product, const QString& mode, bool autoDetected) { if (vendor.isEmpty()) { return QString(); } QString tmp; QString _vendor = vendor.simplified(); QString _product = product.simplified(); QString _mode = mode.simplified().remove(QLatin1Char('(')).remove(QLatin1Char(')')); tmp = QString::fromUtf8("%1 %2").arg(_vendor).arg(_product); - if (!mode.isEmpty() && mode != STR_AUTO_DETECTED) + if (!mode.isEmpty() && mode != STR_AUTO_DETECTED) { tmp.append(QLatin1String(" (")); tmp.append(_mode); tmp.append(autoDetected ? QString::fromUtf8(", %1)").arg(STR_AUTO_DETECTED) : QLatin1String(")")); } else if (autoDetected) { tmp.append(QString::fromUtf8(" (%1)").arg(STR_AUTO_DETECTED)); } return tmp.simplified(); } QString CameraNameHelper::cameraName(const QString& name) { return parseAndFormatCameraName(name, false, false); } QString CameraNameHelper::cameraNameAutoDetected(const QString& name) { return parseAndFormatCameraName(name, true, true); } QString CameraNameHelper::parseAndFormatCameraName(const QString& cameraName, bool parseMode, bool autoDetected) { QString vendorAndProduct = extractCameraNameToken(cameraName, VendorAndProduct); if (vendorAndProduct.isEmpty()) { return QString(); } QString mode = parseMode ? extractCameraNameToken(cameraName, Mode) : QString(); QString tmp = createCameraName(vendorAndProduct, QString(), mode, autoDetected); - return tmp.isEmpty() ? cameraName.simplified() - : tmp; + return (tmp.isEmpty() ? cameraName.simplified() + : tmp); } QString CameraNameHelper::extractCameraNameToken(const QString& cameraName, Token tokenID) { REGEXP_CAMERA_NAME.setMinimal(true); REGEXP_MODES.setMinimal(true); REGEXP_AUTODETECTED.setMinimal(true); if (REGEXP_CAMERA_NAME.exactMatch(cameraName.simplified())) { QString vendorProduct = REGEXP_CAMERA_NAME.cap(1).simplified(); QString tmpMode = REGEXP_CAMERA_NAME.cap(2).simplified(); QString clearedTmpMode = tmpMode; QString mode; clearedTmpMode.remove(REGEXP_AUTODETECTED); if (!tmpMode.isEmpty() && clearedTmpMode.isEmpty()) { mode = tmpMode; } else { mode = REGEXP_MODES.exactMatch(clearedTmpMode) ? clearedTmpMode : QLatin1String(""); } if (tokenID == VendorAndProduct) { - return mode.isEmpty() ? cameraName.simplified() - : vendorProduct; + return (mode.isEmpty() ? cameraName.simplified() + : vendorProduct); } else { return mode; } } - return (tokenID == VendorAndProduct) ? cameraName.simplified() - : QLatin1String(""); + return ((tokenID == VendorAndProduct) ? cameraName.simplified() + : QLatin1String("")); } bool CameraNameHelper::sameDevices(const QString& deviceA, const QString& deviceB) { if (deviceA.isEmpty() || deviceB.isEmpty()) { return false; } if (deviceA == deviceB) { return true; } // We need to parse the names a little bit. First check if the vendor and name match + QString vendorAndProductA = extractCameraNameToken(deviceA, VendorAndProduct); QString vendorAndProductB = extractCameraNameToken(deviceB, VendorAndProduct); QString cameraNameA = createCameraName(vendorAndProductA); QString cameraNameB = createCameraName(vendorAndProductB); // try to clean up the string, if not possible, return false + if (cameraNameA != cameraNameB) { return false; } // is the extracted mode known and equal? + QString modeA = extractCameraNameToken(deviceA, Mode); QString modeB = extractCameraNameToken(deviceB, Mode); bool isModeAValid = REGEXP_MODES.exactMatch(modeA); modeA = isModeAValid ? REGEXP_MODES.cap(1).simplified().toLower() : QLatin1String(""); bool isModeBValid = REGEXP_MODES.exactMatch(modeB); modeB = isModeBValid ? REGEXP_MODES.cap(1).simplified().toLower() : QLatin1String(""); if ((isModeAValid != isModeBValid) || (modeA != modeB)) { return false; } return true; } } // namespace Digikam diff --git a/core/utilities/import/views/freespacetooltip.cpp b/core/utilities/import/views/freespacetooltip.cpp index 3d76850ca4..d92f7ce1ca 100644 --- a/core/utilities/import/views/freespacetooltip.cpp +++ b/core/utilities/import/views/freespacetooltip.cpp @@ -1,93 +1,95 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-01-19 * Description : free space widget tool tip * * Copyright (C) 2009-2020 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "freespacetooltip.h" // Qt includes #include #include #include namespace Digikam { class Q_DECL_HIDDEN FreeSpaceToolTip::Private { public: explicit Private() : parent(nullptr) { } QString tip; QWidget* parent; }; FreeSpaceToolTip::FreeSpaceToolTip(QWidget* const parent) - : DItemToolTip(), d(new Private) + : DItemToolTip(), + d(new Private) { d->parent = parent; } FreeSpaceToolTip::~FreeSpaceToolTip() { delete d; } void FreeSpaceToolTip::setToolTip(const QString& tip) { d->tip = tip; } void FreeSpaceToolTip::show() { updateToolTip(); reposition(); if (isHidden() && !toolTipIsEmpty()) { DItemToolTip::show(); } } QRect FreeSpaceToolTip::repositionRect() { if (!d->parent) { return QRect(); } QRect rect = d->parent->rect(); rect.moveTopLeft(d->parent->mapToGlobal(rect.topLeft())); + return rect; } QString FreeSpaceToolTip::tipContents() { return d->tip; } } // namespace Digikam diff --git a/core/utilities/import/views/importcategorizedview.cpp b/core/utilities/import/views/importcategorizedview.cpp index 9ad3b80f6d..2c645b443d 100644 --- a/core/utilities/import/views/importcategorizedview.cpp +++ b/core/utilities/import/views/importcategorizedview.cpp @@ -1,631 +1,643 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-07-13 * Description : Qt categorized item view for camera items * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "importcategorizedview.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "camitemsortsettings.h" #include "iccsettings.h" #include "itemselectionoverlay.h" #include "importdelegate.h" #include "importtooltipfiller.h" #include "importsettings.h" #include "itemviewtooltip.h" #include "loadingcacheinterface.h" #include "thumbnailloadthread.h" namespace Digikam { class Q_DECL_HIDDEN ImportItemViewToolTip : public ItemViewToolTip { public: explicit ImportItemViewToolTip(ImportCategorizedView* const view) : ItemViewToolTip(view) { } ImportCategorizedView* view() const { return static_cast(ItemViewToolTip::view()); } protected: virtual QString tipContents() { CamItemInfo info = ImportItemModel::retrieveCamItemInfo(currentIndex()); + return ImportToolTipFiller::CamItemInfoTipContents(info); } }; class Q_DECL_HIDDEN ImportCategorizedView::Private { public: explicit Private() : model(nullptr), filterModel(nullptr), delegate(nullptr), showToolTip(false), scrollToItemId(0), delayedEnterTimer(nullptr), currentMouseEvent(nullptr) { } ImportItemModel* model; ImportSortFilterModel* filterModel; ImportDelegate* delegate; bool showToolTip; qlonglong scrollToItemId; QTimer* delayedEnterTimer; QMouseEvent* currentMouseEvent; }; ImportCategorizedView::ImportCategorizedView(QWidget* const parent) : ItemViewCategorized(parent), d(new Private) { setToolTip(new ImportItemViewToolTip(this)); LoadingCacheInterface::connectToSignalFileChanged(this, SLOT(slotFileChanged(QString))); d->delayedEnterTimer = new QTimer(this); d->delayedEnterTimer->setInterval(10); d->delayedEnterTimer->setSingleShot(true); connect(d->delayedEnterTimer, SIGNAL(timeout()), this, SLOT(slotDelayedEnter())); connect(IccSettings::instance(), SIGNAL(settingsChanged(ICCSettingsContainer,ICCSettingsContainer)), this, SLOT(slotIccSettingsChanged(ICCSettingsContainer,ICCSettingsContainer))); } ImportCategorizedView::~ImportCategorizedView() { d->delegate->removeAllOverlays(); delete d; } void ImportCategorizedView::setModels(ImportItemModel* model, ImportSortFilterModel* filterModel) { if (d->delegate) { d->delegate->setAllOverlaysActive(false); } if (d->filterModel) { disconnect(d->filterModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(layoutAboutToBeChanged())); disconnect(d->filterModel, SIGNAL(layoutChanged()), this, SLOT(layoutWasChanged())); } if (d->model) { disconnect(d->model, SIGNAL(itemInfosAdded(QList)), this, SLOT(slotCamItemInfosAdded())); } d->model = model; d->filterModel = filterModel; setModel(d->filterModel); connect(d->filterModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(layoutAboutToBeChanged())); connect(d->filterModel, SIGNAL(layoutChanged()), this, SLOT(layoutWasChanged()), Qt::QueuedConnection); connect(d->model, SIGNAL(itemInfosAdded(QList)), this, SLOT(slotCamItemInfosAdded())); emit modelChanged(); if (d->delegate) { d->delegate->setAllOverlaysActive(true); } } ImportItemModel* ImportCategorizedView::importItemModel() const { return d->model; } ImportSortFilterModel* ImportCategorizedView::importSortFilterModel() const { return d->filterModel; } ImportFilterModel* ImportCategorizedView::importFilterModel() const { return d->filterModel->importFilterModel(); } ImportThumbnailModel* ImportCategorizedView::importThumbnailModel() const { return qobject_cast(d->model); } QSortFilterProxyModel* ImportCategorizedView::filterModel() const { return d->filterModel; } ImportDelegate* ImportCategorizedView::delegate() const { return d->delegate; } void ImportCategorizedView::setItemDelegate(ImportDelegate* delegate) { ThumbnailSize oldSize = thumbnailSize(); ImportDelegate* oldDelegate = d->delegate; if (oldDelegate) { hideIndexNotification(); d->delegate->setAllOverlaysActive(false); d->delegate->setViewOnAllOverlays(nullptr); // Note: Be precise, no wildcard disconnect! + disconnect(d->delegate, SIGNAL(requestNotification(QModelIndex,QString)), this, SLOT(showIndexNotification(QModelIndex,QString))); + disconnect(d->delegate, SIGNAL(hideNotification()), this, SLOT(hideIndexNotification())); } d->delegate = delegate; delegate->setThumbnailSize(oldSize); if (oldDelegate) { d->delegate->setSpacing(oldDelegate->spacing()); } ItemViewCategorized::setItemDelegate(d->delegate); setCategoryDrawer(d->delegate->categoryDrawer()); updateDelegateSizes(); d->delegate->setViewOnAllOverlays(this); d->delegate->setAllOverlaysActive(true); connect(d->delegate, SIGNAL(requestNotification(QModelIndex,QString)), this, SLOT(showIndexNotification(QModelIndex,QString))); connect(d->delegate, SIGNAL(hideNotification()), this, SLOT(hideIndexNotification())); } CamItemInfo ImportCategorizedView::currentInfo() const { return d->filterModel->camItemInfo(currentIndex()); } QUrl ImportCategorizedView::currentUrl() const { return currentInfo().url(); } QList ImportCategorizedView::selectedCamItemInfos() const { return d->filterModel->camItemInfos(selectedIndexes()); } QList ImportCategorizedView::selectedCamItemInfosCurrentFirst() const { QList indexes = selectedIndexes(); QModelIndex current = currentIndex(); QList infos; foreach (const QModelIndex& index, indexes) { CamItemInfo info = d->filterModel->camItemInfo(index); if (index == current) { infos.prepend(info); } else { infos.append(info); } } return infos; } QList ImportCategorizedView::camItemInfos() const { return d->filterModel->camItemInfosSorted(); } QList ImportCategorizedView::urls() const { QList infos = camItemInfos(); QList urls; foreach (const CamItemInfo& info, infos) { urls << info.url(); } return urls; } QList ImportCategorizedView::selectedUrls() const { QList infos = selectedCamItemInfos(); QList urls; foreach (const CamItemInfo& info, infos) { urls << info.url(); } return urls; } void ImportCategorizedView::toIndex(const QUrl& url) { ItemViewCategorized::toIndex(d->filterModel->indexForPath(url.toLocalFile())); } CamItemInfo ImportCategorizedView::nextInOrder(const CamItemInfo& startingPoint, int nth) { QModelIndex index = d->filterModel->indexForCamItemInfo(startingPoint); if (!index.isValid()) { return CamItemInfo(); } return d->filterModel->camItemInfo(d->filterModel->index(index.row() + nth, 0, QModelIndex())); } QModelIndex ImportCategorizedView::nextIndexHint(const QModelIndex& anchor, const QItemSelectionRange& removed) const { QModelIndex hint = ItemViewCategorized::nextIndexHint(anchor, removed); CamItemInfo info = d->filterModel->camItemInfo(anchor); //qCDebug(DIGIKAM_IMPORTUI_LOG) << "Having initial hint" << hint << "for" << anchor << d->model->numberOfIndexesForCamItemInfo(info); // Fixes a special case of multiple (face) entries for the same image. // If one is removed, any entry of the same image shall be preferred. + if (d->model->numberOfIndexesForCamItemInfo(info) > 1) { // The hint is for a different info, but we may have a hint for the same info + if (info != d->filterModel->camItemInfo(hint)) { int minDiff = d->filterModel->rowCount(); QList indexesForCamItemInfo = d->filterModel->mapListFromSource(d->model->indexesForCamItemInfo(info)); foreach (const QModelIndex& index, indexesForCamItemInfo) { - if (index == anchor || !index.isValid() || removed.contains(index)) + if ((index == anchor) || !index.isValid() || removed.contains(index)) { continue; } int distance = qAbs(index.row() - anchor.row()); if (distance < minDiff) { minDiff = distance; hint = index; + //qCDebug(DIGIKAM_IMPORTUI_LOG) << "Chose index" << hint << "at distance" << minDiff << "to" << anchor; } } } } return hint; } ThumbnailSize ImportCategorizedView::thumbnailSize() const { /* ImportThumbnailModel *thumbModel = importThumbnailModel(); + if (thumbModel) + { return thumbModel->thumbnailSize(); + } */ if (d->delegate) { return d->delegate->thumbnailSize(); } return ThumbnailSize(); } void ImportCategorizedView::setThumbnailSize(int size) { setThumbnailSize(ThumbnailSize(size)); } void ImportCategorizedView::setThumbnailSize(const ThumbnailSize& s) { // we abuse this pair of method calls to restore scroll position // TODO check if needed + layoutAboutToBeChanged(); d->delegate->setThumbnailSize(s); layoutWasChanged(); } void ImportCategorizedView::setCurrentWhenAvailable(qlonglong camItemId) { d->scrollToItemId = camItemId; } void ImportCategorizedView::setCurrentUrl(const QUrl& url) { if (url.isEmpty()) { clearSelection(); setCurrentIndex(QModelIndex()); return; } QString path = url.toLocalFile(); QModelIndex index = d->filterModel->indexForPath(path); if (!index.isValid()) { return; } clearSelection(); setCurrentIndex(index); } void ImportCategorizedView::setCurrentInfo(const CamItemInfo& info) { QModelIndex index = d->filterModel->indexForCamItemInfo(info); clearSelection(); setCurrentIndex(index); } void ImportCategorizedView::setSelectedUrls(const QList& urlList) { QItemSelection mySelection; for (QList::const_iterator it = urlList.constBegin() ; it!=urlList.constEnd() ; ++it) { const QString path = it->toLocalFile(); const QModelIndex index = d->filterModel->indexForPath(path); if (!index.isValid()) { qCWarning(DIGIKAM_IMPORTUI_LOG) << "no QModelIndex found for" << *it; } else { // TODO: is there a better way? + mySelection.select(index, index); } } clearSelection(); selectionModel()->select(mySelection, QItemSelectionModel::Select); } void ImportCategorizedView::setSelectedCamItemInfos(const QList& infos) { QItemSelection mySelection; foreach (const CamItemInfo& info, infos) { QModelIndex index = d->filterModel->indexForCamItemInfo(info); mySelection.select(index, index); } selectionModel()->select(mySelection, QItemSelectionModel::ClearAndSelect); } void ImportCategorizedView::hintAt(const CamItemInfo& info) { if (info.isNull()) { return; } QModelIndex index = d->filterModel->indexForCamItemInfo(info); if (!index.isValid()) { return; } selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); scrollTo(index); } void ImportCategorizedView::addOverlay(ItemDelegateOverlay* overlay, ImportDelegate* delegate) { if (!delegate) { delegate = d->delegate; } delegate->installOverlay(overlay); if (delegate == d->delegate) { overlay->setView(this); overlay->setActive(true); } } void ImportCategorizedView::removeOverlay(ItemDelegateOverlay* overlay) { ImportDelegate* delegate = dynamic_cast(overlay->delegate()); if (delegate) { delegate->removeOverlay(overlay); } overlay->setView(nullptr); } void ImportCategorizedView::updateGeometries() { ItemViewCategorized::updateGeometries(); d->delayedEnterTimer->start(); } void ImportCategorizedView::slotDelayedEnter() { // re-emit entered() for index under mouse (after layout). + QModelIndex mouseIndex = indexAt(mapFromGlobal(QCursor::pos())); if (mouseIndex.isValid()) { emit DCategorizedView::entered(mouseIndex); } } void ImportCategorizedView::addSelectionOverlay(ImportDelegate* delegate) { addOverlay(new ItemSelectionOverlay(this), delegate); } void ImportCategorizedView::scrollToStoredItem() { if (d->scrollToItemId) { if (d->model->hasImage(d->scrollToItemId)) { QModelIndex index = d->filterModel->indexForCamItemId(d->scrollToItemId); setCurrentIndex(index); scrollToRelaxed(index, QAbstractItemView::PositionAtCenter); d->scrollToItemId = 0; } } } void ImportCategorizedView::slotCamItemInfosAdded() { if (d->scrollToItemId) { scrollToStoredItem(); } } void ImportCategorizedView::slotFileChanged(const QString& filePath) { QModelIndex index = d->filterModel->indexForPath(filePath); if (index.isValid()) { update(index); } } void ImportCategorizedView::indexActivated(const QModelIndex& index, Qt::KeyboardModifiers modifiers) { CamItemInfo info = d->filterModel->camItemInfo(index); if (!info.isNull()) { activated(info, modifiers); emit camItemInfoActivated(info); } } void ImportCategorizedView::currentChanged(const QModelIndex& index, const QModelIndex& previous) { ItemViewCategorized::currentChanged(index, previous); emit currentChanged(d->filterModel->camItemInfo(index)); } void ImportCategorizedView::selectionChanged(const QItemSelection& selectedItems, const QItemSelection& deselectedItems) { ItemViewCategorized::selectionChanged(selectedItems, deselectedItems); if (!selectedItems.isEmpty()) { emit selected(d->filterModel->camItemInfos(selectedItems.indexes())); } if (!deselectedItems.isEmpty()) { emit deselected(d->filterModel->camItemInfos(deselectedItems.indexes())); } } void ImportCategorizedView::activated(const CamItemInfo&, Qt::KeyboardModifiers) { // implemented in subclass } void ImportCategorizedView::showContextMenuOnIndex(QContextMenuEvent* event, const QModelIndex& index) { CamItemInfo info = d->filterModel->camItemInfo(index); showContextMenuOnInfo(event, info); } void ImportCategorizedView::showContextMenuOnInfo(QContextMenuEvent*, const CamItemInfo&) { // implemented in subclass } void ImportCategorizedView::paintEvent(QPaintEvent* e) { ItemViewCategorized::paintEvent(e); } QItemSelectionModel* ImportCategorizedView::getSelectionModel() const { return selectionModel(); } AbstractItemDragDropHandler* ImportCategorizedView::dragDropHandler() const { return d->model->dragDropHandler(); } void ImportCategorizedView::slotIccSettingsChanged(const ICCSettingsContainer&, const ICCSettingsContainer&) { viewport()->update(); } } // namespace Digikam diff --git a/core/utilities/import/views/importcategorizedview.h b/core/utilities/import/views/importcategorizedview.h index d0589962a8..f5a479326c 100644 --- a/core/utilities/import/views/importcategorizedview.h +++ b/core/utilities/import/views/importcategorizedview.h @@ -1,188 +1,218 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-07-13 * Description : Qt categorized item view for camera items * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_IMPORT_CATEGORIZED_VIEW_H #define DIGIKAM_IMPORT_CATEGORIZED_VIEW_H // Local includes #include "itemviewcategorized.h" #include "importimagemodel.h" #include "importfiltermodel.h" #include "importthumbnailmodel.h" #include "itemdelegateoverlay.h" #include "camiteminfo.h" #include "digikam_export.h" namespace Digikam { class ImportDelegate; class ICCSettingsContainer; class DIGIKAM_EXPORT ImportCategorizedView : public ItemViewCategorized { Q_OBJECT public: explicit ImportCategorizedView(QWidget* const parent = nullptr); ~ImportCategorizedView(); void setModels(ImportItemModel* model, ImportSortFilterModel* filterModel); ImportItemModel* importItemModel() const; ImportSortFilterModel* importSortFilterModel() const; QItemSelectionModel* getSelectionModel() const; - /// Returns any ImportFilterModel in chain. May not be sourceModel() + /** + * Returns any ImportFilterModel in chain. May not be sourceModel() + */ ImportFilterModel* importFilterModel() const; - /// Returns 0 if the ImportItemModel is not an ImportThumbnailModel + /** + * Returns 0 if the ImportItemModel is not an ImportThumbnailModel + */ ImportThumbnailModel* importThumbnailModel() const; ImportDelegate* delegate() const; CamItemInfo currentInfo() const; QUrl currentUrl() const; QList selectedCamItemInfos() const; QList selectedCamItemInfosCurrentFirst() const; QList selectedUrls() const; QList camItemInfos() const; QList urls() const; - /** Selects the index as current and scrolls to it */ + /** + * Selects the index as current and scrolls to it + */ void toIndex(const QUrl& url); /** Returns the n-th info after the given one. * Specifically, return the previous info for nth = -1 * and the next info for n = 1. * Returns a null info if either startingPoint or the nth info are - * not contained in the model */ + * not contained in the model + */ CamItemInfo nextInOrder(const CamItemInfo& startingPoint, int nth); CamItemInfo previousInfo(const CamItemInfo& info) { return nextInOrder(info, -1); } CamItemInfo nextInfo(const CamItemInfo& info) { return nextInOrder(info, 1); } - /// Add and remove an overlay. It will as well be removed automatically when destroyed. - /// Unless you pass a different delegate, the current delegate will be used. + /** + * Add and remove an overlay. It will as well be removed automatically when destroyed. + * Unless you pass a different delegate, the current delegate will be used. + */ void addOverlay(ItemDelegateOverlay* overlay, ImportDelegate* delegate = nullptr); void removeOverlay(ItemDelegateOverlay* overlay); void addSelectionOverlay(ImportDelegate* delegate = nullptr); ThumbnailSize thumbnailSize() const; virtual void setThumbnailSize(const ThumbnailSize& size); public Q_SLOTS: void setThumbnailSize(int size); - /** Scroll the view to the given item when it becomes available */ + /** + * Scroll the view to the given item when it becomes available + */ void setCurrentWhenAvailable(qlonglong camItemId); - /** Set as current item the item identified by its file url */ + /** + * Set as current item the item identified by its file url + */ void setCurrentUrl(const QUrl& url); - /** Set as current item the item identified by the CamItemInfo */ + /** + * Set as current item the item identified by the CamItemInfo + */ void setCurrentInfo(const CamItemInfo& info); - /** Set selected items identified by their file urls */ + /** + * Set selected items identified by their file urls + */ void setSelectedUrls(const QList& urlList); - /** Set selected items */ + /** + * Set selected items + */ void setSelectedCamItemInfos(const QList& infos); - /** Does something to gain attention for info, but not changing current selection */ + /** + * Does something to gain attention for info, but not changing current selection + */ void hintAt(const CamItemInfo& info); Q_SIGNALS: void currentChanged(const CamItemInfo& info); - /// Emitted when new items are selected. The parameter includes only the newly selected infos, - /// there may be other already selected infos. + /** + * Emitted when new items are selected. The parameter includes only the newly selected infos, + * there may be other already selected infos. + */ void selected(const QList& newSelectedInfos); - /// Emitted when items are deselected. There may be other selected infos left. - /// This signal is not emitted when the model is reset; then only selectionCleared is emitted. + /** + * Emitted when items are deselected. There may be other selected infos left. + * This signal is not emitted when the model is reset; then only selectionCleared is emitted. + */ void deselected(const QList& nowDeselectedInfos); - /// Emitted when the given CamItemInfo is activated. Info is never null. + /** + * Emitted when the given CamItemInfo is activated. Info is never null. + */ void camItemInfoActivated(const CamItemInfo& info); - /// Emitted when a new model is set + /** + * Emitted when a new model is set + */ void modelChanged(); protected Q_SLOTS: void slotCamItemInfosAdded(); protected: - // reimplemented from parent class + + /// reimplemented from parent class QSortFilterProxyModel* filterModel() const override; AbstractItemDragDropHandler* dragDropHandler() const override; QModelIndex nextIndexHint(const QModelIndex& indexToAnchor, const QItemSelectionRange& removed) const override; void setItemDelegate(ImportDelegate* delegate); void indexActivated(const QModelIndex& index, Qt::KeyboardModifiers modifiers) override; void currentChanged(const QModelIndex& index, const QModelIndex& previous) override; void paintEvent(QPaintEvent* e) override; void selectionChanged(const QItemSelection&, const QItemSelection&) override; void updateGeometries() override; /// Reimplement these in a subclass virtual void activated(const CamItemInfo& info, Qt::KeyboardModifiers modifiers); virtual void showContextMenuOnInfo(QContextMenuEvent* event, const CamItemInfo& info); virtual void showContextMenuOnIndex(QContextMenuEvent* event, const QModelIndex& index) override; private Q_SLOTS: void slotFileChanged(const QString& filePath); void slotDelayedEnter(); void slotIccSettingsChanged(const ICCSettingsContainer&, const ICCSettingsContainer&); private: void scrollToStoredItem(); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_IMPORT_CATEGORIZED_VIEW_H diff --git a/core/utilities/import/views/importiconview.cpp b/core/utilities/import/views/importiconview.cpp index a12f12a297..f4aa2fa162 100644 --- a/core/utilities/import/views/importiconview.cpp +++ b/core/utilities/import/views/importiconview.cpp @@ -1,487 +1,516 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-22-07 * Description : Icon view for import tool items * * Copyright (C) 2012 by Islam Wazery * Copyright (C) 2012-2020 by Gilles Caulier * * This program is free software you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "importiconview_p.h" // Qt includes #include #include #include // Local includes #include "importcategorizedview.h" #include "importoverlays.h" #include "importsettings.h" #include "camitemsortsettings.h" #include "fileactionmngr.h" #include "importdelegate.h" #include "advancedrenamedialog.h" #include "advancedrenameprocessdialog.h" #include "itemviewutilities.h" #include "importcontextmenu.h" #include "importdragdrop.h" namespace Digikam { ImportIconView::ImportIconView(QWidget* const parent) : ImportCategorizedView(parent), d(new Private(this)) { ImportThumbnailModel* const model = new ImportThumbnailModel(this); ImportFilterModel* const filterModel = new ImportFilterModel(this); filterModel->setSourceImportModel(model); filterModel->sort(0); // an initial sorting is necessary setModels(model, filterModel); d->normalDelegate = new ImportNormalDelegate(this); setItemDelegate(d->normalDelegate); setSpacing(10); ImportSettings* const settings = ImportSettings::instance(); setThumbnailSize(ThumbnailSize(settings->getDefaultIconSize())); importItemModel()->setDragDropHandler(new ImportDragDropHandler(importItemModel())); setDragEnabled(true); setAcceptDrops(true); setDropIndicatorShown(false); setToolTipEnabled(settings->showToolTipsIsValid()); // selection overlay + addSelectionOverlay(d->normalDelegate); - //TODO: addSelectionOverlay(d->faceDelegate); +/* TODO + addSelectionOverlay(d->faceDelegate); +*/ // rotation overlays + d->rotateLeftOverlay = ImportRotateOverlay::left(this); d->rotateRightOverlay = ImportRotateOverlay::right(this); addOverlay(new ImportDownloadOverlay(this)); addOverlay(new ImportLockOverlay(this)); addOverlay(new ImportCoordinatesOverlay(this)); d->updateOverlays(); // rating overlay + ImportRatingOverlay* const ratingOverlay = new ImportRatingOverlay(this); addOverlay(ratingOverlay); - //TODO: GroupIndicatorOverlay* groupOverlay = new GroupIndicatorOverlay(this); - //TODO: addOverlay(groupOverlay); - +/* TODO + GroupIndicatorOverlay* groupOverlay = new GroupIndicatorOverlay(this); + addOverlay(groupOverlay); +*/ connect(ratingOverlay, SIGNAL(ratingEdited(QList,int)), this, SLOT(assignRating(QList,int))); - //TODO: connect(groupOverlay, SIGNAL(toggleGroupOpen(QModelIndex)), - //this, SLOT(groupIndicatorClicked(QModelIndex))); +/* TODO - //TODO: connect(groupOverlay, SIGNAL(showButtonContextMenu(QModelIndex,QContextMenuEvent*)), - //this, SLOT(showGroupContextMenu(QModelIndex,QContextMenuEvent*))); + connect(groupOverlay, SIGNAL(toggleGroupOpen(QModelIndex)), + this, SLOT(groupIndicatorClicked(QModelIndex))); - //TODO: connect(importItemModel()->dragDropHandler(), SIGNAL(assignTags(QList,QList)), - //FileActionMngr::instance(), SLOT(assignTags(QList,QList))); + connect(groupOverlay, SIGNAL(showButtonContextMenu(QModelIndex,QContextMenuEvent*)), + this, SLOT(showGroupContextMenu(QModelIndex,QContextMenuEvent*))); - //TODO: connect(importItemModel()->dragDropHandler(), SIGNAL(addToGroup(CamItemInfo,QList)), - //FileActionMngr::instance(), SLOT(addToGroup(CamItemInfo,QList))); + connect(importItemModel()->dragDropHandler(), SIGNAL(assignTags(QList,QList)), + FileActionMngr::instance(), SLOT(assignTags(QList,QList))); + connect(importItemModel()->dragDropHandler(), SIGNAL(addToGroup(CamItemInfo,QList)), + FileActionMngr::instance(), SLOT(addToGroup(CamItemInfo,QList))); +*/ // --- NOTE: use dynamic binding as slotSetupChanged() is a virtual method which can be re-implemented in derived classes. connect(settings, &ImportSettings::setupChanged, this, &ImportIconView::slotSetupChanged); this->slotSetupChanged(); - - // --- } ImportIconView::~ImportIconView() { delete d; } ItemViewUtilities* ImportIconView::utilities() const { return d->utilities; } void ImportIconView::setThumbnailSize(const ThumbnailSize& size) { ImportCategorizedView::setThumbnailSize(size); } int ImportIconView::fitToWidthIcons() { return delegate()->calculatethumbSizeToFit(viewport()->size().width()); } CamItemInfo ImportIconView::camItemInfo(const QString& folder, const QString& file) { QUrl url = QUrl::fromLocalFile(folder); url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + file); QModelIndex indexForCamItemInfo = importFilterModel()->indexForPath(url.toLocalFile()); if (indexForCamItemInfo.isValid()) { return importFilterModel()->camItemInfo(indexForCamItemInfo); } return CamItemInfo(); } CamItemInfo& ImportIconView::camItemInfoRef(const QString& folder, const QString& file) { QUrl url = QUrl::fromLocalFile(folder); url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + file); QModelIndex indexForCamItemInfo = importFilterModel()->indexForPath(url.toLocalFile()); QModelIndex mappedIndex = importFilterModel()->mapToSource(indexForCamItemInfo); return importItemModel()->camItemInfoRef(mappedIndex); } void ImportIconView::slotSetupChanged() { setToolTipEnabled(ImportSettings::instance()->showToolTipsIsValid()); setFont(ImportSettings::instance()->getIconViewFont()); d->updateOverlays(); ImportCategorizedView::slotSetupChanged(); } void ImportIconView::rename() { - QList urls = selectedUrls(); + QList urls = selectedUrls(); NewNamesList newNamesList; QPointer dlg = new AdvancedRenameDialog(this); dlg->slotAddImages(urls); if (dlg->exec() == QDialog::Accepted) { newNamesList = dlg->newNames(); } delete dlg; if (!newNamesList.isEmpty()) { QPointer dlg2 = new AdvancedRenameProcessDialog(newNamesList); dlg2->exec(); delete dlg2; } } void ImportIconView::deleteSelected(bool /*permanently*/) { CamItemInfoList camItemInfoList = selectedCamItemInfos(); - //FIXME: This way of deletion may not working with camera items. + // FIXME: This way of deletion may not working with camera items. /* if (d->utilities->deleteImages(camItemInfoList, permanently)) { awayFromSelection(); } */ } void ImportIconView::deleteSelectedDirectly(bool /*permanently*/) { CamItemInfoList camItemInfoList = selectedCamItemInfos(); - //FIXME: This way of deletion may not working with camera items. - //d->utilities->deleteImagesDirectly(camItemInfoList, permanently); + + // FIXME: This way of deletion may not working with camera items. +/* + d->utilities->deleteImagesDirectly(camItemInfoList, permanently); +*/ awayFromSelection(); } void ImportIconView::createGroupFromSelection() { - //TODO: Implement grouping in import tool. + // TODO: Implement grouping in import tool. /* QList selectedInfos = selectedCamItemInfosCurrentFirst(); CamItemInfo groupLeader = selectedInfos.takeFirst(); FileActionMngr::instance()->addToGroup(groupLeader, selectedInfos); */ } void ImportIconView::createGroupByTimeFromSelection() { - //TODO: Implement grouping in import tool. + // TODO: Implement grouping in import tool. /* QList selectedInfos = selectedCamItemInfosCurrentFirst(); while (selectedInfos.size() > 0) { QList group; CamItemInfo groupLeader = selectedInfos.takeFirst(); QDateTime dateTime = groupLeader.dateTime(); while (selectedInfos.size() > 0 && abs(dateTime.secsTo(selectedInfos.first().dateTime())) < 2) { group.push_back(selectedInfos.takeFirst()); } FileActionMngr::instance()->addToGroup(groupLeader, group); } */ } void ImportIconView::ungroupSelected() { - //TODO: Implement grouping in import tool. - //FileActionMngr::instance()->ungroup(selectedCamItemInfos()); + // TODO: Implement grouping in import tool. +/* + FileActionMngr::instance()->ungroup(selectedCamItemInfos()); +*/ } void ImportIconView::removeSelectedFromGroup() { - //TODO: Implement grouping in import tool. - //FileActionMngr::instance()->removeFromGroup(selectedCamItemInfos()); + // TODO: Implement grouping in import tool. +/* + FileActionMngr::instance()->removeFromGroup(selectedCamItemInfos()); +*/ } void ImportIconView::slotRotateLeft(const QList& /*indexes*/) { /* QList imageInfos; foreach (const QModelIndex& index, indexes) { ItemInfo imageInfo(importFilterModel()->camItemInfo(index).url()); imageInfos << imageInfo; } FileActionMngr::instance()->transform(imageInfos, MetaEngineRotation::Rotate270); */ } void ImportIconView::slotRotateRight(const QList& /*indexes*/) { /* QList imageInfos; foreach (const QModelIndex& index, indexes) { ItemInfo imageInfo(importFilterModel()->camItemInfo(index).url()); imageInfos << imageInfo; } FileActionMngr::instance()->transform(imageInfos, MetaEngineRotation::Rotate90); */ } void ImportIconView::activated(const CamItemInfo& info, Qt::KeyboardModifiers) { if (info.isNull()) { return; } if (ImportSettings::instance()->getItemLeftClickAction() == ImportSettings::ShowPreview) { emit previewRequested(info, false); } else { - //TODO: openFile(info); +/* TODO + openFile(info); +*/ } } void ImportIconView::showContextMenuOnInfo(QContextMenuEvent* event, const CamItemInfo& /*info*/) { QList selectedInfos = selectedCamItemInfosCurrentFirst(); QList selectedItemIDs; foreach (const CamItemInfo& info, selectedInfos) { selectedItemIDs << info.id; } // -------------------------------------------------------- QMenu popmenu(this); ImportContextMenuHelper cmhelper(&popmenu); cmhelper.addAction(QLatin1String("importui_fullscreen")); cmhelper.addAction(QLatin1String("options_show_menubar")); cmhelper.addAction(QLatin1String("import_zoomfit2window")); cmhelper.addSeparator(); + // -------------------------------------------------------- + cmhelper.addAction(QLatin1String("importui_imagedownload")); cmhelper.addAction(QLatin1String("importui_imagemarkasdownloaded")); cmhelper.addAction(QLatin1String("importui_imagelock")); cmhelper.addAction(QLatin1String("importui_delete")); cmhelper.addSeparator(); cmhelper.addAction(QLatin1String("importui_item_view")); cmhelper.addServicesMenu(selectedUrls()); - //TODO: cmhelper.addRotateMenu(selectedItemIDs); + +/* TODO + cmhelper.addRotateMenu(selectedItemIDs); +*/ + cmhelper.addSeparator(); + // -------------------------------------------------------- + cmhelper.addAction(QLatin1String("importui_selectall")); cmhelper.addAction(QLatin1String("importui_selectnone")); cmhelper.addAction(QLatin1String("importui_selectinvert")); cmhelper.addSeparator(); + // -------------------------------------------------------- - //cmhelper.addAssignTagsMenu(selectedItemIDs); - //cmhelper.addRemoveTagsMenu(selectedItemIDs); - //cmhelper.addSeparator(); +/* + cmhelper.addAssignTagsMenu(selectedItemIDs); + cmhelper.addRemoveTagsMenu(selectedItemIDs); + cmhelper.addSeparator(); +*/ // -------------------------------------------------------- + cmhelper.addLabelsAction(); - //if (!d->faceMode) - //{ - // cmhelper.addGroupMenu(selectedItemIDs); - //} +/* + if (!d->faceMode) + { + cmhelper.addGroupMenu(selectedItemIDs); + } // special action handling -------------------------------- - //connect(&cmhelper, SIGNAL(signalAssignTag(int)), - // this, SLOT(assignTagToSelected(int))); + connect(&cmhelper, SIGNAL(signalAssignTag(int)), + this, SLOT(assignTagToSelected(int))); - //TODO: Implement tag view for import tool. - //connect(&cmhelper, SIGNAL(signalPopupTagsView()), - // this, SIGNAL(signalPopupTagsView())); + TODO: Implement tag view for import tool. - //connect(&cmhelper, SIGNAL(signalRemoveTag(int)), - // this, SLOT(removeTagFromSelected(int))); + connect(&cmhelper, SIGNAL(signalPopupTagsView()), + this, SIGNAL(signalPopupTagsView())); - //connect(&cmhelper, SIGNAL(signalGotoTag(int)), - //this, SIGNAL(gotoTagAndImageRequested(int))); + connect(&cmhelper, SIGNAL(signalRemoveTag(int)), + this, SLOT(removeTagFromSelected(int))); + connect(&cmhelper, SIGNAL(signalGotoTag(int)), + this, SIGNAL(gotoTagAndImageRequested(int))); +*/ connect(&cmhelper, SIGNAL(signalAssignPickLabel(int)), this, SLOT(assignPickLabelToSelected(int))); connect(&cmhelper, SIGNAL(signalAssignColorLabel(int)), this, SLOT(assignColorLabelToSelected(int))); connect(&cmhelper, SIGNAL(signalAssignRating(int)), this, SLOT(assignRatingToSelected(int))); +/* + connect(&cmhelper, SIGNAL(signalAddToExistingQueue(int)), + this, SLOT(insertSelectedToExistingQueue(int))); - //connect(&cmhelper, SIGNAL(signalAddToExistingQueue(int)), - //this, SLOT(insertSelectedToExistingQueue(int))); - - //FIXME: connect(&cmhelper, SIGNAL(signalCreateGroup()), - //this, SLOT(createGroupFromSelection())); - - //connect(&cmhelper, SIGNAL(signalUngroup()), - //this, SLOT(ungroupSelected())); + connect(&cmhelper, SIGNAL(signalCreateGroup()), + this, SLOT(createGroupFromSelection())); - //connect(&cmhelper, SIGNAL(signalRemoveFromGroup()), - //this, SLOT(removeSelectedFromGroup())); + connect(&cmhelper, SIGNAL(signalUngroup()), + this, SLOT(ungroupSelected())); + connect(&cmhelper, SIGNAL(signalRemoveFromGroup()), + this, SLOT(removeSelectedFromGroup())); +*/ // -------------------------------------------------------- cmhelper.exec(event->globalPos()); } void ImportIconView::showContextMenu(QContextMenuEvent* event) { QMenu popmenu(this); ImportContextMenuHelper cmhelper(&popmenu); cmhelper.addAction(QLatin1String("importui_fullscreen")); cmhelper.addAction(QLatin1String("options_show_menubar")); cmhelper.addSeparator(); cmhelper.addAction(QLatin1String("importui_close")); // -------------------------------------------------------- cmhelper.exec(event->globalPos()); } void ImportIconView::assignTagToSelected(int tagID) { CamItemInfoList infos = selectedCamItemInfos(); foreach (const CamItemInfo& info, infos) { importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).tagIds.append(tagID); } } void ImportIconView::removeTagFromSelected(int tagID) { CamItemInfoList infos = selectedCamItemInfos(); foreach (const CamItemInfo& info, infos) { importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).tagIds.removeAll(tagID); } } void ImportIconView::assignPickLabel(const QModelIndex& index, int pickId) { importItemModel()->camItemInfoRef(index).pickLabel = pickId; } void ImportIconView::assignPickLabelToSelected(int pickId) { CamItemInfoList infos = selectedCamItemInfos(); foreach (const CamItemInfo& info, infos) { importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).pickLabel = pickId; } } void ImportIconView::assignColorLabel(const QModelIndex& index, int colorId) { importItemModel()->camItemInfoRef(index).colorLabel = colorId; } void ImportIconView::assignColorLabelToSelected(int colorId) { CamItemInfoList infos = selectedCamItemInfos(); foreach (const CamItemInfo& info, infos) { importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).colorLabel = colorId; } } void ImportIconView::assignRating(const QList& indexes, int rating) { foreach (const QModelIndex& index, indexes) { if (index.isValid()) { importItemModel()->camItemInfoRef(index).rating = rating; } } } void ImportIconView::assignRatingToSelected(int rating) { CamItemInfoList infos = selectedCamItemInfos(); foreach (const CamItemInfo& info, infos) { importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).rating = rating; } } } // namespace Digikam diff --git a/core/utilities/import/views/importiconview.h b/core/utilities/import/views/importiconview.h index b4e9ed470b..3c04f998d4 100644 --- a/core/utilities/import/views/importiconview.h +++ b/core/utilities/import/views/importiconview.h @@ -1,104 +1,107 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-22-07 * Description : Icon view for import tool items * * Copyright (C) 2012 by Islam Wazery * Copyright (C) 2012-2020 by Gilles Caulier * * This program is free software you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_IMPORT_ICON_VIEW_H #define DIGIKAM_IMPORT_ICON_VIEW_H // Local includes #include "importcategorizedview.h" namespace Digikam { class ItemViewUtilities; class ImportIconView : public ImportCategorizedView { Q_OBJECT public: explicit ImportIconView(QWidget* const parent = nullptr); ~ImportIconView(); ItemViewUtilities* utilities() const; int fitToWidthIcons(); CamItemInfo camItemInfo(const QString& folder, const QString& file); CamItemInfo& camItemInfoRef(const QString& folder, const QString& file); virtual void setThumbnailSize(const ThumbnailSize& size) override; public Q_SLOTS: void deleteSelected(bool permanently = false); void deleteSelectedDirectly(bool permanently = false); void createGroupFromSelection(); void createGroupByTimeFromSelection(); void ungroupSelected(); void removeSelectedFromGroup(); void rename(); void assignTagToSelected(int tagID); void removeTagFromSelected(int tagID); void assignPickLabel(const QModelIndex& index, int pickId); void assignPickLabelToSelected(int pickId); void assignColorLabel(const QModelIndex& index, int colorId); void assignColorLabelToSelected(int colorId); void assignRating(const QList& index, int rating); void assignRatingToSelected(int rating); Q_SIGNALS: void previewRequested(const CamItemInfo& info, bool downloadPreview); - //void signalPopupTagsView(); - +/* + void signalPopupTagsView(); +*/ private Q_SLOTS: void slotRotateLeft(const QList&); void slotRotateRight(const QList&); - //void slotInitProgressIndicator(); +/* + void slotInitProgressIndicator(); +*/ protected: virtual void activated(const CamItemInfo& info, Qt::KeyboardModifiers modifiers) override; virtual void showContextMenuOnInfo(QContextMenuEvent* event, const CamItemInfo& info) override; virtual void showContextMenu(QContextMenuEvent* event) override; virtual void slotSetupChanged() override; private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_IMPORT_ICON_VIEW_H diff --git a/core/utilities/import/views/importiconview_p.cpp b/core/utilities/import/views/importiconview_p.cpp index 4f89f9bd48..794e4702ad 100644 --- a/core/utilities/import/views/importiconview_p.cpp +++ b/core/utilities/import/views/importiconview_p.cpp @@ -1,83 +1,84 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-25-07 * Description : Private Qt item view for images * * Copyright (C) 2012 by Islam Wazery * Copyright (C) 2012-2020 by Gilles Caulier * * This program is free software you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "importiconview_p.h" namespace Digikam { ImportIconView::Private::Private(ImportIconView* const qq) - : overlaysActive(false), q_ptr(qq) + : utilities(nullptr), + normalDelegate(nullptr), + overlaysActive(false), + rotateLeftOverlay(nullptr), + rotateRightOverlay(nullptr), + q_ptr(qq) { - utilities = nullptr; - rotateLeftOverlay = nullptr; - rotateRightOverlay = nullptr; - normalDelegate = nullptr; } ImportIconView::Private::~Private() { } void ImportIconView::Private::updateOverlays() { Q_Q(ImportIconView); ImportSettings* const settings = ImportSettings::instance(); if (overlaysActive) { if (!settings->getIconShowOverlays()) { disconnect(rotateLeftOverlay, SIGNAL(signalRotate(QList)), q, SLOT(slotRotateLeft(QList))); disconnect(rotateRightOverlay, SIGNAL(signalRotate(QList)), q, SLOT(slotRotateRight(QList))); q->removeOverlay(rotateRightOverlay); q->removeOverlay(rotateLeftOverlay); overlaysActive = false; } } else { if (settings->getIconShowOverlays()) { q->addOverlay(rotateLeftOverlay, normalDelegate); q->addOverlay(rotateRightOverlay, normalDelegate); connect(rotateLeftOverlay, SIGNAL(signalRotate(QList)), q, SLOT(slotRotateLeft(QList))); connect(rotateRightOverlay, SIGNAL(signalRotate(QList)), q, SLOT(slotRotateRight(QList))); overlaysActive = true; } } } } // namespace Digikam diff --git a/core/utilities/import/views/importiconview_p.h b/core/utilities/import/views/importiconview_p.h index d5517fb984..fcf6b19fe5 100644 --- a/core/utilities/import/views/importiconview_p.h +++ b/core/utilities/import/views/importiconview_p.h @@ -1,73 +1,73 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-25-07 * Description : Private Qt item view for images * * Copyright (C) 2012 by Islam Wazery * Copyright (C) 2012-2020 by Gilles Caulier * * This program is free software you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_IMPORT_ICON_VIEW_PRIVATE_H #define DIGIKAM_IMPORT_ICON_VIEW_PRIVATE_H // Qt includes #include // Local includes #include "importiconview.h" #include "importdelegate.h" #include "importsettings.h" #include "importoverlays.h" namespace Digikam { class ImportNormalDelegate; class Q_DECL_HIDDEN ImportIconView::Private : public QObject { Q_OBJECT Q_DECLARE_PUBLIC(ImportIconView) public: explicit Private(ImportIconView* const qq); virtual ~Private(); void updateOverlays(); public: - ItemViewUtilities* utilities; + ItemViewUtilities* utilities; ImportNormalDelegate* normalDelegate; bool overlaysActive; ImportRotateOverlay* rotateLeftOverlay; ImportRotateOverlay* rotateRightOverlay; private: ImportIconView* q_ptr; }; } // namespace Digikam #endif // DIGIKAM_IMPORT_ICON_VIEW_PRIVATE_H diff --git a/core/utilities/import/views/importpreviewview.cpp b/core/utilities/import/views/importpreviewview.cpp index 5cf8396c8e..42d8fe3dae 100644 --- a/core/utilities/import/views/importpreviewview.cpp +++ b/core/utilities/import/views/importpreviewview.cpp @@ -1,502 +1,529 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-14-07 * Description : An embedded view to show the cam item preview widget. * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "importpreviewview.h" // Qt includes #include #include #include #include #include #include // KDE includes #include // Local includes #include "dimgpreviewitem.h" #include "fileactionmngr.h" #include "importcontextmenu.h" #include "previewlayout.h" #include "thememanager.h" #include "importsettings.h" #include "previewsettings.h" namespace Digikam { class Q_DECL_HIDDEN ImportPreviewViewItem : public DImgPreviewItem { public: explicit ImportPreviewViewItem(ImportPreviewView* const view) - : m_view(view)/*, m_group(0)*/ + : m_view(view) +/* + , m_group(0) +*/ { setAcceptHoverEvents(true); } /* void setFaceGroup(FaceGroup* group) { m_group = group; } */ void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { m_view->showContextMenu(m_info, event); } void setCamItemInfo(const CamItemInfo& info) { m_info = info; if (!info.isNull()) { setPath(info.url().toLocalFile(), true); } } void hoverEnterEvent(QGraphicsSceneHoverEvent* e) { - Q_UNUSED(e) //FIXME - //m_group->itemHoverEnterEvent(e); + Q_UNUSED(e) +/* FIXME + m_group->itemHoverEnterEvent(e); +*/ } void hoverLeaveEvent(QGraphicsSceneHoverEvent* e) { - Q_UNUSED(e) //FIXME: - //m_group->itemHoverLeaveEvent(e); + Q_UNUSED(e) +/* FIXME: + m_group->itemHoverLeaveEvent(e); +*/ } void hoverMoveEvent(QGraphicsSceneHoverEvent* e) { - Q_UNUSED(e) //FIXME: - //m_group->itemHoverMoveEvent(e); + Q_UNUSED(e) +/* FIXME + m_group->itemHoverMoveEvent(e); +*/ } CamItemInfo camItemInfo() const { return m_info; } protected: ImportPreviewView* m_view; - //FaceGroup* m_group; +/* + FaceGroup* m_group; +*/ CamItemInfo m_info; }; // --------------------------------------------------------------------- class Q_DECL_HIDDEN ImportPreviewView::Private { public: explicit Private() + : fullSize(false), + scale(1.0), + isValid(false), + mode(ImportPreviewView::IconViewPreview), + item(nullptr), + escapePreviewAction(nullptr), + prevAction(nullptr), + nextAction(nullptr), + rotLeftAction(nullptr), + rotRightAction(nullptr), + toolBar(nullptr) { - //peopleTagsShown = false; - fullSize = 0; - scale = 1.0; - item = nullptr; - isValid = false; - toolBar = nullptr; - escapePreviewAction = nullptr; - prevAction = nullptr; - nextAction = nullptr; - rotLeftAction = nullptr; - rotRightAction = nullptr; - //peopleToggleAction = 0; - //addPersonAction = 0; - //faceGroup = 0; - mode = ImportPreviewView::IconViewPreview; +/* + peopleTagsShown = false; + peopleToggleAction = 0; + addPersonAction = 0; + faceGroup = 0; +*/ } - //bool peopleTagsShown; bool fullSize; double scale; bool isValid; ImportPreviewView::Mode mode; ImportPreviewViewItem* item; QAction* escapePreviewAction; QAction* prevAction; QAction* nextAction; QAction* rotLeftAction; QAction* rotRightAction; - //QAction* peopleToggleAction; - //QAction* addPersonAction; - //QAction* forgetFacesAction; QToolBar* toolBar; - - //FaceGroup* faceGroup; +/* + bool peopleTagsShown; + QAction* peopleToggleAction; + QAction* addPersonAction; + QAction* forgetFacesAction; + FaceGroup* faceGroup; +*/ }; ImportPreviewView::ImportPreviewView(QWidget* const parent, Mode mode) : GraphicsDImgView(parent), d(new Private) { d->mode = mode; d->item = new ImportPreviewViewItem(this); setItem(d->item); - //d->faceGroup = new FaceGroup(this); - //d->faceGroup->setShowOnHover(true); - - //d->item->setFaceGroup(d->faceGroup); - +/* + d->faceGroup = new FaceGroup(this); + d->faceGroup->setShowOnHover(true); + d->item->setFaceGroup(d->faceGroup); +*/ connect(d->item, SIGNAL(loaded()), this, SLOT(camItemLoaded())); connect(d->item, SIGNAL(loadingFailed()), this, SLOT(camItemLoadingFailed())); // set default zoom + layout()->fitToWindow(); // ------------------------------------------------------------ installPanIcon(); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // ------------------------------------------------------------ d->escapePreviewAction = new QAction(QIcon::fromTheme(QLatin1String("folder-pictures")), i18n("Escape preview"), this); d->prevAction = new QAction(QIcon::fromTheme(QLatin1String("go-previous")), i18nc("go to previous image", "Back"), this); d->nextAction = new QAction(QIcon::fromTheme(QLatin1String("go-next")), i18nc("go to next image", "Forward"), this); d->rotLeftAction = new QAction(QIcon::fromTheme(QLatin1String("object-rotate-left")), i18nc("@info:tooltip", "Rotate Left"), this); d->rotRightAction = new QAction(QIcon::fromTheme(QLatin1String("object-rotate-right")), i18nc("@info:tooltip", "Rotate Right"), this); - //FIXME: d->addPersonAction = new QAction(QIcon::fromTheme(QLatin1String("list-add-user")), i18n("Add a Face Tag"), this); - //FIXME: d->forgetFacesAction = new QAction(QIcon::fromTheme(QLatin1String("list-remove-user")), i18n("Clear all faces on this image"), this); - //FIXME: d->peopleToggleAction = new Qaction(QIcon::fromTheme(QLatin1String("im-user")), i18n("Show Face Tags"), this); - //FIXME: d->peopleToggleAction->setCheckable(true); - +/* + d->addPersonAction = new QAction(QIcon::fromTheme(QLatin1String("list-add-user")), i18n("Add a Face Tag"), this); + d->forgetFacesAction = new QAction(QIcon::fromTheme(QLatin1String("list-remove-user")), i18n("Clear all faces on this image"), this); + d->peopleToggleAction = new Qaction(QIcon::fromTheme(QLatin1String("im-user")), i18n("Show Face Tags"), this); + d->peopleToggleAction->setCheckable(true); +*/ d->toolBar = new QToolBar(this); if (mode == IconViewPreview) { d->toolBar->addAction(d->prevAction); d->toolBar->addAction(d->nextAction); d->toolBar->addAction(d->escapePreviewAction); } d->toolBar->addAction(d->rotLeftAction); d->toolBar->addAction(d->rotRightAction); - //FIXME: d->toolBar->addAction(d->peopleToggleAction); - //FIXME: d->toolBar->addAction(d->addPersonAction); - +/* + d->toolBar->addAction(d->peopleToggleAction); + d->toolBar->addAction(d->addPersonAction); +*/ connect(d->prevAction, SIGNAL(triggered()), this, SIGNAL(toPreviousImage())); connect(d->nextAction, SIGNAL(triggered()), this, SIGNAL(toNextImage())); connect(d->escapePreviewAction, SIGNAL(triggered()), this, SIGNAL(signalEscapePreview())); connect(d->rotLeftAction, SIGNAL(triggered()), this, SLOT(slotRotateLeft())); connect(d->rotRightAction, SIGNAL(triggered()), this, SLOT(slotRotateRight())); +/* + connect(d->peopleToggleAction, SIGNAL(toggled(bool)), + d->faceGroup, SLOT(setVisible(bool))); - //FIXME: connect(d->peopleToggleAction, SIGNAL(toggled(bool)), - //d->faceGroup, SLOT(setVisible(bool))); - - //FIXME: connect(d->addPersonAction, SIGNAL(triggered()), - //d->faceGroup, SLOT(addFace())); - - //FIXME: connect(d->forgetFacesAction, SIGNAL(triggered()), - //d->faceGroup, SLOT(rejectAll())); + connect(d->addPersonAction, SIGNAL(triggered()), + d->faceGroup, SLOT(addFace())); + connect(d->forgetFacesAction, SIGNAL(triggered()), + d->faceGroup, SLOT(rejectAll())); +*/ // ------------------------------------------------------------ connect(this, SIGNAL(toNextImage()), this, SIGNAL(signalNextItem())); connect(this, SIGNAL(toPreviousImage()), this, SIGNAL(signalPrevItem())); connect(this, SIGNAL(activated()), this, SIGNAL(signalEscapePreview())); connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()), this, SLOT(slotThemeChanged())); connect(ImportSettings::instance(), SIGNAL(setupChanged()), this, SLOT(slotSetupChanged())); slotSetupChanged(); } ImportPreviewView::~ImportPreviewView() { delete d->item; delete d; } void ImportPreviewView::reload() { previewItem()->reload(); } void ImportPreviewView::camItemLoaded() { emit signalPreviewLoaded(true); d->rotLeftAction->setEnabled(true); d->rotRightAction->setEnabled(true); - //FIXME: d->faceGroup->setInfo(d->item->camItemInfo()); +/* FIXME + d->faceGroup->setInfo(d->item->camItemInfo()); +*/ } void ImportPreviewView::camItemLoadingFailed() { emit signalPreviewLoaded(false); d->rotLeftAction->setEnabled(false); d->rotRightAction->setEnabled(false); - //FIXME: d->faceGroup->setInfo(CamItemInfo()); +/* FIXME + d->faceGroup->setInfo(CamItemInfo()); +*/ } void ImportPreviewView::setCamItemInfo(const CamItemInfo& info, const CamItemInfo& previous, const CamItemInfo& next) { - //FIXME: d->faceGroup->aboutToSetInfo(info); +/* FIXME + d->faceGroup->aboutToSetInfo(info); +*/ d->item->setCamItemInfo(info); d->prevAction->setEnabled(!previous.isNull()); d->nextAction->setEnabled(!next.isNull()); QStringList previewPaths; if (identifyCategoryforMime(next.mime) == QLatin1String("image")) { previewPaths << next.url().toLocalFile(); } if (identifyCategoryforMime(previous.mime) == QLatin1String("image")) { previewPaths << previous.url().toLocalFile(); } d->item->setPreloadPaths(previewPaths); } QString ImportPreviewView::identifyCategoryforMime(QString mime) { return mime.split(QLatin1Char('/')).at(0); } CamItemInfo ImportPreviewView::getCamItemInfo() const { return d->item->camItemInfo(); } bool ImportPreviewView::acceptsMouseClick(QMouseEvent* e) { if (!GraphicsDImgView::acceptsMouseClick(e)) { return false; } return true; - //FIXME: return d->faceGroup->acceptsMouseClick(mapToScene(e->pos())); +/* FIXME + return d->faceGroup->acceptsMouseClick(mapToScene(e->pos())); +*/ } void ImportPreviewView::enterEvent(QEvent* e) { Q_UNUSED(e) //FIXME //FIXME: d->faceGroup->enterEvent(e); } void ImportPreviewView::leaveEvent(QEvent* e) { Q_UNUSED(e) //FIXME //FIXME: d->faceGroup->leaveEvent(e); } void ImportPreviewView::showEvent(QShowEvent* e) { GraphicsDImgView::showEvent(e); //FIXME: d->faceGroup->setVisible(d->peopleToggleAction->isChecked()); } void ImportPreviewView::showContextMenu(const CamItemInfo& info, QGraphicsSceneContextMenuEvent* event) { if (info.isNull()) { return; } event->accept(); QList idList; idList << info.id; QList selectedItems; selectedItems << info.url(); // -------------------------------------------------------- QMenu popmenu(this); ImportContextMenuHelper cmhelper(&popmenu); cmhelper.addAction(QLatin1String("importui_fullscreen")); cmhelper.addAction(QLatin1String("options_show_menubar")); cmhelper.addSeparator(); // -------------------------------------------------------- if (d->mode == IconViewPreview) { cmhelper.addAction(d->prevAction, true); cmhelper.addAction(d->nextAction, true); cmhelper.addAction(QLatin1String("importui_icon_view")); +/* //cmhelper.addGotoMenu(idList); +*/ cmhelper.addSeparator(); } // -------------------------------------------------------- - +/* //FIXME: cmhelper.addAction(d->peopleToggleAction, true); //FIXME: cmhelper.addAction(d->addPersonAction, true); //FIXME: cmhelper.addAction(d->forgetFacesAction, true); //FIXME: cmhelper.addSeparator(); - +*/ // -------------------------------------------------------- cmhelper.addServicesMenu(selectedItems); cmhelper.addRotateMenu(idList); cmhelper.addSeparator(); // -------------------------------------------------------- cmhelper.addAction(QLatin1String("importui_delete")); cmhelper.addSeparator(); // -------------------------------------------------------- - +/* //FIXME: cmhelper.addAssignTagsMenu(idList); //FIXME: cmhelper.addRemoveTagsMenu(idList); //FIXME: cmhelper.addSeparator(); - +*/ // -------------------------------------------------------- cmhelper.addLabelsAction(); // special action handling -------------------------------- - +/* //FIXME: connect(&cmhelper, SIGNAL(signalAssignTag(int)), //this, SLOT(slotAssignTag(int))); //FIXME: connect(&cmhelper, SIGNAL(signalPopupTagsView()), //this, SIGNAL(signalPopupTagsView())); //FIXME: connect(&cmhelper, SIGNAL(signalRemoveTag(int)), //this, SLOT(slotRemoveTag(int))); //FIXME: connect(&cmhelper, SIGNAL(signalAssignPickLabel(int)), //this, SLOT(slotAssignPickLabel(int))); //FIXME: connect(&cmhelper, SIGNAL(signalAssignColorLabel(int)), //this, SLOT(slotAssignColorLabel(int))); - +*/ connect(&cmhelper, SIGNAL(signalAssignPickLabel(int)), this, SIGNAL(signalAssignPickLabel(int))); connect(&cmhelper, SIGNAL(signalAssignColorLabel(int)), this, SIGNAL(signalAssignColorLabel(int))); connect(&cmhelper, SIGNAL(signalAssignRating(int)), this, SIGNAL(signalAssignRating(int))); - +/* //FIXME: connect(&cmhelper, SIGNAL(signalAddToExistingQueue(int)), //this, SIGNAL(signalAddToExistingQueue(int))); //FIXME: connect(&cmhelper, SIGNAL(signalGotoTag(int)), //this, SIGNAL(signalGotoTagAndItem(int))); - +*/ cmhelper.exec(event->screenPos()); } /* void ImportPreviewView::slotAssignTag(int tagID) { FileActionMngr::instance()->assignTag(d->item->camItemInfo(), tagID); } void ImportPreviewView::slotRemoveTag(int tagID) { FileActionMngr::instance()->removeTag(d->item->camItemInfo(), tagID); } */ void ImportPreviewView::slotThemeChanged() { QPalette plt(palette()); plt.setColor(backgroundRole(), qApp->palette().color(QPalette::Base)); setPalette(plt); } void ImportPreviewView::slotSetupChanged() { PreviewSettings settings; settings.quality = ImportSettings::instance()->getPreviewLoadFullImageSize() ? PreviewSettings::HighQualityPreview : PreviewSettings::FastPreview; previewItem()->setPreviewSettings(settings); d->toolBar->setVisible(ImportSettings::instance()->getPreviewShowIcons()); setShowText(ImportSettings::instance()->getPreviewShowIcons()); // pass auto-suggest? } void ImportPreviewView::slotRotateLeft() { /* ItemInfo info(d->item->camItemInfo().url().toLocalFile()); FileActionMngr::instance()->transform(QList() << info, MetaEngineRotation::Rotate270); */ } void ImportPreviewView::slotRotateRight() { /* ItemInfo info(d->item->camItemInfo().url().toLocalFile()); FileActionMngr::instance()->transform(QList() << info, MetaEngineRotation::Rotate90); */ } void ImportPreviewView::slotDeleteItem() { emit signalDeleteItem(); } } // namespace Digikam diff --git a/core/utilities/import/views/importpreviewview.h b/core/utilities/import/views/importpreviewview.h index e6409e66ee..396c6185ca 100644 --- a/core/utilities/import/views/importpreviewview.h +++ b/core/utilities/import/views/importpreviewview.h @@ -1,118 +1,119 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-14-07 * Description : An embedded view to show the cam item preview widget. * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_IMPORT_PREVIEW_VIEW_H #define DIGIKAM_IMPORT_PREVIEW_VIEW_H // Local includes #include "graphicsdimgview.h" #include "camiteminfo.h" namespace Digikam { class ImportPreviewView : public GraphicsDImgView { Q_OBJECT public: enum Mode { IconViewPreview }; public: explicit ImportPreviewView(QWidget* const parent, Mode mode = IconViewPreview); ~ImportPreviewView(); - void setCamItemInfo(const CamItemInfo& info = CamItemInfo(), + void setCamItemInfo(const CamItemInfo& info = CamItemInfo(), const CamItemInfo& previous = CamItemInfo(), const CamItemInfo& next = CamItemInfo()); CamItemInfo getCamItemInfo() const; void reload(); void setCamItemPath(const QString& path = QString()); void setPreviousNextPaths(const QString& previous, const QString& next); void showContextMenu(const CamItemInfo& info, QGraphicsSceneContextMenuEvent* event); private: QString identifyCategoryforMime(QString mime); Q_SIGNALS: void signalNextItem(); void signalPrevItem(); void signalDeleteItem(); void signalPreviewLoaded(bool success); void signalEscapePreview(); +/* //void signalAddToExistingQueue(int); - //void signalGotoFolderAndItem(const CamItemInfo&); //void signalGotoDateAndItem(const CamItemInfo&); //void signalGotoTagAndItem(int); //void signalPopupTagsView(); +*/ void signalAssignPickLabel(int); void signalAssignColorLabel(int); void signalAssignRating(int); protected: bool acceptsMouseClick(QMouseEvent* e) override; void enterEvent(QEvent* e) override; void leaveEvent(QEvent* e) override; void showEvent(QShowEvent* e) override; private Q_SLOTS: void camItemLoaded(); void camItemLoadingFailed(); - +/* //TODO: Implement Tags and Labels in Import Tool //void slotAssignTag(int tagID); //void slotRemoveTag(int tagID); //void slotAssignPickLabel(int pickId); //void slotAssignColorLabel(int colorId); - +*/ void slotThemeChanged(); void slotSetupChanged(); void slotRotateLeft(); void slotRotateRight(); void slotDeleteItem(); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_IMPORT_PREVIEW_VIEW_H