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_types.h"
14#include "kis_layer.h"
15#include "kis_image.h"
16#include "kis_selection.h"
17#include "kis_paint_device.h"
18#include "KisViewManager.h"
20
21#include <ksharedconfig.h>
22#include <kconfiggroup.h>
23
25#include <KoGroupButton.h>
27#include <kis_slider_spin_box.h>
28
30{
31public:
35 QCheckBox *checkBoxAntiAliasSelection{nullptr};
37 QToolButton *buttonStopGrowingAtDarkestPixel {nullptr};
41
43 {
44 return mode == PIXEL_SELECTION ? 0 : 1;
45 }
46
48 {
49 return index == 0 ? PIXEL_SELECTION : SHAPE_PROTECTION;
50 }
51
53 {
54 switch (action) {
56 return 0;
58 return 1;
59 case SELECTION_ADD:
60 return 2;
62 return 3;
64 return 4;
65 default:
66 return 0;
67 }
68 }
69
71 {
72 switch (index) {
73 case 0:
74 return SELECTION_REPLACE;
75 case 1:
77 case 2:
78 return SELECTION_ADD;
79 case 3:
80 return SELECTION_SUBTRACT;
81 case 4:
83 default:
84 return SELECTION_REPLACE;
85 }
86 }
87
89 {
90 switch (action) {
91 case CurrentLayer:
92 return 0;
93 case AllLayers:
94 return 1;
96 return 2;
97 default:
98 return 0;
99 }
100 }
101
103 {
104 switch (index) {
105 case 0:
106 return CurrentLayer;
107 case 1:
108 return AllLayers;
109 case 2:
110 return ColorLabeledLayers;
111 default:
112 return CurrentLayer;
113 }
114 }
115
116 void on_optionButtonStripMode_buttonToggled(int index, bool checked)
117 {
118 if (!checked) {
119 return;
120 }
121 const SelectionMode mode = buttonIndexToMode(index);
123 Q_EMIT q->modeChanged(mode);
124 }
125
126 void on_optionButtonStripAction_buttonToggled(int index, bool checked)
127 {
128 if (!checked) {
129 return;
130 }
131 Q_EMIT q->actionChanged(buttonIndexToAction(index));
132 }
133
135 {
136 if (!checked) {
137 return;
138 }
141 KisOptionCollectionWidgetWithHeader *sectionReference =
143 "sectionReference");
144 sectionReference->setWidgetVisible("widgetLabels",
147
149 }
150};
151
154 , m_d(new Private)
155{
156 m_d->q = this;
157 // Create widgets
158 m_d->optionButtonStripMode = new KisOptionButtonStrip;
159 m_d->optionButtonStripMode->addButton(
160 KisIconUtils::loadIcon("select-pixel"));
161 m_d->optionButtonStripMode->addButton(
162 KisIconUtils::loadIcon("select-shape"));
163 m_d->optionButtonStripMode->button(0)->setChecked(true);
164
165 m_d->optionButtonStripAction = new KisOptionButtonStrip;
166 m_d->optionButtonStripAction->addButton(
167 KisIconUtils::loadIcon("selection_replace"));
168 m_d->optionButtonStripAction->addButton(
169 KisIconUtils::loadIcon("selection_intersect"));
170 m_d->optionButtonStripAction->addButton(
171 KisIconUtils::loadIcon("selection_add"));
172 m_d->optionButtonStripAction->addButton(
173 KisIconUtils::loadIcon("selection_subtract"));
174 m_d->optionButtonStripAction->addButton(
175 KisIconUtils::loadIcon("selection_symmetric_difference"));
176 m_d->optionButtonStripAction->button(0)->setChecked(true);
177
178 m_d->checkBoxAntiAliasSelection = new QCheckBox(
179 i18nc("The anti-alias checkbox in fill tool options", "Anti-aliasing"));
180 KisOptionCollectionWidget *containerGrowSelection = new KisOptionCollectionWidget;
181 m_d->sliderGrowSelection = new KisSliderSpinBox;
182 m_d->sliderGrowSelection->setPrefix(
183 i18nc("The 'grow/shrink' spinbox prefix in selection tools options",
184 "Grow: "));
185 m_d->sliderGrowSelection->setRange(-400, 400);
186 m_d->sliderGrowSelection->setSoftRange(-40, 40);
187 m_d->sliderGrowSelection->setSuffix(i18n(" px"));
188 m_d->buttonStopGrowingAtDarkestPixel = new QToolButton;
189 m_d->buttonStopGrowingAtDarkestPixel->setAutoRaise(true);
190 m_d->buttonStopGrowingAtDarkestPixel->setCheckable(true);
191 m_d->buttonStopGrowingAtDarkestPixel->setIcon(KisIconUtils::loadIcon("stop-at-boundary"));
192 containerGrowSelection->appendWidget("sliderGrowSelection", m_d->sliderGrowSelection);
193 containerGrowSelection->appendWidget("buttonStopGrowingAtDarkestPixel", m_d->buttonStopGrowingAtDarkestPixel);
194 containerGrowSelection->setOrientation(Qt::Horizontal);
195 containerGrowSelection->setWidgetVisible("buttonStopGrowingAtDarkestPixel", false);
196 m_d->sliderFeatherSelection = new KisSliderSpinBox;
197 m_d->sliderFeatherSelection->setPrefix(
198 i18nc("The 'feather' spinbox prefix in selection tools options",
199 "Feather: "));
200 m_d->sliderFeatherSelection->setRange(0, 400);
201 m_d->sliderFeatherSelection->setSoftRange(0, 40);
202 m_d->sliderFeatherSelection->setSuffix(i18n(" px"));
203
204 m_d->optionButtonStripReference = new KisOptionButtonStrip;
205 m_d->optionButtonStripReference->addButton(
206 KisIconUtils::loadIcon("current-layer"));
207 m_d->optionButtonStripReference->addButton(
208 KisIconUtils::loadIcon("all-layers"));
209 m_d->optionButtonStripReference->addButton(KisIconUtils::loadIcon("tag"));
210 m_d->optionButtonStripReference->button(0)->setChecked(true);
211 m_d->widgetLabels = new KisColorLabelSelectorWidget;
212 m_d->widgetLabels->setExclusive(false);
213 m_d->widgetLabels->setButtonSize(20);
214 m_d->widgetLabels->setButtonWrapEnabled(true);
215 m_d->widgetLabels->setMouseDragEnabled(true);
216
217 // Set the tooltips
218 m_d->optionButtonStripMode->button(0)->setToolTip(
219 i18nc("@info:tooltip", "Pixel Selection"));
220 m_d->optionButtonStripMode->button(1)->setToolTip(
221 i18nc("@info:tooltip", "Vector Selection"));
222
223 m_d->optionButtonStripAction->button(0)->setToolTip(
224 i18nc("@info:tooltip", "Replace"));
225 m_d->optionButtonStripAction->button(1)->setToolTip(
226 i18nc("@info:tooltip", "Intersect"));
227 m_d->optionButtonStripAction->button(2)->setToolTip(
228 i18nc("@info:tooltip", "Add"));
229 m_d->optionButtonStripAction->button(3)->setToolTip(
230 i18nc("@info:tooltip", "Subtract"));
231 m_d->optionButtonStripAction->button(4)->setToolTip(
232 i18nc("@info:tooltip", "Symmetric Difference"));
233
234 m_d->checkBoxAntiAliasSelection->setToolTip(
235 i18n("Smooths the edges of the selection"));
236 m_d->sliderGrowSelection->setToolTip(
237 i18n("Grow or shrink the selection by the set amount"));
238 m_d->buttonStopGrowingAtDarkestPixel->setToolTip(
239 i18n("Stop growing at the darkest and/or most opaque pixels"));
240 m_d->sliderFeatherSelection->setToolTip(
241 i18n("Blur the selection by the set amount"));
242
243 m_d->optionButtonStripReference->button(0)->setToolTip(
244 i18n("Select regions found from the active layer"));
245 m_d->optionButtonStripReference->button(1)->setToolTip(
246 i18n("Select regions found from the merging of all layers"));
247 m_d->optionButtonStripReference->button(2)->setToolTip(
248 i18n("Select regions found from the merging of layers with specific color labels"));
249
250 // Construct the option widget
252
255 i18nc("The 'mode' section label in selection tools options",
256 "Mode"));
257 sectionMode->setPrimaryWidget(m_d->optionButtonStripMode);
258 appendWidget("sectionMode", sectionMode);
259
262 i18nc("The 'action' section label in selection tools options",
263 "Action"));
264 sectionAction->setPrimaryWidget(m_d->optionButtonStripAction);
265 appendWidget("sectionAction", sectionAction);
266
267 KisOptionCollectionWidgetWithHeader *sectionReference =
269 i18nc("The 'reference' section label in selection tools options",
270 "Reference"));
271 sectionReference->setPrimaryWidget(m_d->optionButtonStripReference);
272 sectionReference->appendWidget("widgetLabels", m_d->widgetLabels);
273 sectionReference->setWidgetVisible("widgetLabels", false);
274 appendWidget("sectionReference", sectionReference);
275
276 KisOptionCollectionWidgetWithHeader *sectionAdjustments =
278 i18nc("The 'adjustments' section label in selection tools options",
279 "Adjustments"));
280 sectionAdjustments->appendWidget("checkBoxAntiAliasSelection",
281 m_d->checkBoxAntiAliasSelection);
282 sectionAdjustments->appendWidget("containerGrowSelection", containerGrowSelection);
283 sectionAdjustments->appendWidget("sliderFeather",
284 m_d->sliderFeatherSelection);
285 appendWidget("sectionAdjustments", sectionAdjustments);
286
287 // Make connections
288 connect(m_d->optionButtonStripMode,
289 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
290 [this](int i, int c) {
291 m_d->on_optionButtonStripMode_buttonToggled(i, c);
292 });
293 connect(m_d->optionButtonStripAction,
294 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
295 [this](int i, int c) {
296 m_d->on_optionButtonStripAction_buttonToggled(i, c);
297 });
298 connect(m_d->checkBoxAntiAliasSelection,
299 SIGNAL(toggled(bool)),
300 SIGNAL(antiAliasSelectionChanged(bool)));
301 connect(m_d->sliderGrowSelection,
302 SIGNAL(valueChanged(int)),
303 SIGNAL(growSelectionChanged(int)));
304 connect(m_d->buttonStopGrowingAtDarkestPixel,
305 SIGNAL(toggled(bool)),
307 connect(m_d->sliderFeatherSelection,
308 SIGNAL(valueChanged(int)),
309 SIGNAL(featherSelectionChanged(int)));
310 connect(m_d->optionButtonStripReference,
311 QOverload<int, bool>::of(&KisOptionButtonStrip::buttonToggled),
312 [this](int i, int c) {
313 m_d->on_optionButtonStripReference_buttonToggled(i, c);
314 });
315 connect(m_d->widgetLabels,
316 SIGNAL(selectionChanged()),
318}
319
323
325{
326 return m_d->buttonIndexToMode(
327 m_d->optionButtonStripMode->checkedButtonIndex());
328}
329
331{
332 return m_d->buttonIndexToAction(
333 m_d->optionButtonStripAction->checkedButtonIndex());
334}
335
337{
338 return m_d->checkBoxAntiAliasSelection->isChecked();
339}
340
342{
343 return m_d->sliderGrowSelection->value();
344}
345
347{
348 return m_d->buttonStopGrowingAtDarkestPixel->isChecked();
349}
350
352{
353 return m_d->sliderFeatherSelection->value();
354}
355
358{
359 return m_d->buttonIndexToReferenceLayers(
360 m_d->optionButtonStripReference->checkedButtonIndex());
361}
362
364{
365 return m_d->widgetLabels->selection();
366}
367
369{
371 m_d->optionButtonStripMode->button(m_d->modeToButtonIndex(newMode));
373
374 button->setChecked(true);
375}
376
378{
379 KoGroupButton *button = m_d->optionButtonStripAction->button(
380 m_d->actionToButtonIndex(newAction));
382
383 button->setChecked(true);
384}
385
386void KisSelectionOptions::setAntiAliasSelection(bool newAntiAliasSelection)
387{
388 m_d->checkBoxAntiAliasSelection->setChecked(newAntiAliasSelection);
389}
390
392{
393 m_d->sliderGrowSelection->setValue(newGrowSelection);
394}
395
396void KisSelectionOptions::setStopGrowingAtDarkestPixel(bool newStopGrowingAtDarkestPixel)
397{
398 m_d->buttonStopGrowingAtDarkestPixel->setChecked(newStopGrowingAtDarkestPixel);
399}
400
401void KisSelectionOptions::setFeatherSelection(int newFeatherSelection)
402{
403 m_d->sliderFeatherSelection->setValue(newFeatherSelection);
404}
405
407{
408 KoGroupButton *button = m_d->optionButtonStripReference->button(
409 m_d->referenceLayersToButtonIndex(newReferenceLayers));
411
412 button->setChecked(true);
413}
414
416 const QList<int> &newSelectedColorLabels)
417{
418 m_d->widgetLabels->setSelection(newSelectedColorLabels);
419}
420
422{
423 setWidgetVisible("sectionMode", visible);
424}
425
427{
428 setWidgetVisible("sectionAction", visible);
429}
430
432{
433 widgetAs<KisOptionCollectionWidgetWithHeader*>("sectionAdjustments")
434 ->widgetAs<KisOptionCollectionWidget*>("containerGrowSelection")
435 ->setWidgetVisible("buttonStopGrowingAtDarkestPixel", visible);
436}
437
439{
440 setWidgetVisible("sectionAdjustments", visible);
441}
442
444{
445 setWidgetVisible("sectionReference", visible);
446}
447
449 SelectionAction action,
450 const QKeySequence &shortcut)
451{
452 const QString shortcutString = shortcut.toString(QKeySequence::NativeText);
453 QString toolTipText;
454 const int buttonIndex = m_d->actionToButtonIndex(action);
455
456 switch (action) {
459 toolTipText = shortcutString.isEmpty()
460 ? i18nc("@info:tooltip", "Replace")
461 : i18nc("@info:tooltip", "Replace (%1)", shortcutString);
462 break;
463 case SELECTION_ADD:
464 toolTipText = shortcutString.isEmpty()
465 ? i18nc("@info:tooltip", "Add")
466 : i18nc("@info:tooltip", "Add (%1)", shortcutString);
467 break;
469 toolTipText = shortcutString.isEmpty()
470 ? i18nc("@info:tooltip", "Subtract")
471 : i18nc("@info:tooltip", "Subtract (%1)", shortcutString);
472 break;
474 toolTipText = shortcutString.isEmpty()
475 ? i18nc("@info:tooltip", "Intersect")
476 : i18nc("@info:tooltip", "Intersect (%1)", shortcutString);
477 break;
479 toolTipText = shortcutString.isEmpty()
480 ? i18nc("@info:tooltip", "Symmetric Difference")
481 : i18nc("@info:tooltip",
482 "Symmetric Difference (%1)",
483 shortcutString);
484 break;
485 }
486
487 m_d->optionButtonStripAction->button(buttonIndex)->setToolTip(toolTipText);
488}
SelectionMode
@ PIXEL_SELECTION
@ SHAPE_PROTECTION
SelectionAction
@ SELECTION_REPLACE
@ SELECTION_INTERSECT
@ SELECTION_SYMMETRICDIFFERENCE
@ SELECTION_DEFAULT
@ SELECTION_SUBTRACT
@ SELECTION_ADD
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void setExclusive(bool exclusive)
Set if the button selection is mutually exclusive. This allows switching between single or multiple s...
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 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)