File indexing completed on 2024-05-19 04:26:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include "Shape.h"
0007 #include <kis_icon_utils.h>
0008 #include <SvgWriter.h>
0009 #include <SvgParser.h>
0010 #include <SvgSavingContext.h>
0011 #include <QBuffer>
0012 #include <KoDocumentResourceManager.h>
0013 #include <kis_processing_applicator.h>
0014 #include <KisPart.h>
0015 #include <KisView.h>
0016 #include <KisDocument.h>
0017 #include <kis_canvas2.h>
0018 #include <KisMainWindow.h>
0019 #include <KoShapeController.h>
0020 #include <KoSelection.h>
0021 
0022 #include "Krita.h"
0023 #include "Document.h"
0024 #include "GroupShape.h"
0025 
0026 struct Shape::Private {
0027     Private() {}
0028     KoShape *shape {0};
0029 };
0030 
0031 Shape::Shape(KoShape *shape, QObject *parent)
0032     : QObject(parent)
0033     , d(new Private)
0034 {
0035     d->shape = shape;
0036 }
0037 
0038 Shape::~Shape()
0039 {
0040     delete d;
0041 }
0042 
0043 bool Shape::operator==(const Shape &other) const
0044 {
0045     return (d->shape == other.d->shape);
0046 }
0047 
0048 bool Shape::operator!=(const Shape &other) const
0049 {
0050     return !(operator==(other));
0051 }
0052 
0053 QString Shape::name() const
0054 {
0055     return d->shape->name();
0056 }
0057 
0058 void Shape::setName(const QString &name)
0059 {
0060     d->shape->setName(name);
0061 }
0062 
0063 QString Shape::type() const
0064 {
0065     return d->shape->shapeId();
0066 }
0067 
0068 int Shape::zIndex() const
0069 {
0070     return d->shape->zIndex();
0071 }
0072 
0073 void Shape::setZIndex(int zindex)
0074 {
0075     d->shape->setZIndex(zindex);
0076 }
0077 
0078 bool Shape::selectable() const
0079 {
0080     return d->shape->isSelectable();
0081 }
0082 
0083 void Shape::setSelectable(bool selectable)
0084 {
0085     d->shape->setSelectable(selectable);
0086 }
0087 
0088 bool Shape::geometryProtected() const
0089 {
0090     return d->shape->isGeometryProtected();
0091 }
0092 
0093 void Shape::setGeometryProtected(bool protect)
0094 {
0095     d->shape->setGeometryProtected(protect);
0096 }
0097 
0098 bool Shape::visible() const
0099 {
0100     return d->shape->isVisible();
0101 }
0102 
0103 void Shape::setVisible(bool visible)
0104 {
0105     d->shape->setVisible(visible);
0106 }
0107 
0108 QRectF Shape::boundingBox() const
0109 {
0110     return d->shape->boundingRect();
0111 }
0112 
0113 QPointF Shape::position() const
0114 {
0115     return d->shape->position();
0116 }
0117 
0118 void Shape::setPosition(QPointF point)
0119 {
0120     d->shape->setPosition(point);
0121 }
0122 
0123 QTransform Shape::transformation() const
0124 {
0125     return d->shape->transformation();
0126 }
0127 
0128 void Shape::setTransformation(QTransform matrix)
0129 {
0130     d->shape->setTransformation(matrix);
0131 }
0132 
0133 QTransform Shape::absoluteTransformation() const
0134 {
0135     return d->shape->absoluteTransformation();
0136 }
0137 
0138 void Shape::update()
0139 {
0140     return d->shape->update();
0141 }
0142 
0143 void Shape::updateAbsolute(QRectF box)
0144 {
0145     return d->shape->updateAbsolute(box);
0146 }
0147 
0148 bool Shape::remove()
0149 {
0150     if (!d->shape) return false;
0151     if (!d->shape->parent()) return false;
0152 
0153     bool removeStatus = false;
0154     Document *document = Krita::instance()->activeDocument();
0155 
0156     if (KisPart::instance()->viewCount(document->document()) > 0) {
0157         for (QPointer<KisView> view : KisPart::instance()->views()) {
0158             if (view && view->document() == document->document()) {
0159                 KisProcessingApplicator::runSingleCommandStroke(view->image(), view->canvasBase()->shapeController()->removeShape(d->shape));
0160                 view->image()->waitForDone();
0161                 removeStatus = true;
0162                 break;
0163             }
0164         }
0165     }
0166 
0167     delete document;
0168 
0169     return removeStatus;
0170 }
0171 
0172 QString Shape::toSvg(bool prependStyles, bool stripTextMode)
0173 {
0174     QBuffer shapesBuffer;
0175     QBuffer stylesBuffer;
0176 
0177     shapesBuffer.open(QIODevice::WriteOnly);
0178     stylesBuffer.open(QIODevice::WriteOnly);
0179 
0180     {
0181         SvgSavingContext savingContext(shapesBuffer, stylesBuffer);
0182         savingContext.setStrippedTextMode(stripTextMode);
0183         SvgWriter writer({d->shape});
0184         writer.saveDetached(savingContext);
0185     }
0186 
0187     shapesBuffer.close();
0188     stylesBuffer.close();
0189 
0190     return (prependStyles ? QString::fromUtf8(stylesBuffer.data()):"") + QString::fromUtf8(shapesBuffer.data());
0191 }
0192 
0193 void Shape::select()
0194 {
0195     if (!d->shape) return;
0196 
0197     KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
0198     KoSelection *selection = activeView->canvasBase()->shapeManager()->selection();
0199 
0200     selection->select(d->shape);
0201 }
0202 
0203 void Shape::deselect()
0204 {
0205     if (!d->shape) return;
0206 
0207     KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
0208     KoSelection *selection = activeView->canvasBase()->shapeManager()->selection();
0209 
0210     selection->deselect(d->shape);
0211 }
0212 
0213 bool Shape::isSelected()
0214 {
0215     if (!d->shape) return false;
0216 
0217     KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
0218     KoSelection *selection = activeView->canvasBase()->shapeManager()->selection();
0219 
0220     return selection->isSelected(d->shape);
0221 }
0222 
0223 Shape* Shape::parentShape() const
0224 {
0225     if (!d->shape) return 0;
0226     if (!d->shape->parent()) return 0;
0227 
0228     if (dynamic_cast<KoShapeGroup*>(d->shape->parent())) {
0229         return new GroupShape(dynamic_cast<KoShapeGroup*>(d->shape->parent()));
0230     } else {
0231         return 0;
0232     }
0233 }
0234 
0235 
0236 KoShape *Shape::shape()
0237 {
0238     return d->shape;
0239 }