Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

KoShape.h 40.7 KB
Newer Older
Thomas Zander's avatar
Thomas Zander committed
1
/* This file is part of the KDE project
2
   Copyright (C) 2006-2008 Thorsten Zachmann <zachmann@kde.org>
3
   Copyright (C) 2006, 2008 Casper Boemann <cbr@boemann.dk>
4
   Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
5
   Copyright (C) 2007-2009,2011 Jan Hambrecht <jaham@gmx.net>
Thomas Zander's avatar
Thomas Zander committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

Thomas Zander's avatar
Thomas Zander committed
23 24
#ifndef KOSHAPE_H
#define KOSHAPE_H
Thomas Zander's avatar
Thomas Zander committed
25

26
#include "KoInsets.h"
27
#include "KoFlake.h"
28

29
#include <QTransform>
Thomas Zander's avatar
Thomas Zander committed
30
#include <QVector>
31
#include <QSet>
32
#include <QMap>
Thomas Zander's avatar
Thomas Zander committed
33
#include <QBrush>
34
#include <QMetaType>
Thomas Zander's avatar
Thomas Zander committed
35

36
#include <KoXmlReaderForward.h>
37
//#include <KoSnapData.h>
38

39 40
#include "flake_export.h"

Thomas Zander's avatar
Thomas Zander committed
41 42 43 44 45 46
class QPainter;
class QRectF;
class QPainterPath;

class KoShapeContainer;
class KoShapeBorderModel;
47
class KoShapeBackground;
48
class KoShapeManager;
49
class KoShapeUserData;
50
class KoViewConverter;
51
class KoShapeApplicationData;
52
class KoShapeSavingContext;
53
class KoCanvasBase;
54
class KoShapeLoadingContext;
55
class KoGenStyle;
56
class KoShapeControllerBase;
57
class KoDataCenterBase;
58
class KoShapeShadow;
59
class KoEventAction;
60
class KoShapePrivate;
61
class KoFilterEffectStack;
62
class KoSnapData;
Thomas Zander's avatar
Thomas Zander committed
63

64 65 66
/// Connection point container with id, position
typedef QMap<int, QPointF> KoConnectionPoints;

Thomas Zander's avatar
Thomas Zander committed
67
/**
68
 *
69
 * Base class for all flake shapes. Shapes extend this class
Thomas Zander's avatar
Thomas Zander committed
70 71 72
 * to allow themselves to be manipulated. This class just represents
 * a graphical shape in the document and can be manipulated by some default
 * tools in this library.
73
 *
74
 * Due to the limited responsibility of this class, the extending object
Thomas Zander's avatar
Thomas Zander committed
75
 * can have any data backend and is responsible for painting itself.
76
 *
77
 * We strongly suggest that any extending class will use a Model View
Thomas Zander's avatar
Thomas Zander committed
78
 * Controller (MVC) design where the View part is all in this class, as well
79
 * as the one that inherits from this one.  This allows the data that rests
Thomas Zander's avatar
Thomas Zander committed
80
 * in the model to be reused in different parts of the document. For example
81
 * by having two flake objects that show that same data. Or each showing a section of it.
82
 *
83 84 85 86 87
 * The KoShape data is completely in postscript-points (pt) (see KoUnit
 * for conversion methods to and from points).
 * This image will explain the real-world use of the shape and its options.
 * <img src="../flake_shape_coords.png" align=center><br>
 *  The Rotation center can be returned with absolutePosition()
88
 *
89
 * <p>Flake objects can be created in three ways:
90 91 92 93 94
 * <ul>
 *   <li>a simple new KoDerivedFlake(),
 *   <li>through an associated tool,
 *   <li>through a factory
 * </ul>
95
 *
Thomas Zander's avatar
Thomas Zander committed
96 97 98 99 100 101 102 103 104 105 106 107 108
 * <h1>Shape interaction notifications</h1>
 * We had several notification methods that allow your shape to be notified of changes in other
 * shapes positions or rotation etc.
 * <ol><li>The most general is KoShape::shapeChanged().<br>
 * a virtual method that you can use to check various changed to your shape made by tools or otherwise.</li>
 * <li>for shape hierarchies the parent may receive a notification when a child was modified.
 *  This is done though KoShapeContainerModel::childChanged()</li>
 * <li>any shape that is at a similar position as another shape there is collision detection.
 * You can register your shape to be sensitive to any changes like moving or whatever to
 * <b>other</b> shapes that intersect yours.
 * Such changes will then be notified to your shape using the method from (1) You should call
 * KoShape::setCollisionDetection(bool) to enable this.
 * </ol>
Thomas Zander's avatar
Thomas Zander committed
109
 */
