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(8, 0, 0, 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 layout->insertStretch(2, 1);
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 from tag"));
59 m_closeIconLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
60 m_closeIconLabel->setEnabled(m_editable);
61 m_closeIconLabel->setMaximumSize(QSize(1, 1) * m_size);
62
63 connect(m_closeIconLabel, &QAbstractButton::clicked, this, [&]() {
65 });
66 layout->addWidget(m_closeIconLabel);
67 }
68 setLayout(layout);
69}
70
75
76void WdgCloseableLabel::paintEvent(QPaintEvent *event)
77{
78 QPainter painter(this);
79
80 QColor backGroundColor = qApp->palette().light().color();
81 QColor foregroundColor = qApp->palette().windowText().color();
82 qreal r1 = 0.65;
83 qreal r2 = 1 - r1;
84 QColor outlineColor = QColor::fromRgb(256*(r1*backGroundColor.redF() + r2*foregroundColor.redF()),
85 256*(r1*backGroundColor.greenF() + r2*foregroundColor.greenF()),
86 256*(r1*backGroundColor.blueF() + r2*foregroundColor.blueF()));
87
88
89 QBrush windowB = qApp->palette().window();
90 QBrush windowTextB = qApp->palette().windowText();
91
92 QWidget::paintEvent(event);
93 painter.setRenderHint(QPainter::Antialiasing);
94 QPainterPath path;
95 path.addRoundedRect(this->rect(), 6, 6);
96
97 // good color:
98 painter.fillPath(path, qApp->palette().light());
99
100 if (m_semiSelected) {
101
102 QPen penwt = QPen(outlineColor, 1);
103 penwt.setStyle(Qt::DashLine);
104
105 QPainterPath outlinePath;
106 outlinePath.addRoundedRect(this->rect().adjusted(1, 1, -1, -1), 4, 4);
107
108 painter.setPen(penwt);
109 painter.drawPath(outlinePath);
110 }
111
112}
113
114WdgAddTagButton::WdgAddTagButton(QWidget *parent, bool createNew)
115 : QToolButton(parent),
116 m_createNew(createNew)
117{
118 setPopupMode(QToolButton::InstantPopup);
119 setIcon(KisIconUtils::loadIcon("list-add"));
120 setToolTip(i18n("Assign to tag"));
121 setContentsMargins(0, 0, 0, 0);
122 QSize defaultSize = QSize(1, 1)*m_size;
123 setMinimumSize(defaultSize);
124 setMaximumSize(defaultSize);
125
126 connect(this, SIGNAL(triggered(QAction*)), SLOT(slotAddNewTag(QAction*)));
127
128 if (m_createNew) {
129 UserInputTagAction *newTag = new UserInputTagAction(this);
130 newTag->setCloseParentOnTrigger(false);
131
132 connect(newTag, SIGNAL(triggered(QString)), this, SLOT(slotCreateNewTag(QString)), Qt::UniqueConnection);
133 m_createNewTagAction = newTag;
134 } else {
135 m_noTags = new QAction("No tags present");
136 QFont font = m_noTags->font();
137 font.setItalic(true);
138 m_noTags->setFont(font);
139 }
140
141}
142
147
149{
150 QList<QAction*> actionsToRemove = actions();
151 Q_FOREACH(QAction* action, actionsToRemove) {
152 removeAction(action);
153 }
154
155 Q_FOREACH(KoID tag, notSelected) {
156 QAction* action = new QAction(tag.name());
157 action->setData(QVariant::fromValue<KoID>(tag));
158 addAction(action);
159 }
160
161 QAction *separator = new QAction(this);
162 separator->setSeparator(true);
163 addAction(separator);
164
165 if (m_createNew) {
166 addAction(m_createNewTagAction);
167 setDefaultAction(0);
168 } else {
169 if (notSelected.count() == 0) {
170 addAction(m_noTags);
171 }
172 }
173}
174
176{
177 if (m_lastAction == CreateNewTag) {
179 } else {
181 }
182}
183
185{
186 if (action == m_createNewTagAction) {
187 m_lastTagToCreate = action->data().toString();
192 } else if (!action->data().isNull() && action->data().canConvert<KoID>()) {
193 m_lastTagToAdd = action->data().value<KoID>();
196 }
197
198
199 if (this->menu()) {
200 this->menu()->close();
201 }
202}
203
205{
206 m_lastTagToCreate = tagName;
211
212
213 if (this->menu()) {
214 this->menu()->close();
215 }
216}
217
218void WdgAddTagButton::paintEvent(QPaintEvent *event)
219{
220 Q_UNUSED(event);
221
222 QPainter painter(this);
223 painter.setRenderHint(QPainter::Antialiasing);
224 QPainterPath path;
225 path.addRoundedRect(this->rect(), 6, 6);
226 painter.fillPath(path, qApp->palette().light());
227 painter.setPen(QPen(qApp->palette().windowText(), painter.pen().widthF()));
228 QIcon icon = this->icon();
229 QSize size = this->rect().size()*0.6;
230
231 QSize iconSize = icon.actualSize(size);
232 QPixmap pix = icon.pixmap(iconSize);
233 QSize realSize = iconSize.scaled(iconSize, Qt::KeepAspectRatio);//pix.rect().size();
234 qreal hack = 0.5;
235 QPointF p = this->rect().topLeft() + QPointF(this->rect().width()/2 - realSize.width()/2 - hack, this->rect().height()/2 - realSize.height()/2 - hack);
236 painter.setOpacity(!isEnabled() ? 0.3 : 1.0);
237 painter.drawPixmap(p, pix);
238 painter.setOpacity(1.0);
239}
240
241KisTagSelectionWidget::KisTagSelectionWidget(QWidget *parent, bool createNew)
242 : QWidget(parent),
243 m_createNew(createNew)
244{
247
248 m_layout->addWidget(m_addTagButton);
249 connect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)), Qt::UniqueConnection);
250 connect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)), Qt::UniqueConnection);
251
252 setLayout(m_layout);
253}
254
259
260void KisTagSelectionWidget::setTagList(bool editable, QList<KoID> &selected, QList<KoID> &notSelected)
261{
262 QList<KoID> semiSelected;
263 setTagList(editable, selected, notSelected, semiSelected);
264}
265
266void KisTagSelectionWidget::setTagList(bool editable, QList<KoID> &selected, QList<KoID> &notSelected, QList<KoID> &semiSelected)
267{
268 m_editable = editable;
269 QLayoutItem *item;
270
271 disconnect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)));
272 disconnect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)));
273
274 while((item = m_layout->takeAt(0))) {
275 if (item->widget()) {
276 if (!dynamic_cast<WdgAddTagButton*>(item->widget())) {
277 delete item->widget();
278 }
279 }
280 delete item;
281 }
282
283
284 WdgAddTagButton* addTagButton = dynamic_cast<WdgAddTagButton*>(m_addTagButton);
285 KIS_SAFE_ASSERT_RECOVER_RETURN(addTagButton);
286 addTagButton->setAvailableTagsList(notSelected);
287
288 Q_FOREACH(KoID tag, selected) {
289 WdgCloseableLabel* label = new WdgCloseableLabel(tag, m_editable, false, this);
290 connect(label, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTagFromSelection(KoID)), Qt::UniqueConnection);
291 m_layout->addWidget(label);
292 }
293
294 Q_FOREACH(KoID tag, semiSelected) {
295 WdgCloseableLabel* label = new WdgCloseableLabel(tag, m_editable, true, this);
296 connect(label, SIGNAL(sigRemoveTagFromSelection(KoID)), this, SLOT(slotRemoveTagFromSelection(KoID)), Qt::UniqueConnection);
297 m_layout->addWidget(label);
298 }
299
300 m_layout->addWidget(m_addTagButton);
301 m_addTagButton->setVisible(m_editable);
302
303
304 connect(m_addTagButton, SIGNAL(sigCreateNewTag(QString)), this, SIGNAL(sigCreateNewTag(QString)), Qt::UniqueConnection);
305 connect(m_addTagButton, SIGNAL(sigAddNewTag(KoID)), this, SIGNAL(sigAddTagToSelection(KoID)), Qt::UniqueConnection);
306
307 if (m_editable) {
308 }
309
310 if (layout()) {
311 layout()->invalidate();
312 }
313}
314
316{
317 if (!action) return;
318
319 if (!action->data().isNull()) {
320 KoID custom = action->data().value <KoID>();
321 Q_EMIT sigAddTagToSelection(custom);
322 }
323}
324
QPointF r2
const Params2D p
QPointF r1
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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)