ContextMenu.cc 36.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-2014 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
277
  //============================================================================================================
  // Viewing Direction Menu
  //============================================================================================================

  QMenu* viewingDirectionMenu = new QMenu( tr("Viewing Direction"), _menu);
278
  viewingDirectionMenu->setIcon(QIcon(iconPath+"core_viewingDirection.png"));
279
280
281
282
283
284
285
  _menu->addMenu(viewingDirectionMenu);

  QActionGroup* dirGroup = new QActionGroup(this);

  QAction* viewAction;
  // freeView
  viewAction = new QAction( tr("Free View"), viewingDirectionMenu );
286
  viewAction->setIcon( QIcon(iconPath+"orthogonal.png") );
287
288
289
290
291
292
293
294
  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 );
295
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_top.png") );
296
297
298
299
300
301
302
  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 );
303
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_bottom.png") );
304
305
306
307
308
309
310
  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 );
311
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_left.png") );
312
313
314
315
316
317
318
  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 );
319
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_right.png") );
320
321
322
323
324
325
326
  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 );
327
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_front.png") );
328
329
330
331
332
333
334
  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 );
335
  viewAction->setIcon( QIcon(iconPath+"viewcontrol_back.png") );
336
337
338
339
340
  viewAction->setCheckable( true );
  viewAction->setData( PluginFunctions::VIEW_BACK );
  viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_BACK );
  viewingDirectionMenu->addAction( viewAction );
  dirGroup->addAction(viewAction);
341
342
  
  viewingDirectionMenu->addSeparator();
343
344

  connect( dirGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSetViewingDirection(QAction*) ) );
345
346
347
348
349
350
  
  //===========================================================================
  // Check box to determine whether rotation should be locked or not
  
  QAction* lockAction = viewingDirectionMenu->addAction("Lock rotation");
  lockAction->setCheckable( true );
351
  lockAction->setIcon( QIcon(iconPath+"lock_rotation.png") );
352
353
354
355
356
357
  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) ) );
  
358
359
360
  //====================================================================================================
  // Other Toplevel Action
  //====================================================================================================
361

362
  _menu->addSeparator();
363

364
  //====================================================================================================
365

366
367
368
369
370
371
372
373
374
375
376
377
378
  //============================================================================================================
  // Post processor Manager
  //============================================================================================================

  QAction* showPostProcessorDialog = new QAction(tr("Show post processor manager"),this);
  showPostProcessorDialog->setIcon(QIcon(iconPath+"postprocessors.png"));
  connect(showPostProcessorDialog,SIGNAL(triggered()),this,SLOT(slotShowPostProcessorManager()));
  _menu->addAction(showPostProcessorDialog);

  _menu->addSeparator();

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

379
  QAction* homeAction = new QAction(tr("Restore home view"),_menu);
380
  homeAction->setIcon( QIcon(iconPath+"go-home.png") );
381
  homeAction->setCheckable( false );
382
383
384
  homeAction->setToolTip(tr("Restore <b>home</b> view."));
  homeAction->setWhatsThis( tr("Restore home view<br><br>"
                            "Resets the view to the home view"));
385
386
  _menu->addAction( homeAction );
  connect( homeAction,SIGNAL( triggered() ), this, SLOT( slotContextHomeView() ) );
387

388
  QAction* setHomeAction = new QAction( tr("Set Home View") , _menu );
389
  setHomeAction->setIcon( QIcon(iconPath+"set-home.png") );
390
  setHomeAction->setCheckable( false );
391
392
393
  setHomeAction->setToolTip(tr("Set <b>home</b> view"));
  setHomeAction->setWhatsThis( tr("Store home view<br><br>"
                               "Stores the current view as the home view"));
394
  _menu->addAction( setHomeAction);
395
396
  connect( setHomeAction,SIGNAL( triggered() ), this, SLOT( slotContextSetHomeView() ) );

397
  QAction* viewAllAction = new QAction( tr("View all"), _menu );
398
  viewAllAction->setIcon( QIcon(iconPath+"viewall.png") );
399
  viewAllAction->setCheckable( false );
400
401
402
403
  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."));
