/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* 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 . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS CoreWidget - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
// -------------------- mview
#include "CoreWidget.hh"
#include
#include
#include "../../common/GlobalOptions.hh"
#include
//== IMPLEMENTATION ==========================================================
#include
void CoreWidget::slotCustomContextMenu( const QPoint& _point ) {
QPoint popupPosition;
QPoint scenePos;
// 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());
// Call function to adapt the menu to the currently used contex.
updatePopupMenu(scenePos);
// If the menu is not correctly initialized, dont try to show it.
if ( !contextMenu_->isEmpty () )
contextMenu_->popup( popupPosition );
}
/** \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());
addContextMenus( _menu , CONTEXTNODEMENU, _node->id() ) ;
}
/** \brief Update context Menu when Coordsys node has been clicked on.
*
* 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...
*
* @param _menu Pointer to the context Menu
* @param _part id of the coordsys part which has been clicked on.
*/
void CoreWidget::updatePopupMenuCoordsysNode(QMenu* _menu , const int /*_part*/) {
QString iconPath = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
QAction* typeEntry = new QAction(tr("Viewer Settings"),_menu);
_menu->addAction( typeEntry );
typeEntry->setDisabled(true);
_menu->addSeparator();
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);
//====================================================================================================
// DrawModes
//====================================================================================================
slotUpdateViewerDrawMenu();
if (! viewerDrawMenu_->isEmpty())
_menu->addMenu( viewerDrawMenu_ );
//====================================================================================================
// RenderingOptions
//====================================================================================================
QMenu* renderingOptionsMenu = new QMenu(tr("Rendering Options"),_menu);
renderingOptionsMenu->setIcon( QIcon(iconPath+"core_renderingOptions.png") );
_menu->addMenu(renderingOptionsMenu);
QAction* projectionAction = 0;
if ( examiner_widgets_[PluginFunctions::activeExaminer() ]->projectionMode() == glViewer::PERSPECTIVE_PROJECTION ) {
projectionAction = new QAction( tr("Switch to Orthogonal Projection"), renderingOptionsMenu );
projectionAction->setIcon( QIcon(iconPath+"orthogonal.png") );
projectionAction->setToolTip( tr("Switch to perspective orthogonal mode."));
} else {
projectionAction = new QAction( tr("Switch to Perspective Projection"), renderingOptionsMenu );
projectionAction->setIcon( QIcon(iconPath+"perspective.png") );
projectionAction->setToolTip( tr("Switch to perspective projection mode."));
}
projectionAction->setCheckable( false );
projectionAction->setToolTip( tr("Switch between perspective and "
"parrallel projection mode."));
projectionAction->setWhatsThis( tr("Switch projection modes
"
"Switch between perspective and "
"parrallel projection mode."));
connect( projectionAction,SIGNAL( triggered() ), this, SLOT( slotContextSwitchProjection() ) );
renderingOptionsMenu->addAction( projectionAction );
QAction* animation = renderingOptionsMenu->addAction(tr("Animation"));
animation->setToolTip(tr("Animate rotation of objects"));
animation->setCheckable( true );
animation->setIcon( QIcon(iconPath+"animation.png") );
animation->setChecked( PluginFunctions::viewerProperties(PluginFunctions::activeExaminer()).animation() );
connect(animation, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeAnimation(bool) ) );
//====================================================================================================
QAction* backfaceCulling = renderingOptionsMenu->addAction(tr("Backface Culling"));
backfaceCulling->setToolTip(tr("Enable backface culling"));
backfaceCulling->setCheckable( true );
backfaceCulling->setIcon( QIcon(iconPath+"backFaceCulling.png") );
backfaceCulling->setChecked( PluginFunctions::viewerProperties().backFaceCulling() );
connect(backfaceCulling, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeBackFaceCulling(bool) ) );
//====================================================================================================
QAction* twoSidedLighting = renderingOptionsMenu->addAction(tr("Two-sided Lighting"));
twoSidedLighting->setToolTip(tr("Enable two-sided lighting"));
twoSidedLighting->setCheckable( true );
twoSidedLighting->setIcon( QIcon(iconPath+"twosidedLighting.png") );
twoSidedLighting->setChecked( PluginFunctions::viewerProperties().twoSidedLighting() );
connect(twoSidedLighting, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeTwoSidedLighting(bool) ) );
//====================================================================================================
QAction* multisampling = renderingOptionsMenu->addAction(tr("Multisampling"));
multisampling->setToolTip(tr("Enable Multisampling"));
multisampling->setCheckable( true );
multisampling->setIcon( QIcon(iconPath+"multiSampling.png") );
multisampling->setChecked( PluginFunctions::viewerProperties().multisampling() );
connect(multisampling, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeMultisampling(bool) ) );
//====================================================================================================
QAction* mipmapping = renderingOptionsMenu->addAction(tr("Mipmapping"));
mipmapping->setToolTip(tr("Enable Mipmapping"));
mipmapping->setCheckable( true );
mipmapping->setIcon( QIcon(iconPath+"mipmapping.png") );
mipmapping->setChecked( PluginFunctions::viewerProperties().mipmapping() );
connect(mipmapping, SIGNAL(triggered(bool)), this , SLOT( slotLocalChangeMipmapping(bool) ) );
//============================================================================================================
// Renderer Menu
//============================================================================================================
if ( renderManager().available() > 1 ) {
QMenu* rendererMenu = new QMenu(tr("Renderers"),_menu);
rendererMenu->setIcon(QIcon(iconPath+"renderers.png"));
_menu->addMenu(rendererMenu);
// Recreate actionGroup
QActionGroup* groupRenderer = new QActionGroup( this );
groupRenderer->setExclusive( true );
// Get the options action for the currently active renderer
if( renderManager()[ renderManager().activeId(PluginFunctions::activeExaminer() )]->optionsAction != 0 ) {
rendererMenu->addAction(renderManager()[ renderManager().activeId(PluginFunctions::activeExaminer() ) ]->optionsAction );
rendererMenu->addSeparator();
}
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 * ) ) );
}
//============================================================================================================
// Post processor Menu
//============================================================================================================
if ( postProcessorManager().available() > 1 ) {
QMenu* postProcessorMenu = new QMenu(tr("Post processors"),_menu);
postProcessorMenu->setIcon(QIcon(iconPath+"postprocessors.png"));
_menu->addMenu(postProcessorMenu);
// Recreate actionGroup
QActionGroup* groupPostProcessor = new QActionGroup( this );
groupPostProcessor->setExclusive( true );
// 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 );
postProcessorMenu->addSeparator();
}
// Now add the processor chooser
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
if ( postProcessorManager().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
postProcessorMenu->addActions( groupPostProcessor->actions() );
// Connect signal of group to our managing slot
connect( groupPostProcessor , SIGNAL( triggered( QAction * ) ),
this , SLOT( slotPostProcessorMenu( QAction * ) ) );
}
//============================================================================================================
// Viewing Direction Menu
//============================================================================================================
QMenu* viewingDirectionMenu = new QMenu( tr("Viewing Direction"), _menu);
viewingDirectionMenu->setIcon(QIcon(iconPath+"core_viewingDirection.png"));
_menu->addMenu(viewingDirectionMenu);
QActionGroup* dirGroup = new QActionGroup(this);
QAction* viewAction;
// freeView
viewAction = new QAction( tr("Free View"), viewingDirectionMenu );
viewAction->setIcon( QIcon(iconPath+"orthogonal.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_top.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_bottom.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_left.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_right.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_front.png") );
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 );
viewAction->setIcon( QIcon(iconPath+"viewcontrol_back.png") );
viewAction->setCheckable( true );
viewAction->setData( PluginFunctions::VIEW_BACK );
viewAction->setChecked( PluginFunctions::viewerProperties().currentViewingDirection() == PluginFunctions::VIEW_BACK );
viewingDirectionMenu->addAction( viewAction );
dirGroup->addAction(viewAction);
viewingDirectionMenu->addSeparator();
connect( dirGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSetViewingDirection(QAction*) ) );
//===========================================================================
// Check box to determine whether rotation should be locked or not
QAction* lockAction = viewingDirectionMenu->addAction("Lock rotation");
lockAction->setCheckable( true );
lockAction->setIcon( QIcon(iconPath+"lock_rotation.png") );
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) ) );
//====================================================================================================
// Other Toplevel Action
//====================================================================================================
_menu->addSeparator();
//====================================================================================================
QAction* homeAction = new QAction(tr("Restore home view"),_menu);
homeAction->setIcon( QIcon(iconPath+"go-home.png") );
homeAction->setCheckable( false );
homeAction->setToolTip(tr("Restore home view."));
homeAction->setWhatsThis( tr("Restore home view
"
"Resets the view to the home view"));
_menu->addAction( homeAction );
connect( homeAction,SIGNAL( triggered() ), this, SLOT( slotContextHomeView() ) );
QAction* setHomeAction = new QAction( tr("Set Home View") , _menu );
setHomeAction->setIcon( QIcon(iconPath+"set-home.png") );
setHomeAction->setCheckable( false );
setHomeAction->setToolTip(tr("Set home view"));
setHomeAction->setWhatsThis( tr("Store home view
"
"Stores the current view as the home view"));
_menu->addAction( setHomeAction);
connect( setHomeAction,SIGNAL( triggered() ), this, SLOT( slotContextSetHomeView() ) );
QAction* viewAllAction = new QAction( tr("View all"), _menu );
viewAllAction->setIcon( QIcon(iconPath+"viewall.png") );
viewAllAction->setCheckable( false );
viewAllAction->setToolTip(tr("View all."));
viewAllAction->setWhatsThis( tr("View all
"
"Move the objects in the scene so that"
" the whole scene is visible."));
connect( viewAllAction,SIGNAL( triggered() ), this, SLOT( slotContextViewAll() ) );
_menu->addAction( viewAllAction);
_menu->addSeparator();
//====================================================================================================
QAction* copyView = _menu->addAction(tr("Copy View"));
copyView->setToolTip(tr("Copy current view to clipboard"));
copyView->setIcon( QIcon(iconPath+"edit-copy.png") );
connect(copyView, SIGNAL(triggered()), this, SLOT(slotCopyView()) );
//====================================================================================================
QAction* pasteView = _menu->addAction(tr("Paste View"));
pasteView->setToolTip(tr("Paste current view from clipboard"));
pasteView->setIcon( QIcon(iconPath+"edit-paste.png") );
connect(pasteView, SIGNAL(triggered()), this , SLOT( slotPasteView( ) ) );
//====================================================================================================
QAction* snapshot_examiner = _menu->addAction(tr("Examiner Snapshot"));
snapshot_examiner->setToolTip(tr("Take a snapshot of the current examiner"));
snapshot_examiner->setIcon( QIcon(iconPath+"snapshot.png") );
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"));
snapshot_viewer->setIcon( QIcon(iconPath+"snapshot.png") );
connect(snapshot_viewer, SIGNAL(triggered()), this, SLOT( viewerSnapshotDialog() ) );
}
/** \brief Update context Menu when background has been clicked on.
*
* This function is called when the background in a viewer has been clicked on.
* This context menu will show functions which are related to the background of the
* viewer.
*
* @param _menu Pointer to the context Menu
* @param _point position in the viewer where the user clicked.
*/
void CoreWidget::updatePopupMenuBackground(QMenu* _menu , const QPoint& /*_point*/) {
//====================================================================================================
// DrawModes
//====================================================================================================
slotUpdateViewerDrawMenu();
_menu->addMenu( viewerDrawMenu_ );
_menu->addSeparator();
QAction* action = _menu->addAction(tr("Set Background Color"));
action->setToolTip(tr("Set the background color for the current viewer"));
action->setStatusTip(tr("Set the background color for the current viewer"));
action->setWhatsThis(tr("Set the background color for the current viewer"));
action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"BackgroundColor.png") );
connect(action, SIGNAL(triggered()), this, SLOT(slotSetContextBackgroundColor()) );
/*
* Show coordsys context menu of coordsys if
* invisible...
*/
ACG::SceneGraph::BaseNode* root = PluginFunctions::getSceneGraphRootNode();
ACG::SceneGraph::BaseNode* coordSys = root->find("Core Coordsys Node");
if(!coordSys->visible()) {
if(!coordSysMenu_) {
coordSysMenu_ = new QMenu(tr("Viewer Settings"), _menu);
updatePopupMenuCoordsysNode(coordSysMenu_, 0);
}
_menu->addSeparator();
_menu->addMenu(coordSysMenu_);
}
// Tell Plugins to update their context Menu
emit updateContextMenuBackground();
addContextMenus( _menu , CONTEXTBACKGROUNDMENU ) ;
}
/** \brief Update context Menu an object has been clicked on.
*
* This function is called when an object has been clicked on.
* This context menu will show all properties for the given object.
*
* @param _menu Pointer to the context Menu
* @param _objectId Id of the object that has been clicked on.
*/
void CoreWidget::updatePopupMenuObject(QMenu* _menu , BaseObjectData* _object ) {
QAction* typeEntry = new QAction( typeName(_object->dataType()) ,_menu);
typeEntry->setIcon(typeIcon(_object->dataType()));
_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
if (pickMenu_ != 0 && pickMenu_->actions().size() > 0) {
pickMenu_->setTitle(tr("&Picking"));
contextMenu_->addMenu( pickMenu_ );
pickMenu_->setTearOffEnabled(true);
}
}
bool CoreWidget::addContextMenus( QMenu* _menu , ContextMenuType _type , int _id ) {
bool added = false;
QMap< QString , QAction* > menuMap; //QMap sorts by key
QMap< QString , QAction* > actionMap;
// 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) ) {
emit log(LOGERR,tr("Cant get object for objectContextMenu"));
continue;
}
// Datatype does not match
if ( ! object->dataType( contextMenus_[i].contextType ) )
continue;
break;
case CONTEXTNODEMENU:
break;
}
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;
added = true;
// Get all Actions in the menu and its submenus.
// Set their data to the picked Object id
QList< QAction *> allActions;
if ( menu == 0) {
allActions.push_back(contextMenus_[i].action);
} else {
allActions = menu->actions();
}
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;
}
}
//find the currently selected view mode
int id = -1;
for (int i=0; iname == OpenFlipper::Options::currentViewMode()) {
id = i;
break;
}
}
// 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;
}
/// \todo Sort the menu entries by the order given in visibleContextMenus
//first add all menus
QMapIterator it(menuMap);
QStringList visible = viewModes_[id]->visibleContextMenus;
if (visible.contains("ALL_THAT_EXIST")) {
//this plugin adds all context menus, no special configuration so far.
visible = viewModes_[0]->visibleContextMenus;
}
// Remove Plugin Name from string
visible.replaceInStrings(QRegExp(".*>"), "");
// Remove accelerator specifications
visible.replaceInStrings("&", "");
while (it.hasNext()) {
it.next();
for ( int i = 0 ; i < visible.size(); ++i ) {
if ( it.key().contains(visible[i]) ) {
_menu->addAction( it.value() );
}
}
}
_menu->addSeparator();
//then all actions
QMapIterator it2(actionMap);
while (it2.hasNext()) {
it2.next();
for ( int i = 0 ; i < visible.size(); ++i ) {
if ( it2.key().contains(visible[i]) ) {
_menu->addAction( it2.value() );
}
}
}
return added;
}
/** \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.
* It will decide about the current context, collect all menus for plugins and
* construct the final context menu.
*/
void CoreWidget::updatePopupMenu(const QPoint& _point) {
// Clear the complete context menu.
contextMenu_->clear();
// Clear the selection context menu part.
contextSelectionMenu_->clear();
// =============================================================================
// First do a picking on the current position to check which context we are in.
// =============================================================================
int objectId = -1;
enum CONTEXTTYPE {
COORDSYSCONTEXT ,BACKGROUNDCONTEXT ,OBJECTCONTEXT, NODECONTEXT
} context = BACKGROUNDCONTEXT;
// Do picking in the gl area to find an object
unsigned int node_idx, target_idx;
ACG::Vec3d hit_point;
BaseObjectData* object;
ACG::SceneGraph::BaseNode* node = 0;
if (examiner_widgets_[PluginFunctions::activeExaminer()]->pick( ACG::SceneGraph::PICK_ANYTHING,_point,node_idx, target_idx, &hit_point ) ) {
if ( PluginFunctions::getPickedObject(node_idx, object) ) {
objectId = object->id();
context = OBJECTCONTEXT;
} else {
node = ACG::SceneGraph::find_node( PluginFunctions::getSceneGraphRootNode() , node_idx );
if ( node != 0 && ( node->name() == "Core Coordsys Node") )
context = COORDSYSCONTEXT;
else
context = NODECONTEXT;
}
}
// =============================================================================
// Depending on the context create the basic context menu.
// =============================================================================
QIcon icon;
switch (context) {
case BACKGROUNDCONTEXT:
updatePopupMenuBackground(contextMenu_,_point);
return;
break;
case OBJECTCONTEXT:
updatePopupMenuObject(contextMenu_ , object );
return;
break;
case COORDSYSCONTEXT:
updatePopupMenuCoordsysNode(contextMenu_,target_idx);
return;
break;
case NODECONTEXT:
updatePopupMenuNode(contextMenu_,node);
return;
break;
}
}
void CoreWidget::slotSnapshotName() {
std::cerr << "Todo : slotSnapShotName only sets name for current viewer" << std::endl;
QString fname = PluginFunctions::viewerProperties().snapshotName();
fname.replace('%', '$');
fname = QFileDialog::getSaveFileName ( 0,
tr("Save snapshot name"),
OpenFlipperSettings().value("Core/CurrentDir").toString());
if (!fname.isEmpty())
{
fname.replace('$', '%');
// Get the chosen directory and remember it.
QFileInfo fileInfo(fname);
OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );
PluginFunctions::viewerProperties().snapshotBaseFileName(fname);
QString msg=tr("next snapshot: ");
statusBar()->showMessage(msg);
}
}
void CoreWidget::slotAddContextItem(QAction* _entry, ContextMenuType _type) {
MenuInfo info;
info.action = _entry;
info.type = _type;
contextMenus_.push_back(info);
slotAddContextItemToViewMode(_entry);
}
void CoreWidget::slotAddContextItem( QAction* _entry , DataType _dataType ,ContextMenuType _type ) {
MenuInfo info;
info.action = _entry;
info.contextType = _dataType;
info.type = _type;
contextMenus_.push_back(info);
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() );
}
void CoreWidget::slotUpdateViewerDrawMenu() {
if ( drawGroupViewer_ ) {
disconnect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
this , SLOT( slotViewerDrawMenu( QAction * ) ) );
delete( drawGroupViewer_ );
drawGroupViewer_ = 0;
}
// Recreate drawGroup
drawGroupViewer_ = new QActionGroup( this );
drawGroupViewer_->setExclusive( false );
connect( drawGroupViewer_ , SIGNAL( triggered( QAction * ) ),
this , SLOT( slotViewerDrawMenu( QAction * ) ) );
if ( !viewerDrawMenu_ ) {
QIcon icon;
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
viewerDrawMenu_ = new QMenu(tr("Set Draw Mode"));
viewerDrawMenu_->setTearOffEnabled(true);
viewerDrawMenu_->setIcon(icon);
connect(viewerDrawMenu_,SIGNAL(aboutToShow () ) , this, SLOT(slotUpdateGlobalDrawMenu() ) );
}
// Collect available draw modes
// Single pass action, draw modes independent from multipass rendering
ACG::SceneGraph::CollectDrawModesAction actionAvailable;
ACG::SceneGraph::traverse( PluginFunctions::getRootNode() , actionAvailable);
availableGlobalDrawModes_ = actionAvailable.drawModes();
// Get currently active drawModes (first viewer only )
// TODO: create combination from all viewers!
ACG::SceneGraph::DrawModes::DrawMode activeDrawModes = PluginFunctions::drawMode();
// Convert to ids
std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes() ;
viewerDrawMenu_->clear();
for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
{
ACG::SceneGraph::DrawModes::DrawMode id = availDrawModeIds[i];
std::string descr = id.description();
QAction * action = new QAction( descr.c_str(), drawGroupViewer_ );
action->setCheckable( true );
action->setChecked( activeDrawModes.containsAtomicDrawMode(id) );
}
viewerDrawMenu_->addActions( drawGroupViewer_->actions() );
}
void CoreWidget::slotViewerDrawMenu(QAction * _action) {
//======================================================================================
// Get the mode toggled
//======================================================================================
ACG::SceneGraph::DrawModes::DrawMode mode = 0;
std::vector< ACG::SceneGraph::DrawModes::DrawMode > availDrawModeIds;
availDrawModeIds = availableGlobalDrawModes_.getAtomicDrawModes();
for ( unsigned int i = 0; i < availDrawModeIds.size(); ++i )
{
QString descr = QString( availDrawModeIds[i].description().c_str() );
if ( descr == _action->text() ) {
mode = availDrawModeIds[i];
break;
}
}
if ( qApp->keyboardModifiers() & Qt::ShiftModifier )
PluginFunctions::viewerProperties().drawMode( PluginFunctions::viewerProperties().drawMode() ^ mode );
else
PluginFunctions::viewerProperties().drawMode(mode );
}
void CoreWidget::slotPostProcessorMenu( QAction * _action) {
unsigned int mode = _action->data().toUInt();
postProcessorManager().setActive(mode,PluginFunctions::activeExaminer());
}
void CoreWidget::slotRenderMenu( QAction * _action) {
unsigned int mode = _action->data().toUInt();
renderManager().setActive(mode,PluginFunctions::activeExaminer());
}
//=============================================================================