1 /* This file is part of the KDE project 2 Copyright (C) 2006-2008 Thorsten Zachmann <zachmann@kde.org> 3 Copyright (C) 2006, 2008 C. Boemann <cbo@boemann.dk> 4 Copyright (C) 2006-2010 Thomas Zander <zander@kde.org> 5 Copyright (C) 2007-2009,2011 Jan Hambrecht <jaham@gmx.net> 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public License 18 along with this library; see the file COPYING.LIB. If not, write to 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 #ifndef KOSHAPE_H 24 #define KOSHAPE_H 25 26 #include "KoFlake.h" 27 #include "KoConnectionPoint.h" 28 29 #include <QSharedPointer> 30 #include <QSet> 31 #include <QMetaType> 32 33 #include <KoXmlReaderForward.h> 34 #include <KoShapeBackground.h> 35 36 //#include <KoSnapData.h> 37 38 #include "flake_export.h" 39 40 class QPainter; 41 class QRectF; 42 class QPainterPath; 43 class QTransform; 44 45 class KoShapeContainer; 46 class KoShapeStrokeModel; 47 class KoShapeUserData; 48 class KoViewConverter; 49 class KoShapeApplicationData; 50 class KoShapeSavingContext; 51 class KoShapeLoadingContext; 52 class KoGenStyle; 53 class KoShapeShadow; 54 class KoEventAction; 55 class KoShapePrivate; 56 class KoFilterEffectStack; 57 class KoSnapData; 58 class KoClipPath; 59 class KoShapePaintingContext; 60 class KoShapeAnchor; 61 class KoBorder; 62 struct KoInsets; 63 64 65 /** 66 * 67 * Base class for all flake shapes. Shapes extend this class 68 * to allow themselves to be manipulated. This class just represents 69 * a graphical shape in the document and can be manipulated by some default 70 * tools in this library. 71 * 72 * Due to the limited responsibility of this class, the extending object 73 * can have any data backend and is responsible for painting itself. 74 * 75 * We strongly suggest that any extending class will use a Model View 76 * Controller (MVC) design where the View part is all in this class, as well 77 * as the one that inherits from this one. This allows the data that rests 78 * in the model to be reused in different parts of the document. For example 79 * by having two flake objects that show that same data. Or each showing a section of it. 80 * 81 * The KoShape data is completely in postscript-points (pt) (see KoUnit 82 * for conversion methods to and from points). 83 * This image will explain the real-world use of the shape and its options. 84 * <img src="../flake_shape_coords.png" align=center><br> 85 * The Rotation center can be returned with absolutePosition() 86 * 87 * <p>Flake objects can be created in three ways: 88 * <ul> 89 * <li>a simple new KoDerivedFlake(), 90 * <li>through an associated tool, 91 * <li>through a factory 92 * </ul> 93 * 94 * <h1>Shape interaction notifications</h1> 95 * We had several notification methods that allow your shape to be notified of changes in other 96 * shapes positions or rotation etc. 97 * <ol><li>The most general is KoShape::shapeChanged().<br> 98 * a virtual method that you can use to check various changed to your shape made by tools or otherwise.</li> 99 * <li>for shape hierarchies the parent may receive a notification when a child was modified. 100 * This is done though KoShapeContainerModel::childChanged()</li> 101 * <li>any shape that is at a similar position as another shape there is collision detection. 102 * You can register your shape to be sensitive to any changes like moving or whatever to 103 * <b>other</b> shapes that intersect yours. 104 * Such changes will then be notified to your shape using the method from (1) You should call 105 * KoShape::setCollisionDetection(bool) to enable this. 106 * </ol> 107 */ 108 class FLAKE_EXPORT KoShape 109 { 110 public: 111 /// Used by shapeChanged() to select which change was made 112 enum ChangeType { 113 PositionChanged, ///< used after a setPosition() 114 RotationChanged, ///< used after a setRotation() 115 ScaleChanged, ///< used after a scale() 116 ShearChanged, ///< used after a shear() 117 SizeChanged, ///< used after a setSize() 118 GenericMatrixChange, ///< used after the matrix was changed without knowing which property explicitly changed 119 ParentChanged, ///< used after a setParent() 120 CollisionDetected, ///< used when another shape moved in our boundingrect 121 Deleted, ///< the shape was deleted 122 StrokeChanged, ///< the shapes stroke has changed 123 BackgroundChanged, ///< the shapes background has changed 124 ShadowChanged, ///< the shapes shadow has changed 125 BorderChanged, ///< the shapes border has changed 126 ParameterChanged, ///< the shapes parameter has changed (KoParameterShape only) 127 ContentChanged, ///< the content of the shape changed e.g. a new image inside a pixmap/text change inside a textshape 128 TextRunAroundChanged, ///< used after a setTextRunAroundSide() 129 ChildChanged, ///< a child of a container was changed/removed. This is propagated to all parents 130 ConnectionPointChanged, ///< a connection point has changed 131 ClipPathChanged, ///< the shapes clip path has changed 132 ControlPointChanged, ///< a control point has changed 133 BeginResize, ///< used during resizing 134 EndResize ///< used during resizing 135 }; 136 137 /// The behavior text should do when intersecting this shape. 138 enum TextRunAroundSide { 139 BiggestRunAroundSide, ///< Run other text around the side that has the most space 140 LeftRunAroundSide, ///< Run other text around the left side of the frame 141 RightRunAroundSide, ///< Run other text around the right side of the frame 142 EnoughRunAroundSide, ///< Run other text dynamically around both sides of the shape, provided there is sufficient space left 143 BothRunAroundSide, ///< Run other text around both sides of the shape 144 NoRunAround, ///< The text will be completely avoiding the frame by keeping the horizontal space that this frame occupies blank. 145 RunThrough ///< The text will completely ignore the frame and layout as if it was not there 146 }; 147 148 /// The behavior text should do when intersecting this shape. 149 enum TextRunAroundContour { 150 ContourBox, /// Run other text around a bounding rect of the outline 151 ContourFull, ///< Run other text around also on the inside 152 ContourOutside ///< Run other text around only on the outside 153 }; 154 155 /** 156 * TODO 157 */ 158 enum RunThroughLevel { 159 Background, 160 Foreground 161 }; 162 163 /// Fine grained control of allowed user interactions 164 enum AllowedInteraction { 165 MoveAllowed = 1, ///< Moving the shape is allowed 166 ResizeAllowed = 2, ///< Resizing the shape is allowed 167 ShearingAllowed = 4, ///< Sharing the shape is allowed 168 RotationAllowed = 8, ///< Rotating the shape is allowed 169 SelectionAllowed = 16, ///< Selecting the shape is allowed 170 ContentChangeAllowed = 32, ///< Editing the content is allowed 171 DeletionAllowed = 64 ///< Deleting the shape is allowed 172 }; 173 Q_DECLARE_FLAGS(AllowedInteractions, AllowedInteraction) 174 Q_FLAGS(AllowedInteractions) 175 176 /** 177 * @brief Constructor 178 */ 179 KoShape(); 180 181 /** 182 * @brief Destructor 183 */ 184 virtual ~KoShape(); 185 186 /** 187 * @brief Paint the shape 188 * The class extending this one is responsible for painting itself. Since we do not 189 * assume the shape is square the paint must also clear its background if it will draw 190 * something transparent on top. 191 * This can be done with a method like: 192 * <code> 193 painter.fillRect(converter.normalToView(QRectF(QPointF(0.0,0.0), size())), background());</code> 194 * Or equivalent for non-square objects. 195 * Do note that a shape's top-left is always at coordinate 0,0. Even if the shape itself is rotated 196 * or translated. 197 * @param painter used for painting the shape 198 * @param converter to convert between internal and view coordinates. 199 * @see applyConversion() 200 * @param paintcontext the painting context. 201 */ 202 virtual void paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintcontext) = 0; 203 204 /** 205 * @brief Paint the shape's border 206 * This is a helper function that could be called from the paint() method of all shapes. 207 * @param painter used for painting the shape 208 * @param converter to convert between internal and view coordinates. 209 * @see applyConversion() 210 */ 211 virtual void paintBorder(QPainter &painter, const KoViewConverter &converter); 212 213 /** 214 * Load a shape from odf 215 * 216 * @param context the KoShapeLoadingContext used for loading 217 * @param element element which represents the shape in odf 218 * 219 * @return false if loading failed 220 */ 221 virtual bool loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context) = 0; 222 223 /** 224 * @brief store the shape data as ODF XML. 225 * This is the method that will be called when saving a shape as a described in 226 * OpenDocument 9.2 Drawing Shapes. 227 * @see saveOdfAttributes 228 */ 229 virtual void saveOdf(KoShapeSavingContext &context) const = 0; 230 231 /** 232 * This method can be used while saving the shape as ODF to add the data 233 * stored on this shape to the current element. 234 * 235 * @param context the context for the current save. 236 * @param attributes a number of OdfAttribute items to state which attributes to save. 237 * @see saveOdf 238 */ 239 void saveOdfAttributes(KoShapeSavingContext &context, int attributes) const; 240 241 /** 242 * This method can be used while saving the shape as Odf to add common child elements 243 * 244 * The office:event-listeners and draw:glue-point are saved. 245 * @param context the context for the current save. 246 */ 247 void saveOdfCommonChildElements(KoShapeSavingContext &context) const; 248 249 /** 250 * This method can be used to save contour data from the clipPath() 251 * 252 * The draw:contour-polygon or draw:contour-path elements are saved. 253 * @param context the context for the current save. 254 * @param originalSize the original size of the unscaled image. 255 */ 256 void saveOdfClipContour(KoShapeSavingContext &context, const QSizeF &originalSize) const; 257 258 /** 259 * @brief Scale the shape using the zero-point which is the top-left corner. 260 * @see position() 261 * 262 * @param sx scale in x direction 263 * @param sy scale in y direction 264 */ 265 void scale(qreal sx, qreal sy); 266 267 /** 268 * @brief Rotate the shape (relative) 269 * 270 * The shape will be rotated from the current rotation using the center of the shape using the size() 271 * 272 * @param angle change the angle of rotation increasing it with 'angle' degrees 273 */ 274 void rotate(qreal angle); 275 276 /** 277 * Return the current rotation in degrees. 278 * It returns NaN if the shape has a shearing or scaling transformation applied. 279 */ 280 qreal rotation() const; 281 282 /** 283 * @brief Shear the shape 284 * The shape will be sheared using the zero-point which is the top-left corner. 285 * @see position() 286 * 287 * @param sx shear in x direction 288 * @param sy shear in y direction 289 */ 290 void shear(qreal sx, qreal sy); 291 292 /** 293 * @brief Resize the shape 294 * 295 * @param size the new size of the shape. This is different from scaling as 296 * scaling is a so called secondary operation which is comparable to zooming in 297 * instead of changing the size of the basic shape. 298 * Easiest example of this difference is that using this method will not distort the 299 * size of pattern-fills and strokes. 300 */ 301 virtual void setSize(const QSizeF &size); 302 303 /** 304 * @brief Get the size of the shape in pt. 305 * 306 * The size is in shape coordinates. 307 * 308 * @return the size of the shape as set by setSize() 309 */ 310 virtual QSizeF size() const; 311 312 /** 313 * @brief Set the position of the shape in pt 314 * 315 * @param position the new position of the shape 316 */ 317 virtual void setPosition(const QPointF &position); 318 319 /** 320 * @brief Get the position of the shape in pt 321 * 322 * @return the position of the shape 323 */ 324 QPointF position() const; 325 326 /** 327 * @brief Check if the shape is hit on position 328 * @param position the position where the user clicked. 329 * @return true when it hits. 330 */ 331 virtual bool hitTest(const QPointF &position) const; 332 333 /** 334 * @brief Get the bounding box of the shape 335 * 336 * This includes the line width and the shadow of the shape 337 * 338 * @return the bounding box of the shape 339 */ 340 virtual QRectF boundingRect() const; 341 342 /** 343 * @brief Add a connector point to the shape 344 * 345 * A connector is a place on the shape that allows a graphical connection to be made 346 * using a line, for example. 347 * 348 * @param point the connection point to add 349 * @return the id of the new connection point 350 */ 351 int addConnectionPoint(const KoConnectionPoint &point); 352 353 /** 354 * Sets data of connection point with specified id. 355 * 356 * The position of the connector is restricted to the bounding rectangle of the shape. 357 * When setting a default connection point, the new position is ignored, as these 358 * are fixed at their default position. 359 * The function will insert a new connection point if the specified id was not used 360 * before. 361 * 362 * @param connectionPointId the id of the connection point to set 363 * @param point the connection point data 364 * @return false if specified connection point id is invalid, else true 365 */ 366 bool setConnectionPoint(int connectionPointId, const KoConnectionPoint &point); 367 368 /// Checks if a connection point with the specified id exists 369 bool hasConnectionPoint(int connectionPointId) const; 370 371 /// Returns connection point with specified connection point id 372 KoConnectionPoint connectionPoint(int connectionPointId) const; 373 374 /** 375 * Return a list of the connection points that have been added to this shape. 376 * All the points are relative to the shape position, see absolutePosition(). 377 * @return a list of the connectors that have been added to this shape. 378 */ 379 KoConnectionPoints connectionPoints() const; 380 381 /// Removes connection point with specified id 382 void removeConnectionPoint(int connectionPointId); 383 384 /// Removes all connection points 385 void clearConnectionPoints(); 386 387 /** 388 * Add a event action 389 */ 390 void addEventAction(KoEventAction *action); 391 392 /** 393 * Remove a event action 394 */ 395 void removeEventAction(KoEventAction *action); 396 397 /** 398 * Get all event actions 399 */ 400 QSet<KoEventAction *> eventActions() const; 401 402 /** 403 * Return the side text should flow around this shape. This implements the ODF style:wrap 404 * attribute that specifies how text is displayed around a frame or graphic object. 405 */ 406 TextRunAroundSide textRunAroundSide() const; 407 408 /** 409 * Set the side text should flow around this shape. 410 * @param side the requested side 411 * @param runThrough run through the foreground or background or... 412 */ 413 void setTextRunAroundSide(TextRunAroundSide side, RunThroughLevel runThrough = Background); 414 415 /** 416 * The space between this shape's left edge and text that runs around this shape. 417 * @return the space around this shape to keep free from text 418 */ 419 qreal textRunAroundDistanceLeft() const; 420 421 /** 422 * Set the space between this shape's left edge and the text that run around this shape. 423 * @param distance the space around this shape to keep free from text 424 */ 425 void setTextRunAroundDistanceLeft(qreal distance); 426 427 /** 428 * The space between this shape's top edge and text that runs around this shape. 429 * @return the space around this shape to keep free from text 430 */ 431 qreal textRunAroundDistanceTop() const; 432 433 /** 434 * Set the space between this shape's top edge and the text that run around this shape. 435 * @param distance the space around this shape to keep free from text 436 */ 437 void setTextRunAroundDistanceTop(qreal distance); 438 439 /** 440 * The space between this shape's right edge and text that runs around this shape. 441 * @return the space around this shape to keep free from text 442 */ 443 qreal textRunAroundDistanceRight() const; 444 445 /** 446 * Set the space between this shape's right edge and the text that run around this shape. 447 * @param distance the space around this shape to keep free from text 448 */ 449 void setTextRunAroundDistanceRight(qreal distance); 450 451 /** 452 * The space between this shape's bottom edge and text that runs around this shape. 453 * @return the space around this shape to keep free from text 454 */ 455 qreal textRunAroundDistanceBottom() const; 456 457 /** 458 * Set the space between this shape's bottom edge and the text that run around this shape. 459 * @param distance the space around this shape to keep free from text 460 */ 461 void setTextRunAroundDistanceBottom(qreal distance); 462 463 /** 464 * Return the threshold above which text should flow around this shape. 465 * The text will not flow around the shape on a side unless the space available on that side 466 * is above this threshold. Only used when the text run around side is EnoughRunAroundSide. 467 * @return threshold the threshold 468 */ 469 qreal textRunAroundThreshold() const; 470 471 /** 472 * Set the threshold above which text should flow around this shape. 473 * The text will not flow around the shape on a side unless the space available on that side 474 * is above this threshold. Only used when the text run around side is EnoughRunAroundSide. 475 * @param threshold the new threshold 476 */ 477 void setTextRunAroundThreshold(qreal threshold); 478 479 /** 480 * Return the how tight text run around is done around this shape. 481 * @return the contour 482 */ 483 TextRunAroundContour textRunAroundContour() const; 484 485 /** 486 * Set how tight text run around is done around this shape. 487 * @param contour the new contour 488 */ 489 void setTextRunAroundContour(TextRunAroundContour contour); 490 491 /** 492 * Set the KoShapeAnchor 493 */ 494 void setAnchor(KoShapeAnchor *anchor); 495 496 /** 497 * Return the KoShapeAnchor, or 0 498 */ 499 KoShapeAnchor *anchor() const; 500 501 /** 502 * Set the minimum height of the shape. 503 * Currently it's not respected but only for informational purpose 504 * @param height the minimum height of the frame. 505 */ 506 void setMinimumHeight(qreal height); 507 508 /** 509 * Return the minimum height of the shape. 510 * @return the minimum height of the shape. Default is 0.0. 511 */ 512 qreal minimumHeight() const; 513 514 515 /** 516 * Set the background of the shape. 517 * A shape background can be a plain color, a gradient, a pattern, be fully transparent 518 * or have a complex fill. 519 * Setting such a background will allow the shape to be filled and will be able to tell 520 * if it is transparent or not. 521 * @param background the new shape background. 522 */ 523 void setBackground(QSharedPointer<KoShapeBackground> background); 524 525 /** 526 * return the brush used to paint te background of this shape with. 527 * A QBrush can have a plain color, be fully transparent or have a complex fill. 528 * setting such a brush will allow the shape to fill itself using that brush and 529 * will be able to tell if its transparent or not. 530 * @return the background-brush 531 */ 532 QSharedPointer<KoShapeBackground> background() const; 533 534 /** 535 * Returns true if there is some transparency, false if the shape is fully opaque. 536 * The default implementation will just return if the background has some transparency, 537 * you should override it and always return true if your shape is not square. 538 * @return if the shape is (partly) transparent. 539 */ 540 virtual bool hasTransparency() const; 541 542 /** 543 * Sets shape level transparency. 544 * @param transparency the new shape level transparency 545 */ 546 void setTransparency(qreal transparency); 547 548 /** 549 * Returns the shape level transparency. 550 * @param recursive when true takes the parents transparency into account 551 */ 552 qreal transparency(bool recursive=false) const; 553 554 /** 555 * Retrieve the z-coordinate of this shape. 556 * The zIndex property is used to determine which shape lies on top of other objects. 557 * An shape with a higher z-order is on top, and can obscure another shape. 558 * @return the z-index of this shape. 559 * @see setZIndex() 560 */ 561 int zIndex() const; 562 563 /** 564 * Set the z-coordinate of this shape. 565 * The zIndex property is used to determine which shape lies on top of other objects. 566 * An shape with a higher z-order is on top, and can obscure, another shape. 567 * <p>Just like two objects having the same x or y coordinate will make them 'touch', 568 * so will two objects with the same z-index touch on the z plane. In layering the 569 * shape this, however, can cause a little confusion as one always has to be on top. 570 * The layering if two overlapping objects have the same index is implementation dependent 571 * and probably depends on the order in which they are added to the shape manager. 572 * @param zIndex the new z-index; 573 */ 574 void setZIndex(int zIndex); 575 576 /** 577 * Retrieve the run through property of this shape. 578 * The run through property is used to determine if the shape is behind, inside or before text. 579 * @return the run through of this shape. 580 */ 581 int runThrough(); 582 583 /** 584 * Set the run through property of this shape. 585 * The run through property is used to determine if the shape is behind, inside or before text. 586 * @param runThrough the new run through; 587 */ 588 virtual void setRunThrough(short int runThrough); 589 590 /** 591 * Changes the Shape to be visible or invisible. 592 * Being visible means being painted, as well as being used for 593 * things like guidelines or searches. 594 * @param on when true; set the shape to be visible. 595 * @see setGeometryProtected(), setContentProtected(), setSelectable() 596 */ 597 void setVisible(bool on); 598 /** 599 * Returns current visibility state of this shape. 600 * Being visible means being painted, as well as being used for 601 * things like guidelines or searches. 602 * @param recursive when true, checks visibility recursively 603 * @return current visibility state of this shape. 604 * @see isGeometryProtected(), isContentProtected(), isSelectable() 605 */ 606 bool isVisible(bool recursive = false) const; 607 608 /** 609 * Changes the shape to be printable or not. The default is true. 610 * 611 * If a Shape's print flag is true, the shape will be printed. If 612 * false, the shape will not be printed. If a shape is not visible (@see isVisible), 613 * it isPrinted will return false, too. 614 */ 615 void setPrintable(bool on); 616 617 /** 618 * Returns the current printable state of this shape. 619 * 620 * A shape can be visible but not printable, not printable and not visible 621 * or visible and printable, but not invisible and still printable. 622 * 623 * @return current printable state of this shape. 624 */ 625 bool isPrintable() const; 626 627 /** 628 * Makes it possible for the user to select this shape. 629 * This parameter defaults to true. 630 * @param selectable when true; set the shape to be selectable by the user. 631 * @see setGeometryProtected(), setContentProtected(), setVisible() 632 */ 633 void setSelectable(bool selectable); 634 635 /** 636 * Returns if this shape can be selected by the user. 637 * @return true only when the object is selectable. 638 * @see isGeometryProtected(), isContentProtected(), isVisible() 639 */ 640 bool isSelectable() const; 641 642 /** 643 * Tells the shape to have its position/rotation and size protected from user-changes. 644 * The geometry being protected means the user can not change shape or position of the 645 * shape. This includes any matrix operation such as rotation. 646 * @param on when true; set the shape to have its geometry protected. 647 * @see setContentProtected(), setSelectable(), setVisible() 648 */ 649 void setGeometryProtected(bool on); 650 651 /** 652 * Returns current geometry protection state of this shape. 653 * The geometry being protected means the user can not change shape or position of the 654 * shape. This includes any matrix operation such as rotation. 655 * @return current geometry protection state of this shape. 656 * @see isContentProtected(), isSelectable(), isVisible() 657 */ 658 bool isGeometryProtected() const; 659 660 /** 661 * Marks the shape to have its content protected against editing. 662 * Content protection is a hint for tools to disallow the user editing the content. 663 * @param protect when true set the shapes content to be protected from user modification. 664 * @see setGeometryProtected(), setSelectable(), setVisible() 665 */ 666 void setContentProtected(bool protect); 667 668 /** 669 * Returns current content protection state of this shape. 670 * Content protection is a hint for tools to disallow the user editing the content. 671 * @return current content protection state of this shape. 672 * @see isGeometryProtected(), isSelectable(), isVisible() 673 */ 674 bool isContentProtected() const; 675 676 /** 677 * Returns the parent, or 0 if there is no parent. 678 * @return the parent, or 0 if there is no parent. 679 */ 680 KoShapeContainer *parent() const; 681 682 /** 683 * Set the parent of this shape. 684 * @param parent the new parent of this shape. Can be 0 if the shape has no parent anymore. 685 */ 686 void setParent(KoShapeContainer *parent); 687 688 /** 689 * Request a repaint to be queued. 690 * The repaint will be of the entire Shape, including its selection handles should this 691 * shape be selected. 692 * <p>This method will return immediately and only request a repaint. Successive calls 693 * will be merged into an appropriate repaint action. 694 */ 695 virtual void update() const; 696 697 /** 698 * Request a repaint to be queued. 699 * The repaint will be restricted to the parameters rectangle, which is expected to be 700 * in points (the internal coordinates system of KoShape) and it is expected to be 701 * normalized. 702 * <p>This method will return immediately and only request a repaint. Successive calls 703 * will be merged into an appropriate repaint action. 704 * @param rect the rectangle (in pt) to queue for repaint. 705 */ 706 virtual void update(const QRectF &rect) const; 707 708 /// Used by compareShapeZIndex() to order shapes 709 enum ChildZOrderPolicy { 710 ChildZDefault, 711 ChildZParentChild = ChildZDefault, ///< normal parent/child ordering 712 ChildZPassThrough ///< children are considered equal to this shape 713 }; 714 715 /** 716 * Returns if during compareShapeZIndex() how this shape portrays the values 717 * of its children. The default behaviour is to let this shape's z values take 718 * the place of its children values, so you get a parent/child relationship. 719 * The children are naturally still ordered relatively to their z values 720 * 721 * But for special cases (like Calligra's TextShape) it can be overloaded to return 722 * ChildZPassThrough which means the children keep their own z values 723 * @returns the z order policy of this shape 724 */ 725 virtual ChildZOrderPolicy childZOrderPolicy(); 726 727 /** 728 * This is a method used to sort a list using the STL sorting methods. 729 * @param s1 the first shape 730 * @param s2 the second shape 731 */ 732 static bool compareShapeZIndex(KoShape *s1, KoShape *s2); 733 734 /** 735 * returns the outline of the shape in the form of a path. 736 * The outline returned will always be relative to the position() of the shape, so 737 * moving the shape will not alter the result. The outline is used to draw the stroke 738 * on, for example. 739 * @returns the outline of the shape in the form of a path. 740 */ 741 virtual QPainterPath outline() const; 742 743 /** 744 * returns the outline of the shape in the form of a rect. 745 * The outlineRect returned will always be relative to the position() of the shape, so 746 * moving the shape will not alter the result. The outline is used to calculate 747 * the boundingRect. 748 * @returns the outline of the shape in the form of a rect. 749 */ 750 virtual QRectF outlineRect() const; 751 752 /** 753 * returns the outline of the shape in the form of a path for the use of painting a shadow. 754 * 755 * Normally this would be the same as outline() if there is a fill (background) set on the 756 * shape and empty if not. However, a shape could reimplement this to return an outline 757 * even if no fill is defined. A typical example of this would be the picture shape 758 * which has a picture but almost never a background. 759 * 760 * @returns the outline of the shape in the form of a path. 761 */ 762 virtual QPainterPath shadowOutline() const; 763 764 /** 765 * Returns the currently set stroke, or 0 if there is no stroke. 766 * @return the currently set stroke, or 0 if there is no stroke. 767 */ 768 KoShapeStrokeModel *stroke() const; 769 770 /** 771 * Set a new stroke, removing the old one. 772 * @param stroke the new stroke, or 0 if there should be no stroke. 773 */ 774 void setStroke(KoShapeStrokeModel *stroke); 775 776 /** 777 * Return the insets of the stroke. 778 * Convenience method for KoShapeStrokeModel::strokeInsets() 779 */ 780 KoInsets strokeInsets() const; 781 782 /// Sets the new shadow, removing the old one 783 void setShadow(KoShapeShadow *shadow); 784 785 /// Returns the currently set shadow or 0 if there is no shadow set 786 KoShapeShadow *shadow() const; 787 788 /// Sets the new border, removing the old one. 789 void setBorder(KoBorder *border); 790 791 /// Returns the currently set border or 0 if there is no border set 792 KoBorder *border() const; 793 794 /// Sets a new clip path, removing the old one 795 void setClipPath(KoClipPath *clipPath); 796 797 /// Returns the currently set clip path or 0 if there is no clip path set 798 KoClipPath * clipPath() const; 799 800 /** 801 * Setting the shape to keep its aspect-ratio has the effect that user-scaling will 802 * keep the width/hight ratio intact so as not to distort shapes that rely on that 803 * ratio. 804 * @param keepAspect the new value 805 */ 806 void setKeepAspectRatio(bool keepAspect); 807 808 /** 809 * Setting the shape to keep its aspect-ratio has the effect that user-scaling will 810 * keep the width/hight ratio intact so as not to distort shapes that rely on that 811 * ratio. 812 * @return whether to keep aspect ratio of this shape 813 */ 814 bool keepAspectRatio() const; 815 816 /** 817 * Return the position of this shape regardless of rotation/skew/scaling and regardless of 818 * this shape having a parent (being in a group) or not.<br> 819 * @param anchor The place on the (unaltered) shape that you want the position of. 820 * @return the point that is the absolute, centered position of this shape. 821 */ 822 QPointF absolutePosition(KoFlake::Position anchor = KoFlake::CenteredPosition) const; 823 824 /** 825 * Move this shape to an absolute position where the end location will be the same 826 * regardless of the shape's rotation/skew/scaling and regardless of this shape having 827 * a parent (being in a group) or not.<br> 828 * The newPosition is going to be the center of the shape. 829 * This has the convenient effect that: <pre> 830 shape->setAbsolutePosition(QPointF(0,0)); 831 shape->rotate(45);</pre> 832 Will result in the same visual position of the shape as the opposite:<pre> 833 shape->rotate(45); 834 shape->setAbsolutePosition(QPointF(0,0));</pre> 835 * @param newPosition the new absolute center of the shape. 836 * @param anchor The place on the (unaltered) shape that you set the position of. 837 */ 838 void setAbsolutePosition(const QPointF &newPosition, KoFlake::Position anchor = KoFlake::CenteredPosition); 839 840 /** 841 * Set a data object on the shape to be used by an application. 842 * This is specifically useful when a shape is created in a plugin and that data from that 843 * shape should be accessible outside the plugin. 844 * @param userData the new user data, or 0 to delete the current one. 845 */ 846 void setUserData(KoShapeUserData *userData); 847 /** 848 * Return the current userData. 849 */ 850 KoShapeUserData *userData() const; 851 852 /** 853 * Set a data object on the shape to be used by an application. 854 * This is specifically useful when an application wants to have data that is per shape 855 * and should be deleted when the shape is destructed. 856 * @param applicationData the new application data, or 0 to delete the current one. 857 */ 858 void setApplicationData(KoShapeApplicationData *applicationData); 859 860 /** 861 * Return the current applicationData. 862 */ 863 KoShapeApplicationData *applicationData() const; 864 865 /** 866 * Return the Id of this shape, identifying the type of shape by the id of the factory. 867 * @see KoShapeFactoryBase::shapeId() 868 * @return the id of the shape-type 869 */ 870 QString shapeId() const; 871 872 /** 873 * Set the Id of this shape. A shapeFactory is expected to set the Id at creation 874 * so applications can find out what kind of shape this is. 875 * @see KoShapeFactoryBase::shapeId() 876 * @param id the ID from the factory that created this shape 877 */ 878 void setShapeId(const QString &id); 879 880 /** 881 * Create a matrix that describes all the transformations done on this shape. 882 * 883 * The absolute transformation is the combined transformation of this shape 884 * and all its parents and grandparents. 885 * 886 * @param converter if not null, this method uses the converter to mark the right 887 * offsets in the current view. 888 */ 889 QTransform absoluteTransformation(const KoViewConverter *converter) const; 890 891 /** 892 * Applies a transformation to this shape. 893 * 894 * The transformation given is relative to the global coordinate system, i.e. the document. 895 * This is a convenience function to apply a global transformation to this shape. 896 * @see applyTransformation 897 * 898 * @param matrix the transformation matrix to apply 899 */ 900 void applyAbsoluteTransformation(const QTransform &matrix); 901 902 /** 903 * Sets a new transformation matrix describing the local transformations on this shape. 904 * @param matrix the new transformation matrix 905 */ 906 void setTransformation(const QTransform &matrix); 907 908 /// Returns the shapes local transformation matrix 909 QTransform transformation() const; 910 911 /** 912 * Applies a transformation to this shape. 913 * 914 * The transformation given is relative to the shape coordinate system. 915 * 916 * @param matrix the transformation matrix to apply 917 */ 918 void applyTransformation(const QTransform &matrix); 919 920 /** 921 * Copy all the settings from the parameter shape and apply them to this shape. 922 * Settings like the position and rotation to visible and locked. The parent 923 * is a notable exclusion. 924 * @param shape the shape to use as original 925 */ 926 void copySettings(const KoShape *shape); 927 928 /** 929 * Convenience method that allows people implementing paint() to use the shape 930 * internal coordinate system directly to paint itself instead of considering the 931 * views zoom. 932 * @param painter the painter to alter the zoom level of. 933 * @param converter the converter for the current views zoom. 934 */ 935 static void applyConversion(QPainter &painter, const KoViewConverter &converter); 936 937 /** 938 * @brief Transforms point from shape coordinates to document coordinates 939 * @param point in shape coordinates 940 * @return point in document coordinates 941 */ 942 QPointF shapeToDocument(const QPointF &point) const; 943 944 /** 945 * @brief Transforms rect from shape coordinates to document coordinates 946 * @param rect in shape coordinates 947 * @return rect in document coordinates 948 */ 949 QRectF shapeToDocument(const QRectF &rect) const; 950 951 /** 952 * @brief Transforms point from document coordinates to shape coordinates 953 * @param point in document coordinates 954 * @return point in shape coordinates 955 */ 956 QPointF documentToShape(const QPointF &point) const; 957 958 /** 959 * @brief Transform rect from document coordinates to shape coordinates 960 * @param rect in document coordinates 961 * @return rect in shape coordinates 962 */ 963 QRectF documentToShape(const QRectF &rect) const; 964 965 /** 966 * Returns the name of the shape. 967 * @return the shapes name 968 */ 969 QString name() const; 970 971 /** 972 * Sets the name of the shape. 973 * @param name the new shape name 974 */ 975 void setName(const QString &name); 976 977 /** 978 * Update the position of the shape in the tree of the KoShapeManager. 979 */ 980 void notifyChanged(); 981 982 /** 983 * A shape can be in a state that it is doing processing data like loading or text layout. 984 * In this case it can be shown on screen probably partially but it should really not be printed 985 * until it is fully done processing. 986 * Warning! This method can be blocking for a long time 987 * @param converter The converter to convert between internal and view coordinates. 988 * @param asynchronous If set to true the processing will can take place in a different thread and the 989 * function will not block until the shape is finished. 990 * In case of printing Flake will call this method from a non-main thread and only 991 * start printing it when the in case of printing method returned. 992 * If set to false the processing needs to be done synchronously and will 993 * block until the result is finished. 994 */ 995 virtual void waitUntilReady(const KoViewConverter &converter, bool asynchronous = true) const; 996 997 /// checks recursively if the shape or one of its parents is not visible or locked 998 bool isEditable() const; 999 1000 /** 1001 * Adds a shape which depends on this shape. 1002 * Making a shape dependent on this one means it will get shapeChanged() called 1003 * on each update of this shape. 1004 * 1005 * If this shape already depends on the given shape, establishing the 1006 * dependency is refused to prevent circular dependencies. 1007 * 1008 * @param shape the shape which depends on this shape 1009 * @return true if dependency could be established, otherwise false 1010 * @see removeDependee(), hasDependee() 1011 */ 1012 bool addDependee(KoShape *shape); 1013 1014 /** 1015 * Removes as shape depending on this shape. 1016 * @see addDependee(), hasDependee() 1017 */ 1018 void removeDependee(KoShape *shape); 1019 1020 /// Returns if the given shape is dependent on this shape 1021 bool hasDependee(KoShape *shape) const; 1022 1023 /// Returns list of shapes depending on this shape 1024 QList<KoShape*> dependees() const; 1025 1026 /// Returns additional snap data the shape wants to have snapping to 1027 virtual KoSnapData snapData() const; 1028 1029 /** 1030 * Set additional attribute 1031 * 1032 * This can be used to attach additional attributes to a shape for attributes 1033 * that are application specific like presentation:placeholder 1034 * 1035 * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder 1036 * @param value The value of the attribute 1037 */ 1038 void setAdditionalAttribute(const QString &name, const QString &value); 1039 1040 /** 1041 * Remove additional attribute 1042 * 1043 * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder 1044 */ 1045 void removeAdditionalAttribute(const QString &name); 1046 1047 /** 1048 * Check if additional attribute is set 1049 * 1050 * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder 1051 * 1052 * @return true if there is a attribute with prefix:tag set, false otherwise 1053 */ 1054 bool hasAdditionalAttribute(const QString &name) const; 1055 1056 /** 1057 * Get additional attribute 1058 * 1059 * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder 1060 * 1061 * @return The value of the attribute if it exists or a null string if not found. 1062 */ 1063 QString additionalAttribute(const QString &name) const; 1064 1065 void setAdditionalStyleAttribute(const char *name, const QString &value); 1066 1067 void removeAdditionalStyleAttribute(const char *name); 1068 1069 QString additionalStyleAttribute(const QByteArray &name) const; 1070 1071 QMap<QByteArray, QString> additionalStyleAttributes() const; 1072 1073 /** 1074 * Returns the filter effect stack of the shape 1075 * 1076 * @return the list of filter effects applied on the shape when rendering. 1077 */ 1078 KoFilterEffectStack *filterEffectStack() const; 1079 1080 /// Sets the new filter effect stack, removing the old one 1081 void setFilterEffectStack(KoFilterEffectStack *filterEffectStack); 1082 1083 /** 1084 * Set the property collision detection. 1085 * Setting this to true will result in calls to shapeChanged() with the CollisionDetected 1086 * parameter whenever either this or another shape is moved/rotated etc and intersects this shape. 1087 * @param detect if true detect collisions. 1088 */ 1089 void setCollisionDetection(bool detect); 1090 1091 /** 1092 * get the property collision detection. 1093 * @returns true if collision detection is on. 1094 */ 1095 bool collisionDetection(); 1096 1097 /** 1098 * Return the tool delegates for this shape. 1099 * In Flake a shape being selected will cause the tool manager to make available all tools that 1100 * can edit the selected shapes. In some cases selecting one shape should allow the tool to 1101 * edit a related shape be available too. The tool delegates allows this to happen by taking 1102 * all the shapes in the set into account on tool selection. 1103 * Notice that if the set is non-empty 'this' shape is no longer looked at. You can choose 1104 * to add itself to the set too. 1105 */ 1106 QSet<KoShape*> toolDelegates() const; 1107 1108 /** 1109 * Set the tool delegates. 1110 * @param delegates the new delegates. 1111 * @see toolDelegates() 1112 */ 1113 void setToolDelegates(const QSet<KoShape*> &delegates); 1114 1115 /** 1116 * Return the hyperlink for this shape. 1117 */ 1118 QString hyperLink () const; 1119 1120 /** 1121 * Set hyperlink for this shape. 1122 * @param hyperLink name. 1123 */ 1124 void setHyperLink(const QString &hyperLink); 1125 1126 /** 1127 * Makes it possible for the user to delete this shape. 1128 * This parameter defaults to true. 1129 * @param deletable when true; set the shape to be deletable by the user. 1130 * @see isDeletable(), setGeometryProtected(), setContentProtected(), setSelectable() 1131 */ 1132 void setDeletable(bool deletable); 1133 1134 /** 1135 * Returns if this shape can be deleted by the user. 1136 * @return true only when this shape is deletable. 1137 * @see setDeletable(), isGeometryProtected(), isContentProtected(), isSelectable() 1138 */ 1139 bool isDeletable() const; 1140 1141 /// Sets the AllowedInteraction @p flag to @p value 1142 void setAllowedInteraction(AllowedInteraction flag, bool value); 1143 /// @return the AllowedInteraction state for @p flag. 1144 /// Convenience method that just calls allowedInteractions(recursive).testFlag(flag). 1145 /// @see allowedInteractions() 1146 bool allowedInteraction(AllowedInteraction flag, bool recursive = true) const; 1147 /// Sets the interactions the user is allowed to perform on this shape to @p interactions 1148 void setAllowedInteractions(AllowedInteractions interactions); 1149 /// @return the interactions the user is allowed to perform on this shape. 1150 /// If @p recursive is false, the shapes flags are returned as is. Use this e.g. for ui. 1151 /// If @p recursive is true: 1152 /// If the shape is not visible, no interactions are allowed. 1153 /// If there is a parent, the parent is checked. 1154 /// 1155 /// @see KoShapeContainer::allowedInteractions() 1156 AllowedInteractions allowedInteractions(bool recursive = true) const; 1157 1158 /** 1159 * \internal 1160 * Returns the private object for use within the flake lib 1161 */ 1162 KoShapePrivate *priv(); 1163 1164 protected: 1165 /// constructor 1166 KoShape(KoShapePrivate &); 1167 1168 /* ** loading saving helper methods */ 1169 /// attributes from ODF 1.1 chapter 9.2.15 Common Drawing Shape Attributes 1170 enum OdfAttribute { 1171 OdfTransformation = 1, ///< Store transformation information 1172 OdfSize = 2, ///< Store size information 1173 OdfPosition = 8, ///< Store position 1174 OdfAdditionalAttributes = 4, ///< Store additional attributes of the shape 1175 OdfCommonChildElements = 16, ///< Event actions and connection points 1176 OdfLayer = 64, ///< Store layer name 1177 OdfStyle = 128, ///< Store the style 1178 OdfId = 256, ///< Store the unique ID 1179 OdfName = 512, ///< Store the name of the shape 1180 OdfZIndex = 1024, ///< Store the z-index 1181 OdfViewbox = 2048, ///< Store the viewbox 1182 1183 /// A mask for all mandatory attributes 1184 OdfMandatories = OdfLayer | OdfStyle | OdfId | OdfName | OdfZIndex, 1185 /// A mask for geometry attributes 1186 OdfGeometry = OdfPosition | OdfSize, 1187 /// A mask for all the attributes 1188 OdfAllAttributes = OdfTransformation | OdfGeometry | OdfAdditionalAttributes | OdfMandatories | OdfCommonChildElements 1189 }; 1190 1191 /** 1192 * This method is used during loading of the shape to load common attributes 1193 * 1194 * @param context the KoShapeLoadingContext used for loading 1195 * @param element element which represents the shape in odf 1196 * @param attributes a number of OdfAttribute items to state which attributes to load. 1197 */ 1198 bool loadOdfAttributes(const KoXmlElement &element, KoShapeLoadingContext &context, int attributes); 1199 1200 /** 1201 * Parses the transformation attribute from the given string 1202 * @param transform the transform attribute string 1203 * @param context the loading context 1204 * @return the resulting transformation matrix 1205 */ 1206 QTransform parseOdfTransform(const QString &transform, KoShapeLoadingContext &context); 1207 1208 /** 1209 * @brief Saves the style used for the shape 1210 * 1211 * This method fills the given style object with the stroke and 1212 * background properties and then adds the style to the context. 1213 * 1214 * @param style the style object to fill 1215 * @param context used for saving 1216 * @return the name of the style 1217 * @see saveOdf 1218 */ 1219 virtual QString saveStyle(KoGenStyle &style, KoShapeSavingContext &context) const; 1220 1221 /** 1222 * Loads the stroke and fill style from the given element. 1223 * 1224 * @param element the xml element to load the style from 1225 * @param context the loading context used for loading 1226 */ 1227 virtual void loadStyle(const KoXmlElement &element, KoShapeLoadingContext &context); 1228 1229 /// Loads the stroke style 1230 KoShapeStrokeModel *loadOdfStroke(const KoXmlElement &element, KoShapeLoadingContext &context) const; 1231 1232 /// Loads the fill style 1233 QSharedPointer<KoShapeBackground> loadOdfFill(KoShapeLoadingContext &context) const; 1234 1235 /// Loads the connection points 1236 void loadOdfGluePoints(const KoXmlElement &element, KoShapeLoadingContext &context); 1237 1238 /// Loads the clip contour 1239 void loadOdfClipContour(const KoXmlElement &element, KoShapeLoadingContext &context, const QSizeF &scaleFactor); 1240 1241 /* ** end loading saving */ 1242 1243 /** 1244 * A hook that allows inheriting classes to do something after a KoShape property changed 1245 * This is called whenever the shape, position rotation or scale properties were altered. 1246 * @param type an indicator which type was changed. 1247 * @param shape the shape. 1248 */ 1249 virtual void shapeChanged(ChangeType type, KoShape *shape = 0); 1250 1251 /// return the current matrix that contains the rotation/scale/position of this shape 1252 QTransform transform() const; 1253 1254 KoShapePrivate *d_ptr; 1255 1256 private: 1257 Q_DECLARE_PRIVATE(KoShape) 1258 }; 1259 1260 Q_DECLARE_METATYPE(KoShape*) 1261 Q_DECLARE_OPERATORS_FOR_FLAGS(KoShape::AllowedInteractions) 1262 1263 #endif 1264