110
class FLAKE_EXPORT KoShape
Thomas Zander's avatar
Thomas Zander committed
111 112
{
public:
113 114 115
    /// Used by shapeChanged() to select which change was made
    enum ChangeType {
        PositionChanged, ///< used after a setPosition()
116
        RotationChanged, ///< used after a setRotation()
Thomas Zander's avatar
Thomas Zander committed
117
        ScaleChanged,   ///< used after a scale()
Thomas Zander's avatar
Thomas Zander committed
118
        ShearChanged,   ///< used after a shear()
119
        SizeChanged,    ///< used after a setSize()
120
        GenericMatrixChange,    ///< used after the matrix was changed without knowing which property explicitly changed
121
        ParentChanged,   ///< used after a setParent()
122
        CollisionDetected, ///< used when another shape moved in our boundingrect
123 124
        Deleted, ///< the shape was deleted
        BorderChanged, ///< the shapes border has changed
125
        BackgroundChanged, ///< the shapes background has changed
126
        ShadowChanged, ///< the shapes shadow has changed
127 128
        ParameterChanged, ///< the shapes parameter has changed (KoParameterShape only)
        ContentChanged, ///< the content of the shape changed e.g. a new image inside a pixmap/text change inside a textshape
129
        TextRunAroundChanged, ///< used after a setTextRunAroundSide()
Jan Hambrecht's avatar
Jan Hambrecht committed
130 131
        ChildChanged, ///< a child of a container was changed/removed. This is propagated to all parents
        ConnectionPointChanged ///< a connection point has changed
132 133
    };

Boudewijn Rempt's avatar
Boudewijn Rempt committed
134 135 136 137 138 139
    /// See QGraphicsItem::CacheMode
    enum CacheMode {
        NoCache, ///< no cache -- the default
        ScaledCache, ///< cache at every zoomlevel
    };

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    /// The behavior text should do when intersecting this shape.
    enum TextRunAroundSide {
        BiggestRunAroundSide,   ///< Run other text around the side that has the most space
        LeftRunAroundSide,      ///< Run other text around the left side of the frame
        RightRunAroundSide,     ///< Run other text around the right side of the frame
        AutoRunAroundSide,      ///< Run other text dynamically around both sides of the shape, provided there is sufficient space left
        BothRunAroundSide,      ///< Run other text around both sides of the shape
        NoRunAround,            ///< The text will be completely avoiding the frame by keeping the horizontal space that this frame occupies blank.
        RunThrough              ///< The text will completely ignore the frame and layout as if it was not there
    };

    /**
     * TODO
     */
    enum Through {
        Background,
        Foreground
    };

Thomas Zander's avatar
Thomas Zander committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172
    /**
     * @brief Constructor
     */
    KoShape();

    /**
     * @brief Destructor
     */
    virtual ~KoShape();

    /**
     * @brief Paint the shape
     * The class extending this one is responsible for painting itself.  Since we do not
     * assume the shape is square the paint must also clear its background if it will draw
173
     * something transparent on top.
Thomas Zander's avatar
Thomas Zander committed
174 175 176 177
     * This can be done with a method like:
     * <code>
       painter.fillRect(converter.normalToView(QRectF(QPointF(0.0,0.0), size())), background());</code>
     * Or equavalent for non-square objects.
178 179
     * Do note that a shape's top-left is always at coordinate 0,0. Even if the shape itself is rotated
     * or translated.
Thomas Zander's avatar
Thomas Zander committed
180 181 182 183
     * @param painter used for painting the shape
     * @param converter to convert between internal and view coordinates.
     * @see applyConversion()
     */
184
    virtual void paint(QPainter &painter, const KoViewConverter &converter) = 0;
Thomas Zander's avatar
Thomas Zander committed
185 186 187 188 189 190 191

    /**
     * Paint non-print decorations specific for this type of shape.
     * The default implementation is empty.
     *
     * @param painter used for painting the shape
     * @param converter to convert between internal and view coordinates.
Thomas Zander's avatar
Thomas Zander committed
192
     * @param canvas the canvas that requested this paint.  This can be used to retrieve canvas specific properties
193
     *      like selection and get a reference to the KoResourceManager.
Thomas Zander's avatar
Thomas Zander committed
194
     */
195
    virtual void paintDecorations(QPainter &painter, const KoViewConverter &converter, const KoCanvasBase *canvas);
Thomas Zander's avatar
Thomas Zander committed
196

197 198 199 200 201 202
    /**
     * Load a shape from odf
     *
     * @param context the KoShapeLoadingContext used for loading
     * @param element element which represents the shape in odf
     *
203
     * @return false if loading failed
204
     */
205
    virtual bool loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context) = 0;
206

207
    /**
208
     * @brief store the shape data as ODF XML.
Thomas Zander's avatar
fix dox  
Thomas Zander committed
209
     * This is the method that will be called when saving a shape as a described in
210
     * OpenDocument 9.2 Drawing Shapes.
Thorsten Zachmann's avatar
Thorsten Zachmann committed
211
     * @see saveOdfAttributes
212
     */
213
    virtual void saveOdf(KoShapeSavingContext &context) const = 0;
214 215

    /**
216 217 218 219 220 221
     * This method can be used while saving the shape as ODF to add the data
     * stored on this shape to the current element.
     *
     * @param context the context for the current save.
     * @param attributes a number of OdfAttribute items to state which attributes to save.
     * @see saveOdf
222
     */
223
    void saveOdfAttributes(KoShapeSavingContext &context, int attributes) const;
224

Thorsten Zachmann's avatar
Thorsten Zachmann committed
225 226 227 228 229
    /**
     * This method can be used while saving the shape as Odf to add common child elements
     *
     * The office:event-listeners and draw:glue-point are saved.
     */
230
    void saveOdfCommonChildElements(KoShapeSavingContext &context) const;
Thorsten Zachmann's avatar
Thorsten Zachmann committed
231

Thomas Zander's avatar
Thomas Zander committed
232 233 234 235 236 237 238
    /**
     * @brief Scale the shape using the zero-point which is the top-left corner.
     * @see position()
     *
     * @param sx scale in x direction
     * @param sy scale in y direction
     */
Thomas Zander's avatar
Thomas Zander committed
239
    void scale(qreal sx, qreal sy);
Thomas Zander's avatar
Thomas Zander committed
240 241

    /**
242
     * @brief Rotate the shape (relative)
Thomas Zander's avatar
Thomas Zander committed
243
     *
244
     * The shape will be rotated from the current rotation using the center of the shape using the size()
Thomas Zander's avatar
Thomas Zander committed
245
     *
246
     * @param angle change the angle of rotation increasing it with 'angle' degrees
Thomas Zander's avatar
Thomas Zander committed
247
     */
248
    void rotate(qreal angle);
Thomas Zander's avatar
Thomas Zander committed
249 250 251

    /**
     * Return the current rotation in degrees.
252
     * It returns NaN if the shape has a shearing or scaling transformation applied.
Thomas Zander's avatar
Thomas Zander committed
253
     */
254
    qreal rotation() const;
Thomas Zander's avatar
Thomas Zander committed
255 256 257 258 259 260 261 262 263

    /**
     * @brief Shear the shape
     * The shape will be sheared using the zero-point which is the top-left corner.
     * @see position()
     *
     * @param sx shear in x direction
     * @param sy shear in y direction
     */
Thomas Zander's avatar
Thomas Zander committed
264
    void shear(qreal sx, qreal sy);
