File indexing completed on 2024-04-28 11:22:45
0001 /* 0002 This file is a part of digiKam project 0003 https://www.digikam.org 0004 0005 SPDX-FileCopyrightText: 2006-2018 Gilles Caulier <caulier dot gilles at gmail dot com> 0006 SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad at users dot sourceforge dot net> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #pragma once 0012 0013 #include <ksharedconfig.h> 0014 0015 #include <QExplicitlySharedDataPointer> 0016 #include <QPalette> 0017 #include <QColor> 0018 #include <QBrush> 0019 0020 class SchemeManagerPrivate; 0021 0022 /** 0023 * A set of methods used to work with colors. 0024 * 0025 * SchemeManager currently provides access to the system color palette that the 0026 * user has selected (in the future, it is expected to do more). It greatly 0027 * expands on QPalette by providing five distinct "sets" with several color 0028 * choices each, covering background, foreground, and decoration colors. 0029 * 0030 * A SchemeManager instance represents colors corresponding to a "set", where a 0031 * set consists of those colors used to draw a particular type of element, such 0032 * as a menu, button, view, selected text, or tooltip. Each set has a distinct 0033 * set of colors, so you should always use the correct set for drawing and 0034 * never assume that a particular foreground for one set is the same as the 0035 * foreground for any other set. Individual colors may be quickly referenced by 0036 * creating an anonymous instance and invoking a lookup member. 0037 * 0038 * @note 0039 * The color palettes for the various states of a widget (active, inactive, 0040 * disabled) may be wildly different. Therefore, it is important to take the 0041 * state into account. This is why the SchemeManager constructor requires a 0042 * QPalette::ColorGroup as an argument. 0043 * 0044 * To facilitate working with potentially-varying states, two convenience API's 0045 * are provided. These are SchemeManager::adjustBackground and its sister 0046 * SchemeManager::adjustForeground, and the helper class KStatefulBrush. 0047 * 0048 * @see SchemeManager::ColorSet, SchemeManager::ForegroundRole, 0049 * SchemeManager::BackgroundRole, SchemeManager::DecorationRole, 0050 * SchemeManager::ShadeRole 0051 */ 0052 class SchemeManager 0053 { 0054 public: 0055 0056 /** 0057 * This enumeration describes the color set for which a color is being 0058 * selected. 0059 * 0060 * Color sets define a color "environment", suitable for drawing all parts 0061 * of a given region. Colors from different sets should not be combined. 0062 */ 0063 enum ColorSet 0064 { 0065 /** 0066 * Views; for example, frames, input fields, etc. 0067 * 0068 * If it contains things that can be selected, it is probably a View. 0069 */ 0070 View, 0071 /** 0072 * Non-editable window elements; for example, menus. 0073 * 0074 * If it isn't a Button, View, or Tooltip, it is probably a Window. 0075 */ 0076 Window, 0077 /** 0078 * Buttons and button-like controls. 0079 * 0080 * In addition to buttons, "button-like" controls such as non-editable 0081 * dropdowns, scrollbar sliders, slider handles, etc. should also use 0082 * this role. 0083 */ 0084 Button, 0085 /** 0086 * Selected items in views. 0087 * 0088 * Note that unfocused or disabled selections should use the Window 0089 * role. This makes it more obvious to the user that the view 0090 * containing the selection does not have input focus. 0091 */ 0092 Selection, 0093 /** 0094 * Tooltips. 0095 * 0096 * The tooltip set can often be substituted for the view 0097 * set when editing is not possible, but the Window set is deemed 0098 * inappropriate. "What's This" help is an excellent example, another 0099 * might be pop-up notifications (depending on taste). 0100 */ 0101 Tooltip, 0102 /** 0103 * Complementary areas. 0104 * 0105 * Some applications want some areas to have a different color scheme. 0106 * Usually dark areas over a light theme. For instance the fullscreen UI 0107 * of a picture viewer, or the logout/lock screen of the plasma workspace 0108 * ask for a dark color scheme even on light themes. 0109 * @since 5.19 0110 */ 0111 Complementary 0112 }; 0113 0114 /** 0115 * This enumeration describes the background color being selected from the 0116 * given set. 0117 * 0118 * Background colors are suitable for drawing under text, and should never 0119 * be used to draw text. In combination with one of the overloads of 0120 * SchemeManager::shade, they may be used to generate colors for drawing 0121 * frames, bevels, and similar decorations. 0122 */ 0123 enum BackgroundRole 0124 { 0125 /** 0126 * Normal background. 0127 */ 0128 NormalBackground = 0, 0129 /** 0130 * Alternate background; for example, for use in lists. 0131 * 0132 * This color may be the same as BackgroundNormal, especially in sets 0133 * other than View and Window. 0134 */ 0135 AlternateBackground = 1, 0136 /** 0137 * Third color; for example, items which are new, active, requesting 0138 * attention, etc. 0139 * 0140 * Alerting the user that a certain field must be filled out would be a 0141 * good usage (although NegativeBackground could be used to the same 0142 * effect, depending on what you are trying to achieve). Unlike 0143 * ActiveText, this should not be used for mouseover effects. 0144 */ 0145 ActiveBackground = 2, 0146 /** 0147 * Fourth color; corresponds to (unvisited) links. 0148 * 0149 * Exactly what this might be used for is somewhat harder to qualify; 0150 * it might be used for bookmarks, as a 'you can click here' indicator, 0151 * or to highlight recent content (i.e. in a most-recently-accessed 0152 * list). 0153 */ 0154 LinkBackground = 3, 0155 /** 0156 * Fifth color; corresponds to visited links. 0157 * 0158 * This can also be used to indicate "not recent" content, especially 0159 * when a color is needed to denote content which is "old" or 0160 * "archival". 0161 */ 0162 VisitedBackground = 4, 0163 /** 0164 * Sixth color; for example, errors, untrusted content, etc. 0165 */ 0166 NegativeBackground = 5, 0167 /** 0168 * Seventh color; for example, warnings, secure/encrypted content. 0169 */ 0170 NeutralBackground = 6, 0171 /** 0172 * Eigth color; for example, success messages, trusted content. 0173 */ 0174 PositiveBackground = 7 0175 }; 0176 0177 /** 0178 * This enumeration describes the foreground color being selected from the 0179 * given set. 0180 * 0181 * Foreground colors are suitable for drawing text or glyphs (such as the 0182 * symbols on window decoration buttons, assuming a suitable background 0183 * brush is used), and should never be used to draw backgrounds. 0184 * 0185 * For window decorations, the following is suggested, but not set in 0186 * stone: 0187 * @li Maximize - PositiveText 0188 * @li Minimize - NeutralText 0189 * @li Close - NegativeText 0190 * @li WhatsThis - LinkText 0191 * @li Sticky - ActiveText 0192 */ 0193 enum ForegroundRole 0194 { 0195 /** 0196 * Normal foreground. 0197 */ 0198 NormalText = 0, 0199 /** 0200 * Second color; for example, comments, items which are old, inactive 0201 * or disabled. Generally used for things that are meant to be "less 0202 * important". InactiveText is not the same role as NormalText in the 0203 * inactive state. 0204 */ 0205 InactiveText = 1, 0206 /** 0207 * Third color; for example items which are new, active, requesting 0208 * attention, etc. May be used as a hover color for clickable items. 0209 */ 0210 ActiveText = 2, 0211 /** 0212 * Fourth color; use for (unvisited) links. May also be used for other 0213 * clickable items or content that indicates relationships, items that 0214 * indicate somewhere the user can visit, etc. 0215 */ 0216 LinkText = 3, 0217 /** 0218 * Fifth color; used for (visited) links. As with LinkText, may be used 0219 * for items that have already been "visited" or accessed. May also be 0220 * used to indicate "historical" (i.e. "old") items or information, 0221 * especially if InactiveText is being used in the same context to 0222 * express something different. 0223 */ 0224 VisitedText = 4, 0225 /** 0226 * Sixth color; for example, errors, untrusted content, deletions, 0227 * etc. 0228 */ 0229 NegativeText = 5, 0230 /** 0231 * Seventh color; for example, warnings, secure/encrypted content. 0232 */ 0233 NeutralText = 6, 0234 /** 0235 * Eigth color; for example, additions, success messages, trusted 0236 * content. 0237 */ 0238 PositiveText = 7 0239 }; 0240 0241 /** 0242 * This enumeration describes the decoration color being selected from the 0243 * given set. 0244 * 0245 * Decoration colors are used to draw decorations (such as frames) for 0246 * special purposes. Like color shades, they are neither foreground nor 0247 * background colors. Text should not be painted over a decoration color, 0248 * and decoration colors should not be used to draw text. 0249 */ 0250 enum DecorationRole 0251 { 0252 /** 0253 * Color used to draw decorations for items which have input focus. 0254 */ 0255 FocusColor, 0256 /** 0257 * Color used to draw decorations for items which will be activated by 0258 * clicking. 0259 */ 0260 HoverColor 0261 }; 0262 0263 /** 0264 * This enumeration describes the color shade being selected from the given 0265 * set. 0266 * 0267 * Color shades are used to draw "3d" elements, such as frames and bevels. 0268 * They are neither foreground nor background colors. Text should not be 0269 * painted over a shade, and shades should not be used to draw text. 0270 */ 0271 enum ShadeRole 0272 { 0273 /** 0274 * The light color is lighter than dark() or shadow() and contrasts 0275 * with the base color. 0276 */ 0277 LightShade, 0278 /** 0279 * The midlight color is in between base() and light(). 0280 */ 0281 MidlightShade, 0282 /** 0283 * The mid color is in between base() and dark(). 0284 */ 0285 MidShade, 0286 /** 0287 * The dark color is in between mid() and shadow(). 0288 */ 0289 DarkShade, 0290 /** 0291 * The shadow color is darker than light() or midlight() and contrasts 0292 * the base color. 0293 */ 0294 ShadowShade 0295 }; 0296 0297 public: 0298 0299 /** 0300 * Construct a copy of another SchemeManager. 0301 */ 0302 SchemeManager(const SchemeManager&); 0303 0304 // Don't use dtor with default keyword here because it breaks the PIMPL pattern and refactoring is needed 0305 virtual ~SchemeManager(); 0306 0307 /** 0308 * Standard assignment operator 0309 */ 0310 SchemeManager& operator=(const SchemeManager&); 0311 0312 /** 0313 * Construct a palette from given color set and state, using the colors 0314 * from the given KConfig (if null, the system colors are used). 0315 */ 0316 explicit SchemeManager(QPalette::ColorGroup, ColorSet = View, KSharedConfigPtr = KSharedConfigPtr()); 0317 0318 /** 0319 * Retrieve the requested background brush. 0320 */ 0321 QBrush background(BackgroundRole = NormalBackground) const; 0322 0323 /** 0324 * Retrieve the requested foreground brush. 0325 */ 0326 QBrush foreground(ForegroundRole = NormalText) const; 0327 0328 /** 0329 * Retrieve the requested decoration brush. 0330 */ 0331 QBrush decoration(DecorationRole) const; 0332 0333 /** 0334 * Retrieve the requested shade color, using 0335 * SchemeManager::background(SchemeManager::NormalBackground) 0336 * as the base color and the contrast setting from the KConfig used to 0337 * create this SchemeManager instance (the system contrast setting, if no 0338 * KConfig was specified). 0339 * 0340 * @note Shades are chosen such that all shades would contrast with the 0341 * base color. This means that if base is very dark, the 'dark' shades will 0342 * be lighter than the base color, with midlight() == shadow(). 0343 * Conversely, if the base color is very light, the 'light' shades will be 0344 * darker than the base color, with light() == mid(). 0345 */ 0346 QColor shade(ShadeRole) const; 0347 0348 /** 0349 * Returns the contrast for borders. 0350 * @return the contrast (between 0 for minimum and 10 for maximum 0351 * contrast) 0352 */ 0353 static int contrast(); 0354 0355 /** 0356 * Returns the contrast for borders as a floating point value. 0357 * @param config pointer to the config from which to read the contrast 0358 * setting (the default is to use KSharedConfig::openConfig()) 0359 * @return the contrast (between 0.0 for minimum and 1.0 for maximum 0360 * contrast) 0361 */ 0362 static qreal contrastF(const KSharedConfigPtr& config = KSharedConfigPtr()); 0363 0364 /** 0365 * Retrieve the requested shade color, using the specified color as the 0366 * base color and the system contrast setting. 0367 * 0368 * @note Shades are chosen such that all shades would contrast with the 0369 * base color. This means that if base is very dark, the 'dark' shades will 0370 * be lighter than the base color, with midlight() == shadow(). 0371 * Conversely, if the base color is very light, the 'light' shades will be 0372 * darker than the base color, with light() == mid(). 0373 */ 0374 static QColor shade(const QColor&, ShadeRole); 0375 0376 /** 0377 * Retrieve the requested shade color, using the specified color as the 0378 * base color and the specified contrast. 0379 * 0380 * @param color The base color 0381 * @param role The shade role 0382 * @param contrast Amount roughly specifying the contrast by which to 0383 * adjust the base color, between -1.0 and 1.0 (values between 0.0 and 1.0 0384 * correspond to the value from SchemeManager::contrastF) 0385 * @param chromaAdjust (optional) Amount by which to adjust the chroma of 0386 * the shade (1.0 means no adjustment) 0387 * 0388 * @note Shades are chosen such that all shades would contrast with the 0389 * base color. This means that if base is very dark, the 'dark' shades will 0390 * be lighter than the base color, with midlight() == shadow(). 0391 * Conversely, if the base color is very light, the 'light' shades will be 0392 * darker than the base color, with light() == mid(). 0393 * 0394 */ 0395 static QColor shade(const QColor&, ShadeRole, 0396 qreal contrast, qreal chromaAdjust = 0.0); 0397 0398 /** 0399 * Adjust a QPalette by replacing the specified QPalette::ColorRole with 0400 * the requested background color for all states. Using this method is 0401 * safer than replacing individual states, as it insulates you against 0402 * changes in QPalette::ColorGroup. 0403 * 0404 * @note Although it is possible to replace a foreground color using this 0405 * method, it's bad usability to do so. Just say "no". 0406 */ 0407 static void adjustBackground(QPalette&, 0408 BackgroundRole newRole = NormalBackground, 0409 QPalette::ColorRole color = QPalette::Base, 0410 ColorSet set = View, 0411 KSharedConfigPtr = KSharedConfigPtr()); 0412 0413 /** 0414 * Adjust a QPalette by replacing the specified QPalette::ColorRole with 0415 * the requested foreground color for all states. Using this method is 0416 * safer than replacing individual states, as it insulates you against 0417 * changes in QPalette::ColorGroup. 0418 * 0419 * @note Although it is possible to replace a background color using this 0420 * method, it's bad usability to do so. Just say "no". 0421 */ 0422 static void adjustForeground(QPalette&, 0423 ForegroundRole newRole = NormalText, 0424 QPalette::ColorRole color = QPalette::Text, 0425 ColorSet set = View, 0426 KSharedConfigPtr = KSharedConfigPtr()); 0427 0428 /** 0429 * Used to obtain the QPalette that will be used to set the application 0430 * palette from KDE Platform theme. 0431 * 0432 * @param config KConfig from which to load the colors 0433 * 0434 * @returns the QPalette 0435 */ 0436 static QPalette createApplicationPalette(const KSharedConfigPtr& config); 0437 0438 private: 0439 0440 QExplicitlySharedDataPointer<SchemeManagerPrivate> d; 0441 };