File indexing completed on 2024-05-12 15:59:57

0001 
0002 /* This file is part of the KDE project
0003  *    SPDX-FileCopyrightText: 2013 Sascha Suelzer <s.suelzer@gmail.com>
0004  *    SPDX-FileCopyrightText: 2020 Agata Cacko <cacko.azh@gmail.com>
0005  *
0006  *    SPDX-License-Identifier: LGPL-2.0-or-later
0007  * */
0008 
0009 #include "KisResourceItemChooserContextMenu.h"
0010 
0011 #include <QDebug>
0012 #include <QLabel>
0013 #include <QGridLayout>
0014 
0015 #include <KoIcon.h>
0016 #include <klocalizedstring.h>
0017 #include <KoResource.h>
0018 #include <KisResourceModel.h>
0019 #include <KisTagResourceModel.h>
0020 #include <KisTag.h>
0021 
0022 
0023 #include "kis_debug.h"
0024 
0025 bool isSpecialTag(KisTagSP tag) {
0026     return !tag.isNull() && tag->id() < 0;
0027 }
0028 
0029 
0030 KisResourceItemChooserContextMenu::KisResourceItemChooserContextMenu(KoResourceSP resource,
0031                                                                      const KisTagSP currentlySelectedTag,
0032                                                                      KisTagChooserWidget *tagChooser)
0033     : m_tagChooserWidget(tagChooser)
0034 {
0035     QImage image = resource->image();
0036     QIcon icon(QPixmap::fromImage(image));
0037     QAction *label = new QAction(resource->name(), this);
0038     label->setIcon(icon);
0039 
0040     addAction(label);
0041 
0042     QMenu *removableTagsMenu;
0043     QMenu *assignableTagsMenu;
0044 
0045     m_tagModel = new KisTagModel(resource->resourceType().first);
0046     m_tagModel->sort(KisAllTagsModel::Name);
0047     KisResourceModel resourceModel(resource->resourceType().first);
0048     KisTagResourceModel tagResourceModel(resource->resourceType().first);
0049 
0050     tagResourceModel.setResourcesFilter(QVector<KoResourceSP>() << resource);
0051     tagResourceModel.sort(KisAllTagResourceModel::TagName);
0052 
0053     QList<KisTagSP> removableTags;
0054     for (int i = 0; i < tagResourceModel.rowCount(); ++i) {
0055         KisTagSP tag = tagResourceModel.data(tagResourceModel.index(i, 0), Qt::UserRole + KisAllTagResourceModel::Tag).value<KisTagSP>();
0056         if (!tag.isNull() && tag->valid() && !isSpecialTag(tag)) {
0057             removableTags << tag;
0058         }
0059     }
0060 
0061     QList<KisTagSP> assignableTags;
0062     for (int i = 0; i < m_tagModel->rowCount(); i++) {
0063         QModelIndex index = m_tagModel->index(i, 0);
0064         KisTagSP tag = m_tagModel->tagForIndex(index);
0065          if (!tag.isNull() && tag->valid() && !isSpecialTag(tag)) {
0066              assignableTags << tag;
0067          }
0068      }
0069 
0070     CompareWithOtherTagFunctor comparer(currentlySelectedTag);
0071 
0072     bool currentTagInRemovables = !currentlySelectedTag.isNull();
0073     currentTagInRemovables = currentTagInRemovables
0074             && (std::find_if(removableTags.begin(), removableTags.end(), comparer) != removableTags.end());
0075 
0076     assignableTagsMenu = addMenu(koIcon("list-add"),i18n("Assign to tag"));
0077 
0078     if (!removableTags.isEmpty()) {
0079         addSeparator();
0080         KisTagSP currentTag = currentlySelectedTag;
0081 
0082         if (!currentTag.isNull() && currentTagInRemovables) {
0083             // remove the current tag from both "Remove from tag: " and "Assign to tag: " lists
0084             removableTags.erase(std::remove_if(removableTags.begin(),
0085                                                removableTags.end(),
0086                                                comparer),
0087                                 removableTags.end());
0088             assignableTags.erase(std::remove_if(assignableTags.begin(),
0089                                                 assignableTags.end(),
0090                                                 comparer),
0091                                  assignableTags.end());
0092 
0093             SimpleExistingTagAction *removeTagAction = new SimpleExistingTagAction(resource, currentTag, this);
0094             removeTagAction->setText(i18n("Remove from this tag"));
0095             removeTagAction->setIcon(koIcon("list-remove"));
0096 
0097             connect(removeTagAction, SIGNAL(triggered(const KisTagSP, KoResourceSP)),
0098                     this, SLOT(removeResourceExistingTag(const KisTagSP, KoResourceSP)));
0099             addAction(removeTagAction);
0100         }
0101 
0102         if (!removableTags.isEmpty()) {
0103             removableTagsMenu = addMenu(koIcon("list-remove"),i18n("Remove from other tag"));
0104 
0105             KisTagSP empty;
0106             CompareWithOtherTagFunctor compareWithRemovable(empty);
0107             foreach (const KisTagSP tag, removableTags) {
0108 
0109                 if (tag.isNull()) {
0110                     continue;
0111                 }
0112 
0113                 compareWithRemovable.setReferenceTag(tag);
0114                 assignableTags.erase(std::remove_if(assignableTags.begin(),
0115                                                     assignableTags.end(),
0116                                                     compareWithRemovable),
0117                                      assignableTags.end());
0118 
0119                 SimpleExistingTagAction *removeTagAction = new SimpleExistingTagAction(resource, tag, this);
0120 
0121                 connect(removeTagAction, SIGNAL(triggered(const KisTagSP, KoResourceSP)),
0122                         this, SLOT(removeResourceExistingTag(const KisTagSP, KoResourceSP)));
0123                 removableTagsMenu->addAction(removeTagAction);
0124             }
0125         }
0126 
0127     }
0128 
0129     foreach (const KisTagSP &tag, assignableTags) {
0130         if (tag.isNull()) {
0131             continue;
0132         }
0133 
0134         SimpleExistingTagAction * addTagAction = new SimpleExistingTagAction(resource, tag, this);
0135 
0136         connect(addTagAction, SIGNAL(triggered(const KisTagSP, KoResourceSP)),
0137                 this, SLOT(addResourceExistingTag(const KisTagSP, KoResourceSP)));
0138 
0139         assignableTagsMenu->addAction(addTagAction);
0140     }
0141 
0142     assignableTagsMenu->addSeparator();
0143 
0144     NewTagResourceAction *addNewTagAction = new NewTagResourceAction(resource, this);
0145     connect(addNewTagAction, SIGNAL(triggered(QString, KoResourceSP)), m_tagChooserWidget, SLOT(addTag(QString, KoResourceSP)));
0146 
0147     assignableTagsMenu->addAction(addNewTagAction);
0148 
0149 }
0150 
0151 KisResourceItemChooserContextMenu::~KisResourceItemChooserContextMenu()
0152 {
0153     delete m_tagModel;
0154 }
0155 
0156 void KisResourceItemChooserContextMenu::removeResourceExistingTag(const KisTagSP tag, KoResourceSP resource)
0157 {
0158     KisTagResourceModel tagResourceModel(resource->resourceType().first);
0159     tagResourceModel.untagResources(tag, QVector<int>() << resource->resourceId());
0160 }
0161 
0162 void KisResourceItemChooserContextMenu::addResourceExistingTag(const KisTagSP tag, KoResourceSP resource)
0163 {
0164     KisTagResourceModel tagResourceModel(resource->resourceType().first);
0165     tagResourceModel.tagResources(tag, QVector<int>() << resource->resourceId());
0166 }