Thomas Zander's avatar
Thomas Zander committed
265 266 267 268

    /**
     * @brief Resize the shape
     *
269
     * @param size the new size of the shape.  This is different from scaling as
Jan Hambrecht's avatar
Jan Hambrecht committed
270
     * scaling is a so called secondary operation which is comparable to zooming in
Thomas Zander's avatar
Thomas Zander committed
271 272 273 274
     * instead of changing the size of the basic shape.
     * Easiest example of this difference is that using this method will not distort the
     * size of pattern-fills and borders.
     */
275
    virtual void setSize(const QSizeF &size);
Thomas Zander's avatar
Thomas Zander committed
276 277 278 279

    /**
     * @brief Get the size of the shape in pt.
     *
Thorsten Zachmann's avatar
Thorsten Zachmann committed
280 281
     * The size is in shape coordinates.
     *
Inge Wallin's avatar
Inge Wallin committed
282
     * @return the size of the shape as set by setSize()
Thomas Zander's avatar
Thomas Zander committed
283
     */
Thomas Zander's avatar
Thomas Zander committed
284
    virtual QSizeF size() const;
Thomas Zander's avatar
Thomas Zander committed
285 286 287 288 289 290

    /**
     * @brief Set the position of the shape in pt
     *
     * @param position the new position of the shape
     */
291
    virtual void setPosition(const QPointF &position);
Thomas Zander's avatar
Thomas Zander committed
292 293 294 295 296 297

    /**
     * @brief Get the position of the shape in pt
     *
     * @return the position of the shape
     */
298
    QPointF position() const;
Thomas Zander's avatar
Thomas Zander committed
299 300 301 302 303 304

    /**
     * @brief Check if the shape is hit on position
     * @param position the position where the user clicked.
     * @return true when it hits.
     */
305
    virtual bool hitTest(const QPointF &position) const;
Thomas Zander's avatar
Thomas Zander committed
306 307 308 309 310 311 312 313

    /**
     * @brief Get the bounding box of the shape
     *
     * This includes the line width but not the shadow of the shape
     *
     * @return the bounding box of the shape
     */
314
    virtual QRectF boundingRect() const;
Thomas Zander's avatar
Thomas Zander committed
315 316 317

    /**
     * @brief Add a connector point to the shape
318
     * 
Thomas Zander's avatar
Thomas Zander committed
319 320 321 322
     * A connector is a place on the shape that allows a graphical connection to be made
     * using a line, for example.
     *
     * @param point the position where to place the connector. The points coordinate system
323 324
     *   are based around the zero-pos which is the top-left of the shape. The position of
     *   the connector is restricted to the bounding rectangle of the shape. The point is in pt,
Thomas Zander's avatar
Thomas Zander committed
325
     *   just like the rest of the KoShape class uses.
326
     * @return the id of the new connection point
Thomas Zander's avatar
Thomas Zander committed
327
     */
328 329
    int addConnectionPoint(const QPointF &point);

330 331
    /**
     * Tries to insert connection point with specified id.
332 333 334
     *
     * The position of the connector is restricted to the bounding rectangle of the shape.
     * 
335 336 337 338 339 340 341
     * @param point the position of the connector in shape coordinates
     * @param connectionPointId the id of the connection point to insert
     * @return true if inserting connection point was successful;
     *         false if connection point did already exists or id is invalid
     */
    bool insertConnectionPoint(const QPointF &point, int connectionPointId);

342 343 344 345 346
    /// Checks if a connection point with the specified id exists
    bool hasConnectionPoint(int connectionPointId) const;

    /// Returns connection point with specified connection point id
    QPointF connectionPoint(int connectionPointId) const;
Thomas Zander's avatar
Thomas Zander committed
347

348 349
    /**
     * Sets new position for specified custom connection point
350 351 352
     *
     * The position of the connector is restricted to the bounding rectangle of the shape.
     *
353 354 355 356 357 358
     * @param connectionPointId the id of the custom connection point to change
     * @param newPosition the new position of the custom connection point in shape coordinates
     * @return true if position could be changed, else false
     */
    bool setConnectionPointPosition(int connectionPointId, const QPointF &newPosition);

359 360
    /**
     * Return a list of the connection points that have been added to this shape.
Thomas Zander's avatar
Thomas Zander committed
361
     * All the points are relative to the shape position, see absolutePosition().
362 363
     * @return a list of the connectors that have been added to this shape.
     */
364
    KoConnectionPoints connectionPoints() const;
Thomas Zander's avatar
Thomas Zander committed
365

366 367 368 369 370 371
    /// Removes connection point with specified id
    void removeConnectionPoint(int connectionPointId);

    /// Removes all connection points
    void clearConnectionPoints();

372
    /**
373
     * Add a event action
374
     */
375
    void addEventAction(KoEventAction *action);
376 377 378 379

    /**
     * Remove a event action
     */
380
    void removeEventAction(KoEventAction *action);
381 382 383 384

    /**
     * Get all event actions
     */
385
    QSet<KoEventAction *> eventActions() const;
386

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    /**
     * Return the side text should flow around this shape.
     */
    TextRunAroundSide textRunAroundSide() const;

    /**
     * Set the side text should flow around this shape.
     * @param side the requested side
     */
    void setTextRunAroundSide(TextRunAroundSide side, Through runThrought = Background);

    /**
     * The space between this shape's edge and text that runs around this shape.
     * @return the space around this shape to keep free from text
     */
    qreal textRunAroundDistance() const;

    /**
     * Set the space between this shape's edge and the text that run around this shape.
     * @param distance the space around this shape to keep free from text
     */
    void setTextRunAroundDistance(qreal distance);

Thomas Zander's avatar
Thomas Zander committed
410 411
    /**
     * Set the background of the shape.
412
     * A shape background can be a plain color, a gradient, a pattern, be fully transparent
Jan Hambrecht's avatar
Jan Hambrecht committed
413
     * or have a complex fill.
414
     * Setting such a background will allow the shape to be filled and will be able to tell
Jan Hambrecht's avatar
Jan Hambrecht committed
415 416
     * if it is transparent or not.
     * @param background the new shape background.
Thomas Zander's avatar
Thomas Zander committed
417
     */
