Krita Source Code Documentation
Loading...
Searching...
No Matches
KisToolKnifeOptionsWidget.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Agata Cacko
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include "ui_KisToolKnifeOptionsWidget.h"
10
12
13#include "kis_config.h"
17#include <kis_icon_utils.h>
18#include <KoGroupButton.h>
19#include <KoUnit.h>
20
21#include <kis_node.h>
22#include <kis_shape_layer.h>
23
24
26
27#include <KoUnit.h>
28
31 {
32 }
33
34 Ui_KisToolKnifeOptionsWidget *ui {nullptr};
37 //KoGroupButton* buttonModeMoveGutterEndPoint {nullptr};
38 qreal resolution {1.0};
39
40 QString toolId {""};
41
42
43
44 qreal getThickGapWidth(void)
45 {
46 return ui->thickGapWidth->value();
47 }
48
49 qreal getThinGapWidth(void)
50 {
51 return ui->thinGapWidth->value();
52 }
53
55 {
56 return ui->customGapWidth->value();
57 }
58
60 {
61 if (ui->thickGapWidthRadioButton->isChecked()) {
63 } else if (ui->thinGapWidthRadioButton->isChecked()) {
65 } else if (ui->specialGapWidthRadioButton->isChecked()) {
67 } else { // if (ui->automaticGapWidthRadioButton->isChecked())
69 }
70 }
71
73 if (type == "thick") {
75 } else if (type == "thin") {
77 } else if (type == "special") {
79 } else if (type == "automatic") {
81 } else {
82 // default
84 }
85 }
86
88 switch(type) {
90 return "thick";
91 break;
93 return "thin";
94 break;
96 return "special";
97 break;
99 return "automatic";
100 break;
101 default:
103 }
105 return "thick";
106 }
107
108
109
110 void setWidthTypeFromString(QString typeStr) {
113 ui->thickGapWidthRadioButton->setChecked(true);
114 } else if (type == KisToolKnifeOptionsWidget::Thin) {
115 ui->thinGapWidthRadioButton->setChecked(true);
116 } else if (type == KisToolKnifeOptionsWidget::Special) {
117 ui->specialGapWidthRadioButton->setChecked(true);
118 } else if (type == KisToolKnifeOptionsWidget::Automatic) {
119 ui->automaticGapWidthRadioButton->setChecked(true);
120 } else {
121 // default
122 ui->thickGapWidthRadioButton->setChecked(true);
123 }
124 }
125
126
127
129 switch(type) {
131 return getThickGapWidth();
133 return getThinGapWidth();
135 return getSpecialGapWidth();
136 default: // this handles automatic, too...
137 return getSpecialGapWidth();
138 }
139 }
140
142 return getWidthForType(ui->automaticHorizontalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
143 }
144
146 return getWidthForType(ui->automaticVerticalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
147 }
148
150 return getWidthForType(ui->automaticDiagonalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
151 }
152
153
154
156 switch(type) {
158 return GutterWidthsConfig(getCurrentUnit(), resolution, getThickGapWidth(), ui->gutterWidthAngleSpinBox->value());
160 return GutterWidthsConfig(getCurrentUnit(), resolution, getThinGapWidth(), ui->gutterWidthAngleSpinBox->value());
162 return GutterWidthsConfig(getCurrentUnit(), resolution, getSpecialGapWidth(), ui->gutterWidthAngleSpinBox->value());
164 return GutterWidthsConfig(getCurrentUnit(), resolution, getWidthHorizontal(), getWidthVertical(), getWidthDiagonal(), ui->gutterWidthAngleSpinBox->value());
165 default:
166 return GutterWidthsConfig(getCurrentUnit(), resolution, getSpecialGapWidth(), ui->gutterWidthAngleSpinBox->value());
167 }
168 }
169
170
171
173 if (buttonModeAddGutter && buttonModeAddGutter->isChecked()) {
175 } else if (buttonModeRemoveGutter && buttonModeRemoveGutter->isChecked()) {
177 //} else if (buttonModeMoveGutterEndPoint && buttonModeMoveGutterEndPoint->isChecked()) {
178 // return KisToolKnifeOptionsWidget::MoveGutterEndPoint;
179 } else {
180 // default
182 }
183 }
184
186 return KoUnit::fromSymbol(ui->thickGapWidth->suffix().trimmed());
187 }
188
189 void setUnit(QString unit) {
190 if (ui->unitsCombobox->currentData() != unit) {
191 int index = ui->unitsCombobox->findData(unit);
192 if (index != -1) {
193 ui->unitsCombobox->setCurrentIndex(index);
194 }
195 }
196
197 KoUnit unitBefore = KoUnit::fromSymbol(ui->thickGapWidth->suffix().trimmed());
198 bool success;
199 KoUnit unitNow = KoUnit::fromSymbol(unit.trimmed(), &success);
200
201 if (!success || unit.trimmed() == "" || unitNow.type() == unitBefore.type()) {
202 return;
203 }
204
205 ui->thickGapWidth->setSuffix(" " + unitNow.symbol());
206 ui->thinGapWidth->setSuffix(" " + unitNow.symbol());
207 ui->customGapWidth->setSuffix(" " + unitNow.symbol());
208
209 ui->thickGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->thickGapWidth->value(), unitBefore, unitNow, resolution));
210 ui->thinGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->thinGapWidth->value(), unitBefore, unitNow, resolution));
211 ui->customGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->customGapWidth->value(), unitBefore, unitNow, resolution));
212
213 }
214
216 int index = combobox->findData(type);
217 if (index >= 0) {
218 combobox->setCurrentIndex(index);
219 }
220 }
221
222 void readFromConfig(QString groupId) {
223
224 KConfigGroup configGroup = KSharedConfig::openConfig()->group(groupId);
225
226 QString unitSymbol = configGroup.readEntry("gutter_unit_symbol", "px");
227 bool conversionSuccess;
228 KoUnit::fromSymbol(unitSymbol, &conversionSuccess);
229 if (!conversionSuccess) {
230 unitSymbol = "px";
231 }
232 setUnit(unitSymbol);
233
234 setWidthTypeFromString(configGroup.readEntry("current_gutter_width_type", "thick"));
235
236 ui->thickGapWidth->setValue(configGroup.readEntry("thick_gutter_width", 40.0f));
237 ui->thinGapWidth->setValue(configGroup.readEntry("thin_gutter_width", 15.0f));
238 ui->customGapWidth->setValue(configGroup.readEntry("special_gutter_width", 70.0f));
239
240 ui->gutterWidthAngleSpinBox->setValue(configGroup.readEntry("automatic_gutter_angle", 2.0f));
241
242 KisToolKnifeOptionsWidget::GapWidthType horizontalType = widthTypeFromString(configGroup.readEntry("automatic_horizontal_type", "thick"));
243 KisToolKnifeOptionsWidget::GapWidthType verticalType = widthTypeFromString(configGroup.readEntry("automatic_vertical_type", "thin"));
244 KisToolKnifeOptionsWidget::GapWidthType diagonalType = widthTypeFromString(configGroup.readEntry("automatic_diagonal_type", "thin"));
245
246 setTypeToCombobox(horizontalType, ui->automaticHorizontalCombobox);
247 setTypeToCombobox(verticalType, ui->automaticVerticalCombobox);
248 setTypeToCombobox(diagonalType, ui->automaticDiagonalCombobox);
249
250 }
251
252 void writeToConfig(QString groupId) {
253
254 KConfigGroup configGroup = KSharedConfig::openConfig()->group(groupId);
255
256 configGroup.writeEntry("gutter_unit_symbol", getCurrentUnit().symbol());
257 configGroup.writeEntry("current_gutter_width_type", widthTypeToString(getCurrentWidthType()));
258
259 configGroup.writeEntry("thick_gutter_width", ui->thickGapWidth->value());
260 configGroup.writeEntry("thin_gutter_width", ui->thinGapWidth->value());
261 configGroup.writeEntry("special_gutter_width", ui->customGapWidth->value());
262
263 configGroup.writeEntry("automatic_gutter_angle", ui->gutterWidthAngleSpinBox->value());
264
265 configGroup.writeEntry("automatic_horizontal_type", widthTypeToString(ui->automaticHorizontalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
266 configGroup.writeEntry("automatic_vertical_type", widthTypeToString(ui->automaticVerticalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
267 configGroup.writeEntry("automatic_diagonal_type", widthTypeToString(ui->automaticDiagonalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
268 }
269
270};
271
272KisToolKnifeOptionsWidget::KisToolKnifeOptionsWidget(KisCanvasResourceProvider *provider, QWidget *parent, QString toolId, qreal resolution)
273 : QWidget(parent),
274 m_d(new Private)
275{
276 m_d->ui = new Ui_KisToolKnifeOptionsWidget();
277 m_d->ui->setupUi(this);
278
279 m_d->toolId = toolId;
280 m_d->resolution = resolution;
281
282
283 //m_d->ui->optionButtonStripToolMode->addButton(KisIconUtils::loadIcon("tool_comic_panel_scissors"));
284 //KisOptionButtonStrip *optionButtonStripToolMode =
285 // new KisOptionButtonStrip;
286 m_d->buttonModeAddGutter = m_d->ui->optionButtonStripToolMode->addButton(
287 KisIconUtils::loadIcon("tool_comic_panel_cut"));
288 m_d->buttonModeRemoveGutter = m_d->ui->optionButtonStripToolMode->addButton(
289 KisIconUtils::loadIcon("tool_comic_panel_merge"));
290 //m_d->buttonModeMoveGutterEndPoint = m_d->ui->optionButtonStripToolMode->addButton(
291 // KisIconUtils::loadIcon("tool_comic_panel_move_point"));
292
293 m_d->buttonModeAddGutter->setChecked(true);
294 m_d->buttonModeAddGutter->setMinimumSize(QSize(20, 20));
295 m_d->buttonModeRemoveGutter->setMinimumSize(QSize(20, 20));
296 m_d->buttonModeAddGutter->setIconSize(QSize(16, 16));
297 m_d->buttonModeRemoveGutter->setIconSize(QSize(16, 16));
298
299 m_d->buttonModeAddGutter->setToolTip(i18nc("Tooltip for the button in the Knife Tool for the mode to add gutters/cut through shapes", "Cutting mode: Cuts through shapes to create gutters of specified width."));
300 m_d->buttonModeRemoveGutter->setToolTip(i18nc("Tooltip for the button in the Knife Tool for the mode to remove gutters/merge shapes", "Merging mode: Removes the gutter between shapes."));
301
302 //m_d->buttonModeMoveGutterEndPoint->setMinimumSize(QSize(36, 36));
303 //m_d->buttonModeMoveGutterEndPoint->setIconSize(QSize(28, 28));
304
305
306 m_d->ui->unitsCombobox->addItem(i18n("Pixels"), QVariant("px"));
307 m_d->ui->unitsCombobox->addItem(i18n("Millimeters"), QVariant("mm"));
308
309 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
310 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
311 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
312
313
314 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
315 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
316 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
317
318
319 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
320 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
321 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
322
323
324 m_d->readFromConfig(toolId);
325 connect(m_d->ui->unitsCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(unitForWidthChanged(int)));
326
327 connect(provider, SIGNAL(sigNodeChanged(const KisNodeSP)), this, SLOT(currentNodeChanged(const KisNodeSP)));
328 connect(m_d->buttonModeAddGutter, SIGNAL(clicked()), this, SLOT(modeChanged()));
329 connect(m_d->buttonModeRemoveGutter, SIGNAL(clicked()), this, SLOT(modeChanged()));
330
331 connect(m_d->ui->automaticGapWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(currentWidthSystemChanged()));
332
333 modeChanged();
334 currentNodeChanged(provider->currentNode());
336
337}
338
339
340
342{
343 m_d->writeToConfig(m_d->toolId);
344 delete m_d->ui;
345 m_d->ui = nullptr;
346}
347
349{
350 return m_d->getCurrentWidthsConfig(m_d->getCurrentWidthType());
351}
352
357
359{
360 QString selected = m_d->ui->unitsCombobox->itemData(index).toString();
361 m_d->setUnit(selected);
362}
363
365{
366 const KisShapeLayer *shapeLayer = qobject_cast<const KisShapeLayer*>(node.data());
367 if (!shapeLayer) {
368 m_d->ui->gapOptionsWidget->setVisible(false);
369 m_d->ui->warningLabel->setVisible(true);
370
371 } else {
372 m_d->ui->gapOptionsWidget->setVisible(true);
373 m_d->ui->warningLabel->setVisible(false);
374 }
375}
376
378{
380 switch(mode) {
381 case AddGutter:
382 m_d->ui->gapOptionsWidget->setEnabled(true);
383 break;
384 case RemoveGutter:
385 m_d->ui->gapOptionsWidget->setEnabled(false);
386 break;
387
388 }
389}
390
392{
393
394 GapWidthType gapConfig = m_d->getCurrentWidthType();
395 switch(gapConfig) {
396 case Thin:
397 case Thick:
398 case Special:
399 m_d->ui->automaticDiagonalCombobox->setEnabled(false);
400 m_d->ui->automaticVerticalCombobox->setEnabled(false);
401 m_d->ui->automaticHorizontalCombobox->setEnabled(false);
402 m_d->ui->gutterWidthAngleSpinBox->setEnabled(false);
403 m_d->ui->angleLabel->setEnabled(false);
404 m_d->ui->horizontalLabel->setEnabled(false);
405 m_d->ui->verticalLabel->setEnabled(false);
406 m_d->ui->diagonalLabel->setEnabled(false);
407
408 break;
409 case Automatic:
410 m_d->ui->automaticDiagonalCombobox->setEnabled(true);
411 m_d->ui->automaticVerticalCombobox->setEnabled(true);
412 m_d->ui->automaticHorizontalCombobox->setEnabled(true);
413 m_d->ui->gutterWidthAngleSpinBox->setEnabled(true);
414 m_d->ui->horizontalLabel->setEnabled(true);
415 m_d->ui->verticalLabel->setEnabled(true);
416 m_d->ui->diagonalLabel->setEnabled(true);
417 m_d->ui->angleLabel->setEnabled(true);
418 break;
419 }
420}
421
const QScopedPointer< Private > m_d
void currentNodeChanged(const KisNodeSP node)
KisToolKnifeOptionsWidget(KisCanvasResourceProvider *provider, QWidget *parent, QString toolId, qreal resolution)
static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor=1.0)
Definition KoUnit.cpp:295
KoUnit::Type type() const
Definition KoUnit.h:118
static KoUnit fromSymbol(const QString &symbol, bool *ok=0)
Definition KoUnit.cpp:271
QString symbol() const
Get the symbol string of the unit.
Definition KoUnit.cpp:347
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
Q_DECLARE_METATYPE(KisPaintopLodLimitations)
QIcon loadIcon(const QString &name)
QString widthTypeToString(KisToolKnifeOptionsWidget::GapWidthType type)
KisToolKnifeOptionsWidget::GapWidthType getCurrentWidthType()
GutterWidthsConfig getCurrentWidthsConfig(KisToolKnifeOptionsWidget::GapWidthType type)
void setTypeToCombobox(KisToolKnifeOptionsWidget::GapWidthType type, QComboBox *combobox)
qreal getWidthForType(KisToolKnifeOptionsWidget::GapWidthType type)
KisToolKnifeOptionsWidget::GapWidthType widthTypeFromString(QString type)
KisToolKnifeOptionsWidget::ToolMode getToolMode()