ContextMenu.cc 36.9 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
Jan Möbius's avatar
Jan Möbius committed
4
*      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen       *
Jan Möbius's avatar
Jan Möbius committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
*                           www.openflipper.org                              *
*                                                                            *
*--------------------------------------------------------------------------- *
*  This file is part of OpenFlipper.                                         *
*                                                                            *
*  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 with the               *
*  following exceptions:                                                     *
*                                                                            *
*  If other files instantiate templates or use macros                        *
*  or inline functions from this file, or you compile this file and          *
*  link it with other files to produce an executable, this file does         *
*  not by itself cause the resulting executable to be covered by the         *
*  GNU Lesser General Public License. This exception does not however        *
*  invalidate any other reasons why the executable file might be             *
*  covered by the GNU Lesser General Public License.                         *
*                                                                            *
*  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 LesserGeneral Public           *
*  License along with OpenFlipper. If not,                                   *
*  see <http://www.gnu.org/licenses/>.                                       *
*                                                                            *
33
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
34

35
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
36 37 38 39 40
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
41
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58



//=============================================================================
//
//  CLASS CoreWidget - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================

// -------------------- mview
#include "CoreWidget.hh"

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <OpenFlipper/common/GlobalOptions.hh>
59
#include "../../common/GlobalOptions.hh"
60
#include <OpenFlipper/common/RendererInfo.hh>
Jan Möbius's avatar
 
Jan Möbius committed
61

Jan Möbius's avatar
Jan Möbius committed
62
//== IMPLEMENTATION ==========================================================
63
#include <ACG/Scenegraph/CoordsysNode.hh>
Jan Möbius's avatar
 
Jan Möbius committed
64 65

void CoreWidget::slotCustomContextMenu( const QPoint& _point ) {
Jan Möbius's avatar
Jan Möbius committed
66

Jan Möbius's avatar
Jan Möbius committed
67
  QPoint   popupPosition;
Jan Möbius's avatar
Jan Möbius committed
68
  QPoint   scenePos;
Jan Möbius's avatar
Jan Möbius committed
69

Jan Möbius's avatar
Jan Möbius committed
70 71 72 73
  // Calculate popup position. Use the position from the viewer which was clicked on.
  popupPosition =  examiner_widgets_[PluginFunctions::activeExaminer()]->glMapToGlobal(_point);
  QPointF f = examiner_widgets_[PluginFunctions::activeExaminer()]->mapToScene(QPointF(_point.x(), _point.y()));
  scenePos = QPoint (f.x(), f.y());
74

Jan Möbius's avatar
Jan Möbius committed
75
  // Call function to adapt the menu to the currently used contex.
76
  updatePopupMenu(scenePos);
Jan Möbius's avatar
Jan Möbius committed
77

Jan Möbius's avatar
Jan Möbius committed
78
  // If the menu is not correctly initialized, dont try to show it.
Jan Möbius's avatar
 
Jan Möbius committed
79
  if ( !contextMenu_->isEmpty () )
Jan Möbius's avatar
Jan Möbius committed
80
    contextMenu_->popup( popupPosition );
Jan Möbius's avatar
Jan Möbius committed
81

Jan Möbius's avatar
 
Jan Möbius committed
82 83
}

Marcel Campen's avatar
Marcel Campen committed
84 85 86 87
void CoreWidget::slotHideContextMenu() {
  contextMenu_->hide();
}

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/** \brief Update context Menu when an arbitrary node has been clicked on.
 *
 * This function is called when a node has been clicked on not belonging to an object.
 * This context menu will show all function relevant for the Node.
 *
 * @param _menu Pointer to the context Menu
 * @param _node node which has been clicked on.
 */
void CoreWidget::updatePopupMenuNode(QMenu* _menu , ACG::SceneGraph::BaseNode* _node) {

  QString nodeName = QString(_node->name().c_str());
  QAction* typeEntry = new QAction( nodeName ,_menu );
  _menu->addAction( typeEntry );

  _menu->addSeparator();

  emit updateContextMenuNode(_node->id());

106
  addContextMenus( _menu , CONTEXTNODEMENU, _node->id() ) ;
107 108
}

Jan Möbius's avatar
Jan Möbius committed
109
/** \brief Update context Menu when Coordsys node has been clicked on.
110
 *
Jan Möbius's avatar
Jan Möbius committed
111 112 113
 * This function is called when the coordinate system in a viewer has been clicked on.
 * This context menu will show all function relevant for the current view like the
 * projection/viewing direction...
114
 *
Jan Möbius's avatar
Jan Möbius committed
115 116 117
 * @param _menu Pointer to the context Menu
 * @param _part id of the coordsys part which has been clicked on.
 */
