objectcontroller.cpp
Go to the documentation of this file.
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 #include <QMetaObject>
42 #include <QMetaProperty>
43 #include <QVBoxLayout>
44 #include <QScrollArea>
45 #include "objectcontroller.h"
46 #include "qtvariantproperty.h"
48 #include "qttreepropertybrowser.h"
49 #include "qtpropertybrowser.h"
50 
52 {
53  ObjectController* q_ptr;
54  Q_DECLARE_PUBLIC(ObjectController)
55 public:
56 
57  void addClassProperties(const QMetaObject* metaObject);
58  void updateClassProperties(const QMetaObject* metaObject, bool recursive);
59  void saveExpandedState();
60  void restoreExpandedState();
61  void slotValueChanged(QtProperty* property, const QVariant& value);
62  int enumToInt(const QMetaEnum& metaEnum, int enumValue) const;
63  int intToEnum(const QMetaEnum& metaEnum, int intValue) const;
64  int flagToInt(const QMetaEnum& metaEnum, int flagValue) const;
65  int intToFlag(const QMetaEnum& metaEnum, int intValue) const;
66  bool isSubValue(int value, int subValue) const;
67  bool isPowerOf2(int value) const;
68 
69  QObject* m_object;
70 
71  QMap<const QMetaObject*, QtProperty*> m_classToProperty;
72  QMap<QtProperty*, const QMetaObject*> m_propertyToClass;
73  QMap<QtProperty*, int> m_propertyToIndex;
74  QMap<const QMetaObject*, QMap<int, QtVariantProperty*> > m_classToIndexToProperty;
75 
76  QMap<QtProperty*, bool> m_propertyToExpanded;
77 
78  QList<QtProperty*> m_topLevelProperties;
79 
83 };
84 
85 int ObjectControllerPrivate::enumToInt(const QMetaEnum& metaEnum, int enumValue) const
86 {
87  QMap<int, int> valueMap; // dont show multiple enum values which have the same values
88  int pos = 0;
89 
90  for (int i = 0; i < metaEnum.keyCount(); i++)
91  {
92  int value = metaEnum.value(i);
93 
94  if (!valueMap.contains(value))
95  {
96  if (value == enumValue)
97  {
98  return pos;
99  }
100 
101  valueMap[value] = pos++;
102  }
103  }
104 
105  return -1;
106 }
107 
108 int ObjectControllerPrivate::intToEnum(const QMetaEnum& metaEnum, int intValue) const
109 {
110  QMap<int, bool> valueMap; // dont show multiple enum values which have the same values
111  QList<int> values;
112 
113  for (int i = 0; i < metaEnum.keyCount(); i++)
114  {
115  int value = metaEnum.value(i);
116 
117  if (!valueMap.contains(value))
118  {
119  valueMap[value] = true;
120  values.append(value);
121  }
122  }
123 
124  if (intValue >= values.count())
125  {
126  return -1;
127  }
128 
129  return values.at(intValue);
130 }
131 
132 bool ObjectControllerPrivate::isSubValue(int value, int subValue) const
133 {
134  if (value == subValue)
135  {
136  return true;
137  }
138 
139  int i = 0;
140 
141  while (subValue)
142  {
143  if (!(value & (1 << i)))
144  {
145  if (subValue & 1)
146  {
147  return false;
148  }
149  }
150 
151  i++;
152  subValue = subValue >> 1;
153  }
154 
155  return true;
156 }
157 
159 {
160  while (value)
161  {
162  if (value & 1)
163  {
164  return value == 1;
165  }
166 
167  value = value >> 1;
168  }
169 
170  return false;
171 }
172 
173 int ObjectControllerPrivate::flagToInt(const QMetaEnum& metaEnum, int flagValue) const
174 {
175  if (!flagValue)
176  {
177  return 0;
178  }
179 
180  int intValue = 0;
181  QMap<int, int> valueMap; // dont show multiple enum values which have the same values
182  int pos = 0;
183 
184  for (int i = 0; i < metaEnum.keyCount(); i++)
185  {
186  int value = metaEnum.value(i);
187 
188  if (!valueMap.contains(value) && isPowerOf2(value))
189  {
190  if (isSubValue(flagValue, value))
191  {
192  intValue |= (1 << pos);
193  }
194 
195  valueMap[value] = pos++;
196  }
197  }
198 
199  return intValue;
200 }
201 
202 int ObjectControllerPrivate::intToFlag(const QMetaEnum& metaEnum, int intValue) const
203 {
204  QMap<int, bool> valueMap; // dont show multiple enum values which have the same values
205  QList<int> values;
206 
207  for (int i = 0; i < metaEnum.keyCount(); i++)
208  {
209  int value = metaEnum.value(i);
210 
211  if (!valueMap.contains(value) && isPowerOf2(value))
212  {
213  valueMap[value] = true;
214  values.append(value);
215  }
216  }
217 
218  int flagValue = 0;
219  int temp = intValue;
220  int i = 0;
221 
222  while (temp)
223  {
224  if (i >= values.count())
225  {
226  return -1;
227  }
228 
229  if (temp & 1)
230  {
231  flagValue |= values.at(i);
232  }
233 
234  i++;
235  temp = temp >> 1;
236  }
237 
238  return flagValue;
239 }
240 
241 void ObjectControllerPrivate::updateClassProperties(const QMetaObject* metaObject, bool recursive)
242 {
243  if (!metaObject)
244  {
245  return;
246  }
247 
248  if (recursive)
249  {
250  updateClassProperties(metaObject->superClass(), recursive);
251  }
252 
253  QtProperty* classProperty = m_classToProperty.value(metaObject);
254 
255  if (!classProperty)
256  {
257  return;
258  }
259 
260  for (int idx = metaObject->propertyOffset(); idx < metaObject->propertyCount(); idx++)
261  {
262  QMetaProperty metaProperty = metaObject->property(idx);
263 
264  if (metaProperty.isReadable())
265  {
266  if (m_classToIndexToProperty.contains(metaObject) && m_classToIndexToProperty[metaObject].contains(idx))
267  {
268  QtVariantProperty* subProperty = m_classToIndexToProperty[metaObject][idx];
269 
270  if (metaProperty.isEnumType())
271  {
272  if (metaProperty.isFlagType())
273  {
274  subProperty->setValue(flagToInt(metaProperty.enumerator(), metaProperty.read(m_object).toInt()));
275  }
276  else
277  {
278  subProperty->setValue(enumToInt(metaProperty.enumerator(), metaProperty.read(m_object).toInt()));
279  }
280  }
281  else
282  {
283  subProperty->setValue(metaProperty.read(m_object));
284  }
285  }
286  }
287  }
288 }
289 
290 void ObjectControllerPrivate::addClassProperties(const QMetaObject* metaObject)
291 {
292  if (!metaObject)
293  {
294  return;
295  }
296 
297  addClassProperties(metaObject->superClass());
298 
299  QtProperty* classProperty = m_classToProperty.value(metaObject);
300 
301  if (!classProperty)
302  {
303  QString className = QLatin1String(metaObject->className());
304  classProperty = m_manager->addProperty(QtVariantPropertyManager::groupTypeId(), className);
305  m_classToProperty[metaObject] = classProperty;
306  m_propertyToClass[classProperty] = metaObject;
307 
308  for (int idx = metaObject->propertyOffset(); idx < metaObject->propertyCount(); idx++)
309  {
310  QMetaProperty metaProperty = metaObject->property(idx);
311  int type = metaProperty.userType();
312  QtVariantProperty* subProperty = 0;
313 
314  if (!metaProperty.isReadable())
315  {
316  subProperty = m_readOnlyManager->addProperty(QVariant::String, QLatin1String(metaProperty.name()));
317  subProperty->setValue(QLatin1String("< Non Readable >"));
318  }
319  else if (metaProperty.isEnumType())
320  {
321  if (metaProperty.isFlagType())
322  {
323  subProperty = m_manager->addProperty(QtVariantPropertyManager::flagTypeId(), QLatin1String(metaProperty.name()));
324  QMetaEnum metaEnum = metaProperty.enumerator();
325  QMap<int, bool> valueMap;
326  QStringList flagNames;
327 
328  for (int i = 0; i < metaEnum.keyCount(); i++)
329  {
330  int value = metaEnum.value(i);
331 
332  if (!valueMap.contains(value) && isPowerOf2(value))
333  {
334  valueMap[value] = true;
335  flagNames.append(QLatin1String(metaEnum.key(i)));
336  }
337 
338  subProperty->setAttribute(QLatin1String("flagNames"), flagNames);
339  subProperty->setValue(flagToInt(metaEnum, metaProperty.read(m_object).toInt()));
340  }
341  }
342  else
343  {
344  subProperty = m_manager->addProperty(QtVariantPropertyManager::enumTypeId(), QLatin1String(metaProperty.name()));
345  QMetaEnum metaEnum = metaProperty.enumerator();
346  QMap<int, bool> valueMap; // dont show multiple enum values which have the same values
347  QStringList enumNames;
348 
349  for (int i = 0; i < metaEnum.keyCount(); i++)
350  {
351  int value = metaEnum.value(i);
352 
353  if (!valueMap.contains(value))
354  {
355  valueMap[value] = true;
356  enumNames.append(QLatin1String(metaEnum.key(i)));
357  }
358  }
359 
360  subProperty->setAttribute(QLatin1String("enumNames"), enumNames);
361  subProperty->setValue(enumToInt(metaEnum, metaProperty.read(m_object).toInt()));
362  }
363  }
364  else if (m_manager->isPropertyTypeSupported(type))
365  {
366  if (!metaProperty.isWritable())
367  {
368  subProperty = m_readOnlyManager->addProperty(type, QLatin1String(metaProperty.name()) + QLatin1String(" (Non Writable)"));
369  }
370 
371  if (!metaProperty.isDesignable())
372  {
373  subProperty = m_readOnlyManager->addProperty(type, QLatin1String(metaProperty.name()) + QLatin1String(" (Non Designable)"));
374  }
375  else
376  {
377  subProperty = m_manager->addProperty(type, QLatin1String(metaProperty.name()));
378  }
379 
380  subProperty->setValue(metaProperty.read(m_object));
381  }
382  else
383  {
384  subProperty = m_readOnlyManager->addProperty(QVariant::String, QLatin1String(metaProperty.name()));
385  subProperty->setValue(QLatin1String("< Unknown Type >"));
386  subProperty->setEnabled(false);
387  }
388 
389  classProperty->addSubProperty(subProperty);
390  m_propertyToIndex[subProperty] = idx;
391  m_classToIndexToProperty[metaObject][idx] = subProperty;
392  }
393  }
394  else
395  {
396  updateClassProperties(metaObject, false);
397  }
398 
399  m_topLevelProperties.append(classProperty);
400  m_browser->addProperty(classProperty);
401 }
402 
404 {
405 
406 }
407 
409 {
410 
411 }
412 
414 {
415  if (!m_propertyToIndex.contains(property))
416  {
417  return;
418  }
419 
420  int idx = m_propertyToIndex.value(property);
421 
422  const QMetaObject* metaObject = m_object->metaObject();
423  QMetaProperty metaProperty = metaObject->property(idx);
424 
425  if (metaProperty.isEnumType())
426  {
427  if (metaProperty.isFlagType())
428  {
429  metaProperty.write(m_object, intToFlag(metaProperty.enumerator(), value.toInt()));
430  }
431  else
432  {
433  metaProperty.write(m_object, intToEnum(metaProperty.enumerator(), value.toInt()));
434  }
435  }
436  else
437  {
438  metaProperty.write(m_object, value);
439  }
440 
441  updateClassProperties(metaObject, true);
442 }
443 
444 ///////////////////
445 
447  : QWidget(parent)
448 {
449  d_ptr = new ObjectControllerPrivate;
450  d_ptr->q_ptr = this;
451 
452  d_ptr->m_object = 0;
453  /*
454  QScrollArea *scroll = new QScrollArea(this);
455  scroll->setWidgetResizable(true);
456 
457  d_ptr->m_browser = new QtGroupBoxPropertyBrowser(this);
458  QVBoxLayout *layout = new QVBoxLayout(this);
459  layout->setMargin(0);
460  layout->addWidget(scroll);
461  scroll->setWidget(d_ptr->m_browser);
462  */
463  QtTreePropertyBrowser* browser = new QtTreePropertyBrowser(this);
464  browser->setRootIsDecorated(false);
465  d_ptr->m_browser = browser;
466  QVBoxLayout* layout = new QVBoxLayout(this);
467  layout->setMargin(0);
468  layout->addWidget(d_ptr->m_browser);
469 
470  d_ptr->m_readOnlyManager = new QtVariantPropertyManager(this);
471  d_ptr->m_manager = new QtVariantPropertyManager(this);
472  QtVariantEditorFactory* factory = new QtVariantEditorFactory(this);
473  d_ptr->m_browser->setFactoryForManager(d_ptr->m_manager, factory);
474 
475  connect(d_ptr->m_manager, SIGNAL(valueChanged(QtProperty*, const QVariant&)),
476  this, SLOT(slotValueChanged(QtProperty*, const QVariant&)));
477 }
478 
480 {
481  delete d_ptr;
482 }
483 
484 void ObjectController::setObject(QObject* object)
485 {
486  if (d_ptr->m_object == object)
487  {
488  return;
489  }
490 
491  if (d_ptr->m_object)
492  {
493  d_ptr->saveExpandedState();
494  QListIterator<QtProperty*> it(d_ptr->m_topLevelProperties);
495 
496  while (it.hasNext())
497  {
498  d_ptr->m_browser->removeProperty(it.next());
499  }
500 
501  d_ptr->m_topLevelProperties.clear();
502  }
503 
504  d_ptr->m_object = object;
505 
506  if (!d_ptr->m_object)
507  {
508  return;
509  }
510 
511  d_ptr->addClassProperties(d_ptr->m_object->metaObject());
512 
513  d_ptr->restoreExpandedState();
514 }
515 
516 QObject* ObjectController::object() const
517 {
518  return d_ptr->m_object;
519 }
520 
521 #include "moc_objectcontroller.cpp"
QtVariantPropertyManager::addProperty
virtual QtVariantProperty * addProperty(int propertyType, const QString &name=QString())
Definition: qtvariantproperty.cpp:1403
QtAbstractPropertyBrowser::addProperty
QtBrowserItem * addProperty(QtProperty *property)
Definition: qtpropertybrowser.cpp:1969
ObjectControllerPrivate::m_topLevelProperties
QList< QtProperty * > m_topLevelProperties
Definition: objectcontroller.cpp:116
QtTreePropertyBrowser
The QtTreePropertyBrowser class provides QTreeWidget based property browser.
Definition: qttreepropertybrowser.h:51
ObjectController
Definition: objectcontroller.h:47
ObjectControllerPrivate::isPowerOf2
bool isPowerOf2(int value) const
Definition: objectcontroller.cpp:158
ObjectControllerPrivate::isSubValue
bool isSubValue(int value, int subValue) const
Definition: objectcontroller.cpp:132
QtAbstractPropertyBrowser
QtAbstractPropertyBrowser provides a base class for implementing property browsers.
Definition: qtpropertybrowser.h:289
ObjectControllerPrivate::m_propertyToClass
QMap< QtProperty *, const QMetaObject * > m_propertyToClass
Definition: objectcontroller.cpp:110
ProsthesisInterface.values
values
Definition: ProsthesisInterface.py:190
ObjectControllerPrivate::restoreExpandedState
void restoreExpandedState()
Definition: objectcontroller.cpp:408
QtVariantPropertyManager
The QtVariantPropertyManager class provides and manages QVariant based properties.
Definition: qtvariantproperty.h:75
ObjectControllerPrivate::m_classToIndexToProperty
QMap< const QMetaObject *, QMap< int, QtVariantProperty * > > m_classToIndexToProperty
Definition: objectcontroller.cpp:112
QtProperty
The QtProperty class encapsulates an instance of a property.
Definition: qtpropertybrowser.h:71
ObjectController::~ObjectController
~ObjectController()
Definition: objectcontroller.cpp:479
ObjectControllerPrivate::m_classToProperty
QMap< const QMetaObject *, QtProperty * > m_classToProperty
Definition: objectcontroller.cpp:109
qtpropertybrowser.h
ObjectControllerPrivate::m_manager
QtVariantPropertyManager * m_manager
Definition: objectcontroller.cpp:119
ObjectControllerPrivate::intToFlag
int intToFlag(const QMetaEnum &metaEnum, int intValue) const
Definition: objectcontroller.cpp:202
QtTreePropertyBrowser::setRootIsDecorated
void setRootIsDecorated(bool show)
Definition: qttreepropertybrowser.cpp:989
QtVariantProperty
The QtVariantProperty class is a convenience class handling QVariant based properties.
Definition: qtvariantproperty.h:55
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
ObjectControllerPrivate::updateClassProperties
void updateClassProperties(const QMetaObject *metaObject, bool recursive)
Definition: objectcontroller.cpp:241
QtVariantPropertyManager::isPropertyTypeSupported
virtual bool isPropertyTypeSupported(int propertyType) const
Definition: qtvariantproperty.cpp:1379
ObjectControllerPrivate::m_propertyToIndex
QMap< QtProperty *, int > m_propertyToIndex
Definition: objectcontroller.cpp:111
qtvariantproperty.h
ObjectControllerPrivate::slotValueChanged
void slotValueChanged(QtProperty *property, const QVariant &value)
Definition: objectcontroller.cpp:413
ObjectControllerPrivate::m_readOnlyManager
QtVariantPropertyManager * m_readOnlyManager
Definition: objectcontroller.cpp:120
ObjectControllerPrivate::m_object
QObject * m_object
Definition: objectcontroller.cpp:107
ObjectControllerPrivate::saveExpandedState
void saveExpandedState()
Definition: objectcontroller.cpp:403
qtgroupboxpropertybrowser.h
QtVariantPropertyManager::groupTypeId
static int groupTypeId()
Definition: qtvariantproperty.cpp:115
QtAbstractPropertyBrowser::removeProperty
void removeProperty(QtProperty *property)
Definition: qtpropertybrowser.cpp:2048
QtVariantEditorFactory
The QtVariantEditorFactory class provides widgets for properties created by QtVariantPropertyManager ...
Definition: qtvariantproperty.h:162
QtVariantProperty::setValue
void setValue(const QVariant &value)
Definition: qtvariantproperty.cpp:272
ObjectControllerPrivate::flagToInt
int flagToInt(const QMetaEnum &metaEnum, int flagValue) const
Definition: objectcontroller.cpp:173
ObjectControllerPrivate
Definition: objectcontroller.cpp:51
ObjectController::object
QObject * object() const
Definition: objectcontroller.cpp:516
qttreepropertybrowser.h
QtProperty::setEnabled
void setEnabled(bool enable)
Definition: qtpropertybrowser.cpp:392
QtProperty::addSubProperty
void addSubProperty(QtProperty *property)
Definition: qtpropertybrowser.cpp:427
ObjectControllerPrivate::enumToInt
int enumToInt(const QMetaEnum &metaEnum, int enumValue) const
Definition: objectcontroller.cpp:85
ObjectControllerPrivate::m_browser
QtAbstractPropertyBrowser * m_browser
Definition: objectcontroller.cpp:118
objectcontroller.h
cxxopts::String
std::string String
Definition: cxxopts.hpp:209
QtVariantPropertyManager::flagTypeId
static int flagTypeId()
Definition: qtvariantproperty.cpp:101
ObjectControllerPrivate::m_propertyToExpanded
QMap< QtProperty *, bool > m_propertyToExpanded
Definition: objectcontroller.cpp:114
QtVariantProperty::setAttribute
void setAttribute(const QString &attribute, const QVariant &value)
Definition: qtvariantproperty.cpp:286
QtVariantPropertyManager::enumTypeId
static int enumTypeId()
Definition: qtvariantproperty.cpp:87
QtAbstractPropertyBrowser::setFactoryForManager
void setFactoryForManager(PropertyManager *manager, QtAbstractEditorFactory< PropertyManager > *factory)
Definition: qtpropertybrowser.h:304
ObjectController::setObject
void setObject(QObject *object)
Definition: objectcontroller.cpp:484
ObjectControllerPrivate::addClassProperties
void addClassProperties(const QMetaObject *metaObject)
Definition: objectcontroller.cpp:290
ObjectControllerPrivate::intToEnum
int intToEnum(const QMetaEnum &metaEnum, int intValue) const
Definition: objectcontroller.cpp:108
ObjectController::ObjectController
ObjectController(QWidget *parent=0)
Definition: objectcontroller.cpp:446