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 // if you use this simple cast, the order of buttons must match order of options in the enum
107 int response = QMessageBox::question(0, i18nc("Dialog title", "Overwrite tag?"), i18nc("Question to the user in a dialog about creating a tag",
108 "A tag with this unique name already exists. Do you want to replace it?"),
109 i18nc("Option in a dialog to discard the previously existing tag and creating a new one in its place", "Replace (overwrite) tag"),
110 i18nc("Option in a dialog to undelete (reactivate) existing tag with its old assigned resources", "Restore previous tag"), i18n("Cancel"));
111 if (response == 0) { // Overwrite
112 m_tagModel->addTag(tag, true, QVector<KoResourceSP>()); // will overwrite the tag
113 tagsp = m_tagModel->tagForUrl(tag);
114 } else if (response == 1) { // Restore/use previously existing one
115 m_tagModel->setTagActive(tagsp);
116 } else {
117 updateView();
118 return;
119 }
120 }
121
123 m_tagResourceModel->tagResources(tagsp, m_resourceIds.toVector());
124 updateView();
125}
126
128{
129 if (m_resourceIds.count() == 0) {
130 QList<KoID> emptyList;
131 m_tagSelectionWidget->setTagList(m_editable, emptyList, emptyList);
132 return;
133 }
134
135 QMap<QString, int> tagsCounts;
136 for (int i = 0; i < m_tagModel->rowCount(); i++) {
137 QModelIndex idx = m_tagModel->index(i, 0);
138 int id = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt();
139 if (id < 0) {
140 continue;
141 }
142 QString tagUrl = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Url).toString();
143 if (!tagsCounts.contains(tagUrl)) {
144 tagsCounts.insert(tagUrl, 0);
145 }
146 }
147
148 // IMPORTANT: this only works correctly because there was setResourcesFilter() called in setResourceIds() function
149 // if at any moment there is situation this needs to work without setResourceIds(),
150 // call m_tagResourceModel->setResourcesFilter(m_resourceIds.toVector()); before this loop
151 // (it will make it slightly slower since it invalidates filter in the proxy model)
152 for (int i = 0; i < m_tagResourceModel->rowCount(); i++) {
153 QModelIndex idx = m_tagResourceModel->index(i, 0);
154 KisTagSP tag = m_tagResourceModel->data(idx, Qt::UserRole + KisAllTagResourceModel::Tag).value<KisTagSP>();
155 tagsCounts[tag->url()] += 1;
156 }
157 QList<KoID> semiSelected;
158 QList<KoID> selected;
159 QList<KoID> toSelect;
160
161 for (int i = 0; i < m_tagModel->rowCount(); i++) {
162 QModelIndex idx = m_tagModel->index(i, 0);
163 int id = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt();
164 if (id < 0) {
165 continue;
166 }
167 QString tagUrl = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Url).toString();
168 QString tagName = m_tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Name).toString();
169 KoID tag(tagUrl, tagName);
170 if (tagsCounts[tagUrl] == m_resourceIds.count()) {
171 selected << tag;
172 } else if (tagsCounts[tagUrl] > 0) {
173 semiSelected << tag;
174 toSelect << tag; // we want to be able to add a tag to every resource even though some are already tagged
175 } else {
176 toSelect << tag;
177 }
178 }
179
180 m_tagSelectionWidget->setTagList(m_editable, selected, toSelect, semiSelected);
181}
182
184 : QObject(widget)
185 , m_tagSelectionWidget(widget)
186 , m_editable(editable)
187{
188 connect(widget, SIGNAL(sigAddTagToSelection(KoID)), this, SLOT(slotAddTag(KoID)));
189 connect(widget, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTag(KoID)));
190 updateView();
191}
192
197
199{
200 QList<int> selectedTags;
201 Q_FOREACH(QString resourceType, m_selectedTagsByResourceType.keys()) {
203 QList<KoID> tagList = m_selectedTagsByResourceType[resourceType];
204 Q_FOREACH(KoID tag, tagList) {
205 KisTagSP tagSP = model->tagForUrl(tag.id());
206 selectedTags << tagSP->id();
207 }
208 }
209 return selectedTags;
210}
211
213{
215 if (m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
217 updateView();
218 }
219 }
220
221 Q_EMIT tagRemoved(custom);
222}
223
236
238{
241 }
242 if (!m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
244 updateView();
245 }
246
247 Q_EMIT tagAdded(custom);
248}
249
251{
252 typedef QPair<QString, QString> resourceTypePair;
253 QList<QPair<QString, QString>> resourceTypes = {
254 resourceTypePair(i18n("Brush presets"), ResourceType::PaintOpPresets),
255 resourceTypePair(i18n("Brush tips"), ResourceType::Brushes),
256 resourceTypePair(i18n("Workspaces"), ResourceType::Workspaces),
257 resourceTypePair(i18n("Patterns"), ResourceType::Patterns),
258 resourceTypePair(i18n("Palettes"), ResourceType::Palettes),
259 resourceTypePair(i18n("Layer styles"), ResourceType::LayerStyles),
260 resourceTypePair(i18n("Gradients"), ResourceType::Gradients),
261 resourceTypePair(i18n("Gamut masks"), ResourceType::GamutMasks),
262 resourceTypePair(i18n("SeExpr scripts"), ResourceType::SeExprScripts),
263 };
264
266
268 QList<KoID> notSelected;
269
270
271 for (int i = 0; i < model->rowCount(); i++) {
272 QModelIndex idx = model->index(i, 0);
273 KisTagSP tag = model->data(idx, Qt::UserRole + KisAllTagsModel::KisTagRole).value<KisTagSP>();
274
275 if (tag.isNull() || tag->id() < 0) {
276 continue;
277 }
278
279 KoID custom = KoID(tag->url(), tag->name());
280
282 if (!m_selectedTagsByResourceType[m_resourceType].contains(custom)) {
283 notSelected << custom;
284 }
285 } else { // no tags from this resource type are selected
286 notSelected << custom;
287 }
288 }
289
290 // m_selectedTags is already categorized correctly and is in KoID form
291
292 m_tagSelectionWidget->setTagList(m_editable, selected, notSelected);
293
294}
295
297{
298 m_resourceType = resourceType;
299 updateView();
300}
301
302
303
304
305
306
307
308
309
310
311
312
313
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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