418 419
    void setBackground(KoShapeBackground *background);

Thomas Zander's avatar
Thomas Zander committed
420 421
    /**
     * return the brush used to paint te background of this shape with.
422
     * A QBrush can have a plain color, be fully transparent or have a complex fill.
Thomas Zander's avatar
Thomas Zander committed
423
     * setting such a brush will allow the shape to fill itself using that brush and
424
     * will be able to tell if its transparent or not.
Thomas Zander's avatar
Thomas Zander committed
425 426
     * @return the background-brush
     */
427
    KoShapeBackground *background() const;
Thomas Zander's avatar
Thomas Zander committed
428 429

    /**
430 431
     * Returns true if there is some transparency, false if the shape is fully opaque.
     * The default implementation will just return if the background has some transparency,
Thomas Zander's avatar
Thomas Zander committed
432
     * you should override it and always return true if your shape is not square.
433
     * @return if the shape is (partly) transparent.
Thomas Zander's avatar
Thomas Zander committed
434
     */
Thomas Zander's avatar
Thomas Zander committed
435
    virtual bool hasTransparency() const;
Thomas Zander's avatar
Thomas Zander committed
436

437 438 439 440 441
    /**
     * Sets shape level transparency.
     * @param transparency the new shape level transparency
     */
    void setTransparency(qreal transparency);
442

443 444 445 446 447
    /**
     * Returns the shape level transparency.
     * @param recursive when true takes the parents transparency into account
     */
    qreal transparency(bool recursive=false) const;
448

Thomas Zander's avatar
Thomas Zander committed
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
    /**
     * Retrieve the z-coordinate of this shape.
     * The zIndex property is used to determine which shape lies on top of other objects.
     * An shape with a higher z-order is on top, and can obscure another shape.
     * @return the z-index of this shape.
     * @see setZIndex()
     */
    int zIndex() const;

    /**
     * Set the z-coordinate of this shape.
     * The zIndex property is used to determine which shape lies on top of other objects.
     * An shape with a higher z-order is on top, and can obscure, another shape.
     * <p>Just like two objects having the same x or y coordinate will make them 'touch',
     * so will two objects with the same z-index touch on the z plane.  In layering the
     * shape this, however, can cause a little confusion as one always has to be on top.
465
     * The layering if two overlapping objects have the same index is implementation dependent
Thomas Zander's avatar
Thomas Zander committed
466 467 468
     * and probably depends on the order in which they are added to the shape manager.
     * @param zIndex the new z-index;
     */
Thomas Zander's avatar
Thomas Zander committed
469
    void setZIndex(int zIndex);
Thomas Zander's avatar
Thomas Zander committed
470

471 472 473 474 475 476 477 478 479 480 481 482 483 484
    /**
     * Retrieve the run through property of this shape.
     * The run through property is used to determine if the shape is behind, inside or before text.
     * @return the run through of this shape.
     */
    int runThrough();

    /**
     * Set the run through property of this shape.
     * The run through property is used to determine if the shape is behind, inside or before text.
     * @param runThrough the new run through;
     */
    void setRunThrough(short int runThrough);

Thomas Zander's avatar
Thomas Zander committed
485 486
    /**
     * Changes the Shape to be visible or invisible.
487
     * Being visible means being painted, as well as being used for
Thomas Zander's avatar
Thomas Zander committed
488 489
     *   things like guidelines or searches.
     * @param on when true; set the shape to be visible.
490
     * @see setGeometryProtected(), setContentProtected(), setSelectable()
Thomas Zander's avatar
Thomas Zander committed
491
     */
Thomas Zander's avatar
Thomas Zander committed
492
    void setVisible(bool on);
Thomas Zander's avatar
Thomas Zander committed
493 494
    /**
     * Returns current visibility state of this shape.
495
     * Being visible means being painted, as well as being used for
Thomas Zander's avatar
Thomas Zander committed
496
     *   things like guidelines or searches.
497
     * @param recursive when true, checks visibility recursively
Thomas Zander's avatar
Thomas Zander committed
498
     * @return current visibility state of this shape.
499
     * @see isGeometryProtected(), isContentProtected(), isSelectable()
Thomas Zander's avatar
Thomas Zander committed
500
     */
501
    bool isVisible(bool recursive = false) const;
Thomas Zander's avatar
Thomas Zander committed
502

503 504 505 506 507
    /**
     * Changes the shape to be printable or not. The default is true.
     *
     * If a Shape's print flag is true, the shape will be printed. If
     * false, the shape will not be printed. If a shape is not visible (@see isVisible),
508
     * it isPrinted will return false, too.
509 510 511 512 513 514 515 516 517 518 519 520
     */
    void setPrintable(bool on);

    /**
     * Returns the current printable state of this shape.
     *
     * A shape can be visible but not printable, not printable and not visible
     * or visible and printable, but not invisible and still printable.
     *
     * @return current printable state of this shape.
     */
    bool isPrintable() const;
521

522 523 524
    /**
     * Makes it possible for the user to select this shape.
     * This parameter defaults to true.
Thomas Zander's avatar
Thomas Zander committed
525
     * @param selectable when true; set the shape to be selectable by the user.
526
     * @see setGeometryProtected(), setContentProtected(), setVisible()
527
     */
Thomas Zander's avatar
Thomas Zander committed
528
    void setSelectable(bool selectable);
529

530
    /**
Thomas Zander's avatar
Thomas Zander committed
531
     * Returns if this shape can be selected by the user.
532
     * @return true only when the object is selectable.
533
     * @see isGeometryProtected(), isContentProtected(), isVisible()
534
     */
Thomas Zander's avatar
Thomas Zander committed
535
    bool isSelectable() const;
536

