ContextMenu.cc 37.3 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

    // 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 );
Jan Möbius's avatar
Jan Möbius committed
237

238 239
    }

Jan Möbius's avatar
Jan Möbius committed
240 241 242 243
    QAction* showRendererDialog = new QAction(tr("Show renderer manager"),this);
    connect(showRendererDialog,SIGNAL(triggered()),this,SLOT(slotShowRenderManager()));
    rendererMenu->addAction(showRendererDialog);

Jan Möbius's avatar
Jan Möbius committed
244 245 246 247
    QAction* showRendererObjectWidget = new QAction(tr("Show render objects"),this);
    connect(showRendererObjectWidget,SIGNAL(triggered()),this,SLOT(slotShowRenderObjectWidget()));
    rendererMenu->addAction(showRendererObjectWidget);

Jan Möbius's avatar
Jan Möbius committed
248 249
    rendererMenu->addSeparator();

Jan Möbius's avatar
Jan Möbius committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    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 * ) ) );

  }

273 274 275 276
  //============================================================================================================
  // Post processor Menu
  //============================================================================================================

277
  if ( postProcessorManager().available() > 1 ) {
278
    QMenu* postProcessorMenu = new QMenu(tr("Post processors"),_menu);
279
    postProcessorMenu->setIcon(QIcon(iconPath+"postprocessors.png"));
280 281 282 283 284 285 286

    _menu->addMenu(postProcessorMenu);

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

287 288 289 290
    // 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 );
    }
291

292 293 294
    QAction* showPostProcessorDialog = new QAction(tr("Show post processor manager"),this);
    connect(showPostProcessorDialog,SIGNAL(triggered()),this,SLOT(slotShowPostProcessorManager()));
    postProcessorMenu->addAction(showPostProcessorDialog);
Jan Möbius's avatar
Jan Möbius committed
295

296
    postProcessorMenu->addSeparator();
297 298 299


    // Now add the processor chooser
300 301 302 303 304 305 306
    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
307
      if ( postProcessorManager().activeId(PluginFunctions::activeExaminer() ) == i )
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
        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 * ) ) );

  }

323 324 325 326 327 328

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

  QMenu* viewingDirectionMenu = new QMenu( tr("Viewing Direction"), _menu);
329
  viewingDirectionMenu->setIcon(QIcon(iconPath+"core_viewingDirection.png"));
330 331 332 333 334 335 336
  _menu->addMenu(viewingDirectionMenu);

  QActionGroup* dirGroup = new QActionGroup(this);

  QAction* viewAction;
  // freeView
  viewAction = new QAction( tr("Free View"), viewingDirectionMenu );
337
  viewAction->setIcon( QIcon(iconPath+"orthogonal.png") );
338 339 340 341 342 343 344 345
  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 );
346
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_top.png") );
347 348 349 350 351 352 353
  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 );
354
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_bottom.png") );
355 356 357 358 359 360 361
  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 );
362
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_left.png") );
363 364 365 366 367 368 369
  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 );
370
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_right.png") );
371 372 373 374 375 376 377
  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 );
378
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_front.png") );
379 380 381 382 383 384 385
  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 );
386
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_back.png") );
387 388 389 390 391
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_BACK );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_BACK );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
392 393
  
  viewingDirectionMenu->addSeparator();
394 395

  connect( dirGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSetViewingDirection(QAction*) ) );
396 397 398 399 400 401
  
  //===========================================================================
  // Check box to determine whether rotation should be locked or not
  
  QAction* lockAction = viewingDirectionMenu->addAction("Lock rotation");
  lockAction->setCheckable( true );
402
  lockAction->setIcon( QIcon(iconPath+"lock_rotation.png") );
403 404 405 406 407 408
  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) ) );
  
409 410 411
  //====================================================================================================
  // Other Toplevel Action
  //====================================================================================================
412

413
  _menu->addSeparator();
414

415
  //====================================================================================================
416

417
  QAction* homeAction = new QAction(tr("Restore home view"),_menu);
