File indexing completed on 2023-10-01 04:11:44
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 PLASMA_FRAMESVG_H 0009 #define PLASMA_FRAMESVG_H 0010 0011 #include <QObject> 0012 #include <QPixmap> 0013 0014 #include <plasma/plasma_export.h> 0015 0016 #include <plasma/plasma.h> 0017 #include <plasma/svg.h> 0018 0019 class QPainter; 0020 class QPoint; 0021 class QPointF; 0022 class QRect; 0023 class QRectF; 0024 class QSize; 0025 class QSizeF; 0026 class QMatrix; 0027 0028 namespace Plasma 0029 { 0030 class FrameSvgPrivate; 0031 0032 /** 0033 * @class FrameSvg plasma/framesvg.h <Plasma/FrameSvg> 0034 * 0035 * @short Provides an SVG with borders. 0036 * 0037 * When using SVG images for a background of an object that may change 0038 * its aspect ratio, such as a dialog, simply scaling a single image 0039 * may not be enough. 0040 * 0041 * FrameSvg allows SVGs to provide several elements for borders as well 0042 * as a central element, each of which are scaled individually. These 0043 * elements should be named 0044 * 0045 * - @c center - the central element, which will be scaled in both directions 0046 * - @c top - the top border; the height is fixed, but it will be scaled 0047 * horizontally to the same width as @c center 0048 * - @c bottom - the bottom border; scaled in the same way as @c top 0049 * - @c left - the left border; the width is fixed, but it will be scaled 0050 * vertically to the same height as @c center 0051 * - @c right - the right border; scaled in the same way as @c left 0052 * - @c topleft - fixed size; must be the same height as @c top and the same 0053 * width as @c left 0054 * - @c bottomleft, @c topright, @c bottomright - similar to @c topleft 0055 * 0056 * @c center must exist, but all the others are optional. @c topleft and 0057 * @c topright will be ignored if @c top does not exist, and similarly for 0058 * @c bottomleft and @c bottomright. 0059 * 0060 * @see Plasma::Svg 0061 **/ 0062 class PLASMA_EXPORT FrameSvg : public Svg 0063 { 0064 Q_OBJECT 0065 0066 Q_PROPERTY(EnabledBorders enabledBorders READ enabledBorders WRITE setEnabledBorders) 0067 0068 public: 0069 /** 0070 * These flags represents what borders should be drawn 0071 */ 0072 enum EnabledBorder { 0073 NoBorder = 0, 0074 TopBorder = 1, 0075 BottomBorder = 2, 0076 LeftBorder = 4, 0077 RightBorder = 8, 0078 AllBorders = TopBorder | BottomBorder | LeftBorder | RightBorder, 0079 }; 0080 Q_DECLARE_FLAGS(EnabledBorders, EnabledBorder) 0081 Q_FLAG(EnabledBorders) 0082 0083 /** 0084 * Constructs a new FrameSvg that paints the proper named subelements 0085 * as borders. It may also be used as a regular Plasma::Svg object 0086 * for direct access to elements in the Svg. 0087 * 0088 * @param parent options QObject to parent this to 0089 * 0090 * @related Plasma::Theme 0091 */ 0092 explicit FrameSvg(QObject *parent = nullptr); 0093 ~FrameSvg() override; 0094 0095 /** 0096 * Loads a new Svg 0097 * @param imagePath the new file 0098 */ 0099 Q_INVOKABLE void setImagePath(const QString &path) override; 0100 0101 /** 0102 * Sets what borders should be painted 0103 * @param flags borders we want to paint 0104 */ 0105 void setEnabledBorders(const EnabledBorders borders); 0106 0107 /** 0108 * Convenience method to get the enabled borders 0109 * @return what borders are painted 0110 */ 0111 EnabledBorders enabledBorders() const; 0112 0113 /** 0114 * Resize the frame maintaining the same border size 0115 * @param size the new size of the frame 0116 */ 0117 Q_INVOKABLE void resizeFrame(const QSizeF &size); 0118 0119 /** 0120 * @returns the size of the frame 0121 */ 0122 Q_INVOKABLE QSizeF frameSize() const; 0123 0124 /** 0125 * Returns the margin size given the margin edge we want 0126 * If the given margin is disabled, it will return 0. 0127 * If you don't care about the margin being on or off, use fixedMarginSize() 0128 * @param edge the margin edge we want, top, bottom, left or right 0129 * @return the margin size 0130 */ 0131 Q_INVOKABLE qreal marginSize(const Plasma::Types::MarginEdge edge) const; 0132 0133 /** 0134 * Convenience method that extracts the size of the four margins 0135 * in the four output parameters 0136 * The disabled margins will be 0. 0137 * If you don't care about the margins being on or off, use getFixedMargins() 0138 * @param left left margin size 0139 * @param top top margin size 0140 * @param right right margin size 0141 * @param bottom bottom margin size 0142 */ 0143 Q_INVOKABLE void getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0144 0145 /** 0146 * Returns the margin size given the margin edge we want. 0147 * Compared to marginSize(), this doesn't depend whether the margin is enabled or not 0148 * @param edge the margin edge we want, top, bottom, left or right 0149 * @return the margin size 0150 */ 0151 Q_INVOKABLE qreal fixedMarginSize(const Plasma::Types::MarginEdge edge) const; 0152 0153 /** 0154 * Convenience method that extracts the size of the four margins 0155 * in the four output parameters 0156 * Compared to getMargins(), this doesn't depend whether the margins are enabled or not 0157 * @param left left margin size 0158 * @param top top margin size 0159 * @param right right margin size 0160 * @param bottom bottom margin size 0161 */ 0162 Q_INVOKABLE void getFixedMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0163 0164 /** 0165 * Returns the insets margin size given the margin edge we want. 0166 * @param edge the margin edge we want, top, bottom, left or right 0167 * @return the margin size 0168 * @since 5.77 0169 */ 0170 Q_INVOKABLE qreal insetSize(const Plasma::Types::MarginEdge edge) const; 0171 0172 /** 0173 * Convenience method that extracts the size of the four inset margins 0174 * in the four output parameters 0175 * @param left left margin size 0176 * @param top top margin size 0177 * @param right right margin size 0178 * @param bottom bottom margin size 0179 * @since 5.77 0180 */ 0181 Q_INVOKABLE void getInset(qreal &left, qreal &top, qreal &right, qreal &bottom) const; 0182 0183 /** 0184 * @return the rectangle of the center element, taking the margins into account. 0185 */ 0186 Q_INVOKABLE QRectF contentsRect() const; 0187 0188 /** 0189 * Sets the prefix (@see setElementPrefix) to 'north', 'south', 'west' and 'east' 0190 * when the location is TopEdge, BottomEdge, LeftEdge and RightEdge, 0191 * respectively. Clears the prefix in other cases. 0192 * 0193 * The prefix must exist in the SVG document, which means that this can only be 0194 * called successfully after setImagePath is called. 0195 * @param location location in the UI this frame will be drawn 0196 */ 0197 Q_INVOKABLE void setElementPrefix(Plasma::Types::Location location); 0198 0199 /** 0200 * Sets the prefix for the SVG elements to be used for painting. For example, 0201 * if prefix is 'active', then instead of using the 'top' element of the SVG 0202 * file to paint the top border, 'active-top' element will be used. The same 0203 * goes for other SVG elements. 0204 * 0205 * If the elements with prefixes are not present, the default ones are used. 0206 * (for the sake of speed, the test is present only for the 'center' element) 0207 * 0208 * Setting the prefix manually resets the location to Floating. 0209 * 0210 * The prefix must exist in the SVG document, which means that this can only be 0211 * called successfully after setImagePath is called. 0212 * 0213 * @param prefix prefix for the SVG elements that make up the frame 0214 */ 0215 Q_INVOKABLE void setElementPrefix(const QString &prefix); 0216 0217 /** 0218 * @return true if the svg has the necessary elements with the given prefix 0219 * to draw a frame 0220 * @param prefix the given prefix we want to check if drawable (can have trailing '-' since 5.59) 0221 */ 0222 Q_INVOKABLE bool hasElementPrefix(const QString &prefix) const; 0223 0224 /** 0225 * This is an overloaded method provided for convenience equivalent to 0226 * hasElementPrefix("north"), hasElementPrefix("south") 0227 * hasElementPrefix("west") and hasElementPrefix("east") 0228 * @return true if the svg has the necessary elements with the given prefix 0229 * to draw a frame. 0230 * @param location the given prefix we want to check if drawable 0231 */ 0232 Q_INVOKABLE bool hasElementPrefix(Plasma::Types::Location location) const; 0233 0234 /** 0235 * Returns the prefix for SVG elements of the FrameSvg (including a '-' at the end if not empty) 0236 * @return the prefix 0237 * @sa actualPrefix() 0238 */ 0239 Q_INVOKABLE QString prefix(); 0240 0241 /** 0242 * Returns a mask that tightly contains the fully opaque areas of the svg 0243 * @return a region of opaque areas 0244 */ 0245 Q_INVOKABLE QRegion mask() const; 0246 0247 /** 0248 * @return a pixmap whose alpha channel is the opacity of the frame. It may be the frame itself or a special frame with the mask- prefix 0249 */ 0250 QPixmap alphaMask() const; 0251 0252 /** 0253 * Sets whether saving all the rendered prefixes in a cache or not 0254 * @param cache if use the cache or not 0255 */ 0256 Q_INVOKABLE void setCacheAllRenderedFrames(bool cache); 0257 0258 /** 0259 * @return if all the different prefixes should be kept in a cache when rendered 0260 */ 0261 Q_INVOKABLE bool cacheAllRenderedFrames() const; 0262 0263 /** 0264 * Deletes the internal cache freeing memory: use this if you want to switch the rendered 0265 * element and you don't plan to switch back to the previous one for a long time and you 0266 * used setUsingRenderingCache(true) 0267 */ 0268 Q_INVOKABLE void clearCache(); 0269 0270 /** 0271 * Returns a pixmap of the SVG represented by this object. 0272 * 0273 * @param elelementId the ID string of the element to render, or an empty 0274 * string for the whole SVG (the default) 0275 * @return a QPixmap of the rendered SVG 0276 */ 0277 Q_INVOKABLE QPixmap framePixmap(); 0278 0279 /** 0280 * Paints the loaded SVG with the elements that represents the border 0281 * @param painter the QPainter to use 0282 * @param target the target rectangle on the paint device 0283 * @param source the portion rectangle of the source image 0284 */ 0285 Q_INVOKABLE void paintFrame(QPainter *painter, const QRectF &target, const QRectF &source = QRectF()); 0286 0287 /** 0288 * Paints the loaded SVG with the elements that represents the border 0289 * This is an overloaded member provided for convenience 0290 * @param painter the QPainter to use 0291 * @param pos where to paint the svg 0292 */ 0293 Q_INVOKABLE void paintFrame(QPainter *painter, const QPointF &pos = QPointF(0, 0)); 0294 0295 /** 0296 * @returns the prefix that is actually used (including a '-' at the end if not empty) 0297 * @sa prefix() 0298 */ 0299 QString actualPrefix() const; 0300 0301 /** 0302 * @returns true if we are in a transaction of many changes at once 0303 * and we don't want to rebuild the generated graphics for each change yet 0304 * @since 5.31 0305 */ 0306 bool isRepaintBlocked() const; 0307 0308 /** 0309 * If we will do several changes at once in the frame properties, 0310 * such as prefix, enabled borders and size, in order to not regenerate 0311 * the graphics for each change, set this property to true, and set 0312 * it to false again after applying all the changes needed. 0313 * Note that any change will not be visible in the painted frame while this property is set to true. 0314 * @since 5.31 0315 */ 0316 void setRepaintBlocked(bool blocked); 0317 0318 /** 0319 * This will return the minimum height required to correctly draw this 0320 * SVG. 0321 * @since 5.101 0322 */ 0323 Q_INVOKABLE int minimumDrawingHeight(); 0324 0325 /** 0326 * This will return the minimum width required to correctly draw this 0327 * SVG. 0328 * @since 5.101 0329 */ 0330 Q_INVOKABLE int minimumDrawingWidth(); 0331 0332 private: 0333 FrameSvgPrivate *const d; 0334 friend class FrameData; 0335 }; 0336 0337 Q_DECLARE_OPERATORS_FOR_FLAGS(FrameSvg::EnabledBorders) 0338 0339 } // Plasma namespace 0340 0341 #endif // multiple inclusion guard