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#include "KisPaletteModel.h"
13
14#include "kis_config.h"
18#include <kis_icon_utils.h>
19#include <KoGroupButton.h>
20#include <KoUnit.h>
21
22#include <kis_node.h>
23#include <kis_shape_layer.h>
24
25
27
28#include <KoUnit.h>
29
32 {
33 }
34
35 Ui_KisToolKnifeOptionsWidget *ui {nullptr};
39 qreal resolution {1.0};
40
41 QString toolId {""};
42
43
44
45 qreal getThickGapWidth(void)
46 {
47 return ui->thickGapWidth->value();
48 }
49
50 qreal getThinGapWidth(void)
51 {
52 return ui->thinGapWidth->value();
53 }
54
56 {
57 return ui->customGapWidth->value();
58 }
59
61 {
62 if (ui->thickGapWidthRadioButton->isChecked()) {
64 } else if (ui->thinGapWidthRadioButton->isChecked()) {
66 } else if (ui->specialGapWidthRadioButton->isChecked()) {
68 } else { // if (ui->automaticGapWidthRadioButton->isChecked())
70 }
71 }
72
74 if (type == "thick") {
76 } else if (type == "thin") {
78 } else if (type == "special") {
80 } else if (type == "automatic") {
82 } else {
83 // default
85 }
86 }
87
89 switch(type) {
91 return "thick";
92 break;
94 return "thin";
95 break;
97 return "special";
98 break;
100 return "automatic";
101 break;
102 default:
104 }
106 return "thick";
107 }
108
109
110
111 void setWidthTypeFromString(QString typeStr) {
114 ui->thickGapWidthRadioButton->setChecked(true);
115 } else if (type == KisToolKnifeOptionsWidget::Thin) {
116 ui->thinGapWidthRadioButton->setChecked(true);
117 } else if (type == KisToolKnifeOptionsWidget::Special) {
118 ui->specialGapWidthRadioButton->setChecked(true);
119 } else if (type == KisToolKnifeOptionsWidget::Automatic) {
120 ui->automaticGapWidthRadioButton->setChecked(true);
121 } else {
122 // default
123 ui->thickGapWidthRadioButton->setChecked(true);
124 }
125 }
126
127
128
130 switch(type) {
132 return getThickGapWidth();
134 return getThinGapWidth();
136 return getSpecialGapWidth();
137 default: // this handles automatic, too...
138 return getSpecialGapWidth();
139 }
140 }
141
143 return getWidthForType(ui->automaticHorizontalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
144 }
145
147 return getWidthForType(ui->automaticVerticalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
148 }
149
151 return getWidthForType(ui->automaticDiagonalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>());
152 }
153
154
155
157 switch(type) {
159 return GutterWidthsConfig(getCurrentUnit(), resolution, getThickGapWidth(), ui->gutterWidthAngleSpinBox->value());
161 return GutterWidthsConfig(getCurrentUnit(), resolution, getThinGapWidth(), ui->gutterWidthAngleSpinBox->value());
163 return GutterWidthsConfig(getCurrentUnit(), resolution, getSpecialGapWidth(), ui->gutterWidthAngleSpinBox->value());
165 return GutterWidthsConfig(getCurrentUnit(), resolution, getWidthHorizontal(), getWidthVertical(), getWidthDiagonal(), ui->gutterWidthAngleSpinBox->value());
166 default:
167 return GutterWidthsConfig(getCurrentUnit(), resolution, getSpecialGapWidth(), ui->gutterWidthAngleSpinBox->value());
168 }
169 }
170
171
172
185
187 return KoUnit::fromSymbol(ui->thickGapWidth->suffix().trimmed());
188 }
189
190 void setUnit(QString unit) {
191 if (ui->unitsCombobox->currentData() != unit) {
192 int index = ui->unitsCombobox->findData(unit);
193 if (index != -1) {
194 ui->unitsCombobox->setCurrentIndex(index);
195 }
196 }
197
198 KoUnit unitBefore = KoUnit::fromSymbol(ui->thickGapWidth->suffix().trimmed());
199 bool success;
200 KoUnit unitNow = KoUnit::fromSymbol(unit.trimmed(), &success);
201
202 if (!success || unit.trimmed() == "" || unitNow.type() == unitBefore.type()) {
203 return;
204 }
205
206 ui->thickGapWidth->setSuffix(" " + unitNow.symbol());
207 ui->thinGapWidth->setSuffix(" " + unitNow.symbol());
208 ui->customGapWidth->setSuffix(" " + unitNow.symbol());
209
210 ui->thickGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->thickGapWidth->value(), unitBefore, unitNow, resolution));
211 ui->thinGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->thinGapWidth->value(), unitBefore, unitNow, resolution));
212 ui->customGapWidth->setValue(KoUnit::convertFromUnitToUnit(ui->customGapWidth->value(), unitBefore, unitNow, resolution));
213
214 }
215
217 int index = combobox->findData(type);
218 if (index >= 0) {
219 combobox->setCurrentIndex(index);
220 }
221 }
222
223 void readFromConfig(QString groupId) {
224
225 KConfigGroup configGroup = KSharedConfig::openConfig()->group(groupId);
226
227 QString unitSymbol = configGroup.readEntry("gutter_unit_symbol", "px");
228 bool conversionSuccess;
229 KoUnit::fromSymbol(unitSymbol, &conversionSuccess);
230 if (!conversionSuccess) {
231 unitSymbol = "px";
232 }
233 setUnit(unitSymbol);
234
235 setWidthTypeFromString(configGroup.readEntry("current_gutter_width_type", "thick"));
236
237 ui->thickGapWidth->setValue(configGroup.readEntry("thick_gutter_width", 40.0f));
238 ui->thinGapWidth->setValue(configGroup.readEntry("thin_gutter_width", 15.0f));
239 ui->customGapWidth->setValue(configGroup.readEntry("special_gutter_width", 70.0f));
240
241 ui->gutterWidthAngleSpinBox->setValue(configGroup.readEntry("automatic_gutter_angle", 2.0f));
242
243 KisToolKnifeOptionsWidget::GapWidthType horizontalType = widthTypeFromString(configGroup.readEntry("automatic_horizontal_type", "thick"));
244 KisToolKnifeOptionsWidget::GapWidthType verticalType = widthTypeFromString(configGroup.readEntry("automatic_vertical_type", "thin"));
245 KisToolKnifeOptionsWidget::GapWidthType diagonalType = widthTypeFromString(configGroup.readEntry("automatic_diagonal_type", "thin"));
246
247 setTypeToCombobox(horizontalType, ui->automaticHorizontalCombobox);
248 setTypeToCombobox(verticalType, ui->automaticVerticalCombobox);
249 setTypeToCombobox(diagonalType, ui->automaticDiagonalCombobox);
250
251 }
252
253 void writeToConfig(QString groupId) {
254
255 KConfigGroup configGroup = KSharedConfig::openConfig()->group(groupId);
256
257 configGroup.writeEntry("gutter_unit_symbol", getCurrentUnit().symbol());
258 configGroup.writeEntry("current_gutter_width_type", widthTypeToString(getCurrentWidthType()));
259
260 configGroup.writeEntry("thick_gutter_width", ui->thickGapWidth->value());
261 configGroup.writeEntry("thin_gutter_width", ui->thinGapWidth->value());
262 configGroup.writeEntry("special_gutter_width", ui->customGapWidth->value());
263
264 configGroup.writeEntry("automatic_gutter_angle", ui->gutterWidthAngleSpinBox->value());
265
266 configGroup.writeEntry("automatic_horizontal_type", widthTypeToString(ui->automaticHorizontalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
267 configGroup.writeEntry("automatic_vertical_type", widthTypeToString(ui->automaticVerticalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
268 configGroup.writeEntry("automatic_diagonal_type", widthTypeToString(ui->automaticDiagonalCombobox->currentData().value<KisToolKnifeOptionsWidget::GapWidthType>()));
269 }
270
271};
272
273KisToolKnifeOptionsWidget::KisToolKnifeOptionsWidget(KisCanvasResourceProvider *provider, QWidget *parent, QString toolId, qreal resolution)
274 : QWidget(parent),
275 m_d(new Private)
276{
277 m_d->ui = new Ui_KisToolKnifeOptionsWidget();
278 m_d->ui->setupUi(this);
279
280 m_d->toolId = toolId;
281 m_d->resolution = resolution;
282
283
284 //m_d->ui->optionButtonStripToolMode->addButton(KisIconUtils::loadIcon("tool_comic_panel_scissors"));
285 //KisOptionButtonStrip *optionButtonStripToolMode =
286 // new KisOptionButtonStrip;
287 m_d->buttonModeAddGutter = m_d->ui->optionButtonStripToolMode->addButton(
288 KisIconUtils::loadIcon("tool_comic_panel_cut"));
289 m_d->buttonModeRemoveGutter = m_d->ui->optionButtonStripToolMode->addButton(
290 KisIconUtils::loadIcon("tool_comic_panel_merge"));
291 //m_d->buttonModeMoveGutterEndPoint = m_d->ui->optionButtonStripToolMode->addButton(
292 // KisIconUtils::loadIcon("tool_comic_panel_move_point"));
293
294 m_d->buttonModeAddGutter->setChecked(true);
295 m_d->buttonModeAddGutter->setMinimumSize(QSize(20, 20));
296 m_d->buttonModeRemoveGutter->setMinimumSize(QSize(20, 20));
297 m_d->buttonModeAddGutter->setIconSize(QSize(16, 16));
298 m_d->buttonModeRemoveGutter->setIconSize(QSize(16, 16));
299
300 //m_d->buttonModeMoveGutterEndPoint->setMinimumSize(QSize(36, 36));
301 //m_d->buttonModeMoveGutterEndPoint->setIconSize(QSize(28, 28));
302
303
304 m_d->ui->unitsCombobox->addItem(i18n("Pixels"), QVariant("px"));
305 m_d->ui->unitsCombobox->addItem(i18n("Millimeters"), QVariant("mm"));
306
307 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
308 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
309 m_d->ui->automaticHorizontalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
310
311
312 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
313 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
314 m_d->ui->automaticVerticalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
315
316
317 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Thick type of gutter (in comics); keep consistent with the label in the GUI", "Thick"), QVariant(KisToolKnifeOptionsWidget::Thick));
318 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Thin type of gutter (in comics); keep consistent with the label in the GUI", "Thin"), QVariant(KisToolKnifeOptionsWidget::Thin));
319 m_d->ui->automaticDiagonalCombobox->addItem(i18nc("Special type of gutter (in comics); keep consistent with the label in the GUI", "Special"), QVariant(KisToolKnifeOptionsWidget::Special));
320
321
322 m_d->readFromConfig(toolId);
323 connect(m_d->ui->unitsCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(unitForWidthChanged(int)));
324
325 connect(provider, SIGNAL(sigNodeChanged(const KisNodeSP)), this, SLOT(currentNodeChanged(const KisNodeSP)));
326 connect(m_d->buttonModeAddGutter, SIGNAL(clicked()), this, SLOT(modeChanged()));
327 connect(m_d->buttonModeRemoveGutter, SIGNAL(clicked()), this, SLOT(modeChanged()));
328
329 connect(m_d->ui->automaticGapWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(currentWidthSystemChanged()));
330
331 modeChanged();
332 currentNodeChanged(provider->currentNode());
334
335}
336
337
338
340{
341 m_d->writeToConfig(m_d->toolId);
342 delete m_d->ui;
343 m_d->ui = nullptr;
344}
345
347{
348 return m_d->getCurrentWidthsConfig(m_d->getCurrentWidthType());
349}
350
355
357{
358 QString selected = m_d->ui->unitsCombobox->itemData(index).toString();
359 m_d->setUnit(selected);
360}
361
363{
364 const KisShapeLayer *shapeLayer = qobject_cast<const KisShapeLayer*>(node.data());
365 if (!shapeLayer) {
366 m_d->ui->gapOptionsWidget->setVisible(false);
367 m_d->ui->warningLabel->setVisible(true);
368
369 } else {
370 m_d->ui->gapOptionsWidget->setVisible(true);
371 m_d->ui->warningLabel->setVisible(false);
372 }
373}
374
376{
378 switch(mode) {
379 case AddGutter:
380 m_d->ui->gapOptionsWidget->setEnabled(true);
381 break;
382 case RemoveGutter:
383 m_d->ui->gapOptionsWidget->setEnabled(false);
384 break;
385
386 }
387}
388
390{
391
392 GapWidthType gapConfig = m_d->getCurrentWidthType();
393 switch(gapConfig) {
394 case Thin:
395 case Thick:
396 case Special:
397 m_d->ui->automaticDiagonalCombobox->setEnabled(false);
398 m_d->ui->automaticVerticalCombobox->setEnabled(false);
399 m_d->ui->automaticHorizontalCombobox->setEnabled(false);
400 m_d->ui->gutterWidthAngleSpinBox->setEnabled(false);
401 m_d->ui->angleLabel->setEnabled(false);
402 m_d->ui->horizontalLabel->setEnabled(false);
403 m_d->ui->verticalLabel->setEnabled(false);
404 m_d->ui->diagonalLabel->setEnabled(false);
405
406 break;
407 case Automatic:
408 m_d->ui->automaticDiagonalCombobox->setEnabled(true);
409 m_d->ui->automaticVerticalCombobox->setEnabled(true);
410 m_d->ui->automaticHorizontalCombobox->setEnabled(true);
411 m_d->ui->gutterWidthAngleSpinBox->setEnabled(true);
412 m_d->ui->horizontalLabel->setEnabled(true);
413 m_d->ui->verticalLabel->setEnabled(true);
414 m_d->ui->diagonalLabel->setEnabled(true);
415 m_d->ui->angleLabel->setEnabled(true);
416 break;
417 }
418}
419
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()