418
  homeAction->setIcon( QIcon(iconPath+"go-home.png") );
419
  homeAction->setCheckable( false );
420 421 422
  homeAction->setToolTip(tr("Restore <b>home</b> view."));
  homeAction->setWhatsThis( tr("Restore home view<br><br>"
                            "Resets the view to the home view"));
423 424
  _menu->addAction( homeAction );
  connect( homeAction,SIGNAL( triggered() ), this, SLOT( slotContextHomeView() ) );
425

426
  QAction* setHomeAction = new QAction( tr("Set Home View") , _menu );
427
  setHomeAction->setIcon( QIcon(iconPath+"set-home.png") );
428
  setHomeAction->setCheckable( false );
429 430 431
  setHomeAction->setToolTip(tr("Set <b>home</b> view"));
  setHomeAction->setWhatsThis( tr("Store home view<br><br>"
                               "Stores the current view as the home view"));
432
  _menu->addAction( setHomeAction);
433 434
  connect( setHomeAction,SIGNAL( triggered() ), this, SLOT( slotContextSetHomeView() ) );

435
  QAction* viewAllAction = new QAction( tr("View all"), _menu );
436
  viewAllAction->setIcon( QIcon(iconPath+"viewall.png") );
437
  viewAllAction->setCheckable( false );
438 439 440 441
  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."));
442 443
  connect( viewAllAction,SIGNAL( triggered() ), this, SLOT( slotContextViewAll() ) );
  _menu->addAction( viewAllAction);
444 445


446
  _menu->addSeparator();
447

448
  //====================================================================================================
449

450
  QAction* copyView = _menu->addAction(tr("Copy View"));
451
  copyView->setToolTip(tr("Copy current view, window size and toolbar size to clipboard"));
452
  copyView->setIcon( QIcon(iconPath+"edit-copy.png") );
453 454 455 456
  connect(copyView, SIGNAL(triggered()), this, SLOT(slotCopyView()) );

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

457 458
  QAction* pasteView = _menu->addAction(tr("Paste View"));
  pasteView->setToolTip(tr("Paste current view from clipboard"));
459
  pasteView->setIcon( QIcon(iconPath+"edit-paste.png") );
460
  connect(pasteView, SIGNAL(triggered()), this , SLOT( slotPasteView( ) ) );
461

462
  //====================================================================================================
463

464 465 466 467 468 469 470
  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( ) ) );

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

471 472
  QAction* snapshot_examiner = _menu->addAction(tr("Examiner Snapshot"));
  snapshot_examiner->setToolTip(tr("Take a snapshot of the current examiner"));
473
  snapshot_examiner->setIcon( QIcon(iconPath+"snapshot.png") );
474 475 476 477 478 479
  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"));
480
  snapshot_viewer->setIcon( QIcon(iconPath+"snapshot.png") );
481
  connect(snapshot_viewer, SIGNAL(triggered()), this, SLOT( viewerSnapshotDialog() ) );
482

483 484
}

Jan Möbius's avatar
Jan Möbius committed
485
/** \brief Update context Menu when background has been clicked on.
486
 *
Jan Möbius's avatar
Jan Möbius committed
487
 * This function is called when the background in a viewer has been clicked on.
488
 * This context menu will show functions which are related to the background of the
Jan Möbius's avatar
Jan Möbius committed
489
 * viewer.
490
 *
Jan Möbius's avatar
Jan Möbius committed
491 492 493
 * @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
494
void CoreWidget::updatePopupMenuBackground(QMenu* _menu , const QPoint& /*_point*/) {
495

496 497 498 499 500 501 502
  //====================================================================================================
  // DrawModes
  //====================================================================================================
  slotUpdateViewerDrawMenu();
  _menu->addMenu( viewerDrawMenu_ );

  _menu->addSeparator();
503
  
504 505
  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
506
  action->setStatusTip(tr("Set the background color for the current viewer"));
507
  action->setWhatsThis(tr("Set the background color for the current viewer"));
508
  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"BackgroundColor.png") );
