//=============================================================================
//
// OpenFlipper
// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
// www.openflipper.org
//
//-----------------------------------------------------------------------------
//
// License
//
// OpenFlipper 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.
//
// OpenFlipper 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenFlipper. If not, see .
//
//-----------------------------------------------------------------------------
//
// $Revision$
// $Author$
// $Date$
//
//=============================================================================
#include "DataControlPlugin.hh"
#include
#include
#include
#include
#include
#include "Menu.hh"
/// Slot for Remove action in ContextMenu
void DataControlPlugin::slotPopupRemove ( ) {
QItemSelectionModel* selection = view_->selectionModel();
if (selection == 0) return;
// Get all selected rows
QModelIndexList indexList = selection->selectedRows();
QMessageBox msgBox;
msgBox.setText("Do you really want to remove the selected objects?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
QString text;
for ( int i = 0 ; i < indexList.size() ; ++i) {
BaseObject* deleteItem = model_->getItem( indexList[i] );
text += deleteItem->name() + "\n";
}
msgBox.setDetailedText(text);
if ( msgBox.exec() == QMessageBox::No)
return;
for ( int i = 0 ; i < indexList.size() ; ++i) {
BaseObject* deleteItem = model_->getItem( indexList[i] );
// Skip the root item
if ( model_->isRoot( deleteItem ) )
continue;
// remove the whole subtree below this item
deleteItem->deleteSubtree();
// remove the item itself from the parent
deleteItem->parent()->removeChild(deleteItem);
// delete it
delete deleteItem;
}
emit updateView();
emit updatedObject(-1);
}
/// Slot for Ungroup action in ContextMenu
void DataControlPlugin::slotUngroup ( ) {
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
//remove complete group if selected item was a group
BaseObject* group = model_->getItem( indexList[0]);
for (int i=0; i < group->childCount(); i++){
group->child(i)->setParent(group->parent());
group->parent()->appendChild( group->child(i) );
}
group->parent()->removeChild(group);
delete group;
emit updatedObject(-1);
}
/// Slot for Copy action in ContextMenu
void DataControlPlugin::slotCopy ( ) {
QItemSelectionModel* selection = view_->selectionModel();
if (selection == 0) return;
// Get all selected rows
QModelIndexList indexList = selection->selectedRows();
for ( int i = 0 ; i < indexList.size() ; ++i) {
BaseObject* copyItem = model_->getItem( indexList[i] );
// remove the whole subtree below this item
if ( PluginFunctions::copyObject(copyItem->id()) == -1 ) {
emit log(LOGERR, "Unable to copy object" );
continue;
}
emit updatedObject(copyItem->id());
}
emit updateView();
}
/// Slot for Group action in ContextMenu
void DataControlPlugin::slotGroup ( ) {
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
//check if all objects have the same parent
//abort if the parents differ
BaseObject* parent = (model_->getItem( indexList[0]))->parent();
for ( int i = 1 ; i < indexList.size() ; ++i) {
BaseObject* item = model_->getItem( indexList[i] );
if (parent != item->parent()){
emit log("Cannot group Objects with different parents");
return;
}
}
//create new group
if (parent == 0)
parent = PluginFunctions::objectRoot();
GroupObject* groupItem = new GroupObject( "newGroup", dynamic_cast< GroupObject* >(parent));
groupItem->setName("newGroup " + QString::number(groupItem->id()));
parent->appendChild( dynamic_cast< BaseObject* >( groupItem ) );
groupItem->setParent( parent );
//append new children to group
for ( int i = 0 ; i < indexList.size() ; ++i) {
BaseObject* item = model_->getItem( indexList[i] );
item->parent()->removeChild(item);
item->setParent( dynamic_cast< BaseObject* >( groupItem ) );
groupItem->appendChild(item);
}
emit updatedObject(-1);
}
/// ContextMenu requested - creates the contextMenu
void DataControlPlugin::slotCustomContextMenuRequested ( const QPoint & _pos ) {
popupIndex_ = view_->indexAt(_pos);
if (!popupIndex_.isValid())
return;
BaseObject* item = model_->getItem(popupIndex_);
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
int selectedRows = indexList.size();
Menu menu(0);
QAction* action;
QIcon icon;
if ( selectedRows > 1 ) {
action = menu.addAction("Copy",this,SLOT ( slotCopy() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-copy.png");
action->setIcon(icon);
menu.addAction("Group",this,SLOT ( slotGroup() ));
menu.addSeparator();
menu.addAction("Remove",this,SLOT ( slotPopupRemove() ));
}else
// check if the item is a group item
if ( item->isGroup() ) {
action = menu.addAction("Zoom to objects",this,SLOT ( slotZoomTo() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"zoom-in.png");
action->setIcon(icon);
menu.addAction("Ungroup",this,SLOT ( slotUngroup() ));
menu.addSeparator();
action = menu.addAction("Rename",this,SLOT ( slotRename() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-rename.png");
action->setIcon(icon);
menu.addSeparator();
action = menu.addAction("Remove",this,SLOT ( slotPopupRemove() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-delete-item.png");
action->setIcon(icon);
} else {
action = menu.addAction("Zoom to object",this,SLOT ( slotZoomTo() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"zoom-in.png");
action->setIcon(icon);
action = menu.addAction("Copy",this,SLOT ( slotCopy() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-copy.png");
action->setIcon(icon);
action = menu.addAction("Rename",this,SLOT ( slotRename() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-rename.png");
action->setIcon(icon);
action = menu.addAction("Material Properties",this,SLOT ( slotMaterialProperties() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-material.png");
action->setIcon(icon);
menu.addAction("Group",this,SLOT ( slotGroup() ));
menu.addSeparator();
action = menu.addAction("Remove",this,SLOT ( slotPopupRemove() ));
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-delete-item.png");
action->setIcon(icon);
}
menu.exec(view_->mapToGlobal( _pos) );
}
void DataControlPlugin::slotHeaderCustomContextMenuRequested ( const QPoint & _pos ) {
headerPopupType_ = viewHeader_->logicalIndexAt( _pos );
QMenu menu(0);
QIcon icon;
switch (headerPopupType_) {
// case 0 :
// std::cerr << "0";
// break;
//Show / Hide
case 1 :
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
menu.addAction(icon,"Show all",this,SLOT ( showAll() ));
menu.addAction("Hide all",this,SLOT ( hideAll() ));
break;
// Source
case 2 :
menu.addAction("Select all",this,SLOT ( setAllSource() ));
menu.addAction("Deselect all",this,SLOT ( clearAllSource() ));
break;
// Target
case 3 :
menu.addAction("Select all",this,SLOT ( setAllTarget() ));
menu.addAction("Deselect all",this,SLOT ( clearAllTarget() ));
break;
default :
// std::cerr << "def";
break;
}
menu.exec(viewHeader_->mapToGlobal( _pos ) );
}
void DataControlPlugin::slotRename(){
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
int selectedRows = indexList.size();
if (selectedRows == 1){
BaseObject* item = model_->getItem( indexList[0]);
bool ok;
QString newName = QInputDialog::getText(0, tr("Rename"),
tr("Enter a new name:"), QLineEdit::Normal,
item->name(), &ok);
if (ok && !newName.isEmpty())
item->setName(newName);
}
}
void DataControlPlugin::slotMaterialProperties(){
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
int selectedRows = indexList.size();
if (selectedRows == 1){
BaseObject* item = model_->getItem( indexList[0]);
BaseObjectData* itemData = dynamic_cast< BaseObjectData* > (item);
ACG::QtWidgets::QtMaterialDialog* dialog = new ACG::QtWidgets::QtMaterialDialog( 0, itemData->materialNode() );
dialog->setWindowFlags(dialog->windowFlags() | Qt::WindowStaysOnTopHint);
connect(dialog, SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
this, SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)) );
dialog->setWindowIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-material.png"));
dialog->show();
}
}
///Called when the material properties were changed inside the material dialog
void DataControlPlugin::slotNodeChanged( ACG::SceneGraph::BaseNode* /*_node*/ ){
emit updateView();
}
void DataControlPlugin::slotZoomTo(){
QItemSelectionModel* selection = view_->selectionModel();
// Get all selected rows
QModelIndexList indexList = selection->selectedRows ( 0 );
int selectedRows = indexList.size();
if (selectedRows == 1){
BaseObject* item = model_->getItem( indexList[0]);
if ( item->isGroup() ) {
//zoom to all objects in this group
QList< BaseObject* > children = item->getLeafs();
//compute boundingBox
bool firstRound = true;
ACG::Vec3d bbmin;
ACG::Vec3d bbmax;
for (int i=0; i < children.size(); i++){
BaseObjectData* child = dynamic_cast< BaseObjectData* > (children[i]);
if (child){
ACG::Vec3d cur_min;
ACG::Vec3d cur_max;
child->getBoundingBox(cur_min, cur_max);
if (firstRound){
bbmin = cur_min;
bbmax = cur_max;
firstRound = false;
}else{
bbmin[0] = std::min( bbmin[0], cur_min[0]);
bbmin[1] = std::min( bbmin[1], cur_min[1]);
bbmin[2] = std::min( bbmin[2], cur_min[2]);
bbmax[0] = std::max( bbmax[0], cur_max[0]);
bbmax[1] = std::max( bbmax[0], cur_max[1]);
bbmax[2] = std::max( bbmax[0], cur_max[2]);
}
}
}
//zoom to objects
ACG::Vec3d bbcenter = (bbmax + bbmin) * 0.5;
double bbradius = (bbmax - bbmin).norm();
ACG::Vec3d eye = bbcenter + (PluginFunctions::eyePos() - bbcenter).normalize() * bbradius ;
PluginFunctions::flyTo(eye, bbcenter );
}else{
//zoom to object
BaseObjectData* obj = dynamic_cast< BaseObjectData* >(item);
if (obj){
ACG::Vec3d bbmin;
ACG::Vec3d bbmax;
obj->getBoundingBox(bbmin, bbmax);
if ((bbmin[0] > bbmax[0]) || (bbmin[1] > bbmax[1]) || (bbmin[2] > bbmax[2]))
std::cerr << "Error while computing bounding box!";
ACG::Vec3d bbcenter = (bbmax + bbmin) * 0.5;
double bbradius = (bbmax - bbmin).norm();
ACG::Vec3d eye = bbcenter + (PluginFunctions::eyePos() - bbcenter).normalize() * bbradius ;
PluginFunctions::flyTo(eye, bbcenter );
}
}
}
}