File indexing completed on 2024-05-12 15:56:49
0001 /* This file is part of the KDE project 0002 0003 SPDX-FileCopyrightText: 2006-2008 Thorsten Zachmann <zachmann@kde.org> 0004 SPDX-FileCopyrightText: 2007, 2009 Thomas Zander <zander@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KOSHAPEMANAGER_H 0010 #define KOSHAPEMANAGER_H 0011 0012 #include <QList> 0013 #include <QObject> 0014 #include <QSet> 0015 #include <QRect> 0016 0017 #include "KoFlake.h" 0018 #include "kritaflake_export.h" 0019 0020 #include <memory> 0021 #include <vector> 0022 0023 class KoShape; 0024 class KoSelection; 0025 class KoViewConverter; 0026 class KoCanvasBase; 0027 class KoPointerEvent; 0028 0029 class QPainter; 0030 class QPointF; 0031 class QRectF; 0032 0033 /** 0034 * The shape manager hold a list of all shape which are in scope. 0035 * There is one shape manager per canvas. This makes the shape manager 0036 * different from QGraphicsScene, which contains the datamodel for all 0037 * graphics items: KoShapeManager only contains the subset of shapes 0038 * that are shown in its canvas. 0039 * 0040 * The selection in the different views can be different. 0041 */ 0042 class KRITAFLAKE_EXPORT KoShapeManager : public QObject 0043 { 0044 Q_OBJECT 0045 0046 public: 0047 /// enum for add() 0048 enum Repaint { 0049 PaintShapeOnAdd, ///< Causes each shapes 'update()' to be called after being added to the shapeManager 0050 AddWithoutRepaint ///< Avoids each shapes 'update()' to be called for faster addition when its possible. 0051 }; 0052 0053 /** 0054 * Constructor. 0055 */ 0056 explicit KoShapeManager(KoCanvasBase *canvas); 0057 /** 0058 * Constructor that takes a list of shapes, convenience version. 0059 * @param shapes the shapes to start out with, see also setShapes() 0060 * @param canvas the canvas this shape manager is working on. 0061 */ 0062 KoShapeManager(KoCanvasBase *canvas, const QList<KoShape *> &shapes); 0063 ~KoShapeManager() override; 0064 0065 0066 /** 0067 * Remove all previously owned shapes and make the argument list the new shapes 0068 * to be managed by this manager. 0069 * @param shapes the new shapes to manage. 0070 * @param repaint if true it will trigger a repaint of the shapes 0071 */ 0072 void setShapes(const QList<KoShape *> &shapes, Repaint repaint = PaintShapeOnAdd); 0073 0074 /// returns the list of maintained shapes 0075 QList<KoShape*> shapes() const; 0076 0077 /** 0078 * Get a list of all shapes that don't have a parent. 0079 */ 0080 QList<KoShape*> topLevelShapes() const; 0081 0082 public Q_SLOTS: 0083 /** 0084 * Add a KoShape to be displayed and managed by this manager. 0085 * This will trigger a repaint of the shape. 0086 * @param shape the shape to add 0087 * @param repaint if true it will trigger a repaint of the shape 0088 */ 0089 void addShape(KoShape *shape, KoShapeManager::Repaint repaint = PaintShapeOnAdd); 0090 0091 0092 /** 0093 * Remove a KoShape from this manager 0094 * @param shape the shape to remove 0095 */ 0096 void remove(KoShape *shape); 0097 0098 public: 0099 /// return the selection shapes for this shapeManager 0100 KoSelection *selection() const; 0101 0102 struct PaintJob { 0103 using ShapesStorage = std::vector<std::unique_ptr<KoShape>>; 0104 using SharedSafeStorage = std::shared_ptr<ShapesStorage>; 0105 0106 PaintJob() = default; 0107 PaintJob(QRectF _docUpdateRect, QRect _viewUpdateRect) 0108 : docUpdateRect(_docUpdateRect), 0109 viewUpdateRect(_viewUpdateRect) 0110 { 0111 } 0112 0113 bool isEmpty() const { 0114 return shapes.isEmpty(); 0115 } 0116 0117 QRectF docUpdateRect; 0118 QRect viewUpdateRect; 0119 0120 QList<KoShape*> shapes; 0121 SharedSafeStorage allClonedShapes; 0122 }; 0123 0124 struct PaintJobsOrder 0125 { 0126 QRect uncroppedViewUpdateRect; 0127 QList<PaintJob> jobs; 0128 0129 inline void clear() { 0130 jobs.clear(); 0131 uncroppedViewUpdateRect = QRect(); 0132 } 0133 0134 inline bool isEmpty() const { 0135 return jobs.isEmpty(); 0136 } 0137 }; 0138 0139 /** 0140 * The update signals are usually emitted when the owned of the manager 0141 * calls to preparePaintJobs() in the beginning of the rendering cycle. 0142 * This way we avoid too many signals to be emitted. But some of the 0143 * canvases (e.g. KisShapeSelectionCanvas) doesn't do any rendering (yet?), 0144 * so the signals should be emitted explicitly. 0145 */ 0146 void explicitlyIssueShapeChangedSignals(); 0147 0148 /** 0149 * Prepare a shallow copy of all the shapes and the jobs to be rendered 0150 * asynchronoursly later. The copies are stored in jobs, so that the user 0151 * could later pass these jobs into paintJob() in a separate thread. 0152 * 0153 * @param jobs a list of rects that are going to be updated. docUpdateRect 0154 * and viewUpdateRect should be preinitialized by the caller. 0155 * @param excludeRoot the root shape which should not be copied. It is basically 0156 * a hack to avoid copying of KisShapeLayer, which is not 0157 * copiable. 0158 * \see paintJob() 0159 * \see a comment in KisShapeLayerCanvas::slotStartAsyncRepaint() 0160 */ 0161 void preparePaintJobs(PaintJobsOrder &jobsOrder, KoShape *excludeRoot); 0162 0163 /** 0164 * Render a \p job on \p painter. No mutable internals of the shape 0165 * manager are accessed, so calling this method is safe in multithreading 0166 * environment. 0167 * 0168 * @param painter a painter to paint on. Clip rect of the painter is expected to be setup correctly. 0169 * @param job a job to paint. 0170 * @param forPrint not used in Krita. 0171 * 0172 * \see preparePaintJobs 0173 */ 0174 void paintJob(QPainter &painter, const KoShapeManager::PaintJob &job); 0175 0176 /** 0177 * Paint all shapes and their selection handles etc. 0178 * @param painter the painter to paint to. 0179 * @param forPrint if true, make sure only actual content is drawn and no decorations. 0180 * @param converter to convert between document and view coordinates. 0181 */ 0182 void paint(QPainter &painter); 0183 0184 /** 0185 * Returns the shape located at a specific point in the document. 0186 * If more than one shape is located at the specific point, the given selection type 0187 * controls which of them is returned. 0188 * @param position the position in the document coordinate system. 0189 * @param selection controls which shape is returned when more than one shape is at the specific point 0190 * @param omitHiddenShapes if true, only visible shapes are considered 0191 */ 0192 KoShape *shapeAt(const QPointF &position, KoFlake::ShapeSelection selection = KoFlake::ShapeOnTop, bool omitHiddenShapes = true); 0193 0194 /** 0195 * Returns the shapes which intersects the specific rect in the document. 0196 * @param rect the rectangle in the document coordinate system. 0197 * @param omitHiddenShapes if @c true, only visible shapes are considered 0198 * @param containedMode if @c true use contained mode 0199 */ 0200 QList<KoShape *> shapesAt(const QRectF &rect, bool omitHiddenShapes = true, bool containedMode = false); 0201 0202 /** 0203 * Request a repaint to be queued. 0204 * The repaint will be restricted to the parameters rectangle, which is expected to be 0205 * in points (the document coordinates system of KoShape) and it is expected to be 0206 * normalized and based in the global coordinates, not any local coordinates. 0207 * <p>This method will return immediately and only request a repaint. Successive calls 0208 * will be merged into an appropriate repaint action. 0209 * @param rect the rectangle (in pt) to queue for repaint. 0210 * @param shape the shape that is going to be redrawn; only needed when selectionHandles=true 0211 * @param selectionHandles if true; find out if the shape is selected and repaint its 0212 * selection handles at the same time. 0213 */ 0214 void update(const QRectF &rect, const KoShape *shape = 0, bool selectionHandles = false); 0215 0216 /** 0217 * Block all updates initiated with update() call. The incoming updates will 0218 * be dropped completely. 0219 */ 0220 void setUpdatesBlocked(bool value); 0221 0222 /** 0223 * \see setUpdatesBlocked() 0224 */ 0225 bool updatesBlocked() const; 0226 0227 /** 0228 * Update the tree for finding the shapes. 0229 * This will remove the shape from the tree and will reinsert it again. 0230 * The update to the tree will be posponed until it is needed so that successive calls 0231 * will be merged into one. 0232 * @param shape the shape to updated its position in the tree. 0233 */ 0234 void notifyShapeChanged(KoShape *shape); 0235 0236 /** 0237 * @brief renderSingleShape renders a shape on \p painter. This method includes all the 0238 * needed steps for painting a single shape: setting transformations, clipping and masking. 0239 */ 0240 static void renderSingleShape(KoShape *shape, QPainter &painter); 0241 0242 /** 0243 * A special interface for KoShape to use during shape destruction. Don't use this 0244 * interface directly unless you are KoShape. 0245 */ 0246 struct ShapeInterface { 0247 ShapeInterface(KoShapeManager *_q); 0248 0249 /** 0250 * Called by a shape when it is destructed. Please note that you cannot access 0251 * any shape's method type or information during this call because the shape might be 0252 * semi-destroyed. 0253 */ 0254 void notifyShapeDestructed(KoShape *shape); 0255 0256 protected: 0257 KoShapeManager *q; 0258 }; 0259 0260 ShapeInterface* shapeInterface(); 0261 0262 Q_SIGNALS: 0263 /// emitted when the selection is changed 0264 void selectionChanged(); 0265 /// emitted when an object in the selection is changed (moved/rotated etc) 0266 void selectionContentChanged(); 0267 /// emitted when any object changed (moved/rotated etc) 0268 void contentChanged(); 0269 0270 private: 0271 KoCanvasBase *canvas(); 0272 0273 0274 class Private; 0275 Private * const d; 0276 Q_PRIVATE_SLOT(d, void updateTree()) 0277 Q_PRIVATE_SLOT(d, void forwardCompressedUdpate()) 0278 }; 0279 0280 #endif