File indexing completed on 2024-10-27 04:07:34

0001 /*
0002  *  SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_shape_selection_model.h"
0008 #include "kis_debug.h"
0009 
0010 #include <KoShapeContainer.h>
0011 #include <KoShapeBackground.h>
0012 #include <KoShapeManager.h>
0013 
0014 #include "kis_shape_selection.h"
0015 #include "kis_selection.h"
0016 #include "kis_image.h"
0017 #include "kis_update_selection_job.h"
0018 
0019 
0020 KisShapeSelectionModel::KisShapeSelectionModel(KisImageResolutionProxySP resolutionProxy, KisSelectionWSP selection, KisShapeSelection* shapeSelection)
0021     : m_resolutionProxy(resolutionProxy)
0022     , m_parentSelection(selection)
0023     , m_shapeSelection(shapeSelection)
0024     , m_updatesEnabled(true)
0025 {
0026 }
0027 
0028 KisShapeSelectionModel::~KisShapeSelectionModel()
0029 {
0030     m_parentSelection = 0;
0031 }
0032 
0033 void KisShapeSelectionModel::requestUpdate(const QRect &updateRect)
0034 {
0035     m_shapeSelection->recalculateOutlineCache();
0036 
0037     if (m_updatesEnabled) {
0038         m_parentSelection->requestCompressedProjectionUpdate(updateRect);
0039     }
0040 }
0041 
0042 void KisShapeSelectionModel::setResolutionProxy(KisImageResolutionProxySP newResolutionProxy)
0043 {
0044     const bool resolutionChanged = !m_resolutionProxy->compareResolution(*newResolutionProxy);
0045 
0046     m_resolutionProxy = newResolutionProxy;
0047 
0048     if (resolutionChanged) {
0049         requestUpdate(QRect());
0050     }
0051 }
0052 
0053 KisImageResolutionProxySP KisShapeSelectionModel::resolutionProxy() const
0054 {
0055     return m_resolutionProxy;
0056 }
0057 
0058 void KisShapeSelectionModel::add(KoShape *child)
0059 {
0060     if (!m_shapeSelection) return;
0061 
0062     if (m_shapeMap.contains(child))
0063         return;
0064 
0065     child->setStroke(KoShapeStrokeModelSP());
0066     child->setBackground( QSharedPointer<KoShapeBackground>(0));
0067     m_shapeMap.insert(child, child->boundingRect());
0068     m_shapeSelection->shapeManager()->addShape(child);
0069 
0070     QRect updateRect = child->boundingRect().toAlignedRect();
0071     QTransform matrix;
0072     matrix.scale(m_resolutionProxy->xRes(), m_resolutionProxy->yRes());
0073     updateRect = matrix.mapRect(updateRect);
0074 
0075     if (m_shapeMap.count() == 1) {
0076         // The shape is the first one, so the shape selection just got created
0077         // Pixel selection provides no longer the datamanager of the selection
0078         // so update the whole selection
0079         requestUpdate(QRect());
0080     } else {
0081         requestUpdate(updateRect);
0082     }
0083 }
0084 
0085 void KisShapeSelectionModel::remove(KoShape *child)
0086 {
0087     if (!m_shapeMap.contains(child)) return;
0088 
0089     QRect updateRect = child->boundingRect().toAlignedRect();
0090     m_shapeMap.remove(child);
0091 
0092     if (m_shapeSelection) {
0093         m_shapeSelection->shapeManager()->remove(child);
0094     }
0095     QTransform matrix;
0096     matrix.scale(m_resolutionProxy->xRes(), m_resolutionProxy->yRes());
0097     updateRect = matrix.mapRect(updateRect);
0098     if (m_shapeSelection) { // No m_shapeSelection indicates the selection is being deleted
0099         requestUpdate(updateRect);
0100     }
0101 }
0102 
0103 void KisShapeSelectionModel::setUpdatesEnabled(bool enabled)
0104 {
0105     m_updatesEnabled = enabled;
0106 }
0107 
0108 bool KisShapeSelectionModel::updatesEnabled() const
0109 {
0110     return m_updatesEnabled;
0111 }
0112 
0113 void KisShapeSelectionModel::setClipped(const KoShape *child, bool clipping)
0114 {
0115     Q_UNUSED(child);
0116     Q_UNUSED(clipping);
0117 }
0118 
0119 bool KisShapeSelectionModel::isClipped(const KoShape *child) const
0120 {
0121     Q_UNUSED(child);
0122     return false;
0123 }
0124 
0125 void KisShapeSelectionModel::setInheritsTransform(const KoShape *shape, bool inherit)
0126 {
0127     Q_UNUSED(shape);
0128     Q_UNUSED(inherit);
0129 }
0130 
0131 bool KisShapeSelectionModel::inheritsTransform(const KoShape *shape) const
0132 {
0133     Q_UNUSED(shape);
0134     return false;
0135 }
0136 
0137 int KisShapeSelectionModel::count() const
0138 {
0139     return m_shapeMap.count();
0140 }
0141 
0142 QList<KoShape*> KisShapeSelectionModel::shapes() const
0143 {
0144     return QList<KoShape*>(m_shapeMap.keys());
0145 }
0146 void KisShapeSelectionModel::containerChanged(KoShapeContainer *, KoShape::ChangeType)
0147 {
0148 }
0149 
0150 void KisShapeSelectionModel::childChanged(KoShape * child, KoShape::ChangeType type)
0151 {
0152     if (!m_shapeSelection) return;
0153 
0154     // TODO: check if still needed
0155     if (type == KoShape::ParentChanged) return;
0156 
0157     QRectF changedRect = m_shapeMap[child];
0158     changedRect = changedRect.united(child->boundingRect());
0159     m_shapeMap[child] = child->boundingRect();
0160 
0161     QTransform matrix;
0162     matrix.scale(m_resolutionProxy->xRes(), m_resolutionProxy->yRes());
0163     changedRect = matrix.mapRect(changedRect);
0164 
0165     requestUpdate(changedRect.toAlignedRect());
0166 }
0167 
0168 void KisShapeSelectionModel::setShapeSelection(KisShapeSelection* selection)
0169 {
0170     m_shapeSelection = selection;
0171 }