1
0
Fork 0
forked from len0rd/rockbox
foxbox/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.cpp
Frank Gevaerts 5d22e3cbdd Add wpseditor, the Google Summer of Code 2008 project of Rostislav Chekan. Closes FS#9327
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18362 a1c6a512-1295-4272-9138-f99709370657
2008-08-29 21:08:38 +00:00

236 lines
8.5 KiB
C++

// *************************************************************************************************
//
// QPropertyEditor v 0.1
//
// --------------------------------------
// Copyright (C) 2007 Volker Wiendl
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// *************************************************************************************************
#include "QPropertyModel.h"
#include "Property.h"
#include <Qt/qapplication.h>
#include <Qt/qmetaobject.h>
#include <Qt/qitemeditorfactory.h>
struct PropertyPair {
PropertyPair(const QMetaObject* obj, QMetaProperty property) : Property(property), Object(obj) {}
QMetaProperty Property;
const QMetaObject* Object;
bool operator==(const PropertyPair& other) const {
return QString(other.Property.name()) == QString(Property.name());
}
};
QPropertyModel::QPropertyModel(QObject* parent /*= 0*/) : QAbstractItemModel(parent), m_userCallback(0) {
m_rootItem = new Property("Root",0, this);
}
QPropertyModel::~QPropertyModel() {}
QModelIndex QPropertyModel::index ( int row, int column, const QModelIndex & parent /*= QModelIndex()*/ ) const {
Property *parentItem = m_rootItem;
if (parent.isValid())
parentItem = static_cast<Property*>(parent.internalPointer());
if (row >= parentItem->children().size())
return QModelIndex();
return createIndex(row, column, parentItem->children().at(row));
}
QModelIndex QPropertyModel::parent ( const QModelIndex & index ) const {
if (!index.isValid())
return QModelIndex();
Property *childItem = static_cast<Property*>(index.internalPointer());
Property *parentItem = qobject_cast<Property*>(childItem->parent());
if (!parentItem || parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
int QPropertyModel::rowCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const {
Property *parentItem = m_rootItem;
if (parent.isValid())
parentItem = static_cast<Property*>(parent.internalPointer());
return parentItem->children().size();
}
int QPropertyModel::columnCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const {
(void)parent;
return 2;
}
QVariant QPropertyModel::data ( const QModelIndex & index, int role /*= Qt::DisplayRole*/ ) const {
if (!index.isValid())
return QVariant();
Property *item = static_cast<Property*>(index.internalPointer());
switch (role) {
case Qt::ToolTipRole:
case Qt::DecorationRole:
case Qt::DisplayRole:
case Qt::EditRole:
if (index.column() == 0)
return item->objectName();
if (index.column() == 1)
return item->value(role);
case Qt::BackgroundRole:
if (item->isRoot()) return QApplication::palette("QTreeView").brush(QPalette::Normal, QPalette::Button).color();
break;
};
return QVariant();
}
// edit methods
bool QPropertyModel::setData ( const QModelIndex & index, const QVariant & value, int role /*= Qt::EditRole*/ ) {
if (index.isValid() && role == Qt::EditRole) {
Property *item = static_cast<Property*>(index.internalPointer());
item->setValue(value);
emit dataChanged(index, index);
return true;
}
return false;
}
Qt::ItemFlags QPropertyModel::flags ( const QModelIndex & index ) const {
if (!index.isValid())
return Qt::ItemIsEnabled;
Property *item = static_cast<Property*>(index.internalPointer());
// only allow change of value attribute
if (item->isRoot())
return Qt::ItemIsEnabled;
else if (item->isReadOnly())
return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable;
else
return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
QVariant QPropertyModel::headerData ( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Name");
case 1:
return tr("Value");
}
}
return QVariant();
}
QModelIndex QPropertyModel::buddy ( const QModelIndex & index ) const {
if (index.isValid() && index.column() == 0)
return createIndex(index.row(), 1, index.internalPointer());
return index;
}
void QPropertyModel::addItem(QObject *propertyObject) {
// first create property <-> class hierarchy
QList<PropertyPair> propertyMap;
QList<const QMetaObject*> classList;
const QMetaObject* metaObject = propertyObject->metaObject();
do {
int count = metaObject->propertyCount();
for (int i=0; i<count; ++i) {
QMetaProperty property = metaObject->property(i);
if (property.isUser()) // Hide Qt specific properties
{
PropertyPair pair(metaObject, property);
int index = propertyMap.indexOf(pair);
if (index != -1)
propertyMap[index] = pair;
else
propertyMap.push_back(pair);
}
}
classList.push_front(metaObject);
} while ((metaObject = metaObject->superClass())!=0);
QList<const QMetaObject*> finalClassList;
// remove empty classes from hierarchy list
foreach(const QMetaObject* obj, classList) {
bool keep = false;
foreach(PropertyPair pair, propertyMap) {
if (pair.Object == obj) {
keep = true;
break;
}
}
if (keep)
finalClassList.push_back(obj);
}
// finally insert properties for classes containing them
int i=rowCount();
beginInsertRows(QModelIndex(), i, i + finalClassList.count());
foreach(const QMetaObject* metaObject, finalClassList) {
// Set default name of the hierarchy property to the class name
QString name = metaObject->className();
// Check if there is a special name for the class
int index = metaObject->indexOfClassInfo(qPrintable(name));
if (index != -1)
name = metaObject->classInfo(index).value();
// Create Property Item for class node
Property* propertyItem = new Property(name, 0, m_rootItem);
foreach(PropertyPair pair, propertyMap) {
// Check if the property is associated with the current class from the finalClassList
if (pair.Object == metaObject) {
QMetaProperty property(pair.Property);
Property* p = 0;
if (property.type() == QVariant::UserType && m_userCallback)
p = m_userCallback(property.name(), propertyObject, propertyItem);
else
p = new Property(property.name(), propertyObject, propertyItem);
int index = metaObject->indexOfClassInfo(property.name());
if (index != -1)
p->setEditorHints(metaObject->classInfo(index).value());
}
}
}
endInsertRows();
}
void QPropertyModel::updateItem ( QObject* propertyObject, const QModelIndex& parent /*= QModelIndex() */ ) {
Property *parentItem = m_rootItem;
if (parent.isValid())
parentItem = static_cast<Property*>(parent.internalPointer());
if (parentItem->propertyObject() != propertyObject)
parentItem = parentItem->findPropertyObject(propertyObject);
if (parentItem) // Indicate view that the data for the indices have changed
dataChanged(createIndex(parentItem->row(), 0, static_cast<Property*>(parentItem)), createIndex(parentItem->row(), 1, static_cast<Property*>(parentItem)));
}
void QPropertyModel::clear() {
beginRemoveRows(QModelIndex(), 0, rowCount());
delete m_rootItem;
m_rootItem = new Property("Root",0, this);
endRemoveRows();
}
void QPropertyModel::setCustomPropertyCB(QPropertyEditorWidget::UserTypeCB callback) {
m_userCallback = callback;
}