Add wpseditor, the Google Summer of Code 2008 project of Rostislav Chekan. Closes...
[kugel-rb.git] / utils / wpseditor / gui / src / QPropertyEditor / QPropertyModel.cpp
blobb147cd089daf52e6d0fee38e83f1383d5dbc299f
1 // *************************************************************************************************
2 //
3 // QPropertyEditor v 0.1
4 //
5 // --------------------------------------
6 // Copyright (C) 2007 Volker Wiendl
7 //
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 // *************************************************************************************************
25 #include "QPropertyModel.h"
27 #include "Property.h"
29 #include <Qt/qapplication.h>
30 #include <Qt/qmetaobject.h>
31 #include <Qt/qitemeditorfactory.h>
33 struct PropertyPair {
34 PropertyPair(const QMetaObject* obj, QMetaProperty property) : Property(property), Object(obj) {}
36 QMetaProperty Property;
37 const QMetaObject* Object;
39 bool operator==(const PropertyPair& other) const {
40 return QString(other.Property.name()) == QString(Property.name());
45 QPropertyModel::QPropertyModel(QObject* parent /*= 0*/) : QAbstractItemModel(parent), m_userCallback(0) {
46 m_rootItem = new Property("Root",0, this);
50 QPropertyModel::~QPropertyModel() {}
52 QModelIndex QPropertyModel::index ( int row, int column, const QModelIndex & parent /*= QModelIndex()*/ ) const {
53 Property *parentItem = m_rootItem;
54 if (parent.isValid())
55 parentItem = static_cast<Property*>(parent.internalPointer());
56 if (row >= parentItem->children().size())
57 return QModelIndex();
58 return createIndex(row, column, parentItem->children().at(row));
62 QModelIndex QPropertyModel::parent ( const QModelIndex & index ) const {
63 if (!index.isValid())
64 return QModelIndex();
66 Property *childItem = static_cast<Property*>(index.internalPointer());
67 Property *parentItem = qobject_cast<Property*>(childItem->parent());
69 if (!parentItem || parentItem == m_rootItem)
70 return QModelIndex();
72 return createIndex(parentItem->row(), 0, parentItem);
75 int QPropertyModel::rowCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const {
76 Property *parentItem = m_rootItem;
77 if (parent.isValid())
78 parentItem = static_cast<Property*>(parent.internalPointer());
79 return parentItem->children().size();
82 int QPropertyModel::columnCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const {
83 (void)parent;
84 return 2;
87 QVariant QPropertyModel::data ( const QModelIndex & index, int role /*= Qt::DisplayRole*/ ) const {
88 if (!index.isValid())
89 return QVariant();
91 Property *item = static_cast<Property*>(index.internalPointer());
92 switch (role) {
93 case Qt::ToolTipRole:
94 case Qt::DecorationRole:
95 case Qt::DisplayRole:
96 case Qt::EditRole:
97 if (index.column() == 0)
98 return item->objectName();
99 if (index.column() == 1)
100 return item->value(role);
101 case Qt::BackgroundRole:
102 if (item->isRoot()) return QApplication::palette("QTreeView").brush(QPalette::Normal, QPalette::Button).color();
103 break;
105 return QVariant();
108 // edit methods
109 bool QPropertyModel::setData ( const QModelIndex & index, const QVariant & value, int role /*= Qt::EditRole*/ ) {
110 if (index.isValid() && role == Qt::EditRole) {
111 Property *item = static_cast<Property*>(index.internalPointer());
112 item->setValue(value);
113 emit dataChanged(index, index);
114 return true;
116 return false;
119 Qt::ItemFlags QPropertyModel::flags ( const QModelIndex & index ) const {
120 if (!index.isValid())
121 return Qt::ItemIsEnabled;
122 Property *item = static_cast<Property*>(index.internalPointer());
123 // only allow change of value attribute
124 if (item->isRoot())
125 return Qt::ItemIsEnabled;
126 else if (item->isReadOnly())
127 return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable;
128 else
129 return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
133 QVariant QPropertyModel::headerData ( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const {
134 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
135 switch (section) {
136 case 0:
137 return tr("Name");
138 case 1:
139 return tr("Value");
142 return QVariant();
145 QModelIndex QPropertyModel::buddy ( const QModelIndex & index ) const {
146 if (index.isValid() && index.column() == 0)
147 return createIndex(index.row(), 1, index.internalPointer());
148 return index;
151 void QPropertyModel::addItem(QObject *propertyObject) {
152 // first create property <-> class hierarchy
153 QList<PropertyPair> propertyMap;
154 QList<const QMetaObject*> classList;
155 const QMetaObject* metaObject = propertyObject->metaObject();
156 do {
157 int count = metaObject->propertyCount();
158 for (int i=0; i<count; ++i) {
159 QMetaProperty property = metaObject->property(i);
160 if (property.isUser()) // Hide Qt specific properties
162 PropertyPair pair(metaObject, property);
163 int index = propertyMap.indexOf(pair);
164 if (index != -1)
165 propertyMap[index] = pair;
166 else
167 propertyMap.push_back(pair);
170 classList.push_front(metaObject);
171 } while ((metaObject = metaObject->superClass())!=0);
173 QList<const QMetaObject*> finalClassList;
174 // remove empty classes from hierarchy list
175 foreach(const QMetaObject* obj, classList) {
176 bool keep = false;
177 foreach(PropertyPair pair, propertyMap) {
178 if (pair.Object == obj) {
179 keep = true;
180 break;
183 if (keep)
184 finalClassList.push_back(obj);
187 // finally insert properties for classes containing them
188 int i=rowCount();
189 beginInsertRows(QModelIndex(), i, i + finalClassList.count());
190 foreach(const QMetaObject* metaObject, finalClassList) {
191 // Set default name of the hierarchy property to the class name
192 QString name = metaObject->className();
193 // Check if there is a special name for the class
194 int index = metaObject->indexOfClassInfo(qPrintable(name));
195 if (index != -1)
196 name = metaObject->classInfo(index).value();
197 // Create Property Item for class node
198 Property* propertyItem = new Property(name, 0, m_rootItem);
199 foreach(PropertyPair pair, propertyMap) {
200 // Check if the property is associated with the current class from the finalClassList
201 if (pair.Object == metaObject) {
202 QMetaProperty property(pair.Property);
203 Property* p = 0;
204 if (property.type() == QVariant::UserType && m_userCallback)
205 p = m_userCallback(property.name(), propertyObject, propertyItem);
206 else
207 p = new Property(property.name(), propertyObject, propertyItem);
208 int index = metaObject->indexOfClassInfo(property.name());
209 if (index != -1)
210 p->setEditorHints(metaObject->classInfo(index).value());
214 endInsertRows();
217 void QPropertyModel::updateItem ( QObject* propertyObject, const QModelIndex& parent /*= QModelIndex() */ ) {
218 Property *parentItem = m_rootItem;
219 if (parent.isValid())
220 parentItem = static_cast<Property*>(parent.internalPointer());
221 if (parentItem->propertyObject() != propertyObject)
222 parentItem = parentItem->findPropertyObject(propertyObject);
223 if (parentItem) // Indicate view that the data for the indices have changed
224 dataChanged(createIndex(parentItem->row(), 0, static_cast<Property*>(parentItem)), createIndex(parentItem->row(), 1, static_cast<Property*>(parentItem)));
227 void QPropertyModel::clear() {
228 beginRemoveRows(QModelIndex(), 0, rowCount());
229 delete m_rootItem;
230 m_rootItem = new Property("Root",0, this);
231 endRemoveRows();
234 void QPropertyModel::setCustomPropertyCB(QPropertyEditorWidget::UserTypeCB callback) {
235 m_userCallback = callback;