Thomas Zander's avatar
Thomas Zander committed
537
    /**
538 539 540 541
     * Tells the shape to have its position/rotation and size protected from user-changes.
     * The geometry being protected means the user can not change shape or position of the
     * shape. This includes any matrix operation such as rotation.
     * @param on when true; set the shape to have its geometry protected.
542
     * @see setContentProtected(), setSelectable(), setVisible()
Thomas Zander's avatar
Thomas Zander committed
543
     */
544
    void setGeometryProtected(bool on);
545

Thomas Zander's avatar
Thomas Zander committed
546
    /**
547 548 549 550
     * Returns current geometry protection state of this shape.
     * The geometry being protected means the user can not change shape or position of the
     * shape. This includes any matrix operation such as rotation.
     * @return current geometry protection state of this shape.
551
     * @see isContentProtected(), isSelectable(), isVisible()
Thomas Zander's avatar
Thomas Zander committed
552
     */
553
    bool isGeometryProtected() const;
Thomas Zander's avatar
Thomas Zander committed
554

555 556 557 558
    /**
     * Marks the shape to have its content protected against editing.
     * Content protection is a hint for tools to disallow the user editing the content.
     * @param protect when true set the shapes content to be protected from user modification.
559
     * @see setGeometryProtected(), setSelectable(), setVisible()
560 561
     */
    void setContentProtected(bool protect);
562

563 564 565 566
    /**
     * Returns current content protection state of this shape.
     * Content protection is a hint for tools to disallow the user editing the content.
     * @return current content protection state of this shape.
567
     * @see isGeometryProtected(), isSelectable(), isVisible()
568 569 570
     */
    bool isContentProtected() const;

Thomas Zander's avatar
Thomas Zander committed
571 572 573 574
    /**
     * Returns the parent, or 0 if there is no parent.
     * @return the parent, or 0 if there is no parent.
     */
Thomas Zander's avatar
Thomas Zander committed
575
    KoShapeContainer *parent() const;
Thomas Zander's avatar
Thomas Zander committed
576 577 578 579 580 581 582 583 584 585 586 587 588 589

    /**
     * Set the parent of this shape.
     * @param parent the new parent of this shape. Can be 0 if the shape has no parent anymore.
     */
    void setParent(KoShapeContainer *parent);

    /**
     * Request a repaint to be queued.
     * The repaint will be of the entire Shape, including its selection handles should this
     * shape be selected.
     * <p>This method will return immediately and only request a repaint. Successive calls
     * will be merged into an appropriate repaint action.
     */
590
    virtual void update() const;
Thomas Zander's avatar
Thomas Zander committed
591 592 593 594 595 596 597 598

    /**
     * Request a repaint to be queued.
     * The repaint will be restricted to the parameters rectangle, which is expected to be
     * in points (the internal coordinates system of KoShape) and it is expected to be
     * normalized.
     * <p>This method will return immediately and only request a repaint. Successive calls
     * will be merged into an appropriate repaint action.
Boudewijn Rempt's avatar
Boudewijn Rempt committed
599
     * @param rect the rectangle (in pt) to queue for repaint.
Thomas Zander's avatar
Thomas Zander committed
600
     */
Boudewijn Rempt's avatar
Boudewijn Rempt committed
601
    virtual void update(const QRectF &rect) const;
Thomas Zander's avatar
Thomas Zander committed
602 603 604

    /**
     * This is a method used to sort a list using the STL sorting methods.
605 606
     * @param s1 the first shape
     * @param s2 the second shape
Thomas Zander's avatar
Thomas Zander committed
607
     */
608
    static bool compareShapeZIndex(KoShape *s1, KoShape *s2);
Thomas Zander's avatar
Thomas Zander committed
609 610 611 612 613 614 615 616

    /**
     * returns the outline of the shape in the form of a path.
     * The outline returned will always have the position() of the shape as the origin, so
     * moving the shape will not alter the result.  The outline is used to draw the border
     * on, for example.
     * @returns the outline of the shape in the form of a path.
     */
617
    virtual QPainterPath outline() const;
Thomas Zander's avatar
Thomas Zander committed
618

619 620 621 622 623 624 625 626
    /**
     * returns the outline of the shape in the form of a rect.
     * The outlineRect returned will always have the position() of the shape as the origin, so
     * moving the shape will not alter the result.  The outline is used to calculate the boundingRect.
     * @returns the outline of the shape in the form of a rect.
     */
    virtual QRectF outlineRect() const;

Thomas Zander's avatar
Thomas Zander committed
627 628 629 630
    /**
     * Returns the currently set border, or 0 if there is no border.
     * @return the currently set border, or 0 if there is no border.
     */
631
    KoShapeBorderModel *border() const;
Thomas Zander's avatar
Thomas Zander committed
632 633 634 635 636

    /**
     * Set a new border, removing the old one.
     * @param border the new border, or 0 if there should be no border.
     */
637
    void setBorder(KoShapeBorderModel *border);
Thomas Zander's avatar
Thomas Zander committed
638

639 640 641 642 643 644
    /**
     * Return the insets of the border.
     * Convenience method for KoShapeBorderModel::borderInsets()
     */
    KoInsets borderInsets() const;

645
    /// Sets the new shadow, removing the old one
646
    void setShadow(KoShapeShadow *shadow);
647

648
    /// Returns the currently set shadow or 0 if there is no shadow set
649
    KoShapeShadow *shadow() const;
650

Thomas Zander's avatar
Thomas Zander committed
651 652 653 654 655 656
    /**
     * Setting the shape to keep its aspect-ratio has the effect that user-scaling will
     * keep the width/hight ratio intact so as not to distort shapes that rely on that
     * ratio.
     * @param keepAspect the new value
     */
Thomas Zander's avatar
Thomas Zander committed
657
    void setKeepAspectRatio(bool keepAspect);
658

Thomas Zander's avatar
Thomas Zander committed
659 660 661 662 663 664
    /**
     * Setting the shape to keep its aspect-ratio has the effect that user-scaling will
     * keep the width/hight ratio intact so as not to distort shapes that rely on that
     * ratio.
     * @return whether to keep aspect ratio of this shape
     */
