From: vsr Date: Thu, 3 Apr 2014 09:38:08 +0000 (+0400) Subject: Merge branch V7_3_1_BR X-Git-Tag: V7_4_0a1^0 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=627194285d9b5354291d3a442b68b8740f114eda;hp=fa6b4c6615dbe469d185a85a934d0cf3c8faf39b;p=modules%2Fgui.git Merge branch V7_3_1_BR --- diff --git a/CMakeLists.txt b/CMakeLists.txt index b82a29a24..ef830e6da 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC) SET(${PROJECT_NAME_UC}_MAJOR_VERSION 7) SET(${PROJECT_NAME_UC}_MINOR_VERSION 3) -SET(${PROJECT_NAME_UC}_PATCH_VERSION 0) +SET(${PROJECT_NAME_UC}_PATCH_VERSION 1) SET(${PROJECT_NAME_UC}_VERSION ${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION}) SET(${PROJECT_NAME_UC}_VERSION_DEV 1) @@ -75,10 +75,12 @@ OPTION(SALOME_USE_PYCONSOLE "Enable Python GUI interface (Mandatory in classic c OPTION(SALOME_USE_QXGRAPHVIEWER "Enable QX graph visualization (Mandatory in classic configurations)" ON) CMAKE_DEPENDENT_OPTION(SALOME_USE_SALOMEOBJECT "Enable Salome Object (Mandatory in classic configurations)" ON "SALOME_LIGHT_ONLY" ON) +OPTION(SALOME_USE_SINGLE_DESKTOP "Enable multiple document interface" ON) MARK_AS_ADVANCED(SALOME_LIGHT_ONLY SALOME_USE_VTKVIEWER SALOME_USE_GRAPHICSVIEW) MARK_AS_ADVANCED(SALOME_USE_SALOMEOBJECT SALOME_USE_OCCVIEWER SALOME_USE_GLVIEWER SALOME_USE_PLOT2DVIEWER) MARK_AS_ADVANCED(SALOME_USE_PYCONSOLE SALOME_USE_QXGRAPHVIEWER) +MARK_AS_ADVANCED(SALOME_USE_SINGLE_DESKTOP) # Prerequisites # ============= @@ -129,6 +131,10 @@ IF(SALOME_GUI_USE_OBSERVERS) ADD_DEFINITIONS(-DWITH_SALOMEDS_OBSERVER) ENDIF() +IF(SALOME_USE_SINGLE_DESKTOP) + ADD_DEFINITIONS(-DSINGLE_DESKTOP) +ENDIF() + # OCCT FIND_PACKAGE(SalomeCAS REQUIRED) IF(NOT SALOME_USE_OCCVIEWER) @@ -150,7 +156,7 @@ ELSE() ENDIF() IF(SALOME_USE_VTKVIEWER) # Required components are listed in the FindSalomeVTK.cmake file: - FIND_PACKAGE(SalomeVTK 6.0) + FIND_PACKAGE(SalomeVTK 6.1) SALOME_LOG_OPTIONAL_PACKAGE(VTK SALOME_USE_VTKVIEWER) ELSE() ADD_DEFINITIONS("-DDISABLE_VTKVIEWER") diff --git a/SalomeGUIConfig.cmake.in b/SalomeGUIConfig.cmake.in index b658ac406..a2807ff0d 100644 --- a/SalomeGUIConfig.cmake.in +++ b/SalomeGUIConfig.cmake.in @@ -52,15 +52,51 @@ SET(SALOME_GUI_BUILD_TESTS @SALOME_BUILD_TESTS@) SET(SALOME_GUI_LIGHT_ONLY @SALOME_LIGHT_ONLY@) # Advanced options -SET(SALOME_USE_OCCVIEWER @SALOME_USE_OCCVIEWER@) -SET(SALOME_USE_GLVIEWER @SALOME_USE_GLVIEWER@) -SET(SALOME_USE_VTKVIEWER @SALOME_USE_VTKVIEWER@) -SET(SALOME_USE_PLOT2DVIEWER @SALOME_USE_PLOT2DVIEWER@) -SET(SALOME_USE_GRAPHICSVIEW @SALOME_USE_GRAPHICSVIEW@) -SET(SALOME_USE_QXGRAPHVIEWER @SALOME_USE_QXGRAPHVIEWER@) - -SET(SALOME_USE_PYCONSOLE @SALOME_USE_PYCONSOLE@) -SET(SALOME_USE_SALOMEOBJECT @SALOME_USE_SALOMEOBJECT@) +SET(SALOME_USE_OCCVIEWER @SALOME_USE_OCCVIEWER@) +SET(SALOME_USE_GLVIEWER @SALOME_USE_GLVIEWER@) +SET(SALOME_USE_VTKVIEWER @SALOME_USE_VTKVIEWER@) +SET(SALOME_USE_PLOT2DVIEWER @SALOME_USE_PLOT2DVIEWER@) +SET(SALOME_USE_GRAPHICSVIEW @SALOME_USE_GRAPHICSVIEW@) +SET(SALOME_USE_QXGRAPHVIEWER @SALOME_USE_QXGRAPHVIEWER@) +SET(SALOME_USE_PYCONSOLE @SALOME_USE_PYCONSOLE@) +SET(SALOME_USE_SALOMEOBJECT @SALOME_USE_SALOMEOBJECT@) +SET(SALOME_USE_SINGLE_DESKTOP @SALOME_USE_SINGLE_DESKTOP@) +SET(SALOME_GUI_USE_OBSERVERS @SALOME_GUI_USE_OBSERVERS@) + +IF(SALOME_GUI_LIGHT_ONLY) + LIST(APPEND GUI_DEFINITIONS "-DGUI_DISABLE_CORBA") +ENDIF() +IF(SALOME_USE_SINGLE_DESKTOP) + LIST(APPEND GUI_DEFINITIONS "-DSINGLE_DESKTOP") +ENDIF() +IF(SALOME_GUI_USE_OBSERVERS) + LIST(APPEND GUI_DEFINITIONS "-DWITH_SALOMEDS_OBSERVER") +ENDIF() +IF(NOT SALOME_USE_OCCVIEWER) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_OCCVIEWER") +ENDIF() +IF(NOT SALOME_USE_GLVIEWER) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_GLVIEWER") +ENDIF() + +IF(NOT SALOME_USE_VTKVIEWER) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_VTKVIEWER") +ENDIF() +IF(NOT SALOME_USE_PLOT2DVIEWER) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_PLOT2DVIEWER") +ENDIF() +IF (NOT SALOME_USE_GRAPHICSVIEW) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_GRAPHICSVIEW") +ENDIF() +IF(NOT SALOME_USE_PYCONSOLE) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_PYCONSOLE") +ENDIF() +IF(NOT SALOME_USE_QXGRAPHVIEWER) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_QXGRAPHVIEWER") +ENDIF() +IF(NOT SALOME_USE_SALOMEOBJECT) + LIST(APPEND GUI_DEFINITIONS "-DDISABLE_SALOMEOBJECT") +ENDIF() # Level 1 prerequisites: SET_AND_CHECK(KERNEL_ROOT_DIR_EXP "@PACKAGE_KERNEL_ROOT_DIR@") diff --git a/doc/salome/gui/images/plot2d_view_settings.png b/doc/salome/gui/images/plot2d_view_settings.png index 2b7ddffc7..e87556beb 100644 Binary files a/doc/salome/gui/images/plot2d_view_settings.png and b/doc/salome/gui/images/plot2d_view_settings.png differ diff --git a/doc/salome/gui/images/pref_salome_plot2dviewer.png b/doc/salome/gui/images/pref_salome_plot2dviewer.png index 339dbf950..b75a84069 100644 Binary files a/doc/salome/gui/images/pref_salome_plot2dviewer.png and b/doc/salome/gui/images/pref_salome_plot2dviewer.png differ diff --git a/doc/salome/gui/input/plot2d_viewer.doc b/doc/salome/gui/input/plot2d_viewer.doc index 11640c348..b5072eb85 100644 --- a/doc/salome/gui/input/plot2d_viewer.doc +++ b/doc/salome/gui/input/plot2d_viewer.doc @@ -138,16 +138,28 @@ The options are as follows: - Curve type you can select from \em Points, \em Lines or \em Spline. -- Show legend here you can define the position of the +- Marker size - size of the points (markers) forming curve lines. + +- Background color of the XY plot. + +- Selection color - this submenu allows to select the color of selected object in the viewer. + +- Legend allows specifying the properties of the legend. + + - Show legend - this options specifies if it's necessary to show legend by default. + + - Legend Position here you can define the position of the description table on the XY plot (to the \em Left, to the \em Right, on \em Top or on \em Bottom). + + - Symbol type you can select the type of legend item symbol from "Marker on line" or "Marker above line" -- Legend font here you can set type, face and color for the + - Legend font here you can set type, face and color for the font of Legend item. + + - Legend font color - this allows to select the color of the font of the legend item. -- Marker size - size of the points (markers) forming curve lines. - -- Background color of the XY plot. + - Highlighted legend font color - this submenu allows to select the color of the font of the selected legend item. - Deviation marker allows specifying the properties of the marker, which is used for drawing deviations data. diff --git a/doc/salome/gui/input/setting_preferences.doc b/doc/salome/gui/input/setting_preferences.doc index 9b0899efd..99d478271 100644 --- a/doc/salome/gui/input/setting_preferences.doc +++ b/doc/salome/gui/input/setting_preferences.doc @@ -186,39 +186,43 @@ titles displayed in the viewer: \image html pref_salome_plot2dviewer.png -- Show legend - this options specifies if it's necessary to -show legend by default. -- Legend Position - this submenu allows to set the default position -of the legend, it can be located to the left, to the right, on top or -on bottom of the graph. -- Legend font - this allows to set type and face for the font of Legend item. -- Curve Type - this allows to set the representation of graphs in -your presentations. You can see only Points, points connected with -Lines or points connected with smooth Splines. -- Marker Size - this submenu allows you to set the size of -markers in your graphs. -- Horizontal and Vertical axis scale - this submenus allow you to set -the scale for vertical and horizontal axes. It can be either Linear or -Logarithmic. Note that the Logarithmic scale can be used only -if the minimum value of corresponding component (abscissa or ordinate) -of all points displayed in the viewer is greater than zero. -If this condition is not met, the scale is switched to Linear -automatically, even if it is set to Logarithmic. - Background color - this submenu allows to select the background color. Click on the colored line to access to the \ref select_color_and_font_page "Select Color" dialog box. -- Legend font color - this allows to select the color of the -font of the legend item. -- Highlighted legend font color - this submenu allows to select -the color of the font of the selected legend item. - Selection color - this submenu allows to select the color of selected object in the viewer. -- Deviation marker color - this submenu allows to select the -color of the deviation marker. -- Deviation marker line width allows to define line width of -the deviation marker. -- Deviation marker tick size allows to define size of the upper -and lower horizontal lines of the deviation marker. +- Viewer - allows specifying the properties of the Plot 2D Viewer. + - Curve Type - this allows to set the representation of graphs in + your presentations. You can see only Points, points connected with + Lines or points connected with smooth Splines. + - Marker Size - this submenu allows you to set the size of + markers in your graphs. + - Horizontal and Vertical axis scale - this submenus allow you to set + the scale for vertical and horizontal axes. It can be either Linear or + Logarithmic. Note that the Logarithmic scale can be used only + if the minimum value of corresponding component (abscissa or ordinate) + of all points displayed in the viewer is greater than zero. + If this condition is not met, the scale is switched to Linear + automatically, even if it is set to Logarithmic. + - Deviation marker color - this submenu allows to select the + color of the deviation marker. + - Deviation marker line width allows to define line width of + the deviation marker. + - Deviation marker tick size allows to define size of the upper + and lower horizontal lines of the deviation marker. +- Legend - allows specifying the properties of the legend. + - Show legend - this options specifies if it's necessary to + show legend by default. + - Legend Position - this submenu allows to set the default position + of the legend, it can be located to the left, to the right, on top or + on bottom of the graph. + - Symbol type you can select the type of legend item symbol from "Marker on line" + or "Marker above line" + - Legend font - this allows to set type and face for the font of Legend item. + - Legend font color - this allows to select the color of the + font of the legend item. + - Highlighted legend font color - this submenu allows to select + the color of the font of the selected legend item.

Directories Preferences

