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