diff --git a/Polyhedron/demo/Polyhedron/CGAL_demo/Scene_interface.h b/Polyhedron/demo/Polyhedron/CGAL_demo/Scene_interface.h new file mode 100644 index 00000000000..bfae22f3911 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/CGAL_demo/Scene_interface.h @@ -0,0 +1,111 @@ +#ifndef SCENE_INTERFACE_H +#define SCENE_INTERFACE_H + +#include +#include +#include +#include +#include + +class Scene_item; +// OpenGL rendering mode +enum RenderingMode { Points = 0, + PointsPlusNormals, + Splatting, + Wireframe, + Flat, + FlatPlusEdges, + Gouraud, + LastRenderingMode = Gouraud, + NumberOfRenderingMode = LastRenderingMode+1 }; + +// Interface of Scene class exported to plugins +class Scene_interface { +public: + struct Bbox { + double xmin, ymin, zmin; + double xmax, ymax, zmax; + Bbox(const double _xmin,const double _ymin,const double _zmin, + const double _xmax,const double _ymax,const double _zmax) + : xmin(_xmin), ymin(_ymin), zmin(_zmin), + xmax(_xmax), ymax(_ymax), zmax(_zmax) + { + } + Bbox() + : xmin(0.0), ymin(0.0), zmin(0.0), + xmax(1.0), ymax(1.0), zmax(1.0) + { + } + + Bbox operator+(const Bbox& b) const { + return Bbox((std::min)(xmin, b.xmin), + (std::min)(ymin, b.ymin), + (std::min)(zmin, b.zmin), + (std::max)(xmax, b.xmax), + (std::max)(ymax, b.ymax), + (std::max)(zmax, b.zmax)); + } + + bool operator==(const Bbox&b) const{ + return + xmin==b.xmin && xmax==b.xmax && + ymin==b.ymin && ymax==b.ymax && + zmin==b.zmin && zmax==b.zmax; + } + + bool operator!=(const Bbox& b) const{ + return !(*this == b); + } + + double width() const { return xmax-xmin; } + double height() const { return ymax-ymin; } + double depth() const { return zmax-zmin; } + + double diagonal_length() const + { + return std::sqrt(width()*width() + height()*height() + depth()*depth()); + } + + }; // struct BBox (ad hoc class, does not depend on CGAL kernels + + typedef int Item_id; + + virtual ~Scene_interface() {} + + virtual Item_id addItem(Scene_item* item) = 0; + virtual Scene_item* replaceItem(Item_id, Scene_item*, bool emit_item_about_to_be_destroyed = false) = 0; + + virtual Item_id erase(Item_id) = 0; + // Returns the index of the item just before the one that is erased, + // or just after. Returns -1 if the list is empty. + + virtual Item_id duplicate(Item_id) = 0; + // Returns the index of the new item + // If no new item has been created (because the item type is note + // clonable), returns -1. + + // Accessors (getters) + virtual int numberOfEntries() const = 0; + virtual Scene_item* item(Item_id) const = 0; + virtual Item_id item_id(Scene_item*) const = 0; + virtual Item_id mainSelectionIndex() const = 0; + virtual QList selectionIndices() const = 0; + virtual Item_id selectionAindex() const = 0; + virtual Item_id selectionBindex() const = 0; + + // Get scene bounding box + virtual Bbox bbox() const = 0; + virtual double len_diagonal() const = 0; + +public: + // Notify the scene that an item was modified + virtual void itemChanged(Item_id i) = 0; + virtual void itemChanged(Scene_item*) = 0; + + // Select an item + virtual void setSelectedItem(Item_id) = 0; + +}; // end interface Scene_interface + + +#endif // SCENE_INTERFACE_H diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index fb5676f8931..d56000e588d 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -142,6 +142,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) Viewer_interface_moc.cpp Scene_item_moc.cpp Scene_item.cpp #Scene_item.moc + Scene_group_item.cpp Polyhedron_demo_plugin_helper.cpp) qt5_use_modules(demo_framework OpenGL Gui Widgets Script Xml) @@ -222,7 +223,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) scene_basic_objects scene_polyhedron_item scene_polygon_soup_item - scene_nef_polyhedron_item ) + scene_nef_polyhedron_item) add_to_cached_list( CGAL_EXECUTABLE_TARGETS ${lib} ) endforeach() @@ -264,8 +265,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) FOREACH(SUB_DIR ${DEMO_PLUGINS}) add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/${SUB_DIR}") ENDFOREACH() - add_executable(example_plugin IMPORTED) - set_property(TARGET example_plugin PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../Example_plugin/example_plugin.cmake") + add_item(scene_group_item Scene_group_item.cpp) + polyhedron_demo_plugin(group_plugin Polyhedron_demo_group_plugin ${groupUI_FILES}) + target_link_libraries(group_plugin scene_group_item) # # Exporting # diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 3ee83a7f9bd..e364efe9de4 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -116,7 +116,6 @@ MainWindow::~MainWindow() { delete ui; } - MainWindow::MainWindow(QWidget* parent) : CGAL::Qt::DemosMainWindow(parent) { @@ -146,17 +145,21 @@ MainWindow::MainWindow(QWidget* parent) proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(scene); + SceneDelegate *delegate = new SceneDelegate(this); + delegate->setProxy(proxyModel); + delegate->setScene(scene); + connect(ui->searchEdit, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterFixedString(QString))); sceneView->setModel(proxyModel); // setup the sceneview: delegation and columns sizing... - sceneView->setItemDelegate(new SceneDelegate(this)); + sceneView->setItemDelegate(delegate); - sceneView->header()->setStretchLastSection(false); - sceneView->header()->setSectionResizeMode(Scene::NameColumn, QHeaderView::Stretch); - sceneView->header()->setSectionResizeMode(Scene::NameColumn, QHeaderView::Stretch); + //sceneView->header()->setStretchLastSection(false); + /* sceneView->header()->setSectionResizeMode(Scene::NameColumn, QHeaderView::Stretch); + sceneView->header()->setSectionResizeMode(Scene::NameColumn, QHeaderView::Stretch); sceneView->header()->setSectionResizeMode(Scene::ColorColumn, QHeaderView::ResizeToContents); sceneView->header()->setSectionResizeMode(Scene::RenderingModeColumn, QHeaderView::Fixed); sceneView->header()->setSectionResizeMode(Scene::ABColumn, QHeaderView::Fixed); @@ -165,7 +168,7 @@ MainWindow::MainWindow(QWidget* parent) sceneView->resizeColumnToContents(Scene::RenderingModeColumn); sceneView->resizeColumnToContents(Scene::ABColumn); sceneView->resizeColumnToContents(Scene::VisibleColumn); - +*/ // setup connections connect(scene, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex & )), this, SLOT(updateInfo())); @@ -207,6 +210,15 @@ MainWindow::MainWindow(QWidget* parent) connect(sceneView, SIGNAL(customContextMenuRequested(const QPoint & )), this, SLOT(showSceneContextMenu(const QPoint &))); + connect(sceneView, SIGNAL(expanded(QModelIndex)), + scene, SLOT(setExpanded(QModelIndex))); + + connect(sceneView, SIGNAL(collapsed(QModelIndex)), + scene, SLOT(setCollapsed(QModelIndex))); + + connect(scene, SIGNAL(restoreCollapsedState()), + this, SLOT(restoreCollapseState())); + connect(viewer, SIGNAL(selected(int)), this, SLOT(selectSceneItem(int))); connect(viewer, SIGNAL(selectedPoint(double, double, double)), @@ -999,6 +1011,7 @@ void MainWindow::selectSceneItem(int i) else { QItemSelection s = proxyModel->mapSelectionFromSource(scene->createSelection(i)); + sceneView->selectionModel()->select(s, QItemSelectionModel::ClearAndSelect); } @@ -1053,21 +1066,24 @@ void MainWindow::selectAll() int MainWindow::getSelectedSceneItemIndex() const { - QModelIndexList selectedRows = sceneView->selectionModel()->selectedRows(); - if(selectedRows.size() != 1) + QModelIndexList selectedRows = sceneView->selectionModel()->selectedIndexes(); + if(selectedRows.size() != 5) return -1; else { QModelIndex i = proxyModel->mapToSource(selectedRows.first()); - return i.row(); + return scene->getIdFromModelIndex(i); } } QList MainWindow::getSelectedSceneItemIndices() const { - QModelIndexList selectedRows = sceneView->selectionModel()->selectedRows(); + + QModelIndexList selectedIndices = sceneView->selectionModel()->selectedIndexes(); QList result; - Q_FOREACH(QModelIndex index, selectedRows) { - result << proxyModel->mapToSource(index).row(); + Q_FOREACH(QModelIndex index, selectedIndices) { + int temp = scene->getIdFromModelIndex(proxyModel->mapToSource(index)); + if(!result.contains(temp)) + result<item(selectedItemIndex); + CGAL::Three::Scene_item* item = scene->item(scene->getIdFromModelIndex(scene->index(selectedItemIndex,0,QModelIndex()))); if(!item) return; const char* prop_name = "Menu modified by MainWindow."; @@ -1149,10 +1165,24 @@ void MainWindow::showSceneContextMenu(const QPoint& p) { int index = -1; if(sender == sceneView) { - QModelIndex modelIndex = sceneView->indexAt(p); - if(!modelIndex.isValid()) return; + QModelIndex modelIndex = sceneView->indexAt(p); + if(!modelIndex.isValid()) + { + const char* prop_name = "Menu modified by MainWindow."; - index = proxyModel->mapToSource(modelIndex).row(); + QMenu* menu = ui->menuFile; + if(menu) { + bool menuChanged = menu->property(prop_name).toBool(); + if(!menuChanged) { + menu->setProperty(prop_name, true); + } + } + if(menu) + menu->exec(sender->mapToGlobal(p)); + return; + } + else + index = proxyModel->mapToSource(modelIndex).row(); } else { index = scene->mainSelectionIndex(); @@ -1188,7 +1218,7 @@ void MainWindow::updateInfo() { } ui->infoLabel->setText(item_text); } - else + else ui->infoLabel->clear(); } @@ -1617,5 +1647,35 @@ Q_FOREACH(QAction* a, as) ui->menuOperations->clear(); ui->menuOperations->addActions(as); } - +} + +void MainWindow::recurseExpand(QModelIndex index) +{ + int row = index.row(); + if(index.child(0,0).isValid()) + { + recurseExpand(index.child(0,0)); + } + + QString name = scene->item(scene->getIdFromModelIndex(index))->name(); + Scene_group_item* group = + qobject_cast(scene->item(scene->getIdFromModelIndex(index))); + + if(group && group->isExpanded()) + { + sceneView->setExpanded(proxyModel->mapFromSource(index), true); + } + else if (group && !group->isExpanded()){ + sceneView->setExpanded(proxyModel->mapFromSource(index), false); + } + + + if( index.sibling(row+1,0).isValid()) + recurseExpand(index.sibling(row+1,0)); +} +void MainWindow::restoreCollapseState() +{ + QModelIndex modelIndex = scene->index(0,0,scene->invisibleRootItem()->index()); + if(modelIndex.isValid()) + recurseExpand(modelIndex); } diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 539e2a6380a..6933d95ff9f 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -28,6 +28,7 @@ class Scene_item; } class QSortFilterProxyModel; +class QModelIndex; namespace Ui { class MainWindow; @@ -72,7 +73,8 @@ public Q_SLOTS: void updateViewerBBox(); void open(QString); - //! given an extension file, returns true if `filename` matches the filter + void restoreCollapseState(); + /// given a file extension file, returns true if `filename` matches the filter bool file_matches_filter(const QString& filters, const QString& filename); /*! Open a file with a given loader, and return true if it was successful. @@ -328,6 +330,7 @@ protected: QList getSelectedSceneItemIndices() const; private: + void recurseExpand(QModelIndex index); QString strippedName(const QString &fullFileName); void setMenus(QString, QString, QAction *a); /// plugin black-list diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index 01d9af8ba65..99e13f82bc6 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -201,6 +201,9 @@ QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + QAbstractItemView::InternalMove + true @@ -208,7 +211,7 @@ QAbstractItemView::ExtendedSelection - 0 + 10 diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_polyhedron_transform_item.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_polyhedron_transform_item.cpp index 1c59eb14dd2..6d1ee0e5f09 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_polyhedron_transform_item.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_polyhedron_transform_item.cpp @@ -13,6 +13,7 @@ Scene_polyhedron_transform_item::Scene_polyhedron_transform_item(const qglviewer { frame->setPosition(pos); nb_lines = 0; + invalidate_buffers(); } void Scene_polyhedron_transform_item::initialize_buffers(CGAL::Three::Viewer_interface *viewer =0) const @@ -33,6 +34,7 @@ void Scene_polyhedron_transform_item::initialize_buffers(CGAL::Three::Viewer_int QColor color = this->color(); program->setAttributeValue("colors",color); vaos[Edges]->release(); + program->release(); } nb_lines = positions_lines.size(); @@ -64,7 +66,6 @@ void Scene_polyhedron_transform_item::compute_elements() const positions_lines.push_back(b.z()-center_.z); } - } void Scene_polyhedron_transform_item::draw_edges(CGAL::Three::Viewer_interface* viewer) const @@ -79,6 +80,8 @@ void Scene_polyhedron_transform_item::draw_edges(CGAL::Three::Viewer_interface* for (int i=0; i<16; ++i){ f_matrix.data()[i] = (float)frame->matrix()[i]; } + QColor color = this->color(); + program->setAttributeValue("colors",color); program->setUniformValue("f_matrix", f_matrix); viewer->glDrawArrays(GL_LINES, 0, static_cast(nb_lines/3)); vaos[Edges]->release(); diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.cpp new file mode 100644 index 00000000000..b21178da2ed --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.cpp @@ -0,0 +1,50 @@ +#include "Polyhedron_demo_group_plugin.h" +#include "Polyhedron_demo_group_plugin.moc" +#include "Scene.h" +#include +/**************** + * Group Plugin * + ****************/ + +void Polyhedron_demo_group_plugin::init(QMainWindow* mainWindow, + CGAL::Three::Scene_interface* scene_interface,Messages_interface* m ) { + //get the references + trueScene = dynamic_cast(scene_interface); + this->scene = scene_interface; + this->mw = mainWindow; + messages = m; + //creates and link the actions + actionAddToGroup= new QAction("Add new group", mw); + + if(actionAddToGroup) { + connect(actionAddToGroup, SIGNAL(triggered()), + this, SLOT(add_group())); + } + + QMenu* menuFile = mw->findChild("menuFile"); + if ( NULL != menuFile ) + { + QList menuFileActions = menuFile->actions(); + + // Look for action just after "Load..." action + QAction* actionAfterLoad = NULL; + for ( QList::iterator it_action = menuFileActions.begin(), + end = menuFileActions.end() ; it_action != end ; ++ it_action ) //Q_FOREACH( QAction* action, menuFileActions) + { + if ( NULL != *it_action && (*it_action)->text().contains("Load") ) + { + ++it_action; + if ( it_action != end && NULL != *it_action ) + { + actionAfterLoad = *it_action; + } + } + } + + // Insert "Load implicit function" action + if ( NULL != actionAfterLoad ) + { + menuFile->insertAction(actionAfterLoad,actionAddToGroup); + } + } +} diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.h b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.h new file mode 100644 index 00000000000..6feb8e22ca4 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.h @@ -0,0 +1,110 @@ +#ifndef POLYHEDRON_DEMO_GROUP_H +#define POLYHEDRON_DEMO_GROUP_H +#include +#include +#include +#include +#include "Scene_group_item.h" +#include "CGAL/Three/Scene_interface.h" +#include "Scene.h" + +class Scene_interface; +#include "CGAL/Three/Polyhedron_demo_plugin_helper.h" +class Polyhedron_demo_group_plugin : + public QObject, + public CGAL::Three::Polyhedron_demo_plugin_helper +{ + //Configures CMake to use MOC correctly + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public : + // To silent a warning -Woverloaded-virtual + // See http://stackoverflow.com/questions/9995421/gcc-woverloaded-virtual-warnings + using Polyhedron_demo_plugin_helper::init; + void init(QMainWindow* mw, CGAL::Three::Scene_interface* sc, Messages_interface*); + + bool applicable(QAction*) const + { + return true; + } + + Scene* trueScene; +public Q_SLOTS: + void add_group() { + //Find the indices of the selected items + QList indices; + QList blacklist; + Q_FOREACH(int id, scene->selectionIndices()){ + Scene_group_item* group = + qobject_cast(trueScene->item(id)); + if(group) + Q_FOREACH(Scene_item *item, group->getChildren()) + blacklist<item_id(item); + + if(!indices.contains(id) && !blacklist.contains(id)) + indices<item(id)->has_group!=0){ + //for each group + Q_FOREACH(Scene_group_item *item, trueScene->group_entries()) + { + //if the group contains the selected item + if(item->getChildren().contains(trueScene->item(id))){ + //if it is the first one, we initialize existing_group + if(existing_group == 0) + existing_group = item; + //else we check if it is the same group as before. + //If not, all selected items are not in the same group + else if(existing_group != item) + all_in_one = false; + break; + } + }//end for each group + } + //else it is impossible that all the selected items are in the same group + else{ + all_in_one = false; + break; + } + }//end foreach selected item + + //If all the selected items are in the same group, we put them in a sub_group of this group + if(all_in_one) + { + Q_FOREACH(int id, indices) + trueScene->changeGroup(trueScene->item(id),group); + trueScene->changeGroup(group, existing_group); + scene->addItem(group); + trueScene->group_added(); + } + //else wer create a new group + else + { + Q_FOREACH(int id, indices) + trueScene->changeGroup(trueScene->item(id),group); + scene->addItem(group); + trueScene->group_added(); + } + + } + + +private: + QAction* actionAddToGroup; + void print_message(QString message) { messages->information(message); } + Messages_interface* messages; + +}; //end of class Polyhedron_demo_group_plugin +#endif diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.ui b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.ui new file mode 100644 index 00000000000..c46f985f009 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_group_plugin.ui @@ -0,0 +1,86 @@ + + + GroupDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 9 + 9 + 371 + 211 + + + + + + + + + + + + + + + + buttonBox + accepted() + GroupDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GroupDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.h b/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.h new file mode 100644 index 00000000000..a81f7d379c5 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.h @@ -0,0 +1,65 @@ +#ifndef POLYHEDRON_DEMO_OPERATION_HELPER_H +#define POLYHEDRON_DEMO_OPERATION_HELPER_H + +#include "Scene_item_config.h" //defines SCENE_ITEM_EXPORT + +#include +#include +#include + +class QAction; +struct QMetaObject; +class QMainWindow; +class QDockWidget; + +#include "Polyhedron_demo_plugin_interface.h" +#include "CGAL_demo/Scene_interface.h" + +class SCENE_ITEM_EXPORT Polyhedron_demo_plugin_helper + : public Polyhedron_demo_plugin_interface +{ +public: + // get action object from its name + static QAction* getActionFromMainWindow(QMainWindow*, QString action_name); + + // Init plugin + virtual void init(QMainWindow* mainWindow, Scene_interface* scene_interface); + + // Get list of actions supported by this plugin + virtual QStringList actionsNames() const; + virtual QList actions() const; + + // To get a selected item with the type of SceneType + template + SceneType* get_selected_item() const { + int item_id = scene->mainSelectionIndex(); + SceneType* scene_item = qobject_cast(scene->item(item_id)); + if(!scene_item) { + // no selected SceneType - if there is only one in list return it, otherwise NULL + int counter = 0; + int last_selected = 0; + for(Scene_interface::Item_id i = 0, end = scene->numberOfEntries(); i < end && counter < 2; ++i) { + if(SceneType* tmp = qobject_cast(scene->item(i))) { + scene_item = tmp; + counter++; + last_selected=i; + } + } + if(counter != 1) { return NULL; } + scene->setSelectedItem(last_selected); + } + return scene_item; + } + + void add_dock_widget(QDockWidget* dock); + + // Auto-connect actions to slots. Called by init(). + void autoConnectActions(); + +protected: + QMap actions_map; + Scene_interface* scene; + QMainWindow* mw; +}; + +#endif // POLYHEDRON_DEMO_OPERATION_HELPER_H diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 9e22897db46..e2e6bf08a58 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -18,8 +18,7 @@ #include #include #include - - +#include GlSplat::SplatRenderer* Scene::ms_splatting = 0; int Scene::ms_splattingCounter = 0; @@ -30,7 +29,7 @@ GlSplat::SplatRenderer* Scene::splatting() } Scene::Scene(QObject* parent) - : QAbstractListModel(parent), + : QStandardItemModel(parent), selected_item(-1), item_A(-1), item_B(-1) @@ -50,6 +49,10 @@ Scene::Scene(QObject* parent) Scene::Item_id Scene::addItem(CGAL::Three::Scene_item* item) { + Scene_group_item* group = + qobject_cast(item); + if(group) + m_group_entries.prepend(group); Bbox bbox_before = bbox(); m_entries.push_back(item); connect(item, SIGNAL(itemChanged()), @@ -63,9 +66,17 @@ Scene::addItem(CGAL::Three::Scene_item* item) { Q_EMIT updated_bbox(); } - QAbstractListModel::beginResetModel(); + QList list; + for(int i=0; i<5; i++) + { + list<setEditable(false); + } + invisibleRootItem()->appendRow(list); + for(int i=0; i<5; i++){ + index_map[list.at(i)->index()] = m_entries.size() -1; + } Q_EMIT updated(); - QAbstractListModel::endResetModel(); Item_id id = m_entries.size() - 1; Q_EMIT newItem(id); return id; @@ -92,7 +103,7 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi } Q_EMIT updated(); itemChanged(index); - // QAbstractListModel::reset(); + Q_EMIT restoreCollapsedState(); return item; } @@ -103,50 +114,73 @@ Scene::erase(int index) return -1; CGAL::Three::Scene_item* item = m_entries[index]; + Q_FOREACH(Scene_group_item* group, m_group_entries) + { + if(group->getChildren().contains(item)) + group->removeChild(item); + if (group->getChildren().isEmpty()) + { + m_group_entries.removeOne(group); + m_entries.removeOne(group); + } + } Q_EMIT itemAboutToBeDestroyed(item); delete item; m_entries.removeAt(index); - selected_item = -1; - QAbstractListModel::beginResetModel(); + QStandardItemModel::beginResetModel(); Q_EMIT updated(); - QAbstractListModel::endResetModel(); - + QStandardItemModel::endResetModel(); if(--index >= 0) return index; if(!m_entries.isEmpty()) return 0; return -1; + } int Scene::erase(QList indices) { QList to_be_removed; - + clear(); + index_map.clear(); int max_index = -1; Q_FOREACH(int index, indices) { if(index < 0 || index >= m_entries.size()) continue; + max_index = (std::max)(max_index, index); CGAL::Three::Scene_item* item = m_entries[index]; - to_be_removed.push_back(item); + if(!to_be_removed.contains(item)) + to_be_removed.push_back(item); } - - - Q_FOREACH(CGAL::Three::Scene_item* item, to_be_removed) { + Q_FOREACH(Scene_item* item, to_be_removed) { + Scene_group_item* group = + qobject_cast(item); + if(group) + { + m_group_entries.removeAll(group); + } + Q_FOREACH(Scene_group_item* group_item, m_group_entries) + if(group_item->getChildren().contains(item)) + group_item->removeChild(item); Q_EMIT itemAboutToBeDestroyed(item); delete item; m_entries.removeAll(item); } - selected_item = -1; - QAbstractListModel::beginResetModel(); + Q_FOREACH(Scene_item* item, m_entries) + { + organize_items(item, invisibleRootItem(), 0); + } + QStandardItemModel::beginResetModel(); Q_EMIT updated(); - QAbstractListModel::endResetModel(); - + QStandardItemModel::endResetModel(); + Q_EMIT restoreCollapsedState(); + int index = max_index + 1 - indices.size(); if(index >= m_entries.size()) { index = m_entries.size() - 1; @@ -159,6 +193,16 @@ Scene::erase(QList indices) } +void Scene::remove_item_from_groups(Scene_item* item) +{ + Q_FOREACH(Scene_group_item* group, m_group_entries) + { + if(group->getChildren().contains(item)) + { + group->removeChild(item); + } + } +} Scene::~Scene() { Q_FOREACH(CGAL::Three::Scene_item* item_ptr, m_entries) @@ -230,7 +274,7 @@ void Scene::initializeGL() } -bool +bool Scene::keyPressEvent(QKeyEvent* e){ bool res=false; for (QList::iterator it=selected_items_list.begin(),endit=selected_items_list.end(); @@ -242,7 +286,7 @@ Scene::keyPressEvent(QKeyEvent* e){ return res; } -void +void Scene::draw() { draw_aux(false, 0); @@ -252,7 +296,7 @@ Scene::draw(CGAL::Three::Viewer_interface* viewer) { draw_aux(false, viewer); } -void +void Scene::drawWithNames() { draw_aux(true, 0); @@ -283,7 +327,7 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); viewer->glPointSize(2.f); viewer->glLineWidth(1.0f); - if(index == selected_item) + if(index == selected_item || selected_items_list.contains(index)) { item.selection_changed(true); } @@ -325,7 +369,7 @@ glDepthFunc(GL_LEQUAL); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); viewer->glPointSize(2.f); viewer->glLineWidth(1.0f); - if(index == selected_item) + if(index == selected_item || selected_items_list.contains(index)) { item.selection_changed(true); } @@ -347,7 +391,7 @@ glDepthFunc(GL_LEQUAL); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); viewer->glPointSize(2.f); viewer->glLineWidth(1.0f); - if(index == selected_item) + if(index == selected_item || selected_items_list.contains(index)) { item.selection_changed(true); @@ -438,58 +482,41 @@ glDepthFunc(GL_LEQUAL); // workaround for Qt-4.2 (see above) #undef lighter - -int -Scene::rowCount(const QModelIndex & parent) const -{ - if (parent.isValid()) - return 0; - else - return m_entries.size(); -} - -int -Scene::columnCount(const QModelIndex & parent) const -{ - if (parent.isValid()) - return 0; - else - return NumberOfColumns; -} - -QVariant +QVariant Scene::data(const QModelIndex &index, int role) const { if (!index.isValid()) + { return QVariant(); + } - if(index.row() < 0 || index.row() >= m_entries.size()) + int id = index_map[index]; + if(id < 0 || id >= m_entries.size()) return QVariant(); - if(role == ::Qt::ToolTipRole) { - return m_entries[index.row()]->toolTip(); + return m_entries[id]->toolTip(); } switch(index.column()) { case ColorColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return m_entries.value(index.row())->color(); + return m_entries.value(id)->color(); else if(role == ::Qt::DecorationRole) - return m_entries.value(index.row())->color(); + return m_entries.value(id)->color(); break; case NameColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return m_entries.value(index.row())->name(); + return m_entries.value(id)->name(); if(role == ::Qt::FontRole) - return m_entries.value(index.row())->font(); + return m_entries.value(id)->font(); break; case RenderingModeColumn: if(role == ::Qt::DisplayRole) { - return m_entries.value(index.row())->renderingModeName(); + return m_entries.value(id)->renderingModeName(); } else if(role == ::Qt::EditRole) { - return static_cast(m_entries.value(index.row())->renderingMode()); + return static_cast(m_entries.value(id)->renderingMode()); } else if(role == ::Qt::TextAlignmentRole) { return ::Qt::AlignCenter; @@ -497,9 +524,9 @@ Scene::data(const QModelIndex &index, int role) const break; case ABColumn: if(role == ::Qt::DisplayRole) { - if(index.row() == item_A) + if(id == item_A) return "A"; - if(index.row() == item_B) + if(id == item_B) return "B"; } else if(role == ::Qt::TextAlignmentRole) { @@ -508,7 +535,7 @@ Scene::data(const QModelIndex &index, int role) const break; case VisibleColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return m_entries.value(index.row())->visible(); + return m_entries.value(id)->visible(); break; default: return QVariant(); @@ -516,7 +543,7 @@ Scene::data(const QModelIndex &index, int role) const return QVariant(); } -QVariant +QVariant Scene::headerData ( int section, ::Qt::Orientation orientation, int role ) const { if(orientation == ::Qt::Horizontal) { @@ -551,32 +578,36 @@ Scene::headerData ( int section, ::Qt::Orientation orientation, int role ) const } } } - return QAbstractListModel::headerData(section, orientation, role); + return QStandardItemModel::headerData(section, orientation, role); } -Qt::ItemFlags +Qt::ItemFlags Scene::flags ( const QModelIndex & index ) const { if (index.isValid() && index.column() == NameColumn) { - return QAbstractListModel::flags(index) | ::Qt::ItemIsEditable; + return QStandardItemModel::flags(index) | ::Qt::ItemIsEditable; } else { - return QAbstractListModel::flags(index); + return QStandardItemModel::flags(index); } } -bool -Scene::setData(const QModelIndex &index, +bool +Scene::setData(const QModelIndex &index, const QVariant &value, int role) { + if( role != ::Qt::EditRole || !index.isValid() ) return false; - if(index.row() < 0 || index.row() >= m_entries.size()) + int id = index_map[index]; + if(id < 0 || id >= m_entries.size()){ return false; + } + + CGAL::Three::Scene_item* item = m_entries[id]; - CGAL::Three::Scene_item* item = m_entries[index.row()]; if(!item) return false; switch(index.column()) { @@ -601,13 +632,14 @@ Scene::setData(const QModelIndex &index, rendering_mode = static_cast( (rendering_mode+1) % NumberOfRenderingMode ); } item->setRenderingMode(rendering_mode); - Q_EMIT dataChanged(index, index); + QModelIndex nindex = createIndex(m_entries.size()-1,RenderingModeColumn+1); + Q_EMIT dataChanged(index, nindex); return true; break; } case VisibleColumn: item->setVisible(value.toBool()); - Q_EMIT dataChanged(index, index); + Q_EMIT dataChanged(index, createIndex(m_entries.size()-1,VisibleColumn+1)); return true; default: return false; @@ -615,6 +647,74 @@ Scene::setData(const QModelIndex &index, return false; } +bool Scene::dropMimeData(const QMimeData */*data*/, + Qt::DropAction /*action*/, + int /*row*/, + int /*column*/, + const QModelIndex &parent) +{ + //gets the moving items + QList items; + QList groups_children; + + //get IDs of all children of selected groups + Q_FOREACH(int i, selected_items_list) + { + Scene_group_item* group = + qobject_cast(item(i)); + if(group) + Q_FOREACH(Scene_item* child, group->getChildren()) + groups_children << item_id(child); + } + // Insure that children of selected groups will not be added twice + Q_FOREACH(int i, selected_items_list) + { + if(!groups_children.contains(i)) + items << item(i); + } + //Gets the group at the drop position + Scene_group_item* group = + qobject_cast(this->item(index_map[parent])); + bool one_contained = false; + if(group) + { + Q_FOREACH(int id, selected_items_list) + if(group->getChildren().contains(item(id))) + { + one_contained = true; + break; + } + } + //if the drop item is not a group_item or if it already contains the item, then the drop action must be ignored + if(!group ||one_contained) + { + //unless the drop zone is empty, which means the item should be removed from all groups. + if(!parent.isValid()) + { + Q_FOREACH(Scene_item* item, items) + while(item->has_group!=0) + { + Q_FOREACH(Scene_group_item* group_item, m_group_entries) + if(group_item->getChildren().contains(item)) + { + group_item->removeChild(item); + break; + } + } + group_added(); + return true; + } + return false; + } + Q_FOREACH(Scene_item* item, items) + changeGroup(item, group); + //group->addChild(item(mainSelectionIndex())); + group_added(); + return true; + + +} + Scene::Item_id Scene::mainSelectionIndex() const { return selected_item; } @@ -633,14 +733,14 @@ int Scene::selectionBindex() const { QItemSelection Scene::createSelection(int i) { - return QItemSelection(this->createIndex(i, 0), - this->createIndex(i, LastColumn)); + return QItemSelection(index_map.keys(i).at(0), + index_map.keys(i).at(4)); } QItemSelection Scene::createSelectionAll() { - return QItemSelection(this->createIndex(0, 0), - this->createIndex(m_entries.size() - 1 , LastColumn)); + return QItemSelection(index_map.keys(0).at(0), + index_map.keys(m_entries.size() - 1).at(4)); } void Scene::itemChanged() @@ -657,6 +757,7 @@ void Scene::itemChanged(Item_id i) Q_EMIT dataChanged(this->createIndex(i, 0), this->createIndex(i, LastColumn)); + // Q_EMIT restoreCollapsedState(); } void Scene::itemChanged(CGAL::Three::Scene_item* /* item */) @@ -673,6 +774,7 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, Q_ASSERT(proxyModel); Scene *scene = dynamic_cast(proxyModel->sourceModel()); Q_ASSERT(scene); + int id = scene->index_map[proxyModel->mapToSource(index)]; switch(index.column()) { case Scene::VisibleColumn: if (event->type() == QEvent::MouseButtonPress) { @@ -681,7 +783,7 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, int x = mouseEvent->pos().x() - option.rect.x(); if(x >= (option.rect.width() - size)/2 && x <= (option.rect.width() + size)/2) { - model->setData(index, ! model->data(index).toBool() ); + model->setData(index, !model->data(index).toBool()); } } return false; //so that the selection can change @@ -724,19 +826,19 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, break; case Scene::ABColumn: if (event->type() == QEvent::MouseButtonPress) { - if(index.row() == scene->item_B) { - scene->item_A = index.row(); + if(id == scene->item_B) { + scene->item_A = id; scene->item_B = -1; } - else if(index.row() == scene->item_A) { - scene->item_B = index.row(); + else if(id == scene->item_A) { + scene->item_B = id; scene->item_A = -1; } else if(scene->item_A == -1) { - scene->item_A = index.row(); + scene->item_A = id; } else { - scene->item_B = index.row(); + scene->item_B = id; } scene->dataChanged(scene->createIndex(0, Scene::ABColumn), scene->createIndex(scene->rowCount() - 1, Scene::ABColumn)); @@ -751,31 +853,35 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, void SceneDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + QModelIndex test = proxy->mapToSource(index); if (index.column() != Scene::VisibleColumn) { QItemDelegate::paint(painter, option, index); } else { const QAbstractItemModel *model = index.model(); + QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? (option.state & QStyle::State_Active) ? QPalette::Normal : QPalette::Inactive : QPalette::Disabled; if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.color(cg, QPalette::Highlight)); - bool checked = model->data(index, ::Qt::DisplayRole).toBool(); int width = option.rect.width(); int height = option.rect.height(); size = (std::min)(width, height); int x = option.rect.x() + (option.rect.width() / 2) - (size / 2);; int y = option.rect.y() + (option.rect.height() / 2) - (size / 2); - if(checked) { - painter->drawPixmap(x, y, checkOnPixmap.scaled(QSize(size, size), - ::Qt::KeepAspectRatio, - ::Qt::SmoothTransformation)); - } - else { - painter->drawPixmap(x, y, checkOffPixmap.scaled(QSize(size, size), - ::Qt::KeepAspectRatio, - ::Qt::SmoothTransformation)); + if(test.row()>=0 && test.row()m_entries.size()){ + + if(checked) { + painter->drawPixmap(x, y, checkOnPixmap.scaled(QSize(size, size), + ::Qt::KeepAspectRatio, + ::Qt::SmoothTransformation)); + } + else { + painter->drawPixmap(x, y, checkOffPixmap.scaled(QSize(size, size), + ::Qt::KeepAspectRatio, + ::Qt::SmoothTransformation)); + } } drawFocus(painter, option, option.rect); // since we draw the grid ourselves } @@ -850,6 +956,44 @@ Scene::Bbox Scene::bbox() const } return bbox; } +QList Scene::group_entries() const +{ + return m_group_entries; +} + +QList Scene::item_entries() const +{ + return m_entries; +} +void Scene::group_added() +{ + //makes the hierarchy in the tree + //clears the model + clear(); + index_map.clear(); + //fills the model + Q_FOREACH(Scene_item* item, m_entries) + { + organize_items(item, invisibleRootItem(), 0); + } + Q_EMIT restoreCollapsedState(); +} +void Scene::changeGroup(Scene_item *item, Scene_group_item *target_group) +{ + //remove item from the containing group if any + if(item->has_group!=0) + Q_FOREACH(Scene_group_item* group, m_group_entries) + { + if(group->getChildren().contains(item)) + { + remove_item_from_groups(item); + break; + } + } + //add the item to the target group + target_group->addChild(item); + item->has_group = target_group->has_group +1; +} float Scene::get_bbox_length() const { @@ -859,6 +1003,60 @@ float Scene::get_bbox_length() const #include "Scene_find_items.h" +void Scene::organize_items(Scene_item* item, QStandardItem* root, int loop) +{ + if(item->has_group <= loop) + { + QList list; + for(int i=0; i<5; i++) + { + list<setEditable(false); + + } + root->appendRow(list); + for(int i=0; i<5; i++){ + index_map[list.at(i)->index()] = m_entries.indexOf(item); + } + Scene_group_item* group = + qobject_cast(item); + if(group) + { + Q_FOREACH(Scene_item*child, group->getChildren()) + { + organize_items(child, list.first(), loop+1); + } + } + } +} + +void Scene::setExpanded(QModelIndex id) +{ + Scene_group_item* group = + qobject_cast(item(index_map.value(index(0, 0, id.parent())))); + if(group) + { + group->setExpanded(true); + } +} +void Scene::setCollapsed(QModelIndex id) +{ + Scene_group_item* group = + qobject_cast(item(index_map.value(index(0, 0, id.parent())))); + if(group) + group->setExpanded(false); +} + +int Scene::getIdFromModelIndex(QModelIndex modelId)const +{ + return index_map.value(modelId); +} + +QList Scene::getModelIndexFromId(int id) const +{ + return index_map.keys(id); +} + namespace scene { namespace details { Q_DECL_EXPORT @@ -878,6 +1076,7 @@ findItem(const CGAL::Three::Scene_interface* scene_interface, Q_DECL_EXPORT QList findItems(const CGAL::Three::Scene_interface* scene_interface, + const QMetaObject&, QString name, Scene_item_name_fn_ptr fn) { diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index 50d7f2b7b6f..694a9c02296 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -3,25 +3,25 @@ #define SCENE_H #include "config.h" #include "Scene_config.h" - #include #include #include #include -#include +#include #include #include #include +#include #include #include #include #include - +#include #include #include #include - +#include "Scene_group_item.h" class QEvent; class QMouseEvent; namespace GlSplat { class SplatRenderer; } @@ -29,7 +29,8 @@ namespace CGAL { namespace Three{ class Viewer_interface;}} class SCENE_EXPORT Scene : - public QAbstractListModel, public CGAL::Three::Scene_interface, public CGAL::Three::Scene_draw_interface + public QStandardItemModel, public CGAL::Three::Scene_interface, public CGAL::Three::Scene_draw_interface + { Q_OBJECT Q_PROPERTY(int numberOfEntries READ numberOfEntries) @@ -37,6 +38,8 @@ class SCENE_EXPORT Scene : friend class SceneDelegate; public: + QList getModelIndexFromId(int id) const; + int getIdFromModelIndex(QModelIndex modelId) const; enum Columns { NameColumn = 0, ColorColumn, RenderingModeColumn, @@ -50,8 +53,11 @@ public: //!Adds item to the items list, gives it an ID and //!updates the bounding box if needed. int addItem(CGAL::Three::Scene_item* item); - //!Sets item as the item at index and calls @ref Scene_item#changed(). + //!Moves item to the targeted group. + void changeGroup(CGAL::Three::Scene_item* item, Scene_group_item* target_group); + + //!Sets item as the item at index and calls @ref Scene_item#changed(). //!If emit_item_about_to_be_destroyed is set to true, emits //!an itemAboutToBeDestroyed signal. CGAL::Three::Scene_item* replaceItem(int index, CGAL::Three::Scene_item* item, bool emit_item_about_to_be_destroyed = false); @@ -134,12 +140,9 @@ public: return std::sqrt(dx*dx + dy*dy + dz*dz); } - // QAbstractItemModel functions - //!@returns the number of items, which is also the sumber of rows in the sceneView. - int rowCount ( const QModelIndex & parent = QModelIndex() ) const; - //!@returns the number of columns in the sceneView. - int columnCount ( const QModelIndex & parent = QModelIndex() ) const; - //!@returns the column data corresponding to role. + + // QStandardItemModel functions + bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &parent); QVariant data ( const QModelIndex & index, int role = ::Qt::DisplayRole ) const; //!@returns the type of data correspondind to the role. QVariant headerData ( int section, ::Qt::Orientation orientation, int role = ::Qt::DisplayRole ) const; @@ -148,7 +151,8 @@ public: /*! Sets the column data for the target index. Returns false if index is not valid and * if role is not EditRole.*/ bool setData(const QModelIndex &index, const QVariant &value, int role); - + QList group_entries() const ; + QList item_entries() const ; // auxiliary public function for QMainWindow //!Selects the row at index i in the sceneView. QItemSelection createSelection(int i); @@ -169,6 +173,10 @@ public Q_SLOTS: * Calls @ref Scene_item#changed(). * This function is called by the items.*/ void itemChanged(CGAL::Three::Scene_item*); + //!Removes item from all the groups of the scene. + void remove_item_from_groups(CGAL::Three::Scene_item* item); + //!Re-organizes the sceneView. + void group_added(); //! Sets the selected item to the target index. void setSelectedItemIndex(int i) { @@ -179,7 +187,8 @@ public Q_SLOTS: { selected_item = i; Q_EMIT selectionChanged(i); - }; + } + //! Sets the target item as selected and emits setSelectedItem for its index. void setSelectedItem(CGAL::Three::Scene_item* item_to_select) { @@ -193,12 +202,26 @@ public Q_SLOTS: } ++i; } - }; + } //! Sets the target list of indices as the selected indices. - void setSelectedItemsList(QList l ) + QList setSelectedItemsList(QList l ) { + Q_FOREACH(int i,l) + { + Scene_group_item* group = + qobject_cast(item(i)); + if(group) + { + QList list; + Q_FOREACH(CGAL::Three::Scene_item* child, group->getChildren()) + list<update();} @@ -227,12 +254,16 @@ private: * to its current renderingMode. If with_names is true, uses * the OpenGL mode GL_WITH_NAMES, essentially used for the picking.*/ void draw_aux(bool with_names, CGAL::Three::Viewer_interface*); + //! Re-draw the hierarchy of the view. + void organize_items(CGAL::Three::Scene_item* item, QStandardItem *root, int loop); //! List of Scene_items. typedef QList Entries; //!List containing all the scene_items. Entries m_entries; //! Index of the currently selected item. int selected_item; + //!List containing all the scene_group_items. + QList m_group_entries; //!List of indices of the currently selected items. QList selected_items_list; //!Index of the item_A. @@ -241,10 +272,14 @@ private: int item_B; static GlSplat::SplatRenderer* ms_splatting; static int ms_splattingCounter; + QMap index_map; + public: static GlSplat::SplatRenderer* splatting(); }; // end class Scene + +class QAbstractProxyModel; /*! * \brief The SceneDelegate class * Handles the columns of the sceneView @@ -265,11 +300,21 @@ public: //! Draws the content of the sceneView void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + void setProxy(QAbstractProxyModel* p_proxy){ + proxy = p_proxy; + } + void setScene(Scene* p_scene){ + scene = p_scene; + } private: QPixmap checkOnPixmap; QPixmap checkOffPixmap; + QAbstractProxyModel *proxy; + Scene *scene; mutable int size; }; // end class SceneDelegate #endif // SCENE_H + + diff --git a/Polyhedron/demo/Polyhedron/Scene_find_items.h b/Polyhedron/demo/Polyhedron/Scene_find_items.h index 77318c663ce..eecdd8a481b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_find_items.h +++ b/Polyhedron/demo/Polyhedron/Scene_find_items.h @@ -16,19 +16,19 @@ typedef QString (CGAL::Three::Scene_item ::*Scene_item_name_fn_ptr)() const; // Declaration only (defined in Scene.cpp) SCENE_EXPORT CGAL::Three::Scene_item* -findItem(const Scene_interface* scene_interface, +findItem(const CGAL::Three::Scene_interface* scene_interface, const QMetaObject& metaobj, QString name, Scene_item_name_fn_ptr fn); // Declaration only (defined in Scene.cpp) SCENE_EXPORT QList -findItems(const Scene_interface* scene_interface, +findItems(const CGAL::Three::Scene_interface* scene_interface, const QMetaObject& metaobj, QString name, Scene_item_name_fn_ptr fn); // fwd declaration template -T findItem(const Scene_interface* scene, QString name, +T findItem(const CGAL::Three::Scene_interface* scene, QString name, Scene_item_name_fn_ptr fn) { return @@ -38,7 +38,7 @@ T findItem(const Scene_interface* scene, QString name, } template -QList findItems(const Scene_interface* scene, QString name, +QList findItems(const CGAL::Three::Scene_interface* scene, QString name, Scene_item_name_fn_ptr fn) { QList void_list = @@ -60,7 +60,7 @@ QList findItems(const Scene_interface* scene, QString name, accepted. */ template -T findItem(const Scene_interface* scene, +T findItem(const CGAL::Three::Scene_interface* scene, QString item_name = QString()) { return details::findItem(scene, item_name, &CGAL::Three::Scene_item::name); } @@ -69,7 +69,7 @@ T findItem(const Scene_interface* scene, accepted. */ template -QList findItems(const Scene_interface* scene, +QList findItems(const CGAL::Three::Scene_interface* scene, QString item_name = QString()) { return details::findItems(scene, item_name, &CGAL::Three::Scene_item::name); } @@ -78,7 +78,7 @@ QList findItems(const Scene_interface* scene, omitted, all names are accepted. */ template -T findItemByObjectName(const Scene_interface* scene, +T findItemByObjectName(const CGAL::Three::Scene_interface* scene, QString obj_name = QString()) { return details::findItem(scene, obj_name, &QObject::objectName); } @@ -87,7 +87,7 @@ T findItemByObjectName(const Scene_interface* scene, names are accepted. */ template -QList findItemsByObjectName(const Scene_interface* scene, +QList findItemsByObjectName(const CGAL::Three::Scene_interface* scene, QString obj_name = QString()) { return details::findItems(scene, obj_name, &QObject::objectName); } diff --git a/Polyhedron/demo/Polyhedron/Scene_group_item.cpp b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp new file mode 100644 index 00000000000..5c54247a5c5 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp @@ -0,0 +1,113 @@ + +#include "Scene_group_item.h" +#include + + +Scene_group_item::Scene_group_item(QString name) + : Scene_item(0,0) +{ + this->name_ = name; + expanded = true; +} + +bool Scene_group_item::isFinite() const +{ + Q_FOREACH(Scene_item *item, children) + if(!item->isFinite()){ + return false; + } + return true; +} + +bool Scene_group_item::isEmpty() const { + Q_FOREACH(Scene_item *item, children) + if(!item->isEmpty()){ + return true; + } + return true; +} + +Scene_group_item::Bbox Scene_group_item::bbox() const +{ + return Bbox(0, 0, 0, 0, 0,0); +} + + +bool Scene_group_item::supportsRenderingMode(RenderingMode m) const { + Q_FOREACH(Scene_item* item, children) + if(!item->supportsRenderingMode(m)) + return false; + return !children.isEmpty(); + +} + +QString Scene_group_item::toolTip() const { + QString str = + QObject::tr( "

Number of children: %1
").arg(children.size()); + str+="

"; + str += QString("Bounding box: min (%1,%2,%3), max(%4,%5,%6)") + .arg(bbox().xmin) + .arg(bbox().ymin) + .arg(bbox().zmin) + .arg(bbox().xmax) + .arg(bbox().ymax) + .arg(bbox().zmax); + return str; +} + +void Scene_group_item::addChild(Scene_item* new_item) +{ + if(!children.contains(new_item)) + { + children.append(new_item); + add_group_number(new_item); + } + +} + +void Scene_group_item::add_group_number(Scene_item * new_item) +{ + + Scene_group_item* group = + qobject_cast(new_item); + if(group) + Q_FOREACH(Scene_item* child, group->getChildren()) + add_group_number(child); + new_item->has_group++; +} +void Scene_group_item::setColor(QColor c) +{ + Scene_item::setColor(c); + Q_FOREACH(Scene_item* child, children) + { + child->setColor(c); + } +} + +void Scene_group_item::setRenderingMode(RenderingMode m) +{ + Scene_item::setRenderingMode(m); + Q_FOREACH(Scene_item* child, children) + { + child->setRenderingMode(m); + } +} + +void Scene_group_item::setVisible(bool b) +{ + Scene_item::setVisible(b); + Q_FOREACH(Scene_item* child, children) + { + child->setVisible(b); + } +} + +bool Scene_group_item::isExpanded() const +{ + return expanded; +} + +void Scene_group_item::setExpanded(bool b) +{ + expanded = b; +} diff --git a/Polyhedron/demo/Polyhedron/Scene_group_item.h b/Polyhedron/demo/Polyhedron/Scene_group_item.h new file mode 100644 index 00000000000..36cdf33f05b --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_group_item.h @@ -0,0 +1,95 @@ +#ifndef SCENE_GROUP_ITEM_H +#define SCENE_GROUP_ITEM_H + +#include +#include "Messages_interface.h" +using namespace CGAL::Three; +class Q_DECL_EXPORT Scene_group_item : public Scene_item +{ + Q_OBJECT +public : + Scene_group_item(QString name = QString()); + ~Scene_group_item() {} + bool isFinite() const; + + bool isEmpty() const ; + + bool isExpanded() const; + + void setExpanded(bool); + + Bbox bbox() const; + + Scene_group_item* clone() const {return 0;} + //! Indicate if rendering mode is supported. + bool supportsRenderingMode(RenderingMode m) const; + + QString toolTip() const; + + void addChild(Scene_item* new_item); + + void setColor(QColor c); + + void setRenderingMode(RenderingMode m); + + void setVisible(bool b); + + void setPointsMode() { + setRenderingMode(Points); + } + + void setWireframeMode() { + setRenderingMode(Wireframe); + } + void setWireframe() { + setRenderingMode(Wireframe); + } + + void setFlat() { + setRenderingMode(Flat); + } + void setFlatMode() { + setRenderingMode(Flat); + } + + void setFlatPlusEdgesMode() { + setRenderingMode(FlatPlusEdges); + } + + void setGouraudMode() { + setRenderingMode(Gouraud); + } + + void setPointsPlusNormalsMode(){ + setRenderingMode(PointsPlusNormals); + } + + void setSplattingMode(){ + setRenderingMode(Splatting); + } + + QList getChildren() const {return children;} + + void removeChild( Scene_item* item) + { + Scene_group_item* group = + qobject_cast(item); + if(group) + Q_FOREACH(Scene_item* child, group->getChildren()) + removeChild(child); + item->has_group=0; + children.removeOne(item); + } + +Q_SIGNALS: + void updated(int row, int column); + +private: + QList children; + void add_group_number(Scene_item*new_item); + bool expanded; + +}; //end of class Scene_group_item + + +#endif // SCENE_GROUP_ITEM_H diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp index 5311019cf36..58dd4a9bc50 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp @@ -845,7 +845,6 @@ void Scene_polyhedron_item::draw(CGAL::Three::Viewer_interface* viewer) const { initialize_buffers(viewer); } - if(renderingMode() == Flat || renderingMode() == FlatPlusEdges) vaos[Facets]->bind(); else diff --git a/Three/include/CGAL/Three/Scene_item.h b/Three/include/CGAL/Three/Scene_item.h index ff3c43c1643..fa076f002e6 100644 --- a/Three/include/CGAL/Three/Scene_item.h +++ b/Three/include/CGAL/Three/Scene_item.h @@ -96,6 +96,7 @@ public: buffers[i].create(); } nb_isolated_vertices = 0; + has_group = 0; } //!The Constructor. /*! @@ -127,6 +128,7 @@ public: buffers[i].create(); } nb_isolated_vertices = 0; + has_group = 0; } //! Setter for the number of isolated vertices. void setNbIsolatedvertices(std::size_t nb) { nb_isolated_vertices = nb;} @@ -222,6 +224,7 @@ public: //!Handles key press events. virtual bool keyPressEvent(QKeyEvent*){return false;} + int has_group; public Q_SLOTS: //! Notifies the program that the internal data or the properties of