File indexing completed on 2024-06-02 03:59:20
0001 /* 0002 SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo@kde.org> 0003 SPDX-FileCopyrightText: 2008 Marco Martin <notmart@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef KSVG_FRAMESVG_H 0009 #define KSVG_FRAMESVG_H 0010 0011 #include <QObject> 0012 #include <QPixmap> 0013 0014 #include <ksvg/ksvg_export.h> 0015 0016 #include <ksvg/svg.h> 0017 0018 class QPainter; 0019 class QPoint; 0020 class QPointF; 0021 class QRect; 0022 class QRectF; 0023 class QSize; 0024 class QSizeF; 0025 class QMatrix; 0026 0027 namespace KSvg 0028 { 0029 class FrameSvgPrivate; 0030 0031 /** 0032 * @class FrameSvg ksvg/framesvg.h <KSvg/FrameSvg> 0033 * 0034 * @short Provides an SVG with borders. 0035 * 0036 * When using SVG images for a background of an object that may change 0037 * its aspect ratio, such as a dialog, simply scaling a single image 0038 * may not be enough. 0039 * 0040 * FrameSvg allows SVGs to provide several elements for borders as well 0041 * as a central element, each of which are scaled individually. These elements 0042 * should be named: 0043 * * @c center - the central element, which will be scaled in both directions 0044 * * @c top - the top border; the height is fixed, but it will be scaled 0045 * horizontally to the same width as @c center 0046 * * @c bottom - the bottom border; scaled in the same way as @c top 0047 * * @c left - the left border; the width is fixed, but it will be scaled 0048 * vertically to the same height as @c center 0049 * * @c right - the right border; scaled in the same way as @c left 0050 * * @c topleft - fixed size; must be the same height as @c top and the same 0051 * width as @c left 0052 * * @c bottomleft, @c topright, @c bottomright - similar to @c topleft 0053 * 0054 * @c center must exist, but all the others are optional. @c topleft and 0055 * @c topright will be ignored if @c top does not exist, and similarly for 0056 * @c bottomleft and @c bottomright. 0057 * 0058 * @see KSvg::Svg 0059 **/ 0060 class KSVG_EXPORT FrameSvg : public Svg 0061 { 0062 Q_OBJECT 0063 0064 Q_PROPERTY(EnabledBorders enabledBorders READ enabledBorders WRITE setEnabledBorders) 0065 0066 public: 0067 /** 0068 * @brief This flag enum specifies which borders should be drawn. 0069 */ 0070 enum EnabledBorder { 0071 NoBorder = 0, 0072 TopBorder = 1, 0073 BottomBorder = 2, 0074 LeftBorder = 4, 0075 RightBorder = 8, 0076 AllBorders = TopBorder | BottomBorder | LeftBorder | RightBorder, 0077 }; 0078 Q_DECLARE_FLAGS(EnabledBorders, EnabledBorder) 0079 Q_FLAG(EnabledBorders) 0080 0081 // TODO: merge those two? 0082 enum LocationPrefix { 0083 Floating = 0, /**< Free floating.*/ 0084 TopEdge, /**< Along the top of the screen*/ 0085 BottomEdge, /**< Along the bottom of the screen*/ 0086 LeftEdge, /**< Along the left side of the screen */ 0087 RightEdge, /**< Along the right side of the screen */ 0088 }; 0089 Q_ENUM(LocationPrefix) 0090 0091 enum MarginEdge { 0092 TopMargin = 0, /**< The top margin **/ 0093 BottomMargin, /**< The bottom margin **/ 0094 LeftMargin, /**< The left margin **/ 0095 RightMargin, /**< The right margin **/ 0096 }; 0097 Q_ENUM(MarginEdge) 0098 0099 /** 0100 * Constructs a new FrameSvg that paints the proper named subelements 0101 * as borders. It may also be used as a regular KSvg::Svg object 0102 * for direct access to elements in the Svg. 0103 * 0104 * @param parent options QObject to parent this to 0105 * 0106 * @related KSvg::Theme 0107 */ 0108 explicit FrameSvg(QObject *parent = nullptr); 0109 ~FrameSvg() override; 0110 0111 /** 0112 * Loads a new Svg 0113 * @param imagePath the new file 0114 */ 0115 Q_INVOKABLE void setImagePath(const QString &path) override; 0116 0117 /** 0118 * @brief This method sets which borders should be painted. 0119 * @param flags borders we want to paint 0120 * 0121 * @see ::EnabledBorder 0122 * @param borders 0123 */ 0124 void setEnabledBorders(const EnabledBorders borders); 0125 0126 /** 0127 * @brief This is a convenience method to get the enabled borders. 0128 * @return what borders are painted 0129 */ 0130 EnabledBorders enabledBorders() const; 0131 0132 /** 0133 * @brief This method resizes the frame, maintaining the same border size. 0134 * @param size the new size of the frame 0135 */ 0136 Q_INVOKABLE void resizeFrame(const QSizeF &size); 0137 0138 /** 0139 * @returns the size of the frame 0140 */ 0141 Q_INVOKABLE QSizeF frameSize() const; 0142 0143 /** 0144 * 0145 * @brief This method returns the margin size for the given edge. 0146 * 0147 * Note that @c 0 will be returned if the given margin is disabled. 0148 * 0149 * If you don't care about the margin being on or off, use 0150 * ::fixedMarginSize() instead. 0151 * 0152 * @param edge the margin edge we want, top, bottom, left or right 0153 * @return the margin size 0154 */ 0155 Q_INVOKABLE qreal marginSize(const FrameSvg::MarginEdge edge) const; 0156 0157 /** 0158 * @brief This is a convenience method that extracts the size of the four 0159 * margins and saves their size into the passed variables. 0160 * 0161 * If you don't care about the margins being on or off, use 0162 * ::getFixedMargins() instead. 0163 * 0164 * @param left left margin size 0165 * @param top top margin size 0166 * @param right right margin size 0167 * @param bottom bottom margin size 0168 */ 0169 Q_INVOKABLE void getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0170 0171 /** 0172 * @brief This method returns the margin size for the specified edge. 0173 * 0174 * Compared to ::marginSize(), this does not depend on whether the margin is 0175 * enabled or not. 0176 * 0177 * @param edge the margin edge we want, top, bottom, left or right 0178 * @return the margin size 0179 */ 0180 Q_INVOKABLE qreal fixedMarginSize(const FrameSvg::MarginEdge edge) const; 0181 0182 /** 0183 * @brief This is a convenience method that extracts the size of the four 0184 * margins and saves their size into the passed variables. 0185 * 0186 * Compared to ::getMargins(), this doesn't depend on whether the margins are 0187 * enabled or not. 0188 * 0189 * @param left left margin size 0190 * @param top top margin size 0191 * @param right right margin size 0192 * @param bottom bottom margin size 0193 */ 0194 Q_INVOKABLE void getFixedMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0195 0196 /** 0197 * @brief This method returns the insets margin size for the specified edge. 0198 * @param edge the margin edge we want, top, bottom, left or right 0199 * @return the margin size 0200 * @since 5.77 0201 */ 0202 Q_INVOKABLE qreal insetSize(const FrameSvg::MarginEdge edge) const; 0203 0204 /** 0205 * @brief This is a convenience method that extracts the size of the four 0206 * inset margins and saves their size into the passed variables. 0207 * 0208 * @param left left margin size 0209 * @param top top margin size 0210 * @param right right margin size 0211 * @param bottom bottom margin size 0212 * @since 5.77 0213 */ 0214 Q_INVOKABLE void getInset(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0215 0216 /** 0217 * @brief This method returns the rectangle of the center element, taking 0218 * the margins into account. 0219 */ 0220 Q_INVOKABLE QRectF contentsRect() const; 0221 0222 /** 0223 * @brief This method sets the prefix (@see setElementPrefix) to 'north', 0224 * 'south', 'west' and 'east' when the location is TopEdge, BottomEdge, 0225 * LeftEdge and RightEdge, respectively. Clears the prefix in other cases. 0226 * 0227 * The prefix must exist in the SVG document, which means that this can only 0228 * be called successfully after setImagePath is called. 0229 * 0230 * @param location location in the UI this frame will be drawn 0231 */ 0232 Q_INVOKABLE void setElementPrefix(KSvg::FrameSvg::LocationPrefix location); 0233 0234 /** 0235 * @brief This method sets the prefix for the SVG elements to be used for 0236 * painting. 0237 * 0238 * For example, if prefix is 'active', then instead of using the 'top' 0239 * element of the SVG file to paint the top border, the 'active-top' element 0240 * will be used. The same goes for other SVG elements. 0241 * 0242 * If the elements with prefixes are not present, the default ones are used. 0243 * (for the sake of speed, the test is present only for the 'center' element) 0244 * 0245 * Setting the prefix manually resets the location to Floating. 0246 * 0247 * The prefix must exist in the SVG document, which means that this can only be 0248 * called successfully after setImagePath is called. 0249 * 0250 * @param prefix prefix for the SVG elements that make up the frame 0251 */ 0252 Q_INVOKABLE void setElementPrefix(const QString &prefix); 0253 0254 /** 0255 * @brief This method returns whether the SVG has the necessary elements 0256 * with the given prefix to draw a frame. 0257 * 0258 * @param prefix the given prefix we want to check if drawable (can have trailing '-' since 5.59) 0259 */ 0260 Q_INVOKABLE bool hasElementPrefix(const QString &prefix) const; 0261 0262 /** 0263 * @brief This is an overloaded method provided for convenience that is 0264 * equivalent to hasElementPrefix("north"), hasElementPrefix("south") 0265 * hasElementPrefix("west") and hasElementPrefix("east"). 0266 * 0267 * @return true if the svg has the necessary elements with the given prefix 0268 * to draw a frame. 0269 * 0270 * @param location the given prefix we want to check if drawable 0271 */ 0272 Q_INVOKABLE bool hasElementPrefix(KSvg::FrameSvg::LocationPrefix location) const; 0273 0274 /** 0275 * @brief This method returns the prefix for SVG elements of the FrameSvg 0276 * (including a '-' at the end if not empty). 0277 * 0278 * @return the prefix 0279 * @see actualPrefix() 0280 */ 0281 Q_INVOKABLE QString prefix(); 0282 0283 /** 0284 * @brief This method returns a mask that tightly contains the fully opaque 0285 * areas of the SVG. 0286 * 0287 * @return a region of opaque areas 0288 */ 0289 Q_INVOKABLE QRegion mask() const; 0290 0291 /** 0292 * @brief This method returns a pixmap whose alpha channel is the opacity of 0293 * the frame. It may be the frame itself or a special frame with the 0294 * "mask-" prefix. 0295 */ 0296 QPixmap alphaMask() const; 0297 0298 /** 0299 * @brief This method sets whether saving all the rendered prefixes in a 0300 * cache or not. 0301 * 0302 * @param cache whether to use the cache. 0303 */ 0304 Q_INVOKABLE void setCacheAllRenderedFrames(bool cache); 0305 0306 /** 0307 * @brief This method returns whether all the different prefixes should be 0308 * kept in a cache when rendered. 0309 */ 0310 Q_INVOKABLE bool cacheAllRenderedFrames() const; 0311 0312 /** 0313 * @brief This method deletes the internal cache. 0314 * 0315 * Calling this method frees memeory. Use this if you want to switch the 0316 * rendered element and you don't plan to switch back to the previous one 0317 * for a long time. 0318 * 0319 * This only works if setUsingRenderingCache(@c true) has been called. 0320 * 0321 * @see KSvg::Svg::setUsingRenderingCache() 0322 */ 0323 Q_INVOKABLE void clearCache(); 0324 0325 /** 0326 * @brief This method returns a pixmap of the SVG represented by this 0327 * object. 0328 * 0329 * @param elelementId the ID string of the element to render, or an empty 0330 * string for the whole SVG (the default). 0331 * 0332 * @return a QPixmap of the rendered SVG 0333 */ 0334 Q_INVOKABLE QPixmap framePixmap(); 0335 0336 /** 0337 * @brief This method paints the loaded SVG with the elements that 0338 * represents the border. 0339 * 0340 * @param painter the QPainter to use 0341 * @param target the target rectangle on the paint device 0342 * @param source the portion rectangle of the source image 0343 */ 0344 Q_INVOKABLE void paintFrame(QPainter *painter, const QRectF &target, const QRectF &source = QRectF()); 0345 0346 /** 0347 * @brief This method paints the loaded SVG with the elements that 0348 * represents the border. 0349 * 0350 * This is an overloaded member provided for convenience 0351 * 0352 * @param painter the QPainter to use 0353 * @param pos where to paint the svg 0354 */ 0355 Q_INVOKABLE void paintFrame(QPainter *painter, const QPointF &pos = QPointF(0, 0)); 0356 0357 /** 0358 * @brief This method returns the prefix that is actually being used 0359 * (including a '-' at the end if not empty). 0360 * 0361 * @see ::prefix() 0362 */ 0363 QString actualPrefix() const; 0364 0365 /** 0366 * @brief This method returns whether we are in a transaction of many 0367 * changes at once. 0368 * 0369 * This is used to restrict rebuilding generated graphics for each change 0370 * made. 0371 * 0372 * @since 5.31 0373 */ 0374 bool isRepaintBlocked() const; 0375 0376 /** 0377 * @brief This method sets whether we should block rebuilding generated 0378 * graphics for each change made. 0379 * 0380 * Setting this to @c true will block rebuilding the generated graphics for 0381 * each change made and will do these changes in blocks instead. 0382 * 0383 * How to use this method: 0384 * When making several changes at once to the frame properties--such as 0385 * prefix, enabled borders, and size--set this property to true to avoid 0386 * regenerating the graphics for each change. Set it to false again after 0387 * applying all required changes. 0388 * 0389 * Note that any change will not be visible in the painted frame while this 0390 * property is set to true. 0391 * @since 5.31 0392 */ 0393 void setRepaintBlocked(bool blocked); 0394 0395 /** 0396 * @brief This method returns the minimum height required to correctly draw 0397 * this SVG. 0398 * 0399 * @since 5.101 0400 */ 0401 Q_INVOKABLE int minimumDrawingHeight(); 0402 0403 /** 0404 * @brief This method returns the minimum width required to correctly draw 0405 * this SVG. 0406 * 0407 * @since 5.101 0408 */ 0409 Q_INVOKABLE int minimumDrawingWidth(); 0410 0411 private: 0412 FrameSvgPrivate *const d; 0413 friend class FrameData; 0414 }; 0415 0416 Q_DECLARE_OPERATORS_FOR_FLAGS(FrameSvg::EnabledBorders) 0417 0418 } // KSvg namespace 0419 0420 #endif // multiple inclusion guard