Krita Source Code Documentation
Loading...
Searching...
No Matches
wdgtagselection.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Agata Cacko cacko.azh@gmail.com
3 * SPDX-FileCopyrightText: 2023 Srirupa Datta <srirupa.sps@gmail.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "wdgtagselection.h"
9
10#include <QProcessEnvironment>
11#include <QMessageBox>
12#include <QStandardPaths>
13#include <QGridLayout>
14#include <QTableWidget>
15#include <QPainter>
16#include <QListWidget>
17#include <QAction>
18#include <QMouseEvent>
19#include <QPair>
20
22#include <KoDocumentInfo.h>
23#include <KoFileDialog.h>
24#include <kis_icon.h>
25#include <KoResource.h>
26#include <KoResourceServer.h>
28#include <KisTagModel.h>
29
31
32
33#include "kis_icon.h"
34
36 : QObject(widget)
37 , m_tagSelectionWidget(widget)
38 , m_editable(editable)
39{
40 connect(widget, SIGNAL(sigAddTagToSelection(KoID)), this, SLOT(slotAddTag(KoID)));
41 connect(widget, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTag(KoID)));
42 connect(widget, SIGNAL(sigCreateNewTag(QString)), this, SLOT(slotCreateNewTag(QString)));
43 m_tagSelectionWidget->setEnabled(false); // because there is no resource selected yet
44
45}
46
51
53{
54 QString oldResourceType = m_resourceType;
55 m_resourceIds = resourceIds;
56 m_resourceType = resourceType;
57
58 if (resourceType != "" && (oldResourceType != resourceType || !m_tagResourceModel || !m_tagModel)) {
59 m_tagResourceModel.reset(new KisTagResourceModel(resourceType));
61 m_tagModel.reset(new KisTagModel(resourceType));
63 }
64
65 if (resourceIds.count() == 0) {
66 QList<KoID> emptyList;
67 m_tagSelectionWidget->setTagList(m_editable, emptyList, emptyList);
68 m_tagSelectionWidget->setEnabled(false);
69 } else {
70 m_tagResourceModel->setResourcesFilter(m_resourceIds.toVector());
71 m_tagSelectionWidget->setEnabled(true);
72 updateView();
73 }
74}
75
77{
78 if (m_resourceIds.count() == 0) return;
79
80 KisTagSP tagsp = m_tagModel->tagForUrl(tag.id());
81
82 m_tagResourceModel->untagResources(tagsp, m_resourceIds.toVector());
83 updateView();
84}
85
87{
88 if (m_resourceIds.count() == 0) return;
89
90 KisTagSP tagsp = m_tagModel->tagForUrl(tag.id());
91
92 m_tagResourceModel->tagResources(tagsp, m_resourceIds.toVector());
93 updateView();
94}
95
97{
98 if (m_resourceIds.count() == 0 || m_resourceType == "" || tag == "") return;
99
100 KisTagSP tagsp = m_tagModel->tagForUrl(tag);
101 if (tagsp.isNull()) {
103 m_tagModel->addTag(tag, false, vec);
104 tagsp = m_tagModel->tagForUrl(tag);
105 } else if (!tagsp->active()) { // if tag is active, simply use that tag
106 QMessageBox question = QMessageBox(QMessageBox::Question,
107 i18nc("Dialog title", "Overwrite tag?"),
108 i18nc("Question to the user in a dialog about creating a tag",
109 "A tag with this unique name already exists. Do you want to replace it?")
110 );
111 question.addButton(
112 i18nc("Option in a dialog to discard the previously existing tag and creating a new one in its place",
113 "Replace (overwrite) tag"),
114 QMessageBox::DestructiveRole
115 );
116 question.addButton(
117 i18nc("Option in a dialog to undelete (reactivate) existing tag with its old assigned resources",
118 "Restore previous tag"),
119 QMessageBox::AcceptRole);
120 question.addButton(QMessageBox::Cancel);
121 question.exec();
122 QMessageBox::ButtonRole response = question.buttonRole(question.clickedButton());
123 if (response == QMessageBox::DestructiveRole) { // Overwrite
124 m_tagModel->addTag(tag, true, QVector<KoResourceSP>()); // will overwrite the tag
125 tagsp = m_tagModel->tagForUrl(tag);
126 } else if (response == QMessageBox::AcceptRole) { // Restore/use previously existing one
127 m_tagModel->setTagActive(tagsp);
128 } else {
129 updateView();
130 return;
131 }
132 }
133
135 m_tagResourceModel->tagResources(tagsp, m_resourceIds.toVector());
136 updateView();
137}
138
140{
141 if (m_resourceIds.count() == 0) {
142 QList<KoID> emptyList;
143 m_tagSelectionWidget->setTagList(m_editable, emptyList, emptyList);
144 return;
145 }
146
147 QMap<QString, int> tagsCounts;
148 for (int i = 0; i < m_tagModel->rowCount(); i++) {
149 QModelIndex idx = m_tagModel->index(i, 0);
150 int id = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt();
151 if (id < 0) {
152 continue;
153 }
154 QString tagUrl = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Url).toString();
155 if (!tagsCounts.contains(tagUrl)) {
156 tagsCounts.insert(tagUrl, 0);
157 }
158 }
159
160 // IMPORTANT: this only works correctly because there was setResourcesFilter() called in setResourceIds() function
161 // if at any moment there is situation this needs to work without setResourceIds(),
162 // call m_tagResourceModel->setResourcesFilter(m_resourceIds.toVector()); before this loop
163 // (it will make it slightly slower since it invalidates filter in the proxy model)
164 for (int i = 0; i < m_tagResourceModel->rowCount(); i++) {
165 QModelIndex idx = m_tagResourceModel->index(i, 0);
166 KisTagSP tag = m_tagResourceModel->data(idx, Qt::UserRole + KisAllTagResourceModel::Tag).value<KisTagSP>();
167 tagsCounts[tag->url()] += 1;
168 }
169 QList<KoID> semiSelected;
170 QList<KoID> selected;
171 QList<KoID> toSelect;
172
173 for (int i = 0; i < m_tagModel->rowCount(); i++) {
174 QModelIndex idx = m_tagModel->index(i, 0);
175 int id = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt();
176 if (id < 0) {
177 continue;
178 }
179 QString tagUrl = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Url).toString();
180 QString tagName = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Name).toString();
181 KoID tag(tagUrl, tagName);
182 if (tagsCounts[tagUrl] == m_resourceIds.count()) {
183 selected << tag;
184 } else if (tagsCounts[tagUrl] > 0) {
185 semiSelected << tag;
186 toSelect << tag; // we want to be able to add a tag to every resource even though some are already tagged
187 } else {
188 toSelect << tag;
189 }
190 }
191
192 m_tagSelectionWidget->setTagList(m_editable, selected, toSelect, semiSelected);
193}
194
196 : QObject(widget)
197 , m_tagSelectionWidget(widget)
198 , m_editable(editable)
199{
200 connect(widget, SIGNAL(sigAddTagToSelection(KoID)), this, SLOT(slotAddTag(KoID)));
201 connect(widget, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTag(KoID)));
202 updateView();
203}
204
209
211{
212 QList<int> selectedTags;
213 Q_FOREACH(QString resourceType, m_selectedTagsByResourceType.keys()) {
215 QList<KoID> tagList = m_selectedTagsByResourceType[resourceType];
216 Q_FOREACH(KoID tag, tagList) {
217 KisTagSP tagSP = model->tagForUrl(tag.id());
218 selectedTags << tagSP->id();
219 }
220 }
221 return selectedTags;
222}
223
225{
227 if (m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
229 updateView();
230 }
231 }
232
233 Q_EMIT tagRemoved(custom);
234}
235
248
250{
253 }
254 if (!m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
256 updateView();
257 }
258
259 Q_EMIT tagAdded(custom);
260}
261
263{
264 typedef QPair<QString, QString> resourceTypePair;
265 QList<QPair<QString, QString>> resourceTypes = {
266 resourceTypePair(i18n("Brush presets"), ResourceType::PaintOpPresets),
267 resourceTypePair(i18n("Brush tips"), ResourceType::Brushes),
268 resourceTypePair(i18n("Workspaces"), ResourceType::Workspaces),
269 resourceTypePair(i18n("Patterns"), ResourceType::Patterns),
270 resourceTypePair(i18n("Palettes"), ResourceType::Palettes),
271 resourceTypePair(i18n("Layer styles"), ResourceType::LayerStyles),
272 resourceTypePair(i18n("Gradients"), ResourceType::Gradients),
273 resourceTypePair(i18n("Gamut masks"), ResourceType::GamutMasks),
274 resourceTypePair(i18n("SeExpr scripts"), ResourceType::SeExprScripts),
275 };
276
278
280 QList<KoID> notSelected;
281
282
283 for (int i = 0; i < model->rowCount(); i++) {
284 QModelIndex idx = model->index(i, 0);
285 KisTagSP tag = model->data(idx, Qt::UserRole + KisAllTagsModel::KisTagRole).value<KisTagSP>();
286
287 if (tag.isNull() || tag->id() < 0) {
288 continue;
289 }
290
291 KoID custom = KoID(tag->url(), tag->name());
292
294 if (!m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
295 notSelected << custom;
296 }
297 } else { // no tags from this resource type are selected
298 notSelected << custom;
299 }
300 }
301
302 // m_selectedTags is already categorized correctly and is in KoID form
303
304 m_tagSelectionWidget->setTagList(m_editable, selected, notSelected);
305
306}
307
309{
310 m_resourceType = resourceType;
311 updateView();
312}
313
314
315
316
317
318
319
320
321
322
323
324
325
KisTagSP tagForUrl(const QString &url) const override
Retrieve a tag by url.
The KisTagResourceModel class makes it possible to retrieve the resources for certain tags or the tag...
void setTagList(bool editable, QList< KoID > &selected, QList< KoID > &notSelected)
QMap< QString, QList< KoID > > m_selectedTagsByResourceType
KisWdgTagSelectionControllerBundleTags(KisTagSelectionWidget *widget, bool editable)
KisTagSelectionWidget * m_tagSelectionWidget
void setResourceType(const QString &resourceType)
KisWdgTagSelectionControllerOneResource(KisTagSelectionWidget *widget, bool editable)
void setResourceIds(QString resourceType, QList< int > resourceIds)
KisTagSelectionWidget * m_tagSelectionWidget
QSharedPointer< KisTagResourceModel > m_tagResourceModel
QSharedPointer< KisTagModel > m_tagModel
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
const QString Palettes
const QString LayerStyles
const QString Brushes
const QString GamutMasks
const QString Patterns
const QString SeExprScripts
const QString Gradients
const QString Workspaces
const QString PaintOpPresets