File indexing completed on 2024-09-29 06:30:48
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2003 Benjamin C Meyer <ben+kdelibs at meyerhome dot net> 0004 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KCONFIGDIALOGMANAGER_H 0010 #define KCONFIGDIALOGMANAGER_H 0011 0012 #include <kconfigwidgets_export.h> 0013 0014 #include <QHash> 0015 #include <QObject> 0016 #include <memory> 0017 0018 class KConfigDialogManagerPrivate; 0019 0020 class KCoreConfigSkeleton; 0021 class KConfigSkeleton; 0022 class KConfigSkeletonItem; 0023 class QWidget; 0024 0025 /** 0026 * @class KConfigDialogManager kconfigdialogmanager.h KConfigDialogManager 0027 * 0028 * @short Provides a means of automatically retrieving, 0029 * saving and resetting KConfigSkeleton based settings in a dialog. 0030 * 0031 * The KConfigDialogManager class provides a means of automatically 0032 * retrieving, saving and resetting basic settings. 0033 * It also can emit signals when settings have been changed 0034 * (settings were saved) or modified (the user changes a checkbox 0035 * from on to off). 0036 * 0037 * The object names of the widgets to be managed have to correspond to the names of the 0038 * configuration entries in the KConfigSkeleton object plus an additional 0039 * "kcfg_" prefix. For example a widget with the object name "kcfg_MyOption" 0040 * would be associated to the configuration entry "MyOption". 0041 * 0042 * The widget classes of Qt and KDE Frameworks are supported out of the box, 0043 * for other widgets see below: 0044 * 0045 * @par Using Custom Widgets 0046 * @parblock 0047 * Custom widget classes are supported if they have a Q_PROPERTY defined for the 0048 * property representing the value edited by the widget. By default the property 0049 * is used for which "USER true" is set. For using another property, see below. 0050 * 0051 * Example: 0052 * 0053 * A class ColorEditWidget is used in the settings UI to select a color. The 0054 * color value is set and read as type QColor. For that it has a definition of 0055 * the value property similar to this: 0056 * \code 0057 * Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged USER true) 0058 * \endcode 0059 * And of course it has the definition and implementation of the respective 0060 * read & write methods and the notify signal. 0061 * This class then can be used directly with KConfigDialogManager and does not need 0062 * further setup. 0063 * @endparblock 0064 * 0065 * @par Using Other Properties than The USER Property 0066 * @parblock 0067 * To use a widget's property that is not the USER property, the property to use 0068 * can be selected by setting onto the widget instance a property with the key 0069 * "kcfg_property" and as the value the name of the property: 0070 * \code 0071 * ColorEditWidget *myWidget = new ColorEditWidget; 0072 * myWidget->setProperty("kcfg_property", QByteArray("redColorPart")); 0073 * \endcode 0074 * This selection of the property to use is just valid for this widget instance. 0075 * When using a UI file, the "kcfg_property" property can also be set using Qt Designer. 0076 * @endparblock 0077 * 0078 * @par Configuring Classes to use Other Properties Globally 0079 * @parblock 0080 * Alternatively a non-USER property can be defined for a widget class globally 0081 * by registering it for the class in the KConfigDialogManager::propertyMap(). 0082 * This global registration has lower priority than any "kcfg_property" property 0083 * set on a class instance though, so the latter overrules this global setting. 0084 * Note: setting the property in the propertyMap affects any instances of that 0085 * widget class in the current application, so use only when needed and prefer 0086 * instead the "kcfg_property" property. Especially with software with many 0087 * libraries and 3rd-party plugins in one process there is a chance of 0088 * conflicting settings. 0089 * 0090 * Example: 0091 * 0092 * If the ColorEditWidget has another property redColor defined by 0093 * \code 0094 * Q_PROPERTY(int redColorPart READ redColorPart WRITE setRedColorPart NOTIFY redColorPartChanged) 0095 * \endcode 0096 * and this one should be used in the settings, call somewhere in the code before 0097 * using the settings: 0098 * \code 0099 * KConfigDialogManager::propertyMap()->insert("ColorEditWidget", QByteArray("redColorPart")); 0100 * \endcode 0101 * @endparblock 0102 * 0103 * @par Using Different Signals than The NOTIFY Signal 0104 * @parblock 0105 * If some non-default signal should be used, e.g. because the property to use does not 0106 * have a NOTIFY setting, for a given widget instance the signal to use can be set 0107 * by a property with the key "kcfg_propertyNotify" and as the value the signal signature. 0108 * This will take priority over the signal noted by NOTIFY for the chosen property 0109 * as well as the content of KConfigDialogManager::changedMap(). Since 5.32. 0110 * 0111 * Example: 0112 * 0113 * If for a class OtherColorEditWidget there was no NOTIFY set on the USER property, 0114 * but some signal colorSelected(QColor) defined which would be good enough to reflect 0115 * the settings change, defined by 0116 * \code 0117 * Q_PROPERTY(QColor color READ color WRITE setColor USER true) 0118 * Q_SIGNALS: 0119 * void colorSelected(const QColor &color); 0120 * \endcode 0121 * the signal to use would be defined by this: 0122 * \code 0123 * OtherColorEditWidget *myWidget = new OtherColorEditWidget; 0124 * myWidget->setProperty("kcfg_propertyNotify", QByteArray(SIGNAL(colorSelected(QColor)))); 0125 * \endcode 0126 * @endparblock 0127 * 0128 * @author Benjamin C Meyer <ben+kdelibs at meyerhome dot net> 0129 * @author Waldo Bastian <bastian@kde.org> 0130 */ 0131 class KCONFIGWIDGETS_EXPORT KConfigDialogManager : public QObject 0132 { 0133 Q_OBJECT 0134 0135 Q_SIGNALS: 0136 /** 0137 * One or more of the settings have been saved (such as when the user 0138 * clicks on the Apply button). This is only emitted by updateSettings() 0139 * whenever one or more setting were changed and consequently saved. 0140 */ 0141 void settingsChanged(); // clazy:exclude=overloaded-signal 0142 0143 /** 0144 * If retrieveSettings() was told to track changes then if 0145 * any known setting was changed this signal will be emitted. Note 0146 * that a settings can be modified several times and might go back to the 0147 * original saved state. hasChanged() will tell you if anything has 0148 * actually changed from the saved values. 0149 */ 0150 void widgetModified(); 0151 0152 public: 0153 /** 0154 * Constructor. 0155 * @param parent Dialog widget to manage 0156 * @param conf Object that contains settings 0157 */ 0158 KConfigDialogManager(QWidget *parent, KCoreConfigSkeleton *conf); 0159 0160 /** 0161 * Destructor. 0162 */ 0163 ~KConfigDialogManager() override; 0164 0165 /** 0166 * Add additional widgets to manage 0167 * @param widget Additional widget to manage, including all its children 0168 */ 0169 void addWidget(QWidget *widget); 0170 0171 /** 0172 * Returns whether the current state of the known widgets are 0173 * different from the state in the config object. 0174 */ 0175 bool hasChanged() const; 0176 0177 /** 0178 * Returns whether the current state of the known widgets are 0179 * the same as the default state in the config object. 0180 */ 0181 bool isDefault() const; 0182 0183 /** 0184 * Retrieve the map between widgets class names and the 0185 * USER properties used for the configuration values. 0186 */ 0187 static QHash<QString, QByteArray> *propertyMap(); 0188 0189 public Q_SLOTS: 0190 /** 0191 * Traverse the specified widgets, saving the settings of all known 0192 * widgets in the settings object. 0193 * 0194 * Example use: User clicks Ok or Apply button in a configure dialog. 0195 */ 0196 void updateSettings(); 0197 0198 /** 0199 * Traverse the specified widgets, sets the state of all known 0200 * widgets according to the state in the settings object. 0201 * 0202 * Example use: Initialisation of dialog. 0203 * Example use: User clicks Reset button in a configure dialog. 0204 */ 0205 void updateWidgets(); 0206 0207 /** 0208 * Traverse the specified widgets, sets the state of all known 0209 * widgets according to the default state in the settings object. 0210 * 0211 * Example use: User clicks Defaults button in a configure dialog. 0212 */ 0213 void updateWidgetsDefault(); 0214 0215 /** 0216 * Show or hide an indicator when settings have changed from their default value. 0217 * Update all widgets to show or hide the indicator accordingly. 0218 * 0219 * @since 5.73 0220 */ 0221 void setDefaultsIndicatorsVisible(bool enabled); 0222 0223 protected: 0224 /** 0225 * @param trackChanges - If any changes by the widgets should be tracked 0226 * set true. This causes the emitting the modified() signal when 0227 * something changes. 0228 * TODO: @return bool - True if any setting was changed from the default. 0229 */ 0230 void init(bool trackChanges); 0231 0232 /** 0233 * Recursive function that finds all known children. 0234 * Goes through the children of widget and if any are known and not being 0235 * ignored, stores them in currentGroup. Also checks if the widget 0236 * should be disabled because it is set immutable. 0237 * @param widget - Parent of the children to look at. 0238 * @param trackChanges - If true then tracks any changes to the children of 0239 * widget that are known. 0240 * @return bool - If a widget was set to something other than its default. 0241 */ 0242 bool parseChildren(const QWidget *widget, bool trackChanges); 0243 0244 /** 0245 * Finds the USER property name using Qt's MetaProperty system, and caches 0246 * it in the property map (the cache could be retrieved by propertyMap() ). 0247 */ 0248 QByteArray getUserProperty(const QWidget *widget) const; 0249 0250 /** 0251 * Find the property to use for a widget by querying the "kcfg_property" 0252 * property of the widget. Like a widget can use a property other than the 0253 * USER property. 0254 * @since 4.3 0255 */ 0256 QByteArray getCustomProperty(const QWidget *widget) const; 0257 0258 /** 0259 * Finds the changed signal of the USER property using Qt's MetaProperty system. 0260 * @since 5.32 0261 */ 0262 QByteArray getUserPropertyChangedSignal(const QWidget *widget) const; 0263 0264 /** 0265 * Find the changed signal of the property to use for a widget by querying 0266 * the "kcfg_propertyNotify" property of the widget. Like a widget can use a 0267 * property change signal other than the one for USER property, if there even is one. 0268 * @since 5.32 0269 */ 0270 QByteArray getCustomPropertyChangedSignal(const QWidget *widget) const; 0271 0272 /** 0273 * Set a property 0274 */ 0275 void setProperty(QWidget *w, const QVariant &v); 0276 0277 /** 0278 * Retrieve a property 0279 */ 0280 QVariant property(QWidget *w) const; 0281 0282 /** 0283 * Setup secondary widget properties 0284 */ 0285 void setupWidget(QWidget *widget, KConfigSkeletonItem *item); 0286 0287 /** 0288 * Initializes the property maps 0289 */ 0290 static void initMaps(); 0291 0292 private: 0293 /** 0294 * KConfigDialogManager KConfigDialogManagerPrivate class. 0295 */ 0296 std::unique_ptr<KConfigDialogManagerPrivate> const d; 0297 friend class KConfigDialogManagerPrivate; 0298 0299 Q_DISABLE_COPY(KConfigDialogManager) 0300 Q_PRIVATE_SLOT(d, void onWidgetModified()) 0301 }; 0302 0303 #endif // KCONFIGDIALOGMANAGER_H