Jan Möbius's avatar
Jan Möbius committed
118
void CoreWidget::updatePopupMenuCoordsysNode(QMenu* _menu  , const int /*_part*/) {
119 120 121
    
  QString iconPath = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
  
122
  QAction* typeEntry = new QAction(tr("Viewer Settings"),_menu);
Jan Möbius's avatar
Jan Möbius committed
123
  _menu->addAction( typeEntry );
124
  typeEntry->setDisabled(true);
125
  _menu->addSeparator();
126 127 128 129 130 131 132 133 134 135 136
  
  QAction* orthogonalCoordsys = 0;
  if ( getCoordsysProjection() == ACG::SceneGraph::CoordsysNode::PERSPECTIVE_PROJECTION ) {
    orthogonalCoordsys = new QAction( tr("Switch to Orthogonal coordinate system"), _menu );
    orthogonalCoordsys->setIcon( QIcon(iconPath+"orthogonal.png") );
  } else {
    orthogonalCoordsys = new QAction( tr("Switch to Perspective coordinate system"), _menu );
    orthogonalCoordsys->setIcon( QIcon(iconPath+"perspective.png") );
  }
  connect( orthogonalCoordsys,SIGNAL( triggered() ), this, SLOT( slotContextSwitchCoordsysProjection() ) );
  _menu->addAction(orthogonalCoordsys);
137

Jan Möbius's avatar
Jan Möbius committed
138
  //====================================================================================================
139 140 141
  // DrawModes
  //====================================================================================================
  slotUpdateViewerDrawMenu();
142 143
  if (! viewerDrawMenu_->isEmpty())
    _menu->addMenu( viewerDrawMenu_ );
144

145 146 147
  //====================================================================================================
  // RenderingOptions
  //====================================================================================================
148
  
149
  QMenu* renderingOptionsMenu = new QMenu(tr("Rendering Options"),_menu);
150
  renderingOptionsMenu->setIcon( QIcon(iconPath+"core_renderingOptions.png") );
151
  _menu->addMenu(renderingOptionsMenu);
152

153 154
  QAction* projectionAction = 0;
  if ( examiner_widgets_[PluginFunctions::activeExaminer() ]->projectionMode() == glViewer::PERSPECTIVE_PROJECTION ) {
155
    projectionAction = new QAction( tr("Switch to Orthogonal Projection"), renderingOptionsMenu );
156
    projectionAction->setIcon( QIcon(iconPath+"orthogonal.png") );
157
    projectionAction->setToolTip(   tr("Switch to perspective orthogonal mode."));
158
  } else {
159
    projectionAction = new QAction( tr("Switch to Perspective Projection"), renderingOptionsMenu );
160
    projectionAction->setIcon( QIcon(iconPath+"perspective.png") );
161
    projectionAction->setToolTip(   tr("Switch to perspective projection mode."));
162
  }
163

164
  projectionAction->setCheckable( false );
165 166 167
  projectionAction->setToolTip(   tr("Switch between <b>perspective</b> and "
      "<b>parrallel</b> projection mode."));
  projectionAction->setWhatsThis( tr("Switch projection modes<br><br>"
168
      "Switch between <b>perspective</b> and "
169
      "<b>parrallel</b> projection mode."));
170 171
  connect( projectionAction,SIGNAL( triggered() ), this, SLOT( slotContextSwitchProjection() ) );
  renderingOptionsMenu->addAction( projectionAction );
172 173


174
  QAction* animation = renderingOptionsMenu->addAction(tr("Animation"));
175

176
  animation->setToolTip(tr("Animate rotation of objects"));
177
  animation->setCheckable( true );
178
  animation->setIcon( QIcon(iconPath+"animation.png") );
179 180
  animation->setChecked( PluginFunctions::viewerProperties(PluginFunctions::activeExaminer()).animation() );
  connect(animation, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeAnimation(bool) ) );
181 182


183 184
  //====================================================================================================

185 186
  QAction* backfaceCulling = renderingOptionsMenu->addAction(tr("Backface Culling"));
  backfaceCulling->setToolTip(tr("Enable backface culling"));
187
  backfaceCulling->setCheckable( true );
188
  backfaceCulling->setIcon( QIcon(iconPath+"backFaceCulling.png") );
189 190 191 192 193
  backfaceCulling->setChecked( PluginFunctions::viewerProperties().backFaceCulling() );
  connect(backfaceCulling, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeBackFaceCulling(bool) ) );

  //====================================================================================================

194 195
  QAction* twoSidedLighting = renderingOptionsMenu->addAction(tr("Two-sided Lighting"));
  twoSidedLighting->setToolTip(tr("Enable two-sided lighting"));
196
  twoSidedLighting->setCheckable( true );
197
  twoSidedLighting->setIcon( QIcon(iconPath+"twosidedLighting.png") );
198 199
  twoSidedLighting->setChecked( PluginFunctions::viewerProperties().twoSidedLighting() );
  connect(twoSidedLighting, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeTwoSidedLighting(bool) ) );
200 201 202
  
  //====================================================================================================

203 204
  QAction* multisampling = renderingOptionsMenu->addAction(tr("Multisampling"));
  multisampling->setToolTip(tr("Enable Multisampling"));
205
  multisampling->setCheckable( true );
206
  multisampling->setIcon( QIcon(iconPath+"multiSampling.png") );
207
  multisampling->setChecked( PluginFunctions::viewerProperties().multisampling() );
Mike Kremer's avatar
Mike Kremer committed
208 209 210 211 212 213 214
  connect(multisampling, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeMultisampling(bool) ) );
  
  //====================================================================================================

  QAction* mipmapping = renderingOptionsMenu->addAction(tr("Mipmapping"));
  mipmapping->setToolTip(tr("Enable Mipmapping"));
  mipmapping->setCheckable( true );
215
  mipmapping->setIcon( QIcon(iconPath+"mipmapping.png") );