509
  connect(action, SIGNAL(triggered()), this, SLOT(slotSetContextBackgroundColor()) );
510

511
  /*
Mike Kremer's avatar
Mike Kremer committed
512
   * Show coordsys context menu of coordsys if
513 514 515 516 517 518 519
   * invisible...
   */

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

  if(!coordSys->visible()) {
520 521

	  if(!coordSysMenu_) {
522
		  coordSysMenu_ = new QMenu(tr("Viewer Settings"), _menu);
523 524
		  updatePopupMenuCoordsysNode(coordSysMenu_, 0);
	  }
525
	  _menu->addSeparator();
526
	  _menu->addMenu(coordSysMenu_);
527 528
  }

529 530 531 532 533
  // Tell Plugins to update their context Menu
  emit updateContextMenuBackground();

  addContextMenus( _menu , CONTEXTBACKGROUNDMENU ) ;

Jan Möbius's avatar
Jan Möbius committed
534
}
Jan Möbius's avatar
Jan Möbius committed
535

Jan Möbius's avatar
Jan Möbius committed
536
/** \brief Update popup Menu when an object has been clicked on.
537
 *
Jan Möbius's avatar
Jan Möbius committed
538 539
 * This function is called when an object has been clicked on.
 * This context menu will show all properties for the given object.
540
 *
Jan Möbius's avatar
Jan Möbius committed
541
 * @param _menu Pointer to the context Menu
Jan Möbius's avatar
Jan Möbius committed
542
 * @param _object Object that has been clicked on.
Jan Möbius's avatar
Jan Möbius committed
543
 */
544 545 546
void CoreWidget::updatePopupMenuObject(QMenu* _menu , BaseObjectData* _object ) {

  QAction* typeEntry = new QAction( typeName(_object->dataType()) ,_menu);
547
  typeEntry->setIcon(typeIcon(_object->dataType()));
548 549 550 551 552 553 554 555 556 557 558
  _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
559
  if (pickMenu_ != 0 && pickMenu_->actions().size() > 0) {
560
    pickMenu_->setTitle(tr("&Picking"));
561 562
    contextMenu_->addMenu( pickMenu_ );
    pickMenu_->setTearOffEnabled(true);
563 564 565 566 567 568 569
  }
}

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

  bool added = false;

570 571 572
  QMap< QString , QAction* > menuMap; //QMap sorts by key
  QMap< QString , QAction* > actionMap;

573 574 575 576 577 578 579 580 581 582 583 584
  // 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) ) {
585
          emit log(LOGERR,tr("Cant get object for objectContextMenu"));
586 587 588 589 590 591 592 593 594 595 596 597 598
          continue;
        }

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

        break;
      case CONTEXTNODEMENU:
        break;

    }

599 600 601 602 603 604
    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;
605 606 607 608 609

    added = true;

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

Jan Möbius's avatar
 
Jan Möbius committed
611 612 613 614 615 616 617 618

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

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
    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
634 635 636 637 638 639 640 641
  //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;
    }
  }
642 643 644 645 646 647

  // 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
648 649
  
  /// \todo Sort the menu entries by the order given in visibleContextMenus
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
650
  
651 652
  //first add all menus
  QMapIterator<QString, QAction*> it(menuMap);
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
653 654
  
  QStringList visible = viewModes_[id]->visibleContextMenus;
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
655 656 657 658
  if (visible.contains("ALL_THAT_EXIST")) {
    //this plugin adds all context menus, no special configuration so far.
    visible = viewModes_[0]->visibleContextMenus;
  }
659 660

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

663 664 665
  // Remove accelerator specifications
  visible.replaceInStrings("&", "");

666
  while (it.hasNext()) {
667 668 669 670 671 672 673
    it.next();

	for ( int i = 0 ; i < visible.size(); ++i ) {
	  if ( it.key().contains(visible[i]) ) {
	    _menu->addAction( it.value() );
	  }
    }
674 675 676 677 678 679
  }

  _menu->addSeparator();

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

