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 KisOptionCollectionWidgetWithHeader *sectionAdjustments =
287 i18nc("The 'adjustments' section label in selection tools options",
288 "Adjustments"));
289 sectionAdjustments->appendWidget("checkBoxAntiAliasSelection",
290 m_d->checkBoxAntiAliasSelection);
291 sectionAdjustments->appendWidget("containerGrowSelection", containerGrowSelection);
292 sectionAdjustments->appendWidget("sliderFeather",
293 m_d->sliderFeatherSelection);
294 appendWidget("sectionAdjustments", sectionAdjustments);
295
296 appendWidget("sapChckBox", m_d->checkBoxSelectionActionsPanel);
297
298 // Make connections
299 connect(m_d->optionButtonStripMode,
300 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
301 [this](int i, int c) {
302 m_d->on_optionButtonStripMode_buttonToggled(i, c);
303 });
304 connect(m_d->optionButtonStripAction,
305 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
306 [this](int i, int c) {
307 m_d->on_optionButtonStripAction_buttonToggled(i, c);
308 });
309 connect(m_d->checkBoxAntiAliasSelection,
310 SIGNAL(toggled(bool)),
311 SIGNAL(antiAliasSelectionChanged(bool)));
312 connect(m_d->sliderGrowSelection,
313 SIGNAL(valueChanged(int)),
314 SIGNAL(growSelectionChanged(int)));
315 connect(m_d->buttonStopGrowingAtDarkestPixel,
316 SIGNAL(toggled(bool)),
318 connect(m_d->sliderFeatherSelection,
319 SIGNAL(valueChanged(int)),
320 SIGNAL(featherSelectionChanged(int)));
321 connect(m_d->optionButtonStripReference,
322 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
323 [this](int i, int c) {
324 m_d->on_optionButtonStripReference_buttonToggled(i, c);
325 });
326 connect(m_d->widgetLabels,
327 SIGNAL(selectionChanged()),
329
330 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
331 connect(m_d->checkBoxSelectionActionsPanel,
332 SIGNAL(toggled(bool)),
334}
335
339
341{
342 return m_d->buttonIndexToMode(
343 m_d->optionButtonStripMode->checkedButtonIndex());
344}
345
347{
348 return m_d->buttonIndexToAction(
349 m_d->optionButtonStripAction->checkedButtonIndex());
350}
351
353{
354 return m_d->checkBoxAntiAliasSelection->isChecked();
355}
356
358{
359 return m_d->sliderGrowSelection->value();
360}
361
363{
364 return m_d->buttonStopGrowingAtDarkestPixel->isChecked();
365}
366
368{
369 return m_d->sliderFeatherSelection->value();
370}
371
374{
375 return m_d->buttonIndexToReferenceLayers(
376 m_d->optionButtonStripReference->checkedButtonIndex());
377}
378
380{
381 return m_d->widgetLabels->selection();
382}
383
385{
387 m_d->optionButtonStripMode->button(m_d->modeToButtonIndex(newMode));
389
390 button->setChecked(true);
391}
392
394{
395 KoGroupButton *button = m_d->optionButtonStripAction->button(
396 m_d->actionToButtonIndex(newAction));
398
399 button->setChecked(true);
400}
401
402void KisSelectionOptions::setAntiAliasSelection(bool newAntiAliasSelection)
403{
404 m_d->checkBoxAntiAliasSelection->setChecked(newAntiAliasSelection);
405}
406
408{
409 m_d->sliderGrowSelection->setValue(newGrowSelection);
410}
411
412void KisSelectionOptions::setStopGrowingAtDarkestPixel(bool newStopGrowingAtDarkestPixel)
413{
414 m_d->buttonStopGrowingAtDarkestPixel->setChecked(newStopGrowingAtDarkestPixel);
415}
416
417void KisSelectionOptions::setFeatherSelection(int newFeatherSelection)
418{
419 m_d->sliderFeatherSelection->setValue(newFeatherSelection);
420}
421
423{
424 KoGroupButton *button = m_d->optionButtonStripReference->button(
425 m_d->referenceLayersToButtonIndex(newReferenceLayers));
427
428 button->setChecked(true);
429}
430
432 const QList<int> &newSelectedColorLabels)
433{
434 m_d->widgetLabels->setSelection(newSelectedColorLabels);
435}
436
438{
439 setWidgetVisible("sectionMode", visible);
440}
441
443{
444 setWidgetVisible("sectionAction", visible);
445}
446
448{
449 widgetAs<KisOptionCollectionWidgetWithHeader*>("sectionAdjustments")
450 ->widgetAs<KisOptionCollectionWidget*>("containerGrowSelection")
451 ->setWidgetVisible("buttonStopGrowingAtDarkestPixel", visible);
452}
453
455{
456 setWidgetVisible("sectionAdjustments", visible);
457}
458
460{
461 setWidgetVisible("sectionReference", visible);
462}
463
465 SelectionAction action,
466 const QKeySequence &shortcut)
467{
468 const QString shortcutString = shortcut.toString(QKeySequence::NativeText);
469 QString toolTipText;
470 const int buttonIndex = m_d->actionToButtonIndex(action);
471
472 switch (action) {
475 toolTipText = shortcutString.isEmpty()
476 ? i18nc("@info:tooltip", "Replace")
477 : i18nc("@info:tooltip", "Replace (%1)", shortcutString);
478 break;
479 case SELECTION_ADD:
480 toolTipText = shortcutString.isEmpty()
481 ? i18nc("@info:tooltip", "Add")
482 : i18nc("@info:tooltip", "Add (%1)", shortcutString);
483 break;
485 toolTipText = shortcutString.isEmpty()
486 ? i18nc("@info:tooltip", "Subtract")
487 : i18nc("@info:tooltip", "Subtract (%1)", shortcutString);
488 break;
490 toolTipText = shortcutString.isEmpty()
491 ? i18nc("@info:tooltip", "Intersect")
492 : i18nc("@info:tooltip", "Intersect (%1)", shortcutString);
493 break;
495 toolTipText = shortcutString.isEmpty()
496 ? i18nc("@info:tooltip", "Symmetric Difference")
497 : i18nc("@info:tooltip",
498 "Symmetric Difference (%1)",
499 shortcutString);
500 break;
501 }
502
503 m_d->optionButtonStripAction->button(buttonIndex)->setToolTip(toolTipText);
504}
505
507{
508 KisConfig cfg(true);
509
510 if (cfg.selectionActionBar()) {
511 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::Checked);
512 } else {
513 m_d->checkBoxSelectionActionsPanel->setCheckState(Qt::Unchecked);
514 }
515}
516
518{
519 KisConfig cfg(false);
521
522 blockSignals(true);
524 blockSignals(false);
525}
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)