Mike Kremer's avatar
Mike Kremer committed
216 217
  mipmapping->setChecked( PluginFunctions::viewerProperties().mipmapping() );
  connect(mipmapping, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeMipmapping(bool) ) );
218

Jan Möbius's avatar
Jan Möbius committed
219 220 221 222 223 224
  //============================================================================================================
  // Renderer Menu
  //============================================================================================================

  if ( renderManager().available() > 1 ) {
    QMenu* rendererMenu = new QMenu(tr("Renderers"),_menu);
225
    rendererMenu->setIcon(QIcon(iconPath+"renderers.png"));
Jan Möbius's avatar
Jan Möbius committed
226 227 228 229 230 231 232

    _menu->addMenu(rendererMenu);

    // Recreate actionGroup
    QActionGroup* groupRenderer = new QActionGroup( this );
    groupRenderer->setExclusive( true );

233 234 235 236 237 238 239

    // Get the options action for the currently active renderer
    if( renderManager()[ renderManager().activeId(PluginFunctions::activeExaminer() )]->optionsAction != 0 ) {
      rendererMenu->addAction(renderManager()[ renderManager().activeId(PluginFunctions::activeExaminer() ) ]->optionsAction );
      rendererMenu->addSeparator();
    }

Jan Möbius's avatar
Jan Möbius committed
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    for ( unsigned int i = 0 ; i < renderManager().available() ; ++i) {

      // Add a new Action with the renderer name
      QAction * action = new QAction( renderManager()[i]->name, groupRenderer );
      action->setCheckable( true );

      // Check if this processor is currently active
      if ( renderManager().activeId(PluginFunctions::activeExaminer() ) == i )
        action->setChecked(true);

      // Remember the id for the processor
      action->setData(QVariant(i));
    }

    // Add all new actions from the group to the menu
    rendererMenu->addActions( groupRenderer->actions() );

    // Connect signal of group to our managing slot
    connect( groupRenderer , SIGNAL( triggered( QAction * ) ),
        this               , SLOT( slotRenderMenu( QAction * ) ) );

  }

263 264 265 266
  //============================================================================================================
  // Post processor Menu
  //============================================================================================================

267
  if ( postProcessorManager().available() > 1 ) {
268
    QMenu* postProcessorMenu = new QMenu(tr("Post processors"),_menu);
269
    postProcessorMenu->setIcon(QIcon(iconPath+"postprocessors.png"));
270 271 272 273 274 275 276

    _menu->addMenu(postProcessorMenu);

    // Recreate actionGroup
    QActionGroup* groupPostProcessor = new QActionGroup( this );
    groupPostProcessor->setExclusive( true );

277 278 279 280
    // Get the options action for the currently active postprocessor
    if( postProcessorManager()[ postProcessorManager().activeId(PluginFunctions::activeExaminer() )]->optionsAction != 0 ) {
      postProcessorMenu->addAction(postProcessorManager()[ postProcessorManager().activeId(PluginFunctions::activeExaminer() ) ]->optionsAction );
    }
281

282 283 284 285 286 287
    QAction* showPostProcessorDialog = new QAction(tr("Show post processor manager"),this);

    connect(showPostProcessorDialog,SIGNAL(triggered()),this,SLOT(slotShowPostProcessorManager()));

    postProcessorMenu->addAction(showPostProcessorDialog);
    postProcessorMenu->addSeparator();
288 289 290


    // Now add the processor chooser
291 292 293 294 295 296 297
    for ( unsigned int i = 0 ; i < postProcessorManager().available() ; ++i) {

      // Add a new Action with the postprocessors name
      QAction * action = new QAction( postProcessorManager()[i]->name, groupPostProcessor );
      action->setCheckable( true );

      // Check if this processor is currently active
Jan Möbius's avatar
Jan Möbius committed
298
      if ( postProcessorManager().activeId(PluginFunctions::activeExaminer() ) == i )
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
        action->setChecked(true);

      // Remember the id for the processor
      action->setData(QVariant(i));
    }

    // Add all new actions from the group to the menu
    postProcessorMenu->addActions( groupPostProcessor->actions() );

    // Connect signal of group to our managing slot
    connect( groupPostProcessor , SIGNAL( triggered( QAction * ) ),
             this               , SLOT( slotPostProcessorMenu( QAction * ) ) );

  }

314 315 316 317 318 319

  //============================================================================================================
  // Viewing Direction Menu
  //============================================================================================================

  QMenu* viewingDirectionMenu = new QMenu( tr("Viewing Direction"), _menu);
320
  viewingDirectionMenu->setIcon(QIcon(iconPath+"core_viewingDirection.png"));
321 322 323 324 325 326 327
  _menu->addMenu(viewingDirectionMenu);

  QActionGroup* dirGroup = new QActionGroup(this);

  QAction* viewAction;
  // freeView
  viewAction = new QAction( tr("Free View"), viewingDirectionMenu );
328
  viewAction->setIcon( QIcon(iconPath+"orthogonal.png") );
329 330 331 332 333 334 335 336
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_FREE );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_FREE );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  viewingDirectionMenu->addSeparator();
  // TOP
  viewAction = new QAction( tr("Top View"), viewingDirectionMenu );
337
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_top.png") );
338 339 340 341 342 343 344
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_TOP );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_TOP );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  // BOTTOM
  viewAction = new QAction( tr("Bottom View"), viewingDirectionMenu );
