/*************************************************************************** * This file is part of the Lime Report project * * Copyright (C) 2015 by Alexander Arin * * arin_a@bk.ru * * * ** GNU General Public License Usage ** * * * This library is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ** GNU Lesser General Public License ** * * * 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 3 of the * * License, or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * * License along with this library. * * If not, see . * * * * 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 General Public License for more details. * ****************************************************************************/ #include "lrobjectitemmodel.h" #include #include #include #include namespace LimeReport { QObjectPropertyModel::QObjectPropertyModel(QObject *parent/*=0*/) :QAbstractItemModel(parent),m_rootNode(0),m_object(0),m_dataChanging(false), m_subclassesAsLevel(true), m_validator(0) {} QObjectPropertyModel::~QObjectPropertyModel() { if (m_rootNode) delete m_rootNode; } void QObjectPropertyModel::initModel() { beginResetModel(); delete m_rootNode; m_rootNode=0; if (m_object) { connect(m_object,SIGNAL(destroyed(QObject*)),this,SLOT(slotObjectDestroyed(QObject*))); m_rootNode=new ObjectPropItem(0,0,"root","root",QVariant(),0); m_rootNode->setModel(this); foreach(QObject* item, m_objects) connect(item,SIGNAL(destroyed(QObject*)),this,SLOT(slotObjectDestroyed(QObject*))); addObjectProperties(m_object->metaObject(), m_object, &m_objects); } //reset(); endResetModel(); } void QObjectPropertyModel::setObject(QObject *object) { m_objects.clear(); if (m_object!=object){ submit(); m_object=object; initModel(); } } void QObjectPropertyModel::setMultiObjects(QList* list) { m_objects.clear(); submit(); if (m_object!=list->at(0)){ m_object=list->at(0); list->removeAt(0); foreach(QObject* item, *list) m_objects.append(item); initModel(); } } void QObjectPropertyModel::slotObjectDestroyed(QObject *obj) { m_objects.removeOne(obj); if (m_object == obj){ m_object=0; if (!m_objects.isEmpty()) m_object=m_objects.at(0); initModel(); } } void QObjectPropertyModel::slotPropertyChanged(const QString &propertyName, const QVariant& oldValue, const QVariant& newValue) { Q_UNUSED(oldValue); Q_UNUSED(newValue); if (m_object) updateProperty(propertyName); } void QObjectPropertyModel::slotPropertyObjectNameChanged(const QString &oldName, const QString &newName) { Q_UNUSED(oldName) Q_UNUSED(newName) if (m_object) updateProperty("objectName"); } int QObjectPropertyModel::columnCount(const QModelIndex &/*parent*/) const { return 2; } QVariant QObjectPropertyModel::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation==Qt::Horizontal&&role==Qt::DisplayRole){ if (section==0) return tr("Property Name"); else return tr("Property value"); } else return QVariant(); } ObjectPropItem * QObjectPropertyModel::nodeFromIndex(const QModelIndex &index) const { if(index.isValid()){ return static_cast(index.internalPointer()); } else return m_rootNode; } void QObjectPropertyModel::updateProperty(const QString &propertyName) { if (!m_dataChanging&&m_rootNode){ ObjectPropItem* propItem = m_rootNode->findPropertyItem(propertyName); if (propItem) propItem->updatePropertyValue(); } } void QObjectPropertyModel::setSubclassesAsLevel(bool value) { m_subclassesAsLevel = value; } int QObjectPropertyModel::rowCount(const QModelIndex &parent) const { if (!m_rootNode) return 0; ObjectPropItem *parentNode; if (parent.isValid()) parentNode = nodeFromIndex(parent); else parentNode = m_rootNode; return parentNode->childCount(); } QVariant QObjectPropertyModel::data(const QModelIndex &index, int role) const { ObjectPropItem *node = nodeFromIndex(index); switch (role) { case Qt::DisplayRole: if (!node) return QVariant(); if (index.column()==0){ return node->displayName(); } else return node->displayValue(); break; case Qt::DecorationRole : if (!node) return QIcon(); if (index.column()==1){ return node->iconValue(); }else return QIcon(); break; default: return QVariant(); } } QModelIndex QObjectPropertyModel::index(int row, int column, const QModelIndex &parent) const { if(!m_rootNode) return QModelIndex(); if (!hasIndex(row, column, parent)) return QModelIndex(); ObjectPropItem *parentNode; if (parent.isValid()) parentNode = nodeFromIndex(parent); else parentNode = m_rootNode; ObjectPropItem *childItem=parentNode->child(row); if (childItem){ QModelIndex modelIndex=createIndex(row,column,childItem); if (column==1){ if (childItem->modelIndex()!=modelIndex){ childItem->setModelIndex(modelIndex); } } return modelIndex; } else return QModelIndex(); } QModelIndex QObjectPropertyModel::parent(const QModelIndex &child) const { if (!child.isValid()) return QModelIndex(); ObjectPropItem *childNode = nodeFromIndex(child); if (!childNode) return QModelIndex(); ObjectPropItem *parentNode = childNode->parent(); if ((parentNode == m_rootNode) || (!parentNode)) return QModelIndex(); return createIndex(parentNode->row(),0,parentNode); } Qt::ItemFlags QObjectPropertyModel::flags(const QModelIndex &index) const { if ((index.column()==1)&&(!nodeFromIndex(index)->isValueReadonly())) return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable; else return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } CreatePropItem QObjectPropertyModel::propertyItemCreator(QMetaProperty prop) { CreatePropItem creator=0; creator=ObjectPropFactory::instance().objectCreator(APropIdent(prop.name(),prop.enclosingMetaObject()->className())); if (!creator){ if (prop.isFlagType()){ creator=ObjectPropFactory::instance().objectCreator(APropIdent("flags","")); if (creator){ return creator; } else { qDebug()<<"flags prop editor not found"; return 0; } } if (prop.isEnumType()){ creator=ObjectPropFactory::instance().objectCreator(APropIdent("enum","")); if (creator){ return creator; } else { qDebug()<<"enum prop editor not found"; return 0; } } creator=ObjectPropFactory::instance().objectCreator(APropIdent(prop.typeName(),"")); if (!creator) {qDebug()<<"Editor for propperty name = \""<property(prop.name()), parent, !(prop.isWritable()&&prop.isDesignable()) ); } else { propertyItem=new ObjectPropItem( 0, 0, QString(prop.name()), QString(prop.name()), object->property(prop.name()), parent ); } return propertyItem; } ValidatorIntf *QObjectPropertyModel::validator() const { return m_validator; } void QObjectPropertyModel::setValidator(ValidatorIntf *validator) { m_validator = validator; } void QObjectPropertyModel::addObjectProperties(const QMetaObject *metaObject, QObject *object, ObjectPropItem::ObjectsList *objects, int level) { if (metaObject->propertyCount()>metaObject->propertyOffset()){ ObjectPropItem* objectNode; if (m_subclassesAsLevel){ objectNode=new ObjectPropItem(0,0,metaObject->className(),metaObject->className(),m_rootNode,true); m_rootNode->appendItem(objectNode); } else { objectNode = m_rootNode; } //m_rootNode->appendItem(objectNode); for (int i=metaObject->propertyOffset();ipropertyCount();i++){ if (metaObject->property(i).isDesignable()){ ObjectPropItem* prop=createPropertyItem(metaObject->property(i),object,objects,objectNode); //ObjectPropItem* prop=createPropertyItem(metaObject->property(i),object,objects,m_rootNode); //m_rootNode->appendItem(prop); objectNode->appendItem(prop); } } if (m_subclassesAsLevel){ objectNode->setColorIndex(level); objectNode->sortItem(); level++; } } if (metaObject->superClass()) addObjectProperties(metaObject->superClass(),object,objects,level); m_rootNode->sortItem(); } bool QObjectPropertyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid()&&role==Qt::EditRole){ m_dataChanging=true; ObjectPropItem * propItem = nodeFromIndex(index); if (propItem->propertyValue()!=value){ QString msg; if (validator() && !validator()->validate(propItem->propertyName(),value.toString(),m_object,msg)){ QMessageBox::information(0,tr("Warning"),msg); return true; } QVariant oldValue=propItem->propertyValue(); propItem->setPropertyValue(value); emit dataChanged(index,index); emit objectPropetyChanged(propItem->propertyName(),oldValue,propItem->propertyValue()); } m_dataChanging=false; return true; } return false; } void QObjectPropertyModel::itemDataChanged(const QModelIndex &index) { emit dataChanged(index,index); } }