Thomas Zander's avatar
Thomas Zander committed
665
    bool keepAspectRatio() const;
Thomas Zander's avatar
Thomas Zander committed
666 667 668 669

    /**
     * Return the position of this shape regardless of rotation/skew/scaling and regardless of
     * this shape having a parent (being in a group) or not.<br>
670
     * @param anchor The place on the (unaltered) shape that you want the position of.
Thomas Zander's avatar
Thomas Zander committed
671 672
     * @return the point that is the absolute, centered position of this shape.
     */
Jan Hambrecht's avatar
Jan Hambrecht committed
673
    QPointF absolutePosition(KoFlake::Position anchor = KoFlake::CenteredPosition) const;
674

Thomas Zander's avatar
Thomas Zander committed
675 676 677 678 679 680 681 682 683 684 685 686
    /**
     * Move this shape to an absolute position where the end location will be the same
     * regardless of the shape's rotation/skew/scaling and regardless of this shape having
     * a parent (being in a group) or not.<br>
     * The newPosition is going to be the center of the shape.
     * This has the convenient effect that: <pre>
    shape-&gt;setAbsolutePosition(QPointF(0,0));
    shape-&gt;rotate(45);</pre>
        Will result in the same visual position of the shape as the opposite:<pre>
    shape-&gt;rotate(45);
    shape-&gt;setAbsolutePosition(QPointF(0,0));</pre>
     * @param newPosition the new absolute center of the shape.
Thomas Zander's avatar
Thomas Zander committed
687
     * @param anchor The place on the (unaltered) shape that you set the position of.
Thomas Zander's avatar
Thomas Zander committed
688
     */
Jan Hambrecht's avatar
Jan Hambrecht committed
689
    void setAbsolutePosition(QPointF newPosition, KoFlake::Position anchor = KoFlake::CenteredPosition);
Thomas Zander's avatar
Thomas Zander committed
690

691 692
    /**
     * Set a data object on the shape to be used by an application.
693
     * This is specifically useful when a shape is created in a plugin and that data from that
694 695 696 697 698 699 700 701 702
     * shape should be accessible outside the plugin.
     * @param userData the new user data, or 0 to delete the current one.
     */
    void setUserData(KoShapeUserData *userData);
    /**
     * Return the current userData.
     */
    KoShapeUserData *userData() const;

703 704 705 706 707 708 709
    /**
     * Set a data object on the shape to be used by an application.
     * This is specifically useful when an application wants to have data that is per shape
     * and should be deleted when the shape is destructed.
     * @param applicationData the new application data, or 0 to delete the current one.
     */
    void setApplicationData(KoShapeApplicationData *applicationData);
710

711 712 713 714 715
    /**
     * Return the current applicationData.
     */
    KoShapeApplicationData *applicationData() const;

716
    /**
Marijn Kruisselbrink's avatar
Marijn Kruisselbrink committed
717
     * Return the Id of this shape, identifying the type of shape by the id of the factory.
718
     * @see KoShapeFactoryBase::shapeId()
719 720
     * @return the id of the shape-type
     */
721 722
    QString shapeId() const;

723 724 725
    /**
     * Set the Id of this shape.  A shapeFactory is expected to set the Id at creation
     * so applications can find out what kind of shape this is.
726
     * @see KoShapeFactoryBase::shapeId()
727 728
     * @param id the ID from the factory that created this shape
     */
Thomas Zander's avatar
Thomas Zander committed
729
    void setShapeId(const QString &id);
730

Thomas Zander's avatar
Thomas Zander committed
731 732
    /**
     * Create a matrix that describes all the transformations done on this shape.
733 734 735 736
     *
     * The absolute transformation is the combined transformation of this shape
     * and all its parents and grandparents.
     *
Thomas Zander's avatar
Thomas Zander committed
737 738 739
     * @param converter if not null, this method uses the converter to mark the right
     *        offsets in the current view.
     */
740
    QTransform absoluteTransformation(const KoViewConverter *converter) const;
Thomas Zander's avatar
Thomas Zander committed
741

742 743 744 745
    /**
     * Applies a transformation to this shape.
     *
     * The transformation given is relative to the global coordinate system, i.e. the document.
746 747
     * This is a convenience function to apply a global transformation to this shape.
     * @see applyTransformation
748 749 750
     *
     * @param matrix the transformation matrix to apply
     */
751
    void applyAbsoluteTransformation(const QTransform &matrix);
752 753 754 755 756

    /**
     * Sets a new transformation matrix describing the local transformations on this shape.
     * @param matrix the new transformation matrix
     */
757
    void setTransformation(const QTransform &matrix);
758

759
    /// Returns the shapes local transformation matrix
760
    QTransform transformation() const;
761 762 763 764 765 766 767 768

    /**
     * Applies a transformation to this shape.
     *
     * The transformation given is relative to the shape coordinate system.
     *
     * @param matrix the transformation matrix to apply
     */
769
    void applyTransformation(const QTransform &matrix);
770

Thomas Zander's avatar
Thomas Zander committed
771 772 773 774 775 776
    /**
     * Copy all the settings from the parameter shape and apply them to this shape.
     * Settings like the position and rotation to visible and locked.  The parent
     * is a notable exclusion.
     * @param shape the shape to use as original
     */
Thomas Zander's avatar
Thomas Zander committed
777
    void copySettings(const KoShape *shape);
Thomas Zander's avatar
Thomas Zander committed
778

Thomas Zander's avatar
Thomas Zander committed
779 780 781 782 783 784 785 786 787
    /**
     * Convenience method that allows people implementing paint() to use the shape
     * internal coordinate system directly to paint itself instead of considering the
     * views zoom.
     * @param painter the painter to alter the zoom level of.
     * @param converter the converter for the current views zoom.
     */
    static void applyConversion(QPainter &painter, const KoViewConverter &converter);

788 789 790 791 792
    /**
     * @brief Transforms point from shape coordinates to document coordinates
     * @param point in shape coordinates
     * @return point in document coordinates
     */
793
    QPointF shapeToDocument(const QPointF &point) const;