404
405
  connect( viewAllAction,SIGNAL( triggered() ), this, SLOT( slotContextViewAll() ) );
  _menu->addAction( viewAllAction);
406
407


408
  _menu->addSeparator();
409

410
  //====================================================================================================
411

412
  QAction* copyView = _menu->addAction(tr("Copy View"));
413
  copyView->setToolTip(tr("Copy current view, window size and toolbar size to clipboard"));
414
  copyView->setIcon( QIcon(iconPath+"edit-copy.png") );
415
416
417
418
  connect(copyView, SIGNAL(triggered()), this, SLOT(slotCopyView()) );

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

419
420
  QAction* pasteView = _menu->addAction(tr("Paste View"));
  pasteView->setToolTip(tr("Paste current view from clipboard"));
421
  pasteView->setIcon( QIcon(iconPath+"edit-paste.png") );
422
  connect(pasteView, SIGNAL(triggered()), this , SLOT( slotPasteView( ) ) );
423

424
  //====================================================================================================
425

426
427
428
429
430
431
432
  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( ) ) );

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

433
434
  QAction* snapshot_examiner = _menu->addAction(tr("Examiner Snapshot"));
  snapshot_examiner->setToolTip(tr("Take a snapshot of the current examiner"));
435
  snapshot_examiner->setIcon( QIcon(iconPath+"snapshot.png") );
436
437
438
439
440
441
  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"));
442
  snapshot_viewer->setIcon( QIcon(iconPath+"snapshot.png") );
443
  connect(snapshot_viewer, SIGNAL(triggered()), this, SLOT( viewerSnapshotDialog() ) );
444

445
446
}

Jan Möbius's avatar
Jan Möbius committed
447
/** \brief Update context Menu when background has been clicked on.
448
 *
Jan Möbius's avatar
Jan Möbius committed
449
 * This function is called when the background in a viewer has been clicked on.
450
 * This context menu will show functions which are related to the background of the
Jan Möbius's avatar
Jan Möbius committed
451
 * viewer.
452
 *
Jan Möbius's avatar
Jan Möbius committed
453
454
455
 * @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
456
void CoreWidget::updatePopupMenuBackground(QMenu* _menu , const QPoint& /*_point*/) {
457

458
459
460
461
462
463
464
  //====================================================================================================
  // DrawModes
  //====================================================================================================
  slotUpdateViewerDrawMenu();
  _menu->addMenu( viewerDrawMenu_ );

  _menu->addSeparator();
465
  
466
467
  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
468
  action->setStatusTip(tr("Set the background color for the current viewer"));
469
  action->setWhatsThis(tr("Set the background color for the current viewer"));
470
  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"BackgroundColor.png") );
471
  connect(action, SIGNAL(triggered()), this, SLOT(slotSetContextBackgroundColor()) );
472

473
  /*
Mike Kremer's avatar
Mike Kremer committed
474
   * Show coordsys context menu of coordsys if
475
476
477
478
479
480
481
   * invisible...
   */

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

  if(!coordSys->visible()) {
482
483

	  if(!coordSysMenu_) {
484
		  coordSysMenu_ = new QMenu(tr("Viewer Settings"), _menu);
485
486
		  updatePopupMenuCoordsysNode(coordSysMenu_, 0);
	  }
487
	  _menu->addSeparator();
488
	  _menu->addMenu(coordSysMenu_);
489
490
  }

491
492
493
494
495
  // Tell Plugins to update their context Menu
  emit updateContextMenuBackground();

  addContextMenus( _menu , CONTEXTBACKGROUNDMENU ) ;

Jan Möbius's avatar
Jan Möbius committed
496
}
Jan Möbius's avatar
Jan Möbius committed
497

Jan Möbius's avatar
Jan Möbius committed
498
/** \brief Update popup Menu when an object has been clicked on.
499
 *
Jan Möbius's avatar
Jan Möbius committed
500
501
 * This function is called when an object has been clicked on.
 * This context menu will show all properties for the given object.
502
 *
Jan Möbius's avatar
Jan Möbius committed
503
 * @param _menu Pointer to the context Menu
Jan Möbius's avatar
Jan Möbius committed
504
 * @param _object Object that has been clicked on.
Jan Möbius's avatar
Jan Möbius committed
505
 */