345
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_bottom.png") );
346 347 348 349 350 351 352
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_BOTTOM );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_BOTTOM );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  // LEFT
  viewAction = new QAction( tr("Left View"), viewingDirectionMenu );
353
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_left.png") );
354 355 356 357 358 359 360
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_LEFT );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_LEFT );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  // RIGHT
  viewAction = new QAction( tr("Right View"), viewingDirectionMenu );
361
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_right.png") );
362 363 364 365 366 367 368
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_RIGHT );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_RIGHT );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  // FRONT
  viewAction = new QAction( tr("Front View"), viewingDirectionMenu );
369
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_front.png") );
370 371 372 373 374 375 376
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_FRONT );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_FRONT );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
  // BACK
  viewAction = new QAction( tr("Back View"), viewingDirectionMenu );
377
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_back.png") );
378 379 380 381 382
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_BACK );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_BACK );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
383 384
  
  viewingDirectionMenu->addSeparator();
385 386

  connect( dirGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSetViewingDirection(QAction*) ) );
387 388 389 390 391 392
  
  //===========================================================================
  // Check box to determine whether rotation should be locked or not
  
  QAction* lockAction = viewingDirectionMenu->addAction("Lock rotation");
  lockAction->setCheckable( true );
393
  lockAction->setIcon( QIcon(iconPath+"lock_rotation.png") );
394 395 396 397 398 399
  lockAction->setToolTip(tr("Lock rotation in current examiner"));
  lockAction->setChecked( PluginFunctions::viewerProperties().rotationLocked() );
  viewingDirectionMenu->addAction( lockAction );
  
  connect( lockAction, SIGNAL(triggered(bool)), this, SLOT(slotLockRotation(bool) ) );
  
400 401 402
  //====================================================================================================
  // Other Toplevel Action
  //====================================================================================================
403

404
  _menu->addSeparator();
405

406
  //====================================================================================================
407

408
  QAction* homeAction = new QAction(tr("Restore home view"),_menu);
409
  homeAction->setIcon( QIcon(iconPath+"go-home.png") );
410
  homeAction->setCheckable( false );
411 412 413
  homeAction->setToolTip(tr("Restore <b>home</b> view."));
  homeAction->setWhatsThis( tr("Restore home view<br><br>"
                            "Resets the view to the home view"));
414 415
  _menu->addAction( homeAction );
  connect( homeAction,SIGNAL( triggered() ), this, SLOT( slotContextHomeView() ) );
416

417
  QAction* setHomeAction = new QAction( tr("Set Home View") , _menu );
418
  setHomeAction->setIcon( QIcon(iconPath+"set-home.png") );
419
  setHomeAction->setCheckable( false );
420 421 422
  setHomeAction->setToolTip(tr("Set <b>home</b> view"));
  setHomeAction->setWhatsThis( tr("Store home view<br><br>"
                               "Stores the current view as the home view"));
423
  _menu->addAction( setHomeAction);
424 425
  connect( setHomeAction,SIGNAL( triggered() ), this, SLOT( slotContextSetHomeView() ) );

426
  QAction* viewAllAction = new QAction( tr("View all"), _menu );
427
  viewAllAction->setIcon( QIcon(iconPath+"viewall.png") );
428
  viewAllAction->setCheckable( false );
429 430 431 432
  viewAllAction->setToolTip(tr("View all."));
  viewAllAction->setWhatsThis( tr("View all<br><br>"
                                  "Move the objects in the scene so that"
                                  " the whole scene is visible."));
433 434
  connect( viewAllAction,SIGNAL( triggered() ), this, SLOT( slotContextViewAll() ) );
  _menu->addAction( viewAllAction);
435 436


437
  _menu->addSeparator();
438

439
  //====================================================================================================
440

441
  QAction* copyView = _menu->addAction(tr("Copy View"));
442
  copyView->setToolTip(tr("Copy current view, window size and toolbar size to clipboard"));
443
  copyView->setIcon( QIcon(iconPath+"edit-copy.png") );
444 445 446 447
  connect(copyView, SIGNAL(triggered()), this, SLOT(slotCopyView()) );

  //====================================================================================================

448 449
  QAction* pasteView = _menu->addAction(tr("Paste View"));
  pasteView->setToolTip(tr("Paste current view from clipboard"));
450
  pasteView->setIcon( QIcon(iconPath+"edit-paste.png") );
451
  connect(pasteView, SIGNAL(triggered()), this , SLOT( slotPasteView( ) ) );
452

453
  //====================================================================================================
454

455 456 457 458 459 460 461
  QAction* pasteViewAndWindow = _menu->addAction(tr("Paste View and Window Size"));
  pasteViewAndWindow->setToolTip(tr("Paste current view, window size and the toolbox size from clipboard"));
  pasteViewAndWindow->setIcon( QIcon(iconPath+"edit-paste.png") );
  connect(pasteViewAndWindow, SIGNAL(triggered()), this , SLOT( slotPasteViewAndWindow( ) ) );

  //====================================================================================================

462 463
  QAction* snapshot_examiner = _menu->addAction(tr("Examiner Snapshot"));
  snapshot_examiner->setToolTip(tr("Take a snapshot of the current examiner"));