681 682
  while (it2.hasNext()) {
     it2.next();
683 684 685 686 687 688

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

  return added;
Jan Möbius's avatar
Jan Möbius committed
692
}
Jan Möbius's avatar
Jan Möbius committed
693 694


695
 
696 697 698
/** \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
699 700 701 702
 * 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
703

Jan Möbius's avatar
Jan Möbius committed
704 705
  // Clear the complete context menu.
  contextMenu_->clear();
706

Jan Möbius's avatar
Jan Möbius committed
707 708
  // Clear the selection context menu part.
  contextSelectionMenu_->clear();
Jan Möbius's avatar
Jan Möbius committed
709

Jan Möbius's avatar
Jan Möbius committed
710 711 712
  // =============================================================================
  // First do a picking on the current position to check which context we are in.
  // =============================================================================
713

Jan Möbius's avatar
Jan Möbius committed
714
  enum CONTEXTTYPE {
715
    COORDSYSCONTEXT ,BACKGROUNDCONTEXT ,OBJECTCONTEXT, NODECONTEXT
Jan Möbius's avatar
Jan Möbius committed
716
  } context = BACKGROUNDCONTEXT;
Jan Möbius's avatar
Jan Möbius committed
717

Jan Möbius's avatar
 
Jan Möbius committed
718
  // Do picking in the gl area to find an object
719 720
  unsigned int               node_idx, target_idx;
  ACG::Vec3d                 hit_point;
Jan Möbius's avatar
Jan Möbius committed
721 722
  BaseObjectData*            object = 0;
  ACG::SceneGraph::BaseNode* node   = 0;
723

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

Jan Möbius's avatar
Jan Möbius committed
726 727 728
    if ( PluginFunctions::getPickedObject(node_idx, object) ) {
      context  = OBJECTCONTEXT;
    } else {
729 730
      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
731
        context = COORDSYSCONTEXT;
732 733
      else
        context = NODECONTEXT;
734
    }
735 736
  }

Jan Möbius's avatar
Jan Möbius committed
737 738 739
  // =============================================================================
  // Depending on the context create the basic context menu.
  // =============================================================================
740

Jan Möbius's avatar
Jan Möbius committed
741
  QIcon icon;
742

Jan Möbius's avatar
Jan Möbius committed
743 744 745
  switch (context) {
    case BACKGROUNDCONTEXT:
      updatePopupMenuBackground(contextMenu_,_point);
746
      return;
Jan Möbius's avatar
Jan Möbius committed
747 748
      break;
    case OBJECTCONTEXT:
749
      updatePopupMenuObject(contextMenu_ , object );
750
      return;
Jan Möbius's avatar
Jan Möbius committed
751 752 753
      break;
    case COORDSYSCONTEXT:
      updatePopupMenuCoordsysNode(contextMenu_,target_idx);
754
      return;
Jan Möbius's avatar
Jan Möbius committed
755
      break;
756 757 758 759
    case NODECONTEXT:
      updatePopupMenuNode(contextMenu_,node);
      return;
      break;
Jan Möbius's avatar
 
Jan Möbius committed
760
  }
Jan Möbius's avatar
Jan Möbius committed
761

Jan Möbius's avatar
 
Jan Möbius committed
762 763
}

764

765 766
void CoreWidget::slotSnapshotName() {
  std::cerr << "Todo : slotSnapShotName only sets name for current viewer" << std::endl;
767 768 769 770

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

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

775 776 777 778
  if (!fname.isEmpty())
  {
    fname.replace('$', '%');

Jan Möbius's avatar
Jan Möbius committed
779 780 781 782 783

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

784
    PluginFunctions::viewerProperties().snapshotBaseFileName(fname);
785
    QString msg=tr("next snapshot: ");
786 787 788
    statusBar()->showMessage(msg);
  }

789 790
}

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

Jan Möbius's avatar
Marlin:  
Jan Möbius committed
796 797
  contextMenus_.push_back(info); 
  slotAddContextItemToViewMode(_entry);
Jan Möbius's avatar
 
Jan Möbius committed
798 799
}

Jan Möbius's avatar
 
Jan Möbius committed
800
void CoreWidget::slotAddContextItem( QAction* _entry , DataType _dataType ,ContextMenuType _type ) {
Jan Möbius's avatar
 
Jan Möbius committed
801
  MenuInfo info;
Jan Möbius's avatar
 
Jan Möbius committed
802
  info.action      = _entry;
Jan Möbius's avatar
 
Jan Möbius committed
803
  info.contextType = _dataType;
Jan Möbius's avatar
 
Jan Möbius committed
804
  info.type        = _type;
Jan Möbius's avatar
Jan Möbius committed
805

Jan Möbius's avatar
 
Jan Möbius committed
806
  contextMenus_.push_back(info);
Jan Möbius's avatar
Marlin:  
Jan Möbius committed
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 836 837 838 839 840 841 842 843 844
  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
845 846
}

847 848
void CoreWidget::slotUpdateViewerDrawMenu() {
  if ( drawGroupViewer_ ) {
849

850 851 852 853
    disconnect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
                this             , SLOT( slotViewerDrawMenu( QAction * ) ) );
    delete( drawGroupViewer_ );
    drawGroupViewer_ = 0;
854

855
  }
856

857 858 859
  // Recreate drawGroup
  drawGroupViewer_ = new QActionGroup( this );
  drawGroupViewer_->setExclusive( false );
860

861
  connect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
862 863
           this       , SLOT( slotViewerDrawMenu( QAction * ) ) );

864
  if ( !viewerDrawMenu_ ) {
865

866 867
    QIcon icon;
    icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
868
    viewerDrawMenu_  = new QMenu(tr("Set Draw Mode"));
869 870
    viewerDrawMenu_->setTearOffEnabled(true);
    viewerDrawMenu_->setIcon(icon);
871

872 873
    connect(viewerDrawMenu_,SIGNAL(aboutToShow () ) , this, SLOT(slotUpdateGlobalDrawMenu() ) );
  }
874

875 876
  // Collect available draw modes
  // Single pass action, draw modes independent from multipass rendering
877 878 879
  ACG::SceneGraph::CollectDrawModesAction actionAvailable;
  ACG::SceneGraph::traverse( PluginFunctions::getRootNode() , actionAvailable);
  availableGlobalDrawModes_ = actionAvailable.drawModes();
880

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

885
  // Convert to ids
Jan Möbius's avatar
Jan Möbius committed
886 887
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes() ;
888

889
  viewerDrawMenu_->clear();
890

891 892
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
893 894
    ACG::SceneGraph::DrawModes::DrawMode id    = availDrawModeIds[i];
    std::string  descr =  id.description();
895

Marcel Campen's avatar
Marcel Campen committed
896 897 898 899 900 901
    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() ) );
902 903 904 905 906 907 908
  }

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

}

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

910 911 912
  //======================================================================================
  // Get the mode toggled
  //======================================================================================
Jan Möbius's avatar
Jan Möbius committed
913 914 915
  ACG::SceneGraph::DrawModes::DrawMode mode = 0;
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes();
916 917
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
918
    QString descr = QString(  availDrawModeIds[i].description().c_str() );
919 920 921 922 923 924

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

926 927 928
  if ( qApp->keyboardModifiers() & Qt::ShiftModifier )
    PluginFunctions::viewerProperties().drawMode(  PluginFunctions::viewerProperties().drawMode() ^ mode );
  else
Marcel Campen's avatar
Marcel Campen committed
929 930
  {
    contextMenu_->hide();
931
    PluginFunctions::viewerProperties().drawMode(mode );
Marcel Campen's avatar
Marcel Campen committed
932
  }
933

934 935
}

936 937
void CoreWidget::slotPostProcessorMenu( QAction * _action)  {
  unsigned int mode = _action->data().toUInt();
Jan Möbius's avatar
Jan Möbius committed
938
  postProcessorManager().setActive(mode,PluginFunctions::activeExaminer());
939 940
}

Jan Möbius's avatar
Jan Möbius committed
941 942 943 944 945
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
946
//=============================================================================