Krita Source Code Documentation
Loading...
Searching...
No Matches
KisTagSelectionWidget.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Agata Cacko <cacko.azh@gmail.com>
3 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
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 <QMenu>
20#include <QApplication>
21#include <QInputDialog>
22#include <QPainterPath>
23
24#include <KoFileDialog.h>
25#include <kis_icon.h>
26#include <KoID.h>
27
28#include <kis_debug.h>
29#include <kis_global.h>
30#include <TagActions.h>
31
33#include <kis_signals_blocker.h>
34
35
36#include "kis_icon.h"
37
38
39WdgCloseableLabel::WdgCloseableLabel(KoID tag, bool editable, bool semiSelected, QWidget *parent)
40 : QWidget(parent)
41 , m_editable(editable)
42 , m_semiSelected(semiSelected)
43 , m_tag(tag)
44{
45 QHBoxLayout *layout = new QHBoxLayout(this);
46 layout->setContentsMargins(4, 0, 1, 0);
47 layout->setSpacing(2);
48
49 m_textLabel = new QLabel(parent);
50 m_textLabel->setText(tag.name());
51 m_textLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
52 layout->addWidget(m_textLabel);
53
54 if (m_editable) {
55 m_closeIconLabel = new QPushButton(parent);
56 m_closeIconLabel->setFlat(true);
57 m_closeIconLabel->setIcon(KisIconUtils::loadIcon("docker_close"));
58 m_closeIconLabel->setToolTip(i18n("Remove tag"));
59 m_closeIconLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
60 m_closeIconLabel->setMaximumSize(QSize(1, 1) * m_size);
61
62 connect(m_closeIconLabel, &QAbstractButton::clicked, this, [&]() {
64 });
65 layout->addWidget(m_closeIconLabel);
66 }
67 else {
68 //Add a margin to the right when there's no delete button
69 layout->setContentsMargins(4, 2, 4, 2);
70 }
71 setLayout(layout);
72}
73
78
79void WdgCloseableLabel::paintEvent(QPaintEvent *event)
80{
81 QPainter painter(this);
82
83 QColor backGroundColor = qApp->palette().light().color();
84 QColor foregroundColor = qApp->palette().windowText().color();
85 qreal r1 = 0.65;
86 qreal r2 = 1 - r1;
87 QColor outlineColor = QColor::fromRgb(256*(r1*backGroundColor.redF() + r2*foregroundColor.redF()),
88 256*(r1*backGroundColor.greenF() + r2*foregroundColor.greenF()),
89 256*(r1*backGroundColor.blueF() + r2*foregroundColor.blueF()));
90
91
92 QBrush windowB = qApp->palette().window();
93 QBrush windowTextB = qApp->palette().windowText();
94
95 QWidget::paintEvent(event);
96 painter.setRenderHint(QPainter::Antialiasing);
97 QPainterPath path;
98 path.addRoundedRect(this->rect(), 6, 6);
99
100 // good color:
101 painter.fillPath(path, qApp->palette().light());
102
103 if (m_semiSelected) {
104
105 QPen penwt = QPen(outlineColor, 1);
106 penwt.setStyle(Qt::DashLine);
107
108 QPainterPath outlinePath;
109 outlinePath.addRoundedRect(this->rect().adjusted(1, 1, -1, -1), 4, 4);
110
111 painter.setPen(penwt);
112 painter.drawPath(outlinePath);
113 }
114
115}
116
117WdgAddTagButton::WdgAddTagButton(QWidget *parent, bool createNew)
118 : QToolButton(parent),
119 m_createNew(createNew)
120{
121 setPopupMode(QToolButton::InstantPopup);
122 setIcon(KisIconUtils::loadIcon("list-add"));
123 setToolTip(i18n("Assign to tag"));
124 setContentsMargins(0, 0, 0, 0);
125 QSize defaultSize = QSize(1, 1)*m_size;
126 setMinimumSize(defaultSize);
127 setMaximumSize(defaultSize);
128
129 connect(this, SIGNAL(triggered(QAction*)), SLOT(slotAddNewTag(QAction*)));
130
131 if (m_createNew) {
132 UserInputTagAction *newTag = new UserInputTagAction(this);
133 newTag->setCloseParentOnTrigger(false);
134
135 connect(newTag, SIGNAL(triggered(QString)), this, SLOT(slotCreateNewTag(QString)), Qt::UniqueConnection);
136 m_createNewTagAction = newTag;
137 } else {
138 m_noTags = new QAction("No tags present");
139 QFont font = m_noTags->font();
140 font.setItalic(true);
141 m_noTags->setFont(font);
142 }
143
144}
145
150
152{
153 QList<QAction*> actionsToRemove = actions();
154 Q_FOREACH(QAction* action, actionsToRemove) {
155 removeAction(action);
156 }
157
158 Q_FOREACH(KoID tag, notSelected) {
159 QAction* action = new QAction(tag.name());
160 action->setData(QVariant::fromValue<KoID>(tag));
161 addAction(action);
162 }
163
164 QAction *separator = new QAction(this);
165 separator->setSeparator(true);
166 addAction(separator);
167
168 if (m_createNew) {
169 addAction(m_createNewTagAction);
170 setDefaultAction(0);
171 } else {
172 if (notSelected.count() == 0) {
173 addAction(m_noTags);
174 }
175 }
176}
177
179{
180 if (m_lastAction == CreateNewTag) {
182 } else {
184 }
185}
186
188{
189 if (action == m_createNewTagAction) {
190 m_lastTagToCreate = action->data().toString();
195 } else if (!action->data().isNull() && action->data().canConvert<KoID>()) {
196 m_lastTagToAdd = action->data().value<KoID>();
199 }
200
201
202 if (this->menu()) {
203 this->menu()->close();
204 }
205}
206
208{
209 m_lastTagToCreate = tagName;
214
215
216 if (this->menu()) {
217 this->menu()->close();
218 }
219}
220
221void WdgAddTagButton::paintEvent(QPaintEvent *event)
222{
223 Q_UNUSED(event);
224
225 QPainter painter(this);
226 painter.setRenderHint(QPainter::Antialiasing);
227 QPainterPath path;
228 path.addRoundedRect(this->rect(), 6, 6);
229 painter.fillPath(path, qApp->palette().light());
230
231 //Draw icon
232 painter.setPen(QPen(qApp->palette().windowText(), painter.pen().widthF()));
233 QIcon icon = this->icon();
234 QSize size = this->rect().size()*0.65;
235
236 QSize iconSize = icon.actualSize(size);
237 QPixmap pix = icon.pixmap(iconSize);
238 QSize realSize = iconSize.scaled(iconSize, Qt::KeepAspectRatio);//pix.rect().size();
239 QPointF p = this->rect().topLeft() + QPointF(this->rect().width() - realSize.width(), this->rect().height() - realSize.height()) / 2;
240
241 painter.setOpacity(!isEnabled() ? 0.3 : 1.0);
242 painter.drawPixmap(p, pix);
243 painter.setOpacity(1.0);
244}
245
246KisTagSelectionWidget::KisTagSelectionWidget(QWidget *parent, bool createNew)
247 : QWidget(parent),
248 m_createNew(createNew)
249{
252
253 m_layout->addWidget(m_addTagButton);
254 connect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)), Qt::UniqueConnection);
255 connect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)), Qt::UniqueConnection);
256
257 setLayout(m_layout);
258}
259
264
265void KisTagSelectionWidget::setTagList(bool editable, QList<KoID> &selected, QList<KoID> &notSelected)
266{
267 QList<KoID> semiSelected;
268 setTagList(editable, selected, notSelected, semiSelected);
269}
270
271void KisTagSelectionWidget::setTagList(bool editable, QList<KoID> &selected, QList<KoID> &notSelected, QList<KoID> &semiSelected)
272{
273 m_editable = editable;
274 QLayoutItem *item;
275
276 disconnect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)));
277 disconnect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)));
278
279 while((item = m_layout->takeAt(0))) {
280 if (item->widget()) {
281 if (!dynamic_cast<WdgAddTagButton*>(item->widget())) {
282 delete item->widget();
283 }
284 }
285 delete item;
286 }
287
288
289 WdgAddTagButton* addTagButton = dynamic_cast<WdgAddTagButton*>(m_addTagButton);
290 KIS_SAFE_ASSERT_RECOVER_RETURN(addTagButton);
291 addTagButton->setAvailableTagsList(notSelected);
292
293 Q_FOREACH(KoID tag, selected) {
294 WdgCloseableLabel* label = new WdgCloseableLabel(tag, m_editable, false, this);
295 connect(label, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTagFromSelection(KoID)), Qt::UniqueConnection);
296 m_layout->addWidget(label);
297 }
298
299 Q_FOREACH(KoID tag, semiSelected) {
300 WdgCloseableLabel* label = new WdgCloseableLabel(tag, m_editable, true, this);
301 connect(label, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTagFromSelection(KoID)), Qt::UniqueConnection);
302 m_layout->addWidget(label);
303 }
304
305 m_layout->addWidget(m_addTagButton);
306 m_addTagButton->setVisible(m_editable);
307
308
309 connect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)), Qt::UniqueConnection);
310 connect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)), Qt::UniqueConnection);
311
312 if (m_editable) {
313 }
314
315 if (layout()) {
316 layout()->invalidate();
317 }
318}
319
321{
322 if (!action) return;
323
324 if (!action->data().isNull()) {
325 KoID custom = action->data().value <KoID>();
326 Q_EMIT sigAddTagToSelection(custom);
327 }
328}
329
QPointF r2
const Params2D p
QPointF r1
int iconSize(qreal width, qreal height)
void slotAddTagToSelection(QAction *action)
void sigCreateNewTag(QString tag)
void setTagList(bool editable, QList< KoID > &selected, QList< KoID > &notSelected)
void slotRemoveTagFromSelection(KoID tag)
void sigRemoveTagFromSelection(KoID tag)
KisTagSelectionWidget(QWidget *parent=0, bool createNew=true)
void sigAddTagToSelection(KoID tag)
Definition KoID.h:30
QString name() const
Definition KoID.cpp:68
void setText(const QString &text)
void setCloseParentOnTrigger(bool closeParent)
The UserInputTagAction class defines an action with user text input that sends a signal with a simple...
Definition TagActions.h:131
void slotAddNewTag(QAction *action)
void paintEvent(QPaintEvent *event) override
void sigAddNewTag(KoID tag)
void sigCreateNewTag(QString tagName)
void setAvailableTagsList(QList< KoID > &notSelected)
void slotCreateNewTag(QString tagName)
WdgAddTagButton(QWidget *parent, bool createNew=true)
UserInputTagAction * m_createNewTagAction
WdgCloseableLabel(KoID tag, bool editable, bool semiSelected=false, QWidget *parent=0)
void paintEvent(QPaintEvent *event) override
QPushButton * m_closeIconLabel
void sigRemoveTagFromSelection(KoID tag)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
QIcon loadIcon(const QString &name)