Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_selection_options.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2005 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QCheckBox>
10#include <QToolButton>
11
12#include <kis_icon.h>
13#include "kis_config.h"
14#include "kis_config_notifier.h"
15#include "kis_paint_device.h"
16
17#include <ksharedconfig.h>
18#include <kconfiggroup.h>
19
21#include <KoGroupButton.h>
23#include <kis_slider_spin_box.h>
24
26{
27public:
31 QCheckBox *checkBoxAntiAliasSelection{nullptr};
33 QToolButton *buttonStopGrowingAtDarkestPixel {nullptr};
37 QCheckBox* checkBoxSelectionActionsPanel{nullptr};
38
40 {
41 return mode == PIXEL_SELECTION ? 0 : 1;
42 }
43
45 {
46 return index == 0 ? PIXEL_SELECTION : SHAPE_PROTECTION;
47 }
48
50 {
51 switch (action) {
53 return 0;
55 return 1;
56 case SELECTION_ADD:
57 return 2;
59 return 3;
61 return 4;
62 default:
63 return 0;
64 }
65 }
66
68 {
69 switch (index) {
70 case 0:
71 return SELECTION_REPLACE;
72 case 1:
74 case 2:
75 return SELECTION_ADD;
76 case 3:
77 return SELECTION_SUBTRACT;
78 case 4:
80 default:
81 return SELECTION_REPLACE;
82 }
83 }
84
86 {
87 switch (action) {
88 case CurrentLayer:
89 return 0;
90 case AllLayers:
91 return 1;
93 return 2;
94 default:
95 return 0;
96 }
97 }
98
100 {
101 switch (index) {
102 case 0:
103 return CurrentLayer;
104 case 1:
105 return AllLayers;
106 case 2:
107 return ColorLabeledLayers;
108 default:
109 return CurrentLayer;
110 }
111 }
112
113 void on_optionButtonStripMode_buttonToggled(int index, bool checked)
114 {
115 if (!checked) {
116 return;
117 }
118 const SelectionMode mode = buttonIndexToMode(index);
120 Q_EMIT q->modeChanged(mode);
121 }
122
123 void on_optionButtonStripAction_buttonToggled(int index, bool checked)
124 {
125 if (!checked) {
126 return;
127 }
128 Q_EMIT q->actionChanged(buttonIndexToAction(index));
129 }
130
132 {
133 if (!checked) {
134 return;
135 }
138 KisOptionCollectionWidgetWithHeader *sectionReference =
140 "sectionReference");
141 sectionReference->setWidgetVisible("widgetLabels",
144
146 }
147};
148
151 , m_d(new Private)
152{
153 m_d->q = this;
154 // Create widgets
155 m_d->optionButtonStripMode = new KisOptionButtonStrip;
156 m_d->optionButtonStripMode->addButton(
157 KisIconUtils::loadIcon("select-pixel"));
158 m_d->optionButtonStripMode->addButton(
159 KisIconUtils::loadIcon("select-shape"));
160 m_d->optionButtonStripMode->button(0)->setChecked(true);
161
162 m_d->optionButtonStripAction = new KisOptionButtonStrip;
163 m_d->optionButtonStripAction->addButton(
164 KisIconUtils::loadIcon("selection_replace"));
165 m_d->optionButtonStripAction->addButton(
166 KisIconUtils::loadIcon("selection_intersect"));
167 m_d->optionButtonStripAction->addButton(
168 KisIconUtils::loadIcon("selection_add"));
169 m_d->optionButtonStripAction->addButton(
170 KisIconUtils::loadIcon("selection_subtract"));
171 m_d->optionButtonStripAction->addButton(
172 KisIconUtils::loadIcon("selection_symmetric_difference"));
173 m_d->optionButtonStripAction->button(0)->setChecked(true);
174
175 m_d->checkBoxSelectionActionsPanel = new QCheckBox(i18n("Enable Selection Actions Bar"));
176 m_d->checkBoxSelectionActionsPanel->setToolTip(
177 i18n("When enabled, any selections will produce a small floating panel of useful selection-related actions."));
178
179 KisConfig cfg(true);
180
181 if (cfg.selectionActionBar()) {
182 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::CheckState::Checked);
183 } else {
184 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::CheckState::Unchecked);
185 }
186
187 m_d->checkBoxAntiAliasSelection = new QCheckBox(
188 i18nc("The anti-alias checkbox in fill tool options", "Anti-aliasing"));
189 KisOptionCollectionWidget *containerGrowSelection = new KisOptionCollectionWidget;
190 m_d->sliderGrowSelection = new KisSliderSpinBox;
191 m_d->sliderGrowSelection->setPrefix(
192 i18nc("The 'grow/shrink' spinbox prefix in selection tools options",
193 "Grow: "));
194 m_d->sliderGrowSelection->setRange(-400, 400);
195 m_d->sliderGrowSelection->setSoftRange(-40, 40);
196 m_d->sliderGrowSelection->setSuffix(i18n(" px"));
197 m_d->buttonStopGrowingAtDarkestPixel = new QToolButton;
198 m_d->buttonStopGrowingAtDarkestPixel->setAutoRaise(true);
199 m_d->buttonStopGrowingAtDarkestPixel->setCheckable(true);
200 m_d->buttonStopGrowingAtDarkestPixel->setIcon(KisIconUtils::loadIcon("stop-at-boundary"));
201 containerGrowSelection->appendWidget("sliderGrowSelection", m_d->sliderGrowSelection);
202 containerGrowSelection->appendWidget("buttonStopGrowingAtDarkestPixel", m_d->buttonStopGrowingAtDarkestPixel);
203 containerGrowSelection->setOrientation(Qt::Horizontal);
204 containerGrowSelection->setWidgetVisible("buttonStopGrowingAtDarkestPixel", false);
205 m_d->sliderFeatherSelection = new KisSliderSpinBox;
206 m_d->sliderFeatherSelection->setPrefix(
207 i18nc("The 'feather' spinbox prefix in selection tools options",
208 "Feather: "));
209 m_d->sliderFeatherSelection->setRange(0, 400);
210 m_d->sliderFeatherSelection->setSoftRange(0, 40);
211 m_d->sliderFeatherSelection->setSuffix(i18n(" px"));
212
213 m_d->optionButtonStripReference = new KisOptionButtonStrip;
214 m_d->optionButtonStripReference->addButton(
215 KisIconUtils::loadIcon("current-layer"));
216 m_d->optionButtonStripReference->addButton(
217 KisIconUtils::loadIcon("all-layers"));
218 m_d->optionButtonStripReference->addButton(KisIconUtils::loadIcon("tag"));
219 m_d->optionButtonStripReference->button(0)->setChecked(true);
220 m_d->widgetLabels = new KisColorLabelSelectorWidget;
221 m_d->widgetLabels->setExclusive(false);
222 m_d->widgetLabels->setButtonSize(20);
223 m_d->widgetLabels->setButtonWrapEnabled(true);
224 m_d->widgetLabels->setMouseDragEnabled(true);
225
226 // Set the tooltips
227 m_d->optionButtonStripMode->button(0)->setToolTip(
228 i18nc("@info:tooltip", "Pixel Selection"));
229 m_d->optionButtonStripMode->button(1)->setToolTip(
230 i18nc("@info:tooltip", "Vector Selection"));
231
232 m_d->optionButtonStripAction->button(0)->setToolTip(
233 i18nc("@info:tooltip", "Replace"));
234 m_d->optionButtonStripAction->button(1)->setToolTip(
235 i18nc("@info:tooltip", "Intersect"));
236 m_d->optionButtonStripAction->button(2)->setToolTip(
237 i18nc("@info:tooltip", "Add"));
238 m_d->optionButtonStripAction->button(3)->setToolTip(
239 i18nc("@info:tooltip", "Subtract"));
240 m_d->optionButtonStripAction->button(4)->setToolTip(
241 i18nc("@info:tooltip", "Symmetric Difference"));
242
243 m_d->checkBoxAntiAliasSelection->setToolTip(
244 i18n("Smooths the edges of the selection"));
245 m_d->sliderGrowSelection->setToolTip(
246 i18n("Grow or shrink the selection by the set amount"));
247 m_d->buttonStopGrowingAtDarkestPixel->setToolTip(
248 i18n("Stop growing at the darkest and/or most opaque pixels"));
249 m_d->sliderFeatherSelection->setToolTip(
250 i18n("Blur the selection by the set amount"));
251
252 m_d->optionButtonStripReference->button(0)->setToolTip(
253 i18n("Select regions found from the active layer"));
254 m_d->optionButtonStripReference->button(1)->setToolTip(
255 i18n("Select regions found from the merging of all layers"));
256 m_d->optionButtonStripReference->button(2)->setToolTip(
257 i18n("Select regions found from the merging of layers with specific color labels"));
258
259 // Construct the option widget
261
264 i18nc("The 'mode' section label in selection tools options",
265 "Mode"));
266 sectionMode->setPrimaryWidget(m_d->optionButtonStripMode);
267 appendWidget("sectionMode", sectionMode);
268
271 i18nc("The 'action' section label in selection tools options",
272 "Action"));
273 sectionAction->setPrimaryWidget(m_d->optionButtonStripAction);
274 appendWidget("sectionAction", sectionAction);
275
276 KisOptionCollectionWidgetWithHeader *sectionReference =
278 i18nc("The 'reference' section label in selection tools options",
279 "Reference"));
280 sectionReference->setPrimaryWidget(m_d->optionButtonStripReference);
281 sectionReference->appendWidget("widgetLabels", m_d->widgetLabels);
282 sectionReference->setWidgetVisible("widgetLabels", false);
283 appendWidget("sectionReference", sectionReference);
284
285 appendWidget("sapCheckBox", m_d->checkBoxSelectionActionsPanel);
286
287 KisOptionCollectionWidgetWithHeader *sectionAdjustments =
289 i18nc("The 'adjustments' section label in selection tools options",
290 "Adjustments"));
291 sectionAdjustments->appendWidget("checkBoxAntiAliasSelection",
292 m_d->checkBoxAntiAliasSelection);
293 sectionAdjustments->appendWidget("containerGrowSelection", containerGrowSelection);
294 sectionAdjustments->appendWidget("sliderFeather",
295 m_d->sliderFeatherSelection);
296 appendWidget("sectionAdjustments", sectionAdjustments);
297
298
299 // Make connections
300 connect(m_d->optionButtonStripMode,
301 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
302 [this](int i, int c) {
303 m_d->on_optionButtonStripMode_buttonToggled(i, c);
304 });
305 connect(m_d->optionButtonStripAction,
306 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
307 [this](int i, int c) {
308 m_d->on_optionButtonStripAction_buttonToggled(i, c);
309 });
310 connect(m_d->checkBoxAntiAliasSelection,
311 SIGNAL(toggled(bool)),
312 SIGNAL(antiAliasSelectionChanged(bool)));
313 connect(m_d->sliderGrowSelection,
314 SIGNAL(valueChanged(int)),
315 SIGNAL(growSelectionChanged(int)));
316 connect(m_d->buttonStopGrowingAtDarkestPixel,
317 SIGNAL(toggled(bool)),
319 connect(m_d->sliderFeatherSelection,
320 SIGNAL(valueChanged(int)),
321 SIGNAL(featherSelectionChanged(int)));
322 connect(m_d->optionButtonStripReference,
323 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
324 [this](int i, int c) {
325 m_d->on_optionButtonStripReference_buttonToggled(i, c);
326 });
327 connect(m_d->widgetLabels,
328 SIGNAL(selectionChanged()),
330
331 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
332 connect(m_d->checkBoxSelectionActionsPanel,
333 SIGNAL(toggled(bool)),
335}
336
340
342{
343 return m_d->buttonIndexToMode(
344 m_d->optionButtonStripMode->checkedButtonIndex());
345}
346
348{
349 return m_d->buttonIndexToAction(
350 m_d->optionButtonStripAction->checkedButtonIndex());
351}
352
354{
355 return m_d->checkBoxAntiAliasSelection->isChecked();
356}
357
359{
360 return m_d->sliderGrowSelection->value();
361}
362
364{
365 return m_d->buttonStopGrowingAtDarkestPixel->isChecked();
366}
367
369{
370 return m_d->sliderFeatherSelection->value();
371}
372
375{
376 return m_d->buttonIndexToReferenceLayers(
377 m_d->optionButtonStripReference->checkedButtonIndex());
378}
379
381{
382 return m_d->widgetLabels->selection();
383}
384
386{
388 m_d->optionButtonStripMode->button(m_d->modeToButtonIndex(newMode));
390
391 button->setChecked(true);
392}
393
395{
396 KoGroupButton *button = m_d->optionButtonStripAction->button(
397 m_d->actionToButtonIndex(newAction));
399
400 button->setChecked(true);
401}
402
403void KisSelectionOptions::setAntiAliasSelection(bool newAntiAliasSelection)
404{
405 m_d->checkBoxAntiAliasSelection->setChecked(newAntiAliasSelection);
406}
407
409{
410 m_d->sliderGrowSelection->setValue(newGrowSelection);
411}
412
413void KisSelectionOptions::setStopGrowingAtDarkestPixel(bool newStopGrowingAtDarkestPixel)
414{
415 m_d->buttonStopGrowingAtDarkestPixel->setChecked(newStopGrowingAtDarkestPixel);
416}
417
418void KisSelectionOptions::setFeatherSelection(int newFeatherSelection)
419{
420 m_d->sliderFeatherSelection->setValue(newFeatherSelection);
421}
422
424{
425 KoGroupButton *button = m_d->optionButtonStripReference->button(
426 m_d->referenceLayersToButtonIndex(newReferenceLayers));
428
429 button->setChecked(true);
430}
431
433 const QList<int> &newSelectedColorLabels)
434{
435 m_d->widgetLabels->setSelection(newSelectedColorLabels);
436}
437
439{
440 setWidgetVisible("sectionMode", visible);
441}
442
444{
445 setWidgetVisible("sectionAction", visible);
446}
447
449{
450 widgetAs<KisOptionCollectionWidgetWithHeader*>("sectionAdjustments")
451 ->widgetAs<KisOptionCollectionWidget*>("containerGrowSelection")
452 ->setWidgetVisible("buttonStopGrowingAtDarkestPixel", visible);
453}
454
456{
457 setWidgetVisible("sectionAdjustments", visible);
458}
459
461{
462 setWidgetVisible("sectionReference", visible);
463}
464
466 SelectionAction action,
467 const QKeySequence &shortcut)
468{
469 const QString shortcutString = shortcut.toString(QKeySequence::NativeText);
470 QString toolTipText;
471 const int buttonIndex = m_d->actionToButtonIndex(action);
472
473 switch (action) {
476 toolTipText = shortcutString.isEmpty()
477 ? i18nc("@info:tooltip", "Replace")
478 : i18nc("@info:tooltip", "Replace (%1)", shortcutString);
479 break;
480 case SELECTION_ADD:
481 toolTipText = shortcutString.isEmpty()
482 ? i18nc("@info:tooltip", "Add")
483 : i18nc("@info:tooltip", "Add (%1)", shortcutString);
484 break;
486 toolTipText = shortcutString.isEmpty()
487 ? i18nc("@info:tooltip", "Subtract")
488 : i18nc("@info:tooltip", "Subtract (%1)", shortcutString);
489 break;
491 toolTipText = shortcutString.isEmpty()
492 ? i18nc("@info:tooltip", "Intersect")
493 : i18nc("@info:tooltip", "Intersect (%1)", shortcutString);
494 break;
496 toolTipText = shortcutString.isEmpty()
497 ? i18nc("@info:tooltip", "Symmetric Difference")
498 : i18nc("@info:tooltip",
499 "Symmetric Difference (%1)",
500 shortcutString);
501 break;
502 }
503
504 m_d->optionButtonStripAction->button(buttonIndex)->setToolTip(toolTipText);
505}
506
508{
509 KisConfig cfg(true);
510
511 if (cfg.selectionActionBar()) {
512 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::Checked);
513 } else {
514 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::Unchecked);
515 }
516}
517
519{
520 KisConfig cfg(false);
522
523 blockSignals(true);
525 blockSignals(false);
526}
float value(const T *src, size_t ch)
SelectionMode
@ PIXEL_SELECTION
@ SHAPE_PROTECTION
SelectionAction
@ SELECTION_REPLACE
@ SELECTION_INTERSECT
@ SELECTION_SYMMETRICDIFFERENCE
@ SELECTION_DEFAULT
@ SELECTION_SUBTRACT
@ SELECTION_ADD
void setExclusive(bool exclusive)
Set if the button selection is mutually exclusive. This allows switching between single or multiple s...
static KisConfigNotifier * instance()
bool selectionActionBar(bool defaultValue=false) const
void setSelectionActionBar(bool value)
Provides a list of consecutive tool buttons.
void buttonToggled(KoGroupButton *button, bool checked)
KoGroupButton * addButton(const QIcon &icon, const QString &text=QString())
Wrapper class around a KisOptionCollectionWidget that also provide a header with a title label and an...
void setPrimaryWidget(QWidget *widget)
Set the primary widget. The list widget takes ownership of it.
void appendWidget(const QString &id, QWidget *widget)
Insert the given widget with the given id at the end of the list. The list widget takes ownership of ...
void setWidgetVisible(int index, bool visible)
Set the visibility of the widget that is at the given position.
Class providing a list of widgets with some addons such as separators, orientation or individual widg...
T widgetAs(int index) const
Get the widget that is at the given position casted to some other class.
void setOrientation(Qt::Orientation orientation, bool recursive=false)
Set the orientation of the list of widgets.
KisOptionCollectionWidget(QWidget *parent=nullptr)
void setWidgetVisible(int index, bool visible)
Set the visibility of the widget that is at the given position. Use this function instead of the widg...
void appendWidget(const QString &id, QWidget *widget)
Insert the given widget with the given id at the end of the list. The list widget takes ownership of ...
void setSeparatorsVisible(bool visible)
Set the visibility of the separators.
void on_optionButtonStripAction_buttonToggled(int index, bool checked)
SelectionAction buttonIndexToAction(int index) const
KisOptionButtonStrip * optionButtonStripReference
KisColorLabelSelectorWidget * widgetLabels
ReferenceLayers buttonIndexToReferenceLayers(int index) const
void on_optionButtonStripReference_buttonToggled(int index, bool checked)
int modeToButtonIndex(SelectionMode mode) const
KisOptionButtonStrip * optionButtonStripAction
int referenceLayersToButtonIndex(ReferenceLayers action) const
void on_optionButtonStripMode_buttonToggled(int index, bool checked)
SelectionMode buttonIndexToMode(int index) const
KisOptionButtonStrip * optionButtonStripMode
int actionToButtonIndex(SelectionAction action) const
void updateActionButtonToolTip(SelectionAction action, const QKeySequence &shortcut)
void setStopGrowingAtDarkestPixelButtonVisible(bool visible)
KisSelectionOptions(QWidget *parent=nullptr)
void setModeSectionVisible(bool visible)
void setAdjustmentsSectionVisible(bool visible)
void setMode(SelectionMode newMode)
void setGrowSelection(int newGrowSelection)
void setAntiAliasSelection(bool newAntiAliasSelection)
void slotSelectionActionsPanelCheckboxToggled(bool value)
void actionChanged(SelectionAction action)
void antiAliasSelectionChanged(bool antiAliasSelection)
void setAction(SelectionAction newAction)
SelectionMode mode() const
void setSelectedColorLabels(const QList< int > &newSelectedColorLabels)
void featherSelectionChanged(int featherSelection)
void setReferenceLayers(ReferenceLayers newReferenceLayers)
void selectedColorLabelsChanged()
void setFeatherSelection(int newFeatherSelection)
QList< int > selectedColorLabels() const
void setReferenceSectionVisible(bool visible)
ReferenceLayers referenceLayers() const
void referenceLayersChanged(ReferenceLayers referenceLayers)
QScopedPointer< Private > m_d
void setActionSectionVisible(bool visible)
void stopGrowingAtDarkestPixelChanged(bool stopGrowingAtDarkestPixel)
void growSelectionChanged(int growSelection)
void setStopGrowingAtDarkestPixel(bool newStopGrowingAtDarkestPixel)
SelectionAction action() const
void modeChanged(SelectionMode mode)
This class is a spinbox in which you can click and drag to set the value. A slider like bar is displa...
void setRange(int newMinimum, int newMaximum, bool computeNewFastSliderStep=true)
Set the minimum and the maximum values of the range, computing a new "fast slider step" based on the ...
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
QString button(const QWheelEvent &ev)
QIcon loadIcon(const QString &name)