diff --git a/doc/salome/gui/input/vtk_3d_viewer.doc b/doc/salome/gui/input/vtk_3d_viewer.doc index 2224cfa53..7d044babb 100644 --- a/doc/salome/gui/input/vtk_3d_viewer.doc +++ b/doc/salome/gui/input/vtk_3d_viewer.doc @@ -123,12 +123,12 @@ These buttons orientate the scene strictly about coordinate axes: \image html vtk_view_anticlockwise.png -Rotate counter-clockwise - rotates view 90� counter-clockwise. +Rotate counter-clockwise - rotates view 90° counter-clockwise.
\image html vtk_view_clockwise.png -Rotate clockwise - rotates view 90� clockwise. +Rotate clockwise - rotates view 90° clockwise.
\image html vtk_view_reset.png diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index e6970b23f..65afdae1b 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -868,8 +868,13 @@ void LightApp_Application::onNewWindow() void LightApp_Application::onNewDoc() { //asl: fix for 0020515 - if ( activeStudy() ) + if ( activeStudy() ) { saveDockWindowsState(); +#ifdef SINGLE_DESKTOP + if ( !closeDoc() ) + return; +#endif + } CAM_Application::onNewDoc(); } @@ -881,6 +886,12 @@ void LightApp_Application::onOpenDoc() { SUIT_Study* study = activeStudy(); saveDockWindowsState(); + if (study) { +#ifdef SINGLE_DESKTOP + if ( !closeDoc() ) + return; +#endif + } CAM_Application::onOpenDoc(); @@ -897,6 +908,12 @@ void LightApp_Application::onOpenDoc() */ bool LightApp_Application::onOpenDoc( const QString& aName ) { + if ( activeStudy() ) { +#ifdef SINGLE_DESKTOP + if ( !closeDoc() ) + return false; +#endif + } // We should take mru action first because this application instance can be deleted later. QtxMRUAction* mru = ::qobject_cast( action( MRUId ) ); @@ -2434,22 +2451,18 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref ) int plot2dGroup = pref->addPreference( tr( "PREF_GROUP_PLOT2DVIEWER" ), salomeCat ); //viewTab //pref->setItemProperty( "columns", 2, plot2dGroup ); - // ... -> show legend - pref->addPreference( tr( "PREF_SHOW_LEGEND" ), plot2dGroup, - LightApp_Preferences::Bool, "Plot2d", "ShowLegend" ); - // ... -> legend position - int legendPosition = pref->addPreference( tr( "PREF_LEGEND_POSITION" ), plot2dGroup, - LightApp_Preferences::Selector, "Plot2d", "LegendPos" ); - aValuesList.clear(); - anIndicesList.clear(); - aValuesList << tr("PREF_LEFT") << tr("PREF_RIGHT") << tr("PREF_TOP") << tr("PREF_BOTTOM"); - anIndicesList << 0 << 1 << 2 << 3 ; - pref->setItemProperty( "strings", aValuesList, legendPosition ); - pref->setItemProperty( "indexes", anIndicesList, legendPosition ); - // ... -> legend font - pref->addPreference( tr( "PREF_LEGEND_FONT" ), plot2dGroup, LightApp_Preferences::Font, "Plot2d", "LegendFont" ); - // ... -> curve type - int curveType = pref->addPreference( tr( "PREF_CURVE_TYPE" ), plot2dGroup, + // ... -> background + pref->addPreference( tr( "PREF_VIEWER_BACKGROUND_COLOR" ), plot2dGroup, + LightApp_Preferences::Color, "Plot2d", "Background" ); + // ... -> selection color + pref->addPreference( tr( "PREF_VIEWER_SELECTION" ), plot2dGroup, + LightApp_Preferences::Color, "Plot2d", "SelectionColor" ); + + // ... "Viewer" group <> + int plot2dViewerGroup = pref->addPreference( tr( "PREF_GROUP_VIEWER" ), plot2dGroup ); + + // .... -> curve type + int curveType = pref->addPreference( tr( "PREF_CURVE_TYPE" ), plot2dViewerGroup, LightApp_Preferences::Selector, "Plot2d", "CurveType" ); aValuesList.clear(); anIndicesList.clear(); @@ -2457,13 +2470,13 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref ) anIndicesList << 0 << 1 << 2 ; pref->setItemProperty( "strings", aValuesList, curveType ); pref->setItemProperty( "indexes", anIndicesList, curveType ); - // ... -> marker size - int markerSize = pref->addPreference( tr( "PREF_MARKER_SIZE" ), plot2dGroup, + // .... -> marker size + int markerSize = pref->addPreference( tr( "PREF_MARKER_SIZE" ), plot2dViewerGroup, LightApp_Preferences::IntSpin, "Plot2d", "MarkerSize" ); pref->setItemProperty( "min", 0, markerSize ); pref->setItemProperty( "max", 100, markerSize ); - // ... -> horizontal scaling mode - int horScale = pref->addPreference( tr( "PREF_HOR_AXIS_SCALE" ), plot2dGroup, + // .... -> horizontal scaling mode + int horScale = pref->addPreference( tr( "PREF_HOR_AXIS_SCALE" ), plot2dViewerGroup, LightApp_Preferences::Selector, "Plot2d", "HorScaleMode" ); aValuesList.clear(); anIndicesList.clear(); @@ -2471,34 +2484,59 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref ) anIndicesList << 0 << 1 ; pref->setItemProperty( "strings", aValuesList, horScale ); pref->setItemProperty( "indexes", anIndicesList, horScale ); - // ... -> vertical scaling mode - int verScale = pref->addPreference( tr( "PREF_VERT_AXIS_SCALE" ), plot2dGroup, + // .... -> vertical scaling mode + int verScale = pref->addPreference( tr( "PREF_VERT_AXIS_SCALE" ), plot2dViewerGroup, LightApp_Preferences::Selector, "Plot2d", "VerScaleMode" ); pref->setItemProperty( "strings", aValuesList, verScale ); pref->setItemProperty( "indexes", anIndicesList, verScale ); - // ... -> background - pref->addPreference( tr( "PREF_VIEWER_BACKGROUND_COLOR" ), plot2dGroup, - LightApp_Preferences::Color, "Plot2d", "Background" ); - // ... -> font color - pref->addPreference( tr( "PREF_FONT_COLOR" ), plot2dGroup, LightApp_Preferences::Color, "Plot2d", "LegendFontColor" ); - // ... -> selection font color - pref->addPreference( tr( "PREF_SELECTED_FONT_COLOR" ), plot2dGroup, LightApp_Preferences::Color, "Plot2d", "SelectedLegendFontColor" ); - // ... -> selection color - pref->addPreference( tr( "PREF_VIEWER_SELECTION" ), plot2dGroup, - LightApp_Preferences::Color, "Plot2d", "SelectionColor" ); - // ... -> errors/deviation colot - pref->addPreference( tr( "PREF_DEVIATION_COLOR" ), plot2dGroup, + + // .... -> errors/deviation colot + pref->addPreference( tr( "PREF_DEVIATION_COLOR" ), plot2dViewerGroup, LightApp_Preferences::Color, "Plot2d", "DeviationMarkerColor" ); - // ... -> deviation markers line size - int deviationMarkerLw = pref->addPreference( tr( "PREF_DEVIATION_MARKER_LW" ), plot2dGroup, + // .... -> deviation markers line size + int deviationMarkerLw = pref->addPreference( tr( "PREF_DEVIATION_MARKER_LW" ), plot2dViewerGroup, LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerLineWidth" ); pref->setItemProperty( "min", 1, deviationMarkerLw ); pref->setItemProperty( "max", 5, deviationMarkerLw ); - // ... -> deviation markers tick mark size - int deviationMarkerTs = pref->addPreference( tr( "PREF_DEVIATION_MARKER_TS" ), plot2dGroup, + // .... -> deviation markers tick mark size + int deviationMarkerTs = pref->addPreference( tr( "PREF_DEVIATION_MARKER_TS" ), plot2dViewerGroup, LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerTickSize" ); pref->setItemProperty( "min", 1, deviationMarkerTs ); pref->setItemProperty( "max", 5, deviationMarkerTs ); + // .... "Viewer" group <> + + // ... "Legend" group <> + int plot2dLegendGroup = pref->addPreference( tr( "PREF_GROUP_LEGEND" ), plot2dGroup ); + + // .... -> show legend + pref->addPreference( tr( "PREF_SHOW_LEGEND" ), plot2dLegendGroup, + LightApp_Preferences::Bool, "Plot2d", "ShowLegend" ); + // .... -> legend position + int legendPosition = pref->addPreference( tr( "PREF_LEGEND_POSITION" ), plot2dLegendGroup, + LightApp_Preferences::Selector, "Plot2d", "LegendPos" ); + aValuesList.clear(); + anIndicesList.clear(); + aValuesList << tr("PREF_LEFT") << tr("PREF_RIGHT") << tr("PREF_TOP") << tr("PREF_BOTTOM"); + anIndicesList << 0 << 1 << 2 << 3 ; + pref->setItemProperty( "strings", aValuesList, legendPosition ); + pref->setItemProperty( "indexes", anIndicesList, legendPosition ); + // .... -> Symbol type + int legendSymbolType = pref->addPreference( tr( "PREF_LEGEND_SYMBOL_TYPE" ), plot2dLegendGroup, + LightApp_Preferences::Selector, "Plot2d", "LegendSymbolType" ); + aValuesList.clear(); + anIndicesList.clear(); + aValuesList << tr("PREF_MARKER_ON_LINE") << tr("PREF_MARKER_ABOVE_LINE"); + anIndicesList << 0 << 1 ; + pref->setItemProperty( "strings", aValuesList, legendSymbolType ); + pref->setItemProperty( "indexes", anIndicesList, legendSymbolType ); + // .... -> legend font + pref->addPreference( tr( "PREF_LEGEND_FONT" ), plot2dLegendGroup, LightApp_Preferences::Font, "Plot2d", "LegendFont" ); + // ... -> font color + pref->addPreference( tr( "PREF_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "LegendFontColor" ); + // ... -> selection font color + pref->addPreference( tr( "PREF_SELECTED_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "SelectedLegendFontColor" ); + // ... "Legend" group <> + // .. "Plot2d viewer" group <> // .. "Directories" preferences tab <> @@ -2964,14 +3002,22 @@ void LightApp_Application::preferencesChanged( const QString& sec, const QString } #ifndef DISABLE_PLOT2DVIEWER - if ( sec == "Plot2d" ) { - if( param == "SelectionColor" ) { - QColor c = resMgr->colorValue( sec, param ); - Plot2d_Object::setSelectionColor(c); - } - else if (param == "SelectedLegendFontColor") { - QColor c = resMgr->colorValue( sec, param ); - Plot2d_Object::setHighlightedLegendTextColor(c); + QList lst; + viewManagers( Plot2d_Viewer::Type(), lst ); + QListIterator itPlot2d( lst ); + while ( itPlot2d.hasNext() ) { + SUIT_ViewManager* viewMgr = itPlot2d.next(); + SUIT_ViewModel* vm = viewMgr->getViewModel(); + if ( !vm || !vm->inherits( "Plot2d_Viewer" ) ) + continue; + + Plot2d_Viewer* Plot2dVM = dynamic_cast( vm ); + + viewMgr->setViewModel( vm ); + Plot2d_ViewWindow* wnd = dynamic_cast( viewMgr->getActiveView() ); + if( wnd ) { + Plot2d_ViewFrame* frame = wnd->getViewFrame(); + frame->SetPreference(); } } #endif diff --git a/src/LightApp/LightApp_PyInterp.cxx b/src/LightApp/LightApp_PyInterp.cxx index a138c7ac1..a172c10bc 100644 --- a/src/LightApp/LightApp_PyInterp.cxx +++ b/src/LightApp/LightApp_PyInterp.cxx @@ -22,15 +22,8 @@ // #include "LightApp_PyInterp.h" -#include -#include - -#include - /*! - * constructor : multi Python interpreter, one per SALOME study. - * calls initialize method defined in base class, which calls virtual methods - * initstate & initcontext redefined here. + * constructor : Python interpreter. */ LightApp_PyInterp::LightApp_PyInterp(): PyConsole_EnhInterp() { @@ -44,59 +37,16 @@ LightApp_PyInterp::~LightApp_PyInterp() } /*!\class LightApp_PyInterp - * EDF-CCAR - * When SALOME uses multi Python interpreter feature, - * Every study has its own interpreter and thread state (_tstate = Py_NewInterpreter()) - * This is fine because every study has its own modules (sys.modules) stdout and stderr - * BUT some Python modules must be imported only once. In multi interpreter context Python - * modules (*.py) are imported several times. - * The pyqt module must be imported only once because it registers classes in a C module. - * It's quite the same with omniorb modules (internals and generated with omniidl) - * This problem is handled with "shared modules" defined in salome_shared_modules.py - * These "shared modules" are imported only once and only copied in all the other interpreters - * BUT it's not the only problem. Every interpreter has its own __builtin__ module. That's fine - * but if we have copied some modules and imported others problems may arise with operations that - * are not allowed in restricted execution environment. So we must impose that all interpreters - * have identical __builtin__ module. - * That's all, for the moment ... + * [ABN] : there is now a single Python interpreter for the whole SALOME run. + * Different execution environment are provided to emulate independent + * "virtual" Python interpreters. */ -bool LightApp_PyInterp::initContext() -{ - /*! - * The GIL is assumed to be held - * It is the caller responsability caller to acquire the GIL - * It will still be held on initContext output - */ - if ( !PyConsole_Interp::initContext() ) - return false; - - //Import special module to change the import mechanism - PyObjWrapper m1( PyImport_ImportModule( "import_hook" ) ); - if ( !m1 ) - { - PyErr_Print(); - return false; - } - - // Call init_shared_modules to initialize the shared import mechanism for modules - //that must not be imported twice - PyObjWrapper m2( PyObject_CallMethod( m1, (char*)"init_shared_modules", (char*)"O", SUIT_PYTHON::salome_shared_modules_module ) ); - if ( !m2 ) - { - PyErr_Print(); - return false; - } - return true; -} - /*! Do nothing - The initialization has been done in main + The initialization has been done in main - see SUITApp/SUITApp.cxx - main() */ void LightApp_PyInterp::initPython() { - _gtstate=SUIT_PYTHON::_gtstate; // initialisation in main - _interp=SUIT_PYTHON::_interp; } diff --git a/src/LightApp/LightApp_PyInterp.h b/src/LightApp/LightApp_PyInterp.h index 9d4cb760d..de8c26636 100644 --- a/src/LightApp/LightApp_PyInterp.h +++ b/src/LightApp/LightApp_PyInterp.h @@ -33,7 +33,6 @@ public: protected: virtual void initPython(); - virtual bool initContext(); }; #endif //_LIGHTAPP_PYINTERP_H_ diff --git a/src/LightApp/resources/LightApp.xml b/src/LightApp/resources/LightApp.xml index 751f2293e..ff874775a 100644 --- a/src/LightApp/resources/LightApp.xml +++ b/src/LightApp/resources/LightApp.xml @@ -176,6 +176,7 @@ + diff --git a/src/LightApp/resources/LightApp_msg_en.ts b/src/LightApp/resources/LightApp_msg_en.ts index af04e4301..c9ccbaf8b 100644 --- a/src/LightApp/resources/LightApp_msg_en.ts +++ b/src/LightApp/resources/LightApp_msg_en.ts @@ -670,6 +670,26 @@ The changes will be applied on the next application session. PREF_GROUP_PLOT2DVIEWER Plot 2D Viewer + + PREF_GROUP_VIEWER + Viewer + + + PREF_GROUP_LEGEND + Legend + + + PREF_LEGEND_SYMBOL_TYPE + Symbol type: + + + PREF_MARKER_ABOVE_LINE + Marker above line + + + PREF_MARKER_ON_LINE + Marker on line + PREF_DEVIATION_COLOR Deviation marker color diff --git a/src/LightApp/resources/LightApp_msg_fr.ts b/src/LightApp/resources/LightApp_msg_fr.ts index 694b93bbd..c8496f275 100755 --- a/src/LightApp/resources/LightApp_msg_fr.ts +++ b/src/LightApp/resources/LightApp_msg_fr.ts @@ -670,6 +670,26 @@ Les modifications seront appliquées à la prochaine session. PREF_GROUP_PLOT2DVIEWER Scène Plot2d + + PREF_GROUP_VIEWER + Scène + + + PREF_GROUP_LEGEND + Légende + + + PREF_LEGEND_SYMBOL_TYPE + Type de symbole: + + + PREF_MARKER_ABOVE_LINE + Marqueur dessus de la ligne + + + PREF_MARKER_ON_LINE + Marqueur sur la ligne + PREF_DEVIATION_COLOR Couleur des marqueurs de déviation diff --git a/src/OCCViewer/OCCViewer_ClippingDlg.cxx b/src/OCCViewer/OCCViewer_ClippingDlg.cxx index 23b53653a..40ee9ad46 100644 --- a/src/OCCViewer/OCCViewer_ClippingDlg.cxx +++ b/src/OCCViewer/OCCViewer_ClippingDlg.cxx @@ -1,1507 +1,1507 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -#include "OCCViewer_ClippingDlg.h" - -#include -#include -#include -#include - -#include "SUIT_Session.h" -#include "SUIT_ViewWindow.h" -#include "SUIT_ViewManager.h" -#include "OCCViewer_ClipPlane.h" -#include "OCCViewer_ViewWindow.h" -#include "OCCViewer_ViewPort3d.h" -#include "OCCViewer_ViewModel.h" -#include "OCCViewer_ViewManager.h" -#include "OCCViewer_ClipPlaneInteractor.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// QT Includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/********************************************************************************** - ************************ Internal functions ************************ - *********************************************************************************/ - -void getMinMaxFromContext( Handle(AIS_InteractiveContext) ic, - double theDefaultSize, - double& theXMin, - double& theYMin, - double& theZMin, - double& theXMax, - double& theYMax, - double& theZMax) { - - double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; - aXMin = aYMin = aZMin = DBL_MAX; - aXMax = aYMax = aZMax = -DBL_MAX; - - bool isFound = false; - AIS_ListOfInteractive aList; - ic->DisplayedObjects( aList ); - for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() ) { - Handle(AIS_InteractiveObject) anObj = it.Value(); - if ( !anObj.IsNull() && anObj->HasPresentation() && - !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) ) { - Handle(Prs3d_Presentation) aPrs = anObj->Presentation(); - if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() ) { - isFound = true; - double xmin, ymin, zmin, xmax, ymax, zmax; - aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax ); - aXMin = qMin( aXMin, xmin ); aXMax = qMax( aXMax, xmax ); - aYMin = qMin( aYMin, ymin ); aYMax = qMax( aYMax, ymax ); - aZMin = qMin( aZMin, zmin ); aZMax = qMax( aZMax, zmax ); - } - } - } - - if(!isFound) { - if(theDefaultSize == 0.0) - theDefaultSize = 100.; - aXMin = aYMin = aZMin = -theDefaultSize; - aXMax = aYMax = aZMax = theDefaultSize; - } - theXMin = aXMin;theYMin = aYMin;theZMin = aZMin; - theXMax = aXMax;theYMax = aYMax;theZMax = aZMax; -} - -/*! - Compute the point of bounding box and current clipping plane - */ -void ComputeBoundsParam( const double theBounds[6], - const double theDirection[3], - double theMinPnt[3], - double& theMaxBoundPrj, - double& theMinBoundPrj ) -{ - double aEnlargeBounds[6]; - - // Enlarge bounds in order to avoid conflicts of precision - for(int i = 0; i < 6; i += 2) - { - static double EPS = 1.0E-3; - double aDelta = (theBounds[i+1] - theBounds[i])*EPS; - aEnlargeBounds[i ] = theBounds[i ] - aDelta; - aEnlargeBounds[i+1] = theBounds[i+1] + aDelta; - } - - double aBoundPoints[8][3] = { { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[4] }, - { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[4] }, - { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[4] }, - { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[4] }, - { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[5] }, - { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[5] }, - { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[5] }, - { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[5] } }; - - int aMaxId = 0; - theMaxBoundPrj = theDirection[0] * aBoundPoints[aMaxId][0] + theDirection[1] * aBoundPoints[aMaxId][1] - + theDirection[2] * aBoundPoints[aMaxId][2]; - theMinBoundPrj = theMaxBoundPrj; - for(int i = 1; i < 8; i++) { - double aTmp = theDirection[0] * aBoundPoints[i][0] + theDirection[1] * aBoundPoints[i][1] - + theDirection[2] * aBoundPoints[i][2]; - if(theMaxBoundPrj < aTmp) { - theMaxBoundPrj = aTmp; - aMaxId = i; - } - if(theMinBoundPrj > aTmp) { - theMinBoundPrj = aTmp; - } - } - double *aMinPnt = aBoundPoints[aMaxId]; - theMinPnt[0] = aMinPnt[0]; - theMinPnt[1] = aMinPnt[1]; - theMinPnt[2] = aMinPnt[2]; -} - -/*! - Compute the position of current plane by distance - */ -void DistanceToPosition( const double theBounds[6], - const double theDirection[3], - const double theDist, - double thePos[3] ) -{ - double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3]; - ComputeBoundsParam( theBounds, theDirection, aMinPnt, aMaxBoundPrj, aMinBoundPrj ); - double aLength = (aMaxBoundPrj - aMinBoundPrj) * theDist; - thePos[0] = aMinPnt[0] - theDirection[0] * aLength; - thePos[1] = aMinPnt[1] - theDirection[1] * aLength; - thePos[2] = aMinPnt[2] - theDirection[2] * aLength; -} - -/*! - Compute the parameters of clipping plane - */ -bool ComputeClippingPlaneParameters( const Handle(AIS_InteractiveContext)& theIC, - const double theDefaultSize, - const double theNormal[3], - const double theDist, - double theOrigin[3] ) -{ - double aBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; - - getMinMaxFromContext( theIC, theDefaultSize, aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5] ); - - DistanceToPosition( aBounds, theNormal, theDist, theOrigin ); - return true; -} - -/*! - \brief Converts relative plane parameters to absolute. - \param theIC [in] the interactive context. - \param theDefaultSize [in] the default trihedron size. - \param theDistance [in] the plane distance relative to minimum corner of model boundaries. - \param theDX [in] x component of plane direction. - \param theDY [in] y component of plane direction. - \param theDZ [in] z component of plane direction. - \param theX [out] x coordinate of plane origin. - \param theY [out] y coordinate of plane origin. - \param theZ [out] z coordinate of plane origin. - */ -bool DistanceToXYZ ( const Handle(AIS_InteractiveContext)& theIC, - const double theDefaultSize, - const double theDistance, - const double theDX, - const double theDY, - const double theDZ, - double& theX, - double& theY, - double& theZ ) -{ - double aNormal[3] = { theDX, theDY, theDZ }; - double anOrigin[3] = { 0.0, 0.0, 0.0 }; - - bool anIsOk = ComputeClippingPlaneParameters( theIC, theDefaultSize, aNormal, theDistance, anOrigin ); - - if( !anIsOk ) - { - return false; - } - - theX = anOrigin[0]; - theY = anOrigin[1]; - theZ = anOrigin[2]; - - return true; -} - -/*! - \brief Converts absolute position and direction to bounding box distance. - \param theIC [in] the interactive context. - \param theDefaultSize [in] the default trihedron size. - \param theX [in] x coordinate of plane origin. - \param theY [in] y coordinate of plane origin. - \param theZ [in] z coordinate of plane origin. - \param theDX [in] x component of plane direction. - \param theDY [in] y component of plane direction. - \param theDZ [in] z component of plane direction. - \param theDistance [out] the plane distance relative to minimum corner of model boundaries. - */ -void XYZToDistance ( const Handle(AIS_InteractiveContext)& theIC, - const double theDefaultSize, - const double theX, - const double theY, - const double theZ, - const double theDX, - const double theDY, - const double theDZ, - double& theDistance ) -{ - gp_Pnt aPlaneP( theX, theY, theZ ); - gp_Dir aPlaneN( theDX, theDY, theDZ ); - - double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; - - getMinMaxFromContext( theIC, theDefaultSize, aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); - - Bnd_Box aMinMax; - aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); - - gp_Trsf aRelativeTransform; - aRelativeTransform.SetTransformation( gp_Ax3(), gp_Ax3( aPlaneP, aPlaneN ) ); - Bnd_Box aRelativeBounds = aMinMax.Transformed( aRelativeTransform ); - - aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); - - double aLength = aZmax - aZmin; - double aDistance = aZmax; - - double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0; - aRelativeDistance = qMin( aRelativeDistance, aLength ); - aRelativeDistance = qMax( aRelativeDistance, 0.0 ); - theDistance = aRelativeDistance; -} - -/*! - Compute clipping plane size base point and normal - */ - -void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveContext) theContext, - double& theSize, gp_Pnt& theBasePnt, gp_Dir& theNormal, double defaultSize) { - double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; - aXMin = aYMin = aZMin = DBL_MAX; - aXMax = aYMax = aZMax = -DBL_MAX; - - getMinMaxFromContext(theContext,defaultSize,aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - double aSize = 50; - - double aNormalX = 0.0; - double aNormalY = 0.0; - double aNormalZ = 0.0; - theClipPlane.OrientationToXYZ( aNormalX, aNormalY, aNormalZ ); - gp_Pnt aBasePnt( theClipPlane.X, theClipPlane.Y, theClipPlane.Z ); - gp_Dir aNormal( aNormalX, aNormalY, aNormalZ ); - - // compute clipping plane size - gp_Pnt aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 ); - double aDiag = aCenter.Distance( gp_Pnt( aXMax, aYMax, aZMax ) )*2; - aSize = aDiag * 1.1; - - // compute clipping plane center ( redefine the base point ) - IntAna_IntConicQuad intersector = IntAna_IntConicQuad(); - - intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() ); - - if ( intersector.IsDone() && intersector.NbPoints() == 1 ) - aBasePnt = intersector.Point( 1 ); - - theSize = aSize; - theBasePnt = aBasePnt; - theNormal = aNormal; -} - - -/********************************************************************************* - ********************* class OCCViewer_ClippingDlg ********************* - *********************************************************************************/ -/*! - Constructor - \param view - view window - \param parent - parent widget -*/ -OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCViewer_Viewer* model) - : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ) -{ - setObjectName( "OCCViewer_ClippingDlg" ); - setModal( false ); - - setWindowTitle( tr( "Clipping" ) ); - - setAttribute (Qt::WA_DeleteOnClose, true); - - QVBoxLayout* topLayout = new QVBoxLayout( this ); - topLayout->setMargin( 11 ); topLayout->setSpacing( 6 ); - - /***************************************************************/ - // Controls for selecting, creating, deleting planes - QGroupBox* GroupPlanes = new QGroupBox( tr("CLIPPING_PLANES"), this ); - QHBoxLayout* GroupPlanesLayout = new QHBoxLayout( GroupPlanes ); - ComboBoxPlanes = new QComboBox( GroupPlanes ); - isActivePlane = new QCheckBox( tr("IS_ACTIVE_PLANE"), this ); - buttonNew = new QPushButton( tr("BTN_NEW"), GroupPlanes ); - buttonDelete = new QPushButton( tr("BTN_DELETE"), GroupPlanes ); - buttonDisableAll = new QPushButton( tr("BTN_DISABLE_ALL"), GroupPlanes ); - MenuMode = new QMenu( "MenuMode", buttonNew ); - MenuMode->addAction( tr( "ABSOLUTE" ), this, SLOT( onModeAbsolute() ) ); - MenuMode->addAction( tr( "RELATIVE" ), this, SLOT( onModeRelative() ) ); - buttonNew->setMenu( MenuMode ); - - GroupPlanesLayout->addWidget( ComboBoxPlanes ); - GroupPlanesLayout->addWidget( isActivePlane ); - GroupPlanesLayout->addWidget( buttonNew ); - GroupPlanesLayout->addWidget( buttonDelete ); - GroupPlanesLayout->addWidget( buttonDisableAll ); - - ModeStackedLayout = new QStackedLayout(); - - /********************** Mode Absolute **********************/ - /* Controls for absolute mode of clipping plane: - X, Y, Z - coordinates of the intersection of cutting plane and the three axes - Dx, Dy, Dz - components of normal to the cutting plane - Orientation - direction of cutting plane - */ - const double min = -1e+7; - const double max = 1e+7; - const double step = 5; - const int precision = -7; - - // Croup Point - QGroupBox* GroupAbsolutePoint = new QGroupBox( this ); - GroupAbsolutePoint->setObjectName( "GroupPoint" ); - GroupAbsolutePoint->setTitle( tr("BASE_POINT") ); - QGridLayout* GroupPointLayout = new QGridLayout( GroupAbsolutePoint ); - GroupPointLayout->setAlignment( Qt::AlignTop ); - GroupPointLayout->setSpacing( 6 ); GroupPointLayout->setMargin( 11 ); - - TextLabelX = new QLabel( GroupAbsolutePoint ); - TextLabelX->setObjectName( "TextLabelX" ); - TextLabelX->setText( tr("X:") ); - GroupPointLayout->addWidget( TextLabelX, 0, 0 ); - - SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); - SpinBox_X->setObjectName("SpinBox_X" ); - SpinBox_X->setPrecision( precision ); - GroupPointLayout->addWidget( SpinBox_X, 0, 1 ); - - TextLabelY = new QLabel( GroupAbsolutePoint ); - TextLabelY->setObjectName( "TextLabelY" ); - TextLabelY->setText( tr("Y:") ); - GroupPointLayout->addWidget( TextLabelY, 0, 2 ); - - SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); - SpinBox_Y->setObjectName("SpinBox_Y" ); - SpinBox_Y->setPrecision( precision ); - GroupPointLayout->addWidget( SpinBox_Y, 0, 3 ); - - TextLabelZ = new QLabel( GroupAbsolutePoint ); - TextLabelZ->setObjectName( "TextLabelZ" ); - TextLabelZ->setText( tr("Z:") ); - GroupPointLayout->addWidget( TextLabelZ, 0, 4 ); - - SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); - SpinBox_Z->setObjectName("SpinBox_Z" ); - SpinBox_Z->setPrecision( precision ); - GroupPointLayout->addWidget( SpinBox_Z, 0, 5 ); - - resetButton = new QPushButton( GroupAbsolutePoint ); - resetButton->setObjectName( "resetButton" ); - resetButton->setText( tr( "RESET" ) ); - GroupPointLayout->addWidget( resetButton, 0, 6 ); - - // Group Direction - GroupAbsoluteDirection = new QGroupBox( this ); - GroupAbsoluteDirection->setObjectName( "GroupDirection" ); - GroupAbsoluteDirection->setTitle( tr("DIRECTION") ); - QGridLayout* GroupDirectionLayout = new QGridLayout( GroupAbsoluteDirection ); - GroupDirectionLayout->setAlignment( Qt::AlignTop ); - GroupDirectionLayout->setSpacing( 6 ); - GroupDirectionLayout->setMargin( 11 ); - - TextLabelDx = new QLabel( GroupAbsoluteDirection ); - TextLabelDx->setObjectName( "TextLabelDx" ); - TextLabelDx->setText( tr("Dx:") ); - GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 ); - - SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); - SpinBox_Dx->setObjectName("SpinBox_Dx" ); - SpinBox_Dx->setPrecision( precision ); - GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 ); - - TextLabelDy = new QLabel( GroupAbsoluteDirection ); - TextLabelDy->setObjectName( "TextLabelDy" ); - TextLabelDy->setText( tr("Dy:") ); - GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 ); - - SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); - SpinBox_Dy->setObjectName("SpinBox_Dy" ); - SpinBox_Dy->setPrecision( precision ); - GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 ); - - TextLabelDz = new QLabel( GroupAbsoluteDirection ); - TextLabelDz->setObjectName( "TextLabelDz" ); - TextLabelDz->setText( tr("Dz:") ); - GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 ); - - SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); - SpinBox_Dz->setObjectName("SpinBox_Dz" ); - SpinBox_Dz->setPrecision( precision ); - GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 ); - - invertButton = new QPushButton( GroupAbsoluteDirection ); - invertButton->setObjectName( "invertButton" ); - invertButton->setText( tr( "INVERT" ) ); - GroupDirectionLayout->addWidget( invertButton, 0, 6 ); - - CBAbsoluteOrientation = new QComboBox( GroupAbsoluteDirection ); - CBAbsoluteOrientation->setObjectName( "AbsoluteOrientation" ); - CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "CUSTOM" ) ); - CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||X-Y" ) ); - CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Y-Z" ) ); - CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Z-X" ) ); - GroupDirectionLayout->addWidget( CBAbsoluteOrientation, 1, 0, 1, 6 ); - - QVBoxLayout* ModeActiveLayout = new QVBoxLayout(); - ModeActiveLayout->setMargin( 11 ); ModeActiveLayout->setSpacing( 6 ); - ModeActiveLayout->addWidget( GroupAbsolutePoint ); - ModeActiveLayout->addWidget( GroupAbsoluteDirection ); - - QWidget* ModeActiveWidget = new QWidget( this ); - ModeActiveWidget->setLayout( ModeActiveLayout ); - - /********************** Mode Relative **********************/ - /* Controls for relative mode of clipping plane: - Distance - Value from 0 to 1. - Specifies the distance from the minimum value in a given direction of bounding box to the current position - Rotation1, Rotation2 - turn angles of cutting plane in given directions - Orientation - direction of cutting plane - */ - QGroupBox* GroupParameters = new QGroupBox( tr("PARAMETERS"), this ); - QGridLayout* GroupParametersLayout = new QGridLayout( GroupParameters ); - GroupParametersLayout->setMargin( 11 ); GroupParametersLayout->setSpacing( 6 ); - - TextLabelOrientation = new QLabel( tr("ORIENTATION"), GroupParameters); - TextLabelOrientation->setObjectName( "TextLabelOrientation" ); - GroupParametersLayout->addWidget( TextLabelOrientation, 0, 0 ); - - CBRelativeOrientation = new QComboBox(GroupParameters); - CBRelativeOrientation->setObjectName( "RelativeOrientation" ); - CBRelativeOrientation->addItem( tr("ALONG_XY") ); - CBRelativeOrientation->addItem( tr("ALONG_YZ") ); - CBRelativeOrientation->addItem( tr("ALONG_ZX") ); - GroupParametersLayout->addWidget( CBRelativeOrientation, 0, 1 ); - - TextLabelDistance = new QLabel( tr("DISTANCE"), GroupParameters ); - TextLabelDistance->setObjectName( "TextLabelDistance" ); - GroupParametersLayout->addWidget( TextLabelDistance, 1, 0 ); - - SpinSliderDistance = new QtxDoubleSpinSlider( 0., 1., 0.01, GroupParameters ); - SpinSliderDistance->setObjectName( "SpinSliderDistance" ); - SpinSliderDistance->setPrecision( precision ); - QFont fnt = SpinSliderDistance->font(); fnt.setBold( true ); SpinSliderDistance->setFont( fnt ); - GroupParametersLayout->addWidget( SpinSliderDistance, 1, 1 ); - - QString aUnitRot = "\xB0"; - - TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters ); - TextLabelRotation1->setObjectName( "TextLabelRotation1" ); - GroupParametersLayout->addWidget( TextLabelRotation1, 2, 0 ); - - SpinSliderRotation1 = new QtxIntSpinSlider( -180, 180, 1, GroupParameters ); - SpinSliderRotation1->setObjectName( "SpinSliderRotation1" ); - SpinSliderRotation1->setUnit( aUnitRot ); - SpinSliderRotation1->setFont( fnt ); - GroupParametersLayout->addWidget( SpinSliderRotation1, 2, 1 ); - - TextLabelRotation2 = new QLabel(tr("ROTATION_AROUND_Y_X2Z"), GroupParameters); - TextLabelRotation2->setObjectName( "TextLabelRotation2" ); - TextLabelRotation2->setObjectName( "TextLabelRotation2" ); - GroupParametersLayout->addWidget( TextLabelRotation2, 3, 0 ); - - SpinSliderRotation2 = new QtxIntSpinSlider( -180, 180, 1, GroupParameters ); - SpinSliderRotation2->setObjectName( "SpinSliderRotation2" ); - SpinSliderRotation2->setUnit( aUnitRot ); - SpinSliderRotation2->setFont( fnt ); - GroupParametersLayout->addWidget( SpinSliderRotation2, 3, 1 ); - - /***************************************************************/ - QGroupBox* CheckBoxWidget = new QGroupBox( this ); - QHBoxLayout* CheckBoxLayout = new QHBoxLayout( CheckBoxWidget ); - - PreviewCheckBox = new QCheckBox( tr("PREVIEW"), CheckBoxWidget ); - PreviewCheckBox->setObjectName( "PreviewCheckBox" ); - PreviewCheckBox->setChecked( true ); - CheckBoxLayout->addWidget( PreviewCheckBox, 0, Qt::AlignCenter ); - - AutoApplyCheckBox = new QCheckBox( tr("AUTO_APPLY"), CheckBoxWidget ); - AutoApplyCheckBox->setObjectName( "AutoApplyCheckBox" ); - CheckBoxLayout->addWidget( AutoApplyCheckBox, 0, Qt::AlignCenter ); - - /***************************************************************/ - QGroupBox* GroupButtons = new QGroupBox( this ); - QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons ); - GroupButtonsLayout->setAlignment( Qt::AlignTop ); - GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 ); - - buttonOk = new QPushButton( GroupButtons ); - buttonOk->setObjectName( "buttonOk" ); - buttonOk->setText( tr( "BUT_APPLY_AND_CLOSE" ) ); - buttonOk->setAutoDefault( TRUE ); - buttonOk->setDefault( TRUE ); - GroupButtonsLayout->addWidget( buttonOk ); - - buttonApply = new QPushButton( GroupButtons ); - buttonApply->setObjectName( "buttonApply" ); - buttonApply->setText( tr( "BUT_APPLY" ) ); - buttonApply->setAutoDefault( TRUE ); - buttonApply->setDefault( TRUE ); - GroupButtonsLayout->addWidget( buttonApply ); - - GroupButtonsLayout->addStretch(); - - buttonClose = new QPushButton( GroupButtons ); - buttonClose->setObjectName( "buttonClose" ); - buttonClose->setText( tr( "BUT_CLOSE" ) ); - buttonClose->setAutoDefault( TRUE ); - GroupButtonsLayout->addWidget( buttonClose ); - - QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons ); - buttonHelp->setAutoDefault( TRUE ); - GroupButtonsLayout->addWidget( buttonHelp ); - - /***************************************************************/ - ModeStackedLayout->addWidget( ModeActiveWidget ); - ModeStackedLayout->addWidget( GroupParameters ); - - topLayout->addWidget( GroupPlanes ); - topLayout->addLayout( ModeStackedLayout ); - topLayout->addWidget( CheckBoxWidget ); - topLayout->addWidget( GroupButtons ); - - this->setLayout( topLayout ); - - // Initializations - initParam(); - - // Signals and slots connections - connect( ComboBoxPlanes, SIGNAL( activated( int ) ), this, SLOT( onSelectPlane( int ) ) ); - connect( isActivePlane, SIGNAL ( toggled ( bool ) ), this, SLOT( onValueChanged() ) ); - connect( buttonNew, SIGNAL( clicked() ), buttonNew, SLOT( showMenu() ) ); - connect( buttonDelete, SIGNAL( clicked() ), this, SLOT( ClickOnDelete() ) ); - connect( buttonDisableAll, SIGNAL( clicked() ), this, SLOT( ClickOnDisableAll() ) ); - - connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) ); - connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ; - connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( CBAbsoluteOrientation, SIGNAL ( activated ( int ) ), this, SLOT( onOrientationAbsoluteChanged( int ) ) ) ; - - connect( CBRelativeOrientation, SIGNAL( activated( int ) ), this, SLOT( onOrientationRelativeChanged( int ) ) ); - connect( SpinSliderDistance, SIGNAL( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); - connect( SpinSliderRotation1, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) ); - connect( SpinSliderRotation2, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) ); - - connect( PreviewCheckBox, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ; - connect( AutoApplyCheckBox, SIGNAL ( toggled( bool ) ), this, SLOT( onAutoApply( bool ) ) ); - - connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ; - connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); - connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); - connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) ); - - myBusy = false; - myIsSelectPlane = false; - myIsPlaneCreation = false; - myIsUpdatingControls = false; - myModel = model; - - myModel->getViewer3d()->InitActiveViews(); - - OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) myModel->getViewManager(); - myInteractor = new OCCViewer_ClipPlaneInteractor( aViewMgr, this ); - connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ) ), SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) ); - connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ) ), SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) ); - - myLocalPlanes = myModel->getClipPlanes(); - synchronize(); -} - -/*! - Destructor - Destroys the object and frees any allocated resources -*/ -OCCViewer_ClippingDlg::~OCCViewer_ClippingDlg() -{ - myLocalPlanes.clear(); -} - -/*! - Custom handling of close event: erases preview -*/ -void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e ) -{ - erasePreview(); - QDialog::closeEvent( e ); - OCCViewer_ViewWindow* v = qobject_cast(parent()); - if(v) - v->onClipping(false); -} - -/*! - Custom handling of show event: displays preview -*/ -void OCCViewer_ClippingDlg::showEvent( QShowEvent* e ) -{ - QDialog::showEvent( e ); - onPreview( PreviewCheckBox->isChecked() ); -} - -/*! - Custom handling of hide event: erases preview -*/ -void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e ) -{ - erasePreview(); - QDialog::hideEvent( e ); - OCCViewer_ViewWindow* v = qobject_cast(parent()); - if(v) - v->onClipping(false); - -} - -/*! - Initialization of initial values of widgets -*/ -void OCCViewer_ClippingDlg::initParam() -{ - SpinBox_X->setValue( 0.0 ); - SpinBox_Y->setValue( 0.0 ); - SpinBox_Z->setValue( 0.0 ); - - SpinBox_Dx->setValue( 1.0 ); - SpinBox_Dy->setValue( 1.0 ); - SpinBox_Dz->setValue( 1.0 ); - - CBAbsoluteOrientation->setCurrentIndex(0); - - SpinSliderDistance->setValue( 0.5 ); - SpinSliderRotation1->setValue( 0 ); - SpinSliderRotation2->setValue( 0 ); - CBRelativeOrientation->setCurrentIndex( 0 ); - - isActivePlane->setChecked( true ); -} - -/*! - Set plane parameters from widgets. -*/ -void OCCViewer_ClippingDlg::setPlaneParam( OCCViewer_ClipPlane& thePlane ) -{ - OCCViewer_ClipPlane::PlaneMode aMode = currentPlaneMode(); - - thePlane.Mode = aMode; - - if ( aMode == OCCViewer_ClipPlane::Absolute ) - { - if( qFuzzyIsNull( SpinBox_Dx->value() ) && - qFuzzyIsNull( SpinBox_Dy->value() ) && - qFuzzyIsNull( SpinBox_Dz->value() ) ) { - return; - } - } - - thePlane.OrientationType = (aMode == OCCViewer_ClipPlane::Absolute) - ? CBAbsoluteOrientation->currentIndex() - : CBRelativeOrientation->currentIndex(); - - // Get XYZ, DXYZ - if ( aMode == OCCViewer_ClipPlane::Absolute ) - { - if ( thePlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom ) - { - thePlane.AbsoluteOrientation.Dx = SpinBox_Dx->value(); - thePlane.AbsoluteOrientation.Dy = SpinBox_Dy->value(); - thePlane.AbsoluteOrientation.Dz = SpinBox_Dz->value(); - } - else - { - thePlane.AbsoluteOrientation.IsInvert = SpinBox_Dx->value() < 0.0 - || SpinBox_Dy->value() < 0.0 - || SpinBox_Dz->value() < 0.0; - } - - thePlane.X = SpinBox_X->value(); - thePlane.Y = SpinBox_Y->value(); - thePlane.Z = SpinBox_Z->value(); - } - else - { - thePlane.RelativeOrientation.Rotation1 = SpinSliderRotation1->value(); - thePlane.RelativeOrientation.Rotation2 = SpinSliderRotation2->value(); - - double aPlaneDx = 0.0; - double aPlaneDy = 0.0; - double aPlaneDz = 0.0; - double aX = 0.0; - double aY = 0.0; - double aZ = 0.0; - - OCCViewer_ClipPlane::RelativeToDXYZ( thePlane.OrientationType, - thePlane.RelativeOrientation.Rotation1, - thePlane.RelativeOrientation.Rotation2, - aPlaneDx, aPlaneDy, aPlaneDz ); - - DistanceToXYZ( myModel->getAISContext(), - myModel->trihedronSize(), - SpinSliderDistance->value(), - aPlaneDx, aPlaneDy, aPlaneDz, - aX, aY, aZ ); - - thePlane.X = aX; - thePlane.Y = aY; - thePlane.Z = aZ; - } - - thePlane.IsOn = isActivePlane->isChecked(); -} - -/*! - Synchronize dialog's widgets with data -*/ -void OCCViewer_ClippingDlg::synchronize() -{ - ComboBoxPlanes->clear(); - int aNbPlanesAbsolute = myLocalPlanes.size(); - - QString aName; - for(int i = 1; i<=aNbPlanesAbsolute; i++ ) { - aName = QString("Plane %1").arg(i); - ComboBoxPlanes->addItem( aName ); - } - - int aPos = ComboBoxPlanes->count() - 1; - ComboBoxPlanes->setCurrentIndex( aPos ); - - bool anIsControlsEnable = ( aPos >= 0 ); - if ( anIsControlsEnable ) { - onSelectPlane( aPos ); - } - else { - ComboBoxPlanes->addItem( tr( "NO_PLANES" ) ); - initParam(); - } - if ( currentPlaneMode() == OCCViewer_ClipPlane::Absolute ) - { - SpinBox_X->setEnabled( anIsControlsEnable ); - SpinBox_Y->setEnabled( anIsControlsEnable ); - SpinBox_Z->setEnabled( anIsControlsEnable ); - SpinBox_Dx->setEnabled( anIsControlsEnable ); - SpinBox_Dy->setEnabled( anIsControlsEnable ); - SpinBox_Dz->setEnabled( anIsControlsEnable ); - CBAbsoluteOrientation->setEnabled( anIsControlsEnable ); - invertButton->setEnabled( anIsControlsEnable ); - resetButton->setEnabled( anIsControlsEnable ); - } - else if ( currentPlaneMode() == OCCViewer_ClipPlane::Relative ) - { - CBRelativeOrientation->setEnabled( anIsControlsEnable ); - SpinSliderDistance->setEnabled( anIsControlsEnable ); - SpinSliderRotation1->setEnabled( anIsControlsEnable ); - SpinSliderRotation2->setEnabled( anIsControlsEnable ); - isActivePlane->setEnabled( anIsControlsEnable ); - } - isActivePlane->setEnabled( anIsControlsEnable ); -} - -/*! - Displays preview of clipping plane -*/ -void OCCViewer_ClippingDlg::displayPreview() -{ - if ( myBusy || !isValid() || !myModel) - return; - - Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); - - int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); - - for ( int i=0; i < clipPlanesCount(); i++ ) { - OCCViewer_ClipPlane& aClipPlane = getClipPlane(i); - if ( aClipPlane.IsOn ) { - Handle(AIS_Plane) myPreviewPlane; - double aSize; - gp_Pnt aBasePnt; - gp_Dir aNormal; - clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize()); - myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt ); - myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR ); - myPreviewPlane->SetSize( aSize, aSize ); - ic->SetWidth( myPreviewPlane, 10, false ); - ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false ); - ic->SetTransparency( myPreviewPlane, 0.5, false ); - Quantity_Color c = (aCurPlaneIndex == i) ? Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ) : Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ); - ic->SetColor( myPreviewPlane, c , false ); - ic->Display( myPreviewPlane, 1, 0, false ); - myPreviewPlaneVector.push_back( myPreviewPlane ); - } - } - myModel->update(); - - double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; - getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5, - (aYmax + aYmin) * 0.5, - (aZmax + aZmin) * 0.5 ); - Bnd_Box aMinMax; - aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); - - myInteractor->setPlanes( myPreviewPlaneVector ); - myInteractor->setRotationCenter( aRotationCenter ); - myInteractor->setMinMax( aMinMax ); - myInteractor->setEnabled( true ); -} - -void OCCViewer_ClippingDlg::updatePreview() { - int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); - int count = clipPlanesCount(); - if ( myBusy || - !isValid() || - myIsPlaneCreation || - !myModel || - count == 0 || - (aCurPlaneIndex +1 > count) || - !PreviewCheckBox->isChecked()) - return; - - Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); - - OCCViewer_ClipPlane& aClipPlane = getClipPlane(aCurPlaneIndex); - Handle(AIS_Plane) myPreviewPlane; - - if (aClipPlane.IsOn) { - double aSize; - gp_Pnt aBasePnt; - gp_Dir aNormal; - clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize()); - if(myPreviewPlaneVector.size() < clipPlanesCount()) { - myPreviewPlaneVector.resize(clipPlanesCount()); - } - myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex]; - if(myPreviewPlane.IsNull()) { - //Plane was not created - myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt ); - myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR ); - myPreviewPlane->SetSize( aSize, aSize ); - ic->Display( myPreviewPlane, 1, 0, false ); - ic->SetWidth( myPreviewPlane, 10, false ); - ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false ); - ic->SetTransparency( myPreviewPlane, 0.5, false ); - myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane; - } else { - myPreviewPlane->SetComponent( new Geom_Plane( aBasePnt, aNormal ) ); - myPreviewPlane->SetCenter( aBasePnt ); - myPreviewPlane->SetSize( aSize, aSize ); - } - - ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false ); - ic->Update( myPreviewPlane, Standard_False ); - } else { - if(myPreviewPlaneVector.size() > aCurPlaneIndex ) { - myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex]; - if(ic->IsDisplayed(myPreviewPlane)) { - ic->Erase( myPreviewPlane, false ); - ic->Remove( myPreviewPlane, false ); - } - myPreviewPlaneVector[aCurPlaneIndex].Nullify(); - } - } - for(int i = 0; i < myPreviewPlaneVector.size(); i++) { - if( i == aCurPlaneIndex ) continue; - if(!myPreviewPlaneVector[i].IsNull()) - ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false ); - } - myModel->update(); - - double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; - getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5, - (aYmax + aYmin) * 0.5, - (aZmax + aZmin) * 0.5 ); - Bnd_Box aMinMax; - aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); - - myInteractor->setPlanes( myPreviewPlaneVector ); - myInteractor->setRotationCenter( aRotationCenter ); - myInteractor->setMinMax( aMinMax ); -} - -/*! - Erases preview of clipping plane -*/ -void OCCViewer_ClippingDlg::erasePreview() -{ - if ( !myModel ) - return; - - Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); - - for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) { - Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i]; - if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) { - ic->Erase( myPreviewPlane, false ); - ic->Remove( myPreviewPlane, false ); - myPreviewPlane.Nullify(); - } - } - myPreviewPlaneVector.clear(); - myModel->update(); - myInteractor->setEnabled( false ); -} - -/*! - Return true if plane parameters are valid -*/ -bool OCCViewer_ClippingDlg::isValid() -{ - return ( SpinBox_Dx->value() !=0 || SpinBox_Dy->value() !=0 || SpinBox_Dz->value() !=0 ); -} - -/*! - Update view after changes -*/ -void OCCViewer_ClippingDlg::updateClipping() -{ - if (PreviewCheckBox->isChecked() || AutoApplyCheckBox->isChecked()) - { - if (AutoApplyCheckBox->isChecked()) { - onApply(); - } - - if (!PreviewCheckBox->isChecked()) - myModel->update(); - else - updatePreview(); - } -} - -/*! - Updates state of user controls. -*/ -void OCCViewer_ClippingDlg::updateControls() -{ - if ( clipPlanesCount() == 0 ) - { - initParam(); - return; - } - - int aPlaneIdx = ComboBoxPlanes->currentIndex(); - - OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx ); - - double aPlaneDx = 0.0; - double aPlaneDy = 0.0; - double aPlaneDz = 0.0; - double aDistance = 0.0; - aPlane.OrientationToXYZ( aPlaneDx, aPlaneDy, aPlaneDz ); - - if ( aPlane.Mode == OCCViewer_ClipPlane::Absolute ) - { - ModeStackedLayout->setCurrentIndex( 0 ); - - // Set plane parameters in the dialog - SpinBox_X->setValue( aPlane.X ); - SpinBox_Y->setValue( aPlane.Y ); - SpinBox_Z->setValue( aPlane.Z ); - SpinBox_Dx->setValue( aPlaneDx ); - SpinBox_Dy->setValue( aPlaneDy ); - SpinBox_Dz->setValue( aPlaneDz ); - CBAbsoluteOrientation->setCurrentIndex( aPlane.OrientationType ); - onOrientationAbsoluteChanged( aPlane.OrientationType ); - } - else if( aPlane.Mode == OCCViewer_ClipPlane::Relative ) - { - ModeStackedLayout->setCurrentIndex( 1 ); - - // Set plane parameters in the dialog - SpinSliderRotation1->setValue( int( aPlane.RelativeOrientation.Rotation1 ) ); - SpinSliderRotation2->setValue( int( aPlane.RelativeOrientation.Rotation2 ) ); - - XYZToDistance( myModel->getAISContext(), - myModel->trihedronSize(), - aPlane.X, aPlane.Y, aPlane.Z, - aPlaneDx, aPlaneDy, aPlaneDz, - aDistance ); - - SpinSliderDistance->setValue( aDistance ); - - CBRelativeOrientation->setCurrentIndex( aPlane.OrientationType ); - onOrientationRelativeChanged( aPlane.OrientationType ); - } - - isActivePlane->setChecked( aPlane.IsOn ); -} - -/*! - SLOT on new button click: create a new clipping plane -*/ -void OCCViewer_ClippingDlg::ClickOnNew() -{ - OCCViewer_ClipPlane aClipPlane; - - // init controls state - myIsUpdatingControls = true; - initParam(); - myIsUpdatingControls = false; - - // init plane according to the state of controls - setPlaneParam( aClipPlane ); - - // add plane - myLocalPlanes.push_back( aClipPlane ); - synchronize(); -} - -/*! - SLOT on delete button click: Delete selected clipping plane -*/ -void OCCViewer_ClippingDlg::ClickOnDelete() -{ - int aPlaneIndex = ComboBoxPlanes->currentIndex(); - if ( (clipPlanesCount() == 0) || (aPlaneIndex+1 > clipPlanesCount())) - return; - - myLocalPlanes.erase(myLocalPlanes.begin() + aPlaneIndex); - - Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); - - if(aPlaneIndex+1 <= myPreviewPlaneVector.size()) { - Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[aPlaneIndex]; - if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) { - ic->Erase( myPreviewPlane, false ); - ic->Remove( myPreviewPlane, false ); - } - myPreviewPlaneVector.erase(myPreviewPlaneVector.begin() + aPlaneIndex); - } - synchronize(); - if (AutoApplyCheckBox->isChecked()) { - onApply(); - } - myModel->update(); -} - -/*! - SLOT on disable all button click: Restore initial state of viewer, - erase all clipping planes -*/ -void OCCViewer_ClippingDlg::ClickOnDisableAll() -{ - AutoApplyCheckBox->setChecked (false); - int aClipPlanesCount = clipPlanesCount(); - for ( int anIndex = 0; anIndex < aClipPlanesCount; anIndex++) - { - OCCViewer_ClipPlane& aPlane = getClipPlane(anIndex); - aPlane.IsOn = false; - } - erasePreview(); - isActivePlane->setChecked(false); - myModel->setClipPlanes(myLocalPlanes); - myModel->update(); -} - -/*! - SLOT on ok button click: sets cutting plane and closes dialog -*/ -void OCCViewer_ClippingDlg::ClickOnOk() -{ - onApply(); - ClickOnClose(); -} - -/*! - SLOT on Apply button click: sets cutting plane and update viewer -*/ -void OCCViewer_ClippingDlg::ClickOnApply() -{ - onApply(); - myModel->update(); -} - -/*! - SLOT on close button click: erases preview and rejects dialog -*/ -void OCCViewer_ClippingDlg::ClickOnClose() -{ - erasePreview(); - OCCViewer_ViewWindow* v = qobject_cast(parent()); - if(v) - v->onClipping(false); -} - -/*! - SLOT on help button click: opens a help page -*/ -void OCCViewer_ClippingDlg::ClickOnHelp() -{ - SUIT_Application* app = SUIT_Session::session()->activeApplication(); - if ( app ) - app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" ); -} - -/*! - Set absolute mode of clipping plane -*/ -void OCCViewer_ClippingDlg::onModeAbsolute() -{ - myIsPlaneCreation = true; - ModeStackedLayout->setCurrentIndex(0); - ClickOnNew(); - myIsPlaneCreation = false; - updateClipping(); -} - -/*! - Set relative mode of clipping plane -*/ -void OCCViewer_ClippingDlg::onModeRelative() -{ - myIsPlaneCreation = true; - ModeStackedLayout->setCurrentIndex(1); - ClickOnNew(); - myIsPlaneCreation = false; - SetCurrentPlaneParam(); - updateClipping(); -} - -/*! - SLOT: called on value of clipping plane changed -*/ -void OCCViewer_ClippingDlg::onValueChanged() -{ - if ( myIsUpdatingControls ) - { - return; - } - - SetCurrentPlaneParam(); - - if ( myIsSelectPlane ) - { - return; - } - - updateClipping(); -} - -/*! - Set current parameters of selected plane -*/ -void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex ) -{ - if ( clipPlanesCount() == 0 ) - { - return; - } - - OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex ); - - myIsSelectPlane = true; - updateControls(); - ComboBoxPlanes->setCurrentIndex( theIndex ); - myIsSelectPlane = false; -} - -/*! - Restore parameters of selected plane -*/ -void OCCViewer_ClippingDlg::SetCurrentPlaneParam() -{ - if ( clipPlanesCount() == 0 || myIsSelectPlane || myBusy ) - { - return; - } - - int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); - - OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); - - setPlaneParam( aPlane ); -} - -/*! - SLOT on reset button click: sets default values -*/ -void OCCViewer_ClippingDlg::onReset() -{ - myBusy = true; - SpinBox_X->setValue(0); - SpinBox_Y->setValue(0); - SpinBox_Z->setValue(0); - myBusy = false; - - updateClipping(); -} - -/*! - SLOT on invert button click: inverts normal of cutting plane -*/ -void OCCViewer_ClippingDlg::onInvert() -{ - double Dx = SpinBox_Dx->value(); - double Dy = SpinBox_Dy->value(); - double Dz = SpinBox_Dz->value(); - - myBusy = true; - SpinBox_Dx->setValue( -Dx ); - SpinBox_Dy->setValue( -Dy ); - SpinBox_Dz->setValue( -Dz ); - myBusy = false; - - if ( clipPlanesCount() != 0 ) - { - int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); - OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); - aPlane.AbsoluteOrientation.IsInvert = !aPlane.AbsoluteOrientation.IsInvert; - } - updateClipping(); -} - -/*! - SLOT: called on orientation of clipping plane in absolute mode changed -*/ -void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode ) -{ - bool isUserMode = (mode==0); - - TextLabelX->setEnabled( isUserMode ); - TextLabelY->setEnabled( isUserMode ); - TextLabelZ->setEnabled( isUserMode ); - - SpinBox_X->setEnabled( isUserMode ); - SpinBox_Y->setEnabled( isUserMode ); - SpinBox_Z->setEnabled( isUserMode ); - - TextLabelDx->setEnabled( isUserMode ); - TextLabelDy->setEnabled( isUserMode ); - TextLabelDz->setEnabled( isUserMode ); - - SpinBox_Dx->setEnabled( isUserMode ); - SpinBox_Dy->setEnabled( isUserMode ); - SpinBox_Dz->setEnabled( isUserMode ); - - if ( !isUserMode ) { - - double aDx = 0, aDy = 0, aDz = 0; - - if ( mode == 1 ) - { - aDz = 1; - TextLabelZ->setEnabled( true ); - SpinBox_Z->setEnabled( true ); - SpinBox_Z->setFocus(); - } - else if ( mode == 2 ) - { - aDx = 1; - TextLabelX->setEnabled( true ); - SpinBox_X->setEnabled( true ); - SpinBox_X->setFocus(); - } - else if ( mode == 3 ) - { - aDy = 1; - TextLabelY->setEnabled( true ); - SpinBox_Y->setEnabled( true ); - SpinBox_Y->setFocus(); - } - - int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); - OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); - if ( aPlane.AbsoluteOrientation.IsInvert == true ) - { - aDx = -aDx; - aDy = -aDy; - aDz = -aDz; - } - - myBusy = true; - SpinBox_Dx->setValue( aDx ); - SpinBox_Dy->setValue( aDy ); - SpinBox_Dz->setValue( aDz ); - myBusy = false; - } - - if ( !myIsUpdatingControls ) - { - SetCurrentPlaneParam(); - updateClipping(); - } -} - -/*! - SLOT: called on orientation of clipping plane in relative mode changed -*/ -void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem) -{ - if ( clipPlanesCount() == 0 ) - return; - - if ( theItem == 0 ) { - TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) ); - TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) ); - } - else if ( theItem == 1 ) { - TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) ); - TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) ); - } - else if ( theItem == 2 ) { - TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) ); - TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) ); - } - - if ( !myIsUpdatingControls ) - { - if( (QComboBox*)sender() == CBRelativeOrientation ) - { - SetCurrentPlaneParam(); - } - - updateClipping(); - } -} - -/*! - SLOT: called on preview check box toggled -*/ -void OCCViewer_ClippingDlg::onPreview( bool on ) -{ - erasePreview(); - if ( on ) - displayPreview(); -} - -/*! - SLOT: called on Auto Apply check box toggled -*/ -void OCCViewer_ClippingDlg::onAutoApply( bool toggled ) -{ - if ( toggled ) { - onApply(); - myModel->update(); - } -} - -/*! - SLOT on Apply button click: sets cutting plane -*/ -void OCCViewer_ClippingDlg::onApply() -{ - if ( myBusy ) - return; - myIsSelectPlane = true; - - qApp->processEvents(); - QApplication::setOverrideCursor( Qt::WaitCursor ); - qApp->processEvents(); - - myModel->setClipPlanes(myLocalPlanes); - - QApplication::restoreOverrideCursor(); - myIsSelectPlane = false; -} - -/*! - SLOT: Called when clip plane is clicked in viewer. -*/ -void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane ) -{ - for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ ) - { - Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt ); - if ( aPlane != thePlane ) - { - continue; - } - - ComboBoxPlanes->setCurrentIndex( aPlaneIt ); - - break; - } -} - -/*! - SLOT: Called when clip plane is changed by dragging in viewer. -*/ -void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane ) -{ - for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ ) - { - Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt ); - if ( aPlane != thePlane ) - { - continue; - } - - OCCViewer_ClipPlane& aClipPlane = getClipPlane( aPlaneIt ); - - gp_Pln aPln = thePlane->Component()->Pln(); - const gp_Pnt& aPlaneP = aPln.Location(); - const gp_Dir& aPlaneN = aPln.Axis().Direction(); - - aClipPlane.X = aPlaneP.X(); - aClipPlane.Y = aPlaneP.Y(); - aClipPlane.Z = aPlaneP.Z(); - - if ( aClipPlane.Mode == OCCViewer_ClipPlane::Absolute ) - { - if ( aClipPlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom ) - { - aClipPlane.AbsoluteOrientation.Dx = aPlaneN.X(); - aClipPlane.AbsoluteOrientation.Dy = aPlaneN.Y(); - aClipPlane.AbsoluteOrientation.Dz = aPlaneN.Z(); - } - } - else - { - OCCViewer_ClipPlane::DXYZToRelative( aPlaneN.X(), aPlaneN.Y(), aPlaneN.Z(), - aClipPlane.OrientationType, - aClipPlane.RelativeOrientation.Rotation1, - aClipPlane.RelativeOrientation.Rotation2 ); - } - - myIsUpdatingControls = true; - updateControls(); - myIsUpdatingControls = false; - - if ( AutoApplyCheckBox->isChecked() ) - { - onApply(); - } - - break; - } -} - -OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane( int theIdx ) -{ - return myLocalPlanes[theIdx]; -} - -int OCCViewer_ClippingDlg::clipPlanesCount() -{ - return myLocalPlanes.size(); -} - +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library 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 2.1 of the License, or (at your option) any later version. +// +// This library 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 this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "OCCViewer_ClippingDlg.h" + +#include +#include +#include +#include + +#include "SUIT_Session.h" +#include "SUIT_ViewWindow.h" +#include "SUIT_ViewManager.h" +#include "OCCViewer_ClipPlane.h" +#include "OCCViewer_ViewWindow.h" +#include "OCCViewer_ViewPort3d.h" +#include "OCCViewer_ViewModel.h" +#include "OCCViewer_ViewManager.h" +#include "OCCViewer_ClipPlaneInteractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// QT Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************************** + ************************ Internal functions ************************ + *********************************************************************************/ + +void getMinMaxFromContext( Handle(AIS_InteractiveContext) ic, + double theDefaultSize, + double& theXMin, + double& theYMin, + double& theZMin, + double& theXMax, + double& theYMax, + double& theZMax) { + + double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; + aXMin = aYMin = aZMin = DBL_MAX; + aXMax = aYMax = aZMax = -DBL_MAX; + + bool isFound = false; + AIS_ListOfInteractive aList; + ic->DisplayedObjects( aList ); + for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() ) { + Handle(AIS_InteractiveObject) anObj = it.Value(); + if ( !anObj.IsNull() && anObj->HasPresentation() && + !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) ) { + Handle(Prs3d_Presentation) aPrs = anObj->Presentation(); + if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() ) { + isFound = true; + double xmin, ymin, zmin, xmax, ymax, zmax; + aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax ); + aXMin = qMin( aXMin, xmin ); aXMax = qMax( aXMax, xmax ); + aYMin = qMin( aYMin, ymin ); aYMax = qMax( aYMax, ymax ); + aZMin = qMin( aZMin, zmin ); aZMax = qMax( aZMax, zmax ); + } + } + } + + if(!isFound) { + if(theDefaultSize == 0.0) + theDefaultSize = 100.; + aXMin = aYMin = aZMin = -theDefaultSize; + aXMax = aYMax = aZMax = theDefaultSize; + } + theXMin = aXMin;theYMin = aYMin;theZMin = aZMin; + theXMax = aXMax;theYMax = aYMax;theZMax = aZMax; +} + +/*! + Compute the point of bounding box and current clipping plane + */ +void ComputeBoundsParam( const double theBounds[6], + const double theDirection[3], + double theMinPnt[3], + double& theMaxBoundPrj, + double& theMinBoundPrj ) +{ + double aEnlargeBounds[6]; + + // Enlarge bounds in order to avoid conflicts of precision + for(int i = 0; i < 6; i += 2) + { + static double EPS = 1.0E-3; + double aDelta = (theBounds[i+1] - theBounds[i])*EPS; + aEnlargeBounds[i ] = theBounds[i ] - aDelta; + aEnlargeBounds[i+1] = theBounds[i+1] + aDelta; + } + + double aBoundPoints[8][3] = { { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[4] }, + { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[4] }, + { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[4] }, + { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[4] }, + { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[5] }, + { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[5] }, + { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[5] }, + { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[5] } }; + + int aMaxId = 0; + theMaxBoundPrj = theDirection[0] * aBoundPoints[aMaxId][0] + theDirection[1] * aBoundPoints[aMaxId][1] + + theDirection[2] * aBoundPoints[aMaxId][2]; + theMinBoundPrj = theMaxBoundPrj; + for(int i = 1; i < 8; i++) { + double aTmp = theDirection[0] * aBoundPoints[i][0] + theDirection[1] * aBoundPoints[i][1] + + theDirection[2] * aBoundPoints[i][2]; + if(theMaxBoundPrj < aTmp) { + theMaxBoundPrj = aTmp; + aMaxId = i; + } + if(theMinBoundPrj > aTmp) { + theMinBoundPrj = aTmp; + } + } + double *aMinPnt = aBoundPoints[aMaxId]; + theMinPnt[0] = aMinPnt[0]; + theMinPnt[1] = aMinPnt[1]; + theMinPnt[2] = aMinPnt[2]; +} + +/*! + Compute the position of current plane by distance + */ +void DistanceToPosition( const double theBounds[6], + const double theDirection[3], + const double theDist, + double thePos[3] ) +{ + double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3]; + ComputeBoundsParam( theBounds, theDirection, aMinPnt, aMaxBoundPrj, aMinBoundPrj ); + double aLength = (aMaxBoundPrj - aMinBoundPrj) * theDist; + thePos[0] = aMinPnt[0] - theDirection[0] * aLength; + thePos[1] = aMinPnt[1] - theDirection[1] * aLength; + thePos[2] = aMinPnt[2] - theDirection[2] * aLength; +} + +/*! + Compute the parameters of clipping plane + */ +bool ComputeClippingPlaneParameters( const Handle(AIS_InteractiveContext)& theIC, + const double theDefaultSize, + const double theNormal[3], + const double theDist, + double theOrigin[3] ) +{ + double aBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + + getMinMaxFromContext( theIC, theDefaultSize, aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5] ); + + DistanceToPosition( aBounds, theNormal, theDist, theOrigin ); + return true; +} + +/*! + \brief Converts relative plane parameters to absolute. + \param theIC [in] the interactive context. + \param theDefaultSize [in] the default trihedron size. + \param theDistance [in] the plane distance relative to minimum corner of model boundaries. + \param theDX [in] x component of plane direction. + \param theDY [in] y component of plane direction. + \param theDZ [in] z component of plane direction. + \param theX [out] x coordinate of plane origin. + \param theY [out] y coordinate of plane origin. + \param theZ [out] z coordinate of plane origin. + */ +bool DistanceToXYZ ( const Handle(AIS_InteractiveContext)& theIC, + const double theDefaultSize, + const double theDistance, + const double theDX, + const double theDY, + const double theDZ, + double& theX, + double& theY, + double& theZ ) +{ + double aNormal[3] = { theDX, theDY, theDZ }; + double anOrigin[3] = { 0.0, 0.0, 0.0 }; + + bool anIsOk = ComputeClippingPlaneParameters( theIC, theDefaultSize, aNormal, theDistance, anOrigin ); + + if( !anIsOk ) + { + return false; + } + + theX = anOrigin[0]; + theY = anOrigin[1]; + theZ = anOrigin[2]; + + return true; +} + +/*! + \brief Converts absolute position and direction to bounding box distance. + \param theIC [in] the interactive context. + \param theDefaultSize [in] the default trihedron size. + \param theX [in] x coordinate of plane origin. + \param theY [in] y coordinate of plane origin. + \param theZ [in] z coordinate of plane origin. + \param theDX [in] x component of plane direction. + \param theDY [in] y component of plane direction. + \param theDZ [in] z component of plane direction. + \param theDistance [out] the plane distance relative to minimum corner of model boundaries. + */ +void XYZToDistance ( const Handle(AIS_InteractiveContext)& theIC, + const double theDefaultSize, + const double theX, + const double theY, + const double theZ, + const double theDX, + const double theDY, + const double theDZ, + double& theDistance ) +{ + gp_Pnt aPlaneP( theX, theY, theZ ); + gp_Dir aPlaneN( theDX, theDY, theDZ ); + + double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + + getMinMaxFromContext( theIC, theDefaultSize, aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + Bnd_Box aMinMax; + aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + gp_Trsf aRelativeTransform; + aRelativeTransform.SetTransformation( gp_Ax3(), gp_Ax3( aPlaneP, aPlaneN ) ); + Bnd_Box aRelativeBounds = aMinMax.Transformed( aRelativeTransform ); + + aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + double aLength = aZmax - aZmin; + double aDistance = aZmax; + + double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0; + aRelativeDistance = qMin( aRelativeDistance, aLength ); + aRelativeDistance = qMax( aRelativeDistance, 0.0 ); + theDistance = aRelativeDistance; +} + +/*! + Compute clipping plane size base point and normal + */ + +void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveContext) theContext, + double& theSize, gp_Pnt& theBasePnt, gp_Dir& theNormal, double defaultSize) { + double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; + aXMin = aYMin = aZMin = DBL_MAX; + aXMax = aYMax = aZMax = -DBL_MAX; + + getMinMaxFromContext(theContext,defaultSize,aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); + double aSize = 50; + + double aNormalX = 0.0; + double aNormalY = 0.0; + double aNormalZ = 0.0; + theClipPlane.OrientationToXYZ( aNormalX, aNormalY, aNormalZ ); + gp_Pnt aBasePnt( theClipPlane.X, theClipPlane.Y, theClipPlane.Z ); + gp_Dir aNormal( aNormalX, aNormalY, aNormalZ ); + + // compute clipping plane size + gp_Pnt aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 ); + double aDiag = aCenter.Distance( gp_Pnt( aXMax, aYMax, aZMax ) )*2; + aSize = aDiag * 1.1; + + // compute clipping plane center ( redefine the base point ) + IntAna_IntConicQuad intersector = IntAna_IntConicQuad(); + + intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() ); + + if ( intersector.IsDone() && intersector.NbPoints() == 1 ) + aBasePnt = intersector.Point( 1 ); + + theSize = aSize; + theBasePnt = aBasePnt; + theNormal = aNormal; +} + + +/********************************************************************************* + ********************* class OCCViewer_ClippingDlg ********************* + *********************************************************************************/ +/*! + Constructor + \param view - view window + \param parent - parent widget +*/ +OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCViewer_Viewer* model) + : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ) +{ + setObjectName( "OCCViewer_ClippingDlg" ); + setModal( false ); + + setWindowTitle( tr( "Clipping" ) ); + + setAttribute (Qt::WA_DeleteOnClose, true); + + QVBoxLayout* topLayout = new QVBoxLayout( this ); + topLayout->setMargin( 11 ); topLayout->setSpacing( 6 ); + + /***************************************************************/ + // Controls for selecting, creating, deleting planes + QGroupBox* GroupPlanes = new QGroupBox( tr("CLIPPING_PLANES"), this ); + QHBoxLayout* GroupPlanesLayout = new QHBoxLayout( GroupPlanes ); + ComboBoxPlanes = new QComboBox( GroupPlanes ); + isActivePlane = new QCheckBox( tr("IS_ACTIVE_PLANE"), this ); + buttonNew = new QPushButton( tr("BTN_NEW"), GroupPlanes ); + buttonDelete = new QPushButton( tr("BTN_DELETE"), GroupPlanes ); + buttonDisableAll = new QPushButton( tr("BTN_DISABLE_ALL"), GroupPlanes ); + MenuMode = new QMenu( "MenuMode", buttonNew ); + MenuMode->addAction( tr( "ABSOLUTE" ), this, SLOT( onModeAbsolute() ) ); + MenuMode->addAction( tr( "RELATIVE" ), this, SLOT( onModeRelative() ) ); + buttonNew->setMenu( MenuMode ); + + GroupPlanesLayout->addWidget( ComboBoxPlanes ); + GroupPlanesLayout->addWidget( isActivePlane ); + GroupPlanesLayout->addWidget( buttonNew ); + GroupPlanesLayout->addWidget( buttonDelete ); + GroupPlanesLayout->addWidget( buttonDisableAll ); + + ModeStackedLayout = new QStackedLayout(); + + /********************** Mode Absolute **********************/ + /* Controls for absolute mode of clipping plane: + X, Y, Z - coordinates of the intersection of cutting plane and the three axes + Dx, Dy, Dz - components of normal to the cutting plane + Orientation - direction of cutting plane + */ + const double min = -1e+7; + const double max = 1e+7; + const double step = 5; + const int precision = -7; + + // Croup Point + QGroupBox* GroupAbsolutePoint = new QGroupBox( this ); + GroupAbsolutePoint->setObjectName( "GroupPoint" ); + GroupAbsolutePoint->setTitle( tr("BASE_POINT") ); + QGridLayout* GroupPointLayout = new QGridLayout( GroupAbsolutePoint ); + GroupPointLayout->setAlignment( Qt::AlignTop ); + GroupPointLayout->setSpacing( 6 ); GroupPointLayout->setMargin( 11 ); + + TextLabelX = new QLabel( GroupAbsolutePoint ); + TextLabelX->setObjectName( "TextLabelX" ); + TextLabelX->setText( tr("X:") ); + GroupPointLayout->addWidget( TextLabelX, 0, 0 ); + + SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); + SpinBox_X->setObjectName("SpinBox_X" ); + SpinBox_X->setPrecision( precision ); + GroupPointLayout->addWidget( SpinBox_X, 0, 1 ); + + TextLabelY = new QLabel( GroupAbsolutePoint ); + TextLabelY->setObjectName( "TextLabelY" ); + TextLabelY->setText( tr("Y:") ); + GroupPointLayout->addWidget( TextLabelY, 0, 2 ); + + SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); + SpinBox_Y->setObjectName("SpinBox_Y" ); + SpinBox_Y->setPrecision( precision ); + GroupPointLayout->addWidget( SpinBox_Y, 0, 3 ); + + TextLabelZ = new QLabel( GroupAbsolutePoint ); + TextLabelZ->setObjectName( "TextLabelZ" ); + TextLabelZ->setText( tr("Z:") ); + GroupPointLayout->addWidget( TextLabelZ, 0, 4 ); + + SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint ); + SpinBox_Z->setObjectName("SpinBox_Z" ); + SpinBox_Z->setPrecision( precision ); + GroupPointLayout->addWidget( SpinBox_Z, 0, 5 ); + + resetButton = new QPushButton( GroupAbsolutePoint ); + resetButton->setObjectName( "resetButton" ); + resetButton->setText( tr( "RESET" ) ); + GroupPointLayout->addWidget( resetButton, 0, 6 ); + + // Group Direction + GroupAbsoluteDirection = new QGroupBox( this ); + GroupAbsoluteDirection->setObjectName( "GroupDirection" ); + GroupAbsoluteDirection->setTitle( tr("DIRECTION") ); + QGridLayout* GroupDirectionLayout = new QGridLayout( GroupAbsoluteDirection ); + GroupDirectionLayout->setAlignment( Qt::AlignTop ); + GroupDirectionLayout->setSpacing( 6 ); + GroupDirectionLayout->setMargin( 11 ); + + TextLabelDx = new QLabel( GroupAbsoluteDirection ); + TextLabelDx->setObjectName( "TextLabelDx" ); + TextLabelDx->setText( tr("Dx:") ); + GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 ); + + SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); + SpinBox_Dx->setObjectName("SpinBox_Dx" ); + SpinBox_Dx->setPrecision( precision ); + GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 ); + + TextLabelDy = new QLabel( GroupAbsoluteDirection ); + TextLabelDy->setObjectName( "TextLabelDy" ); + TextLabelDy->setText( tr("Dy:") ); + GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 ); + + SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); + SpinBox_Dy->setObjectName("SpinBox_Dy" ); + SpinBox_Dy->setPrecision( precision ); + GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 ); + + TextLabelDz = new QLabel( GroupAbsoluteDirection ); + TextLabelDz->setObjectName( "TextLabelDz" ); + TextLabelDz->setText( tr("Dz:") ); + GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 ); + + SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection ); + SpinBox_Dz->setObjectName("SpinBox_Dz" ); + SpinBox_Dz->setPrecision( precision ); + GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 ); + + invertButton = new QPushButton( GroupAbsoluteDirection ); + invertButton->setObjectName( "invertButton" ); + invertButton->setText( tr( "INVERT" ) ); + GroupDirectionLayout->addWidget( invertButton, 0, 6 ); + + CBAbsoluteOrientation = new QComboBox( GroupAbsoluteDirection ); + CBAbsoluteOrientation->setObjectName( "AbsoluteOrientation" ); + CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "CUSTOM" ) ); + CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||X-Y" ) ); + CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Y-Z" ) ); + CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Z-X" ) ); + GroupDirectionLayout->addWidget( CBAbsoluteOrientation, 1, 0, 1, 6 ); + + QVBoxLayout* ModeActiveLayout = new QVBoxLayout(); + ModeActiveLayout->setMargin( 11 ); ModeActiveLayout->setSpacing( 6 ); + ModeActiveLayout->addWidget( GroupAbsolutePoint ); + ModeActiveLayout->addWidget( GroupAbsoluteDirection ); + + QWidget* ModeActiveWidget = new QWidget( this ); + ModeActiveWidget->setLayout( ModeActiveLayout ); + + /********************** Mode Relative **********************/ + /* Controls for relative mode of clipping plane: + Distance - Value from 0 to 1. + Specifies the distance from the minimum value in a given direction of bounding box to the current position + Rotation1, Rotation2 - turn angles of cutting plane in given directions + Orientation - direction of cutting plane + */ + QGroupBox* GroupParameters = new QGroupBox( tr("PARAMETERS"), this ); + QGridLayout* GroupParametersLayout = new QGridLayout( GroupParameters ); + GroupParametersLayout->setMargin( 11 ); GroupParametersLayout->setSpacing( 6 ); + + TextLabelOrientation = new QLabel( tr("ORIENTATION"), GroupParameters); + TextLabelOrientation->setObjectName( "TextLabelOrientation" ); + GroupParametersLayout->addWidget( TextLabelOrientation, 0, 0 ); + + CBRelativeOrientation = new QComboBox(GroupParameters); + CBRelativeOrientation->setObjectName( "RelativeOrientation" ); + CBRelativeOrientation->addItem( tr("ALONG_XY") ); + CBRelativeOrientation->addItem( tr("ALONG_YZ") ); + CBRelativeOrientation->addItem( tr("ALONG_ZX") ); + GroupParametersLayout->addWidget( CBRelativeOrientation, 0, 1 ); + + TextLabelDistance = new QLabel( tr("DISTANCE"), GroupParameters ); + TextLabelDistance->setObjectName( "TextLabelDistance" ); + GroupParametersLayout->addWidget( TextLabelDistance, 1, 0 ); + + SpinSliderDistance = new QtxDoubleSpinSlider( 0., 1., 0.01, GroupParameters ); + SpinSliderDistance->setObjectName( "SpinSliderDistance" ); + SpinSliderDistance->setPrecision( precision ); + QFont fnt = SpinSliderDistance->font(); fnt.setBold( true ); SpinSliderDistance->setFont( fnt ); + GroupParametersLayout->addWidget( SpinSliderDistance, 1, 1 ); + + QString aUnitRot = "\xB0"; + + TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters ); + TextLabelRotation1->setObjectName( "TextLabelRotation1" ); + GroupParametersLayout->addWidget( TextLabelRotation1, 2, 0 ); + + SpinSliderRotation1 = new QtxIntSpinSlider( -180, 180, 1, GroupParameters ); + SpinSliderRotation1->setObjectName( "SpinSliderRotation1" ); + SpinSliderRotation1->setUnit( aUnitRot ); + SpinSliderRotation1->setFont( fnt ); + GroupParametersLayout->addWidget( SpinSliderRotation1, 2, 1 ); + + TextLabelRotation2 = new QLabel(tr("ROTATION_AROUND_Y_X2Z"), GroupParameters); + TextLabelRotation2->setObjectName( "TextLabelRotation2" ); + TextLabelRotation2->setObjectName( "TextLabelRotation2" ); + GroupParametersLayout->addWidget( TextLabelRotation2, 3, 0 ); + + SpinSliderRotation2 = new QtxIntSpinSlider( -180, 180, 1, GroupParameters ); + SpinSliderRotation2->setObjectName( "SpinSliderRotation2" ); + SpinSliderRotation2->setUnit( aUnitRot ); + SpinSliderRotation2->setFont( fnt ); + GroupParametersLayout->addWidget( SpinSliderRotation2, 3, 1 ); + + /***************************************************************/ + QGroupBox* CheckBoxWidget = new QGroupBox( this ); + QHBoxLayout* CheckBoxLayout = new QHBoxLayout( CheckBoxWidget ); + + PreviewCheckBox = new QCheckBox( tr("PREVIEW"), CheckBoxWidget ); + PreviewCheckBox->setObjectName( "PreviewCheckBox" ); + PreviewCheckBox->setChecked( true ); + CheckBoxLayout->addWidget( PreviewCheckBox, 0, Qt::AlignCenter ); + + AutoApplyCheckBox = new QCheckBox( tr("AUTO_APPLY"), CheckBoxWidget ); + AutoApplyCheckBox->setObjectName( "AutoApplyCheckBox" ); + CheckBoxLayout->addWidget( AutoApplyCheckBox, 0, Qt::AlignCenter ); + + /***************************************************************/ + QGroupBox* GroupButtons = new QGroupBox( this ); + QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons ); + GroupButtonsLayout->setAlignment( Qt::AlignTop ); + GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 ); + + buttonOk = new QPushButton( GroupButtons ); + buttonOk->setObjectName( "buttonOk" ); + buttonOk->setText( tr( "BUT_APPLY_AND_CLOSE" ) ); + buttonOk->setAutoDefault( TRUE ); + buttonOk->setDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonOk ); + + buttonApply = new QPushButton( GroupButtons ); + buttonApply->setObjectName( "buttonApply" ); + buttonApply->setText( tr( "BUT_APPLY" ) ); + buttonApply->setAutoDefault( TRUE ); + buttonApply->setDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonApply ); + + GroupButtonsLayout->addStretch(); + + buttonClose = new QPushButton( GroupButtons ); + buttonClose->setObjectName( "buttonClose" ); + buttonClose->setText( tr( "BUT_CLOSE" ) ); + buttonClose->setAutoDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonClose ); + + QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons ); + buttonHelp->setAutoDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonHelp ); + + /***************************************************************/ + ModeStackedLayout->addWidget( ModeActiveWidget ); + ModeStackedLayout->addWidget( GroupParameters ); + + topLayout->addWidget( GroupPlanes ); + topLayout->addLayout( ModeStackedLayout ); + topLayout->addWidget( CheckBoxWidget ); + topLayout->addWidget( GroupButtons ); + + this->setLayout( topLayout ); + + // Initializations + initParam(); + + // Signals and slots connections + connect( ComboBoxPlanes, SIGNAL( activated( int ) ), this, SLOT( onSelectPlane( int ) ) ); + connect( isActivePlane, SIGNAL ( toggled ( bool ) ), this, SLOT( onValueChanged() ) ); + connect( buttonNew, SIGNAL( clicked() ), buttonNew, SLOT( showMenu() ) ); + connect( buttonDelete, SIGNAL( clicked() ), this, SLOT( ClickOnDelete() ) ); + connect( buttonDisableAll, SIGNAL( clicked() ), this, SLOT( ClickOnDisableAll() ) ); + + connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) ); + connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ; + connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( CBAbsoluteOrientation, SIGNAL ( activated ( int ) ), this, SLOT( onOrientationAbsoluteChanged( int ) ) ) ; + + connect( CBRelativeOrientation, SIGNAL( activated( int ) ), this, SLOT( onOrientationRelativeChanged( int ) ) ); + connect( SpinSliderDistance, SIGNAL( valueChanged( double ) ), this, SLOT( onValueChanged() ) ); + connect( SpinSliderRotation1, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) ); + connect( SpinSliderRotation2, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) ); + + connect( PreviewCheckBox, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ; + connect( AutoApplyCheckBox, SIGNAL ( toggled( bool ) ), this, SLOT( onAutoApply( bool ) ) ); + + connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ; + connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); + connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); + connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) ); + + myBusy = false; + myIsSelectPlane = false; + myIsPlaneCreation = false; + myIsUpdatingControls = false; + myModel = model; + + myModel->getViewer3d()->InitActiveViews(); + + OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) myModel->getViewManager(); + myInteractor = new OCCViewer_ClipPlaneInteractor( aViewMgr, this ); + connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ) ), SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) ); + connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ) ), SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) ); + + myLocalPlanes = myModel->getClipPlanes(); + synchronize(); +} + +/*! + Destructor + Destroys the object and frees any allocated resources +*/ +OCCViewer_ClippingDlg::~OCCViewer_ClippingDlg() +{ + myLocalPlanes.clear(); +} + +/*! + Custom handling of close event: erases preview +*/ +void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e ) +{ + erasePreview(); + QDialog::closeEvent( e ); + OCCViewer_ViewWindow* v = qobject_cast(parent()); + if(v) + v->onClipping(false); +} + +/*! + Custom handling of show event: displays preview +*/ +void OCCViewer_ClippingDlg::showEvent( QShowEvent* e ) +{ + QDialog::showEvent( e ); + onPreview( PreviewCheckBox->isChecked() ); +} + +/*! + Custom handling of hide event: erases preview +*/ +void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e ) +{ + erasePreview(); + QDialog::hideEvent( e ); + OCCViewer_ViewWindow* v = qobject_cast(parent()); + if(v) + v->onClipping(false); + +} + +/*! + Initialization of initial values of widgets +*/ +void OCCViewer_ClippingDlg::initParam() +{ + SpinBox_X->setValue( 0.0 ); + SpinBox_Y->setValue( 0.0 ); + SpinBox_Z->setValue( 0.0 ); + + SpinBox_Dx->setValue( 1.0 ); + SpinBox_Dy->setValue( 1.0 ); + SpinBox_Dz->setValue( 1.0 ); + + CBAbsoluteOrientation->setCurrentIndex(0); + + SpinSliderDistance->setValue( 0.5 ); + SpinSliderRotation1->setValue( 0 ); + SpinSliderRotation2->setValue( 0 ); + CBRelativeOrientation->setCurrentIndex( 0 ); + + isActivePlane->setChecked( true ); +} + +/*! + Set plane parameters from widgets. +*/ +void OCCViewer_ClippingDlg::setPlaneParam( OCCViewer_ClipPlane& thePlane ) +{ + OCCViewer_ClipPlane::PlaneMode aMode = currentPlaneMode(); + + thePlane.Mode = aMode; + + if ( aMode == OCCViewer_ClipPlane::Absolute ) + { + if( qFuzzyIsNull( SpinBox_Dx->value() ) && + qFuzzyIsNull( SpinBox_Dy->value() ) && + qFuzzyIsNull( SpinBox_Dz->value() ) ) { + return; + } + } + + thePlane.OrientationType = (aMode == OCCViewer_ClipPlane::Absolute) + ? CBAbsoluteOrientation->currentIndex() + : CBRelativeOrientation->currentIndex(); + + // Get XYZ, DXYZ + if ( aMode == OCCViewer_ClipPlane::Absolute ) + { + if ( thePlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom ) + { + thePlane.AbsoluteOrientation.Dx = SpinBox_Dx->value(); + thePlane.AbsoluteOrientation.Dy = SpinBox_Dy->value(); + thePlane.AbsoluteOrientation.Dz = SpinBox_Dz->value(); + } + else + { + thePlane.AbsoluteOrientation.IsInvert = SpinBox_Dx->value() < 0.0 + || SpinBox_Dy->value() < 0.0 + || SpinBox_Dz->value() < 0.0; + } + + thePlane.X = SpinBox_X->value(); + thePlane.Y = SpinBox_Y->value(); + thePlane.Z = SpinBox_Z->value(); + } + else + { + thePlane.RelativeOrientation.Rotation1 = SpinSliderRotation1->value(); + thePlane.RelativeOrientation.Rotation2 = SpinSliderRotation2->value(); + + double aPlaneDx = 0.0; + double aPlaneDy = 0.0; + double aPlaneDz = 0.0; + double aX = 0.0; + double aY = 0.0; + double aZ = 0.0; + + OCCViewer_ClipPlane::RelativeToDXYZ( thePlane.OrientationType, + thePlane.RelativeOrientation.Rotation1, + thePlane.RelativeOrientation.Rotation2, + aPlaneDx, aPlaneDy, aPlaneDz ); + + DistanceToXYZ( myModel->getAISContext(), + myModel->trihedronSize(), + SpinSliderDistance->value(), + aPlaneDx, aPlaneDy, aPlaneDz, + aX, aY, aZ ); + + thePlane.X = aX; + thePlane.Y = aY; + thePlane.Z = aZ; + } + + thePlane.IsOn = isActivePlane->isChecked(); +} + +/*! + Synchronize dialog's widgets with data +*/ +void OCCViewer_ClippingDlg::synchronize() +{ + ComboBoxPlanes->clear(); + int aNbPlanesAbsolute = myLocalPlanes.size(); + + QString aName; + for(int i = 1; i<=aNbPlanesAbsolute; i++ ) { + aName = QString("Plane %1").arg(i); + ComboBoxPlanes->addItem( aName ); + } + + int aPos = ComboBoxPlanes->count() - 1; + ComboBoxPlanes->setCurrentIndex( aPos ); + + bool anIsControlsEnable = ( aPos >= 0 ); + if ( anIsControlsEnable ) { + onSelectPlane( aPos ); + } + else { + ComboBoxPlanes->addItem( tr( "NO_PLANES" ) ); + initParam(); + } + if ( currentPlaneMode() == OCCViewer_ClipPlane::Absolute ) + { + SpinBox_X->setEnabled( anIsControlsEnable ); + SpinBox_Y->setEnabled( anIsControlsEnable ); + SpinBox_Z->setEnabled( anIsControlsEnable ); + SpinBox_Dx->setEnabled( anIsControlsEnable ); + SpinBox_Dy->setEnabled( anIsControlsEnable ); + SpinBox_Dz->setEnabled( anIsControlsEnable ); + CBAbsoluteOrientation->setEnabled( anIsControlsEnable ); + invertButton->setEnabled( anIsControlsEnable ); + resetButton->setEnabled( anIsControlsEnable ); + } + else if ( currentPlaneMode() == OCCViewer_ClipPlane::Relative ) + { + CBRelativeOrientation->setEnabled( anIsControlsEnable ); + SpinSliderDistance->setEnabled( anIsControlsEnable ); + SpinSliderRotation1->setEnabled( anIsControlsEnable ); + SpinSliderRotation2->setEnabled( anIsControlsEnable ); + isActivePlane->setEnabled( anIsControlsEnable ); + } + isActivePlane->setEnabled( anIsControlsEnable ); +} + +/*! + Displays preview of clipping plane +*/ +void OCCViewer_ClippingDlg::displayPreview() +{ + if ( myBusy || !isValid() || !myModel) + return; + + Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); + + int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); + + for ( int i=0; i < clipPlanesCount(); i++ ) { + OCCViewer_ClipPlane& aClipPlane = getClipPlane(i); + if ( aClipPlane.IsOn ) { + Handle(AIS_Plane) myPreviewPlane; + double aSize; + gp_Pnt aBasePnt; + gp_Dir aNormal; + clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize()); + myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt ); + myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR ); + myPreviewPlane->SetSize( aSize, aSize ); + ic->SetWidth( myPreviewPlane, 10, false ); + ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false ); + ic->SetTransparency( myPreviewPlane, 0.5, false ); + Quantity_Color c = (aCurPlaneIndex == i) ? Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ) : Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ); + ic->SetColor( myPreviewPlane, c , false ); + ic->Display( myPreviewPlane, 1, 0, false ); + myPreviewPlaneVector.push_back( myPreviewPlane ); + } + } + myModel->update(); + + double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5, + (aYmax + aYmin) * 0.5, + (aZmax + aZmin) * 0.5 ); + Bnd_Box aMinMax; + aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + myInteractor->setPlanes( myPreviewPlaneVector ); + myInteractor->setRotationCenter( aRotationCenter ); + myInteractor->setMinMax( aMinMax ); + myInteractor->setEnabled( true ); +} + +void OCCViewer_ClippingDlg::updatePreview() { + int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); + int count = clipPlanesCount(); + if ( myBusy || + !isValid() || + myIsPlaneCreation || + !myModel || + count == 0 || + (aCurPlaneIndex +1 > count) || + !PreviewCheckBox->isChecked()) + return; + + Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); + + OCCViewer_ClipPlane& aClipPlane = getClipPlane(aCurPlaneIndex); + Handle(AIS_Plane) myPreviewPlane; + + if (aClipPlane.IsOn) { + double aSize; + gp_Pnt aBasePnt; + gp_Dir aNormal; + clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize()); + if(myPreviewPlaneVector.size() < clipPlanesCount()) { + myPreviewPlaneVector.resize(clipPlanesCount()); + } + myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex]; + if(myPreviewPlane.IsNull()) { + //Plane was not created + myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt ); + myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR ); + myPreviewPlane->SetSize( aSize, aSize ); + ic->Display( myPreviewPlane, 1, 0, false ); + ic->SetWidth( myPreviewPlane, 10, false ); + ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false ); + ic->SetTransparency( myPreviewPlane, 0.5, false ); + myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane; + } else { + myPreviewPlane->SetComponent( new Geom_Plane( aBasePnt, aNormal ) ); + myPreviewPlane->SetCenter( aBasePnt ); + myPreviewPlane->SetSize( aSize, aSize ); + } + + ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false ); + ic->Update( myPreviewPlane, Standard_False ); + } else { + if(myPreviewPlaneVector.size() > aCurPlaneIndex ) { + myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex]; + if(ic->IsDisplayed(myPreviewPlane)) { + ic->Erase( myPreviewPlane, false ); + ic->Remove( myPreviewPlane, false ); + } + myPreviewPlaneVector[aCurPlaneIndex].Nullify(); + } + } + for(int i = 0; i < myPreviewPlaneVector.size(); i++) { + if( i == aCurPlaneIndex ) continue; + if(!myPreviewPlaneVector[i].IsNull()) + ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false ); + } + myModel->update(); + + double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5, + (aYmax + aYmin) * 0.5, + (aZmax + aZmin) * 0.5 ); + Bnd_Box aMinMax; + aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + myInteractor->setPlanes( myPreviewPlaneVector ); + myInteractor->setRotationCenter( aRotationCenter ); + myInteractor->setMinMax( aMinMax ); +} + +/*! + Erases preview of clipping plane +*/ +void OCCViewer_ClippingDlg::erasePreview() +{ + if ( !myModel ) + return; + + Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); + + for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) { + Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i]; + if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) { + ic->Erase( myPreviewPlane, false ); + ic->Remove( myPreviewPlane, false ); + myPreviewPlane.Nullify(); + } + } + myPreviewPlaneVector.clear(); + myModel->update(); + myInteractor->setEnabled( false ); +} + +/*! + Return true if plane parameters are valid +*/ +bool OCCViewer_ClippingDlg::isValid() +{ + return ( SpinBox_Dx->value() !=0 || SpinBox_Dy->value() !=0 || SpinBox_Dz->value() !=0 ); +} + +/*! + Update view after changes +*/ +void OCCViewer_ClippingDlg::updateClipping() +{ + if (PreviewCheckBox->isChecked() || AutoApplyCheckBox->isChecked()) + { + if (AutoApplyCheckBox->isChecked()) { + onApply(); + } + + if (!PreviewCheckBox->isChecked()) + myModel->update(); + else + updatePreview(); + } +} + +/*! + Updates state of user controls. +*/ +void OCCViewer_ClippingDlg::updateControls() +{ + if ( clipPlanesCount() == 0 ) + { + initParam(); + return; + } + + int aPlaneIdx = ComboBoxPlanes->currentIndex(); + + OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx ); + + double aPlaneDx = 0.0; + double aPlaneDy = 0.0; + double aPlaneDz = 0.0; + double aDistance = 0.0; + aPlane.OrientationToXYZ( aPlaneDx, aPlaneDy, aPlaneDz ); + + if ( aPlane.Mode == OCCViewer_ClipPlane::Absolute ) + { + ModeStackedLayout->setCurrentIndex( 0 ); + + // Set plane parameters in the dialog + SpinBox_X->setValue( aPlane.X ); + SpinBox_Y->setValue( aPlane.Y ); + SpinBox_Z->setValue( aPlane.Z ); + SpinBox_Dx->setValue( aPlaneDx ); + SpinBox_Dy->setValue( aPlaneDy ); + SpinBox_Dz->setValue( aPlaneDz ); + CBAbsoluteOrientation->setCurrentIndex( aPlane.OrientationType ); + onOrientationAbsoluteChanged( aPlane.OrientationType ); + } + else if( aPlane.Mode == OCCViewer_ClipPlane::Relative ) + { + ModeStackedLayout->setCurrentIndex( 1 ); + + // Set plane parameters in the dialog + SpinSliderRotation1->setValue( int( aPlane.RelativeOrientation.Rotation1 ) ); + SpinSliderRotation2->setValue( int( aPlane.RelativeOrientation.Rotation2 ) ); + + XYZToDistance( myModel->getAISContext(), + myModel->trihedronSize(), + aPlane.X, aPlane.Y, aPlane.Z, + aPlaneDx, aPlaneDy, aPlaneDz, + aDistance ); + + SpinSliderDistance->setValue( aDistance ); + + CBRelativeOrientation->setCurrentIndex( aPlane.OrientationType ); + onOrientationRelativeChanged( aPlane.OrientationType ); + } + + isActivePlane->setChecked( aPlane.IsOn ); +} + +/*! + SLOT on new button click: create a new clipping plane +*/ +void OCCViewer_ClippingDlg::ClickOnNew() +{ + OCCViewer_ClipPlane aClipPlane; + + // init controls state + myIsUpdatingControls = true; + initParam(); + myIsUpdatingControls = false; + + // init plane according to the state of controls + setPlaneParam( aClipPlane ); + + // add plane + myLocalPlanes.push_back( aClipPlane ); + synchronize(); +} + +/*! + SLOT on delete button click: Delete selected clipping plane +*/ +void OCCViewer_ClippingDlg::ClickOnDelete() +{ + int aPlaneIndex = ComboBoxPlanes->currentIndex(); + if ( (clipPlanesCount() == 0) || (aPlaneIndex+1 > clipPlanesCount())) + return; + + myLocalPlanes.erase(myLocalPlanes.begin() + aPlaneIndex); + + Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); + + if(aPlaneIndex+1 <= myPreviewPlaneVector.size()) { + Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[aPlaneIndex]; + if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) { + ic->Erase( myPreviewPlane, false ); + ic->Remove( myPreviewPlane, false ); + } + myPreviewPlaneVector.erase(myPreviewPlaneVector.begin() + aPlaneIndex); + } + synchronize(); + if (AutoApplyCheckBox->isChecked()) { + onApply(); + } + myModel->update(); +} + +/*! + SLOT on disable all button click: Restore initial state of viewer, + erase all clipping planes +*/ +void OCCViewer_ClippingDlg::ClickOnDisableAll() +{ + AutoApplyCheckBox->setChecked (false); + int aClipPlanesCount = clipPlanesCount(); + for ( int anIndex = 0; anIndex < aClipPlanesCount; anIndex++) + { + OCCViewer_ClipPlane& aPlane = getClipPlane(anIndex); + aPlane.IsOn = false; + } + erasePreview(); + isActivePlane->setChecked(false); + myModel->setClipPlanes(myLocalPlanes); + myModel->update(); +} + +/*! + SLOT on ok button click: sets cutting plane and closes dialog +*/ +void OCCViewer_ClippingDlg::ClickOnOk() +{ + onApply(); + ClickOnClose(); +} + +/*! + SLOT on Apply button click: sets cutting plane and update viewer +*/ +void OCCViewer_ClippingDlg::ClickOnApply() +{ + onApply(); + myModel->update(); +} + +/*! + SLOT on close button click: erases preview and rejects dialog +*/ +void OCCViewer_ClippingDlg::ClickOnClose() +{ + erasePreview(); + OCCViewer_ViewWindow* v = qobject_cast(parent()); + if(v) + v->onClipping(false); +} + +/*! + SLOT on help button click: opens a help page +*/ +void OCCViewer_ClippingDlg::ClickOnHelp() +{ + SUIT_Application* app = SUIT_Session::session()->activeApplication(); + if ( app ) + app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" ); +} + +/*! + Set absolute mode of clipping plane +*/ +void OCCViewer_ClippingDlg::onModeAbsolute() +{ + myIsPlaneCreation = true; + ModeStackedLayout->setCurrentIndex(0); + ClickOnNew(); + myIsPlaneCreation = false; + updateClipping(); +} + +/*! + Set relative mode of clipping plane +*/ +void OCCViewer_ClippingDlg::onModeRelative() +{ + myIsPlaneCreation = true; + ModeStackedLayout->setCurrentIndex(1); + ClickOnNew(); + myIsPlaneCreation = false; + SetCurrentPlaneParam(); + updateClipping(); +} + +/*! + SLOT: called on value of clipping plane changed +*/ +void OCCViewer_ClippingDlg::onValueChanged() +{ + if ( myIsUpdatingControls ) + { + return; + } + + SetCurrentPlaneParam(); + + if ( myIsSelectPlane ) + { + return; + } + + updateClipping(); +} + +/*! + Set current parameters of selected plane +*/ +void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex ) +{ + if ( clipPlanesCount() == 0 ) + { + return; + } + + OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex ); + + myIsSelectPlane = true; + updateControls(); + ComboBoxPlanes->setCurrentIndex( theIndex ); + myIsSelectPlane = false; +} + +/*! + Restore parameters of selected plane +*/ +void OCCViewer_ClippingDlg::SetCurrentPlaneParam() +{ + if ( clipPlanesCount() == 0 || myIsSelectPlane || myBusy ) + { + return; + } + + int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); + + OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); + + setPlaneParam( aPlane ); +} + +/*! + SLOT on reset button click: sets default values +*/ +void OCCViewer_ClippingDlg::onReset() +{ + myBusy = true; + SpinBox_X->setValue(0); + SpinBox_Y->setValue(0); + SpinBox_Z->setValue(0); + myBusy = false; + + updateClipping(); +} + +/*! + SLOT on invert button click: inverts normal of cutting plane +*/ +void OCCViewer_ClippingDlg::onInvert() +{ + double Dx = SpinBox_Dx->value(); + double Dy = SpinBox_Dy->value(); + double Dz = SpinBox_Dz->value(); + + myBusy = true; + SpinBox_Dx->setValue( -Dx ); + SpinBox_Dy->setValue( -Dy ); + SpinBox_Dz->setValue( -Dz ); + myBusy = false; + + if ( clipPlanesCount() != 0 ) + { + int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); + OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); + aPlane.AbsoluteOrientation.IsInvert = !aPlane.AbsoluteOrientation.IsInvert; + } + updateClipping(); +} + +/*! + SLOT: called on orientation of clipping plane in absolute mode changed +*/ +void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode ) +{ + bool isUserMode = (mode==0); + + TextLabelX->setEnabled( isUserMode ); + TextLabelY->setEnabled( isUserMode ); + TextLabelZ->setEnabled( isUserMode ); + + SpinBox_X->setEnabled( isUserMode ); + SpinBox_Y->setEnabled( isUserMode ); + SpinBox_Z->setEnabled( isUserMode ); + + TextLabelDx->setEnabled( isUserMode ); + TextLabelDy->setEnabled( isUserMode ); + TextLabelDz->setEnabled( isUserMode ); + + SpinBox_Dx->setEnabled( isUserMode ); + SpinBox_Dy->setEnabled( isUserMode ); + SpinBox_Dz->setEnabled( isUserMode ); + + if ( !isUserMode ) { + + double aDx = 0, aDy = 0, aDz = 0; + + if ( mode == 1 ) + { + aDz = 1; + TextLabelZ->setEnabled( true ); + SpinBox_Z->setEnabled( true ); + SpinBox_Z->setFocus(); + } + else if ( mode == 2 ) + { + aDx = 1; + TextLabelX->setEnabled( true ); + SpinBox_X->setEnabled( true ); + SpinBox_X->setFocus(); + } + else if ( mode == 3 ) + { + aDy = 1; + TextLabelY->setEnabled( true ); + SpinBox_Y->setEnabled( true ); + SpinBox_Y->setFocus(); + } + + int aCurPlaneIndex = ComboBoxPlanes->currentIndex(); + OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex ); + if ( aPlane.AbsoluteOrientation.IsInvert == true ) + { + aDx = -aDx; + aDy = -aDy; + aDz = -aDz; + } + + myBusy = true; + SpinBox_Dx->setValue( aDx ); + SpinBox_Dy->setValue( aDy ); + SpinBox_Dz->setValue( aDz ); + myBusy = false; + } + + if ( !myIsUpdatingControls ) + { + SetCurrentPlaneParam(); + updateClipping(); + } +} + +/*! + SLOT: called on orientation of clipping plane in relative mode changed +*/ +void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem) +{ + if ( clipPlanesCount() == 0 ) + return; + + if ( theItem == 0 ) { + TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) ); + TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) ); + } + else if ( theItem == 1 ) { + TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) ); + TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) ); + } + else if ( theItem == 2 ) { + TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) ); + TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) ); + } + + if ( !myIsUpdatingControls ) + { + if( (QComboBox*)sender() == CBRelativeOrientation ) + { + SetCurrentPlaneParam(); + } + + updateClipping(); + } +} + +/*! + SLOT: called on preview check box toggled +*/ +void OCCViewer_ClippingDlg::onPreview( bool on ) +{ + erasePreview(); + if ( on ) + displayPreview(); +} + +/*! + SLOT: called on Auto Apply check box toggled +*/ +void OCCViewer_ClippingDlg::onAutoApply( bool toggled ) +{ + if ( toggled ) { + onApply(); + myModel->update(); + } +} + +/*! + SLOT on Apply button click: sets cutting plane +*/ +void OCCViewer_ClippingDlg::onApply() +{ + if ( myBusy ) + return; + myIsSelectPlane = true; + + qApp->processEvents(); + QApplication::setOverrideCursor( Qt::WaitCursor ); + qApp->processEvents(); + + myModel->setClipPlanes(myLocalPlanes); + + QApplication::restoreOverrideCursor(); + myIsSelectPlane = false; +} + +/*! + SLOT: Called when clip plane is clicked in viewer. +*/ +void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane ) +{ + for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ ) + { + Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt ); + if ( aPlane != thePlane ) + { + continue; + } + + ComboBoxPlanes->setCurrentIndex( aPlaneIt ); + + break; + } +} + +/*! + SLOT: Called when clip plane is changed by dragging in viewer. +*/ +void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane ) +{ + for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ ) + { + Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt ); + if ( aPlane != thePlane ) + { + continue; + } + + OCCViewer_ClipPlane& aClipPlane = getClipPlane( aPlaneIt ); + + gp_Pln aPln = thePlane->Component()->Pln(); + const gp_Pnt& aPlaneP = aPln.Location(); + const gp_Dir& aPlaneN = aPln.Axis().Direction(); + + aClipPlane.X = aPlaneP.X(); + aClipPlane.Y = aPlaneP.Y(); + aClipPlane.Z = aPlaneP.Z(); + + if ( aClipPlane.Mode == OCCViewer_ClipPlane::Absolute ) + { + if ( aClipPlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom ) + { + aClipPlane.AbsoluteOrientation.Dx = aPlaneN.X(); + aClipPlane.AbsoluteOrientation.Dy = aPlaneN.Y(); + aClipPlane.AbsoluteOrientation.Dz = aPlaneN.Z(); + } + } + else + { + OCCViewer_ClipPlane::DXYZToRelative( aPlaneN.X(), aPlaneN.Y(), aPlaneN.Z(), + aClipPlane.OrientationType, + aClipPlane.RelativeOrientation.Rotation1, + aClipPlane.RelativeOrientation.Rotation2 ); + } + + myIsUpdatingControls = true; + updateControls(); + myIsUpdatingControls = false; + + if ( AutoApplyCheckBox->isChecked() ) + { + onApply(); + } + + break; + } +} + +OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane( int theIdx ) +{ + return myLocalPlanes[theIdx]; +} + +int OCCViewer_ClippingDlg::clipPlanesCount() +{ + return myLocalPlanes.size(); +} + OCCViewer_ClipPlane::PlaneMode OCCViewer_ClippingDlg::currentPlaneMode() const { return ModeStackedLayout->currentIndex() == 0 diff --git a/src/Plot2d/Plot2d.cxx b/src/Plot2d/Plot2d.cxx index df128be76..ef7abf737 100755 --- a/src/Plot2d/Plot2d.cxx +++ b/src/Plot2d/Plot2d.cxx @@ -529,7 +529,7 @@ bool Plot2d::existMarker( const int rtti, const QwtPlot* thePlot, const QwtSymbo if ( anItem && anItem->rtti() == rtti ) { QwtPlotCurve* crv = dynamic_cast( anItem ); if ( crv ) { - QwtSymbol::Style aStyle = crv->symbol().style(); + QwtSymbol::Style aStyle = crv->symbol()->style(); QColor aColor = crv->pen().color(); Qt::PenStyle aLine = crv->pen().style(); ok = closeColors( aColor, color ) && aStyle == typeMarker && aLine == typeLine; diff --git a/src/Plot2d/Plot2d.h b/src/Plot2d/Plot2d.h index 3ce359999..56fa70e4c 100755 --- a/src/Plot2d/Plot2d.h +++ b/src/Plot2d/Plot2d.h @@ -37,7 +37,9 @@ #endif #include -#include +#include +#include +#include class QPainter; class QwtPlot; diff --git a/src/Plot2d/Plot2d_AnalyticalCurve.cxx b/src/Plot2d/Plot2d_AnalyticalCurve.cxx index e769da386..539547ebf 100755 --- a/src/Plot2d/Plot2d_AnalyticalCurve.cxx +++ b/src/Plot2d/Plot2d_AnalyticalCurve.cxx @@ -165,18 +165,18 @@ void Plot2d_AnalyticalCurve::updatePlotItem() aCurve->setSelected(isSelected()); aCurve->setPen( QPen(aColor , lineW, ps ) ); - aCurve->setSymbol( QwtSymbol( ms, QBrush( aColor ), - QPen( aColor ), - QSize( markerS , markerS ) ) ); + aCurve->setSymbol( new QwtSymbol( ms, QBrush( aColor ), + QPen( aColor ), + QSize( markerS , markerS ) ) ); aCurve->setLegendPen(QPen(getColor(), getLineWidth(), ps )); - aCurve->setLegendSymbol( QwtSymbol( ms, QBrush( getColor() ), - QPen( getColor() ), - QSize( getMarkerSize() , getMarkerSize() ))); + aCurve->setLegendSymbol( new QwtSymbol( ms, QBrush( getColor() ), + QPen( getColor() ), + QSize( getMarkerSize() , getMarkerSize() ))); double *x, *y; long nb = getData( &x, &y ); - aCurve->setData( x, y, nb ); + aCurve->setSamples( x, y, nb ); aCurve->setTitle(getName()); } @@ -213,10 +213,10 @@ void Plot2d_AnalyticalCurve::calculate() { */ bool Plot2d_AnalyticalCurve::checkCurve( const QwtPlot* thePlot) { if( !myExpression.isEmpty() && thePlot ) { - const QwtScaleDiv* div = thePlot->axisScaleDiv(QwtPlot::xBottom); - setRangeBegin(div->lowerBound()); - setRangeEnd(div->upperBound()); - calculate(); + const QwtScaleDiv div = thePlot->axisScaleDiv(QwtPlot::xBottom); + setRangeBegin(div.lowerBound()); + setRangeEnd(div.upperBound()); + calculate(); } return myState == Plot2d_AnalyticalCurve::StateOk; } diff --git a/src/Plot2d/Plot2d_Curve.cxx b/src/Plot2d/Plot2d_Curve.cxx index 8e029c32b..4b7f8878e 100755 --- a/src/Plot2d/Plot2d_Curve.cxx +++ b/src/Plot2d/Plot2d_Curve.cxx @@ -135,19 +135,19 @@ void Plot2d_Curve::updatePlotItem( QwtPlotItem* theItem ) aCurve->setSelected(isSelected()); aCurve->setPen( QPen(aColor , lineW, ps ) ); - aCurve->setSymbol( QwtSymbol( ms, QBrush( aColor ), - QPen( aColor ), - QSize( markerS , markerS ) ) ); + aCurve->setSymbol( new QwtSymbol( ms, QBrush( aColor ), + QPen( aColor ), + QSize( markerS , markerS ) ) ); aCurve->setLegendPen(QPen(getColor(), getLineWidth(), ps )); - aCurve->setLegendSymbol( QwtSymbol( ms, QBrush( getColor() ), - QPen( getColor() ), - QSize( getMarkerSize() , getMarkerSize() ))); + aCurve->setLegendSymbol( new QwtSymbol( ms, QBrush( getColor() ), + QPen( getColor() ), + QSize( getMarkerSize() , getMarkerSize() ))); double *x, *y, *min, *max; long nb = getData( &x, &y ); if(nb > 0 && x && y) { - aCurve->setData( x, y, nb ); + aCurve->setSamples( x, y, nb ); delete [] x; delete [] y; QList idx; @@ -160,7 +160,7 @@ void Plot2d_Curve::updatePlotItem( QwtPlotItem* theItem ) aCurve->clearDeviationData(); } } else { - aCurve->setData( NULL, NULL, 0 ); + aCurve->setSamples( NULL, NULL, 0 ); } } diff --git a/src/Plot2d/Plot2d_Histogram.cxx b/src/Plot2d/Plot2d_Histogram.cxx index 06e2ef1fd..d17361bb8 100644 --- a/src/Plot2d/Plot2d_Histogram.cxx +++ b/src/Plot2d/Plot2d_Histogram.cxx @@ -135,22 +135,20 @@ void Plot2d_Histogram::setData( const QList& theXVals, /*! Gets data */ -QwtIntervalData Plot2d_Histogram::getData() const +QwtIntervalSeriesData Plot2d_Histogram::getData() const { pointList aPoints = getPointList(); int aSize = aPoints.size(); - QwtArray anIntervals( aSize ); - QwtArray aValues( aSize ); + QwtArray anIntervals( aSize ); double aX; double aWidth = myWidth <= 0 ? myDefWidth : myWidth; // VSR: width is either manually assigned or auto-calculated for ( int i = 0; i < aSize; i++ ) { aX = aPoints[i].x; - anIntervals[i] = QwtDoubleInterval( aX - aWidth/2, aX + aWidth/2 ); - aValues[i] = aPoints[i].y; + anIntervals[i] = QwtIntervalSample( aPoints[i].y, aX - aWidth/2, aX + aWidth/2 ); } - return QwtIntervalData( anIntervals, aValues ); + return QwtIntervalSeriesData( anIntervals ); } /*! diff --git a/src/Plot2d/Plot2d_Histogram.h b/src/Plot2d/Plot2d_Histogram.h index f5d5370a1..0e4b319e6 100644 --- a/src/Plot2d/Plot2d_Histogram.h +++ b/src/Plot2d/Plot2d_Histogram.h @@ -28,7 +28,7 @@ #include "Plot2d.h" #include "Plot2d_Object.h" -#include +#include class PLOT2D_EXPORT Plot2d_Histogram : public Plot2d_Object { @@ -39,30 +39,30 @@ public: virtual ~Plot2d_Histogram(); Plot2d_Histogram& operator= ( const Plot2d_Histogram& ); - virtual int rtti(); - virtual QwtPlotItem* createPlotItem(); - virtual void autoFill( const QwtPlot* ); - virtual void updatePlotItem( QwtPlotItem* ); + virtual int rtti(); + virtual QwtPlotItem* createPlotItem(); + virtual void autoFill( const QwtPlot* ); + virtual void updatePlotItem( QwtPlotItem* ); - void setData( const QList&, const QList& ); - QwtIntervalData getData() const; + void setData( const QList&, const QList& ); + QwtIntervalSeriesData getData() const; - void setColor( const QColor& ); - QColor getColor() const; + void setColor( const QColor& ); + QColor getColor() const; - void setWidth( const double ); - double getWidth( const bool ) const; + void setWidth( const double ); + double getWidth( const bool ) const; - static double getMinInterval( const QList& ); + static double getMinInterval( const QList& ); protected: - QColor getNextColor( const QwtPlot* ); - bool existColor( const QwtPlot*, const QColor& ); + QColor getNextColor( const QwtPlot* ); + bool existColor( const QwtPlot*, const QColor& ); private: - QColor myColor; - double myWidth; - double myDefWidth; + QColor myColor; + double myWidth; + double myDefWidth; }; #endif // PLOT2D_HISTOGRAM_H diff --git a/src/Plot2d/Plot2d_Object.cxx b/src/Plot2d/Plot2d_Object.cxx index bb11956b4..3315c46c2 100755 --- a/src/Plot2d/Plot2d_Object.cxx +++ b/src/Plot2d/Plot2d_Object.cxx @@ -25,34 +25,10 @@ #include "Plot2d_Object.h" -#ifndef NO_SUIT -#include -#include -#endif - // Static members QColor Plot2d_Object::mySelectionColor; QColor Plot2d_Object::myHighlightedLegendTextColor; -/* - * Read colors from the resource manager. -*/ -void Plot2d_Object::initColors() { -#ifndef NO_SUIT - SUIT_Session* session = SUIT_Session::session(); - if(!session) - return; - - SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - if(resMgr) { - mySelectionColor = resMgr->colorValue( "Plot2d", "SelectionColor", QColor(80,80,80) ); - myHighlightedLegendTextColor = resMgr->colorValue( "Plot2d", "SelectedLegendFontColor", QColor(255,255,255) ); - } -#else - mySelectionColor = QColor(80,80,80); - myHighlightedLegendTextColor = QColor(255,255,255); -#endif -} /*! Constructor @@ -127,7 +103,7 @@ void Plot2d_Object::updatePlotItem( QwtPlotItem* theItem ) return; if ( theItem->yAxis() != getYAxis() || theItem->xAxis() != getXAxis() ) { - theItem->setAxis( getXAxis(), getYAxis() ); + theItem->setAxes( getXAxis(), getYAxis() ); QwtPlot* aPlot = theItem->plot(); if ( aPlot ) { diff --git a/src/Plot2d/Plot2d_Object.h b/src/Plot2d/Plot2d_Object.h index a0c4740f4..5820a2a19 100755 --- a/src/Plot2d/Plot2d_Object.h +++ b/src/Plot2d/Plot2d_Object.h @@ -105,8 +105,6 @@ public: void setSelected(const bool); bool isSelected() const; - static void initColors(); - static void setSelectionColor(const QColor& c); static QColor selectionColor(); diff --git a/src/Plot2d/Plot2d_PlotItems.cxx b/src/Plot2d/Plot2d_PlotItems.cxx index b477a08f6..a2222caa5 100644 --- a/src/Plot2d/Plot2d_PlotItems.cxx +++ b/src/Plot2d/Plot2d_PlotItems.cxx @@ -24,19 +24,25 @@ #include "Plot2d_PlotItems.h" #include "Plot2d_Object.h" +#include "Plot2d_ViewFrame.h" #include #include #include #include #include +#include +#include #include #include #include #include -#include +#include #include +const int SPACING = 10; +const int SYMBOL_SIZE = 13; + const char* yAxisLeft[] = { "12 12 2 1", " c None", @@ -72,44 +78,69 @@ const char* yAxisRight[] = { " "}; /*! - Constructor of Plot2d_QwtLegendItem + Constructor of Plot2d_QwtLegendLabel */ -Plot2d_QwtLegendItem::Plot2d_QwtLegendItem( QWidget* parent ) : - QwtLegendItem( parent ), +Plot2d_QwtLegendLabel::Plot2d_QwtLegendLabel( QWidget* parent ) : + QwtLegendLabel( parent ), myYAxisIdentifierMode( IM_None ), - myIsSelected(false) + myIsSelected(false), + mySymbol( new QwtSymbol() ), + mySymbolType(0), + myPen( QPen() ) { myYAxisLeftIcon = yAxisLeft; myYAxisRightIcon = yAxisRight; int anIconWidth = qMax( myYAxisLeftIcon.width(), myYAxisRightIcon.width() ); + setSpacing( SPACING ); mySpacingCollapsed = spacing(); - mySpacingExpanded = anIconWidth - mySpacingCollapsed; + mySpacingExpanded = anIconWidth + mySpacingCollapsed; } /*! - Destructor of Plot2d_QwtLegendItem + Destructor of Plot2d_QwtLegendLabel */ -Plot2d_QwtLegendItem::~Plot2d_QwtLegendItem() +Plot2d_QwtLegendLabel::~Plot2d_QwtLegendLabel() { } /*! Set Y axis identifier displaying mode */ -void Plot2d_QwtLegendItem::setYAxisIdentifierMode( const int theMode ) +void Plot2d_QwtLegendLabel::setYAxisIdentifierMode( const int theMode ) { myYAxisIdentifierMode = theMode; setSpacing( theMode == IM_None ? mySpacingCollapsed : mySpacingExpanded ); } /*! - Redefined method of drawing identifier of legend item + Paint the identifier to a given rect. + \param painter Painter + \param rect Rect where to paint */ -void Plot2d_QwtLegendItem::drawIdentifier( QPainter* painter, const QRect& rect ) const +void Plot2d_QwtLegendLabel::drawIdentifier( QPainter* painter, const QRect& rect ) { - QwtLegendItem::drawIdentifier( painter, rect ); + if ( rect.isEmpty() ) + return; + if( myPen.style() != Qt::NoPen ) { + painter->save(); + painter->setPen(myPen); + QwtPainter::drawLine( painter, rect.left() - 2, rect.center().y() + mySymbolType * 4, + rect.right() + 2, rect.center().y() + mySymbolType * 4 ); + painter->restore(); + } + if ( mySymbol->style() != QwtSymbol::NoSymbol ) + { + QRect symbolRect; + symbolRect.setSize( QSize( SYMBOL_SIZE, SYMBOL_SIZE ) ); + symbolRect.moveCenter( QPoint( rect.center().x(), rect.center().y() - mySymbolType * 4 ) ); + painter->save(); + painter->setBrush( mySymbol->brush() ); + painter->setPen( mySymbol->pen() ); + mySymbol->drawSymbol( painter, symbolRect ); + painter->restore(); + } if( myYAxisIdentifierMode != IM_None ) { QPixmap aPixmap( myYAxisIdentifierMode == IM_Left ? yAxisLeft : yAxisRight ); painter->save(); @@ -121,19 +152,22 @@ void Plot2d_QwtLegendItem::drawIdentifier( QPainter* painter, const QRect& rect /*! Update highliting on the item. */ -void Plot2d_QwtLegendItem::updateHighlit() { +void Plot2d_QwtLegendLabel::updateHighlit() { QwtText txt = text(); - if(isSelected()) { + if( isSelected() ) { QColor highlightColor = Plot2d_Object::selectionColor(); - if(highlightColor != txt.backgroundBrush().color()) { - txt.setBackgroundBrush(highlightColor); + if( highlightColor != txt.backgroundBrush().color() ) { + txt.setBackgroundBrush( highlightColor ); setText(txt); } - } else if( QWidget* parent = qobject_cast(this->parent()->parent()) ) { - QPalette aPal = parent->palette(); - if(aPal.color(QPalette::Background) != txt.backgroundBrush().color()) { - txt.setBackgroundBrush(aPal.color(QPalette::Background)); - setText(txt); + } + else if( this->parent() ) { + if(QWidget* parent = qobject_cast( this->parent()->parent() ) ) { + QPalette aPal = parent->palette(); + if( aPal.color( QPalette::Background) != txt.backgroundBrush().color() ) { + txt.setBackgroundBrush( aPal.color( QPalette::Background ) ); + setText( txt ); + } } } } @@ -141,14 +175,14 @@ void Plot2d_QwtLegendItem::updateHighlit() { /*! Sets selected property. */ -void Plot2d_QwtLegendItem::setSelected(const bool on) { +void Plot2d_QwtLegendLabel::setSelected(const bool on) { myIsSelected = on; } /*! Gets selected property. */ -bool Plot2d_QwtLegendItem::isSelected() const { +bool Plot2d_QwtLegendLabel::isSelected() const { return myIsSelected; } @@ -156,17 +190,79 @@ bool Plot2d_QwtLegendItem::isSelected() const { /* Draw text of the item. */ -void Plot2d_QwtLegendItem::drawText(QPainter * painter, const QRect &rect) { +void Plot2d_QwtLegendLabel::drawText( QPainter * painter, const QRectF &rect ) { painter->setPen( isSelected() ? Plot2d_Object::highlightedLegendTextColor() : - getColorFromPalette( QPalette::Text) ); + getColorFromPalette( QPalette::Text) ); - QwtLegendItem::drawText( painter, rect ); + QwtTextLabel::drawText( painter, rect ); +} + +/*! + Sets symbol. +*/ +void Plot2d_QwtLegendLabel::setSymbol( const QwtSymbol* theSymbol ) +{ + mySymbol = new QwtSymbol( theSymbol->style(), theSymbol->brush(), + theSymbol->pen(), theSymbol->size() ); +} + +/*! + Sets symbol type 0(marker on line) or 1(marker above line). +*/ +void Plot2d_QwtLegendLabel::setSymbolType( const int theType ) +{ + mySymbolType = theType; +} + +/*! + Sets pen. +*/ +void Plot2d_QwtLegendLabel::setPen (const QPen& thePen ) +{ + myPen = thePen; +} + +/*! + Redefined method paintEvent of QwtLegendLabel +*/ +void Plot2d_QwtLegendLabel::paintEvent( QPaintEvent *e ) +{ + const QRect cr = contentsRect(); + + int ButtonFrame = 6; + QPainter painter( this ); + painter.setClipRegion( e->region() ); + + if ( isDown() ) + { + qDrawWinButton( &painter, 0, 0, width(), height(), + palette(), true ); + } + + painter.save(); + painter.setClipRect( cr ); + + drawContents( &painter ); + + QRect iconRect = cr; + if ( !icon().isNull() ) + { + if ( itemMode() != QwtLegendData::ReadOnly ) + iconRect.setX( iconRect.x() + ButtonFrame ); + iconRect.setSize( QSize( icon().size().width() + spacing() , + icon().size().height() + spacing() ) ); + iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) ); + } + + drawIdentifier( &painter, iconRect ); + + painter.restore(); } /* Get color from the legend pallete by 'role' flag. */ -QColor Plot2d_QwtLegendItem::getColorFromPalette(QPalette::ColorRole role) { +QColor Plot2d_QwtLegendLabel::getColorFromPalette(QPalette::ColorRole role) { QWidget* pw = parentWidget(); QColor col = palette().color( role ); while( pw ) { @@ -242,72 +338,63 @@ void Plot2d_QwtPlotCurve::setYAxisIdentifierEnabled( const bool on ) /*! Redefined method, which updates legend of the curve */ -void Plot2d_QwtPlotCurve::updateLegend( QwtLegend* legend ) const +void Plot2d_QwtPlotCurve::updateLegend( const QwtPlotItem* thePlotItem, + const QList& theLegendData ) { - if ( !legend ) + if ( !thePlotItem || !thePlotItem->plot() ) return; - QWidget* widget = legend->find( this ); - - if ( testItemAttribute(QwtPlotItem::Legend) ) { - - if ( widget == NULL ) { - widget = legendItem(); - if ( widget ) { - if ( widget->inherits("QwtLegendItem") ) { - QwtLegendItem *label = (QwtLegendItem *)widget; - label->setItemMode(legend->itemMode()); - - if ( plot() ) { - QObject::connect(label, SIGNAL(clicked()), - plot(), SLOT(legendItemClicked())); - QObject::connect(label, SIGNAL(checked(bool)), - plot(), SLOT(legendItemChecked(bool))); - } - } - legend->contentsWidget()->layout()->addWidget(widget); - legend->insert(this, widget); - } - } - - QwtPlotCurve::updateLegend( legend ); - + if ( !testItemAttribute( QwtPlotItem::Legend ) ) + return; - if( Plot2d_QwtLegendItem* anItem = dynamic_cast( widget ) ) { - int aMode = Plot2d_QwtLegendItem::IM_None; - if( myYAxisIdentifierEnabled ) - aMode = myYAxis == QwtPlot::yRight ? - Plot2d_QwtLegendItem::IM_Right : - Plot2d_QwtLegendItem::IM_Left; - anItem->setYAxisIdentifierMode( aMode ); - if(isSelected()) { - anItem->setCurvePen(legendPen()); - anItem->setSymbol(legendSymbol()); - } - anItem->setSelected(isSelected()); - anItem->updateHighlit(); - } + QwtPlotCurve::updateLegend( thePlotItem, theLegendData ); + + const QVariant itemInfo = thePlotItem->plot()->itemToInfo( const_cast< QwtPlotItem *>( thePlotItem ) ); + QwtLegend* legend = dynamic_cast( thePlotItem->plot()->legend() ); + QWidget* widget = legend->legendWidget( itemInfo ); + QwtLegendLabel* label = dynamic_cast( widget ); + if( Plot2d_QwtLegendLabel* anItem = (Plot2d_QwtLegendLabel*)label ) { + int aMode = Plot2d_QwtLegendLabel::IM_None; + if( myYAxisIdentifierEnabled ) + aMode = myYAxis == QwtPlot::yRight ? + Plot2d_QwtLegendLabel::IM_Right : + Plot2d_QwtLegendLabel::IM_Left; + anItem->setYAxisIdentifierMode( aMode ); + + anItem->setSymbol( legendSymbol() ); + if( Plot2d_Plot2d* plot = dynamic_cast( thePlotItem->plot() ) ) + anItem->setSymbolType( plot->getLegendSymbolType() ); + anItem->setPen( legendPen() ); + + anItem->setSelected( isSelected() ); + anItem->updateHighlit(); + anItem->repaint(); } } /*! - Redefined method, which creates and returns legend item of the curve + Redefined method, which updates and calls QwtPlot::autoRefresh() for the parent plot */ -QWidget* Plot2d_QwtPlotCurve::legendItem() const +void Plot2d_QwtPlotCurve::itemChanged() { - return new Plot2d_QwtLegendItem; + if ( plot() ) + updateLegend( this, legendData() ); + + QwtPlotItem::itemChanged(); } /*! Redefined method, which draw a set of points of a curve. */ -void Plot2d_QwtPlotCurve::draw(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void Plot2d_QwtPlotCurve::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QRectF &canvasRect, + int from, int to) const { if (to < 0) to = dataSize() - 1; - QwtPlotCurve::draw(painter, xMap, yMap, from, to); + QwtPlotCurve::drawSeries(painter, xMap, yMap, canvasRect, from, to); //draw deviation data if(hasDeviationData()) { @@ -321,8 +408,9 @@ void Plot2d_QwtPlotCurve::draw(QPainter *painter, painter->setPen(p); for (int i = from; i <= to; i++) { if(!myDeviationData->values(i,min,max)) continue; - xi = x(i); - yi = y(i); + const QPointF sample = data()->sample( i ); + xi = sample.x(); + yi = sample.y(); xp = xMap.transform(xi); ytop = yMap.transform(yi + max); ybtm = yMap.transform(yi - min); @@ -406,7 +494,9 @@ void Plot2d_QwtPlotCurve::clearDeviationData() Constructor. */ Plot2d_SelectableItem::Plot2d_SelectableItem(): - myIsSelected(false) + myIsSelected(false), + myLegendSymbol( new QwtSymbol() ), + myLegendPen( QPen() ) { } @@ -448,15 +538,19 @@ QPen Plot2d_SelectableItem::legendPen() const { /*! Sets legend symbol property. */ -void Plot2d_SelectableItem::setLegendSymbol(const QwtSymbol& s) { - myLegendSymbol = s; +void Plot2d_SelectableItem::setLegendSymbol( const QwtSymbol* s ) { + myLegendSymbol->setStyle( s->style() ); + myLegendSymbol->setBrush( s->brush() ); + myLegendSymbol->setPen( s->pen() ); + myLegendSymbol->setSize( s->size() ); } /*! Sets legend symbol property. */ -QwtSymbol Plot2d_SelectableItem::legendSymbol() const { - return myLegendSymbol; +QwtSymbol* Plot2d_SelectableItem::legendSymbol() const { + return new QwtSymbol( myLegendSymbol->style(), myLegendSymbol->brush(), + myLegendSymbol->pen(), myLegendSymbol->size() ); } /*! @@ -521,16 +615,16 @@ double Plot2d_HistogramQwtItem::baseline() const /*! Sets data to object */ -void Plot2d_HistogramQwtItem::setData( const QwtIntervalData& theData ) +void Plot2d_HistogramQwtItem::setData( const QwtIntervalSeriesData& theData ) { - myData = theData; + myData.setSamples( theData.samples() ); itemChanged(); } /*! Returns data from object */ -const QwtIntervalData& Plot2d_HistogramQwtItem::data() const +const QwtIntervalSeriesData& Plot2d_HistogramQwtItem::data() const { return myData; } @@ -618,7 +712,7 @@ bool Plot2d_HistogramQwtItem::testHistogramAttribute( HistogramAttribute theAttr void Plot2d_HistogramQwtItem::draw( QPainter* thePainter, const QwtScaleMap& theXMap, const QwtScaleMap& theYMap, - const QRect& ) const + const QRectF& ) const { thePainter->setPen( QPen( myColor ) ); @@ -627,19 +721,19 @@ void Plot2d_HistogramQwtItem::draw( QPainter* thePainter, for ( int i = 0; i < (int)myData.size(); i++ ) { if ( myAttributes & Plot2d_HistogramQwtItem::Xfy ) { - const int x2 = theXMap.transform( myData.value( i ) ); + const int x2 = theXMap.transform( myData.sample(i).value ); if ( x2 == x0 ) continue; - int y1 = theYMap.transform( myData.interval( i ).minValue() ); - int y2 = theYMap.transform( myData.interval( i ).maxValue() ); + int y1 = theYMap.transform( myData.sample( i ).interval.minValue() ); + int y2 = theYMap.transform( myData.sample( i ).interval.maxValue() ); if ( y1 > y2 ) qSwap( y1, y2 ); if ( i < (int)myData.size() - 2 ) { - const int yy1 = theYMap.transform( myData.interval(i+1).minValue() ); - const int yy2 = theYMap.transform( myData.interval(i+1).maxValue() ); + const int yy1 = theYMap.transform( myData.sample(i+1).interval.minValue() ); + const int yy2 = theYMap.transform( myData.sample(i+1).interval.maxValue() ); if ( y2 == qwtMin( yy1, yy2 ) ) { - const int xx2 = theXMap.transform( myData.interval(i+1).minValue() ); + const int xx2 = theXMap.transform( myData.sample(i+1).interval.minValue() ); if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) || ( xx2 > x0 && x2 > x0 ) ) ) { // One pixel distance between neighboured bars @@ -650,19 +744,19 @@ void Plot2d_HistogramQwtItem::draw( QPainter* thePainter, drawBar( thePainter, Qt::Horizontal, QRect( x0, y1, x2 - x0, y2 - y1 ) ); } else { - const int y2 = theYMap.transform( myData.value( i ) ); + const int y2 = theYMap.transform( myData.sample( i ).value ); if ( y2 == y0 ) continue; - int x1 = theXMap.transform( myData.interval( i ).minValue() ); - int x2 = theXMap.transform( myData.interval( i ).maxValue() ); + int x1 = theXMap.transform( myData.sample( i ).interval.minValue() ); + int x2 = theXMap.transform( myData.sample( i ).interval.maxValue() ); if ( x1 > x2 ) qSwap( x1, x2 ); if ( i < (int)myData.size() - 2 ) { - const int xx1 = theXMap.transform( myData.interval(i+1).minValue() ); - const int xx2 = theXMap.transform( myData.interval(i+1).maxValue() ); + const int xx1 = theXMap.transform( myData.sample(i+1).interval.minValue() ); + const int xx2 = theXMap.transform( myData.sample(i+1).interval.maxValue() ); if ( x2 == qwtMin( xx1, xx2 ) ) { - const int yy2 = theYMap.transform( myData.value(i+1) ); + const int yy2 = theYMap.transform( myData.sample(i+1).value ); if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) || ( yy2 > y0 && y2 > y0 ) ) ) { // One pixel distance between neighboured bars @@ -756,28 +850,35 @@ QList Plot2d_HistogramItem::getBars() const /*! Set to legend item symbol with color of item */ -void Plot2d_HistogramItem::updateLegend( QwtLegend* theLegend ) const +void Plot2d_HistogramItem::updateLegend( QwtPlotItem* thePlotItem, + QList& theLegendData ) { - if ( !theLegend ) + if ( !thePlotItem || !thePlotItem->plot() ) return; - Plot2d_HistogramQwtItem::updateLegend( theLegend ); + Plot2d_HistogramQwtItem::updateLegend( thePlotItem, theLegendData ); - QWidget* theWidget = theLegend->find( this ); - if ( !theWidget || !theWidget->inherits( "QwtLegendItem" ) ) + const QVariant itemInfo = thePlotItem->plot()->itemToInfo( const_cast< QwtPlotItem *>( thePlotItem ) ); + QwtLegend *legend = dynamic_cast( thePlotItem->plot()->legend() ); + QWidget* widget = legend->legendWidget( itemInfo ); + + if ( !widget || !widget->inherits( "QwtLegendItem" ) ) return; - Plot2d_QwtLegendItem* anItem = ( Plot2d_QwtLegendItem* )theWidget; - QFontMetrics aFMetrics( anItem->font() ); - int aSize = aFMetrics.height(); - QwtSymbol aSymbol( QwtSymbol::Rect, QBrush( legendPen().color() ), - QPen( legendPen().color() ), QSize( aSize, aSize ) ); - anItem->setSymbol( aSymbol ); - anItem->setIdentifierMode( theLegend->identifierMode() - | QwtLegendItem::ShowSymbol ); - anItem->setSelected(isSelected()); - anItem->updateHighlit(); - anItem->update(); + QwtLegendLabel* label = dynamic_cast( widget ); + if( Plot2d_QwtLegendLabel* anItem = (Plot2d_QwtLegendLabel*)( label ) ) { + QFontMetrics aFMetrics( anItem->font() ); + int aSize = aFMetrics.height(); + QwtSymbol* aSymbol = new QwtSymbol( QwtSymbol::Rect, QBrush( legendPen().color() ), + QPen( legendPen().color() ), QSize( aSize, aSize ) ); + anItem->setSymbol( aSymbol ); + if( Plot2d_Plot2d* plot = dynamic_cast( thePlotItem->plot() ) ) + anItem->setSymbolType( plot->getLegendSymbolType() ); + anItem->setSelected( isSelected() ); + anItem->updateHighlit(); + anItem->update(); + anItem->repaint(); + } } /*! @@ -786,7 +887,7 @@ void Plot2d_HistogramItem::updateLegend( QwtLegend* theLegend ) const void Plot2d_HistogramItem::draw( QPainter* thePainter, const QwtScaleMap& theXMap, const QwtScaleMap& theYMap, - const QRect& ) const + const QRectF& ) const { // nds: clear list of bar items Plot2d_HistogramItem* anItem = (Plot2d_HistogramItem*)this; @@ -796,23 +897,23 @@ void Plot2d_HistogramItem::draw( QPainter* thePainter, const int x0 = theXMap.transform( baseline() ); const int y0 = theYMap.transform( baseline() ); - const QwtIntervalData& iData = data(); + const QwtIntervalSeriesData& iData = data(); for ( int i = 0; i < (int)iData.size(); i++ ) { if ( testHistogramAttribute( Plot2d_HistogramItem::Xfy ) ) { - const int x2 = theXMap.transform( iData.value( i ) ); + const int x2 = theXMap.transform( iData.sample(i).value ); if ( x2 == x0 ) continue; - int y1 = theYMap.transform( iData.interval( i ).minValue() ); - int y2 = theYMap.transform( iData.interval( i ).maxValue() ); + int y1 = theYMap.transform( iData.sample(i).interval.minValue() ); + int y2 = theYMap.transform( iData.sample(i).interval.maxValue() ); if ( y1 > y2 ) qSwap( y1, y2 ); if ( i < (int)iData.size() - 2 ) { - const int yy1 = theYMap.transform( iData.interval(i+1).minValue() ); - const int yy2 = theYMap.transform( iData.interval(i+1).maxValue() ); + const int yy1 = theYMap.transform( iData.sample(i+1).interval.minValue() ); + const int yy2 = theYMap.transform( iData.sample(i+1).interval.maxValue() ); if ( y2 == qwtMin( yy1, yy2 ) ) { - const int xx2 = theXMap.transform( iData.interval(i+1).minValue() ); + const int xx2 = theXMap.transform( iData.sample(i+1).interval.minValue() ); if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) || ( xx2 > x0 && x2 > x0 ) ) ) { // One pixel distance between neighboured bars @@ -826,19 +927,19 @@ void Plot2d_HistogramItem::draw( QPainter* thePainter, anItem->myBarItems.append( aRect ); } else { - const int y2 = theYMap.transform( iData.value( i ) ); + const int y2 = theYMap.transform( iData.sample(i).value ); if ( y2 == y0 ) continue; - int x1 = theXMap.transform( iData.interval( i ).minValue() ); - int x2 = theXMap.transform( iData.interval( i ).maxValue() ); + int x1 = theXMap.transform( iData.sample(i).interval.minValue() ); + int x2 = theXMap.transform( iData.sample(i).interval.maxValue() ); if ( x1 > x2 ) qSwap( x1, x2 ); if ( i < (int)iData.size() - 2 ) { - const int xx1 = theXMap.transform( iData.interval(i+1).minValue() ); - const int xx2 = theXMap.transform( iData.interval(i+1).maxValue() ); + const int xx1 = theXMap.transform( iData.sample(i+1).interval.minValue() ); + const int xx2 = theXMap.transform( iData.sample(i+1).interval.maxValue() ); if ( x2 == qwtMin( xx1, xx2 ) ) { - const int yy2 = theYMap.transform( iData.value(i+1) ); + const int yy2 = theYMap.transform( iData.sample(i+1).value ); if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) || ( yy2 > y0 && y2 > y0 ) ) ) { // One pixel distance between neighboured bars @@ -870,15 +971,6 @@ bool Plot2d_HistogramItem::isCrossItems() const return myCrossed; } -/*! - Redefined method, which creates and returns legend item of the curve -*/ -QWidget* Plot2d_HistogramItem::legendItem() const -{ - return new Plot2d_QwtLegendItem; -} - - /*! Draws bar of histogram and on it bars of histograms with lower height. */ @@ -931,3 +1023,29 @@ int Plot2d_HistogramItem::getCrossedTop( const QRect& theRect ) const } return aRes; } + +Plot2d_QwtLegend::Plot2d_QwtLegend( QWidget *parent ): +QwtLegend( parent ) +{ + setAutoFillBackground(true); +} + +Plot2d_QwtLegend::~Plot2d_QwtLegend() +{ +} + +/*! + Redefined method, which create a widget to be inserted into the legend. +*/ +QWidget *Plot2d_QwtLegend::createWidget( const QwtLegendData &data ) const +{ + Q_UNUSED( data ); + + Plot2d_QwtLegendLabel *label = new Plot2d_QwtLegendLabel(); + label->setItemMode( defaultItemMode() ); + + connect( label, SIGNAL( clicked() ), SLOT( itemClicked() ) ); + connect( label, SIGNAL( checked( bool ) ), SLOT( itemChecked( bool ) ) ); + + return label; +} diff --git a/src/Plot2d/Plot2d_PlotItems.h b/src/Plot2d/Plot2d_PlotItems.h index 65f4a2884..fdc95111b 100644 --- a/src/Plot2d/Plot2d_PlotItems.h +++ b/src/Plot2d/Plot2d_PlotItems.h @@ -27,31 +27,37 @@ #include "Plot2d.h" -#include +#include +#include #include #include -#include #include +#include +#include -class PLOT2D_EXPORT Plot2d_QwtLegendItem : public QwtLegendItem +class PLOT2D_EXPORT Plot2d_QwtLegendLabel : public QwtLegendLabel { public: enum YAxisIdentifierMode { IM_None = 0, IM_Left, IM_Right }; public: - Plot2d_QwtLegendItem( QWidget* = 0 ); - virtual ~Plot2d_QwtLegendItem(); + Plot2d_QwtLegendLabel( QWidget* = 0 ); + virtual ~Plot2d_QwtLegendLabel(); public: void setYAxisIdentifierMode( const int ); void updateHighlit(); - void setSelected(const bool on); + void setSelected( const bool on ); bool isSelected() const; - QColor getColorFromPalette(QPalette::ColorRole role); + QColor getColorFromPalette( QPalette::ColorRole role ); + void drawIdentifier( QPainter*, const QRect& ); + void setSymbol( const QwtSymbol* ); + void setSymbolType( const int ); + void setPen( const QPen& ); protected: - virtual void drawIdentifier( QPainter*, const QRect& ) const; - virtual void drawText(QPainter *, const QRect &); + virtual void drawText( QPainter*, const QRectF& ); + virtual void paintEvent( QPaintEvent* ); private: @@ -62,26 +68,29 @@ private: int mySpacingCollapsed; int mySpacingExpanded; bool myIsSelected; + QwtSymbol* mySymbol; + int mySymbolType; + QPen myPen; }; class PLOT2D_EXPORT Plot2d_SelectableItem { public: - Plot2d_SelectableItem(); - ~Plot2d_SelectableItem(); - - void setSelected( const bool ); - bool isSelected() const; - - void setLegendPen( const QPen & ); - QPen legendPen() const; - - void setLegendSymbol( const QwtSymbol& ); - QwtSymbol legendSymbol() const; - + Plot2d_SelectableItem(); + ~Plot2d_SelectableItem(); + + void setSelected( const bool ); + bool isSelected() const; + + void setLegendPen( const QPen& ); + QPen legendPen() const; + + void setLegendSymbol( const QwtSymbol* ); + QwtSymbol* legendSymbol() const; + private: bool myIsSelected; QPen myLegendPen; - QwtSymbol myLegendSymbol; + QwtSymbol* myLegendSymbol; }; class PLOT2D_EXPORT Plot2d_QwtPlotCurve : public QwtPlotCurve, public Plot2d_SelectableItem @@ -92,27 +101,28 @@ public: public: virtual void setYAxisIdentifierEnabled( const bool ); - virtual void draw(QPainter *p, - const QwtScaleMap &xMap, - const QwtScaleMap &yMap, - int from, int to) const; + virtual void drawSeries( QPainter* p, + const QwtScaleMap& xMap, + const QwtScaleMap& yMap, + const QRectF& canvasRect, + int from, int to) const; - void setDeviationData(const double* min, const double* max, const QList &idx); + void setDeviationData( const double* min, const double* max, const QList& idx ); bool hasDeviationData() const; void clearDeviationData(); - protected: - virtual void updateLegend( QwtLegend* ) const; - virtual QWidget* legendItem() const; + virtual void updateLegend( const QwtPlotItem*, + const QList& ); + virtual void itemChanged(); QColor deviationMarkerColor() const; int deviationMarkerLineWidth() const; int deviationMarkerTickSize() const; private: - QwtPlot::Axis myYAxis; - bool myYAxisIdentifierEnabled; + QwtPlot::Axis myYAxis; + bool myYAxisIdentifierEnabled; class Plot2d_DeviationData; Plot2d_DeviationData* myDeviationData; @@ -131,8 +141,8 @@ public: explicit Plot2d_HistogramQwtItem( const QwtText& ); virtual ~Plot2d_HistogramQwtItem(); - void setData( const QwtIntervalData& ); - const QwtIntervalData& data() const; + void setData( const QwtIntervalSeriesData& ); + const QwtIntervalSeriesData& data() const; void setColor( const QColor& ); QColor color() const; @@ -140,7 +150,7 @@ public: virtual QwtDoubleRect boundingRect() const; virtual int rtti() const; virtual void draw( QPainter*, const QwtScaleMap&, - const QwtScaleMap&, const QRect& ) const; + const QwtScaleMap&, const QRectF& ) const; void setBaseline( double ); double baseline() const; @@ -156,7 +166,7 @@ private: private: int myAttributes; - QwtIntervalData myData; + QwtIntervalSeriesData myData; QColor myColor; double myReference; }; @@ -168,25 +178,34 @@ public: explicit Plot2d_HistogramItem( const QwtText& ); virtual ~Plot2d_HistogramItem(); - QList getBars() const; + QList getBars() const; - virtual void updateLegend( QwtLegend* ) const; - virtual void draw( QPainter*, const QwtScaleMap&, - const QwtScaleMap&, const QRect& ) const; + virtual void updateLegend( QwtPlotItem*, + QList& ); + virtual void draw( QPainter*, const QwtScaleMap&, + const QwtScaleMap&, const QRectF& ) const; + + void setCrossItems( bool theCross ); + bool isCrossItems() const; - void setCrossItems( bool theCross ); - bool isCrossItems() const; +protected: + void drawRectAndLowers( QPainter*, Qt::Orientation, + const QRect& ) const; + int getCrossedTop( const QRect& ) const; protected: - void drawRectAndLowers( QPainter*, Qt::Orientation, - const QRect& ) const; - int getCrossedTop( const QRect& ) const; + QList myBarItems; + bool myCrossed; +}; - virtual QWidget* legendItem() const; +class PLOT2D_EXPORT Plot2d_QwtLegend : public QwtLegend +{ +public: + explicit Plot2d_QwtLegend( QWidget *parent = NULL ); + virtual ~Plot2d_QwtLegend(); protected: - QList myBarItems; - bool myCrossed; + virtual QWidget* createWidget( const QwtLegendData& ) const; }; #endif // PLOT2D_PLOTITEMS_H diff --git a/src/Plot2d/Plot2d_SetupViewDlg.cxx b/src/Plot2d/Plot2d_SetupViewDlg.cxx index 9616b3f5d..41c4f8dfd 100755 --- a/src/Plot2d/Plot2d_SetupViewDlg.cxx +++ b/src/Plot2d/Plot2d_SetupViewDlg.cxx @@ -89,19 +89,6 @@ Plot2d_SetupViewDlg::Plot2d_SetupViewDlg( QWidget* parent, myCurveCombo->addItem( tr( "PLOT2D_CURVE_TYPE_LINES" ) ); myCurveCombo->addItem( tr( "PLOT2D_CURVE_TYPE_SPLINE" ) ); - // legend - myLegendCheck = new QCheckBox( tr( "PLOT2D_ENABLE_LEGEND" ), this ); - myLegendCombo = new QComboBox( this ); - myLegendFont = new QtxFontEdit( this ); - myLegendColor = new QtxColorButton( this ); - QLabel* aLegendFontLab = new QLabel( tr( "PLOT2D_LEGEND_FONT" ), this ); - myLegendCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - myLegendCombo->setMinimumWidth( MIN_COMBO_WIDTH ); - myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_LEFT" ) ); - myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_RIGHT" ) ); - myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_TOP" ) ); - myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_BOTTOM" ) ); - // marker size QLabel* aMarkerLab = new QLabel( tr( "PLOT2D_MARKER_SIZE_LBL" ), this ); myMarkerSpin = new QSpinBox( this ); @@ -115,6 +102,68 @@ Plot2d_SetupViewDlg::Plot2d_SetupViewDlg( QWidget* parent, QLabel* aBGLab = new QLabel( tr( "PLOT2D_BACKGROUND_COLOR_LBL" ), this ); myBackgroundBtn = new QtxColorButton( this ); + // selection color + QLabel* aSelectionLab = new QLabel( tr( "PLOT2D_SELECTION_COLOR_LBL" ), this ); + mySelectionBtn = new QtxColorButton( this ); + + QHBoxLayout* ViewerColorLayout = new QHBoxLayout; + ViewerColorLayout->addWidget( aBGLab ); + ViewerColorLayout->addWidget( myBackgroundBtn ); + ViewerColorLayout->addStretch(); + ViewerColorLayout->addWidget( aSelectionLab ); + ViewerColorLayout->addWidget( mySelectionBtn ); + ViewerColorLayout->addStretch(); + + // legend + QGroupBox* aLegendGrp = new QGroupBox( tr( "PLOT2D_LEGEND_GROUP" ), this ); + QGridLayout* aLegendLayout = new QGridLayout( aLegendGrp ); + aLegendLayout->setMargin( MARGIN_SIZE ); aLegendLayout->setSpacing( SPACING_SIZE ); + aLegendGrp->setLayout( aLegendLayout ); + + myLegendCheck = new QCheckBox( tr( "PLOT2D_ENABLE_LEGEND" ), this ); + + QLabel* aLegendPosition = new QLabel( tr( "PLOT2D_LEGEND_POSITION" ), this ); + myLegendCombo = new QComboBox( this ); + myLegendCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myLegendCombo->setMinimumWidth( MIN_COMBO_WIDTH ); + myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_LEFT" ) ); + myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_RIGHT" ) ); + myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_TOP" ) ); + myLegendCombo->addItem( tr( "PLOT2D_LEGEND_POSITION_BOTTOM" ) ); + + QLabel* aLegendSymbolType = new QLabel( tr( "PLOT2D_LEGEND_SYMBOL_TYPE" ), this ); + myLegendSymbolType = new QComboBox( this ); + myLegendSymbolType->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myLegendSymbolType->setMinimumWidth( MIN_COMBO_WIDTH ); + myLegendSymbolType->addItem( tr( "PLOT2D_MARKER_ON_LINE" ) ); + myLegendSymbolType->addItem( tr( "PLOT2D_MARKER_ABOVE_LINE" ) ); + + QLabel* aLegendFontLab = new QLabel( tr( "PLOT2D_LEGEND_FONT" ), this ); + myLegendFont = new QtxFontEdit( this ); + + QLabel* aLegendFontColor = new QLabel( tr( "PLOT2D_LEGEND_FONT_COLOR" ), this ); + myLegendFontColor = new QtxColorButton( this ); + + QLabel* aSelectLegendFontColor = new QLabel( tr( "PLOT2D_SELECTED_LEGEND_FONT_COLOR" ), this ); + mySelectedLegendFontColor = new QtxColorButton( this ); + + QHBoxLayout* FontLayout = new QHBoxLayout; + FontLayout->addWidget( aLegendFontColor ); + FontLayout->addWidget( myLegendFontColor ); + FontLayout->addStretch(); + FontLayout->addWidget( aSelectLegendFontColor ); + FontLayout->addWidget( mySelectedLegendFontColor ); + FontLayout->addStretch(); + + aLegendLayout->addWidget( myLegendCheck, 0, 0 ); + aLegendLayout->addWidget( aLegendPosition, 1, 0 ); + aLegendLayout->addWidget( myLegendCombo, 1, 1 ); + aLegendLayout->addWidget( aLegendSymbolType, 2, 0 ); + aLegendLayout->addWidget( myLegendSymbolType, 2, 1 ); + aLegendLayout->addWidget( aLegendFontLab, 3, 0 ); + aLegendLayout->addWidget( myLegendFont, 3, 1 ); + aLegendLayout->addLayout( FontLayout, 4, 0, 1, 2 ); + //Deviation marker parameters QGroupBox* aDeviationGrp = new QGroupBox( tr( "PLOT2D_DEVIATION_MARKER_TLT" ), this ); QHBoxLayout* aDeviationLayout = new QHBoxLayout(aDeviationGrp); @@ -375,30 +424,21 @@ Plot2d_SetupViewDlg::Plot2d_SetupViewDlg( QWidget* parent, btnLayout->addWidget( myHelpBtn ); // layout widgets - topLayout->addWidget( myTitleCheck, 0, 0 ); - topLayout->addWidget( myTitleEdit, 0, 1, 1, 3 ); - topLayout->addWidget( myLegendCheck, 1, 0 ); - topLayout->addWidget( myLegendCombo, 1, 1 ); - topLayout->addWidget( aCurveLab, 1, 2 ); - topLayout->addWidget( myCurveCombo, 1, 3 ); - topLayout->addWidget( aLegendFontLab,2, 0 ); - topLayout->addWidget( myLegendFont, 2, 1 ); - topLayout->addWidget( myLegendColor, 2, 2 ); - - topLayout->addWidget( aMarkerLab, 3, 0 ); - topLayout->addWidget( myMarkerSpin, 3, 1 ); - QHBoxLayout* bgLayout = new QHBoxLayout; - bgLayout->addWidget( myBackgroundBtn ); bgLayout->addStretch(); - topLayout->addWidget( aBGLab, 3, 2 ); - topLayout->addLayout( bgLayout, 3, 3 ); - topLayout->addWidget( aDeviationGrp, 4, 0, 1, 4 ); - topLayout->addWidget( aNormalizeGrp, 5, 0, 1, 4 ); - topLayout->addWidget( aScaleGrp, 6, 0, 1, 4 ); - topLayout->addWidget( aTabWidget, 7, 0, 1, 4 ); - topLayout->addWidget( myDefCheck, 8, 0, 1, 4 ); - topLayout->setRowStretch( 9, 5 ); - - topLayout->addLayout( btnLayout, 10, 0, 1, 4 ); + topLayout->addWidget( myTitleCheck, 0, 0 ); + topLayout->addWidget( myTitleEdit, 0, 1, 1, 3 ); + topLayout->addWidget( aCurveLab, 1, 0 ); + topLayout->addWidget( myCurveCombo, 1, 1 ); + topLayout->addWidget( aMarkerLab, 2, 0 ); + topLayout->addWidget( myMarkerSpin, 2, 1 ); + topLayout->addLayout( ViewerColorLayout, 3, 0, 1, 4 ); + topLayout->addWidget( aLegendGrp, 4, 0, 1, 4 ); + topLayout->addWidget( aDeviationGrp, 5, 0, 1, 4 ); + topLayout->addWidget( aNormalizeGrp, 6, 0, 1, 4 ); + topLayout->addWidget( aScaleGrp, 7, 0, 1, 4 ); + topLayout->addWidget( aTabWidget, 8, 0, 1, 4 ); + topLayout->addWidget( myDefCheck, 9, 0, 1, 4 ); + topLayout->setRowStretch( 10, 5 ); + topLayout->addLayout( btnLayout, 11, 0, 1, 4 ); if ( !showDefCheck ) myDefCheck->hide(); @@ -698,12 +738,15 @@ bool Plot2d_SetupViewDlg::getRMinNormMode() \param col legend font color \sa isLegendEnabled(), getLegendPos(), getLegendFont() */ -void Plot2d_SetupViewDlg::setLegend( bool enable, int pos, const QFont& fnt, const QColor& col ) +void Plot2d_SetupViewDlg::setLegend( bool enable, int pos, int symbolType, + const QFont& fnt, const QColor& fontColor, const QColor& selFontColor ) { myLegendCheck->setChecked( enable ); myLegendCombo->setCurrentIndex( pos ); + myLegendSymbolType->setCurrentIndex( symbolType ); myLegendFont->setCurrentFont( fnt ); - myLegendColor->setColor( col ); + myLegendFontColor->setColor( fontColor ); + mySelectedLegendFontColor->setColor( selFontColor ); onLegendChecked(); } @@ -727,6 +770,16 @@ int Plot2d_SetupViewDlg::getLegendPos() return myLegendCombo->currentIndex(); } +/*! + \brief Get legend symbol type. + \return legend symbol type: 0 (marker on line), 1 (marker above line) + \sa setLegend() +*/ +int Plot2d_SetupViewDlg::getLegendSymbolType() +{ + return myLegendSymbolType->currentIndex(); +} + /*! \brief Get legend font. \return legend font @@ -744,7 +797,17 @@ QFont Plot2d_SetupViewDlg::getLegendFont() */ QColor Plot2d_SetupViewDlg::getLegendColor() { - return myLegendColor->color(); + return myLegendFontColor->color(); +} + +/*! + \brief Get selected legend font color. + \return selected legend font color + \sa setLegend() +*/ +QColor Plot2d_SetupViewDlg::getSelectedLegendColor() +{ + return mySelectedLegendFontColor->color(); } /*! @@ -840,6 +903,26 @@ QColor Plot2d_SetupViewDlg::getBackgroundColor() return myBackgroundBtn->color(); } +/*! + \brief Set selection color. + \param color selection color + \sa getSelectionColor() +*/ +void Plot2d_SetupViewDlg::setSelectionColor( const QColor& color ) +{ + mySelectionBtn->setColor( color ); +} + +/*! + \brief Get selection color. + \return selection color + \sa setSelectionColor() +*/ +QColor Plot2d_SetupViewDlg::getSelectionColor() +{ + return mySelectionBtn->color(); +} + /*! \brief Set major grid parameters. \param enableX if \c true, horizontal major grid is enabled diff --git a/src/Plot2d/Plot2d_SetupViewDlg.h b/src/Plot2d/Plot2d_SetupViewDlg.h index ea3e659a2..d6ecb76eb 100755 --- a/src/Plot2d/Plot2d_SetupViewDlg.h +++ b/src/Plot2d/Plot2d_SetupViewDlg.h @@ -73,11 +73,13 @@ public: bool getRMinNormMode(); void setRMinNormMode(const bool); - void setLegend( bool, int, const QFont&, const QColor& ); + void setLegend( bool, int, int, const QFont&, const QColor&, const QColor& ); bool isLegendEnabled(); int getLegendPos(); + int getLegendSymbolType(); QFont getLegendFont(); QColor getLegendColor(); + QColor getSelectedLegendColor(); void setMarkerSize( const int ); int getMarkerSize(); @@ -85,6 +87,9 @@ public: void setBackgroundColor( const QColor& ); QColor getBackgroundColor(); + void setSelectionColor( const QColor& ); + QColor getSelectionColor(); + void setMajorGrid( bool, const int, bool, const int, bool, const int ); void getMajorGrid( bool&, int&, bool&, int&, bool&, int& ); void setMinorGrid( bool, const int, bool, const int, bool, const int ); @@ -133,7 +138,9 @@ private: QLineEdit* myTitleYEdit; QLineEdit* myTitleY2Edit; QtxColorButton* myBackgroundBtn; - QtxColorButton* myLegendColor; + QtxColorButton* mySelectionBtn; + QtxColorButton* myLegendFontColor; + QtxColorButton* mySelectedLegendFontColor; QtxFontEdit* myLegendFont; QCheckBox* myXGridCheck; QSpinBox* myXGridSpin; @@ -150,6 +157,7 @@ private: QComboBox* myCurveCombo; QCheckBox* myLegendCheck; QComboBox* myLegendCombo; + QComboBox* myLegendSymbolType; QSpinBox* myMarkerSpin; QComboBox* myXModeCombo; QComboBox* myYModeCombo; diff --git a/src/Plot2d/Plot2d_ViewFrame.cxx b/src/Plot2d/Plot2d_ViewFrame.cxx index f92e2b2bf..a52a6ab99 100755 --- a/src/Plot2d/Plot2d_ViewFrame.cxx +++ b/src/Plot2d/Plot2d_ViewFrame.cxx @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -181,10 +182,11 @@ Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title ) : QWidget (parent, 0), myOperation( NoOpId ), myCurveType( 1 ), - myShowLegend( true ), myLegendPos( 1 ), myLegendFont("Helvetic",12), - myLegendColor(Qt::black), + myShowLegend( true ), myLegendPos( 1 ), myLegendSymbolType( 0 ), myLegendFont("Helvetic",12), + myLegendColor(Qt::black), mySelectedLegendFontColor( Qt::darkBlue ), myMarkerSize( DEFAULT_MARKER_SIZE ), myBackground( Qt::white ), + mySelectionColor( Qt::gray ), myTitle( "" ), myXTitle( "" ), myYTitle( "" ), myY2Title( "" ), myTitleEnabled( true ), myXTitleEnabled( true ), myYTitleEnabled( true ), myY2TitleEnabled (true), @@ -206,18 +208,6 @@ Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title ) aLayout->addWidget( myPlot ); - // createActions(); - connect( myPlot, SIGNAL( legendClicked( QwtPlotItem* ) ), - this, SIGNAL( legendClicked( QwtPlotItem* ) ) ); - - // IPAL 21465 - /* connect( myPlot->axisWidget( QwtPlot::xBottom ), SIGNAL( scaleDivChanged() ), - myPlot, SLOT( onScaleDivChanged() ) ); - connect( myPlot->axisWidget( QwtPlot::yLeft ), SIGNAL( scaleDivChanged() ), - myPlot, SLOT( onScaleDivChanged() ) ); - if (mySecondY) - connect( myPlot->axisWidget( QwtPlot::yRight ), SIGNAL( scaleDivChanged() ), - myPlot, SLOT( onScaleDivChanged() ) );*/ #ifndef NO_SUIT Init(); #endif @@ -236,7 +226,6 @@ void Plot2d_ViewFrame::Init() /* Initial Setup - get from the preferences */ readPreferences(); - myPlot->setMargin( 5 ); setCurveType( myCurveType, false ); setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, false ); setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor, @@ -251,9 +240,12 @@ void Plot2d_ViewFrame::Init() setHorScaleMode( myXMode, false ); setVerScaleMode( myYMode, false ); setBackgroundColor( myBackground ); + setSelectionColor( mySelectionColor ); setLegendPos( myLegendPos ); + setLegendSymbolType( myLegendSymbolType ); setLegendFont( myLegendFont ); setLegendFontColor( myLegendColor ); + setSelectedLegendFontColor( mySelectedLegendFontColor ); showLegend( myShowLegend, false ); myPlot->replot(); @@ -272,6 +264,21 @@ void Plot2d_ViewFrame::Init() } myPlot->canvas()->installEventFilter( this ); } +void Plot2d_ViewFrame::SetPreference() +{ + readPreferences(); + setBackgroundColor( myBackground ); + setSelectionColor( mySelectionColor ); + setCurveType( myCurveType, true ); + setMarkerSize( myMarkerSize, true ); + showLegend( myShowLegend, true ); + setLegendPos( myLegendPos ); + setLegendSymbolType( myLegendSymbolType ); + setLegendFont( myLegendFont ); + setLegendFontColor( myLegendColor ); + setSelectedLegendFontColor( mySelectedLegendFontColor ); + myPlot->replot(); +} /*! Gets window's central widget */ @@ -465,10 +472,13 @@ void Plot2d_ViewFrame::readPreferences() myShowLegend = resMgr->booleanValue( "Plot2d", "ShowLegend", myShowLegend ); myLegendPos = resMgr->integerValue( "Plot2d", "LegendPos", myLegendPos ); + myLegendSymbolType = resMgr->integerValue( "Plot2d", "LegendSymbolType", myLegendSymbolType ); myLegendFont = resMgr->fontValue( "Plot2d", "LegendFont", myLegendFont ); myLegendColor = resMgr->colorValue( "Plot2d", "LegendFontColor", myLegendColor ); + mySelectedLegendFontColor = resMgr->colorValue( "Plot2d", "SelectedLegendFontColor", mySelectedLegendFontColor ); myMarkerSize = resMgr->integerValue( "Plot2d", "MarkerSize", myMarkerSize ); myBackground = resMgr->colorValue( "Plot2d", "Background", myBackground ); + mySelectionColor = resMgr->colorValue( "Plot2d", "SelectionColor", mySelectionColor ); myTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowTitle", myTitleEnabled ); myXTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowHorTitle", myXTitleEnabled ); @@ -519,13 +529,19 @@ void Plot2d_ViewFrame::writePreferences() resMgr->setValue( "Plot2d", "CurveType", myCurveType ); resMgr->setValue( "Plot2d", "ShowLegend", myShowLegend ); resMgr->setValue( "Plot2d", "LegendPos", myLegendPos ); + resMgr->setValue( "Plot2d", "LegendSymbolType", myLegendSymbolType ); resMgr->setValue( "Plot2d", "LegendFont", myLegendFont ); resMgr->setValue( "Plot2d", "LegendFontColor", myLegendColor ); + resMgr->setValue( "Plot2d", "SelectedLegendFontColor", mySelectedLegendFontColor ); resMgr->setValue( "Plot2d", "MarkerSize", myMarkerSize ); resMgr->setValue( "Plot2d", "Background", myBackground ); + resMgr->setValue( "Plot2d", "SelectionColor", mySelectionColor ); resMgr->setValue( "Plot2d", "ShowTitle", myTitleEnabled ); resMgr->setValue( "Plot2d", "ShowHorTitle", myXTitleEnabled ); resMgr->setValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled ); + resMgr->setValue( "Plot2d", "DeviationMarkerColor", myPlot->property(PLOT2D_DEVIATION_COLOR).value() ); + resMgr->setValue( "Plot2d", "DeviationMarkerLineWidth", myPlot->property(PLOT2D_DEVIATION_LW).toInt() ); + resMgr->setValue( "Plot2d", "DeviationMarkerTickSize", myPlot->property(PLOT2D_DEVIATION_TS).toInt() ); if ( mySecondY ) resMgr->setValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled ); @@ -567,8 +583,8 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) QwtValueList aTicks; bool xFound = false, yFound = false; double xCoord, yCoord; - const QwtScaleDiv* aXscale = myPlot->axisScaleDiv( QwtPlot::xBottom ); - aTicks = aXscale->ticks( QwtScaleDiv::MajorTick ); + const QwtScaleDiv& aXscale = myPlot->axisScaleDiv( QwtPlot::xBottom ); + aTicks = aXscale.ticks( QwtScaleDiv::MajorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double majXmark = aTicks[i]; int xmark = myPlot->transform( QwtPlot::xBottom, majXmark ); @@ -579,7 +595,7 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) } } if ( !xFound ) { - aTicks = aXscale->ticks( QwtScaleDiv::MinorTick ); + aTicks = aXscale.ticks( QwtScaleDiv::MinorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double minXmark = aTicks[i]; int xmark = myPlot->transform( QwtPlot::xBottom, minXmark ); @@ -590,8 +606,8 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) } } } - const QwtScaleDiv* aYscale = myPlot->axisScaleDiv( QwtPlot::yLeft ); - aTicks = aYscale->ticks( QwtScaleDiv::MajorTick ); + const QwtScaleDiv& aYscale = myPlot->axisScaleDiv( QwtPlot::yLeft ); + aTicks = aYscale.ticks( QwtScaleDiv::MajorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double majYmark = aTicks[i]; int ymark = myPlot->transform( QwtPlot::yLeft, majYmark ); @@ -602,7 +618,7 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) } } if ( !yFound ) { - aTicks = aYscale->ticks( QwtScaleDiv::MinorTick ); + aTicks = aYscale.ticks( QwtScaleDiv::MinorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double minYmark = aTicks[i]; int ymark = myPlot->transform( QwtPlot::yLeft, minYmark ); @@ -626,8 +642,8 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) bool yFound2 = false; double yCoord2; - const QwtScaleDiv* aYscale2 = myPlot->axisScaleDiv( QwtPlot::yRight ); - aTicks = aYscale2->ticks( QwtScaleDiv::MajorTick ); + const QwtScaleDiv& aYscale2 = myPlot->axisScaleDiv( QwtPlot::yRight ); + aTicks = aYscale2.ticks( QwtScaleDiv::MajorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double majYmark = aTicks[i]; int ymark = myPlot->transform( QwtPlot::yRight, majYmark ); @@ -638,7 +654,7 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) } } if ( !yFound2 ) { - aTicks = aYscale2->ticks( QwtScaleDiv::MinorTick ); + aTicks = aYscale2.ticks( QwtScaleDiv::MinorTick ); for ( i = 0; i < aTicks.count(); i++ ) { double minYmark = aTicks[i]; int ymark = myPlot->transform( QwtPlot::yRight, minYmark ); @@ -731,8 +747,8 @@ QVector< QVector > Plot2d_ViewFrame::displayPlot2dCurveList( con bool displayLegend, const QList< bool >& sides) { // Consider the new legend's entries - // (PB: to update the legend we must remove it and put a new QwtLegend in the QwtPlot) - myPlot->insertLegend( (QwtLegend*)NULL); // we remove here, we shall put at the end + // (PB: to update the legend we must remove it and put a new QwtAbstractLegend in the QwtPlot) + myPlot->insertLegend( (QwtAbstractLegend*)NULL); // we remove here, we shall put at the end int nbAllCurves = curveList.size(); int nbGroups = nbAllCurves / groupSize; @@ -875,9 +891,10 @@ QVector< QVector > Plot2d_ViewFrame::displayPlot2dCurveList( con QwtPlotCurve* plotCurve = dynamic_cast(getPlotObject(plot2dCurve)); vectCurve[ig].push_back(plotCurve); // Modify the points' markers - QwtSymbol symbol(plotCurve->symbol()) ; - symbol.setStyle(symbolStyle1); - symbol.setPen(QPen(color1,lineWidth1)); + QwtSymbol* symbol = new QwtSymbol(plotCurve->symbol()->style(), plotCurve->symbol()->brush(), + plotCurve->symbol()->pen(), plotCurve->symbol()->size()) ; + symbol->setStyle(symbolStyle1); + symbol->setPen(QPen(color1,lineWidth1)); //symbol.setBrush( QBrush( color1)); //QSize size = 0.5*(symbol.size()); //symbol.setSize(size); @@ -1002,7 +1019,7 @@ Plot2d_Curve* Plot2d_ViewFrame::createPlot2dCurve( QString & title, { if (!displayLegend) { - myPlot->insertLegend( (QwtLegend*)NULL); + myPlot->insertLegend( (QwtAbstractLegend*)NULL); } displayCurve( plot2dCurve); @@ -1024,15 +1041,16 @@ Plot2d_Curve* Plot2d_ViewFrame::createPlot2dCurve( QString & title, } // Modify points' markers - QwtSymbol symbol (plotCurve->symbol()) ; - symbol.setStyle( markerKind); + QwtSymbol* symbol = new QwtSymbol( plotCurve->symbol()->style(), plotCurve->symbol()->brush(), + plotCurve->symbol()->pen(), plotCurve->symbol()->size() ) ; + symbol->setStyle( markerKind ); // if (markerKind != QwtSymbol::NoSymbol) { - symbol.setPen( QPen( theColor, lineWidth)); - symbol.setBrush( QBrush( theColor)); - QSize size = 2.0*(symbol.size()); //0.5 - symbol.setSize(size); + symbol->setPen( QPen( theColor, lineWidth)); + symbol->setBrush( QBrush( theColor)); + QSize size = 2.0*(symbol->size()); //0.5 + symbol->setSize(size); } plotCurve->setSymbol( symbol); @@ -1071,14 +1089,14 @@ QwtPlotCurve *Plot2d_ViewFrame::createSegment( double *X, double *Y, int nbPoint QColor & lineColor, QwtSymbol::Style markerKind, bool side) { - QwtPlotCurve* aPCurve = new QwtPlotCurve(); + QwtPlotCurve* aPCurve = new QwtPlotCurve( QString::null ); - aPCurve->setData( X, Y, nbPoint); + aPCurve->setSamples( X, Y, nbPoint); aPCurve->setPen( QPen( lineColor, lineWidth, lineKind)); - QwtSymbol aSymbol; - aSymbol.setStyle( markerKind); - aPCurve->setSymbol( aSymbol); + QwtSymbol* aSymbol; + aSymbol->setStyle( markerKind ); + aPCurve->setSymbol( aSymbol ); // The segment must not have legend's entry aPCurve->setItemAttribute( QwtPlotItem::Legend, false); @@ -1254,13 +1272,8 @@ QwtPlotItem* Plot2d_ViewFrame::displayObject( Plot2d_Object* object, bool update Plot2d_Curve* aCurve = dynamic_cast( object ); if ( aCurve ) { - //myMarkerSize = 1; - //aCurve->setMarkerSize( myMarkerSize ); - - if (aCurve->getMarkerSize() == 0) - { - aCurve->setMarkerSize( myMarkerSize ); - } + if ( aCurve->getMarkerSize() == 0 ) + aCurve->setMarkerSize( myMarkerSize ); processFiltering(update); updatePlotItem( aCurve, anItem ); @@ -1409,10 +1422,12 @@ void Plot2d_ViewFrame::updateLegend( const Plot2d_Prs* prs ) update legend */ void Plot2d_ViewFrame::updateLegend() { - if ( myPlot->getLegend() ) { - ObjectDict::iterator it = myObjects.begin(); - for( ; it != myObjects.end(); ++it ) - it.key()->updateLegend(myPlot->getLegend()); + const QwtPlotItemList& items = myPlot->itemList(); + QwtPlotItemIterator it; + for ( it = items.begin(); it != items.end(); it++ ) { + QwtPlotItem* item = *it; + if ( item ) + item->updateLegend( item, item->legendData() ); } } @@ -1422,14 +1437,7 @@ void Plot2d_ViewFrame::updateLegend() { */ void Plot2d_ViewFrame::fitAll() { - // Postpone fitAll operation until QwtPlot geometry - // has been fully defined - if ( !myPlot->polished() ){ - QApplication::postEvent( this, new QEvent( (QEvent::Type)FITALL_EVENT ) ); - return; - } - - // no need to set auto scaling, it wiil be disabled by setAxisScale() method call + // no need to set auto scaling, it will be disabled by setAxisScale() method call // myPlot->setAxisAutoScale( QwtPlot::yLeft ); // myPlot->setAxisAutoScale( QwtPlot::xBottom ); // myPlot->replot(); @@ -1708,9 +1716,11 @@ void Plot2d_ViewFrame::onSettings() if (mySecondY) dlg->setY2Title( myY2TitleEnabled, myY2Title ); dlg->setCurveType( myCurveType ); - dlg->setLegend( myShowLegend, myLegendPos, myLegendFont, myLegendColor ); + dlg->setLegend( myShowLegend, myLegendPos, myLegendSymbolType, myLegendFont, + myLegendColor, mySelectedLegendFontColor ); dlg->setMarkerSize( myMarkerSize ); dlg->setBackgroundColor( myBackground ); + dlg->setSelectionColor( mySelectionColor ); dlg->setScaleMode(myXMode, myYMode); dlg->setLMinNormMode(myNormLMin); dlg->setLMaxNormMode(myNormLMax); @@ -1759,6 +1769,9 @@ void Plot2d_ViewFrame::onSettings() } if ( myLegendPos != dlg->getLegendPos() ) { setLegendPos( dlg->getLegendPos() ); + } + if ( myLegendSymbolType != dlg->getLegendSymbolType() ) { + setLegendSymbolType( dlg->getLegendSymbolType() ); } if ( myLegendFont != dlg->getLegendFont() ) { setLegendFont( dlg->getLegendFont() ); @@ -1766,6 +1779,9 @@ void Plot2d_ViewFrame::onSettings() if ( myLegendColor != dlg->getLegendColor() ) { setLegendFontColor( dlg->getLegendColor() ); } + if ( mySelectedLegendFontColor != dlg->getSelectedLegendColor() ) { + setSelectedLegendFontColor( dlg->getSelectedLegendColor() ); + } // marker size if ( myMarkerSize != dlg->getMarkerSize() ) { @@ -1775,6 +1791,10 @@ void Plot2d_ViewFrame::onSettings() if ( myBackground != dlg->getBackgroundColor() ) { setBackgroundColor( dlg->getBackgroundColor() ); } + // selection color + if ( mySelectionColor != dlg->getSelectionColor() ) { + setSelectionColor( dlg->getSelectionColor() ); + } // grid bool aXGridMajorEnabled, aXGridMinorEnabled, aYGridMajorEnabled, aYGridMinorEnabled, aY2GridMajorEnabled, aY2GridMinorEnabled; @@ -1850,9 +1870,9 @@ void Plot2d_ViewFrame::removeAnalyticalCurve( Plot2d_AnalyticalCurve* theCurve) void Plot2d_ViewFrame::updateAnalyticalCurve(Plot2d_AnalyticalCurve* c, bool updateView) { if(!c) return; - QwtScaleDiv* div = myPlot->axisScaleDiv(QwtPlot::xBottom); - c->setRangeBegin(div->lowerBound()); - c->setRangeEnd(div->upperBound()); + QwtScaleDiv div = myPlot->axisScaleDiv(QwtPlot::xBottom); + c->setRangeBegin(div.lowerBound()); + c->setRangeEnd(div.upperBound()); c->calculate(); c->setMarkerSize(myMarkerSize); QwtPlotItem* item = c->plotItem(); @@ -1862,6 +1882,7 @@ void Plot2d_ViewFrame::updateAnalyticalCurve(Plot2d_AnalyticalCurve* c, bool upd if( c->isActive() ) { c->updatePlotItem(); item->attach( myPlot ); + item->itemChanged(); item->show(); } c->setAction(Plot2d_AnalyticalCurve::ActNothing); @@ -2008,19 +2029,31 @@ void Plot2d_ViewFrame::showLegend( bool show, bool update ) { myShowLegend = show; if ( myShowLegend ) { - QwtLegend* legend = myPlot->legend(); - if ( !legend ) { - legend = new QwtLegend( myPlot ); + QwtAbstractLegend* absLegend = myPlot->legend(); + QwtLegend* legend = 0; + if ( !absLegend ) { + legend = new Plot2d_QwtLegend( myPlot ); + legend->setDefaultItemMode(QwtLegendData::Clickable); + connect( legend, SIGNAL( clicked (const QVariant&, int) ), + this, SIGNAL( clicked (const QVariant&, int) ) ); legend->setFrameStyle( QFrame::Box | QFrame::Sunken ); } - legend->setItemMode( QwtLegend::ClickableItem ); - myPlot->insertLegend( legend ); - setLegendPos( myLegendPos ); - setLegendFont( myLegendFont ); - setLegendFontColor( myLegendColor ); + else { + legend = dynamic_cast(absLegend); + } + if(legend) { + myPlot->insertLegend( legend ); + setLegendPos( myLegendPos ); + setLegendFont( myLegendFont ); + setLegendFontColor( myLegendColor ); + } } else myPlot->insertLegend( 0 ); + + if( show && update ) + updateLegend(); + if ( update ) myPlot->replot(); } @@ -2031,7 +2064,7 @@ void Plot2d_ViewFrame::showLegend( bool show, bool update ) void Plot2d_ViewFrame::setLegendPos( int pos ) { myLegendPos = pos; - QwtLegend* legend = myPlot->legend(); + QwtAbstractLegend* legend = myPlot->legend(); if ( legend ) { switch( pos ) { case 0: @@ -2058,13 +2091,31 @@ int Plot2d_ViewFrame::getLegendPos() const return myLegendPos; } +/*! + Sets legend symbol type : 0 - marker on line, 1 - marker above line +*/ +void Plot2d_ViewFrame::setLegendSymbolType( int type ) +{ + myLegendSymbolType = type; + myPlot->setLegendSymbolType( type ); + updateLegend(); +} + +/*! + Gets legend symbol type : 0 - marker on line, 1 - marker above line +*/ +int Plot2d_ViewFrame::getLegendSymbolType() const +{ + return myLegendSymbolType; +} + /*! Sets legend font */ void Plot2d_ViewFrame::setLegendFont( const QFont& fnt ) { myLegendFont = fnt; - QwtLegend* legend = myPlot->legend(); + QwtAbstractLegend* legend = myPlot->legend(); if ( legend ) { legend->setFont(fnt); } @@ -2078,21 +2129,13 @@ QFont Plot2d_ViewFrame::getLegendFont() const return myLegendFont; } -/*! - Gets legend font color -*/ -QColor Plot2d_ViewFrame::getLegendFontColor() const -{ - return myLegendColor; -} - /*! Sets legend font color */ void Plot2d_ViewFrame::setLegendFontColor( const QColor& col ) { myLegendColor = col; - QwtLegend* legend = myPlot->legend(); + QwtAbstractLegend* legend = myPlot->legend(); if ( legend ) { QPalette pal = legend->palette(); pal.setColor( QPalette::Text, col ); @@ -2100,6 +2143,31 @@ void Plot2d_ViewFrame::setLegendFontColor( const QColor& col ) } } +/*! + Gets legend font color +*/ +QColor Plot2d_ViewFrame::getLegendFontColor() const +{ + return myLegendColor; +} + +/*! + Sets selected legend font color +*/ +void Plot2d_ViewFrame::setSelectedLegendFontColor( const QColor& col ) +{ + mySelectedLegendFontColor = col; + Plot2d_Object::setHighlightedLegendTextColor( col ); +} + +/*! + Gets selected legend font color +*/ +QColor Plot2d_ViewFrame::getSelectedLegendFontColor() const +{ + return mySelectedLegendFontColor; +} + /*! Sets new marker size */ @@ -2114,11 +2182,11 @@ void Plot2d_ViewFrame::setMarkerSize( const int size, bool update ) QwtPlotCurve* crv = it.key(); if ( crv ) { - QwtSymbol aSymbol = crv->symbol(); - aSymbol.setSize( myMarkerSize, myMarkerSize ); + QwtSymbol* aSymbol = new QwtSymbol( crv->symbol()->style(), crv->symbol()->brush(), + crv->symbol()->pen(), QSize( myMarkerSize, myMarkerSize ) ); crv->setSymbol( aSymbol ); - if(it.value()) - it.value()->setMarkerSize( myMarkerSize ); + if( it.value() ) + it.value()->setMarkerSize( myMarkerSize ); } } if ( update ) @@ -2153,6 +2221,7 @@ void Plot2d_ViewFrame::setBackgroundColor( const QColor& color ) } Repaint(); } + /*! Gets background color */ @@ -2160,6 +2229,24 @@ QColor Plot2d_ViewFrame::backgroundColor() const { return myBackground; } + +/*! + Sets selection color +*/ +void Plot2d_ViewFrame::setSelectionColor( const QColor& color ) +{ + mySelectionColor = color; + Plot2d_Object::setSelectionColor( color ); +} + +/*! + Gets selection color +*/ +QColor Plot2d_ViewFrame::selectionColor() const +{ + return mySelectionColor; +} + /*! Sets hor.axis grid parameters */ @@ -2176,8 +2263,8 @@ void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax, myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor ); QwtPlotGrid* grid = myPlot->grid(); - if ( myPlot->axisScaleDiv( QwtPlot::xBottom ) ) - grid->setXDiv( *myPlot->axisScaleDiv( QwtPlot::xBottom ) ); + if ( !myPlot->axisScaleDiv( QwtPlot::xBottom ).isEmpty() ) + grid->setXDiv( myPlot->axisScaleDiv( QwtPlot::xBottom ) ); grid->enableX( myXGridMajorEnabled ); grid->enableXMin( myXGridMinorEnabled ); @@ -2213,8 +2300,8 @@ void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax, } QwtPlotGrid* grid = myPlot->grid(); - if ( myPlot->axisScaleDiv( QwtPlot::yLeft ) ) - grid->setYDiv( *myPlot->axisScaleDiv( QwtPlot::yLeft ) ); + if ( !myPlot->axisScaleDiv( QwtPlot::yLeft ).isEmpty() ) + grid->setYDiv( myPlot->axisScaleDiv( QwtPlot::yLeft ) ); if (mySecondY) { if (myYGridMajorEnabled) { @@ -2222,8 +2309,8 @@ void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax, grid->enableYMin( myYGridMinorEnabled ); } else if (myY2GridMajorEnabled) { - if ( myPlot->axisScaleDiv( QwtPlot::yRight ) ) - grid->setYDiv( *myPlot->axisScaleDiv( QwtPlot::yRight ) ); + if ( !myPlot->axisScaleDiv( QwtPlot::yRight ).isEmpty() ) + grid->setYDiv( myPlot->axisScaleDiv( QwtPlot::yRight ) ); grid->enableY( myY2GridMajorEnabled ); grid->enableYMin( myY2GridMinorEnabled ); } @@ -2341,6 +2428,12 @@ void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update ) myXMode = mode; + // set bounds of logarithmic scale + if( myXMode != 0 ) { + myPlot->setAxisScale( QwtPlot::xBottom, 1.0, 1e5 ); + myPlot->updateAxes(); + } + myPlot->setLogScale(QwtPlot::xBottom, myXMode != 0); if ( update ) @@ -2377,9 +2470,21 @@ void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update ) } myYMode = mode; + + // set bounds of logarithmic scale + if( myYMode != 0 ){ + myPlot->setAxisScale( QwtPlot::yLeft, 1.0, 1e5 ); + myPlot->updateAxes(); + } + myPlot->setLogScale(QwtPlot::yLeft, myYMode != 0); - if (mySecondY) + if (mySecondY) { + if( myYMode != 0 ){ + myPlot->setAxisScale( QwtPlot::yRight, 1.0, 1e5 ); + myPlot->updateAxes(); + } myPlot->setLogScale( QwtPlot::yRight, myYMode != 0 ); + } if ( update ) fitAll(); @@ -2866,7 +2971,7 @@ void Plot2d_ViewFrame::setEnableAxis( QwtPlot::Axis theAxis, bool isEnable ) class Plot2d_QwtPlotZoomer : public QwtPlotZoomer { public: - Plot2d_QwtPlotZoomer( int xAxis, int yAxis, QwtPlotCanvas* canvas ) + Plot2d_QwtPlotZoomer( int xAxis, int yAxis, QWidget* canvas ) : QwtPlotZoomer( xAxis, yAxis, canvas ) { qApp->installEventFilter( this ); @@ -2881,7 +2986,6 @@ public: */ Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent ) : QwtPlot( parent ), - myIsPolished( false ), myPicker( 0 ) { // Create alternative scales @@ -2890,7 +2994,6 @@ Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent ) setAxisScaleDraw( QwtPlot::yRight, new Plot2d_ScaleDraw() ); myPlotZoomer = new Plot2d_QwtPlotZoomer( QwtPlot::xBottom, QwtPlot::yLeft, canvas() ); - myPlotZoomer->setSelectionFlags( QwtPicker::DragSelection | QwtPicker::CornerToCorner ); myPlotZoomer->setTrackerMode( QwtPicker::AlwaysOff ); myPlotZoomer->setRubberBand( QwtPicker::RectRubberBand ); myPlotZoomer->setRubberBandPen( QColor( Qt::green ) ); @@ -2905,7 +3008,7 @@ Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent ) myScaleDraw = NULL; // grid myGrid = new QwtPlotGrid(); - QPen aMajPen = myGrid->majPen(); + QPen aMajPen = myGrid->majorPen(); aMajPen.setStyle( Qt::DashLine ); myGrid->setPen( aMajPen ); @@ -2935,7 +3038,7 @@ Plot2d_Plot2d::~Plot2d_Plot2d() void Plot2d_Plot2d::setLogScale( int axisId, bool log10 ) { if ( log10 ) - setAxisScaleEngine( axisId, new QwtLog10ScaleEngine() ); + setAxisScaleEngine( axisId, new QwtLogScaleEngine() ); else setAxisScaleEngine( axisId, new QwtLinearScaleEngine() ); } @@ -2972,7 +3075,7 @@ void Plot2d_Plot2d::replot() /*! Get legend */ -QwtLegend* Plot2d_Plot2d::getLegend() +QwtAbstractLegend* Plot2d_Plot2d::getLegend() { #if QWT_VERSION < 0x040200 return d_legend; @@ -3004,12 +3107,14 @@ void Plot2d_Plot2d::defaultPicker() myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1, Qt::RightButton, Qt::ControlModifier ); // zooming button for ( int i = QwtEventPattern::MouseSelect2; i < QwtEventPattern::MouseSelect6; i++ ) - myPlotZoomer->setMousePattern( i, Qt::NoButton, Qt::NoButton ); + myPlotZoomer->setMousePattern( (QwtEventPattern::MousePatternCode)i, Qt::NoButton, + Qt::NoModifier ); } void Plot2d_Plot2d::setPickerMousePattern( int button, int state ) { - myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1, button, state ); + myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1, (Qt::MouseButton)button, + (Qt::KeyboardModifiers)state ); } /*! @@ -3023,11 +3128,11 @@ void Plot2d_Plot2d::setPicker( Plot2d_QwtPlotPicker *picker) /*! * Create marker and tooltip associed with a point */ -QwtPlotMarker* Plot2d_Plot2d::createMarkerAndTooltip( QwtSymbol symbol, - double X, - double Y, - QString & tooltip, - Plot2d_QwtPlotPicker *picker) +QwtPlotMarker* Plot2d_Plot2d::createMarkerAndTooltip( QwtSymbol* symbol, + double X, + double Y, + QString & tooltip, + Plot2d_QwtPlotPicker *picker) { QwtPlotMarker* aPlotMarker = new QwtPlotMarker(); @@ -3054,11 +3159,6 @@ QwtPlotMarker* Plot2d_Plot2d::createMarkerAndTooltip( QwtSymbol symbol, return aPlotMarker; } -bool Plot2d_Plot2d::polished() const -{ - return myIsPolished; -} - QwtPlotGrid* Plot2d_Plot2d::grid() const { return myGrid; @@ -3069,44 +3169,6 @@ QwtPlotZoomer* Plot2d_Plot2d::zoomer() const return myPlotZoomer; } -/*! - Slot: checks the current labels format and change it if needed -*/ -void Plot2d_Plot2d::onScaleDivChanged() -{ - QwtScaleWidget* aSW = 0; - if ( ( aSW = dynamic_cast(sender()) ) ) { - int axisId = -1; - switch ( aSW->alignment() ) { - case QwtScaleDraw::BottomScale: - axisId = QwtPlot::xBottom; - break; - case QwtScaleDraw::LeftScale: - axisId = QwtPlot::yLeft; - break; - case QwtScaleDraw::RightScale: - axisId = QwtPlot::yRight; - break; - default: - break; - } - - if ( axisId >= 0 ) { - QwtScaleMap map = canvasMap(axisId); - double aDist = fabs(map.s2()-map.s1()) / (axisMaxMajor(axisId)*axisMaxMinor(axisId)); - - QString aDistStr; - aDistStr.sprintf("%e",aDist); - int aPrecision = aDistStr.right(aDistStr.length()-aDistStr.indexOf('e')-2).toInt(); - - QwtScaleDraw* aQwtSD = axisScaleDraw(axisId); - Plot2d_ScaleDraw* aPlot2dSD = dynamic_cast(aQwtSD); - if ( ( !aPlot2dSD && aPrecision > 6 ) || ( aPlot2dSD && aPlot2dSD->precision() != aPrecision ) ) - setAxisScaleDraw( axisId, new Plot2d_ScaleDraw(*aQwtSD, 'f', aPrecision) ); - } - } -} - /*! Updates identifiers of Y axis type in the legend. */ @@ -3131,19 +3193,10 @@ void Plot2d_Plot2d::updateYAxisIdentifiers() if ( Plot2d_QwtPlotCurve* aPCurve = dynamic_cast( item ) ) aPCurve->setYAxisIdentifierEnabled( enableYLeft && enableYRight ); if ( item && item->isVisible() && legend() ) - item->updateLegend( legend() ); + item->updateLegend( item, item->legendData() ); } } -/*! - Sets the flag saying that QwtPlot geometry has been fully defined. -*/ -void Plot2d_Plot2d::polish() -{ - QwtPlot::polish(); - myIsPolished = true; -} - // Methods to manage axis graduations /* Create definition and graduations of axes @@ -3348,6 +3401,20 @@ void Plot2d_Plot2d::clearSeparationLineList() mySeparationLineList.clear(); } +/* Set type of legend symbol + */ +void Plot2d_Plot2d::setLegendSymbolType( const int type ) +{ + myLegendSymbolType = type; +} + +/* Get type of legend symbol + */ +int Plot2d_Plot2d::getLegendSymbolType() +{ + return myLegendSymbolType; +} + /*! Creates presentation of object Default implementation is empty @@ -3369,8 +3436,12 @@ void Plot2d_ViewFrame::copyPreferences( Plot2d_ViewFrame* vf ) myCurveType = vf->myCurveType; myShowLegend = vf->myShowLegend; myLegendPos = vf->myLegendPos; + myLegendSymbolType = vf->myLegendSymbolType; + myLegendFont = vf->myLegendFont; + mySelectedLegendFontColor = vf->mySelectedLegendFontColor; myMarkerSize = vf->myMarkerSize; myBackground = vf->myBackground; + mySelectionColor = vf->mySelectionColor; myTitle = vf->myTitle; myXTitle = vf->myXTitle; myYTitle = vf->myYTitle; @@ -3507,22 +3578,24 @@ bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const if( pd ) { - myPlot->print( *pd ); + QwtPlotRenderer* pr = new QwtPlotRenderer(); + pr->renderTo( myPlot, *pd ); res = true; delete pd; } } return res; #endif + } /** * Print Plot2d window */ -void Plot2d_ViewFrame::printPlot( QPainter* p, const QRect& rect, - const QwtPlotPrintFilter& filter ) const +void Plot2d_ViewFrame::printPlot( QPainter* p, const QRectF& rect) const { - myPlot->print( p, rect, filter ); + QwtPlotRenderer* pr = new QwtPlotRenderer(); + pr->render( myPlot, p, rect ); } /*! @@ -3939,7 +4012,7 @@ void Plot2d_ViewFrame::updatePlotItem(Plot2d_Object* theObject, QwtPlotItem* the xNew[j] = itTmp.value().at(j).first; yNew[j] = itTmp.value().at(j).second; } - cu->setData(xNew, yNew,j); + cu->setSamples(xNew, yNew,j); delete [] xNew; delete [] yNew; if(aNormAlgo->getNormalizationMode() != Plot2d_NormalizeAlgorithm::NormalizeNone) { @@ -3957,7 +4030,7 @@ void Plot2d_ViewFrame::updatePlotItem(Plot2d_Object* theObject, QwtPlotItem* the */ QwtPlotCanvas* Plot2d_ViewFrame::getPlotCanvas() const { - return myPlot ? myPlot->canvas() : 0; + return myPlot ? (QwtPlotCanvas*)myPlot->canvas() : 0; } /*! @@ -4108,21 +4181,13 @@ Plot2d_ScaleDraw::Plot2d_ScaleDraw( char f, int prec ) invalidateCache(); } -Plot2d_ScaleDraw::Plot2d_ScaleDraw( const QwtScaleDraw& scaleDraw, char f, int prec ) - : QwtScaleDraw(scaleDraw), - myFormat(f), - myPrecision(prec) -{ - invalidateCache(); -} - QwtText Plot2d_ScaleDraw::label( double value ) const { - QwtScaleMap m = map(); + QwtScaleMap m = scaleMap(); QString str1 = QwtScaleDraw::label( m.s1() ).text(); QString str2 = QwtScaleDraw::label( m.s2() ).text(); if ( str1 == str2 ) { - double aDist = fabs(map().s2()-map().s1())/5; + double aDist = fabs(scaleMap().s2()-scaleMap().s1())/5; int precision = 0; while (aDist < 1 ) { precision++; @@ -4206,9 +4271,13 @@ void Plot2d_AxisScaleDraw::draw( QPainter* painter, const QPalette & palette) co major_ticks.clear(); major_ticks.append( myTicks); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MajorTick, major_ticks); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MediumTick, medium_ticks); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MinorTick, minor_ticks); + + QwtScaleDiv aScaleDiv = myPlot->axisScaleDiv( QwtPlot::xBottom ); + aScaleDiv.setTicks( QwtScaleDiv::MajorTick, major_ticks ); + aScaleDiv.setTicks( QwtScaleDiv::MediumTick, medium_ticks ); + aScaleDiv.setTicks( QwtScaleDiv::MinorTick, minor_ticks ); + myPlot->setAxisScaleDiv( QwtPlot::xBottom, aScaleDiv ); + QwtScaleDraw *scale = myPlot->axisScaleDraw(QwtPlot::xBottom); ((Plot2d_AxisScaleDraw*)(scale))->applyTicks(); @@ -4282,9 +4351,11 @@ void Plot2d_AxisScaleDraw::applyTicks() medium_ticks.clear(); minor_ticks.clear(); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MajorTick, myTicks); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MediumTick, medium_ticks); - myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MinorTick, minor_ticks); + QwtScaleDiv aQwtScaleDiv = myPlot->axisScaleDiv( QwtPlot::xBottom ); + aQwtScaleDiv.setTicks( QwtScaleDiv::MajorTick, myTicks ); + aQwtScaleDiv.setTicks( QwtScaleDiv::MediumTick, medium_ticks ); + aQwtScaleDiv.setTicks( QwtScaleDiv::MinorTick, minor_ticks ); + myPlot->setAxisScaleDiv( QwtPlot::xBottom, aQwtScaleDiv ); QwtScaleDiv* aScaleDiv = (QwtScaleDiv*) &scaleDiv(); @@ -4315,7 +4386,7 @@ void Plot2d_AxisScaleDraw::drawLabel( QPainter* painter, double value) const //const char *c_label = std_label.c_str(); //std::cout << " deviceLabel= |" << c_label << "|" << std::endl; - QPoint p = labelPosition( value ); + QPointF p = labelPosition( value ); p += QPoint(0, DEVICE_BY); QFont prevf = painter->font(); //QColor prevc = (painter->pen()).color(); @@ -4359,13 +4430,11 @@ const double Plot2d_QwtPlotPicker::BOUND_HV_SIZE = 0.2; Plot2d_QwtPlotPicker::Plot2d_QwtPlotPicker( int xAxis, int yAxis, - int selectionFlags, RubberBand rubberBand, DisplayMode trackerMode, QwtPlotCanvas *canvas) : QwtPlotPicker( xAxis, yAxis, - selectionFlags, rubberBand, trackerMode, canvas) // of drawing zone QwtPlot @@ -4388,20 +4457,30 @@ Plot2d_QwtPlotPicker::~Plot2d_QwtPlotPicker() /* Return the tooltip associated with a point when the mouse cursor pass near */ -QwtText Plot2d_QwtPlotPicker::trackerText( const QwtDoublePoint & pos ) const +QwtText Plot2d_QwtPlotPicker::trackerText( const QPoint & pos ) const { for (QList::const_iterator pMarkerIt = pMarkers.begin();pMarkerIt != pMarkers.end(); ++pMarkerIt ) { QwtPlotMarker* pMarker = *pMarkerIt; if ( pMarker != NULL ) { - const QwtSymbol &symb=pMarker->symbol(); - const QSize& sz=symb.size(); + const QwtSymbol* symb=pMarker->symbol(); + const QSize& sz=symb->size(); const QwtScaleMap yMapRef=plot()->canvasMap(QwtPlot::yLeft); const QwtScaleMap xMap=plot()->canvasMap(pMarker->xAxis()); const QwtScaleMap yMap=plot()->canvasMap(pMarker->yAxis()); QwtDoubleRect bound0=pMarker->boundingRect(); - QRect bound00=pMarker->transform(xMap,yMap,bound0); + int x1 = qRound(xMap.transform(bound0.left())); + int x2 = qRound(xMap.transform(bound0.right())); + int y1 = qRound(yMap.transform(bound0.top())); + int y2 = qRound(yMap.transform(bound0.bottom())); + + if ( x2 < x1 ) + qSwap(x1, x2); + if ( y2 < y1 ) + qSwap(y1, y2); + + QRect bound00=QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); QPoint toto(xMap.transform(pos.x()),yMapRef.transform(pos.y())); bound00.setX(bound00.x()-sz.width()); bound00.setY(bound00.y()-sz.height()); diff --git a/src/Plot2d/Plot2d_ViewFrame.h b/src/Plot2d/Plot2d_ViewFrame.h index c8ea7bd2f..0a6f20214 100755 --- a/src/Plot2d/Plot2d_ViewFrame.h +++ b/src/Plot2d/Plot2d_ViewFrame.h @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -74,6 +76,7 @@ public: virtual ~Plot2d_ViewFrame(); void Init(); + void SetPreference(); enum ObjectType { MainTitle, XTitle, YTitle, Y2Title, XAxis, YAxis, Y2Axis }; @@ -186,14 +189,20 @@ public: void showLegend( bool, bool = true ); void setLegendPos( int ); int getLegendPos() const; + void setLegendSymbolType( int ); + int getLegendSymbolType() const; void setLegendFont( const QFont& ); QFont getLegendFont() const; void setLegendFontColor( const QColor& ); QColor getLegendFontColor() const; + void setSelectedLegendFontColor( const QColor& ); + QColor getSelectedLegendFontColor() const; void setMarkerSize( const int, bool = true ); int getMarkerSize() const; virtual void setBackgroundColor( const QColor& ); QColor backgroundColor() const; + virtual void setSelectionColor( const QColor& ); + QColor selectionColor() const; void setXGrid( bool, const int, bool, const int, bool = true ); void setYGrid( bool, const int, bool, const int, bool, const int, bool, const int, bool = true ); @@ -232,8 +241,7 @@ public: void setEnableAxis( QwtPlot::Axis, bool ); virtual bool print( const QString&, const QString& ) const; - void printPlot( QPainter*, const QRect&, - const QwtPlotPrintFilter& = QwtPlotPrintFilter() ) const; + void printPlot( QPainter*, const QRectF& ) const; QString getVisualParameters(); void setVisualParameters( const QString& ); @@ -294,7 +302,7 @@ signals: void vpNormRModeChanged(); void vpCurveChanged(); void contextMenuRequested( QContextMenuEvent* ); - void legendClicked( QwtPlotItem* ); + void clicked (const QVariant&, int ); protected: Plot2d_Plot2d* myPlot; @@ -304,10 +312,13 @@ protected: int myCurveType; bool myShowLegend; int myLegendPos; + int myLegendSymbolType; QFont myLegendFont; QColor myLegendColor; + QColor mySelectedLegendFontColor; int myMarkerSize; QColor myBackground; + QColor mySelectionColor; QString myTitle, myXTitle, myYTitle, myY2Title; bool myTitleEnabled, myXTitleEnabled, myYTitleEnabled, myY2TitleEnabled; bool myXGridMajorEnabled, myYGridMajorEnabled, myY2GridMajorEnabled; @@ -343,26 +354,27 @@ public: Plot2d_Plot2d( QWidget* ); virtual ~Plot2d_Plot2d(); - void setLogScale( int, bool ); + void setLogScale( int, bool ); - void replot(); - QwtLegend* getLegend(); - QSize sizeHint() const; - QSize minimumSizeHint() const; - void defaultPicker(); - void setPickerMousePattern( int, int = Qt::NoButton ); - void setPicker( Plot2d_QwtPlotPicker *picker); + void replot(); + QwtAbstractLegend* getLegend(); + QSize sizeHint() const; + QSize minimumSizeHint() const; + void defaultPicker(); + void setPickerMousePattern( int, int = Qt::NoButton ); + void setPicker( Plot2d_QwtPlotPicker *picker); Plot2d_QwtPlotPicker* getPicker() { return myPicker; } Plot2d_AxisScaleDraw* getScaleDraw() { return myScaleDraw; } QList getSeparationLineList() { return mySeparationLineList; } void clearSeparationLineList(); - QwtPlotMarker *createMarkerAndTooltip( QwtSymbol symbol, - double X, - double Y, - QString & tooltip, - Plot2d_QwtPlotPicker *picker); + void setLegendSymbolType( const int ); + int getLegendSymbolType(); + QwtPlotMarker *createMarkerAndTooltip( QwtSymbol* symbol, + double X, + double Y, + QString & tooltip, + Plot2d_QwtPlotPicker *picker); - bool polished() const; QwtPlotGrid* grid() const; QwtPlotZoomer* zoomer() const; @@ -380,17 +392,9 @@ public: void createSeparationLine( double Xpos); - -public slots: - virtual void polish(); - -protected slots: - void onScaleDivChanged(); - protected: QwtPlotGrid* myGrid; QList myColors; - bool myIsPolished; QwtPlotZoomer* myPlotZoomer; Plot2d_AxisScaleDraw* myScaleDraw; // The point picker associated with the graphic view @@ -398,13 +402,13 @@ protected: private: // List of verticals segments between two curves QList mySeparationLineList; + int myLegendSymbolType; }; class Plot2d_ScaleDraw: public QwtScaleDraw { public: Plot2d_ScaleDraw( char f = 'g', int prec = 6 ); - Plot2d_ScaleDraw( const QwtScaleDraw& scaleDraw, char f = 'g', int prec = 6 ); virtual QwtText label( double value ) const; @@ -486,7 +490,6 @@ public: Plot2d_QwtPlotPicker( int xAxis, int yAxis, - int selectionFlags, RubberBand rubberBand, DisplayMode trackerMode, QwtPlotCanvas *canvas); @@ -502,7 +505,7 @@ public: protected: - virtual QwtText trackerText( const QwtDoublePoint & pos ) const; + virtual QwtText trackerText( const QPoint & pos ) const; }; diff --git a/src/Plot2d/Plot2d_ViewManager.cxx b/src/Plot2d/Plot2d_ViewManager.cxx index 5e3a18b04..1ee5059e4 100755 --- a/src/Plot2d/Plot2d_ViewManager.cxx +++ b/src/Plot2d/Plot2d_ViewManager.cxx @@ -66,8 +66,8 @@ bool Plot2d_ViewManager::insertView( SUIT_ViewWindow* theView ) Plot2d_ViewFrame* aViewFrame = view->getViewFrame(); Plot2d_Viewer* aViewer = getPlot2dModel(); - connect( aViewFrame, SIGNAL( legendClicked( QwtPlotItem* ) ), - aViewer, SLOT( onLegendClicked( QwtPlotItem* ) ) ); + connect( aViewFrame, SIGNAL( clicked(const QVariant&, int) ), + aViewer, SLOT( onClicked(const QVariant&, int) ) ); } return res; } diff --git a/src/Plot2d/Plot2d_ViewModel.cxx b/src/Plot2d/Plot2d_ViewModel.cxx index d7c4d2428..23e5893f0 100755 --- a/src/Plot2d/Plot2d_ViewModel.cxx +++ b/src/Plot2d/Plot2d_ViewModel.cxx @@ -40,7 +40,8 @@ Plot2d_Viewer::Plot2d_Viewer(bool theAutoDel) { myPrs = 0; myAutoDel = theAutoDel; - Plot2d_Object::initColors(); + Plot2d_Object::setSelectionColor( QColor(80,80,80) ); + Plot2d_Object::setHighlightedLegendTextColor( QColor(255,255,255) ); } /*! @@ -219,7 +220,7 @@ void Plot2d_Viewer::onCloneView( Plot2d_ViewFrame* clonedVF, Plot2d_ViewFrame* n /* SLOT: called when clicked item in the legend from Plot2d_ViewManager */ -void Plot2d_Viewer::onLegendClicked( QwtPlotItem* plotItem ) +void Plot2d_Viewer::onClicked(const QVariant& itemInfo, int index) { } diff --git a/src/Plot2d/Plot2d_ViewModel.h b/src/Plot2d/Plot2d_ViewModel.h index d8326c8f8..34ffd843a 100755 --- a/src/Plot2d/Plot2d_ViewModel.h +++ b/src/Plot2d/Plot2d_ViewModel.h @@ -62,7 +62,7 @@ protected slots: void onDumpView(); void onShowToolbar(); virtual void onCloneView( Plot2d_ViewFrame*, Plot2d_ViewFrame* ); - virtual void onLegendClicked( QwtPlotItem* ); + virtual void onClicked( const QVariant&, int ); private: Plot2d_Prs* myPrs; diff --git a/src/Plot2d/Plot2d_ViewWindow.cxx b/src/Plot2d/Plot2d_ViewWindow.cxx index c222b1660..98ce2d862 100755 --- a/src/Plot2d/Plot2d_ViewWindow.cxx +++ b/src/Plot2d/Plot2d_ViewWindow.cxx @@ -864,7 +864,7 @@ void Plot2d_ViewWindow::onPrintView() } QMap< QwtPlotCurve*, QPen > aCurvToPen; - QMap< QwtPlotCurve*, QwtSymbol > aCurvToSymbol; + QMap< QwtPlotCurve*, QwtSymbol* > aCurvToSymbol; if ( needColorCorrection ) { @@ -889,12 +889,12 @@ void Plot2d_ViewWindow::onPrintView() aCurve->setPen( aPen ); // symbol - QwtSymbol aSymbol = aCurve->symbol(); + QwtSymbol* aSymbol = const_cast( aCurve->symbol() ); aCurvToSymbol[ aCurve ] = aSymbol; - aPen = aSymbol.pen(); + aPen = aSymbol->pen(); aPen.setColor( QColor( 0, 0, 0 ) ); aPen.setWidthF( 1.5 ); - aSymbol.setPen( aPen ); + aSymbol->setPen( aPen ); aCurve->setSymbol( aSymbol ); } diff --git a/src/Plot2d/resources/Plot2d_msg_en.ts b/src/Plot2d/resources/Plot2d_msg_en.ts index 3f7bea97e..ff2920585 100644 --- a/src/Plot2d/resources/Plot2d_msg_en.ts +++ b/src/Plot2d/resources/Plot2d_msg_en.ts @@ -335,6 +335,10 @@ PLOT2D_BACKGROUND_COLOR_LBL Background color: + + PLOT2D_SELECTION_COLOR_LBL + Selection color: + PLOT2D_DEVIATION_MARKER_TLT Deviation marker @@ -565,6 +569,34 @@ Logarithmic scale for ordinate axis is not allowed. PLOT2D_ENABLE_MAIN_TITLE Main title + + PLOT2D_LEGEND_GROUP + Legend + + + PLOT2D_LEGEND_POSITION + Legend position: + + + PLOT2D_LEGEND_SYMBOL_TYPE + Symbol type: + + + PLOT2D_MARKER_ABOVE_LINE + Marker above line + + + PLOT2D_MARKER_ON_LINE + Marker on line + + + PLOT2D_LEGEND_FONT_COLOR + Legend font color: + + + PLOT2D_SELECTED_LEGEND_FONT_COLOR + Highlighted legend font color: + TOT_PLOT2D_CURVES_LINES Draw lines diff --git a/src/Plot2d/resources/Plot2d_msg_fr.ts b/src/Plot2d/resources/Plot2d_msg_fr.ts index e4796f09a..3503778e6 100755 --- a/src/Plot2d/resources/Plot2d_msg_fr.ts +++ b/src/Plot2d/resources/Plot2d_msg_fr.ts @@ -335,6 +335,10 @@ PLOT2D_BACKGROUND_COLOR_LBL Couleur d'arrière-plan: + + PLOT2D_SELECTION_COLOR_LBL + Couleur de sélection: + PLOT2D_DEVIATION_MARKER_TLT Marqueur de déviation @@ -565,6 +569,34 @@ L'échelle logarithmique de l'ordonnée n'est pas permise.PLOT2D_ENABLE_MAIN_TITLE Titre principal + + PLOT2D_LEGEND_GROUP + Légende + + + PLOT2D_LEGEND_POSITION + Position de la Légende: + + + PLOT2D_LEGEND_SYMBOL_TYPE + Type de symbole: + + + PLOT2D_MARKER_ABOVE_LINE + Marqueur dessus de la ligne + + + PLOT2D_MARKER_ON_LINE + Marqueur sur la ligne + + + PLOT2D_LEGEND_FONT_COLOR + Couleur de police de la légende: + + + PLOT2D_SELECTED_LEGEND_FONT_COLOR + Couleur de surlignement de la légende: + TOT_PLOT2D_CURVES_LINES Dessiner des lignes diff --git a/src/PyConsole/PyConsole_EnhInterp.cxx b/src/PyConsole/PyConsole_EnhInterp.cxx index 81fc033a3..8915f0765 100644 --- a/src/PyConsole/PyConsole_EnhInterp.cxx +++ b/src/PyConsole/PyConsole_EnhInterp.cxx @@ -73,7 +73,7 @@ int PyConsole_EnhInterp::runDirCommand(const QString & dirArgument, const QStrin if (dirArgument.trimmed() != "") cmd = dirArgument + "."; cmd += _last_matches[0] + ".__doc__"; - PyObject * str = PyRun_String(cmd.toStdString().c_str(), Py_eval_input, _g, _g); + PyObject * str = PyRun_String(cmd.toStdString().c_str(), Py_eval_input, _context, _context); if (!str || str == Py_None || !PyString_Check(str)) { if (!str) @@ -104,7 +104,7 @@ int PyConsole_EnhInterp::runDirAndExtract(const QString& dirArgument, { QRegExp re("^[A-Z].+_[A-Z]+[a-z]+.+$"); // discard SWIG static method, e.g. MEDCouplingUMesh_Blabla QString command("dir(" + dirArgument + ")"); - PyObject * plst = PyRun_String(command.toStdString().c_str(), Py_eval_input, _g, _g); + PyObject * plst = PyRun_String(command.toStdString().c_str(), Py_eval_input, _context, _context); if(!plst || plst == Py_None) { if(!plst) PyErr_Clear(); diff --git a/src/PyConsole/PyConsole_Interp.cxx b/src/PyConsole/PyConsole_Interp.cxx index ee04ddb16..d230e9b12 100644 --- a/src/PyConsole/PyConsole_Interp.cxx +++ b/src/PyConsole/PyConsole_Interp.cxx @@ -31,38 +31,16 @@ \class PyConsole_Interp \brief Python interpreter to be embedded to the SALOME study's GUI. - Python interpreter is created one per SALOME study. + There is only one Python interpreter for the whole SALOME environment. - Call initialize method defined in the base class PyInterp_Interp, - to intialize interpreter after instance creation. + Call the initialize() method defined in the base class PyInterp_Interp, + to initialize the interpreter after instance creation. The method initialize() calls virtuals methods - initPython() to initialize global Python interpreter - - initState() to initialize embedded interpreter state + //- initState() to initialize embedded interpreter state (OBSOLETE) - initContext() to initialize interpreter internal context - initRun() to prepare interpreter for running commands - - /EDF-CCAR/ - When SALOME uses multi Python interpreter feature, - every study has its own interpreter and thread state (_tstate = Py_NewInterpreter()). - This is fine because every study has its own modules (sys.modules) stdout and stderr. - - But some Python modules must be imported only once. In multi interpreter - context Python modules (*.py) are imported several times. - For example, the PyQt module must be imported only once because - it registers classes in a C module. - - It's quite the same with omniorb modules (internals and generated with omniidl). - - This problem is handled with "shared modules" defined in salome_shared_modules.py. - These "shared modules" are imported only once and only copied in all - the other interpreters. - - But it's not the only problem. Every interpreter has its own - __builtin__ module. That's fine but if we have copied some modules - and imported others problems may arise with operations that are not allowed - in restricted execution environment. So we must impose that all interpreters - have identical __builtin__ module. */ /*! @@ -83,42 +61,6 @@ PyConsole_Interp::~PyConsole_Interp() { } -/*! - \brief Initialize internal Python interpreter state. - - When calling initState the GIL is not held - It must not be held on exit - - \return \c true on success -*/ -bool PyConsole_Interp::initState() -{ - PyEval_AcquireLock(); - _tstate = Py_NewInterpreter(); // create an interpreter and save current state - PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv - - if(!builtinmodule) // PAL18041: deepcopy function don't work in Salome - { - //builtinmodule is static member of PyInterp class - //If it is not NULL (initialized to the builtin module of the main interpreter - //all the sub interpreters will have the same builtin - //_interp is a static member and is the main interpreter - //The first time we initialized it to the builtin of main interpreter - builtinmodule=PyDict_GetItemString(_interp->modules, "__builtin__"); - } - - //If builtinmodule has been initialized all the sub interpreters - // will have the same __builtin__ module - if(builtinmodule){ - PyObject *m = PyImport_GetModuleDict(); - PyDict_SetItemString(m, "__builtin__", builtinmodule); - _tstate->interp->builtins = PyModule_GetDict(builtinmodule); - Py_INCREF(_tstate->interp->builtins); - } - PyEval_ReleaseThread(_tstate); - return true; -} - /*! \brief Initialize python interpeter context. @@ -135,10 +77,6 @@ bool PyConsole_Interp::initContext() PyErr_Print(); return false; } - _g = PyModule_GetDict(m); // get interpreter dictionnary context - - if(builtinmodule){ - PyDict_SetItemString(_g, "__builtins__", builtinmodule); // assign singleton __builtin__ module - } + _context = PyModule_GetDict(m); // get interpreter dictionnary context return true; } diff --git a/src/PyConsole/PyConsole_Interp.h b/src/PyConsole/PyConsole_Interp.h index 254cc8146..d122db0a6 100644 --- a/src/PyConsole/PyConsole_Interp.h +++ b/src/PyConsole/PyConsole_Interp.h @@ -39,7 +39,6 @@ public: ~PyConsole_Interp(); protected: - virtual bool initState(); virtual bool initContext(); }; diff --git a/src/PyInterp/PyInterp_Dispatcher.cxx b/src/PyInterp/PyInterp_Dispatcher.cxx index 6f5af57bf..73898b53d 100755 --- a/src/PyInterp/PyInterp_Dispatcher.cxx +++ b/src/PyInterp/PyInterp_Dispatcher.cxx @@ -96,11 +96,11 @@ void PyInterp_Request::setListener( QObject* o ) void PyInterp_LockRequest::safeExecute() { - if ( getInterp() ){ - PyLockWrapper aLock = getInterp()->GetLockWrapper(); + //if ( getInterp() ){ // No need to have an interpreter now! we can simply run in a empty context + PyLockWrapper aLock; // Acquire GIL //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) ); execute(); - } + //} } PyInterp_Event::~PyInterp_Event() diff --git a/src/PyInterp/PyInterp_Interp.cxx b/src/PyInterp/PyInterp_Interp.cxx index 2f8a1db3e..4af91284e 100644 --- a/src/PyInterp/PyInterp_Interp.cxx +++ b/src/PyInterp/PyInterp_Interp.cxx @@ -39,9 +39,6 @@ #define TOP_HISTORY_PY "--- top of history ---" #define BEGIN_HISTORY_PY "--- begin of history ---" -// a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state) -std::map currentThreadMap; - /*! \class PyLockWrapper \brief Python GIL wrapper. @@ -49,16 +46,10 @@ std::map currentThreadMap; /*! \brief Constructor. Automatically acquires GIL. - \param theThreadState python thread state */ -PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): - myThreadState(theThreadState), - mySaveThreadState(0) +PyLockWrapper::PyLockWrapper() { - if (myThreadState->interp == PyInterp_Interp::_interp) - _savestate = PyGILState_Ensure(); - else - PyEval_AcquireThread(myThreadState); + _gil_state = PyGILState_Ensure(); } /*! @@ -66,51 +57,15 @@ PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): */ PyLockWrapper::~PyLockWrapper() { - if (myThreadState->interp == PyInterp_Interp::_interp) - PyGILState_Release(_savestate); - else - PyEval_ReleaseThread(myThreadState); -} - -/*! - \brief Get Python GIL wrapper. - \return GIL lock wrapper (GIL is automatically acquired here) -*/ -PyLockWrapper PyInterp_Interp::GetLockWrapper() -{ - if (_tstate->interp == PyInterp_Interp::_interp) - return _tstate; - - // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread - long currentThreadid=PyThread_get_thread_ident(); // the system thread id - PyThreadState* theThreadState; - if(currentThreadMap.count(currentThreadid) != 0) - { - //a thread state exists for this thread id - PyThreadState* oldThreadState=currentThreadMap[currentThreadid]; - if(_tstate->interp ==oldThreadState->interp) - { - //The old thread state has the same python interpreter as this one : reuse the threadstate - theThreadState=oldThreadState; - } - else - { - //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one - PyEval_AcquireLock(); - PyThreadState_Clear(oldThreadState); - PyThreadState_Delete(oldThreadState); - PyEval_ReleaseLock(); - theThreadState=PyThreadState_New(_tstate->interp); - currentThreadMap[currentThreadid]=theThreadState; - } - } - else - { - // no old thread state for this thread id : create a new one - theThreadState=PyThreadState_New(_tstate->interp); - currentThreadMap[currentThreadid]=theThreadState; - } - return theThreadState; +// if (myThreadState->interp == PyInterp_Interp::_interp) +// PyGILState_Release(_savestate); +// else +// PyEval_ReleaseThread(myThreadState); + + /* The destructor can never be called concurrently by two threads since it is called + * when the GIL is held - the below test should never run concurrently in two threads. + */ + PyGILState_Release(_gil_state); } /* @@ -232,9 +187,9 @@ static PyStdOut* newPyStdOut( bool iscerr ) int PyInterp_Interp::_argc = 1; char* PyInterp_Interp::_argv[] = {(char*)""}; -PyObject* PyInterp_Interp::builtinmodule = NULL; -PyThreadState* PyInterp_Interp::_gtstate = NULL; -PyInterpreterState* PyInterp_Interp::_interp = NULL; +//PyObject* PyInterp_Interp::builtinmodule = NULL; +//PyThreadState* PyInterp_Interp::_gtstate = NULL; +//PyInterpreterState* PyInterp_Interp::_interp = NULL; /*! \brief Basic constructor. @@ -243,10 +198,12 @@ PyInterpreterState* PyInterp_Interp::_interp = NULL; must call virtual method initalize(). */ PyInterp_Interp::PyInterp_Interp(): - _tstate(0), _vout(0), _verr(0), _g(0) + _vout(0), _verr(0), _context(0) { } + + /*! \brief Destructor. */ @@ -271,20 +228,21 @@ void PyInterp_Interp::initialize() _history.clear(); // start a new list of user's commands _ith = _history.begin(); - initPython(); - // Here the global lock is released + initPython(); // This also inits the multi-threading for Python (but w/o acquiring GIL) - initState(); + //initState(); // [ABN] OBSOLETE - PyEval_AcquireThread(_tstate); + // ---- The rest of the initialisation process is done hodling the GIL + PyLockWrapper lck; initContext(); - // used to interpret & compile commands + // used to interpret & compile commands - this is really imported here + // and only added again (with PyImport_AddModule) later on PyObjWrapper m(PyImport_ImportModule("codeop")); if(!m) { PyErr_Print(); - PyEval_ReleaseThread(_tstate); + PyEval_ReleaseLock(); return; } @@ -294,17 +252,16 @@ void PyInterp_Interp::initialize() // All the initRun outputs are redirected to the standard output (console) initRun(); - PyEval_ReleaseThread(_tstate); } /*! \brief Initialize Python interpreter. - In case if Python is not initialized, it sets program name, initializes the interpreter, sets program arguments, - initializes threads. - Otherwise, it just obtains the global interpreter and thread states. This is important for light SALOME configuration, + In case if Python is not initialized, it sets program name, initializes the single true Python + interpreter, sets program arguments, and initializes threads. + Otherwise, does nothing. This is important for light SALOME configuration, as in full SALOME this is done at SalomeApp level. - \sa SalomeApp_PyInterp class + \sa SalomeApp_PyInterp class and main() in SALOME_Session_Server */ void PyInterp_Interp::initPython() { @@ -313,30 +270,22 @@ void PyInterp_Interp::initPython() Py_SetProgramName(_argv[0]); Py_Initialize(); // Initialize the interpreter PySys_SetArgv(_argc, _argv); - PyEval_InitThreads(); // Create (and acquire) the interpreter lock - } - if ( _interp == NULL ) - _interp = PyThreadState_Get()->interp; - if (PyType_Ready(&PyStdOut_Type) < 0) { - PyErr_Print(); + PyEval_InitThreads(); // Create (and acquire) the Python global interpreter lock (GIL) + PyEval_ReleaseLock(); } - if ( _gtstate == NULL ) - _gtstate = PyEval_SaveThread(); // Release global thread state } /*! \brief Get embedded Python interpreter banner. \return banner string */ -std::string PyInterp_Interp::getbanner() +std::string PyInterp_Interp::getbanner() const { - // Should we take the lock ? - // PyEval_RestoreThread(_tstate); + PyLockWrapper lck; std::string aBanner("Python "); aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ; aBanner = aBanner + "\ntype help to get general information on environment\n"; - //PyEval_SaveThread(); return aBanner; } @@ -350,24 +299,13 @@ std::string PyInterp_Interp::getbanner() */ bool PyInterp_Interp::initRun() { - // - // probably all below code isn't required - // - /* - PySys_SetObject("stderr",_verr); - PySys_SetObject("stdout",_vout); - - //PyObject *m = PyImport_GetModuleDict(); - - PySys_SetObject("stdout",PySys_GetObject("__stdout__")); - PySys_SetObject("stderr",PySys_GetObject("__stderr__")); - */ return true; } /*! \brief Compile Python command and evaluate it in the - python dictionary context if possible. + python dictionary context if possible. This is not thread-safe. + This is the caller's responsability to make this thread-safe. \internal \param command Python command string \param context Python context (dictionary) @@ -396,12 +334,7 @@ static int run_command(const char *command, PyObject *context) return 1; } else { - // Complete and correct text. We evaluate it. - //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0 - // PyObjWrapper r(PyEval_EvalCode(v,context,context)); - //#else PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context)); - //#endif if(!r) { // Execution error. We return -1 PyErr_Print(); @@ -433,7 +366,7 @@ void replaceAll(std::string& str, const std::string& from, const std::string& to \return -1 on fatal error, 1 if command is incomplete and 0 if command is executed successfully */ -static int compile_command(const char *command,PyObject *context) +static int compile_command(const char *command, PyObject *context) { // First guess if command is execution of a script with args, or a simple Python command std::string singleCommand = command; @@ -466,7 +399,8 @@ static int compile_command(const char *command,PyObject *context) } /*! - \brief Run Python command. + \brief Run Python command - the command has to fit on a single line (no \n!). + Use ';' if you need multiple statements evaluated at once. \param command Python command \return command status */ @@ -476,8 +410,17 @@ int PyInterp_Interp::run(const char *command) return simpleRun(command); } +/** + * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability + * to acquire GIL if needed. + */ +int PyInterp_Interp::beforeRun() +{ + return 0; +} + /*! - \brief Run Python command (used internally). + \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability. \param command Python command \param addToHistory if \c true (default), the command is added to the commands history \return command status @@ -489,19 +432,22 @@ int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory) _ith = _history.end(); } - // We come from C++ to enter Python world - // We need to acquire the Python global lock - //PyLockWrapper aLock(_tstate); // san - lock is centralized now + // Current stdout and stderr are saved + PyObject * oldOut = PySys_GetObject((char*)"stdout"); + PyObject * oldErr = PySys_GetObject((char*)"stderr"); + // Keep them alive (PySys_GetObject returned a *borrowed* ref!) + Py_INCREF(oldOut); + Py_INCREF(oldErr); - // Reset redirected outputs before treatment + // Redirect outputs to SALOME Python console before treatment PySys_SetObject((char*)"stderr",_verr); PySys_SetObject((char*)"stdout",_vout); - int ier = compile_command(command,_g); + int ier = compile_command(command,_context); - // Outputs are redirected on standards outputs (console) - PySys_SetObject((char*)"stdout",PySys_GetObject((char*)"__stdout__")); - PySys_SetObject((char*)"stderr",PySys_GetObject((char*)"__stderr__")); + // Outputs are redirected to what they were before + PySys_SetObject((char*)"stdout",oldOut); + PySys_SetObject((char*)"stderr",oldErr); return ier; } diff --git a/src/PyInterp/PyInterp_Interp.h b/src/PyInterp/PyInterp_Interp.h index 6c22da317..72125dbd6 100644 --- a/src/PyInterp/PyInterp_Interp.h +++ b/src/PyInterp/PyInterp_Interp.h @@ -32,26 +32,42 @@ #include #include +/** + * Utility class wrappin the Python GIL acquisition. This makes use of the high level + * API (PyGILState_Ensure and PyGILState_Release), and is hence compatible with only + * one running Python interpreter (no call to Py_NewInterpreter()). + * When the class is instanciated the lock is acquired. It is released at destruction time. + * Copy construction (and hence assignation) is forbidden. + */ class PYINTERP_EXPORT PyLockWrapper { - PyThreadState* myThreadState; - PyThreadState* mySaveThreadState; - PyGILState_STATE _savestate; + PyGILState_STATE _gil_state; public: - PyLockWrapper(PyThreadState* theThreadState); + PyLockWrapper(); ~PyLockWrapper(); + +private: + // "Rule of 3" - Forbid usage of copy operator and copy-constructor + PyLockWrapper(const PyLockWrapper & another); + const PyLockWrapper & operator=(const PyLockWrapper & another); }; typedef void PyOutChanged(void* data,char * c); +/** + * Main class representing a *virtual* Python interpreter. There is really only one true + * Python interpreter in the whole application (no call to Py_NewInterpreter), + * but the use of different execution contexts allow + * to split the execution lines, and hence to emulate (relatively) independent interpreters. + * This has some consequences: modules imported in one context are not re-imported in another context + * (only there namespace is made available when importing in another context). + * See also class PyConsole_Interp. + */ class PYINTERP_EXPORT PyInterp_Interp { public: static int _argc; static char* _argv[]; - static PyObject *builtinmodule; - static PyThreadState *_gtstate; - static PyInterpreterState *_interp; PyInterp_Interp(); virtual ~PyInterp_Interp(); @@ -60,33 +76,41 @@ public: virtual int run(const char *command); - PyLockWrapper GetLockWrapper(); + // [ABN] - the PyLockWrapper is no more attached to the interpreter + // PyLockWrapper GetLockWrapper() const; - std::string getbanner(); + std::string getbanner() const; void setverrcb(PyOutChanged*,void*); void setvoutcb(PyOutChanged*,void*); const char * getPrevious(); - const char * getNext(); + const char * getNext(); protected: - PyThreadState * _tstate; + /** Redirection of stdout and stderr */ PyObject * _vout; PyObject * _verr; - PyObject * _g; + /** Execution context (local and global variables) */ + PyObject * _context; PyObject * _codeop; std::list _history; std::list::iterator _ith; - virtual int beforeRun() { return 0; } + virtual int beforeRun(); int simpleRun(const char* command, const bool addToHistory = true); - virtual bool initRun(); virtual void initPython(); - virtual bool initState() = 0; - virtual bool initContext() = 0; + /** OBSOLETE - should'nt be called anymore */ + //virtual bool initState() = 0; + + /** Initialize execution context. Must set the member _context, and return True on success. */ + virtual bool initContext() = 0; + virtual bool initRun(); }; +/** + * Utility class to properly handle the reference counting required on Python objects. + */ class PYINTERP_EXPORT PyObjWrapper { PyObject* myObject; diff --git a/src/PyInterp/PyInterp_Request.h b/src/PyInterp/PyInterp_Request.h index 07a1c14b7..4ceacd3e0 100644 --- a/src/PyInterp/PyInterp_Request.h +++ b/src/PyInterp/PyInterp_Request.h @@ -88,7 +88,7 @@ class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request { public: - PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false ) + PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener=0, bool sync=false ) : PyInterp_Request( listener, sync ), myInterp( interp ) {} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx index 482060181..799522728 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx @@ -67,10 +67,8 @@ extern "C" { static bool alreadyInitialized = false; if ( !alreadyInitialized ) { - // call only once (see comment above) ! - PyEval_RestoreThread( KERNEL_PYTHON::_gtstate); + PyLockWrapper lck; // GIL acquisition INIT_FUNCTION(); - PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate); alreadyInitialized = !alreadyInitialized; } diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx index 21567b75d..2fb54675d 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx @@ -38,11 +38,11 @@ // Py_ssize_t for old Pythons // This code is as recommended by" // http://www.python.org/dev/peps/pep-0353/#conversion-guidelines -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -#endif +//#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +//typedef int Py_ssize_t; +//# define PY_SSIZE_T_MAX INT_MAX +//# define PY_SSIZE_T_MIN INT_MIN +//#endif // // NB: Python requests. @@ -84,21 +84,8 @@ extern "C" // make initialization only once (see comment above) ! if ( !alreadyInitialized ) { - static PyThreadState* gtstate = 0; -#ifndef GUI_DISABLE_CORBA - if ( SUIT_PYTHON::initialized ) - gtstate = SUIT_PYTHON::_gtstate; - else - gtstate = KERNEL_PYTHON::_gtstate; -#else - gtstate = SUIT_PYTHON::_gtstate; -#endif - PyEval_RestoreThread( gtstate ); - + PyLockWrapper lck; // GIL acquisition INIT_FUNCTION(); - - PyEval_ReleaseThread( gtstate ); - alreadyInitialized = !alreadyInitialized; } diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h index 8dfe17f6f..ffcbf2158 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h @@ -71,9 +71,9 @@ public: // data model management QString createObject( const QString& ); QString createObject( const QString&, - const QString&, - const QString&, - const QString& ); + const QString&, + const QString&, + const QString& ); void setName( const QString&, const QString& ); QString getName( const QString& ) const; diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx index b1c259a2b..bb72bb2b6 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx @@ -49,38 +49,9 @@ void SALOME_PYQT_PyInterp::initPython() * Do nothing * The initialization has been done in main */ - MESSAGE("SALOME_PYQT_PyInterp::initPython"); -#ifndef GUI_DISABLE_CORBA - if(SUIT_PYTHON::initialized) { - ASSERT(SUIT_PYTHON::_gtstate); // initialisation in main - SCRUTE(SUIT_PYTHON::_gtstate); - _tstate = SUIT_PYTHON::_gtstate; - } - else { - ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main - SCRUTE(KERNEL_PYTHON::_gtstate); - _tstate = KERNEL_PYTHON::_gtstate; - } -#else - SCRUTE(SUIT_PYTHON::_gtstate); - _tstate = SUIT_PYTHON::_gtstate; -#endif -} - -bool SALOME_PYQT_PyInterp::initState() -{ - /* - * The GIL is assumed to not be held on the call - * The GIL is acquired in initState and will be held on initState exit - * It is the caller responsability to release the lock on exit if needed - */ - PyEval_AcquireThread(_tstate); - SCRUTE(_tstate); - PyEval_ReleaseThread(_tstate); - return true; + MESSAGE("SALOME_PYQT_PyInterp::initPython - does nothing"); } - bool SALOME_PYQT_PyInterp::initContext() { /* @@ -88,10 +59,7 @@ bool SALOME_PYQT_PyInterp::initContext() * It is the caller responsability to acquire the GIL before calling initContext * It will still be held on initContext exit */ - _g = PyDict_New(); // create interpreter dictionnary context - PyObject *bimod = PyImport_ImportModule("__builtin__"); - PyDict_SetItemString(_g, "__builtins__", bimod); - Py_DECREF(bimod); + _context = PyDict_New(); // create interpreter dictionnary context return true; } @@ -100,18 +68,15 @@ int SALOME_PYQT_PyInterp::run(const char *command) MESSAGE("compile"); PyObject *code = Py_CompileString((char *)command,"PyGUI",Py_file_input); if(!code){ - // Une erreur s est produite en general SyntaxError + // An error occured - normally here a SyntaxError PyErr_Print(); return -1; } - //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0 - // PyObject *r = PyEval_EvalCode(code,_g,_g); - //#else - PyObject *r = PyEval_EvalCode((PyCodeObject *)code,_g,_g); - //#endif + PyObject *r = PyEval_EvalCode((PyCodeObject *)code,_context,_context); + Py_DECREF(code); if(!r){ - // Une erreur s est produite a l execution + // An error occured at execution PyErr_Print(); return -1 ; } diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h index 958c35376..5857ffe8d 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h @@ -38,7 +38,6 @@ class SALOME_PYQT_LIGHT_EXPORT SALOME_PYQT_PyInterp : public PyInterp_Interp protected: virtual void initPython(); - virtual bool initState(); virtual bool initContext(); }; diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx index 0a90da490..4a21a4085 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx @@ -228,9 +228,9 @@ public: XmlHandler( PyModuleHelper* helper, const QString& fileName ); void createActions(); void createPopup( QMenu* menu, - const QString& context, - const QString& parent, - const QString& object ); + const QString& context, + const QString& parent, + const QString& object ); void activateMenus( bool ); private: @@ -238,11 +238,11 @@ private: QIcon loadIcon( const QString& fileName ); void createMenu( QDomNode& parentNode, - const int parentMenuId = -1, - QMenu* parentPopup = 0 ); + const int parentMenuId = -1, + QMenu* parentPopup = 0 ); void createToolBar( QDomNode& parentNode ); void insertPopupItems( QDomNode& parentNode, - QMenu* menu ); + QMenu* menu ); private: PyModuleHelper* myHelper; @@ -258,7 +258,7 @@ private: \param fileName path to the XML menu description file */ PyModuleHelper::XmlHandler::XmlHandler( PyModuleHelper* helper, - const QString& fileName ) + const QString& fileName ) : myHelper( helper ) { if ( !fileName.isEmpty() ) { @@ -305,9 +305,9 @@ void PyModuleHelper::XmlHandler::createActions() \param context popup menu object name */ void PyModuleHelper::XmlHandler::createPopup( QMenu* menu, - const QString& context, - const QString& parent, - const QString& object ) + const QString& context, + const QString& parent, + const QString& object ) { // get document element QDomElement aDocElem = myDoc.documentElement(); @@ -364,10 +364,10 @@ QIcon PyModuleHelper::XmlHandler::loadIcon( const QString& fileName ) if ( module() && !fileName.isEmpty() ) { SUIT_ResourceMgr* resMgr = module()->getApp()->resourceMgr(); QPixmap pixmap = resMgr->loadPixmap( module()->name(), - QApplication::translate( module()->name().toLatin1().data(), - fileName.toLatin1().data() ) ); - if ( !pixmap.isNull() ) - icon = QIcon( pixmap ); + QApplication::translate( module()->name().toLatin1().data(), + fileName.toLatin1().data() ) ); + if ( !pixmap.isNull() ) + icon = QIcon( pixmap ); } return icon; @@ -381,8 +381,8 @@ QIcon PyModuleHelper::XmlHandler::loadIcon( const QString& fileName ) \param parentPopup parent popup menu (0 for top-level menu) */ void PyModuleHelper::XmlHandler::createMenu( QDomNode& parentNode, - const int parentMenuId, - QMenu* parentPopup ) + const int parentMenuId, + QMenu* parentPopup ) { if ( !module() || parentNode.isNull() ) return; @@ -425,14 +425,14 @@ void PyModuleHelper::XmlHandler::createMenu( QDomNode& parentNode, if ( id != -1 ) { // create menu action QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); module()->createMenu( action, // action menuId, // parent menu ID id, // ID (same as for createAction()) @@ -496,17 +496,17 @@ void PyModuleHelper::XmlHandler::createToolBar( QDomNode& parentNode ) // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created if ( id != -1 ) { - // create toolbar action - QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); - module()->createTool( action, tbId, -1, pos ); + // create toolbar action + QAction* action = module()->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); + module()->createTool( action, tbId, -1, pos ); } } else if ( aTagName == "separatorTB" || aTagName == "separator" ) { @@ -552,15 +552,15 @@ void PyModuleHelper::XmlHandler::insertPopupItems( QDomNode& parentNode, QMenu* // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created if ( id != -1 ) { - QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); + QAction* action = module()->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0; menu->insertAction( before, action ); } @@ -627,7 +627,7 @@ PyModuleHelper::~PyModuleHelper() { delete myXmlHandler; if ( myInterp && myPyModule ) { - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL Py_XDECREF( myPyModule ); } } @@ -691,8 +691,8 @@ void PyModuleHelper::connectAction( QAction* a ) { if ( myModule && a ) QObject::connect( a, SIGNAL( triggered( bool ) ), - this, SLOT( actionActivated() ), - Qt::UniqueConnection ); + this, SLOT( actionActivated() ), + Qt::UniqueConnection ); } /*! @@ -747,11 +747,11 @@ QStringList PyModuleHelper::viewManagers() const \brief Initialization of the Python-based SALOME module. This method can be used for creation of the menus, toolbars and - other such staff. + other such stuff. There are two ways to do this: - 1) for obsolete modules implementatino this method first tries to read - _.xml resource file which contains a menu, + 1) for obsolete modules, the implementation of this method first tries to read + the _.xml resource file which contains a menu, toolbars and popup menus description; 2) new modules can create menus by direct calling of the corresponding methods of SalomePyQt Python API in the Python @@ -759,7 +759,7 @@ QStringList PyModuleHelper::viewManagers() const \note SALOME supports two modes of modules loading: - immediate (all the modules are created and initialized - immediately when the application object is created; + immediately when the application object is created); - postponed modules loading (used currently); in this mode the module is loaded only by explicit request. If postponed modules loading is not used, the active @@ -798,10 +798,10 @@ void PyModuleHelper::initialize( CAM_Application* app ) { public: InitializeReq( PyModuleHelper* _helper, - CAM_Application* _app ) + CAM_Application* _app ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myApp( _app ) + myApp( _app ) {} protected: virtual void execute() @@ -841,21 +841,21 @@ bool PyModuleHelper::activate( SUIT_Study* study ) { public: ActivateReq( PyModuleHelper* _helper, - SUIT_Study* _study, - bool _customize ) - : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) - myHelper( _helper ), - myStudy ( _study ), - myCustomize( _customize ) - {} + SUIT_Study* _study, + bool _customize ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myHelper( _helper ), + myStudy ( _study ), + myCustomize( _customize ) + {} protected: virtual void execute() - { - if ( !myCustomize ) - myHelper->internalActivate( myStudy ); // first activation stage - else - myHelper->internalCustomize( myStudy ); // second activation stage - } + { + if ( !myCustomize ) + myHelper->internalActivate( myStudy ); // first activation stage + else + myHelper->internalCustomize( myStudy ); // second activation stage + } private: PyModuleHelper* myHelper; SUIT_Study* myStudy; @@ -881,12 +881,12 @@ bool PyModuleHelper::activate( SUIT_Study* study ) if ( myLastActivateStatus ) { // connect preferences changing signal connect( myModule->getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ), - this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); + this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); // connect active view change signal SUIT_Desktop* d = study->application()->desktop(); connect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), - this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); + this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); // if active window exists, call activeViewChanged() function; // temporary solution: if a getActiveView() in SalomePyQt available // we no longer need this @@ -924,11 +924,11 @@ bool PyModuleHelper::deactivate( SUIT_Study* study ) { public: DeactivateReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, + PyModuleHelper* _helper, SUIT_Study* _study ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myStudy ( _study ) + myStudy ( _study ) {} protected: virtual void execute() @@ -950,7 +950,7 @@ bool PyModuleHelper::deactivate( SUIT_Study* study ) // disconnect the SUIT_Desktop signal windowActivated() SUIT_Desktop* d = study->application()->desktop(); disconnect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), - this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); + this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); // deactivate menus, toolbars, etc if ( myXmlHandler ) myXmlHandler->activateMenus( false ); @@ -1023,7 +1023,7 @@ void PyModuleHelper::modelClosed( SUIT_Study* study ) \param parameter preference resources parameter name */ void PyModuleHelper::preferencesChanged( const QString& section, - const QString& parameter ) + const QString& parameter ) { FuncMsg fmsg( "PyModuleHelper::preferencesChanged()" ); @@ -1031,9 +1031,9 @@ void PyModuleHelper::preferencesChanged( const QString& section, { public: PrefChangeReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - const QString& _section, - const QString& _parameter ) + PyModuleHelper* _helper, + const QString& _section, + const QString& _parameter ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper ( _helper ), mySection( _section ), @@ -1065,8 +1065,8 @@ void PyModuleHelper::preferencesChanged( const QString& section, \param parameter preference resources parameter name */ void PyModuleHelper::preferenceChanged( const QString& module, - const QString& section, - const QString& parameter ) + const QString& section, + const QString& parameter ) { FuncMsg fmsg( "PyModuleHelper::preferenceChanged()" ); @@ -1094,10 +1094,10 @@ void PyModuleHelper::studyActivated( SUIT_Study* study ) { public: StudyChangedReq( PyModuleHelper* _helper, - SUIT_Study* _study ) + SUIT_Study* _study ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myStudy ( _study ) + myStudy ( _study ) {} protected: virtual void execute() @@ -1130,8 +1130,8 @@ void PyModuleHelper::actionActivated() { public: ActionReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - int _id ) + PyModuleHelper* _helper, + int _id ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), myId ( _id ) @@ -1176,7 +1176,7 @@ void PyModuleHelper::contextMenu( const QString& context, QMenu* menu ) const QString& _context, QMenu* _menu ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) - myHelper ( _helper ), + myHelper ( _helper ), myContext( _context ), myMenu ( _menu ) {} @@ -1214,7 +1214,7 @@ void PyModuleHelper::createPreferences() { public: CreatePrefReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper ) + PyModuleHelper* _helper ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) {} @@ -1249,11 +1249,11 @@ void PyModuleHelper::activeViewChanged( SUIT_ViewWindow* view ) { public: ActiveViewChangeReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1283,11 +1283,11 @@ void PyModuleHelper::tryCloseView( SUIT_ViewWindow* view ) { public: TryCloseViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1314,8 +1314,8 @@ void PyModuleHelper::closeView( SUIT_ViewWindow* view ) { public: CloseViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), myView( _view ) @@ -1345,11 +1345,11 @@ void PyModuleHelper::cloneView( SUIT_ViewWindow* view ) { public: CloneViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1383,8 +1383,8 @@ void PyModuleHelper::save( QStringList& files ) { public: SaveReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList& _files ) + PyModuleHelper* _helper, + QStringList& _files ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myFiles( _files ) @@ -1420,9 +1420,9 @@ bool PyModuleHelper::load( const QStringList& files ) { public: LoadReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList _files, - bool& _loaded ) + PyModuleHelper* _helper, + QStringList _files, + bool& _loaded ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myFiles( _files ), @@ -1466,8 +1466,8 @@ void PyModuleHelper::dumpPython( QStringList& files ) { public: DumpPythonReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList& _files ) + PyModuleHelper* _helper, + QStringList& _files ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myFiles( _files ) @@ -1504,9 +1504,9 @@ bool PyModuleHelper::isDraggable( const SUIT_DataObject* what ) const { public: IsDraggableReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - LightApp_DataObject* _data_object, - bool& _is_draggable ) + PyModuleHelper* _helper, + LightApp_DataObject* _data_object, + bool& _is_draggable ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myDataObject( _data_object ), @@ -1529,9 +1529,9 @@ bool PyModuleHelper::isDraggable( const SUIT_DataObject* what ) const // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) PyInterp_Dispatcher::Get()->Exec( new IsDraggableReq( myInterp, - const_cast( this ), - const_cast( data_object ), - draggable ) ); + const_cast( this ), + const_cast( data_object ), + draggable ) ); } return draggable; @@ -1553,9 +1553,9 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const { public: IsDropAcceptedReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - LightApp_DataObject* _data_object, - bool& _is_drop_accepted ) + PyModuleHelper* _helper, + LightApp_DataObject* _data_object, + bool& _is_drop_accepted ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myDataObject( _data_object ), @@ -1578,9 +1578,9 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) PyInterp_Dispatcher::Get()->Exec( new IsDropAcceptedReq( myInterp, - const_cast( this ), - const_cast( data_object ), - dropAccepted ) ); + const_cast( this ), + const_cast( data_object ), + dropAccepted ) ); } return dropAccepted; @@ -1594,7 +1594,7 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const \param action current drop action (copy or move) */ void PyModuleHelper::dropObjects( const DataObjectList& what, SUIT_DataObject* where, - const int row, Qt::DropAction action ) + const int row, Qt::DropAction action ) { FuncMsg fmsg( "PyModuleHelper::dropObjects()" ); @@ -1603,17 +1603,17 @@ void PyModuleHelper::dropObjects( const DataObjectList& what, SUIT_DataObject* w { public: DropObjectsReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - const DataObjectList& _what, - SUIT_DataObject* _where, - const int _row, - Qt::DropAction _action ) + PyModuleHelper* _helper, + const DataObjectList& _what, + SUIT_DataObject* _where, + const int _row, + Qt::DropAction _action ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myWhat( _what ), - myWhere( _where ), - myRow( _row ), - myAction ( _action ) + myWhere( _where ), + myRow( _row ), + myAction ( _action ) {} protected: virtual void execute() @@ -1647,10 +1647,10 @@ QString PyModuleHelper::engineIOR() const public: EngineIORReq( PyInterp_Interp* _py_interp, PyModuleHelper* _helper, - QString& _ior ) + QString& _ior ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myIOR( _ior ) + myIOR( _ior ) {} protected: virtual void execute() @@ -1667,8 +1667,8 @@ QString PyModuleHelper::engineIOR() const if ( anIOR.isEmpty() ) { // post request PyInterp_Dispatcher::Get()->Exec( new EngineIORReq( myInterp, - const_cast( this ), - anIOR ) ); + const_cast( this ), + anIOR ) ); } return anIOR; @@ -1708,7 +1708,7 @@ void PyModuleHelper::initInterp( int studyId ) // import 'salome' module and call 'salome_init' method; // do it only once on interpreter creation // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then import a module PyObjWrapper aMod = PyImport_ImportModule( "salome" ); if ( !aMod ) { @@ -1732,7 +1732,7 @@ void PyModuleHelper::initInterp( int studyId ) \brief Import Python GUI module and store reference to the module. \internal - Attention! initInterp() should be called first!!! + Warning! initInterp() should be called first!!! */ void PyModuleHelper::importModule() { @@ -1747,7 +1747,7 @@ void PyModuleHelper::importModule() // import Python GUI module and put it in attribute // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then import a module QString aMod = QString( "%1GUI" ).arg( myModule->name() ); try { @@ -1787,7 +1787,7 @@ void PyModuleHelper::setWorkSpace() // call setWorkSpace() method // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then try to import SalomePyQt module. If it's not possible don't go on. PyObjWrapper aQtModule( PyImport_ImportModule( "SalomePyQt" ) ); @@ -1865,7 +1865,7 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) // then call Python module's initialize() method // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... (the Python module is already imported) // ... finally call Python module's initialize() method @@ -1969,7 +1969,7 @@ void PyModuleHelper::internalActivate( SUIT_Study* study ) } // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // call Python module's activate() method (for the new modules) if ( PyObject_HasAttrString( myPyModule , (char*)"activate" ) ) { @@ -2024,7 +2024,7 @@ void PyModuleHelper::internalCustomize( SUIT_Study* study ) setWorkSpace(); // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL if ( IsCallOldMethods ) { // call Python module's setSettings() method (obsolete) @@ -2166,7 +2166,7 @@ void PyModuleHelper::internalStudyChanged( SUIT_Study* study ) setWorkSpace(); // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // call Python module's activeStudyChanged() method if ( PyObject_HasAttrString( myPyModule, (char*)"activeStudyChanged" ) ) { @@ -2552,7 +2552,7 @@ bool PyModuleHelper::internalIsDraggable( LightApp_DataObject* what ) if ( PyObject_HasAttrString(myPyModule , (char*)"isDraggable") ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDraggable", - (char*)"s", what->entry().toLatin1().constData() ) ); + (char*)"s", what->entry().toLatin1().constData() ) ); if( !res || !PyBool_Check( res )) { PyErr_Print(); draggable = false; @@ -2584,7 +2584,7 @@ bool PyModuleHelper::internalIsDropAccepted( LightApp_DataObject* where ) if ( PyObject_HasAttrString(myPyModule , (char*)"isDropAccepted") ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDropAccepted", - (char*)"s", where->entry().toLatin1().constData() ) ); + (char*)"s", where->entry().toLatin1().constData() ) ); if( !res || !PyBool_Check( res )) { PyErr_Print(); dropAccepted = false; @@ -2606,7 +2606,7 @@ bool PyModuleHelper::internalIsDropAccepted( LightApp_DataObject* where ) \param action current drop action (copy or move) */ void PyModuleHelper::internalDropObjects( const DataObjectList& what, SUIT_DataObject* where, - const int row, Qt::DropAction action ) + const int row, Qt::DropAction action ) { FuncMsg fmsg( "--- PyModuleHelper::internalDropObjects()" ); @@ -2631,10 +2631,10 @@ void PyModuleHelper::internalDropObjects( const DataObjectList& what, SUIT_DataO PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL) ); #endif if ( PyObject_HasAttrString(myPyModule, (char*)"dropObjects") ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii", - sipList.get(), - whereObject->entry().toLatin1().constData(), - row, action ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii", + sipList.get(), + whereObject->entry().toLatin1().constData(), + row, action ) ); if( !res ) { PyErr_Print(); @@ -2663,13 +2663,13 @@ QString PyModuleHelper::internalEngineIOR() const if ( PyObject_HasAttrString( myPyModule , "engineIOR" ) ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"engineIOR", (char*)"" ) ); if ( !res ) { - PyErr_Print(); + PyErr_Print(); } else { - // parse the return value, result chould be string - if ( PyString_Check( res ) ) { - ior = PyString_AsString( res ); - } + // parse the return value, result chould be string + if ( PyString_Check( res ) ) { + ior = PyString_AsString( res ); + } } } } @@ -2688,24 +2688,24 @@ void PyModuleHelper::connectView( SUIT_ViewWindow* view ) // Connect tryCloseView() and deleteView() signals if ( viewMgr ) { connect( viewMgr, SIGNAL( tryCloseView( SUIT_ViewWindow* ) ), - this, SLOT( tryCloseView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + this, SLOT( tryCloseView( SUIT_ViewWindow* ) ), + Qt::UniqueConnection ); connect( viewMgr, SIGNAL( deleteView( SUIT_ViewWindow* ) ), this, SLOT( closeView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } // Connect cloneView() signal of an OCC View if ( view->inherits( "OCCViewer_ViewWindow" ) ) { connect( view, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), this, SLOT( cloneView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } // Connect cloneView() signal of Plot2d View else if ( viewModel && viewModel->inherits( "Plot2d_Viewer" ) ) { connect( viewModel, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), this, SLOT( cloneView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } } diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h index 98f6e8074..b2adf2131 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h @@ -103,7 +103,7 @@ public slots: bool isDraggable( const SUIT_DataObject* ) const; bool isDropAccepted( const SUIT_DataObject* ) const; void dropObjects( const DataObjectList&, SUIT_DataObject*, - const int, Qt::DropAction ); + const int, Qt::DropAction ); QString engineIOR() const; void onObjectBrowserClicked(SUIT_DataObject*, int); @@ -133,7 +133,7 @@ private: bool internalIsDraggable( LightApp_DataObject* ); bool internalIsDropAccepted( LightApp_DataObject* ); void internalDropObjects( const DataObjectList&, SUIT_DataObject*, - const int, Qt::DropAction ); + const int, Qt::DropAction ); QString internalEngineIOR() const; void internalOBClickedPython( const QString&, int ); diff --git a/src/SALOME_SWIG/CMakeLists.txt b/src/SALOME_SWIG/CMakeLists.txt index a4cb8a294..c8932c133 100755 --- a/src/SALOME_SWIG/CMakeLists.txt +++ b/src/SALOME_SWIG/CMakeLists.txt @@ -92,6 +92,5 @@ INSTALL(TARGETS _libSALOME_Swig DESTINATION ${SALOME_INSTALL_PYTHON}) SALOME_INSTALL_SCRIPTS("${_swig_SCRIPTS}" ${SALOME_INSTALL_PYTHON}) SALOME_INSTALL_SCRIPTS("${_other_SCRIPTS}" ${SALOME_INSTALL_SCRIPT_DATA}) -SALOME_INSTALL_SCRIPTS(SALOMEGUI_shared_modules.py ${SALOME_INSTALL_PYTHON_SHARED}) INSTALL(FILES ${libSALOME_Swig_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS}) diff --git a/src/SALOME_SWIG/SALOMEGUI_shared_modules.py b/src/SALOME_SWIG/SALOMEGUI_shared_modules.py deleted file mode 100755 index 6f51cf61e..000000000 --- a/src/SALOME_SWIG/SALOMEGUI_shared_modules.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: iso-8859-1 -*- -# Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE -# -# Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -# -# This library 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 2.1 of the License, or (at your option) any later version. -# -# This library 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 this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - -""" - -""" - -try: - import SALOME_Session_idl -except: - pass - -from import_hook import register_name -register_name("SalomePyQt") - -# this function is required - -def init_shared_modules(): - """ - This function initializes shared modules that need to be - """ - pass diff --git a/src/SPlot2d/SPlot2d_ViewModel.cxx b/src/SPlot2d/SPlot2d_ViewModel.cxx index c811b9680..4bb3a4c03 100644 --- a/src/SPlot2d/SPlot2d_ViewModel.cxx +++ b/src/SPlot2d/SPlot2d_ViewModel.cxx @@ -400,11 +400,13 @@ SUIT_ViewWindow* SPlot2d_Viewer::createView( SUIT_Desktop* theDesktop ) SLOT: called when action "Legend Clicked" is activated. override "onLegendClicked" method from Plot2d_ViewModel. */ -void SPlot2d_Viewer::onLegendClicked( QwtPlotItem* plotItem ) +void SPlot2d_Viewer::onClicked( const QVariant& itemInfo, int index ) { Plot2d_ViewFrame* aViewFrame = getActiveViewFrame(); if(aViewFrame == NULL) return; + QwtPlotItem* plotItem = aViewFrame->getPlot()->infoToItem( itemInfo ); + bool isAnalytical = false; AnalyticalCurveList curves = aViewFrame->getAnalyticalCurves(); foreach ( Plot2d_AnalyticalCurve* curve, curves ) { diff --git a/src/SPlot2d/SPlot2d_ViewModel.h b/src/SPlot2d/SPlot2d_ViewModel.h index 347fd79e2..141a4e7d0 100644 --- a/src/SPlot2d/SPlot2d_ViewModel.h +++ b/src/SPlot2d/SPlot2d_ViewModel.h @@ -84,7 +84,7 @@ public: Handle(SALOME_InteractiveObject) FindIObject( const char* Entry ); protected slots: - virtual void onLegendClicked( QwtPlotItem* plotItem ); + virtual void onClicked( const QVariant&, int ); signals: void legendSelected( const QString& ); diff --git a/src/STD/STD_Application.cxx b/src/STD/STD_Application.cxx index 8ed218f1d..9539d7ee3 100755 --- a/src/STD/STD_Application.cxx +++ b/src/STD/STD_Application.cxx @@ -390,11 +390,17 @@ void STD_Application::afterCloseDoc() /*!Close document, if it's possible.*/ void STD_Application::onCloseDoc( bool ask ) +{ + closeDoc( ask ); +} + +/*!Close document, if it's possible.*/ +bool STD_Application::closeDoc( bool ask ) { bool closePermanently = true; if ( ask && !isPossibleToClose( closePermanently ) ) - return; + return false; SUIT_Study* study = activeStudy(); @@ -430,6 +436,7 @@ void STD_Application::onCloseDoc( bool ask ) if ( !desktop() ) closeApplication(); + return true; } /*!Check the application on closing. diff --git a/src/STD/STD_Application.h b/src/STD/STD_Application.h index fb443d36a..8e5703b01 100755 --- a/src/STD/STD_Application.h +++ b/src/STD/STD_Application.h @@ -167,6 +167,7 @@ protected: virtual int closeChoice( const QString& ); virtual bool closeAction( const int, bool& ); + virtual bool closeDoc( bool ask = true ); private: ViewManagerList myViewMgrs; diff --git a/src/SUITApp/SUITApp.cxx b/src/SUITApp/SUITApp.cxx index 6d44983e9..9340f4d00 100644 --- a/src/SUITApp/SUITApp.cxx +++ b/src/SUITApp/SUITApp.cxx @@ -277,16 +277,7 @@ int main( int argc, char* argv[] ) int _argc = 1; char* _argv[] = {(char*)""}; SUIT_PYTHON::init_python(_argc,_argv); - - PyEval_RestoreThread( SUIT_PYTHON::_gtstate ); - - if ( !SUIT_PYTHON::salome_shared_modules_module ) // import only once - SUIT_PYTHON::salome_shared_modules_module = PyImport_ImportModule( (char*)"salome_shared_modules" ); - if ( !SUIT_PYTHON::salome_shared_modules_module ) - PyErr_Print(); - - PyEval_ReleaseThread( SUIT_PYTHON::_gtstate ); - + PyEval_ReleaseLock(); #endif SUIT_Application* theApp = aSession->startApplication( argList.first() ); diff --git a/src/SUITApp/SUITApp_init_python.cxx b/src/SUITApp/SUITApp_init_python.cxx index 1f2be4ff0..1b51a036b 100644 --- a/src/SUITApp/SUITApp_init_python.cxx +++ b/src/SUITApp/SUITApp_init_python.cxx @@ -22,10 +22,6 @@ // #include "SUITApp_init_python.hxx" - -PyThreadState* SUIT_PYTHON::_gtstate = NULL; -PyObject *SUIT_PYTHON::salome_shared_modules_module = NULL; -PyInterpreterState* SUIT_PYTHON::_interp = NULL; bool SUIT_PYTHON::initialized = false; void SUIT_PYTHON::init_python(int argc, char **argv) @@ -37,9 +33,6 @@ void SUIT_PYTHON::init_python(int argc, char **argv) Py_SetProgramName(argv[0]); Py_Initialize(); // Initialize the interpreter PySys_SetArgv(argc, argv); - SUIT_PYTHON::_interp = PyThreadState_Get()->interp; - PyEval_InitThreads(); // Create (and acquire) the interpreter lock - SUIT_PYTHON::_gtstate = PyEval_SaveThread(); // Release global thread state - SUIT_PYTHON::initialized = true; + PyEval_InitThreads(); // Create (and acquire) the interpreter lock - can be called many times } diff --git a/src/SUITApp/SUITApp_init_python.hxx b/src/SUITApp/SUITApp_init_python.hxx index 0ae8d1c7a..3d4e22318 100644 --- a/src/SUITApp/SUITApp_init_python.hxx +++ b/src/SUITApp/SUITApp_init_python.hxx @@ -48,12 +48,8 @@ struct SUITAPP_EXPORT SUIT_PYTHON { - static PyThreadState *_gtstate; - static PyInterpreterState *_interp; - static PyObject *salome_shared_modules_module; static bool initialized; static void init_python(int argc, char **argv); - }; #endif // _SUITAPP_INIT_PYTHON_ diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index 3291a9a08..2dfa32ca9 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -376,12 +376,13 @@ void SalomeApp_Application::createActions() #ifndef DISABLE_PYCONSOLE #ifndef DISABLE_SALOMEOBJECT // import Python module that manages SALOME plugins - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager"); - PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str()); - if ( !res ) - PyErr_Print(); - PyGILState_Release(gstate); + { + PyLockWrapper lck; // acquire GIL + PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager"); + PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str()); + if ( !res ) + PyErr_Print(); + } // end of SALOME plugins loading #endif #endif @@ -498,6 +499,10 @@ void SalomeApp_Application::onNewWithScript() /*!SLOT. Load document with \a aName.*/ bool SalomeApp_Application::onLoadDoc( const QString& aName ) { +#ifdef SINGLE_DESKTOP + if ( !LightApp_Application::closeDoc() ) + return false; +#endif bool res = true; if ( !activeStudy() ) { // if no study - load in current desktop diff --git a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx index eb9b2c957..336ecad71 100644 --- a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx @@ -440,7 +440,7 @@ SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( cons #ifndef DISABLE_PYCONSOLE PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = pyConsole->getInterp(); - PyLockWrapper aLock = pyInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL std::string command; command = "import salome_notebook ; "; command += "salome_notebook.notebook.setAsReal(\""; diff --git a/src/SalomeApp/SalomeApp_ExceptionHandler.cxx b/src/SalomeApp/SalomeApp_ExceptionHandler.cxx index d068f29c3..d23eb4b04 100644 --- a/src/SalomeApp/SalomeApp_ExceptionHandler.cxx +++ b/src/SalomeApp/SalomeApp_ExceptionHandler.cxx @@ -115,13 +115,12 @@ extern "C" SALOMEAPP_EXPORT SUIT_ExceptionHandler* getExceptionHandler() // We disable FPE signal as it was in earlier versions of SALOME. It is enabled // only in debug mode if the environment variable DISABLE_FPE is not set to 1. bool raiseFPE; -#if defined(_DEBUG_) | defined(_DEBUG) //the Last for WIN32 default settings - raiseFPE = true; - char* envDisableFPE = getenv("DISABLE_FPE"); - if (envDisableFPE && atoi(envDisableFPE)) - raiseFPE = false; -#else raiseFPE = false; + +#if defined(_DEBUG_) | defined(_DEBUG) //the Last for WIN32 default settings + char* envEnableFPE = getenv("ENABLE_FPE"); + if (envEnableFPE && atoi(envEnableFPE)) + raiseFPE = true; #endif return new SalomeApp_ExceptionHandler( raiseFPE ); diff --git a/src/SalomeApp/SalomeApp_IntSpinBox.cxx b/src/SalomeApp/SalomeApp_IntSpinBox.cxx index 4460cd446..1e57bd3fa 100644 --- a/src/SalomeApp/SalomeApp_IntSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_IntSpinBox.cxx @@ -388,7 +388,7 @@ SalomeApp_IntSpinBox::SearchState SalomeApp_IntSpinBox::findVariable( const QStr #ifndef DISABLE_PYCONSOLE PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = pyConsole->getInterp(); - PyLockWrapper aLock = pyInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL std::string command; command = "import salome_notebook ; "; command += "salome_notebook.notebook.setAsInteger(\""; diff --git a/src/SalomeApp/SalomeApp_NoteBook.cxx b/src/SalomeApp/SalomeApp_NoteBook.cxx index 7f4807f8d..45d8dea5b 100644 --- a/src/SalomeApp/SalomeApp_NoteBook.cxx +++ b/src/SalomeApp/SalomeApp_NoteBook.cxx @@ -286,7 +286,7 @@ bool NoteBook_TableRow::IsValidStringValue(const QString theValue) SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ); PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = pyConsole->getInterp(); - PyLockWrapper aLock = pyInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL std::string command = "import salome_notebook ; "; command += "salome_notebook.checkThisNoteBook("; for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ ) { @@ -460,7 +460,7 @@ bool NoteBook_Table::IsValid() const SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ); PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = pyConsole->getInterp(); - PyLockWrapper aLock = pyInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL std::string command = "import salome_notebook ; "; command += "salome_notebook.checkThisNoteBook("; for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ ) diff --git a/src/SalomeApp/SalomeApp_PyInterp.cxx b/src/SalomeApp/SalomeApp_PyInterp.cxx index 8eea465fa..42c8a0a0a 100755 --- a/src/SalomeApp/SalomeApp_PyInterp.cxx +++ b/src/SalomeApp/SalomeApp_PyInterp.cxx @@ -48,70 +48,14 @@ SalomeApp_PyInterp::~SalomeApp_PyInterp() { } -/*!\class SalomeApp_PyInterp - * EDF-CCAR - * When SALOME uses multi Python interpreter feature, - * Every study has its own interpreter and thread state (_tstate = Py_NewInterpreter()) - * This is fine because every study has its own modules (sys.modules) stdout and stderr - * BUT some Python modules must be imported only once. In multi interpreter context Python - * modules (*.py) are imported several times. - * The pyqt module must be imported only once because it registers classes in a C module. - * It's quite the same with omniorb modules (internals and generated with omniidl) - * This problem is handled with "shared modules" defined in salome_shared_modules.py - * These "shared modules" are imported only once and only copied in all the other interpreters - * BUT it's not the only problem. Every interpreter has its own __builtin__ module. That's fine - * but if we have copied some modules and imported others problems may arise with operations that - * are not allowed in restricted execution environment. So we must impose that all interpreters - * have identical __builtin__ module. - * That's all, for the moment ... - */ - - -bool SalomeApp_PyInterp::initContext() -{ - /*! - * The GIL is assumed to be held - * It is the caller responsability caller to acquire the GIL - * It will still be held on initContext output - */ - if ( !PyConsole_Interp::initContext() ) - return false; - - // Import special module to change the import mechanism - PyObjWrapper m1( PyImport_ImportModule( "import_hook" ) ); - if ( !m1 ) - { - MESSAGE( "initContext: problem with import_hook import" ); - PyErr_Print(); - ASSERT( 0 ); - return false; - } - - // Call init_shared_modules to initialize the shared import mechanism for modules - //that must not be imported twice - PyObjWrapper m2( PyObject_CallMethod( m1, (char*)"init_shared_modules", (char*)"O", KERNEL_PYTHON::salome_shared_modules_module ) ); - if ( !m2 ) - { - MESSAGE( "initContext: problem with init_shared_modules call" ); - PyErr_Print(); - ASSERT( 0 ); - return false; - } - - return true; -} - /*! - Do nothing - The initialization has been done in main + Do nothing (we could rely on the test done in the implementation of this method in the super + class PyInterp_Interp, but in this context we are sure the initialization has been done in main() + of SALOME_Session_Server) */ void SalomeApp_PyInterp::initPython() { - MESSAGE("SalomeApp_PyInterp::initPython"); - ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main - SCRUTE(KERNEL_PYTHON::_gtstate); - _gtstate=KERNEL_PYTHON::_gtstate; - _interp=KERNEL_PYTHON::_interp; + MESSAGE("SalomeApp_PyInterp::initPython - does nothing"); } /*! diff --git a/src/SalomeApp/SalomeApp_PyInterp.h b/src/SalomeApp/SalomeApp_PyInterp.h index dd918a150..d2cfa0f0a 100755 --- a/src/SalomeApp/SalomeApp_PyInterp.h +++ b/src/SalomeApp/SalomeApp_PyInterp.h @@ -38,7 +38,6 @@ public: virtual void initPython(); protected: - virtual bool initContext(); virtual int beforeRun(); private: diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx index 8d06a4499..3f78ea2a0 100755 --- a/src/Session/SALOME_Session_Server.cxx +++ b/src/Session/SALOME_Session_Server.cxx @@ -94,8 +94,6 @@ * - get session state */ -PyObject* salome_shared_modules_module = 0; - void MessageOutput( QtMsgType type, const char* msg ) { switch ( type ) @@ -234,32 +232,32 @@ protected: QString fname = QFileInfo( _fname ).fileName(); if( exp.exactMatch( fname ) ) { - QStringList vers = exp.cap( 1 ).split( ".", QString::SkipEmptyParts ); - int major=0, minor=0; - int release = 0, dev1 = 0, dev2 = 0; - if ( vers.count() > 0 ) major = vers[0].toInt(); - if ( vers.count() > 1 ) minor = vers[1].toInt(); - if ( vers.count() > 2 ) { - if ( vers_exp.indexIn( vers[2] ) != -1 ) { - release = vers_exp.cap( 1 ).toInt(); - QString tag = vers_exp.cap( 2 ).toLower(); - if ( !tag.isEmpty() ) { - if ( tag == "rc" ) // release candidate - dev1 = 49; // 'rc'=49 - else // a, b, c, ... - dev1 = (int)( tag[ 0 ].toLatin1() ) - (int)( QChar('a').toLatin1() ) + 1; // 'a'=1, 'b'=2, ..., 'z'=26 - } - if ( !vers_exp.cap( 3 ).isEmpty() ) - dev2 = vers_exp.cap( 3 ).toInt(); - } - } - - int dev = dev1*100+dev2; - id = major; - id*=100; id+=minor; - id*=100; id+=release; - id*=10000; - if ( dev > 0 ) id-=dev; + QStringList vers = exp.cap( 1 ).split( ".", QString::SkipEmptyParts ); + int major=0, minor=0; + int release = 0, dev1 = 0, dev2 = 0; + if ( vers.count() > 0 ) major = vers[0].toInt(); + if ( vers.count() > 1 ) minor = vers[1].toInt(); + if ( vers.count() > 2 ) { + if ( vers_exp.indexIn( vers[2] ) != -1 ) { + release = vers_exp.cap( 1 ).toInt(); + QString tag = vers_exp.cap( 2 ).toLower(); + if ( !tag.isEmpty() ) { + if ( tag == "rc" ) // release candidate + dev1 = 49; // 'rc'=49 + else // a, b, c, ... + dev1 = (int)( tag[ 0 ].toLatin1() ) - (int)( QChar('a').toLatin1() ) + 1; // 'a'=1, 'b'=2, ..., 'z'=26 + } + if ( !vers_exp.cap( 3 ).isEmpty() ) + dev2 = vers_exp.cap( 3 ).toInt(); + } + } + + int dev = dev1*100+dev2; + id = major; + id*=100; id+=minor; + id*=100; id+=release; + id*=10000; + if ( dev > 0 ) id-=dev; } } return id; @@ -475,14 +473,6 @@ int main( int argc, char **argv ) int _argc = 1; char* _argv[] = {(char*)""}; KERNEL_PYTHON::init_python( _argc,_argv ); - PyEval_RestoreThread( KERNEL_PYTHON::_gtstate ); - if ( !KERNEL_PYTHON::salome_shared_modules_module ) // import only once - KERNEL_PYTHON::salome_shared_modules_module = PyImport_ImportModule( "salome_shared_modules" ); - if ( !KERNEL_PYTHON::salome_shared_modules_module ) { - INFOS( "salome_shared_modules_module == NULL" ); - PyErr_Print(); - } - PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate ); // ...create ORB, get RootPOA object, NamingService, etc. ORB_INIT &init = *SINGLETON_::Instance(); @@ -631,28 +621,28 @@ int main( int argc, char **argv ) if ( splash ) splash->finish( aGUIApp->desktop() ); - + result = _qappl.exec(); splash = 0; - + if ( result == SUIT_Session::NORMAL ) { - // desktop is explicitly closed by user from GUI - // exit flags says if it's necessary to shutdown all servers - // all session server only + // desktop is explicitly closed by user from GUI + // exit flags says if it's necessary to shutdown all servers + // all session server only shutdownAll = aGUISession->exitFlags(); - } - else { - // desktop might be closed from: - // - StopSesion() /temporarily/ or - // - Shutdown() /permanently/ - stat = session->GetStatSession(); - shutdownSession = stat.state == SALOME::shutdown; - } - if ( shutdownAll || shutdownSession ) { - _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later - break; - } + } + else { + // desktop might be closed from: + // - StopSesion() /temporarily/ or + // - Shutdown() /permanently/ + stat = session->GetStatSession(); + shutdownSession = stat.state == SALOME::shutdown; + } + if ( shutdownAll || shutdownSession ) { + _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later + break; + } } delete aGUISession;