1 /* 2 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org> 3 SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #ifndef UNITS_H 9 #define UNITS_H 10 11 #include <QObject> 12 #include <QQmlPropertyMap> 13 14 #include <Plasma/Theme> 15 16 #include <KConfigWatcher> 17 18 class QQuickItem; 19 20 class SharedAppFilter : public QObject 21 { 22 Q_OBJECT 23 public: 24 explicit SharedAppFilter(QObject *parent = nullptr); 25 ~SharedAppFilter() override; 26 27 Q_SIGNALS: 28 void fontChanged(); 29 30 protected: 31 bool eventFilter(QObject *watched, QEvent *event) override; 32 }; 33 34 /** 35 * @class Units 36 * @short Expose sizes to QML 37 */ 38 class Units : public QObject 39 { 40 Q_OBJECT 41 42 /** 43 * The fundamental unit of space that should be used for sizes, expressed in pixels. 44 * Given the screen has an accurate DPI settings, it corresponds to the height of 45 * the font's boundingRect. 46 */ 47 Q_PROPERTY(int gridUnit READ gridUnit NOTIFY gridUnitChanged) 48 49 /** 50 * units.iconSizes provides access to platform-dependent icon sizing 51 * 52 * The icon sizes provided are normalized for different DPI, so icons 53 * will scale depending on the DPI. 54 * 55 * Icon sizes from KIconLoader, adjusted to devicePixelRatio: 56 * * small 57 * * smallMedium 58 * * medium 59 * * large 60 * * huge 61 * * enormous 62 * * desktop (DEPRECATED: use iconSizeHints instead) 63 * 64 */ 65 // note the iconSizeChanged signal indicates that one (or more) of these icons have changed 66 // but the property map itself remains constant 67 Q_PROPERTY(QQmlPropertyMap *iconSizes READ iconSizes CONSTANT) 68 69 /** 70 * units.iconSizeHints provides access to user-configurable icon size hints, 71 * to be used where appropriate in the user interface. 72 * 73 * Conceptually, an icon size hint is a key that has one of the sizes from 74 * @iconSizes property as value. 75 * 76 * Currently available hints: 77 * * panel 78 * * desktop 79 */ 80 // note the iconSizeHintsChanged signal indicates that one (or more) of these icons have changed 81 // but the property map itself remains constant 82 Q_PROPERTY(QQmlPropertyMap *iconSizeHints READ iconSizeHints CONSTANT) 83 84 // layout hints 85 86 /** 87 * units.smallSpacing is the amount of spacing that should be used around smaller UI elements, 88 * for example as spacing in Columns. Internally, this size depends on the size of 89 * the default font as rendered on the screen, so it takes user-configured font size and DPI 90 * into account. 91 */ 92 Q_PROPERTY(int smallSpacing READ smallSpacing NOTIFY spacingChanged) 93 94 /** 95 * units.largeSpacing is the amount of spacing that should be used inside bigger UI elements, 96 * for example between an icon and the corresponding text. Internally, this size depends on 97 * the size of the default font as rendered on the screen, so it takes user-configured font 98 * size and DPI into account. 99 */ 100 Q_PROPERTY(int largeSpacing READ largeSpacing NOTIFY spacingChanged) 101 102 /** 103 * The ratio between physical and device-independent pixels. This value does not depend on the \ 104 * size of the configured font. If you want to take font sizes into account when scaling elements, 105 * use PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont), PlasmaCore.Units.smallSpacing and PlasmaCore.Units.largeSpacing. 106 * The devicePixelRatio follows the definition of "device independent pixel" by Microsoft. 107 */ 108 Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged) 109 110 /** 111 * units.longDuration should be used for longer, screen-covering animations, for opening and 112 * closing of dialogs and other "not too small" animations 113 */ 114 Q_PROPERTY(int longDuration READ longDuration NOTIFY durationChanged) 115 116 /** 117 * units.shortDuration should be used for short animations, such as accentuating a UI event, 118 * hover events, etc.. 119 */ 120 Q_PROPERTY(int shortDuration READ shortDuration NOTIFY durationChanged) 121 122 /** 123 * units.veryShortDuration should be used for elements that should animate near instantly, 124 * but should have a hint of smoothness 125 */ 126 Q_PROPERTY(int veryShortDuration READ veryShortDuration NOTIFY durationChanged) 127 128 /** 129 * units.veryLongDuration should be used for specialty animations that benefit 130 * from being even longer than longDuration. 131 */ 132 Q_PROPERTY(int veryLongDuration READ veryLongDuration NOTIFY durationChanged) 133 134 /** 135 * Time in milliseconds equivalent to the theoretical human moment, which can be used 136 * to determine whether how long to wait until the user should be informed of something, 137 * or can be used as the limit for how long something should wait before being 138 * automatically initiated. 139 * 140 * Some examples: 141 * 142 * - When the user types text in a search field, wait no longer than this duration after 143 * the user completes typing before starting the search 144 * - When loading data which would commonly arrive rapidly enough to not require interaction, 145 * wait this long before showing a spinner 146 * 147 * This might seem an arbitrary number, but given the psychological effect that three 148 * seconds seems to be what humans consider a moment (and in the case of waiting for 149 * something to happen, a moment is that time when you think "this is taking a bit long, 150 * isn't it?"), the idea is to postpone for just before such a conceptual moment. The reason 151 * for the two seconds, rather than three, is to function as a middle ground: Not long enough 152 * that the user would think that something has taken too long, for also not so fast as to 153 * happen too soon. 154 * 155 * See also 156 * https://www.psychologytoday.com/blog/all-about-addiction/201101/tick-tock-tick-hugs-and-life-in-3-second-intervals 157 * (the actual paper is hidden behind an academic paywall and consequently not readily 158 * available to us, so the source will have to be the blog entry above) 159 * 160 * @since 5.81 161 */ 162 Q_PROPERTY(int humanMoment READ humanMoment CONSTANT) 163 164 public: 165 /// @cond INTERNAL_DOCS 166 167 ~Units() override; 168 169 /** 170 * @return a reference to the global Units instance 171 * @since 5.31 172 */ 173 static Units &instance(); 174 175 /** 176 * @return pixel value for a grid Unit. Depends on DPI and font size. 177 */ 178 int gridUnit() const; 179 180 /** 181 * @return The ratio between physical and device-independent pixels. 182 */ 183 qreal devicePixelRatio() const; 184 185 /** 186 * @return map with iconsizes, indexed by name 187 */ 188 QQmlPropertyMap *iconSizes() const; 189 190 /** 191 * @return map with user-configurable icon size hints, indexed by name 192 * @since 5.33 193 */ 194 QQmlPropertyMap *iconSizeHints() const; 195 196 /** 197 * @return Pixel value for large spacing between elements. 198 * @since 5.0 199 */ 200 int smallSpacing() const; 201 202 /** 203 * @return Pixel value for large spacing between elements. 204 * @since 5.0 205 */ 206 int largeSpacing() const; 207 208 /** 209 * @return Duration for long animations, in milliseconds. 210 * @since 5.0 211 */ 212 int longDuration() const; 213 214 /** 215 * @return Duration for short animations, in milliseconds. 216 * @since 5.0 217 */ 218 int shortDuration() const; 219 220 /** 221 * @return Duration for very long animations, in milliseconds. 222 * @since 5.69 223 */ 224 int veryLongDuration() const; 225 226 /** 227 * @return Duration for instantaneous animations, in milliseconds. 228 * @since 5.78 229 */ 230 int veryShortDuration() const; 231 232 /** 233 * @return Duration for very long wait times 234 * @since 5.81 235 */ 236 int humanMoment() const; 237 /// @endcond 238 239 /** 240 * @return a size rounded to the nearest inferior standard icon size. 241 * sizes larger than iconSizes.huge, it will be returned unmodified 242 * @param int size the size we want to be rounded down 243 * @see iconSizes 244 */ 245 Q_INVOKABLE static int roundToIconSize(int size); 246 247 Q_SIGNALS: 248 void devicePixelRatioChanged(); 249 void gridUnitChanged(); 250 void iconSizesChanged(); 251 void iconSizeHintsChanged(); 252 void spacingChanged(); 253 void durationChanged(); 254 255 private Q_SLOTS: 256 void iconLoaderSettingsChanged(); 257 void updateSpacing(); 258 259 private: 260 Units(QObject *parent = nullptr); 261 Units(Units const &) = delete; // Copy construct 262 Units(Units &&) = delete; // Move construct 263 Units &operator=(Units const &) = delete; // Copy assign 264 Units &operator=(Units &&) = delete; // Move assign 265 266 void updateDevicePixelRatio(); 267 void updateAnimationSpeed(); 268 269 /** 270 * @return the best-looking icon scale for the given device pixel ratio 271 * Note that this function is only relevant when using Plasma scaling and 272 * when using Qt scaling, it always returns 1. 273 */ 274 static qreal bestIconScaleForDevicePixelRatio(const qreal ratio); 275 276 /** 277 * @return The dpi-adjusted size for a given icon size 278 */ 279 int devicePixelIconSize(const int size) const; 280 281 int m_gridUnit; 282 qreal m_devicePixelRatio; 283 284 QQmlPropertyMap *m_iconSizes; 285 QQmlPropertyMap *m_iconSizeHints; 286 static SharedAppFilter *s_sharedAppFilter; 287 288 int m_smallSpacing; 289 int m_largeSpacing; 290 291 KConfigWatcher::Ptr m_animationSpeedWatcher; 292 int m_longDuration; 293 }; 294 295 #endif // UNITS_H 296