794 795 796 797 798 799

    /**
     * @brief Transforms rect from shape coordinates to document coordinates
     * @param rect in shape coordinates
     * @return rect in document coordinates
     */
800
    QRectF shapeToDocument(const QRectF &rect) const;
801 802 803 804 805 806

    /**
     * @brief Transforms point from document coordinates to shape coordinates
     * @param point in document coordinates
     * @return point in shape coordinates
     */
807
    QPointF documentToShape(const QPointF &point) const;
808 809 810 811 812 813

    /**
     * @brief Transform rect from document coordinates to shape coordinates
     * @param rect in document coordinates
     * @return rect in shape coordinates
     */
814
    QRectF documentToShape(const QRectF &rect) const;
815

816 817 818 819
    /**
     * Returns the name of the shape.
     * @return the shapes name
     */
820
    QString name() const;
821 822 823 824 825

    /**
     * Sets the name of the shape.
     * @param name the new shape name
     */
826
    void setName(const QString &name);
827

828 829 830 831 832
    /**
     * Update the position of the shape in the tree of the KoShapeManager.
     */
    void notifyChanged();

833
    /**
Thomas Zander's avatar
Thomas Zander committed
834
     * A shape can be in a state that it is doing processing data like loading or text layout.
835
     * In this case it can be shown on screen probably partially but it should really not be printed
Thomas Zander's avatar
Thomas Zander committed
836
     * until it is fully done processing.
837
     * Warning! This method can be blocking for a long time
Boudewijn Rempt's avatar
Boudewijn Rempt committed
838 839 840
     * @param asynchronous If set to true the processing will can take place in a different thread and the
     *                     function will not block until the shape is finised.
     *                     In case of printing Flake will call this method from a non-main thread and only
841
     *                     start printing it when the in case of printing method returned.
Boudewijn Rempt's avatar
Boudewijn Rempt committed
842
     *                     If set to false the processing needs to be done synchronously and will
843 844 845
     *                     block until the result is finished.
     */
    virtual void waitUntilReady(const KoViewConverter &converter, bool asynchronous = true) const;
846

Thomas Zander's avatar
api dox  
Thomas Zander committed
847 848 849
    /**
     * Schedule the shape for thread-safe deletion.
     * After calling this method will self-delete in the main threads event loop.
Thomas Zander's avatar
Thomas Zander committed
850 851 852 853
     * If your code deletes a shape and your code can possibly be running in a separate thread,
     * you should use this method to delete the shape.
     * The reason for this is that If you delete a shape from another thread then it is
     * possible the main
Thomas Zander's avatar
api dox  
Thomas Zander committed
854
     * thread will use it after its been removed, while painting for example.
Thomas Zander's avatar
Thomas Zander committed
855 856
     *
     * Note that in contrary to the equivalent method on QObject, you can not call this more than once.
Thomas Zander's avatar
api dox  
Thomas Zander committed
857
     */
858
    void deleteLater();
859

860 861 862
    /// checks recursively if the shape or one of its parents is not visible or locked
    bool isEditable() const;

863 864
    /**
     * Adds a shape which depends on this shape.
865 866
     * Making a shape dependent on this one means it will get shapeChanged() called
     * on each update of this shape.
867 868 869 870 871
     *
     * If this shape already depends on the given shape, establishing the
     * dependency is refused to prevent circular dependencies.
     *
     * @param shape the shape which depends on this shape
872 873
     * @return true if dependency could be established, otherwise false
     * @see removeDependee(), hasDependee()
874
     */
875
    bool addDependee(KoShape *shape);
876

877 878 879 880
    /**
     * Removes as shape depending on this shape.
     * @see addDependee(), hasDependee()
     */
881
    void removeDependee(KoShape *shape);
882

883
    /// Returns if the given shape is dependent on this shape
884
    bool hasDependee(KoShape *shape) const;
885

886 887 888
    /// Returns additional snap data the shape wants to have snapping to
    virtual KoSnapData snapData() const;

889 890 891 892 893 894 895 896 897
    /**
     * Set additional attribute
     *
     * This can be used to attach additional attributes to a shape for attributes
     * that are application specific like presentation:placeholder
     *
     * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
     * @param value The value of the attribute
     */
898
    void setAdditionalAttribute(const QString &name, const QString &value);
899 900 901 902 903 904

    /**
     * Remove additional attribute
     *
     * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
     */
905
    void removeAdditionalAttribute(const QString &name);
906 907 908 909 910 911 912 913

    /**
     * Check if additional attribute is set
     *
     * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
     *
     * @return true if there is a attribute with prefix:tag set, false otherwise
     */
914
    bool hasAdditionalAttribute(const QString &name) const;
915 916 917 918 919 920 921 922

    /**
     * Get additional attribute
     *
     * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
     *
     * @return The value of the attribute if it exists or a null string if not found.
     */
923
    QString additionalAttribute(const QString &name) const;
924

925
    void setAdditionalStyleAttribute(const char *name, const QString &value);
926

927
    void removeAdditionalStyleAttribute(const char *name);
928

929
    /**
930
     * Returns the filter effect stack of the shape
931 932 933
     *
     * @return the list of filter effects applied on the shape when rendering.
     */
934
    KoFilterEffectStack *filterEffectStack() const;
935

936
    /// Sets the new filter effect stack, removing the old one
937
    void setFilterEffectStack(KoFilterEffectStack *filterEffectStack);
938

939 940 941 942 943 944 945 946 947 948 949 950 951 952
    /**
     * Set the property collision detection.
     * Setting this to true will result in calls to shapeChanged() with the CollisionDetected
     * parameter whenever either this or another shape is moved/rotated etc and intersects this shape.
     * @param detect if true detect collisions.
     */
    void setCollisionDetection(bool detect);

    /**
     * get the property collision detection.
     * @returns true if collision detection is on.
     */
    bool collisionDetection();

