From: caremoli Date: Thu, 8 Apr 2010 08:00:07 +0000 (+0000) Subject: CCAR: update branch with V5_1_main changes X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=d055de9c04316ac17585ed1d86f2f9eb8ed63d82;p=modules%2Fgui.git CCAR: update branch with V5_1_main changes --- diff --git a/configure.ac b/configure.ac index a666c53d5..f85a2990a 100644 --- a/configure.ac +++ b/configure.ac @@ -573,6 +573,11 @@ AM_CONDITIONAL(ENABLE_SALOMEOBJECT, [test "$DISABLE_SALOMEOBJECT" = no]) AM_CONDITIONAL(ENABLE_QXGRAPHVIEWER, [test "$DISABLE_QXGRAPHVIEWER" = no]) AM_CONDITIONAL(ENABLE_TESTRECORDER, [test "$ENABLE_TESTRECORDER" = yes]) +if test "$DISABLE_PYCONSOLE" = "no" ; then + AC_DEFINE(SUIT_ENABLE_PYTHON) +fi + + echo echo --------------------------------------------- echo generating Makefiles and configure files @@ -600,8 +605,10 @@ AC_OUTPUT([ \ doc/salome/Makefile \ doc/salome/gui/Makefile \ doc/salome/gui/doxyfile \ + doc/salome/gui/static/header.html \ doc/salome/tui/Makefile \ doc/salome/tui/doxyfile \ + doc/salome/tui/static/header.html \ src/Makefile \ src/CASCatch/Makefile \ src/Qtx/Makefile \ diff --git a/doc/salome/gui/Makefile.am b/doc/salome/gui/Makefile.am index 61de9ca86..a0c3a74be 100644 --- a/doc/salome/gui/Makefile.am +++ b/doc/salome/gui/Makefile.am @@ -25,7 +25,10 @@ # include $(top_srcdir)/adm_local/unix/make_common_starter.am -EXTRA_DIST += images input static +EXTRA_DIST += images input static/footer.html static/doxygen.css + +guidocdir = $(docdir)/gui/GUI +guidoc_DATA = images/head.png usr_docs: doxyfile echo "Running doxygen in directory: "`pwd`; \ diff --git a/doc/salome/gui/doxyfile.in b/doc/salome/gui/doxyfile.in index dd9ea6528..a2a8edbb7 100755 --- a/doc/salome/gui/doxyfile.in +++ b/doc/salome/gui/doxyfile.in @@ -22,7 +22,7 @@ #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -PROJECT_NAME = "GUI Module Reference Manual v.@VERSION@" +PROJECT_NAME = "SALOME GUI User's Guide" OUTPUT_DIRECTORY = GUI CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English @@ -46,9 +46,9 @@ IMAGE_PATH = @srcdir@/images #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = . -HTML_HEADER = @srcdir@/static/header.html +HTML_HEADER = @builddir@/static/header.html HTML_FOOTER = @srcdir@/static/footer.html -#HTML_STYLESHEET = @srcdir@/static/doxygen.css +HTML_STYLESHEET = @srcdir@/static/doxygen.css TOC_EXPAND = YES DISABLE_INDEX = NO GENERATE_TREEVIEW = YES diff --git a/doc/salome/gui/images/head.png b/doc/salome/gui/images/head.png new file mode 100755 index 000000000..307d9ef9a Binary files /dev/null and b/doc/salome/gui/images/head.png differ diff --git a/doc/salome/gui/images/ppref3.png b/doc/salome/gui/images/ppref3.png index 8c31ab8a1..1fcefc175 100755 Binary files a/doc/salome/gui/images/ppref3.png and b/doc/salome/gui/images/ppref3.png differ diff --git a/doc/salome/gui/input/postpro_preferences.doc b/doc/salome/gui/input/postpro_preferences.doc index 2f7550fcc..bc1d7deee 100644 --- a/doc/salome/gui/input/postpro_preferences.doc +++ b/doc/salome/gui/input/postpro_preferences.doc @@ -131,6 +131,19 @@ Cache
  • Cycled animation - allows to start a cycled animation of the presentation.
  • Use proportional timing - allows to render the animation with proportional periods of time between every frame (not depending on the time stamps).
  • Clean memory at each frame - this option allows to optimize the performance of the operation.
  • +
  • Dump mode - this option allows to choose a mode of dumping +the animation process. Three modes are available: +
  • +
  • Time stamp frequency - this option is available if +Save animation to AVI file mode is turned on. It provides a +possibility to capture only timestamps with indices divisable by the +specified frequency, that allows to generate less voluminous films.
  • Sweeping preferences
  • diff --git a/doc/salome/gui/static/doxygen.css b/doc/salome/gui/static/doxygen.css new file mode 100644 index 000000000..05f1531f4 --- /dev/null +++ b/doc/salome/gui/static/doxygen.css @@ -0,0 +1,322 @@ +body { + font-family: Arial, Helvetica, sans-serif; + background-color: #ffffff; +} + +h1 { + text-align: center; + text-decoration: none; + border: none; + line-height: 25px; + text-align: center; +// text-transform:uppercase; + background: #D9f4fd; + font-size: 12pt; + font-weight: bold; + border: 1px solid #CCCCCC; + -moz-border-radius: 8px; + -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); +} + +h2 { + font-size: 12pt; + font-weight: bold; +} + +table { + font-size: 10pt; +} + +CAPTION { + font-weight: bold +} + +/* Link in the top navbar */ +A.qindex {} + +A.qindexRef {} + +/* Link to any cross-referenced Doxygen element inside a code section + (ex: header) +*/ +A.code { + text-decoration: none; + font-weight: normal; + color: #4444ee +} + +A.codeRef { + font-weight: normal; + color: #4444ee +} + +A:hover { + text-decoration: none; + background-color: lightblue; +} + +div.contents { + font-family: Arial, Helvetica, sans-serif; + font-size: 10pt; +} + +div.navpath { + font-size: 11pt; +} + +div.version { + background-color:#ffffde; + border:1px solid #cccccc; + font-family: Arial, Helvetica, sans-serif; + font-size: 9pt; + text-align: center; + width:100px; + -moz-border-radius: 8px; +// -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); +} + +div.header { + background: url("head.png"); + background-color: #175783; + border: 1px solid; + height: 80px; + background-repeat: no-repeat; + margin-bottom: 10px; +} + +div.tabs { + display: none; +} + +div.footer { + background-color: #D9f4fd; + border: 1px solid #AAAAAA; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; + padding: 10px; + margin-top: 15px; +} + +DL.el { + margin-left: -1cm +} + +/* A code fragment (ex: header) */ +div.fragment { + border: none; +} + +/* In the alpha list (coumpound index), style of an alphabetical index letter */ +DIV.ah { + background-color: #CCCCCC; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +/* Method name (+ type) */ +TD.md { + background-color: lightblue; + font-weight: bold; +} + +/* Method parameter (some of them) */ +TD.mdname1 { + background-color: lightblue; + font-weight: bold; color: #602020; +} + +/* Method parameter (some of them) */ +TD.mdname { + background-color: lightblue; + font-weight: bold; + color: #602020; + width: 600px; +} + +/* Separator between methods group (usually empty, seems not supported by IE) */ +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold +} + +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: smaller +} + +/*div.div-page { + background-color: #FFFFFF; + margin-left: 1em; + margin-right: 1em; + margin-top: 1em; + margin-bottom: 0.1em; + + padding-left: 1em; + padding-right: 1em; + padding-top: 0.5em; + padding-bottom: 0.5em; + + border: 2px solid #0D299A; + border-width: 2px; + border-color: #0D299A; +}*/ + +div.tabs { + text-align: justify; + margin-left : 2px; + margin-right : 2px; + margin-top : 2px; + margin-bottom : 2px + font-weight: bold; + color: #FFFFFF; +} + +DIV.div-footer { + margin-left: 1em; + margin-right: 1em; + margin-bottom: 0.2em; + text-align: right; + font-size: 9pt; +} + +/* In File List, Coumpound List, etc, 1st column of the index */ +TD.indexkey { + background-color: #CCCCCC; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} + +/* In File List, Coumpound List, etc, 2nd column of the index */ +TD.indexvalue { + background-color: #CCCCCC; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} + +span.keyword { color: #008000 } +span.keywordtype { color: #604020 } +span.keywordflow { color: #e08000 } +span.comment { color: #800000 } +span.preprocessor { color: #806020 } +span.stringliteral { color: #002080 } +span.charliteral { color: #008080 } + +/* @group Code Colorization */ + +.fragment { + font-family: monospace, fixed; + font-size: 10pt; +} + +pre.fragment { + width: 95%; + border: 1px solid #CCCCCC; + -moz-border-radius: 8px; + -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); + background-color:#EEF3F5; + padding: 4px 6px; + margin: 4px 1px 4px 1px; +} + +/* Top Navigation style */ + +div.navigation { + margin-bottom:20px; +} + +/* Left navigation panel style */ + +body.ftvtree { + background-color: #D9f4fd; + margin: 10px; +} + +div.directory { + margin: 0; +} + +div.directory.p { + margin: 0; +} + +h3.swap { + font-size: 10pt; + margin-bottom: 0; +} + +/* Link to any cross-referenced Doxygen element */ +a.el { + text-decoration: none; + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 9pt; + color: #551a8b; +} + +a.el:hover { + background-color: transparent; +} + +a.elRef { + font-weight: normal; +} + + +#MSearchBox { + -moz-border-radius:8px 8px 8px 8px; + background-color:white; + border:1px solid #84B0C7; + margin:0; + padding:0; + white-space:nowrap; +} + +div.directory img { + vertical-align:-30%; +} + +div.directory p { + white-space:nowrap; + margin: 0; +} + +div.directory-alt div { + display: none; + margin: 0px; +} + + +div.directory div { + display: none; + margin: 0px; +} + +div.version { + background-color:#ffffde; + border:1px solid #cccccc; + font-family: Arial, Helvetica, sans-serif; + font-size: 9pt; + text-align: center; + width:100px; + -moz-border-radius: 8px; +// -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); +} diff --git a/doc/salome/gui/static/footer.html b/doc/salome/gui/static/footer.html index 6eab03cf2..012833eac 100755 --- a/doc/salome/gui/static/footer.html +++ b/doc/salome/gui/static/footer.html @@ -3,10 +3,11 @@ -
    + diff --git a/doc/salome/gui/static/header.html b/doc/salome/gui/static/header.html deleted file mode 100755 index a70a95e30..000000000 --- a/doc/salome/gui/static/header.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - $title - - -
    -
    -SALOME documentation central -
    -
    diff --git a/doc/salome/gui/static/header.html.in b/doc/salome/gui/static/header.html.in new file mode 100755 index 000000000..6795e96eb --- /dev/null +++ b/doc/salome/gui/static/header.html.in @@ -0,0 +1,10 @@ + + + + + $title + + +
    +
    Version: @VERSION@
    + diff --git a/doc/salome/tui/Makefile.am b/doc/salome/tui/Makefile.am index af6eaab26..3346fa12d 100644 --- a/doc/salome/tui/Makefile.am +++ b/doc/salome/tui/Makefile.am @@ -25,7 +25,10 @@ # include $(top_srcdir)/adm_local/unix/make_common_starter.am -EXTRA_DIST += images static +EXTRA_DIST += images input static/footer.html static/doxygen.css + +tuidocdir = $(docdir)/tui/GUI +tuidoc_DATA = images/head.png dev_docs: doxyfile echo "Running doxygen in directory: "`pwd`; \ diff --git a/doc/salome/tui/doxyfile.in b/doc/salome/tui/doxyfile.in index 201628e66..6fb6d427a 100755 --- a/doc/salome/tui/doxyfile.in +++ b/doc/salome/tui/doxyfile.in @@ -24,7 +24,7 @@ #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -PROJECT_NAME = "GUI Module Programming Guide v.@VERSION@" +PROJECT_NAME = "SALOME GUI Developer" PROJECT_NUMBER = OUTPUT_DIRECTORY = GUI CREATE_SUBDIRS = NO @@ -99,8 +99,9 @@ WARN_LOGFILE = INPUT = @top_srcdir@/src \ @top_srcdir@/bin \ @top_srcdir@/idl \ - @top_builddir@/bin -FILE_PATTERNS = *.idl *.hxx *.cxx *.h *.c *.hh *.cc @DOXYGEN_PYTHON_EXTENSION@ + @top_builddir@/bin \ + @srcdir@/input +FILE_PATTERNS = *.idl *.hxx *.cxx *.h *.c *.hh *.cc @DOXYGEN_PYTHON_EXTENSION@ *.doc RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO @@ -137,7 +138,7 @@ IGNORE_PREFIX = GENERATE_HTML = YES HTML_OUTPUT = . HTML_FILE_EXTENSION = .html -HTML_HEADER = @srcdir@/static/myheader.html +HTML_HEADER = @builddir@/static/header.html HTML_FOOTER = @srcdir@/static/footer.html HTML_STYLESHEET = @srcdir@/static/doxygen.css HTML_ALIGN_MEMBERS = YES diff --git a/doc/salome/tui/images/Application-About.png b/doc/salome/tui/images/Application-About.png deleted file mode 100755 index 7b58330d5..000000000 Binary files a/doc/salome/tui/images/Application-About.png and /dev/null differ diff --git a/doc/salome/tui/images/application.gif b/doc/salome/tui/images/application.gif deleted file mode 100755 index 0b05d5c18..000000000 Binary files a/doc/salome/tui/images/application.gif and /dev/null differ diff --git a/doc/salome/tui/images/guiscreen.png b/doc/salome/tui/images/guiscreen.png new file mode 100644 index 000000000..bc900e206 Binary files /dev/null and b/doc/salome/tui/images/guiscreen.png differ diff --git a/doc/salome/tui/images/head.png b/doc/salome/tui/images/head.png new file mode 100755 index 000000000..307d9ef9a Binary files /dev/null and b/doc/salome/tui/images/head.png differ diff --git a/doc/salome/tui/images/html_comments.gif b/doc/salome/tui/images/html_comments.gif deleted file mode 100755 index f0c0f0b47..000000000 Binary files a/doc/salome/tui/images/html_comments.gif and /dev/null differ diff --git a/doc/salome/tui/images/logocorp.gif b/doc/salome/tui/images/logocorp.gif deleted file mode 100755 index 7697e0837..000000000 Binary files a/doc/salome/tui/images/logocorp.gif and /dev/null differ diff --git a/doc/salome/tui/static/doxygen.css b/doc/salome/tui/static/doxygen.css index 4893b5e2a..22dcbdc31 100755 --- a/doc/salome/tui/static/doxygen.css +++ b/doc/salome/tui/static/doxygen.css @@ -1,5 +1,32 @@ -H1 { +body { + font-family: Arial, Helvetica, sans-serif; + background-color: #ffffff; +} + +h1 { text-align: center; + text-decoration: none; + border: none; + line-height: 25px; + text-align: center; +// text-transform:uppercase; + background: #D9f4fd; + font-size: 12pt; + font-weight: bold; + border: 1px solid #CCCCCC; + margin-top: 50px; + -moz-border-radius: 8px; + -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); +} + +h2 { + font-size: 12pt; + font-weight: bold; +} + +table { + font-size: 10pt; + padding-left: 20px; } CAPTION { @@ -11,16 +38,6 @@ A.qindex {} A.qindexRef {} -/* Link to any cross-referenced Doxygen element */ -A.el { - text-decoration: none; - font-weight: bold -} - -A.elRef { - font-weight: bold -} - /* Link to any cross-referenced Doxygen element inside a code section (ex: header) */ @@ -37,7 +54,53 @@ A.codeRef { A:hover { text-decoration: none; - background-color: lightblue + background-color: lightblue; +} + +div.contents { + font-family: Arial, Helvetica, sans-serif; + font-size: 10pt; + padding: 20px; +} + +div.navpath { + font-size: 11pt; +} + +div.header { + background: url("head.png"); + background-color: #175783; + border: 1px solid; + height: 80px; + background-repeat: no-repeat; + margin-bottom:20px; +} + +div.tabs { + text-align: justify; + margin-left : 2px; + margin-right : 2px; + margin-top : 2px; + margin-bottom : 2px + font-weight: bold; + color: #FFFFFF; +} + +div.footer { + background-color: #D9f4fd; + border: 1px solid #AAAAAA; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; + padding: 10px; +} + +div.div-footer { + background-color: #D9f4fd; + border: 1px solid #AAAAAA; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; + padding: 10px; + text-align: center; } DL.el { @@ -45,10 +108,8 @@ DL.el { } /* A code fragment (ex: header) */ -DIV.fragment { - width: 100%; +div.fragment { border: none; - background-color: #CCCCCC } /* In the alpha list (coumpound index), style of an alphabetical index letter */ @@ -94,30 +155,36 @@ DIV.groupText { font-size: smaller } -BODY { background: #FFFFFF -} +/*div.div-page { + background-color: #FFFFFF; + margin-left: 1em; + margin-right: 1em; + margin-top: 1em; + margin-bottom: 0.1em; + + padding-left: 1em; + padding-right: 1em; + padding-top: 0.5em; + padding-bottom: 0.5em; -/* BODY { - background: url(sources/bg_salome.gif) -} */ + border: 2px solid #0D299A; + border-width: 2px; + border-color: #0D299A; +}*/ div.tabs { text-align: justify; + margin-left : 2px; + margin-right : 2px; + margin-top : 2px; + margin-bottom : 2px font-weight: bold; color: #FFFFFF; } -DIV.div-footer { - margin-left: 1em; - margin-right: 1em; - margin-bottom: 0.2em; - text-align: right; - font-size: 9pt; -} - /* In File List, Coumpound List, etc, 1st column of the index */ TD.indexkey { - background-color: #CCCCCC; + background-color: #DDDDEE; font-weight: bold; padding-right : 10px; padding-top : 2px; @@ -131,7 +198,7 @@ TD.indexkey { /* In File List, Coumpound List, etc, 2nd column of the index */ TD.indexvalue { - background-color: #CCCCCC; + background-color: #EEEEFF; font-style: italic; padding-right : 10px; padding-top : 2px; @@ -150,3 +217,118 @@ span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } + +/* @group Code Colorization */ + +.fragment { + font-family: monospace, fixed; + font-size: 10pt; +} + +pre.fragment { + width: 95%; + border: 1px solid #CCCCCC; + -moz-border-radius: 8px; + -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); + background-color:#EEF3F5; + padding: 4px 6px; + margin: 20px; +} + +/* Top Navigation style */ + +div.navigation { + margin-bottom:20px; +} + +/* Left navigation panel style */ + +body.ftvtree { + background-color: #D9f4fd; + margin: 10px; +} + +div.directory { + margin: 0; +} + +div.directory.p { + margin: 0; +} + +h3.swap { + font-size: 10pt; + margin-bottom: 0; +} + +/* Link to any cross-referenced Doxygen element */ +a.el { + text-decoration: none; + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 10pt; + color: #551a8b; +} + +a.el:hover { + background-color: transparent; + color: #551acc; +} + +a { +// text-decoration: none; + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 10pt; + color: #551a8b; +} + +a:hover { + background-color: transparent; + color: #551acc; +} + +a.elRef { + font-weight: normal; +} + + +#MSearchBox { + -moz-border-radius:8px 8px 8px 8px; + background-color:white; + border:1px solid #84B0C7; + margin:0; + padding:0; + white-space:nowrap; +} + +div.directory img { + vertical-align:-30%; +} + +div.directory p { + white-space:nowrap; + margin: 0; +} + +div.directory-alt div { + display: none; + margin: 0px; +} + + +div.directory div { + display: none; + margin: 0px; +} + +div.version { + background-color:#ffffde; + border:1px solid #cccccc; + font-family: Arial, Helvetica, sans-serif; + font-size: 9pt; + text-align: center; + width:100px; + -moz-border-radius: 8px; + // -moz-box-shadow:5px 5px 5px rgba(0, 0, 0, 0.15); +} \ No newline at end of file diff --git a/doc/salome/tui/static/footer.html b/doc/salome/tui/static/footer.html index cb55f397a..012833eac 100755 --- a/doc/salome/tui/static/footer.html +++ b/doc/salome/tui/static/footer.html @@ -1,5 +1,13 @@ - - - - + + + + + + + + diff --git a/doc/salome/tui/static/header.html.in b/doc/salome/tui/static/header.html.in new file mode 100755 index 000000000..1c5ad03b6 --- /dev/null +++ b/doc/salome/tui/static/header.html.in @@ -0,0 +1,14 @@ + + + + + + SALOME Geometry Developer Guide + + + + +
    +
    Version: @VERSION@
    + + diff --git a/doc/salome/tui/static/myheader.html b/doc/salome/tui/static/myheader.html deleted file mode 100755 index d2efb75fa..000000000 --- a/doc/salome/tui/static/myheader.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Main Page - - - - -  - - diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index a9fbd8ee0..d32f884de 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -27,8 +27,10 @@ // E.A. : On windows with python 2.6, there is a conflict // E.A. : between pymath.h and Standard_math.h which define // E.A. : some same symbols : acosh, asinh, ... -#include -#include + #include + #ifndef DISABLE_PYCONSOLE + #include + #endif #endif #ifndef DISABLE_PYCONSOLE @@ -95,6 +97,8 @@ #ifndef DISABLE_PLOT2DVIEWER #include #include + #include + #include #include "LightApp_Plot2dSelector.h" #ifndef DISABLE_SALOMEOBJECT #include @@ -1013,6 +1017,12 @@ void LightApp_Application::onHelpContextModule( const QString& theComponentName, */ void LightApp_Application::onSelectionChanged() { + LightApp_Module* m = dynamic_cast( activeModule() ); + bool canCopy = m ? m->canCopy() : false; + bool canPaste = m ? m->canPaste() : false; + + action( EditCopyId )->setEnabled(canCopy); + action( EditPasteId )->setEnabled(canPaste); } /*! @@ -3248,3 +3258,23 @@ void LightApp_Application::clearKnownViewManagers() removeViewManager(aMgr); } } + +/*! + Copy of current selection + */ +void LightApp_Application::onCopy() +{ + LightApp_Module* m = dynamic_cast( activeModule() ); + if( m ) + m->copy(); +} + +/*! + Paste of current data in clipboard + */ +void LightApp_Application::onPaste() +{ + LightApp_Module* m = dynamic_cast( activeModule() ); + if( m ) + m->paste(); +} diff --git a/src/LightApp/LightApp_Application.h b/src/LightApp/LightApp_Application.h index 27d0852af..8a6911a2d 100644 --- a/src/LightApp/LightApp_Application.h +++ b/src/LightApp/LightApp_Application.h @@ -167,6 +167,9 @@ public slots: virtual void onOpenDoc(); virtual void onHelpAbout(); virtual bool onOpenDoc( const QString& ); + virtual void onCopy(); + virtual void onPaste(); + virtual void onSelectionChanged(); protected: virtual void createActions(); @@ -181,7 +184,6 @@ protected: virtual void setActiveStudy( SUIT_Study* ); virtual void updateCommandsStatus(); - virtual void onSelectionChanged(); virtual void beforeCloseDoc( SUIT_Study* ); virtual void afterCloseDoc(); diff --git a/src/LightApp/LightApp_Module.cxx b/src/LightApp/LightApp_Module.cxx index 761853695..db606ec57 100644 --- a/src/LightApp/LightApp_Module.cxx +++ b/src/LightApp/LightApp_Module.cxx @@ -650,6 +650,39 @@ bool LightApp_Module::reusableOperation( const int id ) return true; } +/*! + virtual method + \return true if module can copy the current selection +*/ +bool LightApp_Module::canCopy() const +{ + return false; +} + +/*! + virtual method + \return true if module can paste previously copied data +*/ +bool LightApp_Module::canPaste() const +{ + return false; +} + +/*! + virtual method + \brief Copies the current selection into clipboard +*/ +void LightApp_Module::copy() +{ +} + +/*! + virtual method + \brief Pastes the current data in the clipboard +*/ +void LightApp_Module::paste() +{ +} int LightApp_Module::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) diff --git a/src/LightApp/LightApp_Module.h b/src/LightApp/LightApp_Module.h index 19c857f48..56b0d3356 100644 --- a/src/LightApp/LightApp_Module.h +++ b/src/LightApp/LightApp_Module.h @@ -92,6 +92,11 @@ public: virtual LightApp_Displayer* displayer(); virtual LightApp_Selection* createSelection() const; + virtual bool canCopy() const; + virtual bool canPaste() const; + virtual void copy(); + virtual void paste(); + int createMenu( const QString&, const int, const int = -1, const int = -1, const int = -1 ); int createMenu( const QString&, const QString&, const int = -1, const int = -1, const int = -1 ); int createMenu( const int, const int, const int = -1, const int = -1 ); diff --git a/src/LightApp/LightApp_ModuleAction.cxx b/src/LightApp/LightApp_ModuleAction.cxx index 36c6fa77b..9986c71d9 100755 --- a/src/LightApp/LightApp_ModuleAction.cxx +++ b/src/LightApp/LightApp_ModuleAction.cxx @@ -462,6 +462,7 @@ void LightApp_ModuleAction::update( QtxComboBox* cb ) if ( !cb ) return; + bool blocked = cb->blockSignals( true ); int curId = mySet->moduleId( active() ); QList alist = mySet->actions(); cb->clear(); @@ -478,6 +479,7 @@ void LightApp_ModuleAction::update( QtxComboBox* cb ) } cb->setCurrentId( curId ); + cb->blockSignals( blocked ); } /*! diff --git a/src/LightApp/LightApp_Plot2dSelector.cxx b/src/LightApp/LightApp_Plot2dSelector.cxx index 9efc836b0..cd7543c27 100755 --- a/src/LightApp/LightApp_Plot2dSelector.cxx +++ b/src/LightApp/LightApp_Plot2dSelector.cxx @@ -28,7 +28,7 @@ /*! Constructor */ -LightApp_Plot2dSelector::LightApp_Plot2dSelector( SPlot2d_Viewer* v, SUIT_SelectionMgr* mgr ) +LightApp_Plot2dSelector::LightApp_Plot2dSelector( Plot2d_Viewer* v, SUIT_SelectionMgr* mgr ) : SUIT_Selector( mgr, v ) { if ( v ) diff --git a/src/LightApp/LightApp_Plot2dSelector.h b/src/LightApp/LightApp_Plot2dSelector.h index b9ba299a3..f63c31978 100755 --- a/src/LightApp/LightApp_Plot2dSelector.h +++ b/src/LightApp/LightApp_Plot2dSelector.h @@ -26,7 +26,7 @@ #include #include -#include +#include class LightApp_DataObject; @@ -39,7 +39,7 @@ class LIGHTAPP_EXPORT LightApp_Plot2dSelector : public QObject, public SUIT_Sele Q_OBJECT public: - LightApp_Plot2dSelector( SPlot2d_Viewer*, SUIT_SelectionMgr* ); + LightApp_Plot2dSelector( Plot2d_Viewer*, SUIT_SelectionMgr* ); virtual ~LightApp_Plot2dSelector(); /*!Return "ObjectBrowser"*/ diff --git a/src/OCCViewer/Makefile.am b/src/OCCViewer/Makefile.am index c2041a5d8..b44468c43 100755 --- a/src/OCCViewer/Makefile.am +++ b/src/OCCViewer/Makefile.am @@ -42,7 +42,8 @@ salomeinclude_HEADERS = \ OCCViewer_ClippingDlg.h \ OCCViewer_AxialScaleDlg.h \ OCCViewer_SetRotationPointDlg.h \ - OCCViewer_Trihedron.h + OCCViewer_Trihedron.h \ + OCCViewer_ToolTip.h dist_libOCCViewer_la_SOURCES = \ OCCViewer_AISSelector.cxx \ diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index 65f1bc061..95e21e560 100755 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -468,8 +468,8 @@ void OCCViewer_ViewWindow::activateZoom() if ( myOperation != ZOOMVIEW ) { QPixmap zoomPixmap (imageZoomCursor); QCursor zoomCursor (zoomPixmap); - setTransformRequested ( ZOOMVIEW ); - myViewPort->setCursor( zoomCursor ); + if( setTransformRequested ( ZOOMVIEW ) ) + myViewPort->setCursor( zoomCursor ); } } @@ -486,8 +486,8 @@ void OCCViewer_ViewWindow::activatePanning() if ( myOperation != PANVIEW ) { QCursor panCursor (Qt::SizeAllCursor); - setTransformRequested ( PANVIEW ); - myViewPort->setCursor( panCursor ); + if( setTransformRequested ( PANVIEW ) ) + myViewPort->setCursor( panCursor ); } } @@ -504,8 +504,8 @@ void OCCViewer_ViewWindow::activateRotation() if ( myOperation != ROTATE ) { QPixmap rotatePixmap (imageRotateCursor); QCursor rotCursor (rotatePixmap); - setTransformRequested ( ROTATE ); - myViewPort->setCursor( rotCursor ); + if( setTransformRequested ( ROTATE ) ) + myViewPort->setCursor( rotCursor ); } } @@ -693,8 +693,8 @@ void OCCViewer_ViewWindow::activateGlobalPanning() aView3d->FitAll(0.01, false); myCursor = cursor(); // save old cursor myViewPort->fitAll(); // fits view before selecting a new scene center - setTransformRequested( PANGLOBAL ); - myViewPort->setCursor( glPanCursor ); + if( setTransformRequested( PANGLOBAL ) ) + myViewPort->setCursor( glPanCursor ); } } @@ -710,22 +710,25 @@ void OCCViewer_ViewWindow::activateWindowFit() if ( myOperation != WINDOWFIT ) { QCursor handCursor (Qt::PointingHandCursor); - setTransformRequested ( WINDOWFIT ); - myViewPort->setCursor ( handCursor ); - myCursorIsHand = true; + if( setTransformRequested ( WINDOWFIT ) ) + { + myViewPort->setCursor ( handCursor ); + myCursorIsHand = true; + } } } /*! \brief Start delayed viewer operation. */ -void OCCViewer_ViewWindow::setTransformRequested( OperationType op ) +bool OCCViewer_ViewWindow::setTransformRequested( OperationType op ) { - myOperation = op; - myViewPort->setMouseTracking( myOperation == NOTHING ); + bool ok = transformEnabled( op ); + myOperation = ok ? op : NOTHING; + myViewPort->setMouseTracking( myOperation == NOTHING ); + return ok; } - /*! \brief Handle mouse move event. \param theEvent mouse event @@ -1907,3 +1910,19 @@ void OCCViewer_ViewWindow::setTransformInProcess( bool bOn ) { myEventStarted = bOn; } + +/*! + Set enabled state of transformation (rotate, zoom, etc) +*/ +void OCCViewer_ViewWindow::setTransformEnabled( const OperationType id, const bool on ) +{ + if ( id != NOTHING ) myStatus.insert( id, on ); +} + +/*! + \return enabled state of transformation (rotate, zoom, etc) +*/ +bool OCCViewer_ViewWindow::transformEnabled( const OperationType id ) const +{ + return myStatus.contains( id ) ? myStatus[ id ] : true; +} diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h index 15fd3b61a..182fadbfc 100755 --- a/src/OCCViewer/OCCViewer_ViewWindow.h +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -88,6 +88,9 @@ public: int interactionStyle() const; void setInteractionStyle( const int ); + void setTransformEnabled( const OperationType, const bool ); + bool transformEnabled( const OperationType ) const; + public slots: void onFrontView(); void onViewFitAll(); @@ -138,7 +141,7 @@ protected: /* Transformation selected but not started yet */ bool transformRequested() const; - void setTransformRequested ( OperationType ); + bool setTransformRequested ( OperationType ); /* Transformation is selected and already started */ bool transformInProcess() const; @@ -209,6 +212,9 @@ private: QtxRectRubberBand* myRectBand; //!< selection rectangle rubber band int myInteractionStyle; + + typedef QMap MapOfTransformStatus; + MapOfTransformStatus myStatus; }; #ifdef WIN32 diff --git a/src/Plot2d/Plot2d_ViewFrame.cxx b/src/Plot2d/Plot2d_ViewFrame.cxx index a6f439f23..6addff3e9 100755 --- a/src/Plot2d/Plot2d_ViewFrame.cxx +++ b/src/Plot2d/Plot2d_ViewFrame.cxx @@ -148,6 +148,40 @@ const char* imageCrossCursor[] = { "................................", "................................"}; +const char* yAxisLeft[] = { + "12 12 2 1", + " c None", + ". c #000000", + " ", + " . ", + " ... ", + " . . . ", + " . ", + " . ", + " . . ", + " . . ", + " ........ ", + " . ", + " . ", + " "}; + +const char* yAxisRight[] = { + "12 12 2 1", + " c None", + ". c #000000", + " ", + " . ", + " ... ", + " . . . ", + " . ", + " . ", + " . . ", + " . . ", + " ........ ", + " . ", + " . ", + " "}; + /*! Constructor @@ -272,14 +306,7 @@ 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; - } + mySecondY = prs->isSecondY(); // display all curves from presentation curveList aCurves = prs->getCurves(); @@ -548,6 +575,9 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update ) if ( !curve ) return; + if ( curve->getYAxis() == QwtPlot::yRight ) + mySecondY = true; + // 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 @@ -560,9 +590,9 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update ) updateCurve( curve, update ); } else { - QwtPlotCurve* aPCurve = new QwtPlotCurve( curve->getVerTitle() ); + Plot2d_QwtPlotCurve* aPCurve = new Plot2d_QwtPlotCurve( curve->getVerTitle(), curve->getYAxis() ); aPCurve->attach( myPlot ); - //myPlot->setCurveYAxis(curveKey, curve->getYAxis()); + aPCurve->setYAxis( curve->getYAxis() ); myPlot->getCurves().insert( aPCurve, curve ); if ( curve->isAutoAssign() ) { @@ -593,6 +623,7 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update ) aPCurve->setData( curve->horData(), curve->verData(), curve->nbPoints() ); } updateTitles(); + myPlot->updateYAxisIdentifiers(); if ( update ) myPlot->replot(); } @@ -629,6 +660,7 @@ void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update ) aPCurve->detach(); myPlot->getCurves().remove( aPCurve ); updateTitles(); + myPlot->updateYAxisIdentifiers(); if ( update ) myPlot->replot(); } @@ -750,7 +782,6 @@ void Plot2d_ViewFrame::fitAll() if (mySecondY) { myPlot->setAxisAutoScale( QwtPlot::yRight ); myPlot->replot(); - QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight ); myPlot->setAxisScale( QwtPlot::yRight, y2min, y2max ); } myPlot->replot(); @@ -834,20 +865,35 @@ void Plot2d_ViewFrame::getFitRangeByCurves(double& xMin, double& xMax, double& y2Min, double& y2Max) { CurveDict cdict = getCurves(); - bool empty = true; + bool emptyV1 = true, emptyV2 = true; if ( !cdict.isEmpty() ) { CurveDict::const_iterator it = myPlot->getCurves().begin(); for ( ; it != myPlot->getCurves().end(); it++ ) { + bool isV2 = it.value()->getYAxis() == QwtPlot::yRight; if ( !it.value()->isEmpty() ) { - if ( empty ) { - xMin = yMin = y2Min = 1e150; - xMax = yMax = y2Max = -1e150; + if ( emptyV1 && emptyV2 ) { + xMin = 1e150; + xMax = -1e150; + } + if ( emptyV1 ) { + yMin = 1e150; + yMax = -1e150; } - empty = false; + if ( emptyV2 ) { + y2Min = 1e150; + y2Max = -1e150; + } + isV2 ? emptyV2 = false : emptyV1 = false; xMin = qMin( xMin, it.value()->getMinX() ); xMax = qMax( xMax, it.value()->getMaxX() ); - yMin = qMin( yMin, it.value()->getMinY() ); - yMax = qMax( yMax, it.value()->getMaxY() ); + if ( isV2 ) { + y2Min = qMin( y2Min, it.value()->getMinY() ); + y2Max = qMax( y2Max, it.value()->getMaxY() ); + } + else { + yMin = qMin( yMin, it.value()->getMinY() ); + yMax = qMax( yMax, it.value()->getMaxY() ); + } } } if ( xMin == xMax ) { @@ -858,15 +904,23 @@ void Plot2d_ViewFrame::getFitRangeByCurves(double& xMin, double& xMax, yMin = yMin == 0. ? -1. : yMin - yMin/10.; yMax = yMax == 0. ? 1 : yMax + yMax/10.; } - y2Min = yMin; - y2Max = yMax; + if ( y2Min == y2Max ) { + y2Min = y2Min == 0. ? -1. : y2Min - y2Min/10.; + y2Max = y2Max == 0. ? 1 : y2Max + y2Max/10.; + } } - if ( empty ) { - // default values + // default values + if ( emptyV1 && emptyV2 ) { xMin = isModeHorLinear() ? 0. : 1.; xMax = isModeHorLinear() ? 1000. : 1e5; - yMin = y2Min = isModeVerLinear() ? 0. : 1.; - yMax = y2Max = isModeVerLinear() ? 1000 : 1e5; + } + if ( emptyV1 ) { + yMin = isModeVerLinear() ? 0. : 1.; + yMax = isModeVerLinear() ? 1000. : 1e5; + } + if ( emptyV2 ) { + y2Min = isModeVerLinear() ? 0. : 1.; + y2Max = isModeVerLinear() ? 1000. : 1e5; } } @@ -1698,6 +1752,25 @@ void Plot2d_Plot2d::setLogScale( int axisId, bool log10 ) */ void Plot2d_Plot2d::replot() { + // the following code is intended to enable only axes + // that are really used by displayed curves + bool enableXBottom = false, enableXTop = false; + bool enableYLeft = false, enableYRight = false; + CurveDict::iterator it = myCurves.begin(); + for( ; it != myCurves.end(); it++ ) { + QwtPlotCurve* aCurve = it.key(); + if( aCurve ) { + enableXBottom |= aCurve->xAxis() == QwtPlot::xBottom; + enableXTop |= aCurve->xAxis() == QwtPlot::xTop; + enableYLeft |= aCurve->yAxis() == QwtPlot::yLeft; + enableYRight |= aCurve->yAxis() == QwtPlot::yRight; + } + } + enableAxis( QwtPlot::xBottom, enableXBottom ); + enableAxis( QwtPlot::xTop, enableXTop ); + enableAxis( QwtPlot::yLeft, enableYLeft ); + enableAxis( QwtPlot::yRight, enableYRight ); + updateLayout(); // to fix bug(?) of Qwt - view is not updated when title is changed QwtPlot::replot(); } @@ -1921,6 +1994,36 @@ void Plot2d_Plot2d::onScaleDivChanged() } } +/*! + Updates identifiers of Y axis type in the legend. +*/ +void Plot2d_Plot2d::updateYAxisIdentifiers() +{ + bool enableYLeft = false, enableYRight = false; + CurveDict::iterator it = myCurves.begin(); + for( ; it != myCurves.end(); it++ ) { + QwtPlotCurve* aCurve = it.key(); + if( aCurve ) { + enableYLeft |= aCurve->yAxis() == QwtPlot::yLeft; + enableYRight |= aCurve->yAxis() == QwtPlot::yRight; + } + } + + // if several curves are attached to different axes + // display corresponding identifiers in the legend, + // otherwise hide them + for( it = myCurves.begin(); it != myCurves.end(); it++ ) + if( Plot2d_QwtPlotCurve* aPCurve = dynamic_cast( it.key() ) ) + aPCurve->setYAxisIdentifierEnabled( enableYLeft && enableYRight ); + + const QwtPlotItemList& anItemList = itemList(); + for( QwtPlotItemIterator anItemIter = anItemList.begin(); anItemIter != anItemList.end(); ++anItemIter ) { + QwtPlotItem* anItem = *anItemIter; + if( anItem && anItem->isVisible() ) + anItem->updateLegend( legend() ); + } +} + /*! Sets the flag saying that QwtPlot geometry has been fully defined. */ @@ -1989,8 +2092,10 @@ void Plot2d_ViewFrame::updateTitles() //QIntDictIterator it( myCurves ); QStringList aXTitles; QStringList aYTitles; + QStringList aY2Titles; QStringList aXUnits; QStringList aYUnits; + QStringList aY2Units; QStringList aTables; int i = 0; @@ -2002,14 +2107,22 @@ void Plot2d_ViewFrame::updateTitles() QString yTitle = aCurve->getVerTitle().trimmed(); QString xUnits = aCurve->getHorUnits().trimmed(); QString yUnits = aCurve->getVerUnits().trimmed(); + bool isY2 = aCurve->getYAxis() == QwtPlot::yRight; - aYTitles.append( yTitle ); if ( !aXTitles.contains( xTitle ) ) aXTitles.append( xTitle ); if ( !aXUnits.contains( xUnits ) ) aXUnits.append( xUnits ); - if ( !aYUnits.contains( yUnits ) ) - aYUnits.append( yUnits ); + if ( isY2 ) { + aY2Titles.append( yTitle ); + if ( !aY2Units.contains( yUnits ) ) + aY2Units.append( yUnits ); + } + else { + aYTitles.append( yTitle ); + if ( !aYUnits.contains( yUnits ) ) + aYUnits.append( yUnits ); + } QString aName = aCurve->getTableTitle(); if( !aName.isEmpty() && !aTables.contains( aName ) ) @@ -2017,24 +2130,32 @@ void Plot2d_ViewFrame::updateTitles() ++i; } // ... and update plot 2d view - QString xUnits, yUnits; + QString xUnits, yUnits, y2Units; 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 ( aY2Units.count() == 1 && !aY2Units[0].isEmpty()) + y2Units = BRACKETIZE( aY2Units[0] ); + QString xTitle, yTitle, y2Title; if ( aXTitles.count() == 1 && aXUnits.count() == 1 ) xTitle = aXTitles[0]; if ( aYTitles.count() == 1 ) yTitle = aYTitles[0]; + if ( aY2Titles.count() == 1 ) + y2Title = aY2Titles[0]; if ( !xTitle.isEmpty() && !xUnits.isEmpty() ) xTitle += " "; if ( !yTitle.isEmpty() && !yUnits.isEmpty() ) yTitle += " "; + if ( !y2Title.isEmpty() && !y2Units.isEmpty() ) + y2Title += " "; setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, true ); setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, true ); + if ( mySecondY ) + setTitle( myY2TitleEnabled, y2Title + y2Units, Y2Title, true ); setTitle( true, aTables.join("; "), MainTitle, true ); } @@ -2255,3 +2376,101 @@ QwtText Plot2d_ScaleDraw::label( double value ) const return QwtScaleDraw::label( value ); } + +/*! + Constructor of Plot2d_QwtLegendItem +*/ +Plot2d_QwtLegendItem::Plot2d_QwtLegendItem( QWidget* parent ) : + QwtLegendItem( parent ), + myYAxisIdentifierMode( IM_None ) +{ + myYAxisLeftIcon = yAxisLeft; + myYAxisRightIcon = yAxisRight; + int anIconWidth = qMax( myYAxisLeftIcon.width(), myYAxisRightIcon.width() ); + + mySpacingCollapsed = spacing(); + mySpacingExpanded = anIconWidth - mySpacingCollapsed; +} + +/*! + Destructor of Plot2d_QwtLegendItem +*/ +Plot2d_QwtLegendItem::~Plot2d_QwtLegendItem() +{ +} + +/*! + Set Y axis identifier displaying mode +*/ +void Plot2d_QwtLegendItem::setYAxisIdentifierMode( const int theMode ) +{ + myYAxisIdentifierMode = theMode; + setSpacing( theMode == IM_None ? mySpacingCollapsed : mySpacingExpanded ); +} + +/*! + Redefined method of drawing identifier of legend item +*/ +void Plot2d_QwtLegendItem::drawIdentifier( QPainter* painter, const QRect& rect ) const +{ + QwtLegendItem::drawIdentifier( painter, rect ); + + if( myYAxisIdentifierMode != IM_None ) { + QPixmap aPixmap( myYAxisIdentifierMode == IM_Left ? yAxisLeft : yAxisRight ); + painter->save(); + painter->drawPixmap( rect.topRight() + QPoint( mySpacingExpanded/2, mySpacingExpanded/2 ), aPixmap ); + painter->restore(); + } +} + +/*! + Constructor of Plot2d_QwtPlotCurve +*/ +Plot2d_QwtPlotCurve::Plot2d_QwtPlotCurve( const QString& title, + QwtPlot::Axis yAxis /*const int index*/ ) : + QwtPlotCurve( title ), + myYAxis( yAxis ), + myYAxisIdentifierEnabled( false ) +{ +} + +/*! + Destructor of Plot2d_QwtPlotCurve +*/ +Plot2d_QwtPlotCurve::~Plot2d_QwtPlotCurve() +{ +} + +/*! + Enable / disable Y axis identifier +*/ +void Plot2d_QwtPlotCurve::setYAxisIdentifierEnabled( const bool on ) +{ + myYAxisIdentifierEnabled = on; +} + +/*! + Redefined method, which updates legend of the curve +*/ +void Plot2d_QwtPlotCurve::updateLegend( QwtLegend* legend ) const +{ + QwtPlotCurve::updateLegend( legend ); + + QWidget* widget = legend->find( this ); + if( Plot2d_QwtLegendItem* anItem = dynamic_cast( widget ) ) { + int aMode = Plot2d_QwtLegendItem::IM_None; + if( myYAxisIdentifierEnabled ) + aMode = myYAxis == QwtPlot::yRight ? + Plot2d_QwtLegendItem::IM_Right : + Plot2d_QwtLegendItem::IM_Left; + anItem->setYAxisIdentifierMode( aMode ); + } +} + +/*! + Redefined method, which creates and returns legend item of the curve +*/ +QWidget* Plot2d_QwtPlotCurve::legendItem() const +{ + return new Plot2d_QwtLegendItem; +} diff --git a/src/Plot2d/Plot2d_ViewFrame.h b/src/Plot2d/Plot2d_ViewFrame.h index 16aca311a..55b616898 100755 --- a/src/Plot2d/Plot2d_ViewFrame.h +++ b/src/Plot2d/Plot2d_ViewFrame.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -227,6 +229,8 @@ public: CurveDict& getCurves() { return myCurves; } Plot2d_Curve* getClosestCurve( QPoint p, double& distance, int& index ); + virtual void updateYAxisIdentifiers(); + public slots: virtual void polish(); @@ -259,4 +263,45 @@ private: int myPrecision; }; +class Plot2d_QwtLegendItem : public QwtLegendItem +{ +public: + enum YAxisIdentifierMode { IM_None = 0, IM_Left, IM_Right }; + +public: + Plot2d_QwtLegendItem( QWidget* = 0 ); + virtual ~Plot2d_QwtLegendItem(); + +public: + void setYAxisIdentifierMode( const int ); + +protected: + virtual void drawIdentifier( QPainter*, const QRect& ) const; + +private: + int myYAxisIdentifierMode; + QPixmap myYAxisLeftIcon; + QPixmap myYAxisRightIcon; + int mySpacingCollapsed; + int mySpacingExpanded; +}; + +class Plot2d_QwtPlotCurve : public QwtPlotCurve +{ +public: + Plot2d_QwtPlotCurve( const QString&, QwtPlot::Axis = QwtPlot::yLeft ); + virtual ~Plot2d_QwtPlotCurve(); + +public: + virtual void setYAxisIdentifierEnabled( const bool ); + +protected: + virtual void updateLegend( QwtLegend* ) const; + virtual QWidget* legendItem() const; + +private: + QwtPlot::Axis myYAxis; + bool myYAxisIdentifierEnabled; +}; + #endif diff --git a/src/QDS/QDS_ComboBox.cxx b/src/QDS/QDS_ComboBox.cxx index a2a26f279..acd8db018 100644 --- a/src/QDS/QDS_ComboBox.cxx +++ b/src/QDS/QDS_ComboBox.cxx @@ -302,7 +302,7 @@ void QDS_ComboBox::setValues( const QList& ids, const QStringList& names ) myUserIds = ids; myUserNames = names; - unitSystemChanged( "" ); + //unitSystemChanged( "" ); } /*! diff --git a/src/QDS/QDS_Datum.cxx b/src/QDS/QDS_Datum.cxx index 4394119f5..609b28e71 100644 --- a/src/QDS/QDS_Datum.cxx +++ b/src/QDS/QDS_Datum.cxx @@ -342,7 +342,7 @@ QString QDS_Datum::label() const if( labStr.isNull() ) labStr = toQString( myDicItem->GetId() ); } - if( myTr ) + if( myTr && labStr.length()>0 ) { QString dest = QApplication::translate( "QDS", labStr.toLatin1().constData() ); if( labStr != dest ) diff --git a/src/Qtx/QtxActionMenuMgr.cxx b/src/Qtx/QtxActionMenuMgr.cxx index 90acf3ff7..9359f1215 100644 --- a/src/Qtx/QtxActionMenuMgr.cxx +++ b/src/Qtx/QtxActionMenuMgr.cxx @@ -491,8 +491,19 @@ void QtxActionMenuMgr::remove( const int id, const int pId, const int group ) delNodes.append( *it ); } + QWidget* mW = menuWidget( pNode ); for ( NodeList::iterator itr = delNodes.begin(); itr != delNodes.end(); ++itr ) + { + int id = (*itr)->id; + if( mW && menuAction( id ) ) + { + mW->removeAction( menuAction( id ) ); + myMenus.remove( id ); + } + else if( mW && itemAction( id ) ) + mW->removeAction( itemAction( id ) ); pNode->children.removeAll( *itr ); + } triggerUpdate( pNode->id, false ); } @@ -984,8 +995,10 @@ bool QtxActionMenuMgr::ownAction( QAction* a, MenuNode* node ) const for ( NodeList::const_iterator iter = node->children.begin(); iter != node->children.end(); ++iter ) { QAction* mya = itemAction( (*iter)->id ); - if ( !mya ) mya = menuAction( (*iter)->id ); - if ( mya && mya == a ) return true; + if ( !mya ) + mya = menuAction( (*iter)->id ); + if ( mya && mya == a ) + return true; } return false; } diff --git a/src/Qtx/QtxComboBox.cxx b/src/Qtx/QtxComboBox.cxx index 74425a788..f02d4d464 100755 --- a/src/Qtx/QtxComboBox.cxx +++ b/src/Qtx/QtxComboBox.cxx @@ -133,7 +133,6 @@ QtxComboBox::QtxComboBox( QWidget* parent ) : QComboBox( parent ), myCleared( false ) { - connect( this, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) ); connect( this, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) ); setModel( new Model( this ) ); } @@ -235,16 +234,6 @@ void QtxComboBox::customEvent( QEvent* e ) lineEdit()->setText( "" ); } -/*! - \brief Called when any item is activated by the user. - \param idx activated item index -*/ -void QtxComboBox::onActivated( int idx ) -{ - resetClear(); - emit activatedId( id( idx ) ); -} - /*! \brief Called when current item is chaned (by the user or programmatically). \param idx item being set current @@ -252,7 +241,10 @@ void QtxComboBox::onActivated( int idx ) void QtxComboBox::onCurrentChanged( int idx ) { if ( idx != -1 ) + { resetClear(); + emit activatedId( id( idx ) ); + } } /*! diff --git a/src/Qtx/QtxComboBox.h b/src/Qtx/QtxComboBox.h index 345881b32..68748f8e2 100755 --- a/src/Qtx/QtxComboBox.h +++ b/src/Qtx/QtxComboBox.h @@ -61,7 +61,6 @@ signals: void activatedId( int ); private slots: - void onActivated( int ); void onCurrentChanged( int ); protected: diff --git a/src/Qtx/QtxDialog.cxx b/src/Qtx/QtxDialog.cxx index f20e41353..a2b86279b 100755 --- a/src/Qtx/QtxDialog.cxx +++ b/src/Qtx/QtxDialog.cxx @@ -440,7 +440,7 @@ QSize QtxDialog::Border::minimumSizeHint() const \param wf dialog box flags (Qt::WindowFlags) */ QtxDialog::QtxDialog( QWidget* parent, bool modal, bool allowResize, const int f, Qt::WindowFlags wf ) -: QDialog( parent, (Qt::WindowFlags)( wf | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint | Qt::Dialog | +: QDialog( parent, (Qt::WindowFlags)( wf | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::Dialog | #ifdef WIN32 ( allowResize ? 0 : Qt::FramelessWindowHint ) | #endif diff --git a/src/Qtx/QtxDoubleSpinBox.cxx b/src/Qtx/QtxDoubleSpinBox.cxx index dad449f6c..579509e92 100644 --- a/src/Qtx/QtxDoubleSpinBox.cxx +++ b/src/Qtx/QtxDoubleSpinBox.cxx @@ -27,6 +27,8 @@ #include #include +#include + /*! \class QtxDoubleSpinBox \brief Enhanced version of the Qt's double spin box. @@ -48,6 +50,15 @@ ... // process entered value } \endcode + + Another useful feature is possibility to use scientific notation (e.g. 1.234e+18) + for the widegt text. To enable this, negative precision should be specified either + through a constructor or using setPrecision() method. + + Note that "decimals" property of QDoubleSpinBox is almost completely substituted + by "myPrecision" field of QtxDoubleSpinBox class. "decimals" is still used + for proper size hint calculation and for rounding minimum and maximum bounds of + the spin box range. */ /*! @@ -97,12 +108,15 @@ QtxDoubleSpinBox::QtxDoubleSpinBox( double min, double max, double step, QWidget \brief Constructor. Constructs a spin box with specified minimum, maximum and step value. - The precision is set to 2 decimal places. + The precision is set to decimal places. The value is initially set to the minimum value. \param min spin box minimum possible value \param max spin box maximum possible value \param step spin box increment/decrement value + \param prec non-negative values means the number of digits after the decimal point, + negative value means the maximum number of significant digits for the scientific notation + \param dec number of digits after the decimal point passed to base Qt class (used for correct control sizing only!) \param parent parent object */ QtxDoubleSpinBox::QtxDoubleSpinBox( double min, double max, double step, int prec, int dec, QWidget* parent ) @@ -202,7 +216,7 @@ double QtxDoubleSpinBox::valueFromText( const QString& text ) const */ QString QtxDoubleSpinBox::textFromValue( double val ) const { - QString s = QLocale().toString( val, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : qAbs( myPrecision ) ); + QString s = QLocale().toString( val, myPrecision >= 0 ? 'f' : 'g', qAbs( myPrecision ) ); return removeTrailingZeroes( s ); } @@ -256,19 +270,23 @@ void QtxDoubleSpinBox::stepBy( int steps ) */ QValidator::State QtxDoubleSpinBox::validate( QString& str, int& pos ) const { - if (myPrecision >= 0) - return QDoubleSpinBox::validate(str, pos); - QString pref = this->prefix(); QString suff = this->suffix(); uint overhead = pref.length() + suff.length(); QValidator::State state = QValidator::Invalid; - + QDoubleValidator v (NULL); - v.setDecimals( decimals() ); + + // If 'g' format is used (myPrecision < 0), then + // myPrecision - 1 digits are allowed after the decimal point. + // Otherwise, expect myPrecision digits after the decimal point. + int decs = myPrecision < 0 ? qAbs( myPrecision ) - 1 : myPrecision; + + v.setDecimals( decs ); v.setBottom( minimum() ); v.setTop( maximum() ); - v.setNotation( QDoubleValidator::ScientificNotation ); + v.setNotation( myPrecision >= 0 ? QDoubleValidator::StandardNotation : + QDoubleValidator::ScientificNotation ); if ( overhead == 0 ) state = v.validate( str, pos ); @@ -300,6 +318,29 @@ QValidator::State QtxDoubleSpinBox::validate( QString& str, int& pos ) const } } } + + // Treat values ouside (min; max) range as Invalid + if ( state == QValidator::Intermediate ){ + bool isOk; + double val = str.toDouble( &isOk ); + if ( isOk ){ + if ( val < minimum() || val > maximum() ) + state = QValidator::Invalid; + } + else if ( myPrecision < 0 ){ + // Consider too large negative exponent as Invalid + QChar e( QLocale().exponential() ); + int epos = str.indexOf( e, 0, Qt::CaseInsensitive ); + if ( epos != -1 ){ + epos++; // Skip exponential symbol itself + QString exponent = str.right( str.length() - epos ); + int expValue = exponent.toInt( &isOk ); + if ( isOk && expValue < std::numeric_limits::min_exponent10 ) + state = QValidator::Invalid; + } + } + } + return state; } diff --git a/src/Qtx/QtxPagePrefMgr.cxx b/src/Qtx/QtxPagePrefMgr.cxx index 6fb5b4359..674f59119 100644 --- a/src/Qtx/QtxPagePrefMgr.cxx +++ b/src/Qtx/QtxPagePrefMgr.cxx @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -2210,6 +2211,201 @@ void QtxPagePrefEditItem::updateEditor() myEditor->setValidator( val ); } +/*! + \class QtxPagePrefSliderItem +*/ + +/*! + \brief Constructor. + + Creates preference item with slider widget + + \param title preference item title + \param parent parent preference item + \param sect resource file section associated with the preference item + \param param resource file parameter associated with the preference item +*/ +QtxPagePrefSliderItem::QtxPagePrefSliderItem( const QString& title, QtxPreferenceItem* parent, + const QString& sect, const QString& param ) +: QtxPageNamedPrefItem( title, parent, sect, param ) +{ + setControl( mySlider = new QSlider( Qt::Horizontal ) ); + mySlider->setTickPosition( QSlider::TicksBothSides ); + + updateSlider(); +} + +/*! + \brief Destructor. +*/ +QtxPagePrefSliderItem::~QtxPagePrefSliderItem() +{ +} + +/*! + \brief Get slider preference item step value. + \return slider single step value + \sa setSingleStep() +*/ +int QtxPagePrefSliderItem::singleStep() const +{ + return mySlider->singleStep(); +} + +/*! + \brief Get slider preference item step value. + \return slider page step value + \sa setPageStep() +*/ +int QtxPagePrefSliderItem::pageStep() const +{ + return mySlider->pageStep(); +} + +/*! + \brief Get slider preference item minimum value. + \return slider minimum value + \sa setMinimum() +*/ +int QtxPagePrefSliderItem::minimum() const +{ + return mySlider->minimum(); +} + +/*! + \brief Get slider preference item maximum value. + \return slider maximum value + \sa setMaximum() +*/ +int QtxPagePrefSliderItem::maximum() const +{ + return mySlider->maximum(); +} + +/*! + \brief Set slider preference item step value. + \param step new slider single step value + \sa step() +*/ +void QtxPagePrefSliderItem::setSingleStep( const int& step ) +{ + mySlider->setSingleStep( step ); +} + +/*! + \brief Set slider preference item step value. + \param step new slider single step value + \sa step() +*/ +void QtxPagePrefSliderItem::setPageStep( const int& step ) +{ + mySlider->setPageStep( step ); +} + +/*! + \brief Set slider preference item minimum value. + \param min new slider minimum value + \sa minimum() +*/ +void QtxPagePrefSliderItem::setMinimum( const int& min ) +{ + mySlider->setMinimum( min ); +} + +/*! + \brief Set slider preference item maximum value. + \param min new slider maximum value + \sa maximum() +*/ +void QtxPagePrefSliderItem::setMaximum( const int& max ) +{ + mySlider->setMaximum( max ); +} + +/*! + \brief Store preference item to the resource manager. + \sa retrieve() +*/ +void QtxPagePrefSliderItem::store() +{ + setInteger( mySlider->value() ); +} + +/*! + \brief Retrieve preference item from the resource manager. + \sa store() +*/ +void QtxPagePrefSliderItem::retrieve() +{ + mySlider->setValue( getInteger( mySlider->value() ) ); +} + +/*! + \brief Get preference item option value. + \param name option name + \return property value or null integer if option is not set + \sa setOptionValue() +*/ +QVariant QtxPagePrefSliderItem::optionValue( const QString& name ) const +{ + if ( name == "minimum" || name == "min" ) + return minimum(); + else if ( name == "maximum" || name == "max" ) + return maximum(); + else if ( name == "single_step" ) + return singleStep(); + else if ( name == "page_step" ) + return pageStep(); + else + return QtxPageNamedPrefItem::optionValue( name ); +} + +/*! + \brief Set preference item option value. + \param name option name + \param val new property value + \sa optionValue() +*/ +void QtxPagePrefSliderItem::setOptionValue( const QString& name, const QVariant& val ) +{ + if ( val.canConvert( QVariant::Int ) ) + { + if ( name == "minimum" || name == "min" ) + setMinimum( val.toInt() ); + else if ( name == "maximum" || name == "max" ) + setMaximum( val.toInt() ); + else if ( name == "single_step" ) + setSingleStep( val.toInt() ); + else if ( name == "page_step" ) + setPageStep( val.toInt() ); + else + QtxPageNamedPrefItem::setOptionValue( name, val ); + } + else + QtxPageNamedPrefItem::setOptionValue( name, val ); +} + +/*! + \brief Update slider widget. +*/ +void QtxPagePrefSliderItem::updateSlider() +{ + int val = mySlider->value(); + int stp = singleStep(); + int ptp = pageStep(); + int min = minimum(); + int max = maximum(); + + control()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + mySlider->setFocusPolicy(Qt::StrongFocus); + + mySlider->setValue( val ); + setSingleStep( stp ); + setPageStep( ptp ); + setMinimum( min ); + setMaximum( max ); +} + /*! \class QtxPagePrefSelectItem \brief GUI implementation of the resources selector item diff --git a/src/Qtx/QtxPagePrefMgr.h b/src/Qtx/QtxPagePrefMgr.h index bbc634240..bd785c716 100644 --- a/src/Qtx/QtxPagePrefMgr.h +++ b/src/Qtx/QtxPagePrefMgr.h @@ -51,6 +51,7 @@ class QListWidget; class QFileDialog; class QDateTimeEdit; class QStackedWidget; +class QSlider; class QTX_EXPORT QtxPagePrefMgr : public QFrame, public QtxPreferenceMgr { @@ -418,6 +419,37 @@ private: QLineEdit* myEditor; }; +class QTX_EXPORT QtxPagePrefSliderItem : public QtxPageNamedPrefItem +{ +public: + QtxPagePrefSliderItem( const QString&, QtxPreferenceItem* = 0, + const QString& = QString(), const QString& = QString() ); + virtual ~QtxPagePrefSliderItem(); + + int singleStep() const; + int pageStep() const; + int minimum() const; + int maximum() const; + + void setSingleStep( const int& ); + void setPageStep( const int& ); + void setMinimum( const int& ); + void setMaximum( const int& ); + + virtual void store(); + virtual void retrieve(); + +protected: + virtual QVariant optionValue( const QString& ) const; + virtual void setOptionValue( const QString&, const QVariant& ); + +private: + void updateSlider(); + +private: + QSlider* mySlider; +}; + class QTX_EXPORT QtxPagePrefSelectItem : public QtxPageNamedPrefItem { public: diff --git a/src/SUIT/SUIT_PreferenceMgr.cxx b/src/SUIT/SUIT_PreferenceMgr.cxx index 512fdafa0..9d21a2fcf 100644 --- a/src/SUIT/SUIT_PreferenceMgr.cxx +++ b/src/SUIT/SUIT_PreferenceMgr.cxx @@ -132,6 +132,9 @@ int SUIT_PreferenceMgr::addItem( const QString& title, const int pId, case Integer: item = new QtxPagePrefEditItem( QtxPagePrefEditItem::Integer, title, parent, sect, param ); break; + case Slider: + item = new QtxPagePrefSliderItem( title, parent, sect, param ); + break; case GroupBox: item = new QtxPagePrefGroupItem( title, parent, sect, param ); break; diff --git a/src/SUIT/SUIT_PreferenceMgr.h b/src/SUIT/SUIT_PreferenceMgr.h index f6987252f..8c9458e3c 100644 --- a/src/SUIT/SUIT_PreferenceMgr.h +++ b/src/SUIT/SUIT_PreferenceMgr.h @@ -39,7 +39,7 @@ class SUIT_EXPORT SUIT_PreferenceMgr : public QtxPagePrefMgr public: typedef enum { Auto, Space, Bool, Color, String, Selector, DblSpin, IntSpin, Double, Integer, - GroupBox, Tab, Frame, Font, DirList, File } PrefItemType; + GroupBox, Tab, Frame, Font, DirList, File, Slider } PrefItemType; public: SUIT_PreferenceMgr( QtxResourceMgr*, QWidget* = 0 ); diff --git a/src/SUIT/SUIT_TreeModel.cxx b/src/SUIT/SUIT_TreeModel.cxx index 3c32c174d..90b1049b5 100755 --- a/src/SUIT/SUIT_TreeModel.cxx +++ b/src/SUIT/SUIT_TreeModel.cxx @@ -580,7 +580,7 @@ QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr ) { for( int i=0, n=myColumns.size(); i -#endif +//#define SUIT_ENABLE_PYTHON +//#include +//#endif #ifdef SUIT_ENABLE_PYTHON #include "SUITApp_init_python.hxx" #endif -#endif //#if defined WIN32 +//#endif //#if defined WIN32 #include "SUITApp_Application.h" @@ -287,7 +287,7 @@ int main( int argc, char* argv[] ) PyEval_RestoreThread( SUIT_PYTHON::_gtstate ); if ( !SUIT_PYTHON::salome_shared_modules_module ) // import only once - SUIT_PYTHON::salome_shared_modules_module = PyImport_ImportModule( "salome_shared_modules" ); + SUIT_PYTHON::salome_shared_modules_module = PyImport_ImportModule( (char*)"salome_shared_modules" ); if ( !SUIT_PYTHON::salome_shared_modules_module ) PyErr_Print(); diff --git a/src/SVTK/SALOME_Actor.cxx b/src/SVTK/SALOME_Actor.cxx index 604f25905..6a04c382b 100644 --- a/src/SVTK/SALOME_Actor.cxx +++ b/src/SVTK/SALOME_Actor.cxx @@ -269,15 +269,12 @@ void SALOME_Actor ::AddToRender(vtkRenderer* theRenderer) { - // these two actors have to be added first - // for correct visualization of selection - theRenderer->AddActor( myHighlightActor.GetPointer() ); - theRenderer->AddActor( myPreHighlightActor.GetPointer() ); - Superclass::AddToRender(theRenderer); myRenderer = theRenderer; + theRenderer->AddActor( myPreHighlightActor.GetPointer() ); + theRenderer->AddActor( myHighlightActor.GetPointer() ); theRenderer->AddActor( myOutlineActor.GetPointer() ); theRenderer->AddActor( myNameActor.GetPointer() ); } @@ -289,11 +286,10 @@ void SALOME_Actor ::RemoveFromRender(vtkRenderer* theRenderer) { - theRenderer->RemoveActor( myHighlightActor.GetPointer() ); - theRenderer->RemoveActor( myPreHighlightActor.GetPointer() ); - Superclass::RemoveFromRender(theRenderer); + theRenderer->RemoveActor( myPreHighlightActor.GetPointer() ); + theRenderer->RemoveActor( myHighlightActor.GetPointer() ); theRenderer->RemoveActor( myOutlineActor.GetPointer() ); theRenderer->RemoveActor( myNameActor.GetPointer() ); } diff --git a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx index f83897839..896c8528b 100644 --- a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx @@ -33,6 +33,8 @@ #include #include +#include +#include #include @@ -54,7 +56,9 @@ SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( QWidget* parent ) myDefaultValue( 0.0 ), myIsRangeSet( false ), myMinimum( 0.0 ), - myMaximum( 99.99 ) + myMaximum( 99.99 ), + myAcceptNames( true ), + myShowTip( true ) { connectSignalsAndSlots(); } @@ -76,7 +80,9 @@ SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double myDefaultValue( 0.0 ), myIsRangeSet( false ), myMinimum( min ), - myMaximum( max ) + myMaximum( max ), + myAcceptNames( true ), + myShowTip( true ) { connectSignalsAndSlots(); } @@ -92,13 +98,24 @@ SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double \param max spin box maximum possible value \param step spin box increment/decrement value \param parent parent object + \param acceptNames if true, enables variable names in the spin box + \param showTip if true, makes the widget show a tooltip when invalid text is entered by the user */ -SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double step, int prec, int dec, QWidget* parent ) +SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, + double max, + double step, + int prec, + int dec, + QWidget* parent, + bool acceptNames, + bool showTip ) : QtxDoubleSpinBox( min, max, step, prec, dec, parent ), myDefaultValue( 0.0 ), myIsRangeSet( false ), myMinimum( min ), - myMaximum( max ) + myMaximum( max ), + myAcceptNames( acceptNames ), + myShowTip( showTip ) { connectSignalsAndSlots(); } @@ -110,6 +127,33 @@ SalomeApp_DoubleSpinBox::~SalomeApp_DoubleSpinBox() { } +/*! + \brief Perform \a steps increment/decrement steps. + + Re-implemented to handle cases when Notebook variable + name is specified by the user as the widget text. + Otherwise, simply calls the base implementation. + + \param steps number of increment/decrement steps +*/ +void SalomeApp_DoubleSpinBox::stepBy( int steps ) +{ + QString str = text(); + QString pref = prefix(); + QString suff = suffix(); + + if ( pref.length() && str.startsWith( pref ) ) + str = str.right( str.length() - pref.length() ); + if ( suff.length() && str.endsWith( suff ) ) + str = str.left( str.length() - suff.length() ); + + QRegExp varNameMask( "([a-z]|[A-Z]|_).*" ); + if ( varNameMask.exactMatch( str ) ) + return; + + QtxDoubleSpinBox::stepBy( steps ); +} + /*! \brief Connect signals and slots. */ @@ -187,7 +231,67 @@ QString SalomeApp_DoubleSpinBox::textFromValue( double val ) const */ QValidator::State SalomeApp_DoubleSpinBox::validate( QString& str, int& pos ) const { - return QValidator::Acceptable; + QValidator::State res = QValidator::Invalid; + + // Considering the input text as a variable name + // Applying Python identifier syntax: + // either a string starting with a letter, or a string starting with + // an underscore followed by at least one alphanumeric character + if ( isAcceptNames() ){ + QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" ); + if ( varNameMask.exactMatch( str ) ) + res = QValidator::Acceptable; + + if ( res == QValidator::Invalid ){ + varNameMask.setPattern( "_" ); + if ( varNameMask.exactMatch( str ) ) + res = QValidator::Intermediate; + } + } + + // Trying to interpret the current input text as a numeric value + if ( res == QValidator::Invalid ) + res = QtxDoubleSpinBox::validate( str, pos ); + + // Show tooltip in case of invalid manual input + if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){ + if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state??? + SalomeApp_DoubleSpinBox* that = const_cast( this ); + QPoint pos( size().width(), 0. ); + QPoint globalPos = mapToGlobal( pos ); + QString minVal = textFromValue( minimum() ); + QString maxVal = textFromValue( maximum() ); + + // Same stuff as in QtxDoubleSpinBox::textFromValue() + int digits = getPrecision(); + + // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1 + // See also QtxDoubleSpinBox::validate() + if ( digits < 0 ) + digits = qAbs( digits ) - 1; + + QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) ); + QString msg( templ.arg( minVal ).arg( maxVal ).arg( digits ) ); + + // Add extra hints to the message (if any passed through dynamic properties) + QVariant propVal = property( "validity_tune_hint" ); + if ( propVal.isValid() ){ + QString extraInfo = propVal.toString(); + if ( !extraInfo.isEmpty() ){ + msg += "\n"; + msg += extraInfo; + } + } + + QToolTip::showText( globalPos, + msg, + that ); + } + else + QToolTip::hideText(); + } + + return res; } /*! @@ -372,3 +476,39 @@ void SalomeApp_DoubleSpinBox::showEvent( QShowEvent* ) { setText( myTextValue ); } + +/*! + \brief Enables or disables variable names in the spin box. + By default, variable names are enabled. + \param flag If true, variable names are enabled. +*/ +void SalomeApp_DoubleSpinBox::setAcceptNames( const bool flag ) +{ + myAcceptNames = flag; +} + +/*! + \brief Returns true if the spin box accepts variable names. +*/ +bool SalomeApp_DoubleSpinBox::isAcceptNames() const +{ + return myAcceptNames; +} + +/*! + \brief Enables or disables tooltips in case of invalid or intermediate-state input. + Tooltips are enabled by default. + \param flag If true, tooltips are enabled. +*/ +void SalomeApp_DoubleSpinBox::setShowTipOnValidate( const bool flag ) +{ + myShowTip = myShowTip; +} + +/*! + \brief Returns true if tooltip should be shown in case of invalid or intermediate-state input. +*/ +bool SalomeApp_DoubleSpinBox::isShowTipOnValidate() const +{ + return myShowTip; +} diff --git a/src/SalomeApp/SalomeApp_DoubleSpinBox.h b/src/SalomeApp/SalomeApp_DoubleSpinBox.h index c5b6539ca..215083bed 100644 --- a/src/SalomeApp/SalomeApp_DoubleSpinBox.h +++ b/src/SalomeApp/SalomeApp_DoubleSpinBox.h @@ -38,9 +38,11 @@ class SALOMEAPP_EXPORT SalomeApp_DoubleSpinBox : public QtxDoubleSpinBox public: SalomeApp_DoubleSpinBox( QWidget* = 0 ); SalomeApp_DoubleSpinBox( double, double, double = 1, QWidget* = 0 ); - SalomeApp_DoubleSpinBox( double, double, double, int, int, QWidget* = 0 ); + SalomeApp_DoubleSpinBox( double, double, double, int, int, QWidget* = 0, bool = true, bool = true ); virtual ~SalomeApp_DoubleSpinBox(); + virtual void stepBy( int ); + virtual double valueFromText( const QString& ) const; virtual QString textFromValue( double ) const; @@ -55,6 +57,12 @@ public: virtual void setText(const QString& ); + void setAcceptNames( const bool ); + bool isAcceptNames() const; + + void setShowTipOnValidate( const bool ); + bool isShowTipOnValidate() const; + signals: void textChanged( const QString& ); @@ -86,6 +94,9 @@ private: QString myCorrectValue; QString myTextValue; + + bool myAcceptNames; + bool myShowTip; }; #endif diff --git a/src/SalomeApp/SalomeApp_IntSpinBox.cxx b/src/SalomeApp/SalomeApp_IntSpinBox.cxx index 76625adc9..7ab394320 100644 --- a/src/SalomeApp/SalomeApp_IntSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_IntSpinBox.cxx @@ -33,6 +33,8 @@ #include #include +#include +#include #include @@ -50,7 +52,9 @@ */ SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( QWidget* parent ) : QtxIntSpinBox( parent ), - myDefaultValue( 0 ) + myDefaultValue( 0 ), + myAcceptNames( true ), + myShowTip( true ) { connectSignalsAndSlots(); } @@ -65,10 +69,19 @@ SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( QWidget* parent ) \param max spin box maximum possible value \param step spin box increment/decrement value \param parent parent object + \param acceptNames if true, enables variable names in the spin box + \param showTip if true, makes the widget show a tooltip when invalid text is entered by the user */ -SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( int min, int max, int step, QWidget* parent ) +SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( int min, + int max, + int step, + QWidget* parent, + bool acceptNames, + bool showTip ) : QtxIntSpinBox( min, max, step, parent ), - myDefaultValue( 0 ) + myDefaultValue( 0 ), + myAcceptNames( acceptNames ), + myShowTip( showTip ) { connectSignalsAndSlots(); } @@ -80,6 +93,34 @@ SalomeApp_IntSpinBox::~SalomeApp_IntSpinBox() { } + +/*! + \brief Perform \a steps increment/decrement steps. + + Re-implemented to handle cases when Notebook variable + name is specified by the user as the widget text. + Otherwise, simply calls the base implementation. + + \param steps number of increment/decrement steps +*/ +void SalomeApp_IntSpinBox::stepBy( int steps ) +{ + QString str = text(); + QString pref = prefix(); + QString suff = suffix(); + + if ( pref.length() && str.startsWith( pref ) ) + str = str.right( str.length() - pref.length() ); + if ( suff.length() && str.endsWith( suff ) ) + str = str.left( str.length() - suff.length() ); + + QRegExp varNameMask( "([a-z]|[A-Z]|_).*" ); + if ( varNameMask.exactMatch( str ) ) + return; + + QtxIntSpinBox::stepBy( steps ); +} + /*! \brief Connect signals and slots. */ @@ -157,7 +198,60 @@ QString SalomeApp_IntSpinBox::textFromValue( int val ) const */ QValidator::State SalomeApp_IntSpinBox::validate( QString& str, int& pos ) const { - return QValidator::Acceptable; + //return QValidator::Acceptable; + QValidator::State res = QValidator::Invalid; + + // Considering the input text as a variable name + // Applying Python identifier syntax: + // either a string starting with a letter, or a string starting with + // an underscore followed by at least one alphanumeric character + if ( isAcceptNames() ){ + QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" ); + if ( varNameMask.exactMatch( str ) ) + res = QValidator::Acceptable; + + if ( res == QValidator::Invalid ){ + varNameMask.setPattern( "_" ); + if ( varNameMask.exactMatch( str ) ) + res = QValidator::Intermediate; + } + } + + // Trying to interpret the current input text as a numeric value + if ( res == QValidator::Invalid ) + res = QtxIntSpinBox::validate( str, pos ); + + // Show tooltip in case of invalid manual input + if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){ + if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state??? + SalomeApp_IntSpinBox* that = const_cast( this ); + QPoint pos( size().width(), 0. ); + QPoint globalPos = mapToGlobal( pos ); + QString minVal = textFromValue( minimum() ); + QString maxVal = textFromValue( maximum() ); + + QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) ); + QString msg( templ.arg( minVal ).arg( maxVal ) ); + + // Add extra hints to the message (if any passed through dynamic properties) + QVariant propVal = property( "validity_tune_hint" ); + if ( propVal.isValid() ){ + QString extraInfo = propVal.toString(); + if ( !extraInfo.isEmpty() ){ + msg += "\n"; + msg += extraInfo; + } + } + + QToolTip::showText( globalPos, + msg, + that ); + } + else + QToolTip::hideText(); + } + + return res; } /*! @@ -330,3 +424,39 @@ void SalomeApp_IntSpinBox::showEvent( QShowEvent* ) { setText( myTextValue ); } + +/*! + \brief Enables or disables variable names in the spin box. + By default, variable names are enabled. + \param flag If true, variable names are enabled. +*/ +void SalomeApp_IntSpinBox::setAcceptNames( const bool flag ) +{ + myAcceptNames = flag; +} + +/*! + \brief Returns true if the spin box accepts variable names. +*/ +bool SalomeApp_IntSpinBox::isAcceptNames() const +{ + return myAcceptNames; +} + +/*! + \brief Enables or disables tooltips in case of invalid or intermediate-state input. + Tooltips are enabled by default. + \param flag If true, tooltips are enabled. +*/ +void SalomeApp_IntSpinBox::setShowTipOnValidate( const bool flag ) +{ + myShowTip = myShowTip; +} + +/*! + \brief Returns true if tooltip should be shown in case of invalid or intermediate-state input. +*/ +bool SalomeApp_IntSpinBox::isShowTipOnValidate() const +{ + return myShowTip; +} diff --git a/src/SalomeApp/SalomeApp_IntSpinBox.h b/src/SalomeApp/SalomeApp_IntSpinBox.h index d15fe99c1..3681cd175 100644 --- a/src/SalomeApp/SalomeApp_IntSpinBox.h +++ b/src/SalomeApp/SalomeApp_IntSpinBox.h @@ -37,9 +37,11 @@ class SALOMEAPP_EXPORT SalomeApp_IntSpinBox : public QtxIntSpinBox public: SalomeApp_IntSpinBox( QWidget* = 0 ); - SalomeApp_IntSpinBox( int, int, int = 1, QWidget* = 0 ); + SalomeApp_IntSpinBox( int, int, int = 1, QWidget* = 0, bool = true, bool = true ); virtual ~SalomeApp_IntSpinBox(); + virtual void stepBy( int ); + virtual int valueFromText( const QString& ) const; virtual QString textFromValue( int ) const; @@ -53,6 +55,12 @@ public: virtual void setText(const QString& ); + void setAcceptNames( const bool ); + bool isAcceptNames() const; + + void setShowTipOnValidate( const bool ); + bool isShowTipOnValidate() const; + signals: void textChanged( const QString& ); @@ -80,6 +88,9 @@ private: QString myCorrectValue; QString myTextValue; + + bool myAcceptNames; + bool myShowTip; }; #endif diff --git a/src/SalomeApp/resources/SalomeApp_msg_en.ts b/src/SalomeApp/resources/SalomeApp_msg_en.ts index 9654d27fa..1caff4a7a 100644 --- a/src/SalomeApp/resources/SalomeApp_msg_en.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_en.ts @@ -453,4 +453,30 @@ Please edit its parameters or remove it from table. Failed to update study! + + SalomeApp_DoubleSpinBox + + VALID_RANGE_VAR_MSG + Specify either a variable name or +a floating-point value in range ( %1; %2 ) +with %3-digit precision + + + VALID_RANGE_NOVAR_MSG + Specify a floating-point value in range ( %1; %2 ) +with %3-digit precision + + + + SalomeApp_IntSpinBox + + VALID_RANGE_VAR_MSG + Specify either a variable name or +an integer value in range ( %1; %2 ) + + + VALID_RANGE_NOVAR_MSG + Specify an integer value in range ( %1; %2 ) + + diff --git a/src/SalomeApp/salome_pluginsmanager.py b/src/SalomeApp/salome_pluginsmanager.py index 581a24fe2..0a7f4167a 100644 --- a/src/SalomeApp/salome_pluginsmanager.py +++ b/src/SalomeApp/salome_pluginsmanager.py @@ -29,6 +29,7 @@ context attributes: - sg : the SALOME Swig interface - studyId : the SALOME studyId that must be used to execute the plugin - study : the SALOME study object that must be used to execute the plugin + """ import os,sys,traceback @@ -82,7 +83,14 @@ class Plugins: for directory in pluginspath.split(SEP): self.plugindirs.append(directory) - self.menu=QtGui.QMenu("Plugins",sgPyQt.getPopupMenu(SalomePyQt.Tools)) + basemenu=sgPyQt.getPopupMenu("Tools") + self.menu=QtGui.QMenu("Plugins",basemenu) + basemenu.addMenu(self.menu) + + #a=QtGui.QAction("Plugins",basemenu) + #a.setMenu(self.menu) + #mid=sgPyQt.createMenu(a,"Tools") + self.menu.connect(self.menu,QtCore.SIGNAL("aboutToShow()"),self.importPlugins) def AddFunction(self,name,description,script,script_type=None): @@ -114,10 +122,10 @@ class Plugins: plugins_files=[] for directory in self.plugindirs: - salome_plugins_file = os.path.join(directory,"salome_plugins.py") - if os.path.isfile(salome_plugins_file): - plugins_files.append((directory,salome_plugins_file)) - lasttime=max(lasttime,os.path.getmtime(salome_plugins_file)) + plugins_file = os.path.join(directory,"salome_plugins.py") + if os.path.isfile(plugins_file): + plugins_files.append((directory,plugins_file)) + lasttime=max(lasttime,os.path.getmtime(plugins_file)) plugins_files.sort() @@ -140,18 +148,19 @@ class Plugins: except: print "Error while loading plugins from file:",salome_plugins_file traceback.print_exc() + self.updateMenu() def updateMenu(self): """Update the Plugins menu""" self.menu.clear() for name,handler in self.handlers.items(): - act=self.menu.addAction(name,handler) + act=self.menu.addAction(name,handler) def activate(self): """Add the Plugins menu to the Tools menu""" - tools_menu= sgPyQt.getPopupMenu(SalomePyQt.Tools) - tools_menu.addMenu(self.menu) + #tools_menu= sgPyQt.getPopupMenu(SalomePyQt.Tools) + #tools_menu.addMenu(self.menu) def deactivate(self): """Remove the Plugins menu from Tools menu (not implemented)""" diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx index 5d42b4661..26a0f0793 100755 --- a/src/Session/SALOME_Session_Server.cxx +++ b/src/Session/SALOME_Session_Server.cxx @@ -66,6 +66,58 @@ #include #include #include +#ifndef WIN32 +#include +#endif + +#include +#include +#include +#include + +typedef void (*sighandler_t)(int); +sighandler_t setsig(int sig, sighandler_t handler) +{ + struct sigaction context, ocontext; + context.sa_handler = handler; + sigemptyset(&context.sa_mask); + context.sa_flags = 0; + if (sigaction(sig, &context, &ocontext) == -1) + return SIG_ERR; + return ocontext.sa_handler; +} + +void AttachDebugger() +{ + if(getenv ("DEBUGGER")) + { + std::stringstream exec; + exec << "$DEBUGGER SALOME_Session_Server " << getpid() << "&"; + std::cerr << exec.str() << std::endl; + system(exec.str().c_str()); + while(1); + } +} + +void Handler(int theSigId) +{ + std::cerr << "SIGSEGV: " << std::endl; + AttachDebugger(); + //to exit or not to exit + exit(1); +} +void terminateHandler(void) +{ + std::cerr << "Terminate: not managed exception !" << std::endl; + AttachDebugger(); +} + +void unexpectedHandler(void) +{ + std::cerr << "Unexpected: unexpected exception !" << std::endl; + AttachDebugger(); +} + #include @@ -336,6 +388,14 @@ void shutdownServers( SALOME_NamingService* theNS ) // ---------------------------- MAIN ----------------------- int main( int argc, char **argv ) { + if(getenv ("DEBUGGER")) + { + setsig(SIGSEGV,&Handler); + setsig(SIGBUS,&Handler); + set_terminate(&terminateHandler); + set_unexpected(&unexpectedHandler); + } + // Install Qt debug messages handler qInstallMsgHandler( MessageOutput ); diff --git a/src/VTKViewer/VTKViewer_PolyDataMapper.cxx b/src/VTKViewer/VTKViewer_PolyDataMapper.cxx index 6373cd0cd..4b59f6ce5 100644 --- a/src/VTKViewer/VTKViewer_PolyDataMapper.cxx +++ b/src/VTKViewer/VTKViewer_PolyDataMapper.cxx @@ -248,12 +248,9 @@ void VTKViewer_PolyDataMapper::InitPointSprites() glPushAttrib( GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT ); - glDepthFunc( GL_LESS ); + glDepthFunc( GL_LEQUAL ); glEnable( GL_DEPTH_TEST ); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); - glEnable( GL_ALPHA_TEST ); glAlphaFunc( GL_GREATER, 0.0 );