506
507
void CoreWidget::updatePopupMenuObject(QMenu* _menu , BaseObjectData* _object ) {

508
  QAction* typeEntry = new QAction( typeName(_object->dataType())+QString(": ")+_object->name() ,_menu);
509
  typeEntry->setIcon(typeIcon(_object->dataType()));
510
511
512
513
514
515
516
517
518
519
520
  _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
521
  if (pickMenu_ != 0 && pickMenu_->actions().size() > 0) {
522
    pickMenu_->setTitle(tr("&Picking"));
523
524
    contextMenu_->addMenu( pickMenu_ );
    pickMenu_->setTearOffEnabled(true);
525
526
527
528
529
530
531
  }
}

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

  bool added = false;

532
533
534
  QMap< QString , QAction* > menuMap; //QMap sorts by key
  QMap< QString , QAction* > actionMap;

535
536
537
538
539
540
541
542
543
544
545
546
  // 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) ) {
547
          emit log(LOGERR,tr("Cant get object for objectContextMenu"));
548
549
550
551
552
553
554
555
556
557
558
559
560
          continue;
        }

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

        break;
      case CONTEXTNODEMENU:
        break;

    }

561
562
563
564
565
566
    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;
567
568
569
570
571

    added = true;

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

Jan Möbius's avatar
   
Jan Möbius committed
573
574
575
576
577
578
579
580

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

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    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
596
597
598
599
600
601
602
603
  //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;
    }
  }
604
605
606
607
608
609

  // 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
610
611
  
  /// \todo Sort the menu entries by the order given in visibleContextMenus
Jan Möbius's avatar
Marlin:    
Jan Möbius committed
612
  
613
614
  //first add all menus
  QMapIterator<QString, QAction*> it(menuMap);
Jan Möbius's avatar
Marlin:    
Jan Möbius committed
615
616
  
  QStringList visible = viewModes_[id]->visibleContextMenus;
Jan Möbius's avatar
Marlin:    
Jan Möbius committed
617
618
619
620
  if (visible.contains("ALL_THAT_EXIST")) {
    //this plugin adds all context menus, no special configuration so far.
    visible = viewModes_[0]->visibleContextMenus;
  }
621
622

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

625
626
627
  // Remove accelerator specifications
  visible.replaceInStrings("&", "");

628
  while (it.hasNext()) {
629
630
631
632
633
634
635
    it.next();

	for ( int i = 0 ; i < visible.size(); ++i ) {
	  if ( it.key().contains(visible[i]) ) {
	    _menu->addAction( it.value() );
	  }
    }
636
637
638
639
640
641
  }

  _menu->addSeparator();

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

643
644
  while (it2.hasNext()) {
     it2.next();
645
646
647
648
649
650

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

  return added;
Jan Möbius's avatar
Jan Möbius committed
654
}
Jan Möbius's avatar
Jan Möbius committed
655
656


657
 
