1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 
42 #ifndef QTPROPERTYBROWSER_H
43 #define QTPROPERTYBROWSER_H
44 
45 #include <QtWidgets/QLineEdit>
46 #include <QtCore/QSet>
47 
48 typedef QLineEdit::EchoMode EchoMode;
49 
50 QT_BEGIN_NAMESPACE
51 
52 class QtAbstractPropertyManager;
53 class QtPropertyPrivate;
54 
55 class QtProperty
56 {
57 public:
58     virtual ~QtProperty();
59 
60     QList<QtProperty *> subProperties() const;
61 
62     QtAbstractPropertyManager *propertyManager() const;
63 
64     QString toolTip() const;
65     QString statusTip() const;
66     QString whatsThis() const;
67     QString propertyName() const;
68     bool isEnabled() const;
69     bool isModified() const;
70 
71     bool hasValue() const;
72     QIcon valueIcon() const;
73     QString valueText() const;
74     QString displayText() const;
75 
76     void setToolTip(const QString &text);
77     void setStatusTip(const QString &text);
78     void setWhatsThis(const QString &text);
79     void setPropertyName(const QString &text);
80     void setEnabled(bool enable);
81     void setModified(bool modified);
82 
83     void addSubProperty(QtProperty *property);
84     void insertSubProperty(QtProperty *property, QtProperty *afterProperty);
85     void removeSubProperty(QtProperty *property);
86 protected:
87     explicit QtProperty(QtAbstractPropertyManager *manager);
88     void propertyChanged();
89 private:
90     friend class QtAbstractPropertyManager;
91     QtPropertyPrivate *d_ptr;
92 };
93 
94 class QtAbstractPropertyManagerPrivate;
95 
96 class QtAbstractPropertyManager : public QObject
97 {
98     Q_OBJECT
99 public:
100 
101     explicit QtAbstractPropertyManager(QObject *parent = 0);
102     ~QtAbstractPropertyManager();
103 
104     QSet<QtProperty *> properties() const;
105     void clear() const;
106 
107     QtProperty *addProperty(const QString &name = QString());
108 Q_SIGNALS:
109 
110     void propertyInserted(QtProperty *property,
111                 QtProperty *parent, QtProperty *after);
112     void propertyChanged(QtProperty *property);
113     void propertyRemoved(QtProperty *property, QtProperty *parent);
114     void propertyDestroyed(QtProperty *property);
115 protected:
116     virtual bool hasValue(const QtProperty *property) const;
117     virtual QIcon valueIcon(const QtProperty *property) const;
118     virtual QString valueText(const QtProperty *property) const;
119     virtual QString displayText(const QtProperty *property) const;
120     virtual EchoMode echoMode(const QtProperty *) const;
121     virtual void initializeProperty(QtProperty *property) = 0;
122     virtual void uninitializeProperty(QtProperty *property);
123     virtual QtProperty *createProperty();
124 private:
125     friend class QtProperty;
126     QtAbstractPropertyManagerPrivate *d_ptr;
127     Q_DECLARE_PRIVATE(QtAbstractPropertyManager)
128     Q_DISABLE_COPY(QtAbstractPropertyManager)
129 };
130 
131 class QtAbstractEditorFactoryBase : public QObject
132 {
133     Q_OBJECT
134 public:
135     virtual QWidget *createEditor(QtProperty *property, QWidget *parent) = 0;
136 protected:
137     explicit QtAbstractEditorFactoryBase(QObject *parent = 0)
QObject(parent)138         : QObject(parent) {}
139 
140     virtual void breakConnection(QtAbstractPropertyManager *manager) = 0;
141 protected Q_SLOTS:
142     virtual void managerDestroyed(QObject *manager) = 0;
143 
144     friend class QtAbstractPropertyBrowser;
145 };
146 
147 template <class PropertyManager>
148 class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase
149 {
150 public:
QtAbstractEditorFactory(QObject * parent)151     explicit QtAbstractEditorFactory(QObject *parent) : QtAbstractEditorFactoryBase(parent) {}
createEditor(QtProperty * property,QWidget * parent)152     QWidget *createEditor(QtProperty *property, QWidget *parent)
153     {
154         QSetIterator<PropertyManager *> it(m_managers);
155         while (it.hasNext()) {
156             PropertyManager *manager = it.next();
157             if (manager == property->propertyManager()) {
158                 return createEditor(manager, property, parent);
159             }
160         }
161         return 0;
162     }
addPropertyManager(PropertyManager * manager)163     void addPropertyManager(PropertyManager *manager)
164     {
165         if (m_managers.contains(manager))
166             return;
167         m_managers.insert(manager);
168         connectPropertyManager(manager);
169         connect(manager, SIGNAL(destroyed(QObject *)),
170                     this, SLOT(managerDestroyed(QObject *)));
171     }
removePropertyManager(PropertyManager * manager)172     void removePropertyManager(PropertyManager *manager)
173     {
174         if (!m_managers.contains(manager))
175             return;
176         disconnect(manager, SIGNAL(destroyed(QObject *)),
177                     this, SLOT(managerDestroyed(QObject *)));
178         disconnectPropertyManager(manager);
179         m_managers.remove(manager);
180     }
propertyManagers()181     QSet<PropertyManager *> propertyManagers() const
182     {
183         return m_managers;
184     }
propertyManager(QtProperty * property)185     PropertyManager *propertyManager(QtProperty *property) const
186     {
187         QtAbstractPropertyManager *manager = property->propertyManager();
188         QSetIterator<PropertyManager *> itManager(m_managers);
189         while (itManager.hasNext()) {
190             PropertyManager *m = itManager.next();
191             if (m == manager) {
192                 return m;
193             }
194         }
195         return 0;
196     }
197 protected:
198     virtual void connectPropertyManager(PropertyManager *manager) = 0;
199     virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property,
200                 QWidget *parent) = 0;
201     virtual void disconnectPropertyManager(PropertyManager *manager) = 0;
managerDestroyed(QObject * manager)202     void managerDestroyed(QObject *manager)
203     {
204         QSetIterator<PropertyManager *> it(m_managers);
205         while (it.hasNext()) {
206             PropertyManager *m = it.next();
207             if (m == manager) {
208                 m_managers.remove(m);
209                 return;
210             }
211         }
212     }
213 private:
breakConnection(QtAbstractPropertyManager * manager)214     void breakConnection(QtAbstractPropertyManager *manager)
215     {
216         QSetIterator<PropertyManager *> it(m_managers);
217         while (it.hasNext()) {
218             PropertyManager *m = it.next();
219             if (m == manager) {
220                 removePropertyManager(m);
221                 return;
222             }
223         }
224     }
225 private:
226     QSet<PropertyManager *> m_managers;
227     friend class QtAbstractPropertyEditor;
228 };
229 
230 class QtAbstractPropertyBrowser;
231 class QtBrowserItemPrivate;
232 
233 class QtBrowserItem
234 {
235 public:
236     QtProperty *property() const;
237     QtBrowserItem *parent() const;
238     QList<QtBrowserItem *> children() const;
239     QtAbstractPropertyBrowser *browser() const;
240 private:
241     explicit QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent);
242     ~QtBrowserItem();
243     QtBrowserItemPrivate *d_ptr;
244     friend class QtAbstractPropertyBrowserPrivate;
245 };
246 
247 class QtAbstractPropertyBrowserPrivate;
248 
249 class QtAbstractPropertyBrowser : public QWidget
250 {
251     Q_OBJECT
252 public:
253 
254     explicit QtAbstractPropertyBrowser(QWidget *parent = 0);
255     ~QtAbstractPropertyBrowser();
256 
257     QList<QtProperty *> properties() const;
258     QList<QtBrowserItem *> items(QtProperty *property) const;
259     QtBrowserItem *topLevelItem(QtProperty *property) const;
260     QList<QtBrowserItem *> topLevelItems() const;
261     void clear();
262 
263     template <class PropertyManager>
setFactoryForManager(PropertyManager * manager,QtAbstractEditorFactory<PropertyManager> * factory)264     void setFactoryForManager(PropertyManager *manager,
265                     QtAbstractEditorFactory<PropertyManager> *factory) {
266         QtAbstractPropertyManager *abstractManager = manager;
267         QtAbstractEditorFactoryBase *abstractFactory = factory;
268 
269         if (addFactory(abstractManager, abstractFactory))
270             factory->addPropertyManager(manager);
271     }
272 
273     void unsetFactoryForManager(QtAbstractPropertyManager *manager);
274 
275     QtBrowserItem *currentItem() const;
276     void setCurrentItem(QtBrowserItem *);
277 
278 Q_SIGNALS:
279     void currentItemChanged(QtBrowserItem *);
280 
281 public Q_SLOTS:
282 
283     QtBrowserItem *addProperty(QtProperty *property);
284     QtBrowserItem *insertProperty(QtProperty *property, QtProperty *afterProperty);
285     void removeProperty(QtProperty *property);
286 
287 protected:
288 
289     virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) = 0;
290     virtual void itemRemoved(QtBrowserItem *item) = 0;
291     // can be tooltip, statustip, whatsthis, name, icon, text.
292     virtual void itemChanged(QtBrowserItem *item) = 0;
293 
294     virtual QWidget *createEditor(QtProperty *property, QWidget *parent);
295 private:
296 
297     bool addFactory(QtAbstractPropertyManager *abstractManager,
298                 QtAbstractEditorFactoryBase *abstractFactory);
299 
300     QtAbstractPropertyBrowserPrivate *d_ptr;
301     Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser)
302     Q_DISABLE_COPY(QtAbstractPropertyBrowser)
303     Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *,
304                             QtProperty *, QtProperty *))
305     Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *,
306                             QtProperty *))
307     Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
308     Q_PRIVATE_SLOT(d_func(), void slotPropertyDataChanged(QtProperty *))
309 
310 };
311 
312 QT_END_NAMESPACE
313 
314 #endif // QTPROPERTYBROWSER_H
315