464
  snapshot_examiner->setIcon( QIcon(iconPath+"snapshot.png") );
465 466 467 468 469 470
  connect(snapshot_examiner, SIGNAL(triggered()), this, SLOT( slotExaminerSnapshot() ) );
  
  //====================================================================================================
  
  QAction* snapshot_viewer = _menu->addAction(tr("Viewer Snapshot"));
  snapshot_viewer->setToolTip(tr("Take a snapshot of the whole viewer"));
471
  snapshot_viewer->setIcon( QIcon(iconPath+"snapshot.png") );
472
  connect(snapshot_viewer, SIGNAL(triggered()), this, SLOT( viewerSnapshotDialog() ) );
473

474 475
}

Jan Möbius's avatar
Jan Möbius committed
476
/** \brief Update context Menu when background has been clicked on.
477
 *
Jan Möbius's avatar
Jan Möbius committed
478
 * This function is called when the background in a viewer has been clicked on.
479
 * This context menu will show functions which are related to the background of the
Jan Möbius's avatar
Jan Möbius committed
480
 * viewer.
481
 *
Jan Möbius's avatar
Jan Möbius committed
482 483 484
 * @param _menu Pointer to the context Menu
 * @param _point position in the viewer where the user clicked.
 */
Jan Möbius's avatar
Jan Möbius committed
485
void CoreWidget::updatePopupMenuBackground(QMenu* _menu , const QPoint& /*_point*/) {
486

487 488 489 490 491 492 493
  //====================================================================================================
  // DrawModes
  //====================================================================================================
  slotUpdateViewerDrawMenu();
  _menu->addMenu( viewerDrawMenu_ );

  _menu->addSeparator();
494
  
495 496
  QAction* action = _menu->addAction(tr("Set Background Color"));
  action->setToolTip(tr("Set the background color for the current viewer"));
Jan Möbius's avatar
Jan Möbius committed
497
  action->setStatusTip(tr("Set the background color for the current viewer"));
498
  action->setWhatsThis(tr("Set the background color for the current viewer"));
499
  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"BackgroundColor.png") );
500
  connect(action, SIGNAL(triggered()), this, SLOT(slotSetContextBackgroundColor()) );
501

502
  /*
Mike Kremer's avatar
Mike Kremer committed
503
   * Show coordsys context menu of coordsys if
504 505 506 507 508 509 510
   * invisible...
   */

  ACG::SceneGraph::BaseNode* root = PluginFunctions::getSceneGraphRootNode();
  ACG::SceneGraph::BaseNode* coordSys = root->find("Core Coordsys Node");

  if(!coordSys->visible()) {
511 512

	  if(!coordSysMenu_) {
513
		  coordSysMenu_ = new QMenu(tr("Viewer Settings"), _menu);
514 515
		  updatePopupMenuCoordsysNode(coordSysMenu_, 0);
	  }
516
	  _menu->addSeparator();
517
	  _menu->addMenu(coordSysMenu_);
518 519
  }

520 521 522 523 524
  // Tell Plugins to update their context Menu
  emit updateContextMenuBackground();

  addContextMenus( _menu , CONTEXTBACKGROUNDMENU ) ;

Jan Möbius's avatar
Jan Möbius committed
525
}
Jan Möbius's avatar
Jan Möbius committed
526

Jan Möbius's avatar
Jan Möbius committed
527
/** \brief Update popup Menu when an object has been clicked on.
528
 *
Jan Möbius's avatar
Jan Möbius committed
529 530
 * This function is called when an object has been clicked on.
 * This context menu will show all properties for the given object.
531
 *
Jan Möbius's avatar
Jan Möbius committed
532
 * @param _menu Pointer to the context Menu
Jan Möbius's avatar
Jan Möbius committed
533
 * @param _object Object that has been clicked on.
Jan Möbius's avatar
Jan Möbius committed
534
 */
535 536 537
void CoreWidget::updatePopupMenuObject(QMenu* _menu , BaseObjectData* _object ) {

  QAction* typeEntry = new QAction( typeName(_object->dataType()) ,_menu);
538
  typeEntry->setIcon(typeIcon(_object->dataType()));
539 540 541 542 543 544 545 546 547 548 549
  _menu->addAction( typeEntry );

  _menu->addSeparator( );

  // Tell Plugins to update their context Menu
  emit updateContextMenu(_object->id() );

  if ( addContextMenus( _menu , CONTEXTOBJECTMENU , _object->id() ) )
    _menu->addSeparator();

  // Add picking Menu
550
  if (pickMenu_ != 0 && pickMenu_->actions().size() > 0) {
551
    pickMenu_->setTitle(tr("&Picking"));
552 553
    contextMenu_->addMenu( pickMenu_ );
    pickMenu_->setTearOffEnabled(true);
554 555 556 557 558 559 560
  }
}