658
659
660
/** \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
661
662
663
664
 * 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
665

Jan Möbius's avatar
Jan Möbius committed
666
667
  // Clear the complete context menu.
  contextMenu_->clear();
668

Jan Möbius's avatar
Jan Möbius committed
669
670
  // Clear the selection context menu part.
  contextSelectionMenu_->clear();
Jan Möbius's avatar
Jan Möbius committed
671

Jan Möbius's avatar
Jan Möbius committed
672
673
674
  // =============================================================================
  // First do a picking on the current position to check which context we are in.
  // =============================================================================
675

Jan Möbius's avatar
Jan Möbius committed
676
  enum CONTEXTTYPE {
677
    COORDSYSCONTEXT ,BACKGROUNDCONTEXT ,OBJECTCONTEXT, NODECONTEXT
Jan Möbius's avatar
Jan Möbius committed
678
  } context = BACKGROUNDCONTEXT;
Jan Möbius's avatar
Jan Möbius committed
679

Jan Möbius's avatar
 
Jan Möbius committed
680
  // Do picking in the gl area to find an object
681
682
  unsigned int               node_idx, target_idx;
  ACG::Vec3d                 hit_point;
Jan Möbius's avatar
Jan Möbius committed
683
684
  BaseObjectData*            object = 0;
  ACG::SceneGraph::BaseNode* node   = 0;
685

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

Jan Möbius's avatar
Jan Möbius committed
688
689
690
    if ( PluginFunctions::getPickedObject(node_idx, object) ) {
      context  = OBJECTCONTEXT;
    } else {
691
692
      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
693
        context = COORDSYSCONTEXT;
694
695
      else
        context = NODECONTEXT;
696
    }
697
698
  }

Jan Möbius's avatar
Jan Möbius committed
699
700
701
  // =============================================================================
  // Depending on the context create the basic context menu.
  // =============================================================================
702

Jan Möbius's avatar
Jan Möbius committed
703
  QIcon icon;
704

Jan Möbius's avatar
Jan Möbius committed
705
706
707
  switch (context) {
    case BACKGROUNDCONTEXT:
      updatePopupMenuBackground(contextMenu_,_point);
708
      return;
Jan Möbius's avatar
Jan Möbius committed
709
710
      break;
    case OBJECTCONTEXT:
711
      updatePopupMenuObject(contextMenu_ , object );
712
      return;
Jan Möbius's avatar
Jan Möbius committed
713
714
715
      break;
    case COORDSYSCONTEXT:
      updatePopupMenuCoordsysNode(contextMenu_,target_idx);
716
      return;
Jan Möbius's avatar
Jan Möbius committed
717
      break;
718
719
720
721
    case NODECONTEXT:
      updatePopupMenuNode(contextMenu_,node);
      return;
      break;
Jan Möbius's avatar
 
Jan Möbius committed
722
  }
Jan Möbius's avatar
Jan Möbius committed
723

Jan Möbius's avatar
 
Jan Möbius committed
724
725
}

726

727
728
void CoreWidget::slotSnapshotName() {
  std::cerr << "Todo : slotSnapShotName only sets name for current viewer" << std::endl;
729
730
731
732

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

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

737
738
739
740
  if (!fname.isEmpty())
  {
    fname.replace('$', '%');

Jan Möbius's avatar
Jan Möbius committed
741
742
743
744
745

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

746
    PluginFunctions::viewerProperties().snapshotBaseFileName(fname);
747
    QString msg=tr("next snapshot: ");
748
749
750
    statusBar()->showMessage(msg);
  }

751
752
}

Jan Möbius's avatar
   
Jan Möbius committed
753
void CoreWidget::slotAddContextItem(QAction* _entry, ContextMenuType _type) {
Jan Möbius's avatar
 
Jan Möbius committed
754
  MenuInfo info;
Jan Möbius's avatar
   
Jan Möbius committed
755
756
  info.action = _entry;
  info.type   = _type;
Jan Möbius's avatar
Jan Möbius committed
757

Jan Möbius's avatar
Marlin:    
Jan Möbius committed
758
759
  contextMenus_.push_back(info); 
  slotAddContextItemToViewMode(_entry);
Jan Möbius's avatar
 
Jan Möbius committed
760
761
}

Jan Möbius's avatar
   
Jan Möbius committed
762
void CoreWidget::slotAddContextItem( QAction* _entry , DataType _dataType ,ContextMenuType _type ) {
Jan Möbius's avatar
 
Jan Möbius committed
763
  MenuInfo info;
Jan Möbius's avatar
   
Jan Möbius committed
764
  info.action      = _entry;
Jan Möbius's avatar
 
Jan Möbius committed
765
  info.contextType = _dataType;
Jan Möbius's avatar
   
Jan Möbius committed
766
  info.type        = _type;
Jan Möbius's avatar
Jan Möbius committed
767

Jan Möbius's avatar
 
Jan Möbius committed
768
  contextMenus_.push_back(info);
Jan Möbius's avatar
Marlin:    
Jan Möbius committed
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
  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
807
808
}

809
810
void CoreWidget::slotUpdateViewerDrawMenu() {
  if ( drawGroupViewer_ ) {
811

812
813
814
815
    disconnect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
                this             , SLOT( slotViewerDrawMenu( QAction * ) ) );
    delete( drawGroupViewer_ );
    drawGroupViewer_ = 0;
816

817
  }
818

819
820
821
  // Recreate drawGroup
  drawGroupViewer_ = new QActionGroup( this );
  drawGroupViewer_->setExclusive( false );
822

823
  connect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
824
825
           this       , SLOT( slotViewerDrawMenu( QAction * ) ) );

826
  if ( !viewerDrawMenu_ ) {
827

828
829
    QIcon icon;
    icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
830
    viewerDrawMenu_  = new QMenu(tr("Set Draw Mode"));
831
832
    viewerDrawMenu_->setTearOffEnabled(true);
    viewerDrawMenu_->setIcon(icon);
833

834
835
    connect(viewerDrawMenu_,SIGNAL(aboutToShow () ) , this, SLOT(slotUpdateGlobalDrawMenu() ) );
  }
836

Matthias Möller's avatar
Matthias Möller committed
837
838
839
840
841
  if (viewerDrawMenuWidget_) {
    delete viewerDrawMenuWidget_;
  }
  viewerDrawMenuWidget_ = new QWidget(viewerDrawMenu_);

842
843
  // Collect available draw modes
  // Single pass action, draw modes independent from multipass rendering
844
845
846
  ACG::SceneGraph::CollectDrawModesAction actionAvailable;
  ACG::SceneGraph::traverse( PluginFunctions::getRootNode() , actionAvailable);
  availableGlobalDrawModes_ = actionAvailable.drawModes();
847

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

852
  // Convert to ids
Jan Möbius's avatar
Jan Möbius committed
853
854
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes() ;
855

856
  viewerDrawMenu_->clear();
857

858
859
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
860
861
    ACG::SceneGraph::DrawModes::DrawMode id    = availDrawModeIds[i];
    std::string  descr =  id.description();
862

Matthias Möller's avatar
Matthias Möller committed
863
    QCheckBox *checkBox = new QCheckBox(QString(descr.c_str()), viewerDrawMenuWidget_);
Marcel Campen's avatar
Marcel Campen committed
864
865
866
867
868
    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() ) );
869
870
871
872
873
874
875
  }

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

}

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

877
878
879
  //======================================================================================
  // Get the mode toggled
  //======================================================================================
Jan Möbius's avatar
Jan Möbius committed
880
881
882
  ACG::SceneGraph::DrawModes::DrawMode mode = 0;
  std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
  availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes();
883
884
  for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
  {
Jan Möbius's avatar
Jan Möbius committed
885
    QString descr = QString(  availDrawModeIds[i].description().c_str() );
886
887
888
889
890
891

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

893
894
895
  if ( qApp->keyboardModifiers() & Qt::ShiftModifier )
    PluginFunctions::viewerProperties().drawMode(  PluginFunctions::viewerProperties().drawMode() ^ mode );
  else
Marcel Campen's avatar
Marcel Campen committed
896
897
  {
    contextMenu_->hide();
898
    PluginFunctions::viewerProperties().drawMode(mode );
Marcel Campen's avatar
Marcel Campen committed
899
  }
900

901
902
}

903
904
void CoreWidget::slotPostProcessorMenu( QAction * _action)  {
  unsigned int mode = _action->data().toUInt();
Jan Möbius's avatar
Jan Möbius committed
905
  postProcessorManager().setActive(mode,PluginFunctions::activeExaminer());
906
907
}

Jan Möbius's avatar
Jan Möbius committed
908
909
910
void CoreWidget::slotRenderMenu( QAction * _action)  {
  unsigned int mode = _action->data().toUInt();
  renderManager().setActive(mode,PluginFunctions::activeExaminer());
911
912
913
914

  QString defaultRendererKey  = "Viewer" + QString::number(PluginFunctions::activeExaminer())+"/DefaultRenderer";
  QString defaultRendererName = renderManager()[mode]->name;
  OpenFlipperSettings().setValue(defaultRendererKey,defaultRendererName);
Jan Möbius's avatar
Jan Möbius committed
915
916
}

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