Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_brush_hud.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_brush_hud.h"
8
9#include <QGuiApplication>
10#include <QVBoxLayout>
11#include <QHBoxLayout>
12#include <QPointer>
13#include <QLabel>
14#include <QPainter>
15#include <QPaintEvent>
16#include <QScrollArea>
17#include <QEvent>
18#include <QToolButton>
19#include <QAction>
20
25#include "kis_paintop_preset.h"
29#include "kis_icon_utils.h"
32#include "kis_elided_label.h"
33
34#include "kis_canvas2.h"
35#include "KisViewManager.h"
36#include "kactioncollection.h"
37
38#include "kis_debug.h"
39
40
58
60 : QWidget(parent, Qt::FramelessWindowHint),
61 m_d(new Private)
62{
63 m_d->provider = provider;
64
65 QVBoxLayout *layout = new QVBoxLayout(this);
66
67 QHBoxLayout *labelLayout = new QHBoxLayout();
68 m_d->lblPresetIcon = new QLabel(this);
69 const QSize iconSize = QSize(22,22);
70 m_d->lblPresetIcon->setMinimumSize(iconSize);
71 m_d->lblPresetIcon->setMaximumSize(iconSize);
72 m_d->lblPresetIcon->setScaledContents(true);
73
74 m_d->lblPresetName = new KisElidedLabel("<Preset Name>", Qt::ElideMiddle, this);
75
76 m_d->btnReloadPreset = new QToolButton(this);
77 m_d->btnReloadPreset->setAutoRaise(true);
78 m_d->btnReloadPreset->setToolTip(i18n("Reload Original Preset"));
79
80 m_d->btnConfigure = new QToolButton(this);
81 m_d->btnConfigure->setAutoRaise(true);
82 m_d->btnConfigure->setToolTip(i18n("Configure the on-canvas brush editor"));
83
84 connect(m_d->btnReloadPreset, SIGNAL(clicked()), SLOT(slotReloadPreset()));
85 connect(m_d->btnConfigure, SIGNAL(clicked()), SLOT(slotConfigBrushHud()));
86
87 labelLayout->addWidget(m_d->lblPresetIcon);
88 labelLayout->addWidget(m_d->lblPresetName);
89 labelLayout->addWidget(m_d->btnReloadPreset);
90 labelLayout->addWidget(m_d->btnConfigure);
91
92 layout->addLayout(labelLayout);
93
94 m_d->wdgPropertiesArea = new QScrollArea(this);
95 m_d->wdgPropertiesArea->setAlignment(Qt::AlignLeft | Qt::AlignTop);
96 m_d->wdgPropertiesArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
97
98 m_d->wdgPropertiesArea->setWidgetResizable(true);
99
100 m_d->wdgProperties = new QWidget(this);
101 m_d->propertiesLayout = new QVBoxLayout(m_d->wdgProperties);
102 m_d->propertiesLayout->setSpacing(0);
103 m_d->propertiesLayout->setContentsMargins(0, 0, 22, 0);
104 m_d->propertiesLayout->setSizeConstraint(QLayout::SetMinimumSize);
105
106 // not adding any widgets until explicitly requested
107
108 m_d->wdgPropertiesArea->setWidget(m_d->wdgProperties);
109 layout->addWidget(m_d->wdgPropertiesArea);
110
111 // unfortunately the sizeHint() function of QScrollArea is pretty broken
112 // and it would add another event loop iteration to react to it anyway,
113 // so let's just catch LayoutRequest events from the properties widget directly
114 m_d->wdgProperties->installEventFilter(this);
115
116 updateIcons();
117
118 setCursor(Qt::ArrowCursor);
119
120 // Prevent tablet events from being captured by the canvas
121 setAttribute(Qt::WA_NoMousePropagation, true);
122}
123
124
125
129
131{
132 this->setPalette(qApp->palette());
133 for(int i=0; i<this->children().size(); i++) {
134 QWidget *w = qobject_cast<QWidget*>(this->children().at(i));
135 if (w) {
136 w->setPalette(qApp->palette());
137 }
138 }
139 for(int i=0; i<m_d->wdgProperties->children().size(); i++) {
140 KisUniformPaintOpPropertyWidget *w = qobject_cast<KisUniformPaintOpPropertyWidget*>(m_d->wdgProperties->children().at(i));
141 if (w) {
142 w->slotThemeChanged(qApp->palette());
143 }
144 }
145 m_d->btnReloadPreset->setIcon(KisIconUtils::loadIcon("reload-preset-16"));
146 m_d->btnConfigure->setIcon(KisIconUtils::loadIcon("applications-system"));
147}
148
150{
151 m_d->presetConnections.clear();
154}
155
157{
158 while (m_d->propertiesLayout->count()) {
159 QLayoutItem *item = m_d->propertiesLayout->takeAt(0);
160
161 QWidget *w = item->widget();
162 if (w) {
163 w->deleteLater();
164 }
165
166 delete item;
167 }
168
169 m_d->currentPreset.clear();
170}
171
173{
174 KisPaintOpPresetSP preset = m_d->provider->currentPreset();
175
176 if (preset == m_d->currentPreset) return;
177
178 m_d->presetConnections.clear();
180
181 m_d->currentPreset = preset;
182 m_d->presetConnections.addConnection(
183 m_d->currentPreset->updateProxy(), SIGNAL(sigUniformPropertiesChanged()),
184 this, SLOT(slotReloadProperties()));
185
186 m_d->lblPresetIcon->setPixmap(QPixmap::fromImage(preset->image()));
187 m_d->lblPresetName->setLongText(preset->name());
188
190
191 {
192 QList<KisUniformPaintOpPropertySP> allProperties = preset->uniformProperties();
193 QList<KisUniformPaintOpPropertySP> discardedProperties;
194
196 cfg.filterProperties(preset->paintOp().id(),
197 allProperties,
198 &properties,
199 &discardedProperties);
200 }
201
202 Q_FOREACH(auto property, properties) {
203 QWidget *w = 0;
204
205 if (!property->isVisible()) continue;
206
207 if (property->type() == KisUniformPaintOpProperty::Int) {
208 w = new KisUniformPaintOpPropertyIntSlider(property, m_d->wdgProperties);
209 } else if (property->type() == KisUniformPaintOpProperty::Double) {
210 w = new KisUniformPaintOpPropertyDoubleSlider(property, m_d->wdgProperties);
211 } else if (property->type() == KisUniformPaintOpProperty::Bool) {
212 w = new KisUniformPaintOpPropertyCheckBox(property, m_d->wdgProperties);
213 } else if (property->type() == KisUniformPaintOpProperty::Combo) {
214 w = new KisUniformPaintOpPropertyComboBox(property, m_d->wdgProperties);
215 }
216
217 if (w) {
218 w->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
219 m_d->propertiesLayout->addWidget(w);
220 }
221 }
222
223 m_d->propertiesLayout->addStretch();
224}
225
226void KisBrushHud::showEvent(QShowEvent *event)
227{
228 m_d->connections.clear();
229 m_d->connections.addUniqueConnection(
230 m_d->provider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
231 this, SLOT(slotCanvasResourceChanged(int,QVariant)));
232
234
235 QWidget::showEvent(event);
236}
237
238void KisBrushHud::hideEvent(QHideEvent *event)
239{
240 m_d->connections.clear();
241 QWidget::hideEvent(event);
242
244}
245
246void KisBrushHud::slotCanvasResourceChanged(int key, const QVariant &resource)
247{
248 Q_UNUSED(resource);
249
252 }
253}
254
255void KisBrushHud::paintEvent(QPaintEvent *event)
256{
257 QColor bgColor = palette().color(QPalette::Window);
258
259 QPainter painter(this);
260 painter.fillRect(rect() & event->rect(), bgColor);
261 painter.end();
262
263 QWidget::paintEvent(event);
264}
265
266bool KisBrushHud::event(QEvent *event)
267{
268 switch (event->type()) {
269 case QEvent::TabletPress:
270 case QEvent::TabletMove:
271 case QEvent::TabletRelease:
272 // Allow the tablet event to be translated to a mouse event on certain platforms
273 break;
274 case QEvent::MouseButtonPress:
275 case QEvent::MouseMove:
276 case QEvent::MouseButtonRelease:
277 case QEvent::Wheel:
278 event->accept();
279 return true;
280 default:
281 break;
282 }
283
284 return QWidget::event(event);
285}
286
287bool KisBrushHud::eventFilter(QObject *watched, QEvent *event)
288{
289 // LayoutRequest event is sent from a layout to its parent widget
290 // when size requirements have been determined, i.e. sizeHint is available
291 if (watched == m_d->wdgProperties && event->type() == QEvent::LayoutRequest)
292 {
293 int totalMargin = 2 * m_d->wdgPropertiesArea->frameWidth();
294 m_d->wdgPropertiesArea->setMinimumWidth(m_d->wdgProperties->sizeHint().width() + totalMargin);
295 }
296 return false;
297}
298
300{
301 if (!m_d->currentPreset) return;
302
303 KisDlgConfigureBrushHud dlg(m_d->currentPreset);
304 dlg.exec();
305
307}
308
310{
311 KisCanvas2* canvas = dynamic_cast<KisCanvas2*>(m_d->provider->canvas());
313 canvas->viewManager()->actionCollection()->action("reload_preset_action")->trigger();
314}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
int iconSize(qreal width, qreal height)
void filterProperties(const QString &paintOpId, const QList< KisUniformPaintOpPropertySP > &allProperties, QList< KisUniformPaintOpPropertySP > *chosenProperties, QList< KisUniformPaintOpPropertySP > *skippedProperties) const
void slotReloadPreset()
void slotCanvasResourceChanged(int key, const QVariant &resource)
KisBrushHud(KisCanvasResourceProvider *provider, QWidget *parent)
const QScopedPointer< Private > m_d
bool eventFilter(QObject *watched, QEvent *event) override
bool event(QEvent *event) override
void paintEvent(QPaintEvent *event) override
void hideEvent(QHideEvent *event) override
void clearProperties() const
~KisBrushHud() override
void updateProperties()
void slotConfigBrushHud()
void slotReloadProperties()
void showEvent(QShowEvent *event) override
KisViewManager * viewManager() const
QAction * action(int index) const
virtual KisKActionCollection * actionCollection() const
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
QIcon loadIcon(const QString &name)
rgba palette[MAX_PALETTE]
Definition palette.c:35
QPointer< QWidget > wdgProperties
KisSignalAutoConnectionsStore presetConnections
QPointer< KisElidedLabel > lblPresetName
KisPaintOpPresetSP currentPreset
QPointer< QToolButton > btnReloadPreset
KisCanvasResourceProvider * provider
QPointer< QVBoxLayout > propertiesLayout
QPointer< QLabel > lblPresetIcon
QPointer< QToolButton > btnConfigure
KisSignalAutoConnectionsStore connections
QPointer< QScrollArea > wdgPropertiesArea