bool CoreWidget::addContextMenus( QMenu* _menu , ContextMenuType _type , int _id ) {

  bool added = false;

561 562 563
  QMap< QString , QAction* > menuMap; //QMap sorts by key
  QMap< QString , QAction* > actionMap;

564 565 566 567 568 569 570 571 572 573 574 575
  // Add context menus from plugins
  for ( uint i = 0 ; i < contextMenus_.size(); ++i ) {

    if ( contextMenus_[i].type != _type )
      continue;

    switch (contextMenus_[i].type) {
      case CONTEXTBACKGROUNDMENU:
        break;
      case CONTEXTOBJECTMENU:
        BaseObjectData* object;
        if ( !PluginFunctions::getObject(_id, object) ) {
576
          emit log(LOGERR,tr("Cant get object for objectContextMenu"));
577 578 579 580 581 582 583 584 585 586 587 588 589
          continue;
        }

        // Datatype does not match
        if ( ! object->dataType(  contextMenus_[i].contextType ) )
          continue;

        break;
      case CONTEXTNODEMENU:
        break;

    }

590 591 592 593 594 595
    QMenu* menu = contextMenus_[i].action->menu();

    if (menu == 0) //is it a menu
      actionMap[ contextMenus_[i].action->text() ] = contextMenus_[i].action;
    else
      menuMap[ contextMenus_[i].action->text() ] = contextMenus_[i].action;
596 597 598 599 600

    added = true;

    // Get all Actions in the menu and its submenus.
    // Set their data to the picked Object id
601

Jan Möbius's avatar
 
Jan Möbius committed
602 603 604 605 606 607 608 609

    QList< QAction *> allActions;
    if ( menu == 0) {
      allActions.push_back(contextMenus_[i].action);
    } else {
      allActions = menu->actions();
    }

610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    while ( !allActions.empty() ) {
      QList< QAction *> tmpList;

      // Set userdata of all actions to the picked Object Id
      for ( int j = 0 ; j < allActions.size(); ++j ) {
        allActions[j]->setData( QVariant( _id ) );
        if ( allActions[j]->menu() != 0 )
          tmpList << allActions[j]->menu()->actions();
      }

      allActions = tmpList;
    }

  }

Jan Möbius's avatar
Marlin:  
Jan Möbius committed
625 626 627 628 629 630 631 632
  //find the currently selected view mode
  int id = -1;
  for (int i=0; i<viewModes_.size(); i++) {
    if (viewModes_[i]->name == OpenFlipper::Options::currentViewMode()) {
      id = i;
      break;
    }
  }
633 634 635 636 637 638

  // Default to mode all (0) if not found
  if ( id == -1 ) {
    emit log(LOGERR, tr("Unable to find view mode %1.").arg(OpenFlipper::Options::currentViewMode()) );
    id = 0;
  }
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
639 640
  
  /// \todo Sort the menu entries by the order given in visibleContextMenus
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
641
  
642 643
  //first add all menus
  QMapIterator<QString, QAction*> it(menuMap);
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
644 645
  
  QStringList visible = viewModes_[id]->visibleContextMenus;
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
646 647 648 649
  if (visible.contains("ALL_THAT_EXIST")) {
    //this plugin adds all context menus, no special configuration so far.
    visible = viewModes_[0]->visibleContextMenus;
  }
650 651

  // Remove Plugin Name from string
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
652
  visible.replaceInStrings(QRegExp(".*>"), "");
653

654 655 656
  // Remove accelerator specifications
  visible.replaceInStrings("&", "");

657
  while (it.hasNext()) {
658 659 660 661 662 663 664
    it.next();

	for ( int i = 0 ; i < visible.size(); ++i ) {
	  if ( it.key().contains(visible[i]) ) {
	    _menu->addAction( it.value() );
	  }
    }
665 666 667 668 669 670
  }

  _menu->addSeparator();

  //then all actions
  QMapIterator<QString, QAction*> it2(actionMap);
671

672 673
  while (it2.hasNext()) {
     it2.next();
674 675 676 677 678 679

	 for ( int i = 0 ; i < visible.size(); ++i ) {
		 if ( it2.key().contains(visible[i]) ) {
	       _menu->addAction( it2.value() );
		 }
	 }
680 681 682
  }

  return added;
Jan Möbius's avatar
Jan Möbius committed
683
}
Jan Möbius's avatar
Jan Möbius committed
684 685


686
 
687 688 689
/** \brief check current context and initialize context menu according to this context.
 *
 * This function is called whenever a context menu for the corewidget is requested.
Jan Möbius's avatar
Jan Möbius committed
690 691 692 693
 * It will decide about the current context, collect all menus for plugins and
 * construct the final context menu.
 */
