diff --git a/core/libs/tags/tagfolderview.cpp b/core/libs/tags/tagfolderview.cpp index 059fb323b9..7c83f67382 100644 --- a/core/libs/tags/tagfolderview.cpp +++ b/core/libs/tags/tagfolderview.cpp @@ -1,384 +1,386 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2005-03-22 * Description : tags folder view. * * Copyright (C) 2005-2006 by Joern Ahrens * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (C) 2009-2011 by Andi Clemens * Copyright (C) 2009-2011 by Johannes Wienke * * 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 "tagfolderview.h" // Qt includes #include #include #include #include #include // KDE includes #include // Local includes #include "digikam_config.h" #include "digikam_debug.h" #include "albummanager.h" #include "contextmenuhelper.h" #include "tagmodificationhelper.h" #include "facetags.h" namespace Digikam { class TagFolderView::Private { public: explicit Private() : showFindDuplicateAction(true), showDeleteFaceTagsAction(false), resetIconAction(0), findDuplAction(0) { } bool showFindDuplicateAction; bool showDeleteFaceTagsAction; QAction* resetIconAction; QAction* findDuplAction; }; TagFolderView::TagFolderView(QWidget* const parent, TagModel* const model) : TagTreeView(parent), d(new Private) { setAlbumModel(model); d->resetIconAction = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")), i18n("Reset Tag Icon"), this); d->findDuplAction = new QAction(QIcon::fromTheme(QLatin1String("tools-wizard")), i18n("Find Duplicates..."), this); setSortingEnabled(true); setSelectAlbumOnClick(true); setEnableContextMenu(true); } TagFolderView::~TagFolderView() { delete d; } void TagFolderView::setShowFindDuplicateAction(bool show) { d->showFindDuplicateAction = show; } void TagFolderView::setShowDeleteFaceTagsAction(bool show) { d->showDeleteFaceTagsAction = show; } QString TagFolderView::contextMenuTitle() const { return i18n("Tags"); } void TagFolderView::addCustomContextMenuActions(ContextMenuHelper& cmh, Album* album) { TAlbum* const tag = dynamic_cast (album); if (!tag) { return; } cmh.addActionNewTag(tagModificationHelper(), tag); #ifdef HAVE_AKONADICONTACT cmh.addCreateTagFromAddressbookMenu(); #endif cmh.addAction(d->resetIconAction); cmh.addSeparator(); QAction* const expandSel = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Expand Selected Nodes"), this); cmh.addAction(expandSel, this, SLOT(slotExpandNode()), false); QAction* const collapseSel = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Collapse Selected Recursively"), this); cmh.addAction(collapseSel, this, SLOT(slotCollapseNode()), false); cmh.addSeparator(); if (d->showFindDuplicateAction) { cmh.addAction(d->findDuplAction); } cmh.addExportMenu(); cmh.addSeparator(); + if (d->showDeleteFaceTagsAction) { cmh.addActionDeleteFaceTag(tagModificationHelper(), tag); cmh.addSeparator(); } else { cmh.addActionDeleteTag(tagModificationHelper(), tag); cmh.addSeparator(); // If the tag is no face tag, add the option to set it as face tag. if (!FaceTags::isPerson(tag->id()) && !tag->isRoot()) { cmh.addActionTagToFaceTag(tagModificationHelper(), tag); } } + cmh.addActionEditTag(tagModificationHelper(), tag); connect(&cmh, SIGNAL(signalAddNewTagFromABCMenu(QString)), this, SLOT(slotTagNewFromABCMenu(QString))); d->resetIconAction->setEnabled(!tag->isRoot()); } void TagFolderView::slotTagNewFromABCMenu(const QString& personName) { TAlbum* const parent = currentAlbum(); if (!parent) { return; } tagModificationHelper()->slotTagNew(parent, personName, QLatin1String("tag-people")); } void TagFolderView::slotExpandNode() { //QModelIndex root = this->model()->index(0,0); QItemSelectionModel* const model = this->selectionModel(); QModelIndexList selected = model->selectedIndexes(); QQueue greyNodes; foreach(const QModelIndex& index, selected) { greyNodes.append(index); expand(index); } - while(!greyNodes.isEmpty()) + while (!greyNodes.isEmpty()) { QModelIndex current = greyNodes.dequeue(); - if(!(current.isValid())) + if (!current.isValid()) { continue; } int it = 0; QModelIndex child = current.child(it++, 0); - while(child.isValid()) + while (child.isValid()) { expand(child); greyNodes.enqueue(child); child = current.child(it++, 0); } } } void TagFolderView::slotCollapseNode() { //QModelIndex root = this->model()->index(0,0); QItemSelectionModel* const model = this->selectionModel(); QModelIndexList selected = model->selectedIndexes(); QQueue greyNodes; foreach(const QModelIndex& index, selected) { greyNodes.append(index); collapse(index); } - while(!greyNodes.isEmpty()) + while (!greyNodes.isEmpty()) { QModelIndex current = greyNodes.dequeue(); - if(!(current.isValid())) + if (!current.isValid()) { continue; } int it = 0; QModelIndex child = current.child(it++, 0); - while(child.isValid()) + while (child.isValid()) { collapse(child); greyNodes.enqueue(child); child = current.child(it++, 0); } } } void TagFolderView::handleCustomContextMenuAction(QAction* action, AlbumPointer album) { Album* const a = album; TAlbum* const tag = dynamic_cast(a); if (!tag) { return; } if (!tag || !action) { return; } if (action == d->resetIconAction) { QString errMsg; AlbumManager::instance()->updateTAlbumIcon(tag, QLatin1String("tag"), 0, errMsg); } else if (action == d->findDuplAction) { QList selected = selectedTagAlbums(); emit signalFindDuplicates(selected); } } -void TagFolderView::setContexMenuItems(ContextMenuHelper& cmh, QList< TAlbum* > albums) +void TagFolderView::setContexMenuItems(ContextMenuHelper& cmh, const QList& albums) { - - if(albums.size() == 1) + if (albums.size() == 1) { addCustomContextMenuActions(cmh, albums.first()); return; } if (d->showFindDuplicateAction) { cmh.addAction(d->findDuplAction); } QAction* const expandSel = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Expand Selected Recursively"), this); cmh.addAction(expandSel, this, SLOT(slotExpandNode()), false); QAction* const collapseSel = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Collapse Selected Recursively"), this); cmh.addAction(collapseSel, this, SLOT(slotCollapseNode()), false); cmh.addSeparator(); cmh.addExportMenu(); cmh.addSeparator(); + if (d->showDeleteFaceTagsAction) { cmh.addActionDeleteFaceTags(tagModificationHelper(), albums); } else { cmh.addActionDeleteTags(tagModificationHelper(), albums); // If one of the selected tags is no face tag, add the action to mark them as face tags. - foreach (TAlbum* const tag, albums) + foreach(TAlbum* const tag, albums) { if (!FaceTags::isPerson(tag->id())) { cmh.addSeparator(); cmh.addActionTagToFaceTag(tagModificationHelper(), tag); break; } } } cmh.addSeparator(); } void TagFolderView::contextMenuEvent(QContextMenuEvent* event) { /* if (!d->enableContextMenu) { return; } */ Album* const album = albumFilterModel()->albumForIndex(indexAt(event->pos())); if (!showContextMenuAt(event, album)) { return; } // switch to the selected album if need /* if (d->selectOnContextMenu && album) { setCurrentAlbum(album); } */ // -------------------------------------------------------- QModelIndexList selectedItems = selectionModel()->selectedIndexes(); std::sort(selectedItems.begin(), selectedItems.end()); QList items; foreach(const QModelIndex& mIndex, selectedItems) { TAlbum* const temp = static_cast(albumForIndex(mIndex)); items.append(temp); } /** * If no item is selected append root tag */ if (items.isEmpty()) { QModelIndex root = this->model()->index(0, 0); items.append(static_cast(albumForIndex(root))); } QMenu popmenu(this); popmenu.addSection(contextMenuIcon(), contextMenuTitle()); ContextMenuHelper cmhelper(&popmenu); setContexMenuItems(cmhelper, items); /* foreach(ContextMenuElement* const element, d->contextMenuElements) { element->addActions(this, cmhelper, album); } */ AlbumPointer albumPointer(album); QAction* const choice = cmhelper.exec(QCursor::pos()); handleCustomContextMenuAction(choice, albumPointer); } } // namespace Digikam diff --git a/core/libs/tags/tagfolderview.h b/core/libs/tags/tagfolderview.h index f68f696c50..055ba371af 100644 --- a/core/libs/tags/tagfolderview.h +++ b/core/libs/tags/tagfolderview.h @@ -1,151 +1,151 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2005-03-22 * Description : tags folder view. * * Copyright (C) 2005-2006 by Joern Ahrens * Copyright (C) 2006-2018 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_TAG_FOLDER_VIEW_H #define DIGIKAM_TAG_FOLDER_VIEW_H // Qt includes #include // Local includes #include "albumtreeview.h" namespace Digikam { class ContextMenuHelper; class TagFolderView: public TagTreeView { Q_OBJECT public: /** * Constructor. * * @param parent parent for Qt's parent child mechanism * @param model tag model to display */ TagFolderView(QWidget* const parent, Digikam::TagModel* const model); /** * Destructor. */ virtual ~TagFolderView(); /** * Define whether to show the "find duplicate" action in context menus * or not. * * @param show if true the action to find duplicate images in * the tag album is displayed */ void setShowFindDuplicateAction(bool show); /** * Define whether to show the "Delete People Tags" action in context menus * or not. * * @param show if true the action to delete people tags in * the tag album is displayed */ void setShowDeleteFaceTagsAction(bool show); Q_SIGNALS: void signalFindDuplicates(const QList& albums); protected: QString contextMenuTitle() const; /** * Hook method to add custom actions to the generated context menu. * * The default implementation adds actions to reset the tag icon and to * find duplicates in a tag album. If you want to use these actions, * remember to call this class' implementation of this method and * the handleCustomContextMenuAction in your derived class. * * @param cmh helper object to create the context menu * @param album tag on which the context menu will be created. May be null if * it is requested on no tag entry */ virtual void addCustomContextMenuActions(ContextMenuHelper& cmh, Album* album); /** * Hook method to handle the custom context menu actions that were added * with addCustomContextMenuActions. * * @param action the action that was chosen by the user, may be null if none * of the custom actions were selected * @param album the tag on which the context menu was requested. May be null * if there was no */ virtual void handleCustomContextMenuAction(QAction* action, AlbumPointer album); /** * Reimplement contextMenuEvent from AbstractAlbumTree to support multiple * selection * * @param event context menu event triggered by right click */ void contextMenuEvent(QContextMenuEvent* event); /** * Implementation of AddCustomContextMenuActions(see above) that handle * multiple selection. If only one element is selected, only * AddCustomContextMenuActions is called * * @param cmh - helper object to create context menu * @param albums - vector of selected albums to be used on menu actions */ - virtual void setContexMenuItems(ContextMenuHelper& cmh, QList< TAlbum* > albums); + virtual void setContexMenuItems(ContextMenuHelper& cmh, const QList& albums); private Q_SLOTS: void slotTagNewFromABCMenu(const QString& personName); /** * @brief slotExpandNode - expands recursively selected nodes */ void slotExpandNode(); /** * @brief slotCollapseNode - collapse recursively selected nodes */ void slotCollapseNode(); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_TAG_FOLDER_VIEW_H diff --git a/core/libs/tags/tagsmanager/tagmngrtreeview.cpp b/core/libs/tags/tagsmanager/tagmngrtreeview.cpp index dab7769daa..8c963aa8c9 100644 --- a/core/libs/tags/tagsmanager/tagmngrtreeview.cpp +++ b/core/libs/tags/tagsmanager/tagmngrtreeview.cpp @@ -1,240 +1,241 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 20013-08-05 * Description : Tag Manager Tree View derived from TagsFolderView to implement * a custom context menu and some batch view options, such as * expanding multiple items * * Copyright (C) 2013 by Veaceslav Munteanu * * 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 "tagmngrtreeview.h" // Qt includes #include #include #include #include // Local includes #include "digikam_debug.h" #include "contextmenuhelper.h" #include "tagsmanager.h" namespace Digikam { class TagMngrTreeView::Private { public: + explicit Private() { tagMngr = 0; } TagsManager* tagMngr; }; TagMngrTreeView::TagMngrTreeView(TagsManager* const parent, TagModel* const model) : TagFolderView(parent, model), d(new Private()) { d->tagMngr = parent; setAlbumFilterModel(new TagsManagerFilterModel(this), albumFilterModel()); setSelectAlbumOnClick(false); expand(albumFilterModel()->rootAlbumIndex()); } TagMngrTreeView::~TagMngrTreeView() { delete d; } void TagMngrTreeView::contextMenuEvent(QContextMenuEvent* event) { QModelIndexList selectedItems = selectionModel()->selectedIndexes(); std::sort(selectedItems.begin(), selectedItems.end()); QList items; foreach(const QModelIndex& mIndex, selectedItems) { TAlbum* const temp = static_cast(albumForIndex(mIndex)); items.append(temp); } /** * Append root tag if no nodes are selected */ if (items.isEmpty()) { - QModelIndex root = this->model()->index(0, 0); + QModelIndex root = model()->index(0, 0); items.append(static_cast(albumForIndex(root))); } QMenu popmenu(this); popmenu.addSection(contextMenuIcon(), contextMenuTitle()); ContextMenuHelper cmhelper(&popmenu); setContexMenuItems(cmhelper, items); QAction* const choice = cmhelper.exec(QCursor::pos()); Q_UNUSED(choice); Q_UNUSED(event); } void TagMngrTreeView::setAlbumFilterModel(TagsManagerFilterModel* const filteredModel, CheckableAlbumFilterModel* const filterModel) { Q_UNUSED(filterModel); m_tfilteredModel = filteredModel; albumFilterModel()->setSourceFilterModel(m_tfilteredModel); } -void TagMngrTreeView::setContexMenuItems(ContextMenuHelper& cmh, QList albums) +void TagMngrTreeView::setContexMenuItems(ContextMenuHelper& cmh, const QList& albums) { bool isRoot = false; if (albums.size() == 1) { TAlbum* const tag = dynamic_cast (albums.first()); if (!tag) { return; } if (tag->isRoot()) { isRoot = true; } cmh.addActionNewTag(tagModificationHelper(), tag); } if (!isRoot) { cmh.addActionDeleteTags(tagModificationHelper(), albums); } else { /** This is a dummy action, delete is disable for root tag **/ QAction* deleteTagsAction = new QAction(QIcon::fromTheme(QLatin1String("user-trash")), i18n("Delete Tags"), this); cmh.addAction(deleteTagsAction); deleteTagsAction->setEnabled(false); } cmh.addSeparator(); QAction* const titleEdit = new QAction(QIcon::fromTheme(QLatin1String("document-edit")), i18n("Edit Tag Title"), this); titleEdit->setShortcut(QKeySequence(Qt::Key_F2)); QAction* const resetIcon = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")), i18n("Reset Tag Icon"), this); QAction* const invSel = new QAction(QIcon::fromTheme(QLatin1String("tag-reset")), i18n("Invert Selection"), this); QAction* const expandTree = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Expand Tag Tree"), this); QAction* const expandSel = new QAction(QIcon::fromTheme(QLatin1String("format-indent-more")), i18n("Expand Selected Nodes"), this); QAction* const delTagFromImg = new QAction(QIcon::fromTheme(QLatin1String("tag-delete")), i18n("Remove Tag from Images"), this); cmh.addAction(titleEdit, d->tagMngr, SLOT(slotEditTagTitle()), false); cmh.addAction(resetIcon, d->tagMngr, SLOT(slotResetTagIcon()), false); cmh.addAction(invSel, d->tagMngr, SLOT(slotInvertSel()), false); cmh.addAction(expandTree, this, SLOT(slotExpandTree()), false); cmh.addAction(expandSel, this , SLOT(slotExpandSelected()), false); cmh.addAction(delTagFromImg, d->tagMngr, SLOT(slotRemoveTagsFromImgs()), false); if (isRoot) { titleEdit->setEnabled(false); resetIcon->setEnabled(false); delTagFromImg->setEnabled(false); } if (albums.size() != 1) { titleEdit->setEnabled(false); } } void TagMngrTreeView::slotExpandSelected() { QModelIndexList list = selectionModel()->selectedIndexes(); foreach(const QModelIndex& index, list) { expand(index); } } void TagMngrTreeView::slotExpandTree() { - QModelIndex root = this->model()->index(0, 0); - QItemSelectionModel* const model = this->selectionModel(); + QModelIndex root = model()->index(0, 0); + QItemSelectionModel* const model = selectionModel(); QModelIndexList selected = model->selectedIndexes(); QQueue greyNodes; greyNodes.append(root); while (!greyNodes.isEmpty()) { QModelIndex current = greyNodes.dequeue(); - if (!(current.isValid())) + if (!current.isValid()) { continue; } - if (this->isExpanded(current)) + if (isExpanded(current)) { int it = 0; QModelIndex child = current.child(it++, 0); while (child.isValid()) { - if (this->isExpanded(child)) + if (isExpanded(child)) { greyNodes.enqueue(child); } else { expand(child); } child = current.child(it++, 0); } } else { expand(current); } } } } // namespace Digikam diff --git a/core/libs/tags/tagsmanager/tagmngrtreeview.h b/core/libs/tags/tagsmanager/tagmngrtreeview.h index fb4f3ea6dd..028e1c3131 100644 --- a/core/libs/tags/tagsmanager/tagmngrtreeview.h +++ b/core/libs/tags/tagsmanager/tagmngrtreeview.h @@ -1,105 +1,105 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 20013-08-05 * Description : Tag Manager Tree View derived from TagsFolderView to implement * a custom context menu and some batch view options, such as * expanding multiple items * * Copyright (C) 2013 by Veaceslav Munteanu * * 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_TAG_MNGR_TREE_VIEW_H #define DIGIKAM_TAG_MNGR_TREE_VIEW_H // Local includes #include "tagfolderview.h" namespace Digikam { class TagsManager; class TagMngrTreeView : public TagFolderView { Q_OBJECT public: explicit TagMngrTreeView(TagsManager* const parent, TagModel* const model); virtual ~TagMngrTreeView(); /** * @brief setAlbumFilterModel - reimplement from AbstractAlbumTree */ void setAlbumFilterModel(TagsManagerFilterModel* const filteredModel, CheckableAlbumFilterModel* const filterModel); TagsManagerFilterModel* getFilterModel() const { return m_tfilteredModel; } protected: /** * @brief setContexMenuItems - Reimplemented method from TagsFolderView. * Will set custom actions for Tags Manager. * Some actions are also available in toolbar * * @param chm - ContextMenuHelper class to help setting some * basic actions * @param albums - List of currently selected albums */ - virtual void setContexMenuItems(ContextMenuHelper& cmh, QList albums); + virtual void setContexMenuItems(ContextMenuHelper& cmh, const QList& albums); /** * @brief contextMenuEvent - Reimplement contextMenuEvent from AbstractAlbumTree * to support multiple selection * * @param event context menu event triggered by right click */ void contextMenuEvent(QContextMenuEvent* event); protected: TagsManagerFilterModel* m_tfilteredModel; public Q_SLOTS: /** * @brief slotExpandTree - connected to expandTree action and will * expand tree by one level */ void slotExpandTree(); /** * @brief slotExpandSelected - connected to expandSel action and will * expand selected nodes by one level */ void slotExpandSelected(); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_TAG_MNGR_TREE_VIEW_H