953 954 955 956 957 958
    /**
     * Return the tool delegates for this shape.
     * In Flake a shape being selected will cause the tool manager to make available all tools that
     * can edit the selected shapes.  In some cases selecting one shape should allow the tool to
     * edit a related shape be available too.  The tool delegates allows this to happen by taking
     * all the shapes in the set into account on tool selection.
Thomas Zander's avatar
Thomas Zander committed
959
     * Notice that if the set is non-empty 'this' shape is no longer looked at. You can choose
960 961 962 963 964 965 966 967 968 969 970
     * to add itself to the set too.
     */
    QSet<KoShape*> toolDelegates() const;

    /**
     * Set the tool delegates.
     * @param delegates the new delegates.
     * @see toolDelegates()
     */
    void setToolDelegates(const QSet<KoShape*> &delegates);

971 972 973 974 975 976 977 978 979 980 981
    /**
     * Return the hyperlink for this shape.
     */
    QString hyperLink () const;

    /**
     * Set hyperlink for this shape.
     * @param hyperLink name.
     */
    void setHyperLink (QString & hyperLink);

982 983
    /**
     * \internal
Marijn Kruisselbrink's avatar
Marijn Kruisselbrink committed
984
     * Returns the private object for use within the flake lib
985 986 987
     */
    KoShapePrivate *priv();

Boudewijn Rempt's avatar
Boudewijn Rempt committed
988 989 990 991 992 993 994 995 996 997 998
    /**
     * Returns the cache mode for this shape. The default mode is NoCache (i.e.,
     * cache is disabled and all painting is immediate).
     */
    CacheMode cacheMode() const;

    /**
     * Set the shape's cache mode to @param mode.
     */
    void setCacheMode(CacheMode cacheMode);

999
protected:
1000 1001
    /// constructor
    KoShape(KoShapePrivate &);
1002

1003
    /* ** loading saving helper methods */
1004 1005
    /// attributes from ODF 1.1 chapter 9.2.15 Common Drawing Shape Attributes
    enum OdfAttribute {
1006 1007
        OdfTransformation = 1,       ///< Store transformation information
        OdfSize = 2,                 ///< Store size information
1008 1009 1010 1011 1012 1013 1014 1015
        OdfPosition = 8,             ///< Store position
        OdfAdditionalAttributes = 4, ///< Store additional attributes of the shape
        OdfCommonChildElements = 16, ///< Event actions and connection points
        OdfLayer = 64,               ///< Store layer name
        OdfStyle = 128,              ///< Store the style
        OdfId = 256,                 ///< Store the unique ID
        OdfName = 512,               ///< Store the name of the shape
        OdfZIndex = 1024,            ///< This only loads the z-index; when saving, it is reflected by the order of the shapes.
1016
        OdfViewbox = 2048,           ///< Store the viewbox
1017 1018 1019 1020 1021

        /// A mask for all mandatory attributes
        OdfMandatories = OdfLayer | OdfStyle | OdfId | OdfName | OdfZIndex,
        /// A mask for geometry attributes
        OdfGeometry = OdfPosition | OdfSize,
1022
        /// A mask for all the attributes
1023
        OdfAllAttributes = OdfTransformation | OdfGeometry | OdfAdditionalAttributes | OdfMandatories | OdfCommonChildElements
1024
    };
1025

1026 1027 1028 1029 1030 1031 1032
    /**
     * This method is used during loading of the shape to load common attributes
     *
     * @param context the KoShapeLoadingContext used for loading
     * @param element element which represents the shape in odf
     * @param attributes a number of OdfAttribute items to state which attributes to load.
     */
1033
    bool loadOdfAttributes(const KoXmlElement &element, KoShapeLoadingContext &context, int attributes);
1034

Jan Hambrecht's avatar
 
Jan Hambrecht committed
1035 1036 1037 1038 1039
    /**
     * Parses the transformation attribute from the given string
     * @param transform the transform attribute string
     * @return the resulting transformation matrix
     */
1040
    QTransform parseOdfTransform(const QString &transform);
Jan Hambrecht's avatar
 
Jan Hambrecht committed
1041

1042
    /**
1043
     * @brief Saves the style used for the shape
1044
     *
1045 1046
     * This method fills the given style object with the border and
     * background properties and then adds the style to the context.
1047
     *
1048
     * @param style the style object to fill
1049 1050 1051
     * @param context used for saving
     * @return the name of the style
     * @see saveOdf
1052
     */
1053
    virtual QString saveStyle(KoGenStyle &style, KoShapeSavingContext &context) const;
1054 1055 1056 1057 1058 1059 1060

    /**
     * Loads the stroke and fill style from the given element.
     *
     * @param element the xml element to  load the style from
     * @param context the loading context used for loading
     */
1061
    virtual void loadStyle(const KoXmlElement &element, KoShapeLoadingContext &context);
1062

1063
    /// Loads the stroke style
1064
    KoShapeBorderModel *loadOdfStroke(const KoXmlElement &element, KoShapeLoadingContext &context) const;
1065

1066
    /// Loads the shadow style
1067
    KoShapeBackground *loadOdfFill(KoShapeLoadingContext &context) const;
1068

1069
    /* ** end loading saving */
1070

1071 1072 1073 1074 1075
    /**
     * A hook that allows inheriting classes to do something after a KoShape property changed
     * This is called whenever the shape, position rotation or scale properties were altered.
     * @param type an indicator which type was changed.
     */
1076
    virtual void shapeChanged(ChangeType type, KoShape *shape = 0);
1077

Thomas Zander's avatar
Thomas Zander committed
1078
    /// return the current matrix that contains the rotation/scale/position of this shape
1079
    QTransform transform() const;
1080

Boudewijn Rempt's avatar
Boudewijn Rempt committed
1081 1082

    friend class KoShapeManagerCachedPaintingStrategy;
1083 1084
    KoShapePrivate *d_ptr;

Thomas Zander's avatar
Thomas Zander committed
1085
private:
1086
    Q_DECLARE_PRIVATE(KoShape)
Thomas Zander's avatar
Thomas Zander committed
1087 1088
};

1089 1090
Q_DECLARE_METATYPE(KoShape*)

Thomas Zander's avatar
Thomas Zander committed
1091
#endif