QtSceneGraphWidget.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS QtSceneGraphWidget - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 //== INCLUDES =================================================================
00052 
00053 
00054 #include "QtSceneGraphWidget.hh"
00055 #include "QtMaterialDialog.hh"
00056 #include "QtClippingDialog.hh"
00057 #include "QtCoordFrameDialog.hh"
00058 #include "QtShaderDialog.hh"
00059 
00060 #include "../Scenegraph/BaseNode.hh"
00061 #include "../Scenegraph/DrawModes.hh"
00062 #include "../Scenegraph/MaterialNode.hh"
00063 #include "../Scenegraph/ClippingNode.hh"
00064 #include "../Scenegraph/ShaderNode.hh"
00065 #include "../Scenegraph/CoordFrameNode.hh"
00066 
00067 #include <QMenu>
00068 #include <QCursor>
00069 #include <QLayout>
00070 #include <QVBoxLayout>
00071 #include <QKeyEvent>
00072 #include <QStringList>
00073 
00074 
00075 //== FORWARDDECLARATIONS ======================================================
00076 
00077 
00078 namespace ACG {
00079   namespace SceneGraph {
00080     class BaseNode;
00081   }
00082 }
00083 
00084 using ACG::SceneGraph::BaseNode;
00085 
00086 
00087 //== NAMESPACES ===============================================================
00088 
00089 namespace ACG {
00090 namespace QtWidgets {
00091 
00092 
00093 //== IMPLEMENTATION ========================================================== 
00094 
00095 
00096 enum PopupMenuItems 
00097 {
00098   M_Options = SceneGraph::DrawModes::UNUSED+1
00099 };
00100 
00101 
00102 //-----------------------------------------------------------------------------
00103 
00104 
00105 QtSceneGraphWidget::
00106 QtSceneGraphWidget( QWidget              * _parent, 
00107                     SceneGraph::BaseNode * _rootNode ) :
00108   QTreeWidget( _parent ),
00109   rootNode_(0),
00110   curItem_(0),
00111   shiftPressed_(false)
00112 
00113 {
00114   setRootIsDecorated(true);
00115 
00116   setSortingEnabled( false );
00117 
00118   setSelectionMode( QAbstractItemView::SingleSelection );
00119 
00120 
00121   setColumnCount( 4 );
00122 
00123   QStringList column_names;
00124   column_names.append( "Node" );
00125   column_names.append( "Type" );
00126   column_names.append( "Status" );
00127   column_names.append( "Mode" );
00128 
00129   setHeaderLabels( column_names );
00130 
00131   modeMenu_ = new QMenu( this );
00132 
00133 
00134   //
00135   // Setup the 'status' actions
00136   //
00137 
00138   statusActions_.menu_ = new QMenu( this );
00139 
00140   QActionGroup * status_ag = new QActionGroup( statusActions_.menu_ );
00141   status_ag->setExclusive( true );
00142 
00143   statusActions_.actionActive_ = new QAction( "Active", status_ag );
00144   statusActions_.actionActive_->setCheckable( true );
00145   statusActions_.actionActive_->setData( QVariant( BaseNode::Active ) );
00146 
00147   statusActions_.actionHideNode_ = new QAction( "Hide Node", status_ag );
00148   statusActions_.actionHideNode_->setCheckable( true );
00149   statusActions_.actionHideNode_->setData( QVariant( BaseNode::HideNode ) );
00150 
00151   statusActions_.actionHideChildren_ = new QAction( "Hide Children", status_ag );
00152   statusActions_.actionHideChildren_->setCheckable( true );
00153   statusActions_.actionHideChildren_->setData( QVariant( BaseNode::HideChildren ) );
00154 
00155   statusActions_.actionHideSubtree_ = new QAction( "Hide Subtree", status_ag );
00156   statusActions_.actionHideSubtree_->setCheckable( true );
00157   statusActions_.actionHideSubtree_->setData( QVariant( BaseNode::HideSubtree ) );
00158 
00159   statusActions_.menu_->addActions( status_ag->actions() );
00160 
00161   connect( status_ag, SIGNAL( triggered( QAction * ) ),
00162            this, SLOT( slotStatusMenu( QAction * ) ) );
00163 
00164 
00165 
00166   connect( this, SIGNAL(itemPressed(QTreeWidgetItem*,int) ),
00167            this, SLOT(slotItemPressed(QTreeWidgetItem*,int)) );
00168 
00169   connect( this, SIGNAL(itemExpanded(QTreeWidgetItem*) ),
00170            this, SLOT(slotItemExpandedOrCollapsed(QTreeWidgetItem*)) );
00171   connect( this, SIGNAL(itemCollapsed(QTreeWidgetItem*) ),
00172            this, SLOT(slotItemExpandedOrCollapsed(QTreeWidgetItem*)) );
00173 
00174   update(_rootNode);
00175 
00176   setMinimumWidth( 600 );
00177   setMinimumHeight( 400 );
00178 
00179 }
00180 
00181 
00182 //-----------------------------------------------------------------------------
00183 
00184 
00185 void 
00186 QtSceneGraphWidget::
00187 update(ACG::SceneGraph::BaseNode* _node)
00188 {
00189   rootNode_ = _node;
00190 
00191   clear();
00192 
00193   Item * item = new Item( this, _node );
00194 
00195   SceneGraph::BaseNode::ChildRIter  cRIt(_node->childrenRBegin()),
00196                                     cREnd(_node->childrenREnd());
00197   for (; cRIt != cREnd; ++cRIt)
00198     update(*cRIt, item);
00199   
00200   expandToDepth ( 0 ); 
00201 
00202   resizeColumnToContents( 0 );
00203   resizeColumnToContents( 1 );
00204   resizeColumnToContents( 2 );
00205   resizeColumnToContents( 3 );
00206 
00207   setMinimumWidth( columnWidth(0) + columnWidth(1) + columnWidth(2) + columnWidth(3) );
00208 }
00209 
00210 
00211 //-----------------------------------------------------------------------------
00212 
00213 
00214 void 
00215 QtSceneGraphWidget::
00216 update(SceneGraph::BaseNode* _node, Item* _parent)
00217 {
00218   // create new item
00219   Item* item = new Item( _parent, _node );
00220 
00221   // process children
00222   SceneGraph::BaseNode::ChildRIter  cRIt(_node->childrenRBegin()),
00223                                     cREnd(_node->childrenREnd());
00224   for (; cRIt != cREnd; ++cRIt)
00225     update(*cRIt, item);
00226 }
00227 
00228 
00229 //-----------------------------------------------------------------------------
00230 
00231 
00232 void 
00233 QtSceneGraphWidget::
00234 slotItemExpandedOrCollapsed( QTreeWidgetItem * /* _item */  )
00235 {
00236   resizeColumnToContents( 0 );
00237 }
00238 
00239 
00240 //-----------------------------------------------------------------------------
00241 
00242 
00243 void 
00244 QtSceneGraphWidget::
00245 slotItemPressed( QTreeWidgetItem * _item,
00246                  int _col)
00247 {
00248 
00249   if ( _item )
00250   {
00251     curItem_ = (Item*) _item;
00252     BaseNode * node = curItem_->node();
00253 
00254     switch ( _col )
00255     {
00256       case 2:
00257       {
00258         statusActions_.actionActive_      ->setChecked( false );
00259         statusActions_.actionHideNode_    ->setChecked( false );
00260         statusActions_.actionHideChildren_->setChecked( false );
00261         statusActions_.actionHideSubtree_ ->setChecked( false );
00262 
00263         switch ( node->status() )
00264         {
00265           case BaseNode::Active:
00266             statusActions_.actionActive_->setChecked( true );
00267             break;
00268           case BaseNode::HideNode:
00269             statusActions_.actionHideNode_->setChecked( true );
00270             break;
00271           case BaseNode::HideChildren:
00272             statusActions_.actionHideChildren_->setChecked( true );
00273             break;
00274           case BaseNode::HideSubtree:
00275             statusActions_.actionHideSubtree_->setChecked( true );
00276             break;
00277         }
00278         statusActions_.menu_->popup( QCursor::pos() ); 
00279         break;
00280       }
00281       case 0: break;
00282       case 1: break;
00283       case 3:
00284       {
00285         modeMenu_->clear();
00286 
00287         QActionGroup * modeGroup = new QActionGroup( modeMenu_ );
00288         modeGroup->setExclusive( true );
00289         connect( modeGroup, SIGNAL( triggered( QAction * ) ),
00290                  this, SLOT( slotModeMenu( QAction * ) ) );
00291 
00292         unsigned int availDrawModes( node->availableDrawModes() );
00293         availDrawModes |= SceneGraph::DrawModes::DEFAULT;
00294         
00295         unsigned int currentDrawMode( node->drawMode() );
00296 
00297         std::vector< unsigned int > available_modes
00298           ( SceneGraph::DrawModes::getDrawModeIDs( availDrawModes ) );
00299 
00300         
00301         for ( unsigned int i = 0; i < available_modes.size(); ++i )
00302         {
00303           unsigned int id    = available_modes[i];
00304           std::string  descr = SceneGraph::DrawModes::description( id );
00305 
00306           QAction * action = new QAction( descr.c_str(), modeGroup );
00307           action->setCheckable( true );
00308           action->setChecked
00309             ( SceneGraph::DrawModes::containsId( currentDrawMode, id ) );
00310           action->setData( QVariant( id ) );
00311         }
00312 
00313         modeMenu_->addActions( modeGroup->actions() );
00314 
00315         if ( dynamic_cast<SceneGraph::MaterialNode*>( node ) )
00316         {
00317           modeMenu_->addSeparator();
00318           QAction * action = modeMenu_->addAction( "Edit material" );
00319           connect( action, SIGNAL( triggered() ),
00320                    this, SLOT( slotEditMaterial() ) );
00321         }
00322         
00323         if ( dynamic_cast<SceneGraph::ShaderNode*>( node ) )
00324         {
00325           modeMenu_->addSeparator();
00326           QAction * action = modeMenu_->addAction( "Edit shaders" );
00327           connect( action, SIGNAL( triggered() ),
00328                    this, SLOT( slotEditShader() ) );
00329         }        
00330 
00331         if ( dynamic_cast<SceneGraph::ClippingNode*>( node ) )
00332         {
00333           modeMenu_->addSeparator();
00334           QAction * action = modeMenu_->addAction( "Edit clip planes" );
00335           connect( action, SIGNAL( triggered() ),
00336                    this, SLOT( slotEditClipPlanes() ) );
00337         }
00338 
00339         if ( dynamic_cast<SceneGraph::CoordFrameNode*>( node ) )
00340         {
00341           modeMenu_->addSeparator();
00342           QAction * action = modeMenu_->addAction( "Edit coord frame" );
00343           connect( action, SIGNAL( triggered() ),
00344                    this, SLOT( slotEditCoordinateFrame() ) );
00345         }
00346 
00347         modeMenu_->popup( QCursor::pos() );
00348 
00349         break;
00350       }
00351       default: break;
00352     }
00353   }
00354 }
00355 
00356 
00357 //-----------------------------------------------------------------------------
00358 
00359 
00360 void QtSceneGraphWidget::slotEditMaterial()
00361 {
00362   if ( curItem_ )
00363   {
00364     SceneGraph::MaterialNode * node =
00365       dynamic_cast< SceneGraph::MaterialNode * >( curItem_->node() );
00366 
00367     QtMaterialDialog* dialog = new QtMaterialDialog( this, node );
00368 
00369     connect(dialog, 
00370             SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
00371             this, 
00372             SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)));
00373 
00374     dialog->show();
00375   }
00376 }
00377 
00378 //-----------------------------------------------------------------------------
00379 
00380 
00381 void QtSceneGraphWidget::slotEditShader()
00382 {
00383   if ( curItem_ )
00384   {
00385     SceneGraph::ShaderNode * node =
00386         dynamic_cast< SceneGraph::ShaderNode * >( curItem_->node() );
00387 
00388     QtShaderDialog* dialog = new QtShaderDialog( this, node );
00389 
00390     connect(dialog, 
00391             SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
00392                    this, 
00393                    SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)));
00394 
00395     dialog->show();
00396   }
00397 }
00398 
00399 
00400 //-----------------------------------------------------------------------------
00401 
00402 
00403 void QtSceneGraphWidget::slotEditClipPlanes()
00404 {
00405   if ( curItem_ )
00406   {
00407     SceneGraph::ClippingNode * node =
00408       dynamic_cast< SceneGraph::ClippingNode * >( curItem_->node() );
00409 
00410     QtClippingDialog * dialog = new QtClippingDialog( this, node );
00411 
00412     connect(dialog, 
00413             SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
00414             this, 
00415             SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)));
00416 
00417     dialog->show();
00418   }
00419 }
00420 
00421 
00422 //-----------------------------------------------------------------------------
00423 
00424 
00425 void QtSceneGraphWidget::slotEditCoordinateFrame()
00426 {
00427   if ( curItem_ )
00428   {
00429     SceneGraph::CoordFrameNode * node =
00430       dynamic_cast< SceneGraph::CoordFrameNode * >( curItem_->node() );
00431 
00432     QtCoordFrameDialog * dialog = new QtCoordFrameDialog( this, node );
00433 
00434     connect(dialog, 
00435             SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
00436             this, 
00437             SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)));
00438 
00439     dialog->show();
00440   }
00441 }
00442 
00443 
00444 //-----------------------------------------------------------------------------
00445 
00446 
00447 void QtSceneGraphWidget::slotModeMenu( QAction * _action )
00448 {
00449   unsigned int id = _action->data().toUInt();
00450 
00451   //    int old_drawmode = curItem_->node()->drawMode();
00452   int new_drawmode = id;
00453   
00454   //    if (shiftPressed_) 
00455   //      new_drawmode ^= (old_drawmode & 0xFFFE);
00456   
00457   curItem_->node()->drawMode( new_drawmode );
00458   curItem_->update();
00459   emit signalNodeChanged( curItem_->node() );
00460 }
00461 
00462 
00463 //-----------------------------------------------------------------------------
00464 
00465 
00466 void QtSceneGraphWidget::slotStatusMenu( QAction * _action )
00467 {
00468   if ( curItem_ )
00469   {
00470     unsigned int status = _action->data().toUInt();
00471     BaseNode * node = curItem_->node();
00472 
00473     node->set_status( (ACG::SceneGraph::BaseNode::StatusMode) status );
00474     curItem_->update();
00475     emit signalNodeChanged( node );
00476   }
00477 }
00478 
00479 
00480 //-----------------------------------------------------------------------------
00481 
00482 
00483 void QtSceneGraphWidget::keyPressEvent(QKeyEvent* _event)
00484 {
00485   switch(_event->key())
00486   {
00487     case Qt::Key_Shift:  shiftPressed_ = true; break;
00488     default : _event->ignore();
00489   }
00490 }
00491 
00492 
00493 void QtSceneGraphWidget::keyReleaseEvent(QKeyEvent *_event)
00494 {
00495   switch(_event->key())
00496   {
00497     case Qt::Key_Shift: shiftPressed_ = false; break;
00498     default : _event->ignore();
00499   }
00500 }
00501 
00502 
00503 //-----------------------------------------------------------------------------
00504 
00505 
00506 void 
00507 QtSceneGraphWidget::
00508 slotNodeChanged(ACG::SceneGraph::BaseNode* _node)
00509 {
00510   emit signalNodeChanged(_node);
00511 }
00512 
00513 
00514 //=============================================================================
00515 
00516 
00517 
00518 
00519 QtSceneGraphWidget::Item::Item( QTreeWidget * _parent,
00520                                 SceneGraph::BaseNode* _node )
00521   : QTreeWidgetItem(_parent), node_(_node)
00522 { 
00523   update(); 
00524 }
00525 
00526 
00527 //-----------------------------------------------------------------------------
00528 
00529 
00530 QtSceneGraphWidget::Item::Item( Item * _parent,
00531                                 SceneGraph::BaseNode* _node )
00532   : QTreeWidgetItem(_parent), node_(_node)
00533 { 
00534   update(); 
00535 }
00536 
00537 
00538 //-----------------------------------------------------------------------------
00539 
00540 
00541 void
00542 QtSceneGraphWidget::Item::update()
00543 {
00544   setText( 0, node_->name().c_str());
00545   setText( 1, node_->className().c_str());
00546 
00547   switch (node_->status())
00548   {
00549     case BaseNode::Active:        setText( 2, "Active");       break;
00550     case BaseNode::HideNode:      setText( 2, "HideNode");     break;
00551     case BaseNode::HideChildren:  setText( 2, "HideChildren"); break;
00552     case BaseNode::HideSubtree:   setText( 2, "HideSubtree");  break;
00553   }
00554 
00555   setText( 3, SceneGraph::DrawModes::description(node_->drawMode()).c_str());
00556 }
00557 
00558 
00559 //-----------------------------------------------------------------------------
00560 
00561 
00562 QtSceneGraphDialog::
00563 QtSceneGraphDialog( QWidget* _parent,
00564                     SceneGraph::BaseNode* _rootNode )
00565   : QDialog(_parent)
00566 {
00567   setModal( false );
00568   QVBoxLayout* l = new QVBoxLayout( this );
00569   
00570   sgw_ = 
00571     new QtSceneGraphWidget( this, _rootNode );
00572 
00573   l->addWidget(sgw_);
00574 
00575   connect( sgw_, 
00576            SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
00577            this, 
00578            SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)) );
00579 }
00580 
00581 
00582 //-----------------------------------------------------------------------------
00583 
00584 
00585 void
00586 QtSceneGraphDialog::
00587 slotNodeChanged(ACG::SceneGraph::BaseNode* _node)
00588 {
00589   emit(signalNodeChanged(_node));
00590 }
00591 
00592 
00593 //-----------------------------------------------------------------------------
00594 
00595 
00596 void
00597 QtSceneGraphDialog::
00598 update(ACG::SceneGraph::BaseNode* _rootNode)
00599 {
00600   sgw_->update(_rootNode);
00601 }
00602 
00603 
00604 //=============================================================================
00605 } // namespace QtWidgets
00606 } // namespace ACG
00607 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .