KWidgetsAddons

kstyleextensions.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2014 Thomas Lübking <thomas.luebking@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kstyleextensions.h"
9
10#include <QWidget>
11
13{
14/*
15 Custom Style Element runtime extension:
16 We reserve one StyleHint to let the effective style inform widgets whether it supports certain
17 string based style elements.
18 As this could lead to number conflicts (i.e. an app utilizing one of the hints itself for other
19 purposes) there're various safety mechanisms to rule out such interference.
20
21 1) It's most unlikely that a widget in some 3rd party app will accidentally call a general
22 QStyle/KStyle styleHint() or draw*() and (unconditionally) expect a valid return, however:
23 a. The StyleHint is not directly above Qt's custom base, assuming most 3rd party apps would
24 - in case - make use of such
25 b. In order to be accepted, the StyleHint query must pass a widget with a perfectly matching
26 name, containing the typical element prefix ("CE_", etc.) and being supported by the current
27 style
28 c. Instead using Qt's fragile qstyleoption_cast on the QStyleOption provided to the StyleHint
29 query, try to dump out a string and hope for the best, we now manipulate the widgets
30 objectName().
31 Plain Qt dependent widgets can do that themselves and if a widget uses KStyle's
32 convenience access functions, it won't notice this at all
33
34 2) The key problem is that a common KDE widget will run into an apps custom style which will then
35 falsely respond to the styleHint() call with an invalid value.
36 To prevent this, supporting styles *must* set a Q_CLASSINFO "X-KDE-CustomElements".
37
38 3) If any of the above traps snaps, the returned id is 0 - the QStyle default, indicating
39 that this element is not supported by the current style.
40
41 Obviously, this contains the "diminished clean" action to (temporarily) manipulate the
42 objectName() of a const QWidget* - but this happens completely inside KStyle or the widget, if
43 it does not make use of KStyles static convenience functions.
44 My biggest worry here would be, that in a multithreaded environment a thread (usually not being
45 owner of the widget) does something crucially relying on the widgets name property...
46 This however would also have to happen during the widget construction or stylechanges, when
47 the functions in doubt will typically be called.
48 So this is imho unlikely causing any trouble, ever.
49*/
50
51/// @private Prevent kapidox's doxygen config to pick up this namespace variable
52static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001;
53/// @private Prevent kapidox's doxygen config to pick up this namespace variable
54static const int X_KdeBase = 0xff000000;
55
56/*
57 The functions called by widgets that request custom element support, passed to the effective style.
58 Collected in a static inline function due to similarity.
59*/
60
61/// @private Prevent kapidox's doxygen config to pick up this namespace method
62static inline int customStyleElement(QStyle::StyleHint type, const QString &element, QWidget *widget)
63{
64 if (!widget || widget->style()->metaObject()->indexOfClassInfo("X-KDE-CustomElements") < 0) {
65 return 0;
66 }
67
68 const QString originalName = widget->objectName();
69 widget->setObjectName(element);
70 const int id = widget->style()->styleHint(type, nullptr, widget);
71 widget->setObjectName(originalName);
72 return id;
73}
74
75QStyle::StyleHint customStyleHint(const QString &element, const QWidget *widget)
76{
77 return (QStyle::StyleHint)customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
78}
79
81{
82 return (QStyle::ControlElement)customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
83}
84
85QStyle::SubElement customSubElement(const QString &element, const QWidget *widget)
86{
87 return (QStyle::SubElement)customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
88}
89
90}
Runtime style extensions You can use this to have a supporting QStyle implementation paint your widge...
QStyle::ControlElement customControlElement(const QString &element, const QWidget *widget)
Resolve a dynamic QStyle::ControlElement for eg.
QStyle::SubElement customSubElement(const QString &element, const QWidget *widget)
Resolve a dynamic QStyle::SubElement for eg.
QStyle::StyleHint customStyleHint(const QString &element, const QWidget *widget)
Resolve a dynamic QStyle::StyleHint to query QStyle::styleHint()
int indexOfClassInfo(const char *name) const const
virtual const QMetaObject * metaObject() const const
void setObjectName(QAnyStringView name)
virtual int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const const=0
QStyle * style() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 4 2024 12:05:10 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.