From: admin Date: Thu, 29 Dec 2005 14:27:27 +0000 (+0000) Subject: This commit was generated by cvs2git to create branch 'BR-D5-38-2003'. X-Git-Tag: TG-D5-38-2003_D2005-29-12~1 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=4cf815fe24038ce0fa67784aa28ca53dbc2957eb;p=modules%2Fgui.git This commit was generated by cvs2git to create branch 'BR-D5-38-2003'. Cherrypick from master 2005-12-29 14:27:26 UTC stv 'Search item referenced list in the component. If not found then list searched in the dictionary.': INSTALL Makefile.in bin/VERSION bin/runLightSalome.sh build_configure doc/salome/GUI_index.html doc/salome/gui/KERNEL/viewers.htm src/CAF/CAF_Study.cxx src/DDS/DDS.h src/DDS/DDS_DicGroup.cxx src/DDS/DDS_DicGroup.h src/DDS/DDS_DicItem.cxx src/DDS/DDS_DicItem.h src/DDS/DDS_Dictionary.cxx src/DDS/DDS_Dictionary.h src/DDS/DDS_KeyWords.cxx src/DDS/DDS_KeyWords.h src/DDS/Makefile.in src/LightApp/LightApp_Application.cxx src/LightApp/LightApp_DataObject.cxx src/LightApp/LightApp_DataObject.h src/LightApp/LightApp_PreferencesDlg.cxx src/LightApp/LightApp_PreferencesDlg.h src/LightApp/LightApp_Selection.cxx src/LightApp/LightApp_Selection.h src/LightApp/LightApp_ShowHideOp.cxx src/LightApp/Makefile.in src/LightApp/resources/LightApp.xml src/LightApp/resources/LightApp_msg_en.po src/Makefile.in src/OCCViewer/Makefile.in src/OCCViewer/OCCViewer_ClippingDlg.cxx src/OCCViewer/OCCViewer_ClippingDlg.h src/OCCViewer/OCCViewer_ViewModel.cxx src/OCCViewer/OCCViewer_ViewWindow.cxx src/OCCViewer/OCCViewer_ViewWindow.h src/OCCViewer/resources/OCCViewer_images.po src/OCCViewer/resources/OCCViewer_msg_en.po src/OCCViewer/resources/view_clipping.png src/OCCViewer/resources/view_clipping_pressed.png src/ObjBrowser/OB_ListItem.cxx src/ObjBrowser/OB_ListItem.h src/ObjBrowser/OB_ListView.cxx src/ObjBrowser/OB_ListView.h src/Plot2d/Plot2d_Curve.cxx src/Plot2d/Plot2d_Curve.h src/Plot2d/Plot2d_SetupViewDlg.cxx src/Plot2d/Plot2d_ViewFrame.cxx src/Plot2d/Plot2d_ViewFrame.h src/Plot2d/Plot2d_ViewWindow.cxx src/Plot2d/Plot2d_ViewWindow.h src/Plot2d/resources/Plot2d_msg_en.po src/PyInterp/PyInterp_Dispatcher.cxx src/PyInterp/PyInterp_base.cxx src/PyInterp/PyInterp_base.h src/PythonConsole/PythonConsole_PyEditor.cxx src/PythonConsole/PythonConsole_PyInterp.cxx src/QDS/Makefile.in src/QDS/QDS.cxx src/QDS/QDS.h src/QDS/QDS_CheckBox.cxx src/QDS/QDS_CheckBox.h src/QDS/QDS_ComboBox.cxx src/QDS/QDS_ComboBox.h src/QDS/QDS_Datum.cxx src/QDS/QDS_Datum.h src/QDS/QDS_LineEdit.cxx src/QDS/QDS_LineEdit.h src/QDS/QDS_SpinBox.cxx src/QDS/QDS_SpinBox.h src/QDS/QDS_SpinBoxDbl.cxx src/QDS/QDS_SpinBoxDbl.h src/QDS/QDS_TextEdit.cxx src/QDS/QDS_TextEdit.h src/QDS/QDS_Validator.cxx src/QDS/QDS_Validator.h src/Qtx/QtxColorScale.cxx src/Qtx/QtxDblSpinBox.cxx src/Qtx/QtxListResourceEdit.cxx src/Qtx/QtxListResourceEdit.h src/Qtx/QtxMainWindow.cxx src/Qtx/QtxMainWindow.h src/Qtx/QtxPopupMgr.cxx src/Qtx/QtxPopupMgr.h src/Qtx/QtxWorkstack.cxx src/Qtx/QtxWorkstack.h src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_PyInterp.cxx src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip src/SALOME_SWIG/salome_test.py src/STD/STD_Application.cxx src/STD/STD_Application.h src/STD/STD_TabDesktop.cxx src/STD/resources/STD_msg_en.po src/SUIT/SUIT_DataOwner.cxx src/SUIT/SUIT_DataOwner.h src/SUIT/SUIT_MessageBox.cxx src/SUIT/SUIT_MessageBox.h src/SUIT/SUIT_SelectionMgr.cxx src/SUIT/SUIT_SelectionMgr.h src/SUIT/SUIT_ViewWindow.cxx src/SUIT/SUIT_ViewWindow.h src/SUITApp/SUITApp.cxx src/SalomeApp/SalomeApp_Application.cxx src/SalomeApp/SalomeApp_Application.h src/SalomeApp/SalomeApp_DataObject.cxx src/SalomeApp/SalomeApp_DataObject.h src/SalomeApp/SalomeApp_Module.cxx src/SalomeApp/SalomeApp_Module.h src/SalomeApp/SalomeApp_PyInterp.cxx src/SalomeApp/resources/SalomeApp_msg_en.po src/Session/SALOME_Session_Server.cxx src/Session/Session_ServerThread.cxx --- diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..dcef3b788 --- /dev/null +++ b/INSTALL @@ -0,0 +1,3 @@ +This is the version 3.1.0 of SALOMEGUI +Compatible with : + - KERNEL 3.1.0 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..989c6a476 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,169 @@ +# -* Makefile *- +# +# Author : Patrick GOLDBRONN (CEA) +# Date : 28/06/2001 +# $Header$ +# + +# source path +top_srcdir=@top_srcdir@ +top_builddir=. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@top_srcdir@/bin:./bin/salome:@top_srcdir@/resources:./bin:@top_srcdir@/idl + + +@COMMENCE@ + +SUBDIRS = idl src doc + +RESOURCES_FILES = \ +back.xpm \ +cascade.png \ +close.png \ +default.png \ +dl_delete.png \ +dl_insert.png \ +dl_moveup.png \ +dl_movedown.png \ +forward.xpm \ +help.png \ +home.xpm \ +new.png \ +open.png \ +print.png \ +reset.png \ +save.png \ +select1.png \ +tile.png \ +Tools_en.xml \ +view_back.png \ +view_bottom.png \ +view_camera_dump.png \ +view_fitall.png \ +view_fitarea.png \ +view_front.png \ +view_glpan.png \ +view_left.png \ +view_pan.png \ +view_reset.png \ +view_right.png \ +view_rotate.png \ +view_top.png \ +view_triedre.png \ +view_zoom.png \ +copy.png \ +paste.png \ +plot2d_dump.png \ +plot2d_fitall.png \ +plot2d_fitarea.png \ +plot2d_legend.png \ +plot2d_linear.png \ +plot2d_linear_y.png \ +plot2d_lines.png \ +plot2d_log.png \ +plot2d_log_y.png \ +plot2d_pan.png \ +plot2d_points.png \ +plot2d_settings.png \ +plot2d_splines.png \ +plot2d_zoom.png \ +uc_add.png \ +uc_current.png \ +uc_del.png \ +uc_new.png \ +uc_clear.png \ +channel.cfg \ + +BIN_SCRIPT= VERSION \ +runLightSalome.csh \ +runLightSalome.sh + +# copy header files in common directory +OWN_CONFIG_H=@OWN_CONFIG_H@ + +ifeq ($(OWN_CONFIG_H),yes) + ifeq ($(HAVE_SSTREAM),yes) + include_list=include/salome/SALOMEconfig.h include/salome/config.h + else + include_list=include/salome/SALOMEconfig.h include/salome/config.h include/salome/sstream + endif +else + ifeq ($(HAVE_SSTREAM),yes) + include_list=include/salome/SALOMEconfig.h + else + include_list=include/salome/SALOMEconfig.h include/salome/sstream + endif +endif + +inc: idl $(include_list) + +include/salome/SALOMEconfig.h: salome_adm/unix/SALOMEconfig.ref + -$(RM) $@ + $(LN_S) ../../$< $@ + +# test if SALOMEconfig.h has changed (contents) +salome_adm/unix/SALOMEconfig.ref: salome_adm/unix/SALOMEconfig.h + @if ! [ -a $@ ]; then \ + cp -p $< $@; \ + fi; \ + if ! cmp $< $@; then \ + cp -p $< $@; \ + fi; \ + +include/salome/config.h: salome_adm/unix/config.h + -$(RM) $@ + $(LN_S) ../../$< $@ + +include/salome/sstream: salome_adm/unix/sstream + -$(RM) $@ + $(LN_S) ../../$< $@ + +depend: depend_idl + +depend_idl: + (cd idl ; $(MAKE) $@) || exit 1 + +# doc is already build : if you want to had documents, go manually to doc and run 'make doc' +#doc: +# (cd doc && $(MAKE) $@) || exit 1 + +# Install make_commence make_conclude ... for other modules +install-make: + ($(INSTALL) -d $(incmakedir) || exit 1); + (sed 's/^prefix=/#prefix=/' $(top_builddir)/adm_local/unix/make_commence > $(incmakedir)/make_commence || exit 1); + + +install-end: +# finish libtool install +# @$(LT) --mode=finish $(libdir) + +install-include: $(include_list) + $(INSTALL) -d $(includedir) + @for f in X $(include_list); do \ + if test $$f != X; then \ + (cp -p $$f $(includedir) || exit 1); \ + fi; \ + done + +# install script in $(bindir) : +install-bin: $(BIN_SCRIPT) + $(INSTALL) -d $(bindir) + $(INSTALL_PROGRAM) $^ $(bindir) + +uninstall: uninstall-idl + +uninstall-idl: + $(RM) $(idldir)/*.idl + +distclean: distclean-other + +distclean-other: + -$(RM) salome_adm/unix/*~ salome_adm/unix/*% salome_adm/unix/*.bak salome_adm/unix/*.new salome_adm/unix/*.old + -$(RM) salome_adm/unix/make_* + -$(RM) salome_adm/unix/depend salome_adm/unix/SALOMEconfig.h salome_adm/unix/config.h + -$(RM) config.cache config.log config.status + +@MODULE@ + +install: install-bin install-include install-make install-end + diff --git a/bin/VERSION b/bin/VERSION new file mode 100755 index 000000000..fe6986e15 --- /dev/null +++ b/bin/VERSION @@ -0,0 +1 @@ +THIS IS SALOME - SALOMEGUI VERSION: 3.1.0 diff --git a/bin/runLightSalome.sh b/bin/runLightSalome.sh new file mode 100755 index 000000000..f99a8125f --- /dev/null +++ b/bin/runLightSalome.sh @@ -0,0 +1,14 @@ +#!/bin/bash -f + +if [ -z "$SUITRoot" ] ; then + export SUITRoot=${GUI_ROOT_DIR}/share/salome +fi +# this variable necessary for loading .ini or .xml file +if [ -z "$LightAppConfig" ] ; then + export LightAppConfig=${GUI_ROOT_DIR}/share/salome/resources +fi +if [ -z "$LightAppResources" ] ; then + export LightAppResources=${GUI_ROOT_DIR}/share/salome/resources +fi + +SUITApp LightApp -style salome $* & diff --git a/build_configure b/build_configure new file mode 100755 index 000000000..ec5cce644 --- /dev/null +++ b/build_configure @@ -0,0 +1,215 @@ +#!/bin/bash + +# +# Tool for updating list of .in file for the SALOME project +# and regenerating configure script +# +# Author : Marc Tajchman - CEA +# Date : 10/10/2002 +# $Header$ +# + +ORIG_DIR=`pwd` +CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` + +######################################################################## +# Test if the KERNEL_ROOT_DIR is set correctly +if test ! -d "${KERNEL_ROOT_DIR}"; then + echo "failed : KERNEL_ROOT_DIR variable is not correct !" + exit +fi + +# Test if the KERNEL_SRC is set correctly + +#if test ! -d "${KERNEL_SRC}"; then +# echo "failed : KERNEL_SRC variable is not correct !" +# exit +#fi +######################################################################## +# find_in - utility function +# +# usage : +# find_in directory filename +# +# Finds files following the *.in pattern, recursively in the +# directory (first argument). +# Results are appended into the file (second argument) +# +# Difference from the standard unix find is that files are tested +# before directories +# + +find_in() +{ + local i + local f=$2 + +# if the first argument is not a directory, returns + + if [ ! -d "$1" ] ; then + return + fi + +# dont look in the CVS directories + + case $1 in + */CVS) return ;; + */adm_local/*) return ;; + *) ;; + esac + +# for each regular file contained in the directory +# test if it's a .in file + + for i in "$1"/* + do + if [ -f "$i" ] ; then + case $i in + *.in) echo " "$i" \\" >> $f;; + *) ;; + esac + fi + done + +# for each subdirectory of the first argument, proceeds recursively + + for i in "$1"/* + do + if [ -d "$i" ] ; then + find_in "$i" "$f" + fi + done +} + + +####################################################################### +# Generate list of .in files (Makefile.in, config.h.in, etc) +# appending it in file configure.in + +cd ${CONF_DIR} +ABS_CONF_DIR=`pwd` + +# +# Common part of the configure.in file +# +chmod u+w configure.in.base +if ! \cp -f configure.in.base configure.in_tmp1 +then + echo + echo "error : can't create files in" ${CONF_DIR} + echo "aborting ..." + chmod u-w configure.in.base + exit +fi +chmod u-w configure.in.base + +if [ -e "${CONF_DIR}/salome_adm" ] ; then + \rm -rf ${CONF_DIR}/salome_adm +fi + +# make a link allowing AC_OUTPUT to find the salome_adm/.../*.in files +echo "" >> configure.in_tmp1 +echo 'ln -fs ${KERNEL_ROOT_DIR}/salome_adm ${ROOT_SRCDIR}/.' >> configure.in_tmp1 + +echo "" >> configure.in_tmp1 +echo "AC_OUTPUT([ \\" >> configure.in_tmp1 + +# +# List of .in files in the adm/unix directory +# These files MUST be on top of AC_OUTPUT list so we +# put them "manually" +# + +echo " ./salome_adm/unix/SALOMEconfig.h \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/F77config.h \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/sstream \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/depend \\" >> configure.in_tmp1 +echo " ./adm_local/unix/make_omniorb \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/envScript \\" >> configure.in_tmp1 +echo " ./adm_local/unix/make_commence \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/make_conclude \\" >> configure.in_tmp1 +echo " ./salome_adm/unix/make_module \\" >> configure.in_tmp1 + +\rm -f configure.in_tmp2 configure.in_tmp3 +touch configure.in_tmp2 +find_in . configure.in_tmp2 +sed -e '/^...salome_adm/d' configure.in_tmp2 > configure.in_tmp3 +sed -e '/^...adm_local.unix.make_omniorb/d' configure.in_tmp3 > configure.in_tmp2 +sed -e '/^...adm_local.unix.make_commence/d' configure.in_tmp2 > configure.in_tmp3 +sed -e '/configure.in/d' configure.in_tmp3 > configure.in_tmp2 +sed -e 's/.in / /' configure.in_tmp2 >> configure.in_tmp1 +#sed '/^.salome_adm/d' configure.in_tmp2 > configure.in_tmp3 +#sed '/configure.in/d' configure.in_tmp3 > configure.in_tmp2 +#sed 's/.in / /' configure.in_tmp2 >> configure.in_tmp1 + +echo "])" >> configure.in_tmp1 + +# delete the link created for AC_OUTPUT +echo "" >> configure.in_tmp1 +#echo 'rm -f ${ROOT_SRCDIR}/salome_adm' >> configure.in_tmp1 +\mv configure.in_tmp1 configure.in_new +\rm -f configure.in_tmp2 configure.in_tmp3 + + +######################################################################## +# Create new (or replace old) configure.in file +# Print a message if the file is write protected +# + +echo +if test ! -f configure.in +then + echo -n "Creating new file 'configure.in' ... " + if \mv configure.in_new configure.in >& /dev/null + then + echo "done" + else + echo "error, check your file permissions" + fi +else + echo -n "Updating 'configure.in' file ... " + if ! \cp configure.in configure.in_old >& /dev/null + then + echo + echo + echo "Can't backup previous configure.in" + echo -n "Continue (you will not be able to revert) - (Y/N) ? " + read R + case "x$R" in + xn*) exit;; + xN*) exit;; + esac + echo + echo -n " " + fi + if \cp configure.in_new configure.in >& /dev/null + then + echo "done" + else + echo + echo "error, can't update previous configure.in" + fi +fi + +######################################################################## +# Use autoconf to rebuild the configure script +# + +if test -f configure +then + echo -n "Updating 'configure' script ... " +else + echo -n "Creating 'configure' script ... " +fi + +aclocal --acdir=adm_local/unix/config_files -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files +if autoconf +then + echo "done" +else + echo "failed (check file permissions and/or user quotas ...)" +fi + +cd ${ORIG_DIR} + +echo diff --git a/doc/salome/GUI_index.html b/doc/salome/GUI_index.html new file mode 100755 index 000000000..465e3ea9d --- /dev/null +++ b/doc/salome/GUI_index.html @@ -0,0 +1,95 @@ + + + + + + + + Gui Module Documentation + + + +
  +
+
                   +   
+ + + + + + + + + +
+ + + +
+ +
+
+
+

GUI MODULE Documentation

+
+
+ + + + + +
+
+ +
+

Application-About.png +     

+
+ +
+ + + + +
+
+
+
+
+ +
+ +
GUI Documentation
+ +
+ +
+ +

+
+ +
+ +
TUI Documentation
+ +
+ +
+ +

+
+
+
+
+
+
+ + diff --git a/doc/salome/gui/KERNEL/viewers.htm b/doc/salome/gui/KERNEL/viewers.htm new file mode 100755 index 000000000..277437987 --- /dev/null +++ b/doc/salome/gui/KERNEL/viewers.htm @@ -0,0 +1,212 @@ + + + + + +Viewers + + + + + + + + + + + +

Viewers

+ +

Salome gives you a choice of four different viewers. This wide choice + of instruments providing both common and unique possibilities aims to + give the users of SALOME Platform maximum convenience and ease in their + work.

+ +

Customizing the viewers you can define settings to be used in them by + default in the Preferences menu.

+ +

Salome Platform also provides you with Viewer + Toolbars, which make it possible to promptly operate your viewer + scene. Some of the functions are common for all viewers.

+ + + + + +

 

+ +

VTK 3d  viewer + (Visualization ToolKit Viewer) and OCC + 3d viewer (Open CasCade Viewer) are both useful for creation of + geometrical models in the GEOM module, however, there some differences, + which specialize the use of the modules.

+ +

OCC 3d viewer is the default + viewer for GEOM Module. Only this viewer gives you the possibility to + select sub-shapes (described in full detail in the help for the GEOM Module). + Unfortunately, you can't visualize meshes in this viewer, for this, use + VTK 3d viewer.   

+ +

VTK 3d  viewer + is the default viewer for SMESH Module. Using this viewer you'll be able + to visualize and work with meshes.  

+ +

Most of functions in Viewer Toolbars of these modules are common for + both viewers, they are:

+ + + +

One more function is available in OCC + 3d viewer only.

+ + + +

 

+ +

Plot 2d viewer is destined to + the representation of  2d + plots and graphs obtained via Post-Pro module.

+ +

Its viewer toolbar gives you fast access to the following operations:

+ + + +

 

+ +

+ +

 

+ +

GL Viewer is used by exterior + modules built-in in the SALOME Platform.

+ + + + diff --git a/src/CAF/CAF_Study.cxx b/src/CAF/CAF_Study.cxx new file mode 100755 index 000000000..176023a1f --- /dev/null +++ b/src/CAF/CAF_Study.cxx @@ -0,0 +1,381 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "CAF_Study.h" + +#include "CAF_Tools.h" +#include "CAF_Operation.h" +#include "CAF_Application.h" + +#include +#include +#include + +#include + +#include +#include + +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CAF_Study::CAF_Study(SUIT_Application* theApp) +: SUIT_Study( theApp ), +myModifiedCnt( 0 ) +{ +} + +CAF_Study::CAF_Study(SUIT_Application* theApp, Handle (TDocStd_Document)& aStdDoc) +: SUIT_Study( theApp ), +myStdDoc( aStdDoc ), +myModifiedCnt( 0 ) +{ +} + +CAF_Study::~CAF_Study() +{ +} + +Handle(TDocStd_Document) CAF_Study::stdDoc() const +{ + return myStdDoc; +} + +void CAF_Study::setStdDoc( Handle(TDocStd_Document)& aStdDoc ) +{ + myStdDoc = aStdDoc; +} + +void CAF_Study::createDocument() +{ + SUIT_Study::createDocument(); + + CAF_Application* app = cafApplication(); + if ( app && !app->stdApp().IsNull() ) + { + try { + TColStd_SequenceOfExtendedString formats; + app->stdApp()->Formats( formats ); + if ( !formats.IsEmpty() ) + app->stdApp()->NewDocument( formats.First(), myStdDoc ); + } + catch ( Standard_Failure ) { + } + } +} + +void CAF_Study::closeDocument( bool permanent ) +{ + Handle(TDocStd_Application) app = stdApp(); + if ( !app.IsNull() && !stdDoc().IsNull() ) + app->Close( stdDoc() ); + + SUIT_Study::closeDocument( permanent ); +} + +bool CAF_Study::openDocument( const QString& fname ) +{ + Handle(TDocStd_Application) app = stdApp(); + if ( app.IsNull() ) + return false; + + bool status = false; + try { + status = app->Open( CAF_Tools::toExtString( fname ), myStdDoc ) == CDF_RS_OK; + } + catch ( Standard_Failure ) { + status = false; + } + + return status && SUIT_Study::openDocument( fname ); +} + +bool CAF_Study::saveDocumentAs( const QString& fname ) +{ + Handle(TDocStd_Application) app = stdApp(); + if ( app.IsNull() ) + return false; + + bool save = false; + if ( !stdDoc().IsNull() && stdDoc()->IsSaved() ) + { + QString path = QDir::convertSeparators( CAF_Tools::toQString( stdDoc()->GetPath() ) ); + save = path == QDir::convertSeparators( fname ); + } + + bool status = false; + try { + if ( save ) + status = app->Save( stdDoc() ) == CDF_SS_OK; + else + { + TCollection_ExtendedString format, path( CAF_Tools::toExtString( fname ) ); + app->Format( path, format ); + + if ( format.Length() ) + stdDoc()->ChangeStorageFormat( format ); + + status = app->SaveAs( stdDoc(), path ) == CDF_SS_OK; + } + } + catch ( Standard_Failure ) { + status = false; + } + + if ( status ) + status = SUIT_Study::saveDocumentAs( fname ); + + if ( status ) + myModifiedCnt = 0; + + return status; +} + +bool CAF_Study::openTransaction() +{ + if ( myStdDoc.IsNull() ) + return false; + + bool res = true; + try { + if ( myStdDoc->HasOpenCommand() ) + myStdDoc->AbortCommand(); + + myStdDoc->OpenCommand(); + } + catch ( Standard_Failure ) { + res = false; + } + + return res; +} + +bool CAF_Study::abortTransaction() +{ + if ( myStdDoc.IsNull() ) + return false; + + bool res = true; + try { + myStdDoc->AbortCommand(); + update(); + } + catch ( Standard_Failure ) { + res = false; + } + return res; +} + +bool CAF_Study::commitTransaction( const QString& name ) +{ + if ( myStdDoc.IsNull() ) + return false; + + bool res = true; + try { + myStdDoc->CommitCommand(); + + if ( canUndo() ) + { + Handle(TDF_Delta) d = myStdDoc->GetUndos().Last(); + if ( !d.IsNull() ) + d->SetName( CAF_Tools::toExtString( name ) ); + } + } + catch ( Standard_Failure ) { + res = false; + } + return res; +} + +bool CAF_Study::hasTransaction() const +{ + if ( myStdDoc.IsNull() ) + return false; + + return myStdDoc->HasOpenCommand(); +} + +/*! + Returns whether the document was saved in file. [ public ] +*/ +bool CAF_Study::isSaved() const +{ + if ( myStdDoc.IsNull() ) + return false; + + return myStdDoc->IsSaved(); +} + +/*! + Returns whether the document is modified. [ public ] +*/ +bool CAF_Study::isModified() const +{ + if ( myStdDoc.IsNull() ) + return false; + +// return myStdDoc->IsModified(); + return myModifiedCnt; +} + +/*! + Increments modification count. If 'undoable' is 'true', this modification + can be rolled back by 'undoModified' otherwise the document will be marked + as 'modiifed' until saved. [ protected ] +*/ +void CAF_Study::doModified( bool undoable ) +{ + if ( myStdDoc.IsNull() ) + return; + + myModifiedCnt++; + + /* Assumed that number of available undos / redos is NOT changed dynamically */ + if ( !undoable ) + myModifiedCnt += myStdDoc->GetAvailableUndos(); +} + +/*! + Decrements modification count. [ protected ] +*/ +void CAF_Study::undoModified() +{ + myModifiedCnt--; +} + +/*! + Clears modification count. [ public ] +*/ +void CAF_Study::clearModified() +{ + myModifiedCnt = 0; +} + +/*! + Undoes the last command. [ public ] +*/ +bool CAF_Study::undo() +{ + if ( myStdDoc.IsNull() ) + return false; + + try { + myStdDoc->Undo(); + undoModified(); /* decrement modification counter */ + } + catch ( Standard_Failure ) { + SUIT_MessageBox::error1( application()->desktop(), tr( "ERR_ERROR" ), + tr( "ERR_DOC_UNDO" ), tr ( "BUT_OK" ) ); + return false; + } + return true; +} + +/*! + Redoes the last undo. [ public ] +*/ +bool CAF_Study::redo() +{ + if ( myStdDoc.IsNull() ) + return false; + + try { + myStdDoc->Redo(); + doModified(); /* increment modification counter */ + } + catch ( Standard_Failure ) { + SUIT_MessageBox::error1( application()->desktop(), tr( "ERR_ERROR" ), + tr( "ERR_DOC_REDO" ), tr ( "BUT_OK" ) ); + return false; + } + return true; +} + +/*! + Check if possible to perform 'undo' command. [ public ] +*/ +bool CAF_Study::canUndo() const +{ + if ( myStdDoc.IsNull() ) + return false; + + return myStdDoc->GetAvailableUndos() > 0; +} + +/*! + Check if possible to perform 'redo' command. [ public ] +*/ +bool CAF_Study::canRedo() const +{ + if ( myStdDoc.IsNull() ) + return false; + + return myStdDoc->GetAvailableRedos() > 0; +} + +/*! + Returns the list of names of 'undo' actions available. [ public ] +*/ +QStringList CAF_Study::undoNames() const +{ + QStringList names; + if ( !myStdDoc.IsNull() ) + { + for ( TDF_ListIteratorOfDeltaList it( myStdDoc->GetUndos() ); it.More(); it.Next() ) + names.prepend( CAF_Tools::toQString( it.Value()->Name() ) ); + } + return names; +} + +/*! + Returns the list of names of 'redo' actions available. [ public ] +*/ +QStringList CAF_Study::redoNames() const +{ + QStringList names; + if ( !myStdDoc.IsNull() ) + { + for ( TDF_ListIteratorOfDeltaList it( myStdDoc->GetRedos() ); it.More(); it.Next() ) + names.append( CAF_Tools::toQString( it.Value()->Name() ) ); + } + return names; +} + +/*! + Returns the standard OCAF application from owner application. [ protected ] +*/ +Handle(TDocStd_Application) CAF_Study::stdApp() const +{ + Handle(TDocStd_Application) stdApp; + CAF_Application* app = cafApplication(); + if ( app ) + stdApp = app->stdApp(); + return stdApp; +} + +/*! + Returns the application casted to type CAF_Application. [ protected ] +*/ +CAF_Application* CAF_Study::cafApplication() const +{ + return ::qt_cast( application() ); +} diff --git a/src/DDS/DDS.h b/src/DDS/DDS.h new file mode 100644 index 000000000..35c38aaf4 --- /dev/null +++ b/src/DDS/DDS.h @@ -0,0 +1,17 @@ +#ifndef DDS_H +#define DDS_H + +#include + +#include +#include + +#define UNIT_SYSTEM_SI "SI" + +typedef enum { DDS_MT_OK, DDS_MT_WARNING, + DDS_MT_ERROR, DDS_MT_ALARM, + DDS_MT_INFO, DDS_MT_NONE } DDS_MsgType; + +DEFINE_BASECOLLECTION(DDS_BaseColOfAsciiString,TCollection_AsciiString) + +#endif diff --git a/src/DDS/DDS_DicGroup.cxx b/src/DDS/DDS_DicGroup.cxx new file mode 100644 index 000000000..ac7f4ad6b --- /dev/null +++ b/src/DDS/DDS_DicGroup.cxx @@ -0,0 +1,130 @@ +#include "DDS_DicGroup.h" + +#include "DDS_Dictionary.h" + +#include +#include + +#include + +#include + +#include +#include + +IMPLEMENT_STANDARD_HANDLE(DDS_DicGroup, MMgt_TShared) +IMPLEMENT_STANDARD_RTTIEXT(DDS_DicGroup, MMgt_TShared) + +DDS_DicGroup::DDS_DicGroup( const TCollection_AsciiString& name ) +: MMgt_TShared(), +myName( name ), +myActiveSystem( UNIT_SYSTEM_SI ) +{ +} + +DDS_DicGroup::DDS_DicGroup( const DDS_DicGroup& ) +{ +} + +TCollection_AsciiString DDS_DicGroup::GetName() const +{ + return myName; +} + +void DDS_DicGroup::GetUnitSystems( TColStd_SequenceOfAsciiString& theSystemSeq ) const +{ + theSystemSeq.Clear(); + for ( UnitSystemMap::Iterator it( myUnitSystem ); it.More(); it.Next() ) + { + if ( it.Key() == TCollection_AsciiString( UNIT_SYSTEM_SI ) ) + theSystemSeq.Prepend( it.Key() ); + else + theSystemSeq.Append( it.Key() ); + } +} + +TCollection_ExtendedString DDS_DicGroup::GetUnitSystemLabel( const TCollection_AsciiString& name ) const +{ + TCollection_ExtendedString aLabel; + if ( myUnitSystem.IsBound( name ) ) + aLabel = myUnitSystem.Find( name ); + return aLabel; +} + +TCollection_AsciiString DDS_DicGroup::GetActiveUnitSystem() const +{ + return myActiveSystem; +} + +void DDS_DicGroup::SetActiveUnitSystem( const TCollection_AsciiString& theSystem ) +{ + if ( myUnitSystem.IsBound( theSystem ) ) + myActiveSystem = theSystem; +} + +void DDS_DicGroup::operator=( const DDS_DicGroup& ) +{ +} + +void DDS_DicGroup::FillDataMap( const LDOM_Element& theComponentData, const LDOM_Element& theDocElement ) +{ + TCollection_AsciiString aCompName = theComponentData.getAttribute( DDS_Dictionary::KeyWord( "COMPONENT_NAME" ) ); + + LDOM_Element systems = theComponentData.GetChildByTagName( DDS_Dictionary::KeyWord( "UNIT_SYSTEMS" ) ); + if ( !systems.isNull() ) + { + LDOM_NodeList systemList = systems.getElementsByTagName( DDS_Dictionary::KeyWord( "UNIT_SYSTEM" ) ); + for ( Standard_Integer i = 0; i < systemList.getLength(); i++ ) + { + LDOM_Element aSystem = (const LDOM_Element &)systemList.item( i ); + TCollection_AsciiString aName = aSystem.getAttribute( DDS_Dictionary::KeyWord( "UNIT_SYSTEM_NAME" ) ); + TCollection_ExtendedString aLabel = aSystem.getAttribute( DDS_Dictionary::KeyWord( "UNIT_SYSTEM_LABEL" ) ); + + if ( aName.IsEmpty() ) + continue; + + if ( !myUnitSystem.IsBound( aName ) ) + myUnitSystem.Bind( aName, aLabel ); + } + } + + if ( !myUnitSystem.IsBound( UNIT_SYSTEM_SI ) ) + { + printf( "Warning: Mandatory unit system SI not defined in component: \"%s\". Added automaticaly", aCompName.ToCString() ); + myUnitSystem.Bind( UNIT_SYSTEM_SI, TCollection_ExtendedString( "System international" ) ); + } + + TColStd_SequenceOfAsciiString unitSystems; + GetUnitSystems( unitSystems ); + + LDOM_NodeList aData = theComponentData.getElementsByTagName( DDS_Dictionary::KeyWord( "DATUM" ) ); + if ( !aData.getLength() ) + return; + + for ( Standard_Integer i = 0; i < aData.getLength(); i++ ) + { + LDOM_Element aQuantity = (const LDOM_Element&)aData.item( i ); + + // 1. Attributes (id,label,units?,format?,required?) + TCollection_AsciiString anID = aQuantity.getAttribute( DDS_Dictionary::KeyWord( "DATUM_ID" ) ); + Handle(DDS_DicItem) aDicItem = new DDS_DicItem(); + + aDicItem->myComponent = this; + aDicItem->FillDataMap( anID, aQuantity, theComponentData, theDocElement, unitSystems ); + myDataMap.Add( anID, aDicItem ); + } +} + +/*! + Returns DicItem with all attached data +*/ + +Handle(DDS_DicItem) DDS_DicGroup::GetDicItem( const TCollection_AsciiString& theID ) const +{ + Handle(DDS_DicItem) aDicItem; + // get dictionary item by id + if ( myDataMap.Contains( theID ) ) + aDicItem = myDataMap.FindFromKey( theID ); + + return aDicItem; +} diff --git a/src/DDS/DDS_DicGroup.h b/src/DDS/DDS_DicGroup.h new file mode 100644 index 000000000..d1c633fab --- /dev/null +++ b/src/DDS/DDS_DicGroup.h @@ -0,0 +1,61 @@ +#ifndef DDS_DICGROUP_H +#define DDS_DICGROUP_H + +#include "DDS.h" + +#include "DDS_DicItem.h" + +#include + +#include + +#include + +class LDOM_Element; +class TColStd_SequenceOfAsciiString; + +DEFINE_STANDARD_HANDLE(DDS_DicGroup, MMgt_TShared) + +class DDS_DicGroup : public MMgt_TShared +{ +public: + DDS_DicGroup( const TCollection_AsciiString& ); + + TCollection_AsciiString GetName() const; + + Standard_EXPORT Handle(DDS_DicItem) GetDicItem( const TCollection_AsciiString& ) const; + + Standard_EXPORT void GetUnitSystems( TColStd_SequenceOfAsciiString& ) const; + Standard_EXPORT TCollection_ExtendedString GetUnitSystemLabel( const TCollection_AsciiString& ) const; + + Standard_EXPORT TCollection_AsciiString GetActiveUnitSystem() const; + Standard_EXPORT void SetActiveUnitSystem( const TCollection_AsciiString& ); + +private: + DDS_DicGroup( const DDS_DicGroup& ); + + void operator=( const DDS_DicGroup& ); + + void FillDataMap( const LDOM_Element&, const LDOM_Element& ); + +private: + typedef NCollection_DataMap UnitSystemMap; + +private: + TCollection_AsciiString myName; + DDS_IndexedDataMapOfDicItems myDataMap; + UnitSystemMap myUnitSystem; + TCollection_AsciiString myActiveSystem; + + friend class DDS_Dictionary; + +public: + DEFINE_STANDARD_RTTI(DDS_DicGroup) +}; + +DEFINE_BASECOLLECTION(DDS_BaseCollectionOfDicGroups, Handle(DDS_DicGroup)) +DEFINE_INDEXEDDATAMAP(DDS_IndexedDataMapOfDicGroups, DDS_BaseCollectionOfDicGroups, + TCollection_AsciiString, Handle(DDS_DicGroup)) + +#endif diff --git a/src/DDS/DDS_DicItem.cxx b/src/DDS/DDS_DicItem.cxx new file mode 100644 index 000000000..fd59f3cd6 --- /dev/null +++ b/src/DDS/DDS_DicItem.cxx @@ -0,0 +1,924 @@ +#include "DDS_DicItem.h" +#include "DDS_Dictionary.h" + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +IMPLEMENT_STANDARD_HANDLE(DDS_DicItem, MMgt_TShared) +IMPLEMENT_STANDARD_RTTIEXT(DDS_DicItem, MMgt_TShared) + +DDS_DicItem::DDS_DicItem() +: myType( 0 ), +myDefValue( 0 ), +myMax( 0 ), +myMin( 0 ), +myMinZoom( 0.1 ), +myMaxZoom( 10 ), +myZoomOrder( 2 ) +{ +} + +DDS_DicItem::DDS_DicItem( const DDS_DicItem& ) +{ +} + +void DDS_DicItem::operator=( const DDS_DicItem& ) +{ +} + +TCollection_AsciiString DDS_DicItem::GetId() const +{ + return myId; +} + +DDS_DicItem::Type DDS_DicItem::GetType() const +{ + return (DDS_DicItem::Type)myType; +} + +TCollection_ExtendedString DDS_DicItem::GetLabel() const +{ + return myLabel; +} + +TCollection_ExtendedString DDS_DicItem::GetFilter() const +{ + return myFilter; +} + +TCollection_ExtendedString DDS_DicItem::GetRequired() const +{ + return myRequired; +} + +DDS_MsgType DDS_DicItem::GetWarningLevel() const +{ + return (DDS_MsgType)myWarnLevel; +} + +TCollection_ExtendedString DDS_DicItem::GetLongDescription() const +{ + return myLongDescr; +} + +TCollection_ExtendedString DDS_DicItem::GetShortDescription() const +{ + return myShortDescr; +} + +TCollection_AsciiString DDS_DicItem::GetComponent() const +{ + TCollection_AsciiString aCompName; + Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent); + if ( !aComponent.IsNull() ) + aCompName = aComponent->GetName(); + return aCompName; +} + +TCollection_AsciiString DDS_DicItem::GetUnits() const +{ + return GetUnits( GetActiveUnitSystem() ); +} + +TCollection_AsciiString DDS_DicItem::GetUnits( const UnitSystem& theSystem ) const +{ + TCollection_AsciiString anUnits; + UnitData* unitData = GetUnitData( theSystem ); + if ( unitData ) + anUnits = unitData->myUnits; + return anUnits; +} + +Standard_Real DDS_DicItem::GetMinValue() const +{ + return GetMinValue( GetActiveUnitSystem() ); +} + +Standard_Real DDS_DicItem::GetMinValue( const UnitSystem& theUnitsSystem ) const +{ + return FromSI( myMin, theUnitsSystem ); +} + +Standard_Real DDS_DicItem::GetMaxValue() const +{ + return GetMaxValue( GetActiveUnitSystem() ); +} + +Standard_Real DDS_DicItem::GetMaxValue( const UnitSystem& theUnitsSystem ) const +{ + return FromSI( myMax, theUnitsSystem ); +} + +Standard_Integer DDS_DicItem::GetPrecision() const +{ + return GetPrecision( GetActiveUnitSystem() ); +} + +Standard_Integer DDS_DicItem::GetPrecision( const UnitSystem& theSystem ) const +{ + Standard_Integer aRes = 0; + UnitData* unitData = GetUnitData( theSystem ); + if ( unitData ) + aRes = unitData->myPrecision; + return aRes; +} + +TCollection_ExtendedString DDS_DicItem::GetDefaultValue() const +{ + return GetDefaultValue( GetActiveUnitSystem() ); +} + +TCollection_ExtendedString DDS_DicItem::GetDefaultValue( const UnitSystem& theSystem ) const +{ + if ( !myDefString.Length() ) + return myDefString; + + TCollection_ExtendedString aStr; + + switch ( myType ) + { + case Float: + case Integer: + aStr = FromSI( myDefValue, theSystem ); + break; + case List: + case String: + aStr = myDefString; + break; + default: + break; + } + return aStr; +} + +TCollection_AsciiString DDS_DicItem::GetFormat( const Standard_Boolean theCanonical ) const +{ + return GetFormat( GetActiveUnitSystem(), theCanonical ); +} + +TCollection_AsciiString DDS_DicItem::GetFormat( const UnitSystem& theSystem, + const Standard_Boolean theCanonical ) const +{ + TCollection_AsciiString aFormat; + UnitData* unitData = GetUnitData( theSystem ); + if ( unitData ) + aFormat = unitData->myFormat; + + if ( theCanonical && aFormat.Length() > 1 ) + { + static TCollection_AsciiString f; + f = aFormat; + Standard_Boolean isRemoved = false; + while ( !isRemoved ) + { + char ch = f.Value( f.Length() - 1 ); + if ( ( ch != '%' && ch != '.' && !IsDigit( ch ) ) && f.Length() > 1 ) + f.Remove( f.Length() - 1 ); + else + isRemoved = true; + } + aFormat = f; + } + + return aFormat; +} + +/*! + Access valueList:name of the parameter. This string is void if the list is + not defined - then use other properties: Type, DefaultValue, MaxValue, MinValue +*/ +TCollection_ExtendedString DDS_DicItem::GetNameOfValues() const +{ + return myListName; +} + +/*! + Access valueList of the parameter. This sequence is empty if the list is + not defined - then use other properties: Type, DefaultValue, MaxValue, MinValue +*/ +Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings, + Handle(TColStd_HArray1OfInteger)& theIntegers ) const +{ + theStrings = myListRef; + theIntegers = myListRefID; + return !theIntegers.IsNull() && !theStrings.IsNull(); +} + +/*! + Access valueList of the parameter. This sequence is empty if the list is not + defined - then use other properties: Type, DefaultValue, MaxValue, MinValue +*/ +Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings, + Handle(TColStd_HArray1OfInteger)& theIntegers, + Handle(TColStd_HArray1OfExtendedString)& theIcons ) const +{ + theStrings = myListRef; + theIntegers = myListRefID; + theIcons = myListRefIcons; + return !theIntegers.IsNull() && !theStrings.IsNull() && !theIcons.IsNull(); +} + +Standard_Boolean DDS_DicItem::GetSpecialValues( TColStd_MapOfReal& theMap ) const +{ + theMap.Clear(); + if ( !myListRef.IsNull() ) + { + for ( Standard_Integer i = myListRef->Lower(); i <= myListRef->Upper(); i++ ) + { + if ( myListRef->Value( i ).IsAscii() ) + { + TCollection_AsciiString aStr( myListRef->Value( i ) ); + if ( aStr.IsRealValue() ) + theMap.Add( aStr.RealValue() ); + } + } + } + + return theMap.Extent() > 0; +} + +/*! + Returns min value of lateral zooming +*/ +Standard_Real DDS_DicItem::GetMinZoom() const +{ + return myMinZoom; +} + +/*! + Returns Max Value of lateral zooming +*/ +Standard_Real DDS_DicItem::GetMaxZoom() const +{ + return myMaxZoom; +} + +/*! + Get Order of lateral zooming +*/ +Standard_Real DDS_DicItem::GetZoomOrder() const +{ + return myZoomOrder; +} + +Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal ) const +{ + return ToSI( theVal, GetActiveUnitSystem() ); +} + +Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal ) const +{ + return FromSI( theVal, GetActiveUnitSystem() ); +} + +/*! + Convert value to default SI units according to current units +*/ +Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const +{ + Standard_Real aRes = theVal; + UnitData* anUnitData = GetUnitData( theUnitsSystem ); + if ( anUnitData ) + aRes = anUnitData->myZero + aRes * anUnitData->myScale; + return aRes; +} + +/*! + Convert value from default SI units according to current units +*/ +Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const +{ + Standard_Real aRes = theVal; + UnitData* anUnitData = GetUnitData( theUnitsSystem ); + if ( anUnitData ) + aRes = ( aRes - anUnitData->myZero ) / anUnitData->myScale; + return aRes; +} + +/*! + Parse record in XML file and retrieve information relevant for this data dic item +*/ +void DDS_DicItem::FillDataMap( TCollection_AsciiString theID, const LDOM_Element& theDatum, + const LDOM_Element& theCompElement, const LDOM_Element& theDocElement, + const TColStd_SequenceOfAsciiString& theSystems ) +{ + TCollection_AsciiString aLabel = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_LABEL" ) ); + TCollection_AsciiString aFormat = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FORMAT" ) ); + TCollection_AsciiString aFilter = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FILTER" ) ); + TCollection_AsciiString aRequired = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_REQUIRED" ) ); + + TCollection_AsciiString aBaseKeyWord = DDS_Dictionary::KeyWord( "DATUM_UNITS" ); + + for ( Standard_Integer j = 1; j <= theSystems.Length(); j++ ) + { + UnitSystem anUnitSystem = theSystems.Value( j ); + if ( !anUnitSystem.Length() ) + continue; + + TCollection_AsciiString aUnitKeyword = anUnitSystem + aBaseKeyWord; + + if ( !myUnitData.IsBound( anUnitSystem ) ) + myUnitData.Bind( anUnitSystem, UnitData() ); + + UnitData& anUnitData = myUnitData.ChangeFind( anUnitSystem ); + anUnitData.myUnits = theDatum.getAttribute( LDOMString( aUnitKeyword.ToCString() ) ); + } + + if ( theSystems.Length() && myUnitData.IsBound( theSystems.First() ) && + !myUnitData.Find( theSystems.First() ).myUnits.Length() ) + { + TCollection_AsciiString units = theDatum.getAttribute( LDOMString( aBaseKeyWord.ToCString() ) ); + if ( units.Length() ) + myUnitData.ChangeFind( theSystems.First() ).myUnits = units; + } + + TCollection_AsciiString units; + for ( NCollection_DataMap::Iterator iter( myUnitData ); iter.More() && units.IsEmpty(); iter.Next() ) + units = iter.Value().myUnits; + + for ( NCollection_DataMap::Iterator itr( myUnitData ); itr.More(); itr.Next() ) + { + UnitData& dataUnits = itr.ChangeValue(); + if ( dataUnits.myUnits.IsEmpty() ) + dataUnits.myUnits = units; + } + + // 2. Elements ( domain, description ) + Standard_Real aRealMinV = 0; + Standard_Real aRealMaxV = 0; + Standard_Real aRealDefV = 0; + + TCollection_AsciiString aType; + + DDS_MsgType aWrongValue = DDS_MT_NONE; + DDS_DicItem::Type aEnumType = DDS_DicItem::Unknown; + + TCollection_AsciiString aMinV; + TCollection_AsciiString aMaxV; + TCollection_AsciiString aDefV; + TCollection_AsciiString aListName; + + TCollection_AsciiString aLongD; + TCollection_AsciiString aShortD; + + TColStd_SequenceOfInteger aSeqOfValueID; + TColStd_SequenceOfExtendedString aSeqOfValue; + TColStd_SequenceOfExtendedString aSeqOfValueIconName; + + // Presentation + Standard_Real aMinZoom = 0; + Standard_Real aMaxZoom = 0; + Standard_Real aZoomOrder = 0; + + // Datum::Reports tags (if any) + LDOM_Element aWLev = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "WARNING_LEVEL" ) ); + if ( !aWLev.isNull() ) + { + TCollection_AsciiString aWrongValWL = aWLev.getAttribute( DDS_Dictionary::KeyWord( "WRONG_VALUE" ) ); + if ( aWrongValWL.IsEqual( "Info" ) ) + aWrongValue = DDS_MT_INFO; + else if ( aWrongValWL.IsEqual( "Warning" ) ) + aWrongValue = DDS_MT_WARNING; + else if ( aWrongValWL.IsEqual( "Alarm" ) ) + aWrongValue = DDS_MT_ALARM; + else if ( aWrongValWL.IsEqual( "Error" ) ) + aWrongValue = DDS_MT_ERROR; + } + + // Datum::Presentation + LDOM_Element aPrs = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "PRS" ) ); + if ( !aPrs.isNull() ) + { + LDOM_Element aLateralZoom = aPrs.GetChildByTagName( DDS_Dictionary::KeyWord( "LATERAL_ZOOM" ) ); + if ( !aLateralZoom.isNull() ) + { + TCollection_AsciiString aMinZoomStr = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MINV" ) ); + TCollection_AsciiString aMaxZoomStr = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MAXV" ) ); + TCollection_AsciiString aZoomOrderStr = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_ORDER" ) ); + + aMinZoomStr.RemoveAll( ' ' ); + if ( aMinZoomStr.IsRealValue() ) + aMinZoom = aMinZoomStr.RealValue(); + + aMaxZoomStr.RemoveAll( ' ' ); + if ( aMaxZoomStr.IsRealValue() ) + aMaxZoom = aMaxZoomStr.RealValue(); + + aZoomOrderStr.RemoveAll( ' ' ); + if ( aZoomOrderStr.IsRealValue() ) + aZoomOrder = aZoomOrderStr.RealValue(); + } + } + + // Quantity::Domain record as the only child of that tag name + LDOM_Element aDomain = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DY_DOMAIN" ) ); + if ( !aDomain.isNull() ) + { + LDOM_Element aValueDescr = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_DESCR" ) ); + if ( !aValueDescr.isNull() ) + { + // read: valueDescr? (type?,min?,max?,default?) + aType = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_TYPE" ) ); + if ( aType.IsEqual( "String" ) ) + aEnumType = String; + else if ( aType.IsEqual( "Float" ) ) + aEnumType = Float; + else if ( aType.IsEqual( "Integer" ) ) + aEnumType = Integer; + + aMinV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MINV" ) ); + aMinV.RemoveAll( ' ' ); + if ( aMinV.IsRealValue() ) + aRealMinV = aMinV.RealValue(); + aMaxV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MAXV" ) ); + aMaxV.RemoveAll( ' ' ); + if ( aMaxV.IsRealValue() ) + aRealMaxV = aMaxV.RealValue(); + aDefV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) ); + aDefV.RemoveAll( ' ' ); + if ( aDefV.IsRealValue() ) + aRealDefV = aDefV.RealValue(); + + TCollection_AsciiString aSpecVal = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_SPEC" ) ); + Split( aSpecVal, myListRef ); + } + else + { + // read: listRef? (list?) + LDOM_Element aListRef = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_REF" ) ); + if ( !aListRef.isNull() ) + { + aType = "List"; + aEnumType = List; + LDOMString aListId = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VLR_LIST" ) ); + aDefV = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) ); + aDefV.RemoveAll( ' ' ); + LDOM_Element foundListItem; + for ( LDOM_Element aListItem = theCompElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) ); + aListItem != NULL && foundListItem == NULL; aListItem = aListItem.GetSiblingByTagName() ) + { + if ( aListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) ) + foundListItem = aListItem; + + } + for ( LDOM_Element aLstItem = theDocElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) ); + aLstItem != NULL && foundListItem == NULL; aLstItem = aLstItem.GetSiblingByTagName() ) + { + if ( aLstItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) ) + foundListItem = aLstItem; + } + + if ( foundListItem != NULL ) + { + // The appropriate list of values is found: store the list name + aListName = foundListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_NAME" ) ); + // Iteration through the list of values + LDOM_Element aListItemValue = foundListItem.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUE" ) ); + while ( aListItemValue != NULL ) + { + // read value ID + TCollection_AsciiString aListValueID = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEID" ) ); + if ( aListValueID.IsIntegerValue() ) + { + // Read the text in the element "value" + LDOM_Text aListItemTxt = (const LDOM_Text&)aListItemValue.getFirstChild(); + if ( !aListItemTxt.isNull() ) + { + // adding ID and text value to sequence + aSeqOfValueID.Append( aListValueID.IntegerValue() ); + aSeqOfValue.Append( aListItemTxt.getData() ); + // adding icon file name (optional) to sequence + TCollection_ExtendedString aListValueIcon = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEICON" ) ); + aSeqOfValueIconName.Append( aListValueIcon ); + } + aListItemValue = aListItemValue.GetSiblingByTagName(); + } + } + } + } + } + } + + // Quantity::Description record as the only child of that tag name + LDOM_Element aDescr = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DESCR" ) ); + if ( !aDescr.isNull() ) + { + // short description (#PCDATA)* + LDOM_Element aShDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "SHORT_D" ) ); + if ( !aShDescr.isNull() ) + { + // text is always a sub-node of element, containing it + LDOM_Text aShDescrTxt = (const LDOM_Text&)aShDescr.getFirstChild(); + if ( !aShDescrTxt.isNull() ) + aShortD = aShDescrTxt.getData(); + } + + // long description (#PCDATA)* + LDOM_Element aLDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "LONG_D" ) ); + if ( !aLDescr.isNull() ) + { + // text is always a sub-node of element, containing it + LDOM_Text aLDescrTxt = (const LDOM_Text&)aLDescr.getFirstChild(); + if ( !aLDescrTxt.isNull() ) + aLongD = aLDescrTxt.getData(); + } + } + + NCollection_DataMap aDimMap; + + for ( NCollection_DataMap::Iterator it( myUnitData ); it.More(); it.Next() ) + { + UnitData& anUnitData = it.ChangeValue(); + + // check units + anUnitData.myZero = 0.; + anUnitData.myScale = 1.; + try { + Standard_CString aUnitDataStr; + aUnitDataStr = (Standard_CString)anUnitData.myUnits.ToCString(); + if ( anUnitData.myUnits.ToCString()[0] && strcmp( anUnitData.myUnits.ToCString(), "%" ) ) + { + Handle(Units_Dimensions) aDim; + anUnitData.myZero = UnitsAPI::AnyToSI( 0.0, aUnitDataStr, aDim ); + anUnitData.myScale = UnitsAPI::AnyToSI( 1.0, aUnitDataStr, aDim ) - anUnitData.myZero; + UnitsAPI::AnyFromSI( 1.0, aUnitDataStr ); + if ( !aDimMap.IsBound( it.Key() ) ) + aDimMap.Bind( it.Key(), aDim ); + } + else if ( anUnitData.myUnits.ToCString()[0] ) // treat '%' as unit with scale 100 + anUnitData.myScale = 0.01; + } + catch( Standard_Failure ) { + anUnitData.myUnits.Clear(); + } + + Handle(Units_Dimensions) aPrev; + Standard_Boolean aStatus = Standard_True; + for ( NCollection_DataMap::Iterator itr( aDimMap ); + itr.More() && aStatus; itr.Next() ) + { + if ( itr.Value().IsNull() ) + continue; + + if ( aPrev.IsNull() ) + aPrev = itr.Value(); + + aStatus = aPrev->IsEqual( itr.Value() ); + } + + if ( !aStatus ) + printf( "Error in DataDictionary: Different dimensions for %s item", theID.ToCString() ); + } + + myId = theID; + myType = aEnumType; + myWarnLevel = aWrongValue; + myLabel = aLabel.ToCString(); + myFilter = aFilter.ToCString(); + myLongDescr = aLongD.ToCString(); + myShortDescr = aShortD.ToCString(); + myMin = aRealMinV; + myMax = aRealMaxV; + myDefValue = aRealDefV; + myDefString = aDefV.ToCString(); + myRequired = aRequired.ToCString(); + myListName = aListName.ToCString(); + myMinZoom = aMinZoom; + myMaxZoom = aMaxZoom; + myZoomOrder = aZoomOrder; + + // prepare formats + PrepareFormats( aFormat ); + + const Standard_Integer aLength = aSeqOfValue.Length(); + if ( aLength > 0 ) + { + myListRef = new TColStd_HArray1OfExtendedString( 1, aLength ); + myListRefID = new TColStd_HArray1OfInteger( 1, aLength ); + myListRefIcons = new TColStd_HArray1OfExtendedString( 1, aLength ); + for ( Standard_Integer i = aLength; i > 0; i-- ) + { + myListRef->ChangeValue( i ) = aSeqOfValue.Value( i ); + myListRefID->ChangeValue( i ) = aSeqOfValueID.Value( i ); + myListRefIcons->ChangeValue( i ) = aSeqOfValueIconName.Value( i ); + } + } + + if ( myType == List && myDefString == "" && !myListRef.IsNull() && myListRef->Length() > 0 ) + myDefString = myListRef->Value( myListRef->Lower() ); +} + +/*! + Returns default formats for each unit systems +*/ +void DDS_DicItem::GetDefaultFormat() +{ + for ( NCollection_DataMap::Iterator it( myUnitData ); it.More(); it.Next() ) + { + UnitData& anUnitData = it.ChangeValue(); + + switch ( myType ) + { + case Integer: + anUnitData.myFormat = "%d"; + break; + case Float: + anUnitData.myFormat = "%g"; + break; + case String: + default: + anUnitData.myFormat.Clear(); + break;; + } + } +} + +/*! + Returns format for the string +*/ +void DDS_DicItem::GetStringFormat( const TCollection_AsciiString& theFlags, + const TCollection_AsciiString& theWidth, + const TCollection_AsciiString& thePrecision, + const TCollection_AsciiString& theTypePrefix, + TCollection_AsciiString& theFormat ) +{ + theFormat = "%"; + theFormat += theFlags; + theFormat += theWidth; + + if ( !thePrecision.IsEmpty() ) + { + theFormat += "."; + theFormat += thePrecision; + } + + theFormat += theTypePrefix; + theFormat += "s"; +} + +/*! + Returns format for the integer +*/ +void DDS_DicItem::GetIntegerFormat( const TCollection_AsciiString& theFlags, + const TCollection_AsciiString& theWidth, + const TCollection_AsciiString& thePrecision, + const TCollection_AsciiString& theTypePrefix, + const Standard_Character theType, + TCollection_AsciiString& theFormat ) +{ + Standard_Integer aPrecision = 0; + if ( !thePrecision.IsEmpty() ) + aPrecision = thePrecision.IntegerValue(); + Standard_Integer aWidth = 0; + + if ( !theWidth.IsEmpty() ) + aWidth = theWidth.IntegerValue(); + + if ( !thePrecision.IsEmpty() && aPrecision < 0 ) + { + // possible value 0.1 will be 10.0 + aWidth -= aPrecision; + aPrecision = 0; + } + + if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) ) + aWidth = aPrecision + 2; + + theFormat = "%"; + + theFormat += theFlags; + if ( !theWidth.IsEmpty() ) + theFormat += aWidth; + + theFormat += theTypePrefix; + theFormat += theType; +} + +/*! + Returns format for the float +*/ +void DDS_DicItem::GetFloatFormat( const TCollection_AsciiString& theFlags, + const TCollection_AsciiString& theWidth, + const TCollection_AsciiString& thePrecision, + const TCollection_AsciiString& theTypePrefix, + const Standard_Character theType, + TCollection_AsciiString& theFormat ) +{ + Standard_Integer aPrecision = 0; + if ( !thePrecision.IsEmpty() ) + aPrecision = thePrecision.IntegerValue(); + Standard_Integer aWidth = 0; + + if (!theWidth.IsEmpty() ) + aWidth = theWidth.IntegerValue(); + + if (!thePrecision.IsEmpty() && aPrecision < 0 ) + { + // possible value 0.1 will be 10.0 + aWidth -= aPrecision; + aPrecision = 0; + } + + if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) ) + { + aWidth = aPrecision + 2; + } + + theFormat = "%"; + theFormat += theFlags; + + if ( !theWidth.IsEmpty() ) + theFormat += aWidth; + + if ( !thePrecision.IsEmpty() ) + { + theFormat += "."; + theFormat += aPrecision; + } + + theFormat += theTypePrefix; + theFormat += theType; +} + +/*! + Prepares three formants for each unit systems +*/ +void DDS_DicItem::PrepareFormats( const TCollection_AsciiString& theFormat ) +{ + for ( NCollection_DataMap::Iterator it( myUnitData ); it.More(); it.Next() ) + { + UnitData& anUnitData = it.ChangeValue(); + + anUnitData.myFormat = theFormat; + anUnitData.myPrecision = 0; + } + + TCollection_AsciiString aPrecisionStr; + if ( theFormat.IsEmpty() && myType == List ) + return; + + // checking % presenting + if ( *theFormat.ToCString() != '%' ) + { + GetDefaultFormat(); + return; + } + + TCollection_AsciiString aStr = ( theFormat.ToCString() + 1 ); + Standard_Character aType = aStr.Value( aStr.Length() ); + + if ( ( aType != 's' && myType == String ) || + ( aType != 'd' && myType == Integer ) || + ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' && myType == Float ) ) + { + GetDefaultFormat(); + return; + } + + // removing type character + aStr.Trunc( aStr.Length() - 1 ); + + TCollection_AsciiString aFlags; + while ( !aStr.IsEmpty() && aStr.Value( 1 ) != '.' && ( aStr.Value( 1 ) < '0' || aStr.Value( 1 ) > '9' ) ) + { + aFlags = aFlags + aStr.Value( 1 ); + aStr.Remove( 1 ); + } + + Standard_Integer aPos = 1; + while ( aPos <= aStr.Length() && ( aStr.Value( aPos ) == '.' || + ( aStr.Value( aPos ) >= '0' && aStr.Value( aPos ) <= '9' ) ) ) + aPos++; + + TCollection_AsciiString aTypePrefix; + if ( aPos <= aStr.Length() ) + { + aTypePrefix = aStr.SubString( aPos, aStr.Length() ); + aStr.Trunc( aPos - 1 ); + } + + Standard_Integer aBasePrecision = 0; + + // taking width and precision + TCollection_AsciiString aPrecision; + + aPos = aStr.Search( "." ); + if ( aPos >= 0 ) + { + // aPrecision is defined + aPrecision = aStr.Split( aPos ); + aStr.Remove( aStr.Length() ); + if ( !aPrecision.IsEmpty() ) + { + if ( !aPrecision.IsIntegerValue() ) + { + GetDefaultFormat(); + return; + } + else + { + aPrecisionStr = aPrecision; + aBasePrecision = aPrecision.IntegerValue(); + } + } + } + + if ( !aStr.IsEmpty() && !aStr.IsIntegerValue() ) + { + GetDefaultFormat(); + return; + } + + NCollection_DataMap::Iterator itr; + + switch ( myType ) + { + case String: + for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() ) + { + if ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' ) + GetStringFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, itr.ChangeValue().myFormat ); + } + break; + case Float: + case Integer: + for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() ) + { + UnitData& anUnitData = itr.ChangeValue(); + Standard_Integer aAmendment = + (Standard_Integer)log10( 10.0 / DDS_Dictionary::FromSI( 10.0, anUnitData.myUnits.ToCString() ) ); + anUnitData.myPrecision = aBasePrecision + aAmendment; + aPrecisionStr = TCollection_AsciiString( anUnitData.myPrecision ); + + // create a formats + if ( myType == Integer ) + GetIntegerFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat ); + else + GetFloatFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat ); + } + break; + default:; + GetDefaultFormat(); + break; + } +} + +void DDS_DicItem::Split( const TCollection_AsciiString& theStr, Handle(TColStd_HArray1OfExtendedString)& aRes ) +{ + aRes.Nullify(); + + if ( theStr.Length() > 0 ) + { + TCollection_AsciiString aStr = theStr; + TColStd_SequenceOfAsciiString aSeq; + Standard_Integer anIndex = aStr.SearchFromEnd( (Standard_CString)" " ); + while( anIndex > 1 ) + { + TCollection_AsciiString tmpStr = aStr.Split( anIndex - 1 ); + tmpStr.RemoveAll( ( Standard_Character )' ' ); + if ( tmpStr.Length() > 0 ) + aSeq.Append( tmpStr ); + anIndex = aStr.SearchFromEnd( (Standard_CString)" " ); + } + + aStr.RemoveAll( ( Standard_Character )' ' ); + if ( aStr.Length() > 0 ) + aSeq.Append( aStr ); + + if ( aSeq.Length() > 0 ) + { + aRes = new TColStd_HArray1OfExtendedString( 1, aSeq.Length() ); + for ( int i = 1, n = aSeq.Length(); i <= n; i++ ) + aRes->ChangeValue( i ) = aSeq( i ); + } + } +} + +DDS_DicItem::UnitData* DDS_DicItem::GetUnitData( const UnitSystem& sys ) const +{ + UnitData* unit = 0; + + if ( myUnitData.IsBound( sys ) ) + unit = (UnitData*)&myUnitData.Find( sys ); + + return unit; +} + +DDS_DicItem::UnitSystem DDS_DicItem::GetActiveUnitSystem() const +{ + UnitSystem aSystem; + Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent); + if ( !aComponent.IsNull() ) + aSystem = aComponent->GetActiveUnitSystem(); + return aSystem; +} diff --git a/src/DDS/DDS_DicItem.h b/src/DDS/DDS_DicItem.h new file mode 100644 index 000000000..871149407 --- /dev/null +++ b/src/DDS/DDS_DicItem.h @@ -0,0 +1,235 @@ +#ifndef DDS_DICITEM_H +#define DDS_DICITEM_H + +#include "DDS.h" + +#include + +#include + +#include +#include + +#include +#include + +class LDOM_Element; +class DDS_Dictionary; +class TColStd_MapOfReal; +class TColStd_SequenceOfInteger; +class TColStd_SequenceOfAsciiString; +class TColStd_SequenceOfExtendedString; + +// Class, containing all information about one parameter: +// unique : id +// obligative: label, type, short description, required +// optional : format, units, +// min value, max value, default value. + +class DDS_DicItem : public MMgt_TShared +{ +public: + enum Type { String, Float, Integer, List, Unknown }; + + // This struct is intended for map of Format, Units, Precision and Scale + struct UnitData + { + Standard_Real myZero; + Standard_Real myScale; + TCollection_AsciiString myUnits; + TCollection_AsciiString myFormat; + Standard_Integer myPrecision; + }; + + typedef TCollection_AsciiString UnitSystem; + +public: + DDS_DicItem(); + + Standard_EXPORT TCollection_AsciiString GetId() const; + // to access Type of the parameter + + Standard_EXPORT DDS_DicItem::Type GetType() const; + // to access Type of the parameter + + Standard_EXPORT TCollection_ExtendedString GetLabel() const; + // to access Label (name) of the parameter + + Standard_EXPORT TCollection_ExtendedString GetFilter() const; + // to access filter (regexp) for the parameter values + + Standard_EXPORT TCollection_ExtendedString GetRequired() const; + // to access Required of the parameter + + Standard_EXPORT DDS_MsgType GetWarningLevel() const; + // to access wrong value warning level of the parameter + + Standard_EXPORT TCollection_ExtendedString GetLongDescription() const; + // to access Long Description of the parameter + + Standard_EXPORT TCollection_ExtendedString GetShortDescription() const; + // to access Short Description of the parameter + + Standard_EXPORT TCollection_AsciiString GetComponent() const; + + Standard_EXPORT TCollection_AsciiString GetUnits() const; + Standard_EXPORT TCollection_AsciiString GetUnits( const UnitSystem& ) const; + // returns units for indicated unit systems + + Standard_EXPORT TCollection_ExtendedString GetDefaultValue() const; + Standard_EXPORT TCollection_ExtendedString GetDefaultValue( const UnitSystem& ) const; + // to access Default Value of the parameter + + Standard_EXPORT Standard_Real GetMinValue() const; + Standard_EXPORT Standard_Real GetMinValue( const UnitSystem& ) const; + // get Min Value of the parameter, either in specified unit system or in internal units (basic SI) + + Standard_EXPORT Standard_Real GetMaxValue() const; + Standard_EXPORT Standard_Real GetMaxValue( const UnitSystem& ) const; + // get Max Value of the parameter, either in specified unit system or in internal units (basic SI) + + Standard_EXPORT Standard_Integer GetPrecision() const; + Standard_EXPORT Standard_Integer GetPrecision( const UnitSystem& ) const; + // returns precision for indicated unit systems + + Standard_EXPORT TCollection_AsciiString GetFormat( const Standard_Boolean = Standard_True ) const; + Standard_EXPORT TCollection_AsciiString GetFormat( const UnitSystem&, + const Standard_Boolean = Standard_True ) const; + // returns format for indicated unit systems + + Standard_EXPORT TCollection_ExtendedString GetNameOfValues() const; + // to access valueList:name of the parameter. + // This string is void if the list is not defined - then use other properties: + // Type, DefaultValue, MaxValue, MinValue + + Standard_EXPORT Standard_Boolean GetListOfValues( Handle(TColStd_HArray1OfExtendedString)&, + Handle(TColStd_HArray1OfInteger)& ) const; + // to access valueList of the parameter + // This sequence is empty if the list not defined - then use other properties: + // Type, DefaultValue, MaxValue, MinValue + + Standard_EXPORT Standard_Boolean GetListOfValues( Handle(TColStd_HArray1OfExtendedString)&, + Handle(TColStd_HArray1OfInteger)&, + Handle(TColStd_HArray1OfExtendedString)& ) const; + // to access valueList of the parameter + // This sequence is empty if the list not defined - then use other properties: + // Type, DefaultValue, MaxValue, MinValue + + Standard_EXPORT Standard_Boolean GetSpecialValues( TColStd_MapOfReal& ) const; + // get values from specVal + + Standard_EXPORT Standard_Real GetMinZoom() const; + // get Min Value of lateral zooming + + Standard_EXPORT Standard_Real GetMaxZoom() const; + // get Max Value of lateral zooming + + Standard_EXPORT Standard_Real GetZoomOrder() const; + // get Order of lateral zooming + + Standard_EXPORT Standard_Real ToSI( const Standard_Real ) const; + Standard_EXPORT Standard_Real FromSI( const Standard_Real ) const; + + Standard_EXPORT Standard_Real ToSI( const Standard_Real, const UnitSystem& ) const; + Standard_EXPORT Standard_Real FromSI( const Standard_Real, const UnitSystem& ) const; + // convert value to and from default SI units according to current units + +private: + DDS_DicItem( const DDS_DicItem& ); + // Copy constructor + + void operator=( const DDS_DicItem& ); + // Assignment operator + + void FillDataMap( TCollection_AsciiString, const LDOM_Element&, + const LDOM_Element&, const LDOM_Element&, + const TColStd_SequenceOfAsciiString& ); + // prepares formants for each unit systems + + + void PrepareFormats( const TCollection_AsciiString& ); + // prepares three formats for each unit systems + + void GetDefaultFormat(); + // returns three default formants for each unit systems + + UnitSystem GetActiveUnitSystem() const; + + void GetStringFormat( const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + TCollection_AsciiString& ); + // returns format for the string + + void GetIntegerFormat( const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + const Standard_Character, + TCollection_AsciiString& ); + // returns format for the integer + + void GetFloatFormat( const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + const TCollection_AsciiString&, + const Standard_Character, + TCollection_AsciiString& ); + // returns format for the float + + void Split( const TCollection_AsciiString&, + Handle(TColStd_HArray1OfExtendedString)& ); + + UnitData* GetUnitData( const UnitSystem& ) const; + +private: + TCollection_AsciiString myId; + TCollection_ExtendedString myLabel; + TCollection_ExtendedString myFilter; + TCollection_ExtendedString myRequired; + + Standard_Integer myType; + Standard_Integer myWarnLevel; + + TCollection_ExtendedString myLongDescr; + TCollection_ExtendedString myShortDescr; + + Standard_Real myMax; + Standard_Real myMin; + Standard_Real myDefValue; + TCollection_ExtendedString myDefString; + + // valueList + TCollection_ExtendedString myListName; + + Handle(TColStd_HArray1OfExtendedString) myListRef; + Handle(TColStd_HArray1OfInteger) myListRefID; + Handle(TColStd_HArray1OfExtendedString) myListRefIcons; + + // presentation + Standard_Real myMinZoom; + Standard_Real myMaxZoom; + Standard_Real myZoomOrder; + + Handle(Standard_Transient) myComponent; + + // unitData + NCollection_DataMap myUnitData; + + friend class DDS_DicGroup; + +public: + // Declaration of CASCADE RTTI + DEFINE_STANDARD_RTTI(DDS_DicItem) +}; + +// Definition of HANDLE object using Standard_DefineHandle.hxx +DEFINE_STANDARD_HANDLE(DDS_DicItem, MMgt_TShared) + +// Container class XMLTools_IndexedDataMapOfDicItems (map of handles) +DEFINE_BASECOLLECTION(DDS_BaseCollectionOfDicItems, Handle(DDS_DicItem)) +DEFINE_INDEXEDDATAMAP(DDS_IndexedDataMapOfDicItems, DDS_BaseCollectionOfDicItems, + TCollection_AsciiString, Handle(DDS_DicItem)) + +#endif diff --git a/src/DDS/DDS_Dictionary.cxx b/src/DDS/DDS_Dictionary.cxx new file mode 100644 index 000000000..3656a3949 --- /dev/null +++ b/src/DDS/DDS_Dictionary.cxx @@ -0,0 +1,232 @@ +#include "DDS_Dictionary.h" + +#include "DDS_KeyWords.h" + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +IMPLEMENT_STANDARD_HANDLE(DDS_Dictionary, MMgt_TShared) +IMPLEMENT_STANDARD_RTTIEXT(DDS_Dictionary, MMgt_TShared) + +DDS_Dictionary::DDS_Dictionary() +: MMgt_TShared() +{ +} + +DDS_Dictionary::DDS_Dictionary( const DDS_Dictionary& ) +{ +} + +void DDS_Dictionary::operator=( const DDS_Dictionary& ) +{ +} + +void DDS_Dictionary::GetUnitSystems( TColStd_SequenceOfAsciiString& theSystems ) const +{ + theSystems.Clear(); + + NCollection_Map aMap; + for ( Standard_Integer i = 1; i <= myGroupMap.Extent(); i++ ) + { + TColStd_SequenceOfAsciiString theSeq; + myGroupMap.FindFromIndex( i )->GetUnitSystems( theSeq ); + for ( Standard_Integer s = 1; s <= theSeq.Length(); s++ ) + { + if ( aMap.Contains( theSeq.Value( s ) ) ) + continue; + + theSystems.Append( theSeq.Value( s ) ); + aMap.Add( theSeq.Value( s ) ); + } + } + +} + +void DDS_Dictionary::GetUnitSystems( TColStd_SequenceOfAsciiString& theSystems, + const TCollection_AsciiString& theComponent ) const +{ + theSystems.Clear(); + if ( myGroupMap.Contains( theComponent ) ) + myGroupMap.FindFromKey( theComponent )->GetUnitSystems( theSystems ); +} + +TCollection_ExtendedString DDS_Dictionary::GetUnitSystemLabel( const TCollection_AsciiString& theSystem ) const +{ + TCollection_ExtendedString aLabel; + for ( Standard_Integer i = 1; i <= myGroupMap.Extent() && !aLabel.Length(); i++ ) + aLabel = myGroupMap.FindFromIndex( i )->GetUnitSystemLabel( theSystem ); + return aLabel; +} + +TCollection_ExtendedString DDS_Dictionary::GetUnitSystemLabel( const TCollection_AsciiString& theSystem, + const TCollection_AsciiString& theComponent ) const +{ + TCollection_ExtendedString aLabel; + if ( myGroupMap.Contains( theComponent ) ) + aLabel = myGroupMap.FindFromKey( theComponent )->GetUnitSystemLabel( theSystem ); + return aLabel; +} + +TCollection_AsciiString DDS_Dictionary::GetActiveUnitSystem() const +{ + TCollection_AsciiString aSystem; + if ( myGroupMap.Extent() ) + aSystem = myGroupMap.FindFromIndex( 1 )->GetActiveUnitSystem(); + return aSystem; +} + +TCollection_AsciiString DDS_Dictionary::GetActiveUnitSystem( const TCollection_AsciiString& theComponent ) const +{ + TCollection_AsciiString aSystem; + if ( myGroupMap.Contains( theComponent ) ) + aSystem = myGroupMap.FindFromKey( theComponent )->GetActiveUnitSystem(); + return aSystem; +} + +void DDS_Dictionary::SetActiveUnitSystem( const TCollection_AsciiString& theSystem ) +{ + for ( Standard_Integer i = 1; i <= myGroupMap.Extent(); i++ ) + myGroupMap.FindFromIndex( i )->SetActiveUnitSystem( theSystem ); +} + +void DDS_Dictionary::SetActiveUnitSystem( const TCollection_AsciiString& theSystem, + const TCollection_AsciiString& theComponent ) +{ + if ( myGroupMap.Contains( theComponent ) ) + myGroupMap.FindFromKey( theComponent )->SetActiveUnitSystem( theSystem ); +} + +/*! + Returns the instance of dictionary. Create instance if it is NULL. +*/ +Handle(DDS_Dictionary) DDS_Dictionary::Get() +{ + static Handle(DDS_Dictionary) sDictionary; + + if ( sDictionary.IsNull() ) + sDictionary = new DDS_Dictionary(); + + return sDictionary; +} + +Standard_Boolean DDS_Dictionary::Load( const TCollection_AsciiString theFileName ) +{ + static NCollection_Map _LoadMap; + + if ( _LoadMap.Contains( theFileName ) ) + return Standard_True; + + Handle(DDS_Dictionary) aDic = Get(); + if ( aDic.IsNull() ) + return Standard_False; + + LDOMParser aParser; + if ( aParser.parse( theFileName.ToCString() ) ) + return Standard_False; + + LDOM_Document aDoc = aParser.getDocument(); + LDOM_Element aDocElement = aDoc.getDocumentElement(); + for ( LDOM_Element aComponentElem = aDocElement.GetChildByTagName( KeyWord( "COMPONENT" ) ); + !aComponentElem.isNull(); aComponentElem = aComponentElem.GetSiblingByTagName() ) + aDic->FillDataMap( aComponentElem, aDocElement ); + + _LoadMap.Add( theFileName ); + + return Standard_True; +} + +LDOMString DDS_Dictionary::KeyWord( const TCollection_AsciiString& key ) +{ + LDOMString keyWord; + Handle(DDS_KeyWords) aKeyWords = DDS_KeyWords::Get(); + if ( !aKeyWords.IsNull() ) + { + TCollection_AsciiString aStr = aKeyWords->GetKeyWord( key ); + if ( aStr.Length() ) + keyWord = LDOMString( aStr.ToCString() ); + } + return keyWord; +} + +/*! + Returns DicItem from specified group with all attached data +*/ + +Handle(DDS_DicItem) DDS_Dictionary::GetDicItem( const TCollection_AsciiString& theID, + const TCollection_AsciiString& theGroup ) const +{ + Handle(DDS_DicItem) aDicItem; + Handle(DDS_DicGroup) aDicGroup; + if ( myGroupMap.Contains( theGroup ) ) + aDicGroup = myGroupMap.FindFromKey( theGroup ); + if ( !aDicGroup.IsNull() ) + aDicItem = aDicGroup->GetDicItem( theID ); + return aDicItem; +} + +/*! + Returns DicItem with all attached data +*/ + +Handle(DDS_DicItem) DDS_Dictionary::GetDicItem( const TCollection_AsciiString& theID ) const +{ + Handle(DDS_DicItem) aDicItem; + for ( Standard_Integer i = 1; i <= myGroupMap.Extent() && aDicItem.IsNull(); i++ ) + aDicItem = myGroupMap.FindFromIndex( i )->GetDicItem( theID ); + return aDicItem; +} + +void DDS_Dictionary::FillDataMap( const LDOM_Element& theComponentData, const LDOM_Element& theDocElement ) +{ + TCollection_AsciiString aCompName = theComponentData.getAttribute( KeyWord( "COMPONENT_NAME" ) ); + if ( !myGroupMap.Contains( aCompName ) ) + myGroupMap.Add( aCompName, new DDS_DicGroup( aCompName ) ); + Handle(DDS_DicGroup) aDicGroup = myGroupMap.FindFromKey( aCompName ); + aDicGroup->FillDataMap( theComponentData, theDocElement ); + myGroupMap.Add( aCompName, aDicGroup ); +} + +Standard_Real DDS_Dictionary::ToSI( const Standard_Real theValue, const Standard_CString theUnits ) +{ + Standard_Real aRetValue = theValue; + if ( theUnits && *theUnits && strcmp( theUnits, "%" ) ) + { + try { + aRetValue = UnitsAPI::AnyToSI( theValue, theUnits ); + } + catch( Standard_Failure ) { + } + } + else if ( theUnits && *theUnits ) + aRetValue = theValue / 100.0; + + return aRetValue; +} + +Standard_Real DDS_Dictionary::FromSI( const Standard_Real theValue, const Standard_CString theUnits ) +{ + Standard_Real aRetValue = theValue; + if ( theUnits && *theUnits && strcmp( theUnits, "%" ) ) + { + try { + aRetValue = UnitsAPI::AnyFromSI( theValue, theUnits ); + } + catch( Standard_Failure ) { + } + } + else if ( theUnits && *theUnits ) + aRetValue = theValue * 100.0; + + return aRetValue; +} diff --git a/src/DDS/DDS_Dictionary.h b/src/DDS/DDS_Dictionary.h new file mode 100644 index 000000000..d58a15f76 --- /dev/null +++ b/src/DDS/DDS_Dictionary.h @@ -0,0 +1,64 @@ +#ifndef DDS_DICTIONARY_H +#define DDS_DICTIONARY_H + +#include "DDS_DicGroup.h" + +#include + +#include + +class LDOM_Element; +class TCollection_AsciiString; + +DEFINE_STANDARD_HANDLE(DDS_Dictionary, MMgt_TShared) + +// Class to provide information about used parameters, +// reading them from 'xml' file +class DDS_Dictionary : public MMgt_TShared +{ +public: + Standard_EXPORT static Handle(DDS_Dictionary) Get(); + + // Return instance of data dictionary. Create instance if it is NULL. + + Standard_EXPORT Handle(DDS_DicItem) GetDicItem( const TCollection_AsciiString& ) const; + Standard_EXPORT Handle(DDS_DicItem) GetDicItem( const TCollection_AsciiString&, + const TCollection_AsciiString& ) const; + + Standard_EXPORT void GetUnitSystems( TColStd_SequenceOfAsciiString& ) const; + Standard_EXPORT void GetUnitSystems( TColStd_SequenceOfAsciiString&, + const TCollection_AsciiString& ) const; + Standard_EXPORT TCollection_ExtendedString GetUnitSystemLabel( const TCollection_AsciiString& ) const; + Standard_EXPORT TCollection_ExtendedString GetUnitSystemLabel( const TCollection_AsciiString&, + const TCollection_AsciiString& ) const; + Standard_EXPORT TCollection_AsciiString GetActiveUnitSystem() const; + Standard_EXPORT TCollection_AsciiString GetActiveUnitSystem( const TCollection_AsciiString& ) const; + Standard_EXPORT void SetActiveUnitSystem( const TCollection_AsciiString& ); + Standard_EXPORT void SetActiveUnitSystem( const TCollection_AsciiString&, + const TCollection_AsciiString& ); + + + static Standard_EXPORT Standard_Boolean Load( const TCollection_AsciiString ); + + static Standard_EXPORT Standard_Real ToSI( const Standard_Real, const Standard_CString ); + static Standard_EXPORT Standard_Real FromSI( const Standard_Real, const Standard_CString ); + + static Standard_EXPORT LDOMString KeyWord( const TCollection_AsciiString& ); + +private: + DDS_Dictionary(); + DDS_Dictionary( const DDS_Dictionary& ); + + void operator=( const DDS_Dictionary& ); + + // prepares formants for each unit systems + void FillDataMap( const LDOM_Element&, const LDOM_Element& ); + +private: + DDS_IndexedDataMapOfDicGroups myGroupMap; + +public: + DEFINE_STANDARD_RTTI(DDS_Dictionary) +}; + +#endif diff --git a/src/DDS/DDS_KeyWords.cxx b/src/DDS/DDS_KeyWords.cxx new file mode 100644 index 000000000..2f53d2a92 --- /dev/null +++ b/src/DDS/DDS_KeyWords.cxx @@ -0,0 +1,83 @@ +#include "DDS_KeyWords.h" + +IMPLEMENT_STANDARD_HANDLE(DDS_KeyWords, MMgt_TShared) +IMPLEMENT_STANDARD_RTTIEXT(DDS_KeyWords, MMgt_TShared) + +DDS_KeyWords::DDS_KeyWords() +: MMgt_TShared() +{ + SetKeyWord( "D_URI", "dictionary" ); + + SetKeyWord( "COMPONENT", "component" ); + SetKeyWord( "COMPONENT_NAME", "name" ); + + SetKeyWord( "UNIT_SYSTEMS", "unitSystems" ); + SetKeyWord( "UNIT_SYSTEM", "system" ); + SetKeyWord( "UNIT_SYSTEM_NAME", "name" ); + SetKeyWord( "UNIT_SYSTEM_LABEL", "label" ); + + SetKeyWord( "DATUM", "datum" ); + SetKeyWord( "DATUM_ID", "id" ); + SetKeyWord( "DATUM_LABEL", "label" ); + SetKeyWord( "DATUM_UNITS", "units" ); + SetKeyWord( "DATUM_FORMAT", "format" ); + SetKeyWord( "DATUM_FILTER", "filter" ); + SetKeyWord( "DATUM_REQUIRED", "required" ); + + SetKeyWord( "VALUE_LIST", "valueList" ); + SetKeyWord( "VALUE_LIST_ID", "listid" ); + SetKeyWord( "VALUE_LIST_NAME", "name" ); + SetKeyWord( "VALUE_LIST_TYPE", "type" ); + SetKeyWord( "VALUE_LIST_VALUE", "value" ); + SetKeyWord( "VALUE_LIST_VALUEID", "id" ); + SetKeyWord( "VALUE_LIST_VALUEICON", "icon" ); + + SetKeyWord( "DY_DOMAIN", "domain" ); + SetKeyWord( "WARNING_LEVEL", "warningLevel" ); + SetKeyWord( "WRONG_VALUE", "wrongValue" ); + SetKeyWord( "VALUE_DESCR", "valueDescr" ); + SetKeyWord( "VALUE_LIST_REF", "listRef" ); + + SetKeyWord( "DESCR", "description" ); + SetKeyWord( "LONG_D", "longDescr" ); + SetKeyWord( "SHORT_D", "shortDescr" ); + + SetKeyWord( "VD_TYPE", "type" ); + SetKeyWord( "VD_DEFV", "default" ); + SetKeyWord( "VD_MAXV", "max" ); + SetKeyWord( "VD_MINV", "min" ); + SetKeyWord( "VD_SPEC", "specVal" ); + SetKeyWord( "VLR_LIST", "list" ); + SetKeyWord( "PRS", "presentation" ); + SetKeyWord( "LATERAL_ZOOM", "lateralZoom" ); + SetKeyWord( "LZ_MINV", "min" ); + SetKeyWord( "LZ_MAXV", "max" ); + SetKeyWord( "LZ_ORDER", "order" ); +} + +Handle(DDS_KeyWords) DDS_KeyWords::Get() +{ + static Handle(DDS_KeyWords) keyWords; + + if ( keyWords.IsNull() ) + keyWords = new DDS_KeyWords(); + + return keyWords; +} + +TCollection_AsciiString DDS_KeyWords::GetKeyWord( const TCollection_AsciiString& key ) const +{ + TCollection_AsciiString keyWord; + if ( myKeyWord.IsBound( key ) ) + keyWord = myKeyWord.Find( key ); + return keyWord; +} + +void DDS_KeyWords::SetKeyWord( const TCollection_AsciiString& key, + const TCollection_AsciiString& keyWord ) +{ + if ( myKeyWord.IsBound( key ) ) + myKeyWord.UnBind( key ); + + myKeyWord.Bind( key, keyWord ); +} diff --git a/src/DDS/DDS_KeyWords.h b/src/DDS/DDS_KeyWords.h new file mode 100644 index 000000000..2c1faf914 --- /dev/null +++ b/src/DDS/DDS_KeyWords.h @@ -0,0 +1,37 @@ +#ifndef DDS_KEYWORDS_H +#define DDS_KEYWORDS_H + +#include "DDS.h" + +#include + +#include + +DEFINE_STANDARD_HANDLE(DDS_KeyWords, MMgt_TShared) + +class TCollection_AsciiString; + +class DDS_KeyWords: public MMgt_TShared +{ +public: + Standard_EXPORT static Handle(DDS_KeyWords) Get(); + + Standard_EXPORT TCollection_AsciiString GetKeyWord( const TCollection_AsciiString& ) const; + Standard_EXPORT void SetKeyWord( const TCollection_AsciiString&, + const TCollection_AsciiString& ); + +private: + DDS_KeyWords(); + +private: + typedef NCollection_DataMap KeyWordMap; + +private: + KeyWordMap myKeyWord; + +public: + DEFINE_STANDARD_RTTI(DDS_KeyWords) +}; + +#endif diff --git a/src/DDS/Makefile.in b/src/DDS/Makefile.in new file mode 100755 index 000000000..a3b9eb89f --- /dev/null +++ b/src/DDS/Makefile.in @@ -0,0 +1,34 @@ +# File : Makefile.in +# Author : Alexander SOLOVYOV (OCN) +# Module : DDS +# $Header: /home/server/cvs/GUI/GUI_SRC/src/DDS/Makefile.in + +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +VPATH=.:@srcdir@ + +@COMMENCE@ + +# header files +EXPORT_HEADERS= DDS.h \ + DDS_DicGroup.h \ + DDS_DicItem.h \ + DDS_Dictionary.h \ + DDS_KeyWords.h + +# Libraries targets +LIB = libDDS.la + +LIB_SRC= DDS_DicGroup.cxx \ + DDS_DicItem.cxx \ + DDS_Dictionary.cxx \ + DDS_KeyWords.cxx + +CPPFLAGS+= $(OCC_INCLUDES) + +LDFLAGS+= $(CAS_KERNEL) $(CAS_OCAF) + +@CONCLUDE@ + + diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx new file mode 100644 index 000000000..50f5fe543 --- /dev/null +++ b/src/LightApp/LightApp_Application.cxx @@ -0,0 +1,1955 @@ +// File: LightApp_Application.cxx +// Created: 6/20/2005 18:39:45 PM +// Author: Natalia Donis +// Copyright (C) CEA 2005 + +#include "PythonConsole_PyInterp.h" // WARNING! This include must be the first! + +#include "LightApp_Application.h" +#include "LightApp_WidgetContainer.h" +#include "LightApp_Module.h" +#include "LightApp_DataModel.h" +#include "LightApp_Study.h" +#include "LightApp_Preferences.h" +#include "LightApp_PreferencesDlg.h" +#include "LightApp_ModuleDlg.h" +#include "LightApp_AboutDlg.h" + +#include "LightApp_OBFilter.h" + +#include "LightApp_GLSelector.h" +#include "LightApp_OBSelector.h" +#include "LightApp_OCCSelector.h" +#include "LightApp_VTKSelector.h" +#include "LightApp_SelectionMgr.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIRST_HELP_ID 1000000 + +#include "SALOME_InteractiveObject.hxx" +#include "SALOME_ListIO.hxx" + +static const char* imageEmptyIcon[] = { +"20 20 1 1", +". c None", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"....................", +"...................."}; + +/*!Create new instance of LightApp_Application.*/ +extern "C" LIGHTAPP_EXPORT SUIT_Application* createApplication() +{ + return new LightApp_Application(); +} + +LightApp_Preferences* LightApp_Application::_prefs_ = 0; + +/* + Class : LightApp_Application + Description : Application containing LightApp module +*/ + +/*!Constructor.*/ +LightApp_Application::LightApp_Application() +: CAM_Application( false ), +myPrefs( 0 ) +{ + STD_TabDesktop* desk = new STD_TabDesktop(); + + setDesktop( desk ); + + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + QPixmap aLogo = aResMgr->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false ); + + desktop()->setIcon( aLogo ); + desktop()->setDockableMenuBar( true ); + desktop()->setDockableStatusBar( false ); + + // base logo (salome itself) + desktop()->addLogo( "_app_base", aResMgr->loadPixmap( "LightApp", tr( "APP_BASE_LOGO" ), false ) ); + // extra logo (salome-based application) + desktop()->addLogo( "_app_extra", aResMgr->loadPixmap( "LightApp", tr( "APP_EXTRA_LOGO" ), false ) ); + + clearViewManagers(); + + mySelMgr = new LightApp_SelectionMgr( this ); + + myAccel = new SUIT_Accel( desktop() ); + myAccel->setActionKey( SUIT_Accel::PanLeft, CTRL+Key_Left, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanRight, CTRL+Key_Right, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanUp, CTRL+Key_Up, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanDown, CTRL+Key_Down, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomIn, CTRL+Key_Plus, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomOut, CTRL+Key_Minus, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomFit, CTRL+Key_Asterisk, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateLeft, ALT+Key_Left, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateRight, ALT+Key_Right, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateUp, ALT+Key_Up, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateDown, ALT+Key_Down, OCCViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanLeft, CTRL+Key_Left, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanRight, CTRL+Key_Right, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanUp, CTRL+Key_Up, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::PanDown, CTRL+Key_Down, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomIn, CTRL+Key_Plus, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomOut, CTRL+Key_Minus, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::ZoomFit, CTRL+Key_Asterisk, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateLeft, ALT+Key_Left, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateRight, ALT+Key_Right, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateUp, ALT+Key_Up, VTKViewer_Viewer::Type() ); + myAccel->setActionKey( SUIT_Accel::RotateDown, ALT+Key_Down, VTKViewer_Viewer::Type() ); + + connect( mySelMgr, SIGNAL( selectionChanged() ), this, SLOT( onSelection() ) ); +} + +/*!Destructor. + *\li Save window geometry. + *\li Save desktop geometry. + *\li Save resource maneger. + *\li Delete selection manager. + */ +LightApp_Application::~LightApp_Application() +{ + saveWindowsGeometry(); + + if ( resourceMgr() ) + { + if ( desktop() ) + desktop()->saveGeometry( resourceMgr(), "desktop" ); + resourceMgr()->save(); + } + delete mySelMgr; +} + +/*!Start application.*/ +void LightApp_Application::start() +{ + if ( desktop() ) + desktop()->loadGeometry( resourceMgr(), "desktop" ); + + CAM_Application::start(); + + QAction* a = action( ViewWindowsId ); + if ( a && a->inherits( "QtxDockAction" ) ) + ((QtxDockAction*)a)->setAutoPlace( true ); + + updateWindows(); + updateViewManagers(); + + putInfo( "" ); + desktop()->statusBar()->message( "" ); +} + +/*!Gets application name.*/ +QString LightApp_Application::applicationName() const +{ + return tr( "APP_NAME" ); +} + +/*!Gets application version.*/ +QString LightApp_Application::applicationVersion() const +{ + static QString _app_version; + + if ( _app_version.isEmpty() ) + { + QString resVersion = tr( "APP_VERSION" ); + if ( resVersion != "APP_VERSION" ) + { + _app_version = resVersion; + } + else + { + QString path( ::getenv( "GUI_ROOT_DIR" ) ); + if ( !path.isEmpty() ) + path += QDir::separator(); + path += QString( "bin/salome/VERSION" ); + + QFile vf( path ); + if ( vf.open( IO_ReadOnly ) ) + { + QString line; + vf.readLine( line, 1024 ); + vf.close(); + + if ( !line.isEmpty() ) + { + while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) ) + line.remove( line.length() - 1, 1 ); + + int idx = line.findRev( ":" ); + if ( idx != -1 ) + _app_version = line.mid( idx + 1 ).stripWhiteSpace(); + } + } + } + } + return _app_version; +} + +/*!Load module by \a name.*/ +CAM_Module* LightApp_Application::loadModule( const QString& name ) +{ + CAM_Module* mod = CAM_Application::loadModule( name ); + if ( mod ) + { + connect( this, SIGNAL( studyOpened() ), mod, SLOT( onModelOpened() ) ); + connect( this, SIGNAL( studySaved() ), mod, SLOT( onModelSaved() ) ); + connect( this, SIGNAL( studyClosed() ), mod, SLOT( onModelClosed() ) ); + } + return mod; +} + +/*!Activate module by \a modName*/ +bool LightApp_Application::activateModule( const QString& modName ) +{ + QString actName; + CAM_Module* prevMod = activeModule(); + + if ( prevMod ) + actName = prevMod->moduleName(); + + if ( actName == modName ) + return true; + + putInfo( tr( "ACTIVATING_MODULE" ).arg( modName ) ); + + saveWindowsGeometry(); + + bool status = CAM_Application::activateModule( modName ); + + updateModuleActions(); + + putInfo( "" ); + + if ( !status ) + return false; + + updateWindows(); + updateViewManagers(); + + return true; +} + +bool LightApp_Application::useStudy(const QString& theName) +{ + createEmptyStudy(); + LightApp_Study* aStudy = dynamic_cast(activeStudy()); + bool res = false; + if (aStudy) + res = aStudy->loadDocument( theName ); + updateDesktopTitle(); + updateCommandsStatus(); + return res; +} + +/*!Gets selection manager.*/ +LightApp_SelectionMgr* LightApp_Application::selectionMgr() const +{ + return mySelMgr; +} + +/*!Create actions:*/ +void LightApp_Application::createActions() +{ + STD_Application::createActions(); + + SUIT_Desktop* desk = desktop(); + SUIT_ResourceMgr* resMgr = resourceMgr(); + + //! Preferences + createAction( PreferencesId, tr( "TOT_DESK_PREFERENCES" ), QIconSet(), + tr( "MEN_DESK_PREFERENCES" ), tr( "PRP_DESK_PREFERENCES" ), + CTRL+Key_F, desk, false, this, SLOT( onPreferences() ) ); + + //! Help for modules + int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 ); + int helpModuleMenu = createMenu( tr( "MEN_DESK_MODULE_HELP" ), helpMenu, -1, 0 ); + createMenu( separator(), helpMenu, -1, 1 ); + + QStringList aModuleList; + modules( aModuleList, false ); + + int id = LightApp_Application::UserID + FIRST_HELP_ID; + // help for KERNEL and GUI + QCString dir; + QString aFileName; + QString root; + QAction* a; + if (dir = getenv("GUI_ROOT_DIR")) { + aFileName = "GUI_index_v3.1.0.html"; + root = Qtx::addSlash( Qtx::addSlash(dir) + Qtx::addSlash("doc") + Qtx::addSlash("salome") ); + if ( QFileInfo( root + aFileName ).exists() ) { + a = createAction( id, tr( QString("Kernel & GUI Help") ), QIconSet(), + tr( QString("Kernel && GUI Help") ), + tr( QString("Kernel & GUI Help") ), + 0, desk, false, this, SLOT( onHelpContentsModule() ) ); + a->setName( QString("GUI") ); + createMenu( a, helpModuleMenu, -1 ); + id++; + } + } + // help for other existing modules + QStringList::Iterator it; + for ( it = aModuleList.begin(); it != aModuleList.end(); ++it ) + { + if ( (*it).isEmpty() ) + continue; + + QString modName = moduleName( *it ); + aFileName = modName + "_index_v3.1.0.html"; + + if (dir = getenv( modName + "_ROOT_DIR")) { + root = Qtx::addSlash( Qtx::addSlash(dir) + Qtx::addSlash("doc") + Qtx::addSlash("salome") ); + if ( QFileInfo( root + aFileName ).exists() ) { + + QAction* a = createAction( id, tr( moduleTitle(modName) + QString(" Help") ), QIconSet(), + tr( moduleTitle(modName) + QString(" Help") ), + tr( moduleTitle(modName) + QString(" Help") ), + 0, desk, false, this, SLOT( onHelpContentsModule() ) ); + a->setName( modName ); + createMenu( a, helpModuleMenu, -1 ); + id++; + } + } + } + + //! MRU + QtxMRUAction* mru = new QtxMRUAction( tr( "TOT_DESK_MRU" ), tr( "MEN_DESK_MRU" ), desk ); + connect( mru, SIGNAL( activated( QString ) ), this, SLOT( onMRUActivated( QString ) ) ); + registerAction( MRUId, mru ); + + // default icon for neutral point ('SALOME' module) + QPixmap defIcon = resMgr->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false ); + if ( defIcon.isNull() ) + defIcon = QPixmap( imageEmptyIcon ); + + //! default icon for any module + QPixmap modIcon = resMgr->loadPixmap( "LightApp", tr( "APP_MODULE_ICO" ), false ); + if ( modIcon.isNull() ) + modIcon = QPixmap( imageEmptyIcon ); + + QToolBar* modTBar = new QtxToolBar( true, desk ); + modTBar->setLabel( tr( "INF_TOOLBAR_MODULES" ) ); + + QActionGroup* modGroup = new QActionGroup( this ); + modGroup->setExclusive( true ); + modGroup->setUsesDropDown( true ); + + a = createAction( -1, tr( "APP_NAME" ), defIcon, tr( "APP_NAME" ), + tr( "PRP_APP_MODULE" ), 0, desk, true ); + modGroup->add( a ); + myActions.insert( QString(), a ); + + QMap iconMap; + moduleIconNames( iconMap ); + + const int iconSize = 20; + + modGroup->addTo( modTBar ); + QObjectList *l = modTBar->queryList( "QComboBox" ); + QObjectListIt oit( *l ); + while ( QObject* obj = oit.current() ) { + QComboBox* cb = (QComboBox*)obj; + if ( cb ) cb->setFocusPolicy( QWidget::NoFocus ); + ++oit; + } + delete l; + + modTBar->addSeparator(); + + QStringList modList; + modules( modList, false ); + + for ( it = modList.begin(); it != modList.end(); ++it ) + { + if ( (*it).isEmpty() ) + continue; + + QString iconName; + if ( iconMap.contains( *it ) ) + iconName = iconMap[*it]; + + QString modName = moduleName( *it ); + + QPixmap icon = resMgr->loadPixmap( modName, iconName, false ); + if ( icon.isNull() ) + icon = modIcon; + + icon.convertFromImage( icon.convertToImage().smoothScale( iconSize, iconSize, QImage::ScaleMin ) ); + + QAction* a = createAction( -1, *it, icon, *it, tr( "PRP_MODULE" ).arg( *it ), 0, desk, true ); + a->addTo( modTBar ); + modGroup->add( a ); + + myActions.insert( *it, a ); + } + + SUIT_Tools::simplifySeparators( modTBar ); + + // New window + int windowMenu = createMenu( tr( "MEN_DESK_WINDOW" ), -1, 100 ); + int newWinMenu = createMenu( tr( "MEN_DESK_NEWWINDOW" ), windowMenu, -1, 0 ); + createMenu( separator(), windowMenu, -1, 1 ); + + QMap accelMap; + accelMap[NewGLViewId] = ALT+Key_G; + accelMap[NewPlot2dId] = ALT+Key_P; + accelMap[NewOCCViewId] = ALT+Key_O; + accelMap[NewVTKViewId] = ALT+Key_K; + + for ( id = NewGLViewId; id <= NewVTKViewId; id++ ) + { + QAction* a = createAction( id, tr( QString( "NEW_WINDOW_%1" ).arg( id - NewGLViewId ) ), QIconSet(), + tr( QString( "NEW_WINDOW_%1" ).arg( id - NewGLViewId ) ), + tr( QString( "NEW_WINDOW_%1" ).arg( id - NewGLViewId ) ), + accelMap.contains( id ) ? accelMap[id] : 0, desk, false, this, SLOT( onNewWindow() ) ); + createMenu( a, newWinMenu, -1 ); + } + + createAction( RenameId, tr( "TOT_RENAME" ), QIconSet(), tr( "MEN_DESK_RENAME" ), tr( "PRP_RENAME" ), + SHIFT+Key_R, desk, false, this, SLOT( onRenameWindow() ) ); + createMenu( RenameId, windowMenu, -1 ); + + connect( modGroup, SIGNAL( selected( QAction* ) ), this, SLOT( onModuleActivation( QAction* ) ) ); + + int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 ); + createMenu( PreferencesId, fileMenu, 15, -1 ); + createMenu( separator(), fileMenu, -1, 15, -1 ); + + /* + createMenu( separator(), fileMenu, -1, 100, -1 ); + createMenu( MRUId, fileMenu, 100, -1 ); + createMenu( separator(), fileMenu, -1, 100, -1 ); + */ +} + +/*!On module activation action.*/ +void LightApp_Application::onModuleActivation( QAction* a ) +{ + if ( !a ) + return; + + QString modName = a->menuText(); + if ( modName == tr( "APP_NAME" ) ) + modName = QString::null; + + // Force user to create/open a study before module activation + QMap iconMap; + moduleIconNames( iconMap ); + QPixmap icon = resourceMgr()->loadPixmap( moduleName( modName ), iconMap[ modName ], false ); + if ( icon.isNull() ) + icon = resourceMgr()->loadPixmap( "LightApp", tr( "APP_MODULE_BIG_ICO" ), false ); // default icon for any module + + bool cancelled = false; + while ( !modName.isEmpty() && !activeStudy() && !cancelled ){ + LightApp_ModuleDlg aDlg( desktop(), modName, icon ); + int res = aDlg.exec(); + + switch ( res ){ + case 1: + onNewDoc(); + break; + case 2: + onOpenDoc(); + break; + case 3: + //onLoadStudy(); + //break; + case 0: + default: + putInfo( tr("INF_CANCELLED") ); + myActions[QString()]->setOn( true ); + cancelled = true; + } + } + + if ( !cancelled ) + activateModule( modName ); +} + +/*!Default module activation.*/ +QString LightApp_Application::defaultModule() const +{ + QStringList aModuleNames; + modules( aModuleNames, false ); // obtain a complete list of module names for the current configuration + //! If there's the one and only module --> activate it automatically + //! TODO: Possible improvement - default module can be taken from preferences + return aModuleNames.count() > 1 ? "" : ( aModuleNames.count() ? aModuleNames.first() : "" ); +} + +/*!On new window slot.*/ +void LightApp_Application::onNewWindow() +{ + const QObject* obj = sender(); + if ( !obj || !obj->inherits( "QAction" ) ) + return; + + QString type; + int id = actionId( (QAction*)obj ); + switch ( id ) + { + case NewGLViewId: + type = GLViewer_Viewer::Type(); + break; + case NewPlot2dId: + type = Plot2d_Viewer::Type(); + break; + case NewOCCViewId: + type = OCCViewer_Viewer::Type(); + break; + case NewVTKViewId: + type = VTKViewer_Viewer::Type(); + break; + } + + if ( !type.isEmpty() ) + createViewManager( type ); +} + +//======================================================================= +// name : onNewDoc +/*! Purpose : SLOT. Create new document*/ +//======================================================================= +void LightApp_Application::onNewDoc() +{ + SUIT_Study* study = activeStudy(); + + saveWindowsGeometry(); + + CAM_Application::onNewDoc(); + + if ( !study ) // new study will be create in THIS application + { + updateWindows(); + updateViewManagers(); + } +} + +//======================================================================= +// name : onOpenDoc +/*! Purpose : SLOT. Open new document*/ +//======================================================================= +void LightApp_Application::onOpenDoc() +{ + SUIT_Study* study = activeStudy(); + saveWindowsGeometry(); + + CAM_Application::onOpenDoc(); + + if ( !study ) // new study will be create in THIS application + { + updateWindows(); + updateViewManagers(); + } +} + +#include "SUIT_MessageBox.h" +/*! Purpose : SLOT. Open new document with \a aName.*/ +bool LightApp_Application::onOpenDoc( const QString& aName ) +{ + bool isAlreadyOpen = false; + + // Look among opened studies + if (activeStudy()) { // at least one study is opened + SUIT_Session* aSession = SUIT_Session::session(); + QPtrList aAppList = aSession->applications(); + QPtrListIterator it (aAppList); + SUIT_Application* aApp = 0; + // iterate on all applications + for (; (aApp = it.current()) && !isAlreadyOpen; ++it) { + if (aApp->activeStudy()->studyName() == aName) { + isAlreadyOpen = true; // Already opened, ask user what to do + + // The document ... is already open. + // Do you want to reload it? + int aAnswer = SUIT_MessageBox::warn2(desktop(), tr("WRN_WARNING"), + tr("QUE_DOC_ALREADYOPEN").arg(aName), + tr("BUT_YES"), tr("BUT_NO"), 1, 2, 2); + if (aAnswer == 1) { // reload + if (activeStudy()->studyName() == aName && aAppList.count() > 1) { + // Opened in THIS (active) application. + STD_Application* app1 = (STD_Application*)aAppList.at(0); + STD_Application* app2 = (STD_Application*)aAppList.at(1); + if (!app1 || !app2) { + // Error + return false; + } + if (app1->activeStudy()->studyName() == aName) { + // app1 is this application, we need another one + app1 = app2; + } + // Close document of this application. This application will be destroyed. + onCloseDoc(/*ask = */false); + // Open the file with another application, as this one will be destroyed. + return app1->onOpenDoc(aName); + } else { + // Opened in another application. + STD_Application* app = (STD_Application*)aApp; + if (app) + app->onCloseDoc(/*ask = */false); + } + } else { // do not reload + // OK, the study will not be reloaded, but we call + // CAM_Application::onOpenDoc( aName ) all the same. + // It will activate a desktop of the study . + } + } + } + } + + bool res = CAM_Application::onOpenDoc( aName ); + + QAction* a = action( MRUId ); + if ( a && a->inherits( "QtxMRUAction" ) ) + { + QtxMRUAction* mru = (QtxMRUAction*)a; + if ( res ) + mru->insert( aName ); + else + mru->remove( aName ); + } + return res; +} + +//======================================================================= +// name : onHelpAbout +/*! Purpose : SLOT. Display "About" message box*/ +//======================================================================= +void LightApp_Application::onHelpAbout() +{ + LightApp_AboutDlg* dlg = new LightApp_AboutDlg( applicationName(), applicationVersion(), desktop() ); + dlg->exec(); + delete dlg; +} + +/*!SLOT. Load document with \a aName.*/ +bool LightApp_Application::onLoadDoc( const QString& aName ) +{ + bool res = CAM_Application::onLoadDoc( aName ); + + /*jfa tmp:QAction* a = action( MRUId ); + if ( a && a->inherits( "QtxMRUAction" ) ) + { + QtxMRUAction* mru = (QtxMRUAction*)a; + if ( res ) + mru->insert( aName ); + else + mru->remove( aName ); + }*/ + return res; +} + +/*!Private SLOT. Selection.*/ +void LightApp_Application::onSelection() +{ + onSelectionChanged(); + + if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) ) + ((LightApp_Module*)activeModule())->selectionChanged(); +} + +/*!Set active study. + *\param study - SUIT_Study. + */ +void LightApp_Application::setActiveStudy( SUIT_Study* study ) +{ + CAM_Application::setActiveStudy( study ); + + activateWindows(); +} + +//======================================================================= +// name : updateCommandsStatus +/*! Purpose : Enable/Disable menu items and toolbar buttons. Rebuild menu*/ +//======================================================================= +void LightApp_Application::updateCommandsStatus() +{ + CAM_Application::updateCommandsStatus(); + + for ( int id = NewGLViewId; id <= NewVTKViewId; id++ ) + { + QAction* a = action( id ); + if ( a ) + a->setEnabled( activeStudy() ); + } +} + +// Helps to execute command +class RunBrowser: public QThread { +public: + + RunBrowser(QString theApp, QString theParams, QString theHelpFile, QString theContext=NULL): + myApp(theApp), myParams(theParams), +#ifdef WIN32 + myHelpFile("file://" + theHelpFile + theContext), +#else + myHelpFile("file:" + theHelpFile + theContext), +#endif + myStatus(0) {}; + + virtual void run() + { + QString aCommand; + + if ( !myApp.isEmpty()) + { + aCommand.sprintf("%s %s %s",myApp.latin1(),myParams.latin1(),myHelpFile.latin1()); + myStatus = system(aCommand); + if(myStatus != 0) + { + QCustomEvent* ce2000 = new QCustomEvent (2000); + postEvent (qApp, ce2000); + } + } + if( myStatus != 0) + { + qApp->lock(); + SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"), + QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").arg(myApp).arg(myHelpFile), + QObject::tr("BUT_OK")); + qApp->unlock(); + } + } + +private: + QString myApp; + QString myParams; + QString myHelpFile; + int myStatus; + +}; + +//======================================================================= +// name : onHelpContentsModule +/*! Purpose : SLOT. Display help contents for choosen module*/ +//======================================================================= +void LightApp_Application::onHelpContentsModule() +{ + const QAction* obj = (QAction*) sender(); + + QString aComponentName = obj->name(); + QString aFileName = aComponentName + "_index_v3.1.0.html"; + + QCString dir = getenv( aComponentName + "_ROOT_DIR"); + QString homeDir = Qtx::addSlash( Qtx::addSlash(dir) + Qtx::addSlash("doc") + Qtx::addSlash("salome") ); + + QString helpFile = QFileInfo( homeDir + aFileName ).absFilePath(); + SUIT_ResourceMgr* resMgr = resourceMgr(); + QString anApp = resMgr->stringValue("ExternalBrowser", "application"); + QString aParams = resMgr->stringValue("ExternalBrowser", "parameters"); + + if (!anApp.isEmpty()) { + RunBrowser* rs = new RunBrowser(anApp, aParams, helpFile); + rs->start(); + } + else { + SUIT_MessageBox::warn1(desktop(), tr("WRN_WARNING"), + tr("DEFINE_EXTERNAL_BROWSER"), + tr("BUT_OK")); + } +} + +/*!Sets enable or disable some actions on selection changed.*/ +void LightApp_Application::onSelectionChanged() +{ +} + +/*!Return window. + *\param flag - key for window + *\param studyId - study id + * Flag used how identificator of window in windows list. + */ +QWidget* LightApp_Application::window( const int flag, const int studyId ) const +{ + QWidget* wid = 0; + + int sId = studyId; + if ( sId < 0 ) + { + if ( !activeStudy() ) + return 0; + else + sId = activeStudy()->id(); + } + + if ( myWindows.contains( flag ) ) + wid = myWindows[flag]->widget( sId ); + + return wid; +} + +/*!Adds window to application. + *\param wid - QWidget + *\param flag - key wor window + *\param studyId - study id + * Flag used how identificator of window in windows list. + */ +void LightApp_Application::addWindow( QWidget* wid, const int flag, const int studyId ) +{ + if ( !wid ) + return; + + int sId = studyId; + if ( sId < 0 ) + { + if ( !activeStudy() ) + return; + else + sId = activeStudy()->id(); + } + + if ( !myWindows.contains( flag ) ) + { + QMap winMap; + currentWindows( winMap ); + + LightApp_WidgetContainer* newWC = new LightApp_WidgetContainer( flag, desktop() ); + connect( newWC, SIGNAL( destroyed ( QObject* ) ), this, SLOT( onWCDestroyed( QObject* ) ) ); + myWindows.insert( flag, newWC ); + if ( winMap.contains( flag ) ) + desktop()->moveDockWindow( myWindows[flag], (Dock)winMap[flag] ); + + myWindows[flag]->setResizeEnabled( true ); + myWindows[flag]->setCloseMode( QDockWindow::Always ); + myWindows[flag]->setName( QString( "dock_window_%1" ).arg( flag ) ); + myWindows[flag]->setFixedExtentWidth( wid->width() ); + myWindows[flag]->setFixedExtentHeight( wid->height() ); + } + + QFont f; + if( wid->inherits( "PythonConsole" ) ) + { + if( resourceMgr()->hasValue( "PyConsole", "font" ) ) + f = resourceMgr()->fontValue( "PyConsole", "font" ); + else + { + f = ( ( PythonConsole* )wid )->font(); + resourceMgr()->setValue( "PyConsole", "font", f ); + } + } + else + f = wid->font(); + + myWindows[flag]->insert( sId, wid ); + wid->setFont(f); + + setWindowShown( flag, !myWindows[flag]->isEmpty() ); +} + +/*!Remove window from application. + *\param flag - key wor window + *\param studyId - study id + * Flag used how identificator of window in windows list. + */ +void LightApp_Application::removeWindow( const int flag, const int studyId ) +{ + if ( !myWindows.contains( flag ) ) + return; + + int sId = studyId; + if ( sId < 0 ) + { + if ( !activeStudy() ) + return; + else + sId = activeStudy()->id(); + } + + QWidget* wid = myWindows[flag]->widget( sId ); + myWindows[flag]->remove( sId ); + delete wid; + + setWindowShown( flag, !myWindows[flag]->isEmpty() ); +} + +/*!Gets window. + *\param flag - key wor window + *\param studyId - study id + * Flag used how identificator of window in windows list. + */ +QWidget* LightApp_Application::getWindow( const int flag, const int studyId ) +{ + QWidget* wid = window( flag, studyId ); + if ( !wid ) + addWindow( wid = createWindow( flag ), flag, studyId ); + + return wid; +} + +/*!Check is window visible?(with identificator \a type)*/ +bool LightApp_Application::isWindowVisible( const int type ) const +{ + bool res = false; + if ( myWindows.contains( type ) ) + { + SUIT_Desktop* desk = ((LightApp_Application*)this)->desktop(); + res = desk && desk->appropriate( myWindows[type] ); + } + return res; +} + +/*!Sets window show or hide. + *\param type - window identificator. + *\param on - true/false (window show/hide) + */ +void LightApp_Application::setWindowShown( const int type, const bool on ) +{ + if ( !desktop() || !myWindows.contains( type ) ) + return; + + QDockWindow* dw = myWindows[type]; + desktop()->setAppropriate( dw, on ); + on ? dw->show() : dw->hide(); +} + +/*!Gets "ObjectBrowser".*/ +OB_Browser* LightApp_Application::objectBrowser() +{ + OB_Browser* ob = 0; + QWidget* wid = window( WT_ObjectBrowser ); + if ( wid && wid->inherits( "OB_Browser" ) ) + ob = (OB_Browser*)wid; + return ob; +} + +/*!Gets "LogWindow".*/ +LogWindow* LightApp_Application::logWindow() +{ + LogWindow* lw = 0; + QWidget* wid = getWindow( WT_LogWindow ); + if ( wid->inherits( "LogWindow" ) ) + lw = (LogWindow*)wid; + return lw; +} + +/*!Get "PythonConsole"*/ +PythonConsole* LightApp_Application::pythonConsole() +{ + PythonConsole* console = 0; + QWidget* wid = getWindow( WT_PyConsole ); + if ( wid->inherits( "PythonConsole" ) ) + console = (PythonConsole*)wid; + return console; +} + +/*!Update obect browser*/ +void LightApp_Application::updateObjectBrowser( const bool updateModels ) +{ + // update existing data models + if ( updateModels ) + { + LightApp_Study* study = dynamic_cast(activeStudy()); + if ( study ) { + CAM_Study::ModelList dm_list; + study->dataModels( dm_list ); + for ( CAM_Study::ModelListIterator it( dm_list ); it.current(); ++it ) { + CAM_DataModel* camDM = it.current(); + if ( camDM && camDM->inherits( "LightApp_DataModel" ) ) + ((LightApp_DataModel*)camDM)->update(); + } + } + } + if ( objectBrowser() ) + { + objectBrowser()->updateGeometry(); + objectBrowser()->updateTree( 0, false ); + } +} + +/*!Gets preferences.*/ +LightApp_Preferences* LightApp_Application::preferences() const +{ + return preferences( false ); +} + +/*!Gets view manager*/ +SUIT_ViewManager* LightApp_Application::getViewManager( const QString& vmType, const bool create ) +{ + SUIT_ViewManager* aVM = viewManager( vmType ); + SUIT_ViewManager* anActiveVM = CAM_Application::activeViewManager(); + + if ( anActiveVM && anActiveVM->getType() == vmType ) + aVM = anActiveVM; + + if ( aVM && create ) + { + if ( !aVM->getActiveView() ) + aVM->createView(); + else + aVM->getActiveView()->setFocus(); + } + else if ( create ) + aVM = createViewManager( vmType ); + + return aVM; +} + +/*!Create view manager.*/ +SUIT_ViewManager* LightApp_Application::createViewManager( const QString& vmType ) +{ + SUIT_ResourceMgr* resMgr = resourceMgr(); + + SUIT_ViewManager* viewMgr = 0; + if( vmType == GLViewer_Viewer::Type() ) + { + viewMgr = new GLViewer_ViewManager( activeStudy(), desktop() ); + new LightApp_GLSelector( (GLViewer_Viewer2d*)viewMgr->getViewModel(), mySelMgr ); + } + else if( vmType == Plot2d_Viewer::Type() ) + { + viewMgr = new Plot2d_ViewManager( activeStudy(), desktop() ); + SPlot2d_Viewer* vm = new SPlot2d_Viewer(); + viewMgr->setViewModel( vm );// custom view model, which extends SALOME_View interface + Plot2d_ViewWindow* wnd = dynamic_cast( viewMgr->getActiveView() ); + if( wnd ) + { + Plot2d_ViewFrame* frame = wnd->getViewFrame(); + frame->setBackgroundColor( resMgr->colorValue( "Plot2d", "Background", frame->backgroundColor() ) ); + } + } + else if( vmType == SUPERVGraph_Viewer::Type() ) + { + viewMgr = new SUPERVGraph_ViewManager( activeStudy(), desktop() ); + SUPERVGraph_Viewer* vm = new SUPERVGraph_Viewer(); + SUPERVGraph_ViewFrame* view = dynamic_cast( vm->getViewManager()->getActiveView() ); + if( view ) + view->setBackgroundColor( resMgr->colorValue( "SUPERVGraph", "Background", view->backgroundColor() ) ); + } + else if( vmType == OCCViewer_Viewer::Type() ) + { + viewMgr = new OCCViewer_ViewManager( activeStudy(), desktop() ); + SOCC_Viewer* vm = new SOCC_Viewer(); + vm->setBackgroundColor( resMgr->colorValue( "OCCViewer", "background", vm->backgroundColor() ) ); + vm->setTrihedronSize( resMgr->integerValue( "OCCViewer", "trihedron_size", vm->trihedronSize() ) ); + int u( 1 ), v( 1 ); + vm->isos( u, v ); + u = resMgr->integerValue( "OCCViewer", "iso_number_u", u ); + v = resMgr->integerValue( "OCCViewer", "iso_number_v", v ); + vm->setIsos( u, v ); + viewMgr->setViewModel( vm );// custom view model, which extends SALOME_View interface + new LightApp_OCCSelector( (OCCViewer_Viewer*)viewMgr->getViewModel(), mySelMgr ); + } + else if ( vmType == SVTK_Viewer::Type() ) + { + viewMgr = new SVTK_ViewManager( activeStudy(), desktop() ); + SVTK_Viewer* vm = dynamic_cast( viewMgr->getViewModel() ); + if( vm ) + { + vm->setBackgroundColor( resMgr->colorValue( "VTKViewer", "background", vm->backgroundColor() ) ); + vm->setTrihedronSize( resMgr->integerValue( "VTKViewer", "trihedron_size", vm->trihedronSize() ) ); + new LightApp_VTKSelector( vm, mySelMgr ); + } + } + + if ( !viewMgr ) + return 0; + + addViewManager( viewMgr ); + SUIT_ViewWindow* viewWin = viewMgr->createViewWindow(); + + if ( viewWin && desktop() ) + viewWin->resize( (int)( desktop()->width() * 0.6 ), (int)( desktop()->height() * 0.6 ) ); + + connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), + this, SLOT( onCloseView( SUIT_ViewManager* ) ) ); + + return viewMgr; +} + +//======================================================================= +// name : onCloseView +/*! Purpose : SLOT. Remove view manager from application*/ +//======================================================================= +void LightApp_Application::onCloseView( SUIT_ViewManager* theVM ) +{ + removeViewManager( theVM ); +} + +/*!Protected SLOT. On study created.*/ +void LightApp_Application::onStudyCreated( SUIT_Study* theStudy ) +{ + SUIT_DataObject* aRoot = 0; + if ( theStudy && theStudy->root() ) + { + aRoot = theStudy->root(); + //aRoot->setName( tr( "DATA_MODELS" ) ); + } + getWindow( WT_ObjectBrowser ); + if ( objectBrowser() != 0 ) + objectBrowser()->setRootObject( aRoot ); + + activateModule( defaultModule() ); + + activateWindows(); +} + +/*!Protected SLOT. On study opened.*/ +void LightApp_Application::onStudyOpened( SUIT_Study* theStudy ) +{ + SUIT_DataObject* aRoot = 0; + if ( theStudy && theStudy->root() ) + { + aRoot = theStudy->root(); + //aRoot->dump(); + } + getWindow( WT_ObjectBrowser ); + if ( objectBrowser() != 0 ) { + objectBrowser()->setRootObject( aRoot ); + } + + activateModule( defaultModule() ); + + activateWindows(); + + emit studyOpened(); +} + +/*!Protected SLOT. On study saved.*/ +void LightApp_Application::onStudySaved( SUIT_Study* ) +{ + emit studySaved(); +} + +/*!Protected SLOT. On study closed.*/ +void LightApp_Application::onStudyClosed( SUIT_Study* ) +{ + emit studyClosed(); + + // Bug 10396: clear selection + mySelMgr->clearSelected(); + + activateModule( "" ); + + saveWindowsGeometry(); +} + +/*!Protected SLOT.On desktop activated.*/ +void LightApp_Application::onDesktopActivated() +{ + CAM_Application::onDesktopActivated(); + LightApp_Module* aModule = dynamic_cast(activeModule()); + if(aModule) + aModule->studyActivated(); +} + +/*!Gets file filter. + *\retval QString "(*.bin)" + */ +QString LightApp_Application::getFileFilter() const +{ + return "(*.bin)"; +} + +/*! Gets file name*/ +QString LightApp_Application::getFileName( bool open, const QString& initial, const QString& filters, + const QString& caption, QWidget* parent ) +{ + if ( !parent ) + parent = desktop(); + QStringList fls = QStringList::split( ";;", filters, false ); + return SUIT_FileDlg::getFileName( parent, initial, fls, caption, open, true ); +} + +/*! Gets directory*/ +QString LightApp_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent ) +{ + if ( !parent ) + parent = desktop(); + return SUIT_FileDlg::getExistingDirectory( parent, initial, caption, true ); +} + +/*! Get open file names*/ +QStringList LightApp_Application::getOpenFileNames( const QString& initial, const QString& filters, + const QString& caption, QWidget* parent ) +{ + if ( !parent ) + parent = desktop(); + QStringList fls = QStringList::split( ";;", filters, false ); + return SUIT_FileDlg::getOpenFileNames( parent, initial, fls, caption, true ); +} + +/*!Private SLOT. Update object browser.*/ +void LightApp_Application::onRefresh() +{ + updateObjectBrowser( true ); +} + +/*!Private SLOT. On preferences.*/ +void LightApp_Application::onPreferences() +{ + QApplication::setOverrideCursor( Qt::waitCursor ); + + LightApp_PreferencesDlg* prefDlg = new LightApp_PreferencesDlg( preferences( true ), desktop()); + + QApplication::restoreOverrideCursor(); + + if ( !prefDlg ) + return; + + if ( ( prefDlg->exec() == QDialog::Accepted || prefDlg->isSaved() ) && resourceMgr() ) { + if ( desktop() ) + desktop()->saveGeometry( resourceMgr(), "desktop" ); + resourceMgr()->save(); + } + + delete prefDlg; +} + +/*!Protected SLOT. On preferences changed.*/ +void LightApp_Application::onPreferenceChanged( QString& modName, QString& section, QString& param ) +{ + LightApp_Module* sMod = 0; + CAM_Module* mod = module( modName ); + if ( mod && mod->inherits( "LightApp_Module" ) ) + sMod = (LightApp_Module*)mod; + + if ( sMod ) + sMod->preferencesChanged( section, param ); + else + preferencesChanged( section, param ); +} + +/*!Private SLOT. On open document with name \a aName.*/ +void LightApp_Application::onMRUActivated( QString aName ) +{ + onOpenDoc( aName ); +} + +/*!Remove all windows from study.*/ +void LightApp_Application::beforeCloseDoc( SUIT_Study* s ) +{ + CAM_Application::beforeCloseDoc( s ); + + for ( WindowMap::ConstIterator itr = myWindows.begin(); s && itr != myWindows.end(); ++itr ) + removeWindow( itr.key(), s->id() ); +} + +/*!Update actions.*/ +void LightApp_Application::updateActions() +{ + updateCommandsStatus(); +} + +//======================================================================= +// name : createNewStudy +/*! Purpose : Create new study*/ +//======================================================================= +SUIT_Study* LightApp_Application::createNewStudy() +{ + LightApp_Study* aStudy = new LightApp_Study( this ); + + // Set up processing of major study-related events + connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) ); + + return aStudy; +} + +/*!Create window.*/ +QWidget* LightApp_Application::createWindow( const int flag ) +{ + QWidget* wid = 0; + if ( flag == WT_ObjectBrowser ) + { + OB_Browser* ob = new OB_Browser( desktop() ); + ob->setAutoUpdate( true ); + ob->setAutoOpenLevel( 1 ); + ob->setCaption( tr( "OBJECT_BROWSER" ) ); + + OB_ListView* ob_list = dynamic_cast( const_cast( ob->listView() ) ); + if( ob_list ) + ob_list->setColumnMaxWidth( 0, desktop()->width()/4 ); + + ob->setFilter( new LightApp_OBFilter( selectionMgr() ) ); + ob->setNameTitle( tr( "OBJ_BROWSER_NAME" ) ); + + // Create OBSelector + new LightApp_OBSelector( ob, mySelMgr ); + + wid = ob; + + ob->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + } + else if ( flag == WT_PyConsole ) + { + PythonConsole* pyCons = new PythonConsole( desktop() ); + pyCons->setCaption( tr( "PYTHON_CONSOLE" ) ); + wid = pyCons; + // pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + } + else if ( flag == WT_LogWindow ) + { + LogWindow* logWin = new LogWindow( desktop() ); + logWin->setCaption( tr( "LOG_WINDOW" ) ); + wid = logWin; + logWin->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + } + return wid; +} + +/*!Default windows(Object Browser, Python Console). + * Adds to map \a aMap. + */ +void LightApp_Application::defaultWindows( QMap& aMap ) const +{ + aMap.insert( WT_ObjectBrowser, Qt::DockLeft ); + aMap.insert( WT_PyConsole, Qt::DockBottom ); + // aMap.insert( WT_LogWindow, Qt::DockBottom ); +} + +/*!Default view manager.*/ +void LightApp_Application::defaultViewManagers( QStringList& ) const +{ + /*!Do nothing.*/ +} + +/*!Gets preferences. + * Create preferences, if \a crt = true. + */ +LightApp_Preferences* LightApp_Application::preferences( const bool crt ) const +{ + if ( myPrefs ) + return myPrefs; + + LightApp_Application* that = (LightApp_Application*)this; + + bool toCreate = !_prefs_ && crt; + if( toCreate ) + { + _prefs_ = new LightApp_Preferences( resourceMgr() ); + that->createPreferences( _prefs_ ); + } + + that->myPrefs = _prefs_; + + QPtrList appList = SUIT_Session::session()->applications(); + for ( QPtrListIterator appIt ( appList ); appIt.current(); ++appIt ) + { + if ( !appIt.current()->inherits( "LightApp_Application" ) ) + continue; + + LightApp_Application* app = (LightApp_Application*)appIt.current(); + + QStringList modNameList; + app->modules( modNameList, false ); + for ( QStringList::const_iterator it = modNameList.begin(); it != modNameList.end(); ++it ) + { + int id = _prefs_->addPreference( *it ); + _prefs_->setItemProperty( id, "info", tr( "PREFERENCES_NOT_LOADED" ).arg( *it ) ); + } + + ModuleList modList; + app->modules( modList ); + for ( ModuleListIterator itr( modList ); itr.current(); ++itr ) + { + LightApp_Module* mod = 0; + if ( itr.current()->inherits( "LightApp_Module" ) ) + mod = (LightApp_Module*)itr.current(); + + if ( mod && !_prefs_->hasModule( mod->moduleName() ) ) + { + int modCat = _prefs_->addPreference( mod->moduleName() ); + _prefs_->setItemProperty( modCat, "info", QString::null ); + if( toCreate ) + mod->createPreferences(); + } + } + } + + connect( myPrefs, SIGNAL( preferenceChanged( QString&, QString&, QString& ) ), + this, SLOT( onPreferenceChanged( QString&, QString&, QString& ) ) ); + + return myPrefs; +} + +/*!Add new module to application.*/ +void LightApp_Application::moduleAdded( CAM_Module* mod ) +{ + CAM_Application::moduleAdded( mod ); + + LightApp_Module* lightMod = 0; + if ( mod && mod->inherits( "LightApp_Module" ) ) + lightMod = (LightApp_Module*)mod; + + if ( myPrefs && lightMod && !myPrefs->hasModule( lightMod->moduleName() )) + { + int modCat = myPrefs->addPreference( mod->moduleName() ); + myPrefs->setItemProperty( modCat, "info", QString::null ); + lightMod->createPreferences(); + } +} + +/*!Create preferences.*/ +void LightApp_Application::createPreferences( LightApp_Preferences* pref ) +{ + if ( !pref ) + return; + + int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) ); + + int genTab = pref->addPreference( tr( "PREF_TAB_GENERAL" ), salomeCat ); + int studyGroup = pref->addPreference( tr( "PREF_GROUP_STUDY" ), genTab ); + pref->setItemProperty( studyGroup, "columns", 1 ); + + pref->addPreference( tr( "PREF_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file" ); + pref->addPreference( tr( "PREF_ASCII_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "ascii_file" ); + int undoPref = pref->addPreference( tr( "PREF_UNDO_LEVEL" ), studyGroup, LightApp_Preferences::IntSpin, "Study", "undo_level" ); + pref->setItemProperty( undoPref, "min", 1 ); + pref->setItemProperty( undoPref, "max", 100 ); + pref->addPreference( tr( "PREF_STORE_POS" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_positions" ); + + int extgroup = pref->addPreference( tr( "PREF_GROUP_EXT_BROWSER" ), genTab ); + pref->setItemProperty( extgroup, "columns", 1 ); + int apppref = pref->addPreference( tr( "PREF_APP" ), extgroup, LightApp_Preferences::File, "ExternalBrowser", "application" ); + pref->setItemProperty( apppref, "existing", true ); + pref->setItemProperty( apppref, "flags", QFileInfo::ExeUser ); + pref->setItemProperty( apppref, "readOnly", false ); + + pref->addPreference( tr( "PREF_PARAM" ), extgroup, LightApp_Preferences::String, "ExternalBrowser", "parameters" ); + + int pythonConsoleGroup = pref->addPreference( tr( "PREF_GROUP_PY_CONSOLE" ), genTab ); + pref->setItemProperty( pythonConsoleGroup, "columns", 1 ); + pref->addPreference( tr( "PREF_FONT" ), pythonConsoleGroup, LightApp_Preferences::Font, "PyConsole", "font" ); + + int viewTab = pref->addPreference( tr( "PREF_TAB_VIEWERS" ), salomeCat ); + + int occGroup = pref->addPreference( tr( "PREF_GROUP_OCCVIEWER" ), viewTab ); + + int vtkGroup = pref->addPreference( tr( "PREF_GROUP_VTKVIEWER" ), viewTab ); + + int plot2dGroup = pref->addPreference( tr( "PREF_GROUP_PLOT2DVIEWER" ), viewTab ); + + int supervGroup = pref->addPreference( tr( "PREF_GROUP_SUPERV" ), viewTab ); + + pref->setItemProperty( occGroup, "columns", 1 ); + pref->setItemProperty( vtkGroup, "columns", 1 ); + pref->setItemProperty( plot2dGroup, "columns", 1 ); + + int occTS = pref->addPreference( tr( "PREF_TRIHEDRON_SIZE" ), occGroup, + LightApp_Preferences::IntSpin, "OCCViewer", "trihedron_size" ); + pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), occGroup, + LightApp_Preferences::Color, "OCCViewer", "background" ); + + pref->setItemProperty( occTS, "min", 1 ); + pref->setItemProperty( occTS, "max", 150 ); + + int isoU = pref->addPreference( tr( "PREF_ISOS_U" ), occGroup, + LightApp_Preferences::IntSpin, "OCCViewer", "iso_number_u" ); + int isoV = pref->addPreference( tr( "PREF_ISOS_V" ), occGroup, + LightApp_Preferences::IntSpin, "OCCViewer", "iso_number_v" ); + + pref->setItemProperty( isoU, "min", 0 ); + pref->setItemProperty( isoU, "max", 100000 ); + + pref->setItemProperty( isoV, "min", 0 ); + pref->setItemProperty( isoV, "max", 100000 ); + + int vtkTS = pref->addPreference( tr( "PREF_TRIHEDRON_SIZE" ), vtkGroup, + LightApp_Preferences::IntSpin, "VTKViewer", "trihedron_size" ); + pref->addPreference( tr( "PREF_RELATIVE_SIZE" ), vtkGroup, LightApp_Preferences::Bool, "VTKViewer", "relative_size" ); + pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), vtkGroup, + LightApp_Preferences::Color, "VTKViewer", "background" ); + + pref->setItemProperty( vtkTS, "min", 1 ); + pref->setItemProperty( vtkTS, "max", 150 ); + + pref->addPreference( tr( "PREF_SHOW_LEGEND" ), plot2dGroup, + LightApp_Preferences::Bool, "Plot2d", "ShowLegend" ); + + int legendPosition = pref->addPreference( tr( "PREF_LEGEND_POSITION" ), plot2dGroup, + LightApp_Preferences::Selector, "Plot2d", "LegendPos" ); + QStringList aLegendPosList; + aLegendPosList.append( tr("PREF_LEFT") ); + aLegendPosList.append( tr("PREF_RIGHT") ); + aLegendPosList.append( tr("PREF_TOP") ); + aLegendPosList.append( tr("PREF_BOTTOM") ); + + QValueList anIndexesList; + anIndexesList.append(0); + anIndexesList.append(1); + anIndexesList.append(2); + anIndexesList.append(3); + + pref->setItemProperty( legendPosition, "strings", aLegendPosList ); + pref->setItemProperty( legendPosition, "indexes", anIndexesList ); + + int curveType = pref->addPreference( tr( "PREF_CURVE_TYPE" ), plot2dGroup, + LightApp_Preferences::Selector, "Plot2d", "CurveType" ); + QStringList aCurveTypesList; + aCurveTypesList.append( tr("PREF_POINTS") ); + aCurveTypesList.append( tr("PREF_LINES") ); + aCurveTypesList.append( tr("PREF_SPLINE") ); + + anIndexesList.clear(); + anIndexesList.append(0); + anIndexesList.append(1); + anIndexesList.append(2); + + pref->setItemProperty( curveType, "strings", aCurveTypesList ); + pref->setItemProperty( curveType, "indexes", anIndexesList ); + + int markerSize = pref->addPreference( tr( "PREF_MARKER_SIZE" ), plot2dGroup, + LightApp_Preferences::IntSpin, "Plot2d", "MarkerSize" ); + + pref->setItemProperty( markerSize, "min", 0 ); + pref->setItemProperty( markerSize, "max", 100 ); + + QStringList aScaleModesList; + aScaleModesList.append( tr("PREF_LINEAR") ); + aScaleModesList.append( tr("PREF_LOGARITHMIC") ); + + anIndexesList.clear(); + anIndexesList.append(0); + anIndexesList.append(1); + + int horScale = pref->addPreference( tr( "PREF_HOR_AXIS_SCALE" ), plot2dGroup, + LightApp_Preferences::Selector, "Plot2d", "HorScaleMode" ); + + pref->setItemProperty( horScale, "strings", aScaleModesList ); + pref->setItemProperty( horScale, "indexes", anIndexesList ); + + int verScale = pref->addPreference( tr( "PREF_VERT_AXIS_SCALE" ), plot2dGroup, + LightApp_Preferences::Selector, "Plot2d", "VerScaleMode" ); + + pref->setItemProperty( verScale, "strings", aScaleModesList ); + pref->setItemProperty( verScale, "indexes", anIndexesList ); + + pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), plot2dGroup, + LightApp_Preferences::Color, "Plot2d", "Background" ); + + int dirTab = pref->addPreference( tr( "PREF_TAB_DIRECTORIES" ), salomeCat ); + int dirGroup = pref->addPreference( tr( "PREF_GROUP_DIRECTORIES" ), dirTab ); + pref->setItemProperty( dirGroup, "columns", 1 ); + pref->addPreference( tr( "" ), dirGroup, + LightApp_Preferences::DirList, "FileDlg", "QuickDirList" ); + + pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), supervGroup, + LightApp_Preferences::Color, "SUPERVGraph", "Background" ); + pref->addPreference( tr( "PREF_SUPERV_TITLE_COLOR" ), supervGroup, + LightApp_Preferences::Color, "SUPERVGraph", "Title" ); +// pref->addPreference( tr( "PREF_SUPERV_CTRL_COLOR" ), supervGroup, +// LightApp_Preferences::Color, "SUPERVGraph", "Ctrl" ); + + int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat ); + int objSetGroup = pref->addPreference( tr( "PREF_OBJ_BROWSER_SETTINGS" ), obTab ); + pref->addPreference( tr( "PREF_AUTO_SIZE_FIRST" ), objSetGroup, LightApp_Preferences::Bool, + "ObjectBrowser", "auto_size_first" ); + pref->addPreference( tr( "PREF_AUTO_SIZE" ), objSetGroup, LightApp_Preferences::Bool, + "ObjectBrowser", "auto_size" ); +} + +/*!Changed preferences */ +void LightApp_Application::preferencesChanged( const QString& sec, const QString& param ) +{ + SUIT_ResourceMgr* resMgr = resourceMgr(); + if ( !resMgr ) + return; + + if ( sec == QString( "OCCViewer" ) && param == QString( "trihedron_size" ) ) + { + int sz = resMgr->integerValue( sec, param, -1 ); + QPtrList lst; + viewManagers( OCCViewer_Viewer::Type(), lst ); + for ( QPtrListIterator it( lst ); it.current() && sz >= 0; ++it ) + { + SUIT_ViewModel* vm = it.current()->getViewModel(); + if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) ) + continue; + + OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm; + occVM->setTrihedronSize( sz ); + occVM->getAISContext()->UpdateCurrentViewer(); + } + } + + if ( sec == QString( "VTKViewer" ) && (param == QString( "trihedron_size" ) || param == QString( "relative_size" )) ) + { + int sz = resMgr->integerValue( "VTKViewer", "trihedron_size", -1 ); + QPtrList lst; + viewManagers( SVTK_Viewer::Type(), lst ); + for ( QPtrListIterator it( lst ); it.current() && sz >= 0; ++it ) + { + SUIT_ViewModel* vm = it.current()->getViewModel(); + if ( !vm || !vm->inherits( "SVTK_Viewer" ) ) + continue; + + SVTK_Viewer* vtkVM = dynamic_cast( vm ); + if( vtkVM ) + { + vtkVM->setTrihedronSize( sz ); + vtkVM->Repaint(); + } + } + } + + if ( sec == QString( "OCCViewer" ) && ( param == QString( "iso_number_u" ) || param == QString( "iso_number_v" ) ) ) + { + QPtrList lst; + viewManagers( OCCViewer_Viewer::Type(), lst ); + int u = resMgr->integerValue( sec, "iso_number_u" ); + int v = resMgr->integerValue( sec, "iso_number_v" ); + for ( QPtrListIterator it( lst ); it.current(); ++it ) + { + OCCViewer_ViewManager* mgr = dynamic_cast( it.current() ); + if( mgr && mgr->getOCCViewer() ) + mgr->getOCCViewer()->setIsos( u, v ); + } + } + + if( sec=="ObjectBrowser" ) + { + if( param=="auto_size" || param=="auto_size_first" ) + { + OB_Browser* ob = objectBrowser(); + if( !ob ) + return; + + bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false ), + autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true ); + ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual ); + ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual ); + updateObjectBrowser( false ); + } + } + + if( sec=="Study" ) + { + if( param=="store_positions" ) + updateWindows(); + } + + if( sec=="PyConsole" ) + { + if( param=="font" ) + if( pythonConsole() ) + pythonConsole()->setFont( resMgr->fontValue( "PyConsole", "font" ) ); + } +} + +/*!Update desktop title.*/ +void LightApp_Application::updateDesktopTitle() { + QString aTitle = applicationName(); + QString aVer = applicationVersion(); + if ( !aVer.isEmpty() ) + aTitle += QString( " " ) + aVer; + + desktop()->setCaption( aTitle ); +} + +/*!Update windows after close document.*/ +void LightApp_Application::afterCloseDoc() +{ + updateWindows(); + + CAM_Application::afterCloseDoc(); +} + +/*!Update module action.*/ +void LightApp_Application::updateModuleActions() +{ + QString modName; + if ( activeModule() ) + modName = activeModule()->moduleName(); + + if ( myActions.contains( modName ) ) + myActions[modName]->setOn( true ); +} + +/*!Gets current windows. + *\param winMap - output current windows map. + */ +void LightApp_Application::currentWindows( QMap& winMap ) const +{ + winMap.clear(); + if ( !activeStudy() ) + return; + + if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) ) + ((LightApp_Module*)activeModule())->windows( winMap ); + else + defaultWindows( winMap ); +} + +/*!Gets current view managers. + *\param lst - output current view managers list. + */ +void LightApp_Application::currentViewManagers( QStringList& lst ) const +{ + lst.clear(); + if ( !activeStudy() ) + return; + + if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) ) + ((LightApp_Module*)activeModule())->viewManagers( lst ); + else + defaultViewManagers( lst ); +} + +/*!Update windows.*/ +void LightApp_Application::updateWindows() +{ + QMap winMap; + currentWindows( winMap ); + + for ( QMap::ConstIterator it = winMap.begin(); it != winMap.end(); ++it ) + getWindow( it.key() ); + + loadWindowsGeometry(); + + for ( WindowMap::ConstIterator itr = myWindows.begin(); itr != myWindows.end(); ++itr ) + setWindowShown( itr.key(), !itr.data()->isEmpty() && winMap.contains( itr.key() ) ); +} + +/*!Update view managers.*/ +void LightApp_Application::updateViewManagers() +{ + QStringList lst; + currentViewManagers( lst ); + + for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it ) + getViewManager( *it, true ); +} + +/*!Load windows geometry.*/ +void LightApp_Application::loadWindowsGeometry() +{ + bool store = resourceMgr()->booleanValue( "Study", "store_positions", true ); + if( !store ) + return; + + QtxDockAction* dockMgr = 0; + + QAction* a = action( ViewWindowsId ); + if ( a && a->inherits( "QtxDockAction" ) ) + dockMgr = (QtxDockAction*)a; + + if ( !dockMgr ) + return; + + QString modName; + if ( activeModule() ) + modName = activeModule()->name(""); + + QString section = QString( "windows_geometry" ); + if ( !modName.isEmpty() ) + section += QString( "." ) + modName; + + dockMgr->loadGeometry( resourceMgr(), section, false ); + dockMgr->restoreGeometry(); +} + +/*!Save windows geometry.*/ +void LightApp_Application::saveWindowsGeometry() +{ + bool store = resourceMgr()->booleanValue( "Study", "store_positions", true ); + if( !store ) + return; + + QtxDockAction* dockMgr = 0; + + QAction* a = action( ViewWindowsId ); + if ( a && a->inherits( "QtxDockAction" ) ) + dockMgr = (QtxDockAction*)a; + + if ( !dockMgr ) + return; + + QString modName; + if ( activeModule() ) + modName = activeModule()->name(""); + + QString section = QString( "windows_geometry" ); + if ( !modName.isEmpty() ) + section += QString( "." ) + modName; + + dockMgr->storeGeometry(); + dockMgr->saveGeometry( resourceMgr(), section, false ); +} + +/*!Activate windows.*/ +void LightApp_Application::activateWindows() +{ + if ( activeStudy() ) + { + for ( WindowMap::Iterator itr = myWindows.begin(); itr != myWindows.end(); ++itr ) + itr.data()->activate( activeStudy()->id() ); + } +} + +/*!Adds icon names for modules.*/ +void LightApp_Application::moduleIconNames( QMap& iconMap ) const +{ + iconMap.clear(); + + SUIT_ResourceMgr* resMgr = resourceMgr(); + if ( !resMgr ) + return; + + QStringList modList; + modules( modList, false ); + + for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it ) + { + QString modName = *it; + QString modIntr = moduleName( modName ); + QString modIcon = resMgr->stringValue( modIntr, "icon", QString::null ); + + if ( modIcon.isEmpty() ) + continue; + + if ( SUIT_Tools::extension( modIcon ).isEmpty() ) + modIcon += QString( ".png" ); + + iconMap.insert( modName, modIcon ); + } +} + +/*!Insert items in popup, which necessary for current application*/ +void LightApp_Application::contextMenuPopup( const QString& type, QPopupMenu* thePopup, QString& title ) +{ + CAM_Application::contextMenuPopup( type, thePopup, title ); + + OB_Browser* ob = objectBrowser(); + if ( !ob || type != ob->popupClientType() ) + return; + + thePopup->insertSeparator(); + thePopup->insertItem( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) ); +} + +/*!Create empty study.*/ +void LightApp_Application::createEmptyStudy() +{ + CAM_Application::createEmptyStudy(); + if ( objectBrowser() ) + objectBrowser()->updateTree(); +} + +/*!Activate module \a mod.*/ +bool LightApp_Application::activateModule( CAM_Module* mod ) +{ + bool res = CAM_Application::activateModule( mod ); + if ( objectBrowser() ) + objectBrowser()->updateTree(); + return res; +} + +/*!return keyborad accelerators manager object */ +SUIT_Accel* LightApp_Application::accel() const +{ + return myAccel; +} + +/*! remove dead widget container from map */ +void LightApp_Application::onWCDestroyed( QObject* ob ) +{ + // remove destroyed widget container from windows map + for ( WindowMap::ConstIterator itr = myWindows.begin(); itr != myWindows.end(); ++itr ) + { + if ( itr.data() != ob ) + continue; + + int key = itr.key(); + myWindows.remove( key ); + break; + } +} + +/*! redefined to remove view manager from memory */ +void LightApp_Application::removeViewManager( SUIT_ViewManager* vm ) +{ + disconnect( vm, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), + this, SLOT( onCloseView( SUIT_ViewManager* ) ) ); + STD_Application::removeViewManager( vm ); + delete vm; +} + +/*! rename active window of desktop */ +void LightApp_Application::onRenameWindow() +{ + if( !desktop() ) + return; + + QWidget* w = desktop()->activeWindow(); + if( !w ) + return; + + bool ok; + QString name = QInputDialog::getText( tr( "TOT_RENAME" ), tr( "PRP_RENAME" ), QLineEdit::Normal, w->caption(), &ok, w ); + if( ok && !name.isEmpty() ) + w->setCaption( name ); +} diff --git a/src/LightApp/LightApp_DataObject.cxx b/src/LightApp/LightApp_DataObject.cxx new file mode 100644 index 000000000..831385908 --- /dev/null +++ b/src/LightApp/LightApp_DataObject.cxx @@ -0,0 +1,189 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "LightApp_DataObject.h" + +#include "LightApp_Study.h" +#include "LightApp_RootObject.h" + +#include "CAM_DataModel.h" +#include "CAM_Module.h" + +#include +#include +#include + +#include + +/*! + Class: LightApp_DataObject::Key + Level: Internal +*/ +class LightApp_DataObject::Key : public SUIT_DataObjectKey +{ +public: + Key( const QString& ); + virtual ~Key(); + + virtual bool isLess( const SUIT_DataObjectKey* ) const; + virtual bool isEqual( const SUIT_DataObjectKey* ) const; + +private: + QString myEntry; +}; + +/*!Constructor. Initialize by \a entry.*/ +LightApp_DataObject::Key::Key( const QString& entry ) +: SUIT_DataObjectKey(), + myEntry( entry ) +{ +} + +/*!Destructor. Do nothing.*/ +LightApp_DataObject::Key::~Key() +{ +} + +/*!Checks: Is current key less than \a other.*/ +bool LightApp_DataObject::Key::isLess( const SUIT_DataObjectKey* other ) const +{ + Key* that = (Key*)other; + return myEntry < that->myEntry; +} + +/*!Checks: Is current key equal with \a other.*/ +bool LightApp_DataObject::Key::isEqual( const SUIT_DataObjectKey* other ) const +{ + Key* that = (Key*)other; + return myEntry == that->myEntry; +} + +/* + Class: LightApp_DataObject + Level: Public +*/ +/*!Constructor. Initialize by \a parent*/ +LightApp_DataObject::LightApp_DataObject( SUIT_DataObject* parent ) +: CAM_DataObject( parent ), myCompObject( 0 ), myCompDataType( "" ) +{ +} + +/*!Destructor. Do nothing.*/ +LightApp_DataObject::~LightApp_DataObject() +{ +} + +/*!Gets object ID. + *\retval QString + */ +QString LightApp_DataObject::entry() const +{ + return QString::null; +} + +/*!Create and return new key object.*/ +SUIT_DataObjectKey* LightApp_DataObject::key() const +{ + QString str = entry(); + return new Key( str ); +} + +/*!Gets component object. + *\retval SUIT_DataObject. + */ +SUIT_DataObject* LightApp_DataObject::componentObject() const +{ + if ( !myCompObject ) { + SUIT_DataObject* compObj = 0; // for root object + + if ( parent() && parent() == root() ) + compObj = (SUIT_DataObject*)this; // for component-level objects + else + { + compObj = parent(); // for lower level objects + while ( compObj && compObj->parent() != root() ) + compObj = compObj->parent(); + } + LightApp_DataObject* that = (LightApp_DataObject*)this; + that->myCompObject = compObj; + } + return myCompObject; +} + +/*!Get component type.*/ +QString LightApp_DataObject::componentDataType() const +{ + if ( myCompDataType.isEmpty() ) { + SUIT_DataObject* aCompObj = componentObject(); + LightApp_ModuleObject* anObj = dynamic_cast( aCompObj ); + if ( anObj ) { + CAM_DataModel* aModel = anObj->dataModel(); + if ( aModel ) { + LightApp_DataObject* that = (LightApp_DataObject*)this; + that->myCompDataType = aModel->module()->name(); + } + } + } + return myCompDataType; +} + +/* + Class: LightApp_ModuleObject + Level: Public +*/ + +/*!Constructor.Initialize by \a parent.*/ +LightApp_ModuleObject::LightApp_ModuleObject( SUIT_DataObject* parent ) +: CAM_RootObject( parent ), + CAM_DataObject( parent ) +{ +} + +/*!Constructor.Initialize by \a module and parent.*/ +LightApp_ModuleObject::LightApp_ModuleObject( CAM_DataModel* dm, SUIT_DataObject* parent ) +: CAM_RootObject( dm, parent ), + CAM_DataObject( parent ) +{ +} + +/*!Destructor. Do nothing.*/ +LightApp_ModuleObject::~LightApp_ModuleObject() +{ +} + +/*!Returns module name */ +QString LightApp_ModuleObject::name() const +{ + return CAM_RootObject::name(); +} + +/*!Insert new child object to the children list at specified position + *\add component in Study for this module object if it necessary*/ +void LightApp_ModuleObject::insertChild( SUIT_DataObject* theObj, int thePosition ) +{ + CAM_RootObject::insertChild(theObj, thePosition); + + CAM_DataModel* aModel = dataModel(); + + LightApp_RootObject* aRoot = dynamic_cast(parent()); + + if (aRoot) + aRoot->study()->addComponent(aModel); + + +} diff --git a/src/LightApp/LightApp_DataObject.h b/src/LightApp/LightApp_DataObject.h new file mode 100644 index 000000000..1f194ffc2 --- /dev/null +++ b/src/LightApp/LightApp_DataObject.h @@ -0,0 +1,72 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef LIGHTAPP_DATAOBJECT_H +#define LIGHTAPP_DATAOBJECT_H + +#include "LightApp.h" + +#include "CAM_DataObject.h" +#include "CAM_DataModel.h" +#include "CAM_RootObject.h" + +class LightApp_Study; + +/*!Description : Data Object has empty entry so it's children must redefine metod entry() and return some unique string*/ +// to do : decomment virtual inheritance +class LIGHTAPP_EXPORT LightApp_DataObject : public virtual CAM_DataObject +{ + class Key; + +public: + enum { CT_Value, CT_Entry, CT_IOR, CT_RefEntry }; + +public: + LightApp_DataObject( SUIT_DataObject* = 0 ); + virtual ~LightApp_DataObject(); + + virtual SUIT_DataObjectKey* key() const; + virtual QString entry() const; + + virtual SUIT_DataObject* componentObject() const; + virtual QString componentDataType() const; + +protected: + QString myCompDataType; + SUIT_DataObject* myCompObject; +}; + +/*! + * LightApp_ModuleObject - class for optimized access to DataModel from + * CAM_RootObject.h. + * In modules which will be redefine LightApp_DataObject, LightApp_ModuleObject must be children from rederined DataObject for having necessary properties and children from LightApp_ModuleObject. + */ + +class LIGHTAPP_EXPORT LightApp_ModuleObject : public CAM_RootObject +{ +public: + LightApp_ModuleObject( SUIT_DataObject* = 0 ); + LightApp_ModuleObject ( CAM_DataModel*, SUIT_DataObject* = 0 ); + + virtual ~LightApp_ModuleObject(); + + virtual QString name() const; + virtual void insertChild( SUIT_DataObject*, int thePosition ); +}; + +#endif diff --git a/src/LightApp/LightApp_PreferencesDlg.cxx b/src/LightApp/LightApp_PreferencesDlg.cxx new file mode 100644 index 000000000..5d0f1ead4 --- /dev/null +++ b/src/LightApp/LightApp_PreferencesDlg.cxx @@ -0,0 +1,104 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: LightApp_PreferencesDlg.cxx +// Author: Sergey TELKOV + +#include "LightApp_PreferencesDlg.h" + +#include "LightApp_Preferences.h" + +#include +#include + +/*! + Constructor. +*/ +LightApp_PreferencesDlg::LightApp_PreferencesDlg( LightApp_Preferences* prefs, QWidget* parent ) +: QtxDialog( parent, 0, true, false, OK | Close | Apply ), +myPrefs( prefs ), mySaved ( false ) +{ + setCaption( tr( "CAPTION" ) ); + + QVBoxLayout* main = new QVBoxLayout( mainFrame(), 5 ); + + QVBox* base = new QVBox( mainFrame() ); + main->addWidget( base ); + + myPrefs->reparent( base, QPoint( 0, 0 ), true ); + + setFocusProxy( myPrefs ); + + setButtonPosition( Right, Close ); + + setDialogFlags( AlignOnce ); + + connect( this, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) ); + connect( this, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); +} + +/*! + Destructor. +*/ +LightApp_PreferencesDlg::~LightApp_PreferencesDlg() +{ + if ( !myPrefs ) + return; + + myPrefs->reparent( 0, QPoint( 0, 0 ), false ); + myPrefs = 0; +} + +/*!Show dialog.*/ +void LightApp_PreferencesDlg::show() +{ + myPrefs->retrieve(); + myPrefs->toBackup(); + + QtxDialog::show(); +} + +/*!Store preferences on accept.*/ +void LightApp_PreferencesDlg::accept() +{ + QtxDialog::accept(); + + myPrefs->store(); + mySaved = true; +} + +/*!Reject. Restore preferences from backup.*/ +void LightApp_PreferencesDlg::reject() +{ + QtxDialog::reject(); + + myPrefs->fromBackup(); +} + +/*!Do nothing.*/ +void LightApp_PreferencesDlg::onHelp() +{ +} + +/*!Store preferences on apply.*/ +void LightApp_PreferencesDlg::onApply() +{ + myPrefs->store(); + myPrefs->toBackup(); + mySaved = true; +} diff --git a/src/LightApp/LightApp_PreferencesDlg.h b/src/LightApp/LightApp_PreferencesDlg.h new file mode 100644 index 000000000..ea7bf55fe --- /dev/null +++ b/src/LightApp/LightApp_PreferencesDlg.h @@ -0,0 +1,55 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: LightApp_PreferencesDlg.h +// Author: Sergey TELKOV + +#ifndef LIGHTAPP_PREFERENCESDLG_H +#define LIGHTAPP_PREFERENCESDLG_H + +#include + +#include + +class LightApp_Preferences; + +class LIGHTAPP_EXPORT LightApp_PreferencesDlg : public QtxDialog +{ + Q_OBJECT + +public: + LightApp_PreferencesDlg( LightApp_Preferences*, QWidget* = 0 ); + virtual ~LightApp_PreferencesDlg(); + + virtual void show(); + virtual void accept(); + virtual void reject(); + + bool isSaved() { return mySaved; } + void setSaved( bool saved ) { mySaved = saved; } + +private slots: + void onHelp(); + void onApply(); + +private: + LightApp_Preferences* myPrefs; + bool mySaved; +}; + +#endif diff --git a/src/LightApp/LightApp_Selection.cxx b/src/LightApp/LightApp_Selection.cxx new file mode 100644 index 000000000..bca35cfec --- /dev/null +++ b/src/LightApp/LightApp_Selection.cxx @@ -0,0 +1,246 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#include "LightApp_Selection.h" +#include "LightApp_SelectionMgr.h" +#include "LightApp_DataOwner.h" +#include "LightApp_Study.h" +#include "LightApp_Application.h" +#include "LightApp_Displayer.h" + +#include "SUIT_Session.h" +#include "SUIT_ViewWindow.h" + +/*! + Constructor +*/ +LightApp_Selection::LightApp_Selection() +: myStudy( 0 ) +{ +} + +/*! + Destructor. +*/ +LightApp_Selection::~LightApp_Selection() +{ +} + +/*! + Initialization. +*/ +void LightApp_Selection::init( const QString& client, LightApp_SelectionMgr* mgr) +{ + myPopupClient = client; + myStudy = 0; + + if( mgr ) + { + if( mgr->application() ) + myStudy = dynamic_cast( mgr->application()->activeStudy() ); + if( !myStudy ) + return; + + //1) to take owners from current popup client + SUIT_DataOwnerPtrList sel( true ), cur_sel( true ); + mgr->selected( sel, client ); + + //2) to take such owners from other popup clients that it's entry is different with every entry from current list + QPtrList aSelectors; + mgr->selectors( aSelectors ); + for( SUIT_Selector* selector = aSelectors.first(); selector; selector = aSelectors.next() ) + { + qDebug( selector->type() ); + if( selector->type()!=client ) + { + mgr->selected( cur_sel, selector->type() ); + SUIT_DataOwnerPtrList::const_iterator aLIt = cur_sel.begin(), aLLast = cur_sel.end(); + for( ; aLIt!=aLLast; aLIt++ ) + sel.append( *aLIt ); //check entry and don't append if such entry is in list already + } + } + + //3) to analyse owner and fill internal data structures + SUIT_DataOwnerPtrList::const_iterator anIt = sel.begin(), aLast = sel.end(); + QMap entries; + QString entry; + int num=0; + for( ; anIt!=aLast; anIt++ ) + { + LightApp_DataOwner* sowner = dynamic_cast( (*anIt ).get() ); + if( sowner ) + { + if( entries.contains( sowner->entry() ) ) + continue; + + entry = myStudy->referencedToEntry( sowner->entry() ); + entries.insert( entry, 0 ); + myEntries.insert( num, entry ); + myIsReferences.insert( num, sowner->entry() == entry ); + processOwner( sowner ); + num++; + } + } + } +} + +/*! + Gets count of entries. +*/ +int LightApp_Selection::count() const +{ + return myEntries.count(); +} + +/*! + Gets QtxValue(); +*/ +QtxValue LightApp_Selection::param( const int ind, const QString& p ) const +{ + LightApp_Application* app = dynamic_cast( myStudy ? myStudy->application() : 0 ); + if( !( ind>=0 && indmoduleTitle( param( ind, "component" ).toString() ); + LightApp_Displayer* d = LightApp_Displayer::FindDisplayer( mod_name, false ); + // false in last parameter means that now we doesn't load module, if it isn't loaded + + bool vis = false; + if( d ) + vis = d->IsDisplayed( myEntries[ ind ] ); + else + { + LightApp_Displayer local_d; + vis = local_d.IsDisplayed( myEntries[ ind ] ); + } + return QtxValue( vis, 0 ); + } + + else if( p=="component" ) + { + return myStudy->componentDataType( myEntries[ ind ] ); + } + + else if( p=="isComponent" ) + { + return QtxValue( myStudy->isComponent( myEntries[ ind ] ), 0 ); + } + + else if( p=="isReference" ) + return QtxValue( isReference( ind ), false ); + + else if( p=="canBeDisplayed" ) + { + QString mod_name = app->moduleTitle( param( ind, "component" ).toString() ); + LightApp_Displayer* d = LightApp_Displayer::FindDisplayer( mod_name, false ); + // false in last parameter means that now we doesn't load module, if it isn't loaded + + return QtxValue( d ? d->canBeDisplayed( myEntries[ ind ] ) : true, 0 ); + //now if displayer is null, it means, that according module isn't loaded, so that we allow to all display/erase + //operations under object + } + + return QtxValue(); +} + +/*! + Gets global parameters. client, isActiveView, activeView etc. +*/ +QtxValue LightApp_Selection::globalParam( const QString& p ) const +{ + if ( p == "client" ) return QtxValue( myPopupClient ); + else if ( p == "activeModule" ) + { + LightApp_Application* app = dynamic_cast( myStudy->application() ); + QString mod_name = app ? QString( app->activeModule()->name() ) : QString::null; + //cout << "activeModule : " << mod_name.latin1() << endl; + if( !mod_name.isEmpty() ) + return mod_name; + else + return QtxValue(); + } + else if ( p == "isActiveView" ) return QtxValue( (bool)activeVW() ); + else if ( p == "activeView" ) return QtxValue( activeViewType() ); +#ifndef WNT + else return QtxPopupMgr::Selection::globalParam( p ); +#else + else return Selection::globalParam( p ); +#endif +} + +/*! + Do nothing. To be redefined by successors +*/ +void LightApp_Selection::processOwner( const LightApp_DataOwner* ) +{ +} + +/*! + Gets entry with index \a index. +*/ +QString LightApp_Selection::entry( const int index ) const +{ + if ( index >= 0 && index < count() ) + return myEntries[ index ]; + return QString(); +} + +/*! + Returns true if i-th selected object was reference to object with entry( i ) +*/ +bool LightApp_Selection::isReference( const int index ) const +{ + if( index >= 0 && index < count() ) + return myIsReferences[ index ]; + else + return false; +} + +/*! + Gets type of active view manager. +*/ +QString LightApp_Selection::activeViewType() const +{ + SUIT_ViewWindow* win = activeVW(); + if ( win ) { + SUIT_ViewManager* vm = win->getViewManager(); + if ( vm ) + return vm->getType(); + } + return QString::null; +} + +/*! + Gets active view window. +*/ +SUIT_ViewWindow* LightApp_Selection::activeVW() const +{ + SUIT_Session* session = SUIT_Session::session(); + if ( session ) { + SUIT_Application* app = session->activeApplication(); + if ( app ) { + SUIT_Desktop* desk = app->desktop(); + if ( desk ) + return desk->activeWindow(); + } + } + return 0; +} diff --git a/src/LightApp/LightApp_Selection.h b/src/LightApp/LightApp_Selection.h new file mode 100644 index 000000000..79cc0fac6 --- /dev/null +++ b/src/LightApp/LightApp_Selection.h @@ -0,0 +1,70 @@ +// LightApp_Selection +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : LightApp_Selection.h +// Author : Alexander SOLOVYOV +// Module : GUI +// $Header$ + +#ifndef LIGHTAPP_SELECTION_HeaderFile +#define LIGHTAPP_SELECTION_HeaderFile + +#include "LightApp.h" +#include + +class LightApp_SelectionMgr; +class LightApp_DataOwner; +class LightApp_Study; +class SUIT_ViewWindow; + + +class LIGHTAPP_EXPORT LightApp_Selection : public QtxPopupMgr::Selection +{ +public: + LightApp_Selection(); + virtual ~LightApp_Selection(); + + virtual void init( const QString&, LightApp_SelectionMgr* ); + virtual void processOwner( const LightApp_DataOwner* ); + + virtual int count() const; + virtual QtxValue param( const int, const QString& ) const; + virtual QtxValue globalParam( const QString& ) const; + void setModuleName( const QString ); + +protected: + QString entry( const int ) const; + bool isReference( const int ) const; + /*!Gets study.*/ + LightApp_Study* study() const { return myStudy; } + QString activeViewType() const; + SUIT_ViewWindow* activeVW() const; + +private: + QString myPopupClient; + QMap myEntries; // entries of selected objects + QMap myIsReferences; // whether i-th selected object was a reference + LightApp_Study* myStudy; +}; + +#endif diff --git a/src/LightApp/LightApp_ShowHideOp.cxx b/src/LightApp/LightApp_ShowHideOp.cxx new file mode 100644 index 000000000..52f16266f --- /dev/null +++ b/src/LightApp/LightApp_ShowHideOp.cxx @@ -0,0 +1,124 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#include "LightApp_ShowHideOp.h" +#include "LightApp_Application.h" +#include "LightApp_DataOwner.h" +#include "LightApp_Module.h" +#include "LightApp_Study.h" +#include "LightApp_Displayer.h" +#include "CAM_Study.h" + +#include "LightApp_SelectionMgr.h" +#include "LightApp_Selection.h" + +#include +#include + +LightApp_ShowHideOp::LightApp_ShowHideOp( ActionType type ) +: LightApp_Operation(), + myActionType( type ) +{ +} + +LightApp_ShowHideOp::~LightApp_ShowHideOp() +{ +} + +void LightApp_ShowHideOp::startOperation() +{ + LightApp_Application* app = dynamic_cast( application() ); + LightApp_Study* study = app ? dynamic_cast( app->activeStudy() ) : 0; + if( !app || !study ) + { + abort(); + return; + } + + LightApp_SelectionMgr* mgr = app->selectionMgr(); + LightApp_Selection sel; sel.init( "", mgr ); + if( sel.count()==0 && myActionType!=ERASE_ALL ) + { + abort(); + return; + } + + QString mod_name; + if( sel.count()>0 ) + { + QString aStr = sel.param( 0, "component" ).toString(); + mod_name = app->moduleTitle( aStr ); + } + else if( app->activeModule() ) + mod_name = app->moduleTitle( app->activeModule()->name() ); + + LightApp_Displayer* d = LightApp_Displayer::FindDisplayer( mod_name, true ); + if( !d ) + { + abort(); + return; + } + + if( myActionType==DISPLAY_ONLY || myActionType==ERASE_ALL ) + { + //ERASE ALL + QStringList comps; + study->components( comps ); + QStringList::const_iterator anIt = comps.begin(), aLast = comps.end(); + for( ; anIt!=aLast; anIt++ ) + { + LightApp_Displayer* disp = LightApp_Displayer::FindDisplayer( app->moduleTitle( *anIt ), true ); + if( disp ) + disp->EraseAll( false, false, 0 ); + } + if( myActionType==ERASE_ALL ) + { + d->UpdateViewer(); + commit(); + return; + } + } + + SALOME_ListIO selObjs; + mgr->selectedObjects( selObjs ); + + QStringList entries; + SALOME_ListIteratorOfListIO anIt( selObjs ); + for( ; anIt.More(); anIt.Next() ) + { + if( anIt.Value().IsNull() ) + continue; + + if( study->isComponent( anIt.Value()->getEntry() ) ) + study->children( anIt.Value()->getEntry(), entries ); + else + entries.append( anIt.Value()->getEntry() ); + } + + for( QStringList::const_iterator it = entries.begin(), last = entries.end(); it!=last; it++ ) + { + QString e = study->referencedToEntry( *it ); + if( myActionType==DISPLAY || myActionType==DISPLAY_ONLY ) + d->Display( e, false, 0 ); + else if( myActionType==ERASE ) + d->Erase( e, false, false, 0 ); + } + d->UpdateViewer(); + commit(); +} diff --git a/src/LightApp/Makefile.in b/src/LightApp/Makefile.in new file mode 100755 index 000000000..092b071f7 --- /dev/null +++ b/src/LightApp/Makefile.in @@ -0,0 +1,113 @@ +# File : Makefile.in +# Author : OCC team (OCN) +# Module : LightApp +# $Header$ + +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@srcdir@/resources + + +@COMMENCE@ + +# header files +EXPORT_HEADERS= LightApp.h \ + LightApp_AboutDlg.h \ + LightApp_Application.h \ + LightApp_DataModel.h \ + LightApp_DataObject.h \ + LightApp_DataOwner.h \ + LightApp_DataSubOwner.h \ + LightApp_Dialog.h \ + LightApp_Displayer.h \ + LightApp_Driver.h \ + LightApp_GLSelector.h \ + LightApp_Module.h \ + LightApp_ModuleDlg.h \ + LightApp_NameDlg.h \ + LightApp_OBFilter.h \ + LightApp_OBSelector.h \ + LightApp_OCCSelector.h \ + LightApp_Operation.h \ + LightApp_Selection.h \ + LightApp_SelectionMgr.h \ + LightApp_ShowHideOp.h \ + LightApp_Study.h \ + LightApp_SwitchOp.h \ + LightApp_Preferences.h \ + LightApp_PreferencesDlg.h \ + LightApp_RootObject.h \ + LightApp_UpdateFlags.h \ + LightApp_VTKSelector.h \ + LightApp_WidgetContainer.h + +# .po files to transform in .qm +PO_FILES = LightApp_images.po \ + LightApp_msg_en.po + +# Libraries targets +LIB = libLightApp.la + +LIB_SRC= LightApp_AboutDlg.cxx \ + LightApp_Application.cxx \ + LightApp_DataModel.cxx \ + LightApp_DataObject.cxx \ + LightApp_DataOwner.cxx \ + LightApp_DataSubOwner.cxx \ + LightApp_Dialog.cxx \ + LightApp_Displayer.cxx \ + LightApp_Driver.cxx \ + LightApp_GLSelector.cxx \ + LightApp_Module.cxx \ + LightApp_ModuleDlg.cxx \ + LightApp_NameDlg.cxx \ + LightApp_OBFilter.cxx \ + LightApp_OBSelector.cxx \ + LightApp_OCCSelector.cxx \ + LightApp_Operation.cxx \ + LightApp_Selection.cxx \ + LightApp_SelectionMgr.cxx \ + LightApp_ShowHideOp.cxx \ + LightApp_Study.cxx \ + LightApp_SwitchOp.cxx \ + LightApp_Preferences.cxx \ + LightApp_PreferencesDlg.cxx \ + LightApp_VTKSelector.cxx \ + LightApp_WidgetContainer.cxx + +LIB_MOC = LightApp_AboutDlg.h \ + LightApp_Application.h \ + LightApp_DataModel.h \ + LightApp_Dialog.h \ + LightApp_GLSelector.h \ + LightApp_OBSelector.h \ + LightApp_OCCSelector.h \ + LightApp_Operation.h \ + LightApp_Module.h \ + LightApp_ModuleDlg.h \ + LightApp_NameDlg.h \ + LightApp_SelectionMgr.h \ + LightApp_ShowHideOp.h \ + LightApp_Study.h \ + LightApp_SwitchOp.h \ + LightApp_Preferences.h \ + LightApp_PreferencesDlg.h \ + LightApp_VTKSelector.h \ + LightApp_WidgetContainer.h + +RESOURCES_FILES = icon_about.png \ + icon_applogo.png \ + icon_default.png \ + icon_module.png \ + icon_module_big.png \ + icon_select.png \ + LightApp.ini \ + LightApp.xml + +CPPFLAGS+=$(PYTHON_INCLUDES) $(QT_INCLUDES) $(QWT_INCLUDES) $(OCC_INCLUDES) $(VTK_INCLUDES) + +LDFLAGS+=$(PYTHON_LIBS) $(QT_MT_LIBS) +LIBS+= -lsuit -lstd -lCAM -lObjBrowser -lLogWindow $(CAS_KERNEL) -lGLViewer -lOCCViewer -lVTKViewer -lSalomeObject -lSOCC -lSVTK -lSPlot2d -lSUPERVGraph -lPyInterp -lPythonConsole + +@CONCLUDE@ diff --git a/src/LightApp/resources/LightApp.xml b/src/LightApp/resources/LightApp.xml new file mode 100644 index 000000000..2a4932e04 --- /dev/null +++ b/src/LightApp/resources/LightApp.xml @@ -0,0 +1,78 @@ + +
+ + + + + +
+
+ + + + + + +
+
+ + +
+
+ + + + + + + + + + + + + + +
+
+ + +
+ + +
+ + +
+
+ +
+
+ + + + +
+
+ + +
+
+ + + + + + + +
+
+ + +
+ +
+ + +
+
diff --git a/src/LightApp/resources/LightApp_msg_en.po b/src/LightApp/resources/LightApp_msg_en.po new file mode 100644 index 000000000..5c3215335 --- /dev/null +++ b/src/LightApp/resources/LightApp_msg_en.po @@ -0,0 +1,315 @@ +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. "Foo::Bar" +# would be translated to "Pub", not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: example-Qt-message-extraction\n" +"POT-Creation-Date: 1999-02-23 15:38+0200\n" +"PO-Revision-Date: 1999-02-23 15:38+0200\n" +"Last-Translator: \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + + +//======================================================================================= + +msgid "APP_NAME" +msgstr "SALOME" + +msgid "ABOUT_CAPTION" +msgstr "About %1" + +msgid "ABOUT_VERSION" +msgstr "Version %1" + +msgid "ABOUT_COPYRIGHT" +msgstr "Copyright (C) 2003-2005 OPEN CASCADE, EADS/CCR, LIP6,\nCEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS" + +msgid "ABOUT_LICENSE" +msgstr "GNU LGPL" + +//======================================================================================= + +msgid "LightApp_Application::ACTIVATING_MODULE" +msgstr "Trying to activate module \"%1\"" + +msgid "LightApp_Application::TOT_RENAME" +msgstr "Rename" + +msgid "LightApp_Application::MEN_DESK_RENAME" +msgstr "&Rename" + +msgid "LightApp_Application::PRP_RENAME" +msgstr "Rename active window" + +msgid "LightApp_Application::TOT_DESK_PREFERENCES" +msgstr "Preferences" + +msgid "LightApp_Application::MEN_DESK_PREFERENCES" +msgstr "Pre&ferences..." + +msgid "LightApp_Application::TOT_DESK_MRU" +msgstr "Most recently used" + +msgid "LightApp_Application::MEN_DESK_MRU" +msgstr "Most recently used" + +msgid "LightApp_Application::PRP_DESK_PREFERENCES" +msgstr "Allow to change the preferences" + +msgid "LightApp_Application::INF_TOOLBAR_MODULES" +msgstr "Modules" + +msgid "LightApp_Application::PRP_APP_MODULE" +msgstr "Switch to SALOME platform neutral point" + +msgid "LightApp_Application::PRP_MODULE" +msgstr "Switch to the module \"%1\"" + +msgid "LightApp_Application::NEW_WINDOW_0" +msgstr "&GL view" + +msgid "LightApp_Application::NEW_WINDOW_1" +msgstr "&Plot2d view" + +msgid "LightApp_Application::NEW_WINDOW_2" +msgstr "&OCC view" + +msgid "LightApp_Application::NEW_WINDOW_3" +msgstr "VT&K view" + +msgid "LightApp_Application::INF_CANCELLED" +msgstr "Module activation cancelled" + +msgid "EXTERNAL_BROWSER_CANNOT_SHOW_PAGE" +msgstr "External browser \"%1\" can not show help page \"%2\"" + +msgid "LightApp_Application::DEFINE_EXTERNAL_BROWSER" +msgstr "Define external browser in preferences" + +msgid "LightApp_Application::DATA_MODELS" +msgstr "Data models" + +msgid "LightApp_Application::OBJECT_BROWSER" +msgstr "Object Browser" + +msgid "LightApp_Application::OBJ_BROWSER_NAME" +msgstr "Object" + +msgid "LightApp_Application::LOG_WINDOW" +msgstr "Message Window" + +//======================================================================================= + +msgid "LightApp_Application::MEN_DESK_MODULE_HELP" +msgstr "Module help" + +//======================================================================================= + +msgid "LightApp_Application::PREFERENCES_NOT_LOADED" +msgstr "Preferences for module \"%1\" will be available when the module will be loaded" + +msgid "LightApp_Application::PREF_CATEGORY_SALOME" +msgstr "SALOME" + +msgid "LightApp_Application::PREF_TAB_GENERAL" +msgstr "General" + +msgid "LightApp_Application::PREF_GROUP_STUDY" +msgstr "Study properties" + +msgid "LightApp_Application::PREF_MULTI_FILE" +msgstr "Multi file save" + +msgid "LightApp_Application::PREF_ASCII_FILE" +msgstr "ASCII save" + +msgid "LightApp_Application::PREF_UNDO_LEVEL" +msgstr "Undo level" + +msgid "LightApp_Application::PREF_STORE_POS" +msgstr "Store positions of windows" + +msgid "LightApp_Application::PREF_GROUP_EXT_BROWSER" +msgstr "External browser" + +msgid "LightApp_Application::PREF_APP" +msgstr "Application" + +msgid "LightApp_Application::PREF_PARAM" +msgstr "Parameters" + +msgid "LightApp_Application::PREF_GROUP_PY_CONSOLE" +msgstr "Python console properties" + +msgid "LightApp_Application::PREF_FONT" +msgstr "Font" + +msgid "LightApp_Application::PREF_TAB_OBJBROWSER" +msgstr "Object browser" + +msgid "LightApp_Application::PREF_OBJ_BROWSER_SETTINGS" +msgstr "Object browser settings" + +msgid "LightApp_Application::PREF_GROUP_DEF_COLUMNS" +msgstr "Default columns" + +msgid "LightApp_Application::PREF_TAB_VIEWERS" +msgstr "Viewers" + +msgid "LightApp_Application::PREF_GROUP_OCCVIEWER" +msgstr "OCC Viewer 3d" + +msgid "LightApp_Application::PREF_GROUP_VTKVIEWER" +msgstr "VTK Viewer 3d" + +msgid "LightApp_Application::PREF_VIEWER_BACKGROUND" +msgstr "Background color" + +msgid "LightApp_Application::PREF_TRIHEDRON_SIZE" +msgstr "Trihedron size" + +msgid "LightApp_Application::PREF_RELATIVE_SIZE" +msgstr "Relative size" + +msgid "LightApp_Application::PREF_ISOS_U" +msgstr "Number of isolines along U" +msgid "LightApp_Application::PREF_ISOS_V" +msgstr "Number of isolines along V" + +msgid "LightApp_Application::PREF_TRIHEDRON_SHOW" +msgstr "Show trihedron" + +msgid "LightApp_Application::PREF_GROUP_PLOT2DVIEWER" +msgstr "Plot2d Viewer" + +msgid "LightApp_Application::PREF_SHOW_LEGEND" +msgstr "Show legend" + +msgid "LightApp_Application::PREF_LEGEND_POSITION" +msgstr "Legend position:" + +msgid "LightApp_Application::PREF_LEFT" +msgstr "Left" + +msgid "LightApp_Application::PREF_RIGHT" +msgstr "Right" + +msgid "LightApp_Application::PREF_TOP" +msgstr "Top" + +msgid "LightApp_Application::PREF_BOTTOM" +msgstr "Bottom" + +msgid "LightApp_Application::PREF_CURVE_TYPE" +msgstr "Curve type:" + +msgid "LightApp_Application::PREF_POINTS" +msgstr "Points" + +msgid "LightApp_Application::PREF_LINES" +msgstr "Lines" + +msgid "LightApp_Application::PREF_SPLINE" +msgstr "Spline" + +msgid "LightApp_Application::PREF_MARKER_SIZE" +msgstr "Marker size:" + +msgid "LightApp_Application::PREF_LINEAR" +msgstr "Linear" + +msgid "LightApp_Application::PREF_LOGARITHMIC" +msgstr "Logarithmic" + +msgid "LightApp_Application::PREF_HOR_AXIS_SCALE" +msgstr "Horizontal axis scale:" + +msgid "LightApp_Application::PREF_VERT_AXIS_SCALE" +msgstr "Vertical axis scale:" + +msgid "LightApp_Application::PREF_TAB_DIRECTORIES" +msgstr "Directories" + +msgid "LightApp_Application::PREF_GROUP_DIRECTORIES" +msgstr "Quick directory list" + +msgid "LightApp_Application::MEN_REFRESH" +msgstr "Refresh" + +msgid "LightApp_Application::PREF_GROUP_SUPERV" +msgstr "Graph Supervisor" + +msgid "LightApp_Application::PREF_SUPERV_TITLE_COLOR" +msgstr "Title color" + +msgid "LightApp_Application::PREF_SUPERV_CTRL_COLOR" +msgstr "Ctrl color" + +msgid "LightApp_Application::PREF_AUTO_SIZE" +msgstr "Auto size for other columns" + +msgid "LightApp_Application::PREF_AUTO_SIZE_FIRST" +msgstr "Auto size for first column" + +//======================================================================================= + +msgid "LightApp_PreferencesDlg::CAPTION" +msgstr "Preferences" + +//======================================================================================= + +msgid "LightApp_Module::TOP_DISPLAY" +msgstr "Display" + +msgid "LightApp_Module::MEN_DISPLAY" +msgstr "Display" + +msgid "LightApp_Module::STB_DISPLAY" +msgstr "Display" + +msgid "LightApp_Module::TOP_ERASE" +msgstr "Erase" + +msgid "LightApp_Module::MEN_ERASE" +msgstr "Erase" + +msgid "LightApp_Module::STB_ERASE" +msgstr "Erase" + +msgid "LightApp_Module::TOP_DISPLAY_ONLY" +msgstr "Display only" + +msgid "LightApp_Module::MEN_DISPLAY_ONLY" +msgstr "Display only" + +msgid "LightApp_Module::STB_DISPLAY_ONLY" +msgstr "Display only" + +msgid "LightApp_Module::TOP_ERASE_ALL" +msgstr "Erase all" + +msgid "LightApp_Module::MEN_ERASE_ALL" +msgstr "Erase all" + +msgid "LightApp_Module::STB_ERASE_ALL" +msgstr "Erase all" +//======================================================================================= + + +msgid "LightApp_ModuleDlg::CAPTION" +msgstr "Activate module" + +msgid "LightApp_ModuleDlg::NEW" +msgstr "&New" + +msgid "LightApp_ModuleDlg::OPEN" +msgstr "&Open" + +msgid "LightApp_ModuleDlg::LOAD" +msgstr "&Load" + +msgid "LightApp_ModuleDlg::CANCEL" +msgstr "&Cancel" + +msgid "LightApp_ModuleDlg::ActivateComponent_DESCRIPTION" +msgstr "Create, open or load study." diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100755 index 000000000..332907b5c --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,40 @@ +# Copyright (C) 2003 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. +# +# 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +# +# +# +# File : Makefile.in +# Author : Patrick GOLDBRONN (CEA) +# Module : SALOME +# $Header$ + +top_srcdir=@top_srcdir@ +top_builddir=.. +srcdir=@srcdir@ +VPATH=.:@srcdir@ + + +@COMMENCE@ + +SUBDIRS = Qtx DDS QDS SUIT STD CAF CAM SUITApp VTKViewer OCCViewer GLViewer \ + LogWindow Event OBJECT Prs PyInterp PythonConsole ObjBrowser \ + RegistryDisplay Plot2d TOOLSGUI SOCC SVTK SPlot2d SUPERVGraph \ + LightApp Session SalomeApp SALOME_SWIG SALOME_PY SALOME_PYQT Style ResExporter + +@MODULE@ diff --git a/src/OCCViewer/Makefile.in b/src/OCCViewer/Makefile.in new file mode 100755 index 000000000..6eb3077b8 --- /dev/null +++ b/src/OCCViewer/Makefile.in @@ -0,0 +1,78 @@ +# File : Makefile.in +# Author : Vladimir Klyachin (OCN) +# Module : OCCViewer +# $Header$ + +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@srcdir@/resources + + +@COMMENCE@ + +# header files +EXPORT_HEADERS= OCCViewer_AISSelector.h \ + OCCViewer_ViewManager.h \ + OCCViewer_ViewModel.h \ + OCCViewer_ViewPort3d.h \ + OCCViewer_ViewPort.h \ + OCCViewer_ViewWindow.h \ + OCCViewer_VService.h \ + OCCViewer_CreateRestoreViewDlg.h \ + OCCViewer.h + +# .po files to transform in .qm +PO_FILES = OCCViewer_images.po \ + OCCViewer_msg_en.po + +# Libraries targets +LIB = libOCCViewer.la +LIB_SRC= OCCViewer_AISSelector.cxx \ + OCCViewer_ViewManager.cxx \ + OCCViewer_ViewModel.cxx \ + OCCViewer_ViewPort3d.cxx \ + OCCViewer_ViewPort.cxx \ + OCCViewer_ViewWindow.cxx \ + OCCViewer_VService.cxx \ + OCCViewer_CreateRestoreViewDlg.cxx \ + OCCViewer_ClippingDlg.cxx + +LIB_MOC = OCCViewer_AISSelector.h \ + OCCViewer_ViewModel.h \ + OCCViewer_ViewPort3d.h \ + OCCViewer_ViewPort.h \ + OCCViewer_ViewWindow.h \ + OCCViewer_ViewManager.h \ + OCCViewer_CreateRestoreViewDlg.h \ + OCCViewer_ClippingDlg.h + +RESOURCES_FILES = \ +view_back.png \ +view_bottom.png \ +view_camera_dump.png \ +view_clone.png \ +view_clipping.png \ +view_clipping_pressed.png \ +view_fitall.png \ +view_fitarea.png \ +view_front.png \ +view_glpan.png \ +view_left.png \ +view_pan.png \ +view_presets.png \ +view_reset.png \ +view_right.png \ +view_rotate.png \ +view_shoot.png \ +view_top.png \ +view_triedre.png \ +view_zoom.png + +CPPFLAGS+=$(QT_INCLUDES) $(OGL_INCLUDES) $(OCC_INCLUDES) + +LDFLAGS+=$(OGL_LIBS) $(QT_MT_LIBS) $(CAS_KERNEL) $(CAS_VIEWER) -lsuit + +@CONCLUDE@ + + diff --git a/src/OCCViewer/OCCViewer_ClippingDlg.cxx b/src/OCCViewer/OCCViewer_ClippingDlg.cxx new file mode 100644 index 000000000..c17bfd33d --- /dev/null +++ b/src/OCCViewer/OCCViewer_ClippingDlg.cxx @@ -0,0 +1,509 @@ +#include "OCCViewer_ClippingDlg.h" + +#include + +#include "SUIT_Session.h" +#include "SUIT_ViewWindow.h" +#include "OCCViewer_ViewWindow.h" +#include "OCCViewer_ViewPort3d.h" + +//#include "utilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// QT Includes +#include +#include +#include +#include +#include +#include +#include + +//================================================================================= +// class : OCCViewer_ClippingDlg() +// purpose : +//================================================================================= +OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, "OCCViewer_ClippingDlg", modal, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ), myView( view ) +{ + setCaption( tr( "Clipping" ) ); + + QVBoxLayout* topLayout = new QVBoxLayout( this ); + topLayout->setMargin( 11 ); topLayout->setSpacing( 6 ); + + /***************************************************************/ + GroupPoint = new QGroupBox( this, "GroupPoint" ); + GroupPoint->setTitle( tr("Base point") ); + GroupPoint->setColumnLayout(0, Qt::Vertical ); + GroupPoint->layout()->setSpacing( 0 ); + GroupPoint->layout()->setMargin( 0 ); + QGridLayout* GroupPointLayout = new QGridLayout( GroupPoint->layout() ); + GroupPointLayout->setAlignment( Qt::AlignTop ); + GroupPointLayout->setSpacing( 6 ); + GroupPointLayout->setMargin( 11 ); + + // Controls + const double min = -1e+06; + const double max = 1e+06; + const double step = 5; + + TextLabelX = new QLabel( GroupPoint, "TextLabelX" ); + TextLabelX->setText( tr("X:") ); + GroupPointLayout->addWidget( TextLabelX, 0, 0 ); + + SpinBox_X = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_X" ); + GroupPointLayout->addWidget( SpinBox_X, 0, 1 ); + + TextLabelY = new QLabel( GroupPoint, "TextLabelY" ); + TextLabelY->setText( tr("Y:") ); + GroupPointLayout->addWidget( TextLabelY, 0, 2 ); + + SpinBox_Y = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Y" ); + GroupPointLayout->addWidget( SpinBox_Y, 0, 3 ); + + TextLabelZ = new QLabel( GroupPoint, "TextLabelZ" ); + TextLabelZ->setText( tr("Z:") ); + GroupPointLayout->addWidget( TextLabelZ, 0, 4 ); + + SpinBox_Z = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Z" ); + GroupPointLayout->addWidget( SpinBox_Z, 0, 5 ); + + resetButton = new QPushButton( GroupPoint, "resetButton" ); + resetButton->setText( tr( "Reset" ) ); + GroupPointLayout->addWidget( resetButton, 0, 6 ); + + /***************************************************************/ + GroupDirection = new QGroupBox( this, "GroupDirection" ); + GroupDirection->setTitle( tr("Direction") ); + GroupDirection->setColumnLayout(0, Qt::Vertical ); + GroupDirection->layout()->setSpacing( 0 ); + GroupDirection->layout()->setMargin( 0 ); + QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection->layout() ); + GroupDirectionLayout->setAlignment( Qt::AlignTop ); + GroupDirectionLayout->setSpacing( 6 ); + GroupDirectionLayout->setMargin( 11 ); + + // Controls + TextLabelDx = new QLabel( GroupDirection, "TextLabelDx" ); + TextLabelDx->setText( tr("Dx:") ); + GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 ); + + SpinBox_Dx = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dx" ); + GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 ); + + TextLabelDy = new QLabel( GroupDirection, "TextLabelDy" ); + TextLabelDy->setText( tr("Dy:") ); + GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 ); + + SpinBox_Dy = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dy" ); + GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 ); + + TextLabelDz = new QLabel( GroupDirection, "TextLabelDz" ); + TextLabelDz->setText( tr("Dz:") ); + GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 ); + + SpinBox_Dz = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dz" ); + GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 ); + + invertButton = new QPushButton( GroupDirection, "invertButton" ); + invertButton->setText( tr( "Invert" ) ); + GroupDirectionLayout->addWidget( invertButton, 0, 6 ); + + DirectionCB = new QComboBox( GroupDirection, "DirectionCB" ); + DirectionCB->insertItem(tr("CUSTOM")); + DirectionCB->insertItem(tr("||X-Y")); + DirectionCB->insertItem(tr("||Y-Z")); + DirectionCB->insertItem(tr("||Z-X")); + GroupDirectionLayout->addMultiCellWidget( DirectionCB, 1, 1, 0, 5 ); + + /***************************************************************/ + + PreviewChB = new QCheckBox( tr("Preview") ,this, "PreviewChB" ); + PreviewChB->setChecked( true ); + + /***************************************************************/ + QGroupBox* GroupButtons = new QGroupBox( this, "GroupButtons" ); + GroupButtons->setColumnLayout(0, Qt::Vertical ); + GroupButtons->layout()->setMargin( 0 ); GroupButtons->layout()->setSpacing( 0 ); + QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons->layout() ); + GroupButtonsLayout->setAlignment( Qt::AlignTop ); + GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 ); + + buttonApply = new QPushButton( GroupButtons, "buttonApply" ); + buttonApply->setText( tr( "BUT_APPLY" ) ); + buttonApply->setAutoDefault( TRUE ); + buttonApply->setDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonApply ); + + GroupButtonsLayout->addStretch(); + + buttonClose = new QPushButton( GroupButtons, "buttonClose" ); + buttonClose->setText( tr( "BUT_CLOSE" ) ); + buttonClose->setAutoDefault( TRUE ); + GroupButtonsLayout->addWidget( buttonClose ); + /***************************************************************/ + + topLayout->addWidget( GroupPoint ); + topLayout->addWidget( GroupDirection ); + + topLayout->addWidget( PreviewChB ); + + topLayout->addWidget( GroupButtons ); + + /* initializations */ + + 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 ); + + /* signals and slots connections */ + 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( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ; + + connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ; + + connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ; + connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); + + myBusy = false; +} + +//================================================================================= +// function : ~ OCCViewer_ClippingDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + + +//================================================================================= +// function : closeEvent +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e ) +{ + erasePreview(); + QDialog::closeEvent( e ); +} + + +//================================================================================= +// function : showEvent +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::showEvent( QShowEvent* e ) +{ + QDialog::showEvent( e ); + onPreview( PreviewChB->isChecked() ); +} + + +//================================================================================= +// function : hideEvent +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e ) +{ + erasePreview(); + QDialog::hideEvent( e ); +} + + +//================================================================================= +// function : ClickOnClose() +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::ClickOnClose() +{ + erasePreview(); + reject(); +} + + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::ClickOnApply() +{ + qApp->processEvents(); + QApplication::setOverrideCursor( Qt::WaitCursor ); + qApp->processEvents(); + + myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(), + SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() ); + + QApplication::restoreOverrideCursor(); + + erasePreview(); +} + + +//================================================================================= +// function : onReset() +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::onReset() +{ + myBusy = true; + SpinBox_X->setValue(0); + SpinBox_Y->setValue(0); + SpinBox_Z->setValue(0); + myBusy = false; + + if ( PreviewChB->isChecked() ) + { + erasePreview(); + displayPreview(); + } +} + + +//================================================================================= +// function : onInvert() +// purpose : +//================================================================================= +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 ( PreviewChB->isChecked() ) + { + erasePreview(); + displayPreview(); + } +} + + +//================================================================================= +// function : onModeChanged() +// purpose : +//================================================================================= +void OCCViewer_ClippingDlg::onModeChanged( 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 ) + return; + + 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(); + } + + myBusy = true; + SpinBox_Dx->setValue( aDx ); + SpinBox_Dy->setValue( aDy ); + SpinBox_Dz->setValue( aDz ); + myBusy = false; + + if ( PreviewChB->isChecked() ) + { + erasePreview(); + displayPreview(); + } +} + + +//================================================================ +// Function : displayPreview +// Purpose : +//================================================================ +void OCCViewer_ClippingDlg::displayPreview() +{ + if ( myBusy || !isValid() ) + return; + + OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel(); + if (!anOCCViewer) + return; + + Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext(); + + 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 ); + } + } + } + + double aSize = 50; + + gp_Pnt aBasePnt( SpinBox_X->value(), SpinBox_Y->value(), SpinBox_Z->value() ); + gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() ); + gp_Pnt aCenter = aBasePnt; + + if ( isFound ) + { + // compute clipping plane size + 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 ); + } + + myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) ); + myPreviewPlane->SetSize( aSize, aSize ); + + ic->Display( myPreviewPlane, 1, -1, false ); + ic->SetWidth( myPreviewPlane, 10, false ); + ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false ); + ic->SetTransparency( myPreviewPlane, 0.5, false ); + ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false ); + + anOCCViewer->update(); +} + + +//================================================================ +// Function : erasePreview +// Purpose : +//================================================================ +void OCCViewer_ClippingDlg::erasePreview () +{ + OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel(); + if (!anOCCViewer) + return; + + Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext(); + + if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) + { + ic->Erase( myPreviewPlane, false, false ); + ic->Remove( myPreviewPlane, false ); + myPreviewPlane.Nullify(); + } + + anOCCViewer->update(); +} + + +//================================================================ +// Function : onValueChanged +// Purpose : +//================================================================ +void OCCViewer_ClippingDlg::onValueChanged() +{ + if ( PreviewChB->isChecked() ) + { + erasePreview(); + displayPreview(); + } +} + + +//================================================================ +// Function : onPreview +// Purpose : +//================================================================ +void OCCViewer_ClippingDlg::onPreview( bool on ) +{ + erasePreview(); + + if ( on ) + displayPreview(); +} + +//================================================================ +// Function : onPreview +// Purpose : +//================================================================ +bool OCCViewer_ClippingDlg::isValid() +{ + return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 ); +} diff --git a/src/OCCViewer/OCCViewer_ClippingDlg.h b/src/OCCViewer/OCCViewer_ClippingDlg.h new file mode 100644 index 000000000..e46903a05 --- /dev/null +++ b/src/OCCViewer/OCCViewer_ClippingDlg.h @@ -0,0 +1,84 @@ +#ifndef OCCVIEWER_CLIPPINGDLG_H +#define OCCVIEWER_CLIPPINGDLG_H + +#include "OCCViewer.h" + +#include + +#include + +class QGroupBox; +class QLabel; +class QPushButton; +class QComboBox; +class QCheckBox; +class QtxDblSpinBox; + +class OCCViewer_ViewWindow; + + +//================================================================================= +// class : OCCViewer_ClippingDlg +// purpose : +//================================================================================= +class OCCViewer_ClippingDlg : public QDialog +{ + Q_OBJECT + + public: + OCCViewer_ClippingDlg(OCCViewer_ViewWindow* , QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0); + ~OCCViewer_ClippingDlg(); + +private : + + virtual void closeEvent( QCloseEvent* e ); + virtual void showEvent ( QShowEvent * ); + virtual void hideEvent ( QHideEvent * ); + void displayPreview(); + void erasePreview(); + + bool isValid(); + + QGroupBox* GroupPoint; + QLabel* TextLabelX; + QLabel* TextLabelY; + QLabel* TextLabelZ; + QtxDblSpinBox* SpinBox_X; + QtxDblSpinBox* SpinBox_Y; + QtxDblSpinBox* SpinBox_Z; + QPushButton* resetButton; + + QGroupBox* GroupDirection; + QLabel* TextLabelDx; + QLabel* TextLabelDy; + QLabel* TextLabelDz; + QtxDblSpinBox* SpinBox_Dx; + QtxDblSpinBox* SpinBox_Dy; + QtxDblSpinBox* SpinBox_Dz; + QPushButton* invertButton; + + QComboBox* DirectionCB; + + QCheckBox* PreviewChB; + + QPushButton* buttonApply; + QPushButton* buttonClose; + + OCCViewer_ViewWindow* myView; + + Handle(AIS_Plane) myPreviewPlane; + + bool myBusy; + +private slots: + void ClickOnApply(); + void ClickOnClose(); + + void onReset(); + void onInvert(); + void onModeChanged( int mode ); + void onValueChanged(); + void onPreview( bool on ); +}; + +#endif // OCCVIEWER_CLIPPINGDLG_H diff --git a/src/OCCViewer/OCCViewer_ViewModel.cxx b/src/OCCViewer/OCCViewer_ViewModel.cxx new file mode 100755 index 000000000..216c9ec84 --- /dev/null +++ b/src/OCCViewer/OCCViewer_ViewModel.cxx @@ -0,0 +1,498 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#include "OCCViewer_ViewModel.h" +#include "OCCViewer_ViewWindow.h" +#include "OCCViewer_VService.h" +#include "OCCViewer_ViewPort3d.h" + +#include "SUIT_ViewWindow.h" +#include "SUIT_Desktop.h" +#include "SUIT_Session.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +OCCViewer_Viewer::OCCViewer_Viewer( bool DisplayTrihedron ) +: SUIT_ViewModel(), +myBgColor( Qt::black ) +{ + // init CasCade viewers + myV3dViewer = OCCViewer_VService::Viewer3d( "", (short*) "Viewer3d", "", 1000., + V3d_XposYnegZpos, true, true ); + + myV3dViewer->Init(); + + myV3dCollector = OCCViewer_VService::Viewer3d( "", (short*) "Collector3d", "", 1000., + V3d_XposYnegZpos, true, true ); + myV3dCollector->Init(); + + // init selector + myAISContext = new AIS_InteractiveContext( myV3dViewer, myV3dCollector); + + myAISContext->SelectionColor( Quantity_NOC_WHITE ); + + // display isoline on planar faces (box for ex.) + myAISContext->IsoOnPlane( true ); + + clearViewAspects(); + + /* create trihedron */ + if( DisplayTrihedron ) + { + Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY()); + myTrihedron = new AIS_Trihedron(anAxis); + myTrihedron->SetInfiniteState( Standard_True ); + + Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB); + //myTrihedron->SetColor( Col ); + myTrihedron->SetArrowColor( Col.Name() ); + myTrihedron->SetSize(100); + Handle(AIS_Drawer) drawer = myTrihedron->Attributes(); + if (drawer->HasDatumAspect()) { + Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect(); + daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB)); + daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB)); + daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB)); + } + + myAISContext->Display(myTrihedron); + myAISContext->Deactivate(myTrihedron); + } + + // selection + mySelectionEnabled = true; + myMultiSelectionEnabled = true; +} + + +OCCViewer_Viewer::~OCCViewer_Viewer() +{ +} + +QColor OCCViewer_Viewer::backgroundColor() const +{ + return myBgColor; +} + +void OCCViewer_Viewer::setBackgroundColor( const QColor& c ) +{ + if ( c.isValid() ) + myBgColor = c; +} + +void OCCViewer_Viewer::initView( OCCViewer_ViewWindow* view ) +{ + if ( view ) { + view->initLayout(); + + OCCViewer_ViewPort3d* vp3d = view->getViewPort(); + if ( vp3d ) + vp3d->setBackgroundColor( myBgColor ); + } +} + + +SUIT_ViewWindow* OCCViewer_Viewer::createView( SUIT_Desktop* theDesktop ) +{ + OCCViewer_ViewWindow* view = new OCCViewer_ViewWindow(theDesktop, this); + initView( view ); + return view; +} + +//********************************************************************* +void OCCViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager) +{ + SUIT_ViewModel::setViewManager(theViewManager); + if (theViewManager) { + connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)), + this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*))); + + connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMove(SUIT_ViewWindow*, QMouseEvent*))); + + connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)), + this, SLOT(onMouseRelease(SUIT_ViewWindow*, QMouseEvent*))); + } +} + + +//********************************************************************* +void OCCViewer_Viewer::onMousePress(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent) +{ + myStartPnt.setX(theEvent->x()); myStartPnt.setY(theEvent->y()); +} + + +//********************************************************************* +void OCCViewer_Viewer::onMouseMove(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent) +{ + if (!mySelectionEnabled) return; + if (!theWindow->inherits("OCCViewer_ViewWindow")) return; + + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow; + if ( isSelectionEnabled() ) + myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView->getViewPort()->getView()); +} + + +//********************************************************************* +void OCCViewer_Viewer::onMouseRelease(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent) +{ + if (!mySelectionEnabled) return; + if (theEvent->button() != Qt::LeftButton) return; + if (!theWindow->inherits("OCCViewer_ViewWindow")) return; + + + myEndPnt.setX(theEvent->x()); myEndPnt.setY(theEvent->y()); + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow; + bool aHasShift = (theEvent->state() & Qt::ShiftButton); + + if (myStartPnt == myEndPnt) + { + if (aHasShift && myMultiSelectionEnabled) + myAISContext->ShiftSelect(); + else + myAISContext->Select(); + } + else + { + if (aHasShift && myMultiSelectionEnabled) + myAISContext->ShiftSelect(myStartPnt.x(), myStartPnt.y(), + myEndPnt.x(), myEndPnt.y(), + aView->getViewPort()->getView(), Standard_False ); + else + myAISContext->Select(myStartPnt.x(), myStartPnt.y(), + myEndPnt.x(), myEndPnt.y(), + aView->getViewPort()->getView(), Standard_False ); + + int Nb = myAISContext->NbSelected(); + if( Nb>1 && !myMultiSelectionEnabled ) + { + myAISContext->InitSelected(); + Handle( SelectMgr_EntityOwner ) anOwner = myAISContext->SelectedOwner(); + if( !anOwner.IsNull() ) + { + myAISContext->ClearSelected( Standard_False ); + myAISContext->AddOrRemoveSelected( anOwner, Standard_False ); + } + } + + myAISContext->UpdateCurrentViewer(); + } + emit selectionChanged(); +} + + +//********************************************************************* +void OCCViewer_Viewer::enableSelection(bool isEnabled) +{ + mySelectionEnabled = isEnabled; + //!! To be done for view windows + if ( !myViewManager ) + return; + + QPtrVector wins = myViewManager->getViews(); + for ( int i = 0; i < wins.count(); i++ ) + { + OCCViewer_ViewWindow* win = ::qt_cast( wins.at( i ) ); + if ( win ) + win->updateEnabledDrawMode(); + } +} + +//********************************************************************* +void OCCViewer_Viewer::enableMultiselection(bool isEnable) +{ + myMultiSelectionEnabled = isEnable; + //!! To be done for view windows + if ( !myViewManager ) + return; + + QPtrVector wins = myViewManager->getViews(); + for ( int i = 0; i < wins.count(); i++ ) + { + OCCViewer_ViewWindow* win = ::qt_cast( wins.at( i ) ); + if ( win ) + win->updateEnabledDrawMode(); + } +} + +//********************************************************************* +void OCCViewer_Viewer::contextMenuPopup(QPopupMenu* thePopup) +{ + thePopup->insertItem( tr( "MEN_DUMP_VIEW" ), this, SLOT( onDumpView() ) ); + thePopup->insertItem( tr( "MEN_CHANGE_BACKGROUD" ), this, SLOT( onChangeBgColor() ) ); + + thePopup->insertSeparator(); + + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView()); + if ( aView && !aView->getToolBar()->isVisible() ) + thePopup->insertItem( tr( "MEN_SHOW_TOOLBAR" ), this, SLOT( onShowToolbar() ) ); +} + +void OCCViewer_Viewer::onDumpView() +{ + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView()); + if ( aView ) + aView->onDumpView(); +} + +//********************************************************************* +void OCCViewer_Viewer::onChangeBgColor() +{ + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView()); + if( !aView ) + return; + OCCViewer_ViewPort3d* aViewPort3d = aView->getViewPort(); + if( !aViewPort3d ) + return; + QColor aColorActive = aViewPort3d->backgroundColor(); + + QColor selColor = QColorDialog::getColor( aColorActive, aView); + if ( selColor.isValid() ) + aViewPort3d->setBackgroundColor(selColor); +} + +//********************************************************************* +void OCCViewer_Viewer::onShowToolbar() { + OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView()); + if ( aView ) + aView->getToolBar()->show(); +} + +//********************************************************************* +void OCCViewer_Viewer::update() +{ + if (!myV3dViewer.IsNull()) + myV3dViewer->Update(); +} + +//********************************************************************* +void OCCViewer_Viewer::getSelectedObjects(AIS_ListOfInteractive& theList) +{ + theList.Clear(); + for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected()) + theList.Append(myAISContext->SelectedInteractive()); +} + +//********************************************************************* +void OCCViewer_Viewer::setObjectsSelected(const AIS_ListOfInteractive& theList) +{ + AIS_ListIteratorOfListOfInteractive aIt; + for (aIt.Initialize(theList); aIt.More(); aIt.Next()) + myAISContext->SetSelected(aIt.Value(), false); + myAISContext->UpdateCurrentViewer(); +} + +//********************************************************************* +void OCCViewer_Viewer::performSelectionChanged() +{ + emit selectionChanged(); +} + +//**************************************************************** + +void OCCViewer_Viewer::onClearViewAspects() +{ + clearViewAspects(); +} + +//**************************************************************** + +void OCCViewer_Viewer::clearViewAspects() +{ + myViewAspects.clear(); +} + +//**************************************************************** + +const viewAspectList& OCCViewer_Viewer::getViewAspects() +{ + return myViewAspects; +} + +//**************************************************************** + +void OCCViewer_Viewer::appendViewAspect( const viewAspect& aParams ) +{ + myViewAspects.append( aParams ); +} + +//**************************************************************** + +void OCCViewer_Viewer::updateViewAspects( const viewAspectList& aViewList ) +{ + myViewAspects = aViewList; +} + +bool OCCViewer_Viewer::highlight( const Handle(AIS_InteractiveObject)& obj, + bool hilight, bool update ) +{ + bool isInLocal = myAISContext->HasOpenedContext(); + if( !obj.IsNull() ) + if( !isInLocal ) + { + if ( hilight && !myAISContext->IsSelected( obj ) ) + myAISContext->AddOrRemoveCurrentObject( obj, false ); + else if ( !hilight && myAISContext->IsSelected( obj ) ) + myAISContext->AddOrRemoveCurrentObject( obj, false ); + } + + if ( update ) + myV3dViewer->Redraw(); + + return false; +} + +bool OCCViewer_Viewer::unHighlightAll( bool updateviewer ) +{ + if ( myAISContext->HasOpenedContext() ) + myAISContext->ClearSelected( updateviewer ); + else + myAISContext->ClearCurrents( updateviewer ); + return false; +} + +bool OCCViewer_Viewer::isInViewer( const Handle(AIS_InteractiveObject)& obj, + bool onlyInViewer ) +{ + AIS_ListOfInteractive List; + myAISContext->DisplayedObjects(List); + + if( !onlyInViewer ) + { + AIS_ListOfInteractive List1; + myAISContext->ObjectsInCollector(List1); + List.Append(List1); + } + + AIS_ListIteratorOfListOfInteractive ite(List); + for ( ; ite.More(); ite.Next() ) + if( ite.Value()==obj ) + return true; + + return false; +} + +bool OCCViewer_Viewer::isVisible( const Handle(AIS_InteractiveObject)& obj ) +{ + return myAISContext->IsDisplayed( obj ); +} + +void OCCViewer_Viewer::setColor( const Handle(AIS_InteractiveObject)& obj, + const QColor& color, + bool update ) +{ + if( !obj.IsNull() ) + { + Quantity_Color CSFColor = Quantity_Color ( color.red() / 255., + color.green() / 255., + color.blue() / 255., + Quantity_TOC_RGB ); + obj->SetColor( CSFColor ); + } + + if( update ) + myV3dViewer->Update(); +} + +void OCCViewer_Viewer::switchRepresentation( const Handle(AIS_InteractiveObject)& obj, + int mode, bool update ) +{ + myAISContext->SetDisplayMode( obj, (Standard_Integer)mode, true ); + if( update ) + myV3dViewer->Update(); +} + +void OCCViewer_Viewer::setTransparency( const Handle(AIS_InteractiveObject)& obj, + float trans, bool update ) +{ + myAISContext->SetTransparency( obj, trans, false ); + myAISContext->Redisplay( obj, Standard_False, Standard_True ); + if( update ) + myV3dViewer->Update(); +} + +//**************************************************************** +void OCCViewer_Viewer::toggleTrihedron() +{ + setTrihedronShown( !isTrihedronVisible() ); +} + +bool OCCViewer_Viewer::isTrihedronVisible() const +{ + return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron ); +} + +void OCCViewer_Viewer::setTrihedronShown( const bool on ) +{ + if ( myTrihedron.IsNull() ) + return; + + if ( on ) + myAISContext->Display( myTrihedron ); + else + myAISContext->Erase( myTrihedron ); +} + +int OCCViewer_Viewer::trihedronSize() const +{ + int sz = 0; + if ( !myTrihedron.IsNull() ) + sz = (int)myTrihedron->Size(); + return sz; +} + +void OCCViewer_Viewer::setTrihedronSize( const int sz ) +{ + if ( !myTrihedron.IsNull() ) + myTrihedron->SetSize( sz ); +} + +void OCCViewer_Viewer::setIsos( const int u, const int v ) +{ + Handle(AIS_InteractiveContext) ic = getAISContext(); + if ( ic.IsNull() ) + return; + + ic->SetIsoNumber( u, AIS_TOI_IsoU ); + ic->SetIsoNumber( v, AIS_TOI_IsoV ); +} + +void OCCViewer_Viewer::isos( int& u, int& v ) const +{ + Handle(AIS_InteractiveContext) ic = getAISContext(); + if ( !ic.IsNull() ) + { + u = ic->IsoNumber( AIS_TOI_IsoU ); + v = ic->IsoNumber( AIS_TOI_IsoV ); + } +} diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx new file mode 100755 index 000000000..4900fd9de --- /dev/null +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -0,0 +1,982 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// OCCViewer_ViewWindow.cxx: implementation of the OCCViewer_ViewWindow class. +// +////////////////////////////////////////////////////////////////////// + +#include "OCCViewer_ViewWindow.h" +#include "OCCViewer_ViewModel.h" +#include "OCCViewer_ViewPort3d.h" +#include "OCCViewer_CreateRestoreViewDlg.h" +#include "OCCViewer_ClippingDlg.h" + +#include "SUIT_Desktop.h" +#include "SUIT_Session.h" +#include "SUIT_ToolButton.h" + +#include "SUIT_Tools.h" +#include "SUIT_ResourceMgr.h" +#include "SUIT_MessageBox.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const char* imageZoomCursor[] = { +"32 32 3 1", +". c None", +"a c #000000", +"# c #ffffff", +"................................", +"................................", +".#######........................", +"..aaaaaaa.......................", +"................................", +".............#####..............", +"...........##.aaaa##............", +"..........#.aa.....a#...........", +".........#.a.........#..........", +".........#a..........#a.........", +"........#.a...........#.........", +"........#a............#a........", +"........#a............#a........", +"........#a............#a........", +"........#a............#a........", +".........#...........#.a........", +".........#a..........#a.........", +".........##.........#.a.........", +"........#####.....##.a..........", +".......###aaa#####.aa...........", +"......###aa...aaaaa.......#.....", +".....###aa................#a....", +"....###aa.................#a....", +"...###aa...............#######..", +"....#aa.................aa#aaaa.", +".....a....................#a....", +"..........................#a....", +"...........................a....", +"................................", +"................................", +"................................", +"................................"}; + +const char* imageRotateCursor[] = { +"32 32 3 1", +". c None", +"a c #000000", +"# c #ffffff", +"................................", +"................................", +"................................", +"................................", +"........#.......................", +".......#.a......................", +"......#######...................", +".......#aaaaa#####..............", +"........#..##.a#aa##........##..", +".........a#.aa..#..a#.....##.aa.", +".........#.a.....#...#..##.aa...", +".........#a.......#..###.aa.....", +"........#.a.......#a..#aa.......", +"........#a.........#..#a........", +"........#a.........#a.#a........", +"........#a.........#a.#a........", +"........#a.........#a.#a........", +".........#.........#a#.a........", +"........##a........#a#a.........", +"......##.a#.......#.#.a.........", +"....##.aa..##.....##.a..........", +"..##.aa.....a#####.aa...........", +"...aa.........aaa#a.............", +"................#.a.............", +"...............#.a..............", +"..............#.a...............", +"...............a................", +"................................", +"................................", +"................................", +"................................", +"................................"}; + +const char* imageCrossCursor[] = { + "32 32 3 1", + ". c None", + "a c #000000", + "# c #ffffff", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "...............#................", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + ".......#################........", + "........aaaaaaa#aaaaaaaaa.......", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "................a...............", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................"}; + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +OCCViewer_ViewWindow::OCCViewer_ViewWindow(SUIT_Desktop* theDesktop, OCCViewer_Viewer* theModel) +: SUIT_ViewWindow(theDesktop) +{ + myModel = theModel; + myRestoreFlag = 0; + myEnableDrawMode = false; + updateEnabledDrawMode(); + myClippingDlg = 0; +} + +//**************************************************************** +void OCCViewer_ViewWindow::initLayout() +{ + myViewPort = new OCCViewer_ViewPort3d( this, myModel->getViewer3d(), V3d_ORTHOGRAPHIC ); + myViewPort->setBackgroundColor(black); + myViewPort->installEventFilter(this); + setCentralWidget(myViewPort); + myOperation = NOTHING; + + setTransformRequested ( NOTHING ); + setTransformInProcess ( false ); + + myToolBar = new QToolBar(this); + myToolBar->setCloseMode(QDockWindow::Undocked); + myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL")); + + createActions(); + createToolBar(); +} + +//**************************************************************** +OCCViewer_ViewWindow::OperationType OCCViewer_ViewWindow::getButtonState(QMouseEvent* theEvent) +{ + OperationType aOp = NOTHING; + if( (theEvent->state() == SUIT_ViewModel::myStateMap[SUIT_ViewModel::ZOOM]) && + (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::ZOOM]) ) + aOp = ZOOMVIEW; + else if( (theEvent->state() == SUIT_ViewModel::myStateMap[SUIT_ViewModel::PAN]) && + (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::PAN]) ) + aOp = PANVIEW; + else if( (theEvent->state() == SUIT_ViewModel::myStateMap[SUIT_ViewModel::ROTATE]) && + (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::ROTATE]) ) + aOp = ROTATE; + + return aOp; +} + +//**************************************************************** +bool OCCViewer_ViewWindow::eventFilter(QObject* watched, QEvent* e) +{ + if ( watched == myViewPort ) { + int aType = e->type(); + switch(aType) { + case QEvent::MouseButtonPress: + vpMousePressEvent((QMouseEvent*) e); + return true; + + case QEvent::MouseButtonRelease: + vpMouseReleaseEvent((QMouseEvent*) e); + return true; + + case QEvent::MouseMove: + vpMouseMoveEvent((QMouseEvent*) e); + return true; + + case QEvent::MouseButtonDblClick: + emit mouseDoubleClicked(this, (QMouseEvent*)e); + return true; + + case QEvent::Wheel: + { + QWheelEvent* aEvent = (QWheelEvent*) e; + double aDelta = aEvent->delta(); + double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.; + myViewPort->getView()->SetZoom(aScale); + } + return true; + + case QEvent::ContextMenu: + { + QContextMenuEvent * aEvent = (QContextMenuEvent*)e; + if ( aEvent->reason() != QContextMenuEvent::Mouse ) + emit contextMenuRequested( aEvent ); + } + return true; + + default: + break; + } + } + return SUIT_ViewWindow::eventFilter(watched, e); +} + +void OCCViewer_ViewWindow::updateEnabledDrawMode() +{ + if ( myModel ) + myEnableDrawMode = myModel->isSelectionEnabled() && myModel->isMultiSelectionEnabled(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent) +{ + myStartX = theEvent->x(); + myStartY = theEvent->y(); + switch ( myOperation ) { + case WINDOWFIT: + if ( theEvent->button() == Qt::LeftButton ) + emit vpTransformationStarted ( WINDOWFIT ); + break; + + case PANGLOBAL: + if ( theEvent->button() == Qt::LeftButton ) + emit vpTransformationStarted ( PANGLOBAL ); + break; + + case ZOOMVIEW: + if ( theEvent->button() == Qt::LeftButton ) + emit vpTransformationStarted ( ZOOMVIEW ); + break; + + case PANVIEW: + if ( theEvent->button() == Qt::LeftButton ) + emit vpTransformationStarted ( PANVIEW ); + break; + + case ROTATE: + if ( theEvent->button() == Qt::LeftButton ) { + myViewPort->startRotation(myStartX, myStartY); + emit vpTransformationStarted ( ROTATE ); + } + break; + + default: + /* Try to activate a transformation */ + switch ( getButtonState(theEvent) ) { + case ZOOMVIEW: + activateZoom(); + break; + case PANVIEW: + activatePanning(); + break; + case ROTATE: + activateRotation(); + myViewPort->startRotation(myStartX, myStartY); + break; + default: + emit mousePressed(this, theEvent); + break; + } + /* notify that we start a transformation */ + if ( transformRequested() ) + emit vpTransformationStarted ( myOperation ); + } + if ( transformRequested() ) + setTransformInProcess( true ); +} + + +//**************************************************************** +void OCCViewer_ViewWindow::activateZoom() +{ + if ( !transformRequested() && !myCursorIsHand ) + myCursor = cursor(); /* save old cursor */ + + if ( myOperation != ZOOMVIEW ) { + QPixmap zoomPixmap (imageZoomCursor); + QCursor zoomCursor (zoomPixmap); + setTransformRequested ( ZOOMVIEW ); + setCursor( zoomCursor ); + } +} + + +//**************************************************************** +/*! + Activates 'panning' transformation +*/ +void OCCViewer_ViewWindow::activatePanning() +{ + if ( !transformRequested() && !myCursorIsHand ) + myCursor = cursor(); // save old cursor + + if ( myOperation != PANVIEW ) { + QCursor panCursor (Qt::SizeAllCursor); + setTransformRequested ( PANVIEW ); + setCursor( panCursor ); + } +} + +//**************************************************************** +/*! + Activates 'rotation' transformation +*/ +void OCCViewer_ViewWindow::activateRotation() +{ + if ( !transformRequested() && !myCursorIsHand ) + myCursor = cursor(); // save old cursor + + if ( myOperation != ROTATE ) { + QPixmap rotatePixmap (imageRotateCursor); + QCursor rotCursor (rotatePixmap); + setTransformRequested ( ROTATE ); + setCursor( rotCursor ); + } +} + +//**************************************************************** +void OCCViewer_ViewWindow::activateGlobalPanning() +{ + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) { + QPixmap globalPanPixmap (imageCrossCursor); + QCursor glPanCursor (globalPanPixmap); + myCurScale = aView3d->Scale(); + aView3d->FitAll(0.01, false); + myCursor = cursor(); // save old cursor + myViewPort->fitAll(); // fits view before selecting a new scene center + setTransformRequested( PANGLOBAL ); + setCursor( glPanCursor ); + } +} + +//**************************************************************** +/*! + Activates 'fit' transformation +*/ +void OCCViewer_ViewWindow::activateWindowFit() +{ + if ( !transformRequested() && !myCursorIsHand ) + myCursor = cursor(); /* save old cursor */ + + if ( myOperation != WINDOWFIT ) { + QCursor handCursor (Qt::PointingHandCursor); + setTransformRequested ( WINDOWFIT ); + setCursor ( handCursor ); + myCursorIsHand = true; + } +} + +//**************************************************************** +/*! + Sets the active operation 'op' +*/ +void OCCViewer_ViewWindow::setTransformRequested ( OperationType op ) +{ + myOperation = op; + myViewPort->setMouseTracking( myOperation == NOTHING ); +} + + +//****************************************************************/ +void OCCViewer_ViewWindow::vpMouseMoveEvent(QMouseEvent* theEvent) +{ + myCurrX = theEvent->x(); + myCurrY = theEvent->y(); + switch (myOperation) { + case ROTATE: + myViewPort->rotate(myCurrX, myCurrY); + break; + + case ZOOMVIEW: + myViewPort->zoom(myStartX, myStartY, myCurrX, myCurrY); + myStartX = myCurrX; + myStartY = myCurrY; + break; + + case PANVIEW: + myViewPort->pan(myCurrX - myStartX, myStartY - myCurrY); + myStartX = myCurrX; + myStartY = myCurrY; + break; + +/* case WINDOWFIT: + myDrawRect = true; + repaint(); + break; +*/ + case PANGLOBAL: + break; + + default: + int aState = theEvent->state(); + //int aButton = theEvent->button(); + if ( aState == Qt::LeftButton || + aState == ( Qt::LeftButton | Qt::ShiftButton) ) { + myDrawRect = myEnableDrawMode; + if ( myDrawRect ) { + drawRect(); + if ( !myCursorIsHand ) { // we are going to sketch a rectangle + QCursor handCursor (Qt::PointingHandCursor); + myCursorIsHand = true; + myCursor = cursor(); + setCursor( handCursor ); + } + } + } + else { + emit mouseMoving( this, theEvent ); + } + } +} + +//****************************************************************/ +void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent) +{ + switch ( myOperation ) { + case NOTHING: + { + emit mouseReleased(this, theEvent); + if(theEvent->button() == RightButton) + { + QContextMenuEvent aEvent( QContextMenuEvent::Mouse, + theEvent->pos(), theEvent->globalPos(), + theEvent->state() ); + emit contextMenuRequested( &aEvent ); + } + } + break; + case ROTATE: + myViewPort->endRotation(); + resetState(); + break; + + case PANVIEW: + case ZOOMVIEW: + resetState(); + break; + + case PANGLOBAL: + if ( theEvent->button() == Qt::LeftButton ) { + myViewPort->setCenter( theEvent->x(), theEvent->y() ); + myViewPort->getView()->SetScale(myCurScale); + resetState(); + } + break; + + case WINDOWFIT: + if ( theEvent->state() == Qt::LeftButton ) { + myCurrX = theEvent->x(); + myCurrY = theEvent->y(); + QRect rect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY); + if ( !rect.isEmpty() ) myViewPort->fitRect(rect); + resetState(); + } + break; + } + + // NOTE: viewer 3D detects a rectangle of selection using this event + // so we must emit it BEFORE resetting the selection rectangle + + if ( theEvent->button() == Qt::LeftButton && myDrawRect ) { + myDrawRect = false; + drawRect(); + resetState(); + myViewPort->update(); + } +} + +//**************************************************************** +/*! + Sets the viewport to its initial state + ( no transformations in process etc. ) +*/ +void OCCViewer_ViewWindow::resetState() +{ + myDrawRect = false; + + /* make rectangle empty (left > right) */ + myRect.setLeft(2); + myRect.setRight(0); + + if ( transformRequested() || myCursorIsHand ) + setCursor( myCursor ); + myCursorIsHand = false; + + if ( transformRequested() ) + emit vpTransformationFinished (myOperation); + + setTransformInProcess( false ); + setTransformRequested( NOTHING ); +} + + +//****************************************************************/ +void OCCViewer_ViewWindow::drawRect() +{ + QPainter aPainter(myViewPort); + aPainter.setRasterOp(Qt::XorROP); + aPainter.setPen(Qt::white); + QRect aRect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY); + if ( !myRect.isEmpty() ) + aPainter.drawRect( myRect ); + aPainter.drawRect(aRect); + myRect = aRect; +} + +//****************************************************************/ +void OCCViewer_ViewWindow::createActions() +{ + if (!myActionsMap.isEmpty()) return; + + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + QtxAction* aAction; + + // Dump view + aAction = new QtxAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_DUMP" ) ), + tr( "MNU_DUMP_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_DUMP_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onDumpView())); + myActionsMap[ DumpId ] = aAction; + + // FitAll + aAction = new QtxAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITALL" ) ), + tr( "MNU_FITALL" ), 0, this); + aAction->setStatusTip(tr("DSC_FITALL")); + connect(aAction, SIGNAL(activated()), this, SLOT(onFitAll())); + myActionsMap[ FitAllId ] = aAction; + + // FitRect + aAction = new QtxAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITAREA" ) ), + tr( "MNU_FITRECT" ), 0, this); + aAction->setStatusTip(tr("DSC_FITRECT")); + connect(aAction, SIGNAL(activated()), this, SLOT(activateWindowFit())); + myActionsMap[ FitRectId ] = aAction; + + // Zoom + aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ZOOM" ) ), + tr( "MNU_ZOOM_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_ZOOM_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(activateZoom())); + myActionsMap[ ZoomId ] = aAction; + + // Panning + aAction = new QtxAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_PAN" ) ), + tr( "MNU_PAN_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_PAN_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(activatePanning())); + myActionsMap[ PanId ] = aAction; + + // Global Panning + aAction = new QtxAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_GLOBALPAN" ) ), + tr( "MNU_GLOBALPAN_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(activateGlobalPanning())); + myActionsMap[ GlobalPanId ] = aAction; + + // Rotation + aAction = new QtxAction(tr("MNU_ROTATE_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ROTATE" ) ), + tr( "MNU_ROTATE_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_ROTATE_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(activateRotation())); + myActionsMap[ RotationId ] = aAction; + + // Projections + aAction = new QtxAction(tr("MNU_FRONT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FRONT" ) ), + tr( "MNU_FRONT_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_FRONT_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onFrontView())); + myActionsMap[ FrontId ] = aAction; + + aAction = new QtxAction(tr("MNU_BACK_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_BACK" ) ), + tr( "MNU_BACK_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_BACK_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onBackView())); + myActionsMap[ BackId ] = aAction; + + aAction = new QtxAction(tr("MNU_TOP_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_TOP" ) ), + tr( "MNU_TOP_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_TOP_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onTopView())); + myActionsMap[ TopId ] = aAction; + + aAction = new QtxAction(tr("MNU_BOTTOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_BOTTOM" ) ), + tr( "MNU_BOTTOM_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_BOTTOM_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onBottomView())); + myActionsMap[ BottomId ] = aAction; + + aAction = new QtxAction(tr("MNU_LEFT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_LEFT" ) ), + tr( "MNU_LEFT_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_LEFT_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onLeftView())); + myActionsMap[ LeftId ] = aAction; + + aAction = new QtxAction(tr("MNU_RIGHT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RIGHT" ) ), + tr( "MNU_RIGHT_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_RIGHT_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onRightView())); + myActionsMap[ RightId ] = aAction; + + // Reset + aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RESET" ) ), + tr( "MNU_RESET_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_RESET_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onResetView())); + myActionsMap[ ResetId ] = aAction; + + // Reset + aAction = new QtxAction(tr("MNU_CLONE_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLONE_VIEW" ) ), + tr( "MNU_CLONE_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_CLONE_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onCloneView())); + myActionsMap[ CloneId ] = aAction; + + aAction = new QtxAction(tr("MNU_CLIPPING"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING" ) ), + tr( "MNU_CLIPPING" ), 0, this); + aAction->setStatusTip(tr("DSC_CLIPPING")); + aAction->setToggleAction( true ); + connect(aAction, SIGNAL(toggled( bool )), this, SLOT(onClipping( bool ))); + myActionsMap[ ClippingId ] = aAction; + + aAction = new QtxAction(tr("MNU_SHOOT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_SHOOT_VIEW" ) ), + tr( "MNU_SHOOT_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_SHOOT_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onMemorizeView())); + myActionsMap[ MemId ] = aAction; + + aAction = new QtxAction(tr("MNU_PRESETS_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_PRESETS_VIEW" ) ), + tr( "MNU_PRESETS_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_PRESETS_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onRestoreView())); + myActionsMap[ RestoreId ] = aAction; + + if (myModel->trihedronActivated()) { + aAction = new QtxAction(tr("MNU_SHOW_TRIHEDRE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_TRIHEDRON" ) ), + tr( "MNU_SHOW_TRIHEDRE" ), 0, this); + aAction->setStatusTip(tr("DSC_SHOW_TRIHEDRE")); + connect(aAction, SIGNAL(activated()), this, SLOT(onTrihedronShow())); + myActionsMap[ TrihedronShowId ] = aAction; + } +} + +//**************************************************************** +void OCCViewer_ViewWindow::createToolBar() +{ + myActionsMap[DumpId]->addTo(myToolBar); + if ( myModel->trihedronActivated() ) + myActionsMap[TrihedronShowId]->addTo(myToolBar); + + SUIT_ToolButton* aScaleBtn = new SUIT_ToolButton(myToolBar, "scale"); + aScaleBtn->AddAction(myActionsMap[FitAllId]); + aScaleBtn->AddAction(myActionsMap[FitRectId]); + aScaleBtn->AddAction(myActionsMap[ZoomId]); + + SUIT_ToolButton* aPanningBtn = new SUIT_ToolButton(myToolBar, "pan"); + aPanningBtn->AddAction(myActionsMap[PanId]); + aPanningBtn->AddAction(myActionsMap[GlobalPanId]); + + myActionsMap[RotationId]->addTo(myToolBar); + + SUIT_ToolButton* aViewsBtn = new SUIT_ToolButton(myToolBar, "projection"); + aViewsBtn->AddAction(myActionsMap[FrontId]); + aViewsBtn->AddAction(myActionsMap[BackId]); + aViewsBtn->AddAction(myActionsMap[TopId]); + aViewsBtn->AddAction(myActionsMap[BottomId]); + aViewsBtn->AddAction(myActionsMap[LeftId]); + aViewsBtn->AddAction(myActionsMap[RightId]); + + myActionsMap[ResetId]->addTo(myToolBar); + + SUIT_ToolButton* aMemBtn = new SUIT_ToolButton(myToolBar, "view"); + aMemBtn->AddAction(myActionsMap[MemId]); + aMemBtn->AddAction(myActionsMap[RestoreId]); + + myToolBar->addSeparator(); + myActionsMap[CloneId]->addTo(myToolBar); + + myToolBar->addSeparator(); + myActionsMap[ClippingId]->addTo(myToolBar); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onViewFitAll() +{ + myViewPort->fitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onFrontView() +{ + emit vpTransformationStarted ( FRONTVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xpos); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onBackView() +{ + emit vpTransformationStarted ( BACKVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xneg); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onTopView() +{ + emit vpTransformationStarted ( TOPVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zpos); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onBottomView() +{ + emit vpTransformationStarted ( BOTTOMVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zneg); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onLeftView() +{ + emit vpTransformationStarted ( LEFTVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Yneg); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onRightView() +{ + emit vpTransformationStarted ( RIGHTVIEW ); + Handle(V3d_View) aView3d = myViewPort->getView(); + if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Ypos); + onViewFitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onResetView() +{ + emit vpTransformationStarted( RESETVIEW ); + bool upd = myViewPort->getView()->SetImmediateUpdate( false ); + myViewPort->getView()->Reset( false ); + myViewPort->fitAll( false, true, false ); + myViewPort->getView()->SetImmediateUpdate( upd ); + myViewPort->getView()->Update(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onFitAll() +{ + emit vpTransformationStarted( FITALLVIEW ); + myViewPort->fitAll(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onCloneView() +{ + SUIT_ViewWindow* vw = myManager->createViewWindow(); + vw->show(); +} + +//**************************************************************** +void OCCViewer_ViewWindow::onClipping( bool on ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + if ( on ) + myActionsMap[ ClippingId ]->setIconSet(aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING_PRESSED" ))); + else + myActionsMap[ ClippingId ]->setIconSet(aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING" ))); + + if ( on ) + { + if ( !myClippingDlg ) + myClippingDlg = new OCCViewer_ClippingDlg( this, myDesktop ); + + if ( !myClippingDlg->isShown() ) + myClippingDlg->show(); + } + else + { + if ( myClippingDlg->isShown() ) + myClippingDlg->hide(); + setCuttingPlane(false); + } +} + +//**************************************************************** +void OCCViewer_ViewWindow::onMemorizeView() +{ + double centerX, centerY, projX, projY, projZ, twist; + double atX, atY, atZ, eyeX, eyeY, eyeZ; + + Handle(V3d_View) aView3d = myViewPort->getView(); + + aView3d->Center( centerX, centerY ); + aView3d->Proj( projX, projY, projZ ); + aView3d->At( atX, atY, atZ ); + aView3d->Eye( eyeX, eyeY, eyeZ ); + twist = aView3d->Twist(); + + viewAspect params; + QString aName = QTime::currentTime().toString() + QString::fromLatin1( " h:m:s" ); + + params.scale = aView3d->Scale(); + params.centerX = centerX; + params.centerY = centerY; + params.projX = projX; + params.projY = projY; + params.projZ = projZ; + params.twist = twist; + params.atX = atX; + params.atY = atY; + params.atZ = atZ; + params.eyeX = eyeX; + params.eyeY = eyeY; + params.eyeZ = eyeZ; + params.name = aName; + + myModel->appendViewAspect( params ); + +} + +//**************************************************************** +void OCCViewer_ViewWindow::onRestoreView() +{ + OCCViewer_CreateRestoreViewDlg* aDlg = new OCCViewer_CreateRestoreViewDlg( centralWidget(), myModel ); + connect( aDlg, SIGNAL( dlgOk() ), this, SLOT( setRestoreFlag() ) ); + aDlg->exec(); + myModel->updateViewAspects( aDlg->parameters() ); + if( myRestoreFlag && aDlg->parameters().count() ) + performRestoring( aDlg->currentItem() ); +} + +//**************************************************************** + +void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem ) +{ + Handle(V3d_View) aView3d = myViewPort->getView(); + + Standard_Boolean prev = aView3d->SetImmediateUpdate( Standard_False ); + aView3d->SetScale( anItem.scale ); + aView3d->SetCenter( anItem.centerX, anItem.centerY ); + aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ ); + aView3d->SetTwist( anItem.twist ); + aView3d->SetAt( anItem.atX, anItem.atY, anItem.atZ ); + aView3d->SetImmediateUpdate( prev ); + aView3d->SetEye( anItem.eyeX, anItem.eyeY, anItem.eyeZ ); + + myRestoreFlag = 0; +} + +void OCCViewer_ViewWindow::setRestoreFlag() +{ + myRestoreFlag = 1; +} + +//**************************************************************** +void OCCViewer_ViewWindow::onTrihedronShow() +{ + myModel->toggleTrihedron(); +} + +//**************************************************************** +QImage OCCViewer_ViewWindow::dumpView() +{ + QPixmap px = QPixmap::grabWindow( myViewPort->winId() ); + return px.convertToImage(); +} + +void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x, const double y, const double z, + const double dx, const double dy, const double dz ) +{ + if ( on ) { + Handle(V3d_Viewer) viewer = myViewPort->getViewer(); + Handle(V3d_View) view = myViewPort->getView(); + + // try to use already existing plane or create a new one + Handle(V3d_Plane) clipPlane; + view->InitActivePlanes(); + if ( view->MoreActivePlanes() ) + clipPlane = view->ActivePlane(); + else + clipPlane = new V3d_Plane( viewer ); + + // set new a,b,c,d values for the plane + gp_Pln pln( gp_Pnt( x, y, z ), gp_Dir( dx, dy, dz ) ); + double a, b, c, d; + pln.Coefficients( a, b, c, d ); + clipPlane->SetPlane( a, b, c, d ); + + Handle(V3d_View) v = myViewPort->getView(); + v->SetPlaneOn( clipPlane ); + v->Update(); + v->Redraw(); + } + else { + Handle(V3d_View) view = myViewPort->getView(); + + // try to use already existing plane + Handle(V3d_Plane) clipPlane; + view->InitActivePlanes(); + if ( view->MoreActivePlanes() ) + clipPlane = view->ActivePlane(); + + Handle(V3d_View) v = myViewPort->getView(); + if ( !clipPlane.IsNull() ) + v->SetPlaneOff( clipPlane ); + else + v->SetPlaneOff(); + + v->Update(); + v->Redraw(); + } + + Handle(V3d_View) v = myViewPort->getView(); + v->Update(); + v->Redraw(); +} diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h new file mode 100755 index 000000000..b4f2bc8db --- /dev/null +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -0,0 +1,156 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef OCCVIEWER_VIEWWINDOW_H +#define OCCVIEWER_VIEWWINDOW_H + +#include "OCCViewer_ViewModel.h" + +#include "SUIT_ViewWindow.h" + +#include "QtxAction.h" + +#include +#include + +class SUIT_Desktop; +class OCCViewer_ViewPort3d; + +class OCCViewer_ClippingDlg; + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +class OCCVIEWER_EXPORT OCCViewer_ViewWindow : public SUIT_ViewWindow +{ + Q_OBJECT + +public: + enum OperationType{ NOTHING, PANVIEW, ZOOMVIEW, ROTATE, PANGLOBAL, WINDOWFIT, FITALLVIEW, RESETVIEW, + FRONTVIEW, BACKVIEW, TOPVIEW, BOTTOMVIEW, LEFTVIEW, RIGHTVIEW }; + + OCCViewer_ViewWindow(SUIT_Desktop* theDesktop, OCCViewer_Viewer* theModel); + virtual ~OCCViewer_ViewWindow() {}; + + OCCViewer_ViewPort3d* getViewPort() { return myViewPort; } + + bool eventFilter(QObject* watched, QEvent* e); + + QToolBar* getToolBar() { return myToolBar; } + + void performRestoring( const viewAspect& ); + + virtual void initLayout(); + + void updateEnabledDrawMode(); + + void setCuttingPlane( bool on, const double x = 0 , const double y = 0 , const double z = 0, + const double dx = 0, const double dy = 0, const double dz = 1); + +public slots: + void onFrontView(); + void onViewFitAll(); + void onBackView(); + void onTopView(); + void onBottomView(); + void onLeftView(); + void onRightView(); + void onResetView(); + void onFitAll(); + void activateZoom(); + void activateWindowFit(); + void activateRotation(); + void activatePanning(); + void activateGlobalPanning(); + void onCloneView(); + void onClipping( bool on ); + void onMemorizeView(); + void onRestoreView(); + void onTrihedronShow(); + void setRestoreFlag(); + +signals: + void vpTransformationStarted(OCCViewer_ViewWindow::OperationType type); + void vpTransformationFinished(OCCViewer_ViewWindow::OperationType type); + void cloneView(); + +protected: + enum { DumpId, FitAllId, FitRectId, ZoomId, PanId, GlobalPanId, RotationId, + FrontId, BackId, TopId, BottomId, LeftId, RightId, ResetId, CloneId, ClippingId, MemId, RestoreId, + TrihedronShowId }; + + typedef QMap ActionsMap; + + QImage dumpView(); + + /* Transformation selected but not started yet */ + bool transformRequested() const { return ( myOperation != NOTHING ); } + void setTransformRequested ( OperationType op ); + + /* Transformation is selected and already started */ + bool transformInProcess() const { return myEventStarted; } + void setTransformInProcess( bool bOn ) { myEventStarted = bOn; } + + void vpMousePressEvent(QMouseEvent* theEvent); + void vpMouseReleaseEvent(QMouseEvent* theEvent); + void vpMouseMoveEvent(QMouseEvent* theEvent); + + void resetState(); + void drawRect(); + + void createActions(); + void createToolBar(); + + virtual OperationType getButtonState(QMouseEvent* theEvent); + + OperationType myOperation; + OCCViewer_Viewer* myModel; + OCCViewer_ViewPort3d* myViewPort; + + int myRestoreFlag; + + int myStartX; + int myStartY; + int myCurrX; + int myCurrY; + + bool myEventStarted; // set when transformation is in process + bool myCursorIsHand; + bool myDrawRect; // set when a rect is used for selection or magnify + bool myEnableDrawMode; + bool myPaintersRedrawing; // set to draw with external painters + + QRect myRect; + QCursor myCursor; + + QToolBar* myToolBar; + ActionsMap myActionsMap; + + double myCurScale; + +private: + OCCViewer_ClippingDlg* myClippingDlg; + +}; + +#ifdef WIN32 +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/OCCViewer/resources/OCCViewer_images.po b/src/OCCViewer/resources/OCCViewer_images.po new file mode 100755 index 000000000..432135489 --- /dev/null +++ b/src/OCCViewer/resources/OCCViewer_images.po @@ -0,0 +1,96 @@ +# SALOME SALOMEGUI : implementation of desktop and GUI kernel +# +# Copyright (C) 2003 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. +# +# 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +# +# +# +# File : SALOMEGUI_icons.po +# Module : SALOME + +msgid "" +msgstr "" +"Project-Id-Version: example-Qt-message-extraction\n" +"POT-Creation-Date: 1999-02-23 15:38+0200\n" +"PO-Revision-Date: 1999-02-23 15:38+0200\n" +"Last-Translator: \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +msgid "ICON_OCCVIEWER_VIEW_BACK" +msgstr "view_back.png" + +msgid "ICON_OCCVIEWER_VIEW_BOTTOM" +msgstr "view_bottom.png" + +msgid "ICON_OCCVIEWER_VIEW_FITALL" +msgstr "view_fitall.png" + +msgid "ICON_OCCVIEWER_VIEW_FITAREA" +msgstr "view_fitarea.png" + +msgid "ICON_OCCVIEWER_VIEW_FRONT" +msgstr "view_front.png" + +msgid "ICON_OCCVIEWER_VIEW_GLOBALPAN" +msgstr "view_glpan.png" + +msgid "ICON_OCCVIEWER_VIEW_LEFT" +msgstr "view_left.png" + +msgid "ICON_OCCVIEWER_VIEW_PAN" +msgstr "view_pan.png" + +msgid "ICON_OCCVIEWER_VIEW_RESET" +msgstr "view_reset.png" + +msgid "ICON_OCCVIEWER_VIEW_RIGHT" +msgstr "view_right.png" + +msgid "ICON_OCCVIEWER_VIEW_ROTATE" +msgstr "view_rotate.png" + +msgid "ICON_OCCVIEWER_VIEW_TOP" +msgstr "view_top.png" + +msgid "ICON_OCCVIEWER_VIEW_ZOOM" +msgstr "view_zoom.png" + +msgid "ICON_OCCVIEWER_VIEW_TRIHEDRON" +msgstr "view_triedre.png" + +msgid "ICON_OCCVIEWER_VIEW_DUMP" +msgstr "view_camera_dump.png" + +msgid "ICON_OCCVIEWER_CLONE_VIEW" +msgstr "view_clone.png" + +msgid "ICON_OCCVIEWER_CLIPPING" +msgstr "view_clipping.png" + +msgid "ICON_OCCVIEWER_CLIPPING_PRESSED" +msgstr "view_clipping_pressed.png" + +msgid "ICON_OCCVIEWER_SHOOT_VIEW" +msgstr "view_shoot.png" + +msgid "ICON_OCCVIEWER_PRESETS_VIEW" +msgstr "view_presets.png" + + + diff --git a/src/OCCViewer/resources/OCCViewer_msg_en.po b/src/OCCViewer/resources/OCCViewer_msg_en.po new file mode 100755 index 000000000..ceab129bf --- /dev/null +++ b/src/OCCViewer/resources/OCCViewer_msg_en.po @@ -0,0 +1,188 @@ +# SALOME SALOMEGUI : implementation of desktop and GUI kernel +# +# Copyright (C) 2003 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. +# +# 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +# +# +# +# File : SALOMEGUI_msg_en.po +# Module : SALOME + +msgid "" +msgstr "" +"Project-Id-Version: example-Qt-message-extraction\n" +"POT-Creation-Date: 1999-02-23 15:38+0200\n" +"PO-Revision-Date: 1999-02-23 15:38+0200\n" +"Last-Translator: \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +msgid "LBL_TOOLBAR_LABEL" +msgstr "View Operations" + +msgid "DSC_FRONT_VIEW" +msgstr "Front View" + +msgid "MNU_FRONT_VIEW" +msgstr "Front" + +msgid "DSC_BACK_VIEW" +msgstr "Back View" + +msgid "MNU_BACK_VIEW" +msgstr "Back" + +msgid "DSC_TOP_VIEW" +msgstr "Top View" + +msgid "MNU_TOP_VIEW" +msgstr "Top" + +msgid "DSC_BOTTOM_VIEW" +msgstr "Bottom View" + +msgid "MNU_BOTTOM_VIEW" +msgstr "Bottom" + +msgid "DSC_LEFT_VIEW" +msgstr "Left View" + +msgid "MNU_LEFT_VIEW" +msgstr "Left" + +msgid "DSC_RIGHT_VIEW" +msgstr "Right View" + +msgid "MNU_RIGHT_VIEW" +msgstr "Right" + +msgid "DSC_RESET_VIEW" +msgstr "Reset View Point" + +msgid "MNU_RESET_VIEW" +msgstr "Reset" + +msgid "DSC_FITALL" +msgstr "Fit all objects inside the view frame" + +msgid "MNU_FITALL" +msgstr "Fit All" + +msgid "DSC_FITRECT" +msgstr "Fit area within the view frame" + +msgid "MNU_FITRECT" +msgstr "Fit Area" + +msgid "DSC_ZOOM_VIEW" +msgstr "Zoom the view" + +msgid "MNU_ZOOM_VIEW" +msgstr "Zoom" + +msgid "DSC_PAN_VIEW" +msgstr "Panning the view" + +msgid "MNU_PAN_VIEW" +msgstr "Panning" + +msgid "DSC_GLOBALPAN_VIEW" +msgstr "Selection of a new center of the view" + +msgid "MNU_GLOBALPAN_VIEW" +msgstr "Global Panning" + +msgid "DSC_ROTATE_VIEW" +msgstr "Rotation of the point of view around the scene center" + +msgid "MNU_ROTATE_VIEW" +msgstr "Rotation" + +msgid "DSC_CLONE_VIEW" +msgstr "Create new OCC viewer for the active scene" + +msgid "MNU_CLONE_VIEW" +msgstr "Clone View" + +msgid "MNU_DUMP_VIEW" +msgstr "Dump view" + +msgid "DSC_CLIPPING" +msgstr "Define clipping plane" + +msgid "MNU_CLIPPING" +msgstr "Clipping" + +msgid "DSC_DUMP_VIEW" +msgstr "Saves the active view in the image file" + +msgid "MNU_SHOOT_VIEW" +msgstr "Memorize View" + +msgid "DSC_SHOOT_VIEW" +msgstr "Memorizes the state of the active view and adds it to the list" + +msgid "MNU_PRESETS_VIEW" +msgstr "Restore View" + +msgid "DSC_PRESETS_VIEW" +msgstr "Selection of the memorized state of the active view" + +msgid "OCC_IMAGE_FILES" +msgstr "Images Files (*.bmp *.png *.jpg *.jpeg)" + +msgid "INF_APP_DUMP_VIEW" +msgstr "Dump view" + +msgid "INF_APP_SHOOT_VIEW" +msgstr "Memorize view" + +msgid "INF_APP_PRESETS_VIEW" +msgstr "Restore view" + +msgid "ERR_DOC_CANT_SAVE_FILE" +msgstr "Cannot save file" + +msgid "ERROR" +msgstr "Error" + +msgid "BUT_OK" +msgstr "Ok" + + +msgid "OCCViewer_Viewer::MEN_DUMP_VIEW" +msgstr "Dump view..." + +msgid "OCCViewer_Viewer::MEN_SHOW_TOOLBAR" +msgstr "Show toolbar" + +msgid "OCCViewer_Viewer::MEN_CHANGE_BACKGROUD" +msgstr "Change background..." + +msgid "OCCViewer_ViewManager::OCC_VIEW_TITLE" +msgstr "OCC scene:%1 - viewer:%2" + + +msgid "OCCViewer_CreateRestoreViewDlg::CAPTION" +msgstr "Restore view" + +msgid "MNU_SHOW_TRIHEDRE" +msgstr "Show/Hide trihedron" + +msgid "DSC_SHOW_TRIHEDRE" +msgstr "Show/Hide trihedron in the current view" diff --git a/src/OCCViewer/resources/view_clipping.png b/src/OCCViewer/resources/view_clipping.png new file mode 100644 index 000000000..dce8bd5c5 Binary files /dev/null and b/src/OCCViewer/resources/view_clipping.png differ diff --git a/src/OCCViewer/resources/view_clipping_pressed.png b/src/OCCViewer/resources/view_clipping_pressed.png new file mode 100644 index 000000000..7895f6554 Binary files /dev/null and b/src/OCCViewer/resources/view_clipping_pressed.png differ diff --git a/src/ObjBrowser/OB_ListItem.cxx b/src/ObjBrowser/OB_ListItem.cxx new file mode 100755 index 000000000..b2ced5c7b --- /dev/null +++ b/src/ObjBrowser/OB_ListItem.cxx @@ -0,0 +1,297 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "OB_ListItem.h" + +#include "OB_ListView.h" + +#include + +#include +#include + +#include +using namespace std; + +/*! + Class: ListItem + Descr: base template class +*/ + +template +ListItemF::ListItemF( T& theT, SUIT_DataObject* obj ) : +myT( theT ), +myObject( obj ) +{ +} + +template +void ListItemF::paintC( QPainter* p, QColorGroup& cg, int c, int w, int align ) +{ +// QColorGroup colorGrp( cg ); + if ( myObject ) + { + if ( myObject->color( SUIT_DataObject::Text ).isValid() ) + cg.setColor( QColorGroup::Text, myObject->color( SUIT_DataObject::Text ) ); + if ( myObject->color( SUIT_DataObject::Base ).isValid() ) + cg.setColor( QColorGroup::Base, myObject->color( SUIT_DataObject::Base ) ); + if ( myObject->color( SUIT_DataObject::Foreground ).isValid() ) + cg.setColor( QColorGroup::Foreground, myObject->color( SUIT_DataObject::Foreground ) ); + if ( myObject->color( SUIT_DataObject::Background ).isValid() ) + cg.setColor( QColorGroup::Background, myObject->color( SUIT_DataObject::Background ) ); + if ( myObject->color( SUIT_DataObject::Highlight ).isValid() ) + cg.setColor( QColorGroup::Highlight, myObject->color( SUIT_DataObject::Highlight ) ); + if ( myObject->color( SUIT_DataObject::HighlightedText ).isValid() ) + cg.setColor( QColorGroup::HighlightedText, myObject->color( SUIT_DataObject::HighlightedText ) ); + } + + + p->fillRect( 0, 0, w, myT.height(), cg.brush( QColorGroup::Base ) ); + //int itemW = myT.width( p->fontMetrics(), myT.listView(), c ); + + //myT.paintCell( p, colorGrp, c, itemW, align ); +} + +template +void ListItemF::paintFoc( QPainter* p, QColorGroup& cg, const QRect& r ) +{ + QRect rect = r; + rect.setWidth( myT.width( p->fontMetrics(), myT.listView(), 0 ) ); + //myT.paintFocus( p, cg, rect ); +} + +template +void ListItemF::setSel( bool s ) +{ + QListView* lv = myT.listView(); + if ( s && lv && lv->inherits( "OB_ListView" ) ) + { + OB_ListView* objlv = (OB_ListView*)lv; + s = s && objlv->isOk( &myT ); + } + + //myT.setSelected( s ); +} + +template +void ListItemF::update() +{ + SUIT_DataObject* obj = dataObject(); + if ( !obj ) + return; + + myT.setText( 0, obj->name() ); + + int aIconW = obj->icon().width(); + if ( aIconW > 0 ) + { + if ( aIconW > 20 ) + { + QWMatrix aM; + double aScale = 20.0 / aIconW; + aM.scale( aScale, aScale ); + myT.setPixmap( 0, obj->icon().xForm( aM ) ); + } + else + myT.setPixmap( 0, obj->icon() ); + } + + myT.setDragEnabled( obj->isDragable() ); + myT.setDropEnabled( true ); +} + +/*! + Class: OB_ListItem + Descr: List view item for OB_Browser. +*/ + +OB_ListItem::OB_ListItem( SUIT_DataObject* obj, QListView* parent ) +: ListItemF( *this, obj ), + QListViewItem(parent) +{ + update(); +} + +OB_ListItem::OB_ListItem( SUIT_DataObject* obj, QListViewItem* parent ) +: ListItemF( *this, obj), + QListViewItem(parent) +{ + update(); +} + +OB_ListItem::OB_ListItem( SUIT_DataObject* obj, QListView* parent, QListViewItem* after ) +: ListItemF( *this, obj), +QListViewItem(parent, after ) +{ + update(); +} + +OB_ListItem::OB_ListItem( SUIT_DataObject* obj, QListViewItem* parent, QListViewItem* after ) +: ListItemF( *this,obj), +QListViewItem(parent, after ) +{ + update(); +} + +OB_ListItem::~OB_ListItem() +{ +} + +void OB_ListItem::setSelected( bool s ) +{ + setSel( s ); + QListViewItem::setSelected( s ); +} + +void OB_ListItem::paintFocus( QPainter* p, const QColorGroup& cg, const QRect& r ) +{ + QColorGroup col_group( cg ); + paintFoc( p, col_group, r ); + + QRect R( r ); + if ( listView() && !listView()->allColumnsShowFocus() ) + R.setWidth( width( p->fontMetrics(), listView(), 0 ) ); + + QListViewItem::paintFocus( p, col_group, R ); +} + +void OB_ListItem::paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ) +{ + QColorGroup col_group( cg ); + paintC( p, col_group, c ,w, align ); + + int W = w; + if ( listView() && !listView()->allColumnsShowFocus() ) + W = width( p->fontMetrics(), listView(), c ); + + QListViewItem::paintCell( p, col_group, c, W, align ); +} + +int OB_ListItem::RTTI() +{ + return 1000; +} + +int OB_ListItem::rtti() const +{ + return RTTI(); +} + +void OB_ListItem::setText( int column, const QString& text ) +{ + QListViewItem::setText( column, text ); + QFontMetrics fm = listView()->fontMetrics(); + int necessary = width( fm, listView(), column ), + current = listView()->columnWidth( column ); + + if( listView()->columnWidthMode( column )==QListView::Maximum && necessary>current ) + listView()->setColumnWidth( column, necessary ); +} + +/*! + Class: OB_CheckListItem + Descr: Check list view item for OB_Browser. +*/ + +OB_CheckListItem::OB_CheckListItem( SUIT_DataObject* obj, QListView* parent, Type type ) +: ListItemF( *this, obj), +QCheckListItem( parent, "", type ) +{ + update(); +} + +OB_CheckListItem::OB_CheckListItem( SUIT_DataObject* obj, QListViewItem* parent, Type type ) +: ListItemF( *this, obj), +QCheckListItem( parent, "", type ) +{ + update(); +} + +OB_CheckListItem::OB_CheckListItem( SUIT_DataObject* obj, QListView* parent, QListViewItem* after, Type type ) +: ListItemF( *this, obj), +#if defined(QT_VERSION) && QT_VERSION >= 0x030101 + QCheckListItem( parent, after, "", type ) +#else + QCheckListItem( parent, "", type ) +#endif +{ + update(); +} + +OB_CheckListItem::OB_CheckListItem( SUIT_DataObject* obj, QListViewItem* parent, QListViewItem* after, Type type ) +: ListItemF( *this, obj), +#if defined(QT_VERSION) && QT_VERSION >= 0x030101 + QCheckListItem( parent, after, "", type ) +#else + QCheckListItem( parent, "", type ) +#endif +{ + update(); +} + +OB_CheckListItem::~OB_CheckListItem() +{ +} + +void OB_CheckListItem::setSelected( bool s ) +{ + setSel( s ); + QCheckListItem::setSelected( s ); +} + +void OB_CheckListItem::paintFocus( QPainter* p, const QColorGroup& cg, const QRect& r ) +{ + QColorGroup col_group( cg ); + paintFoc( p, col_group, r ); + + QRect R( r ); + if ( listView() && !listView()->allColumnsShowFocus() ) + R.setWidth( width( p->fontMetrics(), listView(), 0 ) ); + + QCheckListItem::paintFocus( p, col_group, R ); +} + +void OB_CheckListItem::paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ) +{ + QColorGroup col_group( cg ); + paintC( p, col_group, c ,w, align ); + + int W = w; + if ( listView() && !listView()->allColumnsShowFocus() ) + W = width( p->fontMetrics(), listView(), c ); + + QCheckListItem::paintCell( p, col_group, c, W, align ); +} + +int OB_CheckListItem::RTTI() +{ + return OB_ListItem::RTTI() + 1; +} + +int OB_CheckListItem::rtti() const +{ + return RTTI(); +} + +void OB_CheckListItem::stateChange( bool on ) +{ + QCheckListItem::stateChange( on ); + + if ( dataObject() ) + dataObject()->setOn( on ); +} diff --git a/src/ObjBrowser/OB_ListItem.h b/src/ObjBrowser/OB_ListItem.h new file mode 100755 index 000000000..6b06cd842 --- /dev/null +++ b/src/ObjBrowser/OB_ListItem.h @@ -0,0 +1,115 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#ifndef OB_LISTITEM_H +#define OB_LISTITEM_H + +#include "OB.h" + +#include + +class SUIT_DataObject; + +/* + base template class for ListViewItems and CheckListItems +*/ + +template class ListItemF +{ +public: + ListItemF(T&, SUIT_DataObject* ); + /*ListItem( SUIT_DataObject*, QListView* ); + ListItem( SUIT_DataObject*, QListViewItem* ); + ListItem( SUIT_DataObject*, QListView*, QListViewItem* ); + ListItem( SUIT_DataObject*, QListViewItem*, QListViewItem* ); + + ListItem( SUIT_DataObject*, QListView*, int ); + ListItem( SUIT_DataObject*, QListViewItem*, int ); + ListItem( SUIT_DataObject*, QListView*, QListViewItem*, int ); + ListItem( SUIT_DataObject*, QListViewItem*, QListViewItem*, int );*/ + + void setSel( bool s ); + inline SUIT_DataObject* dataObject() const { return myObject; } + void paintFoc( QPainter* p, QColorGroup& cg, const QRect& r ); + void paintC( QPainter* p, QColorGroup& cg, int c, int w, int align ); + +protected: + void update(); + +protected: + SUIT_DataObject* myObject; + T& myT; +}; + +/* + ListViewItem class +*/ + +class OB_EXPORT OB_ListItem : public ListItemF, public QListViewItem +{ +public: + OB_ListItem( SUIT_DataObject*, QListView* ); + OB_ListItem( SUIT_DataObject*, QListViewItem* ); + OB_ListItem( SUIT_DataObject*, QListView*, QListViewItem* ); + OB_ListItem( SUIT_DataObject*, QListViewItem*, QListViewItem* ); + + virtual ~OB_ListItem(); + + virtual void setSelected( bool s ); + virtual void paintFocus( QPainter* p, const QColorGroup& cg, const QRect& r ); + virtual void paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ); + + virtual void setText ( int column, const QString & text ); + + virtual int rtti() const; + + static int RTTI(); +}; + +/* + CheckListItem class +*/ + +class OB_EXPORT OB_CheckListItem : public ListItemF, public QCheckListItem +{ +public: + OB_CheckListItem( SUIT_DataObject*, QListView*, Type = CheckBox ); + OB_CheckListItem( SUIT_DataObject*, QListViewItem*, Type = CheckBox ); + OB_CheckListItem( SUIT_DataObject*, QListView*, QListViewItem*, Type = CheckBox ); + OB_CheckListItem( SUIT_DataObject*, QListViewItem*, QListViewItem*, Type = CheckBox ); + + virtual ~OB_CheckListItem(); + + virtual void setSelected( bool s ); + virtual void paintFocus( QPainter* p, const QColorGroup& cg, const QRect& r ); + virtual void paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ); + + + virtual int rtti() const; + + static int RTTI(); + +protected: + void stateChange( bool ); + +//private: +// void update(); +}; + +#endif diff --git a/src/ObjBrowser/OB_ListView.cxx b/src/ObjBrowser/OB_ListView.cxx new file mode 100755 index 000000000..53d62602f --- /dev/null +++ b/src/ObjBrowser/OB_ListView.cxx @@ -0,0 +1,200 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "OB_ListView.h" + +#include "OB_Filter.h" +#include "OB_ListItem.h" + +#include + +#include + +OB_ListView::OB_ListView( QWidget* parent, const char* name, WFlags f ) +: QtxListView( parent, name, f ), +myFilter( 0 ) +{ +} + +OB_ListView::OB_ListView( const int state, QWidget* parent, const char* name, WFlags f ) +: QtxListView( state, parent, name, f ), +myFilter( 0 ) +{ +} + +OB_ListView::~OB_ListView() +{ + delete myFilter; +} + +OB_Filter* OB_ListView::filter() const +{ + return myFilter; +} + +void OB_ListView::setFilter( OB_Filter* f ) +{ + if ( myFilter == f ) + return; + + delete myFilter; + myFilter = f; +} + +bool OB_ListView::isOk( QListViewItem* item ) const +{ + bool ok = true; + SUIT_DataObject* obj = dataObject( item ); + if ( obj && filter() ) + ok = filter()->isOk( obj ); + return ok; +} + +QDragObject* OB_ListView::dragObject() +{ + myItems.clear(); + + for ( QListViewItemIterator it( this ); it.current(); ++it ) + if ( it.current()->isSelected() ) + myItems.append( it.current() ); + + return new QTextDrag( "", this ); +} + +void OB_ListView::dragEnterEvent( QDragEnterEvent* e ) +{ + e->accept(); +} + +void OB_ListView::dragMoveEvent( QDragMoveEvent* e ) +{ + QListViewItem* item = dropItem( e ); + + if ( isDropAccepted( item ) ) + { + setCurrentItem( item ); + e->accept( true ); + } + else + e->accept( false ); +} + +void OB_ListView::dropEvent( QDropEvent* e ) +{ + QListViewItem* item = dropItem( e ); + if ( isDropAccepted( item ) ) + { + e->accept(); + emit dropped( myItems, item, e->action() ); + } + myItems.clear(); +} + +void OB_ListView::keyPressEvent( QKeyEvent* ke ) +{ + if ( ( ke->key() == Qt::Key_Plus || ke->key() == Qt::Key_Minus ) && ke->state() & ControlButton ) + { + bool isOpen = ke->key() == Qt::Key_Plus; + for ( QListViewItemIterator it( this ); it.current(); ++it ) + if ( it.current()->childCount() ) + it.current()->setOpen( isOpen ); + } + else + QtxListView::keyPressEvent( ke ); +} + +QListViewItem* OB_ListView::dropItem( QDropEvent* e ) const +{ + QListViewItem* item = 0; + if ( e ) + item = itemAt( QPoint( e->pos().x() - viewport()->x(), e->pos().y() - viewport()->y() ) ); + + return item; +} + +SUIT_DataObject* OB_ListView::dataObject( QListViewItem* item ) const +{ + if ( !item ) + return 0; + + SUIT_DataObject* obj = 0; + + if ( dynamic_cast( item ) ) + obj = dynamic_cast( item )->dataObject(); + else if ( dynamic_cast( item ) ) + obj = dynamic_cast( item )->dataObject(); + + return obj; +} + +bool OB_ListView::isDropAccepted( QListViewItem* item ) const +{ + bool res = true; + + for ( QPtrListIterator it( myItems ); it.current() && res; ++it ) + res = res && isDropAccepted( it.current(), item ); + + return res; +} + +bool OB_ListView::isDropAccepted( QListViewItem* drag, QListViewItem* drop ) const +{ + SUIT_DataObject* dragObj = dataObject( drag ); + SUIT_DataObject* dropObj = dataObject( drop ); + + if ( !dragObj || !dropObj ) + return false; + + return dropObj->isDropAccepted( dragObj ); +} + +void OB_ListView::setColumnWidth( int col, int width ) +{ + int max = columnMaxWidth( col ); + if( max>0 && width>max ) + width = max; + QListView::setColumnWidth( col, width ); +} + +int OB_ListView::columnMaxWidth( const int col ) const +{ + int res = -1; + if( myMaxColWidth.contains( col ) ) + res = myMaxColWidth[col]; + else if( myMaxColRatio.contains( col ) ) + res = int( myMaxColRatio[col]*height() ); + return res; +} + +void OB_ListView::setColumnMaxWidth( const int col, const int w ) +{ + myMaxColWidth.insert( col, w ); +} + +double OB_ListView::columnMaxRatio( const int col ) const +{ + double res = 0.0; + if( myMaxColRatio.contains( col ) ) + res = myMaxColRatio[col]; + return res; +} + +void OB_ListView::setColumnMaxRatio( const int col, const double r ) +{ + myMaxColRatio.insert( col, r ); +} diff --git a/src/ObjBrowser/OB_ListView.h b/src/ObjBrowser/OB_ListView.h new file mode 100755 index 000000000..03a394c21 --- /dev/null +++ b/src/ObjBrowser/OB_ListView.h @@ -0,0 +1,85 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef OB_LISTVIEW_H +#define OB_LISTVIEW_H + +#include "OB.h" + + +#include + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +#include + +class OB_Filter; +class QListViewItem; +class SUIT_DataObject; + +class OB_EXPORT OB_ListView : public QtxListView +{ + Q_OBJECT + +public: + OB_ListView( QWidget* = 0, const char* = 0, WFlags = 0 ); + OB_ListView( const int, QWidget* = 0, const char* = 0, WFlags = 0 ); + virtual ~OB_ListView(); + + OB_Filter* filter() const; + void setFilter( OB_Filter* ); + + bool isOk( QListViewItem* ) const; + virtual void setColumnWidth( int, int ); + int columnMaxWidth( const int ) const; + void setColumnMaxWidth( const int, const int ); + double columnMaxRatio( const int ) const; + void setColumnMaxRatio( const int, const double ); + +signals: + void dropped( QPtrList, QListViewItem*, int ); + +protected: + virtual QDragObject* dragObject(); + virtual void dropEvent( QDropEvent* ); + virtual void dragMoveEvent( QDragMoveEvent* ); + virtual void dragEnterEvent( QDragEnterEvent* ); + + virtual void keyPressEvent( QKeyEvent* ); + +private: + void updateHeader(); + QListViewItem* dropItem( QDropEvent* ) const; + SUIT_DataObject* dataObject( QListViewItem* ) const; + bool isDropAccepted( QListViewItem* ) const; + bool isDropAccepted( QListViewItem*, QListViewItem* ) const; + +protected: + QPtrList myItems; + OB_Filter* myFilter; + QMap myMaxColWidth; + QMap myMaxColRatio; +}; + +#ifdef WIN32 +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/Plot2d/Plot2d_Curve.cxx b/src/Plot2d/Plot2d_Curve.cxx new file mode 100755 index 000000000..c0a9abbb6 --- /dev/null +++ b/src/Plot2d/Plot2d_Curve.cxx @@ -0,0 +1,385 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "Plot2d_Curve.h" +#include + +/*! + Constructor +*/ +Plot2d_Curve::Plot2d_Curve() +: myHorTitle( "" ), myVerTitle( "" ), +myHorUnits( "" ), myVerUnits( "" ), +myAutoAssign( true ), myColor( 0,0,0 ), myMarker( Circle ), myLine( Solid ), myLineWidth( 0 ), +myYAxis( QwtPlot::yLeft ) +{ +} + +/*! + Destructor +*/ +Plot2d_Curve::~Plot2d_Curve() +{ +} + +/*! + Copy constructor. Makes deep copy of data. +*/ +Plot2d_Curve::Plot2d_Curve( const Plot2d_Curve& curve ) +{ + myAutoAssign = curve.isAutoAssign(); + myHorTitle = curve.getHorTitle(); + myVerTitle = curve.getVerTitle(); + myHorUnits = curve.getHorUnits(); + myVerUnits = curve.getVerUnits(); + myColor = curve.getColor(); + myMarker = curve.getMarker(); + myLine = curve.getLine(); + myLineWidth = curve.getLineWidth(); + myPoints = curve.getPointList(); +} + +/*! + operator=. Makes deep copy of data. +*/ +Plot2d_Curve& Plot2d_Curve::operator=( const Plot2d_Curve& curve ) +{ + myAutoAssign = curve.isAutoAssign(); + myHorTitle = curve.getHorTitle(); + myVerTitle = curve.getVerTitle(); + myHorUnits = curve.getHorUnits(); + myVerUnits = curve.getVerUnits(); + myColor = curve.getColor(); + myMarker = curve.getMarker(); + myLine = curve.getLine(); + myLineWidth = curve.getLineWidth(); + myPoints = curve.getPointList(); + return *this; +} + +QString Plot2d_Curve::getTableTitle() const +{ + return QString(); +} + +/*! + Sets curve's horizontal title +*/ +void Plot2d_Curve::setHorTitle( const QString& title ) +{ + myHorTitle = title; +} + +/*! + Gets curve's horizontal title +*/ +QString Plot2d_Curve::getHorTitle() const +{ + return myHorTitle; +} + +/*! + Sets curve's vertical title +*/ +void Plot2d_Curve::setVerTitle( const QString& title ) +{ + myVerTitle = title; +} + +/*! + Gets curve's vertical title +*/ +QString Plot2d_Curve::getVerTitle() const +{ + return myVerTitle; +} + +/*! + Sets curve's horizontal units +*/ +void Plot2d_Curve::setHorUnits( const QString& units ) +{ + myHorUnits = units; +} + +/*! + Gets curve's horizontal units +*/ +QString Plot2d_Curve::getHorUnits() const +{ + return myHorUnits; +} + +/*! + Sets curve's vertical units +*/ +void Plot2d_Curve::setVerUnits( const QString& units ) +{ + myVerUnits = units; +} + +/*! + Gets curve's vertical units +*/ +QString Plot2d_Curve::getVerUnits() const +{ + return myVerUnits; +} + +/*! + Adds one point for curve. +*/ +void Plot2d_Curve::addPoint(double theX, double theY) +{ + Plot2d_Point aPoint; + aPoint.x = theX; + aPoint.y = theY; + myPoints.append(aPoint); +} + +/*! + Insert one point for curve on some position. +*/ +void Plot2d_Curve::insertPoint(int thePos, double theX, double theY) +{ + Plot2d_Point aPoint; + aPoint.x = theX; + aPoint.y = theY; + + QValueList::iterator aIt; + int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if (thePos == aCurrent) { + myPoints.insert(aIt, aPoint); + return; + } + aCurrent++; + } + myPoints.append(aPoint); +} + +/*! + Delete one point for curve on some position. +*/ +void Plot2d_Curve::deletePoint(int thePos) +{ + QValueList::iterator aIt; + int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if (thePos == aCurrent) { + myPoints.remove(aIt); + return; + } + aCurrent++; + } +} + +/*! + Remove all points for curve. +*/ +void Plot2d_Curve::clearAllPoints() +{ + myPoints.clear(); +} + +/*! + Gets curve's data : abscissas of points +*/ +pointList Plot2d_Curve::getPointList() const +{ + return myPoints; +} + +/*! + Sets curve's data. +*/ +void Plot2d_Curve::setData( const double* hData, const double* vData, long size ) +{ + clearAllPoints(); + for(long i = 0; i < size; i++) addPoint(hData[i], vData[i]); +} + +/*! + Gets curve's data : abscissas of points +*/ +double* Plot2d_Curve::horData() const +{ + int aNPoints = nbPoints(); + double* aX = new double[aNPoints]; + for (int i = 0; i < aNPoints; i++) { + aX[i] = myPoints[i].x; + } + return aX; +} + +/*! + Gets curve's data : ordinates of points +*/ +double* Plot2d_Curve::verData() const +{ + int aNPoints = nbPoints(); + double* aY = new double[aNPoints]; + for (int i = 0; i < aNPoints; i++) { + aY[i] = myPoints[i].y; + } + return aY; +} + +/*! + Gets curve's data : number of points +*/ +int Plot2d_Curve::nbPoints() const +{ + return myPoints.count(); +} + +/*! + Returns true if curve has no data +*/ +bool Plot2d_Curve::isEmpty() const +{ + return myPoints.isEmpty(); +} + +/*! + Sets curve's AutoAssign flag - in this case attributes will be set automatically +*/ +void Plot2d_Curve::setAutoAssign( bool on ) +{ + myAutoAssign = on; +} + +/*! + Gets curve's AutoAssign flag state +*/ +bool Plot2d_Curve::isAutoAssign() const +{ + return myAutoAssign; +} + +/*! + Sets curve's color ( and resets AutoAssign flag ) +*/ +void Plot2d_Curve::setColor( const QColor& color ) +{ + myColor = color; + myAutoAssign = false; +} + +/*! + Gets curve's color +*/ +QColor Plot2d_Curve::getColor() const +{ + return myColor; +} + +/*! + Sets curve's marker ( and resets AutoAssign flag ) +*/ +void Plot2d_Curve::setMarker( MarkerType marker ) +{ + myMarker = marker; + myAutoAssign = false; +} + +/*! + Gets curve's marker +*/ +Plot2d_Curve::MarkerType Plot2d_Curve::getMarker() const +{ + return myMarker; +} + +/*! + Sets curve's line type and width ( and resets AutoAssign flag ) + NOTE : A line width of 0 will produce a 1 pixel wide line using a fast algorithm for diagonals. + A line width of 1 will also produce a 1 pixel wide line, but uses a slower more accurate + algorithm for diagonals. + For horizontal and vertical lines a line width of 0 is the same as a line width of 1. +*/ +void Plot2d_Curve::setLine( LineType line, const int lineWidth ) +{ + myLine = line; + myLineWidth = lineWidth; + if ( myLineWidth < 0 ) myLineWidth = 0; + myAutoAssign = false; +} + +/*! + Gets curve's line type +*/ +Plot2d_Curve::LineType Plot2d_Curve::getLine() const +{ + return myLine; +} + +/*! + Gets curve's line width +*/ +int Plot2d_Curve::getLineWidth() const +{ + return myLineWidth; +} + +/*! + Sets curve's y axis +*/ +void Plot2d_Curve::setYAxis(QwtPlot::Axis theYAxis) +{ + if(theYAxis == QwtPlot::yLeft || theYAxis == QwtPlot::yRight) + myYAxis = theYAxis; +} + +/*! + Gets curve's y axis +*/ +QwtPlot::Axis Plot2d_Curve::getYAxis() const +{ + return myYAxis; +} + +/*! + Gets curve's minimal abscissa +*/ +double Plot2d_Curve::getMinX() const +{ + QValueList::const_iterator aIt; + double aMinX = 1e150; + int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if ( (*aIt).x < aMinX ) + aMinX = (*aIt).x; + } + return aMinX; +} + +/*! + Gets curve's minimal ordinate +*/ +double Plot2d_Curve::getMinY() const +{ + QValueList::const_iterator aIt; + double aMinY = 1e150; + int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if ( (*aIt).y < aMinY ) + aMinY = (*aIt).y; + } + return aMinY; +} diff --git a/src/Plot2d/Plot2d_Curve.h b/src/Plot2d/Plot2d_Curve.h new file mode 100755 index 000000000..b17f7c327 --- /dev/null +++ b/src/Plot2d/Plot2d_Curve.h @@ -0,0 +1,108 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef PLOT2D_CURVE_H +#define PLOT2D_CURVE_H + +#include "Plot2d.h" +#include +#include +#include + +class QColor; + +typedef struct +{ + double x; + double y; +} Plot2d_Point; + +typedef QValueList pointList; + +class PLOT2D_EXPORT Plot2d_Curve +{ +public: + enum MarkerType { None, Circle, Rectangle, Diamond, + DTriangle, UTriangle, LTriangle, RTriangle, + Cross, XCross }; + enum LineType { NoPen, Solid, Dash, Dot, DashDot, DashDotDot }; + + Plot2d_Curve(); + virtual ~Plot2d_Curve(); + Plot2d_Curve( const Plot2d_Curve& curve ); + Plot2d_Curve& operator= ( const Plot2d_Curve& curve ); + + virtual QString getTableTitle() const; + + void setHorTitle( const QString& title ); + QString getHorTitle() const; + void setVerTitle( const QString& title ); + QString getVerTitle() const; + void setHorUnits( const QString& units ); + QString getHorUnits() const; + void setVerUnits( const QString& units ); + QString getVerUnits() const; + void addPoint(double theX, double theY); + void insertPoint(int thePos, double theX, double theY); + void deletePoint(int thePos); + void clearAllPoints(); + pointList getPointList() const; + + void setData( const double* hData, const double* vData, long size ); + double* horData() const; + double* verData() const; + + int nbPoints() const; + bool isEmpty() const; + + void setAutoAssign( bool on ); + bool isAutoAssign() const; + void setColor( const QColor& color ); + QColor getColor() const; + void setMarker( MarkerType marker ); + MarkerType getMarker() const; + void setLine( LineType line, const int lineWidth = 0 ); + LineType getLine() const; + int getLineWidth() const; + void setYAxis(QwtPlot::Axis theYAxis); + QwtPlot::Axis getYAxis() const; + + // Protection against QwtCurve::drawLines() bug in Qwt 0.4.x: + // it crashes if switched to X/Y logarithmic mode, when one or more points have + // non-positive X/Y coordinate + double getMinX() const; + double getMinY() const; + +protected: + bool myAutoAssign; + QString myHorTitle; + QString myVerTitle; + QString myHorUnits; + QString myVerUnits; + QColor myColor; + MarkerType myMarker; + LineType myLine; + int myLineWidth; + QwtPlot::Axis myYAxis; + + pointList myPoints; +}; + +typedef QPtrList curveList; + +#endif diff --git a/src/Plot2d/Plot2d_SetupViewDlg.cxx b/src/Plot2d/Plot2d_SetupViewDlg.cxx new file mode 100755 index 000000000..0969b6b44 --- /dev/null +++ b/src/Plot2d/Plot2d_SetupViewDlg.cxx @@ -0,0 +1,669 @@ +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Plot2d_SetupViewDlg.cxx +// Author : Vadim SANDLER +// Module : SALOME +// $Header$ + +#include "Plot2d_SetupViewDlg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MARGIN_SIZE 11 +#define SPACING_SIZE 6 +#define MIN_EDIT_WIDTH 200 +#define MIN_COMBO_WIDTH 100 +#define MIN_SPIN_WIDTH 70 + +/*! + Constructor +*/ +Plot2d_SetupViewDlg::Plot2d_SetupViewDlg( QWidget* parent, bool showDefCheck, bool secondAxisY ) + : QDialog( parent, "Plot2d_SetupViewDlg", true, + WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ) +{ + mySecondAxisY = secondAxisY; + setCaption( tr("TLT_SETUP_PLOT2D_VIEW") ); + setSizeGripEnabled( TRUE ); + QGridLayout* topLayout = new QGridLayout( this ); + topLayout->setSpacing( SPACING_SIZE ); + topLayout->setMargin( MARGIN_SIZE ); + + // main title + myTitleCheck = new QCheckBox( tr( "PLOT2D_ENABLE_MAIN_TITLE" ), this ); + myTitleEdit = new QLineEdit( this ); + myTitleEdit->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myTitleEdit->setMinimumWidth( MIN_EDIT_WIDTH ); + // curve type : points, lines, spline + QLabel* aCurveLab = new QLabel( tr( "PLOT2D_CURVE_TYPE_LBL" ), this ); + myCurveCombo = new QComboBox( false, this ); + myCurveCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myCurveCombo->setMinimumWidth( MIN_COMBO_WIDTH ); + myCurveCombo->insertItem( tr( "PLOT2D_CURVE_TYPE_POINTS" ) ); + myCurveCombo->insertItem( tr( "PLOT2D_CURVE_TYPE_LINES" ) ); + myCurveCombo->insertItem( tr( "PLOT2D_CURVE_TYPE_SPLINE" ) ); + // legend + myLegendCheck = new QCheckBox( tr( "PLOT2D_ENABLE_LEGEND" ), this ); + myLegendCombo = new QComboBox( false, this ); + myLegendCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myLegendCombo->setMinimumWidth( MIN_COMBO_WIDTH ); + myLegendCombo->insertItem( tr( "PLOT2D_LEGEND_POSITION_LEFT" ) ); + myLegendCombo->insertItem( tr( "PLOT2D_LEGEND_POSITION_RIGHT" ) ); + myLegendCombo->insertItem( tr( "PLOT2D_LEGEND_POSITION_TOP" ) ); + myLegendCombo->insertItem( tr( "PLOT2D_LEGEND_POSITION_BOTTOM" ) ); + // marker size + QLabel* aMarkerLab = new QLabel( tr( "PLOT2D_MARKER_SIZE_LBL" ), this ); + myMarkerSpin = new QSpinBox( 0, 100, 1, this ); + myMarkerSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myMarkerSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + + // background color + QLabel* aBGLab = new QLabel( tr( "PLOT2D_BACKGROUND_COLOR_LBL" ), this ); + myBackgroundBtn = new QToolButton( this ); + myBackgroundBtn->setMinimumWidth(20); + + // scale mode + QGroupBox* aScaleGrp = new QGroupBox( tr( "PLOT2D_SCALE_TLT" ), this ); + aScaleGrp->setColumnLayout(0, Qt::Vertical ); + aScaleGrp->layout()->setSpacing( 0 ); aScaleGrp->layout()->setMargin( 0 ); + QGridLayout* aScaleLayout = new QGridLayout( aScaleGrp->layout() ); + aScaleLayout->setMargin( MARGIN_SIZE ); aScaleLayout->setSpacing( SPACING_SIZE ); + + QLabel* xScaleLab = new QLabel( tr( "PLOT2D_SCALE_MODE_HOR" ), aScaleGrp ); + myXModeCombo = new QComboBox( false, aScaleGrp ); + myXModeCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myXModeCombo->setMinimumWidth( MIN_COMBO_WIDTH ); + myXModeCombo->insertItem( tr( "PLOT2D_SCALE_MODE_LINEAR" ) ); + myXModeCombo->insertItem( tr( "PLOT2D_SCALE_MODE_LOGARITHMIC" ) ); + QLabel* yScaleLab = new QLabel( tr( "PLOT2D_SCALE_MODE_VER" ), aScaleGrp ); + myYModeCombo = new QComboBox( false, aScaleGrp ); + myYModeCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myYModeCombo->setMinimumWidth( MIN_COMBO_WIDTH ); + myYModeCombo->insertItem( tr( "PLOT2D_SCALE_MODE_LINEAR" ) ); + myYModeCombo->insertItem( tr( "PLOT2D_SCALE_MODE_LOGARITHMIC" ) ); + + aScaleLayout->addWidget( xScaleLab, 0, 0 ); + aScaleLayout->addWidget( myXModeCombo, 0, 1 ); + aScaleLayout->addWidget( yScaleLab, 0, 2 ); + aScaleLayout->addWidget( myYModeCombo, 0, 3 ); + + // tab widget for choose properties of axis + QTabWidget* aTabWidget = new QTabWidget( this, "tabWidget" ); + + // widget for parameters on Ox + QWidget* aXWidget = new QWidget(aTabWidget); + QGridLayout* aXLayout = new QGridLayout( aXWidget ); + aXLayout->setSpacing( SPACING_SIZE ); + aXLayout->setMargin( MARGIN_SIZE ); + // axis title + myTitleXCheck = new QCheckBox( tr( "PLOT2D_ENABLE_HOR_TITLE" ), aXWidget ); + myTitleXEdit = new QLineEdit( aXWidget ); + myTitleXEdit->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myTitleXEdit->setMinimumWidth( MIN_EDIT_WIDTH ); + aXLayout->addWidget( myTitleXCheck, 1, 0 ); + aXLayout->addMultiCellWidget( myTitleXEdit, 1, 1, 1, 3 ); + // grid + QGroupBox* aGridGrpX = new QGroupBox( tr( "PLOT2D_GRID_TLT" ), aXWidget ); + aGridGrpX->setColumnLayout(0, Qt::Vertical ); + aGridGrpX->layout()->setSpacing( 0 ); aGridGrpX->layout()->setMargin( 0 ); + QGridLayout* aGridLayoutX = new QGridLayout( aGridGrpX->layout() ); + aGridLayoutX->setMargin( MARGIN_SIZE ); aGridLayoutX->setSpacing( SPACING_SIZE ); + myXGridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_HOR_MAJOR" ), aGridGrpX ); + QLabel* aXMajLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpX); + myXGridSpin = new QSpinBox( 1, 100, 1, aGridGrpX ); + myXGridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myXGridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + myXMinGridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_HOR_MINOR" ), aGridGrpX ); + QLabel* aXMinLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpX); + myXMinGridSpin = new QSpinBox( 1, 100, 1, aGridGrpX ); + myXMinGridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myXMinGridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + + aGridLayoutX->addWidget( myXGridCheck, 0, 0 ); + aGridLayoutX->addWidget( aXMajLbl, 0, 1 ); + aGridLayoutX->addWidget( myXGridSpin, 0, 2 ); + aGridLayoutX->addWidget( myXMinGridCheck, 1, 0 ); + aGridLayoutX->addWidget( aXMinLbl, 1, 1 ); + aGridLayoutX->addWidget( myXMinGridSpin, 1, 2 ); + aXLayout->addMultiCellWidget( aGridGrpX, 3, 3, 0, 3 ); + + aTabWidget->addTab( aXWidget, tr( "INF_AXES_X" ) ); + + // widget for parameters on Oy + QWidget* aYWidget = new QWidget(aTabWidget); + QGridLayout* aYLayout = new QGridLayout( aYWidget ); + aYLayout->setSpacing( SPACING_SIZE ); + aYLayout->setMargin( MARGIN_SIZE ); + // axis title + myTitleYCheck = new QCheckBox( tr( "PLOT2D_ENABLE_VER_TITLE" ), aYWidget ); + myTitleYEdit = new QLineEdit( aYWidget ); + myTitleYEdit->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myTitleYEdit->setMinimumWidth( MIN_EDIT_WIDTH ); + aYLayout->addWidget( myTitleYCheck, 1, 0 ); + aYLayout->addMultiCellWidget( myTitleYEdit, 1, 1, 1, 3 ); + // grid + QGroupBox* aGridGrpY = new QGroupBox( tr( "PLOT2D_GRID_TLT" ), aYWidget ); + aGridGrpY->setColumnLayout(0, Qt::Vertical ); + aGridGrpY->layout()->setSpacing( 0 ); aGridGrpY->layout()->setMargin( 0 ); + QGridLayout* aGridLayoutY = new QGridLayout( aGridGrpY->layout() ); + aGridLayoutY->setMargin( MARGIN_SIZE ); aGridLayoutY->setSpacing( SPACING_SIZE ); + myYGridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_VER_MAJOR" ), aGridGrpY ); + QLabel* aYMajLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpY); + myYGridSpin = new QSpinBox( 1, 100, 1, aGridGrpY ); + myYGridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myYGridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + myYMinGridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_VER_MINOR" ), aGridGrpY ); + QLabel* aYMinLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpY); + myYMinGridSpin = new QSpinBox( 1, 100, 1, aGridGrpY ); + myYMinGridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myYMinGridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + + aGridLayoutY->addWidget( myYGridCheck, 0, 0 ); + aGridLayoutY->addWidget( aYMajLbl, 0, 1 ); + aGridLayoutY->addWidget( myYGridSpin, 0, 2 ); + aGridLayoutY->addWidget( myYMinGridCheck, 1, 0 ); + aGridLayoutY->addWidget( aYMinLbl, 1, 1 ); + aGridLayoutY->addWidget( myYMinGridSpin, 1, 2 ); + aYLayout->addMultiCellWidget( aGridGrpY, 3, 3, 0, 3 ); + + aTabWidget->addTab( aYWidget, tr( "INF_AXES_Y_LEFT" ) ); + + // if exist second axis Oy, addition new tab widget for right axis + if (mySecondAxisY) { + // widget for parameters on Oy + QWidget* aYWidget2 = new QWidget(aTabWidget); + QGridLayout* aYLayout2 = new QGridLayout( aYWidget2 ); + aYLayout2->setSpacing( SPACING_SIZE ); + aYLayout2->setMargin( MARGIN_SIZE ); + // axis title + myTitleY2Check = new QCheckBox( tr( "PLOT2D_ENABLE_VER_TITLE" ), aYWidget2 ); + myTitleY2Edit = new QLineEdit( aYWidget2 ); + myTitleY2Edit->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myTitleY2Edit->setMinimumWidth( MIN_EDIT_WIDTH ); + aYLayout2->addWidget( myTitleY2Check, 1, 0 ); + aYLayout2->addMultiCellWidget( myTitleY2Edit, 1, 1, 1, 3 ); + // grid + QGroupBox* aGridGrpY2 = new QGroupBox( tr( "PLOT2D_GRID_TLT" ), aYWidget2 ); + aGridGrpY2->setColumnLayout(0, Qt::Vertical ); + aGridGrpY2->layout()->setSpacing( 0 ); aGridGrpY2->layout()->setMargin( 0 ); + QGridLayout* aGridLayoutY2 = new QGridLayout( aGridGrpY2->layout() ); + aGridLayoutY2->setMargin( MARGIN_SIZE ); aGridLayoutY2->setSpacing( SPACING_SIZE ); + myY2GridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_VER_MAJOR" ), aGridGrpY2 ); + QLabel* aY2MajLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpY2); + myY2GridSpin = new QSpinBox( 1, 100, 1, aGridGrpY2 ); + myY2GridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myY2GridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + myY2MinGridCheck = new QCheckBox( tr( "PLOT2D_GRID_ENABLE_VER_MINOR" ), aGridGrpY2 ); + QLabel* aY2MinLbl = new QLabel( tr( "PLOT2D_MAX_INTERVALS" ), aGridGrpY2); + myY2MinGridSpin = new QSpinBox( 1, 100, 1, aGridGrpY2 ); + myY2MinGridSpin->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + myY2MinGridSpin->setMinimumWidth( MIN_SPIN_WIDTH ); + + aGridLayoutY2->addWidget( myY2GridCheck, 0, 0 ); + aGridLayoutY2->addWidget( aY2MajLbl, 0, 1 ); + aGridLayoutY2->addWidget( myY2GridSpin, 0, 2 ); + aGridLayoutY2->addWidget( myY2MinGridCheck, 1, 0 ); + aGridLayoutY2->addWidget( aY2MinLbl, 1, 1 ); + aGridLayoutY2->addWidget( myY2MinGridSpin, 1, 2 ); + aYLayout2->addMultiCellWidget( aGridGrpY2, 3, 3, 0, 3 ); + + aTabWidget->addTab( aYWidget2, tr( "INF_AXES_Y_RIGHT" ) ); + } + else { + myTitleY2Check = 0; + myTitleY2Edit = 0; + myY2GridCheck = 0; + myY2GridSpin = 0; + myY2MinGridCheck = 0; + myY2MinGridSpin = 0; + myY2ModeCombo = 0; + } + aTabWidget->setCurrentPage( 0 ); + /* "Set as default" check box */ + myDefCheck = new QCheckBox( tr( "PLOT2D_SET_AS_DEFAULT_CHECK" ), this ); + /* OK/Cancel buttons */ + myOkBtn = new QPushButton( tr( "BUT_OK" ), this ); + myOkBtn->setAutoDefault( TRUE ); + myOkBtn->setDefault( TRUE ); + myCancelBtn = new QPushButton( tr( "BUT_CANCEL" ), this ); + myCancelBtn->setAutoDefault( TRUE ); + QHBoxLayout* btnLayout = new QHBoxLayout; + btnLayout->addWidget( myOkBtn ); + btnLayout->addStretch(); + btnLayout->addWidget( myCancelBtn ); + + // layout widgets + topLayout->addWidget( myTitleCheck, 0, 0 ); + topLayout->addMultiCellWidget( myTitleEdit, 0, 0, 1, 3 ); + topLayout->addWidget( aCurveLab, 1, 0 ); + topLayout->addWidget( myCurveCombo, 1, 1 ); + topLayout->addWidget( myLegendCheck, 1, 2 ); + topLayout->addWidget( myLegendCombo, 1, 3 ); + topLayout->addWidget( aMarkerLab, 2, 0 ); + topLayout->addWidget( myMarkerSpin, 2, 1 ); + QHBoxLayout* bgLayout = new QHBoxLayout; + bgLayout->addWidget( myBackgroundBtn ); bgLayout->addStretch(); + topLayout->addWidget( aBGLab, 2, 2 ); + topLayout->addLayout( bgLayout, 2, 3 ); + topLayout->addMultiCellWidget( aScaleGrp, 3, 3, 0, 3 ); + topLayout->addMultiCellWidget( aTabWidget, 4, 4, 0, 3 ); + topLayout->addMultiCellWidget( myDefCheck, 5, 5, 0, 3 ); + topLayout->setRowStretch( 5, 5 ); + + topLayout->addMultiCellLayout( btnLayout, 6, 6, 0, 3 ); + + if ( !showDefCheck ) + myDefCheck->hide(); + + connect( myTitleCheck, SIGNAL( clicked() ), this, SLOT( onMainTitleChecked() ) ); + connect( myTitleXCheck, SIGNAL( clicked() ), this, SLOT( onXTitleChecked() ) ); + connect( myTitleYCheck, SIGNAL( clicked() ), this, SLOT( onYTitleChecked() ) ); + connect( myBackgroundBtn, SIGNAL( clicked() ), this, SLOT( onBackgroundClicked() ) ); + connect( myLegendCheck, SIGNAL( clicked() ), this, SLOT( onLegendChecked() ) ); + connect( myXGridCheck, SIGNAL( clicked() ), this, SLOT( onXGridMajorChecked() ) ); + connect( myYGridCheck, SIGNAL( clicked() ), this, SLOT( onYGridMajorChecked() ) ); + connect( myXMinGridCheck, SIGNAL( clicked() ), this, SLOT( onXGridMinorChecked() ) ); + connect( myYMinGridCheck, SIGNAL( clicked() ), this, SLOT( onYGridMinorChecked() ) ); + + connect( myOkBtn, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + + if (mySecondAxisY) { + connect( myTitleY2Check, SIGNAL( clicked() ), this, SLOT( onY2TitleChecked() ) ); + connect( myY2GridCheck, SIGNAL( clicked() ), this, SLOT( onY2GridMajorChecked() ) ); + connect( myY2MinGridCheck, SIGNAL( clicked() ), this, SLOT( onY2GridMinorChecked() ) ); + } + + // init fields + setBackgroundColor( Qt::gray ); + onMainTitleChecked(); + onXTitleChecked(); + onYTitleChecked(); + onLegendChecked(); + onXGridMajorChecked(); + onYGridMajorChecked(); + onXGridMinorChecked(); + if (mySecondAxisY) { + onY2TitleChecked(); + onY2GridMajorChecked(); + onY2GridMinorChecked(); + } +} + +/*! + Destructor +*/ +Plot2d_SetupViewDlg::~Plot2d_SetupViewDlg() +{ +} +/*! + Sets main title attributes +*/ +void Plot2d_SetupViewDlg::setMainTitle( bool enable, const QString& title ) +{ + myTitleCheck->setChecked( enable ); + if ( !title.isNull() ) + myTitleEdit->setText( title ); + onMainTitleChecked(); +} +/*! + Returns TRUE if main title is enabled +*/ +bool Plot2d_SetupViewDlg::isMainTitleEnabled() +{ + return myTitleCheck->isChecked(); +} +/*! + Gets main title +*/ +QString Plot2d_SetupViewDlg::getMainTitle() +{ + return myTitleEdit->text(); +} +/*! + Sets horizontal axis title attributes +*/ +void Plot2d_SetupViewDlg::setXTitle( bool enable, const QString& title ) +{ + myTitleXCheck->setChecked( enable ); + if ( !title.isNull() ) + myTitleXEdit->setText( title ); + onXTitleChecked(); +} +/*! + Returns TRUE if horizontal axis title is enabled +*/ +bool Plot2d_SetupViewDlg::isXTitleEnabled() +{ + return myTitleXCheck->isChecked(); +} +/*! + Gets horizontal axis title +*/ +QString Plot2d_SetupViewDlg::getXTitle() +{ + return myTitleXEdit->text(); +} +/*! + Sets vertical left axis title attributes +*/ +void Plot2d_SetupViewDlg::setYTitle( bool enable, const QString& title ) +{ + myTitleYCheck->setChecked( enable ); + if ( !title.isNull() ) + myTitleYEdit->setText( title ); + onYTitleChecked(); +} +/*! + Sets vertical right axis title attributes +*/ +void Plot2d_SetupViewDlg::setY2Title( bool enable, const QString& title ) +{ + myTitleY2Check->setChecked( enable ); + if ( !title.isNull() ) + myTitleY2Edit->setText( title ); + onY2TitleChecked(); +} +/*! + Returns TRUE if vertical left axis title is enabled +*/ +bool Plot2d_SetupViewDlg::isYTitleEnabled() +{ + return myTitleYCheck->isChecked(); +} +/*! + Returns TRUE if vertical right axis title is enabled +*/ +bool Plot2d_SetupViewDlg::isY2TitleEnabled() +{ + return myTitleY2Check->isChecked(); +} +/*! + Gets vertical left axis title +*/ +QString Plot2d_SetupViewDlg::getYTitle() +{ + return myTitleYEdit->text(); +} +/*! + Gets vertical right axis title +*/ +QString Plot2d_SetupViewDlg::getY2Title() +{ + return myTitleY2Edit->text(); +} +/*! + Sets curve type : 0 - points, 1 - lines, 2 - splines +*/ +void Plot2d_SetupViewDlg::setCurveType( const int type ) +{ + myCurveCombo->setCurrentItem( type ); +} +/*! + Gets curve type : 0 - points, 1 - lines, 2 - splines +*/ +int Plot2d_SetupViewDlg::getCurveType() +{ + return myCurveCombo->currentItem(); +} +/*! + Sets legend attributes : pos = 0 - left, 1 - right, 2 - top, 3 - bottom +*/ +void Plot2d_SetupViewDlg::setLegend( bool enable, int pos ) +{ + myLegendCheck->setChecked( enable ); + myLegendCombo->setCurrentItem( pos ); + onLegendChecked(); +} +/*! + Returns TRUE if legend is enabled +*/ +bool Plot2d_SetupViewDlg::isLegendEnabled() +{ + return myLegendCheck->isChecked(); +} +/*! + Returns legend position +*/ +int Plot2d_SetupViewDlg::getLegendPos() +{ + return myLegendCombo->currentItem(); +} +/*! + Sets marker size +*/ +void Plot2d_SetupViewDlg::setMarkerSize( const int size ) +{ + myMarkerSpin->setValue( size ); +} +/*! + Gets marker size +*/ +int Plot2d_SetupViewDlg::getMarkerSize() +{ + return myMarkerSpin->value(); +} +/*! + Sets background color +*/ +void Plot2d_SetupViewDlg::setBackgroundColor( const QColor& color ) +{ + QPalette pal = myBackgroundBtn->palette(); + QColorGroup ca = pal.active(); + ca.setColor( QColorGroup::Button, color ); + QColorGroup ci = pal.inactive(); + ci.setColor( QColorGroup::Button, color ); + pal.setActive( ca ); + pal.setInactive( ci ); + myBackgroundBtn->setPalette( pal ); +} +/*! + Gets background color +*/ +QColor Plot2d_SetupViewDlg::getBackgroundColor() +{ + return myBackgroundBtn->palette().active().button(); +} +/*! + Sets major grid parameters +*/ +void Plot2d_SetupViewDlg::setMajorGrid( bool enableX, const int divX, + bool enableY, const int divY, + bool enableY2, const int divY2 ) +{ + myXGridCheck->setChecked( enableX ); + myXGridSpin->setValue( divX ); + myYGridCheck->setChecked( enableY ); + myYGridSpin->setValue( divY ); + onXGridMajorChecked(); + onYGridMajorChecked(); + if (mySecondAxisY) { + myY2GridCheck->setChecked( enableY2 ); + myY2GridSpin->setValue( divY2 ); + onY2GridMajorChecked(); + } +} +/*! + Gets major grid parameters +*/ +void Plot2d_SetupViewDlg::getMajorGrid( bool& enableX, int& divX, + bool& enableY, int& divY, + bool& enableY2, int& divY2) +{ + enableX = myXGridCheck->isChecked(); + divX = myXGridSpin->value(); + enableY = myYGridCheck->isChecked(); + divY = myYGridSpin->value(); + if (mySecondAxisY) { + enableY2 = myY2GridCheck->isChecked(); + divY2 = myY2GridSpin->value(); + } + else { + enableY2 = false; + divY2 = 1; + } +} +/*! + Sets minor grid parameters +*/ +void Plot2d_SetupViewDlg::setMinorGrid( bool enableX, const int divX, + bool enableY, const int divY, + bool enableY2, const int divY2) +{ + myXMinGridCheck->setChecked( enableX ); + myXMinGridSpin->setValue( divX ); + myYMinGridCheck->setChecked( enableY ); + myYMinGridSpin->setValue( divY ); + onXGridMinorChecked(); + onYGridMinorChecked(); + if (mySecondAxisY) { + myY2MinGridCheck->setChecked( enableY2 ); + myY2MinGridSpin->setValue( divY2 ); + onY2GridMinorChecked(); + } +} +/*! + Gets minor grid parameters +*/ +void Plot2d_SetupViewDlg::getMinorGrid( bool& enableX, int& divX, + bool& enableY, int& divY, + bool& enableY2, int& divY2) +{ + enableX = myXMinGridCheck->isChecked(); + divX = myXMinGridSpin->value(); + enableY = myYMinGridCheck->isChecked(); + divY = myYMinGridSpin->value(); + if (mySecondAxisY) { + enableY2 = myY2MinGridCheck->isChecked(); + divY2 = myY2MinGridSpin->value(); + } + else { + enableY2 = false; + divY2 = 1; + } +} +/*! + Sets scale mode for hor. and ver. axes : 0 - linear, 1 - logarithmic +*/ +void Plot2d_SetupViewDlg::setScaleMode( const int xMode, const int yMode ) +{ + myXModeCombo->setCurrentItem( xMode ); + myYModeCombo->setCurrentItem( yMode ); +} +/*! + Gets scale mode for hor. axis : 0 - linear, 1 - logarithmic +*/ +int Plot2d_SetupViewDlg::getXScaleMode() +{ + return myXModeCombo->currentItem(); +} +/*! + Gets scale mode for hor. axis : 0 - linear, 1 - logarithmic +*/ +int Plot2d_SetupViewDlg::getYScaleMode() +{ + return myYModeCombo->currentItem(); +} +/*! + Slot, called when user clicks "Show main title" check box +*/ +void Plot2d_SetupViewDlg::onMainTitleChecked() +{ + myTitleEdit->setEnabled( myTitleCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Show horizontal axis title" check box +*/ +void Plot2d_SetupViewDlg::onXTitleChecked() +{ + myTitleXEdit->setEnabled( myTitleXCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Show vertical left axis title" check box +*/ +void Plot2d_SetupViewDlg::onYTitleChecked() +{ + myTitleYEdit->setEnabled( myTitleYCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Show vertical right axis title" check box +*/ +void Plot2d_SetupViewDlg::onY2TitleChecked() +{ + myTitleY2Edit->setEnabled( myTitleY2Check->isChecked() ); +} +/*! + Slot, called when user clicks "Change bacground color" button +*/ +void Plot2d_SetupViewDlg::onBackgroundClicked() +{ + QColor color = QColorDialog::getColor( getBackgroundColor() ); + if ( color.isValid() ) { + setBackgroundColor( color ); + } +} +/*! + Slot, called when user clicks "Show Legend" check box +*/ +void Plot2d_SetupViewDlg::onLegendChecked() +{ + myLegendCombo->setEnabled( myLegendCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Enable hor. major grid" check box +*/ +void Plot2d_SetupViewDlg::onXGridMajorChecked() +{ + myXMinGridCheck->setEnabled( myXGridCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Enable ver. major grid" check box +*/ +void Plot2d_SetupViewDlg::onYGridMajorChecked() +{ + myYMinGridCheck->setEnabled( myYGridCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Enable ver. major grid" check box +*/ +void Plot2d_SetupViewDlg::onY2GridMajorChecked() +{ + myY2MinGridCheck->setEnabled( myY2GridCheck->isChecked() ); +} +/*! + Slot, called when user clicks "Enable hor. minor grid" check box +*/ +void Plot2d_SetupViewDlg::onXGridMinorChecked() +{ +} +/*! + Slot, called when user clicks "Enable ver. minor grid" check box +*/ +void Plot2d_SetupViewDlg::onYGridMinorChecked() +{ +} +/*! + Slot, called when user clicks "Enable ver. minor grid" check box +*/ +void Plot2d_SetupViewDlg::onY2GridMinorChecked() +{ +} +/*! + Retursns true if "Set as default" check box is on +*/ +bool Plot2d_SetupViewDlg::isSetAsDefault() +{ + return myDefCheck->isChecked(); +} diff --git a/src/Plot2d/Plot2d_ViewFrame.cxx b/src/Plot2d/Plot2d_ViewFrame.cxx new file mode 100755 index 000000000..67933dbae --- /dev/null +++ b/src/Plot2d/Plot2d_ViewFrame.cxx @@ -0,0 +1,1928 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "Plot2d_ViewFrame.h" + +#include "Plot2d_Prs.h" +#include "Plot2d_Curve.h" +#include "Plot2d_FitDataDlg.h" +#include "Plot2d_ViewWindow.h" +#include "Plot2d_SetupViewDlg.h" + +#include "SUIT_Tools.h" +#include "SUIT_Session.h" +#include "SUIT_MessageBox.h" +#include "SUIT_ResourceMgr.h" +#include "SUIT_Application.h" + +#include "qapplication.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define DEFAULT_LINE_WIDTH 0 // (default) line width +#define DEFAULT_MARKER_SIZE 9 // default marker size +#define MIN_RECT_SIZE 11 // min sensibility area size + +const char* imageZoomCursor[] = { +"32 32 3 1", +". c None", +"a c #000000", +"# c #ffffff", +"................................", +"................................", +".#######........................", +"..aaaaaaa.......................", +"................................", +".............#####..............", +"...........##.aaaa##............", +"..........#.aa.....a#...........", +".........#.a.........#..........", +".........#a..........#a.........", +"........#.a...........#.........", +"........#a............#a........", +"........#a............#a........", +"........#a............#a........", +"........#a............#a........", +".........#...........#.a........", +".........#a..........#a.........", +".........##.........#.a.........", +"........#####.....##.a..........", +".......###aaa#####.aa...........", +"......###aa...aaaaa.......#.....", +".....###aa................#a....", +"....###aa.................#a....", +"...###aa...............#######..", +"....#aa.................aa#aaaa.", +".....a....................#a....", +"..........................#a....", +"...........................a....", +"................................", +"................................", +"................................", +"................................"}; + +const char* imageCrossCursor[] = { + "32 32 3 1", + ". c None", + "a c #000000", + "# c #ffffff", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "...............#................", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + ".......#################........", + "........aaaaaaa#aaaaaaaaa.......", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "...............#a...............", + "................a...............", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................", + "................................"}; + + +//================================================================================= +// Plot2d_ViewFrame implementation +//================================================================================= + +/*! + Constructor +*/ +Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title ) + : QWidget (parent, title, 0), + myOperation( NoOpId ), + myCurveType( 1 ), + myShowLegend( true ), myLegendPos( 1 ), + myMarkerSize( DEFAULT_MARKER_SIZE ), + myTitle( "" ), myXTitle( "" ), myYTitle( "" ), myY2Title( "" ), + myBackground( white ), + myTitleEnabled( true ), myXTitleEnabled( true ), + myYTitleEnabled( true ), myY2TitleEnabled (true), + myXGridMajorEnabled( true ), myYGridMajorEnabled( true ), myY2GridMajorEnabled( true ), + myXGridMinorEnabled( false ), myYGridMinorEnabled( false ), myY2GridMinorEnabled( false ), + myXGridMaxMajor( 8 ), myYGridMaxMajor( 8 ), myY2GridMaxMajor( 8 ), + myXGridMaxMinor( 5 ), myYGridMaxMinor( 5 ), myY2GridMaxMinor( 5 ), + myXMode( 0 ), myYMode( 0 ), mySecondY( false ) +{ + /* Plot 2d View */ + QVBoxLayout* aLayout = new QVBoxLayout( this ); + myPlot = new Plot2d_Plot2d( this ); + aLayout->addWidget( myPlot ); + +// createActions(); + + connect( myPlot, SIGNAL( plotMouseMoved( const QMouseEvent& ) ), + this, SLOT( plotMouseMoved( const QMouseEvent& ) ) ); + connect( myPlot, SIGNAL( plotMousePressed( const QMouseEvent& ) ), + this, SLOT( plotMousePressed( const QMouseEvent& ) ) ); + connect( myPlot, SIGNAL( plotMouseReleased( const QMouseEvent& ) ), + this, SLOT( plotMouseReleased( const QMouseEvent& ) ) ); + //connect( myPlot, SIGNAL( legendClicked( long ) ), + // this, SLOT( onLegendClicked( long ) ) ); + + /* Initial Setup - get from the preferences */ + readPreferences(); + + myPlot->setMargin( 5 ); + setCurveType( myCurveType, false ); + setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, false ); + setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor, + myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, false ); + + setTitle( myTitleEnabled, myTitle, MainTitle, false ); + setTitle( myXTitleEnabled, myXTitle, XTitle, false ); + setTitle( myYTitleEnabled, myYTitle, YTitle, false ); + + if (mySecondY) + setTitle( myY2TitleEnabled, myY2Title, Y2Title, false ); + setHorScaleMode( myXMode, false ); + setVerScaleMode( myYMode, false ); + setBackgroundColor( myBackground ); + setLegendPos( myLegendPos ); + showLegend( myShowLegend, false ); + myPlot->replot(); + + if ( parent ) { + resize( (int)(0.8 * parent->width()), (int)(0.8 * parent->height()) ); + } + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + myXDistance = xMap.d2() - xMap.d1(); + myYDistance = yMap.d2() - yMap.d1(); + myYDistance2 = 0; + if (mySecondY) { + QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight ); + myYDistance2 = yMap2.d2() - yMap2.d1(); + } +} +/*! + Destructor +*/ +Plot2d_ViewFrame::~Plot2d_ViewFrame() +{ +} +/*! + Gets window's central widget +*/ +QWidget* Plot2d_ViewFrame::getViewWidget() +{ + return (QWidget*)myPlot; +} +/*! + Actually this method just re-displays all curves which are presented in the viewer +*/ +void Plot2d_ViewFrame::DisplayAll() +{ + QList clist; + getCurves( clist ); + for ( int i = 0; i < (int)clist.count(); i++ ) { + updateCurve( clist.at( i ), false ); + } + myPlot->replot(); +} +/*! + Removes all curves from the view +*/ +void Plot2d_ViewFrame::EraseAll() +{ + myPlot->clear(); + myCurves.clear(); + myPlot->replot(); +} +/*! + Redraws viewframe contents +*/ +void Plot2d_ViewFrame::Repaint() +{ + myPlot->replot(); +} +/*! + Display presentation +*/ +void Plot2d_ViewFrame::Display( const Plot2d_Prs* prs ) +{ + if ( !prs || prs->IsNull() ) + return; + + if (prs->isSecondY()) { + myPlot->enableAxis(QwtPlot::yRight, true); + mySecondY = true; + } + else { + myPlot->enableAxis(QwtPlot::yRight, false); + mySecondY = false; + } + + // display all curves from presentation + curveList aCurves = prs->getCurves(); + displayCurves( aCurves ); + setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, true ); + setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor, + myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, true ); +} + +/*! + Erase presentation +*/ +void Plot2d_ViewFrame::Erase( const Plot2d_Prs* prs, const bool ) +{ + if ( !prs || prs->IsNull() ) + return; + + // erase all curves from presentation + curveList aCurves = prs->getCurves(); + eraseCurves( aCurves ); +} + +/*! + Sets title +*/ +void Plot2d_ViewFrame::setTitle( const QString& title ) +{ + setTitle( myTitleEnabled, title, MainTitle, true ); +} + +/*! + Reads Plot2d view settings from the preferences +*/ +void Plot2d_ViewFrame::readPreferences() +{ + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + + myCurveType = resMgr->integerValue( "Plot2d", "CurveType", myCurveType ); + setCurveType( resMgr->integerValue( "Plot2d", "CurveType", myCurveType ) ); + + myShowLegend = resMgr->booleanValue( "Plot2d", "ShowLegend", myShowLegend ); + myLegendPos = resMgr->integerValue( "Plot2d", "LegendPos", myLegendPos ); + myMarkerSize = resMgr->integerValue( "Plot2d", "MarkerSize", myMarkerSize ); + myBackground = resMgr->colorValue( "Plot2d", "Background", myBackground ); + + myTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowTitle", myTitleEnabled ); + myXTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowHorTitle", myXTitleEnabled ); + myYTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled ); + myY2TitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled ); + + myXGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled ); + myYGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled ); + myY2GridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled ); + + myXGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled ); + myYGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled ); + myY2GridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled ); + + myXGridMaxMajor = resMgr->integerValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor ); + myYGridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor ); + if ( mySecondY ) + myY2GridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorRightGridMax", myY2GridMaxMajor ); + + myXGridMaxMinor = resMgr->integerValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor ); + myYGridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor ); + if ( mySecondY ) + myY2GridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myY2GridMaxMinor ); + + myXMode = resMgr->integerValue( "Plot2d", "HorScaleMode", myXMode ); + myXMode = QMAX( 0, QMIN( 1, myXMode ) ); + + myYMode = resMgr->integerValue( "Plot2d", "VerScaleMode", myYMode ); + myYMode = QMAX( 0, QMIN( 1, myYMode ) ); +} + +/*! + Writes Plot2d view settings to the preferences +*/ +void Plot2d_ViewFrame::writePreferences() +{ + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + + resMgr->setValue( "Plot2d", "CurveType", myCurveType ); + resMgr->setValue( "Plot2d", "ShowLegend", myShowLegend ); + resMgr->setValue( "Plot2d", "LegendPos", myLegendPos ); + resMgr->setValue( "Plot2d", "MarkerSize", myMarkerSize ); + resMgr->setValue( "Plot2d", "Background", myBackground ); + resMgr->setValue( "Plot2d", "ShowTitle", myTitleEnabled ); + resMgr->setValue( "Plot2d", "ShowHorTitle", myXTitleEnabled ); + resMgr->setValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled ); + if ( mySecondY ) + resMgr->setValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled ); + + resMgr->setValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled ); + resMgr->setValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled ); + resMgr->setValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled ); + resMgr->setValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled ); + + resMgr->setValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor ); + resMgr->setValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor ); + + resMgr->setValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor ); + resMgr->setValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor ); + + resMgr->setValue( "Plot2d", "HorScaleMode", myXMode ); + + if ( mySecondY ) + { + resMgr->setValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled ); + resMgr->setValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled ); + resMgr->setValue( "Plot2d", "VerRightMajorGridMax", myY2GridMaxMajor ); + resMgr->setValue( "Plot2d", "VerRightMinorGridMax", myY2GridMaxMinor ); + } + + resMgr->setValue( "Plot2d", "VerScaleMode", myYMode ); +} + +/*! + Prints mouse cursor coordinates into string +*/ +QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) +{ + int i; + bool xFound = false, yFound = false; + double xCoord, yCoord; + const QwtScaleDiv* aXscale = myPlot->axisScale( QwtPlot::xBottom ); + for ( i = 0; i < aXscale->majCnt(); i++ ) { + double majXmark = aXscale->majMark( i ); + int xmark = myPlot->transform( QwtPlot::xBottom, majXmark ); + if ( xmark-2 == pnt.x() ) { + xCoord = majXmark; + xFound = true; + break; + } + } + if ( !xFound ) { + for ( i = 0; i < aXscale->minCnt(); i++ ) { + double minXmark = aXscale->minMark( i ); + int xmark = myPlot->transform( QwtPlot::xBottom, minXmark ); + if ( xmark-2 == pnt.x() ) { + xCoord = minXmark; + xFound = true; + break; + } + } + } + const QwtScaleDiv* aYscale = myPlot->axisScale( QwtPlot::yLeft ); + for ( i = 0; i < aYscale->majCnt(); i++ ) { + double majYmark = aYscale->majMark( i ); + int ymark = myPlot->transform( QwtPlot::yLeft, majYmark ); + if ( ymark-2 == pnt.y() ) { + yCoord = majYmark; + yFound = true; + break; + } + } + if ( !yFound ) { + for ( i = 0; i < aYscale->minCnt(); i++ ) { + double minYmark = aYscale->minMark( i ); + int ymark = myPlot->transform( QwtPlot::yLeft, minYmark ); + if ( ymark-2 == pnt.y() ) { + yCoord = minYmark; + yFound = true; + break; + } + } + } + + QString strX = QString::number( xFound ? xCoord : myPlot->invTransform( QwtPlot::xBottom, pnt.x() ) ).stripWhiteSpace(); + if ( strX == "-0" ) + strX = "0"; + QString strY = QString::number( yFound ? yCoord : myPlot->invTransform( QwtPlot::yLeft, pnt.y() ) ).stripWhiteSpace(); + if ( strY == "-0" ) + strY = "0"; + QString info = ""; + + if (mySecondY) { + bool yFound2 = false; + double yCoord2; + + const QwtScaleDiv* aYscale2 = myPlot->axisScale( QwtPlot::yRight ); + for ( i = 0; i < aYscale2->majCnt(); i++ ) { + double majYmark = aYscale2->majMark( i ); + int ymark = myPlot->transform( QwtPlot::yRight, majYmark ); + if ( ymark-2 == pnt.y() ) { + yCoord2 = majYmark; + yFound2 = true; + break; + } + } + if ( !yFound2 ) { + for ( i = 0; i < aYscale2->minCnt(); i++ ) { + double minYmark = aYscale2->minMark( i ); + int ymark = myPlot->transform( QwtPlot::yRight, minYmark ); + if ( ymark-2 == pnt.y() ) { + yCoord2 = minYmark; + yFound2 = true; + break; + } + } + } + QString strY2 = QString::number( yFound2 ? yCoord2 : + myPlot->invTransform( QwtPlot::yRight, pnt.y() ) ).stripWhiteSpace(); + if ( strY2 == "-0" ) + strY2 = "0"; + info = tr("INF_COORDINATES_SOME_Y").arg( strX ).arg( strY ).arg( strY2 ); + } + else + info = tr("INF_COORDINATES").arg( strX ).arg( strY ); + + return info; +} + +/*! + Converts Plot2d_Curve's marker style to Qwt marker style [ static ] +*/ +static QwtSymbol::Style plot2qwtMarker( Plot2d_Curve::MarkerType m ) +{ + QwtSymbol::Style ms = QwtSymbol::None; + switch ( m ) { + case Plot2d_Curve::Circle: + ms = QwtSymbol::Ellipse; break; + case Plot2d_Curve::Rectangle: + ms = QwtSymbol::Rect; break; + case Plot2d_Curve::Diamond: + ms = QwtSymbol::Diamond; break; + case Plot2d_Curve::DTriangle: + ms = QwtSymbol::DTriangle; break; + case Plot2d_Curve::UTriangle: + ms = QwtSymbol::UTriangle; break; + case Plot2d_Curve::LTriangle: // Qwt confuses LTriangle and RTriangle :((( + ms = QwtSymbol::RTriangle; break; + case Plot2d_Curve::RTriangle: // Qwt confuses LTriangle and RTriangle :((( + ms = QwtSymbol::LTriangle; break; + case Plot2d_Curve::Cross: + ms = QwtSymbol::Cross; break; + case Plot2d_Curve::XCross: + ms = QwtSymbol::XCross; break; + case Plot2d_Curve::None: + default: + ms = QwtSymbol::None; break; + } + return ms; +} + +/*! + Converts Qwt marker style to Plot2d_Curve's marker style [ static ] +*/ +static Plot2d_Curve::MarkerType qwt2plotMarker( QwtSymbol::Style m ) +{ + Plot2d_Curve::MarkerType ms = Plot2d_Curve::None; + switch ( m ) { + case QwtSymbol::Ellipse: + ms = Plot2d_Curve::Circle; break; + case QwtSymbol::Rect: + ms = Plot2d_Curve::Rectangle; break; + case QwtSymbol::Diamond: + ms = Plot2d_Curve::Diamond; break; + case QwtSymbol::DTriangle: + ms = Plot2d_Curve::DTriangle; break; + case QwtSymbol::UTriangle: + ms = Plot2d_Curve::UTriangle; break; + case QwtSymbol::RTriangle: // Qwt confuses LTriangle and RTriangle :((( + ms = Plot2d_Curve::LTriangle; break; + case QwtSymbol::LTriangle: // Qwt confuses LTriangle and RTriangle :((( + ms = Plot2d_Curve::RTriangle; break; + case QwtSymbol::Cross: + ms = Plot2d_Curve::Cross; break; + case QwtSymbol::XCross: + ms = Plot2d_Curve::XCross; break; + case QwtSymbol::None: + default: + ms = Plot2d_Curve::None; break; + } + return ms; +} + +/*! + Converts Plot2d_Curve's line style to Qwt line style [ static ] +*/ +static Qt::PenStyle plot2qwtLine( Plot2d_Curve::LineType p ) +{ + Qt::PenStyle ps = Qt::NoPen; + switch ( p ) { + case Plot2d_Curve::Solid: + ps = Qt::SolidLine; break; + case Plot2d_Curve::Dash: + ps = Qt::DashLine; break; + case Plot2d_Curve::Dot: + ps = Qt::DotLine; break; + case Plot2d_Curve::DashDot: + ps = Qt::DashDotLine; break; + case Plot2d_Curve::DashDotDot: + ps = Qt::DashDotDotLine; break; + case Plot2d_Curve::NoPen: + default: + ps = Qt::NoPen; break; + } + return ps; +} + +/*! + Converts Qwt line style to Plot2d_Curve's line style [ static ] +*/ +static Plot2d_Curve::LineType qwt2plotLine( Qt::PenStyle p ) +{ + Plot2d_Curve::LineType ps = Plot2d_Curve::NoPen; + switch ( p ) { + case Qt::SolidLine: + ps = Plot2d_Curve::Solid; break; + case Qt::DashLine: + ps = Plot2d_Curve::Dash; break; + case Qt::DotLine: + ps = Plot2d_Curve::Dot; break; + case Qt::DashDotLine: + ps = Plot2d_Curve::DashDot; break; + case Qt::DashDotDotLine: + ps = Plot2d_Curve::DashDotDot; break; + case Qt::NoPen: + default: + ps = Plot2d_Curve::NoPen; break; + } + return ps; +} + +/*! + Adds curve into view +*/ +void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update ) +{ + if ( !curve ) + return; + // san -- Protection against QwtCurve bug in Qwt 0.4.x: + // it crashes if switched to X/Y logarithmic mode, when one or more points have + // non-positive X/Y coordinate + if ( myXMode && curve->getMinX() <= 0. ) + setHorScaleMode( 0, false ); + if ( myYMode && curve->getMinY() <= 0. ) + setVerScaleMode( 0, false ); + + + if ( hasCurve( curve ) ) { + updateCurve( curve, update ); + } + else { + long curveKey = myPlot->insertCurve( curve->getVerTitle() ); + myPlot->setCurveYAxis(curveKey, curve->getYAxis()); + + myCurves.insert( curveKey, curve ); + if ( curve->isAutoAssign() ) { + QwtSymbol::Style typeMarker; + QColor color; + Qt::PenStyle typeLine; + myPlot->getNextMarker( typeMarker, color, typeLine ); + myPlot->setCurvePen( curveKey, QPen( color, DEFAULT_LINE_WIDTH, typeLine ) ); + myPlot->setCurveSymbol( curveKey, QwtSymbol( typeMarker, + QBrush( color ), + QPen( color ), + QSize( myMarkerSize, myMarkerSize ) ) ); + curve->setColor( color ); + curve->setLine( qwt2plotLine( typeLine ) ); + curve->setMarker( qwt2plotMarker( typeMarker ) ); + } + else { + Qt::PenStyle ps = plot2qwtLine( curve->getLine() ); + QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() ); + myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) ); + myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, + QBrush( curve->getColor() ), + QPen( curve->getColor() ), + QSize( myMarkerSize, myMarkerSize ) ) ); + } + if ( myCurveType == 0 ) + myPlot->setCurveStyle( curveKey, QwtCurve::NoCurve ); + else if ( myCurveType == 1 ) + myPlot->setCurveStyle( curveKey, QwtCurve::Lines ); + else if ( myCurveType == 2 ) + myPlot->setCurveStyle( curveKey, QwtCurve::Spline ); + myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() ); + } + updateTitles(); + if ( update ) + myPlot->replot(); +} + +/*! + Adds curves into view +*/ +void Plot2d_ViewFrame::displayCurves( const curveList& curves, bool update ) +{ + myPlot->setUpdatesEnabled( false ); + QPtrListIterator it(curves); + Plot2d_Curve* aCurve; + while( (aCurve = it.current()) ) { + displayCurve( aCurve, false ); + ++it; + } + + fitAll(); + myPlot->setUpdatesEnabled( true ); + if ( update ) + myPlot->replot(); +} + +/*! + Erases curve +*/ +void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update ) +{ + if ( !curve ) + return; + int curveKey = hasCurve( curve ); + if ( curveKey ) { + myPlot->removeCurve( curveKey ); + myCurves.remove( curveKey ); + updateTitles(); + if ( update ) + myPlot->replot(); + } +} + +/*! + Erases curves +*/ +void Plot2d_ViewFrame::eraseCurves( const curveList& curves, bool update ) +{ + QPtrListIterator it(curves); + Plot2d_Curve* aCurve; + while( (aCurve = it.current()) ) { + eraseCurve( aCurve, false ); + ++it; + } +// fitAll(); + if ( update ) + myPlot->replot(); +} + +/*! + Updates curves attributes +*/ +void Plot2d_ViewFrame::updateCurve( Plot2d_Curve* curve, bool update ) +{ + if ( !curve ) + return; + int curveKey = hasCurve( curve ); + if ( curveKey ) { + if ( !curve->isAutoAssign() ) { + Qt::PenStyle ps = plot2qwtLine( curve->getLine() ); + QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() ); + myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) ); + myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, + QBrush( curve->getColor() ), + QPen( curve->getColor() ), + QSize( myMarkerSize, myMarkerSize ) ) ); + myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() ); + } + myPlot->setCurveTitle( curveKey, curve->getVerTitle() ); + myPlot->curve( curveKey )->setEnabled( true ); + if ( update ) + myPlot->replot(); + } +} + +/*! + Returns curve key if is is displayed in the viewer and 0 otherwise +*/ +int Plot2d_ViewFrame::hasCurve( Plot2d_Curve* curve ) +{ + QIntDictIterator it( myCurves ); + for ( ; it.current(); ++it ) { + if ( it.current() == curve ) + return it.currentKey(); + } + return 0; +} + +/*! + Gets lsit of displayed curves +*/ +int Plot2d_ViewFrame::getCurves( QList& clist ) +{ + clist.clear(); + clist.setAutoDelete( false ); + QIntDictIterator it( myCurves ); + for ( ; it.current(); ++it ) { + clist.append( it.current() ); + } + return clist.count(); +} + +/*! + Returns true if the curve is visible +*/ +bool Plot2d_ViewFrame::isVisible( Plot2d_Curve* curve ) +{ + if(curve) { + int key = hasCurve( curve ); + if ( key ) + return myPlot->curve( key )->enabled(); + } + return false; +} + +/*! + update legend +*/ +void Plot2d_ViewFrame::updateLegend( const Plot2d_Prs* prs ) +{ + if ( !prs || prs->IsNull() ) + return; + curveList aCurves = prs->getCurves(); + + QPtrListIterator it(aCurves); + Plot2d_Curve* aCurve; + while( (aCurve = it.current()) ) { + int curveKey = hasCurve( aCurve ); + if ( curveKey ) + myPlot->setCurveTitle( curveKey, aCurve->getVerTitle() ); + ++it; + } +} + +/*! + Fits the view to see all data +*/ +void Plot2d_ViewFrame::fitAll() +{ + QwtDiMap xMap1 = myPlot->canvasMap( QwtPlot::xBottom ); + + myPlot->setAxisAutoScale( QwtPlot::yLeft ); + myPlot->setAxisAutoScale( QwtPlot::xBottom ); + myPlot->replot(); + + // for existing grid + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ), + myPlot->invTransform( QwtPlot::xBottom, xMap.i2() ) ); + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), + myPlot->invTransform( QwtPlot::yLeft, yMap.i2() ) ); + + if (mySecondY) { + myPlot->setAxisAutoScale( QwtPlot::yRight ); + myPlot->replot(); + QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight ); + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, yMap2.i1() ), + myPlot->invTransform( QwtPlot::yRight, yMap2.i2() ) ); + } + myPlot->replot(); +} + +/*! + Fits the view to rectangle area (pixels) +*/ +void Plot2d_ViewFrame::fitArea( const QRect& area ) +{ + QRect rect = area.normalize(); + if ( rect.width() < MIN_RECT_SIZE ) { + rect.setWidth( MIN_RECT_SIZE ); + rect.setLeft( rect.left() - MIN_RECT_SIZE/2 ); + } + if ( rect.height() < MIN_RECT_SIZE ) { + rect.setHeight( MIN_RECT_SIZE ); + rect.setTop( rect.top() - MIN_RECT_SIZE/2 ); + } + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, rect.top() ), + myPlot->invTransform( QwtPlot::yLeft, rect.bottom() ) ); + if (mySecondY) + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, rect.top() ), + myPlot->invTransform( QwtPlot::yRight, rect.bottom() ) ); + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, rect.left() ), + myPlot->invTransform( QwtPlot::xBottom, rect.right() ) ); + myPlot->replot(); +} + +/*! + "Fit Data" command for TUI interface +*/ +void Plot2d_ViewFrame::fitData(const int mode, + const double xMin, const double xMax, + const double yMin, const double yMax, + double y2Min, double y2Max) +{ + if ( mode == 0 || mode == 2 ) { + myPlot->setAxisScale( QwtPlot::yLeft, yMax, yMin ); + if (mySecondY) + myPlot->setAxisScale( QwtPlot::yRight, y2Max, y2Min ); + } + if ( mode == 0 || mode == 1 ) + myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax ); + myPlot->replot(); +} + +/*! + Gets current fit ranges for view frame +*/ +void Plot2d_ViewFrame::getFitRanges(double& xMin,double& xMax, + double& yMin, double& yMax, + double& y2Min, double& y2Max) +{ + int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).i1(); + int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).i2(); + int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).i1(); + int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).i2(); + xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin); + xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax); + yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin); + yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax); + y2Min = 0; + y2Max = 0; + if (mySecondY) { + int iyMin = myPlot->canvasMap( QwtPlot::yRight ).i1(); + int iyMax = myPlot->canvasMap( QwtPlot::yRight ).i2(); + y2Min = myPlot->invTransform(QwtPlot::yRight, iyMin); + y2Max = myPlot->invTransform(QwtPlot::yRight, iyMax); + } +} + +/*! + Tests if it is necessary to start operation on mouse action +*/ +int Plot2d_ViewFrame::testOperation( const QMouseEvent& me ) +{ + int btn = me.button() | me.state(); + const int zoomBtn = ControlButton | LeftButton; + const int panBtn = ControlButton | MidButton; + const int fitBtn = ControlButton | RightButton; + + switch (btn) + { + case zoomBtn: + { + QPixmap zoomPixmap (imageZoomCursor); + QCursor zoomCursor (zoomPixmap); + myPlot->canvas()->setCursor( zoomCursor ); + return ZoomId; + } + case panBtn: + myPlot->canvas()->setCursor( QCursor( Qt::SizeAllCursor ) ); + return PanId; + case fitBtn: + myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) ); + return FitAreaId; + default : + return NoOpId; + } +} + +/*! + "Settings" toolbar action slot +*/ +void Plot2d_ViewFrame::onSettings() +{ +#ifdef TEST_AUTOASSIGN + typedef QMap IList; + typedef QMap SList; + IList mars, lins; + SList cols; + cols[ "red-min" ] = 1000; + cols[ "red-max" ] = -1; + cols[ "green-min" ] = 1000; + cols[ "green-max" ] = -1; + cols[ "blue-min" ] = 1000; + cols[ "blue-max" ] = -1; + for ( unsigned i = 0; i < 10000; i++ ) { + QwtSymbol::Style typeMarker; + QColor color; + Qt::PenStyle typeLine; + myPlot->getNextMarker( typeMarker, color, typeLine ); + if ( mars.contains(typeMarker) ) + mars[ typeMarker ] = mars[ typeMarker ]+1; + else + mars[ typeMarker ] = 0; + if ( lins.contains(typeLine) ) + lins[ typeLine ] = lins[ typeLine ]+1; + else + lins[ typeLine ] = 0; + if ( cols[ "red-max" ] < color.red() ) + cols[ "red-max" ] = color.red(); + if ( cols[ "red-min" ] > color.red() ) + cols[ "red-min" ] = color.red(); + if ( cols[ "green-max" ] < color.green() ) + cols[ "green-max" ] = color.green(); + if ( cols[ "green-min" ] > color.green() ) + cols[ "green-min" ] = color.green(); + if ( cols[ "blue-max" ] < color.blue() ) + cols[ "blue-max" ] = color.blue(); + if ( cols[ "blue-min" ] > color.blue() ) + cols[ "blue-min" ] = color.blue(); + } +#endif + + Plot2d_SetupViewDlg* dlg = new Plot2d_SetupViewDlg( this, true, mySecondY ); + dlg->setMainTitle( myTitleEnabled, myTitle ); + dlg->setXTitle( myXTitleEnabled, myXTitle ); + dlg->setYTitle( myYTitleEnabled, myYTitle ); + if (mySecondY) + dlg->setY2Title( myY2TitleEnabled, myY2Title ); + dlg->setCurveType( myCurveType ); + dlg->setLegend( myShowLegend, myLegendPos ); + dlg->setMarkerSize( myMarkerSize ); + dlg->setBackgroundColor( myBackground ); + dlg->setScaleMode(myXMode, myYMode); + // + dlg->setMajorGrid( myXGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::xBottom ), + myYGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yLeft ), + myY2GridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yRight ) ); + dlg->setMinorGrid( myXGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::xBottom ), + myYGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yLeft ), + myY2GridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yRight ) ); + if ( dlg->exec() == QDialog::Accepted ) { + // horizontal axis title + setTitle( dlg->isXTitleEnabled(), dlg->getXTitle(), XTitle, false ); + // vertical left axis title + setTitle( dlg->isYTitleEnabled(), dlg->getYTitle(), YTitle, false ); + if (mySecondY) // vertical right axis title + setTitle( dlg->isY2TitleEnabled(), dlg->getY2Title(), Y2Title, false ); + + // main title + setTitle( dlg->isMainTitleEnabled(), dlg->getMainTitle(), MainTitle, true ); + // curve type + if ( myCurveType != dlg->getCurveType() ) { + setCurveType( dlg->getCurveType(), false ); + } + // legend + if ( myShowLegend != dlg->isLegendEnabled() ) { + showLegend( dlg->isLegendEnabled(), false ); + } + if ( myLegendPos != dlg->getLegendPos() ) { + setLegendPos( dlg->getLegendPos() ); + } + // marker size + if ( myMarkerSize != dlg->getMarkerSize() ) { + setMarkerSize( dlg->getMarkerSize(), false ); + } + // background color + if ( myBackground != dlg->getBackgroundColor() ) { + setBackgroundColor( dlg->getBackgroundColor() ); + } + // grid + bool aXGridMajorEnabled, aXGridMinorEnabled, aYGridMajorEnabled, aYGridMinorEnabled, + aY2GridMajorEnabled, aY2GridMinorEnabled; + int aXGridMaxMajor, aXGridMaxMinor, aYGridMaxMajor, aYGridMaxMinor, + aY2GridMaxMajor, aY2GridMaxMinor; + dlg->getMajorGrid( aXGridMajorEnabled, aXGridMaxMajor, aYGridMajorEnabled, aYGridMaxMajor, + aY2GridMajorEnabled, aY2GridMaxMajor); + dlg->getMinorGrid( aXGridMinorEnabled, aXGridMaxMinor, aYGridMinorEnabled, aYGridMaxMinor, + aY2GridMinorEnabled, aY2GridMaxMinor); + setXGrid( aXGridMajorEnabled, aXGridMaxMajor, aXGridMinorEnabled, aXGridMaxMinor, false ); + setYGrid( aYGridMajorEnabled, aYGridMaxMajor, aYGridMinorEnabled, aYGridMaxMinor, + aY2GridMajorEnabled, aY2GridMaxMajor, aY2GridMinorEnabled, aY2GridMaxMinor, false ); + if ( myXMode != dlg->getXScaleMode() ) { + setHorScaleMode( dlg->getXScaleMode() ); + } + if ( myYMode != dlg->getYScaleMode() ) { + setVerScaleMode( dlg->getYScaleMode() ); + } + // update view + myPlot->replot(); + // update preferences + if ( dlg->isSetAsDefault() ) + writePreferences(); + } + delete dlg; +} + +/*! + "Fit Data" command slot +*/ +void Plot2d_ViewFrame::onFitData() +{ + Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this, mySecondY ); + double xMin,xMax,yMin,yMax,y2Min,y2Max; + getFitRanges(xMin,xMax,yMin,yMax,y2Min,y2Max); + + dlg->setRange( xMin, xMax, yMin, yMax, y2Min, y2Max ); + if ( dlg->exec() == QDialog::Accepted ) { + int mode = dlg->getRange( xMin, xMax, yMin, yMax, y2Min, y2Max ); + fitData(mode,xMin,xMax,yMin,yMax,y2Min,y2Max); + } + delete dlg; +} + +/*! + Change background color +*/ +void Plot2d_ViewFrame::onChangeBackground() +{ + QColor selColor = QColorDialog::getColor ( backgroundColor(), this ); + if ( selColor.isValid() ) { + setBackgroundColor( selColor ); + } +} + +/*! + Sets curve type +*/ +void Plot2d_ViewFrame::setCurveType( int curveType, bool update ) +{ + myCurveType = curveType; + QArray keys = myPlot->curveKeys(); + for ( int i = 0; i < (int)keys.count(); i++ ) { + if ( myCurveType == 0 ) + myPlot->setCurveStyle( keys[i], QwtCurve::Dots );//QwtCurve::NoCurve + else if ( myCurveType == 1 ) + myPlot->setCurveStyle( keys[i], QwtCurve::Lines ); + else if ( myCurveType == 2 ) + myPlot->setCurveStyle( keys[i], QwtCurve::Spline ); + } + if ( update ) + myPlot->replot(); + emit vpCurveChanged(); +} + +void Plot2d_ViewFrame::setCurveTitle( int curveKey, const QString& title ) +{ + if(myPlot) myPlot->setCurveTitle(curveKey, title); +} + +/*! + Shows/hides legend +*/ +void Plot2d_ViewFrame::showLegend( bool show, bool update ) +{ + myShowLegend = show; + myPlot->setAutoLegend( myShowLegend ); + myPlot->enableLegend( myShowLegend ); + if ( update ) + myPlot->replot(); +} + +/*! + Sets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom +*/ +void Plot2d_ViewFrame::setLegendPos( int pos ) +{ + myLegendPos = pos; + switch( pos ) { + case 0: + myPlot->setLegendPos( Qwt::Left ); + break; + case 1: + myPlot->setLegendPos( Qwt::Right ); + break; + case 2: + myPlot->setLegendPos( Qwt::Top ); + break; + case 3: + myPlot->setLegendPos( Qwt::Bottom ); + break; + } +} + +/*! + Sets new marker size +*/ +void Plot2d_ViewFrame::setMarkerSize( const int size, bool update ) +{ + if ( myMarkerSize != size ) + { + myMarkerSize = size; + QArray keys = myPlot->curveKeys(); + for ( int i = 0; i < (int)keys.count(); i++ ) + { + QwtPlotCurve* crv = myPlot->curve( keys[i] ); + if ( crv ) + { + QwtSymbol aSymbol = crv->symbol(); + aSymbol.setSize( myMarkerSize, myMarkerSize ); + myPlot->setCurveSymbol( keys[i], aSymbol ); + } + } + if ( update ) + myPlot->replot(); + } +} + +/*! + Sets background color +*/ +void Plot2d_ViewFrame::setBackgroundColor( const QColor& color ) +{ + myBackground = color; + //myPlot->setCanvasBackground( myBackground ); + myPlot->canvas()->setPalette( myBackground ); + myPlot->setPalette( myBackground ); + QPalette aPal = myPlot->getLegend()->palette(); + for ( int i = 0; i < QPalette::NColorGroups; i++ ) { + QPalette::ColorGroup cg = (QPalette::ColorGroup)i; + aPal.setColor( cg, QColorGroup::Base, myBackground ); + aPal.setColor( cg, QColorGroup::Background, myBackground ); + } + myPlot->getLegend()->setPalette( aPal ); + Repaint(); +} +/*! + Gets background color +*/ +QColor Plot2d_ViewFrame::backgroundColor() const +{ + return myBackground; +} +/*! + Sets hor.axis grid parameters +*/ +void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax, + bool xMinorEnabled, const int xMinorMax, + bool update ) +{ + myXGridMajorEnabled = xMajorEnabled; + myXGridMinorEnabled = xMinorEnabled; + myXGridMaxMajor = xMajorMax; + myXGridMaxMinor = xMinorMax; + myPlot->setAxisMaxMajor( QwtPlot::xBottom, myXGridMaxMajor ); + myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor ); + myPlot->setGridXAxis(QwtPlot::xBottom); + myPlot->enableGridX( myXGridMajorEnabled ); + myPlot->enableGridXMin( myXGridMinorEnabled ); + if ( update ) + myPlot->replot(); +} +/*! + Sets ver.axis grid parameters +*/ +void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax, + bool yMinorEnabled, const int yMinorMax, + bool y2MajorEnabled, const int y2MajorMax, + bool y2MinorEnabled, const int y2MinorMax, + bool update ) +{ + myYGridMajorEnabled = yMajorEnabled; + myYGridMinorEnabled = yMinorEnabled; + myYGridMaxMajor = yMajorMax; + myYGridMaxMinor = yMinorMax; + + if (mySecondY) { + myY2GridMajorEnabled = y2MajorEnabled; + myY2GridMinorEnabled = y2MinorEnabled; + myY2GridMaxMajor = y2MajorMax; + myY2GridMaxMinor = y2MinorMax; + } + myPlot->setAxisMaxMajor( QwtPlot::yLeft, myYGridMaxMajor ); + myPlot->setAxisMaxMinor( QwtPlot::yLeft, myYGridMaxMinor ); + + if (mySecondY) { + myPlot->setAxisMaxMajor( QwtPlot::yRight, myY2GridMaxMajor ); + myPlot->setAxisMaxMinor( QwtPlot::yRight, myY2GridMaxMinor ); + } + + myPlot->setGridYAxis(QwtPlot::yLeft); + + if (mySecondY) { + if (myYGridMajorEnabled) { + myPlot->enableGridYMin(myYGridMinorEnabled); + myPlot->enableGridY( myYGridMajorEnabled); + } + else if (myY2GridMajorEnabled) { + myPlot->setGridYAxis(QwtPlot::yRight); + myPlot->enableGridYMin(myY2GridMinorEnabled); + myPlot->enableGridY(myY2GridMajorEnabled); + } + else { + myPlot->enableGridYMin(false); + myPlot->enableGridY(false); + } + } + else { + myPlot->enableGridY( myYGridMajorEnabled ); + myPlot->enableGridYMin( myYGridMinorEnabled ); + } + if ( update ) + myPlot->replot(); +} + +/*! + Sets title for some axis +*/ +void Plot2d_ViewFrame::setTitle( bool enabled, const QString& title, + ObjectType type, bool update ) +{ + switch (type) { + case MainTitle: + myTitleEnabled = enabled; + myTitle = title; + myPlot->setTitle( myTitleEnabled ? myTitle : QString::null ); + break; + case XTitle: + myXTitleEnabled = enabled; + myXTitle = title; + myPlot->setAxisTitle( QwtPlot::xBottom, myXTitleEnabled ? myXTitle : QString::null ); + break; + case YTitle: + myYTitleEnabled = enabled; + myYTitle = title; + myPlot->setAxisTitle( QwtPlot::yLeft, myYTitleEnabled ? myYTitle : QString::null ); + break; + case Y2Title: + myY2TitleEnabled = enabled; + myY2Title = title; + myPlot->setAxisTitle( QwtPlot::yRight, myY2TitleEnabled ? myY2Title : QString::null ); + break; + } + if ( update ) + myPlot->replot(); +} +/*! + Sets title for some axis +*/ +QString Plot2d_ViewFrame::getTitle( ObjectType type ) const +{ + QString title = ""; + switch (type) { + case MainTitle: + title = myTitle; break; + case XTitle: + title = myXTitle; break; + case YTitle: + title = myYTitle; break; + case Y2Title: + title = myY2Title; break; + } + return title; +} +/*! + Sets font for Plot2d object : title or axis +*/ +void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update) +{ + switch (type) { + case MainTitle: + myPlot->setTitleFont(font); + break; + case XTitle: + myPlot->setAxisTitleFont(QwtPlot::xBottom, font); break; + case YTitle: + myPlot->setAxisTitleFont(QwtPlot::yLeft, font); break; + case Y2Title: + myPlot->setAxisTitleFont(QwtPlot::yRight, font); break; + case XAxis: + myPlot->setAxisFont(QwtPlot::xBottom, font); break; + case YAxis: + myPlot->setAxisFont(QwtPlot::yLeft, font); break; + case Y2Axis: + myPlot->setAxisFont(QwtPlot::yRight, font); break; + } + if ( update ) + myPlot->replot(); +} +/*! + Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic +*/ +void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update ) +{ + // san -- Protection against QwtCurve bug in Qwt 0.4.x: + // it crashes if switched to X/Y logarithmic mode, when one or more points have + // non-positive X/Y coordinate + if ( mode && !isXLogEnabled() ){ + SUIT_MessageBox::warn1(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED"), tr("BUT_OK")); + return; + } + + myXMode = mode; + if ( myXMode == 0 ) // linear + myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false ); + else // logarithmic + myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, true ); + + if ( update ) + fitAll(); + emit vpModeHorChanged(); +} +/*! + Sets scale mode for vertical axis: 0 - linear, 1 - logarithmic +*/ +void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update ) +{ + // san -- Protection against QwtCurve bug in Qwt 0.4.x: + // it crashes if switched to X/Y logarithmic mode, when one or more points have + // non-positive X/Y coordinate + if ( mode && !isYLogEnabled() ){ + SUIT_MessageBox::warn1(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED"), tr("BUT_OK")); + return; + } + + myYMode = mode; + if ( myYMode == 0 ) { // linear + myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false ); + if (mySecondY) + myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, false ); + } + else { // logarithmic + myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, true ); + if (mySecondY) + myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, true ); + } + if ( update ) + fitAll(); + emit vpModeVerChanged(); +} + +/*! + Return, scale mode for horizontal axis +*/ +bool Plot2d_ViewFrame::isModeHorLinear() +{ + return (myXMode == 0 ? true : false); +} + +/*! + Return, scale mode for vertical axis +*/ +bool Plot2d_ViewFrame::isModeVerLinear() +{ + return (myYMode == 0 ? true : false); +} +/*! + Slot, called when user presses mouse button +*/ +void Plot2d_ViewFrame::plotMousePressed(const QMouseEvent& me ) +{ + Plot2d_ViewWindow* aParent = dynamic_cast(parent()); + if (aParent) + aParent->putInfo(getInfo(me.pos())); + if ( myOperation == NoOpId ) + myOperation = testOperation( me ); + if ( myOperation != NoOpId ) { + myPnt = me.pos(); + if ( myOperation == FitAreaId ) { + myPlot->setOutlineStyle( Qwt::Rect ); + } + else if ( myOperation == GlPanId ) { + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) + myYDistance/2, + myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) - myYDistance/2 ); + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) - myXDistance/2, + myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) + myXDistance/2 ); + if (mySecondY) + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) + myYDistance2/2, + myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) - myYDistance2/2 ); + myPlot->replot(); + } + } + else { + int btn = me.button() | me.state(); + if (btn == RightButton) { + QMouseEvent* aEvent = new QMouseEvent(QEvent::MouseButtonPress, + me.pos(), btn, me.state()); + // QMouseEvent 'me' has the 'MouseButtonDblClick' type. In this case we create new event 'aEvent'. + parent()->eventFilter(this, aEvent); + } + } +} +/*! + Slot, called when user moves mouse +*/ +void Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me ) +{ + int dx = me.pos().x() - myPnt.x(); + int dy = me.pos().y() - myPnt.y(); + + if ( myOperation != NoOpId) { + if ( myOperation == ZoomId ) { + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), + myPlot->invTransform( QwtPlot::yLeft, yMap.i2() + dy ) ); + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ), + myPlot->invTransform( QwtPlot::xBottom, xMap.i2() - dx ) ); + if (mySecondY) { + QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight ); + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, y2Map.i1() ), + myPlot->invTransform( QwtPlot::yRight, y2Map.i2() + dy ) ); + } + myPlot->replot(); + myPnt = me.pos(); + } + else if ( myOperation == PanId ) { + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, yMap.i1()-dy ), + myPlot->invTransform( QwtPlot::yLeft, yMap.i2()-dy ) ); + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, xMap.i1()-dx ), + myPlot->invTransform( QwtPlot::xBottom, xMap.i2()-dx ) ); + if (mySecondY) { + QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight ); + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, y2Map.i1()-dy ), + myPlot->invTransform( QwtPlot::yRight, y2Map.i2()-dy ) ); + } + myPlot->replot(); + myPnt = me.pos(); + } + } + else { + Plot2d_ViewWindow* aParent = dynamic_cast(parent()); + if (aParent) + aParent->putInfo(getInfo(me.pos())); + } +} +/*! + Slot, called when user releases mouse +*/ +void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me ) +{ + if ( myOperation == NoOpId && me.button() == RightButton ) + { + QContextMenuEvent aEvent( QContextMenuEvent::Mouse, + me.pos(), me.globalPos(), + me.state() ); + emit contextMenuRequested( &aEvent ); + } + if ( myOperation == FitAreaId ) { + QRect rect( myPnt, me.pos() ); + fitArea( rect ); + } + myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) ); + myPlot->setOutlineStyle( Qwt::Triangle ); + + Plot2d_ViewWindow* aParent = dynamic_cast(parent()); + if (aParent) + aParent->putInfo(tr("INF_READY")); + myOperation = NoOpId; +} +/*! + Slot, called when user wheeling mouse +*/ +void Plot2d_ViewFrame::wheelEvent(QWheelEvent* event) +{ + double aDelta = event->delta(); + double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.; + + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + + myPlot->setAxisScale( QwtPlot::yLeft, + myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), + myPlot->invTransform( QwtPlot::yLeft, yMap.i2() )*aScale ); + myPlot->setAxisScale( QwtPlot::xBottom, + myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ), + myPlot->invTransform( QwtPlot::xBottom, xMap.i2() )*aScale ); + if (mySecondY) { + QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight ); + myPlot->setAxisScale( QwtPlot::yRight, + myPlot->invTransform( QwtPlot::yRight, y2Map.i1() ), + myPlot->invTransform( QwtPlot::yRight, y2Map.i2() )*aScale ); + } + myPlot->replot(); + myPnt = event->pos(); +} +/*! + View operations : Pan view +*/ +void Plot2d_ViewFrame::onViewPan() +{ + QCursor panCursor (Qt::SizeAllCursor); + myPlot->canvas()->setCursor( panCursor ); + myOperation = PanId; + qApp->installEventFilter( this ); +} +/*! + View operations : Zoom view +*/ +void Plot2d_ViewFrame::onViewZoom() +{ + QPixmap zoomPixmap (imageZoomCursor); + QCursor zoomCursor (zoomPixmap); + myPlot->canvas()->setCursor( zoomCursor ); + myOperation = ZoomId; + qApp->installEventFilter( this ); +} +/*! + View operations : Fot All +*/ +void Plot2d_ViewFrame::onViewFitAll() +{ + fitAll(); +} +/*! + View operations : Fit Area +*/ +void Plot2d_ViewFrame::onViewFitArea() +{ + myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) ); + myOperation = FitAreaId; + qApp->installEventFilter( this ); +} +/*! + View operations : Global panning +*/ +void Plot2d_ViewFrame::onViewGlobalPan() +{ + QPixmap globalPanPixmap (imageCrossCursor); + QCursor glPanCursor (globalPanPixmap); + myPlot->canvas()->setCursor( glPanCursor ); + myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false ); + myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false ); + if (mySecondY) + myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, false ); + myPlot->replot(); + QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom ); + QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft ); + + myXDistance = xMap.d2() - xMap.d1(); + myYDistance = yMap.d2() - yMap.d1(); + + if (mySecondY) { + QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight ); + myYDistance2 = yMap2.d2() - yMap2.d1(); + } + fitAll(); + myOperation = GlPanId; + qApp->installEventFilter( this ); +} + +/*! + Precaution for logarithmic X scale +*/ +bool Plot2d_ViewFrame::isXLogEnabled() const +{ + bool allPositive = true; + QIntDictIterator it( myCurves ); + for ( ; allPositive && it.current(); ++it ) { + allPositive = ( it.current()->getMinX() > 0. ); + } + return allPositive; +} + +/*! + Precaution for logarithmic Y scale +*/ +bool Plot2d_ViewFrame::isYLogEnabled() const +{ + bool allPositive = true; + QIntDictIterator it( myCurves ); + for ( ; allPositive && it.current(); ++it ) { + allPositive = ( it.current()->getMinY() > 0. ); + } + return allPositive; +} + +//================================================================================= +// Plot2d_Plot2d implementation +//================================================================================= +/*! + Constructor +*/ +Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent ) + : QwtPlot( parent ) +{ + // outline + enableOutline( true ); + setOutlineStyle( Qwt::Triangle ); + setOutlinePen( green ); + // legend + setAutoLegend( false ); + setLegendFrameStyle( QFrame::Box | QFrame::Sunken ); + enableLegend( false ); + // grid + enableGridX( false ); + enableGridXMin( false ); + enableGridY( false ); + enableGridYMin( false ); + // auto scaling by default + setAxisAutoScale( QwtPlot::yLeft ); + setAxisAutoScale( QwtPlot::yRight ); + setAxisAutoScale( QwtPlot::xBottom ); +} +/*! + Recalculates and redraws Plot 2d view +*/ +void Plot2d_Plot2d::replot() +{ + updateLayout(); // to fix bug(?) of Qwt - view is not updated when title is changed + QwtPlot::replot(); +} + +/*! + Checks if two colors are close to each other [ static ] + uses COLOR_DISTANCE variable as max tolerance for comparing of colors +*/ +const long COLOR_DISTANCE = 100; +const int MAX_ATTEMPTS = 10; +static bool closeColors( const QColor& color1, const QColor& color2 ) +{ + long tol = abs( color2.red() - color1.red() ) + + abs( color2.green() - color1.green() ) + + abs( color2.blue() - color1.blue() ); + + return ( tol <= COLOR_DISTANCE ); +} +/*! + Gets new unique marker for item if possible +*/ +void Plot2d_Plot2d::getNextMarker( QwtSymbol::Style& typeMarker, QColor& color, Qt::PenStyle& typeLine ) +{ + bool bOk = false; + int cnt = 1; + while ( !bOk ) { + int aRed = (int)( 256.0 * rand() / RAND_MAX); // generate random color + int aGreen = (int)( 256.0 * rand() / RAND_MAX); // ... + int aBlue = (int)( 256.0 * rand() / RAND_MAX); // ... + int aMarker = (int)( 9.0 * rand() / RAND_MAX) + 1; // 9 markers types ( not including empty ) + int aLine = (int)( 5.0 * rand() / RAND_MAX) + 1; // 5 line types ( not including empty ) + + typeMarker = ( QwtSymbol::Style )aMarker; + color = QColor( aRed, aGreen, aBlue ); + typeLine = ( Qt::PenStyle )aLine; + + cnt++; + if ( cnt == MAX_ATTEMPTS ) + bOk = true; + else + bOk = !existMarker( typeMarker, color, typeLine ); + } +/* + static int aMarker = -1; + static int aColor = -1; + static int aLine = -1; + + if ( myColors.isEmpty() ) { + // creating colors list + myColors.append( Qt::white ); + myColors.append( Qt::blue ); + myColors.append( Qt::gray ); + myColors.append( Qt::darkGreen ); + myColors.append( Qt::magenta ); + myColors.append( Qt::darkGray ); + myColors.append( Qt::red ); + myColors.append( Qt::darkBlue ); + myColors.append( Qt::darkYellow ); + myColors.append( Qt::cyan ); + myColors.append( Qt::darkRed ); + myColors.append( Qt::darkCyan ); + myColors.append( Qt::yellow ); + myColors.append( Qt::darkMagenta ); + myColors.append( Qt::green ); + myColors.append( Qt::black ); + } + + int nbMarkers = 11; // QwtSymbol supports 11 marker types + int nbLines = 6; // Qt supports 6 line types + int nbColors = myColors.count(); // number of default colors supported + + aMarker = ( aMarker + 1 ) % nbMarkers; + if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++; + aColor = ( aColor + 1 ) % nbColors; + aLine = ( aLine + 1 ) % nbLines; + if ( aLine == Qt::NoPen ) aLine++; + + typeMarker = ( QwtSymbol::Style )aMarker; + color = myColors[ aColor ]; + typeLine = ( Qt::PenStyle )aLine; + if ( !existMarker( typeMarker, color, typeLine ) ) + return; + + int i, j, k; + for ( i = 0; i < nbMarkers; i++ ) { + aMarker = ( aMarker + 1 ) % nbMarkers; + if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++; + for ( j = 0; j < nbColors; j++ ) { + aColor = ( aColor + 1 ) % nbColors; + for ( k = 0; k < nbLines; k++ ) { + aLine = ( aLine + 1 ) % nbLines; + if ( aLine == Qt::NoPen ) aLine++; + if ( !existMarker( ( QwtSymbol::Style )aMarker, aColor, ( Qt::PenStyle )aLine ) ) { + typeMarker = ( QwtSymbol::Style )aMarker; + color = myColors[ aColor ]; + typeLine = ( Qt::PenStyle )aLine; + return; + } + } + } + } +*/ +} + +QSizePolicy Plot2d_Plot2d::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); +} + +QSize Plot2d_Plot2d::sizeHint() const +{ + return QwtPlot::minimumSizeHint(); +} + +/*! + return minimum size for qwt plot +*/ +QSize Plot2d_Plot2d::minimumSizeHint() const +{ + return QSize( 0, 0 ); +// QSize aSize = QwtPlot::minimumSizeHint(); +// return QSize(aSize.width()*3/4, aSize.height()); +} +/*! + Checks if marker belongs to any enitity +*/ +bool Plot2d_Plot2d::existMarker( const QwtSymbol::Style typeMarker, const QColor& color, const Qt::PenStyle typeLine ) +{ + // getting all curves + QArray keys = curveKeys(); + //QColor aRgbColor; + + if ( closeColors( color, backgroundColor() ) ) + return true; + for ( int i = 0; i < (int)keys.count(); i++ ) + { + QwtPlotCurve* crv = curve( keys[i] ); + if ( crv ) { + QwtSymbol::Style aStyle = crv->symbol().style(); + QColor aColor = crv->pen().color(); + Qt::PenStyle aLine = crv->pen().style(); +// if ( aStyle == typeMarker && aColor == color && aLine == typeLine ) + if ( aStyle == typeMarker && closeColors( aColor,color ) && aLine == typeLine ) + return true; + } + } + return false; +} + +// TEMPORARY SOLUTION!!! TO BE IMPLEMENTED!!! +Plot2d_Prs* Plot2d_ViewFrame::CreatePrs( const char* /*entry*/ ) +{ + return 0; +} + +void Plot2d_ViewFrame::copyPreferences( Plot2d_ViewFrame* vf ) +{ + if( !vf ) + return; + + myCurveType = vf->myCurveType; + myShowLegend = vf->myShowLegend; + myLegendPos = vf->myLegendPos; + myMarkerSize = vf->myMarkerSize; + myBackground = vf->myBackground; + myTitle = vf->myTitle; + myXTitle = vf->myXTitle; + myYTitle = vf->myYTitle; + myY2Title = vf->myY2Title; + myTitleEnabled = vf->myTitleEnabled; + myXTitleEnabled = vf->myXTitleEnabled; + myYTitleEnabled = vf->myYTitleEnabled; + myY2TitleEnabled = vf->myY2TitleEnabled; + myXGridMajorEnabled = vf->myXGridMajorEnabled; + myYGridMajorEnabled = vf->myYGridMajorEnabled; + myY2GridMajorEnabled = vf->myY2GridMajorEnabled; + myXGridMinorEnabled = vf->myXGridMinorEnabled; + myYGridMinorEnabled = vf->myYGridMinorEnabled; + myY2GridMinorEnabled = vf->myY2GridMinorEnabled; + myXGridMaxMajor = vf->myXGridMaxMajor; + myYGridMaxMajor = vf->myYGridMaxMajor; + myY2GridMaxMajor = vf->myY2GridMaxMajor; + myXGridMaxMinor = vf->myXGridMaxMinor; + myYGridMaxMinor = vf->myYGridMaxMinor; + myY2GridMaxMinor = vf->myY2GridMaxMinor; + myXMode = vf->myXMode; + myYMode = vf->myYMode; + mySecondY = vf->mySecondY; +} + +/*! + Updates titles according to curves +*/ +#define BRACKETIZE(x) QString( "[ " ) + x + QString( " ]" ) +void Plot2d_ViewFrame::updateTitles() +{ + QIntDictIterator it( myCurves ); + QStringList aXTitles; + QStringList aYTitles; + QStringList aXUnits; + QStringList aYUnits; + QStringList aTables; + int i = 0; + while ( it.current() ) { + // collect titles and units from all curves... + QString xTitle = it.current()->getHorTitle().stripWhiteSpace(); + QString yTitle = it.current()->getVerTitle().stripWhiteSpace(); + QString xUnits = it.current()->getHorUnits().stripWhiteSpace(); + QString yUnits = it.current()->getVerUnits().stripWhiteSpace(); + + aYTitles.append( yTitle ); + if ( aXTitles.find( xTitle ) == aXTitles.end() ) + aXTitles.append( xTitle ); + if ( aXUnits.find( xUnits ) == aXUnits.end() ) + aXUnits.append( xUnits ); + if ( aYUnits.find( yUnits ) == aYUnits.end() ) + aYUnits.append( yUnits ); + + QString aName = it.current()->getTableTitle(); + if( !aName.isEmpty() && aTables.find( aName ) == aTables.end() ) + aTables.append( aName ); + + ++it; + ++i; + } + // ... and update plot 2d view + QString xUnits, yUnits; + if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() ) + xUnits = BRACKETIZE( aXUnits[0] ); + if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty()) + yUnits = BRACKETIZE( aYUnits[0] ); + QString xTitle, yTitle; + if ( aXTitles.count() == 1 && aXUnits.count() == 1 ) + xTitle = aXTitles[0]; + if ( aYTitles.count() == 1 ) + yTitle = aYTitles[0]; + + if ( !xTitle.isEmpty() && !xUnits.isEmpty() ) + xTitle += " "; + if ( !yTitle.isEmpty() && !yUnits.isEmpty() ) + yTitle += " "; + + setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, true ); + setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, true ); + setTitle( true, aTables.join("; "), MainTitle, true ); +} + +bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const +{ +#ifdef WIN32 + return false; + +#else + bool res = false; + if( myPlot ) + { + QPaintDevice* pd = 0; + if( format=="PS" ) + { + QPrinter* pr = new QPrinter( QPrinter::HighResolution ); + pr->setPageSize( QPrinter::A4 ); + pr->setOutputToFile( true ); + pr->setOutputFileName( file ); + pr->setPrintProgram( "" ); + pd = pr; + } + + if( pd ) + { + myPlot->print( *pd ); + res = true; + delete pd; + } + } + return res; +#endif +} diff --git a/src/Plot2d/Plot2d_ViewFrame.h b/src/Plot2d/Plot2d_ViewFrame.h new file mode 100755 index 000000000..51faa0898 --- /dev/null +++ b/src/Plot2d/Plot2d_ViewFrame.h @@ -0,0 +1,196 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef PLOT2D_VIEWFRAME_H +#define PLOT2D_VIEWFRAME_H + +#include "Plot2d_Curve.h" +#include +#include + +class Plot2d_Plot2d; +class Plot2d_Prs; + +typedef QIntDict CurveDict; + +class PLOT2D_EXPORT Plot2d_ViewFrame : public QWidget +{ + Q_OBJECT + + enum { NoOpId, FitAreaId, ZoomId, PanId, GlPanId, DumpId, + ModeXLinearId, ModeXLogarithmicId, ModeYLinearId, ModeYLogarithmicId, + LegendId, CurvePointsId, CurveLinesId, CurveSplinesId }; +public: + /* Construction/destruction */ + Plot2d_ViewFrame( QWidget* parent, const QString& title = "" ); + virtual ~Plot2d_ViewFrame(); + + enum ObjectType { MainTitle, XTitle, YTitle, Y2Title, XAxis, YAxis, Y2Axis }; + +public: + QWidget* getViewWidget(); + + /* display */ + void DisplayAll(); + void EraseAll(); + void Repaint(); + + void Display( const Plot2d_Prs* ); + void Erase( const Plot2d_Prs*, const bool = false ); + Plot2d_Prs* CreatePrs( const char* entry = 0 ); + + /* operations */ + void updateTitles(); + void setTitle( const QString& title ); + QString getTitle() const { return myTitle; } + void displayCurve( Plot2d_Curve* curve, bool update = false ); + void displayCurves( const curveList& curves, bool update = false ); + void eraseCurve( Plot2d_Curve* curve, bool update = false ); + void eraseCurves( const curveList& curves, bool update = false ); + int getCurves( curveList& clist ); + const CurveDict& getCurves() { return myCurves; } + int hasCurve( Plot2d_Curve* curve ); + bool isVisible( Plot2d_Curve* curve ); + void updateCurve( Plot2d_Curve* curve, bool update = false ); + void updateLegend( const Plot2d_Prs* prs ); + void fitAll(); + void fitArea( const QRect& area ); + void fitData(const int mode, + const double xMin, const double xMax, + const double yMin, const double yMax, + const double y2Min = 0, const double y2Max = 0); + + void getFitRanges(double& xMin, double& xMax, + double& yMin, double& yMax, + double& y2Min, double& y2Max); + + /* view parameters */ + void copyPreferences( Plot2d_ViewFrame* ); + void setCurveType( int curveType, bool update = true ); + int getCurveType() const { return myCurveType; } + void setCurveTitle( int curveKey, const QString& title ); + void showLegend( bool show, bool update = true ); + void setLegendPos( int pos ); + int getLegendPos() const { return myLegendPos; } + void setMarkerSize( const int size, bool update = true ); + int getMarkerSize() const { return myMarkerSize; } + void setBackgroundColor( const QColor& color ); + QColor backgroundColor() const; + void setXGrid( bool xMajorEnabled, const int xMajorMax, + bool xMinorEnabled, const int xMinorMax, bool update = true ); + void setYGrid( bool yMajorEnabled, const int yMajorMax, + bool yMinorEnabled, const int yMinorMax, + bool y2MajorEnabled, const int y2MajorMax, + bool y2MinorEnabled, const int y2MinorMax, bool update = true ); + void setTitle( bool enabled, const QString& title, ObjectType type, bool update = true ); + QString getTitle( ObjectType type ) const; + + void setFont( const QFont& font, ObjectType type, bool update = true ); + void setHorScaleMode( const int mode, bool update = true ); + int getHorScaleMode() const { return myXMode; } + void setVerScaleMode( const int mode, bool update = true ); + int getVerScaleMode() const { return myYMode; } + + bool isModeHorLinear(); + bool isModeVerLinear(); + bool isLegendShow() { return myShowLegend; }; + + // Protection against QwtCurve::drawLines() bug in Qwt 0.4.x: + // it crashes if switched to X/Y logarithmic mode, when one or more points have + // non-positive X/Y coordinate + bool isXLogEnabled() const; + bool isYLogEnabled() const; + + virtual bool print( const QString& file, const QString& format ) const; + +protected: + int testOperation( const QMouseEvent& ); + void readPreferences(); + void writePreferences(); + QString getInfo( const QPoint& pnt ); + virtual void wheelEvent( QWheelEvent* ); + +public slots: + void onViewPan(); + void onViewZoom(); + void onViewFitAll(); + void onViewFitArea(); + void onViewGlobalPan(); + void onSettings(); + void onFitData(); + void onChangeBackground(); + +protected slots: + void plotMousePressed( const QMouseEvent& ); + void plotMouseMoved( const QMouseEvent& ); + void plotMouseReleased( const QMouseEvent& ); + +signals: + void vpModeHorChanged(); + void vpModeVerChanged(); + void vpCurveChanged(); + void contextMenuRequested( QContextMenuEvent *e ); + +protected: + Plot2d_Plot2d* myPlot; + int myOperation; + QPoint myPnt; + CurveDict myCurves; + + int myCurveType; + bool myShowLegend; + int myLegendPos; + int myMarkerSize; + QColor myBackground; + QString myTitle, myXTitle, myYTitle, myY2Title; + bool myTitleEnabled, myXTitleEnabled, myYTitleEnabled, myY2TitleEnabled; + bool myXGridMajorEnabled, myYGridMajorEnabled, myY2GridMajorEnabled; + bool myXGridMinorEnabled, myYGridMinorEnabled, myY2GridMinorEnabled; + int myXGridMaxMajor, myYGridMaxMajor, myY2GridMaxMajor; + int myXGridMaxMinor, myYGridMaxMinor, myY2GridMaxMinor; + int myXMode, myYMode; + double myXDistance, myYDistance, myYDistance2; + bool mySecondY; +}; + +class Plot2d_Plot2d : public QwtPlot +{ +public: + Plot2d_Plot2d( QWidget* parent ); + + void replot(); + void getNextMarker( QwtSymbol::Style& typeMarker, QColor& color, Qt::PenStyle& typeLine ); + QwtLegend* getLegend() { +#if QWT_VERSION < 0x040200 + return d_legend; +#else + return legend(); /* mpv: porting to the Qwt 4.2.0 */ +#endif + } + virtual QSize sizeHint() const; + virtual QSizePolicy sizePolicy() const; + virtual QSize minimumSizeHint() const; + +protected: + bool existMarker( const QwtSymbol::Style typeMarker, const QColor& color, const Qt::PenStyle typeLine ); + +protected: + QValueList myColors; +}; + +#endif diff --git a/src/Plot2d/Plot2d_ViewWindow.cxx b/src/Plot2d/Plot2d_ViewWindow.cxx new file mode 100755 index 000000000..5c558ea0f --- /dev/null +++ b/src/Plot2d/Plot2d_ViewWindow.cxx @@ -0,0 +1,467 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// Plot2d_ViewWindow.cxx: implementation of the Plot2d_ViewWindow class. +// +////////////////////////////////////////////////////////////////////// +#include "Plot2d_ViewWindow.h" +#include "Plot2d_ViewFrame.h" + +#include "SUIT_ViewManager.h" +#include "SUIT_ResourceMgr.h" +#include "SUIT_Session.h" +#include "SUIT_ToolButton.h" +#include "SUIT_Desktop.h" + +#include "QtxAction.h" + +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +Plot2d_ViewWindow::Plot2d_ViewWindow(SUIT_Desktop* theDesktop, Plot2d_Viewer* theModel) +: SUIT_ViewWindow(theDesktop) +{ + myModel = theModel; + + myViewFrame = new Plot2d_ViewFrame(this, "plotView"); + setCentralWidget(myViewFrame); + + myToolBar = new QToolBar(this); + myToolBar->setCloseMode(QDockWindow::Undocked); + myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL")); + createActions(); + createToolBar(); + + connect(myViewFrame, SIGNAL(vpModeHorChanged()), this, SLOT(onChangeHorMode())); + connect(myViewFrame, SIGNAL(vpModeVerChanged()), this, SLOT(onChangeVerMode())); + connect(myViewFrame, SIGNAL(vpCurveChanged()), this, SLOT(onChangeCurveMode())); + connect(myViewFrame, SIGNAL(contextMenuRequested( QContextMenuEvent * )), + this, SIGNAL(contextMenuRequested( QContextMenuEvent * )) ); + +} + +Plot2d_ViewWindow::~Plot2d_ViewWindow() +{ +} + +//**************************************************************** +void Plot2d_ViewWindow::putInfo(QString theMsg) +{ + QStatusBar* aStatusBar = myDesktop->statusBar(); + aStatusBar->message(theMsg/*, 3000*/); +} + +//**************************************************************** +void Plot2d_ViewWindow::contextMenuPopup( QPopupMenu* thePopup ) +{ + // scaling + QPopupMenu* scalingPopup = new QPopupMenu( thePopup ); + myActionsMap[ PModeXLinearId ]->addTo( scalingPopup ); + myActionsMap[ PModeXLogarithmicId ]->addTo( scalingPopup ); + onChangeHorMode(); + scalingPopup->insertSeparator(); + myActionsMap[ PModeYLinearId ]->addTo( scalingPopup ); + myActionsMap[ PModeYLogarithmicId ]->addTo( scalingPopup ); + thePopup->insertItem( tr( "SCALING_POPUP" ), scalingPopup ); + onChangeVerMode(); + + thePopup->insertItem(tr("TOT_PLOT2D_FITDATA"), myViewFrame, SLOT(onFitData())); + // curve type + QPopupMenu* curTypePopup = new QPopupMenu( thePopup ); + myActionsMap[ CurvPointsId ]->addTo( curTypePopup ); + myActionsMap[ CurvLinesId ]->addTo( curTypePopup ); + myActionsMap[ CurvSplinesId ]->addTo( curTypePopup ); + thePopup->insertItem( tr( "CURVE_TYPE_POPUP" ), curTypePopup ); + + // legend + myActionsMap[ LegendId ]->addTo(thePopup); + // settings + myActionsMap[ CurvSettingsId ]->addTo(thePopup); +} + +//**************************************************************** +bool Plot2d_ViewWindow::eventFilter(QObject* watched, QEvent* e) +{ + if (watched == myViewFrame) { + int aType = e->type(); + switch(aType) { + case QEvent::MouseButtonPress: + emit mousePressed(this, (QMouseEvent*) e); + return true; + + case QEvent::MouseButtonRelease: + emit mouseReleased(this, (QMouseEvent*) e); + return true; + + case QEvent::MouseMove: + emit mouseMoving(this, (QMouseEvent*) e); + return true; + + default: + break; + } + } + return SUIT_ViewWindow::eventFilter(watched, e); +} + +//**************************************************************** +void Plot2d_ViewWindow::createActions() +{ + if ( !myActionsMap.isEmpty() ) + return; + + QtxAction* aAction; + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + // Dump view + aAction = new QtxAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_DUMP" ) ), + tr( "MNU_DUMP_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_DUMP_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onDumpView())); + myActionsMap[ DumpId ] = aAction; + + // FitAll + aAction = new QtxAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_FIT_ALL" ) ), + tr( "MNU_FITALL" ), 0, this); + aAction->setStatusTip(tr("DSC_FITALL")); + connect(aAction, SIGNAL(activated()), this, SLOT(onFitAll())); + myActionsMap[ FitAllId ] = aAction; + + // FitRect + aAction = new QtxAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_FIT_AREA" ) ), + tr( "MNU_FITRECT" ), 0, this); + aAction->setStatusTip(tr("DSC_FITRECT")); + connect(aAction, SIGNAL(activated()), this, SLOT(onFitRect())); + myActionsMap[ FitRectId ] = aAction; + + // Zoom + aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_ZOOM" ) ), + tr( "MNU_ZOOM_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_ZOOM_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onZoom())); + myActionsMap[ ZoomId ] = aAction; + + // Panning + aAction = new QtxAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_PAN" ) ), + tr( "MNU_PAN_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_PAN_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onPanning())); + myActionsMap[ PanId ] = aAction; + + // Global Panning + aAction = new QtxAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_GLOBALPAN" ) ), + tr( "MNU_GLOBALPAN_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW")); + connect(aAction, SIGNAL(activated()), this, SLOT(onGlobalPanning())); + myActionsMap[ GlobalPanId ] = aAction; + + // Curve type - points + aAction = new QtxAction(tr("TOT_PLOT2D_CURVES_POINTS"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_CURVES_POINTS")), + tr("MEN_PLOT2D_CURVES_POINTS"), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_CURVES_POINTS")); + connect(aAction, SIGNAL(activated()), this, SLOT(onCurves())); + aAction->setToggleAction(true); + myActionsMap[ CurvPointsId ] = aAction; + + // Curve type - lines + aAction = new QtxAction(tr("TOT_PLOT2D_CURVES_LINES"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_CURVES_LINES")), + tr("MEN_PLOT2D_CURVES_LINES"), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_CURVES_LINES")); + connect(aAction, SIGNAL(activated()), this, SLOT(onCurves())); + aAction->setToggleAction(true); + myActionsMap[ CurvLinesId ] = aAction; + + // Curve type - splines + aAction = new QtxAction(tr("TOT_PLOT2D_CURVES_SPLINES"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_CURVES_SPLINES")), + tr("MEN_PLOT2D_CURVES_SPLINES"), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_CURVES_SPLINES")); + connect(aAction, SIGNAL(activated()), this, SLOT(onCurves())); + aAction->setToggleAction(true); + myActionsMap[ CurvSplinesId ] = aAction; + + // Mode for X (linear or logarithmic) + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LINEAR_HOR"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LINEAR_HOR")), + tr("MEN_PLOT2D_MODE_LINEAR_HOR"), 0, this); + aAction->setStatusTip (tr("PRP_PLOT2D_MODE_LINEAR_HOR")); + connect(aAction, SIGNAL(activated()), this, SLOT(onViewHorMode())); + myActionsMap[ HorId ] = aAction; + + // Mode for Y (linear or logarithmic) + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LINEAR_VER"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LINEAR_VER")), + tr("MEN_PLOT2D_MODE_LINEAR_VER" ), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_MODE_LINEAR_VER")); + connect(aAction, SIGNAL(activated()), this, SLOT(onViewVerMode())); + myActionsMap[ VerId ] = aAction; + + // Legend + aAction = new QtxAction(tr("TOT_PLOT2D_SHOW_LEGEND"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_SHOW_LEGEND")), + tr("MEN_PLOT2D_SHOW_LEGEND"), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_SHOW_LEGEND")); + connect(aAction, SIGNAL(activated()), this, SLOT(onLegend())); + aAction->setToggleAction(true); + myActionsMap[ LegendId ] = aAction; + + // Settings + aAction = new QtxAction(tr( "TOT_PLOT2D_SETTINGS"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_SETTINGS")), + tr("MEN_PLOT2D_SETTINGS"), 0, this); + aAction->setStatusTip(tr( "PRP_PLOT2D_SETTINGS")); + connect(aAction, SIGNAL(activated()), myViewFrame, SLOT(onSettings())); + myActionsMap[ CurvSettingsId ] = aAction; + + // Clone + aAction = new QtxAction(tr("MNU_CLONE_VIEW"), aResMgr->loadPixmap( "Plot2d", tr( "ICON_PLOT2D_CLONE_VIEW" ) ), + tr( "MNU_CLONE_VIEW" ), 0, this); + aAction->setStatusTip(tr("DSC_CLONE_VIEW")); + connect(aAction, SIGNAL(activated()), this, SIGNAL(cloneView())); + myActionsMap[ CloneId ] = aAction; + + /* Popup Actions */ + /* Linear/logarithmic mode */ + // Horizontal axis + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LINEAR_HOR"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LINEAR_HOR")), + tr("MEN_PLOT2D_MODE_LINEAR_HOR"), 0, this); + aAction->setStatusTip (tr("PRP_PLOT2D_MODE_LINEAR_HOR")); + aAction->setToggleAction(true); + myActionsMap[PModeXLinearId] = aAction; + connect(aAction, SIGNAL(activated()), this, SLOT(onViewHorMode())); + + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LOGARITHMIC_HOR"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LOGARITHMIC_HOR")), + tr("MEN_PLOT2D_MODE_LOGARITHMIC_HOR"), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_MODE_LOGARITHMIC_HOR")); + aAction->setToggleAction(true); + myActionsMap[PModeXLogarithmicId] = aAction; + connect(aAction, SIGNAL(activated()), this, SLOT(onViewHorMode())); + + // Vertical axis + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LINEAR_VER"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LINEAR_VER")), + tr("MEN_PLOT2D_MODE_LINEAR_VER" ), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_MODE_LINEAR_VER")); + aAction->setToggleAction(true); + myActionsMap[PModeYLinearId] = aAction; + connect(aAction, SIGNAL(activated()), this, SLOT(onViewVerMode())); + + aAction = new QtxAction(tr("TOT_PLOT2D_MODE_LOGARITHMIC_VER"), + aResMgr->loadPixmap("Plot2d", tr("ICON_PLOT2D_MODE_LOGARITHMIC_VER")), + tr("MEN_PLOT2D_MODE_LOGARITHMIC_VER" ), 0, this); + aAction->setStatusTip(tr("PRP_PLOT2D_MODE_LOGARITHMIC_VER")); + aAction->setToggleAction(true); + myActionsMap[PModeYLogarithmicId] = aAction; + connect(aAction, SIGNAL(activated()), this, SLOT(onViewVerMode())); + +} + +//**************************************************************** +void Plot2d_ViewWindow::createToolBar() +{ + myActionsMap[DumpId]->addTo(myToolBar); + + SUIT_ToolButton* aScaleBtn = new SUIT_ToolButton(myToolBar); + aScaleBtn->AddAction(myActionsMap[FitAllId]); + aScaleBtn->AddAction(myActionsMap[FitRectId]); + aScaleBtn->AddAction(myActionsMap[ZoomId]); + + SUIT_ToolButton* aPanBtn = new SUIT_ToolButton(myToolBar); + aPanBtn->AddAction(myActionsMap[PanId]); + aPanBtn->AddAction(myActionsMap[GlobalPanId]); + + myCurveBtn = new SUIT_ToolButton(myToolBar); + myCurveBtn->AddAction(myActionsMap[CurvPointsId]); + myCurveBtn->AddAction(myActionsMap[CurvLinesId]); + myCurveBtn->AddAction(myActionsMap[CurvSplinesId]); + myActionsMap[CurvLinesId]->setOn(true); + onChangeCurveMode(); + + myActionsMap[HorId]->addTo(myToolBar); + onChangeHorMode(); + myActionsMap[VerId]->addTo(myToolBar); + onChangeVerMode(); + + myActionsMap[LegendId]->addTo(myToolBar); + myActionsMap[CurvSettingsId]->addTo(myToolBar); + myActionsMap[CloneId]->addTo(myToolBar); + onChangeLegendMode(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onChangeHorMode() +{ + bool aLinear = myViewFrame->isModeHorLinear(); + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + myActionsMap[PModeXLinearId]->setOn( aLinear ); + myActionsMap[PModeXLogarithmicId]->setOn( !aLinear ); + + QPixmap pix = aResMgr->loadPixmap( "Plot2d", tr( aLinear ? "ICON_PLOT2D_MODE_LOGARITHMIC_HOR" : + "ICON_PLOT2D_MODE_LINEAR_HOR" ) ); + myActionsMap[HorId]->setIconSet( pix ); + myActionsMap[HorId]->setToolTip( tr( aLinear ? "TOT_PLOT2D_MODE_LOGARITHMIC_HOR" : + "TOT_PLOT2D_MODE_LINEAR_HOR" ) ); + myActionsMap[HorId]->setStatusTip( tr( aLinear ? "PRP_PLOT2D_MODE_LOGARITHMIC_HOR" : + "PRP_PLOT2D_MODE_LINEAR_HOR" ) ); + + myActionsMap[GlobalPanId]->setEnabled( myViewFrame->isModeVerLinear() && myViewFrame->isModeHorLinear() ); +} + +//**************************************************************** +void Plot2d_ViewWindow::onChangeVerMode() +{ + bool aLinear = myViewFrame->isModeVerLinear(); + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + myActionsMap[PModeYLinearId]->setOn( aLinear ); + myActionsMap[PModeYLogarithmicId]->setOn( !aLinear ); + + QPixmap pix = aResMgr->loadPixmap( "Plot2d", tr( aLinear ? "ICON_PLOT2D_MODE_LOGARITHMIC_VER" : + "ICON_PLOT2D_MODE_LINEAR_VER" ) ); + myActionsMap[VerId]->setIconSet( pix ); + myActionsMap[VerId]->setToolTip( tr( aLinear ? "TOT_PLOT2D_MODE_LOGARITHMIC_VER" : + "TOT_PLOT2D_MODE_LINEAR_VER" ) ); + myActionsMap[VerId]->setStatusTip( tr( aLinear ? "PRP_PLOT2D_MODE_LOGARITHMIC_VER" : + "PRP_PLOT2D_MODE_LINEAR_VER" ) ); + + myActionsMap[GlobalPanId]->setEnabled( myViewFrame->isModeVerLinear() && myViewFrame->isModeHorLinear() ); +} + +//**************************************************************** +void Plot2d_ViewWindow::onChangeCurveMode() +{ + int aCurveType = myViewFrame->getCurveType(); + myCurveBtn->SetItem(aCurveType); + + myActionsMap[CurvPointsId]->setOn(aCurveType == 0); + myActionsMap[CurvLinesId]->setOn(aCurveType == 1); + myActionsMap[CurvSplinesId]->setOn(aCurveType == 2); +} + +//**************************************************************** +void Plot2d_ViewWindow::onChangeLegendMode() +{ + myActionsMap[ LegendId ]->setOn(myViewFrame->isLegendShow()); +} + +//**************************************************************** +void Plot2d_ViewWindow::onFitAll() +{ + myViewFrame->onViewFitAll(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onFitRect() +{ + myViewFrame->onViewFitArea(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onZoom() +{ + myViewFrame->onViewZoom(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onPanning() +{ + myViewFrame->onViewPan(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onGlobalPanning() +{ + myViewFrame->onViewGlobalPan(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onViewHorMode() +{ + if (myViewFrame->isModeHorLinear()) + myViewFrame->setHorScaleMode(1); + else + myViewFrame->setHorScaleMode(0); +} + +//**************************************************************** +void Plot2d_ViewWindow::onViewVerMode() +{ + if (myViewFrame->isModeVerLinear()) + myViewFrame->setVerScaleMode(1); + else + myViewFrame->setVerScaleMode(0); +} + +//**************************************************************** +void Plot2d_ViewWindow::onLegend() +{ + myViewFrame->showLegend(!myViewFrame->isLegendShow()); + onChangeLegendMode(); +} + +//**************************************************************** +void Plot2d_ViewWindow::onCurves() +{ + QtxAction* aSender = (QtxAction*) sender(); + if(aSender == myActionsMap[CurvPointsId]) + myViewFrame->setCurveType(0); + else if(aSender == myActionsMap[CurvLinesId]) + myViewFrame->setCurveType(1); + else if(aSender == myActionsMap[CurvSplinesId]) + myViewFrame->setCurveType(2); +} + +//**************************************************************** +void Plot2d_ViewWindow::onDumpView() +{ + qApp->postEvent( myViewFrame, new QPaintEvent( QRect( 0, 0, myViewFrame->width(), myViewFrame->height() ), TRUE ) ); + SUIT_ViewWindow::onDumpView(); +} + +//**************************************************************** +QImage Plot2d_ViewWindow::dumpView() +{ + QPixmap px = QPixmap::grabWindow( myViewFrame->winId() ); + return px.convertToImage(); +} + +bool Plot2d_ViewWindow::dumpViewToFormat( const QString& fileName, const QString& format ) +{ + bool res = myViewFrame ? myViewFrame->print( fileName, format ) : false; + if( !res ) + res = SUIT_ViewWindow::dumpViewToFormat( fileName, format ); + + return res; +} + +QString Plot2d_ViewWindow::filter() const +{ + return SUIT_ViewWindow::filter() + ";;" + tr( "POSTSCRIPT_FILES" ); +} diff --git a/src/Plot2d/Plot2d_ViewWindow.h b/src/Plot2d/Plot2d_ViewWindow.h new file mode 100755 index 000000000..571d692bf --- /dev/null +++ b/src/Plot2d/Plot2d_ViewWindow.h @@ -0,0 +1,100 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef PLOT2D_VIEWWINDOW_H +#define PLOT2D_VIEWWINDOW_H + +#include "Plot2d.h" +#include + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +class SUIT_Desktop; +class Plot2d_Viewer; +class Plot2d_ViewFrame; +class QtxAction; +class SUIT_ToolButton; + +class PLOT2D_EXPORT Plot2d_ViewWindow : public SUIT_ViewWindow +{ + Q_OBJECT + +public: + Plot2d_ViewWindow( SUIT_Desktop* theDesktop, Plot2d_Viewer* theModel ); + virtual ~Plot2d_ViewWindow(); + + Plot2d_Viewer* getModel() { return myModel; } + void putInfo(QString theMsg); + Plot2d_ViewFrame* getViewFrame() { return myViewFrame; }; + QToolBar* getToolBar() { return myToolBar; }; + void contextMenuPopup( QPopupMenu* thePopup ); + +protected: + virtual QImage dumpView(); + virtual QString filter() const; + virtual bool dumpViewToFormat( const QString& fileName, const QString& format ); + +private: + bool eventFilter(QObject* watched, QEvent* e); + + void createActions(); + void createToolBar(); + +public slots: + void onChangeHorMode(); + void onChangeVerMode(); + void onChangeCurveMode(); + void onChangeLegendMode(); + + void onFitAll(); + void onFitRect(); + void onZoom(); + void onPanning(); + void onGlobalPanning(); + void onViewHorMode(); + void onViewVerMode(); + void onLegend(); + void onCurves(); + + void onDumpView(); + +signals: + void cloneView(); + +protected: + enum { DumpId, FitAllId, FitRectId, ZoomId, PanId, GlobalPanId, HorId, + VerId, LegendId, CurvPointsId, CurvLinesId, CurvSplinesId, CurvSettingsId, CloneId, + PModeXLinearId, PModeXLogarithmicId, PModeYLinearId, PModeYLogarithmicId }; + typedef QMap ActionsMap; + ActionsMap myActionsMap; + +private: + Plot2d_Viewer* myModel; + Plot2d_ViewFrame* myViewFrame; + QToolBar* myToolBar; + + SUIT_ToolButton* myCurveBtn; +}; + +#ifdef WIN32 +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/Plot2d/resources/Plot2d_msg_en.po b/src/Plot2d/resources/Plot2d_msg_en.po new file mode 100755 index 000000000..a646152b5 --- /dev/null +++ b/src/Plot2d/resources/Plot2d_msg_en.po @@ -0,0 +1,393 @@ +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. "Foo::Bar" +# would be translated to "Pub", not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: example-Qt-message-extraction\n" +"POT-Creation-Date: 1999-02-23 15:38+0200\n" +"PO-Revision-Date: 1999-02-23 15:38+0200\n" +"Last-Translator: \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +# ------------------------------------ +# Plot2d_ViewFrame +# ------------------------------------ +msgid "TOT_PLOT2D_MODE_LINEAR_HOR" +msgstr "Horizontal axis: linear" + +msgid "MEN_PLOT2D_MODE_LINEAR_HOR" +msgstr "Horizontal axis: linear" + +msgid "PRP_PLOT2D_MODE_LINEAR_HOR" +msgstr "Switches view to linear scaling mode along horizontal axis" + +msgid "TOT_PLOT2D_MODE_LOGARITHMIC_HOR" +msgstr "Horizontal axis: logarithmic" + +msgid "MEN_PLOT2D_MODE_LOGARITHMIC_HOR" +msgstr "Horizontal axis: logarithmic" + +msgid "PRP_PLOT2D_MODE_LOGARITHMIC_HOR" +msgstr "Switches view to logarithmic scaling mode along horizontal axis" + +msgid "TOT_PLOT2D_MODE_LINEAR_VER" +msgstr "Vertical axis: linear" + +msgid "MEN_PLOT2D_MODE_LINEAR_VER" +msgstr "Vertical axis: linear" + +msgid "PRP_PLOT2D_MODE_LINEAR_VER" +msgstr "Switches view to linear scaling mode along vertical axis" + +msgid "TOT_PLOT2D_MODE_LOGARITHMIC_VER" +msgstr "Vertical axis: logarithmic" + +msgid "MEN_PLOT2D_MODE_LOGARITHMIC_VER" +msgstr "Vertical axis: logarithmic" + +msgid "PRP_PLOT2D_MODE_LOGARITHMIC_VER" +msgstr "Switches view to logarithmic scaling mode along vertical axis" + +msgid "TOT_PLOT2D_SHOW_LEGEND" +msgstr "Show Legend" + +msgid "MEN_PLOT2D_SHOW_LEGEND" +msgstr "Show &Legend" + +msgid "PRP_PLOT2D_SHOW_LEGEND" +msgstr "Enables/disables legend" + +msgid "TOT_PLOT2D_CURVES_POINTS" +msgstr "Draw points" + +msgid "MEN_PLOT2D_CURVES_POINTS" +msgstr "Draw points" + +msgid "PRP_PLOT2D_CURVES_POINTS" +msgstr "Switches view to points mode" + +msgid "TOT_PLOT2D_CURVES_LINES" +msgstr "Draw lines" + +msgid "MEN_PLOT2D_CURVES_LINES" +msgstr "Draw lines" + +msgid "PRP_PLOT2D_CURVES_LINES" +msgstr "Switches view to lines mode" + +msgid "TOT_PLOT2D_CURVES_SPLINES" +msgstr "Draw splines" + +msgid "MEN_PLOT2D_CURVES_SPLINES" +msgstr "Draw splines" + +msgid "PRP_PLOT2D_CURVES_SPLINES" +msgstr "Switches view to splines mode" + +msgid "TOT_PLOT2D_SETTINGS" +msgstr "Settings" + +msgid "MEN_PLOT2D_SETTINGS" +msgstr "&Settings" + +msgid "PRP_PLOT2D_SETTINGS" +msgstr "Setups view properties" + +msgid "TOT_PLOT2D_FITDATA" +msgstr "Fit range" + +msgid "MEN_PLOT2D_FITDATA" +msgstr "Fit &Range" + +msgid "PRP_PLOT2D_FITDATA" +msgstr "Fits view to the given data range" + +msgid "TOT_PLOT2D_CHANGE_BACKGROUND" +msgstr "Change background" + +msgid "MEN_PLOT2D_CHANGE_BACKGROUND" +msgstr "Change background..." + +msgid "PRP_PLOT2D_CHANGE_BACKGROUND" +msgstr "Change background color" + +msgid "SCALING_POPUP" +msgstr "Scaling" + +msgid "CURVE_TYPE_POPUP" +msgstr "Curve type" + +msgid "INF_COORDINATES" +msgstr "Coordinates: X : %1, Y : %2" + +msgid "WARNING" +msgstr "Warning" + +msgid "WRN_XLOG_NOT_ALLOWED" +msgstr "Some points with non-positive abscissa values have been detected.\nLogarithmic scale for abscissa axis is not allowed." + +msgid "WRN_YLOG_NOT_ALLOWED" +msgstr "Some points with non-positive ordinate values have been detected.\nLogarithmic scale for ordinate axis is not allowed." + +msgid "INF_COORDINATES_SOME_Y" +msgstr "Coordinates: X : %1, Y : %2 ( %3 )" + +#msgid "INF_READY" +#msgstr "Ready" + +msgid "PLOT2D_IMAGE_FILES" +msgstr "Images Files (*.bmp *.png *.jpg *.jpeg)" + +msgid "INF_APP_DUMP_VIEW" +msgstr "Dump view" + +msgid "ERR_DOC_CANT_SAVE_FILE" +msgstr "Cannot save file" + +msgid "ERROR" +msgstr "Error" + +msgid "BUT_OK" +msgstr "Ok" + +# ------------------------------------ +# Plot2d_SetupViewDlg +# ------------------------------------ +msgid "TLT_SETUP_PLOT2D_VIEW" +msgstr "Plot 2d View Settings" + +msgid "PLOT2D_ENABLE_MAIN_TITLE" +msgstr "Main title" + +msgid "PLOT2D_ENABLE_HOR_TITLE" +msgstr "Horizontal axis title" + +msgid "INF_AXES_X" +msgstr "Axis X" + +msgid "INF_AXES_Y_LEFT" +msgstr "Axis Y Left" + +msgid "INF_AXES_Y_RIGHT" +msgstr "Axis Y Right" + +msgid "PLOT2D_ENABLE_VER_TITLE" +msgstr "Vertical axis title" + +msgid "PLOT2D_CURVE_TYPE_LBL" +msgstr "Curve type:" + +msgid "PLOT2D_CURVE_TYPE_POINTS" +msgstr "Points" + +msgid "PLOT2D_CURVE_TYPE_LINES" +msgstr "Lines" + +msgid "PLOT2D_CURVE_TYPE_SPLINE" +msgstr "Spline" + +msgid "PLOT2D_ENABLE_LEGEND" +msgstr "Show legend" + +msgid "PLOT2D_LEGEND_POSITION_LEFT" +msgstr "Left" + +msgid "PLOT2D_LEGEND_POSITION_RIGHT" +msgstr "Right" + +msgid "PLOT2D_LEGEND_POSITION_TOP" +msgstr "Top" + +msgid "PLOT2D_LEGEND_POSITION_BOTTOM" +msgstr "Bottom" + +msgid "PLOT2D_MARKER_SIZE_LBL" +msgstr "Marker size:" + +msgid "PLOT2D_BACKGROUND_COLOR_LBL" +msgstr "Background color:" + +msgid "PLOT2D_SCALE_TLT" +msgstr "Scale mode" + +msgid "PLOT2D_SCALE_MODE_HOR" +msgstr "Horizontal axis:" + +msgid "PLOT2D_SCALE_MODE_VER" +msgstr "Vertical axis:" + +msgid "PLOT2D_SCALE_MODE_LINEAR" +msgstr "Linear" + +msgid "PLOT2D_SCALE_MODE_LOGARITHMIC" +msgstr "Logarithmic" + +msgid "PLOT2D_GRID_TLT" +msgstr "Grid / Axes marks" + +msgid "PLOT2D_GRID_ENABLE_HOR_MAJOR" +msgstr "Horizontal major" + +msgid "PLOT2D_GRID_ENABLE_VER_MAJOR" +msgstr "Vertical major" + +msgid "PLOT2D_GRID_ENABLE_HOR_MINOR" +msgstr "Horizontal minor" + +msgid "PLOT2D_GRID_ENABLE_VER_MINOR" +msgstr "Vertical minor" + +msgid "PLOT2D_MAX_INTERVALS" +msgstr "Max intervals" + +msgid "PLOT2D_SET_AS_DEFAULT_CHECK" +msgstr "Save settings as default" + +# ------------------------------------ +# Plot2d_FitDataDlg +# ------------------------------------ +msgid "FIT_DATA_TLT" +msgstr "Fit Data Range" + +msgid "Plot2d_FitDataDlg::FIT_ALL" +msgstr "Fit both" + +msgid "Plot2d_FitDataDlg::FIT_HORIZONTAL" +msgstr "Fit horizontally" + +msgid "Plot2d_FitDataDlg::FIT_VERTICAL" +msgstr "Fit vertically" + +msgid "Plot2d_FitDataDlg::HORIZONTAL_AXIS" +msgstr "Horizontal axis" + +msgid "Plot2d_FitDataDlg::VERTICAL_AXIS" +msgstr "Vertical axis" + +msgid "Plot2d_FitDataDlg::VERTICAL_LEFT_AXIS" +msgstr "Vertical left axis" + +msgid "Plot2d_FitDataDlg::VERTICAL_RIGHT_AXIS" +msgstr "Vertical right axis" + +msgid "Plot2d_FitDataDlg::MIN_VALUE_LAB" +msgstr "Min:" + +msgid "Plot2d_FitDataDlg::MAX_VALUE_LAB" +msgstr "Max:" + +# ------------------------------------ +# Plot2d_ViewWindow +# ------------------------------------ + +msgid "LBL_TOOLBAR_LABEL" +msgstr "View Operations" + +msgid "DSC_DUMP_VIEW" +msgstr "Saves the active view in the image file" + +msgid "MNU_DUMP_VIEW" +msgstr "Dump view..." + +msgid "DSC_FITALL" +msgstr "Fit all objects inside the view frame" + +msgid "MNU_FITALL" +msgstr "Fit All" + +msgid "DSC_FITRECT" +msgstr "Fit area within the view frame" + +msgid "MNU_FITRECT" +msgstr "Fit Area" + +msgid "DSC_ZOOM_VIEW" +msgstr "Zoom the view" + +msgid "MNU_ZOOM_VIEW" +msgstr "Zoom" + +msgid "DSC_PAN_VIEW" +msgstr "Panning the view" + +msgid "MNU_PAN_VIEW" +msgstr "Panning" + +msgid "DSC_GLOBALPAN_VIEW" +msgstr "Selection of a new center of the view" + +msgid "MNU_GLOBALPAN_VIEW" +msgstr "Global Panning" + +msgid "DSC_CLONE_VIEW" +msgstr "Create new OCC viewer for the active scene" + +msgid "MNU_CLONE_VIEW" +msgstr "Clone View" + + +msgid "TLT_SETUP_CURVE" +msgstr "Setup Curve" + +msgid "CURVE_LINE_TYPE_LAB" +msgstr "Line type:" + +msgid "CURVE_LINE_WIDTH_LAB" +msgstr "Line width:" + +msgid "CURVE_MARKER_TYPE_LAB" +msgstr "Marker type:" + +msgid "CURVE_COLOR_LAB" +msgstr "Color:" + +msgid "NONE_LINE_LBL" +msgstr "None" + +msgid "SOLID_LINE_LBL" +msgstr "Solid" + +msgid "DASH_LINE_LBL" +msgstr "Dash" + +msgid "DOT_LINE_LBL" +msgstr "Dot" + +msgid "DASHDOT_LINE_LBL" +msgstr "DashDot" + +msgid "DAHSDOTDOT_LINE_LBL" +msgstr "DashDotDot" + +msgid "NONE_MARKER_LBL" +msgstr "None" + +msgid "CIRCLE_MARKER_LBL" +msgstr "Circle" + +msgid "RECTANGLE_MARKER_LBL" +msgstr "Rectangle" + +msgid "DIAMOND_MARKER_LBL" +msgstr "Diamond" + +msgid "DTRIANGLE_MARKER_LBL" +msgstr "Downward triangle" + +msgid "UTRIANGLE_MARKER_LBL" +msgstr "Upward triangle" + +msgid "LTRIANGLE_MARKER_LBL" +msgstr "Leftward triangle" + +msgid "RTRIANGLE_MARKER_LBL" +msgstr "Rightward triangle" + +msgid "CROSS_MARKER_LBL" +msgstr "Cross" + +msgid "XCROSS_MARKER_LBL" +msgstr "Diagonal cross" + +msgid "POSTSCRIPT_FILES" +msgstr "PostScript files (*.ps)" diff --git a/src/PyInterp/PyInterp_Dispatcher.cxx b/src/PyInterp/PyInterp_Dispatcher.cxx new file mode 100755 index 000000000..3d5067dba --- /dev/null +++ b/src/PyInterp/PyInterp_Dispatcher.cxx @@ -0,0 +1,213 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2005 CEA/DEN, EDF R&D +// +// +// +// File : PyInterp_Dispatcher.cxx +// Author : Sergey ANIKIN, OCC +// Module : GUI +// $Header$ + + +#include +#include +#include + +#include +#include + +//#include +using namespace std; + +PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0; + +////////////////////////////////////////////////////////// +// class : PyInterp_Request +////////////////////////////////////////////////////////// + +void PyInterp_Request::process() +{ + safeExecute(); + + myMutex.lock(); + //if ( !IsSync() && getListener() && getEvent() ) + if ( getListener() && getEvent() ) + postEvent(); + myMutex.unlock(); +} + +void PyInterp_Request::safeExecute() +{ + execute(); +} + +void PyInterp_Request::Destroy( PyInterp_Request* request ) +{ + // Lock and unlock the mutex to avoid errors on its deletion + request->myMutex.lock(); + request->myMutex.unlock(); + delete request; +} + +QEvent* PyInterp_Request::createEvent() const +{ + return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this ); +} + +QEvent* PyInterp_Request::getEvent() +{ + //if ( !myEvent && !IsSync() ) + if ( !myEvent ) + myEvent = createEvent(); + return myEvent; +} + +void PyInterp_Request::postEvent() +{ +#if QT_VERSION >= 0x030303 +// MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3") + QApplication::postEvent( getListener(), getEvent() ); +#else +// MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5") + QThread::postEvent( getListener(), getEvent() ); +#endif +} + +void PyInterp_Request::setListener( QObject* o ) +{ + myMutex.lock(); + myListener = o; + myMutex.unlock(); +} + +void PyInterp_LockRequest::safeExecute() +{ + if ( getInterp() ){ + PyLockWrapper aLock = getInterp()->GetLockWrapper(); + execute(); + } +} + +////////////////////////////////////////////////////////// +// class : PyInterp_Event +////////////////////////////////////////////////////////// + +PyInterp_Event::~PyInterp_Event() +{ + PyInterp_Request::Destroy( myRequest ); + myRequest = 0; +} + +////////////////////////////////////////////////////////// +// class : PyInterp_Dispatcher +////////////////////////////////////////////////////////// + +PyInterp_Dispatcher* PyInterp_Dispatcher::Get() +{ + if ( !myInstance ) + myInstance = new PyInterp_Dispatcher(); + return myInstance; +} + +PyInterp_Dispatcher::PyInterp_Dispatcher() +: QThread() +{ + myWatcher = new PyInterp_Watcher(); +} + +PyInterp_Dispatcher::~PyInterp_Dispatcher() +{ + // Clear the request queue + myQueueMutex.lock(); + + for ( std::list::iterator it = myQueue.begin(); it != myQueue.end(); ++it ) + PyInterp_Request::Destroy( *it ); + myQueue.clear(); + + myQueueMutex.unlock(); + + // Wait for run() to finish + wait(); + + delete myWatcher; + myWatcher = 0; +} + +bool PyInterp_Dispatcher::IsBusy() const +{ + return running(); +} + +void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest ) +{ + if ( !theRequest ) + return; + + //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy! + if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy! + processRequest( theRequest ); + else { // asynchronous processing + myQueueMutex.lock(); + myQueue.push_back( theRequest ); + if ( theRequest->getListener() ) + QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) ); + myQueueMutex.unlock(); + + if ( !IsBusy() ) + start(); + } +} + +void PyInterp_Dispatcher::run() +{ +// MESSAGE("*** PyInterp_Dispatcher::run(): STARTED") + PyInterp_Request* aRequest; + + // prepare for queue size check + myQueueMutex.lock(); + + while( myQueue.size() ) { +// MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue") + aRequest = myQueue.front(); + + // let other threads append their requests to the end of the queue + myQueueMutex.unlock(); + + // processRequest() may delete a request, so this pointer must not be used + // after request is processed! + processRequest( aRequest ); + + // prepare for removal of the first request in the queue + myQueueMutex.lock(); + // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it + if ( myQueue.front() == aRequest ) // It's still here --> remove it + myQueue.pop_front(); + +// MESSAGE("*** PyInterp_Dispatcher::run(): request processed") + } + + myQueueMutex.unlock(); +// MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED") +} + +void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest ) +{ + theRequest->process(); +} + +void PyInterp_Dispatcher::objectDestroyed( const QObject* o ) +{ + // prepare for modification of the queue + myQueueMutex.lock(); + + for ( std::list::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){ + if ( o == (*it)->getListener() ){ + (*it)->setListener( 0 ); // to prevent event posting + it = myQueue.erase( it ); + } + } + + myQueueMutex.unlock(); +} + diff --git a/src/PyInterp/PyInterp_base.cxx b/src/PyInterp/PyInterp_base.cxx new file mode 100644 index 000000000..69ccefc9d --- /dev/null +++ b/src/PyInterp/PyInterp_base.cxx @@ -0,0 +1,300 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : PyInterp_base.cxx +// Author : Christian CAREMOLI, Paul RASCLE, EDF +// Module : SALOME +// $Header$ + + +#include +#include + +#include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)! +#include + +using namespace std; + +PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): + myThreadState(theThreadState), + mySaveThreadState(0) +{ +#if defined(USE_GILSTATE) + if (myThreadState->interp == PyInterp_base::_interp) { + _savestate = PyGILState_Ensure(); + } else { + PyEval_AcquireThread(myThreadState); + } +#else + PyEval_AcquireThread(myThreadState); +#endif +} + +PyLockWrapper::~PyLockWrapper() +{ +#if defined(USE_GILSTATE) + if (myThreadState->interp == PyInterp_base::_interp) { + PyGILState_Release(_savestate); + } else { + PyEval_ReleaseThread(myThreadState); + } +#else + PyEval_ReleaseThread(myThreadState); +#endif +} + +class PyReleaseLock{ +public: + ~PyReleaseLock(){ + PyEval_ReleaseLock(); + } +}; + + +PyLockWrapper PyInterp_base::GetLockWrapper(){ + return _tstate; +} + + +// main python interpreter (static attributes) + +int PyInterp_base::_argc = 1; +char* PyInterp_base::_argv[] = {""}; + +PyObject *PyInterp_base::builtinmodule = NULL; + +PyThreadState *PyInterp_base::_gtstate = NULL; +PyInterpreterState *PyInterp_base::_interp = NULL; + + +/*! + * basic constructor here : herited classes constructors must call initalize() method + * defined here. + */ +PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true) +{ +} + +PyInterp_base::~PyInterp_base() +{ +} + + +/*! + * Must be called by herited classes constructors. initialize() calls virtuals methods + * initstate & initcontext, not defined here in base class. initstate & initcontext methods + * must be implemented in herited classes, following the Python interpreter policy + * (mono or multi interpreter...). + */ +void PyInterp_base::initialize() +{ + _history.clear(); // start a new list of user's commands + _ith = _history.begin(); + + init_python(); + // Here the global lock is released + + initState(); + + PyLockWrapper aLock= GetLockWrapper(); + + initContext(); + + // used to interpret & compile commands + PyObjWrapper m(PyImport_ImportModule("codeop")); + if(!m){ + PyErr_Print(); + return; + } + + // Create cStringIO to capture stdout and stderr + PycString_IMPORT; + _vout = PycStringIO->NewOutput(128); + _verr = PycStringIO->NewOutput(128); + + // All the initRun outputs are redirected to the standard output (console) + initRun(); +} + +void PyInterp_base::init_python() +{ + _atFirst = false; + if (Py_IsInitialized()) + return; + + // Python is not initialized + Py_SetProgramName(_argv[0]); + Py_Initialize(); // Initialize the interpreter + PySys_SetArgv(_argc, _argv); + PyEval_InitThreads(); // Create (and acquire) the interpreter lock + _interp = PyThreadState_Get()->interp; + _gtstate = PyEval_SaveThread(); // Release global thread state +} + +string PyInterp_base::getbanner() +{ + // Should we take the lock ? + // PyEval_RestoreThread(_tstate); + 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; +} + + +int PyInterp_base::initRun() +{ + PySys_SetObject("stderr",_verr); + PySys_SetObject("stdout",_vout); + + PyObjWrapper verr(PyObject_CallMethod(_verr,"reset","")); + PyObjWrapper vout(PyObject_CallMethod(_vout,"reset","")); + + //PyObject *m = PyImport_GetModuleDict(); + + PySys_SetObject("stdout",PySys_GetObject("__stdout__")); + PySys_SetObject("stderr",PySys_GetObject("__stderr__")); + + return 0; +} + + +/*! + * This function compiles a string (command) and then evaluates it in the dictionnary + * context if possible. + * Returns : + * -1 : fatal error + * 1 : incomplete text + * 0 : complete text executed with success + */ +int compile_command(const char *command,PyObject *context) +{ + PyObject *m = PyImport_AddModule("codeop"); + if(!m){ // Fatal error. No way to go on. + PyErr_Print(); + return -1; + } + PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command)); + if(!v){ + // Error encountered. It should be SyntaxError, + //so we don't write out traceback + PyObjWrapper exception, value, tb; + PyErr_Fetch(&exception, &value, &tb); + PyErr_NormalizeException(&exception, &value, &tb); + PyErr_Display(exception, value, NULL); + return -1; + }else if (v == Py_None){ + // Incomplete text we return 1 : we need a complete text to execute + 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(); + return -1; + } + // The command has been successfully executed. Return 0 + return 0; + } +} + + +int PyInterp_base::run(const char *command) +{ + if(_atFirst){ + int ret = 0; + ret = simpleRun("from Help import *"); + if (ret) { + _atFirst = false; + return ret; + } + ret = simpleRun("import salome"); + if (ret) { + _atFirst = false; + return ret; + } + ret = simpleRun("salome.salome_init()"); + if (ret) { + _atFirst = false; + return ret; + } + _atFirst = false; + } + return simpleRun(command); +} + + +int PyInterp_base::simpleRun(const char *command) +{ + if( !_atFirst && strcmp(command,"") != 0 ) { + _history.push_back(command); + _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 + + // Reset redirected outputs before treatment + PySys_SetObject("stderr",_verr); + PySys_SetObject("stdout",_vout); + + PyObjWrapper verr(PyObject_CallMethod(_verr,"reset","")); + PyObjWrapper vout(PyObject_CallMethod(_vout,"reset","")); + + int ier = compile_command(command,_g); + + // Outputs are redirected on standards outputs (console) + PySys_SetObject("stdout",PySys_GetObject("__stdout__")); + PySys_SetObject("stderr",PySys_GetObject("__stderr__")); + + return ier; +} + + +const char * PyInterp_base::getPrevious() +{ + if(_ith != _history.begin()){ + _ith--; + return (*_ith).c_str(); + } + else + return BEGIN_HISTORY_PY; +} + + +const char * PyInterp_base::getNext() +{ + if(_ith != _history.end()){ + _ith++; + } + if (_ith == _history.end()) + return TOP_HISTORY_PY; + else + return (*_ith).c_str(); +} + + +string PyInterp_base::getverr(){ + //PyLockWrapper aLock(_tstate); + PyObjWrapper v(PycStringIO->cgetvalue(_verr)); + string aRet(PyString_AsString(v)); + return aRet; +} + + +string PyInterp_base::getvout(){ + //PyLockWrapper aLock(_tstate); + PyObjWrapper v(PycStringIO->cgetvalue(_vout)); + string aRet(PyString_AsString(v)); + return aRet; +} diff --git a/src/PyInterp/PyInterp_base.h b/src/PyInterp/PyInterp_base.h new file mode 100644 index 000000000..66847770d --- /dev/null +++ b/src/PyInterp/PyInterp_base.h @@ -0,0 +1,132 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : PyInterp_base.h +// Author : Christian CAREMOLI, Paul RASCLE, EDF +// Module : SALOME +// $Header$ + +#ifndef _PYINTERP_BASE_H_ +#define _PYINTERP_BASE_H_ + +#include "PyInterp.h" + +#include +#include +#include + +// include order important! +// pthread then python then qt +//#include // must be before Python.h ! + +#include // must be before qt includes ... +#include // Python include needed for versions before 2.4. Included in Python.h now. +#include // Python include needed for versions before 2.4. Included in Python.h now. + +//#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0 +//extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l); +//#endif + +/* For 2.3, use the PyGILState_ calls */ +#if (PY_VERSION_HEX >= 0x02030000) +#define USE_GILSTATE +#endif + +#define TOP_HISTORY_PY "--- top of history ---" +#define BEGIN_HISTORY_PY "--- begin of history ---" + +class PYINTERP_EXPORT PyLockWrapper +{ + PyThreadState* myThreadState; + PyThreadState* mySaveThreadState; +#if defined(USE_GILSTATE) + PyGILState_STATE _savestate ; +#endif + public: + PyLockWrapper(PyThreadState* theThreadState); + ~PyLockWrapper(); +}; + +class PYINTERP_EXPORT PyInterp_base{ + public: + static int _argc; + static char* _argv[]; + static PyObject *builtinmodule; + static PyThreadState *_gtstate; + static PyInterpreterState *_interp; + + PyInterp_base(); + ~PyInterp_base(); + + virtual void initialize(); + virtual void init_python(); + // init_python() made virtual to: + // 1. Remove dependency on KERNEL in light SALOME configuration + // 2. Allow redefinition of this method in SalomeApp_PyInterp class (it should be empty there and rely on KERNEL_PYTHON) + + virtual int run(const char *command); + + PyLockWrapper GetLockWrapper(); + + std::string getbanner(); + std::string getverr(); + std::string getvout(); + + const char * getPrevious(); + const char * getNext(); + + protected: + PyThreadState * _tstate; + PyObject * _vout; + PyObject * _verr; + PyObject * _g; + PyObject * _codeop; + std::list _history; + std::list::iterator _ith; + bool _atFirst; + + int simpleRun(const char* command); + int initRun(); + + virtual bool initState() = 0; + virtual bool initContext() = 0; +}; + + +class PYINTERP_EXPORT PyObjWrapper{ + PyObject* myObject; +public: + PyObjWrapper(PyObject* theObject): myObject(theObject) {} + PyObjWrapper(): myObject(0) {} + operator PyObject*(){ + return myObject; + } + PyObject* operator->(){ + return myObject; + } + PyObject* get(){ + return myObject; + } + bool operator!(){ + return !myObject; + } + bool operator==(PyObject* theObject){ + return myObject == theObject; + } + PyObject** operator&(){ + return &myObject; + } + PyObjWrapper& operator=(PyObjWrapper* theObjWrapper){ + Py_XDECREF(myObject); + myObject = theObjWrapper->myObject; + return *this; + } + virtual ~PyObjWrapper(){ + Py_XDECREF(myObject); + } +}; + +#endif diff --git a/src/PythonConsole/PythonConsole_PyEditor.cxx b/src/PythonConsole/PythonConsole_PyEditor.cxx new file mode 100755 index 000000000..5bb4aed68 --- /dev/null +++ b/src/PythonConsole/PythonConsole_PyEditor.cxx @@ -0,0 +1,729 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : PythonConsole_PyEditor.cxx +// Author : Nicolas REJNERI +// Module : SALOME + +#include // this include must be first (see PyInterp_base.h)! + +#include + +#include + +#include +#include +#include +#include +#include + +using namespace std; + +//#ifdef _DEBUG_ +//static int MYDEBUG = 1; +//#else +//static int MYDEBUG = 0; +//#endif + + +enum { IdCopy, IdPaste, IdClear, IdSelectAll }; + + +static QString READY_PROMPT = ">>> "; +static QString DOTS_PROMPT = "... "; +#define PROMPT_SIZE _currentPrompt.length() + +class ExecCommand : public PyInterp_LockRequest +{ +public: + ExecCommand(PyInterp_base* theInterp, const char* theCommand, + PythonConsole_PyEditor* theListener, bool sync = false) + : PyInterp_LockRequest( theInterp, theListener, sync ), + myCommand( theCommand ), myState( PyInterp_Event::OK ) + {} + +protected: + virtual void execute(){ + if(myCommand != ""){ +// if(MYDEBUG) MESSAGE("*** ExecCommand::execute() started"); + int ret = getInterp()->run( myCommand.latin1() ); +// if(MYDEBUG) MESSAGE("ExecCommand::execute() - myInterp = "< 0) + myState = PyInterp_Event::INCOMPLETE; + myError = getInterp()->getverr().c_str(); + myOutput = getInterp()->getvout().c_str(); +// if(MYDEBUG) MESSAGE("*** ExecCommand::execute() finished"); + }else{ + myError = ""; + myOutput = ""; + } + } + + virtual QEvent* createEvent() const + { + return new PyInterp_Event( myState, (PyInterp_Request*)this ); + } + +public: + QString myError; + QString myOutput; + +private: + QString myCommand; + int myState; +}; + + +/*! + Constructor +*/ +PythonConsole_PyEditor::PythonConsole_PyEditor(PyInterp_base* theInterp, QWidget *theParent, const char* theName): + QTextEdit(theParent,theName), + myInterp( 0 ) +{ + QString fntSet( "" ); + QFont aFont = SUIT_Tools::stringToFont( fntSet ); + setFont(aFont); + //setTextFormat(QTextEdit::PlainText); + setUndoRedoEnabled( false ); + + _currentPrompt = READY_PROMPT; + setWordWrap(NoWrap); + + connect(this,SIGNAL(returnPressed()),this,SLOT(handleReturn()) ); + + // san - This is necessary for troubleless initialization + onPyInterpChanged( theInterp ); +} + +/*! + Destructor +*/ +PythonConsole_PyEditor::~PythonConsole_PyEditor() +{ +// if(MYDEBUG) MESSAGE("PythonConsole_PyEditor::~PythonConsole_PyEditor()"); +} + +/*! + Called to insert a string s +*/ +void PythonConsole_PyEditor::setText(QString s) +{ + int para=paragraphs()-1; + int col=paragraphLength(para); + insertAt(s,para,col); + int n = paragraphs()-1; + setCursorPosition( n, paragraphLength(n)); +} + +/*! + Convenient method for executing a Python command, + as if the user typed it manually +*/ +void PythonConsole_PyEditor::exec( const QString& command ) +{ + // Some interactive command is being executed in this editor -> do nothing + if ( isReadOnly() ) + return; + int para=paragraphs()-1; + removeParagraph( para ); + _currentPrompt = READY_PROMPT; + _buf.truncate(0); + _isInHistory = false; + setText( "\n" + _currentPrompt); + setText( command + "\n" ); + handleReturn(); +} + +/*! + Called when an handleReturn +*/ +void PythonConsole_PyEditor::handleReturn() +{ + int para=paragraphs()-2; + _buf.append(text(para).remove(0,PROMPT_SIZE)); + _buf.truncate( _buf.length() - 1 ); + setReadOnly( true ); + viewport()->setCursor( waitCursor ); + + // Post a request to execute Python command + // Editor will be informed via a custom event that execution has been completed + PyInterp_Dispatcher::Get()->Exec( new ExecCommand( myInterp, _buf.latin1(), this ) ); +} + +/* + Processes drop event: paste dragged text +*/ +void PythonConsole_PyEditor::contentsDropEvent( QDropEvent* event ) +{ + event->acceptAction(); + QString text; + if ( QTextDrag::decode( event, text ) ) { + int par, col; + int endLine = paragraphs() -1; + col = charAt( event->pos(), &par ); + + if ( col >= 0 && par >= 0 ) { + if ( par != endLine || col < PROMPT_SIZE ) { + par = endLine; + col = paragraphLength( endLine ); + } + setCursorPosition( par, col ); + insertAt( text, par, col ); + removeSelection(); + } + } +} + +/* + Processes middle button release event - paste clipboard's contents +*/ +void PythonConsole_PyEditor::contentsMouseReleaseEvent( QMouseEvent* event ) +{ + if ( event->button() == LeftButton ) { + QTextEdit::contentsMouseReleaseEvent(event); + copy(); + } + if ( event->button() == MidButton ) { + if (QApplication::clipboard()->supportsSelection()) { + int par, col; + int endLine = paragraphs() -1; + col = charAt( event->pos(), &par ); + if ( col >= 0 && par >= 0 ) { + if ( par != endLine || col < PROMPT_SIZE ) + setCursorPosition( endLine, paragraphLength( endLine ) ); + else + setCursorPosition( par, col ); + QApplication::clipboard()->setSelectionMode(TRUE); + paste(); + QApplication::clipboard()->setSelectionMode(FALSE); + } + } + } + else { + QTextEdit::contentsMouseReleaseEvent(event); + } +} + +/* + Processes own popup menu +*/ +void PythonConsole_PyEditor::mousePressEvent (QMouseEvent* event) +{ + if ( event->button() == RightButton ) { + QPopupMenu *popup = new QPopupMenu( this ); + QMap idMap; + + int para1, col1, para2, col2; + getSelection(¶1, &col1, ¶2, &col2); + bool allSelected = hasSelectedText() && + para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && para2 == paragraphLength(para2); + int id; + id = popup->insertItem( tr( "EDIT_COPY_CMD" ) ); + idMap.insert(IdCopy, id); + id = popup->insertItem( tr( "EDIT_PASTE_CMD" ) ); + idMap.insert(IdPaste, id); + id = popup->insertItem( tr( "EDIT_CLEAR_CMD" ) ); + idMap.insert(IdClear, id); + popup->insertSeparator(); + id = popup->insertItem( tr( "EDIT_SELECTALL_CMD" ) ); + idMap.insert(IdSelectAll, id); + popup->setItemEnabled( idMap[ IdCopy ], hasSelectedText() ); + popup->setItemEnabled( idMap[ IdPaste ], + !isReadOnly() && (bool)QApplication::clipboard()->text().length() ); + popup->setItemEnabled( idMap[ IdSelectAll ], + (bool)text().length() && !allSelected ); + + int r = popup->exec( event->globalPos() ); + delete popup; + + if ( r == idMap[ IdCopy ] ) { + copy(); + } + else if ( r == idMap[ IdPaste ] ) { + paste(); + } + else if ( r == idMap[ IdClear ] ) { + clear(); + setText(myBanner); + _currentPrompt = READY_PROMPT; + setText(_currentPrompt); + } + else if ( r == idMap[ IdSelectAll ] ) { + selectAll(); + } + } + else { + QTextEdit::mousePressEvent(event); + } +} + +/*! + Checks, is the string a command line or not. +*/ + +bool PythonConsole_PyEditor::isCommand( const QString& str) const +{ + // prompt may be '>>> ' or for '... ' + return ( str.find( READY_PROMPT ) == 0 || str.find( DOTS_PROMPT ) == 0 ); +} + + +/*! + Called when a keyPress event +*/ +void PythonConsole_PyEditor::keyPressEvent( QKeyEvent* e ) +{ + // get cursor position + int curLine, curCol; + getCursorPosition(&curLine, &curCol); + + // get last edited line + int endLine = paragraphs() -1; + + // get pressed key code + int aKey = e->key(); + + // check if is pressed + bool ctrlPressed = e->state() & ControlButton; + // check if is pressed + bool shftPressed = e->state() & ShiftButton; + + // process + key-bindings + if ( aKey == Key_C && ctrlPressed ) { + _buf.truncate(0); + setText("\n"); + _currentPrompt = READY_PROMPT; + setText(_currentPrompt); + return; + } + + // check for printed key + aKey = ( aKey < Key_Space || aKey > Key_ydiaeresis ) ? aKey : 0; + + switch ( aKey ) { + case 0 : + // any printed key + { + if ( curLine < endLine || curCol < PROMPT_SIZE ) + moveCursor( QTextEdit::MoveEnd, false ); + QTextEdit::keyPressEvent( e ); + break; + } + case Key_Return: + case Key_Enter: + // key + { + moveCursor( QTextEdit::MoveEnd, false ); + QTextEdit::keyPressEvent( e ); + break; + } + case Key_Up: + // arrow key: process as follows: + // - without , modifiers: previous command in history + // - with modifier key pressed: move cursor one row up without selection + // - with modifier key pressed: move cursor one row up with selection + // - with + modifier keys pressed: scroll one row up + { + if ( ctrlPressed && shftPressed ) { + scrollBy( 0, -QFontMetrics( font() ).lineSpacing() ); + } + else if ( shftPressed ) { + if ( curLine > 0 ) + moveCursor( QTextEdit::MoveUp, true ); + } + else if ( ctrlPressed ) { + moveCursor( QTextEdit::MoveUp, false ); + } + else { + QString histLine = _currentPrompt; + if ( ! _isInHistory ) { + _isInHistory = true; + _currentCommand = text( endLine ).remove( 0, PROMPT_SIZE ); + _currentCommand.truncate( _currentCommand.length() - 1 ); + } + QString previousCommand = myInterp->getPrevious(); + if ( previousCommand.compare( BEGIN_HISTORY_PY ) != 0 ) + { + removeParagraph( endLine ); + histLine.append( previousCommand ); + append( histLine ); + } + moveCursor( QTextEdit::MoveEnd, false ); + } + break; + } + case Key_Down: + // arrow key: process as follows: + // - without , modifiers: next command in history + // - with modifier key pressed: move cursor one row down without selection + // - with modifier key pressed: move cursor one row down with selection + // - with + modifier keys pressed: scroll one row down + { + if ( ctrlPressed && shftPressed ) { + scrollBy( 0, QFontMetrics( font() ).lineSpacing() ); + } + else if ( shftPressed ) { + if ( curLine < endLine ) + moveCursor( QTextEdit::MoveDown, true ); + } + else if ( ctrlPressed ) { + moveCursor( QTextEdit::MoveDown, false ); + } + else { + QString histLine = _currentPrompt; + QString nextCommand = myInterp->getNext(); + if ( nextCommand.compare( TOP_HISTORY_PY ) != 0 ) { + removeParagraph( endLine ); + histLine.append( nextCommand ); + append( histLine ); + } + else { + if (_isInHistory) { + _isInHistory = false; + removeParagraph( endLine ); + histLine.append( _currentCommand ); + append( histLine ); + } + } + moveCursor( QTextEdit::MoveEnd, false ); + } + break; + } + case Key_Left: + // arrow key: process as follows: + // - without , modifiers: move one symbol left (taking into account prompt) + // - with modifier key pressed: move one word left (taking into account prompt) + // - with modifier key pressed: move one symbol left with selection + // - with + modifier keys pressed: move one word left with selection + { + if ( !shftPressed && isCommand( text( curLine ) ) && curCol <= PROMPT_SIZE ) { + setCursorPosition( curLine-1, 0 ); + moveCursor( QTextEdit::MoveLineEnd, false ); + } + else { + QTextEdit::keyPressEvent( e ); + } + break; + } + case Key_Right: + // arrow key: process as follows: + // - without , modifiers: move one symbol right (taking into account prompt) + // - with modifier key pressed: move one word right (taking into account prompt) + // - with modifier key pressed: move one symbol right with selection + // - with + modifier keys pressed: move one word right with selection + { + if ( !shftPressed ) { + if ( curCol < paragraphLength( curLine ) ) { + if ( isCommand( text( curLine ) ) && curCol < PROMPT_SIZE ) { + setCursorPosition( curLine, PROMPT_SIZE ); + break; + } + } + else { + if ( curLine < endLine && isCommand( text( curLine+1 ) ) ) { + setCursorPosition( curLine+1, PROMPT_SIZE ); + break; + } + } + } + QTextEdit::keyPressEvent( e ); + break; + } + case Key_PageUp: + // key: process as follows: + // - without , modifiers: first command in history + // - with modifier key pressed: move cursor one page up without selection + // - with modifier key pressed: move cursor one page up with selection + // - with + modifier keys pressed: scroll one page up + { + if ( ctrlPressed && shftPressed ) { + scrollBy( 0, -visibleHeight() ); + } + else if ( shftPressed ) { + if ( curLine > 0 ) + moveCursor( QTextEdit::MovePgUp, true ); + } + else if ( ctrlPressed ) { + moveCursor( QTextEdit::MovePgUp, false ); + } + else { + QString histLine = _currentPrompt; + if ( ! _isInHistory ) { + _isInHistory = true; + _currentCommand = text( endLine ).remove( 0, PROMPT_SIZE ); + _currentCommand.truncate( _currentCommand.length() - 1 ); + } + QString firstCommand = myInterp->getPrevious(); + QString pcmd; + while ( ( pcmd = QString( myInterp->getPrevious() ) ).compare( BEGIN_HISTORY_PY ) != 0 ) + firstCommand = pcmd; + if ( firstCommand.compare( BEGIN_HISTORY_PY ) != 0 ) { + removeParagraph( endLine ); + histLine.append( firstCommand ); + insertParagraph( histLine, -1 ); + } + moveCursor( QTextEdit::MoveEnd, false ); + } + break; + } + case Key_PageDown: + // key: process as follows: + // - without , modifiers: last command in history + // - with modifier key pressed: move cursor one page down without selection + // - with modifier key pressed: move cursor one page down with selection + // - with + modifier keys pressed: scroll one page down + { + if ( ctrlPressed && shftPressed ) { + scrollBy( 0, visibleHeight() ); + } + else if ( shftPressed ) { + if ( curLine < endLine ) + moveCursor( QTextEdit::MovePgDown, true ); + } + else if ( ctrlPressed ) { + moveCursor( QTextEdit::MovePgDown, false ); + } + else { + if ( _isInHistory ) { + QString histLine = _currentPrompt; + while ( QString( myInterp->getNext() ).compare( TOP_HISTORY_PY ) != 0 ); + _isInHistory = false; + removeParagraph( endLine ); + histLine.append( _currentCommand ); + insertParagraph( histLine, -1 ); + } + moveCursor( QTextEdit::MoveEnd, false ); + } + break; + } + case Key_Home: + // key: process as follows: + // - without , modifiers: move cursor to the beginning of the current line without selection + // - with modifier key pressed: move cursor to the very first symbol without selection + // - with modifier key pressed: move cursor to the beginning of the current line with selection + // - with + modifier keys pressed: move cursor to the very first symbol with selection + { + if ( ctrlPressed ) { + moveCursor( QTextEdit::MoveHome, shftPressed ); + } + else { + if ( isCommand( text( curLine ) ) ) { + int ps1, ps2, cs1, cs2; + bool hasSelection = hasSelectedText(); + if ( hasSelection ) + getSelection( &ps1, &cs1, &ps2, &cs2 ); + removeSelection(); + horizontalScrollBar()->setValue( horizontalScrollBar()->minValue() ); + if ( curCol > PROMPT_SIZE && shftPressed ) + setSelection( curLine, PROMPT_SIZE, curLine, ( hasSelection && ps1 == ps2 && ps1 == curLine && cs2 > PROMPT_SIZE ) ? cs2 : curCol ); + setCursorPosition( curLine, PROMPT_SIZE ); + } + else { + moveCursor( QTextEdit::MoveLineStart, shftPressed ); + } + } + break; + } + case Key_End: + // key: process as follows: + // - without , modifiers: move cursor to the end of the current line without selection + // - with modifier key pressed: move cursor to the very last symbol without selection + // - with modifier key pressed: move cursor to the end of the current line with selection + // - with + modifier keys pressed: move cursor to the very last symbol with selection + { + if ( ctrlPressed ) { + moveCursor( QTextEdit::MoveEnd, shftPressed ); + } + else { + moveCursor( QTextEdit::MoveLineEnd, shftPressed ); + } + break; + } + case Key_Backspace : + // key: process as follows + // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt) + // - with modifier key pressed: delete previous word + // works only for last (command) line + { + if ( curLine == endLine && ( curCol > PROMPT_SIZE || curCol >= PROMPT_SIZE && hasSelectedText() ) ) { + if ( ctrlPressed && !hasSelectedText() ) { + QString txt = text( curLine ); + int ind = curCol-1; + while ( ind > 0 && txt[ ind ] == ' ' ) ind--; + ind = txt.findRev( ' ', ind ) + 1; + if ( ind > PROMPT_SIZE-1 ) { + setSelection( curLine, ind, curLine, curCol ); + removeSelectedText(); + } + else { + QTextEdit::keyPressEvent( e ); + } + } + else { + QTextEdit::keyPressEvent( e ); + } + } + break; + } + case Key_Delete : + // key: process as follows + // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt) + // - with modifier key pressed: delete next word + // works only for last (command) line + { + if ( curLine == endLine && curCol > PROMPT_SIZE-1 ) { + if ( ctrlPressed && !hasSelectedText() ) { + QString txt = text( curLine ); + int ind = curCol; + while ( ind < txt.length()-1 && txt[ ind ] == ' ' ) ind++; + ind = txt.find( ' ', ind ); + while ( ind < txt.length()-1 && txt[ ind ] == ' ' ) ind++; + if ( ind > PROMPT_SIZE-1 ) { + setSelection( curLine, curCol, curLine, ind ); + removeSelectedText(); + } + else { + QTextEdit::keyPressEvent( e ); + } + } + else { + QTextEdit::keyPressEvent( e ); + } + } + break; + } + case Key_Insert : + // key: process as follows + // - with modifier key pressed: copy() + // - with modifier key pressed: paste() to the command line + { + if ( ctrlPressed ) { + copy(); + } + else if ( shftPressed ) { + if ( curLine != endLine || curCol < PROMPT_SIZE ) + moveCursor( QTextEdit::MoveEnd, false ); + paste(); + } + else + QTextEdit::keyPressEvent( e ); + break; + } + } +} + +/*! + Handles notifications coming from Python dispatcher +*/ +void PythonConsole_PyEditor::customEvent(QCustomEvent* e) +{ + switch( e->type() ) { + case PyInterp_Event::OK: + case PyInterp_Event::ERROR: + { + PyInterp_Event* pe = dynamic_cast( e ); + if ( pe ){ + ExecCommand* ec = dynamic_cast( pe->GetRequest() ); + if ( ec ){ + // The next line has appeared dangerous in case if + // Python command execution has produced very large output. + // A more clever approach is needed... + setText(ec->myOutput); + setText(ec->myError); + } + } + _buf.truncate(0); + _currentPrompt = READY_PROMPT; + setText(_currentPrompt); + viewport()->unsetCursor(); + break; + } + case PyInterp_Event::INCOMPLETE: + { + _buf.append("\n"); + _currentPrompt = DOTS_PROMPT; + setText(_currentPrompt); + viewport()->unsetCursor(); + break; + } + default: + QTextEdit::customEvent( e ); + } + + setReadOnly( false ); + _isInHistory = false; +} + +/*! + Handles Python interpreter change +*/ +void PythonConsole_PyEditor::onPyInterpChanged( PyInterp_base* interp ) +{ + if ( myInterp != interp + // Force read-only state and wait cursor when myInterp is NULL + || !myInterp ){ + myInterp = interp; + if ( myInterp ){ + myBanner = myInterp->getbanner().c_str(); + setText(myBanner); + _buf.truncate(0); + setReadOnly( false ); + _isInHistory = false; + setText(_currentPrompt); + viewport()->unsetCursor(); + } + else { + clear(); + setReadOnly( true ); + viewport()->setCursor( waitCursor ); + } + } +} + +QPopupMenu* PythonConsole_PyEditor::createPopupMenu( const QPoint& pos ) +{ + QPopupMenu* popup = QTextEdit::createPopupMenu( pos ); + + QValueList ids; + for ( int i = 0; popup && i < popup->count(); i++ ) + { + if ( !popup->isItemEnabled( popup->idAt( i ) ) ) + ids.append( popup->idAt( i ) ); + } + + for ( QValueList::const_iterator it = ids.begin(); it != ids.end(); ++it ) + popup->removeItem( *it ); + + SUIT_Tools::simplifySeparators( popup ); + + if ( !popup->count() ) + { + delete popup; + popup = 0; + } + + return popup; +} diff --git a/src/PythonConsole/PythonConsole_PyInterp.cxx b/src/PythonConsole/PythonConsole_PyInterp.cxx new file mode 100755 index 000000000..5b7d3e579 --- /dev/null +++ b/src/PythonConsole/PythonConsole_PyInterp.cxx @@ -0,0 +1,121 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : PythonConsole_PyInterp.cxx +// Author : Nicolas REJNERI +// Module : SALOME +// $Header$ + +#include "PythonConsole_PyInterp.h" +//#include "utilities.h" + +using namespace std; + + +//#ifdef _DEBUG_ +//static int MYDEBUG = 0; +//#else +//static int MYDEBUG = 0; +//#endif + + +/*! + * constructor : multi Python interpreter, one per SALOME study. + * calls initialize method defined in base class, which calls virtual methods + * initstate & initcontext redefined here. + */ +PythonConsole_PyInterp::PythonConsole_PyInterp(): PyInterp_base() +{ +} + +PythonConsole_PyInterp::~PythonConsole_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 PythonConsole_PyInterp::initState() +{ + /* + * The GIL is acquired and will be held on initState output + * It is the caller responsability to release the lock if needed + */ + PyEval_AcquireLock(); + _tstate = Py_NewInterpreter(); // create an interpreter and save current state + PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv +// if(MYDEBUG) MESSAGE("PythonConsole_PyInterp::initState - this = "<ob_refcnt); // builtinmodule reference counter + _tstate->interp->builtins = PyModule_GetDict(builtinmodule); + Py_INCREF(_tstate->interp->builtins); + } + PyEval_ReleaseThread(_tstate); + return true; +} + + +bool PythonConsole_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 + */ + PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context) + if(!m){ +// if(MYDEBUG) MESSAGE("problem..."); + PyErr_Print(); +// ASSERT(0); + return false; + } + _g = PyModule_GetDict(m); // get interpreter dictionnary context +// if(MYDEBUG) MESSAGE("PythonConsole_PyInterp::initContext - this = "< + +#include +#include + +#include +#include + +QValueList QDS::_datumList; + +QString QDS::toQString( const TCollection_AsciiString& src ) +{ + QTextCodec* codec = QTextCodec::codecForLocale(); + QString res; + if ( !src.IsEmpty() ) + res = codec ? codec->toUnicode( (char*)src.ToCString(), src.Length() ) : + QString( (char*)src.ToCString() ); + return res; +} + +QString QDS::toQString( const TCollection_ExtendedString& src ) +{ + if ( src.IsAscii() ) + return toQString( TCollection_AsciiString( src ) ); + else + return QString( (QChar*)src.ToExtString(), src.Length() ); +} + +QString QDS::toQString( const Handle(TCollection_HAsciiString)& src ) +{ + if ( src.IsNull() ) + return QString::null; + else + return toQString( src->String() ); +} + +QString QDS::toQString( const Handle(TCollection_HExtendedString)& src ) +{ + if ( src.IsNull() ) + return QString::null; + else + return toQString( src->String() ); +} + +TCollection_AsciiString QDS::toAsciiString( const QString& src ) +{ + TCollection_AsciiString res; + if ( src.latin1() ) + { + QTextCodec* codec = QTextCodec::codecForLocale(); + if ( codec ) + { + int len = -1; + QCString str = codec->fromUnicode( src, len ); + res = TCollection_AsciiString( (Standard_CString)(const char*)str, len ); + } + else + res = TCollection_AsciiString( (char*)src.latin1() ); + } + return res; +} + +TCollection_AsciiString QDS::toAsciiString( const TCollection_ExtendedString& src ) +{ + return TCollection_AsciiString( src ); +} + +TCollection_AsciiString QDS::toAsciiString( const Handle(TCollection_HExtendedString)& src ) +{ + TCollection_AsciiString res; + if ( !src.IsNull() ) + res = toAsciiString( src->String() ); + return res; +} + +TCollection_ExtendedString QDS::toExtString( const QString& src ) +{ + if ( src.isEmpty() ) + return TCollection_ExtendedString(); + + Standard_Integer len = src.length(); + Standard_ExtString extStr = new Standard_ExtCharacter[( len + 1 ) * 2]; + memcpy( extStr, src.unicode(), len * 2 ); + extStr[len] = 0; + + TCollection_ExtendedString trg( extStr ); + + delete [] extStr; + + return trg; +} + +TCollection_ExtendedString QDS::toExtString( const TCollection_AsciiString& src ) +{ + return TCollection_ExtendedString( src ); +} + +bool QDS::load( const QString& dictPath ) +{ + if ( dictPath.isEmpty() ) + return false; + + return DDS_Dictionary::Load( toAsciiString( dictPath ) ); +} + +QString QDS::unitSystemLabel( const QString& sys, const QString& comp ) +{ + QString lab; + TCollection_AsciiString system = toAsciiString( sys ); + Handle(DDS_Dictionary) dic = DDS_Dictionary::Get(); + if ( !dic.IsNull() ) + lab = toQString( comp.isEmpty() ? dic->GetUnitSystemLabel( system ) : + dic->GetUnitSystemLabel( system, toAsciiString( comp ) ) ); + return lab; +} + +QString QDS::activeUnitSystem( const QString& comp ) +{ + QString sys; + Handle(DDS_Dictionary) dic = DDS_Dictionary::Get(); + if ( !dic.IsNull() ) + sys = toQString( comp.isEmpty() ? dic->GetActiveUnitSystem() : + dic->GetActiveUnitSystem( toAsciiString( comp ) ) ); + return sys; +} + +void QDS::setActiveUnitSystem( const QString& sys, const QString& comp ) +{ + Handle(DDS_Dictionary) dic = DDS_Dictionary::Get(); + if ( dic.IsNull() ) + return; + + TCollection_AsciiString system = toAsciiString( sys ); + comp.isEmpty() ? dic->SetActiveUnitSystem( system ) : + dic->SetActiveUnitSystem( system, toAsciiString( comp ) ); + + QString unitSys = activeUnitSystem( comp ); + if ( sys == unitSys ) + return; + + TCollection_AsciiString aComp = toAsciiString( comp ); + for ( QValueList::iterator it = _datumList.begin(); it != _datumList.end(); ++it ) + { + QDS_Datum* datum = *it; + if ( !datum ) + continue; + + bool ok = aComp.IsEmpty(); + if ( !ok ) + { + Handle(DDS_DicItem) item = datum->dicItem(); + ok = !item.IsNull() && aComp == item->GetComponent(); + } + + if ( ok ) + datum->unitSystemChanged( unitSys ); + } +} + +void QDS::insertDatum( QDS_Datum* datum ) +{ + if ( !datum ) + return; + + _datumList.append( datum ); +} + +void QDS::removeDatum( QDS_Datum* datum ) +{ + if ( !datum ) + return; + + _datumList.remove( datum ); +} diff --git a/src/QDS/QDS.h b/src/QDS/QDS.h new file mode 100644 index 000000000..c9ff5edd0 --- /dev/null +++ b/src/QDS/QDS.h @@ -0,0 +1,66 @@ +#ifndef QDS_H +#define QDS_H + +#ifdef WIN32 +#ifdef QDS_EXPORTS +#define QDS_EXPORT __declspec(dllexport) +#else +#define QDS_EXPORT __declspec(dllimport) +#endif +#else +#define QDS_EXPORT +#endif + +#if defined WIN32 +#pragma warning ( disable:4251 ) +#pragma warning ( disable:4786 ) +#endif + +#include +#include + +#include + +#include + +class QDS_Datum; +class Handle(TCollection_HAsciiString); +class Handle(TCollection_HExtendedString); + +class QDS_EXPORT QDS +{ +public: + typedef enum { None = 0x00, Label = 0x01, Control = 0x02, Units = 0x04, + NotFormat = 0x08, NotAccel = 0x10, UnitsWithLabel = 0x20, + All = Label | Control | Units } DatumFlags; + +public: + static bool load( const QString& ); + + static QString unitSystemLabel( const QString&, + const QString& = QString::null ); + static QString activeUnitSystem( const QString& = QString::null ); + static void setActiveUnitSystem( const QString&, + const QString& = QString::null ); + + static QString toQString( const TCollection_AsciiString& ); + static QString toQString( const TCollection_ExtendedString& ); + static QString toQString( const Handle(TCollection_HAsciiString)& ); + static QString toQString( const Handle(TCollection_HExtendedString)& ); + + static TCollection_AsciiString toAsciiString( const QString& ); + static TCollection_AsciiString toAsciiString( const TCollection_ExtendedString& ); + static TCollection_AsciiString toAsciiString( const Handle(TCollection_HExtendedString)& ); + + static TCollection_ExtendedString toExtString( const QString& ); + static TCollection_ExtendedString toExtString( const TCollection_AsciiString& ); + +protected: + static void insertDatum( QDS_Datum* ); + static void removeDatum( QDS_Datum* ); + +private: + static QValueList _datumList; +}; + +#endif diff --git a/src/QDS/QDS_CheckBox.cxx b/src/QDS/QDS_CheckBox.cxx new file mode 100644 index 000000000..7f1924d97 --- /dev/null +++ b/src/QDS/QDS_CheckBox.cxx @@ -0,0 +1,76 @@ +#include "QDS_CheckBox.h" + +#include + +/*! + Constructor. This method is protected. Object can't be directly constructed. + Use static method QDS_CheckBox::Create instead. +*/ +QDS_CheckBox::QDS_CheckBox( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_CheckBox::~QDS_CheckBox() +{ +} + +/*! + Returns string from QCheckBox widget. +*/ +QString QDS_CheckBox::getString() const +{ + return checkBox() && checkBox()->isChecked() ? "1" : "0"; +} + +/*! + Sets the string into QCheckBox widget. +*/ +void QDS_CheckBox::setString( const QString& txt ) +{ + bool isOk; + int val = (int)txt.toDouble( &isOk ); + if ( checkBox() ) + checkBox()->setChecked( isOk && val != 0 ); +} + +/*! + Returns pointer to QCheckBox widget. +*/ +QCheckBox* QDS_CheckBox::checkBox() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QCheckBox widget as control subwidget. +*/ +QWidget* QDS_CheckBox::createControl( QWidget* parent ) +{ + QCheckBox* cb = new QCheckBox( parent ); + connect( cb, SIGNAL( stateChanged( int ) ), SLOT( onParamChanged() ) ); + connect( cb, SIGNAL( toggled( bool ) ), SIGNAL( toggled( bool ) ) ); + return cb; +} + +/*! + Notify about shanging of control state +*/ +void QDS_CheckBox::onParamChanged() +{ + emit paramChanged(); +} + +void QDS_CheckBox::setChecked( const bool theState ) +{ + if ( checkBox() ) + checkBox()->setChecked( theState ); +} + +bool QDS_CheckBox::isChecked() const +{ + return checkBox() ? checkBox()->isChecked() : false; +} diff --git a/src/QDS/QDS_CheckBox.h b/src/QDS/QDS_CheckBox.h new file mode 100644 index 000000000..7c04edaad --- /dev/null +++ b/src/QDS/QDS_CheckBox.h @@ -0,0 +1,33 @@ +#ifndef QDS_CHECKBOX_H +#define QDS_CHECKBOX_H + +#include "QDS_Datum.h" + +class QCheckBox; + +class QDS_EXPORT QDS_CheckBox : public QDS_Datum +{ + Q_OBJECT + +public: + QDS_CheckBox( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_CheckBox(); + + bool isChecked() const; + void setChecked( const bool ); + +signals: + void toggled( bool ); + +private slots: + void onParamChanged(); + +protected: + QCheckBox* checkBox() const; + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); +}; + +#endif diff --git a/src/QDS/QDS_ComboBox.cxx b/src/QDS/QDS_ComboBox.cxx new file mode 100644 index 000000000..f5e9ef80b --- /dev/null +++ b/src/QDS/QDS_ComboBox.cxx @@ -0,0 +1,563 @@ +#include "QDS_ComboBox.h" + +#include + +#include +#include +#include + +#include + +/*! + Constructor. +*/ +QDS_ComboBox::QDS_ComboBox( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_ComboBox::~QDS_ComboBox() +{ +} + +/*! + Returns true if ComboBox allow to edit current Text. +*/ +bool QDS_ComboBox::editable() const +{ + if ( comboBox() && comboBox()->lineEdit() ) + return !comboBox()->lineEdit()->isReadOnly(); + else + return false; +} + +/*! + Sets the possibily of current text editing. +*/ +void QDS_ComboBox::setEditable( const bool on ) +{ + QComboBox* aCombo = comboBox(); + if ( aCombo ) + aCombo->setEditable( on ); + if ( aCombo && aCombo->lineEdit() ) + { + aCombo->lineEdit()->setReadOnly( !on ); + aCombo->clearValidator(); + if ( on ) + aCombo->setValidator( validator() ); + } +} + +/*! + Returns number of items in ComboBox. If total is 'false' then only + visible items are taken into account otherwise all items. +*/ +int QDS_ComboBox::count( bool total ) const +{ + if ( total ) + return myValue.count(); + else if ( comboBox() ) + return comboBox()->count(); + else + return 0; +} + +/*! + Returns list of ids. If total is 'false' then only visible items + are taken into account otherwise all items. +*/ +void QDS_ComboBox::values( QValueList& ids, bool total ) const +{ + ids.clear(); + for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it ) + if ( total || ( myState.contains( *it ) && myState[*it] ) ) + ids.append( *it ); +} + +/*! + Returns the current id as integer. +*/ +int QDS_ComboBox::integerValue() const +{ + QComboBox* cb = comboBox(); + QString cur = getString(); + if ( cb && cb->count() > 0 && cb->currentItem() >= 0 ) + cur = cb->text( cb->currentItem() ); + + if ( cb && cur == getString() ) + return getId( cb->currentItem() ); + else + return getId( getString() ); +} + +/*! + Returns the current id as double. +*/ +double QDS_ComboBox::doubleValue() const +{ + QComboBox* cb = comboBox(); + QString cur = getString(); + if ( cb && cb->count() > 0 && cb->currentItem() >= 0 ) + cur = cb->text( cb->currentItem() ); + + if ( cb && cur == getString() ) + return getId( cb->currentItem() ); + else + return getId( getString() ); +} + +/*! + Set the current item acording to specified id. +*/ +void QDS_ComboBox::setIntegerValue( const int id ) +{ + if ( myValue.contains( id ) ) + setString( myValue[id] ); + else + setString( "" ); +} + +/*! + Get the integer part of specified value and use it as new current identifier. +*/ +void QDS_ComboBox::setDoubleValue( const double val ) +{ + int id = (int)val; + if ( myValue.contains( id ) ) + setString( myValue[id] ); + else if ( id == -1 ) + setString( "" ); +} + +/*! + Returns visible state of identificator. +*/ +bool QDS_ComboBox::state( const int id ) const +{ + bool state = false; + if ( myState.contains( id ) ) + state = myState[id]; + return state; +} + +/*! + Sets the visible state of identificator. If 'id' is -1 then specified + state will be set to all ids. +*/ +void QDS_ComboBox::setState( const bool on, const int id, const bool append ) +{ + QValueList lst; + if ( id < 0 ) + { + for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it ) + lst.append( it.key() ); + } + else + lst.append( id ); + + setState( on, lst, append ); +} + +/*! + Sets the visible state of identificator from the specified list. +*/ +void QDS_ComboBox::setState( const bool on, const QValueList& ids, const bool append ) +{ + if ( ids.isEmpty() && append ) + return; + + bool changed = false; + + QMap aMap; + for ( uint i = 0; i < ids.count(); i++ ) + aMap.insert( *ids.at( i ), 0 ); + + for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it ) + { + if ( aMap.contains( it.key() ) ) + { + if ( it.data() != on ) + { + it.data() = on; + changed = true; + } + } + else if ( !append && it.data() == on ) + { + it.data() = !on; + changed = true; + } + } + if ( changed ) + updateComboBox(); +} + +/*! + Sets the user items into the combo box. +*/ +void QDS_ComboBox::setValues( const QValueList& ids, const QStringList& names ) +{ + if ( ids.count() != names.count() ) + return; + + myUserIds = ids; + myUserNames = names; +} + +/*! + This is an overloaded member function, provided for convenience. + It behaves essentially like the above function. It creates + QValueList (0, 1, 2 ... ) and call previous method +*/ +void QDS_ComboBox::setValues( const QStringList& names ) +{ + QValueList< int > ids; + for ( int i = 0, n = names.count(); i < n; i++ ) + ids.append( i ); + setValues( ids, names ); +} + +/*! + Sets the active item as item with default id. If default + not defined then first item will be used. +*/ +void QDS_ComboBox::reset() +{ + int id = -1; + QString aDefValue = defaultValue(); + if ( !aDefValue.isEmpty() ) + id = aDefValue.toInt(); + + if ( id == -1 ) + id = getId( 0 ); + + setIntegerValue( id ); +} + +/*! + Returns identifier from given ComboBox string item. +*/ +int QDS_ComboBox::stringToValue( const QString& str ) const +{ + return getId( str ); +} + +/*! + Returns ComboBox string item from given identifier. +*/ +QString QDS_ComboBox::valueToString( const int val ) const +{ + QString str; + if ( myValue.contains( val ) ) + str = myValue[val]; + return str; +} + +/*! + Returns string from QLineEdit widget. +*/ +QString QDS_ComboBox::getString() const +{ + QString res; + QtxComboBox* cb = comboBox(); + if ( cb ) + { + if ( !cb->editable() ) + { + if ( !cb->isCleared() ) + res = cb->currentText(); + } + else + res = cb->lineEdit()->text(); + } + return res; +} + +/*! + Sets the string into QLineEdit widget. +*/ +void QDS_ComboBox::setString( const QString& txt ) +{ + QtxComboBox* cb = comboBox(); + if ( !cb ) + return; + + bool isClear = cb->isCleared(); + + int idx = -1; + for ( int i = 0; i < cb->count() && idx == -1; i++ ) + if ( cb->text( i ) == txt ) + idx = i; + + int old = cb->currentItem(); + if ( idx != -1 ) + cb->setCurrentItem( idx ); + else if ( txt.isEmpty() ) + { + if ( !cb->editable() ) + cb->setCurrentText( txt ); + else + cb->lineEdit()->setText( txt ); + } + if ( isClear != txt.isEmpty() || ( !isClear && old != cb->currentItem() ) ) + { + onParamChanged(); + QString str = getString(); + emit activated( integerValue() ); + emit activated( str ); + emit paramChanged(); + emit paramChanged( str ); + } +} + +/*! + Returns pointer to QtxComboBox widget. +*/ +QtxComboBox* QDS_ComboBox::comboBox() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QComboBox widget as control subwidget. +*/ +QWidget* QDS_ComboBox::createControl( QWidget* parent ) +{ + QtxComboBox* cb = new QtxComboBox( parent ); + cb->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ) ); + connect( cb, SIGNAL( textChanged( const QString& ) ), this, + SLOT( onTextChanged( const QString& ) ) ); + connect( cb, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) ); + return cb; +} + +void QDS_ComboBox::unitSystemChanged( const QString& system ) +{ + QDS_Datum::unitSystemChanged( system ); + + Handle(TColStd_HArray1OfInteger) anIds; + Handle(TColStd_HArray1OfExtendedString) aValues, anIcons; + + Handle(DDS_DicItem) aDicItem = dicItem(); + if ( !aDicItem.IsNull() ) + aDicItem->GetListOfValues( aValues, anIds, anIcons ); + + myValue.clear(); + myIcons.clear(); + myDataIds.clear(); + + QMap userMap; + QIntList::iterator iIt = myUserIds.begin(); + QStringList::iterator sIt = myUserNames.begin(); + for ( ; iIt != myUserIds.end() && sIt != myUserNames.end(); ++iIt, ++sIt ) + userMap.insert( *iIt, *sIt ); + + if ( !anIds.IsNull() && !aValues.IsNull() && + anIds->Length() == aValues->Length() ) + { + for ( int i = anIds->Lower(); i <= anIds->Upper(); i++ ) + { + QString aValue; + QPixmap aPixmap; + int id = anIds->Value( i ); + if ( userMap.contains( id ) ) + aValue = userMap[id]; + else + { + aValue = toQString( aValues->Value( i ) ); + if ( !anIcons.IsNull() && i <= anIcons->Upper() ) + { + QString anIconId = toQString( anIcons->Value( i ) ); + if ( anIconId != "" ) + aPixmap = QPixmap( anIconId ); + } + } + + myDataIds.append( id ); + myValue.insert( id, aValue ); + myState.insert( id, true ); + if ( !aPixmap.isNull() ) + myIcons.insert( id, aPixmap ); + } + } + + for ( iIt = myUserIds.begin(); iIt != myUserIds.end(); ++iIt ) + { + int id = *iIt; + if ( !myValue.contains( id ) ) + { + myDataIds.append( id ); + myValue.insert( id, userMap[id] ); + } + } + + QIntList del, add; + for ( IdStateMap::Iterator it1 = myState.begin(); it1 != myState.end(); ++it1 ) + if ( !myValue.contains( it1.key() ) ) + del.append( it1.key() ); + + for ( IdValueMap::Iterator it2 = myValue.begin(); it2 != myValue.end(); ++it2 ) + if ( !myState.contains( it2.key() ) ) + add.append( it2.key() ); + + for ( QIntList::iterator iter1 = del.begin(); iter1 != del.end(); ++iter1 ) + myState.remove( *iter1 ); + + for ( QIntList::iterator iter2 = add.begin(); iter2 != add.end(); ++iter2 ) + myState.insert( *iter2, true ); + + updateComboBox(); +} + +/*! + Notify about text changing in line edit of ComboBox. +*/ +void QDS_ComboBox::onTextChanged( const QString& ) +{ + onParamChanged(); + emit paramChanged(); + QString str = getString(); + emit paramChanged( str ); +} + +/*! + Notify about activation new item. +*/ +void QDS_ComboBox::onActivated( int idx ) +{ + if ( comboBox() ) + comboBox()->setCurrentItem( comboBox()->currentItem() ); + + int id = getId( idx ); + if ( id != -1 ) + { + onParamChanged(); + QString str = getString(); + emit activated( id ); + emit activated( str ); + emit paramChanged(); + emit paramChanged( str ); + } +} + +/*! + Updates ComboBox after have change of visible state or items have been inserted / removed. +*/ +void QDS_ComboBox::updateComboBox() +{ + QtxComboBox* cb = comboBox(); + + int curId = -1; + + bool isClear = false; + + if ( cb ) + { + isClear = cb->isCleared(); + + curId = getId( cb->currentItem() ); + cb->clear(); + } + + myIndex.clear(); + + int idx = 0; + for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it ) + { + int id = *it; + if ( !myValue.contains( id ) || !myState.contains( id ) || !myState[id] ) + continue; + + myIndex.insert( id, idx++ ); + if ( cb ) + { + if ( myIcons.contains( id ) ) + cb->insertItem( myIcons[id], myValue[id] ); + else + cb->insertItem( myValue[id] ); + } + } + + if ( cb && cb->count() ) + { + cb->setFont( cb->font() ); + cb->updateGeometry(); + + if ( isClear ) + cb->setCurrentText( "" ); + else + { + if ( getIndex( curId ) != -1 ) + cb->setCurrentItem( getIndex( curId ) ); + if ( curId != getId( cb->currentItem() ) ) + onActivated( cb->currentItem() ); + } + } +} + +/*! + Returns index of ComboBox item according to id. +*/ +int QDS_ComboBox::getIndex( const int id ) const +{ + int idx = -1; + if ( myIndex.contains( id ) ) + idx = myIndex[id]; + return idx; +} + +/*! + Returns index of ComboBox item according to string. +*/ +int QDS_ComboBox::getIndex( const QString& str ) const +{ + int idx = -1; + QComboBox* cb = comboBox(); + if ( cb ) + { + for ( int i = 0; i < cb->count() && idx == -1; i++ ) + if ( cb->text( i ) == str ) + idx = i; + } + return idx; +} + +/*! + Returns id according to ComboBox item index. +*/ +int QDS_ComboBox::getId( const int idx ) const +{ + int id = -1; + IdIndexMap::ConstIterator it = myIndex.begin(); + for (; it != myIndex.end() && id == -1; ++it ) + if ( it.data() == idx ) + id = it.key(); + return id; +} + +/*! + Returns id according to ComboBox item string. +*/ +int QDS_ComboBox::getId( const QString& str ) const +{ + int id = -1; + int candidate = -1; + IdValueMap::ConstIterator it = myValue.begin(); + for (; it != myValue.end() && id == -1; ++it ) + { + if ( it.data() == str ) + { + if ( state( it.key() ) ) + id = it.key(); + else + candidate = it.key(); + } + } + if ( id == -1 ) + id = candidate; + + return id; +} diff --git a/src/QDS/QDS_ComboBox.h b/src/QDS/QDS_ComboBox.h new file mode 100644 index 000000000..9650f4c58 --- /dev/null +++ b/src/QDS/QDS_ComboBox.h @@ -0,0 +1,92 @@ +#ifndef QDS_COMBOBOX_H +#define QDS_COMBOBOX_H + +#include "QDS_Datum.h" + +#include +#include +#include + +#include + +#ifdef WNT +#pragma warning( disable:4251 ) +#endif + +class QDS_EXPORT QDS_ComboBox : public QDS_Datum +{ + Q_OBJECT + +public: + QDS_ComboBox( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_ComboBox(); + + bool editable() const; + void setEditable( const bool ); + + int count( bool = false ) const; + void values( QValueList&, bool = false ) const; + + virtual int integerValue() const; + virtual double doubleValue() const; + virtual void setIntegerValue( const int ); + virtual void setDoubleValue( const double ); + + bool state( const int ) const; + void setState( const bool, const int, const bool = true ); + void setState( const bool, const QValueList&, const bool = true ); + void setValues( const QValueList&, const QStringList& ); + void setValues( const QStringList& ); + + virtual void reset(); + + int stringToValue( const QString& ) const; + QString valueToString( const int ) const; + +signals: + void activated( int ); + void activated( const QString& ); + +protected slots: + virtual void onActivated( int ); + virtual void onTextChanged( const QString& ); + +protected: + QtxComboBox* comboBox() const; + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); + + virtual void unitSystemChanged( const QString& ); + +private: + int getId( const int ) const; + int getId( const QString& ) const; + int getIndex( const int ) const; + int getIndex( const QString& ) const; + + void updateComboBox(); + +private: + typedef QMap IdIconsMap; + typedef QMap IdValueMap; + typedef QMap IdStateMap; + typedef QMap IdIndexMap; + +private: + IdValueMap myValue; + IdStateMap myState; + IdIndexMap myIndex; + IdIconsMap myIcons; + + QIntList myDataIds; + QIntList myUserIds; + QStringList myUserNames; +}; + +#ifdef WNT +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/QDS/QDS_Datum.cxx b/src/QDS/QDS_Datum.cxx new file mode 100644 index 000000000..ff3ed8aca --- /dev/null +++ b/src/QDS/QDS_Datum.cxx @@ -0,0 +1,1383 @@ +#include "QDS_Datum.h" + +#include "QDS_Validator.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/*! + Class: QDS_Datum::Wrapper + Descr: Wrapper widget for sub widgets. [internal] +*/ + +class QDS_Datum::Wrapper : public QWidget +{ +public: + Wrapper( QWidget* = 0 ); + virtual ~Wrapper(); + + QWidget* widget() const; + void setWidget( QWidget* ); + + virtual bool eventFilter( QObject*, QEvent* ); + +protected: + virtual void resizeEvent( QResizeEvent* ); + +private: + QWidget* myWid; +}; + + +QDS_Datum::Wrapper::Wrapper( QWidget* parent ) +: QWidget( parent ), +myWid( 0 ) +{ + QHBoxLayout* base = new QHBoxLayout( this ); + base->setAutoAdd( true ); +} + +QDS_Datum::Wrapper::~Wrapper() +{ +} + +QWidget* QDS_Datum::Wrapper::widget() const +{ + return myWid; +} + +void QDS_Datum::Wrapper::setWidget( QWidget* wid ) +{ + if ( myWid == wid ) + return; + + if ( myWid ) + myWid->removeEventFilter( this ); + + myWid = wid; + + if ( !myWid ) + return; + + if ( myWid->parent() != this ) + myWid->reparent( this, QPoint( 0, 0 ) ); + + setFocusProxy( myWid ); + + myWid->updateGeometry(); + updateGeometry(); + + myWid->installEventFilter( this ); +} + +bool QDS_Datum::Wrapper::eventFilter( QObject* o, QEvent* e ) +{ + if ( e->type() == QEvent::Resize && o == widget() ) + { + QResizeEvent* re = (QResizeEvent*)e; + if ( re->size() != size() ) + resize( re->size() ); + } + return QWidget::eventFilter( o, e ); +} + +void QDS_Datum::Wrapper::resizeEvent( QResizeEvent* e ) +{ + QWidget::resizeEvent( e ); + + if ( widget() && widget()->size() != size() ) + widget()->resize( size() ); +} + +/*! + Class: QDS_Datum + Descr: Base class for control used data dictionary. [public] +*/ + +QDS_Datum::QDS_Datum( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QObject( parent ), +myId( id ), +myLabel( 0 ), +myUnits( 0 ), +myControl( 0 ), +myFlags( flags ), +myInitialised( false ) +{ + if ( myFlags & Label ) + myWrapper.insert( Label, new Wrapper( parent ) ); + if ( myFlags & Control ) + myWrapper.insert( Control, new Wrapper( parent ) ); + if ( myFlags & Units ) + myWrapper.insert( Units, new Wrapper( parent ) ); + + for ( QMap::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it ) + connect( it.data(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + + Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get(); + if ( aDict.IsNull() ) + return; + + TCollection_AsciiString anId = toAsciiString( id ); + TCollection_AsciiString aComp = toAsciiString( comp ); + + if ( aComp.IsEmpty() ) + setDicItem( aDict->GetDicItem( anId ) ); + else + setDicItem( aDict->GetDicItem( anId, aComp ) ); + + QTimer::singleShot( 0, this, SLOT( onInitDatum() ) ); + + if ( parent ) + parent->installEventFilter( this ); + + insertDatum( this ); +} + +QDS_Datum::~QDS_Datum() +{ + removeDatum( this ); + + delete myLabel; + delete myUnits; + delete myControl; +/* + for ( QMap::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it ) + delete it.data(); +*/ +} + +QString QDS_Datum::id() const +{ + initDatum(); + + return myId; +} + +int QDS_Datum::type() const +{ + initDatum(); + + int res = DDS_DicItem::Unknown; + if ( !myDicItem.IsNull() ) + res = myDicItem->GetType(); + return res; +} + +QString QDS_Datum::label() const +{ + initDatum(); + + QString labStr; + if ( !myDicItem.IsNull() ) + labStr = toQString( myDicItem->GetLabel() ); + + if ( flags() & NotAccel ) + labStr = removeAccel( labStr ); + + return labStr; +} + +QString QDS_Datum::units() const +{ + initDatum(); + + QString unitStr; + if ( !myDicItem.IsNull() ) + unitStr = toQString( myDicItem->GetUnits() ); + return unitStr; +} + +QString QDS_Datum::filter() const +{ + initDatum(); + + QString fltr; + if ( !myDicItem.IsNull() ) + fltr = toQString( myDicItem->GetFilter() ); + return fltr; +} + +QString QDS_Datum::format() const +{ + initDatum(); + + QString fmtStr; + if ( !myDicItem.IsNull() ) + fmtStr = toQString( myDicItem->GetFormat( false ) ); + return fmtStr; +} + +QString QDS_Datum::defaultValue() const +{ + initDatum(); + + QString pref = prefix(); + QString suff = suffix(); + + QString def; + if ( !myDicItem.IsNull() ) + def = toQString( myDicItem->GetDefaultValue() ); + + QString aDef = def.stripWhiteSpace(); + if ( !pref.isEmpty() && aDef.left( pref.length() ) == pref ) + aDef = aDef.mid( pref.length() ); + + if ( !suff.isEmpty() && aDef.right( suff.length() ) == suff ) + aDef = aDef.mid( 0, aDef.length() - suff.length() ); + + return aDef; +} + +QString QDS_Datum::minimumValue() const +{ + initDatum(); + + QString min; + if ( !myDicItem.IsNull() ) + min = format( format(), type(), myDicItem->GetMinValue() ); + return min; +} + +QString QDS_Datum::maximumValue() const +{ + initDatum(); + + QString max; + if ( !myDicItem.IsNull() ) + max = format( format(), type(), myDicItem->GetMaxValue() ); + return max; +} + +QString QDS_Datum::longDescription() const +{ + initDatum(); + + QString ldStr; + if ( !myDicItem.IsNull() ) + ldStr = toQString( myDicItem->GetLongDescription() ); + return ldStr; +} + +QString QDS_Datum::shortDescription() const +{ + initDatum(); + + QString sdStr; + if ( !myDicItem.IsNull() ) + sdStr = toQString( myDicItem->GetLongDescription() ); + return sdStr; +} + +QString QDS_Datum::stringValue() const +{ + initDatum(); + + if ( getString() == myTargetValue ) + return mySourceValue; + else + return getString(); +} + +double QDS_Datum::doubleValue() const +{ + initDatum(); + + double res = 0; + if ( !myTargetValue.isNull() && myTargetValue == getString() ) + res = mySourceValue.toDouble(); + else + { + res = getString().toDouble(); + if ( !myDicItem.IsNull() ) + res = myDicItem->ToSI( res ); + } + + return res; +} + +int QDS_Datum::integerValue() const +{ + initDatum(); + + int res = 0; + if ( !myTargetValue.isNull() && myTargetValue == getString() ) + res = mySourceValue.toInt(); + else + { + double val = getString().toDouble(); + if ( !myDicItem.IsNull() ) + res = (int)myDicItem->ToSI( val ); + } + + return res; +} + +QString QDS_Datum::text() const +{ + initDatum(); + + QString aLabel = label(); + QString aData = stringValue(); + QString aUnits = units(); + + QString res = aLabel; + if ( !res.isEmpty() && !aData.isEmpty() ) + res += QString( ": " ); + + res += aData; + if ( !aUnits.isEmpty() ) + res += QString( " " ) + aUnits; + + return res; +} + +bool QDS_Datum::isEmpty() const +{ + return stringValue().isEmpty(); +} + +void QDS_Datum::reset() +{ + initDatum(); + + mySourceValue = defaultValue(); + setString( format( ( myFlags & NotFormat ) ? (QString) "" : format(), type(), mySourceValue ) ); + invalidateCache(); + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); +} + +void QDS_Datum::clear() +{ + initDatum(); + + if ( !getString().isEmpty() ) + { + mySourceValue = ""; + setString( mySourceValue ); + invalidateCache(); + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); + } +} + +void QDS_Datum::setStringValue( const QString& txt ) +{ + initDatum(); + + mySourceValue = txt; + QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), txt ); + setString( aStr ); + myTargetValue = aStr; + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); +} + +void QDS_Datum::setDoubleValue( const double num ) +{ + initDatum(); + + mySourceValue = QString().setNum( num, 'g', 16 ); + double val = num; + if ( !myDicItem.IsNull() ) + val = myDicItem->FromSI( val ); + + QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val ); + setString( aStr ); + myTargetValue = aStr; + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); +} + +void QDS_Datum::setIntegerValue( const int num ) +{ + initDatum(); + + mySourceValue = QString().setNum( num ); + double val = num; + if ( !myDicItem.IsNull() ) + val = myDicItem->FromSI( val ); + + QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val ); + setString( aStr ); + myTargetValue = aStr; + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); +} + +/*! + Returns true if all subwidgets specified by 'element' enabled. +*/ +bool QDS_Datum::isEnabled( const int element ) const +{ + initDatum(); + + bool res = true; + if ( element & Label ) + res = res && labelWidget() && labelWidget()->isEnabled(); + if ( element & Units ) + res = res && unitsWidget() && unitsWidget()->isEnabled(); + if ( element & Control ) + res = res && controlWidget() && controlWidget()->isEnabled(); + return res; +} + +/*! + Enable/Disable subwidgets specified by 'element'. + Values: Label, Control, Units or their combinations. +*/ +void QDS_Datum::setEnabled( const bool on, const int element ) +{ + initDatum(); + + if ( element & Label && labelWidget() ) + labelWidget()->setEnabled( on ); + if ( element & Units && unitsWidget() ) + unitsWidget()->setEnabled( on ); + if ( element & Control && controlWidget() ) + controlWidget()->setEnabled( on ); +} + +/*! + Enable/Disable control. +*/ +void QDS_Datum::setEnabled( bool on ) +{ + setEnabled( on, Control ); +} + +void QDS_Datum::setShown( const bool visible, const int flags ) +{ + if ( visible ) + show( flags ); + else + hide( flags ); +} + +/*! + Show subwidgets specified by 'element'. + Values: Label, Control, Units or their combinations. +*/ +void QDS_Datum::show( const int element ) +{ + initDatum(); + + if ( ( element & Label ) && labelWidget() ) + labelWidget()->show(); + if ( ( element & Units ) && unitsWidget() ) + unitsWidget()->show(); + if ( ( element & Control ) && controlWidget() ) + controlWidget()->show(); +} + +/*! + Hide subwidgets specified by 'element'. + Values: Label, Control, Units or their combinations. +*/ +void QDS_Datum::hide( const int element ) +{ + initDatum(); + + if ( ( element & Label ) && labelWidget() ) + labelWidget()->hide(); + if ( ( element & Units ) && unitsWidget() ) + unitsWidget()->hide(); + if ( ( element & Control ) && controlWidget() ) + controlWidget()->hide(); +} + +/*! + Returns subwidget specified by 'element'. + Possible values: Label, Control, Units. +*/ +QWidget* QDS_Datum::widget( const int element ) const +{ + initDatum(); + return wrapper( element ); +} + +/*! + Set the input focus on the control widget. +*/ +void QDS_Datum::setFocus() +{ + initDatum(); + + if ( controlWidget() ) + controlWidget()->setFocus(); +} + +/*! + Returns true if control contains valid value otherwise returns false + and display warning message box if parameter msgBox is set. +*/ +bool QDS_Datum::isValid( const bool msgBox, const QString& extMsg, const QString& extLabel ) const +{ + initDatum(); + + if ( type() == DDS_DicItem::String && isDoubleFormat( format() ) ) + return true; + + bool aState = true; + QString aStr = getString(); + if ( aStr.isEmpty() ) + aState = false; + else + aState = validate( aStr ); + + if ( msgBox && !aState ) + { + QString info; + if ( !label().isEmpty() ) + info += tr( "DATA_INCORRECT_VALUE" ).arg( label() ); + else if ( !extLabel.isEmpty() ) + info += tr( "DATA_INCORRECT_VALUE" ).arg( extLabel ); + + QString typeStr; + switch ( type() ) + { + case DDS_DicItem::String: + typeStr = tr( "DATA_STRING" ); + break; + case DDS_DicItem::Integer: + typeStr = tr( "DATA_INTEGER" ); + break; + case DDS_DicItem::Float: + typeStr = tr( "DATA_FLOAT" ); + break; + default: + typeStr = tr( "DATA_NON_EMPTY" ); + break; + } + info += ( info.isEmpty() ? (QString) "" : QString( "\n" ) ) + + tr( "DATA_SHOULD_BE_VALUE" ).arg( typeStr ); + QString limit; + if ( type() == DDS_DicItem::Float || type() == DDS_DicItem::Integer ) + { + QString aMinValue = minValue(); + QString aMaxValue = maxValue(); + if ( !aMinValue.isEmpty() && !aMaxValue.isEmpty() ) + limit = tr( "DATA_RANGE" ).arg( aMinValue ).arg( aMaxValue ); + else if ( !aMinValue.isEmpty() ) + limit = tr( "DATA_MIN_LIMIT" ).arg( aMinValue ); + else if ( !aMaxValue.isEmpty() ) + limit = tr( "DATA_MAX_LIMIT" ).arg( aMaxValue ); + } + if ( !limit.isEmpty() ) + info += limit; + + info += QString( ".\n" ) + tr( "DATA_INPUT_VALUE" ); + + if ( !extMsg.isEmpty() ) + info += QString( "\n" ) + extMsg; + + QString msg; + for ( uint i = 0; i < info.length(); i++ ) + if ( info.at( i ) == '\n' ) + msg += QString( "
" ); + else + msg += info.at( i ); + + info = QString( "

%1

" ).arg( msg ); + + QMessageBox::critical( controlWidget() ? controlWidget()->topLevelWidget() : 0, + tr( "DATA_ERR_TITLE" ), info, tr( "BUT_OK" ) ); + if ( controlWidget() ) + controlWidget()->setFocus(); + } + return aState; +} + +/*! + Add widgets to the vertical layout. +*/ +void QDS_Datum::addTo( QVBoxLayout* l ) +{ + initDatum(); + + if ( !l ) + return; + + if ( wrapper( Label ) ) + l->addWidget( wrapper( Label ) ); + if ( wrapper( Control ) ) + l->addWidget( wrapper( Control ) ); + if ( wrapper( Units ) ) + l->addWidget( wrapper( Units ) ); +} + +/*! + Add widgets to the horizaontal layout. +*/ +void QDS_Datum::addTo( QHBoxLayout* l ) +{ + initDatum(); + + if ( !l ) + return; + + if ( wrapper( Label ) ) + l->addWidget( wrapper( Label ) ); + if ( wrapper( Control ) ) + l->addWidget( wrapper( Control ) ); + if ( wrapper( Units ) ) + l->addWidget( unitsWidget() ); +} + +/*! + Add widgets to the grid layout. +*/ +void QDS_Datum::addTo( QGridLayout* theLay, const int theRow, const int theCol, bool vertical ) +{ + initDatum(); + + if ( !theLay ) + return; + + int row = theRow; + int col = theCol; + if ( wrapper( Label ) ) + { + theLay->addWidget( wrapper( Label ), row, col ); + vertical ? row++ : col++; + } + if ( wrapper( Control ) ) + { + theLay->addWidget( wrapper( Control ), row, col ); + vertical ? row++ : col++; + } + if ( wrapper( Units ) ) + theLay->addWidget( wrapper( Units ), row, col ); +} + +/*! + Set the aligment of Label or Units. For Control nothing happens. +*/ +void QDS_Datum::setAlignment( const int align, const int type ) +{ + initDatum(); + + if ( ( type & Label ) && labelWidget() ) + labelWidget()->setAlignment( align ); + if ( ( type & Units ) && unitsWidget() ) + unitsWidget()->setAlignment( align ); +} + +bool QDS_Datum::eventFilter( QObject* o, QEvent* e ) +{ + if ( o == parent() ) + { + if ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent || + ( e->type() == QEvent::ChildInserted && ((QChildEvent*)e)->child() == this ) ) + initDatum(); + } + return QObject::eventFilter( o, e ); +} + +/*! + Notify about parameter changing. +*/ +void QDS_Datum::onParamChanged() +{ +} + +/*! + Delayed initialization. +*/ +void QDS_Datum::onInitDatum() +{ + initDatum(); +} + +/*! + Notify about subwidgets destroying. Allow to avoid repeated deleting in destructor. +*/ +void QDS_Datum::onDestroyed( QObject* obj ) +{ + myWrapper.remove( wrapperType( (Wrapper*)obj ) ); +} + +/*! + Returns QLabel instance which contains data dictionary label. +*/ +QLabel* QDS_Datum::labelWidget() const +{ + initDatum(); + return myLabel; +} + +/*! + Returns QLabel instance which contains data dictionary units. +*/ +QLabel* QDS_Datum::unitsWidget() const +{ + initDatum(); + return myUnits; +} + +/*! + Returns QWidget which contains user input data. +*/ +QWidget* QDS_Datum::controlWidget() const +{ + initDatum(); + return myControl; +} + +/*! + Returns the dictionary item from the datum. +*/ +Handle(DDS_DicItem) QDS_Datum::dicItem() const +{ + return myDicItem; +} + +/*! + Set the dictionary item in to the datum. +*/ +void QDS_Datum::setDicItem( const Handle(DDS_DicItem)& item ) +{ + myDicItem = item; +} + +/*! + Creates QLabel widget for data label. +*/ +QLabel* QDS_Datum::createLabel( QWidget* parent ) +{ + return new QLabel( parent ); +} + +/*! + Creates QLabel widget for data units. +*/ +QLabel* QDS_Datum::createUnits( QWidget* parent ) +{ + return new QLabel( parent ); +} + +/*! + Returns validator accordance to data type. +*/ +QValidator* QDS_Datum::validator( const bool limits ) const +{ + QValidator* aValidator = 0; + + QString fltr = filter(); + + if ( type() == DDS_DicItem::String ) + { + QString aFlags; + QString aFormat = canonicalFormat( format(), aFlags ); + + int len = -1; + int pos = aFormat.find( "." ); + if ( pos != -1 ) + { + QString numStr = aFormat.mid( pos + 1, aFormat.length() - pos - 2 ); + bool ok; + int numVal = numStr.toInt( &ok ); + if ( ok ) + len = numVal; + } + + QDS_StringValidator* aStrVal = new QDS_StringValidator( fltr, aFlags, (QObject*)this ); + aStrVal->setLength( len ); + + aValidator = aStrVal; + } + else if ( type() == DDS_DicItem::Integer ) + { + QDS_IntegerValidator* aIntVal = new QDS_IntegerValidator( fltr, (QObject*)this ); + + bool ok; + int limit; + limit = minValue().toInt( &ok ); + if ( ok && limits ) + aIntVal->setBottom( limit ); + limit = maxValue().toInt( &ok ); + if ( ok && limits ) + aIntVal->setTop( limit ); + + aValidator = aIntVal; + } + else if ( type() == DDS_DicItem::Float ) + { + QDS_DoubleValidator* aFloatVal = new QDS_DoubleValidator( fltr, (QObject*)this ); + + bool ok; + double limit; + limit = minValue().toDouble( &ok ); + if ( ok && limits ) + aFloatVal->setBottom( limit ); + limit = maxValue().toDouble( &ok ); + if ( ok && limits ) + aFloatVal->setTop( limit ); + + aValidator = aFloatVal; + } + + return aValidator; +} + +/*! + Checks the given string are valid or not. +*/ +bool QDS_Datum::validate( const QString& txt ) const +{ + if ( type() == DDS_DicItem::Unknown || + type() == DDS_DicItem::String && isDoubleFormat( format() ) ) + return true; + + QValidator* aValidator = validator( true ); + + if ( !aValidator ) + return true; + + int pos = 0; + QString str( txt ); + bool res = aValidator->validate( str, pos ) == QValidator::Acceptable; + + delete aValidator; + + return res; +} + +/*! + Retrieves information from data dictionary and create subwidgets using virtual mechanism. + Virtual mechanism doesn't work in constructor and destructor, therefore this method should + be called outside the constructor. +*/ +void QDS_Datum::initialize() +{ + if ( wrapper( Label ) ) + wrapper( Label )->setWidget( myLabel = createLabel( wrapper( Label ) ) ); + if ( wrapper( Control ) ) + wrapper( Control )->setWidget( myControl = createControl( wrapper( Control ) ) ); + if ( wrapper( Units ) ) + wrapper( Units )->setWidget( myUnits = createUnits( wrapper( Units ) ) ); + + TCollection_AsciiString comp; + Handle(DDS_DicItem) item = dicItem(); + if ( !item.IsNull() ) + comp = item->GetComponent(); + + QString unitSystem; + Handle(DDS_Dictionary) dic = DDS_Dictionary::Get(); + if ( !dic.IsNull() ) + unitSystem = toQString( comp.IsEmpty() ? dic->GetActiveUnitSystem() : + dic->GetActiveUnitSystem( comp ) ); + + unitSystemChanged( unitSystem ); + + QWidget* ctrl = controlWidget(); + if ( ctrl ) + { + QString lDescr = longDescription(); + QString sDescr = shortDescription(); + if ( !sDescr.isEmpty() ) + QToolTip::add( ctrl, sDescr ); + if ( !lDescr.isEmpty() ) + QWhatsThis::add( ctrl, lDescr ); + } + + if ( labelWidget() && ctrl && !( flags() & NotAccel ) ) + labelWidget()->setBuddy( ctrl ); +} + +void QDS_Datum::unitSystemChanged( const QString& unitSystem ) +{ + QString labText = label(); + QString unitText = unitsToText( units() ); + + if ( flags() & UnitsWithLabel ) + { + if ( labText.isEmpty() ) + labText = unitText; + else if ( !unitText.isEmpty() ) + labText = QString( "%1 (%2)" ).arg( labText ).arg( unitText ); + unitText = QString::null; + } + + if ( labelWidget() ) + labelWidget()->setText( labText ); + + if ( unitsWidget() ) + unitsWidget()->setText( unitText ); + + reset(); +} + +/*! + Covert units into text presentation. +*/ +QString QDS_Datum::unitsToText( const QString& uni ) +{ + int pos = -1; + QString aUnits = uni; + while ( ( pos = aUnits.find( "**" ) ) != -1 ) + { + aUnits = aUnits.mid( 0, pos ) + QString( "" ) + + aUnits.mid( pos + 2, 1 ) + QString( "" ) + + aUnits.mid( pos + 3 ); + } + return aUnits; +} + +/*! + Covert text presentation into internal units format. +*/ +QString QDS_Datum::textToUnits( const QString& txt ) +{ + int pos = -1; + QString aUnits = txt; + while ( ( pos = aUnits.find( "" ) ) != -1 ) + { + aUnits.remove( pos, 5 ); + aUnits.insert( pos, "**" ); + } + while ( ( pos = aUnits.find( "" ) ) != -1 ) + aUnits.remove( pos, 6 ); + return aUnits; +} + +/*! + Format the specified integer as data dictionary value. +*/ +QString QDS_Datum::format( const int num, const QString& id, const bool convert ) +{ + Handle(DDS_DicItem) anItem; + int aNum = num; + QString anUnit; + + QString aFormat; + int aType = DDS_DicItem::Unknown; + Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get(); + if ( !aDict.IsNull() ) + { + anItem = aDict->GetDicItem( toAsciiString( id ) ); + if ( !anItem.IsNull() ) + { + aType = anItem->GetType(); + aFormat = toQString( anItem->GetFormat( false ) ); + if ( convert ) + aNum = ( int )anItem->FromSI( aNum ); + } + } + + return format( aFormat, aType, aNum ); +} + +/*! + Format the specified double as data dictionary value. +*/ +QString QDS_Datum::format( const double num, const QString& id, const bool convert ) +{ + Handle(DDS_DicItem) anItem; + double aNum = num; + QString anUnit; + + QString aFormat; + int aType = DDS_DicItem::Unknown; + Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get(); + if ( !aDict.IsNull() ) + { + anItem = aDict->GetDicItem( toAsciiString( id ) ); + if ( !anItem.IsNull() ) + { + aType = anItem->GetType(); + aFormat = toQString( anItem->GetFormat( false ) ); + if ( convert ) + aNum = anItem->FromSI( aNum ); + } + } + + return format( aFormat, aType, aNum ); +} + +/*! + Format the specified string as data dictionary value. +*/ +QString QDS_Datum::format( const QString& str, const QString& id, const bool convert ) +{ + Handle(DDS_DicItem) anItem; + QString aStr = str; + QString anUnit; + + QString aFormat; + int aType = DDS_DicItem::Unknown; + Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get(); + if ( !aDict.IsNull() ) + { + anItem = aDict->GetDicItem( toAsciiString( id ) ); + if ( !anItem.IsNull() ) + { + aType = anItem->GetType(); + aFormat = toQString( anItem->GetFormat( false ) ); + if ( convert ) + aStr = QString::number( anItem->FromSI( aStr.toDouble() ), 'f', 16 ); + } + } + + return format( aFormat, aType, aStr ); +} + +/*! + Format the given string accordance to data format. +*/ +QString QDS_Datum::format( const QString& aFormat, const int aType, const int aValue ) +{ + QString txt; + + if ( !aFormat.isEmpty() ) + { + switch ( aType ) + { + case DDS_DicItem::Float: + txt = sprintf( aFormat, (double)aValue ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::Integer: + txt = sprintf( aFormat, aValue ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::String: + default: + txt = sprintf( aFormat, aValue ); + break; + } + } + else + txt = QString().setNum( aValue ); + + return txt; +} + +/*! + Format the given string accordance to data format. +*/ +QString QDS_Datum::format( const QString& aFormat, const int aType, const double aValue ) +{ + QString txt; + + if ( !aFormat.isEmpty() ) + { + switch ( aType ) + { + case DDS_DicItem::Float: + txt = QString().sprintf( aFormat, aValue ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::Integer: + txt = QString().sprintf( aFormat, (int)aValue ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::String: + default: + txt = QString().sprintf( aFormat, aValue ); + break; + } + } + else + txt = QString().setNum( aValue, 'g', 16 ); + + return txt; +} + +/*! + Format the given string accordance to data format. +*/ +QString QDS_Datum::format( const QString& aFormat, const int aType, const QString& aValue ) +{ + QString txt = aValue; + + if ( aType != DDS_DicItem::String ) + txt = txt.stripWhiteSpace(); + + if ( aFormat.isEmpty() || txt.isEmpty() ) + return txt; + + switch ( aType ) + { + case DDS_DicItem::Float: + txt = txt.replace( 'd', 'e' ).replace( 'D', 'E' ); + txt = sprintf( aFormat, txt.toDouble() ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::Integer: + txt = sprintf( aFormat, txt.toInt() ); + txt = txt.stripWhiteSpace(); + break; + case DDS_DicItem::String: + txt = sprintf( aFormat, txt ); + break; + } + + return txt; +} + +/*! + Wrapper around the standard sprintf function. + Process some non standard flags from format string. +*/ +QString QDS_Datum::sprintf( const QString& fmt, const int val ) +{ + return QString().sprintf( canonicalFormat( fmt ), val ); +} + +/*! + Wrapper around the standard sprintf function. + Process some non standard flags from format string. +*/ +QString QDS_Datum::sprintf( const QString& fmt, const double val ) +{ + return QString().sprintf( canonicalFormat( fmt ), val ); +} + +/*! + Wrapper around the standard sprintf function. + Process some non standard flags from format string. +*/ +QString QDS_Datum::sprintf( const QString& fmt, const QString& val ) +{ + QString aFlags; + QString aFormat = canonicalFormat( fmt, aFlags ); + + QString txt = val; + + QRegExp rx( "^(%[0-9]*.?[0-9]*s)$" ); + if ( aFormat.find( rx ) != -1 ) + { + // QString().sprintf() always expects string in UTF8 encoding, so we cannot use it here + char* buf = new char[txt.length() + 1]; + ::sprintf( buf, aFormat.latin1(), (const char*)(txt.local8Bit()) ); + txt = QString::fromLocal8Bit( buf ); + + delete[] buf; + } + + if ( isDoubleFormat( aFormat ) ) + { + /*bool isOk; + double aVal = txt.toDouble( &isOk ); + if ( isOk ) + { + txt = sprintf( aFormat, aVal ); + txt = txt.replace( 'e', 'D' ); + }*/ + } + + if ( aFlags.contains( "u", false ) ) + txt = txt.upper(); + if ( aFlags.contains( "l", false ) ) + txt = txt.lower(); + + return txt; +} + +/*! + Returns the canonical sprintf format. +*/ +QString QDS_Datum::canonicalFormat( const QString& fmt ) +{ + QString flags; + return canonicalFormat( fmt, flags ); +} + +/*! + Returns the canonical sprintf format and non standard flags. +*/ +QString QDS_Datum::canonicalFormat( const QString& fmt, QString& flags ) +{ + QString newFmt = fmt; + flags = QString::null; + + QRegExp rx( "^(%[0-9]*.?[0-9]*)([a-z,A-Z]+)[g|c|d|i|o|u|x|e|f|n|p|s|X|E|G]$" ); + if ( rx.search( newFmt ) >= 0 ) + { + flags = rx.cap( 2 ); + newFmt.remove( rx.pos( 2 ), flags.length() ); + } + return newFmt; +} + +/*! + Returns displayable units string for given DD ID +*/ +QString QDS_Datum::units( const QString& id ) +{ + QString anUnit; + Handle(DDS_DicItem) anItem; + + Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get(); + if ( !aDict.IsNull() ) + { + anItem = aDict->GetDicItem( toAsciiString( id ) ); + if ( !anItem.IsNull() ) + anUnit = unitsToText( toQString( anItem->GetUnits() ) ); + } + return anUnit; +} + +/*! + Get prefix string from format. +*/ +QString QDS_Datum::prefix() const +{ + return QString::null; +} + +/*! + Get suffix string from format. +*/ +QString QDS_Datum::suffix() const +{ + return QString::null; +} + +/*! + Get min value. +*/ +QString QDS_Datum::minValue() const +{ + QString pref = prefix(); + QString suff = suffix(); + + QString aMin = minimumValue().stripWhiteSpace(); + + if ( !pref.isEmpty() && aMin.left( pref.length() ) == pref ) + aMin = aMin.mid( pref.length() ); + + if ( !suff.isEmpty() && aMin.right( suff.length() ) == suff ) + aMin = aMin.mid( 0, aMin.length() - suff.length() ); + + return aMin; +} + +/*! + Get max value. +*/ +QString QDS_Datum::maxValue() const +{ + QString pref = prefix(); + QString suff = suffix(); + + QString aMax = maximumValue().stripWhiteSpace(); + + if ( !pref.isEmpty() && aMax.left( pref.length() ) == pref ) + aMax = aMax.mid( pref.length() ); + + if ( !suff.isEmpty() && aMax.right( suff.length() ) == suff ) + aMax = aMax.mid( 0, aMax.length() - suff.length() ); + + return aMax; +} + +/*! + Reset the numeric value cache. +*/ +void QDS_Datum::invalidateCache() +{ + myTargetValue = QString::null; +} + +QString QDS_Datum::removeAccel( const QString& src ) +{ + QString trg = src; + + for ( uint i = 0; i < trg.length(); ) + { + if ( trg.mid( i, 2 ) == QString( "&&" ) ) + i += 2; + else if ( trg.at( i ) == '&' ) + trg.remove( i, 1 ); + else + i++; + } + return trg; +} + +bool QDS_Datum::isDoubleFormat( const QString& theFormat ) +{ + if ( theFormat.length() > 0 ) + { + QChar c = theFormat[ (int)( theFormat.length() - 1 ) ]; + return c == 'f' || c == 'g' || c == 'e' || c == 'G' || c == 'E'; + } + else + return false; +} + +int QDS_Datum::flags() const +{ + return myFlags; +} + +void QDS_Datum::initDatum() const +{ + if ( myInitialised ) + return; + + QDS_Datum* that = (QDS_Datum*)this; + that->myInitialised = true; + that->initialize(); + + if ( parent() ) + parent()->removeEventFilter( this ); +} + +QDS_Datum::Wrapper* QDS_Datum::wrapper( QWidget* wid ) const +{ + if ( !wid ) + return 0; + + Wrapper* wrap = 0; + for ( QMap::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && !wrap; ++it ) + { + if ( it.data() && it.data()->widget() == wid ) + wrap = it.data(); + } + return wrap; +} + +QDS_Datum::Wrapper* QDS_Datum::wrapper( const int id ) const +{ + Wrapper* wrap = 0; + if ( myWrapper.contains( id ) ) + wrap = myWrapper[id]; + return wrap; +} + +int QDS_Datum::wrapperType( QDS_Datum::Wrapper* wrap ) const +{ + int id = -1; + for ( QMap::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && id == -1; ++it ) + { + if ( it.data() == wrap ) + id = it.key(); + } + return id; +} diff --git a/src/QDS/QDS_Datum.h b/src/QDS/QDS_Datum.h new file mode 100644 index 000000000..be0247441 --- /dev/null +++ b/src/QDS/QDS_Datum.h @@ -0,0 +1,175 @@ +#ifndef QDS_DATUM_H +#define QDS_DATUM_H + +#include "QDS.h" + +#include +#include +#include + +#include + +class QLabel; +class QWidget; +class QValidator; +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; + +class Handle(DDS_Dictionary); + +class QDS_EXPORT QDS_Datum : public QObject, public QDS +{ + Q_OBJECT + + class Wrapper; + +public: + QDS_Datum( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_Datum(); + + QString id() const; + int type() const; + QString label() const; + QString units() const; + QString filter() const; + QString format() const; + QString longDescription() const; + QString shortDescription() const; + + QString defaultValue() const; + QString minimumValue() const; + QString maximumValue() const; + + virtual QString stringValue() const; + virtual double doubleValue() const; + virtual int integerValue() const; + + QString text() const; + + virtual bool isEmpty() const; + + virtual void reset(); + virtual void clear(); + + virtual void setStringValue( const QString& ); + virtual void setDoubleValue( const double ); + virtual void setIntegerValue( const int ); + + virtual bool isEnabled( const int = Control ) const; + virtual void setEnabled( const bool, const int ); + + void show( const int = -1 ); + void hide( const int = -1 ); + void setShown( const bool, const int = -1 ); + + QWidget* widget( const int ) const; + void setFocus(); + + virtual bool isValid( const bool = true, + const QString& = QString::null, + const QString& = QString::null ) const; + virtual QValidator* validator( const bool = false ) const; + + void addTo( QVBoxLayout* ); + void addTo( QHBoxLayout* ); + void addTo( QGridLayout*, const int, const int, const bool = false ); + + virtual void setAlignment( const int, const int = Label ); + + static QString unitsToText( const QString& ); + static QString textToUnits( const QString& ); + + static QString format( const QString&, const QString&, const bool = false ); + static QString format( const int, const QString&, const bool = false ); + static QString format( const double, const QString&, const bool = false ); + static QString units( const QString& ); + + virtual bool eventFilter( QObject*, QEvent* ); + +signals: + void paramChanged(); + void paramChanged( QString& ); + +public slots: + void setEnabled( bool ); + +protected slots: + virtual void onParamChanged(); + +private slots: + void onInitDatum(); + void onDestroyed( QObject* ); + +protected: + QLabel* labelWidget() const; + QLabel* unitsWidget() const; + QWidget* controlWidget() const; + + Handle(DDS_DicItem) dicItem() const; + void setDicItem( const Handle(DDS_DicItem)& ); + + int flags() const; + + void invalidateCache(); + + virtual QLabel* createLabel( QWidget* ); + virtual QLabel* createUnits( QWidget* ); + virtual QWidget* createControl( QWidget* ) = 0; + + virtual QString getString() const = 0; + virtual void setString( const QString& ) = 0; + + virtual bool validate( const QString& ) const; + + QString prefix() const; + QString suffix() const; + virtual QString minValue() const; + virtual QString maxValue() const; + + static QString format( const QString&, const int, const int ); + static QString format( const QString&, const int, const double ); + static QString format( const QString&, const int, const QString& ); + + static QString sprintf( const QString&, const int ); + static QString sprintf( const QString&, const double ); + static QString sprintf( const QString&, const QString& ); + + virtual void unitSystemChanged( const QString& ); + +private: + void initialize(); + void initDatum() const; + + Wrapper* wrapper( QWidget* ) const; + Wrapper* wrapper( const int ) const; + int wrapperType( Wrapper* ) const; + + static QString removeAccel( const QString& ); + static bool isDoubleFormat( const QString& ); + static QString canonicalFormat( const QString& ); + static QString canonicalFormat( const QString&, QString& ); + +private: + typedef QGuardedPtr GuardedLabel; + typedef QGuardedPtr GuardedWidget; + +private: + QString myId; + int myFlags; + Handle(DDS_DicItem) myDicItem; + QMap myWrapper; + + GuardedLabel myLabel; + GuardedLabel myUnits; + GuardedWidget myControl; + + QString mySourceValue; + QString myTargetValue; + + bool myInitialised; + + friend class QDS; +}; + +#endif diff --git a/src/QDS/QDS_LineEdit.cxx b/src/QDS/QDS_LineEdit.cxx new file mode 100644 index 000000000..15cc3f057 --- /dev/null +++ b/src/QDS/QDS_LineEdit.cxx @@ -0,0 +1,172 @@ +#include "QDS_LineEdit.h" + +#include +#include + +/* + Class: QDS_LineEdit::Editor + Descr: Internal class inherited from line edit +*/ + +class QDS_LineEdit::Editor : public QLineEdit +{ +public: + Editor( QWidget* parent = 0 ) : QLineEdit( parent ), myNumber( 2 ) {}; + virtual ~Editor() {}; + + void setNumber( const int num ) { myNumber = num; }; + + virtual QSize minimumSizeHint() const + { + return QLineEdit::minimumSizeHint(). + expandedTo( QSize( fontMetrics().width( "0" ) * myNumber, 0 ) ); + } + + virtual QSize sizeHint() const + { + return minimumSizeHint(); + } + +private: + int myNumber; +}; + +/* + Class: QDS_LineEdit + Descr: Data control corresponding to line edit +*/ + +/*! + Constructor. +*/ +QDS_LineEdit::QDS_LineEdit( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_LineEdit::~QDS_LineEdit() +{ +} + +void QDS_LineEdit::unitSystemChanged( const QString& system ) +{ + QDS_Datum::unitSystemChanged( system ); + + QLineEdit* le = lineEdit(); + if ( !le ) + return; + + delete le->validator(); + le->clearValidator(); + QValidator* valid = validator(); + if ( valid ) + le->setValidator( valid ); + + QString aFormat = format(); + int num = 0; + int pos = aFormat.find( '%' ); + if ( pos != -1 ) + { + pos++; + QString aLen; + while ( pos < (int)aFormat.length() && aFormat.at( pos ).isDigit() ) + aLen += aFormat.at( pos++ ); + if ( pos < (int)aFormat.length() && aFormat.at( pos ) == '.' ) + num += 1; + if ( !aLen.isEmpty() ) + num += aLen.toInt(); + } + + int zeroLen = format( format(), type(), 0 ).length(); + int minLen = format( format(), type(), minValue() ).length(); + int maxLen = format( format(), type(), maxValue() ).length(); + + num = QMAX( QMAX( num, zeroLen ), QMAX( minLen, maxLen ) ); + ((Editor*)le)->setNumber( num ); +} + +/*! + Set the aligment of line edit. +*/ +void QDS_LineEdit::setAlignment( const int align, const int type ) +{ + if ( ( type & Control ) && lineEdit() ) + lineEdit()->setAlignment( align ); + + QDS_Datum::setAlignment( align, type ); +} + +/*! + Returns string from QLineEdit widget. +*/ +QString QDS_LineEdit::getString() const +{ + QString res; + if ( lineEdit() ) + res = lineEdit()->text(); + return res; +} + +/*! + Sets the string into QLineEdit widget. +*/ +void QDS_LineEdit::setString( const QString& txt ) +{ + if ( lineEdit() ) + lineEdit()->setText( txt ); +} + +/*! + Returns pointer to QLineEdit widget. +*/ +QLineEdit* QDS_LineEdit::lineEdit() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QLineEdit widget as control subwidget. +*/ +QWidget* QDS_LineEdit::createControl( QWidget* parent ) +{ + Editor* le = new Editor( parent ); + connect( le, SIGNAL( returnPressed() ), this, SIGNAL( returnPressed() ) ); + connect( le, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); + return le; +} + +/*! + Notify about text changing in line edit. +*/ +void QDS_LineEdit::onTextChanged( const QString& ) +{ + invalidateCache(); + + onParamChanged(); + QString str = getString(); + emit paramChanged(); + emit paramChanged( str ); +} + +/*! + Checks the current parameter value on validity. +*/ +void QDS_LineEdit::onParamChanged() +{ + QLineEdit* anEdit = lineEdit(); + if ( !anEdit ) + return; + + bool aValid = isValid( false ); + + QPalette aPal = anEdit->palette(); + if ( !aValid ) + aPal.setColor( QPalette::Active, QColorGroup::Text, QColor( 255, 0, 0 ) ); + else + aPal.setColor( QPalette::Active, QColorGroup::Text, QColor( 0, 0, 0 ) ); + + anEdit->setPalette( aPal ); +} diff --git a/src/QDS/QDS_LineEdit.h b/src/QDS/QDS_LineEdit.h new file mode 100644 index 000000000..883d38cb7 --- /dev/null +++ b/src/QDS/QDS_LineEdit.h @@ -0,0 +1,40 @@ +#ifndef QDS_LINEEDIT_H +#define QDS_LINEEDIT_H + +#include "QDS_Datum.h" + +class QLineEdit; + +class QDS_EXPORT QDS_LineEdit : public QDS_Datum +{ + Q_OBJECT + +protected: + class Editor; + +public: + QDS_LineEdit( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_LineEdit(); + + virtual void setAlignment( const int, const int = Label ); + +signals: + void returnPressed(); + +protected slots: + virtual void onParamChanged(); + +private slots: + void onTextChanged( const QString& ); + +protected: + QLineEdit* lineEdit() const; + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); + + virtual void unitSystemChanged( const QString& ); +}; + +#endif diff --git a/src/QDS/QDS_SpinBox.cxx b/src/QDS/QDS_SpinBox.cxx new file mode 100644 index 000000000..d25322c3f --- /dev/null +++ b/src/QDS/QDS_SpinBox.cxx @@ -0,0 +1,117 @@ +#include "QDS_SpinBox.h" + +#include +#include + +/*! + Constructor. +*/ +QDS_SpinBox::QDS_SpinBox( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_SpinBox::~QDS_SpinBox() +{ +} + +/*! + Returns string from QSpinBox widget. +*/ +QString QDS_SpinBox::getString() const +{ + QString res; + QSpinBox* aSpinBox = spinBox(); + if ( aSpinBox ) + { + res = aSpinBox->text(); + if ( !aSpinBox->suffix().isEmpty() ) + res.remove( res.find( aSpinBox->suffix() ), aSpinBox->suffix().length() ); + if ( !aSpinBox->prefix().isEmpty() ) + res.remove( res.find( aSpinBox->prefix() ), aSpinBox->prefix().length() ); + } + return res; +} + +/*! + Sets the string into QSpinBox widget. +*/ +void QDS_SpinBox::setString( const QString& txt ) +{ + if ( spinBox() ) + spinBox()->setValue( txt.toInt() ); +} + +/*! + Returns pointer to QSpinBox widget. +*/ +QSpinBox* QDS_SpinBox::spinBox() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QSpinBox widget as control subwidget. +*/ +QWidget* QDS_SpinBox::createControl( QWidget* parent ) +{ + QSpinBox* aSpinBox = new QSpinBox( parent ); + aSpinBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( aSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged( int ) ) ); + return aSpinBox; +} + +/*! + Notify about text changing in spin box. +*/ +void QDS_SpinBox::onValueChanged( int val ) +{ + onParamChanged(); + QString str = QString::number( val ); + emit paramChanged(); + emit paramChanged( str ); +} + +/*! + Sets the increment step. +*/ +void QDS_SpinBox::setStep( const int step ) +{ + if ( spinBox() ) + spinBox()->setLineStep( step ); +} + +/*! + Returns the increment step. +*/ +int QDS_SpinBox::step() const +{ + int s = 0; + if ( spinBox() ) + s = spinBox()->lineStep(); + return s; +} + +/*! + This method is redefined from ancestor class to perform own initialization ( suffix, prefix, etc ). +*/ +void QDS_SpinBox::unitSystemChanged( const QString& system ) +{ + QDS_Datum::unitSystemChanged( system ); + + QSpinBox* sb = spinBox(); + if ( sb ) + { + delete sb->validator(); + QValidator* valid = validator(); + sb->setValidator( valid ); + + sb->setSuffix( suffix() ); + sb->setPrefix( prefix() ); + sb->setMinValue( minValue().toInt() ); + sb->setMaxValue( maxValue().toInt() ); + } +} diff --git a/src/QDS/QDS_SpinBox.h b/src/QDS/QDS_SpinBox.h new file mode 100644 index 000000000..d6490edbf --- /dev/null +++ b/src/QDS/QDS_SpinBox.h @@ -0,0 +1,33 @@ +#ifndef QDS_SPINBOX_H +#define QDS_SPINBOX_H + +#include "QDS_Datum.h" + +class QSpinBox; + +class QDS_EXPORT QDS_SpinBox : public QDS_Datum +{ + Q_OBJECT + +public: + QDS_SpinBox( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_SpinBox(); + + int step() const; + void setStep( const int ); + +private slots: + void onValueChanged( int ); + +protected: + QSpinBox* spinBox() const; + + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); + + virtual void unitSystemChanged( const QString& ); +}; + +#endif diff --git a/src/QDS/QDS_SpinBoxDbl.cxx b/src/QDS/QDS_SpinBoxDbl.cxx new file mode 100644 index 000000000..42d1e2f9e --- /dev/null +++ b/src/QDS/QDS_SpinBoxDbl.cxx @@ -0,0 +1,135 @@ +#include "QDS_SpinBoxDbl.h" + +#include + +#include + +#include + +/*! + Constructor. +*/ +QDS_SpinBoxDbl::QDS_SpinBoxDbl( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_SpinBoxDbl::~QDS_SpinBoxDbl() +{ +} + +/*! + Returns string from QSpinBox widget. +*/ +QString QDS_SpinBoxDbl::getString() const +{ + QString res; + QtxDblSpinBox* sb = spinBox(); + if ( sb ) + { + bool hasFocus = sb->hasFocus(); + if ( hasFocus ) + sb->clearFocus(); + + res = sb->text(); + if ( !sb->suffix().isEmpty() ) + res.remove( res.find( sb->suffix() ), sb->suffix().length() ); + if ( !sb->prefix().isEmpty() ) + res.remove( res.find( sb->prefix() ), sb->prefix().length() ); + + if ( hasFocus ) + sb->setFocus(); + } + + return res; +} + +/*! + Sets the string into QSpinBox widget. +*/ +void QDS_SpinBoxDbl::setString( const QString& txt ) +{ + if ( spinBox() ) + spinBox()->setValue( txt.toDouble() ); +} + +/*! + Returns pointer to XMLGUI_SpinBoxDbl widget. +*/ +QtxDblSpinBox* QDS_SpinBoxDbl::spinBox() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QSpinBox widget as control subwidget. +*/ +QWidget* QDS_SpinBoxDbl::createControl( QWidget* parent ) +{ + QtxDblSpinBox* aSpinBox = new QtxDblSpinBox( parent ); + aSpinBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( aSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( onValueChanged( double ) ) ); + return aSpinBox; +} + +/*! + Notify about text changing in spin box. +*/ +void QDS_SpinBoxDbl::onValueChanged( double ) +{ + onParamChanged(); + QString str = getString(); + + emit paramChanged(); + emit paramChanged( str ); +} + +/*! + Returns the increment step. +*/ +double QDS_SpinBoxDbl::step() const +{ + double s = 0; + if ( spinBox() ) + s = spinBox()->lineStep(); + return s; +} + +/*! + Sets the increment step. +*/ +void QDS_SpinBoxDbl::setStep( const double step ) +{ + if ( spinBox() ) + spinBox()->setLineStep( step ); +} + +void QDS_SpinBoxDbl::unitSystemChanged( const QString& system ) +{ + QDS_Datum::unitSystemChanged( system ); + + QtxDblSpinBox* sb = spinBox(); + if ( !sb ) + return; + + delete sb->validator(); + QValidator* valid = validator(); + sb->setValidator( valid ); + + sb->setSuffix( suffix() ); + sb->setPrefix( prefix() ); + + Standard_Integer aPreci = 1; + Handle(DDS_DicItem) aDicItem = dicItem(); + if ( !aDicItem.IsNull() ) + aPreci = aDicItem->GetPrecision(); + + sb->setPrecision( aPreci ); + + sb->setLineStep( .1 ); + sb->setMinValue( minValue().toDouble() ); + sb->setMaxValue( maxValue().toDouble() ); +} diff --git a/src/QDS/QDS_SpinBoxDbl.h b/src/QDS/QDS_SpinBoxDbl.h new file mode 100644 index 000000000..a0c5e3096 --- /dev/null +++ b/src/QDS/QDS_SpinBoxDbl.h @@ -0,0 +1,32 @@ +#ifndef QDS_PINBOXDBL_H +#define QDS_PINBOXDBL_H + +#include "QDS_Datum.h" + +class QtxDblSpinBox; + +class QDS_EXPORT QDS_SpinBoxDbl : public QDS_Datum +{ + Q_OBJECT + +public: + QDS_SpinBoxDbl( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_SpinBoxDbl(); + + double step() const; + void setStep( const double ); + +private slots: + void onValueChanged( double ); + +protected: + QtxDblSpinBox* spinBox() const; + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); + + virtual void unitSystemChanged( const QString& ); +}; + +#endif diff --git a/src/QDS/QDS_TextEdit.cxx b/src/QDS/QDS_TextEdit.cxx new file mode 100644 index 000000000..65fbcb28e --- /dev/null +++ b/src/QDS/QDS_TextEdit.cxx @@ -0,0 +1,71 @@ +#include "QDS_TextEdit.h" + +#include + +/*! + Constructor. +*/ +QDS_TextEdit::QDS_TextEdit( const QString& id, QWidget* parent, const int flags, const QString& comp ) +: QDS_Datum( id, parent, flags, comp ) +{ +} + +/*! + Destructor. +*/ +QDS_TextEdit::~QDS_TextEdit() +{ +} + +/*! + Returns string from QTextEdit widget. +*/ +QString QDS_TextEdit::getString() const +{ + QString res; + if ( textEdit() ) + res = textEdit()->text(); + return res; +} + +/*! + Sets the string into QTextEdit widget. +*/ +void QDS_TextEdit::setString( const QString& txt ) +{ + if ( textEdit() ) + textEdit()->setText( txt ); +} + +/*! + Returns pointer to QTextEdit widget. +*/ +QTextEdit* QDS_TextEdit::textEdit() const +{ + return ::qt_cast( controlWidget() ); +} + +/*! + Create QTextEdit widget as control subwidget. +*/ +QWidget* QDS_TextEdit::createControl( QWidget* parent ) +{ + QTextEdit* te = new QTextEdit( parent ); + connect( te, SIGNAL( textChanged() ), this, SLOT( onTextChanged() ) ); + return te; +} + +/*! + Notify about text changing in line edit. +*/ +void QDS_TextEdit::onTextChanged() +{ + invalidateCache(); + + onParamChanged(); + + QString str = getString(); + + emit paramChanged(); + emit paramChanged( str ); +} diff --git a/src/QDS/QDS_TextEdit.h b/src/QDS/QDS_TextEdit.h new file mode 100644 index 000000000..917ff13e4 --- /dev/null +++ b/src/QDS/QDS_TextEdit.h @@ -0,0 +1,30 @@ +#ifndef QDS_TEXTEEDIT_H +#define QDS_TEXTEEDIT_H + +#include "QDS_Datum.h" + +class QTextEdit; + +class QDS_EXPORT QDS_TextEdit : public QDS_Datum +{ + Q_OBJECT + +public: + QDS_TextEdit( const QString&, QWidget* = 0, const int = All, const QString& = QString::null ); + virtual ~QDS_TextEdit(); + +signals: + void returnPressed(); + +private slots: + void onTextChanged(); + +protected: + QTextEdit* textEdit() const; + virtual QWidget* createControl( QWidget* ); + + virtual QString getString() const; + virtual void setString( const QString& ); +}; + +#endif diff --git a/src/QDS/QDS_Validator.cxx b/src/QDS/QDS_Validator.cxx new file mode 100644 index 000000000..d83463eae --- /dev/null +++ b/src/QDS/QDS_Validator.cxx @@ -0,0 +1,127 @@ +#include "QDS_Validator.h" + +/*! + Class: QDS_IntegerValidator +*/ + +QDS_IntegerValidator::QDS_IntegerValidator( QObject* p ) +: QIntValidator( p ) +{ +} + +QDS_IntegerValidator::QDS_IntegerValidator( const QString& f, QObject* p ) +: QIntValidator( p ), +myFilter( f ) +{ +} + +QDS_IntegerValidator::~QDS_IntegerValidator() +{ +} + +QValidator::State QDS_IntegerValidator::validate( QString& input, int& pos ) const +{ + State rgState = Acceptable; + State ivState = QIntValidator::validate( input, pos ); + if ( ivState != Invalid && !myFilter.isEmpty() ) + rgState = QRegExpValidator( QRegExp( myFilter ), 0 ).validate( input, pos ); + + ivState = QMIN( ivState, rgState ); + + return ivState; +} + +/*! + Class: QDS_DoubleValidator +*/ + +QDS_DoubleValidator::QDS_DoubleValidator( QObject* p ) +: QDoubleValidator( p ) +{ +} + +QDS_DoubleValidator::QDS_DoubleValidator( const QString& f, QObject* p ) +: QDoubleValidator( p ), +myFilter( f ) +{ +} + +QDS_DoubleValidator::~QDS_DoubleValidator() +{ +} + +QValidator::State QDS_DoubleValidator::validate( QString& input, int& pos ) const +{ + State rgState = Acceptable; + State dvState = QDoubleValidator::validate( input, pos ); + if ( dvState != Invalid && !myFilter.isEmpty() ) + rgState = QRegExpValidator( QRegExp( myFilter ), 0 ).validate( input, pos ); + + dvState = QMIN( dvState, rgState ); + + return dvState; +} + +/*! + Class: QDS_StringValidator +*/ + +QDS_StringValidator::QDS_StringValidator( QObject* p ) +: QValidator( p ), +myLen( -1 ) +{ +} + +QDS_StringValidator::QDS_StringValidator( const QString& f, QObject* p ) +: QValidator( p ), +myFlags( f ), +myLen( -1 ) +{ +} + +QDS_StringValidator::QDS_StringValidator( const QString& ft, const QString& fg, QObject* p ) +: QValidator( p ), +myLen( -1 ), +myFilter( ft ), +myFlags( fg ) +{ +} + +QDS_StringValidator::~QDS_StringValidator() +{ +} + +int QDS_StringValidator::length() const +{ + return myLen; +} + +void QDS_StringValidator::setLength( const int l ) +{ + myLen = l; +} + +QValidator::State QDS_StringValidator::validate( QString& input, int& pos ) const +{ + if ( input.isEmpty() ) + return Acceptable; + + QString orig = input; + if ( myFlags.contains( 'u', false ) ) + input = input.upper(); + if ( myFlags.contains( 'l', false ) ) + input = input.lower(); + + State rgState = Acceptable; + State svState = orig == input ? Acceptable : Intermediate; + + if ( myLen >= 0 && (int)input.length() > myLen ) + svState = Intermediate; + + if ( !myFilter.isEmpty() ) + rgState = QRegExpValidator( QRegExp( myFilter ), 0 ).validate( input, pos ); + + svState = QMIN( svState, rgState ); + + return svState; +} diff --git a/src/QDS/QDS_Validator.h b/src/QDS/QDS_Validator.h new file mode 100644 index 000000000..bc966c03c --- /dev/null +++ b/src/QDS/QDS_Validator.h @@ -0,0 +1,66 @@ +#ifndef QDS_VALIDATOR_H +#define QDS_VALIDATOR_H + +#include "QDS.h" + +#include + +/*! + Class: QDS_IntegerValidator +*/ + +class QDS_EXPORT QDS_IntegerValidator : public QIntValidator +{ +public: + QDS_IntegerValidator( QObject* p = 0 ); + QDS_IntegerValidator( const QString& f, QObject* p = 0 ); + virtual ~QDS_IntegerValidator(); + + virtual State validate( QString&, int& ) const; + +private: + QString myFilter; +}; + +/*! + Class: QDS_DoubleValidator +*/ + +class QDS_DoubleValidator : public QDoubleValidator +{ +public: + QDS_DoubleValidator( QObject* p = 0 ); + QDS_DoubleValidator( const QString& f, QObject* p = 0 ); + virtual ~QDS_DoubleValidator(); + + virtual State validate( QString&, int& ) const; + +private: + QString myFilter; +}; + +/*! + Class: QDS_StringValidator +*/ + +class QDS_EXPORT QDS_StringValidator : public QValidator +{ +public: + + QDS_StringValidator( QObject* p = 0 ); + QDS_StringValidator( const QString& f, QObject* p = 0 ); + QDS_StringValidator( const QString& ft, const QString& fg, QObject* p = 0 ); + virtual ~QDS_StringValidator(); + + virtual State validate( QString&, int& ) const; + + int length() const; + void setLength( const int ); + +private: + int myLen; + QString myFlags; + QString myFilter; +}; + +#endif diff --git a/src/Qtx/QtxColorScale.cxx b/src/Qtx/QtxColorScale.cxx new file mode 100755 index 000000000..7be7ba48d --- /dev/null +++ b/src/Qtx/QtxColorScale.cxx @@ -0,0 +1,1313 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxColorScale.cxx +// Author: Sergey TELKOV + +#include "QtxColorScale.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/********************************************************************* +** Class: QtxColorScale +** Descr: Color Scale widget. +** Level: Public +*********************************************************************/ + +QtxColorScale::QtxColorScale( QWidget* parent, const char* name, WFlags f ) +: QFrame( parent, name, f | WResizeNoErase | WRepaintNoErase ), +myDock( 0 ), +myMin( 0.0 ), +myMax( 1.0 ), +myTitle( "" ), +myInterval( 10 ), +myStyleSheet( 0 ), +myFormat( "%.4g" ), +myColorMode( Auto ), +myLabelMode( Auto ), +myLabelPos( Right ), +myTitlePos( Center ), +myDumpMode( NoDump ), +myFlags( AtBorder | WrapTitle ) +{ + setCaption( tr ( "Color scale" ) ); +} + +QtxColorScale::QtxColorScale( const int num, QWidget* parent, const char* name, WFlags f ) +: QFrame( parent, name, f | WResizeNoErase | WRepaintNoErase ), +myDock( 0 ), +myMin( 0.0 ), +myMax( 1.0 ), +myTitle( "" ), +myInterval( num ), +myStyleSheet( 0 ), +myFormat( "%.4g" ), +myColorMode( Auto ), +myLabelMode( Auto ), +myLabelPos( Right ), +myTitlePos( Center ), +myDumpMode( NoDump ), +myFlags( AtBorder | WrapTitle ) +{ + setCaption( tr ( "Color scale" ) ); +} + +#if QT_VER == 3 + +QtxColorScale::QtxColorScale( Dock* dock, const char* name, WFlags f ) +: QFrame( dock, name, f | WResizeNoErase | WRepaintNoErase ), +myMin( 0.0 ), +myMax( 1.0 ), +myTitle( "" ), +myDock( dock ), +myInterval( 10 ), +myStyleSheet( 0 ), +myFormat( "%.4g" ), +myColorMode( Auto ), +myLabelMode( Auto ), +myLabelPos( Right ), +myTitlePos( Center ), +myDumpMode( NoDump ), +myFlags( AtBorder | WrapTitle ) +{ + setCaption( tr ( "Color scale" ) ); +} + +#endif + +QtxColorScale::~QtxColorScale() +{ +} + +//================================================================ +// Function : minimum +// Purpose : Returns minimal limit of scale. +//================================================================ + +double QtxColorScale::minimum() const +{ + return myMin; +} + +//================================================================ +// Function : maximum +// Purpose : Returns maximal limit of scale. +//================================================================ + +double QtxColorScale::maximum() const +{ + return myMax; +} + +//================================================================ +// Function : range +// Purpose : Returns range (minimal and maximal limits) of scale. +//================================================================ + +void QtxColorScale::range( double& min, double& max ) const +{ + min = myMin; + max = myMax; +} + +//================================================================ +// Function : title +// Purpose : Returns the current title string. +//================================================================ + +QString QtxColorScale::title() const +{ + return myTitle; +} + +//================================================================ +// Function : format +// Purpose : Returns the current format of number presentation in +// labels for Auto label mode (sprintf specification). +//================================================================ + +QString QtxColorScale::format() const +{ + return myFormat; +} + +//================================================================ +// Function : dumpMode +// Purpose : Returns dump mode. +//================================================================ + +int QtxColorScale::dumpMode() const +{ + return myDumpMode; +} + +//================================================================ +// Function : labelMode +// Purpose : Returns label mode. +//================================================================ + +int QtxColorScale::labelMode() const +{ + return myLabelMode; +} + +//================================================================ +// Function : colorMode +// Purpose : Returns color mode. +//================================================================ + +int QtxColorScale::colorMode() const +{ + return myColorMode; +} + +//================================================================ +// Function : intervalsNumber +// Purpose : Returns intervals number of color scale. +//================================================================ + +int QtxColorScale::intervalsNumber() const +{ + return myInterval; +} + +//================================================================ +// Function : label +// Purpose : Returns the user label of specified interval. +//================================================================ + +QString QtxColorScale::label( const int idx ) const +{ + QString res; + if ( idx >= 0 && idx < (int)myLabels.count() ) + res = *myLabels.at( idx ); + return res; +} + +//================================================================ +// Function : color +// Purpose : Returns the user color of specified interval. +//================================================================ + +QColor QtxColorScale::color( const int idx ) const +{ + QColor res; + if ( idx >= 0 && idx < (int)myColors.count() ) + res = *myColors.at( idx ); + return res; +} + +//================================================================ +// Function : labels +// Purpose : Returns the user labels. +//================================================================ + +void QtxColorScale::labels( QStringList& list ) const +{ + list = myLabels; +} + +//================================================================ +// Function : colors +// Purpose : Returns the user color. +//================================================================ + +void QtxColorScale::colors( QValueList& list ) const +{ + list = myColors; +} + +//================================================================ +// Function : labelPosition +// Purpose : Returns the label position. +//================================================================ + +int QtxColorScale::labelPosition() const +{ + return myLabelPos; +} + +//================================================================ +// Function : titlePosition +// Purpose : Returns the title position. +//================================================================ + +int QtxColorScale::titlePosition() const +{ + return myTitlePos; +} + +//================================================================ +// Function : setMinimum +// Purpose : Sets the minimum limit. +//================================================================ + +void QtxColorScale::setMinimum( const double val ) +{ + setRange( val, maximum() ); +} + +//================================================================ +// Function : setMaximum +// Purpose : Sets the maximum limit. +//================================================================ + +void QtxColorScale::setMaximum( const double val ) +{ + setRange( minimum(), val ); +} + +//================================================================ +// Function : setRange +// Purpose : Sets the minimum and maximum limits. +//================================================================ + +void QtxColorScale::setRange( const double min, const double max ) +{ + if ( myMin == min && myMax == max ) + return; + + myMin = min; + myMax = max; + + myPrecise = QString::null; + + if ( colorMode() == Auto || labelMode() == Auto ) + updateScale(); +} + +//================================================================ +// Function : setTitle +// Purpose : Sets the title string. +//================================================================ + +void QtxColorScale::setTitle( const QString& str ) +{ + if ( myTitle == str ) + return; + + myTitle = str; + updateScale(); +} + +//================================================================ +// Function : setFormat +// Purpose : Sets the format of number presentation in labels for +// Auto label mode (sprintf specification). +//================================================================ + +void QtxColorScale::setFormat( const QString& format ) +{ + if ( myFormat == format ) + return; + + myFormat = format; + myPrecise = QString::null; + if ( colorMode() == Auto ) + updateScale(); +} + +//================================================================ +// Function : setIntervalsNumber +// Purpose : Sets the number of intervals. +//================================================================ + +void QtxColorScale::setIntervalsNumber( const int num ) +{ + if ( myInterval == num || num < 1 ) + return; + + myInterval = num; + myPrecise = QString::null; + + updateScale(); +} + +//================================================================ +// Function : setLabel +// Purpose : Sets the user label for specified interval. If number +// of interval is negative then user label will be added +// as new at the end of list. +//================================================================ + +void QtxColorScale::setLabel( const QString& txt, const int idx ) +{ + bool changed = false; + uint i = idx < 0 ? myLabels.count() : idx; + if ( i < myLabels.count() ) + { + changed = *myLabels.at( i ) != txt; + myLabels[i] = txt; + } + else + { + changed = true; + while ( i >= myLabels.count() ) + myLabels.append( "" ); + myLabels[i] = txt; + } + if ( changed ) + updateScale(); +} + +//================================================================ +// Function : setColor +// Purpose : Sets the user color for specified interval. If number +// of interval is negative then user color will be added +// as new at the end of list. +//================================================================ + +void QtxColorScale::setColor( const QColor& clr, const int idx ) +{ + bool changed = false; + uint i = idx < 0 ? myColors.count() : idx; + if ( i < myColors.count() ) + { + changed = *myColors.at( i ) != clr; + myColors[i] = clr; + } + else + { + changed = true; + while ( i >= myColors.count() ) + myColors.append( QColor() ); + myColors[i] = clr; + } + if ( changed ) + updateScale(); +} + +//================================================================ +// Function : setLabels +// Purpose : Replace the all user label with specified list. +//================================================================ + +void QtxColorScale::setLabels( const QStringList& list ) +{ + if ( list.isEmpty() ) + return; + + myLabels = list; + updateScale(); +} + +//================================================================ +// Function : setColors +// Purpose : Replace the all user colors with specified list. +//================================================================ + +void QtxColorScale::setColors( const QValueList& list ) +{ + if ( list.isEmpty() ) + return; + + myColors = list; + updateScale(); +} + +//================================================================ +// Function : setColorMode +// Purpose : Sets the color mode (Auto or User). +//================================================================ + +void QtxColorScale::setColorMode( const int mode ) +{ + if ( myColorMode == mode ) + return; + + myColorMode = mode; + updateScale(); +} + +//================================================================ +// Function : setDumpMode +// Purpose : Sets the dump mode. +//================================================================ + +void QtxColorScale::setDumpMode( const int mode ) +{ + myDumpMode = mode; +} + +//================================================================ +// Function : setLabelMode +// Purpose : Sets the label mode (Auto or User). +//================================================================ + +void QtxColorScale::setLabelMode( const int mode ) +{ + if ( myLabelMode != mode ) + { + myLabelMode = mode; + updateScale(); + } +} + +//================================================================ +// Function : setLabelPosition +// Purpose : Sets the label position. +//================================================================ + +void QtxColorScale::setLabelPosition( const int pos ) +{ + if ( myLabelPos != pos && pos >= None && pos <= Center ) + { + myLabelPos = pos; + updateScale(); + } +} + +//================================================================ +// Function : setTitlePosition +// Purpose : Sets the title position. +//================================================================ + +void QtxColorScale::setTitlePosition( const int pos ) +{ + if ( myTitlePos != pos && pos >= None && pos <= Center ) + { + myTitlePos = pos; + updateScale(); + } +} + +//================================================================ +// Function : setFlags +// Purpose : Set the specified flags. +//================================================================ + +void QtxColorScale::setFlags( const int flags ) +{ + int prev = myFlags; + myFlags |= flags; + if ( prev != myFlags ) + updateScale(); +} + +//================================================================ +// Function : testFlags +// Purpose : Returns true if specified flags are setted. +//================================================================ + +bool QtxColorScale::testFlags( const int flags ) const +{ + return ( myFlags & flags ) == flags; +} + +//================================================================ +// Function : clearFlags +// Purpose : Clear (reset) the specified flags. +//================================================================ + +void QtxColorScale::clearFlags( const int flags ) +{ + int prev = myFlags; + myFlags &= ~flags; + if ( prev != myFlags ) + updateScale(); +} + +//================================================================ +// Function : minimumSizeHint +// Purpose : +//================================================================ + +QSize QtxColorScale::minimumSizeHint() const +{ + QSize sz = calculateSize( true, myFlags, titlePosition() != None, labelPosition() != None, true ); + return sz + QSize( frameWidth(), frameWidth() ); +} + +//================================================================ +// Function : sizeHint +// Purpose : +//================================================================ + +QSize QtxColorScale::sizeHint() const +{ + QSize sz = calculateSize( false, myFlags, titlePosition() != None, labelPosition() != None, true ); + return sz + QSize( frameWidth(), frameWidth() ); +} + +//================================================================ +// Function : calculateSize +// Purpose : Dump color scale into pixmap with current size. +//================================================================ + +QSize QtxColorScale::calculateSize( const bool min, const int flags, const bool title, + const bool labels, const bool colors ) const +{ + int num = intervalsNumber(); + + int spacer = 5; + int textWidth = 0; + int textHeight = fontMetrics().height(); + int colorWidth = 20; + + if ( labels && colors ) + { + QtxColorScale* that = (QtxColorScale*)this; + QString fmt = that->myFormat; + + for ( int idx = 0; idx < num; idx++ ) + textWidth = QMAX( textWidth, fontMetrics().width( getLabel( idx ) ) ); + + if ( !min ) + that->myFormat = that->myFormat.replace( QRegExp( "g" ), "f" ); + + for ( int index = 0; index < num; index++ ) + textWidth = QMAX( textWidth, fontMetrics().width( getLabel( index ) ) ); + + that->myFormat = fmt; + } + + int scaleWidth = 0; + int scaleHeight = 0; + + int titleWidth = 0; + int titleHeight = 0; + + if ( flags & AtBorder ) + { + num++; + if ( min && title && !myTitle.isEmpty() ) + titleHeight += 10; + } + + if ( colors ) + { + scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer; + if ( min ) + scaleHeight = QMAX( 2 * num, 3 * textHeight ); + else + scaleHeight = (int)( 1.5 * ( num + 1 ) * textHeight ); + } + + if ( title ) + { + QSimpleRichText* srt = simpleRichText( flags ); + if ( srt ) + { + QPainter p( this ); + if ( scaleWidth ) + srt->setWidth( &p, scaleWidth ); + + titleHeight = srt->height() + spacer; + titleWidth = srt->widthUsed() + 10; + + delete srt; + } + } + + int W = QMAX( titleWidth, scaleWidth ) + width() - contentsRect().width(); + int H = scaleHeight + titleHeight + height() - contentsRect().height(); + + return QSize( W, H ); +} + +//================================================================ +// Function : dump +// Purpose : Dump color scale into pixmap with current size. +//================================================================ + +QPixmap QtxColorScale::dump() const +{ + QPixmap aPix; + + if ( dumpMode() != NoDump ) + { + aPix = QPixmap( size() ); + if ( !aPix.isNull() ) + { + bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump ); + bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) && + labelPosition() != None; + bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) && + titlePosition() != None; + +#if QT_VER < 3 + QColor bgc = backgroundColor(); +#else + QColor bgc = paletteBackgroundColor(); +#endif + QPainter p; + p.begin( &aPix ); + p.fillRect( 0, 0, aPix.width(), aPix.height(), bgc ); + drawScale( &p, bgc, false, 0, 0, aPix.width(), aPix.height(), title, label, scale ); + p.end(); + } + } + + return aPix; +} + +//================================================================ +// Function : dump +// Purpose : Dump color scale into pixmap with specified size. +//================================================================ + +QPixmap QtxColorScale::dump( const int w, const int h ) const +{ +#if QT_VER < 3 + return dump( backgroundColor(), w, h ); +#else + return dump( paletteBackgroundColor(), w, h ); +#endif +} + +//================================================================ +// Function : dump +// Purpose : Dump color scale into pixmap with specified size +// and background color. +//================================================================ + +QPixmap QtxColorScale::dump( const QColor& bg, const int w, const int h ) const +{ + QPixmap aPix; + if ( dumpMode() != NoDump ) + { + bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump ); + bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) && + labelPosition() != None; + bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) && + titlePosition() != None; + + int W = w; + int H = h; + if ( W < 0 || H < 0 ) + { + QSize sz = calculateSize( false, myFlags & ~WrapTitle, title, label, scale ); + + if ( W < 0 ) + W = sz.width(); + if ( H < 0 ) + H = sz.height(); + } + + aPix = QPixmap( W, H ); + if ( !aPix.isNull() ) + { + QPainter p; + p.begin( &aPix ); + p.fillRect( 0, 0, aPix.width(), aPix.height(), bg ); + drawScale( &p, bg, false, 0, 0, aPix.width(), aPix.height(), title, label, scale ); + p.end(); + } + } + + return aPix; +} + +//================================================================ +// Function : show +// Purpose : Show the color scale. [Reimplemented] +//================================================================ + +void QtxColorScale::show() +{ +#if QT_VER == 3 + if ( myDock ) + myDock->activate(); + else +#endif + QFrame::show(); +} + +//================================================================ +// Function : hide +// Purpose : Hides the color scale. [Reimplemented] +//================================================================ + +void QtxColorScale::hide() +{ +#if QT_VER == 3 + if ( myDock ) + myDock->deactivate(); + else +#endif + QFrame::hide(); +} + +//================================================================ +// Function : drawContents +// Purpose : Draw color scale contents. [Reimplemented] +//================================================================ + +void QtxColorScale::drawContents( QPainter* p ) +{ + if ( !isUpdatesEnabled() ) + return; + + QRect aDrawRect = contentsRect(); + + drawScale( p, false/*testFlags( Transparent )*/, aDrawRect.x(), + aDrawRect.y(), aDrawRect.width(), aDrawRect.height(), + titlePosition() != None, labelPosition() != None, true ); +} + +//================================================================ +// Function : drawScale +// Purpose : Draw color scale contents. +//================================================================ + +void QtxColorScale::drawScale( QPainter* p, const bool transp, const int X, const int Y, + const int W, const int H, const bool title, + const bool label, const bool scale ) const +{ + QPixmap cache( W, H ); + QPainter cp( &cache ); + +#if QT_VER < 3 + drawScale( &cp, backgroundColor(), transp, 0, 0, W, H, title, label, scale ); +#else + drawScale( &cp, paletteBackgroundColor(), transp, 0, 0, W, H, title, label, scale ); +#endif + cp.end(); + + p->drawPixmap( X, Y, cache ); +} + +//================================================================ +// Function : drawScale +// Purpose : Draw color scale contents. +//================================================================ + +void QtxColorScale::drawScale( QPainter* p, const QColor& bg, const bool transp, + const int X, const int Y, const int W, const int H, + const bool drawTitle, const bool drawLabel, const bool drawColors ) const +{ + if ( !transp ) + p->fillRect( X, Y, W, H, bg ); + + int num = intervalsNumber(); + + int labPos = labelPosition(); + + int spacer = 5; + int textWidth = 0; + int textHeight = p->fontMetrics().height(); + + QString aTitle = title(); + + int titleWidth = 0; + int titleHeight = 0; + + if ( qGray( bg.rgb() ) < 128 ) + p->setPen( QColor( 255, 255, 255 ) ); + else + p->setPen( QColor( 0, 0, 0 ) ); + + // Draw title + if ( drawTitle ) + { + QSimpleRichText* srt = simpleRichText( myFlags ); + if ( srt ) + { + srt->setWidth( p, W - 10 ); + titleHeight = srt->height() + spacer; + titleWidth = srt->widthUsed(); + QColorGroup cg = colorGroup(); + cg.setColor( QColorGroup::Text, p->pen().color() ); + srt->draw( p, X + 5, Y, QRect( 0, 0, srt->width(), srt->height() ), cg ); + + delete srt; + } + } + + bool reverse = testFlags( Reverse ); + + QValueList colors; + QValueList labels; + for ( int idx = 0; idx < num; idx++ ) + { + if ( reverse ) + { + colors.append( getColor( idx ) ); + labels.append( getLabel( idx ) ); + } + else + { + colors.prepend( getColor( idx ) ); + labels.prepend( getLabel( idx ) ); + } + } + + if ( testFlags( AtBorder ) ) + { + if ( reverse ) + labels.append( getLabel( num ) ); + else + labels.prepend( getLabel( num ) ); + if ( drawLabel ) + textWidth = QMAX( textWidth, p->fontMetrics().width( labels.last() ) ); + } + + if ( drawLabel ) + { + const QFontMetrics& fm = p->fontMetrics(); + for ( QStringList::ConstIterator it = labels.begin(); it != labels.end(); ++it ) + textWidth = QMAX( textWidth, fm.width( *it) ); + } + + int lab = labels.count(); + + double spc = ( H - ( ( QMIN( lab, 2 ) + QABS( lab - num - 1 ) ) * textHeight ) - titleHeight ); + double val = spc != 0 ? 1.0 * ( lab - QMIN( lab, 2 ) ) * textHeight / spc : 0; + double iPart; + double fPart = modf( val, &iPart ); + int filter = (int)iPart + ( fPart != 0 ? 1 : 0 ); + filter = QMAX( filter, 1 ); + + double step = 1.0 * ( H - ( lab - num + QABS( lab - num - 1 ) ) * textHeight - titleHeight ) / num; + + int ascent = p->fontMetrics().ascent(); + int colorWidth = QMAX( 5, QMIN( 20, W - textWidth - 3 * spacer ) ); + if ( labPos == Center || !drawLabel ) + colorWidth = W - 2 * spacer; + + // Draw colors + int x = X + spacer; + switch ( labPos ) + { + case Left: + x += textWidth + ( textWidth ? 1 : 0 ) * spacer; + break; + } + + double offset = 1.0 * textHeight / 2 * ( lab - num + QABS( lab - num - 1 ) ) + titleHeight; + QValueList::Iterator cit = colors.begin(); + uint ci = 0; + for ( ci = 0; cit != colors.end() && drawColors; ++cit, ci++ ) + { + int y = (int)( Y + ci * step + offset ); + int h = (int)( Y + ( ci + 1 ) * step + offset ) - y; + p->fillRect( x, y, colorWidth, h, *cit ); + } + + if ( drawColors ) + p->drawRect( int( x - 1 ), int( Y + offset - 1 ), int( colorWidth + 2 ), int( ci * step + 2 ) ); + + // Draw labels + offset = 1.0 * QABS( lab - num - 1 ) * ( step - textHeight ) / 2 + + 1.0 * QABS( lab - num - 1 ) * textHeight / 2; + offset += titleHeight; + if ( drawLabel && !labels.isEmpty() ) + { + int i1 = 0; + int i2 = lab - 1; + int last1( i1 ), last2( i2 ); + int x = X + spacer; + switch ( labPos ) + { + case Center: + x += ( colorWidth - textWidth ) / 2; + break; + case Right: + x += colorWidth + spacer; + break; + } + while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) ) + { + int pos1 = i1; + int pos2 = lab - 1 - i2; + if ( filter && !( pos1 % filter ) ) + { + p->drawText( x, (int)( Y + i1 * step + ascent + offset ), *labels.at( i1 ) ); + last1 = i1; + } + if ( filter && !( pos2 % filter ) ) + { + p->drawText( x, (int)( Y + i2 * step + ascent + offset ), *labels.at( i2 ) ); + last2 = i2; + } + i1++; + i2--; + } + int pos = i1; + int i0 = -1; + while ( pos <= i2 && i0 == -1 ) + { + if ( filter && !( pos % filter ) && + QABS( pos - last1 ) >= filter && QABS( pos - last2 ) >= filter ) + i0 = pos; + pos++; + } + + if ( i0 != -1 ) + p->drawText( x, (int)( Y + i0 * step + ascent + offset ), *labels.at( i0 ) ); + } +} + +//================================================================ +// Function : getFormat +// Purpose : Returns the format for number labels. +//================================================================ + +QString QtxColorScale::getFormat() const +{ + QString aFormat = format(); + + if ( !testFlags( PreciseFormat ) || testFlags( Integer ) ) + return aFormat; + + if ( !myPrecise.isEmpty() ) + return myPrecise; + + if ( aFormat.find( QRegExp( "^(%[0-9]*.?[0-9]*[fegFEG])$" ) ) != 0 ) + return aFormat; + + int pos1 = aFormat.find( '.' ); + int pos2 = aFormat.find( QRegExp( "[fegFEG]") ); + + QString aLocFormat; + int precision = 1; + if ( pos1 > 0 ) + { + aLocFormat = aFormat.mid( 0, pos1 + 1 ); + precision = aFormat.mid( pos1 + 1, pos2 - pos1 - 1 ).toInt(); + if ( precision < 1 ) + precision = 1; + } + else + return aFormat; + + QtxColorScale* that = (QtxColorScale*)this; + + // calculate format, maximum precision limited + // to 7 digits after the decimal point. + while ( myPrecise.isEmpty() && precision < 7 ) + { + QString aTmpFormat = aLocFormat; + aTmpFormat += QString( "%1" ).arg( precision ); + aTmpFormat += aFormat.mid( pos2 ); + + QMap map; + bool isHasTwinz = false; + + for ( int idx = 0; idx < intervalsNumber() && !isHasTwinz; idx++ ) + { + double val = getNumber( idx ); + QString tmpname = QString().sprintf( aTmpFormat, val ); + isHasTwinz = map.contains( tmpname ); + map.insert( tmpname, 1 ); + } + + if ( !isHasTwinz ) + that->myPrecise = aTmpFormat; + precision++; + } + + if ( !myPrecise.isEmpty() ) + aFormat = myPrecise; + + return aFormat; +} + +//================================================================ +// Function : getNumber +// Purpose : Returns the number for specified interval. +//================================================================ + +double QtxColorScale::getNumber( const int idx ) const +{ + double val = 0; + if ( intervalsNumber() > 0 ) + val = minimum() + idx * ( QABS( maximum() - minimum() ) / intervalsNumber() ); + return val; +} + +//================================================================ +// Function : getLabel +// Purpose : Returns the label for specified interval according +// to the current label mode. +//================================================================ + +QString QtxColorScale::getLabel( const int idx ) const +{ + QString res; + if ( labelMode() == User ) + res = label( idx ); + else + { + double val = getNumber( idx ); + res = QString().sprintf( getFormat(), testFlags( Integer ) ? (int)val : val ); + } + return res; +} + +//================================================================ +// Function : getColor +// Purpose : Returns the color for specified interval according +// to the current color mode. +//================================================================ + +QColor QtxColorScale::getColor( const int idx ) const +{ + QColor res; + if ( colorMode() == User ) + res = color( idx ); + else + res = Qtx::scaleColor( idx, 0, intervalsNumber() - 1 ); + return res; +} + +//================================================================ +// Function : updateScale +// Purpose : Update color scale if it required. +//================================================================ + +void QtxColorScale::updateScale() +{ + update(); + updateGeometry(); +} + +//================================================================ +// Function : simpleRichText +// Purpose : Return QSimpleRichText object for title. If title +// not defined (empty string) then return null pointer. +// Object should be deleted by caller function. +//================================================================ + +QSimpleRichText* QtxColorScale::simpleRichText( const int flags ) const +{ + QSimpleRichText* srt = 0; + + QString aTitle; + switch ( titlePosition() ) + { + case Left: + aTitle = QString( "

%1

" ); + break; + case Right: + aTitle = QString( "

%1

" ); + break; + case Center: + aTitle = QString( "

%1

" ); + break; + case None: + default: + break; + } + + if ( !aTitle.isEmpty() && !title().isEmpty() ) + { + if ( !myStyleSheet ) + { + QtxColorScale* that = (QtxColorScale*)this; + that->myStyleSheet = new QStyleSheet( that ); + } + + if ( myStyleSheet ) + { + QStyleSheetItem* item = myStyleSheet->item( "p" ); + if ( item ) + item->setWhiteSpaceMode( flags & WrapTitle ? QStyleSheetItem::WhiteSpaceNormal : + QStyleSheetItem::WhiteSpaceNoWrap ); + } + + aTitle = aTitle.arg( title() ); + srt = new QSimpleRichText( aTitle, font(), QString::null, myStyleSheet ); + } + + return srt; +} + +#if QT_VER == 3 + +/********************************************************************* +** Class: QtxColorScale::Dock +** Descr: Dockable window contains the color scale. +** Level: Public +*********************************************************************/ + +//================================================================ +// Function : Dock +// Purpose : Constructor. +//================================================================ + +QtxColorScale::Dock::Dock( Place p, QWidget* parent, const char* name, WFlags f ) +: QDockWindow( p, parent, name, f ), +myBlockShow( false ), +myBlockResize( false ) +{ + myScale = new QtxColorScale( this ); + + setWidget( myScale ); + + setCloseMode( Always ); + setMovingEnabled( true ); + setResizeEnabled( true ); + setHorizontalStretchable( false ); + + setCaption( tr ( "Color scale" ) ); +} + +//================================================================ +// Function : ~Dock +// Purpose : Destructor. +//================================================================ + +QtxColorScale::Dock::~Dock() +{ +} + +//================================================================ +// Function : colorScale +// Purpose : Returns color scale widget. +//================================================================ + +QtxColorScale* QtxColorScale::Dock::colorScale() const +{ + return myScale; +} + +//================================================================ +// Function : activate +// Purpose : Set the dockable window is visible for main window. +//================================================================ + +void QtxColorScale::Dock::activate() +{ + if ( myBlockShow ) + return; + + QMainWindow* mw = 0; + QWidget* p = parentWidget(); + while ( !mw && p ) + { + if ( p->inherits( "QMainWindow" ) ) + mw = (QMainWindow*)p; + p = p->parentWidget(); + } + if ( mw ) + mw->setAppropriate( this, true ); +} + +//================================================================ +// Function : deactivate +// Purpose : Set the dockable window is hidden for main window. +//================================================================ + +void QtxColorScale::Dock::deactivate() +{ + if ( myBlockShow ) + return; + + QMainWindow* mw = 0; + QWidget* p = parentWidget(); + while ( !mw && p ) + { + if ( p->inherits( "QMainWindow" ) ) + mw = (QMainWindow*)p; + p = p->parentWidget(); + } + if ( mw ) + mw->setAppropriate( this, false ); +} + +//================================================================ +// Function : isActive +// Purpose : Returns true if the dockable window is visible. +//================================================================ + +bool QtxColorScale::Dock::isActive() const +{ + QMainWindow* mw = 0; + QWidget* p = parentWidget(); + while ( !mw && p ) + { + if ( p->inherits( "QMainWindow" ) ) + mw = (QMainWindow*)p; + p = p->parentWidget(); + } + if ( mw ) + return mw->appropriate( (QDockWindow*)this ); + else + return false; +} + +//================================================================ +// Function : show +// Purpose : Reimplemented for internal reasons. +//================================================================ + +void QtxColorScale::Dock::show() +{ + bool f = myBlockShow; + myBlockShow = true; + QDockWindow::show(); + myBlockShow = f; +} + +//================================================================ +// Function : hide +// Purpose : Reimplemented for internal reasons. +//================================================================ + +void QtxColorScale::Dock::hide() +{ + bool f = myBlockShow; + myBlockShow = false; + QDockWindow::hide(); + myBlockShow = f; +} + +//================================================================ +// Function : resize +// Purpose : Make extent width as maximum value of widget width. +//================================================================ + +void QtxColorScale::Dock::resize( int w, int h ) +{ + QDockWindow::resize( w, h ); + + if ( myBlockResize ) + return; + + if ( orientation() == Qt::Vertical ) + setFixedExtentWidth( QMAX( fixedExtent().width(), w ) ); + else if ( orientation() == Qt::Horizontal ) + setFixedExtentHeight( QMAX( fixedExtent().height(), h ) ); +} + +//================================================================ +// Function : setOrientation +// Purpose : +//================================================================ + +void QtxColorScale::Dock::setOrientation( Orientation o ) +{ + bool b = myBlockResize; + myBlockResize = true; + QDockWindow::setOrientation( o ); + myBlockResize = b; +} + +#endif diff --git a/src/Qtx/QtxDblSpinBox.cxx b/src/Qtx/QtxDblSpinBox.cxx new file mode 100755 index 000000000..081259255 --- /dev/null +++ b/src/Qtx/QtxDblSpinBox.cxx @@ -0,0 +1,473 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxDblSpinBox.cxx +// Author: Sergey TELKOV + +#include "QtxDblSpinBox.h" + +#include +#include +#include + +/* + Class: QtxDblSpinBox::Validator [internal] + Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator) +*/ + +class QtxDblSpinBox::Validator : public QDoubleValidator +{ +public: + Validator( QtxDblSpinBox* sb, const char* name ) + : QDoubleValidator( sb, name ), spinBox( sb ) {} + + virtual State validate( QString& str, int& pos ) const; + +private: + QtxDblSpinBox* spinBox; +}; + +QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const +{ + QString pref = spinBox->prefix(); + QString suff = spinBox->suffix(); + uint overhead = pref.length() + suff.length(); + State state = Invalid; + + if ( overhead == 0 ) + state = QDoubleValidator::validate( str, pos ); + else + { + if ( str.length() >= overhead && str.startsWith( pref ) && + str.right( suff.length() ) == suff ) + { + QString core = str.mid( pref.length(), str.length() - overhead ); + int corePos = pos - pref.length(); + state = QDoubleValidator::validate( core, corePos ); + pos = corePos + pref.length(); + str.replace( pref.length(), str.length() - overhead, core ); + } + else + { + state = QDoubleValidator::validate( str, pos ); + if ( state == Invalid ) + { + QString special = spinBox->specialValueText().stripWhiteSpace(); + QString candidate = str.stripWhiteSpace(); + if ( special.startsWith( candidate ) ) + { + if ( candidate.length() == special.length() ) + state = Acceptable; + else + state = Intermediate; + } + } + } + } + return state; +} + +/* + Class: QtxDblSpinBox + Descr: Spin box for real numbers. +*/ + +QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name ) +: QSpinBox( parent, name ), +myCleared( false ), +myBlocked( false ), +myPrecision( 0 ) +{ + myMin = QRangeControl::minValue(); + myMax = QRangeControl::maxValue(); + myStep = QRangeControl::lineStep(); + myValue = myMin; + setValidator( new Validator( this, "double_spinbox_validator" ) ); + rangeChange(); + updateDisplay(); + + connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name ) +: QSpinBox( parent, name ), +myMin( min ), +myMax( max ), +myStep( step ), +myCleared( false ), +myBlocked( false ), +myPrecision( 0 ) +{ + myValue = myMin; + setValidator( new Validator( this, "double_spinbox_validator" ) ); + rangeChange(); + updateDisplay(); + + connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +QtxDblSpinBox::~QtxDblSpinBox() +{ +} + +double QtxDblSpinBox::minValue() const +{ + return myMin; +} + +double QtxDblSpinBox::maxValue() const +{ + return myMax; +} + +void QtxDblSpinBox::setMinValue( int min ) +{ + setMinValue( (double)min ); +} + +void QtxDblSpinBox::setMinValue( double min ) +{ + if ( myMin != min ) + { + myMin = min; + rangeChange(); + } +} + +void QtxDblSpinBox::setMaxValue( int max ) +{ + setMaxValue( (double)max ); +} + +void QtxDblSpinBox::setMaxValue( double max ) +{ + if ( myMax != max ) + { + myMax = max; + rangeChange(); + } +} + +void QtxDblSpinBox::setRange( int min, int max ) +{ + setRange( (double)min, (double)max ); +} + +void QtxDblSpinBox::setRange( double min, double max ) +{ + if ( myMin != min || myMax != max ) + { + myMin = min; + myMax = max; + rangeChange(); + } +} + +double QtxDblSpinBox::lineStep() const +{ + return myStep; +} + +void QtxDblSpinBox::setLineStep( int step ) +{ + setLineStep( (double)step ); +} + +void QtxDblSpinBox::setLineStep( double step ) +{ + myStep = step; +} + +double QtxDblSpinBox::value() const +{ + QSpinBox::value(); + + return myValue; +} + +void QtxDblSpinBox::setValue( int val ) +{ + setValue( (double)val ); +} + +void QtxDblSpinBox::setValue( double val ) +{ + myCleared = false; + double prevVal = myValue; + myValue = bound( val ); + if ( prevVal != myValue ) + valueChange(); +} + +void QtxDblSpinBox::stepUp() +{ + interpretText(); + if ( wrapping() && myValue + myStep > myMax ) + setValue( myMin ); + else + setValue( myValue + myStep ); +} + +void QtxDblSpinBox::stepDown() +{ + interpretText(); + if ( wrapping() && myValue - myStep < myMin ) + setValue( myMax ); + else + setValue( myValue - myStep ); +} + +int QtxDblSpinBox::precision() const +{ + return myPrecision; +} + +void QtxDblSpinBox::setPrecision( const int prec ) +{ + int newPrec = QMAX( prec, 0 ); + int oldPrec = QMAX( myPrecision, 0 ); + myPrecision = prec; + if ( newPrec != oldPrec ) + updateDisplay(); +} + +bool QtxDblSpinBox::isCleared() const +{ + return myCleared; +} + +void QtxDblSpinBox::setCleared( const bool on ) +{ + if ( myCleared == on ) + return; + + myCleared = on; + updateDisplay(); +} + +void QtxDblSpinBox::selectAll() +{ +#if QT_VER >= 3 + QSpinBox::selectAll(); +#else + editor()->selectAll(); +#endif +} + +bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e ) +{ + if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() ) + { + bool state = QSpinBox::eventFilter( o, e ); + if ( e->type() == QEvent::FocusOut && o == editor() ) + updateDisplay(); + return state; + } + + if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide ) + return false; + + if ( e->type() == QEvent::KeyPress && + ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) ) + { + QApplication::sendEvent( this, e ); + return true; + } + + return QSpinBox::eventFilter( o, e ); +} + +void QtxDblSpinBox::updateDisplay() +{ + if ( myBlocked ) + return; + + bool upd = editor()->isUpdatesEnabled(); + editor()->setUpdatesEnabled( false ); + + bool isBlock = myBlocked; + myBlocked = true; + + QString txt = currentValueText(); + + if ( myValue >= myMax ) + QSpinBox::setValue( QSpinBox::maxValue() ); + else if ( myValue <= myMin ) + QSpinBox::setValue( QSpinBox::minValue() ); + else + QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 ); + + QSpinBox::updateDisplay(); + + editor()->setUpdatesEnabled( upd ); + + editor()->setText( myCleared ? QString::null : txt ); + if ( !myCleared && editor()->hasFocus() ) + { + if ( editor()->text() == specialValueText() ) + editor()->selectAll(); + else + editor()->setSelection( prefix().length(), editor()->text().length() - prefix().length() - suffix().length() ); + } + else + editor()->setCursorPosition( 0 ); + + myBlocked = isBlock; +} + +void QtxDblSpinBox::interpretText() +{ + myCleared = false; + + bool ok = true; + bool done = false; + double newVal = 0; + if ( !specialValueText().isEmpty() ) + { + QString s = QString( text() ).stripWhiteSpace(); + QString t = QString( specialValueText() ).stripWhiteSpace(); + if ( s == t ) + { + newVal = minValue(); + done = true; + } + } + if ( !done ) + newVal = mapTextToDoubleValue( &ok ); + if ( ok ) + setValue( newVal ); + updateDisplay(); +} + +void QtxDblSpinBox::valueChange() +{ + updateDisplay(); + emit valueChanged( myValue ); + emit valueChanged( currentValueText() ); +} + +void QtxDblSpinBox::rangeChange() +{ + double min = QMIN( myMin, myMax ); + double max = QMAX( myMin, myMax ); + myMin = min; + myMax = max; + QDoubleValidator* v = ::qt_cast( validator() ); + if ( v ) + v->setRange( myMin, myMax ); + + if ( myMin == myMax ) + QSpinBox::setRange( 0, 0 ); + else + QSpinBox::setRange( 0, 2 ); + + setValue( myValue ); + updateDisplay(); +} + +QString QtxDblSpinBox::currentValueText() +{ + QString s; + if ( (myValue == minValue()) && !specialValueText().isEmpty() ) + s = specialValueText(); + else + { + s = prefix(); + s.append( mapValueToText( myValue ) ); + s.append( suffix() ); + } + return s; +} + +QString QtxDblSpinBox::mapValueToText( double v ) +{ + QString s; + s.setNum( v, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) ); + return removeTrailingZeroes( s ); +} + +QString QtxDblSpinBox::mapValueToText( int ) +{ + QString s; + s.setNum( myValue, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) ); + return removeTrailingZeroes( s ); +} + +double QtxDblSpinBox::mapTextToDoubleValue( bool* ok ) +{ + QString s = text(); + double newVal = s.toDouble( ok ); + if ( !(*ok) && !( !prefix() && !suffix() ) ) + { + s = cleanText(); + newVal = s.toDouble( ok ); + } + return newVal; +} + +double QtxDblSpinBox::bound( double val ) +{ + double newVal = val; + if ( newVal > myMax ) + newVal = myMax; + if ( newVal < myMin ) + newVal = myMin; + return newVal; +} + +void QtxDblSpinBox::leaveEvent( QEvent* e ) +{ + if ( !myCleared ) + QSpinBox::leaveEvent( e ); +} + +void QtxDblSpinBox::wheelEvent( QWheelEvent* e ) +{ + if ( !isEnabled() ) + return; + + QSpinBox::wheelEvent( e ); + updateDisplay(); +} + +void QtxDblSpinBox::onTextChanged( const QString& str ) +{ + if ( !myBlocked ) + myCleared = false; +} + +QString QtxDblSpinBox::removeTrailingZeroes( const QString& src ) const +{ + QString delim( "." ); + + int idx = src.findRev( delim ); + if ( idx == -1 ) + return src; + + QString iPart = src.left( idx ); + QString fPart = src.mid( idx + 1 ); + + while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' ) + fPart.remove( fPart.length() - 1, 1 ); + + QString res = iPart; + if ( !fPart.isEmpty() ) + res += delim + fPart; + + return res; +} diff --git a/src/Qtx/QtxListResourceEdit.cxx b/src/Qtx/QtxListResourceEdit.cxx new file mode 100644 index 000000000..75e74e998 --- /dev/null +++ b/src/Qtx/QtxListResourceEdit.cxx @@ -0,0 +1,1424 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxListResourceEdit.cxx +// Author: Sergey TELKOV + +#include "QtxListResourceEdit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QtxIntSpinBox.h" +#include "QtxDblSpinBox.h" +#include "QtxComboBox.h" +#include "QtxDirListEditor.h" + +/* + Class: QtxListResourceEdit + Descr: GUI implementation of QtxResourceEdit - manager of resources +*/ + +QtxListResourceEdit::QtxListResourceEdit( QtxResourceMgr* mgr, QWidget* parent ) +: QFrame( parent ), +QtxResourceEdit( mgr ) +{ + QVBoxLayout* main = new QVBoxLayout( this, 0, 5 ); + QGroupBox* base = new QGroupBox( 1, Qt::Vertical, "", this ); + base->setFrameStyle( QFrame::NoFrame ); + base->setInsideMargin( 0 ); + main->addWidget( base ); + + myList = new QListBox( base ); + myStack = new QWidgetStack( base ); + + myList->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + myStack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + myList->setSelectionMode( QListBox::Single ); + + connect( myList, SIGNAL( selectionChanged() ), this, SLOT( onSelectionChanged() ) ); + + setFocusProxy( myList ); + + updateState(); +} + +QtxListResourceEdit::~QtxListResourceEdit() +{ +} + +void QtxListResourceEdit::setItemProperty( const int id, const QString& prop, const QVariant& val ) +{ + Item* i = item( id ); + if ( !i ) + return; + + bool prev = i->isEmpty(); + + QtxResourceEdit::setItemProperty( id, prop, val ); + + bool next = i->isEmpty(); + + if ( prev != next ) + updateVisible(); +} + +void QtxListResourceEdit::onSelectionChanged() +{ + QString title = myList->text( myList->index( myList->selectedItem() ) ); + if ( title.isEmpty() ) + return; + + Item* i = 0; + QPtrList lst; + childItems( lst ); + for ( QPtrListIterator it( lst ); it.current() && !i; ++it ) + { + if ( it.current()->title() == title ) + i = it.current(); + } + + if ( i ) + myStack->raiseWidget( i->id() ); +} + +void QtxListResourceEdit::itemAdded( QtxResourceEdit::Item* i ) +{ + if ( !i ) + return; + + QPtrList items; + childItems( items ); + + if ( items.contains( i ) || items.contains( i->parentItem() ) ) + updateVisible(); +} + +QtxResourceEdit::Item* QtxListResourceEdit::createItem( const QString& title, const int ) +{ + Item* i = item( title, -1 ); + if ( i ) + return i; + + Category* category = new Category( this, myStack ); + myStack->addWidget( category, category->id() ); + + updateVisible(); + + if ( !myList->selectedItem() ) + myList->setSelected( 0, true ); + + updateState(); + + return category; +} + +void QtxListResourceEdit::changedResources( const QMap& map ) +{ + QMap idMap; + for ( QMap::ConstIterator it = map.begin(); it != map.end(); ++it ) + { + idMap.insert( it.key()->id(), it.data() ); + + emit resourceChanged( it.key()->id() ); + + QString sec, param; + it.key()->resource( sec, param ); + emit resourceChanged( sec, param ); + } + + emit resourcesChanged( idMap ); +} + +void QtxListResourceEdit::updateState() +{ + if ( myList->selectedItem() && myStack->visibleWidget() ) + myStack->show(); + else + myStack->hide(); +} + +void QtxListResourceEdit::updateVisible() +{ + QPtrList items; + childItems( items ); + + QString name = myList->text( myList->index( myList->selectedItem() ) ); + + myList->clear(); + for ( QPtrListIterator it( items ); it.current(); ++it ) + { + if ( it.current()->isEmpty() ) + continue; + + myList->insertItem( it.current()->title() ); + } + + int idx = -1; + for ( int i = 0; i < (int)myList->count() && idx == -1; i++ ) + { + if ( myList->text( i ) == name ) + idx = i; + } + + myList->setSelected( QMAX( idx, 0 ), true ); + + updateState(); +} + +/* + Class: QtxListResourceEdit::Category + Descr: GUI implementation of preferences category. +*/ + +QtxListResourceEdit::Category::Category( QtxListResourceEdit* edit, QWidget* parent ) +: QFrame( parent ), +Item( edit ) +{ + QVBoxLayout* main = new QVBoxLayout( this ); + QGroupBox* base = new QGroupBox( 1, Qt::Horizontal, "", this ); + base->setFrameStyle( QFrame::NoFrame ); + base->setInsideMargin( 0 ); + main->addWidget( base, 1 ); + + myTabs = new QTabWidget( base ); + myInfo = new QLabel( base ); + + myInfo->setAlignment( Qt::AlignCenter ); + myInfo->setFrameStyle( QFrame::WinPanel | QFrame::Raised ); + myInfo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + updateState(); +} + +QtxListResourceEdit::Category::~Category() +{ +} + +bool QtxListResourceEdit::Category::isEmpty() const +{ + return Item::isEmpty() && myInfo->text().isEmpty(); +} + +int QtxListResourceEdit::Category::type() const +{ + return -1; +} + +void QtxListResourceEdit::Category::store() +{ +} + +void QtxListResourceEdit::Category::retrieve() +{ +} + +QVariant QtxListResourceEdit::Category::property( const QString& prop ) const +{ + QVariant var; + if ( prop == QString( "information" ) || prop == QString( "info" ) ) + var = myInfo->text(); + return var; +} + +void QtxListResourceEdit::Category::setProperty( const QString& name, const QVariant& var ) +{ + QVariant prop = var; + if ( !prop.cast( QVariant::String ) ) + return; + + if ( name == QString( "information" ) || name == QString( "info" ) ) + myInfo->setText( prop.toString() ); + + updateState(); +} + +QtxResourceEdit::Item* QtxListResourceEdit::Category::createItem( const QString& title, const int ) +{ + Item* i = item( title, id() ); + if ( i ) + return i; + + Tab* tab = new Tab( resourceEdit(), this, this ); + myTabs->addTab( tab, title ); + + updateState(); + + return tab; +} + +void QtxListResourceEdit::Category::updateState() +{ + if ( myTabs->count() ) + myTabs->show(); + else + myTabs->hide(); + + if ( !myTabs->count() && !myInfo->text().isEmpty() ) + myInfo->show(); + else + myInfo->hide(); +} + +/* + Class: QtxListResourceEdit::Tab + Descr: GUI implementation of resources tab. +*/ + +QtxListResourceEdit::Tab::Tab( QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: QFrame( parent ), +Item( edit, pItem ) +{ + QVBoxLayout* main = new QVBoxLayout( this ); + QVBox* vbox = new QVBox( this ); + vbox->setMargin( 5 ); + myMainFrame = vbox; + main->addWidget( myMainFrame ); + main->addStretch( 1 ); +} + +QtxListResourceEdit::Tab::~Tab() +{ +} + +int QtxListResourceEdit::Tab::type() const +{ + return -1; +} + +void QtxListResourceEdit::Tab::store() +{ +} + +void QtxListResourceEdit::Tab::retrieve() +{ +} + +void QtxListResourceEdit::Tab::polish() +{ + QFrame::polish(); + + adjustLabels(); +} + +QtxResourceEdit::Item* QtxListResourceEdit::Tab::createItem( const QString& title, const int ) +{ + Item* i = item( title, id() ); + if ( i ) + return i; + + Group* group = new Group( title, resourceEdit(), this, myMainFrame ); + + return group; +} + +void QtxListResourceEdit::Tab::adjustLabels() +{ + QObjectList* labels = queryList( "QLabel" ); + if ( labels ) + { + int w = 0; + for ( QObjectListIt it1( *labels ); it1.current(); ++it1 ) + { + if ( it1.current()->isWidgetType() ) + { + QWidget* wid = (QWidget*)it1.current(); + w = QMAX( w, wid->sizeHint().width() ); + } + } + for ( QObjectListIt it2( *labels ); it2.current(); ++it2 ) + { + if ( it2.current()->isWidgetType() ) + { + QWidget* wid = (QWidget*)it2.current(); + wid->setMinimumWidth( w ); + } + } + delete labels; + } +} + +/* + Class: QtxListResourceEdit::Group + Descr: GUI implementation of resources group. +*/ + +QtxListResourceEdit::Group::Group( const QString& title, QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: QGroupBox( 2, Qt::Horizontal, title, parent ), +Item( edit, pItem ) +{ +} + +QtxListResourceEdit::Group::~Group() +{ +} + +int QtxListResourceEdit::Group::type() const +{ + return -1; +} + +void QtxListResourceEdit::Group::store() +{ +} + +void QtxListResourceEdit::Group::retrieve() +{ +} + +QVariant QtxListResourceEdit::Group::property( const QString& prop ) const +{ + QVariant var; + if ( prop == "columns" ) + var = QVariant( columns() ); + else if ( prop == "orientation" ) + var = QVariant( orientation() ); + else if ( prop == "frame" ) + var = QVariant( frameStyle() != QFrame::NoFrame ); + return var; +} + +void QtxListResourceEdit::Group::setProperty( const QString& name, const QVariant& var ) +{ + QVariant prop = var; + if ( !prop.cast( QVariant::Int ) ) + return; + + if ( name == QString( "columns" ) && prop.cast( QVariant::Int ) && prop.toInt() > 0 ) + setColumns( prop.toInt() ); + else if ( name == QString( "orientation" ) && prop.cast( QVariant::Int ) ) + { + int o = prop.toInt(); + if ( o == Qt::Horizontal || o == Qt::Vertical ) + setOrientation( (Orientation)o ); + } + else if ( name == "frame" && prop.cast( QVariant::Bool ) ) + { + setInsideMargin( prop.toBool() ? 5 : 0 ); + QGroupBox::setTitle( prop.toBool() ? Item::title() : QString::null ); + setFrameStyle( prop.toBool() ? QFrame::Box | QFrame::Sunken : QFrame::NoFrame ); + } +} + +void QtxListResourceEdit::Group::setTitle( const QString& title ) +{ + Item::setTitle( title ); + QGroupBox::setTitle( title ); +} + +QtxResourceEdit::Item* QtxListResourceEdit::Group::createItem( const QString& title, const int type ) +{ + Item* item = 0; + + switch ( type ) + { + case Color: + item = new ColorItem( title, resourceEdit(), this, this ); + break; + case Bool: + item = new StateItem( title, resourceEdit(), this, this ); + break; + case String: + item = new StringItem( title, resourceEdit(), this, this ); + break; + case Selector: + item = new SelectItem( title, resourceEdit(), this, this ); + break; + case DblSpin: + item = new DoubleSpinItem( title, resourceEdit(), this, this ); + break; + case IntSpin: + item = new IntegerSpinItem( title, resourceEdit(), this, this ); + break; + case Double: + item = new DoubleEditItem( title, resourceEdit(), this, this ); + break; + case Integer: + item = new IntegerEditItem( title, resourceEdit(), this, this ); + break; + case Space: + item = new Spacer( resourceEdit(), this, this ); + break; + case GroupBox: + item = new Group( title, resourceEdit(), this, this ); + break; + case Font: + item = new FontItem( title, resourceEdit(), this, this ); + break; + case DirList: + item = new DirListItem( title, resourceEdit(), this, this ); + break; + case File: + item = new FileItem( title, resourceEdit(), this, this ); + break; + } + + return item; +} + +/* + Class: QtxListResourceEdit::PrefItem + Descr: Base class for preferences items. +*/ + +QtxListResourceEdit::PrefItem::PrefItem( const int type, QtxResourceEdit* edit, Item* pi, QWidget* parent ) +: QHBox( parent ), +Item( edit, pi ), +myType( type ) +{ + setSpacing( 5 ); +} + +QtxListResourceEdit::PrefItem::~PrefItem() +{ +} + +int QtxListResourceEdit::PrefItem::type() const +{ + return myType; +} + +QtxResourceEdit::Item* QtxListResourceEdit::PrefItem::createItem( const QString&, const int ) +{ + return 0; +} + +/* + Class: QtxListResourceEdit::Spacer + Descr: GUI implementation of resources spacer. +*/ + +QtxListResourceEdit::Spacer::Spacer( QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: PrefItem( Space, edit, pItem, parent ) +{ + setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::Spacer::~Spacer() +{ +} + +void QtxListResourceEdit::Spacer::store() +{ +} + +void QtxListResourceEdit::Spacer::retrieve() +{ +} + +/* + Class: QtxListResourceEdit::SelectItem + Descr: GUI implementation of resources list item. +*/ + +QtxListResourceEdit::SelectItem::SelectItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Selector, edit, pItem, parent ) +{ + new QLabel( title, this ); + myList = new QComboBox( false, this ); + myList->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::SelectItem::~SelectItem() +{ +} + +void QtxListResourceEdit::SelectItem::store() +{ + int idx = myList->currentItem(); + if ( myIndex.contains( idx ) ) + setInteger( myIndex[idx] ); +} + +void QtxListResourceEdit::SelectItem::retrieve() +{ + int id = getInteger( -1 ); + + int idx = -1; + for ( QMap::ConstIterator it = myIndex.begin(); it != myIndex.end() && idx == -1; ++it ) + { + if ( it.data() == id ) + idx = it.key(); + } + + myList->setCurrentItem( idx ); +} + +QVariant QtxListResourceEdit::SelectItem::property( const QString& name ) const +{ + QVariant val; + if ( name == QString( "strings" ) ) + { + QStringList lst; + for ( int i = 0; i < (int)myList->count(); i++ ) + lst.append( myList->text( i ) ); + val = QVariant( lst ); + } + else if ( name == QString( "indexes" ) ) + { + QValueList lst; + for ( int i = 0; i < (int)myList->count(); i++ ) + lst.append( myIndex.contains( i ) ? myIndex[i] : 0 ); + val = QVariant( lst ); + } + return val; +} + +void QtxListResourceEdit::SelectItem::setProperty( const QString& name, const QVariant& val ) +{ + if ( name == QString( "strings" ) ) + setStrings( val ); + else if ( name == QString( "indexes" ) ) + setIndexes( val ); +} + +void QtxListResourceEdit::SelectItem::setStrings( const QVariant& var ) +{ + if ( var.type() != QVariant::StringList ) + return; + + setStrings( var.toStringList() ); +} + +void QtxListResourceEdit::SelectItem::setIndexes( const QVariant& var ) +{ + if ( var.type() != QVariant::List ) + return; + + QValueList varList = var.toList(); + QValueList lst; + for ( QValueList::const_iterator it = varList.begin(); it != varList.end(); ++it ) + { + if ( (*it).canCast( QVariant::Int ) ) + lst.append( (*it).toInt() ); + } + setIndexes( lst ); +} + +void QtxListResourceEdit::SelectItem::setStrings( const QStringList& lst ) +{ + myList->clear(); + myList->insertStringList( lst ); +} + +void QtxListResourceEdit::SelectItem::setIndexes( const QValueList& lst ) +{ + myIndex.clear(); + + int idx = 0; + for ( QValueList::const_iterator it = lst.begin(); it != lst.end(); ++it, idx++ ) + myIndex.insert( idx, *it ); +} + +/* + Class: QtxListResourceEdit::StateItem + Descr: GUI implementation of resources bool item. +*/ + +QtxListResourceEdit::StateItem::StateItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Bool, edit, pItem, parent ) +{ + myState = new QCheckBox( title, this ); + myState->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::StateItem::~StateItem() +{ +} + +void QtxListResourceEdit::StateItem::store() +{ + setBoolean( myState->isChecked() ); +} + +void QtxListResourceEdit::StateItem::retrieve() +{ + myState->setChecked( getBoolean() ); +} + +/* + Class: QtxListResourceEdit::StringItem + Descr: GUI implementation of resources string item. +*/ + +QtxListResourceEdit::StringItem::StringItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( String, edit, pItem, parent ) +{ + new QLabel( title, this ); + myString = new QLineEdit( this ); + myString->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::StringItem::~StringItem() +{ +} + +void QtxListResourceEdit::StringItem::store() +{ + setString( myString->text() ); +} + +void QtxListResourceEdit::StringItem::retrieve() +{ + myString->setText( getString() ); +} + +/* + Class: QtxListResourceEdit::IntegerEditItem + Descr: GUI implementation of resources integer item. +*/ + +QtxListResourceEdit::IntegerEditItem::IntegerEditItem( const QString& title, QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: PrefItem( Integer, edit, pItem, parent ) +{ + new QLabel( title, this ); + myInteger = new QLineEdit( this ); + myInteger->setValidator( new QIntValidator( myInteger ) ); + myInteger->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::IntegerEditItem::~IntegerEditItem() +{ +} + +void QtxListResourceEdit::IntegerEditItem::store() +{ + setString( myInteger->text() ); +} + +void QtxListResourceEdit::IntegerEditItem::retrieve() +{ + myInteger->setText( getString() ); +} + +/* + Class: QtxListResourceEdit::IntegerSpinItem + Descr: GUI implementation of resources integer item. +*/ + +QtxListResourceEdit::IntegerSpinItem::IntegerSpinItem( const QString& title, QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: PrefItem( IntSpin, edit, pItem, parent ) +{ + new QLabel( title, this ); + myInteger = new QtxIntSpinBox( this ); + myInteger->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::IntegerSpinItem::~IntegerSpinItem() +{ +} + +void QtxListResourceEdit::IntegerSpinItem::store() +{ + setInteger( myInteger->value() ); +} + +void QtxListResourceEdit::IntegerSpinItem::retrieve() +{ + myInteger->setValue( getInteger() ); +} + +QVariant QtxListResourceEdit::IntegerSpinItem::property( const QString& name ) const +{ + QVariant var; + if ( name == QString( "minimum" ) || name == QString( "min" ) ) + var = QVariant( myInteger->minValue() ); + else if ( name == QString( "maximum" ) || name == QString( "max" ) ) + var = QVariant( myInteger->maxValue() ); + else if ( name == QString( "step" ) ) + var = QVariant( myInteger->lineStep() ); + else if ( name == QString( "special" ) ) + var = QVariant( myInteger->specialValueText() ); + else if ( name == QString( "prefix" ) ) + var = QVariant( myInteger->prefix() ); + else if ( name == QString( "suffix" ) ) + var = QVariant( myInteger->suffix() ); + return var; +} + +void QtxListResourceEdit::IntegerSpinItem::setProperty( const QString& name, const QVariant& var ) +{ + QVariant prop = var; + + if ( ( name == QString( "minimum" ) || name == QString( "min" ) ) && prop.cast( QVariant::Int ) ) + myInteger->setMinValue( prop.toInt() ); + else if ( ( name == QString( "maximum" ) || name == QString( "max" ) ) && prop.cast( QVariant::Int ) ) + myInteger->setMaxValue( prop.toInt() ); + else if ( name == QString( "step" ) && prop.cast( QVariant::Int ) && prop.toInt() > 0 ) + myInteger->setLineStep( prop.toInt() ); + else if ( name == QString( "special" ) && prop.cast( QVariant::String ) ) + myInteger->setSpecialValueText( prop.toString() ); + else if ( name == QString( "prefix" ) && prop.cast( QVariant::String ) ) + myInteger->setPrefix( prop.toString() ); + else if ( name == QString( "suffix" ) && prop.cast( QVariant::String ) ) + myInteger->setSuffix( prop.toString() ); +} + +/* + Class: QtxListResourceEdit::DoubleEditItem + Descr: GUI implementation of resources string item. +*/ + +QtxListResourceEdit::DoubleEditItem::DoubleEditItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Double, edit, pItem, parent ) +{ + new QLabel( title, this ); + myDouble = new QLineEdit( this ); + myDouble->setValidator( new QDoubleValidator( myDouble ) ); + myDouble->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::DoubleEditItem::~DoubleEditItem() +{ +} + +void QtxListResourceEdit::DoubleEditItem::store() +{ + setString( myDouble->text() ); +} + +void QtxListResourceEdit::DoubleEditItem::retrieve() +{ + myDouble->setText( getString() ); +} + +/* + Class: QtxListResourceEdit::DoubleSpinItem + Descr: GUI implementation of resources double item. +*/ + +QtxListResourceEdit::DoubleSpinItem::DoubleSpinItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( DblSpin, edit, pItem, parent ) +{ + new QLabel( title, this ); + myDouble = new QtxDblSpinBox( this ); + myDouble->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::DoubleSpinItem::~DoubleSpinItem() +{ +} + +void QtxListResourceEdit::DoubleSpinItem::store() +{ + setDouble( myDouble->value() ); +} + +void QtxListResourceEdit::DoubleSpinItem::retrieve() +{ + myDouble->setValue( getDouble() ); +} + +QVariant QtxListResourceEdit::DoubleSpinItem::property( const QString& name ) const +{ + QVariant var; + if ( name == QString( "minimum" ) || name == QString( "min" ) ) + var = QVariant( myDouble->minValue() ); + else if ( name == QString( "maximum" ) || name == QString( "max" ) ) + var = QVariant( myDouble->maxValue() ); + else if ( name == QString( "precision" ) ) + var = QVariant( myDouble->precision() ); + else if ( name == QString( "step" ) ) + var = QVariant( myDouble->lineStep() ); + else if ( name == QString( "special" ) ) + var = QVariant( myDouble->specialValueText() ); + else if ( name == QString( "prefix" ) ) + var = QVariant( myDouble->prefix() ); + else if ( name == QString( "suffix" ) ) + var = QVariant( myDouble->suffix() ); + return var; +} + +void QtxListResourceEdit::DoubleSpinItem::setProperty( const QString& name, const QVariant& var ) +{ + QVariant prop = var; + + if ( ( name == QString( "minimum" ) || name == QString( "min" ) ) && prop.cast( QVariant::Double ) ) + myDouble->setMinValue( prop.toDouble() ); + else if ( ( name == QString( "maximum" ) || name == QString( "max" ) ) && prop.cast( QVariant::Double ) ) + myDouble->setMaxValue( prop.toDouble() ); + else if ( name == QString( "step" ) && prop.cast( QVariant::Double ) && prop.toDouble() > 0 ) + myDouble->setLineStep( prop.toDouble() ); + else if ( name == QString( "precision" ) && prop.cast( QVariant::Int ) && prop.toInt() > 0 ) + myDouble->setPrecision( prop.toInt() ); + else if ( name == QString( "special" ) && prop.cast( QVariant::String ) ) + myDouble->setSpecialValueText( prop.toString() ); + else if ( name == QString( "prefix" ) && prop.cast( QVariant::String ) ) + myDouble->setPrefix( prop.toString() ); + else if ( name == QString( "suffix" ) && prop.cast( QVariant::String ) ) + myDouble->setSuffix( prop.toString() ); +} + +/* + Class: QtxListResourceEdit::ColorItem + Descr: GUI implementation of resources color item. +*/ + +QtxListResourceEdit::ColorItem::ColorItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Color, edit, pItem, parent ) +{ + class ColorSelector : public QLabel + { + public: + ColorSelector( QWidget* parent = 0 ) : QLabel( parent ) + { + setFrameStyle( WinPanel | Raised ); + } + virtual ~ColorSelector() {} + virtual QSize minimumSizeHint() const + { + return QLabel::minimumSizeHint() + QSize( 0, 2 ); + } + + protected: + virtual void mousePressEvent( QMouseEvent* e ) + { + if ( e->button() == LeftButton ) + { + setFrameStyle( WinPanel | Sunken ); + QColor c = QColorDialog::getColor( paletteBackgroundColor(), this ); + if ( c.isValid() ) + setPaletteBackgroundColor( c ); + + setFrameStyle( WinPanel | Raised ); + } + } + }; + + new QLabel( title, this ); + myColor = new ColorSelector( this ); + myColor->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); +} + +QtxListResourceEdit::ColorItem::~ColorItem() +{ +} + +void QtxListResourceEdit::ColorItem::store() +{ + setColor( myColor->paletteBackgroundColor() ); +} + +void QtxListResourceEdit::ColorItem::retrieve() +{ + myColor->setPaletteBackgroundColor( getColor() ); +} + + +/* + Class: QtxListResourceEdit::FontItem + Descr: GUI implementation of resources font item. +*/ +QtxListResourceEdit::FontItem::FontItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Font, edit, pItem, parent ) +{ + new QLabel( title, this ); + myFamilies = new QtxComboBox( false, this ); + mySizes = new QtxComboBox( true, this ); + mySizes->setInsertionPolicy( QComboBox::NoInsertion ); + myBold = new QCheckBox( tr( "Bold" ), this ); + myItalic = new QCheckBox( tr( "Italic" ), this ); + myUnderline = new QCheckBox( tr( "Underline" ), this ); + myPreview = new QToolButton( this ); + myPreview->setText( "..." ); + + myFamilies->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); + mySizes->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); + + connect( myFamilies, SIGNAL( activated( int ) ), this, SLOT( onActivateFamily( int ) ) ); + connect( myPreview, SIGNAL( clicked() ), this, SLOT( onPreview() ) ); + + setProperty( "system", ( bool )true ); + setProperty( "widget_flags", ( int )All ); +} + +QtxListResourceEdit::FontItem::~FontItem() +{ +} + +void QtxListResourceEdit::FontItem::store() +{ + QFont f( family(), size() ); + bool bold, italic, underline; + params( bold, italic, underline ); + f.setBold( bold ); + f.setItalic( italic ); + f.setUnderline( underline ); + Item::setFont( f ); +} + +void QtxListResourceEdit::FontItem::retrieve() +{ + QFont f = getFont(); + setFamily( f.family() ); + setSize( f.pointSize() ); + setParams( f.bold(), f.italic(), f.underline() ); +} + +QVariant QtxListResourceEdit::FontItem::property( const QString& name ) const +{ + if( name=="system" ) + return myIsSystem; + + else if( name=="widget_flags" ) + return ( int )myFlags; + + if( myIsSystem ) + { + if( name=="families" ) + { + QFontDatabase fdb; + return fdb.families(); + } + + else if( name=="default_family" ) + { + QFontDatabase fdb; + QStringList fam = fdb.families(); + if( fam.count()>0 ) + return fam.first(); + else + return QString::null; + } + + else + { + QStringList parts = QStringList::split( ":", name ); + if( parts.count()==2 ) + { + if( parts[1]=="default_bold" || parts[1]=="default_italic" || parts[1]=="default_underline" ) + return false; + + else if( parts[1]=="sizes" ) + { + QFontDatabase fdb; + QValueList sizes = fdb.pointSizes( parts[0] ); + QValueList vsizes; + QValueList::const_iterator anIt = sizes.begin(), + aLast = sizes.end(); + for( ; anIt!=aLast; anIt++ ) + vsizes.append( *anIt ); + + return vsizes; + } + + else if( parts[1]=="default_size" ) + { + if( parts[0].isEmpty() ) + return 0; + + QFontDatabase fdb; + QValueList sizes = fdb.pointSizes( parts[0] ); + if( sizes.count()>0 ) + return sizes.first(); + else + return 0; + } + } + } + } + + else if( myProperties.contains( name ) ) + return myProperties[ name ]; + + return QVariant(); +} + +void QtxListResourceEdit::FontItem::setProperty( const QString& name, const QVariant& value ) +{ + if( name=="system" ) + { + if( !value.canCast( QVariant::Bool ) ) + return; + + bool isSystem = value.toBool(); + if( myIsSystem==isSystem ) + return; + + myIsSystem = isSystem; + + QVariant families = property( "families" ); + QString fam = family(); + + myFamilies->clear(); + if( families.canCast( QVariant::StringList ) ) + { + QStringList list = families.toStringList(); + myFamilies->insertStringList( list ); + } + + setFamily( fam ); + setSize( -1 ); //set default size + } + + else if( name=="widget_flags" ) + { + if( !value.canCast( QVariant::Int ) ) + return; + + int wf = value.toInt(); + + myFlags = wf; + myFamilies ->setShown( wf & Family ); + mySizes ->setShown( wf & Size ); + mySizes->lineEdit()->setReadOnly( ( wf & UserSize )==0 ); + myBold ->setShown( wf & Bold ); + myItalic ->setShown( wf & Italic ); + myUnderline->setShown( wf & Underline ); + bool isSystem = property( "system" ).canCast( QVariant::Bool ) ? property( "system" ).toBool() : false; + myPreview->setShown( ( wf & Preview ) && isSystem ); + + internalUpdate(); + } + + else + myProperties[ name ] = value; +} + +void QtxListResourceEdit::FontItem::setFamily( const QString& f ) +{ + QString curtext; + if( myFamilies->isShown() ) + { + if( myFamilies->listBox()->findItem( f, Qt::ExactMatch ) ) + curtext = f; + } + else + { + QVariant deffam = property( "default_family" ); + if( deffam.canCast( QVariant::String ) ) + curtext = deffam.toString(); + } + + int idx = -1; + for ( int i = 0; i < (int)myFamilies->count() && idx < 0; i++ ) + { + if ( myFamilies->text( i ) == curtext ) + idx = i; + } + + if ( idx >= 0 ) + myFamilies->setCurrentItem( idx ); + + onActivateFamily( idx ); +} + +QString QtxListResourceEdit::FontItem::family() const +{ + return myFamilies->currentText(); +} + +void QtxListResourceEdit::FontItem::setSize( const int s ) +{ + int cursize = -1; + if( mySizes->isShown() && s>0 ) + { + if( ( myFlags & UserSize ) || mySizes->listBox()->findItem( QString( "%1" ).arg( s ), Qt::ExactMatch ) ) + cursize = s; + } + else + { + QVariant defsize = property( QString( "%1:default_size" ).arg( family() ) ); + if( defsize.canCast( QVariant::Int ) ) + cursize = defsize.toInt(); + } + + mySizes->setCurrentText( cursize>0 ? QString( "%1" ).arg( cursize ) : "" ); +} + +int QtxListResourceEdit::FontItem::size() const +{ + QString s = mySizes->currentText(); + bool ok; + int pSize = s.toInt( &ok ); + return ( ok ? pSize : 0 ); +} + +void QtxListResourceEdit::FontItem::setParams( const bool bold, const bool italic, const bool underline ) +{ + bool curbold = false, curitalic = false, curunderline = false; + if( myBold->isShown() ) + curbold = bold; + else + { + QVariant def = property( QString( "%1:default_bold" ).arg( family() ) ); + if( def.canCast( QVariant::Bool ) ) + curbold = def.toBool(); + } + if( myItalic->isShown() ) + curitalic = italic; + else + { + QVariant def = property( QString( "%1:default_italic" ).arg( family() ) ); + if( def.canCast( QVariant::Bool ) ) + curitalic = def.toBool(); + } + if( myUnderline->isShown() ) + curunderline = underline; + else + { + QVariant def = property( QString( "%1:default_underline" ).arg( family() ) ); + if( def.canCast( QVariant::Bool ) ) + curunderline = def.toBool(); + } + myBold->setChecked( curbold ); + myItalic->setChecked( curitalic ); + myUnderline->setChecked( curunderline ); +} + +void QtxListResourceEdit::FontItem::params( bool& bold, bool& italic, bool& underline ) +{ + bold = myBold->isChecked(); + italic = myItalic->isChecked(); + underline = myUnderline->isChecked(); +} + +void QtxListResourceEdit::FontItem::internalUpdate() +{ + //update internal selection of font properties + setFamily( family() ); + setSize( size() ); + bool b1, b2, b3; + params( b1, b2, b3 ); + setParams( b1, b2, b3 ); +} + +void QtxListResourceEdit::FontItem::onActivateFamily( int ) +{ + QVariant sizes = property( QString( "%1:sizes" ).arg( family() ) ); + + int s = size(); + mySizes->clear(); + if( sizes.canCast( QVariant::List ) ) + { + QValueList list = sizes.toList(); + QStringList sizeItems; + QValueList::const_iterator anIt = list.begin(), + aLast = list.end(); + for( ; anIt!=aLast; anIt++ ) + if( (*anIt).canCast( QVariant::Int ) && (*anIt).toInt()>0 ) + sizeItems.append( QString( "%1" ).arg( (*anIt).toInt() ) ); + mySizes->insertStringList( sizeItems ); + } + setSize( s ); +} + +void QtxListResourceEdit::FontItem::onPreview() +{ + QFont f( family(), size() ); + bool bold, italic, underline; + params( bold, italic, underline ); + f.setBold( bold ); + f.setItalic( italic ); + f.setUnderline( underline ); + + bool ok; + f = QFontDialog::getFont( &ok, f ); + + if( ok ) + { + setFamily( f.family() ); + setSize( f.pointSize() ); + setParams( f.bold(), f.italic(), f.underline() ); + } +} + + + + + +/* + Class: QtxListResourceEdit::DirListItem + Descr: +*/ +QtxListResourceEdit::DirListItem::DirListItem( const QString& title, QtxResourceEdit* edit, Item* pItem, QWidget* parent ) +: PrefItem( Font, edit, pItem, parent ) +{ + myDirListEditor = new QtxDirListEditor( this ); +} + +QtxListResourceEdit::DirListItem::~DirListItem() +{ +} + +void QtxListResourceEdit::DirListItem::store() +{ + QStringList list; + myDirListEditor->getPathList(list); + setString( QString(list.join(";")) ); +} + +void QtxListResourceEdit::DirListItem::retrieve() +{ + myDirListEditor->setPathList(QStringList::split(";", getString())); +} + + + +/* + Class: QtxListResourceEdit::FileItem + Descr: GUI implementation of resources file item. +*/ +QtxListResourceEdit::FileItem::FileItem( const QString& title, QtxResourceEdit* edit, + Item* pItem, QWidget* parent ) +: PrefItem( Font, edit, pItem, parent ), + myFlags( QFileInfo::ReadUser ), + myIsExisting( true ), + myIsReadOnly ( true ), + myFileDlg( 0 ) +{ + new QLabel( title, this ); + myFile = new QLineEdit( this ); + myFile->setValidator( new FileValidator( this, myFile ) ); + myFile->setReadOnly( myIsReadOnly ); + myOpenFile = new QToolButton( this ); + myOpenFile->setText( "..." ); + connect( myOpenFile, SIGNAL( clicked() ), this, SLOT( onOpenFile() ) ); +} + +QtxListResourceEdit::FileItem::~FileItem() +{ + if( myFileDlg ) + delete myFileDlg; +} + +void QtxListResourceEdit::FileItem::store() +{ + setString( myFile->text() ); +} + +void QtxListResourceEdit::FileItem::retrieve() +{ + myFile->setText( getString() ); +} + +QVariant QtxListResourceEdit::FileItem::property( const QString& name ) const +{ + if( name=="filter" ) + return myFilter; + else if( name=="existing" ) + return myIsExisting; + else if( name=="flags" ) + return myFlags; + else if( name=="readOnly") + return myIsReadOnly; + + return QVariant(); +} + +void QtxListResourceEdit::FileItem::setProperty( const QString& name, const QVariant& value ) +{ + if( name=="filter" ) + { + if( value.canCast( QVariant::String ) ) + { + myFilter.clear(); + myFilter.append( value.toString() ); + } + else if( value.canCast( QVariant::StringList ) ) + myFilter = value.toStringList(); + } + else if( name=="existing" && value.canCast( QVariant::Bool ) ) + myIsExisting = value.toBool(); + + else if( name=="flags" && value.canCast( QVariant::UInt ) ) + myFlags = value.toUInt(); + + else if( name=="readOnly" && value.canCast( QVariant::Bool) ) { + myIsReadOnly = value.toBool(); + myFile->setReadOnly( myIsReadOnly ); + } +} + +void QtxListResourceEdit::FileItem::onOpenFile() +{ + if( !myFileDlg ) + { + myFileDlg = new QFileDialog( "." ); + connect( myFileDlg, SIGNAL( fileHighlighted( const QString& ) ), this, SLOT( onFileSelected( const QString& ) ) ); + } + + myFileDlg->setCaption( title() ); + myFileDlg->setFilters( myFilter ); + myFileDlg->setMode( myIsExisting ? QFileDialog::ExistingFile : QFileDialog::AnyFile ); + + if( myFileDlg->exec()==QDialog::Accepted ) + { + myFile->setText( myFileDlg->selectedFile() ); + } +} + +bool QtxListResourceEdit::FileItem::isFileCorrect( const QString& f ) const +{ + bool res = false; + QFileInfo info( f ); + if( !myIsExisting || info.exists() ) + res = info.isFile() && info.permission( myFlags ); + + return res; +} + +void QtxListResourceEdit::FileItem::onFileSelected( const QString& f ) +{ + if( myFileDlg && !isFileCorrect( f ) ) + myFileDlg->setSelection( "" ); +} + + + +QtxListResourceEdit::FileItem::FileValidator::FileValidator( FileItem* item, QObject* parent ) +: QValidator( parent ), + myItem( item ) +{ +} + +QtxListResourceEdit::FileItem::FileValidator::~FileValidator() +{ +} + +QValidator::State QtxListResourceEdit::FileItem::FileValidator::validate( QString& f, int& ) const +{ + if( myItem && myItem->isFileCorrect( f ) ) + return QValidator::Acceptable; + else + return QValidator::Intermediate; +} diff --git a/src/Qtx/QtxListResourceEdit.h b/src/Qtx/QtxListResourceEdit.h new file mode 100644 index 000000000..19713ca08 --- /dev/null +++ b/src/Qtx/QtxListResourceEdit.h @@ -0,0 +1,530 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxListResourceEdit.h +// Author: Sergey TELKOV + +#ifndef QTXLISTRESOURCEEDIT_H +#define QTXLISTRESOURCEEDIT_H + +#include "QtxResourceEdit.h" + +#include +#include +#include +#include +#include + +class QLabel; +class QListBox; +class QLineEdit; +class QCheckBox; +class QComboBox; +class QTabWidget; +class QWidgetStack; + +class QtxIntSpinBox; +class QtxDblSpinBox; + +class QtxDirListEditor; + +/* + Class: QtxListResourceEdit + Descr: GUI implementation of QtxResourceEdit - manager of resources +*/ + +class QTX_EXPORT QtxListResourceEdit : public QFrame, public QtxResourceEdit +{ + Q_OBJECT + +public: + class Tab; + class Group; + class Category; + class PrefItem; + + class Spacer; + class ColorItem; + class StateItem; + class SelectItem; + class StringItem; + class DoubleSpinItem; + class DoubleEditItem; + class IntegerSpinItem; + class IntegerEditItem; + class FontItem; + class FileItem; + class DirListItem; + + enum { Space, Bool, Color, String, Selector, DblSpin, IntSpin, Double, Integer, GroupBox, Font, DirList, File, User }; + +public: + QtxListResourceEdit( QtxResourceMgr*, QWidget* = 0 ); + virtual ~QtxListResourceEdit(); + + virtual void setItemProperty( const int, const QString&, const QVariant& ); + +signals: + void resourceChanged( int ); + void resourceChanged( QString&, QString& ); + void resourcesChanged( const QMap& ); + +private slots: + void onSelectionChanged(); + +protected: + virtual void itemAdded( Item* ); + virtual Item* createItem( const QString&, const int ); + virtual void changedResources( const QMap& ); + +private: + void updateState(); + void updateVisible(); + +private: + QListBox* myList; + QWidgetStack* myStack; +}; + +/* + Class: QtxListResourceEdit::Category + Descr: GUI implementation of 'Category' frame +*/ + +class QtxListResourceEdit::Category : public QFrame, public Item +{ +public: + Category( QtxListResourceEdit*, QWidget* = 0 ); + virtual ~Category(); + + virtual bool isEmpty() const; + + virtual int type() const; + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + +protected: + virtual Item* createItem( const QString&, const int ); + +private: + void updateState(); + +private: + QLabel* myInfo; + QTabWidget* myTabs; +}; + +/* + Class: QtxListResourceEdit::Tab + Descr: GUI implementation of resources tab. +*/ + +class QtxListResourceEdit::Tab : public QFrame, public Item +{ +public: + Tab( QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~Tab(); + + virtual int type() const; + virtual void store(); + virtual void retrieve(); + +public: + virtual void polish(); + +protected: + virtual Item* createItem( const QString&, const int ); + +private: + void adjustLabels(); + +private: + QWidget* myMainFrame; +}; + +/* + Class: QtxListResourceEdit::Group + Descr: GUI implementation of resources group. +*/ + +class QtxListResourceEdit::Group : public QGroupBox, public Item +{ +public: + Group( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~Group(); + + virtual int type() const; + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + + virtual void setTitle( const QString& ); + +protected: + virtual Item* createItem( const QString&, const int ); +}; + +/* + Class: QtxListResourceEdit::PrefItem + Descr: Base class for preferences items. +*/ + +class QtxListResourceEdit::PrefItem : public QHBox, public Item +{ +public: + PrefItem( const int, QtxResourceEdit*, Item* = 0, QWidget* = 0 ); + virtual ~PrefItem(); + + virtual int type() const; + +protected: + virtual Item* createItem( const QString&, const int ); + +private: + int myType; +}; + +/* + Class: QtxListResourceEdit::Spacer + Descr: GUI implementation of resources spacer. +*/ + +class QtxListResourceEdit::Spacer : public PrefItem +{ +public: + Spacer( QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~Spacer(); + + virtual void store(); + virtual void retrieve(); +}; + +/* + Class: QtxListResourceEdit::SelectItem + Descr: GUI implementation of resources selector item. +*/ + +class QtxListResourceEdit::SelectItem : public PrefItem +{ +public: + SelectItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~SelectItem(); + + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + +private: + void setStrings( const QVariant& ); + void setIndexes( const QVariant& ); + + void setStrings( const QStringList& ); + void setIndexes( const QValueList& ); + +private: + QComboBox* myList; + QMap myIndex; +}; + +/* + Class: QtxListResourceEdit::StateItem + Descr: GUI implementation of resources bool item. +*/ + +class QtxListResourceEdit::StateItem : public PrefItem +{ +public: + StateItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~StateItem(); + + virtual void store(); + virtual void retrieve(); + +private: + QCheckBox* myState; +}; + +/* + Class: QtxListResourceEdit::StringItem + Descr: GUI implementation of resources string item. +*/ + +class QtxListResourceEdit::StringItem : public PrefItem +{ +public: + StringItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~StringItem(); + + virtual void store(); + virtual void retrieve(); + +private: + QLineEdit* myString; +}; + +/* + Class: QtxListResourceEdit::IntegerEditItem + Descr: GUI implementation of resources integer item. +*/ + +class QtxListResourceEdit::IntegerEditItem : public PrefItem +{ +public: + IntegerEditItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~IntegerEditItem(); + + virtual void store(); + virtual void retrieve(); + +private: + QLineEdit* myInteger; +}; + +/* + Class: QtxListResourceEdit::IntegerSpinItem + Descr: GUI implementation of resources integer item. +*/ + +class QtxListResourceEdit::IntegerSpinItem : public PrefItem +{ +public: + IntegerSpinItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~IntegerSpinItem(); + + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + +private: + QtxIntSpinBox* myInteger; +}; + +/* + Class: QtxListResourceEdit::DoubleEditItem + Descr: GUI implementation of resources double item. +*/ + +class QtxListResourceEdit::DoubleEditItem : public PrefItem +{ +public: + DoubleEditItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~DoubleEditItem(); + + virtual void store(); + virtual void retrieve(); + +private: + QLineEdit* myDouble; +}; + +/* + Class: QtxListResourceEdit::DoubleSpinItem + Descr: GUI implementation of resources double item. +*/ + +class QtxListResourceEdit::DoubleSpinItem : public PrefItem +{ +public: + DoubleSpinItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~DoubleSpinItem(); + + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + +private: + QtxDblSpinBox* myDouble; +}; + +/* + Class: QtxListResourceEdit::ColorItem + Descr: GUI implementation of resources color item. +*/ + +class QtxListResourceEdit::ColorItem : public PrefItem +{ +public: + ColorItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~ColorItem(); + + virtual void store(); + virtual void retrieve(); + +private: + QWidget* myColor; +}; + +/* + Class: QtxListResourceEdit::FontItem + Descr: GUI implementation of resources font item. +*/ + +class QtxComboBox; +class QToolButton; + +class QtxListResourceEdit::FontItem : public PrefItem +{ + Q_OBJECT + +public: + typedef enum + { + Family = 0x01, + Size = 0x02, + UserSize = 0x04, + Bold = 0x08, + Italic = 0x10, + Underline = 0x20, + Preview = 0x40, + + All = Family | Size | UserSize | Bold | Italic | Underline | Preview + + } WidgetFlags; + +public: + FontItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~FontItem(); + + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + +private slots: + void onActivateFamily( int ); + void onPreview(); + +private: + void setFamily( const QString& ); + QString family() const; + void setSize( const int ); + int size() const; + void setParams( const bool, const bool, const bool ); + void params( bool&, bool&, bool& ); + void internalUpdate(); + +private: + int myFlags; + bool myIsSystem; + QtxComboBox *myFamilies, *mySizes; + QCheckBox *myBold, *myItalic, *myUnderline; + QToolButton *myPreview; + QMap myProperties; +}; + + +/*! + * \brief GUI implementation of resources directory list item. + * + * + */ +class QtxListResourceEdit::DirListItem : public PrefItem +{ + Q_OBJECT + +public: + + /*! + * \brief Constructor + */ + DirListItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + /*! + * \brief Destructor + */ + virtual ~DirListItem(); + + /*! + * \brief Stores the data + */ + virtual void store(); + + /*! + * \brief Retrieves the data + */ + virtual void retrieve(); + +private: + QtxDirListEditor* myDirListEditor; //!< The widget wich implements in GUI the list of directories +}; + +/* + Class: QtxListResourceEdit::FontItem + Descr: GUI implementation of resources font item. +*/ + +class QtxComboBox; +class QToolButton; +class QFileDialog; + +class QtxListResourceEdit::FileItem : public PrefItem +{ + Q_OBJECT + +private: + class FileValidator : public QValidator + { + public: + FileValidator( FileItem*, QObject* ); + ~FileValidator(); + + virtual QValidator::State validate( QString&, int& ) const; + + private: + FileItem* myItem; + }; + +public: + FileItem( const QString&, QtxResourceEdit*, Item*, QWidget* = 0 ); + virtual ~FileItem(); + + virtual void store(); + virtual void retrieve(); + + virtual QVariant property( const QString& ) const; + virtual void setProperty( const QString&, const QVariant& ); + + virtual bool isFileCorrect( const QString& ) const; + +private slots: + void onOpenFile(); + void onFileSelected( const QString& ); + +private: + uint myFlags; + bool myIsReadOnly; + QStringList myFilter; + bool myIsExisting; + QLineEdit* myFile; + QToolButton* myOpenFile; + QFileDialog* myFileDlg; +}; + + +#endif diff --git a/src/Qtx/QtxMainWindow.cxx b/src/Qtx/QtxMainWindow.cxx new file mode 100644 index 000000000..b8968ef8c --- /dev/null +++ b/src/Qtx/QtxMainWindow.cxx @@ -0,0 +1,383 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxMainWindow.cxx +// Author: Sergey TELKOV + +#include "QtxMainWindow.h" + +#include "QtxToolBar.h" +#include "QtxResourceMgr.h" + +#include +#include +#include +#include + +/*! + Class: QtxMainWindow::Filter [Internal] + Descr: Internal object with event filter for QtxMainWindow. +*/ + +class QtxMainWindow::Filter : public QObject +{ +public: + Filter( QWidget*, QtxMainWindow*, QObject* = 0 ); + virtual ~Filter(); + + virtual bool eventFilter( QObject*, QEvent* ); + +private: + QMainWindow* myMain; + QWidget* myWidget; +}; + +QtxMainWindow::Filter::Filter( QWidget* wid, QtxMainWindow* mw, QObject* parent ) +: QObject( parent ), +myMain( mw ), +myWidget( wid ) +{ + myMain->installEventFilter( this ); +}; + +QtxMainWindow::Filter::~Filter() +{ +} + +bool QtxMainWindow::Filter::eventFilter( QObject* o, QEvent* e ) +{ + if ( myMain == o && e->type() == QEvent::ChildRemoved && + myWidget == ((QChildEvent*)e)->child() ) + return true; + + return QObject::eventFilter( o, e ); +} + +/*! + Class: QtxMainWindow [Public] + Descr: Main window with support of dockable menubar/status bar + and geometry store/retrieve. +*/ + +QtxMainWindow::QtxMainWindow( QWidget* parent, const char* name, WFlags f ) +: QMainWindow( parent, name, f ), +myMode( -1 ), +myMenuBar( NULL ), +myStatusBar( NULL ) +{ +} + +QtxMainWindow::~QtxMainWindow() +{ + setDockableMenuBar( false ); + setDockableStatusBar( false ); +} + +bool QtxMainWindow::isDockableMenuBar() const +{ + return myMenuBar; +} + +void QtxMainWindow::setDockableMenuBar( const bool on ) +{ + if ( isDockableMenuBar() == on ) + return; + + QMenuBar* mb = menuBar(); + if ( !mb ) + return; + + if ( on && !myMenuBar ) + { + mb->setCaption( tr( "Menu bar" ) ); + QtxToolBar* dockMb = new QtxToolBar( true, this, "menu bar container" ); + myMenuBar = dockMb; + new Filter( mb, this, myMenuBar ); + dockMb->setWidget( mb ); + dockMb->setNewLine( true ); + dockMb->setStretchable( true ); + dockMb->setResizeEnabled( false ); + + moveDockWindow( dockMb, DockTop ); + setDockEnabled( dockMb, Left, false ); + setDockEnabled( dockMb, Right, false ); + + setAppropriate( dockMb, false ); + + connect( dockMb, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + } + else if ( !on && myMenuBar ) + { + mb->reparent( this, QPoint( 0, 0 ), mb->isVisibleTo( mb->parentWidget() ) ); + disconnect( myMenuBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + delete myMenuBar; + myMenuBar = 0; + QChildEvent ce( QEvent::ChildRemoved, mb ); + QApplication::sendEvent( this, &ce ); + } + + setUpLayout(); +} + +bool QtxMainWindow::isDockableStatusBar() const +{ + return myStatusBar; +} + +void QtxMainWindow::setDockableStatusBar( const bool on ) +{ + if ( isDockableStatusBar() == on ) + return; + + QStatusBar* sb = statusBar(); + if ( !sb ) + return; + + if ( on && !myStatusBar ) + { + sb->setCaption( tr( "Status bar" ) ); + QtxToolBar* dockSb = new QtxToolBar( true, this, "status bar container" ); + myStatusBar = dockSb; + new Filter( sb, this, myStatusBar ); + dockSb->setWidget( sb ); + dockSb->setNewLine( true ); + dockSb->setStretchable( true ); + dockSb->setResizeEnabled( false ); + sb->setMinimumWidth( 250 ); + + sb->setSizeGripEnabled( false ); + + moveDockWindow( dockSb, DockBottom ); + setDockEnabled( dockSb, Left, false ); + setDockEnabled( dockSb, Right, false ); + + setAppropriate( dockSb, false ); + + connect( dockSb, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + } + else if ( !on && myStatusBar ) + { + sb->reparent( this, QPoint( 0, 0 ), sb->isVisibleTo( sb->parentWidget() ) ); + disconnect( myStatusBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + delete myStatusBar; + myStatusBar = 0; + QChildEvent ce( QEvent::ChildRemoved, sb ); + QApplication::sendEvent( this, &ce ); + + sb->setSizeGripEnabled( true ); + } + + setUpLayout(); +} + +void QtxMainWindow::loadGeometry( QtxResourceMgr* resMgr, const QString& section ) +{ + QString sec = section.stripWhiteSpace(); + if ( !resMgr || sec.isEmpty() ) + return; + + int winState = -1; + if ( !resMgr->value( sec, "state", winState ) ) + { + QString stateStr; + if ( resMgr->value( sec, "state", stateStr ) ) + winState = windowState( stateStr ); + } + + int win_w = resMgr->integerValue( sec, "width", width() ); + int win_h = resMgr->integerValue( sec, "height", height() ); + + int winPosX = windowPosition( resMgr->stringValue( sec, QString( "pos_x" ), QString::null ) ); + int winPosY = windowPosition( resMgr->stringValue( sec, QString( "pos_y" ), QString::null ) ); + + QWidget* desk = QApplication::desktop(); + + int win_x = 0; + if ( winPosX == WP_Absolute ) + win_x = resMgr->integerValue( sec, "pos_x", x() ); + else if ( desk ) + win_x = relativeCoordinate( winPosX, desk->width(), win_w ); + + int win_y = 0; + if ( winPosX == WP_Absolute ) + win_y = resMgr->integerValue( sec, "pos_y", y() ); + else if ( desk ) + win_y = relativeCoordinate( winPosY, desk->height(), win_h ); + + bool vis = isVisibleTo( parentWidget() ); + + resize( win_w, win_h ); + move( win_x, win_y ); + + myMode = -1; + + if ( vis ) + QApplication::postEvent( this, new QCustomEvent( QEvent::User, (void*)winState ) ); + else + myMode = winState; +} + +void QtxMainWindow::show() +{ + if ( myMode != -1 ) + QApplication::postEvent( this, new QCustomEvent( QEvent::User, (void*)myMode ) ); + + myMode = -1; + + QMainWindow::show(); +} + +void QtxMainWindow::customEvent( QCustomEvent* e ) +{ + QMainWindow::customEvent( e ); + + int mode = (int)e->data(); + switch ( mode ) + { + case WS_Normal: + showNormal(); + break; + case WS_Minimized: + showMinimized(); + break; + case WS_Maximized: + showMaximized(); + break; + } +} + +int QtxMainWindow::relativeCoordinate( const int type, const int WH, const int wh ) const +{ + int res = 0; + switch ( type ) + { + case WP_Center: + res = ( WH - wh ) / 2; + break; + case WP_Left: + res = 0; + break; + case WP_Right: + res = WH - wh; + break; + } + return res; +} + +void QtxMainWindow::saveGeometry( QtxResourceMgr* resMgr, const QString& section ) const +{ + QString sec = section.stripWhiteSpace(); + if ( !resMgr || sec.isEmpty() ) + return; + + resMgr->setValue( sec, "pos_x", pos().x() ); + resMgr->setValue( sec, "pos_y", pos().y() ); + resMgr->setValue( sec, "width", width() ); + resMgr->setValue( sec, "height", height() ); + + int winState = WS_Normal; + if ( isMinimized() ) + winState = WS_Minimized; + else if ( isMaximized() ) + winState = WS_Maximized; + + resMgr->setValue( sec, "state", winState ); +} + +bool QtxMainWindow::eventFilter( QObject* o, QEvent* e ) +{ + return QMainWindow::eventFilter( o, e ); +} + +void QtxMainWindow::setAppropriate( QDockWindow* dw, bool a ) +{ + QMainWindow::setAppropriate( dw, myStatusBar != dw && myMenuBar != dw && a ); +} + +void QtxMainWindow::setUpLayout() +{ + QMainWindow::setUpLayout(); + + if ( myMenuBar && layout() ) + layout()->setMenuBar( 0 ); +} + +void QtxMainWindow::onDestroyed( QObject* obj ) +{ + QObject* o = 0; + if ( obj == myMenuBar ) + { + myMenuBar = 0; + o = menuBar(); + } + else if ( obj == myStatusBar ) + { + myStatusBar = 0; + o = statusBar(); + } + + if ( o ) + { + QChildEvent ce( QEvent::ChildRemoved, o ); + QApplication::sendEvent( this, &ce ); + } +} + +int QtxMainWindow::windowState( const QString& str ) const +{ + static QMap winStateMap; + if ( winStateMap.isEmpty() ) + { + winStateMap["normal"] = WS_Normal; + winStateMap["min"] = WS_Minimized; + winStateMap["mini"] = WS_Minimized; + winStateMap["minimized"] = WS_Minimized; + winStateMap["max"] = WS_Maximized; + winStateMap["maxi"] = WS_Maximized; + winStateMap["maximized"] = WS_Maximized; + winStateMap["hidden"] = WS_Hidden; + winStateMap["hided"] = WS_Hidden; + winStateMap["hide"] = WS_Hidden; + winStateMap["invisible"] = WS_Hidden; + } + + int res = -1; + QString stateStr = str.stripWhiteSpace().lower(); + if ( winStateMap.contains( stateStr ) ) + res = winStateMap[stateStr]; + return res; +} + +int QtxMainWindow::windowPosition( const QString& str ) const +{ + static QMap winPosMap; + if ( winPosMap.isEmpty() ) + { + winPosMap["center"] = WP_Center; + winPosMap["left"] = WP_Left; + winPosMap["right"] = WP_Right; + winPosMap["top"] = WP_Top; + winPosMap["bottom"] = WP_Bottom; + } + + int res = WP_Absolute; + QString posStr = str.stripWhiteSpace().lower(); + if ( winPosMap.contains( posStr ) ) + res = winPosMap[posStr]; + return res; +} diff --git a/src/Qtx/QtxMainWindow.h b/src/Qtx/QtxMainWindow.h new file mode 100644 index 000000000..c2aa1bdb7 --- /dev/null +++ b/src/Qtx/QtxMainWindow.h @@ -0,0 +1,78 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxMainWindow.h +// Author: Sergey TELKOV + +#ifndef QTXMAINWINDOW_H +#define QTXMAINWINDOW_H + +#include "Qtx.h" + +#include + +class QDockWindow; +class QtxResourceMgr; + +class QTX_EXPORT QtxMainWindow : public QMainWindow +{ + Q_OBJECT + + class Filter; + + enum { WS_Normal, WS_Minimized, WS_Maximized, WS_Hidden }; + enum { WP_Absolute, WP_Center, WP_Left, WP_Right, WP_Top = WP_Left, WP_Bottom = WP_Right }; + +public: + QtxMainWindow( QWidget* = 0, const char* = 0, WFlags = WType_TopLevel ); + virtual ~QtxMainWindow(); + + bool isDockableMenuBar() const; + void setDockableMenuBar( const bool ); + + bool isDockableStatusBar() const; + void setDockableStatusBar( const bool ); + + void loadGeometry( QtxResourceMgr*, const QString& ); + void saveGeometry( QtxResourceMgr*, const QString& ) const; + + virtual bool eventFilter( QObject*, QEvent* ); + +public slots: + virtual void show(); + virtual void setAppropriate( QDockWindow*, bool ); + +protected: + virtual void setUpLayout(); + virtual void customEvent( QCustomEvent* ); + +private slots: + void onDestroyed( QObject* ); + +private: + int windowState( const QString& ) const; + int windowPosition( const QString& ) const; + int relativeCoordinate( const int, const int, const int ) const; + +private: + int myMode; + QDockWindow* myMenuBar; + QDockWindow* myStatusBar; +}; + +#endif diff --git a/src/Qtx/QtxPopupMgr.cxx b/src/Qtx/QtxPopupMgr.cxx new file mode 100644 index 000000000..f01716c16 --- /dev/null +++ b/src/Qtx/QtxPopupMgr.cxx @@ -0,0 +1,735 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#include "QtxPopupMgr.h" +#include "QtxListOfOperations.h" +#include "QtxStdOperations.h" +#include "QtxAction.h" + +#include +#include + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxValue QtxPopupMgr::Selection::globalParam( const QString& str ) const +{ + if( str==selCountParam() ) + return count(); + + else if( str[0]==equality() ) + { + QtxSets::ValueSet set; + QString par = str.mid( 1 ); + + for( int i=0, n=count(); i CacheMap; + + QtxPopupMgr::Selection* mySel; + CacheMap myParamCache; +}; + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxCacheSelection::QtxCacheSelection( QtxPopupMgr::Selection* sel ) +: mySel( sel ) +{ +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxCacheSelection::~QtxCacheSelection() +{ +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +int QtxCacheSelection::count() const +{ + return mySel ? mySel->count() : 0; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxValue QtxCacheSelection::param( const int i, const QString& name ) const +{ + QString param_name = name + "#####" + QString::number( i ); + if( myParamCache.contains( param_name ) ) + return myParamCache[ param_name ]; + else + { + QtxValue v; + if( mySel ) + v = mySel->param( i, name ); + if( v.isValid() ) + ( ( CacheMap& )myParamCache ).insert( param_name, v ); + return v; + } +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxValue QtxCacheSelection::globalParam( const QString& name ) const +{ + if( myParamCache.contains( name ) ) + return myParamCache[ name ]; + else + { + QtxValue v; + if( mySel ) + v = mySel->globalParam( name ); + if( v.isValid() ) + ( ( CacheMap& )myParamCache ).insert( name, v ); + return v; + } +} + + + + + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::Operations::Operations( QtxPopupMgr* mgr ) +: QtxStrings(), + myPopupMgr( mgr ) +{ + QStringList aList; + aList.append( "every" ); + aList.append( "any" ); + aList.append( "onlyone" ); + addOperations( aList ); + + myParser = new QtxParser( mgr->myOperations ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::Operations::~Operations() +{ + delete myParser; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +int QtxPopupMgr::Operations::prior( const QString& op, bool isBin ) const +{ + if( !isBin && ( op=="every" || op=="any" || op=="onlyone" ) ) + return 1; + else + return QtxStrings::prior( op, isBin ); + +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxParser::Error QtxPopupMgr::Operations::calculate + ( const QString& op, QtxValue& v1, QtxValue& v2 ) const +{ + int ind = -1; + if( op=="every" ) + ind = 0; + else if( op=="any" ) + ind = 1; + else if( op=="onlyone" ) + ind = 2; + + if( ind>=0 && ind<=2 ) + { + QString val_name = op + "(" + v2.toString() + ")"; + QtxParser::Error err = QtxParser::OK; + + if( !myValues.contains( val_name ) ) + { + myParser->setExpr( v2.toString() ); + QStringList params, specific; + myParser->paramsList( params ); + + myParser->clear(); + myPopupMgr->setParams( myParser, specific ); + + QtxPopupMgr::Selection* sel = myPopupMgr->myCurrentSelection; + + int global_result = 0; + if( sel ) + for( int i=0, n=sel->count(); iparam( i, *anIt ); + if( v.isValid() ) + myParser->set( *anIt, v ); + else + return QtxParser::InvalidToken; + } + + QtxValue res = myParser->calculate(); + err = myParser->lastError(); + if( err==QtxParser::OK ) + if( res.type()==QVariant::Bool ) + { + if( res.toBool() ) + global_result++; + if( ind==2 && global_result>1 ) + break; + } + else + return QtxParser::InvalidResult; + else + return err; + } + + QtxValue& vv = ( QtxValue& )myValues[ val_name ]; + vv = ( ind==0 && global_result==sel->count() ) || + ( ind==1 ) || + ( ind==2 && global_result==1 ); + } + + v2 = myValues[ val_name ]; + + return err; + } + else + return QtxStrings::calculate( op, v1, v2 ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::Operations::clear() +{ + myValues.clear(); +} + + + + + + + + + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::QtxPopupMgr( QPopupMenu* popup, QObject* parent ) +: QtxActionMenuMgr( popup, parent ), + myCurrentSelection( 0 ) +{ + createOperations(); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::~QtxPopupMgr() +{ +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::createOperations() +{ + myOperations = new QtxListOfOperations; + myOperations->prepend( "logic", new QtxLogic(), 0 ); + myOperations->prepend( "arithm", new QtxArithmetics(), 50 ); + myOperations->append( "strings", new QtxStrings(), 100 ); + myOperations->append( "sets", new QtxSets(), 150 ); + myOperations->append( "custom", new Operations( this ), 200 ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +int QtxPopupMgr::registerAction( QAction* act, + const QString& visible, + const QString& toggle, + const int id ) +{ + int _id = QtxActionMenuMgr::registerAction( act, id ); + setRule( _id, visible, true ); + setRule( _id, toggle, false ); + return _id; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::unRegisterAction( const int id ) +{ + QAction* act = action( id ); + + myVisibility.remove( act ); + myToggle.remove( act ); + + remove( id ); + //QtxActionMenuMgr::unRegisterAction( id ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +bool QtxPopupMgr::hasRule( QAction* act, bool visibility ) const +{ + return map( visibility ).contains( act ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +bool QtxPopupMgr::hasRule( const int id, bool visibility ) const +{ + return hasRule( action( id ), visibility ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::setRule( QAction* act, const QString& rule, bool visibility ) +{ + if( !act || rule.isEmpty() ) + return; + + if( !hasRule( act, visibility ) ) + { + QtxParser* p = new QtxParser( myOperations, rule ); + if( p->lastError()==QtxParser::OK ) + map( visibility ).insert( act, p ); + else + delete p; + } + else + { + QtxParser* p = map( visibility )[ act ]; + p->setExpr( rule ); + if( p->lastError()!=QtxParser::OK ) + p->setExpr( QString() ); + } +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::setRule( const int id, const QString& rule, bool visibility ) +{ + setRule( action( id ), rule, visibility ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +bool result( QtxParser* p ) +{ + bool res = false; + if( p ) + { + QtxValue vv = p->calculate(); + res = p->lastError()==QtxParser::OK && + ( ( vv.type()==QVariant::Int && vv.toInt()!=0 ) || + ( vv.type()==QVariant::Bool && vv.toBool() ) ); + } + return res; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::setParams( QtxParser* p, QStringList& specific ) const +{ + if( !p || !myCurrentSelection ) + return; + + QStringList params; + + p->paramsList( params ); + QStringList::const_iterator anIt = params.begin(), + aLast = params.end(); + for( ; anIt!=aLast; anIt++ ) + { + QtxValue v = myCurrentSelection->globalParam( *anIt ); + if( v.isValid() ) + p->set( *anIt, v ); + else + specific.append( *anIt ); + } +} + +bool operator<( const QtxValue& v1, const QtxValue& v2 ) +{ + QVariant::Type t1 = v1.type(), t2 = v2.type(); + if( t1==t2 ) + { + switch( t1 ) + { + case QVariant::Int: + return v1.toInt() < v2.toInt(); + + case QVariant::Double: + return v1.toDouble() < v2.toDouble(); + + case QVariant::CString: + case QVariant::String: + return v1.toString() < v2.toString(); + + case QVariant::StringList: + case QVariant::List: + { + const QValueList& aList1 = v1.toList(), aList2 = v2.toList(); + QValueList::const_iterator + anIt1 = aList1.begin(), aLast1 = aList1.end(), + anIt2 = aList2.begin(), aLast2 = aList2.end(); + for( ; anIt1!=aLast1 && anIt2!=aLast2; anIt1++, anIt2++ ) + if( (*anIt1)!=(*anIt2) ) + return (*anIt1)<(*anIt2); + + return anIt1==aLast1 && anIt2!=aLast2; + } + + default: + return v1.toString()menuText(); + + bool res = false; + if( !act ) + return res; + + if( hasRule( act, visibility ) ) + { + QtxParser* p = map( visibility )[ act ]; + QStringList specific; + p->clear(); + ( ( Operations* )myOperations->operations( "custom" ) )->clear(); + + setParams( p, specific ); + + QMap,int> aCorteges; + QValueList c; + + if( specific.count()>0 ) + if( myCurrentSelection ) + { + res = false; + + for( int i=0, n=myCurrentSelection->count(); iparam( i, *anIt1 ) ); + aCorteges.insert( c, 0 ); + } + + //qDebug( QString( "%1 corteges" ).arg( aCorteges.count() ) ); + QMap,int>::const_iterator anIt = aCorteges.begin(), aLast = aCorteges.end(); + for( ; anIt!=aLast; anIt++ ) + { + QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end(); + const QValueList& aCortege = anIt.key(); + QValueList::const_iterator anIt2 = aCortege.begin(); + for( ; anIt1!=aLast1; anIt1++, anIt2++ ) + p->set( *anIt1, *anIt2 ); + res = res || result( p ); + } + + /* + for( int i=0, n=myCurrentSelection->count(); iset( *anIt1, myCurrentSelection->param( i, *anIt1 ) ); + res = res || result( p ); + }*/ + } + else + res = false; + else + res = result( p ); + } + + return res; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +bool QtxPopupMgr::isVisible( const int actId, const int place ) const +{ + bool res = QtxActionMenuMgr::isVisible( actId, place ); + QAction* act = action( actId ); + if( hasRule( act, true ) ) + res = res && isSatisfied( act, true ); + return res; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +void QtxPopupMgr::updatePopup( QPopupMenu* p, Selection* sel ) +{ + QTime t1 = QTime::currentTime(); + + if( !p || !sel ) + return; + + myCurrentSelection = new QtxCacheSelection( sel ); + RulesMap::iterator anIt = myToggle.begin(), + aLast = myToggle.end(); + for( ; anIt!=aLast; anIt++ ) + if( anIt.key()->isToggleAction() && hasRule( anIt.key(), false ) ) + anIt.key()->setOn( isSatisfied( anIt.key(), false ) ); + + setWidget( ( QWidget* )p ); + updateMenu(); + QTime t2 = QTime::currentTime(); + qDebug( QString( "update popup time = %1 msecs" ).arg( t1.msecsTo( t2 ) ) ); + qDebug( QString( "number of objects = %1" ).arg( myCurrentSelection->count() ) ); + + delete myCurrentSelection; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::RulesMap& QtxPopupMgr::map( bool visibility ) const +{ + return ( RulesMap& )( visibility ? myVisibility : myToggle ); +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +bool QtxPopupMgr::load( const QString& fname, QtxActionMgr::Reader& r ) +{ + PopupCreator cr( &r, this ); + return r.read( fname, cr ); +} + + + + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::PopupCreator::PopupCreator( QtxActionMgr::Reader* r, + QtxPopupMgr* mgr ) +: QtxActionMgr::Creator( r ), + myMgr( mgr ) +{ +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QtxPopupMgr::PopupCreator::~PopupCreator() +{ +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +int QtxPopupMgr::PopupCreator::append( const QString& tag, const bool subMenu, + const ItemAttributes& attr, const int pId ) +{ + if( !myMgr || !reader() ) + return -1; + + QString label = reader()->option( "label", "label" ), + id = reader()->option( "id", "id" ), + pos = reader()->option( "pos", "pos" ), + group = reader()->option( "group", "group" ), + tooltip = reader()->option( "tooltip", "tooltip" ), + sep = reader()->option( "separator", "separator" ), + accel = reader()->option( "accel", "accel" ), + icon = reader()->option( "icon", "icon" ), + toggle = reader()->option( "toggle", "toggle" ); + + int res = -1, actId = intValue( attr, id, -1 );; + if( subMenu ) + res = myMgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) ); + else if( tag==sep ) + res = myMgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) ); + else //if( !myMgr->contains( actId ) ) + { + QPixmap pix; QIconSet set; + QString name = strValue( attr, icon ); + if( !name.isEmpty() ) + { + if( loadPixmap( name, pix ) ) + set = QIconSet( pix ); + } + + QString actLabel = strValue( attr, label ); + QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, actLabel, + QKeySequence( strValue( attr, accel ) ), + myMgr ); + newAct->setToolTip( strValue( attr, tooltip ) ); + QString toggleact = strValue( attr, toggle ); + bool isToggle = !toggleact.isEmpty(); + newAct->setToggleAction( isToggle ); + newAct->setOn( toggleact.lower()=="true" ); + + connect( newAct ); + int aid = myMgr->registerAction( newAct, visibleRule( attr ), + isToggle ? toggleRule( attr ) : QString::null, + actId ); + res = myMgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) ); + } + + return res; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QString QtxPopupMgr::PopupCreator::visibleRule( const ItemAttributes& ) const +{ + return QString::null; +} + +//================================================================ +// Function : +// Purpose : +//================================================================ +QString QtxPopupMgr::PopupCreator::toggleRule( const ItemAttributes& ) const +{ + return QString::null; +} diff --git a/src/Qtx/QtxPopupMgr.h b/src/Qtx/QtxPopupMgr.h new file mode 100644 index 000000000..a75a7dced --- /dev/null +++ b/src/Qtx/QtxPopupMgr.h @@ -0,0 +1,136 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// + +#ifndef __QTX_POPUP_MGR_HEADER__ +#define __QTX_POPUP_MGR_HEADER__ + +#include "Qtx.h" +#include "QtxActionMenuMgr.h" +#include "QtxParser.h" +#include "QtxStdOperations.h" + +#include + +class QtxListOfOperations; + +//================================================================ +// Class : +// Purpose : +//================================================================ +class QTX_EXPORT QtxPopupMgr : public QtxActionMenuMgr +{ + Q_OBJECT + +public: + class QTX_EXPORT Selection + { + public: + virtual int count() const = 0; + virtual QtxValue param( const int, const QString& ) const = 0; + virtual QtxValue globalParam( const QString& ) const; + + virtual QChar equality() const; + virtual QString selCountParam() const; + + static QChar defEquality(); + static QString defSelCountParam(); + }; + +protected: + class Operations : public QtxStrings + { + public: + Operations( QtxPopupMgr* ); + virtual ~Operations(); + + virtual int prior( const QString&, bool isBin ) const; + virtual QtxParser::Error calculate( const QString&, QtxValue&, QtxValue& ) const; + + void clear(); + + private: + QtxPopupMgr* myPopupMgr; + QtxParser* myParser; + QMap< QString, QtxValue > myValues; + }; + + friend class Operations; + +protected: + class PopupCreator; + +public: + QtxPopupMgr( QPopupMenu*, QObject* = 0 ); + virtual ~QtxPopupMgr(); + + virtual int registerAction( QAction*, + const QString& visible, + const QString& toggle = QString::null, + const int = -1 ); + virtual void unRegisterAction( const int ); + + virtual bool isVisible( const int actId, const int place ) const; + + bool hasRule( QAction*, bool visibility ) const; + bool hasRule( const int, bool visibility ) const; + void setRule( QAction*, const QString&, bool visibility ); + void setRule( const int, const QString&, bool visibility ); + void updatePopup( QPopupMenu*, Selection* ); + + //return name of parameter corresponding to selected objects count + //it will be set automatically + + virtual bool load( const QString&, QtxActionMgr::Reader& ); + +protected: + typedef QMap< QAction*, QtxParser* > RulesMap; + +protected: + virtual bool isSatisfied( QAction*, bool visibility ) const; + void setParams( QtxParser*, QStringList& ) const; + RulesMap& map( bool visibility ) const; + + void createOperations(); + +private: + RulesMap myVisibility, myToggle; + Selection* myCurrentSelection; + QtxListOfOperations* myOperations; +}; + + + +class QtxPopupMgr::PopupCreator : public QtxActionMgr::Creator +{ +public: + PopupCreator( QtxActionMgr::Reader*, QtxPopupMgr* ); + virtual ~PopupCreator(); + + virtual int append( const QString&, const bool, + const ItemAttributes&, const int ); + + virtual QString visibleRule( const ItemAttributes& ) const; + virtual QString toggleRule( const ItemAttributes& ) const; + +private: + QtxPopupMgr* myMgr; +}; + + +#endif diff --git a/src/Qtx/QtxWorkstack.cxx b/src/Qtx/QtxWorkstack.cxx new file mode 100644 index 000000000..c267236f2 --- /dev/null +++ b/src/Qtx/QtxWorkstack.cxx @@ -0,0 +1,2011 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxWorkstack.cxx +// Author: Sergey TELKOV + +#include "QtxWorkstack.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DARK_COLOR_LIGHT 250 +/*! + Class: QtxWorkstack [Public] + Descr: +*/ + +QtxWorkstack::QtxWorkstack( QWidget* parent ) +: QWidget( parent ), +myWin( 0 ), +myArea( 0 ), +myWorkWin( 0 ), +myWorkArea( 0 ) +{ + myActionsMap.insert( SplitVertical, new QAction( tr( "Split vertically" ), 0, this ) ); + myActionsMap.insert( SplitHorizontal, new QAction( tr( "Split horizontally" ), 0, this ) ); + myActionsMap.insert( Close, new QAction( tr( "Close" ), 0, this ) ); + myActionsMap.insert( Rename, new QAction( tr( "Rename" ), 0, this ) ); + + connect( myActionsMap[SplitVertical], SIGNAL( activated() ), this, SLOT( splitVertical() ) ); + connect( myActionsMap[SplitHorizontal], SIGNAL( activated() ), this, SLOT( splitHorizontal() ) ); + connect( myActionsMap[Close], SIGNAL( activated() ), this, SLOT( onCloseWindow() ) ); + connect( myActionsMap[Rename], SIGNAL( activated() ), this, SLOT( onRename() ) ); + + QVBoxLayout* base = new QVBoxLayout( this ); + mySplit = new QSplitter( this ); + mySplit->setChildrenCollapsible( false ); + base->addWidget( mySplit ); +} + +QtxWorkstack::~QtxWorkstack() +{ +} + +QWidgetList QtxWorkstack::windowList() const +{ + QPtrList lst; + areas( mySplit, lst, true ); + + QWidgetList widList; + for ( QPtrListIterator it( lst ); it.current(); ++it ) + { + QWidgetList wids = it.current()->widgetList(); + for ( QWidgetListIt itr( wids ); itr.current(); ++itr ) + widList.append( itr.current() ); + } + + return widList; +} + +QWidgetList QtxWorkstack::splitWindowList() const +{ + return myArea ? myArea->widgetList() : QWidgetList(); +} + +QWidget* QtxWorkstack::activeWindow() const +{ + return myWin; +} + +void QtxWorkstack::split( const int o ) +{ + QtxWorkstackArea* area = myWorkArea; + if ( !area ) + area = activeArea(); + if ( !area ) + return; + + if ( area->widgetList().count() < 2 ) + return; + + QWidget* curWid = area->activeWidget(); + if ( !curWid ) + return; + + QSplitter* s = splitter( area ); + QPtrList areaList; + areas( s, areaList ); + + QPtrList splitList; + splitters( s, splitList ); + + QSplitter* trg = 0; + if ( areaList.count() + splitList.count() < 2 || s->orientation() == o ) + trg = s; + + if ( !trg ) + trg = wrapSplitter( area ); + + if ( !trg ) + return; + + trg->setOrientation( (Orientation)o ); + + QtxWorkstackArea* newArea = createArea( 0 ); + insertWidget( newArea, trg, area ); + + area->removeWidget( curWid ); + newArea->insertWidget( curWid ); + + distributeSpace( trg ); + + curWid->show(); + curWid->setFocus(); +} + +/*! +* \brief Split workarea of the given widget on two parts. +* \param wid - widget, belonging to this workstack +* \param o - orientation of splitting (Qt::Horizontal or Qt::Vertical) +* \param type - type of splitting, see SplitType enumeration +*/ +void QtxWorkstack::Split (QWidget* wid, const Qt::Orientation o, const SplitType type) +{ + if (!wid) return; + + // find area of the given widget + QtxWorkstackArea* area = NULL; + QPtrList allAreas; + areas(mySplit, allAreas, true); + + QPtrListIterator it (allAreas); + for (; it.current() && !area; ++it) { + if (it.current()->contains(wid)) + area = it.current(); + } + if (!area) return; + + QWidgetList wids = area->widgetList(); + if (wids.count() < 2) + return; + + QSplitter* s = splitter(area); + QPtrList areaList; + areas(s, areaList); + + QPtrList splitList; + splitters(s, splitList); + + QSplitter* trg = 0; + if (areaList.count() + splitList.count() < 2 || s->orientation() == o) + trg = s; + + if (!trg) trg = wrapSplitter(area); + if (!trg) return; + + trg->setOrientation(o); + + QtxWorkstackArea* newArea = createArea(0); + insertWidget(newArea, trg, area); + + switch (type) { + case SPLIT_STAY: + { + QWidgetListIt itr (wids); + for (; itr.current(); ++itr) + { + QWidget* wid_i = itr.current(); + if (wid_i != wid) { + area->removeWidget(wid_i); + newArea->insertWidget(wid_i); + } + } + } + break; + case SPLIT_AT: + { + QWidgetListIt itr (wids); + for (; itr.current() && itr.current() != wid; ++itr) { + } + for (; itr.current(); ++itr) { + area->removeWidget(itr.current()); + newArea->insertWidget(itr.current()); + } + } + break; + case SPLIT_MOVE: + area->removeWidget(wid); + newArea->insertWidget(wid); + break; + } + + distributeSpace(trg); +} + +/*! +* \brief Put given widget on top of its workarea +* \param wid - widget, belonging to this workstack +*/ +/* +void QtxWorkstack::OnTop (QWidget* wid) +{ + if ( !wid ) + return; + + // find area of the given widget + QtxWorkstackArea* area = 0; + QPtrList allAreas; + areas( mySplit, allAreas, true ); + for ( QPtrListIterator it( allAreas ); it.current() && !area; ++it ) + { + if ( it.current()->contains( wid ) ) + area = it.current(); + } + + if ( area ) + area->setActiveWidget( wid ); +} +*/ + +/*! +* \brief Move widget(s) from source workarea into target workarea +* or just reorder widgets inside one workarea. +* \param wid1 - widget from target workarea +* \param wid2 - widget from source workarea +* \param all - if this parameter is TRUE, all widgets from source workarea will +* be moved into the target one, else only the \a wid2 will be moved +* +* Move \a wid2 in target workarea. Put it right after \a wid1. +* If value of boolean argument is TRUE, all widgets from source workarea +* will be moved together with \a wid2, source workarea will be deleted. +* If \a wid1 and \a wid2 belongs to one workarea, simple reordering will take place. +*/ +void QtxWorkstack::Attract ( QWidget* wid1, QWidget* wid2, const bool all ) +{ + if ( !wid1 || !wid2 ) + return; + + // find area of the widgets + QtxWorkstackArea *area1 = NULL, *area2 = NULL; + QPtrList allAreas; + areas(mySplit, allAreas, true); + QPtrListIterator it (allAreas); + for (; it.current() && !(area1 && area2); ++it) { + if (it.current()->contains(wid1)) + area1 = it.current(); + if (it.current()->contains(wid2)) + area2 = it.current(); + } + if (!area1 || !area2) return; + + QWidget* curWid = area1->activeWidget(); + if (!curWid) return; + + if (area1 == area2) { + if (all) { + // Set wid1 at first position, wid2 at second + area1->insertWidget(wid1); + area1->insertWidget(wid2, 1); + } else { + // Set wid2 right after wid1 + area1->removeWidget(wid2); + int wid1_ind = 0; + QWidgetList wids1 = area1->widgetList(); + QWidgetListIt itr1 (wids1); + for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind); + area1->insertWidget(wid2, wid1_ind + 1); + } + } else { + int wid1_ind = 0; + QWidgetList wids1 = area1->widgetList(); + QWidgetListIt itr1 (wids1); + for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind); + + if (all) { + // Set wid2 right after wid1, other widgets from area2 right after wid2 + QWidgetList wids2 = area2->widgetList(); + QWidgetListIt itr2 (wids2); + for (int ind = wid1_ind + 1; itr2.current(); ++itr2, ++ind) + { + area2->removeWidget(itr2.current()); + if (itr2.current() == wid2) { + area1->insertWidget(itr2.current(), wid1_ind + 1); + } else { + area1->insertWidget(itr2.current(), ind); + } + } + } else { + // Set wid2 right after wid1 + area2->removeWidget(wid2); + area1->insertWidget(wid2, wid1_ind + 1); + } + } + + area1->setActiveWidget( curWid ); +} + +static void setSizes (QIntList& szList, const int item_ind, + const int new_near, const int new_this, const int new_farr) +{ + // set size to all items before an item # + int cur_pos = 0; + QIntList::iterator its = szList.begin(); + for (; its != szList.end() && cur_pos < item_ind; ++its, ++cur_pos) { + *its = new_near; + } + if (its == szList.end()) return; + // set size to item # + *its = new_this; + ++its; + // set size to all items after an item # + for (; its != szList.end(); ++its) { + *its = new_farr; + } +} + +/*! +* \brief Set position of the widget relatively its splitter. +* \param wid - widget to set position of +* \param pos - position relatively splitter. Value in range [0..1]. +* +* Orientation of positioning will correspond to the splitter orientation. +*/ +void QtxWorkstack::SetRelativePositionInSplitter( QWidget* wid, const double position ) +{ + if ( position < 0.0 || 1.0 < position) + return; + + if ( !wid ) + return; + + // find area of the given widget + QtxWorkstackArea* area = NULL; + QPtrList allAreas; + areas(mySplit, allAreas, true); + for ( QPtrListIterator it( allAreas ); + it.current() && !area; + ++it ) + { + if (it.current()->contains(wid)) + area = it.current(); + } + + if ( !area ) + return; + + QSplitter* split = splitter( area ); + if ( !split ) + return; + + // find index of the area in its splitter + int item_ind = -1; + bool isFound = false; + const QObjectList* was = split->children(); + for (QObjectListIt ito (*was); ito.current() && !isFound; ++ito, ++item_ind) + { + if (ito.current() == area) + isFound = true; + } + if (!isFound || item_ind == 0) + return; + + QIntList szList = split->sizes(); + int splitter_size = (split->orientation() == Horizontal ? + split->width() : split->height()); + int nb = szList.count(); + + int new_prev = int(splitter_size * position / item_ind); + int new_next = int(splitter_size * (1.0 - position) / (nb - item_ind)); + setSizes (szList, item_ind, new_prev, new_next, new_next); + split->setSizes(szList); +} + +/*! +* \brief Set position of the widget relatively the entire workstack. +* \param wid - widget to set position of +* \param o - orientation of positioning (Qt::Horizontal or Qt::Vertical). +* If o = Qt::Horizontal, horizontal position of \a wid will be changed. +* If o = Qt::Vertical, vertical position of \a wid will be changed. +* \param pos - position relatively workstack. Value in range [0..1]. +*/ +void QtxWorkstack::SetRelativePosition( QWidget* wid, const Qt::Orientation o, + const double position ) +{ + if ( position < 0.0 || 1.0 < position ) + return; + + if ( !wid ) + return; + + int splitter_size = o == Horizontal ? mySplit->width() : mySplit->height(); + int need_pos = int( position * splitter_size ); + int splitter_pos = 0; + + if ( setPosition( wid, mySplit, o, need_pos, splitter_pos ) != 0 ) + { + // impossible to set required position + } +} + +/*! +* \brief Sets the action's accelerator key to accel. +* \param id - the key of the action in the actions map. +* \param accel - action's accelerator key. +*/ +void QtxWorkstack::setAccel( const int id, const int accel ) +{ + if ( !myActionsMap.contains( id ) ) + return; + + myActionsMap[id]->setAccel( accel ); +} + +/*! +* \brief Returns the action's accelerator key. +* \param id - the key of the action in the actions map. +* \retval int - action's accelerator key. +*/ +int QtxWorkstack::accel( const int id ) const +{ + int res = 0; + if ( myActionsMap.contains( id ) ) + res = myActionsMap[id]->accel(); + return res; +} + +static int positionSimple (QIntList& szList, const int nb, const int splitter_size, + const int item_ind, const int item_rel_pos, + const int need_pos, const int splitter_pos) +{ + if (item_ind == 0) { // cannot move in this splitter + return (need_pos - splitter_pos); + } + + int delta = 0; + int new_prev = 0; + int new_this = szList[item_ind]; + int new_next = 0; + + bool isToCheck = false; + + if (need_pos < splitter_pos) { + // Set size of all previous workareas to zero <-- + if (item_ind == nb - 1) { + // item iz last in the splitter, it will occupy all the splitter + new_this = splitter_size; + } else { + // recompute size of next items in splitter + new_next = (splitter_size - new_this) / (nb - item_ind - 1); + } + delta = need_pos - splitter_pos; + + } else if (need_pos > (splitter_pos + splitter_size)) { + // Set size of all next workareas to zero --> + // recompute size of previous items in splitter + new_this = 0; + new_prev = (splitter_size - new_this) / item_ind; + delta = need_pos - (splitter_pos + splitter_size - new_this); + + } else { // required position lays inside this splitter + // Move workarea inside splitter into required position <-> + int new_item_rel_pos = need_pos - splitter_pos; + new_prev = new_item_rel_pos / item_ind; + if (need_pos < (splitter_pos + item_rel_pos)) { + // Make previous workareas smaller, next - bigger + // No problem to keep old size of the widget + } else { + // Make previous workareas bigger, next - smaller + if (new_this > splitter_size - new_item_rel_pos) { + new_this = splitter_size - new_item_rel_pos; + } + // jfa to do: in this case fixed size of next widgets could prevent right resizing + isToCheck = true; + } + if (item_ind == nb - 1) { + new_this = splitter_size - new_item_rel_pos; + } else { + new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1); + } + delta = 0; + } + + setSizes (szList, item_ind, new_prev, new_this, new_next); + return delta; +} + +/*! +* \brief Set position of given widget. +* \param wid - widget to be moved +* \param split - currently processed splitter (goes from more common +* to more particular splitter in recursion calls) +* \param o - orientation of positioning +* \param need_pos - required position of the given widget in pixels +* (from top/left side of workstack area) +* \param splitter_pos - position of the splitter \a split +* (from top/left side of workstack area) +* \retval int - returns difference between a required and a distinguished position. +* +* Internal method. Recursively calls itself. +* Is called from SetRelativePosition public method. +*/ +int QtxWorkstack::setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o, + const int need_pos, const int splitter_pos ) +{ + if ( !wid || !split ) + return need_pos - splitter_pos; + + // Find corresponding sub-splitter. + // Find also index of appropriate item in current splitter. + int cur_ind = 0, item_ind = 0; + bool isBottom = false, isFound = false; + QSplitter* sub_split = NULL; + const QObjectList* objs = split->children(); + if ( objs ) + { + for (QObjectListIt it (*objs); it.current() && !isFound; ++it) + { + if (it.current()->inherits( "QtxWorkstackArea")) { + if (((QtxWorkstackArea*)it.current())->contains(wid)) { + item_ind = cur_ind; + isBottom = true; + isFound = true; + } + cur_ind++; + } else if (it.current()->inherits("QSplitter")) { + QPtrList areaList; + areas((QSplitter*)it.current(), areaList, true); + for (QPtrListIterator ita (areaList); + ita.current() && !isFound; + ++ita) + { + if (ita.current()->contains(wid)) { + item_ind = cur_ind; + isFound = true; + sub_split = (QSplitter*)it.current(); + } + } + cur_ind++; + } + } + } + if (!isFound) + return (need_pos - splitter_pos); + + if (split->orientation() == o) { + // Find coordinates of near and far sides of the appropriate item relatively current splitter + int splitter_size = (o == Horizontal ? split->width() : split->height()); + QIntList szList = split->sizes(); + int nb = szList.count(); + int item_rel_pos = 0; // position of near side of item relatively this splitter + for (int i = 0; i < item_ind; i++) { + item_rel_pos += szList[i]; + } + int item_size = szList[item_ind]; // size of item + int item_pos = splitter_pos + item_rel_pos; + + // Resize splitter items to complete the conditions + if (isBottom) { + // I. Bottom of splitters stack reached + + int delta = positionSimple(szList, nb, splitter_size, item_ind, item_rel_pos, need_pos, splitter_pos); + split->setSizes(szList); + // Recompute delta, as some windows can reject given size + int new_item_rel_pos = 0; + QIntList szList1 = split->sizes(); + for (int i = 0; i < item_ind; i++) { + new_item_rel_pos += szList1[i]; + } + delta = need_pos - (splitter_pos + new_item_rel_pos); + return delta; + + } else { + // II. Bottom of splitters stack is not yet reached + + if (item_ind == 0) { // cannot move in this splitter + // Process in sub-splitter + return setPosition(wid, sub_split, o, need_pos, splitter_pos); + } + + int new_prev = 0; + int new_this = szList[item_ind]; + int new_next = 0; + + if (need_pos < splitter_pos) { + // Set size of all previous workareas to zero <-- + if (item_ind == nb - 1) { + new_this = splitter_size; + } else { + new_next = (splitter_size - new_this) / (nb - item_ind - 1); + } + setSizes (szList, item_ind, new_prev, new_this, new_next); + split->setSizes(szList); + // Recompute splitter_pos, as some windows can reject given size + int new_item_rel_pos = 0; + QIntList szList1 = split->sizes(); + for (int i = 0; i < item_ind; i++) { + new_item_rel_pos += szList1[i]; + } + // Process in sub-splitter + return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos); + } else if (need_pos > (splitter_pos + splitter_size)) { + // Set size of all next workareas to zero --> + new_prev = (splitter_size - new_this) / item_ind; + setSizes (szList, item_ind, new_prev, new_this, new_next); + split->setSizes(szList); + // Recompute splitter_pos, as some windows can reject given size + int new_item_rel_pos = 0; + QIntList szList1 = split->sizes(); + for (int i = 0; i < item_ind; i++) { + new_item_rel_pos += szList1[i]; + } + // Process in sub-splitter + return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos); + } else { + // Set appropriate size of all previous/next items <-> + int new_item_rel_pos = item_rel_pos; + if (need_pos < item_pos || (item_pos + item_size) < need_pos) { + // Move item inside splitter into required position <-> + int new_this = szList[item_ind]; + int new_next = 0; + new_item_rel_pos = need_pos - splitter_pos; + if ((item_pos + item_size) < need_pos) { + //new_item_rel_pos = need_pos - (item_pos + item_size); + new_item_rel_pos = item_rel_pos + (need_pos - (item_pos + item_size)); + } + int new_prev = new_item_rel_pos / item_ind; + if (need_pos < (splitter_pos + item_rel_pos)) { + // Make previous workareas smaller, next - bigger + // No problem to keep old size of the widget + } else { + // Make previous workareas bigger, next - smaller + if (new_this > splitter_size - new_item_rel_pos) { + new_this = splitter_size - new_item_rel_pos; + } + } + if (item_ind == nb - 1) { + new_this = splitter_size - new_item_rel_pos; + } else { + new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1); + } + setSizes (szList, item_ind, new_prev, new_this, new_next); + split->setSizes(szList); + // Recompute new_item_rel_pos, as some windows can reject given size + new_item_rel_pos = 0; + QIntList szList1 = split->sizes(); + for (int i = 0; i < item_ind; i++) { + new_item_rel_pos += szList1[i]; + } + } else { + // Do nothing + } + // Process in sub-splitter + int add_pos = setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos); + if (add_pos == 0) + return 0; + + // this can be if corresponding workarea is first in sub-splitter + // or sub-splitter has another orientation + + // Resize ones again to reach precize position <-> + int need_pos_1 = splitter_pos + new_item_rel_pos + add_pos; + + // Move workarea inside splitter into required position <-> + int delta_1 = positionSimple(szList, nb, splitter_size, item_ind, + new_item_rel_pos, need_pos_1, splitter_pos); + split->setSizes(szList); + // Recompute new_item_rel_pos, as some windows can reject given size + new_item_rel_pos = 0; + QIntList szList1 = split->sizes(); + for (int i = 0; i < item_ind; i++) { + new_item_rel_pos += szList1[i]; + } + delta_1 = need_pos_1 - (splitter_pos + new_item_rel_pos); + return delta_1; + } + } + } else { + return setPosition(wid, sub_split, o, need_pos, splitter_pos); + } + + return 0; +} + +void QtxWorkstack::distributeSpace( QSplitter* split ) const +{ + if ( !split ) + return; + + QIntList szList = split->sizes(); + int size = ( split->orientation() == Horizontal ? + split->width() : split->height() ) / szList.count(); + for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it ) + *it = size; + split->setSizes( szList ); +} + +void QtxWorkstack::splitVertical() +{ + split( Qt::Horizontal ); +} + +void QtxWorkstack::splitHorizontal() +{ + split( Qt::Vertical ); +} + +void QtxWorkstack::onRename() +{ + if ( !myWorkWin ) + return; + + bool ok = false; + QString newName = QInputDialog::getText( tr( "Rename" ), tr( "Enter new name:" ), QLineEdit::Normal, + myWorkWin->caption(), &ok, topLevelWidget() ); + if ( ok && !newName.isEmpty() ) + myWorkWin->setCaption( newName ); +} + +QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area ) +{ + if ( !area ) + return 0; + + QSplitter* pSplit = splitter( area ); + if ( !pSplit ) + return 0; + + bool upd = pSplit->isUpdatesEnabled(); + pSplit->setUpdatesEnabled( false ); + + QIntList szList = pSplit->sizes(); + + QSplitter* wrap = new QSplitter( 0 ); +#if defined QT_VERSION && QT_VERSION >= 0x30200 + wrap->setChildrenCollapsible( false ); +#endif + insertWidget( wrap, pSplit, area ); + area->reparent( wrap, QPoint( 0, 0 ), true ); + + pSplit->setSizes( szList ); + + pSplit->setUpdatesEnabled( upd ); + + return wrap; +} + +void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after ) +{ + if ( !wid || !pWid ) + return; + + QWidgetList moveList; + const QObjectList* lst = pWid->children(); + if ( lst ) + { + bool found = false; + for ( QObjectListIt it( *lst ); it.current(); ++it ) + { + if ( found && ( it.current()->inherits( "QSplitter" ) || + it.current()->inherits( "QtxWorkstackArea" ) ) ) + moveList.append( (QWidget*)it.current() ); + if ( it.current() == after ) + found = true; + } + } + + QMap map; + for ( QWidgetListIt it( moveList ); it.current(); ++it ) + { + map.insert( it.current(), it.current()->isVisibleTo( it.current()->parentWidget() ) ); + it.current()->reparent( 0, QPoint( 0, 0 ), false ); + } + + wid->reparent( pWid, QPoint( 0, 0 ), true ); + + for ( QWidgetListIt itr( moveList ); itr.current(); ++itr ) + itr.current()->reparent( pWid, QPoint( 0, 0 ), map.contains( itr.current() ) ? map[itr.current()] : false ); +} + +/*! +* \brief Closes the active window. +*/ +void QtxWorkstack::onCloseWindow() +{ + if ( myWorkWin ) + myWorkWin->close(); + else if( activeWindow() ) + activeWindow()->close(); +} + +void QtxWorkstack::onDestroyed( QObject* obj ) +{ + QtxWorkstackArea* area = (QtxWorkstackArea*)obj; + + if ( area == myArea ) + myArea = 0; + + if ( !myArea ) + { + QtxWorkstackArea* cur = neighbourArea( area ); + if ( cur ) + cur->setFocus(); + } + + QApplication::postEvent( this, new QCustomEvent( QEvent::User ) ); +} + +void QtxWorkstack::onWindowActivated( QWidget* wid ) +{ + const QObject* obj = sender(); + if ( !obj->inherits( "QtxWorkstackArea" ) ) + return; + + setActiveArea( (QtxWorkstackArea*)obj ); +} + +void QtxWorkstack::onDeactivated( QtxWorkstackArea* area ) +{ + if ( myArea != area ) + return; + + QPtrList lst; + areas( mySplit, lst, true ); + + int idx = lst.find( area ); + if ( idx == -1 ) + return; + + myWin = 0; + myArea = 0; + + QtxWorkstackArea* newArea = neighbourArea( area ); + if ( newArea && newArea->activeWidget() ) + newArea->activeWidget()->setFocus(); + + QApplication::postEvent( this, new QCustomEvent( QEvent::User ) ); +} + +void QtxWorkstack::onContextMenuRequested( QWidget* w, QPoint p ) +{ + QtxWorkstackArea* anArea = dynamic_cast( (QObject*)sender() ); + if ( !anArea ) + anArea = activeArea(); + + if ( !anArea ) + return; + + QWidgetList lst = anArea->widgetList(); + if ( lst.isEmpty() ) + return; + + myWorkWin = w; + myWorkArea = anArea; + + QPopupMenu* pm = new QPopupMenu(); + + if ( lst.count() > 1 ) + { + myActionsMap[SplitVertical]->addTo( pm ); + myActionsMap[SplitHorizontal]->addTo( pm ); + pm->insertSeparator(); + } + + if ( w ) + { + myActionsMap[Close]->addTo( pm ); + myActionsMap[Rename]->addTo( pm ); + } + + if ( pm->count() ) + pm->exec( p ); + + delete pm; + + myWorkWin = 0; + myWorkArea = 0; +} + +void QtxWorkstack::childEvent( QChildEvent* e ) +{ + if ( e->inserted() && e->child()->isWidgetType() ) + { + QWidget* w = (QWidget*)e->child(); + if ( w && w != mySplit ) + { + targetArea()->insertWidget( w ); + return; + } + } + QWidget::childEvent( e ); +} + +void QtxWorkstack::customEvent( QCustomEvent* e ) +{ + updateState(); +} + +QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const +{ + if ( !area ) + return 0; + + QSplitter* split = 0; + + QWidget* wid = area->parentWidget(); + if ( wid && wid->inherits( "QSplitter" ) ) + split = (QSplitter*)wid; + + return split; +} + +void QtxWorkstack::splitters( QSplitter* split, QPtrList& splitList, const bool rec ) const +{ + if ( !split ) + return; + + const QObjectList* objs = split->children(); + if ( objs ) + { + for ( QObjectListIt it( *objs ); it.current(); ++it ) + { + if ( rec ) + splitters( (QSplitter*)it.current(), splitList, rec ); + if ( it.current()->inherits( "QSplitter" ) ) + splitList.append( (QSplitter*)it.current() ); + } + } +} + +void QtxWorkstack::areas( QSplitter* split, QPtrList& areaList, const bool rec ) const +{ + if ( !split ) + return; + + const QObjectList* objs = split->children(); + if ( objs ) + { + for ( QObjectListIt it( *objs ); it.current(); ++it ) + { + if ( it.current()->inherits( "QtxWorkstackArea" ) ) + areaList.append( (QtxWorkstackArea*)it.current() ); + else if ( rec && it.current()->inherits( "QSplitter" ) ) + areas( (QSplitter*)it.current(), areaList, rec ); + } + } +} + +QtxWorkstackArea* QtxWorkstack::activeArea() const +{ + return myArea; +} + +QtxWorkstackArea* QtxWorkstack::targetArea() +{ + QtxWorkstackArea* area = activeArea(); + if ( !area ) + area = currentArea(); + if ( !area ) + { + QPtrList lst; + areas( mySplit, lst ); + if ( !lst.isEmpty() ) + area = lst.first(); + } + + if ( !area ) + area = createArea( mySplit ); + + return area; +} + +QtxWorkstackArea* QtxWorkstack::currentArea() const +{ + QtxWorkstackArea* area = 0; + QWidget* wid = focusWidget(); + while ( wid && !area ) + { + if ( wid->inherits( "QtxWorkstackArea" ) ) + area = (QtxWorkstackArea*)wid; + wid = wid->parentWidget(); + } + + return area; +} + +QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const +{ + QtxWorkstackArea* area = new QtxWorkstackArea( parent ); + + connect( area, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + connect( area, SIGNAL( activated( QWidget* ) ), this, SLOT( onWindowActivated( QWidget* ) ) ); + connect( area, SIGNAL( contextMenuRequested( QWidget*, QPoint ) ), + this, SLOT( onContextMenuRequested( QWidget*, QPoint ) ) ); + connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) ); + + return area; +} + +void QtxWorkstack::setActiveArea( QtxWorkstackArea* area ) +{ + QWidget* oldCur = myWin; + + QtxWorkstackArea* oldArea = myArea; + + myArea = area; + + if ( myArea != oldArea ) + { + if ( oldArea ) + oldArea->updateActiveState(); + if ( myArea ) + myArea->updateActiveState(); + } + + if ( myArea ) + myWin = myArea->activeWidget(); + + if ( myWin && oldCur != myWin ) + emit windowActivated( myWin ); +} + +QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const +{ + QPtrList lst; + areas( mySplit, lst, true ); + int pos = lst.find( area ); + if ( pos < 0 ) + return 0; + + QtxWorkstackArea* na = 0; + for ( int i = pos - 1; i >= 0 && !na; i-- ) + { + if ( !lst.at( i )->isEmpty() ) + na = lst.at( i ); + } + + for ( int j = pos + 1; j < (int)lst.count() && !na; j++ ) + { + if ( !lst.at( j )->isEmpty() ) + na = lst.at( j ); + } + return na; +} + +QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const +{ + QtxWorkstackArea* area = 0; + QPtrList lst; + areas( mySplit, lst, true ); + for ( QPtrListIterator it( lst ); it.current() && !area; ++it ) + { + QtxWorkstackArea* cur = it.current(); + QRect r = cur->geometry(); + if ( cur->parentWidget() ) + r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() ); + if ( r.contains( p ) ) + area = cur; + } + return area; +} + +void QtxWorkstack::updateState() +{ + updateState( mySplit ); +} + +void QtxWorkstack::updateState( QSplitter* split ) +{ + QPtrList recList; + splitters( split, recList, false ); + for ( QPtrListIterator itr( recList ); itr.current(); ++itr ) + updateState( itr.current() ); + + QPtrList splitList; + splitters( split, splitList, false ); + + QPtrList areaList; + areas( split, areaList, false ); + + bool vis = false; + for ( QPtrListIterator it( areaList ); it.current(); ++it ) + { + if ( it.current()->isEmpty() ) + it.current()->hide(); + else + { + it.current()->show(); + vis = true; + } + } + + if ( split == mySplit ) + return; + + for ( QPtrListIterator iter( splitList ); iter.current() && !vis; ++iter ) + vis = iter.current()->isVisibleTo( iter.current()->parentWidget() ); + + if ( areaList.isEmpty() && splitList.isEmpty() ) + delete split; + else if ( vis ) + split->show(); + else + split->hide(); +} + +/*! + Class: QtxWorkstackArea [Internal] + Descr: +*/ + +QtxWorkstackArea::QtxWorkstackArea( QWidget* parent ) +: QWidget( parent ) +{ + QVBoxLayout* base = new QVBoxLayout( this ); + + QHBox* top = new QHBox( this ); + base->addWidget( top ); + + myBar = new QtxWorkstackTabBar( top ); + + QPushButton* close = new QPushButton( top ); + close->setPixmap( style().stylePixmap( QStyle::SP_TitleBarCloseButton ) ); + close->setAutoDefault( true ); + close->setFlat( true ); + myClose = close; + + top->setStretchFactor( myBar, 1 ); + + myStack = new QWidgetStack( this ); + + base->addWidget( myStack, 1 ); + + connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) ); + connect( myBar, SIGNAL( selected( int ) ), this, SLOT( onSelected( int ) ) ); + connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) ); + connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) ); + + updateState(); + + updateActiveState(); + + qApp->installEventFilter( this ); +} + +QtxWorkstackArea::~QtxWorkstackArea() +{ + qApp->removeEventFilter( this ); +} + +bool QtxWorkstackArea::isEmpty() const +{ + bool res = false; + for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it ) + res = it.data().vis; + return !res; +} + +void QtxWorkstackArea::insertWidget( QWidget* wid, const int idx ) +{ + if ( !wid ) + return; + + int pos = myList.find( wid ); + if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) ) + return; + + myList.removeRef( wid ); + pos = idx < 0 ? myList.count() : idx; + myList.insert( QMIN( pos, (int)myList.count() ), wid ); + if ( !myInfo.contains( wid ) ) + { + QtxWorkstackChild* child = new QtxWorkstackChild( wid, myStack ); + myChild.insert( wid, child ); + myInfo.insert( wid, WidgetInfo() ); + myInfo[wid].id = generateId(); + myInfo[wid].vis = wid->isVisibleTo( wid->parentWidget() ); + + connect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) ); + connect( wid, SIGNAL( destroyed() ), this, SLOT( onWidgetDestroyed() ) ); + connect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) ); + connect( child, SIGNAL( hided( QtxWorkstackChild* ) ), this, SLOT( onChildHided( QtxWorkstackChild* ) ) ); + connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) ); + connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) ); + } + + updateState(); + + setWidgetActive( wid ); + wid->setFocus(); +} + +void QtxWorkstackArea::onContextMenuRequested( QPoint p ) +{ + const QtxWorkstackTabBar* bar = ::qt_cast( sender() ); + if ( !bar ) + return; + + QWidget* wid = 0; + QTab* tab = myBar->tabAt( tabAt( p ) ); + if ( tab ) + wid = widget( tab->identifier() ); + + emit contextMenuRequested( wid, p ); +} + +void QtxWorkstackArea::onWidgetDestroyed() +{ + if ( sender() ) + removeWidget( (QWidget*)sender(), false ); +} + +void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del ) +{ + if ( !myList.contains( wid ) ) + return; + + if ( myBar->tab( widgetId( wid ) ) ) + myBar->removeTab( myBar->tab( widgetId( wid ) ) ); + myStack->removeWidget( child( wid ) ); + + myList.remove( wid ); + myInfo.remove( wid ); + myChild.remove( wid ); + + if( del ) + { + delete child( wid ); + if( myList.isEmpty() ) + delete this; + else + updateState(); + } + else + updateState(); +} + +QWidgetList QtxWorkstackArea::widgetList() const +{ + QWidgetList lst; + for ( QWidgetListIt it( myList ); it.current(); ++it ) + { + if ( widgetVisibility( it.current() ) ) + lst.append( it.current() ); + } + return lst; +} + +QWidget* QtxWorkstackArea::activeWidget() const +{ + return widget( myBar->currentTab() ); +} + +void QtxWorkstackArea::setActiveWidget( QWidget* wid ) +{ + myBar->setCurrentTab( widgetId( wid ) ); +} + +bool QtxWorkstackArea::contains( QWidget* wid ) const +{ + return myList.contains( wid ); +} + +void QtxWorkstackArea::show() +{ + QMap map; + for ( QWidgetListIt it( myList ); it.current(); ++it ) + { + map.insert( it.current(), isBlocked( it.current() ) ); + setBlocked( it.current(), true ); + } + + QWidget::show(); + + for ( QWidgetListIt itr( myList ); itr.current(); ++itr ) + setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false ); +} + +void QtxWorkstackArea::hide() +{ + QMap map; + for ( QWidgetListIt it( myList ); it.current(); ++it ) + { + map.insert( it.current(), isBlocked( it.current() ) ); + setBlocked( it.current(), true ); + } + + QWidget::hide(); + + for ( QWidgetListIt itr( myList ); itr.current(); ++itr ) + setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false ); +} + +bool QtxWorkstackArea::isActive() const +{ + QtxWorkstack* ws = workstack(); + if ( !ws ) + return false; + + return ws->activeArea() == this; +} + +void QtxWorkstackArea::updateActiveState() +{ + myBar->setActive( isActive() ); +} + +QtxWorkstack* QtxWorkstackArea::workstack() const +{ + QtxWorkstack* ws = 0; + QWidget* wid = parentWidget(); + while ( wid && !ws ) + { + if ( wid->inherits( "QtxWorkstack" ) ) + ws = (QtxWorkstack*)wid; + wid = wid->parentWidget(); + } + return ws; +} + +bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e ) +{ + if ( o->isWidgetType() ) + { + QWidget* wid = (QWidget*)o; + if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress ) + { + bool ok = false; + while ( !ok && wid && wid != myClose ) + { + ok = wid == this; + wid = wid->parentWidget(); + } + if ( ok ) + QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) ); + } + } + return false; +} + +QRect QtxWorkstackArea::floatRect() const +{ + QRect r = myStack->geometry(); + return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) ); +} + +QRect QtxWorkstackArea::floatTab( const int idx ) const +{ + return myBar->tabRect( idx ); +} + +int QtxWorkstackArea::tabAt( const QPoint& p ) const +{ + int idx = -1; + for ( int i = 0; i < myBar->count() && idx == -1; i++ ) + { + QRect r = myBar->tabRect( i ); + if ( r.isValid() && r.contains( p ) ) + idx = i; + } + return idx; +} + +void QtxWorkstackArea::customEvent( QCustomEvent* e ) +{ + switch ( e->type() ) + { + case ActivateWidget: + emit activated( activeWidget() ); + break; + case FocusWidget: + if ( activeWidget() ) + { + if ( !activeWidget()->focusWidget() ) + activeWidget()->setFocus(); + else { + if ( activeWidget()->focusWidget()->hasFocus()) { + QFocusEvent in(QEvent::FocusIn); + QApplication::sendEvent(this, &in); + } + else + activeWidget()->focusWidget()->setFocus(); + } + } + break; + case RemoveWidget: + removeWidget( (QWidget*)e->data() ); + break; + } +} + +void QtxWorkstackArea::focusInEvent( QFocusEvent* e ) +{ + QWidget::focusInEvent( e ); + + emit activated( activeWidget() ); +} + +void QtxWorkstackArea::mousePressEvent( QMouseEvent* e ) +{ + QWidget::mousePressEvent( e ); + + emit activated( activeWidget() ); +} + +void QtxWorkstackArea::onClose() +{ + QWidget* wid = activeWidget(); + if ( wid ) + wid->close(); +} + +void QtxWorkstackArea::onSelected( int id ) +{ + updateCurrent(); + + emit activated( activeWidget() ); +} + +void QtxWorkstackArea::onDragActiveTab() +{ + QtxWorkstackChild* c = child( activeWidget() ); + if ( !c ) + return; + + new QtxWorkstackDrag( workstack(), c ); +} + +void QtxWorkstackArea::onChildDestroyed( QObject* obj ) +{ + QtxWorkstackChild* child = (QtxWorkstackChild*)obj; + myStack->removeWidget( child ); + + QWidget* wid = 0; + for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it ) + { + if ( it.data() == child ) + wid = it.key(); + } + + myChild.remove( wid ); + + QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)RemoveWidget, wid ) ); +} + +void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c ) +{ + setWidgetShown( c->widget(), true ); +} + +void QtxWorkstackArea::onChildHided( QtxWorkstackChild* c ) +{ + setWidgetShown( c->widget(), false ); +} + +void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c ) +{ + setWidgetActive( c->widget() ); +} + +void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c ) +{ + updateTab( c->widget() ); +} + +void QtxWorkstackArea::updateCurrent() +{ + QMap map; + for ( QWidgetListIt it( myList ); it.current(); ++it ) + { + map.insert( it.current(), isBlocked( it.current() ) ); + setBlocked( it.current(), true ); + } + + myStack->raiseWidget( myBar->currentTab() ); + + for ( QWidgetListIt itr( myList ); itr.current(); ++itr ) + setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false ); +} + +void QtxWorkstackArea::updateTab( QWidget* wid ) +{ + QTab* tab = myBar->tab( widgetId( wid ) ); + if ( !tab ) + return; + + QIconSet icoSet; + if ( wid->icon() ) + { + QPixmap pix = *wid->icon(); + pix.convertFromImage( pix.convertToImage().smoothScale( pix.width(), 16, QImage::ScaleMin ) ); + icoSet = QIconSet( pix ); + } + + tab->setIconSet( icoSet ); + tab->setText( wid->caption() ); +} + +QWidget* QtxWorkstackArea::widget( const int id ) const +{ + QWidget* wid = 0; + for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it ) + { + if ( it.data().id == id ) + wid = it.key(); + } + return wid; +} + +int QtxWorkstackArea::widgetId( QWidget* wid ) const +{ + int id = -1; + if ( myInfo.contains( wid ) ) + id = myInfo[wid].id; + return id; +} + +bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const +{ + bool res = false; + if ( myInfo.contains( wid ) ) + res = myInfo[wid].vis; + return res; +} + +void QtxWorkstackArea::setWidgetActive( QWidget* wid ) +{ + int id = widgetId( wid ); + if ( id < 0 ) + return; + + myBar->setCurrentTab( id ); +} + +void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on ) +{ + if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on ) + return; + + myInfo[wid].vis = on; + updateState(); +} + +void QtxWorkstackArea::updateState() +{ + bool updBar = myBar->isUpdatesEnabled(); + bool updStk = myStack->isUpdatesEnabled(); + myBar->setUpdatesEnabled( false ); + myStack->setUpdatesEnabled( false ); + + bool block = myBar->signalsBlocked(); + myBar->blockSignals( true ); + + QWidget* prev = activeWidget(); + + int idx = 0; + for ( QWidgetListIt it( myList ); it.current(); ++it ) + { + QWidget* wid = it.current(); + int id = widgetId( wid ); + + if ( id < 0 ) + continue; + + bool vis = widgetVisibility( wid ); + + if ( myBar->tab( id ) && ( !vis || myBar->indexOf( id ) != idx ) ) + myBar->removeTab( myBar->tab( id ) ); + + if ( !myBar->tab( id ) && vis ) + { + QTab* tab = new QTab( wid->caption() ); + myBar->insertTab( tab, idx ); + tab->setIdentifier( id ); + } + + updateTab( wid ); + + bool block = isBlocked( wid ); + setBlocked( wid, true ); + + QtxWorkstackChild* cont = child( wid ); + + if ( !vis ) + myStack->removeWidget( cont ); + else if ( !myStack->widget( id ) ) + myStack->addWidget( cont, id ); + + if ( vis ) + idx++; + + setBlocked( wid, block ); + } + + int curId = widgetId( prev ); + if ( !myBar->tab( curId ) ) + { + QWidget* wid = 0; + int pos = myList.find( prev ); + for ( int i = pos - 1; i >= 0 && !wid; i-- ) + { + if ( widgetVisibility( myList.at( i ) ) ) + wid = myList.at( i ); + } + + for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ ) + { + if ( widgetVisibility( myList.at( j ) ) ) + wid = myList.at( j ); + } + + if ( wid ) + curId = widgetId( wid ); + } + + myBar->setCurrentTab( curId ); + + myBar->blockSignals( block ); + + updateCurrent(); + + myBar->setUpdatesEnabled( updBar ); + myStack->setUpdatesEnabled( updStk ); + if ( updBar ) + myBar->update(); + if ( updStk ) + myStack->update(); + + QResizeEvent re( myBar->size(), myBar->size() ); + QApplication::sendEvent( myBar, &re ); + + if ( isEmpty() ) + { + hide(); + emit deactivated( this ); + } + else + { + show(); + if ( prev != activeWidget() ) + emit activated( activeWidget() ); + } +} + +int QtxWorkstackArea::generateId() const +{ + QMap map; + + for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end(); ++it ) + map.insert( it.data().id, 0 ); + + int id = 0; + while ( map.contains( id ) ) + id++; + + return id; +} + +bool QtxWorkstackArea::isBlocked( QWidget* wid ) const +{ + return myBlock.contains( wid ); +} + +void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on ) +{ + if ( on ) + myBlock.insert( wid, 0 ); + else + myBlock.remove( wid ); +} + +QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const +{ + QtxWorkstackChild* res = 0; + if ( myChild.contains( wid ) ) + res = myChild[wid]; + return res; +} + +/*! + Class: QtxWorkstackChild [Internal] + Descr: +*/ + +QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent ) +: QHBox( parent ), +myWidget( wid ) +{ + myWidget->reparent( this, QPoint( 0, 0 ), myWidget->isVisibleTo( myWidget->parentWidget() ) ); + myWidget->installEventFilter( this ); + + connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); +} + +QtxWorkstackChild::~QtxWorkstackChild() +{ + qApp->removeEventFilter( this ); + + if ( !widget() ) + return; + + widget()->removeEventFilter( this ); + widget()->reparent( 0, QPoint( 0, 0 ), false ); + disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); +} + +QWidget* QtxWorkstackChild::widget() const +{ + return myWidget; +} + +bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e ) +{ + if ( o->isWidgetType() ) + { + if ( e->type() == QEvent::CaptionChange || e->type() == QEvent::IconChange ) + emit captionChanged( this ); + + if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) ) + emit shown( this ); + + if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) + emit hided( this ); + + if ( e->type() == QEvent::FocusIn ) + emit activated( this ); + } + return QHBox::eventFilter( o, e ); +} + +void QtxWorkstackChild::onDestroyed( QObject* obj ) +{ + if ( obj != widget() ) + return; + + myWidget = 0; + deleteLater(); +} + +void QtxWorkstackChild::childEvent( QChildEvent* e ) +{ + if ( e->type() == QEvent::ChildRemoved && e->child() == widget() ) + { + myWidget = 0; + deleteLater(); + } + QHBox::childEvent( e ); +} + +/*! + Class: QtxWorkstackTabBar [Internal] + Descr: +*/ + +QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent ) +: QTabBar( parent ), +myId( -1 ) +{ +} + +QtxWorkstackTabBar::~QtxWorkstackTabBar() +{ +} + +void QtxWorkstackTabBar::setActive( const bool on ) +{ + QFont aFont = font(); + aFont.setUnderline( on ); + QColorGroup* aColGrp = new QColorGroup(); + QPalette aPal = palette(); + if ( !on ) { + aPal.setColor( QColorGroup::HighlightedText, aColGrp->foreground() ); + aPal.setColor( QColorGroup::Highlight, colorGroup().dark().light( DARK_COLOR_LIGHT ) ); + setPalette( aPal ); + } + else { + aPal.setColor( QColorGroup::HighlightedText, aColGrp->highlightedText() ); + aPal.setColor( QColorGroup::Highlight, aColGrp->highlight() ); + unsetPalette(); + } + setFont( aFont ); + + update(); +} + +QRect QtxWorkstackTabBar::tabRect( const int idx ) const +{ + QRect r; + QTab* t = tabAt( idx ); + if ( t ) + { + r = t->rect(); + r.setLeft( QMAX( r.left(), 0 ) ); + + int x1 = tabAt( 0 )->rect().left(); + int x2 = tabAt( count() - 1 )->rect().right(); + + int bw = 0; + if ( QABS( x2 - x1 ) > width() ) +#if defined QT_VERSION && QT_VERSION >= 0x30300 + bw = 2 * style().pixelMetric( QStyle::PM_TabBarScrollButtonWidth, this ); +#else + bw = 2 * 16; +#endif + + int limit = width() - bw; + r.setRight( QMIN( r.right(), limit ) ); + + r = QRect( mapToGlobal( r.topLeft() ), r.size() ); + } + return r; +} + +void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e ) +{ + if ( myId != -1 && !tab( myId )->rect().contains( e->pos() ) ) + { + myId = -1; + emit dragActiveTab(); + } + + QTabBar::mouseMoveEvent( e ); +} + +void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e ) +{ + QTabBar::mousePressEvent( e ); + + if ( e->button() == LeftButton ) + myId = currentTab(); +} + +void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e ) +{ + QTabBar::mouseReleaseEvent( e ); + + myId = -1; + + if ( e->button() == RightButton ) + emit contextMenuRequested( e->globalPos() ); +} + +void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e ) +{ + if ( e->reason() != QContextMenuEvent::Mouse ) + emit contextMenuRequested( e->globalPos() ); +} + +void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const +{ + if ( currentTab() != t->identifier() ) + { + QFont fnt = p->font(); + fnt.setUnderline( false ); + p->setFont( fnt ); + } + QTabBar::paintLabel( p, br, t, has_focus ); +} + +/*! + Class: QtxWorkstackDrag [Internal] + Descr: +*/ + +QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child ) +: QObject( 0 ), +myWS( ws ), +myTab( -1 ), +myArea( 0 ), +myPainter( 0 ), +myChild( child ) +{ + qApp->installEventFilter( this ); +} + +QtxWorkstackDrag::~QtxWorkstackDrag() +{ + qApp->removeEventFilter( this ); + + endDrawRect(); +} + +bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e ) +{ + switch ( e->type() ) + { + case QEvent::MouseMove: + updateTarget( ((QMouseEvent*)e)->globalPos() ); + break; + case QEvent::MouseButtonRelease: + drawRect(); + endDrawRect(); + dropWidget(); + deleteLater(); + break; + default: + return false; + } + return true; +} + +void QtxWorkstackDrag::updateTarget( const QPoint& p ) +{ + int tab = -1; + QtxWorkstackArea* area = detectTarget( p, tab ); + setTarget( area, tab ); +} + +QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const +{ + if ( p.isNull() ) + return 0; + + QtxWorkstackArea* area = myWS->areaAt( p ); + if ( area ) + tab = area->tabAt( p ); + return area; +} + +void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab ) +{ + if ( !area || ( myArea == area && tab == myTab ) ) + return; + + startDrawRect(); + + if ( myArea ) + drawRect(); + + myTab = tab; + myArea = area; + + if ( myArea ) + drawRect(); +} + +void QtxWorkstackDrag::dropWidget() +{ + if ( myArea ) + myArea->insertWidget( myChild->widget(), myTab ); +} + +void QtxWorkstackDrag::drawRect() +{ + if ( !myPainter || !myArea ) + return; + + QRect r = myArea->floatRect(); + int m = myPainter->pen().width(); + + r.setTop( r.top() + m + 2 ); + r.setLeft( r.left() + m + 2 ); + r.setRight( r.right() - m - 2 ); + r.setBottom( r.bottom() - m - 2 ); + + myPainter->drawRect( r ); + + QRect tr = myArea->floatTab( myTab ); + tr.setTop( tr.top() + m ); + tr.setLeft( tr.left() + m ); + tr.setRight( tr.right() - m ); + tr.setBottom( tr.bottom() - m ); + + myPainter->drawRect( tr ); +} + +void QtxWorkstackDrag::endDrawRect() +{ + delete myPainter; + myPainter = 0; +} + +void QtxWorkstackDrag::startDrawRect() +{ + if ( myPainter ) + return; + + int scr = QApplication::desktop()->screenNumber( (QWidget*)this ); + QWidget* paint_on = QApplication::desktop()->screen( scr ); + + myPainter = new QPainter( paint_on, true ); + myPainter->setPen( QPen( gray, 3 ) ); + myPainter->setRasterOp( XorROP ); +} diff --git a/src/Qtx/QtxWorkstack.h b/src/Qtx/QtxWorkstack.h new file mode 100644 index 000000000..8157a2a81 --- /dev/null +++ b/src/Qtx/QtxWorkstack.h @@ -0,0 +1,338 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// File: QtxWorkstack.h +// Author: Sergey TELKOV + +#ifndef QTXWORKSTACK_H +#define QTXWORKSTACK_H + +#include "Qtx.h" + +#include +#include +#include +#include + +class QAction; +class QTabBar; +class QPainter; +class QSplitter; +class QPushButton; +class QWidgetStack; + +class QtxWorkstackArea; +class QtxWorkstackDrag; +class QtxWorkstackChild; +class QtxWorkstackTabBar; + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +class QTX_EXPORT QtxWorkstack : public QWidget +{ + Q_OBJECT + +public: + enum { SplitVertical, SplitHorizontal, Close, Rename }; + + enum SplitType + { + SPLIT_STAY, //!< given widget stays in its workarea, others are moved into a new one + SPLIT_AT, //!< widgets before a given widget stays in they workarea, others are moved into a new one + SPLIT_MOVE //!< given widget is moved into a new workarea, others stay in an old one + }; + +public: + QtxWorkstack( QWidget* = 0 ); + virtual ~QtxWorkstack(); + + QWidgetList windowList() const; + QWidgetList splitWindowList() const; + + QWidget* activeWindow() const; + + int accel( const int ) const; + void setAccel( const int, const int ); + + void split( const int ); + + // STV: Useless function. wid->setFocus() should be used instead. + // void OnTop( QWidget* wid); + + void Split( QWidget* wid, const Qt::Orientation o, const SplitType type ); + void Attract( QWidget* wid1, QWidget* wid2, const bool all ); + void SetRelativePosition( QWidget* wid, const Qt::Orientation o, const double pos ); + void SetRelativePositionInSplitter( QWidget* wid, const double pos ); + +signals: + void windowActivated( QWidget* ); + +public slots: + void splitVertical(); + void splitHorizontal(); + +private slots: + void onRename(); + void onCloseWindow(); + void onDestroyed( QObject* ); + void onWindowActivated( QWidget* ); + void onContextMenuRequested( QWidget*, QPoint ); + void onDeactivated( QtxWorkstackArea* ); + +protected: + virtual void childEvent( QChildEvent* ); + virtual void customEvent( QCustomEvent* ); + +private: + QSplitter* splitter( QtxWorkstackArea* ) const; + void splitters( QSplitter*, QPtrList&, const bool = false ) const; + void areas( QSplitter*, QPtrList&, const bool = false ) const; + + QSplitter* wrapSplitter( QtxWorkstackArea* ); + void insertWidget( QWidget*, QWidget*, QWidget* ); + + QtxWorkstackArea* areaAt( const QPoint& ) const; + + QtxWorkstackArea* targetArea(); + QtxWorkstackArea* activeArea() const; + QtxWorkstackArea* currentArea() const; + + void setActiveArea( QtxWorkstackArea* ); + QtxWorkstackArea* neighbourArea( QtxWorkstackArea* ) const; + + QtxWorkstackArea* createArea( QWidget* ) const; + + void updateState(); + void updateState( QSplitter* ); + + void distributeSpace( QSplitter* ) const; + int setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o, + const int need_pos, const int splitter_pos ); + +private: + QWidget* myWin; + QtxWorkstackArea* myArea; + QSplitter* mySplit; + QWidget* myWorkWin; + QtxWorkstackArea* myWorkArea; + + QMap myActionsMap; //!< The map of the actions. Allows to get the QAction object by the key. + + friend class QtxWorkstackArea; + friend class QtxWorkstackDrag; +}; + +class QtxWorkstackArea : public QWidget +{ + Q_OBJECT + +public: + QtxWorkstackArea( QWidget* ); + virtual ~QtxWorkstackArea(); + + bool isEmpty() const; + + void insertWidget( QWidget*, const int = -1 ); + void removeWidget( QWidget*, const bool = true ); + + QWidget* activeWidget() const; + void setActiveWidget( QWidget* ); + + bool contains( QWidget* ) const; + + QWidgetList widgetList() const; + + bool isActive() const; + void updateActiveState(); + + QtxWorkstack* workstack() const; + + virtual bool eventFilter( QObject*, QEvent* ); + + QRect floatRect() const; + QRect floatTab( const int ) const; + + int tabAt( const QPoint& ) const; + +signals: + void activated( QWidget* ); + void contextMenuRequested( QWidget*, QPoint ); + void deactivated( QtxWorkstackArea* ); + +public slots: + virtual void show(); + virtual void hide(); + +private slots: + void onClose(); + void onSelected( int ); + + void onWidgetDestroyed(); + + void onChildDestroyed( QObject* ); + void onChildShown( QtxWorkstackChild* ); + void onChildHided( QtxWorkstackChild* ); + void onChildActivated( QtxWorkstackChild* ); + void onChildCaptionChanged( QtxWorkstackChild* ); + + void onDragActiveTab(); + void onContextMenuRequested( QPoint ); + +protected: + virtual void customEvent( QCustomEvent* ); + virtual void focusInEvent( QFocusEvent* ); + virtual void mousePressEvent( QMouseEvent* ); + +private: + enum { ActivateWidget = QEvent::User, FocusWidget, RemoveWidget }; + +private: + void updateState(); + void updateCurrent(); + void updateTab( QWidget* ); + + QWidget* widget( const int ) const; + int widgetId( QWidget* ) const; + bool widgetVisibility( QWidget* ) const; + + void setWidgetActive( QWidget* ); + void setWidgetShown( QWidget*, const bool ); + + int generateId() const; + + bool isBlocked( QWidget* ) const; + void setBlocked( QWidget*, const bool ); + + QtxWorkstackChild* child( QWidget* ) const; + +private: + struct WidgetInfo + { + WidgetInfo() : id( 0 ), vis( false ) {} + int id; bool vis; + }; + + typedef QMap BlockMap; + typedef QMap ChildMap; + typedef QMap WidgetInfoMap; + +private: + QtxWorkstackTabBar* myBar; + QPushButton* myClose; + QWidgetStack* myStack; + + QWidgetList myList; + WidgetInfoMap myInfo; + ChildMap myChild; + BlockMap myBlock; +}; + +class QtxWorkstackChild : public QHBox +{ + Q_OBJECT + +public: + QtxWorkstackChild( QWidget*, QWidget* = 0 ); + virtual ~QtxWorkstackChild(); + + QWidget* widget() const; + + virtual bool eventFilter( QObject*, QEvent* ); + +signals: + void shown( QtxWorkstackChild* ); + void hided( QtxWorkstackChild* ); + void activated( QtxWorkstackChild* ); + void captionChanged( QtxWorkstackChild* ); + +private slots: + void onDestroyed( QObject* ); + +protected: + virtual void childEvent( QChildEvent* ); + +private: + QWidget* myWidget; +}; + +class QtxWorkstackTabBar : public QTabBar +{ + Q_OBJECT + +public: + QtxWorkstackTabBar( QWidget* = 0 ); + virtual ~QtxWorkstackTabBar(); + + QRect tabRect( const int ) const; + + void setActive( const bool ); + +signals: + void dragActiveTab(); + void contextMenuRequested( QPoint ); + +protected: + virtual void mouseMoveEvent( QMouseEvent* ); + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void contextMenuEvent( QContextMenuEvent* ); + + virtual void paintLabel( QPainter*, const QRect&, QTab*, bool ) const; + +private: + int myId; +}; + +class QtxWorkstackDrag : public QObject +{ + Q_OBJECT + +public: + QtxWorkstackDrag( QtxWorkstack*, QtxWorkstackChild* ); + virtual ~QtxWorkstackDrag(); + + virtual bool eventFilter( QObject*, QEvent* ); + +private: + void dropWidget(); + + void updateTarget( const QPoint& ); + QtxWorkstackArea* detectTarget( const QPoint&, int& ) const; + void setTarget( QtxWorkstackArea*, const int ); + + void drawRect(); + void endDrawRect(); + void startDrawRect(); + +private: + QtxWorkstack* myWS; + QtxWorkstackChild* myChild; + + int myTab; + QtxWorkstackArea* myArea; + QPainter* myPainter; + +}; + +#ifdef WIN32 +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx new file mode 100644 index 000000000..3cb6cbbda --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx @@ -0,0 +1,1345 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +//============================================================================= +// File : SALOME_PYQT_Module.cxx +// Created : 25/04/05 +// Author : Vadim SANDLER +// Project : SALOME +// Copyright : 2003-2005 CEA/DEN, EDF R&D +// $Header : $ +//============================================================================= + +#include "SALOME_PYQT_Module.h" + +#include "PyInterp_Dispatcher.h" +#include "SUIT_ResourceMgr.h" +#include "STD_MDIDesktop.h" +#include "STD_TabDesktop.h" +#include "SalomeApp_Application.h" +#include "SalomeApp_Study.h" + +#include "QtxWorkstack.h" +#include +#include + +#include +#include +#include +#include + +#include "SALOME_PYQT_SipDefs.h" +#if defined(SIP_VERS_v4_old) || defined(SIP_VERS_v4_new) +#include "sipAPISalomePyQtGUI.h" +#else +#include "sipSalomePyQtGUIDeclSalomePyQtGUI.h" +#endif + +#include +#include + +#include + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +// Default name of the module, replaced at the moment of module creation +#define __DEFAULT_NAME__ "SALOME_PYQT_Module" + +/////////////////////////////////////////////////////////////////////////////// +// If __CALL_OLD_METHODS__ macro is not defined the invoking of obsolete Python +// module's methods like setSetting(), definePopup(), etc. is blocked. +// This macro is defined by default (in Makefile) +#ifdef __CALL_OLD_METHODS__ +const bool IsCallOldMethods = true; +#else +const bool IsCallOldMethods = false; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// NB: Python requests. +// General rule for Python requests created by SALOME_PYQT_Module: +// all requests should be executed SYNCHRONOUSLY within the main GUI thread. +// However, it is obligatory that ANY Python call is wrapped with a request object, +// so that ALL Python API calls are serialized with PyInterp_Dispatcher. +/////////////////////////////////////////////////////////////////////////////// + +//============================================================================= +// The class for parsing of the XML resource files. +// Used for backward compatibility with existing Python modules. +//============================================================================= +class SALOME_PYQT_XmlHandler +{ +public: + SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, const QString& fileName ); + void createActions(); + void createPopup ( QPopupMenu* menu, + const QString& context, + const QString& parent, + const QString& object ); + +protected: + void createToolBar ( QDomNode& parentNode ); + void createMenu ( QDomNode& parentNode, + const int parentMenuId = -1 ); + + void insertPopupItems( QDomNode& parentNode, + QPopupMenu* menu ); + +private: + SALOME_PYQT_Module* myModule; + QDomDocument myDoc; +}; + +//============================================================================= +// SALOME_PYQT_Module class implementation (implements CAM_Module API for +// all Python-based SALOME module +//============================================================================= + +// While the SalomePyQtGUI library is not imported in Python it's initialization function +// should be called manually (and only once) in order to initialize global sip data +// and to get C API from sip : sipBuildResult for example +#if defined(SIP_STATIC_MODULE) +extern "C" void initSalomePyQtGUI(); +#else +PyMODINIT_FUNC initSalomePyQtGUI(); +#endif + +/*! + * This function creates an instance of SALOME_PYQT_Module object by request + * of and application object when the module is loaded. + */ +extern "C" { + SALOME_PYQT_EXPORT CAM_Module* createModule() { + static bool alreadyInitialized = false; + if ( !alreadyInitialized ) { + // call only once (see above) ! + PyEval_RestoreThread( KERNEL_PYTHON::_gtstate ); + initSalomePyQtGUI(); + PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate ); + alreadyInitialized = !alreadyInitialized; + } + return new SALOME_PYQT_Module(); + } +} + +/*! + * Static variables definition + */ +SALOME_PYQT_Module::InterpMap SALOME_PYQT_Module::myInterpMap; +SALOME_PYQT_Module* SALOME_PYQT_Module::myInitModule = 0; + +/*! + * Little trick : provide an access to being activated Python module from outside; + * needed by the SalomePyQt library :( +*/ +SALOME_PYQT_Module* SALOME_PYQT_Module::getInitModule() +{ + return myInitModule; +} + +/*! + * Constructor + */ +SALOME_PYQT_Module::SALOME_PYQT_Module() : + SalomeApp_Module( __DEFAULT_NAME__ ), myModule( 0 ), myXmlHandler ( 0 ) +{ + myMenuActionList.setAutoDelete( false ); + myPopupActionList.setAutoDelete( false ); + myToolbarActionList.setAutoDelete( false ); +} + +/*! + * Destructor + */ +SALOME_PYQT_Module::~SALOME_PYQT_Module() +{ + myMenuActionList.clear(); + myPopupActionList.clear(); + myToolbarActionList.clear(); + if ( myXmlHandler ) + delete myXmlHandler; +} + +/*! + * Initialization of the module. + * Inherited from CAM_Module. + * + * This method is used for creation of the menus, toolbars and other staff. + * There are two ways: + * - for obsolete modules this method first tries to read _.xml + * resource file which contains a menu, toolbars and popup menus description. + * - new modules can create menus by by calling the corresponding methods of SalomePyQt + * Python API in the Python module's initialize() method which is called from here. + * NOTE: if postponed modules loading is not used, the active study might be not defined + * yet at this stage, so initialize() method should not perform any study-based initialization. + */ +void SALOME_PYQT_Module::initialize( CAM_Application* app ) +{ + SalomeApp_Module::initialize( app ); + + // Try to get XML resource file name + SUIT_ResourceMgr* aResMgr = getApp()->resourceMgr(); + QString aLang = aResMgr->stringValue( "language", "language", QString::null ); + if ( aLang.isEmpty() ) aLang = QString( "en" ); + QString aName = name( "" ); + QString aFileName = aName + "_" + aLang + ".xml"; + aFileName = aResMgr->path( "resources", aName, aFileName ); + + // parse XML file if it is found and create actions + if ( !myXmlHandler && !aFileName.isEmpty() ) { + myXmlHandler = new SALOME_PYQT_XmlHandler( this, aFileName ); + myXmlHandler->createActions(); + } + + // perform internal initialization and call module's initialize() method + // InitializeReq: request class for internal init() operation + class InitializeReq : public PyInterp_Request + { + public: + InitializeReq( CAM_Application* _app, + SALOME_PYQT_Module* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myApp( _app ), + myObj( _obj ) {} + + protected: + virtual void execute() + { + myObj->init( myApp ); + } + + private: + CAM_Application* myApp; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new InitializeReq( app, this ) ); +} + +/*! + * Activation of the module. + * Inherited from CAM_Module. + */ +bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy ) +{ + MESSAGE( "SALOME_PYQT_Module::activateModule" ); + + bool res = SalomeApp_Module::activateModule( theStudy ); + + if ( !res ) + return res; + + // ActivateReq: request class for internal activate() operation + class ActivateReq : public PyInterp_Request + { + public: + ActivateReq( SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->activate( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new ActivateReq( theStudy, this ) ); + + // activate menus, toolbars, etc + setMenuShown( true ); + setToolShown( true ); + + return true; +} + +/*! + * Deactivation of the module. + * Inherited from CAM_Module. + */ +bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* theStudy ) +{ + MESSAGE( "SALOME_PYQT_Module::deactivateModule" ); + + bool res = SalomeApp_Module::deactivateModule( theStudy ); + + // deactivate menus, toolbars, etc + setMenuShown( false ); + setToolShown( false ); + + // DeactivateReq: request class for internal deactivate() operation + class DeactivateReq : public PyInterp_LockRequest + { + public: + DeactivateReq( PyInterp_base* _py_interp, + SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->deactivate( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new DeactivateReq( myInterp, theStudy, this ) ); + + return res; +} + +/*! + * Processes GUI action (from main menu, toolbar or context popup menu) + */ +void SALOME_PYQT_Module::onGUIEvent() +{ + // get sender action + const QObject* obj = sender(); + if ( !obj || !obj->inherits( "QAction" ) ) + return; + QAction* action = (QAction*)obj; + + // get action ID + int id = actionId( action ); + MESSAGE( "SALOME_PYQT_Module::onGUIEvent: id = " << id ); + + // perform synchronous request to Python event dispatcher + class GUIEvent : public PyInterp_LockRequest + { + public: + GUIEvent( PyInterp_base* _py_interp, + SALOME_PYQT_Module* _obj, + int _id ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myId ( _id ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->guiEvent( myId ); + } + + private: + int myId; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new GUIEvent( myInterp, this, id ) ); +} + +/*! + * Processes GUI action (from context popup menu, only for XML-based actions!) + */ +void SALOME_PYQT_Module::onGUIEvent( int id ) +{ + // perform synchronous request to Python event dispatcher + class GUIEvent : public PyInterp_LockRequest + { + public: + GUIEvent( PyInterp_base* _py_interp, + SALOME_PYQT_Module* _obj, + int _id ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myId ( _id ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->guiEvent( myId ); + } + + private: + int myId; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new GUIEvent( myInterp, this, id ) ); +} + +/*! + Context popup menu request. + Called when user activates popup menu in some window (view, object browser, etc). + */ +void SALOME_PYQT_Module::contextMenuPopup( const QString& theContext, QPopupMenu* thePopupMenu, QString& /*title*/ ) +{ + MESSAGE( "SALOME_PYQT_Module::contextMenuPopup : " << theContext.latin1() ); + // perform synchronous request to Python event dispatcher + class PopupMenuEvent : public PyInterp_LockRequest + { + public: + PopupMenuEvent( PyInterp_base* _py_interp, + SALOME_PYQT_Module* _obj, + const QString& _context, + QPopupMenu* _popup ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myContext( _context ), + myPopup ( _popup ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->contextMenu( myContext, myPopup ); + } + + private: + SALOME_PYQT_Module* myObj; + QString myContext; + QPopupMenu* myPopup; + }; + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new PopupMenuEvent( myInterp, this, theContext, thePopupMenu ) ); +} + +/*! + * Defines the dockable window associated with the module. + * To fill the list of windows the correspondind Python module's windows() + * method is called from SALOME_PYQT_Module::init() method. + * By default, ObjectBrowser, PythonConsole and LogWindow are provided. + */ +void SALOME_PYQT_Module::windows( QMap& mappa ) const +{ + // First clear the output parameters + QMap::ConstIterator it; + for ( it = myWindowsMap.begin(); it != myWindowsMap.end(); ++it ) { + mappa[ it.key() ] = it.data(); + } +} + +/*! + * Defines the compatible views which should be opened on module activation. + * To fill the list of views the correspondind Python module's views() + * method is called from SALOME_PYQT_Module::init() method. + * By default, the list is empty. + */ +void SALOME_PYQT_Module::viewManagers( QStringList& listik ) const +{ + for ( QStringList::ConstIterator it = myViewMgrList.begin(); it != myViewMgrList.end(); ++it ) { + listik.append( *it ); + } +} + +/*! + * Performs internal initialization + * - initializes/gets the Python interpreter (one per study) + * - imports the Python module + * - passes the workspace widget to the Python module + * - calls Python module's initialize() method + * - calls Python module's windows() method + * - calls Python module's views() method + */ +void SALOME_PYQT_Module::init( CAM_Application* app ) +{ + // reset interpreter to NULL + myInterp = NULL; + + // get study Id + SalomeApp_Application* anApp = dynamic_cast( app ); + if ( !anApp ) + return; + + SalomeApp_Study* aStudy = dynamic_cast( app->activeStudy() ); + if ( !aStudy ) + return; + int aStudyId = aStudy ? aStudy->studyDS()->StudyId() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + myInitModule = this; + + if ( IsCallOldMethods ) { // __CALL_OLD_METHODS__ + // call Python module's setWorkspace() method + setWorkSpace(); + } //__CALL_OLD_METHODS__ + + // then call Python module's initialize() method + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... (the Python module is already imported) + // ... finally call Python module's initialize() method + if(PyObject_HasAttrString(myModule , "initialize")){ + PyObjWrapper res( PyObject_CallMethod( myModule, "initialize", "" ) ); + if( !res ) { + PyErr_Print(); + } + } + + // get the windows list from the Python module by calling windows() method + // ... first put default values + myWindowsMap.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::DockLeft ); + myWindowsMap.insert( SalomeApp_Application::WT_PyConsole, Qt::DockBottom ); + // VSR: LogWindow is not yet implemented + // myWindowsMap.insert( SalomeApp_Application::WT_LogWindow, Qt::DockBottom ); + + if(PyObject_HasAttrString(myModule , "windows")){ + PyObjWrapper res1( PyObject_CallMethod( myModule, "windows", "" ) ); + if( !res1 ) { + PyErr_Print(); + } + else { + myWindowsMap.clear(); + if ( PyDict_Check( res1 ) ) { + PyObject* key; + PyObject* value; + int pos = 0; + while ( PyDict_Next( res1, &pos, &key, &value ) ) { + // parse the return value + // it should be a map: {integer:integer} + int aKey, aValue; + if( key && PyInt_Check( key ) && value && PyInt_Check( value ) ) { + aKey = PyInt_AsLong( key ); + aValue = PyInt_AsLong( value ); + myWindowsMap[ aKey ] = aValue; + } + } + } + } + } + // get the windows list from the Python module by calling views() method + if(PyObject_HasAttrString(myModule , "views")){ + PyObjWrapper res2( PyObject_CallMethod( myModule, "views", "" ) ); + if( !res2 ) { + PyErr_Print(); + } + else { + // parse the return value + // result can be one string... + if ( PyString_Check( res2 ) ) { + myViewMgrList.append( PyString_AsString( res2 ) ); + } + // ... or list of strings + else if ( PyList_Check( res2 ) ) { + int size = PyList_Size( res2 ); + for ( int i = 0; i < size; i++ ) { + PyObject* value = PyList_GetItem( res2, i ); + if( value && PyString_Check( value ) ) { + myViewMgrList.append( PyString_AsString( value ) ); + } + } + } + } + } + myInitModule = 0; +} + +/*! + * Performs internal activation: + * - initializes/gets the Python interpreter (one per study) + * - imports the Python GUI module + * - calls Python module's setSettings() method (obsolete function, used for compatibility with old code) + * or activate() method (for new modules) + */ +void SALOME_PYQT_Module::activate( SUIT_Study* theStudy ) +{ + // get study Id + SalomeApp_Study* aStudy = dynamic_cast( theStudy ); + int aStudyId = aStudy ? aStudy->studyDS()->StudyId() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + // get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + if ( IsCallOldMethods ) { //__CALL_OLD_METHODS__ + // call Python module's setSettings() method (obsolete) + if(PyObject_HasAttrString(myModule , "setSettings")){ + PyObjWrapper res( PyObject_CallMethod( myModule, "setSettings", "" ) ); + if( !res ) { + PyErr_Print(); + } + } + } //__CALL_OLD_METHODS__ + + // call Python module's activate() method (for the new modules) + if(PyObject_HasAttrString(myModule , "activate")){ + PyObjWrapper res1( PyObject_CallMethod( myModule, "activate", "" ) ); + if( !res1 ) { + PyErr_Print(); + } + } +} + +/*! + * Performs internal deactivation: + * - calls Python module's deactivate() method + */ +void SALOME_PYQT_Module::deactivate( SUIT_Study* theStudy ) +{ + // check if the subinterpreter is initialized and Python module is imported + if ( !myInterp || !myModule ) { + // Error! Python subinterpreter should be initialized and module should be imported first! + return; + } + // then call Python module's deactivate() method + if(PyObject_HasAttrString(myModule , "deactivate")){ + PyObjWrapper res( PyObject_CallMethod( myModule, "deactivate", "" ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + * Called when active the study is actived (user brings its desktop to top) + * - initializes/gets the Python interpreter (one per study) + * - imports the Python GUI module + * - calls Python module's activeStudyChanged() method + */ +void SALOME_PYQT_Module::studyChanged( SUIT_Study* theStudy ) +{ + // get study Id + SalomeApp_Study* aStudy = dynamic_cast( theStudy ); + int aStudyId = aStudy ? aStudy->studyDS()->StudyId() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + // get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + // call Python module's activeStudyChanged() method + if(PyObject_HasAttrString(myModule , "activeStudyChanged")){ + PyObjWrapper res( PyObject_CallMethod( myModule, "activeStudyChanged", "i", aStudyId ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + * Get module engine, returns nil var if engine is not found in LifeCycleCORBA + */ +Engines::Component_var SALOME_PYQT_Module::getEngine() const +{ + Engines::Component_var comp; + // temporary solution + try { + comp = getApp()->lcc()->FindOrLoad_Component( "FactoryServerPy", name( "" ) ); + } + catch (CORBA::Exception&) { + } + return comp; +} + +/*! + * Get module engine IOR, returns empty string if engine is not found in LifeCycleCORBA + */ +QString SALOME_PYQT_Module::engineIOR() const +{ + if ( !CORBA::is_nil( getEngine() ) ) + return QString( getApp()->orb()->object_to_string( getEngine() ) ); + return QString( "" ); +} + +/*! + * Called when study desktop is activated. + * Used for notifying about changing of the active study. + */ +void SALOME_PYQT_Module::studyActivated() +{ + // StudyChangedReq: request class for internal studyChanged() operation + class StudyChangedReq : public PyInterp_Request + { + public: + StudyChangedReq( SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->studyChanged( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new StudyChangedReq( application()->activeStudy(), this ) ); +} + +/*! + * Processes context popup menu request + * - calls Python module's definePopup(...) method (obsolete function, used for compatibility with old code) + * to define the popup menu context + * - parses XML resourses file (if exists) and fills the popup menu with the items) + * - calls Python module's customPopup(...) method (obsolete function, used for compatibility with old code) + * to allow module to customize the popup menu + * - for new modules calls createPopupMenu() function to allow the modules to build the popup menu + * by using insertItem(...) Qt functions. + */ +void SALOME_PYQT_Module::contextMenu( const QString& theContext, QPopupMenu* thePopupMenu ) +{ + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + QString aContext( theContext ), aObject( "" ), aParent( "" ); + + if ( IsCallOldMethods && PyObject_HasAttrString(myModule , "definePopup") ) { //__CALL_OLD_METHODS__ + // call definePopup() Python module's function + // this is obsolete function, used only for compatibility reasons + PyObjWrapper res(PyObject_CallMethod( myModule, + "definePopup", + "sss", + aContext.latin1(), + aObject.latin1(), + aParent.latin1() ) ); + if( !res ) { + PyErr_Print(); + } + else { + // parse return value + char *co, *ob, *pa; + if( PyArg_ParseTuple( res, "sss", &co, &ob, &pa ) ) { + aContext = co; + aObject = ob; + aParent = pa; + } + } + } //__CALL_OLD_METHODS__ + + // first try to create menu via XML parser: + // we create popup menus without help of QtxPopupMgr + if ( myXmlHandler ) + myXmlHandler->createPopup( thePopupMenu, aContext, aParent, aObject ); + + PyObjWrapper sipPopup( sipBuildResult( 0, "M", thePopupMenu, sipClass_QPopupMenu ) ); + + // then call Python module's createPopupMenu() method (for new modules) + if ( PyObject_HasAttrString(myModule , "createPopupMenu") ) { + PyObjWrapper res1( PyObject_CallMethod( myModule, + "createPopupMenu", + "Os", + sipPopup.get(), + aContext.latin1() ) ); + if( !res1 ) { + PyErr_Print(); + } + } + + if ( IsCallOldMethods && PyObject_HasAttrString(myModule , "customPopup") ) { //__CALL_OLD_METHODS__ + // call customPopup() Python module's function + // this is obsolete function, used only for compatibility reasons + PyObjWrapper res2( PyObject_CallMethod( myModule, + "customPopup", + "Osss", + sipPopup.get(), + aContext.latin1(), + aObject.latin1(), + aParent.latin1() ) ); + if( !res2 ) { + PyErr_Print(); + } + } //__CALL_OLD_METHODS__ +} + +/*! + * Processes GUI event + * - calls Python module's OnGUIEvent() method + */ +void SALOME_PYQT_Module::guiEvent( const int theId ) +{ + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString(myModule , "OnGUIEvent") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, "OnGUIEvent", "i", theId ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + * Initialises python subinterpreter (one per study) + */ +void SALOME_PYQT_Module::initInterp( int theStudyId ) +{ + // check study Id + if ( !theStudyId ) { + // Error! Study Id must not be 0! + myInterp = NULL; + return; + } + // try to find the subinterpreter + if( myInterpMap.find( theStudyId ) != myInterpMap.end() ) { + // found! + myInterp = myInterpMap[ theStudyId ]; + return; + } + // not found - create a new one! + /////////////////////////////////////////////////////////////////// + // Attention: the creation of Python interpretor must be protected + // by a C++ Lock because of C threads + /////////////////////////////////////////////////////////////////// + myInterp = new SALOME_PYQT_PyInterp(); + myInterp->initialize(); + myInterpMap[ theStudyId ] = myInterp; + + // import 'salome' module and call 'salome_init' method; + // do it only once on interpreter creation + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... then import a module + PyObjWrapper aMod = PyImport_ImportModule( "salome" ); + if( !aMod ) { + // Error! + PyErr_Print(); + return; + } + // ... then call a method + PyObjWrapper aRes( PyObject_CallMethod( aMod, "salome_init", "" ) ); + if( !aRes ) { + // Error! + PyErr_Print(); + return; + } +} + +/*! + * Imports Python GUI module and remember the reference to the module + * !!! initInterp() should be called first!!! + */ +void SALOME_PYQT_Module::importModule() +{ + // check if the subinterpreter is initialized + if ( !myInterp ) { + // Error! Python subinterpreter should be initialized first! + myModule = 0; + return; + } + // import Python GUI module and puts it in attribute + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... then import a module + QString aMod = QString( name("") ) + "GUI"; + myModule = PyImport_ImportModule( (char*)( aMod.latin1() ) ); + if( !myModule ) { + // Error! + PyErr_Print(); + return; + } +} + +/*! + * Calls .setWorkSpace() method with PyQt QWidget object to use with + * interpreter. + * !!! initInterp() and importModule() should be called first!!! + */ +void SALOME_PYQT_Module::setWorkSpace() +{ + // check if the subinterpreter is initialized and Python module is imported + if ( !myInterp || !myModule ) { + // Error! Python subinterpreter should be initialized and module should be imported first! + return; + } + + // call setWorkspace() method + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + // ... then try to import SalomePyQt module. If it's not possible don't go on. + PyObjWrapper aQtModule( PyImport_ImportModule( "SalomePyQt" ) ); + if( !aQtModule ) { + // Error! + PyErr_Print(); + return; + } + + if ( IsCallOldMethods ) { //__CALL_OLD_METHODS__ + // ... then get workspace object + QWidget* aWorkspace = 0; + if ( getApp()->desktop()->inherits( "STD_MDIDesktop" ) ) { + STD_MDIDesktop* aDesktop = dynamic_cast( getApp()->desktop() ); + if ( aDesktop ) + aWorkspace = aDesktop->workspace(); + } + else if ( getApp()->desktop()->inherits( "STD_TabDesktop" ) ) { + STD_TabDesktop* aDesktop = dynamic_cast( getApp()->desktop() ); + if ( aDesktop ) + aWorkspace = aDesktop->workstack(); + } + PyObjWrapper pyws( sipBuildResult( 0, "M", aWorkspace, sipClass_QWidget ) ); + // ... and finally call Python module's setWorkspace() method (obsolete) + if ( PyObject_HasAttrString(myModule , "setWorkSpace") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, "setWorkSpace", "O", pyws.get() ) ); + if( !res ) { + PyErr_Print(); + } + } + } //__CALL_OLD_METHODS__ +} + +/*! + * Adds an action into private action list [internal usage] + */ +void SALOME_PYQT_Module::addAction( const PyQtGUIAction type, QAction* action ) +{ + switch ( type ) { + case PYQT_ACTION_MENU: + myMenuActionList.append( action ); + break; + case PYQT_ACTION_TOOLBAL: + myToolbarActionList.append( action ); + break; + case PYQT_ACTION_POPUP: + myPopupActionList.append( action ); + break; + } +} + + +/*! + * The next methods just call the parent implementation. + * This is done to open protected methods from CAM_Module class. +*/ +int SALOME_PYQT_Module::createTool( const QString& name ) +{ + return SalomeApp_Module::createTool( name ); +} +int SALOME_PYQT_Module::createTool( const int id, const int tBar, const int idx ) +{ + return SalomeApp_Module::createTool( id, tBar, idx ); +} +int SALOME_PYQT_Module::createTool( const int id, const QString& tBar, const int idx ) +{ + return SalomeApp_Module::createTool( id, tBar, idx ); +} +int SALOME_PYQT_Module::createTool( QAction* a, const int tBar, const int id, const int idx ) +{ + return SalomeApp_Module::createTool( a, tBar, id, idx ); +} +int SALOME_PYQT_Module::createTool( QAction* a, const QString& tBar, const int id, const int idx ) +{ + return SalomeApp_Module::createTool( a, tBar, id, idx ); +} +int SALOME_PYQT_Module::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( subMenu, menu, id, group, idx ); +} +int SALOME_PYQT_Module::createMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( subMenu, menu, id, group, idx ); +} +int SALOME_PYQT_Module::createMenu( const int id, const int menu, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( id, menu, group, idx ); +} +int SALOME_PYQT_Module::createMenu( const int id, const QString& menu, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( id, menu, group, idx ); +} +int SALOME_PYQT_Module::createMenu( QAction* a, const int menu, const int id, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( a, menu, id, group, idx ); +} +int SALOME_PYQT_Module::createMenu( QAction* a, const QString& menu, const int id, const int group, const int idx ) +{ + return SalomeApp_Module::createMenu( a, menu, id, group, idx ); +} +QAction* SALOME_PYQT_Module::createSeparator() +{ + return SalomeApp_Module::separator(); +} +QAction* SALOME_PYQT_Module::action( const int id ) const +{ + QAction* a = SalomeApp_Module::action( id ); + if ( !a ) // try own action map for menu items + a = SalomeApp_Module::action( id + PYQT_ACTION_MENU ); + if ( !a ) // try own action map for toolbar items + a = SalomeApp_Module::action( id + PYQT_ACTION_TOOLBAL ); + if ( !a ) // try own action map for popup items + a = SalomeApp_Module::action( id + PYQT_ACTION_POPUP ); + return a; +} +int SALOME_PYQT_Module::actionId( const QAction* a ) const +{ + int id = SalomeApp_Module::actionId( a ); + if ( myMenuActionList.contains( a ) ) // check own action map for menu items + id -= PYQT_ACTION_MENU; + if ( myToolbarActionList.contains( a ) ) // check own action map for toolbar items + id -= PYQT_ACTION_TOOLBAL; + if ( myPopupActionList.contains( a ) ) // check own action map for popup items + id -= PYQT_ACTION_POPUP; + return id; +} +QAction* SALOME_PYQT_Module::createAction( const int id, const QString& text, const QString& icon, + const QString& menu, const QString& tip, const int key, + const bool toggle ) +{ + QIconSet anIcon; + if ( !icon.isEmpty() ) { + QPixmap pixmap = getApp()->resourceMgr()->loadPixmap( name(""), tr( icon ) ); + if ( !pixmap.isNull() ) + anIcon = QIconSet( pixmap ); + } + return SalomeApp_Module::createAction( id, text, anIcon, menu, tip, key, getApp()->desktop(), toggle, this, SLOT( onGUIEvent() ) ); +} + + +//============================================================================= +// SALOME_PYQT_XmlHandler class implementation +//============================================================================= + +// gets an tag name for the dom element [ static ] +// returns an empty string if the element does not have tag name +static QString tagName( const QDomElement& element ) { + return element.tagName().stripWhiteSpace(); +} + +// gets an attribute by it's name for the dom element [ static ] +// returns an empty string if the element does not have such attribute +static QString attribute( const QDomElement& element, const QString& attName ) { + return element.attribute( attName ).stripWhiteSpace(); +} + +// checks the given value for the boolean value [ static ] +// returns TRUE if string is "true", "yes" or "1" +static bool checkBool( const QString& value ) { + return ( value == "true" || value == "yes" || value == "1" ); +} + +// checks the given value for the integer value [ static ] +// returns -1 if item is empty or presents and invalid number +static int checkInt( const QString& value ) +{ + return value.isEmpty() ? -1 : value.toInt(); +} + +/*! + * Constructor + */ +SALOME_PYQT_XmlHandler::SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, const QString& fileName ) + : myModule( module ) +{ + QFile aFile( fileName ); + if ( !aFile.open( IO_ReadOnly ) ) + return; + if ( !myDoc.setContent( &aFile ) ) { + aFile.close(); + return; + } + aFile.close(); +} + +/*! + Called by SALOME_PYQT_Module::initialize() in order to create actions + (menus, toolbars, popup menus) + */ +void SALOME_PYQT_XmlHandler::createActions() +{ + // get document element + QDomElement aDocElem = myDoc.documentElement(); + + // get main menu actions + QDomNodeList aMenuList = aDocElem.elementsByTagName( "menu-item" ); + for ( int i = 0; i < aMenuList.count(); i++ ) { + QDomNode n = aMenuList.item( i ); + createMenu( n ); + } + + // create toolbars actions + QDomNodeList aToolsList = aDocElem.elementsByTagName( "toolbar" ); + for ( int i = 0; i < aToolsList.count(); i++ ) { + QDomNode n = aToolsList.item( i ); + createToolBar( n ); + } +} + +/*! + * Creates popup menu + */ +void SALOME_PYQT_XmlHandler::createPopup( QPopupMenu* menu, + const QString& context, + const QString& parent, + const QString& object ) +{ + // get document element + QDomElement aDocElem = myDoc.documentElement(); + + // get popup menus actions + QDomNodeList aPopupList = aDocElem.elementsByTagName( "popupmenu" ); + for ( int i = 0; i < aPopupList.count(); i++ ) { + QDomNode n = aPopupList.item( i ); + if ( !n.isNull() && n.isElement() ) { + QDomElement e = n.toElement(); + QString lab = attribute( e, "label-id" ); + QString ctx = attribute( e, "context-id" ); + QString prt = attribute( e, "parent-id" ); + QString obj = attribute( e, "object-id" ); + if ( ctx == context && prt == parent && obj == object ) { + insertPopupItems( n, menu ); + break; + } + } + } +} + +/*! + Create main menu with child actions + */ +void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentMenuId ) +{ + if ( !myModule ) + return; + + if ( parentNode.isNull() ) + return; + + QDomElement parentElement = parentNode.toElement(); + if ( !parentElement.isNull() ) { + QString plabel = attribute( parentElement, "label-id" ); + int pid = checkInt( attribute( parentElement, "item-id" ) ); + int ppos = checkInt( attribute( parentElement, "pos-id" ) ); + if ( !plabel.isEmpty() ) { + // create menu + int menuId = myModule->createMenu( plabel, // label + parentMenuId, // parent menu ID, should be -1 for main menu + pid, // ID + 80, // group ID + ppos ); // position + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + if ( aTagName == "popup-item" ) { + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + QString tooltip = attribute( elem, "tooltip-id" ); + QString accel = attribute( elem, "accel-id" ); + bool toggle = checkBool( attribute( elem, "toggle-id" ) ); + ////QString execute = attribute( elem, "execute-action" ); // not used + + // -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 && !myModule->action( SALOME_PYQT_Module::PYQT_ACTION_MENU + id ) ) { + // little trick to have several actions with same ID for menus and toolbars + id = SALOME_PYQT_Module::PYQT_ACTION_MENU + id; + // create menu action + QAction* action = myModule->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + toggle ); // toogled action + myModule->addAction( SALOME_PYQT_Module::PYQT_ACTION_MENU, action ); + myModule->createMenu( action, menuId, -1, 80, pos ); + } + } + else if ( aTagName == "submenu" ) { + // create sub-menu + createMenu( node, menuId ); + } + else if ( aTagName == "separator" ) { + // create menu separator + int pos = checkInt( attribute( elem, "pos-id" ) ); + QAction* action = myModule->createSeparator(); + myModule->createMenu( action, menuId, -1, 80, pos ); + } + } + node = node.nextSibling(); + } + } + } +} + +/*! + Create a toolbar with child actions + */ +void SALOME_PYQT_XmlHandler::createToolBar( QDomNode& parentNode ) +{ + if ( !myModule ) + return; + + if ( parentNode.isNull() ) + return; + + QDomElement parentElement = parentNode.toElement(); + if ( !parentElement.isNull() ) { + QString aLabel = attribute( parentElement, "label-id" ); + if ( !aLabel.isEmpty() ) { + // create toolbar + int tbId = myModule->createTool( aLabel ); + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + if ( aTagName == "toolbutton-item" ) { + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + QString tooltip = attribute( elem, "tooltip-id" ); + QString accel = attribute( elem, "accel-id" ); + bool toggle = checkBool( attribute( elem, "toggle-id" ) ); + ////QString execute = attribute( elem, "execute-action" ); // not used + + // -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 && !myModule->action( SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL + id ) ) { + // little trick to have several actions with same ID for menus and toolbars + id = SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL + id; + // create toolbar action + QAction* action = myModule->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + toggle ); // toogled action + myModule->addAction( SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL, action ); + myModule->createTool( action, tbId, -1, pos ); + } + } + else if ( aTagName == "separatorTB" ) { + // create toolbar separator + int pos = checkInt( attribute( elem, "pos-id" ) ); + QAction* action = myModule->createSeparator(); + myModule->createTool( action, tbId, -1, pos ); + } + } + node = node.nextSibling(); + } + } + } +} + +void SALOME_PYQT_XmlHandler::insertPopupItems( QDomNode& parentNode, QPopupMenu* menu ) +{ + if ( !myModule ) + return; + + if ( parentNode.isNull() ) + return; + + // we create popup menus without help of QtxPopupMgr + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + if ( aTagName == "popup-item" ) { + // insert a command item + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + /////QString tooltip = attribute( elem, "tooltip-id" ); // not used + QString accel = attribute( elem, "accel-id" ); + /////bool toggle = checkBool( attribute( elem, "toggle-id" ) ); // not used + /////QString execute = attribute( elem, "execute-action" ); // not used + + QIconSet anIcon; + if ( !icon.isEmpty() ) { + QPixmap pixmap = myModule->getApp()->resourceMgr()->loadPixmap( myModule->name(""), icon ); + if ( !pixmap.isNull() ) + anIcon = QIconSet( pixmap ); + } + + // -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 ) { + menu->insertItem( anIcon, label, myModule, SLOT( onGUIEvent(int) ), QKeySequence( accel ), id, pos ); + } + } + else if ( aTagName == "submenu" ) { + // create sub-menu + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + + QIconSet anIcon; + if ( !icon.isEmpty() ) { + QPixmap pixmap = myModule->getApp()->resourceMgr()->loadPixmap( myModule->name(""), icon ); + if ( !pixmap.isNull() ) + anIcon = QIconSet( pixmap ); + } + + QPopupMenu* newPopup = new QPopupMenu( menu, label ); + menu->insertItem( anIcon, label, newPopup, id, pos ); + insertPopupItems( node, newPopup ); + } + else if ( aTagName == "separator" ) { + // create menu separator + int pos = checkInt( attribute( elem, "pos-id" ) ); + menu->insertSeparator( pos ); + } + } + node = node.nextSibling(); + } +} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_PyInterp.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_PyInterp.cxx new file mode 100644 index 000000000..1956ec3af --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_PyInterp.cxx @@ -0,0 +1,83 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : SALOME_PYQT_PyInterp.cxx +// Author : Christian CAREMOLI, Paul RASCLE, EDF +// Module : SALOME +// $Header$ + +#include "SALOME_PYQT_PyInterp.h" // this include must be first (see PyInterp_base.h)! +#include "utilities.h" +#include "Container_init_python.hxx" + +using namespace std; + + +/*! + * constructor : the main SALOME Python interpreter is used for PyQt GUI. + * calls initialize method defined in base class, which calls virtual methods + * initstate & initcontext redefined here + */ +SALOME_PYQT_PyInterp::SALOME_PYQT_PyInterp(): PyInterp_base() +{ +} + +SALOME_PYQT_PyInterp::~SALOME_PYQT_PyInterp() +{ +} + +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 + */ + SCRUTE(KERNEL_PYTHON::_gtstate); + _tstate = KERNEL_PYTHON::_gtstate; + PyEval_AcquireThread(_tstate); + SCRUTE(_tstate); + PyEval_ReleaseThread(_tstate); + return true; +} + +bool SALOME_PYQT_PyInterp::initContext() +{ + /* + * The GIL is assumed to be held + * 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); + return true; +} + +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 + 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 + Py_DECREF(code); + if(!r){ + // Une erreur s est produite a l execution + PyErr_Print(); + return -1 ; + } + Py_DECREF(r); + return 0; +} diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx new file mode 100644 index 000000000..d7b887fe6 --- /dev/null +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -0,0 +1,1255 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +//============================================================================= +// File : SalomePyQt.cxx +// Created : 25/04/05 +// Author : Vadim SANDLER +// Project : SALOME +// Copyright : 2003-2005 CEA/DEN, EDF R&D +// $Header : $ +//============================================================================= + +#include "SALOME_PYQT_Module.h" // this include must be first!!! +#include "SalomePyQt.h" + +#include +#include +#include +#include +#include +#include + +#include "SALOME_Event.hxx" + +#include "SUIT_Session.h" +#include "SUIT_Desktop.h" +#include "SUIT_ResourceMgr.h" +#include "SUIT_Tools.h" +#include "STD_MDIDesktop.h" +#include "SalomeApp_Application.h" +#include "SalomeApp_Study.h" +#include "LightApp_SelectionMgr.h" +#include "OB_Browser.h" +#include "QtxAction.h" + +using namespace std; + +//==================================================================================== +// static functions +//==================================================================================== +/*! + getApplication() + Returns active application object [ static ] +*/ +static SalomeApp_Application* getApplication() { + if ( SUIT_Session::session() ) + return dynamic_cast( SUIT_Session::session()->activeApplication() ); + return NULL; +} + +/*! + getActiveStudy() + Gets active study or 0 if there is no study opened [ static ] +*/ +static SalomeApp_Study* getActiveStudy() +{ + if ( getApplication() ) + return dynamic_cast( getApplication()->activeStudy() ); + return 0; +} + +//==================================================================================== +// SALOME_Selection class. +//==================================================================================== +static QMap SelMap; + +/*! + SALOME_Selection::GetSelection + Creates or finds the selection object (one per study). +*/ +SALOME_Selection* SALOME_Selection::GetSelection( SalomeApp_Application* app ) +{ + SALOME_Selection* sel = 0; + if ( app && SelMap.find( app ) != SelMap.end() ) + sel = SelMap[ app ]; + else + sel = SelMap[ app ] = new SALOME_Selection( app ); + return sel; +} + +/*! + SALOME_Selection::SALOME_Selection + Selection constructor. +*/ +SALOME_Selection::SALOME_Selection( QObject* p ) : QObject( p ), mySelMgr( 0 ) +{ + SalomeApp_Application* app = dynamic_cast( p ); + if ( app ) { + mySelMgr = app->selectionMgr(); + connect( mySelMgr, SIGNAL( selectionChanged() ), this, SIGNAL( currentSelectionChanged() ) ); + connect( mySelMgr, SIGNAL( destroyed() ), this, SLOT ( onSelMgrDestroyed() ) ); + } +} +/*! + SALOME_Selection::~SALOME_Selection + Selection destructor. Removes selection object from the map. +*/ +SALOME_Selection::~SALOME_Selection() +{ + SalomeApp_Application* app = dynamic_cast( parent() ); + if ( app && SelMap.find( app ) != SelMap.end() ) + SelMap.remove( app ); +} + +/*! + SALOME_Selection::onSelMgrDestroyed + Watches for the selection manager destroying when study is closed. +*/ +void SALOME_Selection::onSelMgrDestroyed() +{ + mySelMgr = 0; +} + +/*! + SALOME_Selection::Clear + Clears the selection. +*/ +void SALOME_Selection::Clear() +{ + class TEvent: public SALOME_Event { + LightApp_SelectionMgr* mySelMgr; + public: + TEvent( LightApp_SelectionMgr* selMgr ) + : mySelMgr( selMgr ) {} + virtual void Execute() { + if ( mySelMgr ) + mySelMgr->clearSelected(); + } + }; + ProcessVoidEvent( new TEvent( mySelMgr ) ); +} + +/*! + SALOME_Selection::ClearIObjects + Clears the selection. +*/ +void SALOME_Selection::ClearIObjects() +{ + Clear(); +} + +/*! + SALOME_Selection::ClearFilters + Removes all selection filters. +*/ +void SALOME_Selection::ClearFilters() +{ + class TEvent: public SALOME_Event { + LightApp_SelectionMgr* mySelMgr; + public: + TEvent( LightApp_SelectionMgr* selMgr ) + : mySelMgr( selMgr ) {} + virtual void Execute() { + if ( mySelMgr ) + mySelMgr->clearFilters(); + } + }; + ProcessVoidEvent( new TEvent( mySelMgr ) ); +} + +//==================================================================================== +// SalomePyQt class +//==================================================================================== + +/*! + SalomePyQt::getDesktop + Gets desktop. Returns 0 in error. +*/ +class TGetDesktopEvent: public SALOME_Event { +public: + typedef QWidget* TResult; + TResult myResult; + TGetDesktopEvent() : myResult( 0 ) {} + virtual void Execute() { + if ( getApplication() ) + myResult = (QWidget*)( getApplication()->desktop() ); + } +}; +QWidget* SalomePyQt::getDesktop() +{ + return ProcessEvent( new TGetDesktopEvent() ); +} + +/*! + SalomePyQt::getMainFrame + Gets workspace widget. Returns 0 in error. +*/ +class TGetMainFrameEvent: public SALOME_Event { +public: + typedef QWidget* TResult; + TResult myResult; + TGetMainFrameEvent() : myResult( 0 ) {} + virtual void Execute() { + if ( getApplication() ) { + SUIT_Desktop* aDesktop = getApplication()->desktop(); + myResult = (QWidget*)( aDesktop->centralWidget() ); + } + } +}; +QWidget* SalomePyQt::getMainFrame() +{ + return ProcessEvent( new TGetMainFrameEvent() ); +} + +/*! + SalomePyQt::getMainMenuBar + Gets main menu. Returns 0 in error. +*/ +class TGetMainMenuBarEvent: public SALOME_Event { +public: + typedef QMenuBar* TResult; + TResult myResult; + TGetMainMenuBarEvent() : myResult( 0 ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + myResult = anApp->desktop()->menuBar(); + } + } +}; +QMenuBar* SalomePyQt::getMainMenuBar() +{ + return ProcessEvent( new TGetMainMenuBarEvent() ); +} + +/*! + SalomePyQt::getPopupMenu + Gets an main menu's child popup menu by its id +*/ +class TGetPopupMenuEvent: public SALOME_Event { +public: + typedef QPopupMenu* TResult; + TResult myResult; + MenuName myMenuName; + TGetPopupMenuEvent( const MenuName menu ) : myResult( 0 ), myMenuName( menu ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + QMenuBar* menuBar = anApp->desktop()->menuBar(); + if ( menuBar ) { + QString menu; + switch( myMenuName) { + case File: + menu = QObject::tr( "MEN_DESK_FILE" ); break; + case View: + menu = QObject::tr( "MEN_DESK_VIEW" ); break; + case Edit: + menu = QObject::tr( "MEN_DESK_EDIT" ); break; + case Preferences: + menu = QObject::tr( "MEN_DESK_PREFERENCES" ); break; + case Tools: + menu = QObject::tr( "MEN_DESK_TOOLS" ); break; + case Window: + menu = QObject::tr( "MEN_DESK_WINDOW" ); break; + case Help: + menu = QObject::tr( "MEN_DESK_HELP" ); break; + } + for ( int i = 0; i < menuBar->count() && !myResult; i++ ) { + QMenuItem* item = menuBar->findItem( menuBar->idAt( i ) ); + if ( item && item->text() == menu && item->popup() ) + myResult = item->popup(); + } + } + } + } +}; +QPopupMenu* SalomePyQt::getPopupMenu( const MenuName menu ) +{ + return ProcessEvent( new TGetPopupMenuEvent( menu ) ); +} + +/*! + SalomePyQt::getStudyId + Returns active study's ID or 0 if there is no active study. +*/ +class TGetStudyIdEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + TGetStudyIdEvent() : myResult( 0 ) {} + virtual void Execute() { + if ( SalomeApp_Study* aStudy = getActiveStudy() ) { + myResult = aStudy->studyDS()->StudyId(); + } + } +}; +int SalomePyQt::getStudyId() +{ + return ProcessEvent( new TGetStudyIdEvent() ); +} + +/*! + SalomePyQt::getSelection + Creates a Selection object (to provide a compatibility with previous SALOME GUI). +*/ +class TGetSelectionEvent: public SALOME_Event { +public: + typedef SALOME_Selection* TResult; + TResult myResult; + TGetSelectionEvent() : myResult( 0 ) {} + virtual void Execute() { + myResult = SALOME_Selection::GetSelection( getApplication() ); + } +}; +SALOME_Selection* SalomePyQt::getSelection() +{ + return ProcessEvent( new TGetSelectionEvent() ); +} + +/*! + SalomePyQt::putInfo + Puts an information message to the desktop's status bar + (with optional delay parameter given in seconds) +*/ +class TPutInfoEvent: public SALOME_Event { + QString myMsg; + int mySecs; +public: + TPutInfoEvent( const QString& msg, const int sec = 0 ) : myMsg( msg ), mySecs( sec ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + anApp->putInfo( myMsg, mySecs * 1000 ); + } + } +}; +void SalomePyQt::putInfo( const QString& msg, const int sec ) +{ + ProcessVoidEvent( new TPutInfoEvent( msg, sec ) ); +} + +/*! + SalomePyQt::getActiveComponent + Returns an active component name or empty string if there is no active component +*/ +class TGetActiveComponentEvent: public SALOME_Event { +public: + typedef QString TResult; + TResult myResult; + TGetActiveComponentEvent() {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + if ( CAM_Module* mod = anApp->activeModule() ) { + myResult = mod->name(""); + } + } + } +}; +const QString SalomePyQt::getActiveComponent() +{ + return ProcessEvent( new TGetActiveComponentEvent() ); +} + +/*! + SalomePyQt::updateObjBrowser + Updates an Object Browser of a given study. + If <= 0 the active study's object browser is updated. + parameter is obsolete parameter and currently not used. To be removed lately. +*/ +void SalomePyQt::updateObjBrowser( const int studyId, bool updateSelection ) +{ + class TEvent: public SALOME_Event { + int myStudyId; + bool myUpdateSelection; + public: + TEvent( const int studyId, bool updateSelection ) + : myStudyId( studyId ), myUpdateSelection( updateSelection ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + if ( getActiveStudy() && myStudyId <= 0 ) + myStudyId = getActiveStudy()->id(); + if ( myStudyId > 0 ) { + QPtrList apps = SUIT_Session::session()->applications(); + QPtrListIterator it( apps ); + for( ; it.current(); ++it ) { + SalomeApp_Application* anApp = dynamic_cast( it.current() ); + if ( anApp && anApp->activeStudy() && anApp->activeStudy()->id() == myStudyId ) + anApp->updateObjectBrowser(); + } + } + } + } + }; + ProcessVoidEvent( new TEvent( studyId, updateSelection ) ); +} + +const char* DEFAULT_SECTION = "SalomePyQt"; + +/*! + SalomePyQt::addStringSetting + Adds a string setting to the application preferences + parameter is obsolete parameter and currently not used. To be removed lately. + This function is obsolete. Use addSetting() instead. +*/ +void SalomePyQt::addStringSetting( const QString& name, const QString& value, bool autoValue ) +{ + class TEvent: public SALOME_Event { + QString myName; + QString myValue; + bool myAutoValue; + public: + TEvent( const QString& name, const QString& value, bool autoValue ) + : myName( name ), myValue( value ), myAutoValue( autoValue ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QStringList sl = QStringList::split( ":", myName ); + QString _sec = sl.count() > 1 ? sl[ 0 ].stripWhiteSpace() : QString( DEFAULT_SECTION ); + QString _nam = sl.count() > 1 ? sl[ 1 ].stripWhiteSpace() : sl.count() > 0 ? sl[ 0 ].stripWhiteSpace() : QString( "" ); + if ( !_sec.isEmpty() && !_nam.isEmpty() ) + resMgr->setValue( _sec, _nam, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( name, value, autoValue ) ); +} + +/*! + SalomePyQt::addIntSetting + Adds an integer setting to the application preferences + parameter is obsolete parameter and currently not used. To be removed lately. + This function is obsolete. Use addSetting() instead. +*/ +void SalomePyQt::addIntSetting( const QString& name, const int value, bool autoValue) +{ + class TEvent: public SALOME_Event { + QString myName; + int myValue; + bool myAutoValue; + public: + TEvent( const QString& name, const int value, bool autoValue ) + : myName( name ), myValue( value ), myAutoValue( autoValue ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QStringList sl = QStringList::split( ":", myName ); + QString _sec = sl.count() > 1 ? sl[ 0 ].stripWhiteSpace() : QString( DEFAULT_SECTION ); + QString _nam = sl.count() > 1 ? sl[ 1 ].stripWhiteSpace() : sl.count() > 0 ? sl[ 0 ].stripWhiteSpace() : QString( "" ); + if ( !_sec.isEmpty() && !_nam.isEmpty() ) + resMgr->setValue( _sec, _nam, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( name, value, autoValue ) ); +} + +/*! + SalomePyQt::addDoubleSetting + Adds an double setting to the application preferences + parameter is obsolete parameter and currently not used. To be removed lately. + This function is obsolete. Use addSetting() instead. +*/ +void SalomePyQt::addDoubleSetting( const QString& name, const double value, bool autoValue ) +{ + class TEvent: public SALOME_Event { + QString myName; + double myValue; + bool myAutoValue; + public: + TEvent( const QString& name, const double value, bool autoValue ) + : myName( name ), myValue( value ), myAutoValue( autoValue ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QStringList sl = QStringList::split( ":", myName ); + QString _sec = sl.count() > 1 ? sl[ 0 ].stripWhiteSpace() : QString( DEFAULT_SECTION ); + QString _nam = sl.count() > 1 ? sl[ 1 ].stripWhiteSpace() : sl.count() > 0 ? sl[ 0 ].stripWhiteSpace() : QString( "" ); + if ( !_sec.isEmpty() && !_nam.isEmpty() ) + resMgr->setValue( _sec, _nam, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( name, value, autoValue ) ); +} + +/*! + SalomePyQt::removeSettings + Removes a setting from the application preferences + This function is obsolete. Use removeSetting() instead. +*/ +void SalomePyQt::removeSettings( const QString& name ) +{ + class TEvent: public SALOME_Event { + QString myName; + public: + TEvent( const QString& name ) : myName( name ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QStringList sl = QStringList::split( ":", myName ); + QString _sec = sl.count() > 1 ? sl[ 0 ].stripWhiteSpace() : QString( DEFAULT_SECTION ); + QString _nam = sl.count() > 1 ? sl[ 1 ].stripWhiteSpace() : sl.count() > 0 ? sl[ 0 ].stripWhiteSpace() : QString( "" ); + if ( !_sec.isEmpty() && !_nam.isEmpty() ) + resMgr->remove( _sec, _nam ); + } + } + }; + ProcessVoidEvent( new TEvent( name ) ); +} + +/*! + SalomePyQt::getSetting + Gets a setting value (as string) + This function is obsolete. Use stringSetting(), integerSetting(), + boolSetting(), stringSetting() or colorSetting() instead. +*/ +class TGetSettingEvent: public SALOME_Event { +public: + typedef QString TResult; + TResult myResult; + QString myName; + TGetSettingEvent( const QString& name ) : myName( name ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QStringList sl = QStringList::split( ":", myName ); + QString _sec = sl.count() > 1 ? sl[ 0 ].stripWhiteSpace() : QString( DEFAULT_SECTION ); + QString _nam = sl.count() > 1 ? sl[ 1 ].stripWhiteSpace() : sl.count() > 0 ? sl[ 0 ].stripWhiteSpace() : QString( "" ); + myResult = ( !_sec.isEmpty() && !_nam.isEmpty() ) ? resMgr->stringValue( _sec, _nam, "" ) : QString( "" ); + } + } +}; +QString SalomePyQt::getSetting( const QString& name ) +{ + return ProcessEvent( new TGetSettingEvent( name ) ); +} + +/*! + SalomePyQt::addSetting + Adds a double setting to the application preferences +*/ +void SalomePyQt::addSetting( const QString& section, const QString& name, const double value ) +{ + class TEvent: public SALOME_Event { + QString mySection; + QString myName; + double myValue; + public: + TEvent( const QString& section, const QString& name, double value ) + : mySection( section ), myName( name ), myValue( value ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !mySection.isEmpty() && !myName.isEmpty() ) + resMgr->setValue( mySection, myName, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( section, name, value ) ); +} + +/*! + SalomePyQt::addSetting + Adds an integer setting to the application preferences +*/ +void SalomePyQt::addSetting( const QString& section, const QString& name, const int value ) +{ + class TEvent: public SALOME_Event { + QString mySection; + QString myName; + int myValue; + public: + TEvent( const QString& section, const QString& name, int value ) + : mySection( section ), myName( name ), myValue( value ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !mySection.isEmpty() && !myName.isEmpty() ) + resMgr->setValue( mySection, myName, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( section, name, value ) ); +} + +/*! + SalomePyQt::addSetting + Adds a string setting to the application preferences +*/ +void SalomePyQt::addSetting( const QString& section, const QString& name, const QString& value ) +{ + class TEvent: public SALOME_Event { + QString mySection; + QString myName; + QString myValue; + public: + TEvent( const QString& section, const QString& name, const QString& value ) + : mySection( section ), myName( name ), myValue( value ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !mySection.isEmpty() && !myName.isEmpty() ) + resMgr->setValue( mySection, myName, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( section, name, value ) ); +} + +/*! + SalomePyQt::addSetting + Adds a color setting to the application preferences +*/ +void SalomePyQt::addSetting( const QString& section, const QString& name, const QColor& value ) +{ + class TEvent: public SALOME_Event { + QString mySection; + QString myName; + QColor myValue; + public: + TEvent( const QString& section, const QString& name, const QColor& value ) + : mySection( section ), myName( name ), myValue( value ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !mySection.isEmpty() && !myName.isEmpty() ) + resMgr->setValue( mySection, myName, myValue ); + } + } + }; + ProcessVoidEvent( new TEvent( section, name, value ) ); +} + +/*! + SalomePyQt::integerSetting + Gets an integer setting from the application preferences +*/ +class TGetIntSettingEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + QString mySection; + QString myName; + TResult myDefault; + TGetIntSettingEvent( const QString& section, const QString& name, const int def ) + : mySection( section ), myName( name ), myDefault( def ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->integerValue( mySection, myName, myDefault ) : myDefault; + } + } +}; +int SalomePyQt::integerSetting( const QString& section, const QString& name, const int def ) +{ + return ProcessEvent( new TGetIntSettingEvent( section, name, def ) ); +} + +/*! + SalomePyQt::doubleSetting + Gets a double setting from the application preferences +*/ +class TGetDblSettingEvent: public SALOME_Event { +public: + typedef double TResult; + TResult myResult; + QString mySection; + QString myName; + TResult myDefault; + TGetDblSettingEvent( const QString& section, const QString& name, const double def ) + : mySection( section ), myName( name ), myDefault( def ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->doubleValue( mySection, myName, myDefault ) : myDefault; + } + } +}; +double SalomePyQt::doubleSetting( const QString& section, const QString& name, const int def ) +{ + return ProcessEvent( new TGetDblSettingEvent( section, name, def ) ); +} + +/*! + SalomePyQt::boolSetting + Gets a boolean setting from the application preferences +*/ +class TGetBoolSettingEvent: public SALOME_Event { +public: + typedef bool TResult; + TResult myResult; + QString mySection; + QString myName; + TResult myDefault; + TGetBoolSettingEvent( const QString& section, const QString& name, const bool def ) + : mySection( section ), myName( name ), myDefault( def ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->booleanValue( mySection, myName, myDefault ) : myDefault; + } + } +}; +bool SalomePyQt::boolSetting( const QString& section, const QString& name, const bool def ) +{ + return ProcessEvent( new TGetBoolSettingEvent( section, name, def ) ); +} + +/*! + SalomePyQt::stringSetting + Gets a string setting from the application preferences +*/ +class TGetStrSettingEvent: public SALOME_Event { +public: + typedef QString TResult; + TResult myResult; + QString mySection; + QString myName; + TResult myDefault; + TGetStrSettingEvent( const QString& section, const QString& name, const QString& def ) + : mySection( section ), myName( name ), myDefault( def ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->stringValue( mySection, myName, myDefault ) : myDefault; + } + } +}; +QString SalomePyQt::stringSetting( const QString& section, const QString& name, const QString& def ) +{ + return ProcessEvent( new TGetStrSettingEvent( section, name, def ) ); +} + +/*! + SalomePyQt::colorSetting + Gets a color setting from the application preferences +*/ +class TGetColorSettingEvent: public SALOME_Event { +public: + typedef QColor TResult; + TResult myResult; + QString mySection; + QString myName; + TResult myDefault; + TGetColorSettingEvent( const QString& section, const QString& name, const QColor& def ) + : mySection( section ), myName( name ), myDefault( def ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->colorValue( mySection, myName, myDefault ) : myDefault; + } + } +}; +QColor SalomePyQt::colorSetting ( const QString& section, const QString& name, const QColor& def ) +{ + return ProcessEvent( new TGetColorSettingEvent( section, name, def ) ); +} + +/*! + SalomePyQt::removeSetting + Removes a setting from the application preferences +*/ +void SalomePyQt::removeSetting( const QString& section, const QString& name ) +{ + class TEvent: public SALOME_Event { + QString mySection; + QString myName; + public: + TEvent( const QString& section, const QString& name ) : mySection( section ), myName( name ) {} + virtual void Execute() { + if ( SUIT_Session::session() ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !mySection.isEmpty() && !myName.isEmpty() ) + resMgr->remove( mySection, myName ); + } + } + }; + ProcessVoidEvent( new TEvent( section, name ) ); +} + +/*! + SalomePyQt::getFileName + Displays 'Open/Save file' dialog box and returns a user's choice (file name) +*/ +class TGetFileNameEvent: public SALOME_Event { +public: + typedef QString TResult; + TResult myResult; + QWidget* myParent; + QString myInitial; + QStringList myFilters; + QString myCaption; + bool myOpen; + TGetFileNameEvent( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption, + bool open ) + : myParent ( parent ), + myInitial( initial ), + myFilters( filters ), + myCaption( caption ), + myOpen ( open ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + myResult = anApp->getFileName( myOpen, myInitial, myFilters.join(";;"), myCaption, myParent ); + } + } +}; +QString SalomePyQt::getFileName( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption, + bool open ) +{ + return ProcessEvent( new TGetFileNameEvent( parent, initial, filters, caption, open ) ); +} + +/*! + SalomePyQt::getOpenFileNames + Displays 'Open files' dialog box and returns a user's choice (a list of file names) +*/ +class TGetOpenFileNamesEvent: public SALOME_Event { +public: + typedef QStringList TResult; + TResult myResult; + QWidget* myParent; + QString myInitial; + QStringList myFilters; + QString myCaption; + TGetOpenFileNamesEvent( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption ) + : myParent ( parent ), + myInitial( initial ), + myFilters( filters ), + myCaption( caption ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + myResult = anApp->getOpenFileNames( myInitial, myFilters.join(";;"), myCaption, myParent ); + } + } +}; +QStringList SalomePyQt::getOpenFileNames( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption ) +{ + return ProcessEvent( new TGetOpenFileNamesEvent( parent, initial, filters, caption ) ); +} + +/*! + SalomePyQt::getExistingDirectory + Displays 'Get Directory' dialog box and returns a user's choice (a directory name) +*/ +class TGetExistingDirectoryEvent: public SALOME_Event { +public: + typedef QString TResult; + TResult myResult; + QWidget* myParent; + QString myInitial; + QString myCaption; + TGetExistingDirectoryEvent( QWidget* parent, + const QString& initial, + const QString& caption ) + : myParent ( parent ), + myInitial( initial ), + myCaption( caption ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + myResult = anApp->getDirectory( myInitial, myCaption, myParent ); + } + } +}; +QString SalomePyQt::getExistingDirectory( QWidget* parent, + const QString& initial, + const QString& caption ) +{ + return ProcessEvent( new TGetExistingDirectoryEvent( parent, initial, caption ) ); +} + +/*! + SalomePyQt::helpContext + Opens external browser to display 'context help' information + current implementation does nothing. +*/ +void SalomePyQt::helpContext( const QString& source, const QString& context ) { + class TEvent: public SALOME_Event { + QString mySource; + QString myContext; + public: + TEvent( const QString& source, const QString& context ) + : mySource( source ), myContext( context ) {} + virtual void Execute() { + if ( /*SalomeApp_Application* anApp =*/ getApplication() ) { + // VSR: TODO + // anApp->helpContext( mySource, myContext ); + } + } + }; + ProcessVoidEvent( new TEvent( source, context ) ); +} + +/*! + SalomePyQt::dumpView + Dumps the contents of the currently active view to the image file + in the given format (JPEG, PNG, BMP are supported) +*/ +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 ( SalomeApp_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 ).upper(); + if ( fmt.isEmpty() ) fmt = QString( "BMP" ); // default format + if ( fmt == "JPG" ) fmt = "JPEG"; + myResult = im.save( myFileName, fmt.latin1() ); + } + } + } + } + } +}; +bool SalomePyQt::dumpView( const QString& filename ) +{ + return ProcessEvent( new TDumpViewEvent( filename ) ); +} + +/*! + SalomePyQt::createTool + These methods allow operating with the toolbars: + - create a new toolbar or get the existing one (the toolbar name is passed as parameter); + this method returns an id of the toolbar; + - add action with given id (must be created previously) and optional index to the existing toolbar + (toobar is identified either by its id or by its name) + these methods return an id of the action. + If error occurs, the -1 value is returned. +*/ +class CrTool +{ +public: + CrTool( const QString& tBar ) + : myCase( 0 ), myTbName( tBar ) {} + CrTool( const int id, const int tBar, const int idx ) + : myCase( 1 ), myId( id ), myTbId( tBar ), myIndex( idx ) {} + CrTool( const int id, const QString& tBar, const int idx ) + : myCase( 2 ), myId( id ), myTbName( tBar ), myIndex( idx ) {} + CrTool( QtxAction* action, const int tbId, const int id, const int idx ) + : myCase( 3 ), myAction( action ), myTbId( tbId ), myId( id ), myIndex( idx ) {} + CrTool( QtxAction* action, const QString& tBar, const int id, const int idx ) + : myCase( 4 ), myAction( action ), myTbName( tBar ), myId( id ), myIndex( idx ) {} + + int execute( SALOME_PYQT_Module* module ) const + { + if ( module ) { + switch ( myCase ) { + case 0: + return module->createTool( myTbName ); + case 1: + return module->createTool( myId, myTbId, myIndex ); + case 2: + return module->createTool( myId, myTbName, myIndex ); + case 3: + return module->createTool( myAction, myTbId, myId, myIndex ); + case 4: + return module->createTool( myAction, myTbName, myId, myIndex ); + } + } + return -1; + } +private: + int myCase; + QString myTbName; + int myTbId; + QtxAction* myAction; + int myId; + int myIndex; +}; +class TCreateToolEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + const CrTool& myCrTool; + TCreateToolEvent( const CrTool& crTool ) + : myResult( -1 ), myCrTool( crTool ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + myResult = myCrTool.execute( module ); + } + } +}; +// create new toolbar or get existing by name +int SalomePyQt::createTool( const QString& tBar ) +{ + return ProcessEvent( new TCreateToolEvent( CrTool( tBar ) ) ); +} +// add action with id and index to the existing tollbar +int SalomePyQt::createTool( const int id, const int tBar, const int idx ) +{ + return ProcessEvent( new TCreateToolEvent( CrTool( id, tBar, idx ) ) ); +} +// add action with id and index to the existing tollbar +int SalomePyQt::createTool( const int id, const QString& tBar, const int idx ) +{ + return ProcessEvent( new TCreateToolEvent( CrTool( id, tBar, idx ) ) ); +} +// add action with id and index to the existing tollbar +int SalomePyQt::createTool( QtxAction* a, const int tBar, const int id, const int idx ) +{ + return ProcessEvent( new TCreateToolEvent( CrTool( a, tBar, id, idx ) ) ); +} +// add action with id and index to the existing tollbar +int SalomePyQt::createTool( QtxAction* a, const QString& tBar, const int id, const int idx ) +{ + return ProcessEvent( new TCreateToolEvent( CrTool( a, tBar, id, idx ) ) ); +} + +/*! + SalomePyQt::createMenu + These methods allow operating with the main menu: + - create a new menu or submenu or get the existing one (the parent menu name or id is passed as parameter, + if it is empty or -1, it means that main menu is created, otherwise submenu is created); + this method returns an id of the menu/submenu; + - add action with given id (must be created previously) and optional index and group number to the existing menu + or submenu (menu name or id us passed as parameter) + these methods return an id of the action. + If error occurs, the -1 value is returned. +*/ +class CrMenu +{ +public: + CrMenu( const QString& subMenu, const int menu, const int group, const int idx ) + : myCase( 0 ), mySubMenuName( subMenu ), myMenuId( menu ), myGroup( group ), myIndex( idx ) {} + CrMenu( const QString& subMenu, const QString& menu, const int group, const int idx ) + : myCase( 1 ), mySubMenuName( subMenu ), myMenuName( menu ), myGroup( group ), myIndex( idx ) {} + CrMenu( const int id, const int menu, const int group, const int idx ) + : myCase( 2 ), myId( id ), myMenuId( menu ), myGroup( group ), myIndex( idx ) {} + CrMenu( const int id, const QString& menu, const int group, const int idx ) + : myCase( 3 ), myId( id ), myMenuName( menu ), myGroup( group ), myIndex( idx ) {} + CrMenu( QtxAction* action, const int menu, const int id, const int group, const int idx ) + : myCase( 4 ), myAction( action ), myMenuId( menu ), myId( id ), myGroup( group ), myIndex( idx ) {} + CrMenu( QtxAction* action, const QString& menu, const int id, const int group, const int idx ) + : myCase( 5 ), myAction( action ), myMenuName( menu ), myId( id ), myGroup( group ), myIndex( idx ) {} + + int execute( SALOME_PYQT_Module* module ) const + { + if ( module ) { + switch ( myCase ) { + case 0: + return module->createMenu( mySubMenuName, myMenuId, -1, myGroup, myIndex ); + case 1: + return module->createMenu( mySubMenuName, myMenuName, -1, myGroup, myIndex ); + case 2: + return module->createMenu( myId, myMenuId, myGroup, myIndex ); + case 3: + return module->createMenu( myId, myMenuName, myGroup, myIndex ); + case 4: + return module->createMenu( myAction, myMenuId, myId, myGroup, myIndex ); + case 5: + return module->createMenu( myAction, myMenuName, myId, myGroup, myIndex ); + } + } + return -1; + } +private: + int myCase; + QString myMenuName; + int myMenuId; + QString mySubMenuName; + int myGroup; + QtxAction* myAction; + int myId; + int myIndex; +}; +class TCreateMenuEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + const CrMenu& myCrMenu; + TCreateMenuEvent( const CrMenu& crMenu ) + : myResult( -1 ), myCrMenu( crMenu ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + myResult = myCrMenu.execute( module ); + } + } +}; +int SalomePyQt::createMenu( const QString& subMenu, const int menu, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, group, idx ) ) ); +} + +int SalomePyQt::createMenu( const QString& subMenu, const QString& menu, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, group, idx ) ) ); +} + +int SalomePyQt::createMenu( const int id, const int menu, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( id, menu, group, idx ) ) ); +} + +int SalomePyQt::createMenu( const int id, const QString& menu, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( id, menu, group, idx ) ) ); +} + +int SalomePyQt::createMenu( QtxAction* a, const int menu, const int id, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( a, menu, id, group, idx ) ) ); +} + +int SalomePyQt::createMenu( QtxAction* a, const QString& menu, const int id, const int group, const int idx ) +{ + return ProcessEvent( new TCreateMenuEvent( CrMenu( a, menu, id, group, idx ) ) ); +} + +/*! + SalomePyQt::createSeparator + Create a separator action which can be then used in the menu or toolbar. +*/ +class TCreateSepEvent: public SALOME_Event { +public: + typedef QtxAction* TResult; + TResult myResult; + TCreateSepEvent() + : myResult( 0 ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + if ( module ) + myResult = (QtxAction*)module->createSeparator(); + } + } +}; +QtxAction* SalomePyQt::createSeparator() +{ + return ProcessEvent( new TCreateSepEvent() ); +} + +/*! + SalomePyQt::createAction + Create an action which can be then used in the menu or toolbar: + - id : the unique id action to be registered to; + - menuText : action text which should appear in menu; + - tipText : text which should appear in the tooltip; + - statusText : text which should appear in the status bar when action is activated; + - icon : the name of the icon file (the actual icon file name can be coded in the translation files); + - key : the key accelrator for the action + - toggle : if true the action is checkable +*/ +class TCreateActionEvent: public SALOME_Event { +public: + typedef QtxAction* TResult; + TResult myResult; + int myId; + QString myMenuText; + QString myTipText; + QString myStatusText; + QString myIcon; + int myKey; + bool myToggle; + TCreateActionEvent( const int id, const QString& menuText, const QString& tipText, + const QString& statusText, const QString& icon, const int key, const bool toggle ) + : myResult( 0 ), myId( id ), myMenuText( menuText ), myTipText( tipText ), + myStatusText( statusText ), myIcon( icon ), myKey( key ), myToggle( toggle ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + if ( module ) + myResult = (QtxAction*)module->createAction( myId, myTipText, myIcon, myMenuText, myStatusText, myKey, myToggle ); + } + } +}; +QtxAction* SalomePyQt::createAction( const int id, const QString& menuText, + const QString& tipText, const QString& statusText, + const QString& icon, const int key, const bool toggle ) +{ + return ProcessEvent( new TCreateActionEvent( id, menuText, tipText, statusText, icon, key, toggle ) ); +} + +/*! + SalomePyQt::action + Get an action by its id. Returns 0 if the action with such id was not registered. +*/ +class TActionEvent: public SALOME_Event { +public: + typedef QtxAction* TResult; + TResult myResult; + int myId; + TActionEvent( const int id ) + : myResult( 0 ), myId( id ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + if ( module ) + myResult = (QtxAction*)module->action( myId ); + } + } +}; +QtxAction* SalomePyQt::action( const int id ) +{ + return ProcessEvent( new TActionEvent( id ) ); +} + +/*! + SalomePyQt::actionId + Get an action id. Returns -1 if the action was not registered. +*/ +class TActionIdEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + const QtxAction* myAction; + TActionIdEvent( const QtxAction* action ) + : myResult( -1 ), myAction( action ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + if ( module ) + myResult = module->actionId( myAction ); + } + } +}; +int SalomePyQt::actionId( const QtxAction* a ) +{ + return ProcessEvent( new TActionIdEvent( a ) ); +} diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip new file mode 100644 index 000000000..f306399b1 --- /dev/null +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip @@ -0,0 +1,129 @@ +//============================================================================= +// File : SalomePyQt_v4.sip +// Created : 25/04/05 +// Author : Vadim SANDLER +// Project : SALOME +// Copyright : 2003-2005 CEA/DEN, EDF R&D +// $Header : $ +//============================================================================= + +%Module SalomePyQt + +%Import qtmod.sip + +class SALOME_Selection : QObject +{ +%TypeHeaderCode +#include +%End + +public: + void Clear(); + void ClearIObjects(); + void ClearFilters(); + +private: + SALOME_Selection( QObject* /TransferThis/ ); + +signals: + void currentSelectionChanged(); +}; + +enum MenuName { + File = 1, + View = 2, + Edit = 3, + Preferences = 4, + Tools = 5, + Window = 6, + Help = 7 +}; + +enum { + WT_ObjectBrowser, + WT_PyConsole, + WT_LogWindow, + WT_User +}; + +class QtxAction : QAction +{ +%TypeHeaderCode +#include +%End + +private: + QtxAction(const QtxAction &); +}; + +class SalomePyQt +{ +%TypeHeaderCode +#include +%End + +public: + static QWidget* getDesktop(); + static QWidget* getMainFrame(); + static QMenuBar* getMainMenuBar(); + static QPopupMenu* getPopupMenu( const MenuName ); + static SALOME_Selection* getSelection() /Factory/; + static int getStudyId(); + static void putInfo( const QString&, const int = 0 ); + static const QString getActiveComponent(); + static void updateObjBrowser( const int = 0, bool = true ); + + static QString getFileName ( QWidget*, const QString&, const QStringList&, const QString&, bool ) /ReleaseGIL/ ; + static QStringList getOpenFileNames ( QWidget*, const QString&, const QStringList&, const QString& ); + static QString getExistingDirectory( QWidget*, const QString&, const QString& ); + + static void helpContext( const QString&, const QString& ); + + static bool dumpView( const QString& ); + + static int createTool( const QString& ); + static int createTool( const int, const int, const int = -1 ); + static int createTool( const int, const QString&, const int = -1 ); + static int createTool( QtxAction*, const int, const int = -1, const int = -1 ); + static int createTool( QtxAction*, const QString&, const int = -1, const int = -1 ); + + static int createMenu( const QString&, const int, + const int = -1, const int = -1 ); + static int createMenu( const QString&, const QString&, + const int = -1, const int = -1 ); + static int createMenu( const int, const int, + const int = -1, const int = -1 ); + static int createMenu( const int, const QString&, + const int = -1, const int = -1 ); + static int createMenu( QtxAction*, const int, const int = -1, + const int = -1, const int = -1 ); + static int createMenu( QtxAction*, const QString&, const int = -1, + const int = -1, const int = -1 ); + + static QtxAction* createSeparator(); + + static QtxAction* createAction( const int, const QString&, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const int = 0, const bool = false ); + + static QtxAction* action( const int ); + static int actionId( const QtxAction* ); + + static void addSetting ( const QString&, const QString&, const double ); + static void addSetting ( const QString&, const QString&, const int /Constrained/ ); + static void addSetting ( const QString&, const QString&, const QString& ); + static void addSetting ( const QString&, const QString&, const QColor& ); + static int integerSetting( const QString&, const QString&, const int = 0 ); + static double doubleSetting ( const QString&, const QString&, const int = 0 ); + static bool boolSetting ( const QString&, const QString&, const bool = 0 ); + static QString stringSetting ( const QString&, const QString&, const QString& = QString("") ); + static QColor colorSetting ( const QString&, const QString&, const QColor& = QColor() ); + static void removeSetting ( const QString&, const QString& ); + +// obsolete + static void addStringSetting( const QString&, const QString&, bool = true ); + static void addIntSetting ( const QString&, const int, bool = true ); + static void addDoubleSetting( const QString&, const double, bool = true ); + static void removeSettings ( const QString& ); + static QString getSetting ( const QString& ); +}; diff --git a/src/SALOME_SWIG/salome_test.py b/src/SALOME_SWIG/salome_test.py new file mode 100755 index 000000000..75e5f0bbd --- /dev/null +++ b/src/SALOME_SWIG/salome_test.py @@ -0,0 +1,486 @@ +# SALOME SALOME_SWIG : binding of C++ implementation and Python +# +# Copyright (C) 2003 CEA/DEN, EDF R&D +# +# +# +# File : salome_test.py +# Module : SALOME + +print "Test the application loading GEOM, SMESH, VISU, MED, components and doing some" +print "operation within the components." + +import salome +from salome import sg +import SALOMEDS +import os + +import SALOME_ModuleCatalog + +print "======================================================================" +print " Get Catalog " +print "======================================================================" +obj = salome.naming_service.Resolve('Kernel/ModulCatalog') +catalog = obj._narrow(SALOME_ModuleCatalog.ModuleCatalog) + +print "======================================================================" +print " Create Study " +print "======================================================================" + +comp = catalog.GetComponent("GEOM") +if comp is None: + raise RuntimeError,"Component GEOM not found in Module Catalog." + +import geompy + +print "=================================" +print " create AttributeReal " +print "=================================" +A = geompy.myBuilder.FindOrCreateAttribute(geompy.father, "AttributeReal") +if A == None : + raise RuntimeError, "Can't create AttributeReal attribute" +A = A._narrow(SALOMEDS.AttributeReal) +A.SetValue(0.0001) +if A.Value() != 0.0001: + raise RuntimeError, "Error : wrong value of AttributeReal" + +print +print " =========== Test Geometry ==========================" +print + +print "===================================" +print " define a box" +print "===================================" + +box = geompy.MakeBox(0., 0., 0., 100., 200., 300.) +idbox = geompy.addToStudy(box,"box") + +print +print "============= Test SMESH =============================" +print + +import StdMeshers + +comp = catalog.GetComponent("SMESH") +if comp is None: + raise RuntimeError,"Component SMESH not found in Module Catalog." + +comp = catalog.GetComponent("MED") +if comp is None: + raise RuntimeError,"Component MED not found in Module Catalog." + +import SMESH + +geom = salome.lcc.FindOrLoadComponent("FactoryServer", "GEOM") +myBuilder = salome.myStudy.NewBuilder() + +smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH") +smeshgui = salome.ImportComponentGUI("SMESH") +smeshgui.Init(salome.myStudyId); + +ShapeTypeCompSolid = 1 +ShapeTypeSolid = 2 +ShapeTypeShell = 3 +ShapeTypeFace = 4 +ShapeTypeWire = 5 +ShapeTypeEdge = 6 +ShapeTypeVertex = 7 + +# ---- define a box + +box = geompy.MakeBox(0., 0., 0., 100., 200., 300.) +idbox = geompy.addToStudy(box,"box") + +# ---- add first face of box in study + +subShapeList=geompy.SubShapeAll(box,ShapeTypeFace) +face=subShapeList[0] +name = geompy.SubShapeName(face, box) +print name +idface=geompy.addToStudyInFather(box,face,name) + +# ---- add shell from box in study + +subShellList=geompy.SubShapeAll(box,ShapeTypeShell) +shell = subShellList[0] +name = geompy.SubShapeName(shell, box) +print name +idshell=geompy.addToStudyInFather(box,shell,name) + +# ---- add first edge of face in study + +edgeList = geompy.SubShapeAll(face,ShapeTypeEdge) +edge=edgeList[0]; +name = geompy.SubShapeName(edge, face) +print name +idedge=geompy.addToStudyInFather(face,edge,name) + + +# ---- SMESH + +# ---- create Hypothesis + +print "-------------------------- create Hypothesis" +print "-------------------------- LocalLength" +hypLen1 = smesh.CreateHypothesis( "LocalLength", "libStdMeshersEngine.so" ) +hypLen1.SetLength(100) +print hypLen1.GetName() +print hypLen1.GetId() +print hypLen1.GetLength() + +smeshgui.SetName(salome.ObjectToID(hypLen1), "Local_Length_100") + +print "-------------------------- NumberOfSegments" +hypNbSeg1= smesh.CreateHypothesis( "NumberOfSegments", "libStdMeshersEngine.so" ) +hypNbSeg1.SetNumberOfSegments(7) +print hypNbSeg1.GetName() +print hypNbSeg1.GetId() +print hypNbSeg1.GetNumberOfSegments() + +smeshgui.SetName(salome.ObjectToID(hypNbSeg1), "NumberOfSegments_7") + +print "-------------------------- MaxElementArea" +hypArea1 = smesh.CreateHypothesis( "MaxElementArea", "libStdMeshersEngine.so" ) +hypArea1.SetMaxElementArea(2500) +print hypArea1.GetName() +print hypArea1.GetId() +print hypArea1.GetMaxElementArea() + +smeshgui.SetName(salome.ObjectToID(hypArea1), "MaxElementArea_2500") + +print "-------------------------- MaxElementArea" +hypArea2 = smesh.CreateHypothesis( "MaxElementArea", "libStdMeshersEngine.so" ) +hypArea2.SetMaxElementArea(500) +print hypArea2.GetName() +print hypArea2.GetId() +print hypArea2.GetMaxElementArea() + +smeshgui.SetName(salome.ObjectToID(hypArea2), "MaxElementArea_500") + +print "-------------------------- Regular_1D" +algoReg = smesh.CreateHypothesis( "Regular_1D", "libStdMeshersEngine.so" ) +listHyp=algoReg.GetCompatibleHypothesis() +for hyp in listHyp: + print hyp +print algoReg.GetName() +print algoReg.GetId() + +smeshgui.SetName(salome.ObjectToID(algoReg), "Regular_1D" ) + +print "-------------------------- MEFISTO_2D" +algoMef = smesh.CreateHypothesis( "MEFISTO_2D", "libStdMeshersEngine.so" ) +listHyp=algoMef.GetCompatibleHypothesis() +for hyp in listHyp: + print hyp +print algoMef.GetName() +print algoMef.GetId() + +smeshgui.SetName(salome.ObjectToID(algoMef), "MEFISTO_2D" ) + +# ---- add hypothesis to box + +print "-------------------------- add hypothesis to box" +box=salome.IDToObject(idbox) +mesh = smesh.CreateMesh(box) + +smeshgui.SetName( salome.ObjectToID(mesh), "MeshBox" ); + +ret=mesh.AddHypothesis(box,algoReg) +print ret +ret=mesh.AddHypothesis(box,algoMef) +print ret + + +ret=mesh.AddHypothesis(box,hypNbSeg1) +print ret +ret=mesh.AddHypothesis(box,hypArea1) +print ret + + +# ---- add hypothesis to edge + +print "-------------------------- add hypothesis to edge" +edge=salome.IDToObject(idedge) +submesh=mesh.GetSubMesh(edge, "SubMeshEdge") + +ret=mesh.AddHypothesis(edge,algoReg) +print ret +ret=mesh.AddHypothesis(edge,hypLen1) +print ret + +print "-------------------------- add hypothesis to face" +face=salome.IDToObject(idface) +submesh = mesh.GetSubMesh(face, "SubMeshFace") + +ret=mesh.AddHypothesis(face,hypArea2) +print ret + +smesh.Compute(mesh, box) +sg.updateObjBrowser(1); + +print +print "============= Test Supervisor =============================" +print + +comp = catalog.GetComponent("SUPERV") +if comp is None: + raise RuntimeError,"Component SUPERV not found in Module Catalog." + +from SuperV import * +import SALOMEDS +myStudy = salome.myStudy +myBuilder = myStudy.NewBuilder() + +SuperVision = lcc.FindOrLoadComponent("SuperVisionContainer","SUPERV") +father = myStudy.FindComponent("SUPERV") +if father is None: + father = myBuilder.NewComponent("SUPERV") + A1 = myBuilder.FindOrCreateAttribute(father, "AttributeName"); + FName = A1._narrow(SALOMEDS.AttributeName) + FName.SetValue( salome.sg.getComponentUserName("SUPERV") ) + A2 = myBuilder.FindOrCreateAttribute(father, "AttributePixMap"); + aPixmap = A2._narrow(SALOMEDS.AttributePixMap); + aPixmap.SetPixMap( "ICON_OBJBROWSER_Supervision" ); + myBuilder.DefineComponentInstance(father,SuperVision) + +def addStudy(ior): + dataflow = SuperVision.getStreamGraph(ior) + name=dataflow.Name() + itr = myStudy.NewChildIterator(father) + while itr.More(): + item=itr.Value() + res,A=item.FindAttribute("AttributeName") + if res: + aName = A._narrow(SALOMEDS.AttributeName) + if aName.Value() == name : + print myBuilder.FindOrCreateAttribute(item, "AttributeIOR") + A = myBuilder.FindOrCreateAttribute(item, "AttributeIOR") + print "A = ", A + if A is not None : + #res,A = myBuilder.FindOrCreateAttribute(item, "AttributeIOR") + anIOR = A._narrow(SALOMEDS.AttributeIOR); + print "anIOR.SetValue(dataflow.getIOR())" + anIOR.SetValue(dataflow.getIOR()) + return + itr.Next() + obj = myBuilder.NewObject(father) + A=myBuilder.FindOrCreateAttribute(obj, "AttributeName") + aName=A._narrow(SALOMEDS.AttributeName) + aName.SetValue(name) + A=myBuilder.FindOrCreateAttribute(obj, "AttributeIOR") + anIOR = A._narrow(SALOMEDS.AttributeIOR) + anIOR.SetValue(dataflow.getIOR()) + +import os +dir= os.getenv("DATA_DIR") +if dir == None: + raise RuntimeError, "DATA_DIR is not defined" +xmlfile = dir +"/Superv/Graphs/GraphGeomEssai.xml" +print "Load dataflow from the file : " +print xmlfile +print + +myGraph = StreamGraph ( xmlfile ) + +# This DataFlow is "valid" : no loop, correct links between Nodes etc... +print "myGraph.IsValid() = ", myGraph.IsValid() + +# Get Nodes +myGraph.PrintNodes() + +# This DataFlow is "executable" : all pending Ports are defined with Datas +print myGraph.IsExecutable() + +# Starts only execution of that DataFlow and gets control immediatly +print myGraph.Run() + +# That DataFlow is running ==> 0 (false) +print myGraph.IsDone() + +# Events of execution : +aStatus,aNode,anEvent,aState = myGraph.Event() +while aStatus : + print aNode.Thread(),aNode.SubGraph(),aNode.Name(),anEvent,aState + aStatus,aNode,anEvent,aState = myGraph.Event() +print "myGraph.IsDone() = ",myGraph.IsDone() + +# Wait for Completion (but it is already done after event loop ...) +print "Done : ",myGraph.DoneW() + +print " " +#print "Type : print myGraph.IsDone()" +#print " If execution is finished ==> 1 (true)" +res=myGraph.IsDone() +if res != 1: + raise RuntimeError, "myGraph.Run() is not done" + +print " " +print "Type : myGraph.PrintPorts()" +print " to see input and output values of the graph" +myGraph.PrintPorts() + +# Export will create newsupervisionexample.xml and the corresponding .py file +tmpdir=os.getenv("TmpDir") +if tmpdir is None: + tmpdir="/tmp" +file = tmpdir + "/newsupervisionexample" +print "--------------\n"+file+"\n--------------\n" +myGraph.Export(file) + +ior = salome.orb.object_to_string(myGraph.G) +addStudy(ior) + +GraphName = myGraph.Name() +print "Befor save ", +#nodes = myGraph.Nodes() +nodes = myGraph.G.Nodes().FNodes +length_bs = len(nodes) +print "ListOfNodes length = ", length_bs +names=[] +for node in nodes: + names.append(node.Name()) +print names + +# Graph creation +GraphInLines = StreamGraph( 'GraphInLines' ) +GraphInLines.SetName( 'GraphInLines' ) +GraphInLines.SetAuthor( '' ) +GraphInLines.SetComment( '' ) +GraphInLines.Coords( 0 , 0 ) + +# Creation of InLine Nodes +PyAdd = [] +PyAdd.append( 'def Add(a,b) : ' ) +PyAdd.append( ' return a+b ' ) +PyAdd.append( '' ) +Add = GraphInLines.INode( 'Add' , PyAdd ) +Add.InPort( 'a' , 'long' ) +Add.InPort( 'b' , 'long' ) +Add.OutPort( 'f' , 'long' ) +Add.SetName( 'Add' ) +Add.SetAuthor( '' ) +Add.SetComment( 'Python function' ) +Add.Coords( 351 , 77 ) +PySub = [] +PySub.append( 'def Sub(a,b) : ' ) +PySub.append( ' return a-b ' ) +PySub.append( '' ) +Sub = GraphInLines.INode( 'Sub' , PySub ) +Sub.InPort( 'a' , 'long' ) +Sub.InPort( 'b' , 'long' ) +Sub.OutPort( 'f' , 'long' ) +Sub.SetName( 'Sub' ) +Sub.SetAuthor( '' ) +Sub.SetComment( 'Python function' ) +Sub.Coords( 86 , 333 ) +PyMul = [] +PyMul.append( 'def Mul(a,b) : ' ) +PyMul.append( ' return a*b ' ) +Mul = GraphInLines.INode( 'Mul' , PyMul ) +Mul.InPort( 'a' , 'long' ) +Mul.InPort( 'b' , 'long' ) +Mul.OutPort( 'Result' , 'long' ) +Mul.SetName( 'Mul' ) +Mul.SetAuthor( '' ) +Mul.SetComment( 'Python function' ) +Mul.Coords( 616 , 247 ) + +# Creation of intermediate Output variables and of Control Links +Addf = Add.Port( 'f' ) +Mula = GraphInLines.Link( Addf , Mul.Port( 'a' ) ) +Mula.AddCoord( 1 , 570 , 356 ) +Mula.AddCoord( 2 , 570 , 186 ) +Subf = Sub.Port( 'f' ) +Mulb = GraphInLines.Link( Subf , Mul.Port( 'b' ) ) +Mulb.AddCoord( 1 , 282 , 376 ) +Mulb.AddCoord( 2 , 282 , 442 ) +Addb = GraphInLines.Link( Subf , Add.Port( 'b' ) ) +Addb.AddCoord( 1 , 283 , 209 ) +Addb.AddCoord( 2 , 283 , 374 ) +Addb.AddCoord( 3 , 283 , 442 ) + +# Creation of Input datas +Adda = Add.Input( 'a' , 1) +Suba = Sub.Input( 'a' , 3) +Subb = Sub.Input( 'b' , 4) + +# Creation of Output variables +MulResult = Mul.Port( 'Result' ) + +GraphInLines.Run() + +GraphInLines.DoneW() + +GraphInLines.PrintPorts() + +sg.updateObjBrowser(1); + +print +print "============= Test VISU and MED =============================" +print + +comp = catalog.GetComponent("VISU") +if comp is None: + raise RuntimeError,"Component VISU not found in Module Catalog." + +import sys +import SALOMEDS +import SALOME +import SALOME_MED +import VISU + +import visu_gui + +medFileName = "pointe.med" +medFile = os.getenv('DATA_DIR') + '/MedFiles/' + medFileName +print "Load ", medFile + +studyCurrent = salome.myStudyName + +med_comp = salome.lcc.FindOrLoadComponent("FactoryServer", "MED") +myVisu = salome.lcc.FindOrLoadComponent("FactoryServer", "VISU") + +try: + if os.access(medFile, os.R_OK) : + if not os.access(medFile, os.W_OK) : + import random + medFileNew = "/tmp/" + str(random.randint(0,1000000)) + "_" + medFileName + print " -- Copy " + medFile + " to " + medFileNew + os.system("cp "+ medFile + " " + medFileNew) + medFile = medFileNew + os.system("chmod 755 " + medFile) + + if os.access(medFile, os.W_OK) : + med_comp.readStructFileWithFieldType(medFile,studyCurrent) + med_obj = visu_gui.visu.getMedObjectFromStudy() + print "med_obj - ", med_obj + + myField1 = visu_gui.visu.getFieldObjectFromStudy(2,1) + aMeshName = "maa1" + anEntity = VISU.NODE + aTimeStampId = -1 + + myResult1 = myVisu.ImportMedField(myField1) + aMesh1 = myVisu.MeshOnEntity(myResult1, aMeshName, anEntity); + + aScalarMap1= myVisu.ScalarMapOnField(myResult1, aMeshName, anEntity, myField1.getName(), aTimeStampId) + + myResult2 = myVisu.ImportFile(medFile); + aMesh2 = myVisu.MeshOnEntity(myResult2, aMeshName, anEntity); + + aTimeStampId = 3 + aScalarMap2= myVisu.ScalarMapOnField(myResult2, aMeshName, anEntity, myField1.getName(), aTimeStampId) + + sg.updateObjBrowser(0) + else : print "We have no permission to rewrite medFile, so readStructFileWithFieldType can't open this file"; + else : print "We have no permission to read medFile, it will not be opened"; + +except: + if sys.exc_type == SALOME.SALOME_Exception : + print "There is no permission to read " + medFile + else : + print sys.exc_type + print sys.exc_value + print sys.exc_traceback + +sg.updateObjBrowser(1); diff --git a/src/STD/STD_Application.cxx b/src/STD/STD_Application.cxx new file mode 100755 index 000000000..3e955e6c9 --- /dev/null +++ b/src/STD/STD_Application.cxx @@ -0,0 +1,881 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "STD_Application.h" + +#include "STD_MDIDesktop.h" + +#include "STD_CloseDlg.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/*!Create and return new instance of STD_Application*/ +extern "C" STD_EXPORT SUIT_Application* createApplication() +{ + return new STD_Application(); +} + +/*!Constructor.*/ +STD_Application::STD_Application() +: SUIT_Application(), +myEditEnabled( true ), +myActiveViewMgr( 0 ) +{ + STD_MDIDesktop* desk = new STD_MDIDesktop(); + + setDesktop( desk ); +} + +/*!Destructor.*/ +STD_Application::~STD_Application() +{ +} + +/*! \retval QString "StdApplication"*/ +QString STD_Application::applicationName() const +{ + return QString( "StdApplication" ); +} + +/*!Start STD_Application*/ +void STD_Application::start() +{ + createActions(); + + updateDesktopTitle(); + updateCommandsStatus(); + setEditEnabled( myEditEnabled ); + + loadPreferences(); + + SUIT_Application::start(); +} + +/*! + Close the Application +*/ +void STD_Application::closeApplication() +{ + if ( desktop() ) + savePreferences(); + + SUIT_Application::closeApplication(); +} + +/*!Event on closing desktop*/ +void STD_Application::onDesktopClosing( SUIT_Desktop*, QCloseEvent* e ) +{ + if ( SUIT_Session::session()->applications().count() < 2 ) + { + onExit(); + return; + } + + if ( !isPossibleToClose() ) + { + e->ignore(); + return; + } + + SUIT_Study* study = activeStudy(); + + if ( study ) + study->closeDocument(); + + setActiveStudy( 0 ); + delete study; + + savePreferences(); + + setDesktop( 0 ); + + closeApplication(); +} + +/*!Create actions, menus and tools*/ +void STD_Application::createActions() +{ + SUIT_Desktop* desk = desktop(); + SUIT_ResourceMgr* resMgr = resourceMgr(); + if ( !desk || !resMgr ) + return; + + // Create actions + + createAction( FileNewId, tr( "TOT_DESK_FILE_NEW" ), + resMgr->loadPixmap( "STD", tr( "ICON_FILE_NEW" ) ), + tr( "MEN_DESK_FILE_NEW" ), tr( "PRP_DESK_FILE_NEW" ), + CTRL+Key_N, desk, false, this, SLOT( onNewDoc() ) ); + + createAction( FileOpenId, tr( "TOT_DESK_FILE_OPEN" ), + resMgr->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ), + tr( "MEN_DESK_FILE_OPEN" ), tr( "PRP_DESK_FILE_OPEN" ), + CTRL+Key_O, desk, false, this, SLOT( onOpenDoc() ) ); + + createAction( FileCloseId, tr( "TOT_DESK_FILE_CLOSE" ), + resMgr->loadPixmap( "STD", tr( "ICON_FILE_CLOSE" ) ), + tr( "MEN_DESK_FILE_CLOSE" ), tr( "PRP_DESK_FILE_CLOSE" ), + CTRL+Key_W, desk, false, this, SLOT( onCloseDoc() ) ); + + createAction( FileExitId, tr( "TOT_DESK_FILE_EXIT" ), QIconSet(), + tr( "MEN_DESK_FILE_EXIT" ), tr( "PRP_DESK_FILE_EXIT" ), + CTRL+Key_Q, desk, false, this, SLOT( onExit() ) ); + + createAction( FileSaveId, tr( "TOT_DESK_FILE_SAVE" ), + resMgr->loadPixmap( "STD", tr( "ICON_FILE_SAVE" ) ), + tr( "MEN_DESK_FILE_SAVE" ), tr( "PRP_DESK_FILE_SAVE" ), + CTRL+Key_S, desk, false, this, SLOT( onSaveDoc() ) ); + + createAction( FileSaveAsId, tr( "TOT_DESK_FILE_SAVEAS" ), QIconSet(), + tr( "MEN_DESK_FILE_SAVEAS" ), tr( "PRP_DESK_FILE_SAVEAS" ), + CTRL+Key_A, desk, false, this, SLOT( onSaveAsDoc() ) ); + + createAction( EditCopyId, tr( "TOT_DESK_EDIT_COPY" ), + resMgr->loadPixmap( "STD", tr( "ICON_EDIT_COPY" ) ), + tr( "MEN_DESK_EDIT_COPY" ), tr( "PRP_DESK_EDIT_COPY" ), + CTRL+Key_C, desk, false, this, SLOT( onCopy() ) ); + + createAction( EditPasteId, tr( "TOT_DESK_EDIT_PASTE" ), + resMgr->loadPixmap( "STD", tr( "ICON_EDIT_PASTE" ) ), + tr( "MEN_DESK_EDIT_PASTE" ), tr( "PRP_DESK_EDIT_PASTE" ), + CTRL+Key_V, desk, false, this, SLOT( onPaste() ) ); + + QAction* a = createAction( ViewStatusBarId, tr( "TOT_DESK_VIEW_STATUSBAR" ), + QIconSet(), tr( "MEN_DESK_VIEW_STATUSBAR" ), + tr( "PRP_DESK_VIEW_STATUSBAR" ), SHIFT+Key_S, desk, true ); + a->setOn( desk->statusBar()->isVisibleTo( desk ) ); + connect( a, SIGNAL( toggled( bool ) ), this, SLOT( onViewStatusBar( bool ) ) ); + + createAction( NewWindowId, tr( "TOT_DESK_NEWWINDOW" ), QIconSet(), + tr( "MEN_DESK_NEWWINDOW" ), tr( "PRP_DESK_NEWWINDOW" ), 0, desk ); + + createAction( HelpAboutId, tr( "TOT_DESK_HELP_ABOUT" ), QIconSet(), + tr( "MEN_DESK_HELP_ABOUT" ), tr( "PRP_DESK_HELP_ABOUT" ), + SHIFT+Key_A, desk, false, this, SLOT( onHelpAbout() ) ); + + //SRN: BugID IPAL9021, add an action "Load" + createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ), + resMgr->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ), + tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ), + CTRL+Key_L, desk, false, this, SLOT( onLoadDoc() ) ); + //SRN: BugID IPAL9021: End + + QtxDockAction* da = new QtxDockAction( tr( "TOT_DOCK_WINDOWS" ), tr( "MEN_DOCK_WINDOWS" ), desk ); + registerAction( ViewWindowsId, da ); + da->setAutoPlace( false ); + + // Create menus + + int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1, -1, 0 ); + int editMenu = createMenu( tr( "MEN_DESK_EDIT" ), -1, -1, 10 ); + int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1, -1, 10 ); + int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 ); + + // Create menu items + + createMenu( FileNewId, fileMenu, 0 ); + createMenu( FileOpenId, fileMenu, 0 ); + createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load" + createMenu( FileCloseId, fileMenu, 0 ); + createMenu( separator(), fileMenu, -1, 0 ); + createMenu( FileSaveId, fileMenu, 0 ); + createMenu( FileSaveAsId, fileMenu, 0 ); + createMenu( separator(), fileMenu, -1, 0 ); + + createMenu( separator(), fileMenu ); + createMenu( FileExitId, fileMenu ); + + createMenu( EditCopyId, editMenu ); + createMenu( EditPasteId, editMenu ); + createMenu( separator(), editMenu ); + + createMenu( ViewWindowsId, viewMenu ); + createMenu( ViewStatusBarId, viewMenu ); + createMenu( separator(), viewMenu ); + + createMenu( HelpAboutId, helpMenu ); + createMenu( separator(), helpMenu ); + + // Create tool bars + + int stdTBar = createTool( tr( "INF_DESK_TOOLBAR_STANDARD" ) ); + + // Create tool items + + createTool( FileNewId, stdTBar ); + createTool( FileOpenId, stdTBar ); + createTool( FileSaveId, stdTBar ); + createTool( FileCloseId, stdTBar ); + createTool( separator(), stdTBar ); + createTool( EditCopyId, stdTBar ); + createTool( EditPasteId, stdTBar ); +} + +/*!Opens new application*/ +void STD_Application::onNewDoc() +{ + QApplication::setOverrideCursor( Qt::waitCursor ); + + if ( !activeStudy() ) + { + createEmptyStudy(); + activeStudy()->createDocument(); + studyCreated( activeStudy() ); + } + else + { + SUIT_Application* aApp = startApplication( 0, 0 ); + if ( aApp->inherits( "STD_Application" ) ) + ((STD_Application*)aApp)->onNewDoc(); + else + { + aApp->createEmptyStudy(); + aApp->activeStudy()->createDocument(); + } + } + + QApplication::restoreOverrideCursor(); +} + +/*!Put file name from file dialog to onOpenDoc(const QString&) function*/ +void STD_Application::onOpenDoc() +{ + // It is preferrable to use OS-specific file dialog box here !!! + QString aName = getFileName( true, QString::null, getFileFilter(), QString::null, 0 ); + if ( aName.isNull() ) + return; + + onOpenDoc( aName ); +} + +/*! \retval true, if document was opened successful, else false.*/ +bool STD_Application::onOpenDoc( const QString& aName ) +{ + QApplication::setOverrideCursor( Qt::waitCursor ); + + bool res = true; + if ( !activeStudy() ) + { + // if no study - open in current desktop + res = useFile( aName ); + } + else + { + // if study exists - open in new desktop. Check: is the same file is opened? + SUIT_Session* aSession = SUIT_Session::session(); + QPtrList aAppList = aSession->applications(); + bool isAlreadyOpen = false; + SUIT_Application* aApp = 0; + for ( QPtrListIterator it( aAppList ); it.current() && !isAlreadyOpen; ++it ) + { + aApp = it.current(); + if ( aApp->activeStudy()->studyName() == aName ) + isAlreadyOpen = true; + } + if ( !isAlreadyOpen ) + { + aApp = startApplication( 0, 0 ); + if ( aApp ) + res = aApp->useFile( aName ); + if ( !res ) + aApp->closeApplication(); + } + else + aApp->desktop()->setActiveWindow(); + } + + QApplication::restoreOverrideCursor(); + + return res; +} + +/*! called on loading the existent study */ +void STD_Application::onLoadDoc() +{ +} + +/*! \retval true, if document was loaded successful, else false.*/ +bool STD_Application::onLoadDoc( const QString& aName ) +{ + bool res = true; + if ( !activeStudy() ) + { + // if no study - load in current desktop + res = useStudy( aName ); + } + else + { + // if study exists - load in new desktop. Check: is the same file is loaded? + SUIT_Session* aSession = SUIT_Session::session(); + QPtrList aAppList = aSession->applications(); + bool isAlreadyOpen = false; + SUIT_Application* aApp = 0; + for ( QPtrListIterator it( aAppList ); it.current() && !isAlreadyOpen; ++it ) + { + aApp = it.current(); + if ( aApp->activeStudy()->studyName() == aName ) + isAlreadyOpen = true; + } + if ( !isAlreadyOpen ) + { + aApp = startApplication( 0, 0 ); + if ( aApp ) + res = aApp->useStudy( aName ); + } + else + aApp->desktop()->setActiveWindow(); + } + return res; +} + +/*!Virtual function. Not implemented here.*/ +void STD_Application::beforeCloseDoc( SUIT_Study* ) +{ +} + +/*!Virtual function. Not implemented here.*/ +void STD_Application::afterCloseDoc() +{ +} + +/*!Close document, if it's possible.*/ +void STD_Application::onCloseDoc( bool ask ) +{ + if ( ask && !isPossibleToClose() ) + return; + + SUIT_Study* study = activeStudy(); + + beforeCloseDoc( study ); + + if ( study ) + study->closeDocument(myClosePermanently); + + clearViewManagers(); + + setActiveStudy( 0 ); + delete study; + + int aNbStudies = 0; + QPtrList apps = SUIT_Session::session()->applications(); + for ( unsigned i = 0; i < apps.count(); i++ ) + aNbStudies += apps.at( i )->getNbStudies(); + + // STV: aNbStudies - number of currently existing studies (exclude currently closed) + // STV: aNbStudies should be compared with 0. + if ( aNbStudies ) + { + savePreferences(); + setDesktop( 0 ); + } + else + { + updateDesktopTitle(); + updateCommandsStatus(); + } + + afterCloseDoc(); + + if ( !desktop() ) + closeApplication(); +} + +/*!Check the application on closing. + * \retval true if possible, else false + */ +bool STD_Application::isPossibleToClose() +{ + myClosePermanently = true; //SRN: BugID: IPAL9021 + if ( activeStudy() ) + { + activeStudy()->abortAllOperations(); + if ( activeStudy()->isModified() ) + { + QString sName = activeStudy()->studyName().stripWhiteSpace(); + QString msg = sName.isEmpty() ? tr( "INF_DOC_MODIFIED" ) : tr ( "INF_DOCUMENT_MODIFIED" ).arg( sName ); + + //SRN: BugID: IPAL9021: Begin + STD_CloseDlg dlg(desktop()); + switch( dlg.exec() ) + { + case 1: + if ( activeStudy()->isSaved() ) + onSaveDoc(); + else if ( !onSaveAsDoc() ) + return false; + break; + case 2: + break; + case 3: + myClosePermanently = false; + break; + case 4: + default: + return false; + } + //SRN: BugID: IPAL9021: End + } + } + return true; +} + +/*!Save document if all ok, else error message.*/ +void STD_Application::onSaveDoc() +{ + if ( !activeStudy() ) + return; + + bool isOk = false; + if ( activeStudy()->isSaved() ) + { + putInfo( tr( "INF_DOC_SAVING" ) + activeStudy()->studyName() ); + + QApplication::setOverrideCursor( Qt::waitCursor ); + + isOk = activeStudy()->saveDocument(); + + QApplication::restoreOverrideCursor(); + + if ( !isOk ) + { + putInfo( "" ); + SUIT_MessageBox::error1( desktop(), tr( "TIT_FILE_SAVEAS" ), + tr( "MSG_CANT_SAVE" ).arg( activeStudy()->studyName() ), tr( "BUT_OK" ) ); + } + else + putInfo( tr( "INF_DOC_SAVED" ).arg( "" ) ); + } + + if ( isOk ) + studySaved( activeStudy() ); + else + onSaveAsDoc(); +} + +/*! \retval TRUE, if doument saved successful, else FALSE.*/ +bool STD_Application::onSaveAsDoc() +{ + SUIT_Study* study = activeStudy(); + if ( !study ) + return false; + + bool isOk = false; + while ( !isOk ) + { + QString aName = getFileName( false, study->studyName(), getFileFilter(), QString::null, 0 ); + if ( aName.isNull() ) + return false; + + QApplication::setOverrideCursor( Qt::waitCursor ); + + putInfo( tr( "INF_DOC_SAVING" ) + aName ); + isOk = study->saveDocumentAs( aName ); + + putInfo( isOk ? tr( "INF_DOC_SAVED" ).arg( aName ) : "" ); + + QApplication::restoreOverrideCursor(); + + if ( !isOk ) + SUIT_MessageBox::error1( desktop(), tr( "ERROR" ), + tr( "INF_DOC_SAVING_FAILS" ).arg( aName ), tr( "BUT_OK" ) ); + } + + studySaved( activeStudy() ); + + return isOk; +} + +/*!Closing session.*/ +void STD_Application::onExit() +{ + int aAnswer = SUIT_MessageBox::info2( desktop(), tr( "INF_DESK_EXIT" ), tr( "QUE_DESK_EXIT" ), + tr( "BUT_OK" ), tr( "BUT_CANCEL" ), 1, 2, 2 ); + if ( aAnswer == 1 ) + SUIT_Session::session()->closeSession(); +} + +/*!Virtual slot. Not implemented here.*/ +void STD_Application::onCopy() +{ +} + +/*!Virtual slot. Not implemented here.*/ +void STD_Application::onPaste() +{ +} + +/*!Sets \a theEnable for menu manager and for tool manager.*/ +void STD_Application::setEditEnabled( bool theEnable ) +{ + myEditEnabled = theEnable; + + QtxActionMenuMgr* mMgr = desktop()->menuMgr(); + QtxActionToolMgr* tMgr = desktop()->toolMgr(); + + for ( int i = EditCopyId; i <= EditPasteId; i++ ) + { + mMgr->setShown( i, myEditEnabled ); + tMgr->setShown( i, myEditEnabled ); + } +} + +/*!\retval true, if document opened successful, else false.*/ +bool STD_Application::useFile(const QString& theFileName) +{ + bool res = SUIT_Application::useFile( theFileName ); + + if ( res ) + studyOpened( activeStudy() ); + + return res; +} + +/*!Update desktop title.*/ +void STD_Application::updateDesktopTitle() +{ + QString aTitle = applicationName(); + QString aVer = applicationVersion(); + if ( !aVer.isEmpty() ) + aTitle += QString( " " ) + aVer; + + if ( activeStudy() ) + { + QString sName = SUIT_Tools::file( activeStudy()->studyName().stripWhiteSpace(), false ); + if ( !sName.isEmpty() ) + aTitle += QString( " - [%1]" ).arg( sName ); + } + + desktop()->setCaption( aTitle ); +} + +/*!Update commands status.*/ +void STD_Application::updateCommandsStatus() +{ + bool aHasStudy = activeStudy() != 0; + bool aIsNeedToSave = false; + if ( aHasStudy ) + aIsNeedToSave = !activeStudy()->isSaved() || activeStudy()->isModified(); + + if ( action( FileSaveId ) ) + action( FileSaveId )->setEnabled( aIsNeedToSave ); + if ( action( FileSaveAsId ) ) + action( FileSaveAsId )->setEnabled( aHasStudy ); + if ( action( FileCloseId ) ) + action( FileCloseId )->setEnabled( aHasStudy ); + if ( action( NewWindowId ) ) + action( NewWindowId )->setEnabled( aHasStudy ); +} + +/*!\retval SUIT_ViewManager by viewer manager type name.*/ +SUIT_ViewManager* STD_Application::viewManager( const QString& vmType ) const +{ + SUIT_ViewManager* vm = 0; + for ( QPtrListIterator it( myViewMgrs ); it.current() && !vm; ++it ) + { + if ( it.current()->getType() == vmType ) + vm = it.current(); + } + return vm; +} + +/*! \param vmType - input view manager type name + * \param lst - output list of view managers with types \a vmType. + */ +void STD_Application::viewManagers( const QString& vmType, ViewManagerList& lst ) const +{ + for ( QPtrListIterator it( myViewMgrs ); it.current(); ++it ) + if ( it.current()->getType() == vmType ) + lst.append( it.current() ); +} + +/*!\param lst - output list of all view managers.*/ +void STD_Application::viewManagers( ViewManagerList& lst ) const +{ + for ( QPtrListIterator it( myViewMgrs ); it.current(); ++it ) + lst.append( it.current() ); +} + +/*!\retval ViewManagerList - const list of all view managers.*/ +ViewManagerList STD_Application::viewManagers() const +{ + ViewManagerList lst; + viewManagers( lst ); + return lst; +} + +/*!\retval SUIT_ViewManager - return pointer to active view manager.*/ +SUIT_ViewManager* STD_Application::activeViewManager() const +{ + return myActiveViewMgr; +} + +/*!Add view manager to view managers list, if it not already there.*/ +void STD_Application::addViewManager( SUIT_ViewManager* vm ) +{ + if ( !vm ) + return; + + if ( !containsViewManager( vm ) ) + { + myViewMgrs.append( vm ); + connect( vm, SIGNAL( activated( SUIT_ViewManager* ) ), + this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) ); + vm->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + + emit viewManagerAdded( vm ); + } +/* + if ( !activeViewManager() && myViewMgrs.count() == 1 ) + setActiveViewManager( vm ); +*/ +} + +/*!Remove view manager from view managers list.*/ +void STD_Application::removeViewManager( SUIT_ViewManager* vm ) +{ + if ( !vm ) + return; + + vm->closeAllViews(); + + emit viewManagerRemoved( vm ); + + vm->disconnectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + vm->disconnect(); + myViewMgrs.removeRef( vm ); + + if ( myActiveViewMgr == vm ) + myActiveViewMgr = 0; +} + +/*!Remove all view managers from view managers list.*/ +void STD_Application::clearViewManagers() +{ + ViewManagerList lst; + viewManagers( lst ); + + for ( QPtrListIterator it( lst ); it.current(); ++it ) + removeViewManager( it.current() ); +} + +/*!\retval TRUE, if view manager \a vm, already in view manager list (\a myViewMgrs).*/ +bool STD_Application::containsViewManager( SUIT_ViewManager* vm ) const +{ + return myViewMgrs.contains( vm ) > 0; +} + +/*!Private slot, sets active manager to \vm, if \vm in view managers list.*/ +void STD_Application::onViewManagerActivated( SUIT_ViewManager* vm ) +{ + setActiveViewManager( vm ); +} + +/*!Sets status bar show, if \on = true, else status bar hide.*/ +void STD_Application::onViewStatusBar( bool on ) +{ + if ( on ) + desktop()->statusBar()->show(); + else + desktop()->statusBar()->hide(); +} + +/*!Call SUIT_MessageBox::info1(...) with about information.*/ +void STD_Application::onHelpAbout() +{ + SUIT_MessageBox::info1( desktop(), tr( "About" ), tr( "ABOUT_INFO" ), "&OK" ); +} + +/*!Create empty study. \n + * Create new view manager and adding it to view managers list. + */ +void STD_Application::createEmptyStudy() +{ + SUIT_Application::createEmptyStudy(); + + SUIT_ViewManager* vm = new SUIT_ViewManager( activeStudy(), desktop(), new SUIT_ViewModel() ); + + addViewManager( vm ); +} + +/*!Sets active manager to \vm, if \vm in view managers list.*/ +void STD_Application::setActiveViewManager( SUIT_ViewManager* vm ) +{ + if ( !containsViewManager( vm ) ) + return; + + myActiveViewMgr = vm; + emit viewManagerActivated( vm ); +} + +/*!Public slot. */ +void STD_Application::onConnectPopupRequest( SUIT_PopupClient* client, QContextMenuEvent* e ) +{ + QtxPopupMenu* popup = new QtxPopupMenu(); + // fill popup by own items + QString title; + contextMenuPopup( client->popupClientType(), popup, title ); + popup->setTitleText( title ); + + popup->insertSeparator(); + // add items from popup client + client->contextMenuPopup( popup ); + + SUIT_Tools::simplifySeparators( popup ); + + if ( popup->count() ) + popup->exec( e->globalPos() ); + delete popup; +} + +#include + +/*!\retval QString - return file name from dialog.*/ +QString STD_Application::getFileName( bool open, const QString& initial, const QString& filters, + const QString& caption, QWidget* parent ) +{ + if ( !parent ) + parent = desktop(); + if ( open ) + { + return QFileDialog::getOpenFileName( initial, filters, parent, 0, caption ); + } + else + { + QString aName; + QString aUsedFilter; + QString anOldPath = initial; + + bool isOk = false; + while ( !isOk ) + { + // It is preferrable to use OS-specific file dialog box here !!! + aName = QFileDialog::getSaveFileName( anOldPath, filters, parent, 0, caption, &aUsedFilter ); + + if ( aName.isNull() ) + isOk = true; + else + { + int aEnd = aUsedFilter.findRev( ')' ); + int aStart = aUsedFilter.findRev( '(', aEnd ); + QString wcStr = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 ); + + int idx = 0; + QStringList extList; + QRegExp rx( "[\b\\*]*\\.([\\w]+)" ); + while ( ( idx = rx.search( wcStr, idx ) ) != -1 ) + { + extList.append( rx.cap( 1 ) ); + idx += rx.matchedLength(); + } + + if ( !extList.isEmpty() && !extList.contains( QFileInfo( aName ).extension() ) ) + aName += QString( ".%1" ).arg( extList.first() ); + + if ( QFileInfo( aName ).exists() ) + { + int aAnswer = SUIT_MessageBox::warn3( desktop(), tr( "TIT_FILE_SAVEAS" ), + tr( "MSG_FILE_EXISTS" ).arg( aName ), + tr( "BUT_YES" ), tr( "BUT_NO" ), tr( "BUT_CANCEL" ), 1, 2, 3, 1 ); + if ( aAnswer == 3 ) + { // cancelled + aName = QString::null; + isOk = true; + } + else if ( aAnswer == 2 ) // not save to this file + anOldPath = aName; // not to return to the same initial dir at each "while" step + else // overwrite the existing file + isOk = true; + } + else + isOk = true; + } + } + return aName; + } +} + +/*!\retval QString - return directory name from dialog.*/ +QString STD_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent ) +{ + if ( !parent ) + parent = desktop(); + return QFileDialog::getExistingDirectory( initial, parent, 0, caption, true ); +} + +void STD_Application::setDesktop( SUIT_Desktop* desk ) +{ + SUIT_Desktop* prev = desktop(); + + SUIT_Application::setDesktop( desk ); + + if ( prev != desk && desk ) + connect( desk, SIGNAL( closing( SUIT_Desktop*, QCloseEvent* ) ), + this, SLOT( onDesktopClosing( SUIT_Desktop*, QCloseEvent* ) ) ); +} + +/*! + Allow to load preferences before the desktop will be shown. +*/ +void STD_Application::loadPreferences() +{ +} + +/*! + Allow to save preferences before the application will be closed. +*/ +void STD_Application::savePreferences() +{ +} + +void STD_Application::studyCreated( SUIT_Study* ) +{ + updateDesktopTitle(); + updateCommandsStatus(); +} + +void STD_Application::studyOpened( SUIT_Study* ) +{ + updateDesktopTitle(); + updateCommandsStatus(); +} + +void STD_Application::studySaved( SUIT_Study* ) +{ + updateDesktopTitle(); + updateCommandsStatus(); +} diff --git a/src/STD/STD_Application.h b/src/STD/STD_Application.h new file mode 100755 index 000000000..c8e3b4ad5 --- /dev/null +++ b/src/STD/STD_Application.h @@ -0,0 +1,159 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef STD_APPLICATION_H +#define STD_APPLICATION_H + +#include "STD.h" + +#include + +#include +#include + +#include +#include + +class QToolBar; +class QtxAction; +class QPopupMenu; +class SUIT_Operation; +class SUIT_ViewWindow; +class SUIT_ToolWindow; + +typedef QPtrList ViewManagerList; + +#if defined WIN32 +#pragma warning( disable: 4251 ) +#endif + +class STD_EXPORT STD_Application : public SUIT_Application +{ + Q_OBJECT + +public: + STD_Application(); + virtual ~STD_Application(); + + virtual QString applicationName() const; + + virtual bool isPossibleToClose(); + virtual bool useFile( const QString& ); + + virtual void createEmptyStudy(); + + void setEditEnabled( const bool ); + bool isEditEnabled() const { return myEditEnabled; } + + void clearViewManagers(); + virtual void addViewManager( SUIT_ViewManager* ); + virtual void removeViewManager( SUIT_ViewManager* ); + + SUIT_ViewManager* activeViewManager() const; + SUIT_ViewManager* viewManager( const QString& ) const; + + bool containsViewManager( SUIT_ViewManager* ) const; + + ViewManagerList viewManagers() const; + void viewManagers( ViewManagerList& ) const; + void viewManagers( const QString&, ViewManagerList& ) const; + + virtual QString getFileFilter() const { return QString::null; } + virtual QString getFileName( bool open, const QString& initial, const QString& filters, + const QString& caption, QWidget* parent ); + QString getDirectory( const QString& initial, const QString& caption, QWidget* parent ); + + virtual void start(); + + virtual void closeApplication(); + + virtual void contextMenuPopup( const QString&, QPopupMenu*, QString& ) {} + +signals: + /*!emit that view manager added*/ + void viewManagerAdded( SUIT_ViewManager* ); + /*!emit that view manager removed*/ + void viewManagerRemoved( SUIT_ViewManager* ); + /*!emit that view manager activated*/ + void viewManagerActivated( SUIT_ViewManager* ); + +public slots: + virtual void onNewDoc(); + virtual void onCloseDoc( bool ask = true ); + virtual void onSaveDoc(); + virtual bool onSaveAsDoc(); + + virtual void onOpenDoc(); + virtual bool onOpenDoc( const QString& ); + + virtual void onLoadDoc(); + virtual bool onLoadDoc( const QString& ); + + virtual void onExit(); + + virtual void onCopy(); + virtual void onPaste(); + + virtual void onViewStatusBar( bool ); + + virtual void onHelpAbout(); + + virtual void onDesktopClosing( SUIT_Desktop*, QCloseEvent* ); + virtual void onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ); + +private slots: + virtual void onViewManagerActivated( SUIT_ViewManager* ); + +protected: + enum { FileNewId, FileOpenId, FileCloseId, FileSaveId, FileSaveAsId, + FileExitId, EditCutId, EditCopyId, EditPasteId, ViewStatusBarId, + NewWindowId, HelpAboutId, ViewWindowsId, FileLoadId, UserID }; + +protected: + virtual void createActions(); + virtual void updateDesktopTitle(); + virtual void updateCommandsStatus(); + + virtual void setDesktop( SUIT_Desktop* ); + + virtual void loadPreferences(); + virtual void savePreferences(); + + virtual void studySaved( SUIT_Study* ); + virtual void studyOpened( SUIT_Study* ); + virtual void studyCreated( SUIT_Study* ); + + virtual void beforeCloseDoc( SUIT_Study* theDoc ); + virtual void afterCloseDoc(); + + virtual void setActiveViewManager( SUIT_ViewManager* ); + +private: + ViewManagerList myViewMgrs; + SUIT_ViewManager* myActiveViewMgr; + +private: + bool myEditEnabled; + bool myClosePermanently; +}; + +#if defined WIN32 +#pragma warning( default: 4251 ) +#endif + +#endif diff --git a/src/STD/STD_TabDesktop.cxx b/src/STD/STD_TabDesktop.cxx new file mode 100644 index 000000000..24dfd5ccf --- /dev/null +++ b/src/STD/STD_TabDesktop.cxx @@ -0,0 +1,199 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "STD_TabDesktop.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/*!Constructor.Create new instances of QVBox and QtxWorkstack.*/ +STD_TabDesktop::STD_TabDesktop() +: SUIT_Desktop(), +myWorkstack( 0 ), +myWorkstackAction( 0 ) +{ + QVBox* base = new QVBox( this ); + base->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + + setCentralWidget( base ); + + myWorkstack = new QtxWorkstack( base ); + // setting Expanding size policy for central workstack. If there are several widgets + // in central area of Desktop, other widgets will be added below the workstack (CATHARE, TRIPOLI modules). + // But the workstack must occupy as much space as possible -- set Expanding for it. + myWorkstack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + myWorkstack->setAccel(QtxWorkstack::SplitVertical, SHIFT + Key_V); + myWorkstack->setAccel(QtxWorkstack::SplitHorizontal, SHIFT + Key_H); + myWorkstack->setAccel(QtxWorkstack::Close, SHIFT + Key_C); + + connect( myWorkstack, SIGNAL( windowActivated( QWidget* ) ), + this, SLOT( onWindowActivated( QWidget* ) ) ); + + createActions(); +} + +/*!Destructor.*/ +STD_TabDesktop::~STD_TabDesktop() +{ +} + +/*!\retval SUIT_ViewWindow - return const active window.*/ +SUIT_ViewWindow* STD_TabDesktop::activeWindow() const +{ + SUIT_ViewWindow* wnd = 0; + + QWidget* wid = myWorkstack->activeWindow(); + if ( wid && wid->inherits( "SUIT_ViewWindow" ) ) + wnd = (SUIT_ViewWindow*)wid; + + return wnd; +} + +/*!\retval QPtrList - return const active window list.*/ +QPtrList STD_TabDesktop::windows() const +{ + QPtrList winList; + + QWidgetList children = myWorkstack->windowList(); + for ( QWidgetListIt it( children ); it.current(); ++it ) + { + if ( it.current()->inherits( "SUIT_ViewWindow" ) ) + winList.append( (SUIT_ViewWindow*)it.current() ); + } + + return winList; +} + +/*!\retval QWidget pointer - QT work stack.*/ +QWidget* STD_TabDesktop::parentArea() const +{ + return workstack(); +} + +/*!Call method perform for operation \a type.*/ +void STD_TabDesktop::windowOperation( const int type ) +{ + myWorkstackAction->perform( operationFlag( type ) ); +} + +/*!Sets window operations by \a first ... parameters.*/ +void STD_TabDesktop::setWindowOperations( const int first, ... ) +{ + va_list ints; + va_start( ints, first ); + + QValueList typeList; + + int cur = first; + while ( cur ) + { + typeList.append( cur ); + cur = va_arg( ints, int ); + } + + setWindowOperations( typeList ); +} + +/*!Sets window operations by variable \a opList - operation list.*/ +void STD_TabDesktop::setWindowOperations( const QValueList& opList ) +{ + int flags = 0; + + for ( QValueList::const_iterator it = opList.begin(); it != opList.end(); ++it ) + flags = flags | operationFlag( *it ); + + myWorkstackAction->setItems( flags ); +} + +/*!\retval QtxWorkstack pointer - QT work stack.*/ +QtxWorkstack* STD_TabDesktop::workstack() const +{ + return myWorkstack; +} + +/*!Emit window activated.*/ +void STD_TabDesktop::onWindowActivated( QWidget* w ) +{ + if ( w && w->inherits( "SUIT_ViewWindow" ) ) + emit windowActivated( (SUIT_ViewWindow*)w ); +} + +/*!Create actions for window.*/ +void STD_TabDesktop::createActions() +{ + if ( myWorkstackAction ) + return; + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( !resMgr ) + return; + + myWorkstackAction = new QtxWorkstackAction( workstack(), this ); + + myWorkstackAction->setItems( QtxWorkstackAction::Split | QtxWorkstackAction::Windows ); + + // Split Horizontal + myWorkstackAction->setIconSet( QtxWorkstackAction::HSplit, + resMgr->loadPixmap( "STD", tr( "ICON_DESK_WINDOW_HSPLIT" ) ) ); + myWorkstackAction->setMenuText( QtxWorkstackAction::HSplit, tr( "MEN_DESK_WINDOW_HSPLIT" ) ); + myWorkstackAction->setStatusTip( QtxWorkstackAction::HSplit, tr( "PRP_DESK_WINDOW_HSPLIT" ) ); + + // Split Vertical + myWorkstackAction->setIconSet( QtxWorkstackAction::VSplit, + resMgr->loadPixmap( "STD", tr( "ICON_DESK_WINDOW_VSPLIT" ) ) ); + myWorkstackAction->setMenuText( QtxWorkstackAction::VSplit, tr( "MEN_DESK_WINDOW_VSPLIT" ) ); + myWorkstackAction->setStatusTip( QtxWorkstackAction::VSplit, tr( "PRP_DESK_WINDOW_VSPLIT" ) ); + + QtxActionMenuMgr* mMgr = menuMgr(); + if ( !mMgr ) + return; + + int winMenuId = mMgr->insert( tr( "MEN_DESK_WINDOW" ), -1, 100 ); + mMgr->insert( myWorkstackAction, winMenuId, -1 ); + mMgr->insert( QtxActionMenuMgr::separator(), winMenuId, -1 ); +} + +/*!Convert STD_TabDesktop enumerations to QtxWorkstackAction*/ +int STD_TabDesktop::operationFlag( const int type ) const +{ + int res = 0; + switch ( type ) + { + case VSplit: + res = QtxWorkstackAction::VSplit; + break; + case HSplit: + res = QtxWorkstackAction::HSplit; + break; + } + return res; +} diff --git a/src/STD/resources/STD_msg_en.po b/src/STD/resources/STD_msg_en.po new file mode 100755 index 000000000..2c5d9fd37 --- /dev/null +++ b/src/STD/resources/STD_msg_en.po @@ -0,0 +1,361 @@ +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. "Foo::Bar" +# would be translated to "Pub", not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: example-Qt-message-extraction\n" +"POT-Creation-Date: 1999-02-23 15:38+0200\n" +"PO-Revision-Date: 1999-02-23 15:38+0200\n" +"Last-Translator: \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +msgid "INF_READY" +msgstr "Ready" + +msgid "BUT_OK" +msgstr "OK" + +msgid "BUT_CANCEL" +msgstr "Cancel" + +msgid "BUT_CLOSE" +msgstr "Close" + +msgid "BUT_HELP" +msgstr "Help" + +msgid "BUT_YES" +msgstr "Yes" + +msgid "BUT_NO" +msgstr "No" + +msgid "BUT_APPLY" +msgstr "Apply" + +msgid "ERR_ERROR" +msgstr "Error" + +msgid "WRN_WARNING" +msgstr "Warning" + +msgid "INF_INFO" +msgstr "Information" + +msgid "FILTER_FILES" +msgstr "%1 Files (%2)" + +msgid "ALL_FILES" +msgstr "All Files (*.*)" + +msgid "INF_CANCELLED" +msgstr "Cancelled" + +msgid "ERR_UNKNOWN" +msgstr "Unknown error" + +## ---------------------------------------------------- + +msgid "INF_DESK_DOC_CREATE" +msgstr "Create a new document" + +msgid "ERR_APP_NOAPP" +msgstr "No application" + +msgid "INF_DESK_EXIT" +msgstr "Exit" + +msgid "INF_DESK_TOOLBAR_STANDARD" +msgstr "Standard" + +msgid "MEN_DESK_FILE" +msgstr "&File" + +msgid "MEN_DESK_FILE_CLOSE" +msgstr "&Close" + +msgid "MEN_DESK_FILE_EXIT" +msgstr "E&xit" + +msgid "MEN_DESK_FILE_NEW" +msgstr "&New" + +msgid "MEN_DESK_FILE_OPEN" +msgstr "&Open..." + +msgid "MEN_DESK_FILE_PRINT" +msgstr "&Print" + +msgid "MEN_DESK_FILE_SAVE" +msgstr "&Save" + +msgid "MEN_DESK_FILE_SAVEAS" +msgstr "Save &As..." + +msgid "MEN_DESK_EDIT" +msgstr "&Edit" + +msgid "MEN_DESK_EDIT_CUT" +msgstr "Cu&t" + +msgid "MEN_DESK_EDIT_COPY" +msgstr "&Copy" + +msgid "MEN_DESK_EDIT_PASTE" +msgstr "&Paste" + +msgid "MEN_DESK_HELP" +msgstr "&Help" + +msgid "MEN_DESK_HELP_ABOUT" +msgstr "&About..." + +msgid "MEN_DESK_HELP_CONTENTS" +msgstr "&Contents" + +msgid "MEN_DESK_HELP_SEARCH" +msgstr "&Search..." + +msgid "MEN_DESK_VIEW" +msgstr "&View" + +msgid "MEN_DESK_VIEW_TOOLBARS" +msgstr "T&oolbars" + +msgid "MEN_DESK_VIEW_STATUSBAR" +msgstr "&Status Bar" + +msgid "MEN_DESK_VIEW_STDTOOLBAR" +msgstr "&Standard" + +msgid "PRP_DESK_FILE_CLOSE" +msgstr "Closes the active document" + +msgid "PRP_DESK_FILE_EXIT" +msgstr "Exits the application" + +msgid "PRP_DESK_FILE_NEW" +msgstr "Creates a new document" + +msgid "PRP_DESK_FILE_OPEN" +msgstr "Opens an existing document" + +msgid "PRP_DESK_FILE_PRINT" +msgstr "Prints the active document" + +msgid "PRP_DESK_FILE_SAVE" +msgstr "Saves the active document" + +msgid "PRP_DESK_FILE_SAVEAS" +msgstr "Saves the active document with a new name" + +msgid "PRP_DESK_EDIT_CUT" +msgstr "Cuts the selection and puts it to the Clipboard" + +msgid "PRP_DESK_EDIT_COPY" +msgstr "Copy the selection to the Clipboard" + +msgid "PRP_DESK_EDIT_PASTE" +msgstr "Inserts the Clipboard content at the insertion point" + +msgid "PRP_DESK_HELP_ABOUT" +msgstr "Shows \'About\' dialog" + +msgid "PRP_DESK_HELP_CONTENTS" +msgstr "Shows the whole help contents" + +msgid "PRP_DESK_HELP_SEARCH" +msgstr "Searches help for a topic" + +msgid "PRP_DESK_VIEW_STATUSBAR" +msgstr "Toggles status bar view on/off" + +msgid "PRP_DESK_VIEW_STDTOOLBAR" +msgstr "Toggles standard toolbar on/off" + +msgid "QUE_DESK_EXIT" +msgstr "Do you really want to quit ?" + +msgid "TOT_DESK_FILE_NEW" +msgstr "New document" + +msgid "TOT_DESK_FILE_OPEN" +msgstr "Open document" + +msgid "TOT_DESK_FILE_CLOSE" +msgstr "Close document" + +msgid "TOT_DESK_FILE_PRINT" +msgstr "Print document" + +msgid "TOT_DESK_FILE_SAVE" +msgstr "Save document" + +msgid "TOT_DESK_FILE_SAVEAS" +msgstr "Save document as..." + +msgid "TOT_DESK_FILE_EXIT" +msgstr "Exit from application" + +msgid "TOT_DESK_EDIT_CUT" +msgstr "Cut" + +msgid "TOT_DESK_EDIT_COPY" +msgstr "Copy" + +msgid "TOT_DESK_EDIT_PASTE" +msgstr "Paste" + +msgid "TOT_DESK_HELP_ABOUT" +msgstr "About..." + +msgid "STD_Application::TOT_DOCK_WINDOWS" +msgstr "Show / hide dockable windows and toolbars" + +msgid "STD_Application::MEN_DOCK_WINDOWS" +msgstr "Windows and Toolbars" + +msgid "ERR_DOC_UNKNOWNTYPE_OPEN" +msgstr "You are trying to open a document of an unknown type\n( %1 )" + +msgid "ERR_DOC_UNKNOWNTYPE_SAVE" +msgstr "You are trying to save this document under an unknown type\n( %1 )" + +msgid "ERR_DOC_PERMISSIONDENIED_SAVE" +msgstr "Can not save file %1. Permission denied" + +msgid "ERR_DOC_DIRWITHNAMEEXIST_SAVE" +msgstr "Can not save file %1.\nDirectory with this name exist on disc. Try to use another name" + +msgid "QUE_DOC_FILEEXISTS" +msgstr "The file %1 already exists.\nDo you want to overwrite it ?" + +msgid "ERR_DESK_NOAPP" +msgstr "No applications registered" + +msgid "DESK_DEFAULTTITLE" +msgstr "Qt Application Desktop" + +msgid "QUE_DOC_ALREADYOPEN" +msgstr "The document %1 is already open.\nDo you want to reload it ?" + +msgid "MEN_DESK_WINDOW" +msgstr "&Window" + +msgid "MEN_DESK_NEWWINDOW" +msgstr "&New Window" + +msgid "TOT_DESK_NEWWINDOW" +msgstr "Create new Window" + +msgid "PRP_DESK_NEWWINDOW" +msgstr "Create new Window" + +msgid "MEN_DESK_WINDOW_CASCADE" +msgstr "&Cascade" + +msgid "PRP_DESK_WINDOW_CASCADE" +msgstr "Arranges the windows as overlapping tiles" + +msgid "MEN_DESK_WINDOW_TILE" +msgstr "&Tile" + +msgid "PRP_DESK_WINDOW_TILE" +msgstr "Arranges the windows as nonoverlapping tiles" + +msgid "MEN_DESK_WINDOW_HTILE" +msgstr "Tile &Horizontally" + +msgid "PRP_DESK_WINDOW_HTILE" +msgstr "Arranges the windows as nonoverlapping horizontal tiles" + +msgid "MEN_DESK_WINDOW_VTILE" +msgstr "Tile &Vertically" + +msgid "PRP_DESK_WINDOW_VTILE" +msgstr "Arranges the windows as nonoverlapping vertical tiles" + +msgid "PRP_DESK_WINDOW_ACTIVATE" +msgstr "Activates this window" + +msgid "MEN_DESK_WINDOW_HSPLIT" +msgstr "Split &Horizontally" + +msgid "PRP_DESK_WINDOW_HSPLIT" +msgstr "Splits the active window on two horizontal parts" + +msgid "MEN_DESK_WINDOW_VSPLIT" +msgstr "Split &Vertically" + +msgid "PRP_DESK_WINDOW_VSPLIT" +msgstr "Splits the active window on two vertical parts" + +msgid "INF_DESK_DOCALREADYOPEN" +msgstr "A document cannot be saved under a name of a document already opened.\nPlease, type another name for the document you want to save.\n( %1 )" + +msgid "MEN_DESK_FILE_MRU" +msgstr "Recent &Files" + +msgid "PRP_DESK_FILE_MRU" +msgstr "Opens a document" + +msgid "STD_Application::ABOUT_INFO" +msgstr "SUIT Std application" + +msgid "MSG_FILE_EXISTS" +msgstr "File \"%1\" already exists.\nDo you want to overwrite it?" + +msgid "MSG_CANT_SAVE" +msgstr "Can't save file \"%1\"." + +msgid "TIT_FILE_SAVEAS" +msgstr "Save As" + +msgid "STD_Application::INF_DOC_MODIFIED" +msgstr "Document has been modified.\nDo you want to save changes?" + +msgid "STD_Application::INF_DOCUMENT_MODIFIED" +msgstr "Document \"%1\" has been modified.\nDo you want to save changes?" + +msgid "STD_Application::INF_DOC_SAVED" +msgstr "Study %1 saved" + +msgid "STD_Application::INF_DOC_SAVING" +msgstr "Saving study " + +msgid "STD_Application::INF_DOC_SAVING_FAILS" +msgstr "Can't save file \"%1\".\nPossible reason is permission denied or disc full.\nTry to use another file name." + +msgid "CLOSE_DLG_SAVE_CLOSE" +msgstr "&Save&&Close" + +msgid "CLOSE_DLG_CLOSE" +msgstr "&Close w/o saving" + +msgid "CLOSE_DLG_UNLOAD" +msgstr "&Unload" + +msgid "TOT_DESK_FILE_LOAD" +msgstr "Load document" + +msgid "PRP_DESK_FILE_LOAD" +msgstr "Load a document" + +msgid "MEN_DESK_FILE_LOAD" +msgstr "Conn&ect" + +msgid "CLOSE_DLG_CAPTION" +msgstr "Close active study" + +msgid "CLOSE_DLG_DESCRIPTION" +msgstr "Do you want to close or only unload the study" + +msgid "DLG_LOAD_STUDY_CAPTION" +msgstr "Load Study" + +msgid "MEN_STUDIES_CHOICE" +msgstr "Choose existent study." + + + + diff --git a/src/SUIT/SUIT_DataOwner.cxx b/src/SUIT/SUIT_DataOwner.cxx new file mode 100755 index 000000000..28ceb5153 --- /dev/null +++ b/src/SUIT/SUIT_DataOwner.cxx @@ -0,0 +1,172 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "SUIT_DataOwner.h" + +#ifndef WNT +#include +#define _typeinfo std::type_info +#else +#include +#define _typeinfo type_info +#endif + +//******************************************************************** +// SUIT_DataOwner class +//******************************************************************** + + +/*! Constructor*/ +SUIT_DataOwner::SUIT_DataOwner() +{ +} + +/*! Destructor*/ +SUIT_DataOwner::~SUIT_DataOwner() +{ +} + +/*! operator== : compares two owners*/ +bool operator==( const SUIT_DataOwnerPtr& p1, const SUIT_DataOwnerPtr& p2 ) +{ + if ( !p1.isNull() && !p2.isNull() ) + return (p1->isEqual( *p2 ) && p2->isEqual( *p1 )); + return p1.isNull() && p2.isNull(); +} + +//******************************************************************** +/*! \class SUIT_DataOwnerPtrList + * implements value list with unique items (uniqueness is + * provided by operator==()) + */ +//******************************************************************** + +//==================================================================== +//! Constructor (default) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList() + : QValueList(), + mySkipEqual( true ) +{ +} + +//==================================================================== +//! Constructor (default) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList( const bool skipAllEqual ) + : QValueList(), + mySkipEqual( skipAllEqual ) +{ +} + +//==================================================================== +//! Constructor (copy) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList( const SUIT_DataOwnerPtrList& l ) + : QValueList( l ), + mySkipEqual( true ) +{ +} + +//==================================================================== +//! Constructor (copy) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList( const SUIT_DataOwnerPtrList& l, const bool skipAllEqual ) + : QValueList(), + mySkipEqual( skipAllEqual ) +{ + if ( skipAllEqual == l.mySkipEqual ) + operator =( l ); + else + { + SUIT_DataOwnerPtrList::const_iterator beginIt = l.begin(); + SUIT_DataOwnerPtrList::const_iterator endIt = l.end(); + for( ; beginIt != endIt; ++beginIt ) + append( *beginIt ); + } +} + +#ifndef QT_NO_STL +//==================================================================== +//! Constructor (from stl) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList( const std::list& l ) + : QValueList( l ), + mySkipEqual( true ) +{ +} +#endif + +#ifndef QT_NO_STL +//==================================================================== +//! Constructor (from stl) +//==================================================================== +SUIT_DataOwnerPtrList::SUIT_DataOwnerPtrList( const std::list& l, const bool skipAllEqual ) + : QValueList(), + mySkipEqual( skipAllEqual ) +{ + std::list::const_iterator beginIt = l.begin(); + std::list::const_iterator endIt = l.begin(); + for( ; beginIt != endIt; ++beginIt ) + append( *beginIt ); +} +#endif + +//==================================================================== +//! Appends an item to the list +//==================================================================== +SUIT_DataOwnerPtrList::iterator SUIT_DataOwnerPtrList::append( const SUIT_DataOwnerPtr& x ) +{ + if( mySkipEqual && myMap.contains( x ) ) //contains uses SUIT_DataOwnerPtr::operator== + return myMap[ x ]; + + iterator it = QValueList::append( x ); + + if( mySkipEqual ) + myMap.insert( x, it ); + + return it; +} + +//==================================================================== +//! Clear list +//==================================================================== +void SUIT_DataOwnerPtrList::clear() +{ + if( mySkipEqual ) + myMap.clear(); + QValueList::clear(); +} + +//==================================================================== +//! Remove an item from the list +//==================================================================== +uint SUIT_DataOwnerPtrList::remove(const SUIT_DataOwnerPtr& x ) +{ + if( mySkipEqual && myMap.contains(x) ) + myMap.remove(x); + return QValueList::remove( x ); +} + +//==================================================================== +//! +//==================================================================== +bool operator<( const SUIT_DataOwnerPtr& p1, const SUIT_DataOwnerPtr& p2 ) +{ + return p1.get() +#include + +#ifdef WIN32 +#pragma warning( disable:4275 ) +#endif + +class SUIT_EXPORT SUIT_DataOwner : public RefCount +{ +public: + SUIT_DataOwner();//!< constructor + virtual ~SUIT_DataOwner();//!< destructor + //! compare function + virtual bool isEqual( const SUIT_DataOwner& ) const = 0; +}; + +/*! \typedef SUIT_DataOwnerPtr + * Define smart pointer for SUIT_DataOwner object + */ +typedef SMART(SUIT_DataOwner) SUIT_DataOwnerPtr; + +/*! Comparing two SUIT_DataOwnerPtr objects.*/ +bool operator==( const SUIT_DataOwnerPtr&, const SUIT_DataOwnerPtr& ); + +/*! \class QValueList + * \brief For more documentation see QT documentation. + * QT class + */ +/*! \class SUIT_DataOwnerPtrList + * \brief Manage list of SUIT_DataOwnerPtr. + */ +class SUIT_EXPORT SUIT_DataOwnerPtrList : public QValueList +{ +public: + SUIT_DataOwnerPtrList(); //!< constructor + SUIT_DataOwnerPtrList( const bool skipAllEqual );//!< constructor + SUIT_DataOwnerPtrList( const SUIT_DataOwnerPtrList& l ); //!< copy constructor + SUIT_DataOwnerPtrList( const SUIT_DataOwnerPtrList& l, const bool skipAllEqual );//!< copy constructor +#ifndef QT_NO_STL + SUIT_DataOwnerPtrList( const std::list& l ); //!< copy constructor for STL list + SUIT_DataOwnerPtrList( const std::list& l, const bool skipAllEqual );//!< copy constructor for STL list +#endif + + iterator append ( const SUIT_DataOwnerPtr& x );//!< append function + void clear (); + uint remove (const SUIT_DataOwnerPtr& x ); + +private: + // hide this methods: only append() should be used to add items to the list + iterator prepend( const SUIT_DataOwnerPtr& x );//!< hide method + iterator insert ( iterator it, const SUIT_DataOwnerPtr& x );//!< hide method + void push_front ( const SUIT_DataOwnerPtr& x );//!< hide method + void push_back ( const SUIT_DataOwnerPtr& x );//!< hide method + +private: + bool mySkipEqual; + QMap myMap; +}; + +#ifdef WIN32 +#pragma warning( default:4275 ) +#endif + +#endif diff --git a/src/SUIT/SUIT_MessageBox.cxx b/src/SUIT/SUIT_MessageBox.cxx new file mode 100755 index 000000000..1d4d03cad --- /dev/null +++ b/src/SUIT/SUIT_MessageBox.cxx @@ -0,0 +1,349 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +/******************************************************************** +** Class: SUIT_MessageBox +** Descr: Message dialog box for SUIT-based application +** Module: SUIT +** Created: UI team, 02.10.00 +*********************************************************************/ + +#include "SUIT_MessageBox.h" +#include "SUIT_OverrideCursor.h" + +#include +#include + +/*! + Shows info message box with one button [ static ] +*/ +int SUIT_MessageBox::info1( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0 ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + int ret = QMessageBox::information( parent, caption, text, textButton0, + QString::null, QString::null, 0, 0 ); + qApp->processEvents(); + return ret; +} + +/*! + Shows warning message box with one button [ static ] +*/ +int SUIT_MessageBox::warn1( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0 ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + int ret = QMessageBox::warning( parent, caption, text, textButton0, + QString::null, QString::null, 0, 0 ); + qApp->processEvents(); + return ret; +} + +/*! + Shows error message box with one button [ static ] +*/ +int SUIT_MessageBox::error1( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0 ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + int ret = QMessageBox::critical( parent, caption, text, textButton0, + QString::null, QString::null, 0, 0 ); + qApp->processEvents(); + return ret; +} + +/*! + Shows question message box with one button [ static ] +*/ +int SUIT_MessageBox::question1( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0 ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + int ret = QMessageBox::question( parent, caption, text, textButton0, + QString::null, QString::null, 0, 0 ); + qApp->processEvents(); + return ret; +} + +/*! + Shows info message box with two buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::info2( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + int idButton0, int idButton1, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else + idDefault = 0; + + int ret = QMessageBox::information( parent, caption, text, textButton0, + textButton1, QString::null, idDefault ); + qApp->processEvents(); + return ( ret == 0 ? idButton0 : idButton1 ); +} + +/*! + Shows warning message box with two buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::warn2( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + int idButton0, int idButton1, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else + idDefault = 0; + + int ret = QMessageBox::warning( parent, caption, text, textButton0, + textButton1, QString::null, idDefault ); + qApp->processEvents(); + return ( ret == 0 ? idButton0 : idButton1 ); +} + +/*! + Shows error message box with two buttons + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::error2( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + int idButton0, int idButton1, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else + idDefault = 0; + + int ret = QMessageBox::critical( parent, caption, text, textButton0, + textButton1, QString::null, idDefault ); + qApp->processEvents(); + return ( ret == 0 ? idButton0 : idButton1 ); +} + +/*! + Shows question message box with two buttons + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::question2( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + int idButton0, int idButton1, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else + idDefault = 0; + + int ret = QMessageBox::question( parent, caption, text, textButton0, + textButton1, QString::null, idDefault ); + qApp->processEvents(); + return ( ret == 0 ? idButton0 : idButton1 ); +} + +/*! + Shows info message box with three buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::info3( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + const QString& textButton2, + int idButton0, int idButton1, + int idButton2, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else if ( idDefault == idButton2 ) + idDefault = 2; + else + idDefault = 0; + + int ret = QMessageBox::information( parent, caption, text, textButton0, + textButton1, textButton2, idDefault ); + qApp->processEvents(); + switch ( ret ) + { + case 0: + return idButton0; + case 1: + return idButton1; + case 2: + return idButton2; + } + return -1; +} + +/*! + Shows warning message box with three buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::warn3( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + const QString& textButton2, + int idButton0, int idButton1, + int idButton2, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else if ( idDefault == idButton2 ) + idDefault = 2; + else + idDefault = 0; + + int ret = QMessageBox::warning( parent, caption, text, textButton0, + textButton1, textButton2, idDefault ); + qApp->processEvents(); + switch ( ret ) + { + case 0: + return idButton0; + case 1: + return idButton1; + case 2: + return idButton2; + } + return -1; +} + +/*! + Shows error message box with three buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::error3( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + const QString& textButton2, + int idButton0, int idButton1, + int idButton2, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else if ( idDefault == idButton2 ) + idDefault = 2; + else + idDefault = 0; + + int ret = QMessageBox::critical( parent, caption, text, textButton0, + textButton1, textButton2, idDefault ); + qApp->processEvents(); + switch ( ret ) + { + case 0: + return idButton0; + case 1: + return idButton1; + case 2: + return idButton2; + } + return -1; +} + +/*! + Shows question message box with three buttons. + Returns id of the pressed button or -1 if escaped [ static ] +*/ +int SUIT_MessageBox::question3( QWidget* parent, + const QString& caption, + const QString& text, + const QString& textButton0, + const QString& textButton1, + const QString& textButton2, + int idButton0, int idButton1, + int idButton2, int idDefault ) +{ + SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::arrowCursor ); + + if ( idDefault == idButton0 ) + idDefault = 0; + else if ( idDefault == idButton1 ) + idDefault = 1; + else if ( idDefault == idButton2 ) + idDefault = 2; + else + idDefault = 0; + + int ret = QMessageBox::question( parent, caption, text, textButton0, + textButton1, textButton2, idDefault ); + qApp->processEvents(); + switch ( ret ) + { + case 0: + return idButton0; + case 1: + return idButton1; + case 2: + return idButton2; + } + return -1; +} diff --git a/src/SUIT/SUIT_MessageBox.h b/src/SUIT/SUIT_MessageBox.h new file mode 100755 index 000000000..f8cf626be --- /dev/null +++ b/src/SUIT/SUIT_MessageBox.h @@ -0,0 +1,92 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +/******************************************************************** +** Class: SUIT_MessageBox +** Descr: Message dialog box for SUIT-based application +** Module: SUIT +** Created: UI team, 02.10.00 +*********************************************************************/ +#ifndef SUIT_MESSAGEBOX_H +#define SUIT_MESSAGEBOX_H + +#include "SUIT.h" + +#include +#include + +#define SUIT_OK 1 +#define SUIT_CANCEL 2 +#define SUIT_YES 3 +#define SUIT_NO 4 +#define SUIT_HELP 5 + +class SUIT_EXPORT SUIT_MessageBox +{ +public: + + /** @name One button message boxes.*/ + //@{ + static int info1 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0 ); + static int warn1 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0 ); + static int error1 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0 ); + static int question1 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0 ); + //@} + + /** @name Two buttons message boxes.*/ + //@{ + static int info2 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + int idButton0, int idButton1, int idDefault ); + static int warn2 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + int idButton0, int idButton1, int idDefault ); + static int error2 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + int idButton0, int idButton1, int idDefault ); + static int question2 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + int idButton0, int idButton1, int idDefault ); + //@} + + /** @name Three buttons message boxes.*/ + //@{ + static int info3 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + const QString& textButton2, int idButton0, int idButton1, + int idButton2, int idDefault ); + static int warn3 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + const QString& textButton2, int idButton0, int idButton1, + int idButton2, int idDefault ); + static int error3 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + const QString& textButton2, int idButton0, int idButton1, + int idButton2, int idDefault ); + static int question3 ( QWidget* parent, const QString& caption, const QString& text, + const QString& textButton0, const QString& textButton1, + const QString& textButton2, int idButton0, int idButton1, + int idButton2, int idDefault ); + //@} +}; + +#endif diff --git a/src/SUIT/SUIT_SelectionMgr.cxx b/src/SUIT/SUIT_SelectionMgr.cxx new file mode 100755 index 000000000..98a33e83a --- /dev/null +++ b/src/SUIT/SUIT_SelectionMgr.cxx @@ -0,0 +1,329 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "SUIT_SelectionMgr.h" + +/*!\class SUIT_SelectionMgr + * Provide selection manager. Manipulate by selection filters, modes, data owners. + */ + +/*!constructor. initialize myIterations and myIsSelChangeEnabled.*/ +SUIT_SelectionMgr::SUIT_SelectionMgr( const bool Feedback, QObject* p ) +: QObject( p ), +myIterations( Feedback ? 1 : 0 ), +myIsSelChangeEnabled( true ) +{ +} + +/*!destructor. mySelectors auto delete.*/ +SUIT_SelectionMgr::~SUIT_SelectionMgr() +{ + mySelectors.setAutoDelete( true ); +} + +/*!Add selector \a sel to selectors list,if it's not exists in list.*/ +void SUIT_SelectionMgr::installSelector( SUIT_Selector* sel ) +{ + if ( sel && !mySelectors.contains( sel ) ) + mySelectors.append( sel ); +} + +/*!Remove selector \a sel from list.*/ +void SUIT_SelectionMgr::removeSelector( SUIT_Selector* sel ) +{ + mySelectors.remove( sel ); +} + +/*!Gets selectors list to \a lst.*/ +void SUIT_SelectionMgr::selectors( QPtrList& lst ) const +{ + lst.clear(); + for ( SelectorListIterator it( mySelectors ); it.current(); ++it ) + lst.append( it.current() ); +} + +/*!Gets selectors list to \a lst with type \a typ.*/ +void SUIT_SelectionMgr::selectors( const QString& typ, QPtrList& lst ) const +{ + lst.clear(); + for ( SelectorListIterator it( mySelectors ); it.current(); ++it ) + { + if ( it.current()->type() == typ ) + lst.append( it.current() ); + } +} + +/*! Sets ebabled to \a on for all data owners with type \a typ. +*/ +void SUIT_SelectionMgr::setEnabled( const bool on, const QString& typ ) +{ + for ( SelectorListIterator it( mySelectors ); it.current(); ++it ) + { + if ( typ.isEmpty() || it.current()->type() == typ ) + it.current()->setEnabled( on ); + } +} + +/*! Gets selected data owners from list with type \a type to list \a lst. +*/ +void SUIT_SelectionMgr::selected( SUIT_DataOwnerPtrList& lst, const QString& type ) const +{ + lst.clear(); + + for ( SelectorListIterator it( mySelectors ); it.current(); ++it ) + { + if ( !type.isEmpty() && it.current()->type() != type ) + continue; + SUIT_DataOwnerPtrList curList; + it.current()->selected( curList ); + for ( SUIT_DataOwnerPtrList::const_iterator itr = curList.begin(); itr != curList.end(); ++itr ) + lst.append( *itr ); + } +} + +/*! Sets selected data owners from \a lst and append to list, if \a append - true. +*/ +void SUIT_SelectionMgr::setSelected( const SUIT_DataOwnerPtrList& lst, const bool append ) +{ + SUIT_DataOwnerPtrList owners; + filterOwners( lst, owners ); + + for ( SelectorListIterator it( mySelectors ); it.current(); ++it ) + { + if ( append ) + { + SUIT_DataOwnerPtrList current; + it.current()->selected( current ); + for ( SUIT_DataOwnerPtrList::const_iterator it = current.begin(); it != current.end(); ++it ) + owners.append( *it ); + } + it.current()->setSelected( owners ); + } +} + +/*! Clear selected data owners. +*/ +void SUIT_SelectionMgr::clearSelected() +{ + setSelected( SUIT_DataOwnerPtrList() ); +} + +/*! On selection \a sel changed. +*/ +void SUIT_SelectionMgr::selectionChanged( SUIT_Selector* sel ) +{ + if ( !sel || !myIsSelChangeEnabled || !sel->isEnabled() ) + return; + + SUIT_DataOwnerPtrList owners; + + myIsSelChangeEnabled = false; + sel->selected( owners ); + + SUIT_DataOwnerPtrList newOwners; + filterOwners( owners, newOwners ); + + for ( int i = 0; i < myIterations; i++ ) + { + for ( SUIT_Selector* aSel = mySelectors.first(); aSel; aSel = mySelectors.next() ) + { + // Temporary action(to avoid selection of the objects which don't pass the filters): + //if ( aSel != sel ) + aSel->setSelected( newOwners ); + } + } + myIsSelChangeEnabled = true; + + emit selectionChanged(); +} + +/*! + Returns true if selection manger is in synchronising mode + (during synchonisation of the selectors selection). +*/ +bool SUIT_SelectionMgr::isSynchronizing() const +{ + return !myIsSelChangeEnabled; +} + +/*! Checks: Is selection manager has selection mode \a mode? +*/ +bool SUIT_SelectionMgr::hasSelectionMode( const int mode ) const +{ + return mySelModes.contains( mode ); +} + +/*! Gets selection modes to list \a vals. +*/ +void SUIT_SelectionMgr::selectionModes( QValueList& vals ) const +{ + vals = mySelModes; +} + +/*! Set selection mode \a mode to list of selection modes. +*/ +void SUIT_SelectionMgr::setSelectionModes( const int mode ) +{ + QValueList lst; + lst.append( mode ); + setSelectionModes( lst ); +} + +/*! Sets selection modes list from \a lst. +*/ +void SUIT_SelectionMgr::setSelectionModes( const QValueList& lst ) +{ + mySelModes = lst; +} + +/*! Append selection mode \a mode to list of selection modes. +*/ +void SUIT_SelectionMgr::appendSelectionModes( const int mode ) +{ + QValueList lst; + lst.append( mode ); + appendSelectionModes( lst ); +} + +/*! Append selection modes \a lst list. +*/ +void SUIT_SelectionMgr::appendSelectionModes( const QValueList& lst ) +{ + QMap map; + for ( QValueList::const_iterator it = mySelModes.begin(); it != mySelModes.end(); ++it ) + map.insert( *it, 0 ); + + for ( QValueList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) + { + if ( !map.contains( *itr ) ) + mySelModes.append( *itr ); + } +} + +/*! Remove selection mode \a mode from list. +*/ +void SUIT_SelectionMgr::removeSelectionModes( const int mode ) +{ + QValueList lst; + lst.append( mode ); + removeSelectionModes( lst ); +} + +/*! Remove selection modea \a lst from list. +*/ +void SUIT_SelectionMgr::removeSelectionModes( const QValueList& lst ) +{ + QMap map; + for ( QValueList::const_iterator it = mySelModes.begin(); it != mySelModes.end(); ++it ) + map.insert( *it, 0 ); + + for ( QValueList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) + map.remove( *itr ); + + mySelModes.clear(); + for ( QMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter ) + mySelModes.append( iter.key() ); +} + +/*! Checks data owner is ok? +*/ +bool SUIT_SelectionMgr::isOk( const SUIT_DataOwner* owner ) const +{ + if ( !owner ) + return false; + + bool ok = true; + for ( SelFilterListIterator it( myFilters ); it.current() && ok; ++it ) + ok = it.current()->isOk( owner ); + + return ok; +} + +/*! Checks data owner pointer is ok? +*/ +bool SUIT_SelectionMgr::isOk( const SUIT_DataOwnerPtr& ptr ) const +{ + if ( ptr.isNull() ) + return false; + + return isOk( ptr.operator->() ); +} + +/*! Checks selection manager has filter \a f? +*/ +bool SUIT_SelectionMgr::hasFilter( SUIT_SelectionFilter* f ) const +{ + return myFilters.contains( f ); +} + +/*! Install filter \a f and set selected, if \a update = true. +*/ +void SUIT_SelectionMgr::installFilter( SUIT_SelectionFilter* f, const bool updateSelection ) +{ + if ( !hasFilter( f ) ) + { + SUIT_DataOwnerPtrList selOwners; + if( updateSelection ) + selected( selOwners ); + + myFilters.append( f ); + + if( updateSelection ) + setSelected( selOwners ); + } +} + +/*! Remove filter \a f from filters list. +*/ +void SUIT_SelectionMgr::removeFilter( SUIT_SelectionFilter* f ) +{ + myFilters.remove( f ); +} + +/*! Clear filters list. +*/ +void SUIT_SelectionMgr::clearFilters() +{ + myFilters.clear(); +} + +/*! Sets auto delete filter. +*/ +bool SUIT_SelectionMgr::autoDeleteFilter() const +{ + return myFilters.autoDelete(); +} + +/*! Sets auto delete filter to \a on. +*/ +void SUIT_SelectionMgr::setAutoDeleteFilter( const bool on ) +{ + myFilters.setAutoDelete( on ); +} + +/*! Gets good data owners list to \a out from \a in. +*/ +void SUIT_SelectionMgr::filterOwners( const SUIT_DataOwnerPtrList& in, SUIT_DataOwnerPtrList& out ) const +{ + out.clear(); + for ( SUIT_DataOwnerPtrList::const_iterator it = in.begin(); it != in.end(); ++it ) + { + if ( isOk( *it ) ) + out.append( *it ); + } +} diff --git a/src/SUIT/SUIT_SelectionMgr.h b/src/SUIT/SUIT_SelectionMgr.h new file mode 100755 index 000000000..d471b2f73 --- /dev/null +++ b/src/SUIT/SUIT_SelectionMgr.h @@ -0,0 +1,114 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef SUIT_SELECTIONMGR_H +#define SUIT_SELECTIONMGR_H + +#include "SUIT_Selector.h" +#include "SUIT_DataOwner.h" +#include "SUIT_SelectionFilter.h" + +#include +#include +#include + +#ifdef WIN32 +#pragma warning ( disable : 4251 ) +#endif + +class SUIT_EXPORT SUIT_SelectionMgr : public QObject +{ + Q_OBJECT + +public: + SUIT_SelectionMgr( const bool = true, QObject* = 0 ); + virtual ~SUIT_SelectionMgr(); + + void clearSelected(); + virtual void selected( SUIT_DataOwnerPtrList&, const QString& = QString::null ) const; + virtual void setSelected( const SUIT_DataOwnerPtrList&, const bool = false ); + + void selectors( QPtrList& ) const; + void selectors( const QString&, QPtrList& ) const; + + + void setEnabled( const bool, const QString& = QString::null ); + + + bool hasSelectionMode( const int ) const; + void selectionModes( QValueList& ) const; + + void setSelectionModes( const int ); + virtual void setSelectionModes( const QValueList& ); + + void appendSelectionModes( const int ); + virtual void appendSelectionModes( const QValueList& ); + + void removeSelectionModes( const int ); + virtual void removeSelectionModes( const QValueList& ); + + + bool isOk( const SUIT_DataOwner* ) const; + bool isOk( const SUIT_DataOwnerPtr& ) const; + + bool hasFilter( SUIT_SelectionFilter* ) const; + + virtual void installFilter( SUIT_SelectionFilter*, const bool = true ); + virtual void removeFilter( SUIT_SelectionFilter* ); + virtual void clearFilters(); + + bool autoDeleteFilter() const; + void setAutoDeleteFilter( const bool ); + + bool isSynchronizing() const; + +signals: + void selectionChanged(); + +protected: + virtual void selectionChanged( SUIT_Selector* ); + + typedef QPtrListIterator SelectorListIterator; + + virtual void installSelector( SUIT_Selector* ); + virtual void removeSelector( SUIT_Selector* ); + +private: + void filterOwners( const SUIT_DataOwnerPtrList&, SUIT_DataOwnerPtrList& ) const; + + typedef QPtrList SelectorList; + typedef QPtrList SelFilterList; + typedef QPtrListIterator SelFilterListIterator; + +protected: + SelectorList mySelectors; + +private: + SelFilterList myFilters; + QValueList mySelModes; + int myIterations; + bool myIsSelChangeEnabled; + + friend class SUIT_Selector; +}; + +#ifdef WIN32 +#pragma warning ( default : 4251 ) +#endif + +#endif diff --git a/src/SUIT/SUIT_ViewWindow.cxx b/src/SUIT/SUIT_ViewWindow.cxx new file mode 100755 index 000000000..bd4c32e69 --- /dev/null +++ b/src/SUIT/SUIT_ViewWindow.cxx @@ -0,0 +1,160 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// SUIT_ViewWindow.cxx: implementation of the SUIT_ViewWindow class. +// +////////////////////////////////////////////////////////////////////// + +#include "SUIT_ViewWindow.h" +#include "SUIT_Desktop.h" +#include "SUIT_Application.h" +#include "SUIT_Study.h" +#include "SUIT_ViewManager.h" +#include "SUIT_Tools.h" +#include "SUIT_MessageBox.h" +#include +#include +#include +#include + +/*!\class SUIT_ViewWindow + * Class provide view window. + */ + +/*! Dump view custom event*/ +const int DUMP_EVENT = QEvent::User + 123; + +/*! Constructor.*/ +SUIT_ViewWindow::SUIT_ViewWindow(SUIT_Desktop* theDesktop) +: QMainWindow( theDesktop, "SUIT_ViewWindow", Qt::WDestructiveClose ) +{ + myDesktop = theDesktop; + + if ( myDesktop->icon() ) + setIcon( *myDesktop->icon() ); +} + +/*! Destructor.*/ +SUIT_ViewWindow::~SUIT_ViewWindow() +{ +} + +void SUIT_ViewWindow::setViewManager( SUIT_ViewManager* theManager ) +{ + myManager = theManager; +} + +SUIT_ViewManager* SUIT_ViewWindow::getViewManager() const +{ + return myManager; +} + +QImage SUIT_ViewWindow::dumpView() +{ + return QImage(); +} + +bool SUIT_ViewWindow::dumpViewToFormat( const QString& fileName, const QString& format ) +{ + QImage img = dumpView(); + if( img.isNull() ) + return false; + + QString fmt = format; + if( fmt.isEmpty() ) + fmt = QString( "BMP" ); // default format + else if( fmt == "JPG" ) + fmt = "JPEG"; + + QApplication::setOverrideCursor( Qt::waitCursor ); + bool res = img.save( fileName, fmt.latin1() ); + QApplication::restoreOverrideCursor(); + return res; +} + +/*! Close event \a theEvent. +*/ +void SUIT_ViewWindow::closeEvent(QCloseEvent* theEvent) +{ + QMainWindow::closeEvent( theEvent ); + emit closing( this ); +} + +/*! Context menu requested for event \a e. +*/ +void SUIT_ViewWindow::contextMenuEvent ( QContextMenuEvent * e ) +{ + if ( e->reason() != QContextMenuEvent::Mouse ) + emit contextMenuRequested( e ); +} + +/*! Post events on dump view. +*/ +void SUIT_ViewWindow::onDumpView() +{ + qApp->postEvent( this, new QPaintEvent( QRect( 0, 0, width(), height() ), TRUE ) ); + qApp->postEvent( this, new QCustomEvent( DUMP_EVENT ) ); +} + +QString SUIT_ViewWindow::filter() const +{ + return tr( "TLT_IMAGE_FILES" ); +} + +/*! Reaction view window on event \a e. +*/ +bool SUIT_ViewWindow::event( QEvent* e ) +{ + if ( e->type() == DUMP_EVENT ) + { + bool bOk = false; + if ( myManager && myManager->study() && myManager->study()->application() ) + { + // get file name + SUIT_Application* app = myManager->study()->application(); + QString fileName = app->getFileName( false, QString::null, filter(), tr( "TLT_DUMP_VIEW" ), 0 ); + if( !fileName.isEmpty() ) + { + QString fmt = SUIT_Tools::extension( fileName ).upper(); + bOk = dumpViewToFormat( fileName, fmt ); + } + else + { + bOk = true; // cancelled + } + } + if ( !bOk ) { + SUIT_MessageBox::error1( this, tr( "ERROR" ), tr( "ERR_CANT_DUMP_VIEW" ), tr( "BUT_OK" ) ); + } + return TRUE; + } + return QMainWindow::event( e ); +} + +/*! Called by SUIT_Accel::onActivated() when a key accelerator was activated and this window was active +*/ +void SUIT_ViewWindow::onAccelAction( int _action ) +{ + action( _action ); +} + +/*! action handle standard action (zoom, pan) or custom action. to be redefined in successors. +*/ +void SUIT_ViewWindow::action( const int ) +{ +} diff --git a/src/SUIT/SUIT_ViewWindow.h b/src/SUIT/SUIT_ViewWindow.h new file mode 100755 index 000000000..1ac79a504 --- /dev/null +++ b/src/SUIT/SUIT_ViewWindow.h @@ -0,0 +1,79 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +// SUIT_ViewWindow.h: interface for the SUIT_ViewWindow class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_SUIT_VIEWWINDOW_H__82C3D51A_6F10_45B0_BCFE_3CB3EF596A4D__INCLUDED_) +#define AFX_SUIT_VIEWWINDOW_H__82C3D51A_6F10_45B0_BCFE_3CB3EF596A4D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "SUIT.h" + +#include + +class SUIT_Desktop; +class SUIT_ViewManager; +class QImage; + +class SUIT_EXPORT SUIT_ViewWindow: public QMainWindow +{ + Q_OBJECT +public: + SUIT_ViewWindow( SUIT_Desktop* ); + virtual ~SUIT_ViewWindow(); + + void setViewManager( SUIT_ViewManager* ); + SUIT_ViewManager* getViewManager() const; + + bool event(QEvent*); + + virtual QImage dumpView(); + virtual bool dumpViewToFormat( const QString& fileName, const QString& format ); + + void onAccelAction( int ); + +public slots: + virtual void onDumpView(); + +signals: + void closing( SUIT_ViewWindow* ); + void mousePressed( SUIT_ViewWindow*, QMouseEvent* ); + void mouseReleased( SUIT_ViewWindow*, QMouseEvent* ); + void mouseDoubleClicked( SUIT_ViewWindow*, QMouseEvent* ); + void mouseMoving( SUIT_ViewWindow*, QMouseEvent* ); + void wheeling( SUIT_ViewWindow*, QWheelEvent* ); + void keyPressed( SUIT_ViewWindow*, QKeyEvent* ); + void keyReleased( SUIT_ViewWindow*, QKeyEvent* ); + void contextMenuRequested( QContextMenuEvent *e ); + +protected: + void closeEvent( QCloseEvent* ); + virtual void contextMenuEvent( QContextMenuEvent* ); + virtual QString filter() const; + virtual void action( const int ); + + SUIT_Desktop* myDesktop; + SUIT_ViewManager* myManager; +}; + +#endif // !defined(AFX_SUIT_VIEWWINDOW_H__82C3D51A_6F10_45B0_BCFE_3CB3EF596A4D__INCLUDED_) diff --git a/src/SUITApp/SUITApp.cxx b/src/SUITApp/SUITApp.cxx new file mode 100644 index 000000000..497906700 --- /dev/null +++ b/src/SUITApp/SUITApp.cxx @@ -0,0 +1,174 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#if defined WNT + +#undef SUIT_ENABLE_PYTHON +//#else +//#include "SUITconfig.h" +#endif + +#include "SUITApp_Application.h" + +#include +#include +#include + + +#ifdef SUIT_ENABLE_PYTHON +#include +#endif + +#include +#include +#include +#include + +#include + +QString salomeVersion() +{ + QString path( ::getenv( "GUI_ROOT_DIR" ) ); + if ( !path.isEmpty() ) + path += QDir::separator(); + + path += QString( "bin/salome/VERSION" ); + + QFile vf( path ); + if ( !vf.open( IO_ReadOnly ) ) + return QString::null; + + QString line; + vf.readLine( line, 1024 ); + vf.close(); + + if ( line.isEmpty() ) + return QString::null; + + while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) ) + line.remove( line.length() - 1, 1 ); + + QString ver; + int idx = line.findRev( ":" ); + if ( idx != -1 ) + ver = line.mid( idx + 1 ).stripWhiteSpace(); + + return ver; +} + + +/* XPM */ +static const char* pixmap_not_found_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #A80000", +" ", +" ", +" . . ", +" .+. .+. ", +" .+++. .+++. ", +" .+++.+++. ", +" .+++++. ", +" .+++. ", +" .+++++. ", +" .+++.+++. ", +" .+++. .+++. ", +" .+. .+. ", +" . . ", +" ", +" ", +" "}; + +class SUITApp_Session: public SUIT_Session +{ +public: + SUITApp_Session( bool theIniFormat ) : SUIT_Session(), myIniFormat ( theIniFormat ) {} + virtual ~SUITApp_Session() {} + +protected: + virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + { + SUIT_ResourceMgr* resMgr = 0; + if ( myIniFormat ) + { + resMgr = new SUIT_ResourceMgr( appName ); + resMgr->setCurrentFormat( "ini" ); + } + else + { + resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) ); + resMgr->setVersion( salomeVersion() ); + resMgr->setCurrentFormat( "xml" ); + } + + if ( resMgr ) + { + static QPixmap defaultPixmap( pixmap_not_found_xpm ); + resMgr->setDefaultPixmap( defaultPixmap ); + resMgr->setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); + } + return resMgr; + } + +private: + bool myIniFormat; +}; + +int main( int args, char* argv[] ) +{ +#ifdef SUIT_ENABLE_PYTHON + Py_Initialize(); + PySys_SetArgv( args, argv ); +#endif + + QStringList argList; + bool noExceptHandling = false; + bool iniFormat = false; + for ( int i = 1; i < args /*&& !noExceptHandling*/; i++ ) + { + if ( !strcmp( argv[i], "/noexcepthandling" ) ) + noExceptHandling = true; + else if ( !strcmp( argv[i], "--format=ini") ) + iniFormat = true; + else + argList.append( QString( argv[i] ) ); + } + + SUITApp_Application app( args, argv ); + + int result = -1; + if ( !argList.isEmpty() ) + { + SUITApp_Session* aSession = new SUITApp_Session( iniFormat ); + SUIT_Application* theApp = aSession->startApplication( argList.first() ); + if ( theApp ) + { + if ( !noExceptHandling ) + app.setHandler( aSession->handler() ); + +// if ( !app.mainWidget() ) +// app.setMainWidget( theApp->desktop() ); + + result = app.exec(); + } + delete aSession; + } + + return result; +} diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx new file mode 100644 index 000000000..690b13b52 --- /dev/null +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -0,0 +1,833 @@ +// File: SalomeApp_Application.cxx +// Created: 10/22/2004 3:23:45 PM +// Author: Sergey LITONIN +// Copyright (C) CEA 2004 + +#include "SalomeApp_PyInterp.h" // WARNING! This include must be the first! + +#include "SalomeApp_Application.h" + +#include "SalomeApp_Study.h" +#include "SalomeApp_DataModel.h" +#include "SalomeApp_DataObject.h" +#include "SalomeApp_EventFilter.h" + +#include "SalomeApp_StudyPropertiesDlg.h" + +#include "SalomeApp_CheckFileDlg.h" + +#include "LightApp_Application.h" +#include "LightApp_Preferences.h" +#include "LightApp_WidgetContainer.h" +#include "LightApp_SelectionMgr.h" + +#include "STD_LoadStudiesDlg.h" + +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "SALOMEDS_StudyManager.hxx" +#include "SALOMEDS_SObject.hxx" + +#include "SALOME_ListIteratorOfListIO.hxx" +#include "SALOME_ListIO.hxx" + +#include "ToolsGUI_CatalogGeneratorDlg.h" +#include "ToolsGUI_RegWidget.h" + +/*!Create new instance of SalomeApp_Application.*/ +extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication() +{ + return new SalomeApp_Application(); +} + +/* + Class : SalomeApp_Application + Description : Application containing SalomeApp module or LightApp module +*/ + +/*!Constructor.*/ +SalomeApp_Application::SalomeApp_Application() +: LightApp_Application() +{ +} + +/*!Destructor. + *\li Destroy event filter. + */ +SalomeApp_Application::~SalomeApp_Application() +{ + // Do not destroy. It's a singleton ! + //SalomeApp_EventFilter::Destroy(); +} + +/*!Start application.*/ +void SalomeApp_Application::start() +{ + LightApp_Application::start(); + + SalomeApp_EventFilter::Init(); +} + +/*!Create actions:*/ +void SalomeApp_Application::createActions() +{ + LightApp_Application::createActions(); + + SUIT_Desktop* desk = desktop(); + + //! Dump study + createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIconSet(), + tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ), + CTRL+Key_D, desk, false, this, SLOT( onDumpStudy() ) ); + + //! Load script + createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIconSet(), + tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ), + CTRL+Key_T, desk, false, this, SLOT( onLoadScript() ) ); + + //! Properties + createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIconSet(), + tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ), + CTRL+Key_P, desk, false, this, SLOT( onProperties() ) ); + + //! Catalog Generator + createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIconSet(), + tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ), + SHIFT+Key_G, desk, false, this, SLOT( onCatalogGen() ) ); + + //! Registry Display + createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIconSet(), + tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ), + SHIFT+Key_D, desk, false, this, SLOT( onRegDisplay() ) ); + + int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 ); + + createMenu( DumpStudyId, fileMenu, 10, -1 ); + createMenu( separator(), fileMenu, -1, 15, -1 ); + createMenu( LoadScriptId, fileMenu, 10, -1 ); + createMenu( separator(), fileMenu, -1, 15, -1 ); + createMenu( PropertiesId, fileMenu, 10, -1 ); + createMenu( separator(), fileMenu, -1, 15, -1 ); + + int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, -1, 50 ); + createMenu( CatalogGenId, toolsMenu, 10, -1 ); + createMenu( RegDisplayId, toolsMenu, 10, -1 ); + createMenu( separator(), toolsMenu, -1, 15, -1 ); +} + +/*! Purpose : SLOT. Open new document with \a aName.*/ +bool SalomeApp_Application::onOpenDoc( const QString& aName ) +{ + bool res = false, toOpen = true, isAlreadyOpen = false; + + // Look among opened studies + if (activeStudy()) { // at least one study is opened + SUIT_Session* aSession = SUIT_Session::session(); + QPtrList aAppList = aSession->applications(); + QPtrListIterator it (aAppList); + SUIT_Application* aApp = 0; + // iterate on all applications + for (; (aApp = it.current()) && !isAlreadyOpen; ++it) { + if (aApp->activeStudy()->studyName() == aName) { + isAlreadyOpen = true; // Already opened, ask user what to do + + // The document ... is already open. + // Do you want to reload it? + int aAnswer = SUIT_MessageBox::warn2(desktop(), tr("WRN_WARNING"), + tr("QUE_DOC_ALREADYOPEN").arg(aName), + tr("BUT_YES"), tr("BUT_NO"), 1, 2, 2); + if (aAnswer == 1) { // reload + if (activeStudy()->studyName() == aName && aAppList.count() > 1) { + // Opened in THIS (active) application. + STD_Application* app1 = (STD_Application*)aAppList.at(0); + STD_Application* app2 = (STD_Application*)aAppList.at(1); + if (!app1 || !app2) { + // Error + return false; + } + if (app1->activeStudy()->studyName() == aName) { + // app1 is this application, we need another one + app1 = app2; + } + // Close document of this application. This application will be destroyed. + onCloseDoc(/*ask = */false); + // Open the file with another application, as this one will be destroyed. + return app1->onOpenDoc(aName); + } else { + // Opened in another application. + STD_Application* app = (STD_Application*)aApp; + if (app) + app->onCloseDoc(/*ask = */false); + } + } else { // do not reload + // OK, the study will not be reloaded, but we call + // CAM_Application::onOpenDoc( aName ) all the same. + // It will activate a desktop of the study . + } + } + } + } + + // Look among unloaded studies + if (!isAlreadyOpen) { + std::vector List = studyMgr()->GetOpenStudies(); + + QString studyName; + for (unsigned int ind = 0; ind < List.size() && !isAlreadyOpen; ind++) { + studyName = List[ind].c_str(); + if (aName == studyName) { + // Already exists unloaded, ask user what to do + isAlreadyOpen = true; + + // The document ... already exists in the study manager. + // Do you want to reload it? + int aAnswer = SUIT_MessageBox::warn2(desktop(), tr("WRN_WARNING"), + tr("QUE_DOC_ALREADYEXIST").arg(aName), + tr("BUT_YES"), tr("BUT_NO"), 1, 2, 2); + if (aAnswer == 1) { + _PTR(Study) aStudy = studyMgr()->GetStudyByName(aName.latin1()); + if (aStudy) + studyMgr()->Close(aStudy); + } else { + toOpen = false; + } + } + } + } + + if (toOpen) + res = CAM_Application::onOpenDoc( aName ); + + QAction* a = action( MRUId ); + if ( a && a->inherits( "QtxMRUAction" ) ) + { + QtxMRUAction* mru = (QtxMRUAction*)a; + if ( res ) + mru->insert( aName ); + else + mru->remove( aName ); + } + return res; +} + +/*!SLOT. Load document.*/ +void SalomeApp_Application::onLoadDoc() +{ + QString name, studyname, ext; + + STD_LoadStudiesDlg aDlg( desktop(), TRUE); + + std::vector List = studyMgr()->GetOpenStudies(); + + SUIT_Session* aSession = SUIT_Session::session(); + QPtrList aAppList = aSession->applications(); + SUIT_Application* aApp = 0; + + for (unsigned int ind = 0; ind < List.size(); ind++) { + studyname = List[ind].c_str(); + //Add to list only unloaded studies + bool isAlreadyOpen = false; + for ( QPtrListIterator it( aAppList ); it.current() && !isAlreadyOpen; ++it ) + { + aApp = it.current(); + if(!aApp || !aApp->activeStudy()) continue; + if ( aApp->activeStudy()->studyName() == studyname ) isAlreadyOpen = true; + } + + if ( !isAlreadyOpen ) aDlg.ListComponent->insertItem( studyname ); + } + + int retVal = aDlg.exec(); + studyname = aDlg.ListComponent->currentText(); + + if (retVal == QDialog::Rejected) + return; + + if ( studyname.isNull() || studyname.isEmpty() ) + return; + + name = studyname; + name.replace( QRegExp(":"), "/" ); + + if( LightApp_Application::onLoadDoc( name ) ) + { + updateWindows(); + updateViewManagers(); + updateObjectBrowser(true); + } +} + + +/*!SLOT. Load document with \a aName.*/ +bool SalomeApp_Application::onLoadDoc( const QString& aName ) +{ + return LightApp_Application::onLoadDoc( aName ); +} + +/*!SLOT. Copy objects to study maneger from selection maneger..*/ +void SalomeApp_Application::onCopy() +{ + SALOME_ListIO list; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects(list); + + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if(study == NULL) return; + + _PTR(Study) stdDS = study->studyDS(); + if(!stdDS) return; + + SALOME_ListIteratorOfListIO it( list ); + if(it.More()) + { + _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); + try { + studyMgr()->Copy(so); + onSelectionChanged(); + } + catch(...) { + } + } +} + +/*!SLOT. Paste objects to study maneger from selection manager.*/ +void SalomeApp_Application::onPaste() +{ + SALOME_ListIO list; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects(list); + + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if(study == NULL) return; + + _PTR(Study) stdDS = study->studyDS(); + if(!stdDS) return; + + SALOME_ListIteratorOfListIO it( list ); + if(it.More()) + { + _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); + try { + studyMgr()->Paste(so); + updateObjectBrowser( true ); + updateActions(); //SRN: BugID IPAL9377, case 3 + } + catch(...) { + } + } +} + +/*!Sets enable or disable some actions on selection changed.*/ +void SalomeApp_Application::onSelectionChanged() +{ + SALOME_ListIO list; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects(list); + + bool canCopy = false; + bool canPaste = false; + + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if (study != NULL) { + _PTR(Study) stdDS = study->studyDS(); + + if (stdDS) { + SALOME_ListIteratorOfListIO it ( list ); + + if (it.More() && list.Extent() == 1) { + _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); + + if ( so ) { + SALOMEDS_SObject* aSO = dynamic_cast(so.get()); + + if ( aSO ) { + canCopy = studyMgr()->CanCopy(so); + canPaste = studyMgr()->CanPaste(so); + } + } + } + } + } + + action(EditCopyId)->setEnabled(canCopy); + action(EditPasteId)->setEnabled(canPaste); +} + +/*!Delete references.*/ +void SalomeApp_Application::onDeleteInvalidReferences() +{ + SALOME_ListIO aList; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects( aList, QString::null, false ); + + if( aList.IsEmpty() ) + return; + + SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); + _PTR(Study) aStudyDS = aStudy->studyDS(); + _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder(); + _PTR(SObject) anObj; + + for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() ) + if ( it.Value()->hasEntry() ) + { + _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; + while( aRefObj && aRefObj->ReferencedObject( anObj ) ) + aRefObj = anObj; + + if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) + aStudyBuilder->RemoveReference( aSObject ); + } + updateObjectBrowser(); +} + +/*!Private SLOT. */ +void SalomeApp_Application::onOpenWith() +{ + QApplication::setOverrideCursor( Qt::waitCursor ); + SALOME_ListIO aList; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects(aList); + if (aList.Extent() != 1) + { + QApplication::restoreOverrideCursor(); + return; + } + Handle(SALOME_InteractiveObject) aIObj = aList.First(); + QString aModuleName(aIObj->getComponentDataType()); + QString aModuleTitle = moduleTitle(aModuleName); + activateModule(aModuleTitle); + QApplication::restoreOverrideCursor(); +} + +//======================================================================= +// name : createNewStudy +/*! Purpose : Create new study*/ +//======================================================================= +SUIT_Study* SalomeApp_Application::createNewStudy() +{ + SalomeApp_Study* aStudy = new SalomeApp_Study( this ); + + // Set up processing of major study-related events + connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) ); + connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) ); + + return aStudy; +} + +//======================================================================= +// name : updateCommandsStatus +/*! Purpose : Enable/Disable menu items and toolbar buttons. Rebuild menu*/ +//======================================================================= +void SalomeApp_Application::updateCommandsStatus() +{ + LightApp_Application::updateCommandsStatus(); + + // Dump study menu + QAction* a = action( DumpStudyId ); + if ( a ) + a->setEnabled( activeStudy() ); + + // Load script menu + a = action( LoadScriptId ); + if ( a ) + a->setEnabled( activeStudy() ); + + a = action( PropertiesId ); + if( a ) + a->setEnabled( activeStudy() ); + + // update state of Copy/Paste menu items + onSelectionChanged(); +} + +/*!Private SLOT. On dump study.*/ +void SalomeApp_Application::onDumpStudy( ) +{ + SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); + if ( !appStudy ) return; + _PTR(Study) aStudy = appStudy->studyDS(); + + QStringList aFilters; + aFilters.append( tr( "PYTHON_FILES_FILTER" ) ); + + SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg( desktop(), false, tr("PUBLISH_IN_STUDY"), true, true); + fd->setCaption( tr( "TOT_DESK_FILE_DUMP_STUDY" ) ); + fd->setFilters( aFilters ); + fd->SetChecked(true); + fd->exec(); + QString aFileName = fd->selectedFile(); + bool toPublish = fd->IsChecked(); + delete fd; + + if(!aFileName.isEmpty()) { + QFileInfo aFileInfo(aFileName); + bool res = aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish ); + if ( !res ) + SUIT_MessageBox::warn1 ( desktop(), + QObject::tr("WRN_WARNING"), + tr("WRN_DUMP_STUDY_FAILED"), + QObject::tr("BUT_OK") ); + } +} + +/*!Private SLOT. On load script.*/ +void SalomeApp_Application::onLoadScript( ) +{ + SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); + if ( !appStudy ) return; + _PTR(Study) aStudy = appStudy->studyDS(); + + if ( aStudy->GetProperties()->IsLocked() ) { + SUIT_MessageBox::warn1 ( desktop(), + QObject::tr("WRN_WARNING"), + QObject::tr("WRN_STUDY_LOCKED"), + QObject::tr("BUT_OK") ); + return; + } + + QStringList filtersList; + filtersList.append(tr("PYTHON_FILES_FILTER")); + filtersList.append(tr("ALL_FILES_FILTER")); + + QString aFile = SUIT_FileDlg::getFileName( desktop(), "", filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true ); + + if ( !aFile.isEmpty() ) + { + QString command = QString("execfile(\"%1\")").arg(aFile); + + PythonConsole* pyConsole = pythonConsole(); + + if ( pyConsole ) + pyConsole->exec( command ); + } +} + +/*!Gets file filter. + *\retval QString "(*.hdf)" + */ +QString SalomeApp_Application::getFileFilter() const +{ + return "(*.hdf)"; +} + +/*!Create window.*/ +QWidget* SalomeApp_Application::createWindow( const int flag ) +{ + QWidget* wid = 0; + if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag); + + SUIT_ResourceMgr* resMgr = resourceMgr(); + + if ( flag == WT_ObjectBrowser ) + { + OB_Browser* ob = (OB_Browser*)wid; + connect( ob->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( onDblClick( QListViewItem* ) ) ); + bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false ), + autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true ); + for ( int i = SalomeApp_DataObject::CT_Value; i <= SalomeApp_DataObject::CT_RefEntry; i++ ) + { + ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i ); + ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser", + QString().sprintf( "visibility_column_%d", i ), true ) ); + } + ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual ); + ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual ); + ob->resize( desktop()->width()/3, ob->height() ); + } + else if ( flag == WT_PyConsole ) + { + PythonConsole* pyCons = new PythonConsole( desktop(), new SalomeApp_PyInterp() ); + pyCons->setCaption( tr( "PYTHON_CONSOLE" ) ); + wid = pyCons; + pyCons->resize( pyCons->width(), desktop()->height()/4 ); + //pyCons->connectPopupRequest(this, SLOT(onConnectPopupRequest(SUIT_PopupClient*, QContextMenuEvent*))); + } + return wid; +} + +/*!Create preferences.*/ +void SalomeApp_Application::createPreferences( LightApp_Preferences* pref ) +{ + LightApp_Application::createPreferences(pref); + + if ( !pref ) + return; + + int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) ); + int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat ); + int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab ); + for ( int i = SalomeApp_DataObject::CT_Value; i <= SalomeApp_DataObject::CT_RefEntry; i++ ) + { + pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), defCols, + LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_%d", i ) ); + } + pref->setItemProperty( defCols, "columns", 1 ); +} + +/*!Update desktop title.*/ +void SalomeApp_Application::updateDesktopTitle() { + QString aTitle = applicationName(); + QString aVer = applicationVersion(); + if ( !aVer.isEmpty() ) + aTitle += QString( " " ) + aVer; + + if ( activeStudy() ) + { + QString sName = SUIT_Tools::file( activeStudy()->studyName().stripWhiteSpace(), false ); + if ( !sName.isEmpty() ) { + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if ( study ) { + _PTR(Study) stdDS = study->studyDS(); + if(stdDS) { + if ( stdDS->GetProperties()->IsLocked() ) { + aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) ); + } else { + aTitle += QString( " - [%1]" ).arg( sName ); + } + } + } + } + } + + desktop()->setCaption( aTitle ); +} + +/*!Gets CORBA::ORB_var*/ +CORBA::ORB_var SalomeApp_Application::orb() +{ + ORB_INIT& init = *SINGLETON_::Instance(); + static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() ); + return _orb; +} + +/*!Create and return SALOMEDS_StudyManager.*/ +SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr() +{ + static SALOMEDSClient_StudyManager* _sm = new SALOMEDS_StudyManager(); + return _sm; +} + +/*!Create and return SALOME_NamingService.*/ +SALOME_NamingService* SalomeApp_Application::namingService() +{ + static SALOME_NamingService* _ns = new SALOME_NamingService( orb() ); + return _ns; +} + +/*!Create and return SALOME_LifeCycleCORBA.*/ +SALOME_LifeCycleCORBA* SalomeApp_Application::lcc() +{ + static SALOME_LifeCycleCORBA* _lcc = new SALOME_LifeCycleCORBA( namingService() ); + return _lcc; +} + +/*!Return default engine IOR for light modules*/ +QString SalomeApp_Application::defaultEngineIOR() +{ + /// Look for a default module engine (needed for CORBAless modules to use SALOMEDS persistence) + QString anIOR( "" ); + CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" ); + if ( !CORBA::is_nil( anEngine ) ) + anIOR = orb()->object_to_string( anEngine ); + return anIOR; +} + +/*!Private SLOT. On preferences.*/ +void SalomeApp_Application::onProperties() +{ + SalomeApp_Study* study = dynamic_cast( activeStudy() ); + if( !study ) + return; + + _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder(); + SB->NewCommand(); + + SalomeApp_StudyPropertiesDlg aDlg( desktop() ); + int res = aDlg.exec(); + if( res==QDialog::Accepted && aDlg.isChanged() ) + SB->CommitCommand(); + else + SB->AbortCommand(); + + //study->updateCaptions(); + updateDesktopTitle(); + updateActions(); +} + +/*!Insert items in popup, which necessary for current application*/ +void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* thePopup, QString& title ) +{ + LightApp_Application::contextMenuPopup( type, thePopup, title ); + + OB_Browser* ob = objectBrowser(); + if ( !ob || type != ob->popupClientType() ) + return; + + // Get selected objects + SALOME_ListIO aList; + LightApp_SelectionMgr* mgr = selectionMgr(); + mgr->selectedObjects( aList, QString::null, false ); + + // "Delete reference" item should appear only for invalid references + + // isInvalidRefs will be true, if at least one of selected objects is invalid reference + bool isInvalidRefs = false; + SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); + _PTR(Study) aStudyDS = aStudy->studyDS(); + _PTR(SObject) anObj; + + for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() ) + if( it.Value()->hasEntry() ) + { + _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; + while( aRefObj && aRefObj->ReferencedObject( anObj ) ) + aRefObj = anObj; + + if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) + isInvalidRefs = true; + } + + // Add "Delete reference" item to popup + if ( isInvalidRefs ) + { + thePopup->insertSeparator(); + thePopup->insertItem( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) ); + return; + } + + aList.Clear(); + mgr->selectedObjects( aList ); + + // "Activate module" item should appear only if it's necessary + if (aList.Extent() != 1) + return; + Handle(SALOME_InteractiveObject) aIObj = aList.First(); + QString aModuleName(aIObj->getComponentDataType()); + QString aModuleTitle = moduleTitle(aModuleName); + CAM_Module* currentModule = activeModule(); + if (currentModule && currentModule->moduleName() == aModuleTitle) + return; + thePopup->insertItem( tr( "MEN_OPENWITH" ), this, SLOT( onOpenWith() ) ); +} + +/*!Update obect browser: + 1.if 'updateModels' true, update existing data models; + 2. update "non-existing" (not loaded yet) data models; + 3. update object browser if it existing */ +void SalomeApp_Application::updateObjectBrowser( const bool updateModels ) +{ + // update existing data models (already loaded SComponents) + LightApp_Application::updateObjectBrowser(updateModels); + + // update "non-existing" (not loaded yet) data models + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if ( study ) + { + _PTR(Study) stdDS = study->studyDS(); + if( stdDS ) + { + for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() ) + { + _PTR(SComponent) aComponent ( it->Value() ); + + if ( aComponent->ComponentDataType() == "Interface Applicative" ) + continue; // skip the magic "Interface Applicative" component + + SalomeApp_DataModel::BuildTree( aComponent, study->root(), study, /*skipExisitng=*/true ); + } + } + } + + if ( objectBrowser() ) + { + objectBrowser()->updateGeometry(); + objectBrowser()->updateTree( 0, false ); + } +} + +/*!Display Catalog Genenerator dialog */ +void SalomeApp_Application::onCatalogGen() +{ + ToolsGUI_CatalogGeneratorDlg aDlg( desktop() ); + aDlg.exec(); +} + +/*!Display Registry Display dialog */ +void SalomeApp_Application::onRegDisplay() +{ + CORBA::ORB_var anOrb = orb(); + ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop(), "Registry" ); + regWnd->show(); + regWnd->raise(); + regWnd->setActiveWindow(); +} + +/*!find original object by double click on item */ +void SalomeApp_Application::onDblClick( QListViewItem* it ) +{ + OB_ListItem* item = dynamic_cast( it ); + SalomeApp_Study* study = dynamic_cast( activeStudy() ); + + if( study && item ) + { + SalomeApp_DataObject* obj = dynamic_cast( item->dataObject() ); + if( !obj ) + return; + + QString entry = obj->entry(); + _PTR(SObject) sobj = study->studyDS()->FindObjectID( entry.latin1() ), ref; + + if( sobj && sobj->ReferencedObject( ref ) ) + { + entry = ref->GetID().c_str(); + QListViewItemIterator anIt( item->listView() ); + for( ; anIt.current(); anIt++ ) + { + OB_ListItem* item = dynamic_cast( anIt.current() ); + if( !item ) + continue; + + SalomeApp_DataObject* original = dynamic_cast( item->dataObject() ); + if( original->entry()!=entry ) + continue; + + OB_Browser* br = objectBrowser(); + br->setSelected( original ); + SUIT_DataObject* p = original->parent(); + while( p ) + { + br->setOpen( p ); + p = p->parent(); + } + break; + } + } + } +} diff --git a/src/SalomeApp/SalomeApp_Application.h b/src/SalomeApp/SalomeApp_Application.h new file mode 100644 index 000000000..2462e557b --- /dev/null +++ b/src/SalomeApp/SalomeApp_Application.h @@ -0,0 +1,103 @@ +// File: SalomeApp_Application.h +// Created: 10/22/2004 3:37:25 PM +// Author: Sergey LITONIN +// Copyright (C) CEA 2004 + +#ifndef SALOMEAPP_APPLICATION_H +#define SALOMEAPP_APPLICATION_H + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "SalomeApp.h" +#include + +#include + +#include +//#include CORBA_CLIENT_HEADER(SALOMEDS) +#include + +#include "SALOMEDSClient.hxx" + +class QAction; +class QComboBox; +class QDockWindow; + +class LightApp_Preferences; +class SalomeApp_Module; + +class SALOME_LifeCycleCORBA; + +class QListViewItem; + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +/*! + Description : Application containing SalomeApp module or LightApp module +*/ + +class SALOMEAPP_EXPORT SalomeApp_Application : public LightApp_Application +{ + Q_OBJECT + +public: + enum { DumpStudyId = LightApp_Application::UserID, LoadScriptId, PropertiesId, + CatalogGenId, RegDisplayId, UserID }; + +public: + SalomeApp_Application(); + virtual ~SalomeApp_Application(); + + virtual void updateObjectBrowser( const bool = true ); + + virtual QString getFileFilter() const; + + virtual void start(); + + virtual void contextMenuPopup( const QString&, QPopupMenu*, QString& ); + + static CORBA::ORB_var orb(); + static SALOMEDSClient_StudyManager* studyMgr(); + static SALOME_NamingService* namingService(); + static SALOME_LifeCycleCORBA* lcc(); + static QString defaultEngineIOR(); + +public slots: + virtual bool onOpenDoc( const QString& ); + virtual void onLoadDoc(); + virtual bool onLoadDoc( const QString& ); + virtual void onCopy(); + virtual void onPaste(); + +protected: + virtual void createActions(); + virtual SUIT_Study* createNewStudy(); + virtual QWidget* createWindow( const int ); + + virtual void updateCommandsStatus(); + virtual void onSelectionChanged(); + + virtual void createPreferences( LightApp_Preferences* ); + virtual void updateDesktopTitle(); + +private slots: + void onDeleteInvalidReferences(); + void onDblClick( QListViewItem* ); + void onProperties(); + void onDumpStudy(); + void onLoadScript(); + + void onCatalogGen(); + void onRegDisplay(); + void onOpenWith(); +}; + +#ifdef WIN32 +#pragma warning( default:4251 ) +#endif + +#endif diff --git a/src/SalomeApp/SalomeApp_DataObject.cxx b/src/SalomeApp/SalomeApp_DataObject.cxx new file mode 100644 index 000000000..938754e92 --- /dev/null +++ b/src/SalomeApp/SalomeApp_DataObject.cxx @@ -0,0 +1,373 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#include "SalomeApp_DataObject.h" + +#include "SalomeApp_Study.h" +#include "LightApp_RootObject.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* + Class: SalomeApp_DataObject + Level: Public +*/ +/*!Constructor. Initialize by \a parent*/ +SalomeApp_DataObject::SalomeApp_DataObject( SUIT_DataObject* parent ) +: LightApp_DataObject( parent ), + CAM_DataObject( parent ), + myEntry( "" ), + myName( "" ) +{ +} + +/*!Constructor. Initialize by \a parent and SObject*/ +SalomeApp_DataObject::SalomeApp_DataObject( const _PTR(SObject)& sobj, SUIT_DataObject* parent ) +: LightApp_DataObject( parent ), + CAM_DataObject( parent ), + myName( "" ) +{ + myObject = sobj; + myEntry = myObject->GetID().c_str(); +} + +/*!Destructor. Do nothing.*/ +SalomeApp_DataObject::~SalomeApp_DataObject() +{ +} + +/*!Gets object ID. + *\retval QString + */ +QString SalomeApp_DataObject::entry() const +{ + if ( myObject ) + return myObject->GetID().c_str(); + return QString::null; + //return myEntry; +} + +/*!Gets name of object.*/ +QString SalomeApp_DataObject::name() const +{ + //if ( myName.isEmpty() ) + { + QString str; + if ( myObject ) + str = myObject->GetName().c_str(); + + if ( str.isEmpty() ) + { + _PTR(SObject) refObj = referencedObject(); + if ( refObj ) + str = refObj->GetName().c_str(); + } + + if ( isReference() ) + { + if ( !(QString(referencedObject()->GetName().c_str()).isEmpty()) ) + str = QString( "* " ) + str; + else + str = QString( "" ); + } + SalomeApp_DataObject* that = (SalomeApp_DataObject*)this; + that->myName = str; + } + return myName; +} + +/*!Gets icon picture of object.*/ +QPixmap SalomeApp_DataObject::icon() const +{ + _PTR(GenericAttribute) anAttr; + if ( myObject && myObject->FindAttribute( anAttr, "AttributePixMap" ) ){ + _PTR(AttributePixMap) aPixAttr ( anAttr ); + if ( aPixAttr->HasPixMap() ){ + QString pixmapName = QObject::tr( aPixAttr->GetPixMap().c_str() ); + LightApp_RootObject* aRoot = dynamic_cast( root() ); + if ( aRoot && aRoot->study() ) { + QPixmap pixmap = aRoot->study()->application()->resourceMgr()->loadPixmap( componentDataType(), pixmapName, false ); + return pixmap; + } + } + } + return QPixmap(); +} + +/*!Gets text value for one of entity: + *\li Value (id = SalomeApp_DataObject::CT_Value) + *\li Entry (id = SalomeApp_DataObject::CT_Entry) + *\li IOR (id = SalomeApp_DataObject::CT_IOR) + *\li Reference entry (id = SalomeApp_DataObject::CT_RefEntry) + */ +QString SalomeApp_DataObject::text( const int id ) const +{ + QString txt; + switch ( id ) + { + case CT_Value: +#ifndef WNT + if ( componentObject() != this ) +#else + if ( componentObject() != (SUIT_DataObject*)this ) +#endif + txt = value( referencedObject() ); + break; + case CT_Entry: + txt = entry( object() ); + break; + case CT_IOR: + txt = ior( referencedObject() ); + break; + case CT_RefEntry: + if ( isReference() ) + txt = entry( referencedObject() ); + break; + } + return txt; +} + +/*!Get color value for one of entity: + *\li Text color + *\li Highlight color + *\li Higlighted text color + */ +QColor SalomeApp_DataObject::color( const ColorRole cr ) const +{ + QColor clr; + switch ( cr ) + { + case Text: + if ( isReference() ) + { + if ( !(QString(referencedObject()->GetName().c_str()).isEmpty()) ) + clr = QColor( 255, 0, 0 ); + else + clr = QColor( 200, 200, 200 ); + } + else if ( myObject ) + { + _PTR(GenericAttribute) anAttr; + if ( myObject->FindAttribute( anAttr, "AttributeTextColor" ) ) + { + _PTR(AttributeTextColor) aColAttr = anAttr; + clr = QColor( (int)aColAttr->TextColor().R, (int)aColAttr->TextColor().G, (int)aColAttr->TextColor().B ); + } + } + break; + case Highlight: + if ( isReference() ) + { + if ( !(QString(referencedObject()->GetName().c_str()).isEmpty()) ) + clr = QColor( 255, 0, 0 ); + else + clr = QColor( 200, 200, 200 ); + } + break; + case HighlightedText: + if ( isReference() ) + clr = QColor( 255, 255, 255 ); + break; + } + return clr; +} + +/*!Gets tooltip.*/ +QString SalomeApp_DataObject::toolTip() const +{ + //return object()->Name(); + return QString( "Object \'%1\', module \'%2\', ID=%3" ).arg( name() ).arg( componentDataType() ).arg( entry() ); +} + +/*!Get component type.*/ +QString SalomeApp_DataObject::componentDataType() const +{ + // if ( myCompDataType.isEmpty() ) { + const SalomeApp_DataObject* compObj = dynamic_cast( componentObject() ); + if ( compObj && compObj->object() ) + { + _PTR(SComponent) aComp( compObj->object() ); + if ( aComp ) { + SalomeApp_DataObject* that = (SalomeApp_DataObject*)this; + that->myCompDataType = aComp->ComponentDataType().c_str(); + } + } + // } + return myCompDataType; +} + +/*!Gets object.*/ +_PTR(SObject) SalomeApp_DataObject::object() const +{ + return myObject; +} + +/*!Checks: Is object reference.*/ +bool SalomeApp_DataObject::isReference() const +{ + bool isRef = false; + if ( myObject ) + { + _PTR(SObject) refObj; + isRef = myObject->ReferencedObject( refObj ); + } + return isRef; +} + +/*!Gets reference object.*/ +_PTR(SObject) SalomeApp_DataObject::referencedObject() const +{ + _PTR(SObject) refObj; + _PTR(SObject) obj = myObject; + while ( obj && obj->ReferencedObject( refObj ) ) + obj = refObj; + + return obj; +} + +/*!Gets IOR*/ +QString SalomeApp_DataObject::ior( const _PTR(SObject)& obj ) const +{ + QString txt; + if ( obj ) + { + _PTR(GenericAttribute) attr; + if ( obj->FindAttribute( attr, "AttributeIOR" ) ) + { + _PTR(AttributeIOR) iorAttr = attr; + if ( iorAttr ) + { + std::string str = iorAttr->Value(); + txt = QString( str.c_str() ); + } + } + } + return txt; +} + +/*!Gets Entry*/ +QString SalomeApp_DataObject::entry( const _PTR(SObject)& obj ) const +{ + QString txt; + if ( obj ) + { + std::string str = obj->GetID(); + txt = QString( str.c_str() ); + } + return txt; +} + +/*!Value*/ +QString SalomeApp_DataObject::value( const _PTR(SObject)& obj ) const +{ + if ( !obj ) + return QString::null; + + QString val; + _PTR(GenericAttribute) attr; + + if ( obj->FindAttribute( attr, "AttributeInteger" ) ) + { + _PTR(AttributeInteger) intAttr = attr; + if ( intAttr ) + val = QString::number( intAttr->Value() ); + } + else if ( obj->FindAttribute( attr, "AttributeReal" ) ) + { + _PTR(AttributeReal) realAttr = attr; + if ( realAttr ) + val = QString::number( realAttr->Value() ); + } + else if ( obj->FindAttribute( attr, "AttributeTableOfInteger" ) ) + { + _PTR(AttributeTableOfInteger) tableAttr = attr; + std::string title = tableAttr->GetTitle(); + val = QString( title.c_str() ); + if ( !val.isEmpty() ) + val += QString( " " ); + val += QString( "[%1,%2]" ).arg( tableAttr->GetNbRows() ).arg( tableAttr->GetNbColumns() ); + } + else if ( obj->FindAttribute( attr, "AttributeTableOfReal" ) ) + { + _PTR(AttributeTableOfReal) tableAttr = attr; + std::string title = tableAttr->GetTitle(); + val = QString( title.c_str() ); + if ( !val.isEmpty() ) + val += QString( " " ); + val += QString( "[%1,%2]" ).arg( tableAttr->GetNbRows() ).arg( tableAttr->GetNbColumns() ); + } + else if ( obj->FindAttribute( attr, "AttributeComment") ) + { + _PTR(AttributeComment) comm = attr; + std::string str = comm->Value(); + val = QString( str.c_str() ); + } + + return val; +} + +/* + Class: SalomeApp_ModuleObject + Level: Public +*/ + +/*!Constructor.Initialize by \a parent.*/ +SalomeApp_ModuleObject::SalomeApp_ModuleObject( SUIT_DataObject* parent ) +: SalomeApp_DataObject( parent ), + CAM_RootObject( parent ), + CAM_DataObject( parent ) +{ +} + +/*!Constructor.Initialize by \a parent and SObject.*/ +SalomeApp_ModuleObject::SalomeApp_ModuleObject( const _PTR(SObject)& sobj, SUIT_DataObject* parent ) +: SalomeApp_DataObject( sobj, parent ), + CAM_RootObject( 0, parent ), + CAM_DataObject( parent ) +{ +} + +/*!Constructor.Initialize by \a parent and CAM_DataModel.*/ +SalomeApp_ModuleObject::SalomeApp_ModuleObject( CAM_DataModel* dm, const _PTR(SObject)& sobj, SUIT_DataObject* parent ) +: SalomeApp_DataObject( sobj, parent ), + CAM_RootObject( dm, parent ), + CAM_DataObject( parent ) +{ +} + +/*!Destructor. Do nothing.*/ +SalomeApp_ModuleObject::~SalomeApp_ModuleObject() +{ +} + +/*!Returns module name */ +QString SalomeApp_ModuleObject::name() const +{ + return SalomeApp_DataObject::name(); +} + diff --git a/src/SalomeApp/SalomeApp_DataObject.h b/src/SalomeApp/SalomeApp_DataObject.h new file mode 100644 index 000000000..15a1d96bf --- /dev/null +++ b/src/SalomeApp/SalomeApp_DataObject.h @@ -0,0 +1,88 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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. +// +// 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/ +// +#ifndef SALOMEAPP_DATAOBJECT_H +#define SALOMEAPP_DATAOBJECT_H + +#include "SalomeApp.h" + +#include "LightApp_DataObject.h" +#include "CAM_RootObject.h" + +#include "SALOMEDSClient.hxx" + +class SalomeApp_Study; + +class SALOMEAPP_EXPORT SalomeApp_DataObject : public LightApp_DataObject +{ + +public: + enum { CT_Value, CT_Entry, CT_IOR, CT_RefEntry }; + +public: + SalomeApp_DataObject( SUIT_DataObject* = 0 ); + SalomeApp_DataObject( const _PTR(SObject)&, SUIT_DataObject* = 0 ); + virtual ~SalomeApp_DataObject(); + + virtual QString name() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + + virtual QString text( const int ) const; + virtual QColor color( const ColorRole ) const; + + virtual QString entry() const; + + /*! location of corresponding SALOMEDS::SObject */ + virtual _PTR(SObject) object() const; + + bool isReference() const; + _PTR(SObject) referencedObject() const; + + /*! GEOM, SMESH, VISU, etc.*/ + virtual QString componentDataType() const; + +private: + QString ior( const _PTR(SObject)& ) const; + QString entry( const _PTR(SObject)& ) const; + QString value( const _PTR(SObject)& ) const; + +private: + _PTR(SObject) myObject; + QString myEntry; + QString myName; +}; + +/*! + * SalomeApp_ModuleObject - class for optimized access to DataModel from + * SalomeApp_DataObject instances - see also CAM_RootObject.h + */ + +class SALOMEAPP_EXPORT SalomeApp_ModuleObject : public SalomeApp_DataObject, + public CAM_RootObject +{ +public: + SalomeApp_ModuleObject( SUIT_DataObject* = 0 ); + SalomeApp_ModuleObject( const _PTR(SObject)&, SUIT_DataObject* = 0 ); + SalomeApp_ModuleObject( CAM_DataModel*, const _PTR(SObject)&, SUIT_DataObject* = 0 ); + virtual ~SalomeApp_ModuleObject(); + + virtual QString name() const; +}; + +#endif diff --git a/src/SalomeApp/SalomeApp_Module.cxx b/src/SalomeApp/SalomeApp_Module.cxx new file mode 100644 index 000000000..9284a5792 --- /dev/null +++ b/src/SalomeApp/SalomeApp_Module.cxx @@ -0,0 +1,99 @@ +// File: SalomeApp_Module.cxx +// Created: 10/25/2004 11:39:56 AM +// Author: Sergey LITONIN +// Copyright (C) CEA 2004 + +#include "SalomeApp_Module.h" +#include "SalomeApp_DataModel.h" +#include "SalomeApp_Application.h" +#include "SalomeApp_Study.h" + +#include "LightApp_Selection.h" +#include "LightApp_Operation.h" +#include "LightApp_Preferences.h" + +#include "CAM_DataModel.h" + +#include "OB_Browser.h" + +#include +#include +#include + +#include + +#include +#include + +/*!Constructor.*/ +SalomeApp_Module::SalomeApp_Module( const QString& name ) +: LightApp_Module( name ) +{ +} + +/*!Destructor.*/ +SalomeApp_Module::~SalomeApp_Module() +{ +} + +/*!Gets application.*/ +SalomeApp_Application* SalomeApp_Module::getApp() const +{ + return (SalomeApp_Application*)application(); +} + +/*!Create new instance of data model and return it.*/ +CAM_DataModel* SalomeApp_Module::createDataModel() +{ + return new SalomeApp_DataModel(this); +} + +/*!Create and return instance of LightApp_Selection.*/ +LightApp_Selection* SalomeApp_Module::createSelection() const +{ + return LightApp_Module::createSelection(); +} + +void SalomeApp_Module::extractContainers( const SALOME_ListIO& source, SALOME_ListIO& dest ) const +{ + SalomeApp_Study* study = dynamic_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); + if( !study ) + { + dest = source; + return; + } + + SALOME_ListIteratorOfListIO anIt( source ); + for( ; anIt.More(); anIt.Next() ) + { + Handle( SALOME_InteractiveObject ) obj = anIt.Value(); + if( obj->hasEntry() ) + { + _PTR(SObject) SO = study->studyDS()->FindObjectID( obj->getEntry() ); + if( SO && QString( SO->GetID().c_str() ) == SO->GetFatherComponent()->GetID().c_str() ) + { //component is selected + _PTR(SComponent) SC( SO->GetFatherComponent() ); + _PTR(ChildIterator) anIter ( study->studyDS()->NewChildIterator( SC ) ); + anIter->InitEx( true ); + while( anIter->More() ) + { + _PTR(SObject) valSO ( anIter->Value() ); + _PTR(SObject) refSO; + if( !valSO->ReferencedObject( refSO ) ) + { + QString id = valSO->GetID().c_str(), + comp = SC->ComponentDataType().c_str(), + val = valSO->GetName().c_str(); + + Handle( SALOME_InteractiveObject ) new_obj = + new SALOME_InteractiveObject( id.latin1(), comp.latin1(), val.latin1() ); + dest.Append( new_obj ); + } + anIter->Next(); + } + continue; + } + } + dest.Append( obj ); + } +} diff --git a/src/SalomeApp/SalomeApp_Module.h b/src/SalomeApp/SalomeApp_Module.h new file mode 100644 index 000000000..433d918fd --- /dev/null +++ b/src/SalomeApp/SalomeApp_Module.h @@ -0,0 +1,50 @@ +// File: SalomeApp_Module.h +// Created: 10/25/2004 11:33:06 AM +// Author: Sergey LITONIN +// Copyright (C) CEA 2004 + +#ifndef SALOMEAPP_MODULE_H +#define SALOMEAPP_MODULE_H + +#include "SalomeApp.h" + +#include + +#include + +class CAM_DataModel; +class SalomeApp_Application; +class LightApp_Operation; +class LightApp_Selection; +class SALOME_ListIO; +class QString; + +/*! + * \brief Base class for all salome modules +*/ +class SALOMEAPP_EXPORT SalomeApp_Module : public LightApp_Module +{ + Q_OBJECT + +public: + SalomeApp_Module( const QString& ); + virtual ~SalomeApp_Module(); + + /*! engineIOR() should be a pure virtual method, to avoid logical errors!\n + * Implementation in derived classes can return the following values:\n + * module`s engine IOR - means that this is a standard SALOME module with a CORBA engine + * \li "" (empty string) - means that this not correct SALOME module + */ + virtual QString engineIOR() const = 0; + + /*! Convenient shortcuts*/ + + SalomeApp_Application* getApp() const; + +protected: + virtual CAM_DataModel* createDataModel(); + virtual LightApp_Selection* createSelection() const; + virtual void extractContainers( const SALOME_ListIO&, SALOME_ListIO& ) const; +}; + +#endif diff --git a/src/SalomeApp/SalomeApp_PyInterp.cxx b/src/SalomeApp/SalomeApp_PyInterp.cxx new file mode 100755 index 000000000..19bc57559 --- /dev/null +++ b/src/SalomeApp/SalomeApp_PyInterp.cxx @@ -0,0 +1,123 @@ +// SALOME SALOMEGUI : implementation of desktop and GUI kernel +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : SalomeApp_PyInterp.cxx +// Author : Nicolas REJNERI +// Module : SALOME +// $Header$ + +#include "SalomeApp_PyInterp.h" + +#include +#include + +#include +#include + +#include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)! + +#include +using namespace std; + +/*! + * constructor : multi Python interpreter, one per SALOME study. + * calls initialize method defined in base class, which calls virtual methods + * initstate & initcontext redefined here. + */ +SalomeApp_PyInterp::SalomeApp_PyInterp(): PythonConsole_PyInterp() +{ +} + +/*! + * Destructor. + */ +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 ( !PythonConsole_PyInterp::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, "init_shared_modules", "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; +} + +void SalomeApp_PyInterp::init_python() +{ + /* + * Do nothing + * The initialization has been done in main + */ + MESSAGE("PyInterp_base::init_python"); + ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main + SCRUTE(KERNEL_PYTHON::_gtstate); + _gtstate=KERNEL_PYTHON::_gtstate; + _interp=KERNEL_PYTHON::_interp; +} + diff --git a/src/SalomeApp/resources/SalomeApp_msg_en.po b/src/SalomeApp/resources/SalomeApp_msg_en.po new file mode 100644 index 000000000..a739779d2 --- /dev/null +++ b/src/SalomeApp/resources/SalomeApp_msg_en.po @@ -0,0 +1,192 @@ +// File: CATHAREGUI_msg_en.po +// Created: 10/25/2004 12:46:36 PM +// Author: Sergey LITONIN +// Copyright (C) CEA 2004 + +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2002-02-22 16:56:46 CET\n" +"PO-Revision-Date: 2004-02-17 11:17+0300\n" +"Last-Translator: FULLNAME \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +//======================================================================================= + +msgid "BUT_OK" +msgstr "&OK" + +msgid "BUT_NEW" +msgstr "&New" + +msgid "BUT_OPEN" +msgstr "&Open" + +msgid "BUT_LOAD" +msgstr "&Load" + +msgid "BUT_CANCEL" +msgstr "&Cancel" + +//======================================================================================= + +msgid "SalomeApp_Application::PYTHON_CONSOLE" +msgstr "Python Console" + +msgid "SalomeApp_Application::TOT_DESK_FILE_DUMP_STUDY" +msgstr "Dump study" + +msgid "SalomeApp_Application::MEN_DESK_FILE_DUMP_STUDY" +msgstr "&Dump study..." + +msgid "SalomeApp_Application::PRP_DESK_FILE_DUMP_STUDY" +msgstr "Dumps study to the python script" + +msgid "SalomeApp_Application::TOT_DESK_FILE_LOAD_SCRIPT" +msgstr "Load python script" + +msgid "SalomeApp_Application::MEN_DESK_FILE_LOAD_SCRIPT" +msgstr "Load scrip&t..." + +msgid "SalomeApp_Application::PRP_DESK_FILE_LOAD_SCRIPT" +msgstr "Loads python script from file" + +msgid "SalomeApp_Application::TOT_FILE_DESK_PREFERENCES" +msgstr "Preferences" + +msgid "SalomeApp_Application::MEN_DESK_TOOLS" +msgstr "&Tools" + +msgid "SalomeApp_Application::TOT_DESK_CATALOG_GENERATOR" +msgstr "Catalog generator" + +msgid "SalomeApp_Application::MEN_DESK_CATALOG_GENERATOR" +msgstr "Catalog &generator" + +msgid "SalomeApp_Application::PRP_DESK_CATALOG_GENERATOR" +msgstr "Generates XML catalog of a component's interface" + +msgid "SalomeApp_Application::TOT_DESK_REGISTRY_DISPLAY" +msgstr "Registry display" + +msgid "SalomeApp_Application::MEN_DESK_REGISTRY_DISPLAY" +msgstr "Registry &display" + +msgid "SalomeApp_Application::PRP_DESK_REGISTRY_DISPLAY" +msgstr "Displays content of the Registry CORBA server" + +msgid "SalomeApp_Application::TOT_DESK_MRU" +msgstr "Most recently used" + +msgid "SalomeApp_Application::MEN_DESK_MRU" +msgstr "Most recently used" + +msgid "SalomeApp_Application::TOT_DESK_PROPERTIES" +msgstr "Study properties" + +msgid "SalomeApp_Application::MEN_DESK_PROPERTIES" +msgstr "Pro&perties..." + +msgid "SalomeApp_Application::PRP_DESK_PROPERTIES" +msgstr "Edits study properties" + +msgid "SalomeApp_Application::PREF_CATEGORY_SALOME" +msgstr "SALOME" + +msgid "SalomeApp_Application::PREF_TAB_OBJBROWSER" +msgstr "Object browser" + +msgid "SalomeApp_Application::MEN_OPENWITH" +msgstr "Activate Module" + +msgid "SalomeApp_Application::MEN_DELETE_INVALID_REFERENCE" +msgstr "Delete Invalid Reference" + +//======================================================================================= + +msgid "SalomeApp_Application::MEN_WINDOWS_NEW" +msgstr "New window" + +msgid "SalomeApp_Application::MEN_VIEW_WNDS" +msgstr "Windows" + +//======================================================================================= + +msgid "SalomeApp_Application::PREF_GROUP_DEF_COLUMNS" +msgstr "Default columns" + +msgid "SalomeApp_Application::PREF_OBJ_BROWSER_SETTINGS" +msgstr "Settings" + +//======================================================================================= + +msgid "SalomeApp_Application::OBJ_BROWSER_NAME" +msgstr "Object" + +msgid "SalomeApp_Application::OBJ_BROWSER_COLUMN_0" +msgstr "Value" + +msgid "SalomeApp_Application::OBJ_BROWSER_COLUMN_1" +msgstr "Entry" + +msgid "SalomeApp_Application::OBJ_BROWSER_COLUMN_2" +msgstr "IOR" + +msgid "SalomeApp_Application::OBJ_BROWSER_COLUMN_3" +msgstr "Reference entry" + +msgid "SalomeApp_Application::ALL_FILES_FILTER" +msgstr "All files (*.*)" + +msgid "SalomeApp_Application::PYTHON_FILES_FILTER" +msgstr "PYTHON Files (*.py)" + +msgid "SalomeApp_Application::STUDY_LOCKED" +msgstr "LOCKED" + +msgid "SalomeApp_Application::QUE_DOC_ALREADYEXIST" +msgstr "The document %1 already exists in study manager.\nDo you want to reload it ?" + +//======================================================================================= + +msgid "SalomeApp_StudyPropertiesDlg::PRP_MODE_FROM_SCRATCH" +msgstr "from scratch" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_MODE_FROM_COPYFROM" +msgstr "copy from" + +msgid "SalomeApp_StudyPropertiesDlg::TLT_STUDY_PROPERTIES" +msgstr "Study Properties" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_AUTHOR" +msgstr "Author" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_DATE" +msgstr "Created" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_MODE" +msgstr "Mode" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_LOCKED" +msgstr "Locked" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_MODIFIED" +msgstr "Modified" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_MODIFICATIONS" +msgstr "Modifications" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_YES" +msgstr "Yes" + +msgid "SalomeApp_StudyPropertiesDlg::PRP_NO" +msgstr "No" + +//======================================================================================= + +msgid "SalomeApp_Application::PUBLISH_IN_STUDY" +msgstr "Publish in study" + +msgid "SalomeApp_Application::WRN_DUMP_STUDY_FAILED" +msgstr "Dump study failed" + diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx new file mode 100755 index 000000000..ac7738582 --- /dev/null +++ b/src/Session/SALOME_Session_Server.cxx @@ -0,0 +1,446 @@ +// SALOME Session : implementation of Session.idl +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : SALOME_Session_Server.cxx +// Author : Paul RASCLE, EDF +// Module : SALOME + +#include +#include "Utils_ORB_INIT.hxx" +#include "Utils_SINGLETON.hxx" +#include "SALOME_NamingService.hxx" +#include "SALOMETraceCollector.hxx" + +#include "InquireServersQThread.h" // splash + +#include +#ifndef WNT +#include +#endif + +#include +#include +#include +#include + +#include "Utils_SALOME_Exception.hxx" +#include "Utils_CorbaException.hxx" +#include "SALOME_Event.hxx" + +#include +#include CORBA_SERVER_HEADER(SALOME_Session) +#include CORBA_SERVER_HEADER(SALOMEDS) + +#include +#include "Session_Session_i.hxx" +#include "Session_ServerLauncher.hxx" + +#include "SUIT_Tools.h" +#include "SUIT_Session.h" +#include "SUIT_Application.h" +#include "SUIT_MessageBox.h" +#include "SUIT_ResourceMgr.h" + +#include "SUIT_ExceptionHandler.h" + +extern "C" int HandleSignals( QApplication *theQApplication ); + +/*! - read arguments, define list of server to launch with their arguments. + * - wait for naming service + * - create and run a thread for launch of all servers + * +*/ + +//! CORBA server for SALOME Session +/*! + * SALOME_Session Server launches a SALOME session servant. + * The servant registers to the Naming Service. + * See SALOME_Session.idl for interface specification. + * + * Main services offered by the servant are: + * - launch GUI + * - stop Session ( must be idle ) + * - get session state + */ + +PyObject* salome_shared_modules_module = 0; + +void MessageOutput( QtMsgType type, const char* msg ) +{ + switch ( type ) + { + case QtDebugMsg: + MESSAGE( "Debug: " << msg ); + break; + case QtWarningMsg: + MESSAGE( "Warning: " << msg ); + break; + case QtFatalMsg: + MESSAGE( "Fatal: " << msg ); + break; + } +} + +/* XPM */ +static const char* pixmap_not_found_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #A80000", +" ", +" ", +" . . ", +" .+. .+. ", +" .+++. .+++. ", +" .+++.+++. ", +" .+++++. ", +" .+++. ", +" .+++++. ", +" .+++.+++. ", +" .+++. .+++. ", +" .+. .+. ", +" . . ", +" ", +" ", +" "}; + +QString salomeVersion() +{ + QString path( ::getenv( "GUI_ROOT_DIR" ) ); + if ( !path.isEmpty() ) + path += QDir::separator(); + path += QString( "bin/salome/VERSION" ); + + QFile vf( path ); + if ( !vf.open( IO_ReadOnly ) ) + return QString::null; + + QString line; + vf.readLine( line, 1024 ); + vf.close(); + + if ( line.isEmpty() ) + return QString::null; + + while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) ) + line.remove( line.length() - 1, 1 ); + + QString ver; + int idx = line.findRev( ":" ); + if ( idx != -1 ) + ver = line.mid( idx + 1 ).stripWhiteSpace(); + + return ver; +} + +class SALOME_ResourceMgr : public SUIT_ResourceMgr +{ +public: + SALOME_ResourceMgr( const QString& app, const QString& resVarTemplate ) : SUIT_ResourceMgr( app, resVarTemplate ) + { + setCurrentFormat( "xml" ); + setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); + setDefaultPixmap( QPixmap( pixmap_not_found_xpm ) ); + } + static void initResourceMgr() + { + if ( myExtAppName.isNull() || myExtAppVersion.isNull() ) { + SALOME_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) ); + resMgr.loadLanguage( "SalomeApp", "en" ); + + myExtAppName = QObject::tr( "APP_NAME" ).stripWhiteSpace(); + if ( myExtAppName == "APP_NAME" || myExtAppName.lower() == "salome" ) + myExtAppName = "SalomeApp"; + myExtAppVersion = QObject::tr( "APP_VERSION" ); + if ( myExtAppVersion == "APP_VERSION" ) { + if ( myExtAppName != "SalomeApp" ) + myExtAppVersion = ""; + else myExtAppVersion = salomeVersion(); + } + } + } + QString version() const { return myExtAppVersion; } + +protected: + QString userFileName( const QString& appName ) const + { + if ( version().isNull() ) return ""; + return SUIT_ResourceMgr::userFileName( myExtAppName ); + } + +public: + static QString myExtAppName; + static QString myExtAppVersion; +}; + +QString SALOME_ResourceMgr::myExtAppName = QString::null; +QString SALOME_ResourceMgr::myExtAppVersion = QString::null; + +class SALOME_Session : public SUIT_Session +{ +public: + SALOME_Session() : SUIT_Session() {} + virtual ~SALOME_Session() {} + +protected: + virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + { + SALOME_ResourceMgr::initResourceMgr(); + SALOME_ResourceMgr* resMgr = new SALOME_ResourceMgr( appName, QString( "%1Config" ) ); + return resMgr; + } +}; + +class SALOME_QApplication : public QApplication +{ +public: + SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv ), myHandler ( 0 ) {} + + virtual bool notify( QObject* receiver, QEvent* e ) + { + return myHandler ? myHandler->handle( receiver, e ) : + QApplication::notify( receiver, e ); + } + SUIT_ExceptionHandler* handler() const { return myHandler; } + void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; } + +private: + SUIT_ExceptionHandler* myHandler; +}; + +// class which calls SALOME::Session::GetInterface() from another thread +// to avoid mutual lock ( if called from the same thread as main() +class GetInterfaceThread : public QThread +{ +public: + GetInterfaceThread( SALOME::Session_var s ) : session ( s ) {} +protected: + virtual void run() + { + if ( !CORBA::is_nil( session ) ) + session->GetInterface(); + else + printf( "\nFATAL ERROR: SALOME::Session object is nil! Can not display GUI\n\n" ); + } +private: + SALOME::Session_var session; +}; + +// returns true if 'str' is found in argv +bool isFound( const char* str, int argc, char** argv ) +{ + for ( int i = 1; i <= ( argc-1 ); i++ ) + if ( !strcmp( argv[i], str ) ) + return true; + return false; +} + +// ---------------------------- MAIN ----------------------- +int main( int argc, char **argv ) +{ + qInstallMsgHandler( MessageOutput ); + + // QApplication should be create before all other operations + // When uses QApplication::libraryPaths() ( example, QFile::encodeName() ) + // qApp used for detection of the executable dir path. + SALOME_QApplication _qappl( argc, argv ); + ASSERT( QObject::connect( &_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) ); + + QString path = QDir::convertSeparators( SUIT_Tools::addSlash( QString( ::getenv( "GUI_ROOT_DIR" ) ) ) + QString( "bin/salome" ) ); + _qappl.addLibraryPath( path ); + + _qappl.setStyle( "salome" ); + + int result = -1; + + CORBA::ORB_var orb; + PortableServer::POA_var poa; + + SUIT_Session* aGUISession = 0; + SALOME_NamingService* _NS = 0; + GetInterfaceThread* guiThread = 0; + Session_ServerLauncher* myServerLauncher = 0; + + try { + + // Python initialisation : only once + + int _argc = 1; + char* _argv[] = {""}; + 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(); + ASSERT( SINGLETON_::IsAlreadyExisting() ); + int orbArgc = 1; + orb = init( orbArgc, argv ); + + // Install SALOME thread event handler + SALOME_Event::GetSessionThread(); + + CORBA::Object_var obj = orb->resolve_initial_references( "RootPOA" ); + poa = PortableServer::POA::_narrow( obj ); + + PortableServer::POAManager_var pman = poa->the_POAManager(); + pman->activate() ; + INFOS( "pman->activate()" ); + + _NS = new SALOME_NamingService( orb ); + + result = 0; + } + catch ( SALOME_Exception& e ) { + INFOS( "run(): SALOME::SALOME_Exception is caught: "<name(); + INFOS ( "run(): CORBA exception of the kind : "<start(); + + _ServerLaunch.wait( &_GUIMutex ); // to be reseased by Launch server thread when ready: + + // show splash screen if "SPLASH" parameter was passed ( default ) + if ( isFound( "SPLASH", argc, argv ) ) + { + // create temporary resource manager just to load splash icon + SUIT_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) ); + resMgr.setCurrentFormat( "xml" ); + resMgr.loadLanguage( "LightApp", "en" ); + + // create splash object: widget ( splash with progress bar ) and "pinging" thread + InquireServersGUI splash; + splash.setPixmap( resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ) ); + SUIT_Tools::centerWidget( &splash, _qappl.desktop() ); + + _qappl.setMainWidget( &splash ); + QObject::connect( &_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ); + splash.show(); // display splash with running progress bar + _qappl.exec(); // wait untill splash closes ( progress runs till end or Cancel is pressed ) + + result = splash.getExitStatus(); // 1 is error + } + else + _SessionStarted.wait(); + } + + // call Session::GetInterface() if "GUI" parameter was passed ( default ) + if ( !result && isFound( "GUI", argc, argv ) ) + { + CORBA::Object_var obj = _NS->Resolve( "/Kernel/Session" ); + SALOME::Session_var session = SALOME::Session::_narrow( obj ) ; + ASSERT ( ! CORBA::is_nil( session ) ); + + INFOS( "Session activated, Launch IAPP..." ); + guiThread = new GetInterfaceThread( session ); + guiThread->start(); + } + + if ( !result ) + { + + // GUI activation + // Allow multiple activation/deactivation of GUI + while ( true ) + { + MESSAGE( "waiting wakeAll()" ); + _ServerLaunch.wait( &_GUIMutex ); // to be reseased by Launch server thread when ready: + // atomic operation lock - unlock on mutex + // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll() + // this thread wakes up, and lock mutex + + _GUIMutex.unlock(); + + // SUIT_Session creation + aGUISession = new SALOME_Session(); + + // Load SalomeApp dynamic library + INFOS( "creation SUIT_Application" ); + SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 ); + if ( aGUIApp ) + { + if ( !isFound( "noexcepthandler", argc, argv ) ) + _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application + // aGUISession contains SalomeApp_ExceptionHandler + // Run GUI loop + MESSAGE( "run(): starting the main event loop" ); + result = _qappl.exec(); + + if ( result == SUIT_Session::FROM_GUI ) // desktop is closed by user from GUI + break; + } + + delete aGUISession; + aGUISession = 0; + + // Prepare _GUIMutex for a new GUI activation + _GUIMutex.lock(); + } + } + + if ( myServerLauncher ) + myServerLauncher->KillAll(); // kill embedded servers + + delete aGUISession; + delete guiThread; + delete myServerLauncher; + delete _NS; + + LocalTraceBufferPool *bp1 = LocalTraceBufferPool::instance(); + LocalTraceBufferPool::deleteInstance(bp1); + + return result; +} diff --git a/src/Session/Session_ServerThread.cxx b/src/Session/Session_ServerThread.cxx new file mode 100755 index 000000000..7e3714518 --- /dev/null +++ b/src/Session/Session_ServerThread.cxx @@ -0,0 +1,559 @@ +// SALOME Session : implementation of Session_ServerThread.cxx +// +// Copyright (C) 2003 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. +// +// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Session_ServerThread.cxx +// Author : Paul RASCLE, EDF +// Module : SALOME +// $Header$ + +// #include +// #include CORBA_SERVER_HEADER(SALOME_Session) +// #include CORBA_SERVER_HEADER(SALOMEDS) + +#include "Session_ServerThread.hxx" + +#include "SALOME_Container_i.hxx" +#include "SALOME_ContainerManager.hxx" +#include "SALOMEDS_StudyManager_i.hxx" +#include "SALOME_ModuleCatalog_impl.hxx" +#include "RegistryService.hxx" +#include "Session_Session_i.hxx" +#include "SalomeApp_Engine_i.hxx" + +#include "Utils_ORB_INIT.hxx" +#include "Utils_SINGLETON.hxx" +#include "Utils_SALOME_Exception.hxx" +#include "OpUtil.hxx" +#include "NamingService_WaitForServerReadiness.hxx" +#include "utilities.h" + +#include +#include + +using namespace std; + +const int Session_ServerThread::NB_SRV_TYP = 7; +const char* Session_ServerThread::_serverTypes[NB_SRV_TYP] = {"Container", + "ModuleCatalog", + "Registry", + "SALOMEDS", + "Session", + "SalomeAppEngine", + "ContainerManager"}; + +//============================================================================= +/*! + * default constructor not for use + */ +//============================================================================= + +Session_ServerThread::Session_ServerThread() +{ + ASSERT(0); // must not be called +} + +//============================================================================= +/*! + * constructor + */ +//============================================================================= + +Session_ServerThread::Session_ServerThread(int argc, + char ** argv, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + QMutex *GUIMutex) +{ + //MESSAGE("Session_ServerThread Constructor " << argv[0]); + _argc = argc; + _argv = argv; + _orb = CORBA::ORB::_duplicate(orb); + _root_poa = PortableServer::POA::_duplicate(poa); + _GUIMutex = GUIMutex; + _servType =-1; + _NS = new SALOME_NamingService(_orb); // one instance per server to limit + // multi thread coherence problems +} + +//============================================================================= +/*! + * destructor + */ +//============================================================================= + +Session_ServerThread::~Session_ServerThread() +{ + //MESSAGE("~Session_ServerThread "<< _argv[0]); +} + +//============================================================================= +/*! + * run the thread : activate one servant, the servant type is given by + * argument _argv[0] + */ +//============================================================================= + +void Session_ServerThread::Init() +{ + MESSAGE("Session_ServerThread::Init "<< _argv[0]); + + for (int i=0; i<_argc; i++) SCRUTE(_argv[i]); +#ifndef WNT + for (int i=0; iactivate_object (Catalogue_i); + + CORBA::Object_ptr myCata = Catalogue_i->_this(); + _NS->Register(myCata ,"/Kernel/ModulCatalog"); + } + catch(CORBA::SystemException&) + { + INFOS( "Caught CORBA::SystemException." ); + } + catch(CORBA::Exception&) + { + INFOS( "Caught CORBA::Exception." ); + } + catch(omniORB::fatalException& fe) + { + INFOS( "Caught omniORB::fatalException:" ); + INFOS( " file: " << fe.file() ); + INFOS( " line: " << fe.line() ); + INFOS( " mesg: " << fe.errmsg() ); + } + catch(...) + { + INFOS( "Caught unknown exception." ); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateSALOMEDS(int argc, + char ** argv) +{ + try + { + INFOS("SALOMEDS thread started"); + // We allocate the objects on the heap. Since these are reference + // counted objects, they will be deleted by the POA when they are no + // longer needed. + + SALOMEDS_StudyManager_i * myStudyManager_i + = new SALOMEDS_StudyManager_i(_orb,_root_poa); + + // Activate the objects. This tells the POA that the objects are + // ready to accept requests. + + PortableServer::ObjectId_var myStudyManager_iid + = _root_poa->activate_object(myStudyManager_i); + myStudyManager_i->register_name("/myStudyManager"); + } + catch(CORBA::SystemException&) + { + INFOS( "Caught CORBA::SystemException." ); + } + catch(CORBA::Exception&) + { + INFOS( "Caught CORBA::Exception." ); + } + catch(omniORB::fatalException& fe) + { + INFOS( "Caught omniORB::fatalException:" ); + INFOS( " file: " << fe.file() ); + INFOS( " line: " << fe.line() ); + INFOS( " mesg: " << fe.errmsg() ); + } + catch(...) + { + INFOS( "Caught unknown exception." ); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateRegistry(int argc, + char ** argv) +{ + INFOS("Registry thread started"); + SCRUTE(argc); + if( argc<3 ) + { + INFOS("you must provide the Salome session name when you call SALOME_Registry_Server"); + throw CommException("you must provide the Salome session name when you call SALOME_Registry_Server"); + } + const char *ptrSessionName=0; + + int k=0 ; + for ( k=1 ; k0); + const char *registryName = "Registry"; + Registry::Components_var varComponents; + try + { + RegistryService *ptrRegistry = SINGLETON_::Instance(); + ptrRegistry->SessionName( ptrSessionName ); + varComponents = ptrRegistry->_this(); + // The RegistryService must not already exist. + + try + { + CORBA::Object_var pipo = _NS->Resolve( registryName ); + if (CORBA::is_nil(pipo) ) throw ServiceUnreachable(); + INFOS("RegistryService servant already existing" ); + ASSERT(0); + } + catch( const ServiceUnreachable &ex ) + { + } + catch( const CORBA::Exception &exx ) + { + } + string absoluteName = string("/") + registryName; + _NS->Register( varComponents , absoluteName.c_str() ); + MESSAGE("On attend les requetes des clients"); + } + catch( const SALOME_Exception &ex ) + { + INFOS( "Communication Error : " << ex.what() ); + ASSERT(0); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateContainerManager(int argc, + char ** argv) +{ + try + { + PortableServer::POA_var root_poa=PortableServer::POA::_the_root_poa(); + cout << "ActivateContainerManager ......!!!! " << endl; + SALOME_ContainerManager * myContainer + = new SALOME_ContainerManager(_orb); + } + catch(CORBA::SystemException&) + { + INFOS("Caught CORBA::SystemException."); + } + catch(PortableServer::POA::WrongPolicy&) + { + INFOS("Caught CORBA::WrongPolicyException."); + } + catch(PortableServer::POA::ServantAlreadyActive&) + { + INFOS("Caught CORBA::ServantAlreadyActiveException"); + } + catch(CORBA::Exception&) + { + INFOS("Caught CORBA::Exception."); + } + catch(...) + { + INFOS("Caught unknown exception."); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateContainer(int argc, + char ** argv) +{ + try + { + INFOS("Container thread started"); + + // get or create the child POA + + PortableServer::POA_var factory_poa; + try + { + factory_poa = _root_poa->find_POA("factory_poa",0); + // 0 = no activation (already done if exists) + } + catch (PortableServer::POA::AdapterNonExistent&) + { + INFOS("factory_poa does not exists, create..."); + // define policy objects + PortableServer::ImplicitActivationPolicy_var implicitActivation = + _root_poa->create_implicit_activation_policy( + PortableServer::NO_IMPLICIT_ACTIVATION); + // default = NO_IMPLICIT_ACTIVATION + PortableServer::ThreadPolicy_var threadPolicy = + _root_poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL); + // default = ORB_CTRL_MODEL, other choice SINGLE_THREAD_MODEL + + // create policy list + CORBA::PolicyList policyList; + policyList.length(2); + policyList[0] = PortableServer::ImplicitActivationPolicy:: + _duplicate(implicitActivation); + policyList[1] = PortableServer::ThreadPolicy:: + _duplicate(threadPolicy); + + PortableServer::POAManager_var nil_mgr + = PortableServer::POAManager::_nil(); + factory_poa = _root_poa->create_POA("factory_poa", + nil_mgr, + policyList); + //with nil_mgr instead of pman, + //a new POA manager is created with the new POA + + // destroy policy objects + implicitActivation->destroy(); + threadPolicy->destroy(); + + // obtain the factory poa manager + PortableServer::POAManager_var pmanfac = factory_poa->the_POAManager(); + pmanfac->activate(); + MESSAGE("pmanfac->activate()"); + } + + char *containerName = ""; + if (argc >1) + { + containerName = argv[1]; + } + + Engines_Container_i * myContainer + = new Engines_Container_i(_orb, _root_poa, containerName , argc , argv , true , false); + } + catch(CORBA::SystemException&) + { + INFOS("Caught CORBA::SystemException."); + } + catch(PortableServer::POA::WrongPolicy&) + { + INFOS("Caught CORBA::WrongPolicyException."); + } + catch(PortableServer::POA::ServantAlreadyActive&) + { + INFOS("Caught CORBA::ServantAlreadyActiveException"); + } + catch(CORBA::Exception&) + { + INFOS("Caught CORBA::Exception."); + } + catch(...) + { + INFOS("Caught unknown exception."); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateEngine(int /*argc*/, char ** /*argv*/) +{ + try + { + INFOS("SalomeApp_Engine thread started"); + SalomeApp_Engine_i* anEngine = new SalomeApp_Engine_i(); + /*PortableServer::ObjectId_var id = */_root_poa->activate_object( anEngine ); + INFOS("poa->activate_object( SalomeApp_Engine )"); + + CORBA::Object_ptr obj = anEngine->_this(); + _NS->Register( obj ,"/SalomeAppEngine"); + + } + catch (CORBA::SystemException&) + { + INFOS("Caught CORBA::SystemException."); + } + catch (CORBA::Exception&) + { + INFOS("Caught CORBA::Exception."); + } + catch (...) + { + INFOS("Caught unknown exception."); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Session_ServerThread::ActivateSession(int argc, + char ** argv) +{ + MESSAGE("Session_ServerThread::ActivateSession() not implemented!"); +} + +Session_SessionThread::Session_SessionThread(int argc, + char** argv, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + QMutex* GUIMutex, + QWaitCondition* GUILauncher) +: Session_ServerThread(argc, argv, orb, poa, GUIMutex), + _GUILauncher( GUILauncher ) +{ +} + +Session_SessionThread::~Session_SessionThread() +{ +} + +void Session_SessionThread::ActivateSession(int argc, + char ** argv) +{ + try + { + INFOS("Session thread started"); + SALOME_Session_i * mySALOME_Session + = new SALOME_Session_i(argc, argv, _orb, _root_poa, _GUIMutex, _GUILauncher) ; + PortableServer::ObjectId_var mySALOME_Sessionid + = _root_poa->activate_object(mySALOME_Session); + INFOS("poa->activate_object(mySALOME_Session)"); + + CORBA::Object_var obj = mySALOME_Session->_this(); + CORBA::String_var sior(_orb->object_to_string(obj)); + + mySALOME_Session->NSregister(); + } + catch (CORBA::SystemException&) + { + INFOS("Caught CORBA::SystemException."); + } + catch (CORBA::Exception&) + { + INFOS("Caught CORBA::Exception."); + } + catch (...) + { + INFOS("Caught unknown exception."); + } +}