//=============================================================================
//
// OpenFlipper
// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
// www.openflipper.org
//
//-----------------------------------------------------------------------------
//
// License
//
// 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.
//
// 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 Lesser General Public License
// along with OpenFlipper. If not, see .
//
//-----------------------------------------------------------------------------
//
// $Revision$
// $Author$
// $Date$
//
//=============================================================================
//=============================================================================
//
// CLASS CoreWidget - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
// -------------------- mview
#include "CoreWidget.hh"
#include
#include
//== IMPLEMENTATION ==========================================================
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_->exec( popupPosition );
}
/** \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) {
std::cerr << "Coordsys part was : " << _part << std::endl;
QAction* typeEntry = new QAction("Viewer Settings",_menu);
_menu->addAction( typeEntry );
//====================================================================================================
}
/** \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) {
QAction* typeEntry = new QAction("Background",_menu);
_menu->addAction( typeEntry );
//====================================================================================================
QAction* action = _menu->addAction("Set Background Color");
action->setToolTip("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"));
connect(action, SIGNAL(triggered()), this, SLOT(slotSetLocalBackgroundColor()) );
//====================================================================================================
}
/** \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 , const int _objectId ) {
std::cerr << "Object Context Menu for id: " << _objectId << std::endl;
}
/** \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
} context = BACKGROUNDCONTEXT;
// Do picking in the gl area to find an object
unsigned int node_idx, target_idx;
ACG::Vec3d hit_point;
BaseObjectData* object;
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 {
ACG::SceneGraph::BaseNode* node = ACG::SceneGraph::find_node( PluginFunctions::getSceneGraphRootNode() , node_idx );
if ( node != 0 && ( node->name() == "Core Coordsys Node") )
context = COORDSYSCONTEXT;
}
}
// =============================================================================
// Depending on the context create the basic context menu.
// =============================================================================
QIcon icon;
QAction* typeEntry = 0;
switch (context) {
case BACKGROUNDCONTEXT:
updatePopupMenuBackground(contextMenu_,_point);
break;
case OBJECTCONTEXT:
typeEntry = new QAction("Object",contextMenu_);
contextMenu_->addAction( typeEntry );
break;
case COORDSYSCONTEXT:
updatePopupMenuCoordsysNode(contextMenu_,target_idx);
break;
}
// Add the global entry to the context menu.
QAction* entrySeparator = contextMenu_->addSeparator( );
QAction* contextSelectionAction = contextMenu_->addMenu( contextSelectionMenu_ );
int topLevelAdded = 0;
if ( objectId != -1) {
emit updateContextMenu(objectId);
// Add an empty Menu defining the current Type
typeEntry->setText( typeName(object->dataType()) );
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+ typeIcon(object->dataType()) );
typeEntry->setIcon(icon);
// Add real context Menus first
for ( uint i = 0 ; i < contextMenus_.size(); ++i ) {
// check if the dataType of the object matches the context type
if ( object->dataType( contextMenus_[i].contextType ) ) {
if ( contextMenus_[i].position == CONTEXTTOPLEVELMENU ) {
contextMenu_->addMenu( contextMenus_[i].menu );
topLevelAdded++;
} else if ( contextMenus_[i].position == CONTEXTSELECTIONMENU ) {
contextSelectionMenu_->addMenu(contextMenus_[i].menu);
}
// Get all Actions in the menu and its submenus.
// Set their data to the picked Object id
QList< QAction *> allActions = contextMenus_[i].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( objectId ) );
if ( allActions[j]->menu() != 0 )
tmpList << allActions[j]->menu()->actions();
}
allActions = tmpList;
}
}
}
} else {
emit updateContextMenu(-1);
// Add real context Menus first
for ( uint i = 0 ; i < contextMenus_.size(); ++i ) {
if ( contextMenus_[i].contextType == DATA_NONE ) {
contextMenu_->addMenu( contextMenus_[i].menu );
topLevelAdded++;
}
}
if ( topLevelAdded == 0 ) {
contextMenu_->removeAction(typeEntry);
contextMenu_->removeAction(entrySeparator);
}
}
if ( contextSelectionMenu_->isEmpty() )
contextMenu_->removeAction( contextSelectionAction );
if ( topLevelAdded > 0 )
contextMenu_->addSeparator();
// Add persistent context Menus as second part
for ( uint i = 0 ; i < persistentContextMenus_.size(); ++i ) {
contextMenu_->addMenu( persistentContextMenus_[i].menu );
// Get all Actions in the menu and its submenus.
// Set their data to the picked Object id
QList< QAction *> allActions = persistentContextMenus_[i].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( objectId ) );
if ( allActions[j]->menu() != 0 )
tmpList << allActions[j]->menu()->actions();
}
allActions = tmpList;
}
}
// Only add Separator if we had plugin context menus
if ( persistentContextMenus_.size() > 0 )
contextMenu_->addSeparator();
if (examiner_widgets_[0]->getPickMenu() != NULL) {
if ( examiner_widgets_[0]->getPickMenu()->actions().size() > 0 ) {
examiner_widgets_[0]->getPickMenu()->setTitle("&Picking");
contextMenu_->addMenu(examiner_widgets_[0]->getPickMenu() );
examiner_widgets_[0]->getPickMenu()->setTearOffEnabled(true);
}
}
// Add a functions menu
QAction* action;
if ( functionMenu_ == 0 ){
functionMenu_ = new QMenu("&Functions",contextMenu_);
//====================================================================================================
action = functionMenu_->addAction("Snapshot");
action->setToolTip("Make a snapshot");
connect(action, SIGNAL(triggered()), this, SLOT( slotSnapshot() ) );
//====================================================================================================
action = functionMenu_->addAction("Set Snapshot Name");
action->setToolTip("Set a name for snapshots");
connect(action, SIGNAL(triggered()), this, SLOT(slotSnapshotName()) );
//====================================================================================================
functionMenu_->addSeparator();
//====================================================================================================
action = functionMenu_->addAction("Copy View");
action->setToolTip("Copy current view to clipboard");
connect(action, SIGNAL(triggered()), this, SLOT(slotCopyView()) );
//====================================================================================================
action = functionMenu_->addAction("Paste View");
action->setToolTip("Paste current view from clipboard");
connect(action, SIGNAL(triggered()), this , SLOT( slotPasteView( ) ) );
//====================================================================================================
functionMenu_->addSeparator();
//====================================================================================================
action = functionMenu_->addAction("Animation");
action->setToolTip("Animate rotation of objects");
action->setCheckable( true );
action->setChecked( PluginFunctions::viewerProperties().animation() );
connect(action, SIGNAL(triggered(bool)), this , SLOT( slotChangeAnimation(bool) ) );
//====================================================================================================
action = functionMenu_->addAction("Backface Culling");
action->setToolTip("Enable backface culling");
action->setCheckable( true );
action->setChecked( PluginFunctions::viewerProperties().backFaceCulling() );
connect(action, SIGNAL(triggered(bool)), this , SLOT( slotChangeBackFaceCulling(bool) ) );
//====================================================================================================
action = functionMenu_->addAction("Two-sided Lighting");
action->setToolTip("Enable two-sided lighting");
action->setCheckable( true );
action->setChecked( PluginFunctions::viewerProperties().twoSidedLighting() );
connect(action, SIGNAL(triggered(bool)), this , SLOT( slotChangeTwoSidedLighting(bool) ) );
functionMenu_->setTearOffEnabled(true);
}
contextMenu_->addMenu(functionMenu_ );
if ( ( examiner_widgets_[PluginFunctions::activeExaminer()]->getDrawMenu() != NULL ) && OpenFlipper::Options::drawModesInContextMenu() ) {
examiner_widgets_[PluginFunctions::activeExaminer()]->getDrawMenu()->setTitle("&DrawModes");
QAction* drawMenuAction = contextMenu_->addMenu(examiner_widgets_[PluginFunctions::activeExaminer()]->getDrawMenu() );
QIcon icon;
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"drawModes.png");
drawMenuAction->setIcon(icon);
examiner_widgets_[PluginFunctions::activeExaminer()]->getDrawMenu()->setTearOffEnabled(true);
}
}
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, "Save snapshot name" );
if (!fname.isEmpty())
{
fname.replace('$', '%');
PluginFunctions::viewerProperties().snapshotBaseFileName(fname);
QString msg="next snapshot: ";
statusBar()->showMessage(msg);
}
}
void CoreWidget::slotChangeAnimation(bool _animation){
if ( shiftPressed_ ){
for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
PluginFunctions::viewerProperties(i).animation(_animation);
}else
PluginFunctions::viewerProperties().animation(_animation);
}
void CoreWidget::slotChangeBackFaceCulling(bool _backFaceCulling){
if ( shiftPressed_ ){
for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
PluginFunctions::viewerProperties(i).backFaceCulling(_backFaceCulling);
}else
PluginFunctions::viewerProperties().backFaceCulling(_backFaceCulling);
}
void CoreWidget::slotChangeTwoSidedLighting(bool _lighting){
if ( shiftPressed_ ){
for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
PluginFunctions::viewerProperties(i).twoSidedLighting(_lighting);
}else
PluginFunctions::viewerProperties().twoSidedLighting(_lighting);
}
void CoreWidget::slotSnapshot() {
examiner_widgets_[PluginFunctions::activeExaminer()]->snapshot();
}
void CoreWidget::slotPasteView( ) {
examiner_widgets_[PluginFunctions::activeExaminer()]->actionPasteView();
}
void CoreWidget::slotCopyView( ) {
examiner_widgets_[PluginFunctions::activeExaminer()]->actionCopyView();
}
void CoreWidget::slotAddContextMenu(QMenu* _menu) {
MenuInfo info;
info.menu = _menu;
persistentContextMenus_.push_back(info);
}
void CoreWidget::slotAddContextMenu( QMenu* _menu , DataType _dataType ,ContextMenuType _type ) {
MenuInfo info;
info.menu = _menu;
info.contextType = _dataType;
info.position = _type;
contextMenus_.push_back(info);
}
//=============================================================================