void CoreWidget::updatePopupMenu(const QPoint& _point) {
Jan Möbius's avatar
Jan Möbius committed
694

Jan Möbius's avatar
Jan Möbius committed
695 696
  // Clear the complete context menu.
  contextMenu_->clear();
697

Jan Möbius's avatar
Jan Möbius committed
698 699
  // Clear the selection context menu part.
  contextSelectionMenu_->clear();
Jan Möbius's avatar
Jan Möbius committed
700

Jan Möbius's avatar
Jan Möbius committed
701 702 703
  // =============================================================================
  // First do a picking on the current position to check which context we are in.
  // =============================================================================
704

Jan Möbius's avatar
Jan Möbius committed
705
  enum CONTEXTTYPE {
706
    COORDSYSCONTEXT ,BACKGROUNDCONTEXT ,OBJECTCONTEXT, NODECONTEXT
Jan Möbius's avatar
Jan Möbius committed
707
  } context = BACKGROUNDCONTEXT;
Jan Möbius's avatar
Jan Möbius committed
708

Jan Möbius's avatar
 
Jan Möbius committed
709
  // Do picking in the gl area to find an object
710 711
  unsigned int               node_idx, target_idx;
  ACG::Vec3d                 hit_point;
Jan Möbius's avatar
Jan Möbius committed
712 713
  BaseObjectData*            object = 0;
  ACG::SceneGraph::BaseNode* node   = 0;
714

715
  if (examiner_widgets_[PluginFunctions::activeExaminer()]->pick( ACG::SceneGraph::PICK_ANYTHING,_point,node_idx, target_idx, &hit_point ) ) {
716

Jan Möbius's avatar
Jan Möbius committed
717 718 719
    if ( PluginFunctions::getPickedObject(node_idx, object) ) {
      context  = OBJECTCONTEXT;
    } else {
720 721
      node = ACG::SceneGraph::find_node( PluginFunctions::getSceneGraphRootNode() , node_idx );
      if ( node != 0 && ( node->name() == "Core Coordsys Node") )
Jan Möbius's avatar
Jan Möbius committed
722
        context = COORDSYSCONTEXT;
723 724
      else
        context = NODECONTEXT;
725
    }
726 727
  }

Jan Möbius's avatar
Jan Möbius committed
728 729 730
  // =============================================================================
  // Depending on the context create the basic context menu.
  // =============================================================================
731

Jan Möbius's avatar
Jan Möbius committed
732
  QIcon icon;
733

Jan Möbius's avatar
Jan Möbius committed
734 735 736
  switch (context) {
    case BACKGROUNDCONTEXT:
      updatePopupMenuBackground(contextMenu_,_point);
737
      return;
Jan Möbius's avatar
Jan Möbius committed
738 739
      break;
    case OBJECTCONTEXT:
740
      updatePopupMenuObject(contextMenu_ , object );
741
      return;
Jan Möbius's avatar
Jan Möbius committed
742 743 744
      break;
    case COORDSYSCONTEXT:
      updatePopupMenuCoordsysNode(contextMenu_,target_idx);
745
      return;
Jan Möbius's avatar
Jan Möbius committed
746
      break;
747 748 749 750
    case NODECONTEXT:
      updatePopupMenuNode(contextMenu_,node);
      return;
      break;
Jan Möbius's avatar
 
Jan Möbius committed
751
  }
Jan Möbius's avatar
Jan Möbius committed
752

Jan Möbius's avatar
 
Jan Möbius committed
753 754
}

755

756 757
void CoreWidget::slotSnapshotName() {
  std::cerr << "Todo : slotSnapShotName only sets name for current viewer" << std::endl;
758 759 760 761

  QString fname = PluginFunctions::viewerProperties().snapshotName();

  fname.replace('%', '$');
Jan Möbius's avatar
Jan Möbius committed
762 763 764 765
  fname = QFileDialog::getSaveFileName ( 0,
                                         tr("Save snapshot name"),
                                         OpenFlipperSettings().value("Core/CurrentDir").toString());

766 767 768 769
  if (!fname.isEmpty())
  {
    fname.replace('$', '%');

Jan Möbius's avatar
Jan Möbius committed
770 771 772 773 774

    // Get the chosen directory and remember it.
    QFileInfo fileInfo(fname);
    OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );

775
    PluginFunctions::viewerProperties().snapshotBaseFileName(fname);
776
    QString msg=tr("next snapshot: ");
777 778 779
    statusBar()->showMessage(msg);
  }

780 781
}

Jan Möbius's avatar
 
Jan Möbius committed
782
void CoreWidget::slotAddContextItem(QAction* _entry, ContextMenuType _type) {
Jan Möbius's avatar
 
Jan Möbius committed
783
  MenuInfo info;
Jan Möbius's avatar
 
Jan Möbius committed
784 785
  info.action = _entry;
  info.type   = _type;
Jan Möbius's avatar
Jan Möbius committed
786

Jan Möbius's avatar
Marlin:  
Jan Möbius committed
787 788
  contextMenus_.push_back(info); 
  slotAddContextItemToViewMode(_entry);
Jan Möbius's avatar
 
Jan Möbius committed
789 790
}

Jan Möbius's avatar
 
Jan Möbius committed
791
void CoreWidget::slotAddContextItem( QAction* _entry , DataType _dataType ,ContextMenuType _type ) {
Jan Möbius's avatar
 
Jan Möbius committed
792
  MenuInfo info;
Jan Möbius's avatar
 
Jan Möbius committed
793
  info.action      = _entry;
Jan Möbius's avatar
 
Jan Möbius committed
794
  info.contextType = _dataType;
Jan Möbius's avatar
 
Jan Möbius committed
795
  info.type        = _type;
Jan Möbius's avatar
Jan Möbius committed
796

Jan Möbius's avatar
 
Jan Möbius committed
797
  contextMenus_.push_back(info);
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
  slotAddContextItemToViewMode(_entry);
}

