PropertyModel.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <cfloat>
00028 #endif
00029 
00030 #include "PropertyModel.h"
00031 #include "PropertyItem.h"
00032 
00033 using namespace Gui::PropertyEditor;
00034 
00035 
00036 /* TRANSLATOR Gui::PropertyEditor::PropertyModel */
00037 
00038 PropertyModel::PropertyModel(QObject* parent)
00039     : QAbstractItemModel(parent)
00040 {
00041     rootItem = static_cast<PropertyItem*>(PropertyItem::create());
00042 }
00043 
00044 PropertyModel::~PropertyModel()
00045 {
00046     delete rootItem;
00047 }
00048 
00049 QModelIndex PropertyModel::buddy ( const QModelIndex & index ) const
00050 {
00051     if (index.column() == 1)
00052         return index;
00053     return index.sibling(index.row(), 1);
00054 }
00055 
00056 int PropertyModel::columnCount ( const QModelIndex & parent ) const
00057 {
00058     // <property, value>, hence always 2
00059     if (parent.isValid())
00060         return static_cast<PropertyItem*>(parent.internalPointer())->columnCount();
00061     else
00062         return rootItem->columnCount();
00063 }
00064 
00065 QVariant PropertyModel::data ( const QModelIndex & index, int role ) const
00066 {
00067     if (!index.isValid())
00068         return QVariant();
00069 
00070     PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
00071     return item->data(index.column(), role);
00072 }
00073 
00074 bool PropertyModel::setData(const QModelIndex& index, const QVariant & value, int role)
00075 {
00076     if (!index.isValid())
00077         return false;
00078 
00079     // we check whether the data has really changed, otherwise we ignore it
00080     if (role == Qt::EditRole) {
00081         PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
00082         QVariant data = item->data(index.column(), role);
00083         if (data.type() == QVariant::Double && value.type() == QVariant::Double) {
00084             // since we store some properties as floats we get some round-off
00085             // errors here. Thus, we use an epsilon here.
00086             double d = data.toDouble();
00087             double v = value.toDouble();
00088             if (fabs(d-v) > FLT_EPSILON)
00089                 return item->setData(value);
00090         }
00091         else if (data != value)
00092             return item->setData(value);
00093     }
00094 
00095     return true;
00096 }
00097 
00098 Qt::ItemFlags PropertyModel::flags(const QModelIndex &index) const
00099 {
00100     PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
00101     return item->flags(index.column());
00102 }
00103 
00104 QModelIndex PropertyModel::index ( int row, int column, const QModelIndex & parent ) const
00105 {
00106     PropertyItem *parentItem;
00107 
00108     if (!parent.isValid())
00109         parentItem = rootItem;
00110     else
00111         parentItem = static_cast<PropertyItem*>(parent.internalPointer());
00112 
00113     PropertyItem *childItem = parentItem->child(row);
00114     if (childItem)
00115         return createIndex(row, column, childItem);
00116     else
00117         return QModelIndex();
00118 }
00119 
00120 QModelIndex PropertyModel::parent ( const QModelIndex & index ) const
00121 {
00122     if (!index.isValid())
00123         return QModelIndex();
00124 
00125     PropertyItem *childItem = static_cast<PropertyItem*>(index.internalPointer());
00126     PropertyItem *parentItem = childItem->parent();
00127 
00128     if (parentItem == rootItem)
00129         return QModelIndex();
00130 
00131     return createIndex(parentItem->row(), 0, parentItem);
00132 }
00133 
00134 int PropertyModel::rowCount ( const QModelIndex & parent ) const
00135 {
00136     PropertyItem *parentItem;
00137 
00138     if (!parent.isValid())
00139         parentItem = rootItem;
00140     else
00141         parentItem = static_cast<PropertyItem*>(parent.internalPointer());
00142 
00143     return parentItem->childCount();
00144 }
00145 
00146 QVariant PropertyModel::headerData (int section, Qt::Orientation orientation, int role) const
00147 {
00148     if (orientation == Qt::Horizontal) {
00149         if (role != Qt::DisplayRole)
00150             return QVariant();
00151         if (section == 0)
00152             return tr("Property");
00153         if (section == 1)
00154             return tr("Value");
00155     }
00156 
00157     return QVariant();
00158 }
00159 
00160 bool PropertyModel::setHeaderData (int, Qt::Orientation, const QVariant &, int)
00161 {
00162     return false;
00163 }
00164 
00165 QStringList PropertyModel::propertyPathFromIndex(const QModelIndex& index) const
00166 {
00167     QStringList path;
00168     if (index.isValid()) {
00169         PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
00170         if (!item->isSeparator()) {
00171             do {
00172                 path.push_front(item->propertyName());
00173                 item = item->parent();
00174             }
00175             while (item != this->rootItem && item != 0);
00176         }
00177     }
00178 
00179     return path;
00180 }
00181 
00182 QModelIndex PropertyModel::propertyIndexFromPath(const QStringList& path) const
00183 {
00184     QModelIndex parent;
00185     for (QStringList::const_iterator it = path.begin(); it != path.end(); ++it) {
00186         int rows = this->rowCount(parent);
00187         for (int i=0; i<rows; i++) {
00188             QModelIndex index = this->index(i, 0, parent);
00189             if (index.isValid()) {
00190                 PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
00191                 if (item->propertyName() == *it) {
00192                     parent = index;
00193                     break;
00194                 }
00195             }
00196         }
00197     }
00198     return parent;
00199 }
00200 
00201 void PropertyModel::buildUp(const std::map<std::string, std::vector<App::Property*> >& props)
00202 {
00203     // fill up the listview with the properties
00204     rootItem->reset();
00205 
00206     // sort the properties into their groups
00207     std::map<std::string, std::vector<std::vector<App::Property*> > > propGroup;
00208     std::map<std::string, std::vector<App::Property*> >
00209         ::const_iterator jt;
00210     for (jt = props.begin(); jt != props.end(); ++jt) {
00211         App::Property* prop = jt->second.front();
00212         const char* group = prop->getGroup();
00213         std::string grp = group ? group : "Base";
00214         propGroup[grp].push_back(jt->second);
00215     }
00216 
00217     std::map<std::string, std::vector<std::vector<App::Property*> > >
00218         ::const_iterator kt;
00219     for (kt = propGroup.begin(); kt != propGroup.end(); ++kt) {
00220         // set group item
00221         PropertyItem* group = static_cast<PropertyItem*>(PropertySeparatorItem::create());
00222         group->setParent(rootItem);
00223         rootItem->appendChild(group);
00224         group->setPropertyName(QString::fromAscii(kt->first.c_str()));
00225 
00226         // setup the items for the properties
00227         std::vector<std::vector<App::Property*> >::const_iterator it;
00228         for (it = kt->second.begin(); it != kt->second.end(); ++it) {
00229             App::Property* prop = it->front();
00230             QString editor = QString::fromAscii(prop->getEditorName());
00231             if (!editor.isEmpty()) {
00232                 Base::BaseClass* item = 0;
00233                 try {
00234                     item = static_cast<Base::BaseClass*>(Base::Type::
00235                         createInstanceByName(prop->getEditorName(),true));
00236                 }
00237                 catch (...) {
00238                 }
00239                 if (!item) {
00240                     qWarning("No property item for type %s found\n", prop->getEditorName());
00241                     continue;
00242                 }
00243                 if (item->getTypeId().isDerivedFrom(PropertyItem::getClassTypeId())) {
00244                     PropertyItem* child = (PropertyItem*)item;
00245                     child->setParent(rootItem);
00246                     rootItem->appendChild(child);
00247                     child->setPropertyName(QString::fromAscii(prop->getName()));
00248                     child->setPropertyData(*it);
00249                 }
00250             }
00251         }
00252     }
00253 
00254     reset();
00255 }
00256 
00257 #include "moc_PropertyModel.cpp"

Generated on Wed Nov 23 19:00:31 2011 for FreeCAD by  doxygen 1.6.1