From 4976d6e4367b5f2008fe1c0fe9051e6556f0d5b8 Mon Sep 17 00:00:00 2001 From: vtn Date: Tue, 19 Mar 2013 10:42:22 +0000 Subject: [PATCH] Added support of Plot2d curves to SalomePyQt python module. --- src/SALOME_PYQT/SalomePyQt/Makefile.am | 5 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx | 424 +++++++++++++++++++--- src/SALOME_PYQT/SalomePyQt/SalomePyQt.h | 28 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip | 68 +++- 4 files changed, 468 insertions(+), 57 deletions(-) diff --git a/src/SALOME_PYQT/SalomePyQt/Makefile.am b/src/SALOME_PYQT/SalomePyQt/Makefile.am index e08d35457..ee9da42f0 100644 --- a/src/SALOME_PYQT/SalomePyQt/Makefile.am +++ b/src/SALOME_PYQT/SalomePyQt/Makefile.am @@ -30,10 +30,11 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am SIP_SRC = sipAPISalomePyQt.h \ sipSalomePyQtSalomePyQt.cc \ sipSalomePyQtSALOME_Selection.cc \ - sipSalomePyQtQtxAction.cc \ + sipSalomePyQtQtxAction.cc \ sipSalomePyQtQtxActionGroup.cc \ sipSalomePyQtQtxActionSet.cc \ - sipSalomePyQtcmodule.cc + sipSalomePyQtcmodule.cc \ + sipSalomePyQtPlot2d_Curve.cc # Sip definition file SIP_FILES = SalomePyQt.sip diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx index 899508ad3..6efe3b600 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -63,6 +63,7 @@ #include #include #include +#include /*! \brief Get the currently active application. @@ -1476,51 +1477,6 @@ void SalomePyQt::helpContext( const QString& source, const QString& context ) ProcessVoidEvent( new TEvent( source, context ) ); } -/*! - \fn bool SalomePyQt::dumpView( const QString& filename ); - \brief Dump the contents of the currently active view window - to the image file in the specified format. - - For the current moment JPEG, PNG and BMP images formats are supported. - The image format is defined automatically by the file name extension. - By default, BMP format is used. - - \param filename image file name - \return operation status (\c true on success) -*/ - -class TDumpViewEvent: public SALOME_Event -{ -public: - typedef bool TResult; - TResult myResult; - QString myFileName; - TDumpViewEvent( const QString& filename ) - : myResult ( false ), myFileName( filename ) {} - virtual void Execute() - { - if ( LightApp_Application* anApp = getApplication() ) { - SUIT_ViewManager* vm = anApp->activeViewManager(); - if ( vm ) { - SUIT_ViewWindow* vw = vm->getActiveView(); - if ( vw ) { - QImage im = vw->dumpView(); - if ( !im.isNull() && !myFileName.isEmpty() ) { - QString fmt = SUIT_Tools::extension( myFileName ).toUpper(); - if ( fmt.isEmpty() ) fmt = QString( "BMP" ); // default format - if ( fmt == "JPG" ) fmt = "JPEG"; - myResult = im.save( myFileName, fmt.toLatin1() ); - } - } - } - } - } -}; -bool SalomePyQt::dumpView( const QString& filename ) -{ - return ProcessEvent( new TDumpViewEvent( filename ) ); -} - /*! \fn int SalomePyQt::defaultMenuGroup(); \brief Get detault menu group identifier which can be used when @@ -2249,6 +2205,70 @@ static SUIT_ViewWindow* getWnd( const int id ) return resWnd; } +/*! + \fn bool SalomePyQt::dumpView( const QString& filename, const int id = 0 ); + \brief Dump the contents of the id view window. If id is 0 then current active view is processed. + to the image file in the specified format. + + For the current moment JPEG, PNG and BMP images formats are supported. + The image format is defined automatically by the file name extension. + By default, BMP format is used. + + \param filename image file name + \return operation status (\c true on success) +*/ + +class TDumpViewEvent: public SALOME_Event +{ +public: + typedef bool TResult; + TResult myResult; + QString myFileName; + int myWndId; + TDumpViewEvent( const QString& filename, const int id ) + : myResult ( false ), myFileName( filename ), myWndId(id) {} + virtual void Execute() + { + SUIT_ViewWindow* wnd = NULL; + if(myWndId == 0) + { + if ( LightApp_Application* anApp = getApplication() ) { + SUIT_ViewManager* vm = anApp->activeViewManager(); + if ( vm ) + wnd = vm->getActiveView(); + } + myWndId = wnd->getId(); + } + else + { + wnd = dynamic_cast(getWnd( myWndId )); + } + if ( wnd ) { + QString fmt = SUIT_Tools::extension( myFileName ).toUpper(); + if(fmt == "PS" || fmt == "EPS" || fmt == "PDF") { + Plot2d_ViewWindow* wnd2D = dynamic_cast(wnd); + if(wnd2D) { + myResult = wnd2D->getViewFrame()->print(myFileName, fmt); + } else { + myResult = false; + } + } else { + QImage im = wnd->dumpView(); + if ( !im.isNull() && !myFileName.isEmpty() ) { + if ( fmt.isEmpty() ) fmt = QString( "BMP" ); // default format + if ( fmt == "JPG" ) fmt = "JPEG"; + myResult = im.save( myFileName, fmt.toLatin1() ); + } + } + } + } +}; +bool SalomePyQt::dumpView( const QString& filename, const int id ) +{ + return ProcessEvent( new TDumpViewEvent( filename, id ) ); +} + + /*! \fn QList SalomePyQt::getViews() \brief Get list of integer identifiers of all the currently opened views @@ -2484,9 +2504,12 @@ bool SalomePyQt::activateView( const int id ) } /*! - \fn int SalomePyQt::createView( const QString& type ) + \fn int SalomePyQt::createView( const QString& type, bool visible = true, const int width = 0, const int height = 0 ) \brief Create new view and activate it \param type viewer type + \param visible + \param width + \param height \return integer identifier of created view (or -1 if view could not be created) */ @@ -2496,9 +2519,15 @@ public: typedef int TResult; TResult myResult; QString myType; - TCreateView( const QString& theType ) + bool myVisible; + int myWidth; + int myHeight; + TCreateView( const QString& theType, bool visible, const int width, const int height ) : myResult( -1 ), - myType( theType ) {} + myType( theType ), + myVisible(visible), + myWidth(width), + myHeight(height) {} virtual void Execute() { LightApp_Application* app = getApplication(); @@ -2508,15 +2537,29 @@ public: if ( viewMgr ) { SUIT_ViewWindow* wnd = viewMgr->getActiveView(); - if ( wnd ) + if ( wnd ) { + wnd->setShown(myVisible); + if(!myVisible && myWidth == 0 && myHeight == 0) { + myWidth = 1024; + myHeight = 768; + } + if(myWidth > 0 && myHeight > 0) { + Plot2d_ViewWindow* wnd2D = dynamic_cast(wnd); + if(wnd2D) { + wnd2D->getViewFrame()->setGeometry(0,0,myWidth,myHeight); + } else { + wnd->setGeometry(0,0,myWidth,myHeight); + } + } myResult = wnd->getId(); + } } } } }; -int SalomePyQt::createView( const QString& type ) +int SalomePyQt::createView( const QString& type, bool visible, const int width, const int height ) { - return ProcessEvent( new TCreateView( type ) ); + return ProcessEvent( new TCreateView( type, visible, width, height ) ); } /*! @@ -2645,6 +2688,31 @@ int SalomePyQt::cloneView( const int id ) return ProcessEvent( new TCloneView( id ) ); } +/*! + \fn bool SalomePyQt::setViewVisible( const int id, const bool visible ) + \brief Set view visibility. + \param id window identifier + \param visible new visiblity +*/ + +void SalomePyQt::setViewVisible( const int id, const bool visible ) +{ + class TEvent: public SALOME_Event + { + int myWndId; + bool myVisible; + public: + TEvent( const int id, const bool visible ) + : myWndId( id ), myVisible( visible ) {} + virtual void Execute() + { + SUIT_ViewWindow* wnd = getWnd( myWndId ); + if ( wnd ) wnd->setVisible( myVisible ); + } + }; + ProcessVoidEvent( new TEvent( id, visible ) ); +} + /*! \fn bool SalomePyQt::isViewVisible( const int id ) \brief Check whether view is visible ( i.e. it is on the top of the views stack) @@ -3249,3 +3317,257 @@ QStringList SalomePyQt::getChildren(const QString& obj, const bool rec) { return ProcessEvent( new TGetChildrenEvent(obj,rec) ); } + + +/*! + \fn void SalomePyQt::displayCurve( const int id, Plot2d_Curve* theCurve ) + \brief Display theCurve in view + \param id window identifier + \param theCurve curve to display +*/ + +class TDisplayCurve: public SALOME_Event +{ +public: + int myWndId; + Plot2d_Curve* myCurve; + TDisplayCurve(const int id, Plot2d_Curve* theCurve) : myWndId(id), myCurve(theCurve) {} + virtual void Execute() { + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + wnd->getViewFrame()->displayCurve(myCurve); + } + } +}; +void SalomePyQt::displayCurve(const int id, Plot2d_Curve* theCurve) +{ + ProcessVoidEvent( new TDisplayCurve(id, theCurve) ); +} + +/*! + \fn void SalomePyQt::eraseCurve( const int id, Plot2d_Curve* theCurve ) + \brief Erase theCurve in view + \param id window identifier + \param theCurve curve to erase +*/ + +class TEraseCurve: public SALOME_Event +{ +public: + int myWndId; + Plot2d_Curve* myCurve; + TEraseCurve(const int id, Plot2d_Curve* theCurve) : myWndId(id), myCurve(theCurve) {} + virtual void Execute() { + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + wnd->getViewFrame()->eraseCurve(myCurve); + } + } +}; +void SalomePyQt::eraseCurve(const int id, Plot2d_Curve* theCurve) +{ + ProcessVoidEvent( new TEraseCurve(id, theCurve) ); +} + +/*! + \fn void SalomePyQt::deleteCurve( Plot2d_Curve* theCurve ) + \brief Delete theCurve from all views + \param theCurve curve to delete +*/ + +class TDeleteCurve: public SALOME_Event +{ +public: + Plot2d_Curve* myCurve; + TDeleteCurve(Plot2d_Curve* theCurve) : myCurve(theCurve) {} + virtual void Execute() { + LightApp_Application* app = getApplication(); + if ( app ) + { + STD_TabDesktop* tabDesk = dynamic_cast( app->desktop() ); + if ( tabDesk ) + { + QList wndlist = tabDesk->windows(); + SUIT_ViewWindow* wnd; + foreach ( wnd, wndlist ) + { + Plot2d_ViewWindow* aP2d = dynamic_cast(wnd); + if(aP2d) + { + aP2d->getViewFrame()->eraseObject(myCurve); + } + } + } + } + } +}; +void SalomePyQt::eraseCurve(Plot2d_Curve * theCurve) +{ + ProcessVoidEvent( new TDeleteCurve(theCurve) ); +} + +/*! + \brief updateCurves (repaint) curves in view window. +*/ +void SalomePyQt::updateCurves(const int id) +{ + class TEvent: public SALOME_Event + { + public: + int myWndId; + TEvent( const int id ) : myWndId( id ) {} + virtual void Execute() + { + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + wnd->getViewFrame()->DisplayAll(); + } + } + }; + ProcessVoidEvent( new TEvent(id) ); +} + +/*! + \fn void SalomePyQt::setPlot2dTitle( const int id, const QString& title, ObjectType type = MainTitle, bool show = true ) + \brief Set title of corresponding type + \param id window identifier + \param title + \param type is type of title + \param show +*/ + +class TSetPlot2dTitle: public SALOME_Event +{ +public: + int myWndId; + Plot2d_Curve* myCurve; + QString myTitle; + ObjectType myType; + bool myShow; + TSetPlot2dTitle(const int id, const QString& title, ObjectType type, bool show) : + myWndId(id), + myTitle(title), + myType(type), + myShow(show) {} + virtual void Execute() { + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + wnd->getViewFrame()->setTitle(myShow, myTitle, (Plot2d_ViewFrame::ObjectType)myType, false); + } + } +}; +void SalomePyQt::setPlot2dTitle(const int id, const QString& title, ObjectType type, bool show) +{ + ProcessVoidEvent( new TSetPlot2dTitle(id, title, type, show) ); +} + +/*! + \fn QList SalomePyQt::getPlot2dFitRangeByCurves( const int id ) + \brief Get list of Plot2d view ranges + \param id window identifier + \return list of view ranges (XMin, XMax, YMin, YMax) +*/ + +class TFitRangeByCurves: public SALOME_Event +{ +public: + typedef QList TResult; + TResult myResult; + int myWndId; + TFitRangeByCurves( const int id ) + : myWndId( id ) {} + virtual void Execute() + { + myResult.clear(); + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + double XMin, XMax, YMin, YMax, Y2Min, Y2Max; + wnd->getViewFrame()->getFitRangeByCurves(XMin, XMax, YMin, YMax, Y2Min, Y2Max); + myResult.append(XMin); + myResult.append(XMax); + myResult.append(YMin); + myResult.append(YMax); + } + } +}; +QList SalomePyQt::getPlot2dFitRangeByCurves( const int id ) +{ + return ProcessEvent( new TFitRangeByCurves( id ) ); +} + +/*! + \fn QList SalomePyQt::getPlot2dFitRangeCurrent( const int id ) + \brief Get list of current Plot2d view ranges + \param id window identifier + \return list of view ranges (XMin, XMax, YMin, YMax) +*/ + +class TFitRangeCurrent: public SALOME_Event +{ +public: + typedef QList TResult; + TResult myResult; + int myWndId; + TFitRangeCurrent( const int id ) + : myWndId( id ) {} + virtual void Execute() + { + myResult.clear(); + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + double XMin, XMax, YMin, YMax, Y2Min, Y2Max; + wnd->getViewFrame()->getFitRanges(XMin, XMax, YMin, YMax, Y2Min, Y2Max); + myResult.append(XMin); + myResult.append(XMax); + myResult.append(YMin); + myResult.append(YMax); + } + } +}; +QList SalomePyQt::getPlot2dFitRangeCurrent( const int id ) +{ + return ProcessEvent( new TFitRangeCurrent( id ) ); +} + +/*! + \fn void SalomePyQt::setPlot2dFitRange( const int id, const double XMin, const double XMax, const double YMin, const double YMax ) + \brief Set range of Plot2d view + \param id window identifier + \param XMin + \param XMax + \param YMin + \param YMax +*/ + +class TPlot2dFitRange: public SALOME_Event +{ +public: + int myWndId; + double myXMin; + double myXMax; + double myYMin; + double myYMax; + TPlot2dFitRange(const int id, const double XMin, const double XMax, const double YMin, const double YMax) : + myWndId(id), + myXMin(XMin), + myXMax(XMax), + myYMin(YMin), + myYMax(YMax) {} + virtual void Execute() { + Plot2d_ViewWindow* wnd = dynamic_cast(getWnd( myWndId )); + if ( wnd ) + { + wnd->getViewFrame()->fitData(0, myXMin, myXMax, myYMin, myYMax); + } + } +}; +void SalomePyQt::setPlot2dFitRange(const int id, const double XMin, const double XMax, const double YMin, const double YMax) +{ + ProcessVoidEvent( new TPlot2dFitRange(id, XMin, XMax, YMin, YMax) ); +} diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h index 4f0decebc..98eb7f9fa 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h @@ -34,6 +34,7 @@ #include #include +#include class LightApp_SelectionMgr; class LightApp_Application; @@ -43,6 +44,7 @@ class QWidget; class QAction; class QTreeView; class QtxActionGroup; +class Plot2d_Curve; class SALOME_Selection : public QObject { @@ -116,6 +118,18 @@ enum Action { SplitAt = 2 //!< the view area is splitted in such a way, that specified view and all views which follow it, are moved to the new area }; +//! Type of titles in Plot3d View +enum ObjectType +{ + MainTitle = Plot2d_ViewFrame::MainTitle, + XTitle = Plot2d_ViewFrame::XTitle, + YTitle = Plot2d_ViewFrame::YTitle, + Y2Title = Plot2d_ViewFrame::Y2Title, + XAxis = Plot2d_ViewFrame::XAxis, + YAxis = Plot2d_ViewFrame::YAxis, + Y2Axis = Plot2d_ViewFrame::Y2Axis +}; + class SalomePyQt { public: @@ -166,7 +180,7 @@ public: static void helpContext( const QString&, const QString& ); - static bool dumpView( const QString& ); + static bool dumpView( const QString&, const int = 0 ); static int defaultMenuGroup(); @@ -245,10 +259,11 @@ public: static QString getViewTitle( const int ); static QList findViews( const QString& ); static bool activateView( const int ); - static int createView( const QString& ); + static int createView( const QString&, bool visible = true, const int width = 0, const int height = 0 ); static int createView( const QString&, QWidget* ); static bool closeView( const int ); static int cloneView( const int ); + static void setViewVisible( const int id, bool visible = true ); static bool isViewVisible( const int ); static void setViewClosable( const int, const bool ); static bool isViewClosable( const int ); @@ -257,6 +272,15 @@ public: static bool splitView( const int, const Orientation, const Action ); static bool moveView( const int, const int, const bool ); static QList neighbourViews( const int ); + + static void displayCurve(const int, Plot2d_Curve*); + static void eraseCurve(const int, Plot2d_Curve*); + static void eraseCurve(Plot2d_Curve*); + static void updateCurves( const int ); + static void setPlot2dTitle(const int, const QString&, ObjectType = MainTitle, bool = true); + static QList getPlot2dFitRangeByCurves(const int); + static QList getPlot2dFitRangeCurrent(const int); + static void setPlot2dFitRange(const int, const double XMin, const double XMax, const double YMin, const double YMax); }; #endif // SALOME_PYQT_H diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip index 2eb35bd84..464835c19 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip @@ -33,6 +33,7 @@ #include #include #include +#include %End class SALOME_Selection : QObject @@ -196,6 +197,59 @@ private: QtxActionGroup( const QtxActionGroup& ); }; +enum ObjectType +{ + MainTitle, + XTitle, + YTitle, + Y2Title, + XAxis, + YAxis, + Y2Axis +}; + +class Plot2d_Curve +{ +%TypeHeaderCode +#include +%End + +%ConvertToSubClassCode + if ( dynamic_cast( sipCpp ) ) + sipClass = sipClass_Plot2d_Curve; + else + sipClass = NULL; +%End + +public: + Plot2d_Curve(); + virtual ~Plot2d_Curve(); + void setName( const QString& ); + void addPoint( double, double ); + void addPoints(SIP_PYLIST X, SIP_PYLIST Y); +%MethodCode + int nx = PyList_Size(a0); + int ny = PyList_Size(a1); + + if( nx != ny ) { + PyErr_Format(PyExc_TypeError,"The dimention of x and y should be the same. It is %d and %d currently.", nx, ny); + } + + int i; + PyObject *pX, *pY; + + for (i=0; iaddPoint(aX, aY); + } +%End +}; + class SalomePyQt { %TypeHeaderCode @@ -249,7 +303,7 @@ public: static QIcon loadIcon( const QString&, const QString& ) /ReleaseGIL/ ; static void helpContext( const QString&, const QString& ) /ReleaseGIL/ ; - static bool dumpView( const QString& ) /ReleaseGIL/ ; + static bool dumpView( const QString&, const int = 0 ) /ReleaseGIL/ ; static int defaultMenuGroup() /ReleaseGIL/ ; @@ -328,10 +382,11 @@ public: static QString getViewTitle( const int ) /ReleaseGIL/ ; static QList findViews( const QString& ) /ReleaseGIL/ ; static bool activateView( const int ) /ReleaseGIL/ ; - static int createView( const QString& ) /ReleaseGIL/ ; + static int createView( const QString&, bool visible = true, const int width = 0, const int height = 0 ) /ReleaseGIL/ ; static int createView( const QString&, QWidget* ) /ReleaseGIL/ ; static bool closeView( const int ) /ReleaseGIL/ ; static int cloneView( const int ) /ReleaseGIL/ ; + static void setViewVisible( const int id, bool visible = true ) /ReleaseGIL/ ; static bool isViewVisible( const int id ) /ReleaseGIL/ ; static void setViewClosable( const int id, const bool ) /ReleaseGIL/ ; static bool isViewClosable( const int id ) /ReleaseGIL/ ; @@ -340,4 +395,13 @@ public: static bool splitView( const int, Orientation, Action ) /ReleaseGIL/ ; static bool moveView( const int, const int, const bool ) /ReleaseGIL/ ; static QList neighbourViews( const int ) /ReleaseGIL/ ; + + static void displayCurve(const int, Plot2d_Curve*) /ReleaseGIL/ ; + static void eraseCurve(const int, Plot2d_Curve*) /ReleaseGIL/ ; + static void eraseCurve(Plot2d_Curve*) /ReleaseGIL/ ; + static void updateCurves( const int ) /ReleaseGIL/ ; + static void setPlot2dTitle(const int, const QString&, ObjectType = MainTitle, bool = true) /ReleaseGIL/ ; + static QList getPlot2dFitRangeByCurves(const int) /ReleaseGIL/ ; + static QList getPlot2dFitRangeCurrent(const int) /ReleaseGIL/ ; + static void setPlot2dFitRange(const int, const double XMin, const double XMax, const double YMin, const double YMax ) /ReleaseGIL/ ; }; -- 2.39.2