Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MultiObjectPropertyModel.cc
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 * $Revision: 21177 $ *
45 * $LastChangedBy: moebius $ *
46 * $Date: 2015-09-07 08:56:47 +0200 (Mo, 07 Sep 2015) $ *
47 * *
48 \*===========================================================================*/
49 
50 #include "MultiObjectPropertyModel.hh"
51 
52 #include "PropertyModelFactory.hh"
53 #include "OpenMesh/OMPropertyModel.hh"
54 #include "OpenVolumeMesh/OVMPropertyModel.hh"
55 
56 MultiObjectPropertyModel::MultiObjectPropertyModel(const QStringList& res, QObject *parent) :
57  PropertyModel(parent), restriction(res), datatypes(supportedDataTypes()), widget(0)
58 {
59  QVBoxLayout* layout = new QVBoxLayout();
60  widget = new QWidget();
61  widget->setLayout(layout);
62 }
63 
64 MultiObjectPropertyModel::~MultiObjectPropertyModel()
65 {
66  for (size_t i = 0; i < propWidgets.size(); ++i)
67  {
68  delete propWidgets[i];
69  }
70  delete widget;
71 }
72 
73 QVariant MultiObjectPropertyModel::data(const QModelIndex & index, int role) const
74 {
75  switch (role) {
76  case Qt::DisplayRole:
77  return QVariant(propNames[index.row()]);
78  default:
79  return QVariant::Invalid;
80  }
81 }
82 
83 int MultiObjectPropertyModel::rowCount(const QModelIndex & parent) const
84 {
85  return propNames.size();
86 }
87 
88 QVariant MultiObjectPropertyModel::headerData(int section, Qt::Orientation orientation, int role) const
89 {
90  return QVariant::Invalid;
91 }
92 
94 {
95  using namespace PluginFunctions;
96 
97  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
98  {
99  // get the property model and call objectUpdated
100  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
101  if (model == 0) continue;
102  model->objectUpdated();
103  }
104 }
105 
106 void MultiObjectPropertyModel::visualize(QModelIndexList selectedIndices, QWidgetList widgets)
107 {
108  using namespace PluginFunctions;
109 
110  // return if nothing is selected
111  if (selectedIndices.size() < 1) return;
112 
113  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
114  {
115  // get the property model and update it
116  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
117  if (model == 0) continue;
118  model->gatherProperties();
119 
120  QModelIndexList indexList;
121  QWidgetList widgetList;
122 
123  for (int i = 0; i < selectedIndices.size(); ++i)
124  {
125  const QString name = selectedIndices[i].data().toString();
126 
127  // skip this property if it does not exist
128  const QModelIndex idx = model->indexFromFancyPropName(name);
129  if (!idx.isValid()) continue;
130 
131  // insert items into lists
132  indexList.append(idx);
133  widgetList.append(propWidgets[selectedIndices[i].row()]);
134  }
135 
136  // visualize the property
137  model->visualize(indexList, widgetList);
138  }
139 }
140 
141 void MultiObjectPropertyModel::removeProperty(QModelIndexList selectedIndices)
142 {
143  using namespace PluginFunctions;
144 
145  // return if nothing is selected
146  if (selectedIndices.size() < 1) return;
147 
148  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
149  {
150  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
151  if (model == 0) continue;
152 
153  QModelIndexList indexList;
154 
155  for (int i = 0; i < selectedIndices.size(); ++i)
156  {
157  const QString name = selectedIndices[i].data().toString();
158 
159  // skip this property if it does not exist
160  const QModelIndex idx = model->indexFromFancyPropName(name);
161  if (!idx.isValid()) continue;
162 
163  // insert item into list
164  indexList.append(idx);
165  }
166 
167  model->removeProperty(indexList);
168  }
169 
170  // update this model
172 }
173 
174 void MultiObjectPropertyModel::duplicateProperty(QModelIndexList selectedIndices)
175 {
176  using namespace PluginFunctions;
177 
178  // return if nothing is selected
179  if (selectedIndices.size() < 1) return;
180 
181  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
182  {
183  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
184  if (model == 0) continue;
185 
186  QModelIndexList indexList;
187 
188  for (int i = 0; i < selectedIndices.size(); ++i)
189  {
190  const QString name = selectedIndices[i].data().toString();
191 
192  // skip this property if it does not exist
193  const QModelIndex idx = model->indexFromFancyPropName(name);
194  if (!idx.isValid()) continue;
195 
196  // insert item into list
197  indexList.append(idx);
198  }
199 
200  model->duplicateProperty(indexList);
201  }
202 
203  // update this model
205 }
206 
208 {
209  using namespace PluginFunctions;
210 
211  beginResetModel();
212  propNames.clear();
213  propInfos.clear();
214  for (size_t i = 0; i < propWidgets.size(); ++i)
215  {
216  delete propWidgets[i];
217  }
218  propWidgets.clear();
219  endResetModel();
220 
221  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
222  {
223  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
224  if (model == 0) continue;
225  model->gatherProperties();
226 
227  for (int i = 0; i < model->rowCount(); ++i)
228  {
229  const QModelIndex idx = model->index(i, 0);
230  const QString name = idx.data().toString();
231 
232  // add property
233  if (std::find(propNames.begin(), propNames.end(), name) == propNames.end())
234  {
235  PropertyInfo info = model->getPropertyInfo(idx);
236  QWidget* widget = createWidgetForType(info.typeinfo());
237  setRange(info, widget);
238 
239  propNames.push_back(name);
240  propInfos.push_back(info);
241  propWidgets.push_back(widget);
242  }
243  }
244  }
245 }
246 
247 void MultiObjectPropertyModel::clear(QModelIndexList selectedIndices)
248 {
249  using namespace PluginFunctions;
250 
251  // return if nothing is selected
252  if (selectedIndices.size() < 1) return;
253 
254  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
255  {
256  PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
257  if (model == 0) continue;
258 
259  QModelIndexList indexList;
260 
261  for (int i = 0; i < selectedIndices.size(); ++i)
262  {
263  const QString name = selectedIndices[i].data().toString();
264 
265  // skip this property if it does not exist
266  const QModelIndex idx = model->indexFromFancyPropName(name);
267  if (!idx.isValid()) continue;
268 
269  // insert item into list
270  indexList.append(idx);
271  }
272 
273  model->clear(indexList);
274  }
275 }
276 
278 {
279  widget->hide();
280 }
281 
283 {
284  return widget;
285 }
286 
287 void MultiObjectPropertyModel::updateWidget(const QModelIndexList& selectedIndices)
288 {
289  QLayout* layout = widget->layout();
290 
291  for (unsigned int i = 0; i < propWidgets.size(); ++i)
292  {
293  propWidgets[i]->hide();
294  }
295 
296  for (int i = 0; i < selectedIndices.size(); ++i)
297  {
298  const int row = selectedIndices[i].row();
299  QWidget* w = propWidgets[row];
300  layout->addWidget(w);
301  w->show();
302  }
303 
304  widget->setLayout(layout);
305 }
306 
308 {
309 
310 }
311 
313 {
314  return propInfos[index.row()];
315 }
316 
317 QWidget* MultiObjectPropertyModel::createWidgetForType(const TypeInfoWrapper& info) const
318 {
319  // OpenMesh
320  // ----------------------------------------
321 
323  return new BooleanWidget();
325  return new IntegerWidget();
327  return new IntegerWidget();
329  return new DoubleWidget();
331  return new VectorWidget;
333  return new VectorWidget;
335  return new VectorWidget;
337  return new VectorWidget;
338 
339  #ifdef ENABLE_SKELETON_SUPPORT
341  return new SkinWeightsWidget;
342  #endif
343 
344 
345  // OpenVolumeMesh
346  // ----------------------------------------
347 
348  #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
349  if (OVMPropertyModel<HexahedralMesh>::isBoolType(info))
350  return new BooleanWidget();
351  if (OVMPropertyModel<HexahedralMesh>::isIntType(info))
352  return new IntegerWidget();
353  if (OVMPropertyModel<HexahedralMesh>::isUnsignedIntType(info))
354  return new IntegerWidget();
355  if (OVMPropertyModel<HexahedralMesh>::isDoubleType(info))
356  return new DoubleWidget();
357  if (OVMPropertyModel<HexahedralMesh>::isVec3dType(info))
358  return new VectorWidget();
359  if (OVMPropertyModel<HexahedralMesh>::isVec3fType(info))
360  return new VectorWidget();
361  #endif
362 
363 
364  // Other
365  // ----------------------------------------
366 
367  return new QWidget();
368 }
369 
370 template <typename ItemHandle, typename PropHandle, typename T>
371 void range3_om(const OpenMesh::BaseKernel* mesh, unsigned int n, const std::string& name, T& min, T& max)
372 {
373  PropHandle ph;
374  mesh->get_property_handle(ph, name);
375  if (!ph.is_valid()) return;
376 
377  for (unsigned int i = 0; i < n; ++i)
378  {
379  const ItemHandle ih(i);
380  min = std::min(min, mesh->property(ph, ih));
381  max = std::max(max, mesh->property(ph, ih));
382  }
383 }
384 
385 template <typename ItemHandle, typename Property, typename T>
386 void range3_ovm(Property& prop, unsigned int n, T& min, T& max)
387 {
388  for (unsigned int i = 0; i < n; ++i)
389  {
390  const ItemHandle ih(i);
391  min = std::min(min, prop[ih]);
392  max = std::max(max, prop[ih]);
393  }
394 }
395 
396 template <typename Mesh, typename T>
397 void range2_om(const Mesh* mesh, const PropertyInfo& info, T& min, T&max)
398 {
399  if (mesh == 0) return;
400 
401  if (info.isVertexProp())
403  (mesh, mesh->n_vertices(), info.propName(), min, max);
404  if (info.isHalfedgeProp())
406  (mesh, mesh->n_halfedges(), info.propName(), min, max);
407  if (info.isEdgeProp())
409  (mesh, mesh->n_edges(), info.propName(), min, max);
410  if (info.isFaceProp())
412  (mesh, mesh->n_faces(), info.propName(), min, max);
413 }
414 
415 template <typename Mesh, typename T>
416 void range2_ovm(Mesh* mesh, const PropertyInfo& info, T& min, T&max)
417 {
418  if (mesh == 0) return;
419 
420  if (info.isCellProp() && mesh->template cell_property_exists<T>(info.propName())) {
421  OpenVolumeMesh::CellPropertyT<T> prop = mesh->template request_cell_property<T>(info.propName());
422  range3_ovm<OpenVolumeMesh::CellHandle, OpenVolumeMesh::CellPropertyT<T>, T>
423  (prop, mesh->n_cells(), min, max);
424  }
425  if (info.isEdgeProp() && mesh->template edge_property_exists<T>(info.propName())) {
426  OpenVolumeMesh::EdgePropertyT<T> prop = mesh->template request_edge_property<T>(info.propName());
427  range3_ovm<OpenVolumeMesh::EdgeHandle, OpenVolumeMesh::EdgePropertyT<T>, T>
428  (prop, mesh->n_edges(), min, max);
429  }
430  if (info.isFaceProp() && mesh->template face_property_exists<T>(info.propName())) {
431  OpenVolumeMesh::FacePropertyT<T> prop = mesh->template request_face_property<T>(info.propName());
432  range3_ovm<OpenVolumeMesh::FaceHandle, OpenVolumeMesh::FacePropertyT<T>, T>
433  (prop, mesh->n_faces(), min, max);
434  }
435  if (info.isHalfedgeProp() && mesh->template halfedge_property_exists<T>(info.propName())) {
436  OpenVolumeMesh::HalfEdgePropertyT<T> prop = mesh->template request_halfedge_property<T>(info.propName());
437  range3_ovm<OpenVolumeMesh::HalfEdgeHandle, OpenVolumeMesh::HalfEdgePropertyT<T>, T>
438  (prop, mesh->n_halfedges(), min, max);
439  }
440  if (info.isHalffaceProp() && mesh->template halfface_property_exists<T>(info.propName())) {
441  OpenVolumeMesh::HalfFacePropertyT<T> prop = mesh->template request_halfface_property<T>(info.propName());
442  range3_ovm<OpenVolumeMesh::HalfFaceHandle, OpenVolumeMesh::HalfFacePropertyT<T>, T>
443  (prop, mesh->n_halffaces(), min, max);
444  }
445  if (info.isVertexProp() && mesh->template vertex_property_exists<T>(info.propName())) {
446  OpenVolumeMesh::VertexPropertyT<T> prop = mesh->template request_vertex_property<T>(info.propName());
447  range3_ovm<OpenVolumeMesh::VertexHandle, OpenVolumeMesh::VertexPropertyT<T>, T>
448  (prop, mesh->n_vertices(), min, max);
449  }
450 }
451 
452 template <typename T>
453 void range1(const BaseObject* obj, const PropertyInfo& info, T& min, T& max)
454 {
455  using namespace PluginFunctions;
456 
457  if (obj->dataType(DATA_TRIANGLE_MESH))
458  range2_om(triMesh(obj->id()), info, min, max);
459  if (obj->dataType(DATA_POLY_MESH))
460  range2_om(polyMesh(obj->id()), info, min, max);
461 
462  #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
463  if (obj->dataType(DATA_POLYHEDRAL_MESH))
464  range2_ovm(polyhedralMesh(obj->id()), info, min, max);
465  #endif
466 
467  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
468  if (obj->dataType(DATA_HEXAHEDRAL_MESH))
469  range2_ovm(hexahedralMesh(obj->id()), info, min, max);
470  #endif
471 }
472 
473 void MultiObjectPropertyModel::setRange(const PropertyInfo& info, QWidget* widget) const
474 {
475  using namespace PluginFunctions;
476 
477  bool isDoubleType = info.typeinfo() == OMPropertyModel<TriMesh>::proptype_double;
478 
479  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
480  isDoubleType |= OVMPropertyModel<HexahedralMesh>::isDoubleType(info.typeinfo());
481  #endif
482 
483  bool isIntType = info.typeinfo() == OMPropertyModel<TriMesh>::proptype_int;
484 
485  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
486  isIntType |= OVMPropertyModel<HexahedralMesh>::isIntType(info.typeinfo());
487  #endif
488 
489  if (isDoubleType)
490  {
491  double min = +DBL_MAX;
492  double max = -DBL_MAX;
493 
494  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
495  {
496  range1<double>(*o_it, info, min, max);
497  }
498 
499  DoubleWidget* w = static_cast<DoubleWidget*>(widget);
500  w->doubleFixedRange->toggle();
501  w->doubleFixedRangeMin->setValue(min);
502  w->doubleFixedRangeMax->setValue(max);
503  }
504 
505  if (isIntType)
506  {
507  int min = +INT_MAX;
508  int max = -INT_MAX;
509 
510  for (ObjectIterator o_it(restriction, datatypes); o_it != objectsEnd(); ++o_it)
511  {
512  range1<int>(*o_it, info, min, max);
513  }
514 
515  IntegerWidget* w = static_cast<IntegerWidget*>(widget);
516  w->intFixedRange->toggle();
517  w->intFixedRangeMin->setValue(min);
518  w->intFixedRangeMax->setValue(max);
519  }
520 }
virtual void hideWidget()
Hides the widget.
virtual void duplicateProperty(QModelIndexList selectedIndices)
Duplicates the selected properties.
virtual void connectLogs(PropertyVisualizer *propViz)
Connects the PropertyVisualizer log signals with the log slot.
This class vizualizes a property.
virtual void removeProperty(QModelIndexList selectedIndices)=0
Removes the selected properties.
PropertyT< T > & property(VPropHandleT< T > _ph)
Definition: BaseKernel.hh:294
#define DATA_POLYHEDRAL_MESH
Wraps the information of a type.
Definition: Utils.hh:79
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Handle for a halfedge entity.
Definition: Handles.hh:132
virtual void clear(QModelIndexList selectedIndices)
Clears the selected property visualization.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
virtual void duplicateProperty(QModelIndexList selectedIndices)=0
Duplicates the selected properties.
virtual PropertyInfo getPropertyInfo(const QModelIndex index) const =0
Returns the property info for the property with the given index.
virtual void objectUpdated()
Revisualizes visualized properties.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
virtual void gatherProperties()
Searches for properties and creates PropertyVisualizers.
virtual void clear(QModelIndexList selectedIndices)=0
Clears the selected property visualization.
virtual void removeProperty(QModelIndexList selectedIndices)
Removes the selected properties.
virtual void gatherProperties()=0
Searches for properties and creates PropertyVisualizers.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Handle for a vertex entity.
Definition: Handles.hh:125
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
Handle for a edge entity.
Definition: Handles.hh:139
virtual void objectUpdated()=0
Revisualizes visualized properties.
virtual PropertyInfo getPropertyInfo(const QModelIndex index) const
Returns the property info for the property with the given index.
virtual void visualize(QModelIndexList selectedIndices, QWidgetList widgets=QWidgetList())=0
Visualizes the selected properties.
Handle for a face entity.
Definition: Handles.hh:146
static T & Instance()
Definition: SingletonT.hh:94
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
Definition: BaseKernel.hh:243
Property classes for the different entity types.
virtual QWidget * getWidget()
Returns the widget.
#define DATA_HEXAHEDRAL_MESH
virtual void visualize(QModelIndexList selectedIndices, QWidgetList widgets=QWidgetList())
Visualizes the selected properties.
virtual void updateWidget(const QModelIndexList &selectedIndices)
Updates the widget.
QModelIndex indexFromFancyPropName(const QString &propName) const
Returns the index of the property with the given name.
Cellection of information about a property.
Definition: Utils.hh:115
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
int id() const
Definition: BaseObject.cc:201
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.