void CoreWidget::slotAddContextItemToViewMode( QAction* _entry ) {
  int id = -1;
  // Find the plugin which added this Context Menu
  for ( uint i = 0 ; i < plugins_.size(); ++i ) {
    if ( plugins_[i].plugin == sender() ) {
      id = i;
      break;
    }
  }

  // Find the scripting plugin because we assign this context menu to it as we did not find the original sender
  if ( id == -1 ) {
    for ( uint i = 0 ; i < plugins_.size(); ++i ) {
      if ( plugins_[i].name == "Scripting" ) {
        id = i;
        break;
      }
    }


    if ( id == -1 ) {
      std::cerr << "Unknown sender plugin when adding Context Menu!" << std::endl;
      return;
    }
  }

  plugins_[id].contextMenus.push_back( std::pair< QString,QAction* >( plugins_[id].name + "->" + _entry->text(), _entry) );

  // add widget name to viewMode 'all'
  if ( !viewModes_[0]->visibleContextMenus.contains(plugins_[id].name + "->" + _entry->text()) ){
    viewModes_[0]->visibleContextMenus << plugins_[id].name + "->" + _entry->text();
    viewModes_[0]->visibleContextMenus.sort();
  }

  setViewMode( OpenFlipper::Options::currentViewMode() );
Jan Möbius's avatar
 
Jan Möbius committed
836 837
}

838 839
void CoreWidget::slotUpdateViewerDrawMenu() {
  if ( drawGroupViewer_ ) {
840

841 842 843 844
    disconnect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
                this             , SLOT( slotViewerDrawMenu( QAction * ) ) );
    delete( drawGroupViewer_ );
    drawGroupViewer_ = 0;
845

846
  }
847

848 849 850
  // Recreate drawGroup
  drawGroupViewer_ = new QActionGroup( this );
  drawGroupViewer_->setExclusive( false );
851

852
  connect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
853 854
           this       , SLOT( slotViewerDrawMenu( QAction * ) ) );

855
  if ( !viewerDrawMenu_ ) {
856

857 858
    QIcon icon;
    icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
859
    viewerDrawMenu_  = new QMenu(tr("Set Draw Mode"));
860 861
    viewerDrawMenu_->setTearOffEnabled(true);
    viewerDrawMenu_->setIcon(icon);
862

863 864
    connect(viewerDrawMenu_,SIGNAL(aboutToShow () ) , this, SLOT(slotUpdateGlobalDrawMenu() ) );
  }
865

866 867
  // Collect available draw modes
  // Single pass action, draw modes independent from multipass rendering
868 869 870
  ACG::SceneGraph::CollectDrawModesAction actionAvailable;
  ACG::SceneGraph::traverse( PluginFunctions::getRootNode() , actionAvailable);
  availableGlobalDrawModes_ = actionAvailable.drawModes();
871

872 873
  // Get currently active drawModes (first viewer only )
  // TODO: create combination from all viewers!
Jan Möbius's avatar
Jan Möbius committed
874
  ACG::SceneGraph::DrawModes::DrawMode activeDrawModes = PluginFunctions::drawMode();
875

876
  // Convert to ids
Jan Möbius's avatar
Jan Möbius committed
877 878
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes() ;
879

880
  viewerDrawMenu_->clear();
881

882 883
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
884 885
    ACG::SceneGraph::DrawModes::DrawMode id    = availDrawModeIds[i];
    std::string  descr =  id.description();
886

Marcel Campen's avatar
Marcel Campen committed
887 888 889 890 891 892
    QCheckBox *checkBox = new QCheckBox(QString(descr.c_str()), viewerDrawMenu_);
    checkBox->setChecked(activeDrawModes.containsAtomicDrawMode(id));
    QWidgetAction *checkableAction = new QWidgetAction(drawGroupViewer_);
    checkableAction->setText(descr.c_str());
    checkableAction->setDefaultWidget(checkBox);
    connect(checkBox, SIGNAL(toggled(bool) ), checkableAction, SLOT(trigger() ) );
893 894 895 896 897 898 899
  }

  viewerDrawMenu_->addActions( drawGroupViewer_->actions() );

}

void CoreWidget::slotViewerDrawMenu(QAction * _action) {
900

901 902 903
  //======================================================================================
  // Get the mode toggled
  //======================================================================================
Jan Möbius's avatar
Jan Möbius committed
904 905 906
  ACG::SceneGraph::DrawModes::DrawMode mode = 0;
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes();
907 908
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
909
    QString descr = QString(  availDrawModeIds[i].description().c_str() );
910 911 912 913 914 915

    if ( descr == _action->text() ) {
      mode = availDrawModeIds[i];
      break;
    }
  }
916

917 918 919
  if ( qApp->keyboardModifiers() & Qt::ShiftModifier )
    PluginFunctions::viewerProperties().drawMode(  PluginFunctions::viewerProperties().drawMode() ^ mode );
  else
Marcel Campen's avatar
Marcel Campen committed
920 921
  {
    contextMenu_->hide();
922
    PluginFunctions::viewerProperties().drawMode(mode );
Marcel Campen's avatar
Marcel Campen committed
923
  }
924

925 926
}

927 928
void CoreWidget::slotPostProcessorMenu( QAction * _action)  {
  unsigned int mode = _action->data().toUInt();
Jan Möbius's avatar
Jan Möbius committed
929
  postProcessorManager().setActive(mode,PluginFunctions::activeExaminer());
930 931
}

Jan Möbius's avatar
Jan Möbius committed
932 933 934 935 936
void CoreWidget::slotRenderMenu( QAction * _action)  {
  unsigned int mode = _action->data().toUInt();
  renderManager().setActive(mode,PluginFunctions::activeExaminer());
}

Jan Möbius's avatar
 
Jan Möbius committed
937
//=============================================================================