Developer Documentation
PropertyNameListModel.hh
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 
44 #pragma once
45 
46 #include <OpenMesh/Core/Utils/BaseProperty.hh>
47 
48 #include <QAbstractListModel>
49 
50 #include <set>
51 #include <vector>
52 #include <algorithm>
53 
54 class PropertyNameListModel: public QAbstractListModel {
55  public:
56  enum ENTITY_FILTER {
57  EF_ANY = 0x0F,
58  EF_FACE = 0x01,
59  EF_EDGE = 0x02,
60  EF_HALFEDGE = 0x04,
61  EF_VERTEX = 0x08,
62  };
63 
64  static const char *entity2str(ENTITY_FILTER entity);
65 
67  public:
68  TypeInfoWrapper(const std::type_info & ti, const char *friendlyName) : ti(&ti), friendlyName(friendlyName) {}
69  explicit TypeInfoWrapper(const std::type_info & ti) : ti(&ti),friendlyName("") {}
70 
71  operator const std::type_info *() const { return ti; }
72  operator const std::type_info &() const { return *ti; }
73  operator const char *() const { return friendlyName; }
74 
75  const std::type_info *operator->() const { return ti; }
76  const std::type_info &get() const { return *ti; }
77  const char *getName() const { return friendlyName; }
78 
79  bool operator==(const TypeInfoWrapper & other) const {
80  /*
81  * We compare name strings, not the type ids themselves because
82  * the same type from different SOs will give different type ids.
83  */
84  return strcmp(ti->name(), other.ti->name()) == 0;
85  }
86 
87  bool operator<(const TypeInfoWrapper & other) const {
88  return strcmp(ti->name(), other.ti->name()) < 0;
89  }
90 
91  private:
92  const std::type_info *ti;
93  const char *friendlyName;
94  };
95 
96  class PROP_INFO {
97  public:
98  PROP_INFO(const std::string &propName, const TypeInfoWrapper &typeinfo, ENTITY_FILTER entity) :
99  propName_(propName), typeinfo_(typeinfo), entity(entity) {}
100 
101  QString toString() const {
102  return tr("%3 %1 : %2").arg(propName_.c_str()).arg(friendlyTypeName()).arg(QString::fromUtf8(entity2str(entity)));
103  }
104 
105  bool operator==(const PROP_INFO &rhs) const {
106  return propName_ == rhs.propName_ && typeinfo_ == rhs.typeinfo_ && entity == rhs.entity;
107  }
108 
109  bool operator<(const PROP_INFO &rhs) const {
110  if (entity != rhs.entity) return entity < rhs.entity;
111 
112  int result = propName_.compare(rhs.propName_);
113  if (result) return result < 0;
114 
115  return typeinfo_ < rhs.typeinfo_;
116  }
117 
118  inline bool isFaceProp() const { return entity == EF_FACE; }
119  inline bool isEdgeProp() const { return entity == EF_EDGE; }
120  inline bool isHalfedgeProp() const { return entity == EF_HALFEDGE; }
121  inline bool isVertexProp() const { return entity == EF_VERTEX; }
122 
123  inline const std::string &propName() const { return propName_; }
124  inline const char *friendlyTypeName() const { return typeinfo_.getName(); }
125  inline const TypeInfoWrapper &typeinfo() const { return typeinfo_; }
126  inline ENTITY_FILTER entityType() const { return entity; }
127 
128  private:
129  std::string propName_;
130  TypeInfoWrapper typeinfo_;
131  ENTITY_FILTER entity;
132  };
133 
134  public:
135  explicit PropertyNameListModel(QObject *parent = 0);
136  virtual ~PropertyNameListModel();
137 
138  virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
139  virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
140  virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
141 
147  template<typename MeshT>
148  void refresh(MeshT *mesh, ENTITY_FILTER entityFilterMask, std::type_info *typeIdFilter) {
149  std::vector<PROP_INFO> propList;
150 
151  if (mesh) {
152  if (entityFilterMask & EF_FACE)
153  gatherProperties(mesh, mesh->fprops_begin(), mesh->fprops_end(), typeIdFilter, std::back_inserter(propList), EF_FACE);
154 
155  if (entityFilterMask & EF_EDGE)
156  gatherProperties(mesh, mesh->eprops_begin(), mesh->eprops_end(), typeIdFilter, std::back_inserter(propList), EF_EDGE);
157 
158  if (entityFilterMask & EF_HALFEDGE)
159  gatherProperties(mesh, mesh->hprops_begin(), mesh->hprops_end(), typeIdFilter, std::back_inserter(propList), EF_HALFEDGE);
160 
161  if (entityFilterMask & EF_VERTEX)
162  gatherProperties(mesh, mesh->vprops_begin(), mesh->vprops_end(), typeIdFilter, std::back_inserter(propList), EF_VERTEX);
163  }
164 
165  std::sort(propList.begin(), propList.end());
166 
167  if (propList != propList_) {
168  if (!tryInsertionsDeletions(propList)) {
169  beginResetModel();
170  propList_.swap(propList);
171  endResetModel();
172  }
173  }
174  }
175 
181  bool tryInsertionsDeletions(std::vector<PROP_INFO> &propList);
182 
183  template<typename MeshT, typename OUTPUT_ITERATOR>
184  void gatherProperties(MeshT *mesh,
185  typename MeshT::prop_iterator props_first,
186  typename MeshT::prop_iterator props_last,
187  std::type_info *typeIdFilter, OUTPUT_ITERATOR oit,
188  ENTITY_FILTER entity) {
189 
190  for (typename MeshT::prop_iterator pit = props_first; pit != props_last; ++pit) {
191  OpenMesh::BaseProperty * const baseProp = *pit;
192  if (!baseProp) continue;
193 
194  TypeInfoWrapper bp_type {typeid(*baseProp)};
195  TYPE_INFO_SET::const_iterator sane_prop_it = sane_prop_types.find(bp_type);
196  if ((typeIdFilter == 0 || TypeInfoWrapper(*typeIdFilter) == bp_type) && sane_prop_it != sane_prop_types.end()) {
197  *oit++ = PROP_INFO(baseProp->name(), *sane_prop_it, entity);
198  }
199  }
200  }
201 
202  const PROP_INFO &operator[] (size_t index) {
203  return propList_[index];
204  }
205 
206  protected:
207  std::vector<PROP_INFO> propList_;
208 
209  public:
210  static const TypeInfoWrapper proptype_bool;
211  static const TypeInfoWrapper proptype_int;
212  static const TypeInfoWrapper proptype_uint;
213  static const TypeInfoWrapper proptype_double;
214  static const TypeInfoWrapper proptype_Vec3d;
215  static const TypeInfoWrapper proptype_Vec3f;
216  static const TypeInfoWrapper proptype_Vec2d;
217  static const TypeInfoWrapper proptype_Vec2f;
218  static const TypeInfoWrapper proptype_Matrix3x3d;
219  static const TypeInfoWrapper proptype_SkinWeights;
220 
221  private:
222  typedef std::set<TypeInfoWrapper> TYPE_INFO_SET;
223  static const TypeInfoWrapper prop_types[];
224  static const TYPE_INFO_SET sane_prop_types;
225 };
226 
bool tryInsertionsDeletions(std::vector< PROP_INFO > &propList)
const std::string & name() const
Return the name of the property.
void refresh(MeshT *mesh, ENTITY_FILTER entityFilterMask, std::type_info *typeIdFilter)