File indexing completed on 2024-06-23 04:28:10

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2007 Martin Pfeiffer <hubipete@gmx.net>
0003  * SPDX-FileCopyrightText: 2007 Jan Hambrecht <jaham@gmx.net>
0004  * SPDX-FileCopyrightText: 2008 Thorsten Zachmann <zachmann@kde.org>
0005  * SPDX-FileCopyrightText: 2010 Thomas Zander <zander@kde.org>
0006  *
0007  * SPDX-License-Identifier: LGPL-2.0-or-later
0008  */
0009 
0010 #include "DefaultToolGeometryWidget.h"
0011 #include "DefaultTool.h"
0012 
0013 #include <KoInteractionTool.h>
0014 #include <KoCanvasBase.h>
0015 #include <KoCanvasResourceProvider.h>
0016 #include <KoSelectedShapesProxy.h>
0017 #include <KoSelection.h>
0018 #include <KoUnit.h>
0019 #include <commands/KoShapeResizeCommand.h>
0020 #include <commands/KoShapeMoveCommand.h>
0021 #include <commands/KoShapeSizeCommand.h>
0022 #include <commands/KoShapeTransformCommand.h>
0023 #include <commands/KoShapeKeepAspectRatioCommand.h>
0024 #include <commands/KoShapeTransparencyCommand.h>
0025 #include <commands/KoShapePaintOrderCommand.h>
0026 #include "SelectionDecorator.h"
0027 #include <KoShapeGroup.h>
0028 
0029 #include "KoAnchorSelectionWidget.h"
0030 
0031 #include <QAction>
0032 #include <QSize>
0033 #include <QRadioButton>
0034 #include <QLabel>
0035 #include <QCheckBox>
0036 #include <QDoubleSpinBox>
0037 #include <QList>
0038 #include <QTransform>
0039 #include <kis_algebra_2d.h>
0040 
0041 #include "kis_aspect_ratio_locker.h"
0042 #include "kis_debug.h"
0043 #include "kis_acyclic_signal_connector.h"
0044 #include "kis_signal_compressor.h"
0045 #include "kis_signals_blocker.h"
0046 #include "kis_icon.h"
0047 
0048 
0049 DefaultToolGeometryWidget::DefaultToolGeometryWidget(KoInteractionTool *tool, QWidget *parent)
0050     : QWidget(parent)
0051     , m_tool(tool)
0052     , m_sizeAspectLocker(new KisAspectRatioLocker())
0053     , m_savedUniformScaling(false)
0054 {
0055     setupUi(this);
0056 
0057     setUnit(KoUnit(KoUnit::Point));
0058 
0059     // Connect and initialize automated aspect locker
0060     m_sizeAspectLocker->connectSpinBoxes(widthSpinBox, heightSpinBox, aspectButton);
0061     aspectButton->setKeepAspectRatio(false);
0062 
0063 
0064     // TODO: use valueChanged() instead!
0065     connect(positionXSpinBox, SIGNAL(valueChangedPt(qreal)), this, SLOT(slotRepositionShapes()));
0066     connect(positionYSpinBox, SIGNAL(valueChangedPt(qreal)), this, SLOT(slotRepositionShapes()));
0067 
0068     KoSelectedShapesProxy *selectedShapesProxy = m_tool->canvas()->selectedShapesProxy();
0069 
0070     connect(selectedShapesProxy, SIGNAL(selectionChanged()), this, SLOT(slotUpdateCheckboxes()));
0071     connect(selectedShapesProxy, SIGNAL(selectionChanged()), this, SLOT(slotUpdatePositionBoxes()));
0072     connect(selectedShapesProxy, SIGNAL(selectionChanged()), this, SLOT(slotUpdateOpacitySlider()));
0073 
0074     connect(selectedShapesProxy, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdatePositionBoxes()));
0075     connect(selectedShapesProxy, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdateOpacitySlider()));
0076 
0077     connect(chkGlobalCoordinates, SIGNAL(toggled(bool)), SLOT(slotUpdateSizeBoxes()));
0078     connect(chkGlobalCoordinates, SIGNAL(toggled(bool)), SLOT(slotUpdateAspectButton()));
0079 
0080 
0081     /**
0082      * A huge block of self-blocking acyclic connections
0083      */
0084     KisAcyclicSignalConnector *acyclicConnector = new KisAcyclicSignalConnector(this);
0085     acyclicConnector->connectForwardVoid(m_sizeAspectLocker.data(), SIGNAL(aspectButtonChanged()), this, SLOT(slotAspectButtonToggled()));
0086     acyclicConnector->connectBackwardVoid(selectedShapesProxy, SIGNAL(selectionChanged()), this, SLOT(slotUpdateAspectButton()));
0087     acyclicConnector->connectBackwardVoid(selectedShapesProxy, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdateAspectButton()));
0088 
0089     KisAcyclicSignalConnector *sizeConnector = acyclicConnector->createCoordinatedConnector();
0090     sizeConnector->connectForwardVoid(m_sizeAspectLocker.data(), SIGNAL(sliderValueChanged()), this, SLOT(slotResizeShapes()));
0091     sizeConnector->connectBackwardVoid(selectedShapesProxy, SIGNAL(selectionChanged()), this, SLOT(slotUpdateSizeBoxes()));
0092 
0093     KisAcyclicSignalConnector *contentSizeConnector = acyclicConnector->createCoordinatedConnector();
0094     contentSizeConnector->connectBackwardVoid(selectedShapesProxy, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdateSizeBoxesNoAspectChange()));
0095 
0096 
0097     // Connect and initialize anchor point resource
0098     KoCanvasResourceProvider *resourceManager = m_tool->canvas()->resourceManager();
0099     connect(resourceManager,
0100             SIGNAL(canvasResourceChanged(int,QVariant)),
0101             SLOT(resourceChanged(int,QVariant)));
0102     resourceManager->setResource(DefaultTool::HotPosition, int(KoFlake::AnchorPosition::Center));
0103     positionSelector->setValue(KoFlake::AnchorPosition(resourceManager->resource(DefaultTool::HotPosition).toInt()));
0104 
0105     // Connect anchor point selector
0106     connect(positionSelector, SIGNAL(valueChanged(KoFlake::AnchorPosition)), SLOT(slotAnchorPointChanged()));
0107 
0108     cmbPaintOrder->setIconSize(QSize(22, 22));
0109     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-fill-stroke-marker"), i18n("Fill, Stroke, Markers"));
0110     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-fill-marker-stroke"), i18n("Fill, Markers, Stroke"));
0111     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-stroke-fill-marker"), i18n("Stroke, Fill, Markers"));
0112     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-stroke-marker-fill"), i18n("Stroke, Markers, Fill"));
0113     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-marker-fill-stroke"), i18n("Markers, Fill, Stroke"));
0114     cmbPaintOrder->addItem(KisIconUtils::loadIcon("paint-order-marker-stroke-fill"), i18n("Markers, Stroke, Fill"));
0115     connect(cmbPaintOrder, SIGNAL(currentIndexChanged(int)), SLOT(slotPaintOrderChanged()));
0116 
0117 
0118     dblOpacity->setRange(0.0, 1.0, 2);
0119     dblOpacity->setSingleStep(0.01);
0120     dblOpacity->setFastSliderStep(0.1);
0121     dblOpacity->setTextTemplates(i18nc("{n} is the number value, % is the percent sign", "Opacity: {n}"),
0122                                  i18nc("{n} is the number value, % is the percent sign", "Opacity [*varies*]: {n}"));
0123 
0124     dblOpacity->setValueGetter(
0125         [](KoShape *s) { return 1.0 - s->transparency(); }
0126     );
0127 
0128     connect(dblOpacity, SIGNAL(valueChanged(qreal)), SLOT(slotOpacitySliderChanged(qreal)));
0129 
0130     // cold init
0131     slotUpdateOpacitySlider();
0132 }
0133 
0134 DefaultToolGeometryWidget::~DefaultToolGeometryWidget()
0135 {
0136 }
0137 
0138 namespace {
0139 
0140 void tryAnchorPosition(KoFlake::AnchorPosition anchor,
0141                        const QRectF &rect,
0142                        QPointF *position)
0143 {
0144     bool valid = false;
0145     QPointF anchoredPosition = KoFlake::anchorToPoint(anchor, rect, &valid);
0146 
0147     if (valid) {
0148         *position = anchoredPosition;
0149     }
0150 }
0151 
0152 QRectF calculateSelectionBounds(KoSelection *selection,
0153                                 KoFlake::AnchorPosition anchor,
0154                                 bool useGlobalSize,
0155                                 QList<KoShape*> *outShapes = 0)
0156 {
0157     QList<KoShape*> shapes = selection->selectedEditableShapes();
0158 
0159     KoShape *shape = shapes.size() == 1 ? shapes.first() : selection;
0160 
0161     QRectF resultRect = shape->outlineRect();
0162 
0163     QPointF resultPoint = resultRect.topLeft();
0164     tryAnchorPosition(anchor, resultRect, &resultPoint);
0165 
0166     if (useGlobalSize) {
0167         resultRect = shape->absoluteTransformation().mapRect(resultRect);
0168     } else {
0169         /**
0170          * Some shapes, e.g. KoSelection and KoShapeGroup don't have real size() and
0171          * do all the resizing with transformation(), just try to cover this case and
0172          * fetch their scale using the transform.
0173          */
0174 
0175         KisAlgebra2D::DecomposedMatrix matrix(shape->transformation());
0176         resultRect = matrix.scaleTransform().mapRect(resultRect);
0177     }
0178 
0179     resultPoint = shape->absoluteTransformation().map(resultPoint);
0180 
0181     if (outShapes) {
0182         *outShapes = shapes;
0183     }
0184 
0185     return QRectF(resultPoint, resultRect.size());
0186 }
0187 
0188 }
0189 
0190 void DefaultToolGeometryWidget::slotAnchorPointChanged()
0191 {
0192     if (!isVisible()) return;
0193 
0194     QVariant newValue(positionSelector->value());
0195     m_tool->canvas()->resourceManager()->setResource(DefaultTool::HotPosition, newValue);
0196     slotUpdatePositionBoxes();
0197 }
0198 
0199 void DefaultToolGeometryWidget::slotUpdateCheckboxes()
0200 {
0201     if (!isVisible()) return;
0202 
0203     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0204     QList<KoShape*> shapes = selection->selectedEditableShapes();
0205 
0206     KoShapeGroup *onlyGroupShape = 0;
0207 
0208     if (shapes.size() == 1) {
0209         onlyGroupShape = dynamic_cast<KoShapeGroup*>(shapes.first());
0210     }
0211 
0212     const bool uniformScalingAvailable = shapes.size() <= 1 && !onlyGroupShape;
0213 
0214     if (uniformScalingAvailable && !chkUniformScaling->isEnabled()) {
0215         chkUniformScaling->setChecked(m_savedUniformScaling);
0216         chkUniformScaling->setEnabled(uniformScalingAvailable);
0217     } else if (!uniformScalingAvailable && chkUniformScaling->isEnabled()) {
0218         m_savedUniformScaling = chkUniformScaling->isChecked();
0219         chkUniformScaling->setChecked(true);
0220         chkUniformScaling->setEnabled(uniformScalingAvailable);
0221     }
0222 
0223     // TODO: not implemented yet!
0224     chkAnchorLock->setEnabled(false);
0225 }
0226 
0227 void DefaultToolGeometryWidget::slotAspectButtonToggled()
0228 {
0229     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0230     QList<KoShape*> shapes = selection->selectedEditableShapes();
0231 
0232     KUndo2Command *cmd =
0233         new KoShapeKeepAspectRatioCommand(shapes, aspectButton->keepAspectRatio());
0234 
0235     m_tool->canvas()->addCommand(cmd);
0236 }
0237 
0238 void DefaultToolGeometryWidget::slotUpdateAspectButton()
0239 {
0240     if (!isVisible()) return;
0241 
0242     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0243     QList<KoShape*> shapes = selection->selectedEditableShapes();
0244 
0245     bool hasKeepAspectRatio = false;
0246     bool hasNotKeepAspectRatio = false;
0247 
0248     Q_FOREACH (KoShape *shape, shapes) {
0249         if (shape->keepAspectRatio()) {
0250             hasKeepAspectRatio = true;
0251         } else {
0252             hasNotKeepAspectRatio = true;
0253         }
0254 
0255         if (hasKeepAspectRatio && hasNotKeepAspectRatio) break;
0256     }
0257 
0258     Q_UNUSED(hasNotKeepAspectRatio); // TODO: use for tristated mode of the checkbox
0259 
0260     const bool useGlobalSize = chkGlobalCoordinates->isChecked();
0261     const KoFlake::AnchorPosition anchor = positionSelector->value();
0262     const QRectF bounds = calculateSelectionBounds(selection, anchor, useGlobalSize);
0263     const bool hasNullDimensions = bounds.isEmpty();
0264 
0265     aspectButton->setKeepAspectRatio(hasKeepAspectRatio && !hasNullDimensions);
0266     aspectButton->setEnabled(!hasNullDimensions);
0267 }
0268 
0269 //namespace {
0270 //qreal calculateCommonShapeTransparency(const QList<KoShape*> &shapes)
0271 //{
0272 //    qreal commonTransparency = -1.0;
0273 
0274 //    Q_FOREACH (KoShape *shape, shapes) {
0275 //        if (commonTransparency < 0) {
0276 //            commonTransparency = shape->transparency();
0277 //        } else if (!qFuzzyCompare(commonTransparency, shape->transparency())) {
0278 //            commonTransparency = -1.0;
0279 //            break;
0280 //        }
0281 //    }
0282 
0283 //    return commonTransparency;
0284 //}
0285 //}
0286 
0287 void DefaultToolGeometryWidget::slotOpacitySliderChanged(qreal newOpacity)
0288 {
0289     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0290     QList<KoShape*> shapes = selection->selectedEditableShapes();
0291     if (shapes.isEmpty()) return;
0292 
0293     KUndo2Command *cmd =
0294         new KoShapeTransparencyCommand(shapes, 1.0 - newOpacity);
0295 
0296     m_tool->canvas()->addCommand(cmd);
0297 }
0298 
0299 void DefaultToolGeometryWidget::slotUpdateOpacitySlider()
0300 {
0301     if (!isVisible()) return;
0302 
0303     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0304     QList<KoShape*> shapes = selection->selectedEditableShapes();
0305 
0306     dblOpacity->setSelection(shapes);
0307 }
0308 
0309 void DefaultToolGeometryWidget::slotPaintOrderChanged()
0310 {
0311     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0312     QList<KoShape*> shapes = selection->selectedEditableShapes();
0313     if (shapes.isEmpty()) return;
0314 
0315     KoShape::PaintOrder first = KoShape::Fill;
0316     KoShape::PaintOrder second = KoShape::Stroke;
0317 
0318     switch(cmbPaintOrder->currentIndex()) {
0319     case 1:
0320         first = KoShape::Fill;
0321         second = KoShape::Markers;
0322         break;
0323     case 2:
0324         first = KoShape::Stroke;
0325         second = KoShape::Fill;
0326         break;
0327     case 3:
0328         first = KoShape::Stroke;
0329         second = KoShape::Markers;
0330         break;
0331     case 4:
0332         first = KoShape::Markers;
0333         second = KoShape::Fill;
0334         break;
0335     case 5:
0336         first = KoShape::Markers;
0337         second = KoShape::Stroke;
0338         break;
0339     default:
0340         first = KoShape::Fill;
0341         second = KoShape::Stroke;
0342     }
0343 
0344     KUndo2Command *cmd =
0345         new KoShapePaintOrderCommand(shapes, first, second);
0346 
0347     m_tool->canvas()->addCommand(cmd);
0348 }
0349 
0350 void DefaultToolGeometryWidget::slotUpdatePaintOrder() {
0351     if (!isVisible()) return;
0352 
0353     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0354     QList<KoShape*> shapes = selection->selectedEditableShapes();
0355 
0356     if (!shapes.isEmpty()) {
0357         KoShape *shape = shapes.first();
0358         QVector<KoShape::PaintOrder> paintOrder = shape->paintOrder();
0359         int index = 0;
0360         if (paintOrder.first() == KoShape::Fill) {
0361             index = paintOrder.at(1) == KoShape::Stroke? 0: 1;
0362         } else if (paintOrder.first() == KoShape::Stroke) {
0363             index = paintOrder.at(1) == KoShape::Fill? 2: 3;
0364         } else {
0365             index = paintOrder.at(1) == KoShape::Fill? 4: 5;
0366         }
0367         cmbPaintOrder->setCurrentIndex(index);
0368     }
0369 }
0370 
0371 void DefaultToolGeometryWidget::slotUpdateSizeBoxes(bool updateAspect)
0372 {
0373     if (!isVisible()) return;
0374 
0375     const bool useGlobalSize = chkGlobalCoordinates->isChecked();
0376     const KoFlake::AnchorPosition anchor = positionSelector->value();
0377 
0378     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0379     const QRectF bounds = calculateSelectionBounds(selection, anchor, useGlobalSize);
0380 
0381     const bool hasSizeConfiguration = !bounds.isNull();
0382 
0383     widthSpinBox->setEnabled(hasSizeConfiguration && bounds.width() > 0);
0384     heightSpinBox->setEnabled(hasSizeConfiguration && bounds.height() > 0);
0385 
0386     if (hasSizeConfiguration) {
0387         KisSignalsBlocker b(widthSpinBox, heightSpinBox);
0388         widthSpinBox->changeValue(bounds.width());
0389         heightSpinBox->changeValue(bounds.height());
0390 
0391         if (updateAspect) {
0392             m_sizeAspectLocker->updateAspect();
0393         }
0394     }
0395 }
0396 
0397 void DefaultToolGeometryWidget::slotUpdateSizeBoxesNoAspectChange()
0398 {
0399     slotUpdateSizeBoxes(false);
0400 }
0401 
0402 void DefaultToolGeometryWidget::slotUpdatePositionBoxes()
0403 {
0404     if (!isVisible()) return;
0405 
0406     const bool useGlobalSize = chkGlobalCoordinates->isChecked();
0407     const KoFlake::AnchorPosition anchor = positionSelector->value();
0408 
0409     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0410     QRectF bounds = calculateSelectionBounds(selection, anchor, useGlobalSize);
0411 
0412     const bool hasSizeConfiguration = !bounds.isNull();
0413 
0414     positionXSpinBox->setEnabled(hasSizeConfiguration);
0415     positionYSpinBox->setEnabled(hasSizeConfiguration);
0416 
0417     if (hasSizeConfiguration) {
0418         KisSignalsBlocker b(positionXSpinBox, positionYSpinBox);
0419         positionXSpinBox->changeValue(bounds.x());
0420         positionYSpinBox->changeValue(bounds.y());
0421     }
0422 }
0423 
0424 void DefaultToolGeometryWidget::slotRepositionShapes()
0425 {
0426     static const qreal eps = 1e-6;
0427 
0428     const bool useGlobalSize = chkGlobalCoordinates->isChecked();
0429     const KoFlake::AnchorPosition anchor = positionSelector->value();
0430 
0431     QList<KoShape*> shapes;
0432     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0433     QRectF bounds = calculateSelectionBounds(selection, anchor, useGlobalSize, &shapes);
0434 
0435     if (bounds.isNull()) return;
0436 
0437     const QPointF oldPosition = bounds.topLeft();
0438     const QPointF newPosition(positionXSpinBox->value(), positionYSpinBox->value());
0439     const QPointF diff = newPosition - oldPosition;
0440 
0441     if (diff.manhattanLength() < eps) return;
0442 
0443     QList<QPointF> oldPositions;
0444     QList<QPointF> newPositions;
0445 
0446     Q_FOREACH (KoShape *shape, shapes) {
0447         const QPointF oldShapePosition = shape->absolutePosition(anchor);
0448 
0449         oldPositions << shape->absolutePosition(anchor);
0450         newPositions << oldShapePosition + diff;
0451     }
0452 
0453     KUndo2Command *cmd = new KoShapeMoveCommand(shapes, oldPositions, newPositions, anchor);
0454     m_tool->canvas()->addCommand(cmd);
0455 }
0456 
0457 void DefaultToolGeometryWidget::slotResizeShapes()
0458 {
0459     static const qreal eps = 1e-4;
0460 
0461     const bool useGlobalSize = chkGlobalCoordinates->isChecked();
0462     const KoFlake::AnchorPosition anchor = positionSelector->value();
0463 
0464     QList<KoShape*> shapes;
0465     KoSelection *selection = m_tool->canvas()->selectedShapesProxy()->selection();
0466     QRectF bounds = calculateSelectionBounds(selection, anchor, useGlobalSize, &shapes);
0467 
0468     if (bounds.isNull()) return;
0469 
0470     const QSizeF oldSize(bounds.size());
0471 
0472     QSizeF newSize(widthSpinBox->value(), heightSpinBox->value());
0473     newSize = KisAlgebra2D::ensureSizeNotSmaller(newSize, QSizeF(eps, eps));
0474 
0475     const qreal scaleX = oldSize.width() > 0 ? newSize.width() / oldSize.width() : 1.0;
0476     const qreal scaleY = oldSize.height() > 0 ? newSize.height() / oldSize.height() : 1.0;
0477 
0478     if (qAbs(scaleX - 1.0) < eps && qAbs(scaleY - 1.0) < eps) return;
0479 
0480     const bool usePostScaling =
0481         shapes.size() > 1 || chkUniformScaling->isChecked();
0482 
0483     KUndo2Command *cmd = new KoShapeResizeCommand(shapes,
0484                                                   scaleX, scaleY,
0485                                                   bounds.topLeft(),
0486                                                   useGlobalSize,
0487                                                   usePostScaling,
0488                                                   selection->transformation());
0489     m_tool->canvas()->addCommand(cmd);
0490 }
0491 
0492 void DefaultToolGeometryWidget::setUnit(const KoUnit &unit)
0493 {
0494     positionXSpinBox->setUnit(unit);
0495     positionYSpinBox->setUnit(unit);
0496     widthSpinBox->setUnit(unit);
0497     heightSpinBox->setUnit(unit);
0498 
0499     positionXSpinBox->setDecimals(2);
0500     positionYSpinBox->setDecimals(2);
0501     widthSpinBox->setDecimals(2);
0502     heightSpinBox->setDecimals(2);
0503 
0504     positionXSpinBox->setLineStep(1.0);
0505     positionYSpinBox->setLineStep(1.0);
0506     widthSpinBox->setLineStep(1.0);
0507     heightSpinBox->setLineStep(1.0);
0508 
0509     slotUpdatePositionBoxes();
0510     slotUpdateSizeBoxes();
0511 }
0512 
0513 bool DefaultToolGeometryWidget::useUniformScaling() const
0514 {
0515     return chkUniformScaling->isChecked();
0516 }
0517 
0518 void DefaultToolGeometryWidget::showEvent(QShowEvent *event)
0519 {
0520     QWidget::showEvent(event);
0521 
0522     slotUpdatePositionBoxes();
0523     slotUpdateSizeBoxes();
0524     slotUpdateOpacitySlider();
0525     slotUpdateAspectButton();
0526     slotUpdateCheckboxes();
0527     slotAnchorPointChanged();
0528     slotUpdatePaintOrder();
0529 }
0530 
0531 void DefaultToolGeometryWidget::resourceChanged(int key, const QVariant &res)
0532 {
0533     if (key == KoCanvasResource::Unit) {
0534         setUnit(res.value<KoUnit>());
0535     } else if (key == DefaultTool::HotPosition) {
0536         positionSelector->setValue(KoFlake::AnchorPosition(res.toInt()));
0537     }
0538 }