From 97482df035ee6e97dde980312a5b02d356b03702 Mon Sep 17 00:00:00 2001 From: ribes Date: Mon, 9 Nov 2009 09:26:21 +0000 Subject: [PATCH] Initial commit --- AUTHORS | 0 COPYING | 340 ++++++++++++ ChangeLog | 0 Makefile.am | 3 + NEWS | 0 README | 1 + TO_BE_REMOVED | 1 - build_configure | 39 ++ configure.ac | 133 +++++ m4/ac_cxx_option.m4 | 42 ++ m4/ac_linker_options.m4 | 47 ++ m4/check_omniorb.m4 | 257 +++++++++ m4/check_salome.m4 | 164 ++++++ m4/check_sphinx.m4 | 35 ++ m4/i2_check_qt4.m4 | 411 +++++++++++++++ m4/production.m4 | 101 ++++ src/Makefile.am | 20 + src/bases/BL_Exception.cxx | 35 ++ src/bases/BL_Exception.hxx | 38 ++ src/bases/BL_Traces.hxx | 38 ++ src/bases/Makefile.am | 26 + src/bases/make_begin.am | 38 ++ src/engine/BL_Job.cxx | 182 +++++++ src/engine/BL_Job.hxx | 103 ++++ src/engine/BL_JobsManager.cxx | 327 ++++++++++++ src/engine/BL_JobsManager.hxx | 81 +++ src/engine/BL_SALOMEServices.cxx | 214 ++++++++ src/engine/BL_SALOMEServices.hxx | 68 +++ src/genericgui/BL_Buttons.cxx | 120 +++++ src/genericgui/BL_Buttons.hxx | 62 +++ src/genericgui/BL_CreateJobWizard.cxx | 686 +++++++++++++++++++++++++ src/genericgui/BL_CreateJobWizard.hxx | 199 +++++++ src/genericgui/BL_GenericGui.cxx | 313 +++++++++++ src/genericgui/BL_GenericGui.hxx | 98 ++++ src/genericgui/BL_JobTab.cxx | 259 ++++++++++ src/genericgui/BL_JobTab.hxx | 78 +++ src/genericgui/BL_JobsManager_QT.cxx | 330 ++++++++++++ src/genericgui/BL_JobsManager_QT.hxx | 97 ++++ src/genericgui/BL_JobsTable.cxx | 44 ++ src/genericgui/BL_JobsTable.hxx | 42 ++ src/genericgui/BL_MachineCatalog.cxx | 66 +++ src/genericgui/BL_MachineCatalog.hxx | 54 ++ src/genericgui/BL_MainButtons.cxx | 0 src/genericgui/BL_MainButtons.hxx | 0 src/genericgui/BL_QModelManager.cxx | 131 +++++ src/genericgui/BL_QModelManager.hxx | 56 ++ src/genericgui/BL_Summary.cxx | 137 +++++ src/genericgui/BL_Summary.hxx | 59 +++ src/genericgui/Makefile.am | 64 +++ src/salomegui/BL_SalomeGui.cxx | 85 +++ src/salomegui/BL_SalomeGui.hxx | 54 ++ src/salomegui/Makefile.am | 78 +++ src/salomegui/resources/SalomeApp.xml | 31 ++ src/salomegui/resources/jobmanager.png | Bin 0 -> 63360 bytes src/standalone/Makefile.am | 23 + src/standalone/main.cxx | 21 + src/standalone/start_jobmanager.sh.in | 48 ++ src/wrappers/BL_MainWindows_Qt.cxx | 77 +++ src/wrappers/BL_MainWindows_Qt.hxx | 58 +++ src/wrappers/BL_MainWindows_SALOME.cxx | 100 ++++ src/wrappers/BL_MainWindows_SALOME.hxx | 80 +++ src/wrappers/BL_MainWindows_Wrap.hxx | 54 ++ src/wrappers/Makefile.am | 54 ++ 63 files changed, 6401 insertions(+), 1 deletion(-) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README delete mode 100644 TO_BE_REMOVED create mode 100755 build_configure create mode 100644 configure.ac create mode 100644 m4/ac_cxx_option.m4 create mode 100644 m4/ac_linker_options.m4 create mode 100644 m4/check_omniorb.m4 create mode 100644 m4/check_salome.m4 create mode 100644 m4/check_sphinx.m4 create mode 100644 m4/i2_check_qt4.m4 create mode 100644 m4/production.m4 create mode 100644 src/Makefile.am create mode 100644 src/bases/BL_Exception.cxx create mode 100644 src/bases/BL_Exception.hxx create mode 100644 src/bases/BL_Traces.hxx create mode 100644 src/bases/Makefile.am create mode 100644 src/bases/make_begin.am create mode 100644 src/engine/BL_Job.cxx create mode 100644 src/engine/BL_Job.hxx create mode 100644 src/engine/BL_JobsManager.cxx create mode 100644 src/engine/BL_JobsManager.hxx create mode 100644 src/engine/BL_SALOMEServices.cxx create mode 100644 src/engine/BL_SALOMEServices.hxx create mode 100644 src/genericgui/BL_Buttons.cxx create mode 100644 src/genericgui/BL_Buttons.hxx create mode 100644 src/genericgui/BL_CreateJobWizard.cxx create mode 100644 src/genericgui/BL_CreateJobWizard.hxx create mode 100644 src/genericgui/BL_GenericGui.cxx create mode 100644 src/genericgui/BL_GenericGui.hxx create mode 100644 src/genericgui/BL_JobTab.cxx create mode 100644 src/genericgui/BL_JobTab.hxx create mode 100644 src/genericgui/BL_JobsManager_QT.cxx create mode 100644 src/genericgui/BL_JobsManager_QT.hxx create mode 100644 src/genericgui/BL_JobsTable.cxx create mode 100644 src/genericgui/BL_JobsTable.hxx create mode 100644 src/genericgui/BL_MachineCatalog.cxx create mode 100644 src/genericgui/BL_MachineCatalog.hxx create mode 100644 src/genericgui/BL_MainButtons.cxx create mode 100644 src/genericgui/BL_MainButtons.hxx create mode 100644 src/genericgui/BL_QModelManager.cxx create mode 100644 src/genericgui/BL_QModelManager.hxx create mode 100644 src/genericgui/BL_Summary.cxx create mode 100644 src/genericgui/BL_Summary.hxx create mode 100644 src/genericgui/Makefile.am create mode 100644 src/salomegui/BL_SalomeGui.cxx create mode 100644 src/salomegui/BL_SalomeGui.hxx create mode 100644 src/salomegui/Makefile.am create mode 100644 src/salomegui/resources/SalomeApp.xml create mode 100644 src/salomegui/resources/jobmanager.png create mode 100644 src/standalone/Makefile.am create mode 100644 src/standalone/main.cxx create mode 100644 src/standalone/start_jobmanager.sh.in create mode 100644 src/wrappers/BL_MainWindows_Qt.cxx create mode 100644 src/wrappers/BL_MainWindows_Qt.hxx create mode 100644 src/wrappers/BL_MainWindows_SALOME.cxx create mode 100644 src/wrappers/BL_MainWindows_SALOME.hxx create mode 100644 src/wrappers/BL_MainWindows_Wrap.hxx create mode 100644 src/wrappers/Makefile.am diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..f8238b2 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..2833438 --- /dev/null +++ b/README @@ -0,0 +1 @@ +This module is an interface to use SALOME Launcher services. diff --git a/TO_BE_REMOVED b/TO_BE_REMOVED deleted file mode 100644 index 74cd5ce..0000000 --- a/TO_BE_REMOVED +++ /dev/null @@ -1 +0,0 @@ -TEst diff --git a/build_configure b/build_configure new file mode 100755 index 0000000..e3987c4 --- /dev/null +++ b/build_configure @@ -0,0 +1,39 @@ +#! /bin/sh +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +ORIG_DIR=`pwd` +run() { + local logfile=$ORIG_DIR/build_configure.log + printf "%-50s" "$1 ... " + eval $1 > $logfile 2>&1 + if test $? != 0 ; then + echo "[FAILED]" + echo "see file build_configure.log ..." + exit 1 + fi + echo "[ OK ]" +} + +run "libtoolize --force --copy --automake" +run "aclocal -I m4" +run "autoheader -I m4" +run "autoconf" +run "automake --add-missing --copy" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..da46773 --- /dev/null +++ b/configure.ac @@ -0,0 +1,133 @@ +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# +# -- +# Author : André RIBES (EDF) +# -- +# ----------------------------------------------------------------------------- +# +AC_INIT([JOBMANAGER project], [0.1], [andre.ribes@edf.fr], [JobManager-Module]) +AM_INIT_AUTOMAKE([tar-pax]) +AC_CONFIG_HEADER(jobmanager_config.h) + +# set up MODULE_NAME variable for dynamic construction of directories (resources, etc.) +MODULE_NAME=jobmanager +AC_SUBST(MODULE_NAME) + +XVERSION=0x001 +AC_SUBST(XVERSION) + +RELEASE=$VERSION +AC_SUBST(RELEASE) + +# This function return on stdout the absolute path of the filename in +# argument. Exemple: +# $ filename="../KERNEL_SRC/configure +# $ absfilename=`absolute_path $filename` +function absolute_path { + filename=$1 + here=`pwd` + apath=`dirname $filename` + cd $apath + apath=`pwd` + cd $here + echo $apath +} + +# Build directory, where the configure script is executed. +ROOT_BUILDDIR=`pwd` +# Source directory, where the configure script is located. +ROOT_SRCDIR=`absolute_path $0` + +AC_SUBST(ROOT_SRCDIR) +AC_SUBST(ROOT_BUILDDIR) + +echo +echo Source root directory : $ROOT_SRCDIR +echo Build root directory : $ROOT_BUILDDIR + +# ----------------------------------------------------------------------------- + +AC_ENABLE_DEBUG(yes) +AC_DISABLE_PRODUCTION + +#Linker options +AC_CANONICAL_BUILD +AC_LINKER_OPTIONS + +#Mandatory products +AC_PROG_CXX +AM_PROG_LIBTOOL +AC_CHECK_LIB(dl,dlopen) +I2_CHECK_QT4 +AC_CHECK_OMNIORB + +# Optional products +CHECK_SPHINX + +AC_CHECK_KERNEL +CHECK_GUI(SALOME_Session_Server,SALOME_Session_Server) + +AM_CONDITIONAL([SALOME_KERNEL], [test "x$KERNEL_ROOT_DIR" != "x"]) +AM_CONDITIONAL([HAS_GUI], [test "x$GUI_ROOT_DIR" != "x"]) + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE $VERSION" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options Summary:" +echo +echo "Mandatory products:" +echo " Qt4 (graphic interface) : $qt_ok" +echo " OmniOrb (CORBA) ........ : $omniORB_ok" +echo " SALOME KERNEL .......... : $Kernel_ok" +echo " SALOME GUI ............. : $SalomeGUI_ok" +echo +echo "Optional products:" +echo " Sphinx (user doc) ...... : $sphinx_ok" +echo +echo "------------------------------------------------------------------------" +echo + +if test "x$omniORB_ok" = "xno"; then + AC_MSG_ERROR([OmniOrb is required],1) +fi +if test "x$qt_ok" = "xno"; then + AC_MSG_ERROR([Qt4 is required],1) +fi +if test "x$Kernel_ok" = "xno"; then + AC_MSG_ERROR([SALOME KERNEL is required],1) +fi +if test "x$SalomeGui_ok" = "xno"; then + AC_MSG_ERROR([SALOME GUI is required],1) +fi + +AC_OUTPUT([ \ + Makefile \ + src/Makefile \ + src/bases/Makefile \ + src/engine/Makefile \ + src/genericgui/Makefile \ + src/wrappers/Makefile \ + src/standalone/Makefile \ + src/standalone/start_jobmanager.sh \ + src/salomegui/Makefile \ +]) diff --git a/m4/ac_cxx_option.m4 b/m4/ac_cxx_option.m4 new file mode 100644 index 0000000..6f31513 --- /dev/null +++ b/m4/ac_cxx_option.m4 @@ -0,0 +1,42 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +dnl @synopsis AC_CXX_OPTION(-option,variable where we add option if ok,action if ok; action if not ok) +dnl Check options for C++ compiler +dnl @author Bernard Secher - 15/01/2004 +dnl +AC_DEFUN([AC_CXX_OPTION], [ + AC_MSG_CHECKING(wether $CXX accepts $1) + cat > conftest.cxx < conftest.log 2>&1 + rm -f a.out + var=`echo $1 | sed -e "s, .*$,," | sed -e "s,^-,,"` +#CCRT if ! grep -e $var conftest.log > /dev/null 2>&1 ; then + if grep -e $var conftest.log > /dev/null 2>&1 ; then + AC_MSG_RESULT(no) + eval $4 + else + AC_MSG_RESULT(yes) + $2="${$2} $1" + eval $3 + fi +]) + + diff --git a/m4/ac_linker_options.m4 b/m4/ac_linker_options.m4 new file mode 100644 index 0000000..cec98c4 --- /dev/null +++ b/m4/ac_linker_options.m4 @@ -0,0 +1,47 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +dnl @synopsis AC_LINKER_OPTIONS +dnl Check warning flags for C++ compiler to control warning messages +dnl +AC_DEFUN([AC_LINKER_OPTIONS],[ + + AC_CHECKING(for LIB_LOCATION_SUFFIX) + LIB_LOCATION_SUFFIX="" + AC_SUBST(LIB_LOCATION_SUFFIX) + AC_MSG_RESULT(LIB_LOCATION_SUFFIX is $LIB_LOCATION_SUFFIX) + + for opt in "-Xlinker -export-dynamic" -transitive_link; do + AC_CXX_OPTION($opt,LDEXPDYNFLAGS,flag=yes,flag=no) + if test "$flag" = "yes"; then + break + fi + done + AC_SUBST(LDEXPDYNFLAGS) + +dnl + case $host_os in + osf*) + STDLIB="-lcxxstd" + ;; + *) + STDLIB="-lstdc++" + ;; + esac + AC_SUBST(STDLIB) +]) diff --git a/m4/check_omniorb.m4 b/m4/check_omniorb.m4 new file mode 100644 index 0000000..f2be9a7 --- /dev/null +++ b/m4/check_omniorb.m4 @@ -0,0 +1,257 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +AC_DEFUN([AC_CHECK_OMNIORB],[ +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +AC_REQUIRE([AC_PROG_CXXCPP])dnl + +AC_CHECKING(for omniORB) +omniORB_ok=yes + +if test "x$PYTHON" = "x" +then + CHECK_PYTHON +fi + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +AC_PATH_PROG(OMNIORB_IDL, omniidl) +if test "x$OMNIORB_IDL" = "x" +then + omniORB_ok=no + AC_MSG_RESULT(omniORB binaries not in PATH variable) +else + omniORB_ok=yes +fi + +if test "x$omniORB_ok" = "xyes" +then + AC_SUBST(OMNIORB_IDL) + + OMNIORB_BIN=`echo ${OMNIORB_IDL} | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` + OMNIORB_ROOT=${OMNIORB_BIN} + # one-level up + OMNIORB_ROOT=`echo ${OMNIORB_ROOT} | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` + # + # + if test -d $OMNIORB_ROOT/include ; then + # if $OMNIORB_ROOT/include exists, there are a lot of chance that + # this is omniORB4.x installed via configure && make && make install + OMNIORB_LIB=`echo ${OMNIORB_BIN} | sed -e "s,bin\$,lib,"` + OMNIORB_VERSION=4 + else + # omniORB has been installed old way + OMNIORB_LIB=`echo ${OMNIORB_BIN} | sed -e "s,bin/,lib/,"` + # one-level up again + OMNIORB_ROOT=`echo ${OMNIORB_ROOT} | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` + if test -d $OMNIORB_ROOT/include/omniORB4 ; then + OMNIORB_VERSION=4 + else + OMNIORB_VERSION=3 + fi + fi + AC_SUBST(OMNIORB_ROOT) + + OMNIORB_INCLUDES="-I$OMNIORB_ROOT/include -I$OMNIORB_ROOT/include/omniORB${OMNIORB_VERSION} -I$OMNIORB_ROOT/include/COS" + AC_SUBST(OMNIORB_INCLUDES) + + # ENABLE_PTHREADS + + OMNIORB_CXXFLAGS="-DOMNIORB_VERSION=$OMNIORB_VERSION" + case $build_cpu in + sparc*) + OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__sparc__" + ;; + *86*) + OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__x86__" + ;; + esac + case $build_os in + solaris*) + __OSVERSION__=5 + OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__sunos__" + ;; + linux*) + __OSVERSION__=2 + OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__linux__ -D_REENTRANT" + ;; + esac + AC_SUBST(OMNIORB_CXXFLAGS) + + CPPFLAGS_old=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $OMNIORB_CXXFLAGS $OMNIORB_INCLUDES" + + AC_LANG_CPLUSPLUS + AC_CHECK_HEADER(CORBA.h,omniORB_ok="yes",omniORB_ok="no") + + CPPFLAGS=$CPPFLAGS_old + +fi + +if test "x$omniORB_ok" = "xyes" +then + if test "x$OMNIORB_LIB" = "x/usr/lib" + then + OMNIORB_LDFLAGS="" + OMNIORB_RFLAGS="" + else + OMNIORB_LDFLAGS="-L$OMNIORB_LIB" + OMNIORB_RFLAGS="-R$OMNIORB_LIB" + fi + + LIBS_old=$LIBS + LIBS="$LIBS $OMNIORB_LDFLAGS -lomnithread" + + CXXFLAGS_old=$CXXFLAGS + CXXFLAGS="$CXXFLAGS $OMNIORB_CXXFLAGS $OMNIORB_INCLUDES" + + AC_MSG_CHECKING(whether we can link with omnithreads) + AC_CACHE_VAL(salome_cv_lib_omnithreads,[ + AC_TRY_LINK( +#include +, omni_mutex my_mutex, + eval "salome_cv_lib_omnithreads=yes",eval "salome_cv_lib_omnithreads=no") + ]) + + omniORB_ok="$salome_cv_lib_omnithreads" + if test "x$omniORB_ok" = "xno" + then + AC_MSG_RESULT(omnithreads not found) + else + AC_MSG_RESULT(yes) + fi + + LIBS=$LIBS_old + CXXFLAGS=$CXXFLAGS_old +fi + + +dnl omniORB_ok=yes +if test "x$omniORB_ok" = "xyes" +then + + AC_CHECK_LIB(socket,socket, LIBS="-lsocket $LIBS",,) + AC_CHECK_LIB(nsl,gethostbyname, LIBS="-lnsl $LIBS",,) + + LIBS_old=$LIBS + OMNIORB_LIBS="$OMNIORB_LDFLAGS" + OMNIORB_LIBS="$OMNIORB_LIBS -lomniORB${OMNIORB_VERSION}" + OMNIORB_LIBS="$OMNIORB_LIBS -lomniDynamic${OMNIORB_VERSION}" + OMNIORB_LIBS="$OMNIORB_LIBS -lCOS${OMNIORB_VERSION}" + OMNIORB_LIBS="$OMNIORB_LIBS -lCOSDynamic${OMNIORB_VERSION}" + OMNIORB_LIBS="$OMNIORB_LIBS -lomnithread" + OMNIORB_LIBS="$OMNIORB_LIBS ${OMNIORB_RFLAGS}" + if test $OMNIORB_VERSION = 3 ; then + OMNIORB_LIBS="$OMNIORB_LIBS -ltcpwrapGK" + fi + AC_SUBST(OMNIORB_LIBS) + + LIBS="$OMNIORB_LIBS $LIBS" + CXXFLAGS_old=$CXXFLAGS + CXXFLAGS="$CXXFLAGS $OMNIORB_CXXFLAGS $OMNIORB_INCLUDES" + + AC_MSG_CHECKING(whether we can link with omniORB) + AC_CACHE_VAL(salome_cv_lib_omniorb,[ + AC_TRY_LINK( +#include +, CORBA::ORB_var orb, + eval "salome_cv_lib_omniorb3=yes",eval "salome_cv_lib_omniorb3=no") + ]) + omniORB_ok="$salome_cv_lib_omniorb3" + + omniORB_ok=yes + if test "x$omniORB_ok" = "xno" + then + AC_MSG_RESULT(omniORB library linking failed) + omniORB_ok=no + else + AC_MSG_RESULT(yes) + fi + LIBS="$LIBS_old" + CXXFLAGS=$CXXFLAGS_old +fi + + +if test "x$omniORB_ok" = "xyes" +then + + OMNIORB_IDLCXXFLAGS="-nf -I$OMNIORB_ROOT/idl" + OMNIORB_IDLPYFLAGS="-bpython -I$OMNIORB_ROOT/idl" + AC_SUBST(OMNIORB_IDLCXXFLAGS) + AC_SUBST(OMNIORB_IDLPYFLAGS) + + OMNIORB_IDL_CLN_H=.hh + OMNIORB_IDL_CLN_CXX=SK.cc + OMNIORB_IDL_CLN_OBJ=SK.o + AC_SUBST(OMNIORB_IDL_CLN_H) + AC_SUBST(OMNIORB_IDL_CLN_CXX) + AC_SUBST(OMNIORB_IDL_CLN_OBJ) + + OMNIORB_IDL_SRV_H=.hh + OMNIORB_IDL_SRV_CXX=SK.cc + OMNIORB_IDL_SRV_OBJ=SK.o + AC_SUBST(OMNIORB_IDL_SRV_H) + AC_SUBST(OMNIORB_IDL_SRV_CXX) + AC_SUBST(OMNIORB_IDL_SRV_OBJ) + + OMNIORB_IDL_TIE_H= + OMNIORB_IDL_TIE_CXX= + AC_SUBST(OMNIORB_IDL_TIE_H) + AC_SUBST(OMNIORB_IDL_TIE_CXX) + + AC_DEFINE(OMNIORB,,[Presence de omniORB]) + + CORBA_HAVE_POA=1 + AC_DEFINE(CORBA_HAVE_POA,,[POA presence]) + + CORBA_ORB_INIT_HAVE_3_ARGS=1 + AC_DEFINE(CORBA_ORB_INIT_HAVE_3_ARGS,,[?]) + CORBA_ORB_INIT_THIRD_ARG='"omniORB"' + AC_DEFINE(CORBA_ORB_INIT_THIRD_ARG, "omniORB", [?]) + +fi + +omniORBpy_ok=no +if test "x$omniORB_ok" = "xyes" +then + AC_MSG_CHECKING(omniORBpy) + $PYTHON -c "import omniORB" &> /dev/null + if test $? = 0 ; then + AC_MSG_RESULT(yes) + omniORBpy_ok=yes + else + AC_MSG_RESULT(no, check your installation of omniORBpy) + omniORBpy_ok=no + fi +fi + +dnl AC_LANG_RESTORE + +AC_MSG_RESULT(for omniORBpy: $omniORBpy_ok) +AC_MSG_RESULT(for omniORB: $omniORB_ok) + +IDL=${OMNIORB_IDL} +IDLGENFLAGS="-bcxx " +AC_SUBST(IDL) +AC_SUBST(IDLGENFLAGS) + +])dnl +dnl diff --git a/m4/check_salome.m4 b/m4/check_salome.m4 new file mode 100644 index 0000000..f6bdfa7 --- /dev/null +++ b/m4/check_salome.m4 @@ -0,0 +1,164 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +# Check availability of Salome's KERNEL binary distribution +# +# Author : Jerome Roy (CEA, 2003) +# + +AC_DEFUN([AC_CHECK_KERNEL],[ + +AC_CHECKING(for Kernel) + +Kernel_ok=no +dsc_ok=no + +AC_ARG_WITH(kernel, + [ --with-kernel=DIR root directory path of KERNEL build or installation], + KERNEL_DIR="$withval",KERNEL_DIR="") + +if test "x$KERNEL_DIR" = "x" ; then + +# no --with-kernel-dir option used + + if test "x$KERNEL_ROOT_DIR" != "x" ; then + + # KERNEL_ROOT_DIR environment variable defined + KERNEL_DIR=$KERNEL_ROOT_DIR + + else + + # search Kernel binaries in PATH variable + AC_PATH_PROG(TEMP, runSalome) + if test "x$TEMP" != "x" ; then + KERNEL_BIN_DIR=`dirname $TEMP` + KERNEL_DIR=`dirname $KERNEL_BIN_DIR` + fi + + fi +# +fi + + +if test -f ${KERNEL_DIR}/bin/salome/runSalome ; then + Kernel_ok=yes + AC_MSG_RESULT(Using Kernel module distribution in ${KERNEL_DIR}) + AC_DEFINE(SALOME_KERNEL,,[With Salome KERNEL]) + + if test "x$KERNEL_ROOT_DIR" = "x" ; then + KERNEL_ROOT_DIR=${KERNEL_DIR} + fi + if test "x$KERNEL_SITE_DIR" = "x" ; then + KERNEL_SITE_DIR=${KERNEL_ROOT_DIR} + fi + SALOME_ROOT_DIR=`AS_DIRNAME(["$KERNEL_ROOT_DIR"])` + SALOME_VERSION="`echo $KERNEL_ROOT_DIR | sed s@$SALOME_ROOT_DIR/KERNEL@@`" + + if test -f ${KERNEL_DIR}/idl/salome/DSC_Engines.idl ; then + # DSC extension available + dsc_ok=yes + AC_MSG_RESULT(Using DSC Ports module distribution in ${KERNEL_DIR}) + AC_DEFINE(DSC_PORTS,,[With DSC ports]) + else + AC_MSG_WARN("Cannot find DSC Ports module distribution") + fi + + KERNEL_LDFLAGS=-L${KERNEL_ROOT_DIR}/lib/salome + KERNEL_CXXFLAGS=-I${KERNEL_ROOT_DIR}/include/salome + + AC_SUBST(KERNEL_ROOT_DIR) + AC_SUBST(KERNEL_SITE_DIR) + AC_SUBST(SALOME_ROOT_DIR) + AC_SUBST(SALOME_VERSION) + AC_SUBST(KERNEL_LDFLAGS) + AC_SUBST(KERNEL_CXXFLAGS) + +else + AC_MSG_WARN("Cannot find compiled Kernel module distribution") +fi + +AC_MSG_RESULT(for Kernel: $Kernel_ok) + +])dnl + +# ----------------------------------------------------------------------------- +# --- from GUI_SRC 3.2.3 +# Check availability of Salome binary distribution +# +# Author : Marc Tajchman (CEA, 2002) +#------------------------------------------------------------ + +AC_DEFUN([CHECK_GUI],[ +AC_REQUIRE([AC_LINKER_OPTIONS])dnl + +AC_CHECKING(for $2 $1 ) + +SalomeGUI_ok=no + +GUI_LDFLAGS="" +GUI_CXXFLAGS="" + +AC_ARG_WITH(gui, + [ --with-gui=DIR root directory path of SALOME GUI installation], + [SALOME_GUI_DIR="$withval"],[SALOME_GUI_DIR=""]) + +if test "x${SALOME_GUI_DIR}" = "x" ; then + # no --with-gui-dir option used + AC_MSG_RESULT(try \${GUI_ROOT_DIR}: ${GUI_ROOT_DIR}) + if test "x${GUI_ROOT_DIR}" != "x" ; then + # SALOME_ROOT_DIR environment variable defined + SALOME_GUI_DIR=${GUI_ROOT_DIR} + else + # search Salome binaries in PATH variable + AC_PATH_PROG(TEMP, $1) + if test "x${TEMP}" != "x" ; then + AC_MSG_RESULT($1 was found at : ${TEMP}) + SALOME_BIN_DIR=`dirname ${TEMP}` + SALOME_GUI_DIR=`cd ${SALOME_BIN_DIR}/../..; pwd` + fi + fi +fi + +if test -f ${SALOME_GUI_DIR}/bin/salome/$1 ; then + SalomeGUI_ok=yes + AC_MSG_RESULT(Using SALOME GUI distribution in ${SALOME_GUI_DIR}) + + if test "x${GUI_ROOT_DIR}" == "x" ; then + GUI_ROOT_DIR=${SALOME_GUI_DIR} + fi + + AC_SUBST(GUI_ROOT_DIR) + + GUI_LDFLAGS=-L${SALOME_GUI_DIR}/lib/salome + GUI_CXXFLAGS=-I${SALOME_GUI_DIR}/include/salome + + AC_SUBST(GUI_LDFLAGS) + AC_SUBST(GUI_CXXFLAGS) +else + AC_MSG_WARN("Cannot find compiled SALOME GUI distribution") +fi + +AC_MSG_RESULT(for $2: ${SalomeGUI_ok}) + +])dnl + +AC_DEFUN([CHECK_SALOME_GUI],[ + CHECK_GUI([SUITApp], + [SALOME GUI]) +])dnl + diff --git a/m4/check_sphinx.m4 b/m4/check_sphinx.m4 new file mode 100644 index 0000000..eec1495 --- /dev/null +++ b/m4/check_sphinx.m4 @@ -0,0 +1,35 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +AC_DEFUN([CHECK_SPHINX],[ + +AC_CHECKING(for sphinx doc generator) + +sphinx_ok=yes +dnl where is sphinx ? +AC_PATH_PROG(SPHINX,sphinx-build) +if test "x$SPHINX" = "x" +then + AC_MSG_WARN(sphinx not found) + sphinx_ok=no +fi + +AM_CONDITIONAL(SPHINX_IS_OK, [test x"$sphinx_ok" = xyes]) + +])dnl +dnl diff --git a/m4/i2_check_qt4.m4 b/m4/i2_check_qt4.m4 new file mode 100644 index 0000000..355c389 --- /dev/null +++ b/m4/i2_check_qt4.m4 @@ -0,0 +1,411 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +dnl the following variables are exported: +dnl QT_MOC +dnl QT_UIC +dnl QT_DIR +dnl qt4_cppflags +dnl qt4_ldflags +dnl qt4_libs +dnl WITH_QT4 +dnl qt4 is searched in the following order +dnl path given with --with-qt4 options +dnl presence of QTDIR variable +dnl /usr +dnl usages +dnl ./configure --prefix=/home/prascle/partage/maquettes/install +dnl ./configure --prefix=/home/prascle/partage/maquettes/install --with-qt4 +dnl ./configure --prefix=/home/prascle/partage/maquettes/install --with-qt4=/opt/qt443 +dnl ./configure --prefix=/home/prascle/partage/maquettes/install --with-qt4-includes=/usr/include/qt4 +dnl ./configure --prefix=/home/prascle/partage/maquettes/install --with-qt4-includes=/usr/include/qt4 --with-qt4-libraries=/usr/lib -with-qt4-tools=/usr/bin +dnl ./configure --prefix=/home/prascle/partage/maquettes/install --without-qt4 +dnl +AC_DEFUN([I2_CHECK_QT4], +[ + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PROG_CPP]) + + qt_ok=no + + # --- check if qt4 standard install directory is defined (with subdirectories bin lib include) + qt4_install_path="" + AC_ARG_WITH([qt4], + AC_HELP_STRING([--with-qt4@<:@=DIR@:>@], [where the Qt4 package with a standard install is: default @<:@$QTDIR@:>@ or @<:@/usr@:>@]), + [qt4_install_path=$withval], [withval=notset]) + + # --- if qt4 standard install directory is defined but with no path: QTDIR value if defined, or /usr + if test x${withval} = xyes + then + if test -z $QTDIR + then + qt4_install_path="/usr" + else + qt4_install_path=$QTDIR + fi + fi + + # --- if qt4 standard install directory is not defined: QTDIR value if defined, or /usr + if test x${withval} = xnotset + then + if test -z $QTDIR + then + qt4_install_path="/usr" + else + if test $QTDIR = /usr/lib/qt3 ; then + if test -d /usr/lib/qt4 ; then + AC_MSG_RESULT(it is strange for a qt4 installation !) + AC_MSG_RESULT(/usr/lib/qt4 is present) + AC_MSG_RESULT(replacing QTDIR by /usr/lib/qt4) + QTDIR=/usr/lib/qt4 + fi + fi + qt4_install_path=$QTDIR + fi + fi + + # --- if qt4 standard install directory is not wanted: --without-qt4 or --with-qt4=no + if test x${withval} = xno + then + qt4_install_path="" + fi + + QT_DIR=${qt4_install_path} + AC_SUBST(QT_DIR) + + # --- check if qt4 includes directory is defined + qt4_include_path="" + AC_ARG_WITH([qt4-includes], + AC_HELP_STRING([--with-qt4-includes@<:@=DIR@:>@], [where the Qt4 includes are: default @<:@$QTDIR/include@:>@ or @<:@/usr/include@:>@]), + [qt4_include_path=$withval], [withval=no]) + if test x${withval} != xno + then + # --- qt4 includes directory is defined + if test x${qt4_include_path} = xyes + then + qt4_include_path="/usr/include" + fi + else + if test x${qt4_install_path} != x + then + qt4_include_path="${qt4_install_path}/include" + fi + fi + + + # --- check if qt4 libraries directory is defined + qt4_library_path="" + AC_ARG_WITH([qt4-libraries], + AC_HELP_STRING([--with-qt4-libraries@<:@=DIR@:>@], [where the Qt4 libraries are: default @<:@$QTDIR/lib@:>@ or @<:@/usr/lib@:>@]), + [qt4_library_path=$withval], [withval=no]) + if test x${withval} != xno + then + # --- qt4 libraries directory is defined + if test x${qt4_library_path} = xyes + then + qt4_library_path="/usr/lib" + fi + else + if test x${qt4_install_path} != x + then + qt4_library_path="${qt4_install_path}/lib" + fi + fi + + # --- check if qt4 tools directory is defined + qt4_tools_path="" + AC_ARG_WITH([qt4-tools], + AC_HELP_STRING([--with-qt4-tools@<:@=DIR@:>@], [where the Qt4 executable tools are: default @<:@$QTDIR/bin@:>@ or @<:@/usr/bin@:>@]), + [qt4_tools_path=$withval], [withval=no]) + if test x${withval} != xno + then + # --- qt4 tools directory is defined + if test x${qt4_tools_path} = xyes + then + qt4_tools_path="/usr/bin" + fi + else + if test x${qt4_install_path} != x + then + qt4_tools_path="${qt4_install_path}/bin" + fi + fi + + WITH_QT4=0 + + AC_MSG_NOTICE(${qt4_include_path}) + AC_MSG_NOTICE(${qt4_library_path}) + AC_MSG_NOTICE(${qt4_tools_path}) + + # test if qt4 is completely defined + qt4_defined=yes + if test x${qt4_include_path} = x + then + qt4_defined=no + AC_MSG_NOTICE([No Qt4 include path defined]) + fi + if test x${qt4_library_path} = x + then + qt4_defined=no + AC_MSG_NOTICE([No Qt4 library path defined]) + fi + if test x${qt4_tools_path} = x + then + qt4_defined=no + AC_MSG_NOTICE([No Qt4 tools path defined]) + fi + + # saving values for compilation variables + saved_CPPFLAGS=$CPPFLAGS + saved_LDFLAGS=$LDFLAGS + saved_LIBS=$LIBS + + if ! test x${qt4_defined} = xno + then + # ask for qt4 support + AC_MSG_NOTICE([checking whether qt4 tools and headers are present]) + + # --- we test the presence of moc,first under the form moc-qt4, then moc + AC_PATH_PROGS(qt4_moc_found, [moc-qt4 moc], no, ${qt4_tools_path}) + test x${qt4_moc_found} = xno && AC_MSG_ERROR([Qt4 moc command NOT FOUND]) + QT_MOC=$qt4_moc_found + AC_SUBST(QT_MOC) + + # --- we test the presence of uic,first under the form uic-qt4, then uic + AC_PATH_PROGS(qt4_uic_found, [uic-qt4 uic], no, ${qt4_tools_path}) + test x${qt4_uic_found} = xno && AC_MSG_ERROR([Qt4 uic command NOT FOUND]) + QT_UIC=$qt4_uic_found + AC_SUBST(QT_UIC) + + # --- we test the presence of rcc,first under the form rcc-qt4, then rcc + AC_PATH_PROGS(qt4_rcc_found, [rcc-qt4 rcc], no, ${qt4_tools_path}) + test x${qt4_rcc_found} = xno && AC_MSG_ERROR([Qt4 rcc command NOT FOUND]) + QT_RCC=$qt4_rcc_found + AC_SUBST(QT_RCC) + + # --- we test the header file presence and usability + QTINC="" + AC_CHECK_FILE($qt4_include_path/qt4/QtCore/qglobal.h,QTINC="/qt4",QTINC="") + qt4_include_path="$qt4_include_path${QTINC}" + qt4_cppflags="" + qt4_cppflags="${qt4_cppflags} -I$qt4_include_path/QtCore" + qt4_cppflags="${qt4_cppflags} -I$qt4_include_path/QtGui" + qt4_cppflags="${qt4_cppflags} -I$qt4_include_path/Qt" + qt4_cppflags="${qt4_cppflags} -I$qt4_include_path" + CPPFLAGS="${CPPFLAGS} ${qt4_cppflags}" + AC_LANG_PUSH(C++) + AC_CHECK_HEADERS([qapplication.h], + [qt4_header_found=yes], + [qt4_header_found=no], + []) + AC_LANG_POP(C++) + test x${qt4_header_found} = xno && AC_MSG_ERROR([Qt4 include file NOT FOUND]) + AC_SUBST(qt4_cppflags) + + # --- we test the library file presence and usability + if test x${qt4_library_path} = /usr/lib + then + qt4_ldflags="" + else + qt4_ldflags="-L$qt4_library_path" + fi + + AC_MSG_NOTICE([checking whether link with qt4 is working]) + qt4_lib_name=QtGui + qt4_libs="-l$qt4_lib_name" + LDFLAGS="${LDFLAGS} ${qt4_ldflags}" + LIBS="${LIBS} ${qt4_libs}" + AC_LANG_PUSH(C++) + + AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[ #include + #include ]], + [[ QApplication app(0, 0); + QPushButton hello("Hello world!"); + hello.resize(100, 30); + hello.show(); ]] )], + [qt4_lib_found=yes], [qt4_lib_found=no] ) + + test x${qt4_lib_found} = xno && AC_MSG_ERROR([Qt4 library NOT FOUND]) + + AC_LANG_POP(C++) + AC_SUBST(qt4_ldflags) + AC_SUBST(qt4_libs) + + # --- after all tests are successful, we support Qt4 + WITH_QT4=1 + qt_ok=yes + AC_MSG_NOTICE([Qt4 support is OK]) + + else + # --- no Qt4 support + AC_MSG_NOTICE([No Qt4 support]) + fi + + # Propagate test into atlocal + AC_SUBST(WITH_QT4) + + # Propagate test into Makefiles... + AM_CONDITIONAL(WITH_QT4, test $WITH_QT4 = 1) + + # ... and into source files + AC_DEFINE_UNQUOTED(HAS_QT4, $WITH_QT4, [Qt4 library]) + + # restoring saved values + CPPFLAGS=$saved_CPPFLAGS + LDFLAGS=$saved_LDFLAGS + LIBS=$saved_LIBS + +]) + + +AC_DEFUN([I2_CHECK_QSCINTILLA], +[ + AC_REQUIRE([I2_CHECK_QT4]) + + qscintilla_ok=no + WITH_QSCI4=0 + + # --- check if qsci4 includes directory is defined + qsci4_include_path="" + qsci4_cppflags="" + + AC_ARG_WITH([qsci4-includes], + AC_HELP_STRING([--with-qsci4-includes@<:@=DIR@:>@], [where the Qsci4 includes are: default @<:@$QTDIR/include/Qsci@:>@ or @<:@/usr/include/Qsci@:>@]), + [qsci4_include_path=$withval]) + + if test x${qsci4_include_path} = x ; then + # --- "" --- try to use QSCINTILLA_DIR/include/Qsci + if test "x${QSCINTILLA_DIR}" != "x" ; then + qsci4_include_path="${QSCINTILLA_DIR}/include" + else + qsci4_include_path=no + fi + fi + + if test x${qsci4_include_path} = xno ; then + # --- "no" --- no native installation, try to find in Qt + qsci4_include_path="${QT_DIR}/include${QTINC}/Qsci" + qsci4_cppflags=" -I$qsci4_include_path" + # " -I${QT_DIR}/include${QTINC}" is included in qt4_cppflags + else + if test x${qsci4_include_path} = xyes ; then + # --- "yes" --- try to find in /usr/include/Qsci + qsci4_include_path="/usr/include${QTINC}/Qsci" + qsci4_cppflags=" -I$qsci4_include_path" + # " -I/usr/include${QTINC}" is included in qt4_cppflags or by default (if QTINC is empty) + else + # --- "other" --- try to find in given dir + qsci4_cppflags=" -I$qsci4_include_path/Qsci -I$qsci4_include_path" + fi + fi + + AC_MSG_NOTICE($qsci4_cppflags) + + # --- check if qsci4 libraries directory is defined + qsci4_library_path="" + + AC_ARG_WITH([qsci4-libraries], + AC_HELP_STRING([--with-qsci4-libraries@<:@=DIR@:>@], [where the Qsci4 libraries are: default @<:@$QTDIR/lib@:>@ or @<:@/usr/lib@:>@]), + [qsci4_library_path=$withval]) + + if test x${qsci4_library_path} = x ; then + # --- "" --- try to use QSCINTILLA_DIR/lib + if test "x${QSCINTILLA_DIR}" != "x" ; then + qsci4_library_path="${QSCINTILLA_DIR}/lib" + else + qsci4_library_path=no + fi + fi + + if test x${qsci4_library_path} = xno ; then + # --- "no" --- no native installation, try to find in Qt + qsci4_library_path="${QT_DIR}/lib" + else + if test x${qsci4_library_path} = xyes ; then + # --- "yes" --- try to find in /usr/lib + qsci4_library_path="/usr/lib" + fi + fi + + AC_MSG_NOTICE($qsci4_library_path) + + # saving values for compilation variables + saved_CPPFLAGS=$CPPFLAGS + saved_LDFLAGS=$LDFLAGS + saved_LIBS=$LIBS + + # ask for qsci4 support + AC_MSG_NOTICE([checking whether qscintilla for qt4 headers are present]) + + # --- we test the header file presence and usability + CPPFLAGS="${CPPFLAGS} ${qsci4_cppflags} ${qt4_cppflags}" + AC_LANG_PUSH(C++) + AC_CHECK_HEADERS([qsciscintilla.h], + [qsci4_header_found=yes], + [qsci4_header_found=no], + []) + AC_LANG_POP(C++) + if test x${qsci4_header_found} = xyes + then + AC_SUBST(qsci4_cppflags) + + # --- we test the library file presence and usability + if test x${qsci4_library_path} = x/usr/lib/qt4/lib + then + qsci4_library_path=/usr/lib + fi + if test x${qsci4_library_path} = x/usr/lib + then + qsci4_ldflags="" + else + qsci4_ldflags="-L$qsci4_library_path" + fi + + AC_MSG_NOTICE([checking whether qscintilla2 library is present]) + qsci4_libs=-lqscintilla2 + AC_CHECK_FILE([${qsci4_library_path}/libqscintilla2.so], + [qsci4_library_found=yes], + [qsci4_library_found=no]) + if test x${qsci4_library_found} = xyes + then + AC_MSG_NOTICE([qscintilla for qt4 support]) + AC_SUBST(qsci4_ldflags) + AC_SUBST(qsci4_libs) + WITH_QSCI4=1 + qscintilla_ok=yes + # Propagate test into atlocal + AC_SUBST(WITH_QSCI4) + fi + + else + AC_MSG_NOTICE([no support for qscintilla for qt4]) + fi + + # Propagate test into Makefiles... + AM_CONDITIONAL(WITH_QSCI4, test $WITH_QSCI4 = 1) + + # ... and into source files + AC_DEFINE_UNQUOTED(HAS_QSCI4, $WITH_QSCI4, [QsciScintilla library]) + + # restoring saved values + CPPFLAGS=$saved_CPPFLAGS + LDFLAGS=$saved_LDFLAGS + LIBS=$saved_LIBS + +]) diff --git a/m4/production.m4 b/m4/production.m4 new file mode 100644 index 0000000..802d37e --- /dev/null +++ b/m4/production.m4 @@ -0,0 +1,101 @@ +dnl Copyright (C) 2006-2008 CEA/DEN, EDF R&D +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl +dnl define macros : +dnl AC_ENABLE_PRODUCTION AC_DISABLE_PRODUCTION +dnl AC_ENABLE_DEBUG AC_DISABLE_DEBUG +dnl version $Id$ +dnl author Patrick GOLDBRONN +dnl +# AC_ENABLE_PRODUCTION +AC_DEFUN(AC_ENABLE_PRODUCTION, [dnl +define([AC_ENABLE_PRODUCTION_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(production, +changequote(<<, >>)dnl +<< --enable-production[=PKGS] build without debug information [default=>>AC_ENABLE_PRODUCTION_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_production=yes ;; +no) enable_production=no ;; +*) + enable_production=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_production=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_production=AC_ENABLE_PRODUCTION_DEFAULT)dnl +if test "X$enable_production" = "Xyes"; then + FFLAGS="$FFLAGS -O3 " + CFLAGS="$CFLAGS -O3 " + CXXFLAGS="$CXXFLAGS -O3 " +else + FFLAGS="$FFLAGS" + CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS" +fi +]) + +# AC_DISABLE_PRODUCTION - set the default flag to --disable-production +AC_DEFUN(AC_DISABLE_PRODUCTION, [AC_ENABLE_PRODUCTION(no)]) + +# AC_ENABLE_DEBUG +AC_DEFUN(AC_ENABLE_DEBUG, [dnl +define([AC_ENABLE_DEBUG_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(debug, +changequote(<<, >>)dnl +<< --enable-debug[=PKGS] build without debug information [default=>>AC_ENABLE_DEBUG_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_debug=yes ;; +no) enable_debug=no ;; +*) + enable_debug=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_debug=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_debug=AC_ENABLE_DEBUG_DEFAULT)dnl + +if test "X$enable_debug" = "Xyes"; then + FFLAGS="$FFLAGS -g " + CFLAGS="$CFLAGS -g " + CXXFLAGS="$CXXFLAGS -g -D_DEBUG_ " +else + FFLAGS="$FFLAGS" + CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS" +fi +]) + +# AC_DISABLE_DEBUG - set the default flag to --disable-debug +AC_DEFUN(AC_DISABLE_DEBUG, [AC_ENABLE_DEBUG(no)]) + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..0897ae9 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,20 @@ +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +SUBDIRS = bases engine genericgui wrappers standalone salomegui diff --git a/src/bases/BL_Exception.cxx b/src/bases/BL_Exception.cxx new file mode 100644 index 0000000..087eeb7 --- /dev/null +++ b/src/bases/BL_Exception.cxx @@ -0,0 +1,35 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_Exception.hxx" + +BL::Exception::Exception(const std::string& what):_what(what) +{ +} + +BL::Exception::~Exception() throw () +{ +} + +const char * +BL::Exception::what( void ) const throw () +{ + return _what.c_str(); +} + diff --git a/src/bases/BL_Exception.hxx b/src/bases/BL_Exception.hxx new file mode 100644 index 0000000..a03a836 --- /dev/null +++ b/src/bases/BL_Exception.hxx @@ -0,0 +1,38 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// +#ifndef __BL_EXCEPTION_HXX__ +#define __BL_EXCEPTION_HXX__ + +#include +#include + +namespace BL +{ + class Exception : public std::exception + { + protected: + std::string _what; + public: + Exception(const std::string& what); + const char *what( void ) const throw (); + virtual ~Exception() throw (); + }; +} + +#endif diff --git a/src/bases/BL_Traces.hxx b/src/bases/BL_Traces.hxx new file mode 100644 index 0000000..74ea636 --- /dev/null +++ b/src/bases/BL_Traces.hxx @@ -0,0 +1,38 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef __BL_TRACES_HXX__ +#define __BL_TRACES_HXX__ + +#include "BL_Exception.hxx" +#include +#include + +#ifdef _DEBUG_ +#define DEBTRACE(msg) {std::cerr< +#include + +namespace BL{ + + class Job + { + public: + Job(); + Job(const std::string & name); + virtual ~Job(); + + void setName(const std::string & name); + std::string getName(); + + enum JobType {YACS_SCHEMA, COMMAND}; + void setType(BL::Job::JobType type); + BL::Job::JobType getType(); + + void setYACSFile(std::string & yacs_file); + std::string & getYACSFile(); + + void setCommand(std::string & command); + std::string & getCommand(); + + struct BatchParam + { + std::string batch_directory; + std::string expected_during_time; + std::string expected_memory; + int nb_proc; + }; + void setBatchParameters(BL::Job::BatchParam & param); + BL::Job::BatchParam & getBatchParameters(); + + struct FilesParam + { + std::string result_directory; + std::list input_files_list; + std::list output_files_list; + }; + void setFilesParameters(BL::Job::FilesParam & param); + BL::Job::FilesParam & getFilesParameters(); + + void setMachine(std::string & machine); + std::string & getMachine(); + + enum State {CREATED, IN_PROCESS, QUEUED, RUNNING, PAUSED, FINISHED, ERROR}; + void setState(BL::Job::State state); + BL::Job::State getState(); + + enum ThreadState {NOTHING, STARTING}; + void setThreadState(BL::Job::ThreadState state); + BL::Job::ThreadState getThreadState(); + + void setSalomeLauncherId(int id); + int getSalomeLauncherId(); + + + private: + BL::Job::State _state; + BL::Job::ThreadState _thread_state; + + std::string _name; + + BL::Job::JobType _type; + std::string _yacs_file; + std::string _command; + + BL::Job::BatchParam _batch_params; + BL::Job::FilesParam _files_params; + std::string _machine_choosed; + + int _salome_launcher_id; + }; + +} + +#endif diff --git a/src/engine/BL_JobsManager.cxx b/src/engine/BL_JobsManager.cxx new file mode 100644 index 0000000..985d280 --- /dev/null +++ b/src/engine/BL_JobsManager.cxx @@ -0,0 +1,327 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_JobsManager.hxx" + +BL::JobsManager::JobsManager(BL::SALOMEServices * salome_services) +{ + DEBTRACE("Creating BL::JobsManager"); + BL_ASSERT(salome_services); + _salome_services = salome_services; + _observer = NULL; +} + +BL::JobsManager::~JobsManager() +{ + DEBTRACE("Destroying BL::JobsManager"); + + // Delete All Jobs ! + _jobs_it = _jobs.begin(); + for(;_jobs_it != _jobs.end();_jobs_it++) + delete _jobs_it->second; +} + +void +BL::JobsManager::setObserver(BL::Observer * observer) +{ + BL_ASSERT(observer); + _observer = observer; +} + +BL::Job * +BL::JobsManager::addNewJob(const std::string & name) +{ + DEBTRACE("addNewJob BL::JobsManager"); + + BL::Job * new_job = NULL; + + _jobs_it = _jobs.find(name); + if (_jobs_it == _jobs.end()) + { + new_job = new BL::Job(name); + + // Ajout dans la liste + _jobs[name] = new_job; + } + else + DEBTRACE("addNewJob Error !!!! Job already exist: " << name); + + return new_job; +} + +void +BL::JobsManager::removeJob(const std::string & name) +{ + DEBTRACE("removeJob BL::JobsManager"); + _jobs_it = _jobs.find(name); + if (_jobs_it != _jobs.end()) + { + std::string result = ""; + if (_jobs_it->second->getSalomeLauncherId() != -1) + result = _salome_services->delete_job(_jobs_it->second); + + delete _jobs_it->second; + _jobs.erase(_jobs_it->first); + + if (_observer) + if (result != "") + _observer->sendEvent("delete_job", "Error", name, result); + else + _observer->sendEvent("delete_job", "Ok", name, ""); + } + else + DEBTRACE("removeJob Error !!!! Job does not exist: " << name); +} + +BL::Job * +BL::JobsManager::getJob(const std::string & name) +{ + DEBTRACE("getJob BL::JobsManager called"); + return _jobs[name]; +} + +std::map & +BL::JobsManager::getJobs() +{ + return _jobs; +} + +bool +BL::JobsManager::job_already_exist(const std::string & name) +{ + _jobs_it = _jobs.find(name); + + if (_jobs_it == _jobs.end()) + return false; + else + return true; + +} + +void +BL::JobsManager::start_job(const std::string & name) +{ + DEBTRACE("BL::JobsManager::start_job called for job: " << name); + + // Check job exits + _jobs_it = _jobs.find(name); + if (_jobs_it == _jobs.end()) + { + DEBTRACE("BL::JobsManager::start_job job unknown: " << name); + return; + } + else + { + _thread_mutex.lock(); + BL::Job * job = _jobs_it->second; + // Check Job Exec State - multithread protection + if (job->getThreadState() == BL::Job::NOTHING) + { + // Prepare Info for thread + BL::JobsManager::thread_info * ti = new thread_info(); + ti->object_ptr = this; + ti->job_name = name; + job->setState(BL::Job::IN_PROCESS); + job->setThreadState(BL::Job::STARTING); + omni_thread::create(BL::JobsManager::starting_job_thread, ti); + } + else + { + DEBTRACE("BL::JobsManager::start_job nothin to do, job already starting, job name: " << name); + } + _thread_mutex.unlock(); + } +} + +void +BL::JobsManager::starting_job_thread(void * object_ptr) +{ + DEBTRACE("starting_job_thread BL::JobsManager called"); + BL::JobsManager::thread_info * ti = reinterpret_cast(object_ptr); + BL::JobsManager * object = ti->object_ptr; + std::string job_name = ti->job_name; + BL::Job * job = object->getJob(job_name); + + std::string result = object->_salome_services->start_job(job); + + object->_thread_mutex.lock(); + // End + if (result == "") + { + if (object->_observer) + object->_observer->sendEvent("start_job", "Ok", job_name, ""); + job->setState(BL::Job::QUEUED); + job->setThreadState(BL::Job::NOTHING); + } + else + { + if (object->_observer) + object->_observer->sendEvent("start_job", "Error", job_name, result); + job->setState(BL::Job::ERROR); + job->setThreadState(BL::Job::NOTHING); + } + object->_thread_mutex.unlock(); +} + +void +BL::JobsManager::refresh_jobs() +{ + DEBTRACE("refresh_jobs BL::JobsManager called"); + + omni_thread::create(BL::JobsManager::refresh_job, this); +} + +void +BL::JobsManager::refresh_job(void * object_ptr) +{ + DEBTRACE("refresh_job BL::JobsManager called"); + BL::JobsManager * object = reinterpret_cast(object_ptr); + + //iterate on all jobs + _jobs_map::iterator jobs_it; + jobs_it = object->_jobs.begin(); + for(;jobs_it != object->_jobs.end();jobs_it++) + { + BL::Job * job = jobs_it->second; + if (job->getSalomeLauncherId() != -1) + { + object->_thread_mutex.lock(); + if (job->getThreadState() == BL::Job::NOTHING) + { + BL::Job::State job_state = job->getState(); + if (job_state != BL::Job::FINISHED or job_state != BL::Job::ERROR) + { + std::string result = object->_salome_services->refresh_job(job); + if (result == "QUEUED") + { + if (job_state != BL::Job::QUEUED) + { + job->setState(BL::Job::QUEUED); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + } + else if (result == "IN_PROCESS") + { + if (job_state != BL::Job::IN_PROCESS) + { + job->setState(BL::Job::IN_PROCESS); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + } + else if (result == "RUNNING") + { + if (job_state != BL::Job::RUNNING) + { + job->setState(BL::Job::RUNNING); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + } + else if (result == "PAUSED") + { + if (job_state != BL::Job::PAUSED) + { + job->setState(BL::Job::PAUSED); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + } + else if (result == "FINISHED") + { + job->setState(BL::Job::FINISHED); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + else if (result == "ERROR") + { + job->setState(BL::Job::ERROR); + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Ok", job->getName(), "new state"); + } + else + { + // Error using launcher... + if (object->_observer) + object->_observer->sendEvent("refresh_job", "Error", job->getName(), result); + } + } + } + object->_thread_mutex.unlock(); + } + } +} + +void +BL::JobsManager::get_results_job(const std::string & name) +{ + DEBTRACE("get_results_job BL::JobsManager called"); + + // Check job exits + _jobs_it = _jobs.find(name); + if (_jobs_it == _jobs.end()) + { + DEBTRACE("BL::JobsManager::get_results_job job unknown: " << name); + return; + } + else + { + BL::Job * job = _jobs_it->second; + if (job->getState() == BL::Job::FINISHED) + { + // Prepare Info for thread + BL::JobsManager::thread_info * ti = new thread_info(); + ti->object_ptr = this; + ti->job_name = name; + omni_thread::create(BL::JobsManager::get_results_job_thread, ti); + } + else + { + DEBTRACE("BL::JobsManager::get_results_job job bad job state !"); + return; + } + } +} + +void +BL::JobsManager::get_results_job_thread(void * object_ptr) +{ + DEBTRACE("get_results_job_thread BL::JobsManager called"); + BL::JobsManager::thread_info * ti = reinterpret_cast(object_ptr); + BL::JobsManager * object = ti->object_ptr; + std::string job_name = ti->job_name; + BL::Job * job = object->getJob(job_name); + + object->_thread_mutex_results.lock(); + std::string result = object->_salome_services->get_results_job(job); + + // End + if (result == "") + { + if (object->_observer) + object->_observer->sendEvent("get_results_job", "Ok", job_name, ""); + } + else + { + if (object->_observer) + object->_observer->sendEvent("get_results_job", "Error", job_name, result); + } + object->_thread_mutex_results.unlock(); +} diff --git a/src/engine/BL_JobsManager.hxx b/src/engine/BL_JobsManager.hxx new file mode 100644 index 0000000..675a5ab --- /dev/null +++ b/src/engine/BL_JobsManager.hxx @@ -0,0 +1,81 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_JOBSMANAGER_HXX_ +#define _BL_JOBSMANAGER_HXX_ + +#include "BL_Job.hxx" +#include "BL_SALOMEServices.hxx" +#include "BL_Traces.hxx" +#include "BL_Observer.hxx" + +#include +#include + +#include + +namespace BL{ + + class JobsManager + { + public: + JobsManager(BL::SALOMEServices * salome_services); + virtual ~JobsManager(); + + void setObserver(BL::Observer * observer); + + BL::Job * addNewJob(const std::string & name); + void removeJob(const std::string & name); + + BL::Job * getJob(const std::string & name); + std::map & getJobs(); + + bool job_already_exist(const std::string & name); + + virtual void start_job(const std::string & name); + virtual void refresh_jobs(); + virtual void get_results_job(const std::string & name); + + static void starting_job_thread(void * object_ptr); + static void get_results_job_thread(void * object_ptr); + static void refresh_job(void * object_ptr); + + struct thread_info + { + BL::JobsManager * object_ptr; + std::string job_name; + }; + + protected: + BL::SALOMEServices * _salome_services; + BL::Observer * _observer; + + private: + typedef std::map _jobs_map; + _jobs_map _jobs; + _jobs_map::iterator _jobs_it; + + omni_mutex _thread_mutex; + omni_mutex _thread_mutex_results; + }; + +} + +#endif + diff --git a/src/engine/BL_SALOMEServices.cxx b/src/engine/BL_SALOMEServices.cxx new file mode 100644 index 0000000..8f6a9d0 --- /dev/null +++ b/src/engine/BL_SALOMEServices.cxx @@ -0,0 +1,214 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_SALOMEServices.hxx" + +BL::SALOMEServices::SALOMEServices() +{ + int nbargs = 0; char **args = 0; + _orb = CORBA::ORB_init (nbargs, args); + _salome_naming_service = NULL; + _lcc = NULL; + _state = false; +} + +BL::SALOMEServices::~SALOMEServices() +{ + if (_salome_naming_service) + delete _salome_naming_service; + if (_lcc) + delete _lcc; +} + +bool +BL::SALOMEServices::initNS() +{ + bool return_value = true; + _salome_naming_service = new SALOME_NamingService(_orb); + _lcc = new SALOME_LifeCycleCORBA(_salome_naming_service); + CORBA::Object_var obj = _salome_naming_service->Resolve("/SalomeLauncher"); + _salome_launcher = Engines::SalomeLauncher::_narrow(obj); + + if (CORBA::is_nil(_salome_launcher)) + { + DEBTRACE("SALOME Launcher is not reachable!") + return_value = false; + } + + obj = _salome_naming_service->Resolve("/ResourcesManager"); + _resources_manager = Engines::ResourcesManager::_narrow(obj); + if (CORBA::is_nil(_resources_manager)) + { + DEBTRACE("SALOME Resource Manager is not reachable !"); + return_value = false; + } + + _state = return_value; + return return_value; +} + +std::list +BL::SALOMEServices::getMachineList() +{ + std::list machine_list; + + if (_state) + { + Engines::MachineParameters params; + _lcc->preSet(params); + Engines::MachineList * machineList = _resources_manager->GetFittingResources(params); + for (int i = 0; i < machineList->length(); i++) + { + const char* aMachine = (*machineList)[i]; + machine_list.push_back(aMachine); + } + } + + return machine_list; +} + +std::string +BL::SALOMEServices::start_job(BL::Job * job) +{ + return start_yacs_job(job); +} + +std::string +BL::SALOMEServices::start_yacs_job(BL::Job * job) +{ + std::string ret = ""; + // Prepare Arguments + const char * fileToExecute = job->getYACSFile().c_str(); + + BL::Job::FilesParam files = job->getFilesParameters(); + Engines::FilesList_var filesToExport = new Engines::FilesList; + filesToExport->length(files.input_files_list.size()); + std::list::iterator it; + int i = 0; + for (it=files.input_files_list.begin() ; it != files.input_files_list.end(); it++) + { + filesToExport[i] = CORBA::string_dup((*it).c_str()); + i++; + } + Engines::FilesList_var filesToImport = new Engines::FilesList; + filesToImport->length(files.output_files_list.size()); + i = 0; + for (it=files.output_files_list.begin() ; it != files.output_files_list.end(); it++) + { + filesToImport[i] = CORBA::string_dup((*it).c_str()); + i++; + } + + BL::Job::BatchParam cpp_batch_params = job->getBatchParameters(); + Engines::BatchParameters_var batch_params = new Engines::BatchParameters; + batch_params->batch_directory = CORBA::string_dup(cpp_batch_params.batch_directory.c_str()); + batch_params->expected_during_time = CORBA::string_dup(cpp_batch_params.expected_during_time.c_str()); + batch_params->mem = CORBA::string_dup(cpp_batch_params.expected_memory.c_str()); + batch_params->nb_proc = cpp_batch_params.nb_proc; + + Engines::MachineParameters_var machine = new Engines::MachineParameters; + machine->hostname = CORBA::string_dup(job->getMachine().c_str()); + + // Start Job ! + try + { + int job_id = _salome_launcher->submitSalomeJob(fileToExecute, filesToExport, + filesToImport, batch_params, machine); + job->setSalomeLauncherId(job_id); + } + catch (const SALOME::SALOME_Exception & ex) + { + DEBTRACE("SALOME Exception in submitSalomeJob !"); + ret = ex.details.text.in(); + } + return ret; +} + +std::string +BL::SALOMEServices::refresh_job(BL::Job * job) +{ + std::string ret = ""; + + Engines::MachineParameters_var machine = new Engines::MachineParameters; + machine->hostname = CORBA::string_dup(job->getMachine().c_str()); + + // Refresh Job ! + try + { + CORBA::String_var result = _salome_launcher->queryJob(job->getSalomeLauncherId(), machine); + std::string res = result.in(); + if (res == "Running") + return "RUNNING"; + else if (res == "Done") + return "FINISHED"; + else + return result.in(); + } + catch (const SALOME::SALOME_Exception & ex) + { + DEBTRACE("SALOME Exception in refresh_job !"); + ret = ex.details.text.in(); + } + return ret; +} + +std::string +BL::SALOMEServices::delete_job(BL::Job * job) +{ + std::string ret = ""; + + Engines::MachineParameters_var machine = new Engines::MachineParameters; + machine->hostname = CORBA::string_dup(job->getMachine().c_str()); + + // Delete Job ! + try + { + _salome_launcher->deleteJob(job->getSalomeLauncherId(), machine); + } + catch (const SALOME::SALOME_Exception & ex) + { + DEBTRACE("SALOME Exception in refresh_job !"); + ret = ex.details.text.in(); + } + return ret; +} + +std::string +BL::SALOMEServices::get_results_job(BL::Job * job) +{ + std::string ret = ""; + + Engines::MachineParameters_var machine = new Engines::MachineParameters; + machine->hostname = CORBA::string_dup(job->getMachine().c_str()); + + BL::Job::FilesParam files = job->getFilesParameters(); + CORBA::String_var directory = CORBA::string_dup(files.result_directory.c_str()); + + // get job results ! + try + { + _salome_launcher->getResultsJob(directory, job->getSalomeLauncherId(), machine); + } + catch (const SALOME::SALOME_Exception & ex) + { + DEBTRACE("SALOME Exception in refresh_job !"); + ret = ex.details.text.in(); + } + return ret; +} diff --git a/src/engine/BL_SALOMEServices.hxx b/src/engine/BL_SALOMEServices.hxx new file mode 100644 index 0000000..f5e597d --- /dev/null +++ b/src/engine/BL_SALOMEServices.hxx @@ -0,0 +1,68 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_SALOMESERVICES_HXX_ +#define _BL_SALOMESERVICES_HXX_ + +#include "BL_Traces.hxx" +#include "BL_Job.hxx" + +#include "SALOME_NamingService.hxx" +#include "SALOME_LifeCycleCORBA.hxx" +#include "SALOME_ContainerManager.hh" + +#include +#include +#include + +namespace BL{ + + class SALOMEServices + { + public: + SALOMEServices(); + virtual ~SALOMEServices(); + + bool initNS(); + + std::list getMachineList(); + + std::string start_job(BL::Job * job); + std::string refresh_job(BL::Job * job); + std::string delete_job(BL::Job * job); + std::string get_results_job(BL::Job * job); + + protected: + std::string start_yacs_job(BL::Job * job); + + private: + CORBA::ORB_var _orb; + SALOME_NamingService * _salome_naming_service; + SALOME_LifeCycleCORBA * _lcc; + Engines::SalomeLauncher_var _salome_launcher; + Engines::ResourcesManager_var _resources_manager; + + bool _state; + }; + +} + +#endif + + diff --git a/src/genericgui/BL_Buttons.cxx b/src/genericgui/BL_Buttons.cxx new file mode 100644 index 0000000..b13f7df --- /dev/null +++ b/src/genericgui/BL_Buttons.cxx @@ -0,0 +1,120 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_Buttons.hxx" + +BL::Buttons::Buttons(QWidget * parent) : QGroupBox(parent) +{ + DEBTRACE("Creating BL::Buttons"); + + setTitle("Actions"); + + _create_button = new QPushButton("Create Job", this); + _start_button = new QPushButton("Start Job", this); + _delete_button = new QPushButton("Delete Job", this); + _get_results_button = new QPushButton("Get Job Results", this); + _refresh_button = new QPushButton("Refresh Jobs", this); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(_create_button); + mainLayout->addWidget(_start_button); + mainLayout->addWidget(_delete_button); + mainLayout->addWidget(_get_results_button); + mainLayout->addWidget(_refresh_button); + mainLayout->setSpacing(0); // Space between buttons + + setLayout(mainLayout); + + //QSizePolicy poli; + //poli.setControlType(QSizePolicy::PushButton); + //poli.setVerticalPolicy(QSizePolicy::Fixed); + //poli.setHorizontalPolicy(QSizePolicy::Fixed); + //setSizePolicy(poli); +} + +BL::Buttons::~Buttons() +{ + DEBTRACE("Destroying BL::Buttons"); +} + +void +BL::Buttons::setCreateButtonSlot(QObject * receiver, const char * name) +{ + connect(_create_button, SIGNAL(clicked()), receiver, name); +} + +void +BL::Buttons::setStartButtonSlot(QObject * receiver, const char * name) +{ + connect(_start_button, SIGNAL(clicked()), receiver, name); +} + +void +BL::Buttons::setDeleteButtonSlot(QObject * receiver, const char * name) +{ + connect(_delete_button, SIGNAL(clicked()), receiver, name); +} + +void +BL::Buttons::setRefreshButtonSlot(QObject * receiver, const char * name) +{ + connect(_refresh_button, SIGNAL(clicked()), receiver, name); +} + +void +BL::Buttons::setGetResultsButtonSlot(QObject * receiver, const char * name) +{ + connect(_get_results_button, SIGNAL(clicked()), receiver, name); +} + +void +BL::Buttons::enable_start_button() +{ + _start_button->setEnabled(true); +} + +void +BL::Buttons::disable_start_button() +{ + _start_button->setEnabled(false); +} + +void +BL::Buttons::enable_delete_button() +{ + _delete_button->setEnabled(true); +} + +void +BL::Buttons::disable_delete_button() +{ + _delete_button->setEnabled(false); +} + +void +BL::Buttons::enable_get_results_button() +{ + _get_results_button->setEnabled(true); +} + +void +BL::Buttons::disable_get_results_button() +{ + _get_results_button->setEnabled(false); +} diff --git a/src/genericgui/BL_Buttons.hxx b/src/genericgui/BL_Buttons.hxx new file mode 100644 index 0000000..866e96d --- /dev/null +++ b/src/genericgui/BL_Buttons.hxx @@ -0,0 +1,62 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_BUTTONS_HXX_ +#define _BL_BUTTONS_HXX_ + +#include + +#include "BL_Traces.hxx" + +namespace BL +{ + class Buttons: public QGroupBox + { + Q_OBJECT + + public: + Buttons(QWidget * parent); + virtual ~Buttons(); + + void setCreateButtonSlot(QObject * receiver, const char * name); + void setStartButtonSlot(QObject * receiver, const char * name); + void setDeleteButtonSlot(QObject * receiver, const char * name); + void setRefreshButtonSlot(QObject * receiver, const char * name); + void setGetResultsButtonSlot(QObject * receiver, const char * name); + + void enable_start_button(); + void disable_start_button(); + + void enable_delete_button(); + void disable_delete_button(); + + void enable_get_results_button(); + void disable_get_results_button(); + + protected: + QPushButton * _create_button; + QPushButton * _start_button; + QPushButton * _delete_button; + QPushButton * _get_results_button; + QPushButton * _refresh_button; + }; +} + +#endif + diff --git a/src/genericgui/BL_CreateJobWizard.cxx b/src/genericgui/BL_CreateJobWizard.cxx new file mode 100644 index 0000000..99ae4ee --- /dev/null +++ b/src/genericgui/BL_CreateJobWizard.cxx @@ -0,0 +1,686 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_CreateJobWizard.hxx" + +BL::CreateJobWizard::CreateJobWizard(BL::JobsManager_QT * jobs_manager, BL::SALOMEServices * salome_services) +{ + DEBTRACE("Creating BL::CreateJobWizard"); + BL_ASSERT(jobs_manager); + BL_ASSERT(salome_services); + _jobs_manager = jobs_manager; + + job_name = ""; + yacs_file = ""; + command = ""; + batch_directory = ""; + expected_during_time = ""; + expected_memory = ""; + nb_proc = 1; + + result_directory = ""; + + machine_choosed = ""; + + start_job = false; + + setOptions(QWizard::IndependentPages | QWizard::NoBackButtonOnStartPage); + + setPage(Page_JobName, new BL::CreateJobWizard::JobNamePage(this, _jobs_manager)); + setPage(Page_YACSSchema, new BL::YACSSchemaPage(this)); + setPage(Page_BatchParameters, new BL::BatchParametersPage(this)); + setPage(Page_Files, new BL::FilesPage(this)); + setPage(Page_Command_Main_Definitions, new BL::CreateJobWizard::CommandMainPage(this)); + setPage(Page_Machine, new BL::MachinePage(this, salome_services)); + setPage(Page_Conclusion, new BL::CreateJobWizard::ConclusionPage(this)); + + setWindowTitle("Create Job Wizard"); + connect(this, SIGNAL(finished(int)), this, SLOT(end(int))); +} + +BL::CreateJobWizard::~CreateJobWizard() +{ + DEBTRACE("Destroying BL::CreateJobWizard"); +} + +void +BL::CreateJobWizard::setFilesList(QListWidget * input_files_list, QListWidget * output_files_list) +{ + _input_files_list = input_files_list; + _output_files_list = output_files_list; +} + +void +BL::CreateJobWizard::end(int result) +{ + DEBTRACE("End of BL::CreateJobWizard"); + if (result) + { + // Job Name Panel + QString f_job_name = field("job_name").toString(); + job_name = f_job_name.toStdString(); + + // YACS Schema Panel + QString f_yacs_file = field("yacs_file").toString(); + yacs_file = f_yacs_file.toStdString(); + + // Command Panel + QString f_command = field("command").toString(); + command = f_command.toStdString(); + + // Batch Panel + QString f_batch_directory = field("batch_directory").toString(); + batch_directory = f_batch_directory.toStdString(); + + QString time_hour; + QString time_min; + if (field("during_time_hour").toInt() < 10) + time_hour = "0" + field("during_time_hour").toString(); + else + time_hour = field("during_time_hour").toString(); + if (field("during_time_min").toInt() < 10) + time_min = "0" + field("during_time_min").toString(); + else + time_min = field("during_time_min").toString(); + expected_during_time = time_hour.toStdString() + ":" + time_min.toStdString() + ":00"; + + QString mem = field("mem_value").toString(); + int mem_type_i = field("mem_type").toInt(); + QString mem_type("gb"); + if (mem_type_i == 0) + mem_type = "mb"; + expected_memory = mem.toStdString() + mem_type.toStdString(); + + nb_proc = field("proc_value").toInt(); + + // Files Panel + QString f_result_directory = field("result_directory").toString(); + result_directory = f_result_directory.toStdString(); + for (int i = 0; i < _input_files_list->count(); ++i) + { + QListWidgetItem * item = _input_files_list->item(i); + QString item_text = item->text(); + input_files_list.push_back(item_text.toStdString()); + } + for (int i = 0; i < _output_files_list->count(); ++i) + { + QListWidgetItem * item = _output_files_list->item(i); + QString item_text = item->text(); + output_files_list.push_back(item_text.toStdString()); + } + + // Machine list + QString f_machine_choosed = field("machine_choosed").toString(); + machine_choosed = f_machine_choosed.toStdString(); + + start_job = field("start_job").toBool(); + } +} + +// Job Name Page +BL::CreateJobWizard::JobNamePage::JobNamePage(QWidget * parent, BL::JobsManager_QT * jobs_manager) +: QWizardPage(parent) +{ + _jobs_manager = jobs_manager; + setTitle("Create a new job"); + + QLabel *label = new QLabel("Enter Job name, you cannot add two jobs with the same name"); + label->setWordWrap(true); + QLabel * nameLabel = new QLabel("Job Name:"); + QLineEdit * _nameLineEdit = new QLineEdit(this); + registerField("job_name", _nameLineEdit); + + QLabel * label_type = new QLabel("Choose type of batch job:"); + QGroupBox *groupBox = new QGroupBox(); + _yacs_schema_button = new QRadioButton(tr("YACS Schema")); + _yacs_schema_button->setChecked(true); + QRadioButton *radio2 = new QRadioButton(tr("Command")); + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(_yacs_schema_button); + vbox->addWidget(radio2); + vbox->addStretch(1); + groupBox->setLayout(vbox); + + // Layouts + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(label); + QGridLayout *layout = new QGridLayout; + layout->addWidget(nameLabel, 0, 0); + layout->addWidget(_nameLineEdit, 0, 1); + main_layout->insertLayout(-1, layout); + layout->addWidget(label_type, 2, 0); + layout->addWidget(groupBox, 3, 0, 1, -1); + setLayout(main_layout); +} + +BL::CreateJobWizard::JobNamePage::~JobNamePage() +{} + +bool +BL::CreateJobWizard::JobNamePage::validatePage() +{ + DEBTRACE("Calling validatePage of BL::CreateJobWizard::JobNamePage"); + bool return_value; + QString job_name = field("job_name").toString(); + + // Check if job name is empty + if (job_name == "") + { + QMessageBox::warning(NULL, "Job Name Error", "Job name entered is empty, enter a job name or cancel the wizard"); + return_value = false; + } + + // Check if job name already exists + else { + if (_jobs_manager->job_already_exist(job_name.toStdString()) == false) + { + return_value = true; + } + else + { + QMessageBox::critical(NULL, "Job Name Error", "Job name entered is already used"); + QString value(""); + setField("job_name", value); + return_value = false; + } + } + + return return_value; +} + +int +BL::CreateJobWizard::JobNamePage::nextId() const +{ + if (_yacs_schema_button->isChecked()) + { + return BL::CreateJobWizard::Page_YACSSchema; + } + else + { + return BL::CreateJobWizard::Page_Command_Main_Definitions; + } +} + +BL::YACSSchemaPage::YACSSchemaPage(QWidget * parent) +: QWizardPage(parent) +{ + setTitle("Choose YACS Schema"); + + QLabel *label = new QLabel("In this step you have to choose what YACS Schema you want to execute"); + label->setWordWrap(true); + + _yacs_file_button = new QPushButton(tr("Choose YACS Schema file")); + _yacs_file_button->show(); + connect(_yacs_file_button, SIGNAL(clicked()), this, SLOT(choose_file())); + + _yacs_file_text = new QLineEdit(this); + _yacs_file_text->setText(""); + registerField("yacs_file", _yacs_file_text); + _yacs_file_text->setReadOnly(true); + + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(label); + QGridLayout *layout = new QGridLayout; + layout->addWidget(_yacs_file_button, 0, 0); + layout->addWidget(_yacs_file_text, 0, 1); + main_layout->insertLayout(-1, layout); + setLayout(main_layout); +}; + +BL::YACSSchemaPage::~YACSSchemaPage() +{} + +bool +BL::YACSSchemaPage::validatePage() +{ + bool return_value; + QString yacs_file = field("yacs_file").toString(); + if (yacs_file != "") + { + return_value = true; + } + else + { + QMessageBox::warning(NULL, "YACS File Error", "Please choose a YACS File"); + return_value = false; + } + return return_value; +} + +void +BL::YACSSchemaPage::choose_file() +{ + QString yacs_file = QFileDialog::getOpenFileName(this, + tr("Open YACS files"), "", + tr("XML (*.xml);;All Files (*)")); + _yacs_file_text->setReadOnly(false); + _yacs_file_text->setText(yacs_file); + _yacs_file_text->setReadOnly(true); +} + +int +BL::YACSSchemaPage::nextId() const +{ + return BL::CreateJobWizard::Page_BatchParameters; +} + +BL::CreateJobWizard::CommandMainPage::CommandMainPage(QWidget * parent) +: QWizardPage(parent) +{ + setTitle("Define command job"); + QLabel *label = new QLabel("Enter the command that will be executed into the resource"); + label->setWordWrap(true); + + // command + QLabel * label_command = new QLabel("Command: "); + QLineEdit * line_command = new QLineEdit(this); + registerField("command", line_command); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(label_command, 0, 0); + layout->addWidget(line_command, 0, 1); + + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(label); + main_layout->insertLayout(-1, layout); + setLayout(main_layout); +}; + +BL::CreateJobWizard::CommandMainPage::~CommandMainPage() +{} + +bool +BL::CreateJobWizard::CommandMainPage::validatePage() +{ + QString command = field("command").toString(); + if (command == "") + { + QMessageBox::warning(NULL, "Command Error", "Please enter a command"); + return false; + } + + return true; +} + +int +BL::CreateJobWizard::CommandMainPage::nextId() const +{ + return BL::CreateJobWizard::Page_BatchParameters; +} + +BL::BatchParametersPage::BatchParametersPage(QWidget * parent) +: QWizardPage(parent) +{ + setTitle("Enter Batch Parameters"); + + QLabel *label = new QLabel("In this step you define the parameters of your job"); + label->setWordWrap(true); + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(label); + + // batch_directory + QLabel * label_directory = new QLabel("Batch directory: "); + QLineEdit * line_directory = new QLineEdit(this); + registerField("batch_directory", line_directory); + + // exected during time + QLabel * label_during_time = new QLabel("Expected during time: "); + QSpinBox * spin_during_time_hour = new QSpinBox(this); + QLabel * label_during_time_hour = new QLabel("Hours"); + spin_during_time_hour->setMinimum(0); + spin_during_time_hour->setMaximum(1000000); + registerField("during_time_hour", spin_during_time_hour); + QSpinBox * spin_during_time_min = new QSpinBox(this); + QLabel * label_during_time_min = new QLabel("Minutes"); + spin_during_time_min->setMinimum(0); + spin_during_time_min->setMaximum(59); + registerField("during_time_min", spin_during_time_min); + + // memory + QLabel * label_memory = new QLabel("Memory per nodes expected: "); + QSpinBox * spin_memory = new QSpinBox(this); + spin_memory->setMinimum(0); + spin_memory->setMaximum(1000000); + registerField("mem_value", spin_memory); + QComboBox * combo_memory = new QComboBox(this); + combo_memory->addItem("MB"); + combo_memory->addItem("GB"); + combo_memory->setCurrentIndex(1); + registerField("mem_type", combo_memory); + + // proc + QLabel * label_proc = new QLabel("Number of proc expected: "); + QSpinBox * spin_proc = new QSpinBox(this); + spin_proc->setMinimum(1); + spin_proc->setMaximum(1000000); + registerField("proc_value", spin_proc); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(label_directory, 0, 0); + layout->addWidget(line_directory, 0, 1, 1, -1); + layout->addWidget(label_during_time, 1, 0); + layout->addWidget(spin_during_time_hour, 1, 1); + layout->addWidget(label_during_time_hour, 1, 2); + layout->addWidget(spin_during_time_min, 1, 3); + layout->addWidget(label_during_time_min, 1, 4); + layout->addWidget(label_memory, 2, 0); + layout->addWidget(spin_memory, 2, 1); + layout->addWidget(combo_memory, 2, 2); + layout->addWidget(label_proc, 3, 0); + layout->addWidget(spin_proc, 3, 1); + + main_layout->insertLayout(-1, layout); + + setLayout(main_layout); +}; + +BL::BatchParametersPage::~BatchParametersPage() +{} + +bool +BL::BatchParametersPage::validatePage() +{ + QString batch_directory = field("batch_directory").toString(); + if (batch_directory == "") + { + QMessageBox::warning(NULL, "Batch Directory Error", "Please enter a batch directory"); + return false; + } + + int time_hour = field("during_time_hour").toInt(); + int time_min = field("during_time_min").toInt(); + if (time_hour == 0 and time_min == 0) + { + QMessageBox::warning(NULL, "Time Error", "Please enter an expected during time"); + return false; + } + + int mem = field("mem_value").toInt(); + if (mem == 0) + { + QMessageBox::warning(NULL, "Memory Error", "Please enter an expected memory"); + return false; + } + + return true; +} + +int +BL::BatchParametersPage::nextId() const +{ + return BL::CreateJobWizard::Page_Files; +} + +BL::FilesPage::FilesPage(BL::CreateJobWizard * parent) +: QWizardPage(parent) +{ + setTitle("Enter Input and Output Files"); + + QLabel * main_label = new QLabel("In this step you define input and output files of your job"); + main_label->setWordWrap(true); + + // input_files + QGroupBox * input_group_box = new QGroupBox("Input Files"); + _input_files_button = new QPushButton("Add input files"); + _input_files_button->show(); + connect(_input_files_button, SIGNAL(clicked()), this, SLOT(choose_input_files())); + _remove_input_files_button = new QPushButton("Remove input files"); + _remove_input_files_button->show(); + _remove_input_files_button->setEnabled(false); + connect(_remove_input_files_button, SIGNAL(clicked()), this, SLOT(remove_input_files())); + _input_files_list = new QListWidget(); + _input_files_list->setSelectionMode(QAbstractItemView::MultiSelection); + connect(_input_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(input_itemSelectionChanged())); + + QGridLayout * input_box = new QGridLayout; + input_box->addWidget(_input_files_button, 0, 0); + input_box->addWidget(_remove_input_files_button, 0, 1); + input_box->addWidget(_input_files_list, 1, 0, 1, -1); + input_group_box->setLayout(input_box); + + // output_files + QGroupBox * output_group_box = new QGroupBox("Output Files"); + _output_files_button = new QPushButton("Add output file"); + _output_files_button->show(); + connect(_output_files_button, SIGNAL(clicked()), this, SLOT(add_output_file())); + _remove_output_files_button = new QPushButton("Remove output files"); + _remove_output_files_button->show(); + _remove_output_files_button->setEnabled(false); + connect(_remove_output_files_button, SIGNAL(clicked()), this, SLOT(remove_output_files())); + _output_files_list = new QListWidget(); + _output_files_list->setSelectionMode(QAbstractItemView::MultiSelection); + _output_files_list->setEditTriggers(QAbstractItemView::DoubleClicked); + connect(_output_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(output_itemSelectionChanged())); + + // Results Directory + QLabel * label_result_directory = new QLabel("Result directory: "); + QLineEdit * result_directory = new QLineEdit(this); + registerField("result_directory", result_directory); + + QGridLayout * output_box = new QGridLayout; + output_box->addWidget(_output_files_button, 0, 0); + output_box->addWidget(_remove_output_files_button, 0, 1); + output_box->addWidget(_output_files_list, 1, 0, 1, -1); + output_box->addWidget(label_result_directory, 2, 0); + output_box->addWidget(result_directory, 2, 1, 1, -1); + output_group_box->setLayout(output_box); + + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(main_label); + main_layout->addWidget(input_group_box); + main_layout->addWidget(output_group_box); + setLayout(main_layout); + + parent->setFilesList(_input_files_list, _output_files_list); +}; + +BL::FilesPage::~FilesPage() +{} + +bool +BL::FilesPage::validatePage() +{ + QString result_directory = field("result_directory").toString(); + + for (int i = 0; i < _output_files_list->count(); ++i) + { + QListWidgetItem * item = _output_files_list->item(i); + if (item->text() == "TO EDIT!") + { + QMessageBox::warning(NULL, "Ouput Files Error", "Some output files are not defined !"); + return false; + } + } + + if (result_directory == "" and _output_files_list->count() != 0) + { + QMessageBox::warning(NULL, "Result Directory Error", "Please enter a result directory or remove output files"); + return false; + } + + if (result_directory != "" and _output_files_list->count() == 0) + { + QMessageBox::warning(NULL, "Result Error", "Please add output files or erase result directory"); + return false; + } + + return true; +} + +void +BL::FilesPage::choose_input_files() +{ + QStringList files = QFileDialog::getOpenFileNames(this, + tr("Add input files"), "", + tr("All Files (*)")); + for (int i = 0; i < files.size(); ++i) + { + if (_input_files_list->findItems(files.at(i), Qt::MatchFixedString).size() == 0) + _input_files_list->addItem(files.at(i)); + } +} + +void +BL::FilesPage::remove_input_files() +{ + QList list = _input_files_list->selectedItems(); + for (int i = 0; i < list.size(); ++i) + { + int row = _input_files_list->row( list.at(i) ); + delete _input_files_list->takeItem(row); + } +} + +void +BL::FilesPage::input_itemSelectionChanged() +{ + if (_input_files_list->selectedItems().size() > 0) + _remove_input_files_button->setEnabled(true); + else + _remove_input_files_button->setEnabled(false); +} + +void +BL::FilesPage::add_output_file() +{ + QListWidgetItem * new_item = new QListWidgetItem("TO EDIT!"); + new_item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled); + _output_files_list->addItem(new_item); +} + +void +BL::FilesPage::remove_output_files() +{ + QList list = _output_files_list->selectedItems(); + for (int i = 0; i < list.size(); ++i) + { + int row = _output_files_list->row( list.at(i) ); + delete _output_files_list->takeItem(row); + } +} + +void +BL::FilesPage::output_itemSelectionChanged() +{ + if (_output_files_list->selectedItems().size() > 0) + _remove_output_files_button->setEnabled(true); + else + _remove_output_files_button->setEnabled(false); +} + +int +BL::FilesPage::nextId() const +{ + return BL::CreateJobWizard::Page_Machine; +} + +BL::CreateJobWizard::ConclusionPage::ConclusionPage(QWidget * parent) +: QWizardPage(parent) +{ + setTitle("Job definition is finished"); + QCheckBox * check_box = new QCheckBox("Start job after creation"); + registerField("start_job", check_box); + QVBoxLayout * main_layout = new QVBoxLayout; + main_layout->addWidget(check_box); + setLayout(main_layout); +}; + +BL::CreateJobWizard::ConclusionPage::~ConclusionPage() +{} + +bool +BL::CreateJobWizard::ConclusionPage::validatePage() +{ + return true; +} + +int +BL::CreateJobWizard::ConclusionPage::nextId() const +{ + return -1; +} + +BL::MachinePage::MachinePage(BL::CreateJobWizard * parent, BL::SALOMEServices * salome_services) +: QWizardPage(parent) +{ + _salome_services = salome_services; + setTitle("Select a Machine"); + + QLabel * main_label = new QLabel("In this step you select the machine of your job"); + main_label->setWordWrap(true); + + // input_Machine + QGroupBox * machine_group_box = new QGroupBox("Machine List"); + _machine_list = new QListWidget(); + _machine_list->setSelectionMode(QAbstractItemView::SingleSelection); + std::list machine_list = _salome_services->getMachineList(); + std::list::iterator it; + for (it = machine_list.begin(); it != machine_list.end(); it++) + { + std::string machine = *it; + _machine_list->addItem(QString(machine.c_str())); + } + connect(_machine_list, SIGNAL(itemSelectionChanged()), this, SLOT(machine_itemSelectionChanged())); + QVBoxLayout * machine_list_layout = new QVBoxLayout(); + machine_list_layout->addWidget(_machine_list); + machine_group_box->setLayout(machine_list_layout); + + QLabel * machine_label = new QLabel("Machine selected: "); + _machine_choosed = new QLineEdit(); + _machine_choosed->setText(""); + _machine_choosed->setReadOnly(true); + registerField("machine_choosed", _machine_choosed); + + QGridLayout * main_layout = new QGridLayout; + main_layout->addWidget(machine_group_box, 0, 0, 1, -1); + main_layout->addWidget(machine_label, 1, 0); + main_layout->addWidget(_machine_choosed, 1, 1); + setLayout(main_layout); +}; + +BL::MachinePage::~MachinePage() +{} + +bool +BL::MachinePage::validatePage() +{ + QString machine_choosed = field("machine_choosed").toString(); + if (machine_choosed == "") + { + QMessageBox::warning(NULL, "Machine Error", "Please choose a machine"); + return false; + } + return true; +} + +void +BL::MachinePage::machine_itemSelectionChanged() +{ + _machine_choosed->setReadOnly(false); + QList list = _machine_list->selectedItems(); + QListWidgetItem * item = list.at(0); + _machine_choosed->setText(item->text()); + _machine_choosed->setReadOnly(true); +} + +int +BL::MachinePage::nextId() const +{ + return BL::CreateJobWizard::Page_Conclusion; +} diff --git a/src/genericgui/BL_CreateJobWizard.hxx b/src/genericgui/BL_CreateJobWizard.hxx new file mode 100644 index 0000000..ede4b4b --- /dev/null +++ b/src/genericgui/BL_CreateJobWizard.hxx @@ -0,0 +1,199 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_CREATEJOBWIZARD_HXX_ +#define _BL_CREATEJOBWIZARD_HXX_ + +#include + +#include "BL_Traces.hxx" +#include "BL_JobsManager_QT.hxx" +#include "BL_SALOMEServices.hxx" + +#include +#include + +namespace BL{ + + class JobsManager_QT; + class CreateJobWizard: virtual public QWizard + { + Q_OBJECT + + public: + CreateJobWizard(BL::JobsManager_QT * jobs_manager, BL::SALOMEServices * salome_services); + virtual ~CreateJobWizard(); + + void setFilesList(QListWidget * input_files_list, QListWidget * output_files_list); + + public slots: + void end(int result); + + private: + //Page Name + QLineEdit * _nameLineEdit; + BL::JobsManager_QT * _jobs_manager; + QListWidget * _input_files_list; + QListWidget * _output_files_list; + + public: + // Results + std::string job_name; + + std::string yacs_file; + + std::string command; + + std::string batch_directory; + std::string expected_during_time; + std::string expected_memory; + int nb_proc; + + std::string result_directory; + std::list input_files_list; + std::list output_files_list; + + std::string machine_choosed; + + bool start_job; + + public: + enum {Page_JobName, Page_YACSSchema, Page_BatchParameters, Page_Files, + Page_Command_Main_Definitions, Page_Machine, Page_Conclusion}; + + class JobNamePage: virtual public QWizardPage + { + public: + JobNamePage(QWidget * parent, BL::JobsManager_QT * jobs_manager); + virtual ~JobNamePage(); + + virtual bool validatePage(); + virtual int nextId() const ; + + private: + BL::JobsManager_QT * _jobs_manager; + QRadioButton * _yacs_schema_button; + }; + + + class CommandMainPage: virtual public QWizardPage + { + public: + CommandMainPage(QWidget * parent); + virtual ~CommandMainPage(); + + virtual bool validatePage(); + virtual int nextId() const ; + }; + + class ConclusionPage: virtual public QWizardPage + { + public: + ConclusionPage(QWidget * parent); + virtual ~ConclusionPage(); + + virtual bool validatePage(); + virtual int nextId() const ; + }; + }; + + class YACSSchemaPage: virtual public QWizardPage + { + Q_OBJECT + + public: + YACSSchemaPage(QWidget * parent); + virtual ~YACSSchemaPage(); + + virtual bool validatePage(); + virtual int nextId() const ; + + public slots: + void choose_file(); + + private: + QPushButton * _yacs_file_button; + QLineEdit * _yacs_file_text; + }; + + class BatchParametersPage: virtual public QWizardPage + { + Q_OBJECT + + public: + BatchParametersPage(QWidget * parent); + virtual ~BatchParametersPage(); + + virtual bool validatePage(); + virtual int nextId() const; + }; + + class FilesPage: virtual public QWizardPage + { + Q_OBJECT + + public: + FilesPage(BL::CreateJobWizard * parent); + virtual ~FilesPage(); + + virtual int nextId() const; + virtual bool validatePage(); + + public slots: + void choose_input_files(); + void remove_input_files(); + void input_itemSelectionChanged(); + + void add_output_file(); + void remove_output_files(); + void output_itemSelectionChanged(); + + private: + QPushButton * _input_files_button; + QPushButton * _remove_input_files_button; + QListWidget * _input_files_list; + + QPushButton * _output_files_button; + QPushButton * _remove_output_files_button; + QListWidget * _output_files_list; + }; + + class MachinePage: virtual public QWizardPage + { + Q_OBJECT + + public: + MachinePage(BL::CreateJobWizard * parent, BL::SALOMEServices * salome_services); + virtual ~MachinePage(); + + virtual int nextId() const; + virtual bool validatePage(); + + public slots: + void machine_itemSelectionChanged(); + + private: + QListWidget * _machine_list; + QLineEdit * _machine_choosed; + BL::SALOMEServices * _salome_services; + }; +} + +#endif + diff --git a/src/genericgui/BL_GenericGui.cxx b/src/genericgui/BL_GenericGui.cxx new file mode 100644 index 0000000..49d37af --- /dev/null +++ b/src/genericgui/BL_GenericGui.cxx @@ -0,0 +1,313 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_GenericGui.hxx" + +BL::GenericGui::GenericGui(BL::MainWindows_Wrap * wrapper) : QObject(wrapper->getDockParent()) +{ + DEBTRACE("Creating BL::GenericGui"); + BL_ASSERT(wrapper); + _wrapper = wrapper; + _row_selected = -1; + _job_name_selected = ""; + + _dock_parent = _wrapper->getDockParent(); + _tab_parent = _wrapper->getTabParent(); + + _salome_services = new BL::SALOMEServices(); + if (_salome_services->initNS() == false) + DEBMSG("WARNING !!!!! SALOME IS NOT REACHABLE !!!!"); + _jobs_manager = new BL::JobsManager_QT(_dock_parent, _salome_services); + _model_manager = new BL::QModelManager(this, _jobs_manager); + + _model = _model_manager->getModel(); + + // ---- Adding different GUI parts + + /* Buttons */ + _buttons = new BL::Buttons(_tab_parent); + _buttons->setCreateButtonSlot(this, SLOT(create_job())); + _buttons->setStartButtonSlot(this, SLOT(start_job())); + _buttons->setDeleteButtonSlot(this, SLOT(delete_job())); + _buttons->setRefreshButtonSlot(this, SLOT(refresh_job())); + _buttons->setGetResultsButtonSlot(this, SLOT(get_results_job())); + + /* Jobs Table */ + _jobs_table = new BL::JobsTable(_tab_parent); + _jobs_table->setModel(_model); + + /* Job Tab */ + _job_tab = new BL::JobTab(_tab_parent, _jobs_manager); + _job_tab->setModel(_model); + + /* Tab Central Widget */ + QWidget * central_widget = new QWidget(_tab_parent); + + QSplitter * tab_central_widget = new QSplitter(Qt::Vertical, central_widget); + tab_central_widget->addWidget(_jobs_table); + tab_central_widget->addWidget(_job_tab); + tab_central_widget->setChildrenCollapsible(false); + + QVBoxLayout * central_layout = new QVBoxLayout; + central_layout->addWidget(_buttons); + central_layout->addWidget(tab_central_widget); + central_widget->setLayout(central_layout); + + _tab_parent->setCentralWidget(central_widget); + // Test tab + //QDockWidget * dw_main = new QDockWidget(_tab_parent); + //dw_main->setWidget(central_widget); + //_tab_parent->addDockWidget(Qt::LeftDockWidgetArea, dw_main); + + /* Summary */ + _dw_summary = new QDockWidget(_dock_parent); + _dw_summary->setWindowTitle("Summary"); + _summary = new BL::Summary(_dock_parent, _jobs_manager); + _summary->setModel(_model); + _dw_summary->setWidget(_summary); + + /* MachineCatalog */ + _dw_machine_catalog = new QDockWidget(_dock_parent); + _dw_machine_catalog->setWindowTitle("Machine Catalog"); + _machine_catalog = new BL::MachineCatalog(_dock_parent, _salome_services); + _dw_machine_catalog->setWidget(_machine_catalog); + + /* Main Dock Window */ + _dock_parent->addDockWidget(Qt::RightDockWidgetArea, _jobs_manager); + _dock_parent->addDockWidget(Qt::RightDockWidgetArea, _dw_summary); + _dock_parent->addDockWidget(Qt::RightDockWidgetArea, _dw_machine_catalog); + _dock_parent->splitDockWidget(_jobs_manager, _dw_summary, Qt::Vertical); + _dock_parent->tabifyDockWidget(_dw_summary, _dw_machine_catalog); + + /* Signals and Slots */ + + // JobsManager -> Model + connect(_jobs_manager, SIGNAL(new_job_added(QString)), _model_manager, SLOT(new_job_added(QString))); + connect(_jobs_manager, SIGNAL(job_state_changed(QString)), _model_manager, SLOT(job_state_changed(QString))); + connect(_jobs_manager, SIGNAL(job_state_changed(QString)), this, SLOT(job_state_changed(QString))); + + // Model -> X + connect(_model, SIGNAL(rowsInserted(QModelIndex, int, int)), _summary, SLOT(rowsInserted(QModelIndex, int, int))); + connect(_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), _summary, SLOT(rowsRemoved(QModelIndex, int, int))); + connect(_model, SIGNAL(itemChanged(QStandardItem*)), _summary, SLOT(itemChanged(QStandardItem*))); + connect(_model, SIGNAL(itemChanged(QStandardItem*)), _job_tab, SLOT(itemChanged(QStandardItem*))); + + // TableView -> X + connect(_jobs_table, SIGNAL(clicked(QModelIndex)), _job_tab, SLOT(job_selected(QModelIndex))); + connect(_jobs_table, SIGNAL(clicked(QModelIndex)), this, SLOT(job_selected(QModelIndex))); + connect(_jobs_table, SIGNAL(clicked(QModelIndex)), _model_manager, SLOT(job_selected(QModelIndex))); + + // Delete Job -> X + connect(this, SIGNAL(job_deleted(QString)), _job_tab, SLOT(reset(QString))); +} + +BL::GenericGui::~GenericGui() +{ + DEBTRACE("Destroying BL::GenericGui"); + + delete _salome_services; +} + +void +BL::GenericGui::showDockWidgets(bool isVisible) +{ + DEBTRACE("BL::GenericGui::showDockWidgets " << isVisible); + if (_jobs_manager) _jobs_manager->setVisible(isVisible); + if (_dw_summary) _dw_summary->setVisible(isVisible); + if (_dw_machine_catalog) _dw_machine_catalog->setVisible(isVisible); +} + +void +BL::GenericGui::createActions() +{ + DEBTRACE("CreateActions BL::GenericGui"); + _create_job_action = _wrapper->createAction("Create Job", QIcon(), "Create Job", "Create Job", 0, _dock_parent, false, this, SLOT(create_job())); + _start_job_action = _wrapper->createAction("Start Job", QIcon(), "Start Job", "Start Job", 0, _dock_parent, false, this, SLOT(start_job())); + _delete_job_action = _wrapper->createAction("Delete Job", QIcon(), "Delete Job", "Delete Job", 0, _dock_parent, false, this, SLOT(delete_job())); + _refresh_job_action = _wrapper->createAction("Refresh Job", QIcon(), "Refresh Job", "Refresh Job", 0, _dock_parent, false, this, SLOT(refresh_job())); + _get_results_job_action = _wrapper->createAction("Get Job Results", QIcon(), "Get Job Results", "Get Job Results", 0, _dock_parent, false, this, SLOT(refresh_job())); +} + +void +BL::GenericGui::createMenus() +{ + DEBTRACE("CreateMenus BL::GenericGui"); + int menu_id = _wrapper->createTopMenu("JobManager"); + _wrapper->addActionToMenu(_create_job_action, menu_id); + _wrapper->addActionToMenu(_start_job_action, menu_id); + _wrapper->addActionToMenu(_delete_job_action, menu_id); + _wrapper->addActionToMenu(_get_results_job_action, menu_id); + _wrapper->addActionToMenu(_refresh_job_action, menu_id); +} + +void +BL::GenericGui::create_job() +{ + DEBTRACE("Create Job Slot BL::GenericGui"); + _jobs_manager->create_job_wizard(); +} + +void +BL::GenericGui::start_job() +{ + DEBTRACE("Start Job Slot BL::GenericGui"); + _jobs_manager->start_job(_job_name_selected.toStdString()); + updateButtonsStates(); +} + +void +BL::GenericGui::refresh_job() +{ + DEBTRACE("Refresh Job Slot BL::GenericGui"); + _jobs_manager->refresh_jobs(); +} + +void +BL::GenericGui::get_results_job() +{ + DEBTRACE("Get Results Job Slot BL::GenericGui"); + _jobs_manager->get_results_job(_job_name_selected.toStdString()); +} + +void +BL::GenericGui::delete_job() +{ + DEBTRACE("Delete Job Slot BL::GenericGui"); + int ret = QMessageBox::warning(NULL, "Delete a job", "Do you really want to delete this job ?", + QMessageBox::Ok|QMessageBox::Cancel, + QMessageBox::Ok); + if (ret == QMessageBox::Ok) + { + _jobs_manager->delete_job(_job_name_selected); + _model_manager->deleteJob(_row_selected); + emit job_deleted(_job_name_selected); + _row_selected = -1; + _job_name_selected = ""; + updateButtonsStates(); + } +} + +void +BL::GenericGui::job_selected(const QModelIndex & index) +{ + DEBTRACE("BL::GenericGui::job_selected slot"); + QStandardItem * item = _model->itemFromIndex(index); + QStandardItem * item_name = _model->item(item->row()); + _row_selected = item->row(); + _job_name_selected = item_name->text(); + updateButtonsStates(); +} + +void +BL::GenericGui::job_state_changed(const QString & name) +{ + if (name == _job_name_selected) + updateButtonsStates(); +} +void +BL::GenericGui::updateButtonsStates() +{ + DEBTRACE("BL::GenericGui::updateButtonsStates slot"); + + // First case: no job selected + if (_job_name_selected == "" and _row_selected == -1) + { + _start_job_action->setEnabled(false); + _delete_job_action->setEnabled(false); + _get_results_job_action->setEnabled(false); + _buttons->disable_start_button(); + _buttons->disable_delete_button(); + _buttons->disable_get_results_button(); + } + else if (_job_name_selected != "" and _row_selected != -1) + { + BL::Job * job = _jobs_manager->getJob(_job_name_selected.toStdString()); + BL::Job::State job_state = job->getState(); + + switch (job_state) + { + case BL::Job::CREATED: + _start_job_action->setEnabled(true); + _delete_job_action->setEnabled(true); + _get_results_job_action->setEnabled(false); + _buttons->enable_start_button(); + _buttons->enable_delete_button(); + _buttons->disable_get_results_button(); + break; + + case BL::Job::IN_PROCESS: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(false); + _buttons->disable_delete_button(); + _get_results_job_action->setEnabled(false); + _buttons->disable_get_results_button(); + break; + + case BL::Job::QUEUED: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(true); + _buttons->enable_delete_button(); + _get_results_job_action->setEnabled(false); + _buttons->disable_get_results_button(); + break; + + case BL::Job::RUNNING: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(true); + _buttons->enable_delete_button(); + _get_results_job_action->setEnabled(false); + _buttons->disable_get_results_button(); + break; + + case BL::Job::PAUSED: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(true); + _buttons->enable_delete_button(); + _get_results_job_action->setEnabled(false); + _buttons->disable_get_results_button(); + break; + + case BL::Job::ERROR: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(true); + _buttons->enable_delete_button(); + _get_results_job_action->setEnabled(false); + _buttons->disable_get_results_button(); + break; + + case BL::Job::FINISHED: + _start_job_action->setEnabled(false); + _buttons->disable_start_button(); + _delete_job_action->setEnabled(true); + _buttons->enable_delete_button(); + _get_results_job_action->setEnabled(true); + _buttons->enable_get_results_button(); + break; + } + } + else + { + DEBTRACE("ERROR in updateButtonsStates !!!!!!"); + } +} diff --git a/src/genericgui/BL_GenericGui.hxx b/src/genericgui/BL_GenericGui.hxx new file mode 100644 index 0000000..161a24e --- /dev/null +++ b/src/genericgui/BL_GenericGui.hxx @@ -0,0 +1,98 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_GENERICGUI_HXX_ +#define _BL_GENERICGUI_HXX_ + +#include + +#include "BL_Traces.hxx" + +#include "BL_SALOMEServices.hxx" + +#include "BL_MainWindows_Wrap.hxx" + +#include "BL_QModelManager.hxx" +#include "BL_JobsManager_QT.hxx" +#include "BL_JobsTable.hxx" +#include "BL_JobTab.hxx" +#include "BL_Buttons.hxx" +#include "BL_Summary.hxx" +#include "BL_MachineCatalog.hxx" + +namespace BL +{ + class GenericGui: public QObject + { + Q_OBJECT + + public: + GenericGui(BL::MainWindows_Wrap * wrapper); + virtual ~GenericGui(); + + void showDockWidgets(bool isVisible); + void createActions(); + void createMenus(); + + public slots: + void create_job(); + void start_job(); + void delete_job(); + void refresh_job(); + void get_results_job(); + void job_selected(const QModelIndex & index); + void job_state_changed(const QString & name); + void updateButtonsStates(); + + signals: + void job_deleted(QString job_name); + + protected: + + BL::MainWindows_Wrap * _wrapper; + + BL::SALOMEServices * _salome_services; + + QMainWindow * _dock_parent; + QMainWindow * _tab_parent; + QDockWidget * _dw_summary; + QDockWidget * _dw_machine_catalog; + + BL::Buttons * _buttons; + BL::JobsTable * _jobs_table; + BL::JobTab * _job_tab; + BL::Summary * _summary; + + QAction * _create_job_action; + QAction * _start_job_action; + QAction * _delete_job_action; + QAction * _get_results_job_action; + QAction * _refresh_job_action; + + BL::JobsManager_QT * _jobs_manager; + BL::QModelManager * _model_manager; + QStandardItemModel * _model; + BL::MachineCatalog * _machine_catalog; + + int _row_selected; + QString _job_name_selected; + }; +} + +#endif diff --git a/src/genericgui/BL_JobTab.cxx b/src/genericgui/BL_JobTab.cxx new file mode 100644 index 0000000..5f139cc --- /dev/null +++ b/src/genericgui/BL_JobTab.cxx @@ -0,0 +1,259 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_JobTab.hxx" +#include "BL_Traces.hxx" + +BL::JobTab::JobTab(QWidget *parent, BL::JobsManager_QT * jobs_manager) : QTabWidget(parent) +{ + DEBTRACE("Creating BL::JobTab"); + BL_ASSERT(parent); + BL_ASSERT(jobs_manager); + _parent = parent; + _jobs_manager = jobs_manager; + _model = NULL; + + createJobSummaryTab(); + createJobFilesTab(); + + addTab(_summary_tab, "Job Summary"); + addTab(_files_tab, "Job Files"); +} + +BL::JobTab::~JobTab() +{ + DEBTRACE("Destroying BL::JobTab"); +} + +void +BL::JobTab::setModel(QStandardItemModel * model) +{ + DEBTRACE("Call setModel BL::JobTab"); + BL_ASSERT(model); + + _model = model; +} + +void +BL::JobTab::createJobSummaryTab() +{ + _summary_tab = new QWidget(this); + + QLabel * job_name_label = new QLabel("Name:"); + _job_name_label_value = new QLabel(""); + QLabel * job_type_label = new QLabel("Type:"); + _job_type_label_value = new QLabel(""); + QLabel * job_state_label = new QLabel("State:"); + _job_state_label_value = new QLabel(""); + QLabel * job_machine_label = new QLabel("Machine:"); + _job_machine_label_value = new QLabel(""); + _job_command_label = new QLabel("Schema or Command:"); + _job_command_label_value = new QLabel(""); + + QGroupBox * main_values_box = new QGroupBox("Main values"); + QFormLayout * values_form = new QFormLayout; + values_form->insertRow(0, job_name_label, _job_name_label_value); + values_form->insertRow(1, job_type_label, _job_type_label_value); + values_form->insertRow(2, job_state_label, _job_state_label_value); + values_form->insertRow(3, job_machine_label, _job_machine_label_value); + values_form->insertRow(4, _job_command_label, _job_command_label_value); + main_values_box->setLayout(values_form); + + QLabel * job_nif_label = new QLabel("Number of Input Files:"); + _job_nif_label_value = new QLabel(""); + QLabel * job_nof_label = new QLabel("Number of Output Files:"); + _job_nof_label_value = new QLabel(""); + QLabel * job_bd_label = new QLabel("Execution directory:"); + _job_bd_label_value = new QLabel(""); + QLabel * job_rd_label = new QLabel("Result directory:"); + _job_rd_label_value = new QLabel(""); + + QLabel * job_edt_label = new QLabel("Expected during time:"); + _job_edt_label_value = new QLabel(""); + QLabel * job_em_label = new QLabel("Expected memory:"); + _job_em_label_value = new QLabel(""); + QLabel * job_nop_label = new QLabel("Number of processors:"); + _job_nop_label_value = new QLabel(""); + + QGroupBox * run_values_box = new QGroupBox("Run values"); + QFormLayout * run_values_form = new QFormLayout; + run_values_form->insertRow(0, job_nif_label, _job_nif_label_value); + run_values_form->insertRow(1, job_nof_label, _job_nof_label_value); + run_values_form->insertRow(2, job_bd_label, _job_bd_label_value); + run_values_form->insertRow(3, job_rd_label, _job_rd_label_value); + QFormLayout * other_run_values_form = new QFormLayout; + other_run_values_form->insertRow(0, job_edt_label, _job_edt_label_value); + other_run_values_form->insertRow(1, job_em_label, _job_em_label_value); + other_run_values_form->insertRow(2, job_nop_label, _job_nop_label_value); + QHBoxLayout * box_layout = new QHBoxLayout(); + box_layout->addLayout(run_values_form); + box_layout->addLayout(other_run_values_form); + run_values_box->setLayout(box_layout); + + QVBoxLayout * mainLayout = new QVBoxLayout(); + mainLayout->addWidget(main_values_box); + mainLayout->addWidget(run_values_box); + _summary_tab->setLayout(mainLayout); +} + +void +BL::JobTab::createJobFilesTab() +{ + _files_tab = new QWidget(this); + + _input_files_list = new QListWidget(this); + _input_files_list->setSelectionMode(QAbstractItemView::NoSelection); + QGroupBox * input_files_box = new QGroupBox("Input Files"); + QVBoxLayout * input_layout = new QVBoxLayout(); + input_layout->addWidget(_input_files_list); + input_files_box->setLayout(input_layout); + + _output_files_list = new QListWidget(this); + _output_files_list->setSelectionMode(QAbstractItemView::NoSelection); + QGroupBox * output_files_box = new QGroupBox("Output Files"); + QVBoxLayout * output_layout = new QVBoxLayout(); + output_layout->addWidget(_output_files_list); + output_files_box->setLayout(output_layout); + + QVBoxLayout * mainLayout = new QVBoxLayout(); + mainLayout->addWidget(input_files_box); + mainLayout->addWidget(output_files_box); + _files_tab->setLayout(mainLayout); +} + +void +BL::JobTab::job_selected(const QModelIndex & index) +{ + DEBTRACE("BL::JobTab::job_selected slot"); + QStandardItem * item = _model->itemFromIndex(index); + QStandardItem * item_name = _model->item(item->row()); + if (item) + { + BL::Job * job = _jobs_manager->getJob(item_name->text().toStdString()); + + _job_name_label_value->setText(QString(job->getName().c_str())); + + if (job->getState() == BL::Job::CREATED) + _job_state_label_value->setText("Created"); + else if (job->getState() == BL::Job::IN_PROCESS) + _job_state_label_value->setText("In Process"); + else if (job->getState() == BL::Job::QUEUED) + _job_state_label_value->setText("Queued"); + else if (job->getState() == BL::Job::RUNNING) + _job_state_label_value->setText("Running"); + else if (job->getState() == BL::Job::PAUSED) + _job_state_label_value->setText("Paused"); + else if (job->getState() == BL::Job::ERROR) + _job_state_label_value->setText("Error"); + else + _job_state_label_value->setText("Finished"); + + if (job->getType() == BL::Job::YACS_SCHEMA) + { + _job_command_label->setText("Schema:"); + _job_command_label_value->setText(QString(job->getYACSFile().c_str())); + _job_type_label_value->setText("YACS_Schema"); + } + else + { + _job_command_label->setText("Command:"); + _job_command_label_value->setText(QString(job->getCommand().c_str())); + _job_type_label_value->setText("Command"); + } + + _job_machine_label_value->setText(QString(job->getMachine().c_str())); + + BL::Job::BatchParam batch_params = job->getBatchParameters(); + + BL::Job::FilesParam files_params = job->getFilesParameters(); + int nif = files_params.input_files_list.size(); + _job_nif_label_value->setText(QVariant(nif).toString()); + int nof = files_params.output_files_list.size(); + _job_nof_label_value->setText(QVariant(nof).toString()); + _job_bd_label_value->setText(QString(batch_params.batch_directory.c_str())); + _job_rd_label_value->setText(QString(files_params.result_directory.c_str())); + + _job_edt_label_value->setText(QString(batch_params.expected_during_time.c_str())); + _job_em_label_value->setText(QString(batch_params.expected_memory.c_str())); + _job_nop_label_value->setText(QVariant(batch_params.nb_proc).toString()); + + std::list::iterator it; + for (it = files_params.input_files_list.begin(); it != files_params.input_files_list.end(); it++) + { + std::string file = *it; + _input_files_list->addItem(QString(file.c_str())); + } + for (it = files_params.output_files_list.begin(); it != files_params.output_files_list.end(); it++) + { + std::string file = *it; + _output_files_list->addItem(QString(file.c_str())); + } + + } + else + DEBTRACE ("itemFromIndex returns 0 !"); +} + +void +BL::JobTab::itemChanged(QStandardItem * item) +{ + DEBTRACE("BL::JobTab::itemChanged slot"); + + QStandardItem * item_name = _model->item(item->row()); + BL::Job * job = _jobs_manager->getJob(item_name->text().toStdString()); + + if (_job_name_label_value->text() == QString(job->getName().c_str())) + { + if (job->getState() == BL::Job::CREATED) + _job_state_label_value->setText("Created"); + else if (job->getState() == BL::Job::IN_PROCESS) + _job_state_label_value->setText("In Process"); + else if (job->getState() == BL::Job::QUEUED) + _job_state_label_value->setText("Queued"); + else if (job->getState() == BL::Job::RUNNING) + _job_state_label_value->setText("Running"); + else if (job->getState() == BL::Job::PAUSED) + _job_state_label_value->setText("Paused"); + else if (job->getState() == BL::Job::ERROR) + _job_state_label_value->setText("Error"); + else + _job_state_label_value->setText("Finished"); + } +} + +void +BL::JobTab::reset(QString job_name) +{ + _job_name_label_value->setText(""); + _job_type_label_value->setText(""); + _job_state_label_value->setText(""); + _job_machine_label_value->setText(""); + _job_nif_label_value->setText(""); + _job_nof_label_value->setText(""); + _job_bd_label_value->setText(""); + _job_rd_label_value->setText(""); + _job_edt_label_value->setText(""); + _job_em_label_value->setText(""); + _job_nop_label_value->setText(""); + _job_command_label->setText("Schema or Command:"); + _job_command_label_value->setText(""); + + _input_files_list->clear(); + _output_files_list->clear(); +} diff --git a/src/genericgui/BL_JobTab.hxx b/src/genericgui/BL_JobTab.hxx new file mode 100644 index 0000000..2f68cc0 --- /dev/null +++ b/src/genericgui/BL_JobTab.hxx @@ -0,0 +1,78 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_JOBTAB_HXX_ +#define _BL_JOBTAB_HXX_ + +#include + +#include "BL_JobsManager_QT.hxx" + +namespace BL +{ + class JobTab: public QTabWidget + { + Q_OBJECT + + public: + JobTab(QWidget *parent, BL::JobsManager_QT * jobs_manager); + virtual ~JobTab(); + + void setModel(QStandardItemModel * model); + + void createJobSummaryTab(); + void createJobFilesTab(); + + public slots: + void job_selected(const QModelIndex & index); + void itemChanged(QStandardItem * item); + void reset(QString job_name); + + protected: + QWidget* _parent; + QStandardItemModel * _model; + BL::JobsManager_QT * _jobs_manager; + + QWidget * _summary_tab; + // Main Values + QLabel * _job_name_label_value; + QLabel * _job_type_label_value; + QLabel * _job_state_label_value; + QLabel * _job_machine_label_value; + QLabel * _job_command_label; + QLabel * _job_command_label_value; + + // Run Values + QLabel * _job_nif_label_value; + QLabel * _job_nof_label_value; + QLabel * _job_bd_label_value; + QLabel * _job_rd_label_value; + QLabel * _job_edt_label_value; + QLabel * _job_em_label_value; + QLabel * _job_nop_label_value; + + QWidget * _files_tab; + + QListWidget * _input_files_list; + QListWidget * _output_files_list; + }; +} + +#endif + diff --git a/src/genericgui/BL_JobsManager_QT.cxx b/src/genericgui/BL_JobsManager_QT.cxx new file mode 100644 index 0000000..04cc1b5 --- /dev/null +++ b/src/genericgui/BL_JobsManager_QT.cxx @@ -0,0 +1,330 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_JobsManager_QT.hxx" + +BL::JobManagerEvent::JobManagerEvent(const std::string & action_i, + const std::string & event_name_i, + const std::string & job_name_i, + const std::string & data_i) : QEvent(QEvent::User) +{ + action = action_i; + event_name = event_name_i; + job_name = job_name_i; + data = data_i; +} + +BL::JobManagerEvent::~JobManagerEvent() {} + +BL::JobsManager_QT::JobsManager_QT(QWidget * parent, BL::SALOMEServices * salome_services) : + QDockWidget(parent), BL::JobsManager(salome_services) +{ + DEBTRACE("Creating BL::JobsManager_QT"); + setObserver(this); + + // Widget Part + + QWidget * main_widget = new QWidget(this); + + _load_jobs = new QPushButton("Load Jobs"); + _save_jobs = new QPushButton("Save Jobs"); + _auto_refresh_jobs = new QPushButton("Auto Refresh: no"); + _timer = new QTimer(this); + _timer->stop(); + connect(_timer, SIGNAL(timeout()), this, SLOT(RefreshJobs())); + + // Menu for auto refresh + QMenu * refresh_menu = new QMenu(this); + refresh_menu->addAction("No", this, SLOT(no_auto_refresh())); + refresh_menu->addAction("10 seconds", this, SLOT(ten_seconds_refresh())); + refresh_menu->addAction("30 seconds", this, SLOT(thirty_seconds_refresh())); + refresh_menu->addAction("1 minute", this, SLOT(one_minute_refresh())); + refresh_menu->addAction("5 minutes", this, SLOT(five_minutes_refresh())); + refresh_menu->addAction("30 minutes", this, SLOT(thirty_minutes_refresh())); + refresh_menu->addAction("1 hour", this, SLOT(one_hour_refresh())); + _auto_refresh_jobs->setMenu(refresh_menu); + + QHBoxLayout * button_layout = new QHBoxLayout(); + button_layout->addWidget(_load_jobs); + button_layout->addWidget(_save_jobs); + button_layout->addWidget(_auto_refresh_jobs); + + QGroupBox * message_box = new QGroupBox("Messages"); + _log = new QTextEdit(this); + _log->setReadOnly(true); + QVBoxLayout * message_box_layout = new QVBoxLayout(message_box); + message_box_layout->addWidget(_log); + message_box->setLayout(message_box_layout); + + QVBoxLayout * mainLayout = new QVBoxLayout(); + mainLayout->addLayout(button_layout); + mainLayout->addWidget(message_box); + main_widget->setLayout(mainLayout); + + setWidget(main_widget); + setWindowTitle("Job Manager"); +} + +BL::JobsManager_QT::~JobsManager_QT() +{ + DEBTRACE("Destroying BL::JobsManager_QT"); +} + +void +BL::JobsManager_QT::RefreshJobs() +{ + refresh_jobs(); +} + +void +BL::JobsManager_QT::no_auto_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: no"); + _timer->stop(); +} + +void +BL::JobsManager_QT::ten_seconds_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 10s"); + _timer->stop(); + _timer->start(10 * 1000); +} + +void +BL::JobsManager_QT::thirty_seconds_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 30s"); + _timer->stop(); + _timer->start(30 * 1000); +} + +void +BL::JobsManager_QT::one_minute_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 1min"); + _timer->stop(); + _timer->start(1 * 60 * 1000); +} + +void +BL::JobsManager_QT::five_minutes_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 5min"); + _timer->stop(); + _timer->start(5 * 60 * 1000); +} + +void +BL::JobsManager_QT::thirty_minutes_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 30min"); + _timer->stop(); + _timer->start(30 * 60 * 1000); +} + +void +BL::JobsManager_QT::one_hour_refresh() +{ + _auto_refresh_jobs->setText("Auto Refresh: 1hour"); + _timer->stop(); + _timer->start(1 * 60 * 60 * 1000); +} + +void +BL::JobsManager_QT::create_job_wizard() +{ + BL::CreateJobWizard wizard(this, _salome_services); + wizard.exec(); + + if (wizard.job_name != "") + { + BL::Job * new_job = addNewJob(wizard.job_name); + if (wizard.yacs_file != "") + { + // YACS schema job + new_job->setType(BL::Job::YACS_SCHEMA); + new_job->setYACSFile(wizard.yacs_file); + BL::Job::BatchParam param; + param.batch_directory = wizard.batch_directory; + param.expected_during_time = wizard.expected_during_time; + param.expected_memory = wizard.expected_memory; + param.nb_proc = wizard.nb_proc; + new_job->setBatchParameters(param); + BL::Job::FilesParam files_params; + files_params.result_directory = wizard.result_directory; + files_params.input_files_list = wizard.input_files_list; + files_params.output_files_list = wizard.output_files_list; + new_job->setFilesParameters(files_params); + new_job->setMachine(wizard.machine_choosed); + } + else + { + // Command Job + new_job->setType(BL::Job::COMMAND); + new_job->setCommand(wizard.command); + BL::Job::BatchParam param; + param.batch_directory = wizard.batch_directory; + param.expected_during_time = wizard.expected_during_time; + param.expected_memory = wizard.expected_memory; + param.nb_proc = wizard.nb_proc; + new_job->setBatchParameters(param); + BL::Job::FilesParam files_params; + files_params.result_directory = wizard.result_directory; + files_params.input_files_list = wizard.input_files_list; + files_params.output_files_list = wizard.output_files_list; + new_job->setFilesParameters(files_params); + new_job->setMachine(wizard.machine_choosed); + } + emit new_job_added(QString::fromStdString(wizard.job_name)); + if (wizard.start_job) + start_job(wizard.job_name); + } + else + { + DEBTRACE("User cancel Create Job Wizard"); + } +} + +void +BL::JobsManager_QT::delete_job(QString job_name) +{ + BL::JobsManager::removeJob(job_name.toStdString()); +} + +void +BL::JobsManager_QT::sendEvent(const std::string & action, + const std::string & event_name, + const std::string & job_name, + const std::string & data) +{ + DEBTRACE("sendEvent BL::JobsManager_QT"); + + // Sending a QEvent to go back to main thread + BL::JobManagerEvent * event = new JobManagerEvent(action, event_name, job_name, data); + QApplication::postEvent(this, event); +} + +bool +BL::JobsManager_QT::event(QEvent * e) +{ + QDockWidget::event(e); + JobManagerEvent * event = dynamic_cast(e); + if (!event) return false; + + DEBTRACE("BL::JobsManager_QT Receiving event : " + << event->action << " " + << event->event_name << " " + << event->job_name << " " + << event->data); + if (event->action == "start_job") + { + if (event->event_name == "Ok") + { + QString str((event->job_name).c_str()); + write_normal_text("Job " + str + " queued\n"); + } + else + { + QString str((event->job_name).c_str()); + write_error_text("Error in starting job: " + str + "\n"); + write_error_text("*** "); + write_error_text((event->data).c_str()); + write_error_text(" ***\n"); + } + emit job_state_changed(QString((event->job_name).c_str())); + } + else if (event->action == "refresh_job") + { + if (event->event_name == "Ok") + { + QString str((event->job_name).c_str()); + write_normal_text("Job " + str + " state changed\n"); + emit job_state_changed(QString((event->job_name).c_str())); + } + else + { + QString str((event->job_name).c_str()); + write_error_text("Error in refreshing job: " + str + "\n"); + write_error_text("*** "); + write_error_text((event->data).c_str()); + write_error_text(" ***\n"); + } + } + else if (event->action == "delete_job") + { + if (event->event_name == "Ok") + { + QString str((event->job_name).c_str()); + write_normal_text("Job " + str + " deleted\n"); + } + else + { + QString str((event->job_name).c_str()); + write_error_text("Warning delete job: " + str + " maybe not complete, exception catch in SALOME Launcher service\n"); + write_error_text("*** "); + write_error_text((event->data).c_str()); + write_error_text(" ***\n"); + } + } + else if (event->action == "get_results_job") + { + if (event->event_name == "Ok") + { + QString str((event->job_name).c_str()); + write_normal_text("Results of Job " + str + " are get\n"); + } + else + { + QString str((event->job_name).c_str()); + write_error_text("Warning for results of job: " + str + " maybe not complete, exception catch in SALOME Launcher service\n"); + write_error_text("*** "); + write_error_text((event->data).c_str()); + write_error_text(" ***\n"); + } + } + else + { + QString str((event->action).c_str()); + write_error_text("Unknown type of event received:" + str + "\n"); + } + return true; +} + +void +BL::JobsManager_QT::write_normal_text(const QString & text) +{ + _log->setReadOnly(false); + QTextCursor cursor = _log->textCursor(); + QTextCharFormat text_format; + text_format.setForeground(Qt::darkBlue); + cursor.insertText(text, text_format); + _log->setTextCursor(cursor); + _log->setReadOnly(true); +} + +void +BL::JobsManager_QT::write_error_text(const QString & text) +{ + QTextCursor cursor = _log->textCursor(); + QTextCharFormat text_format; + text_format.setForeground(Qt::red); + cursor.insertText(text, text_format); + _log->setTextCursor(cursor); +} diff --git a/src/genericgui/BL_JobsManager_QT.hxx b/src/genericgui/BL_JobsManager_QT.hxx new file mode 100644 index 0000000..b1b0980 --- /dev/null +++ b/src/genericgui/BL_JobsManager_QT.hxx @@ -0,0 +1,97 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_JOBSMANAGER_QT_HXX_ +#define _BL_JOBSMANAGER_QT_HXX_ + +#include + +#include "BL_Traces.hxx" +#include "BL_JobsManager.hxx" +#include "BL_CreateJobWizard.hxx" + +#include + +namespace BL{ + + class JobManagerEvent : public QEvent + { + public: + JobManagerEvent(const std::string & action_i, + const std::string & event_name_i, + const std::string & job_name_i, + const std::string & data_i); + virtual ~JobManagerEvent(); + + public: + std::string action; + std::string event_name; + std::string job_name; + std::string data; + }; + + class JobsManager_QT: virtual public QDockWidget, + virtual public BL::JobsManager, + virtual public BL::Observer + { + Q_OBJECT + + public: + JobsManager_QT(QWidget * parent, BL::SALOMEServices * salome_services); + virtual ~JobsManager_QT(); + + void delete_job(QString job_name); + void create_job_wizard(); + + virtual void sendEvent(const std::string & action, + const std::string & event_name, + const std::string & job_name, + const std::string & data); + bool event(QEvent * e); + + void write_normal_text(const QString & text); + void write_error_text(const QString & text); + + public slots: + void RefreshJobs(); + void no_auto_refresh(); + void ten_seconds_refresh(); + void thirty_seconds_refresh(); + void one_minute_refresh(); + void five_minutes_refresh(); + void thirty_minutes_refresh(); + void one_hour_refresh(); + + signals: + void new_job_added(const QString & name); + void job_state_changed(const QString & name); + + private: + QPushButton * _load_jobs; + QPushButton * _save_jobs; + QPushButton * _auto_refresh_jobs; + QTimer * _timer; + QTextEdit * _log; + }; + +} + +#endif + + diff --git a/src/genericgui/BL_JobsTable.cxx b/src/genericgui/BL_JobsTable.cxx new file mode 100644 index 0000000..8a1f3fb --- /dev/null +++ b/src/genericgui/BL_JobsTable.cxx @@ -0,0 +1,44 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_JobsTable.hxx" +#include "BL_Traces.hxx" + +BL::JobsTable::JobsTable(QWidget *parent) : QTableView(parent) +{ + DEBTRACE("Creating BL::JobsTable"); + BL_ASSERT(parent); + _parent = parent; + + // Init + setShowGrid(false); + setCornerButtonEnabled(false); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setSelectionBehavior(QAbstractItemView::SelectRows); + setAlternatingRowColors(true); + setSortingEnabled(true); + + QHeaderView * header_view = verticalHeader(); + header_view->setClickable(false); +} + +BL::JobsTable::~JobsTable() +{ + DEBTRACE("Destroying BL::JobsTable"); +} diff --git a/src/genericgui/BL_JobsTable.hxx b/src/genericgui/BL_JobsTable.hxx new file mode 100644 index 0000000..ace8b2f --- /dev/null +++ b/src/genericgui/BL_JobsTable.hxx @@ -0,0 +1,42 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_JOBSTABLE_HXX_ +#define _BL_JOBSTABLE_HXX_ + +#include + +namespace BL +{ + class JobsTable: public QTableView + { + Q_OBJECT + + public: + JobsTable(QWidget *parent); + virtual ~JobsTable(); + + protected: + QWidget* _parent; + + }; +} + +#endif + diff --git a/src/genericgui/BL_MachineCatalog.cxx b/src/genericgui/BL_MachineCatalog.cxx new file mode 100644 index 0000000..eae8ded --- /dev/null +++ b/src/genericgui/BL_MachineCatalog.cxx @@ -0,0 +1,66 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_MachineCatalog.hxx" +#include "BL_Traces.hxx" + +BL::MachineCatalog::MachineCatalog(QWidget *parent, BL::SALOMEServices * salome_services) : QWidget(parent) +{ + DEBTRACE("Creating BL::MachineCatalog"); + BL_ASSERT(parent); + BL_ASSERT(salome_services); + _parent = parent; + _salome_services = salome_services; + + _refresh_button = new QPushButton("Refresh Machine List"); + _refresh_button->show(); + connect(_refresh_button, SIGNAL(clicked()), this, SLOT(refresh_machine_list())); + _machine_files_list = new QListWidget(this); + _machine_files_list->setSelectionMode(QAbstractItemView::NoSelection); + std::list machine_list = _salome_services->getMachineList(); + std::list::iterator it; + for (it = machine_list.begin(); it != machine_list.end(); it++) + { + std::string machine = *it; + _machine_files_list->addItem(QString(machine.c_str())); + } + + QVBoxLayout * mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(_refresh_button); + mainLayout->addWidget(_machine_files_list); + setLayout(mainLayout); +} + +BL::MachineCatalog::~MachineCatalog() +{ + DEBTRACE("Destroying BL::MachineCatalog"); +} + +void +BL::MachineCatalog::refresh_machine_list() +{ + _machine_files_list->clear(); + std::list machine_list = _salome_services->getMachineList(); + std::list::iterator it; + for (it = machine_list.begin(); it != machine_list.end(); it++) + { + std::string machine = *it; + _machine_files_list->addItem(QString(machine.c_str())); + } +} diff --git a/src/genericgui/BL_MachineCatalog.hxx b/src/genericgui/BL_MachineCatalog.hxx new file mode 100644 index 0000000..95355b4 --- /dev/null +++ b/src/genericgui/BL_MachineCatalog.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_MACHINECATALOG_HXX_ +#define _BL_MACHINECATALOG_HXX_ + +#include + +#include "BL_SALOMEServices.hxx" + +#include +#include + +namespace BL +{ + class MachineCatalog: public QWidget + { + Q_OBJECT + + public: + MachineCatalog(QWidget *parent, BL::SALOMEServices * salome_services); + virtual ~MachineCatalog(); + + public slots: + void refresh_machine_list(); + + protected: + QWidget* _parent; + BL::SALOMEServices * _salome_services; + + QPushButton * _refresh_button; + QListWidget * _machine_files_list; + }; +} + +#endif + + diff --git a/src/genericgui/BL_MainButtons.cxx b/src/genericgui/BL_MainButtons.cxx new file mode 100644 index 0000000..e69de29 diff --git a/src/genericgui/BL_MainButtons.hxx b/src/genericgui/BL_MainButtons.hxx new file mode 100644 index 0000000..e69de29 diff --git a/src/genericgui/BL_QModelManager.cxx b/src/genericgui/BL_QModelManager.cxx new file mode 100644 index 0000000..6412dd2 --- /dev/null +++ b/src/genericgui/BL_QModelManager.cxx @@ -0,0 +1,131 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_QModelManager.hxx" + +BL::QModelManager::QModelManager(QObject * parent, BL::JobsManager_QT * jobs_manager) : QObject(parent) +{ + DEBTRACE("Creating BL::QModelManager"); + BL_ASSERT(jobs_manager); + _jobs_manager = jobs_manager; + + _model = new QStandardItemModel(this); + QStringList headers; + headers << "Job Name" << "Type" << "State" << "Machine"; + _model->setHorizontalHeaderLabels(headers); +} + +BL::QModelManager::~QModelManager() +{ + DEBTRACE("Destroying BL::QModelManager"); +} + +QStandardItemModel * +BL::QModelManager::getModel() +{ + DEBTRACE("getModel BL::QModelManager called"); + + return _model; +} + +void +BL::QModelManager::new_job_added(const QString & name) +{ + BL::Job * job = _jobs_manager->getJob(name.toStdString()); + QStandardItem * new_job_name = new QStandardItem(name); + + QStandardItem * new_job_type; + if (job->getType() == BL::Job::YACS_SCHEMA) + new_job_type = new QStandardItem("YACS_Schema"); + else + new_job_type = new QStandardItem("Command"); + + QStandardItem * new_job_state; + if (job->getState() == BL::Job::CREATED) + new_job_state = new QStandardItem("Created"); + else if (job->getState() == BL::Job::QUEUED) + new_job_state = new QStandardItem("Queued"); + else if (job->getState() == BL::Job::RUNNING) + new_job_state = new QStandardItem("Running"); + else if (job->getState() == BL::Job::PAUSED) + new_job_state = new QStandardItem("Paused"); + else if (job->getState() == BL::Job::ERROR) + new_job_state = new QStandardItem("Error"); + else + new_job_state = new QStandardItem("Finished"); + + QStandardItem * new_job_machine = new QStandardItem(job->getMachine().c_str()); + + int row = _model->rowCount(); + _model->setItem(row, 0, new_job_name); + _model->setItem(row, 1, new_job_type); + _model->setItem(row, 2, new_job_state); + _model->setItem(row, 3, new_job_machine); +} + +void +BL::QModelManager::job_state_changed(const QString & name) +{ + DEBTRACE("BL::QModelManager::job_state_changed received"); + + BL::Job * job = _jobs_manager->getJob(name.toStdString()); + QList item_list = _model->findItems(name); + QStandardItem * job_state_item = _model->item(item_list.at(0)->row(), 2); + + if (job->getState() == BL::Job::CREATED) + job_state_item->setText("Created"); + else if (job->getState() == BL::Job::QUEUED) + job_state_item->setText("Queued"); + else if (job->getState() == BL::Job::RUNNING) + job_state_item->setText("Running"); + else if (job->getState() == BL::Job::PAUSED) + job_state_item->setText("Paused"); + else if (job->getState() == BL::Job::ERROR) + job_state_item->setText("Error"); + else + job_state_item->setText("Finished"); +} + +void +BL::QModelManager::deleteJob(int row) +{ + _model->removeRow(row); +} + +void +BL::QModelManager::job_selected(const QModelIndex & index) +{ + DEBTRACE("BL::QModelManager::job_selected slot"); + QStandardItem * item = _model->itemFromIndex(index); + int row = item->row(); + + // Algo un peu bourrin.... + for (int i = 0; i < _model->rowCount(); i++) + for (int j = 0; j < _model->columnCount(); j++) + { + _model->item(i,j)->setBackground(QBrush(Qt::white)); + _model->item(i,j)->setForeground(QBrush(Qt::black)); + } + + for (int j = 0; j < _model->columnCount(); j++) + { + _model->item(row,j)->setBackground(QBrush(Qt::darkBlue)); + _model->item(row,j)->setForeground(QBrush(Qt::white)); + } +} diff --git a/src/genericgui/BL_QModelManager.hxx b/src/genericgui/BL_QModelManager.hxx new file mode 100644 index 0000000..868d93a --- /dev/null +++ b/src/genericgui/BL_QModelManager.hxx @@ -0,0 +1,56 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_QMODELMANAGER_HXX_ +#define _BL_QMODELMANAGER_HXX_ + +#include + +#include "BL_Job.hxx" +#include "BL_JobsManager_QT.hxx" + +namespace BL{ + + class QModelManager: virtual public QObject + { + Q_OBJECT + + public: + QModelManager(QObject * parent, BL::JobsManager_QT * jobs_manager); + virtual ~QModelManager(); + + QStandardItemModel * getModel(); + + void deleteJob(int row); + + public slots: + void new_job_added(const QString & name); + void job_state_changed(const QString & name); + void job_selected(const QModelIndex & index); + + private: + QStandardItemModel * _model; + BL::JobsManager_QT * _jobs_manager; + + }; + +} + +#endif + diff --git a/src/genericgui/BL_Summary.cxx b/src/genericgui/BL_Summary.cxx new file mode 100644 index 0000000..4cb67fc --- /dev/null +++ b/src/genericgui/BL_Summary.cxx @@ -0,0 +1,137 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#include "BL_Summary.hxx" +#include "BL_Traces.hxx" + +BL::Summary::Summary(QWidget *parent, BL::JobsManager_QT * jobs_manager) : QWidget(parent) +{ + DEBTRACE("Creating BL::Summary"); + BL_ASSERT(parent); + BL_ASSERT(jobs_manager); + _parent = parent; + _jobs_manager = jobs_manager; + _model = NULL; + + + QLabel * summary_jobs = new QLabel("Jobs Summary:"); + QLabel * total_label = new QLabel("Number of jobs:"); + _total_line = new QLabel; + _total_line->setText("0"); + + QLabel * created_label = new QLabel("Number of created jobs:"); + _created_line = new QLabel; + _created_line->setText("0"); + + QLabel * queued_label = new QLabel("Number of queued jobs:"); + _queued_line = new QLabel; + _queued_line->setText("0"); + + QLabel * running_label = new QLabel("Number of running jobs:"); + _running_line = new QLabel; + _running_line->setText("0"); + + QLabel * finished_label = new QLabel("Number of finished jobs:"); + _finished_line = new QLabel; + _finished_line->setText("0"); + + QFormLayout *mainLayout = new QFormLayout; + mainLayout->insertRow(0, summary_jobs); + mainLayout->insertRow(1, total_label, _total_line); + mainLayout->insertRow(2, created_label, _created_line); + mainLayout->insertRow(3, queued_label, _queued_line); + mainLayout->insertRow(4, running_label, _running_line); + mainLayout->insertRow(5, finished_label, _finished_line); + setLayout(mainLayout); +} + +BL::Summary::~Summary() +{ + DEBTRACE("Destroying BL::Summary"); +} + +void +BL::Summary::setModel(QStandardItemModel * model) +{ + DEBTRACE("Call setModel BL::Summary"); + BL_ASSERT(model); + + _model = model; +} + +void +BL::Summary::rowsInserted(const QModelIndex & parent, int start, int end) +{ + DEBTRACE("BL::Summary::rowsInserted slot"); + updateJobs(); +} + +void +BL::Summary::rowsRemoved(const QModelIndex & parent, int start, int end) +{ + DEBTRACE("BL::Summary::rowsRemoved slot"); + updateJobs(); +} + +void +BL::Summary::itemChanged(QStandardItem * item) +{ + updateJobs(); +} + +void +BL::Summary::updateJobs() +{ + // Total + QVariant row_number = _model->rowCount(); + _total_line->setText(row_number.toString()); + + // New count... + _created_line->setText("0"); + _queued_line->setText("0"); + _running_line->setText("0"); + _finished_line->setText("0"); + + int created_jobs = 0; + int queued_jobs = 0; + int running_jobs = 0; + int finished_jobs = 0; + std::map jobs = _jobs_manager->getJobs(); + std::map::iterator jobs_it; + jobs_it = jobs.begin(); + for(; jobs_it != jobs.end(); jobs_it++) + { + BL::Job * job = jobs_it->second; + BL::Job::State job_state = job->getState(); + if (job_state == BL::Job::CREATED) + created_jobs++; + if (job_state == BL::Job::QUEUED) + queued_jobs++; + if (job_state == BL::Job::RUNNING) + running_jobs++; + if (job_state == BL::Job::FINISHED) + finished_jobs++; + } + + // End + _created_line->setText(QVariant(created_jobs).toString()); + _queued_line->setText(QVariant(queued_jobs).toString()); + _running_line->setText(QVariant(running_jobs).toString()); + _finished_line->setText(QVariant(finished_jobs).toString()); +} diff --git a/src/genericgui/BL_Summary.hxx b/src/genericgui/BL_Summary.hxx new file mode 100644 index 0000000..b972388 --- /dev/null +++ b/src/genericgui/BL_Summary.hxx @@ -0,0 +1,59 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +// + +#ifndef _BL_SUMMARY_HXX_ +#define _BL_SUMMARY_HXX_ + +#include +#include "BL_JobsManager_QT.hxx" + +namespace BL +{ + class Summary: public QWidget + { + Q_OBJECT + + public: + Summary(QWidget *parent, BL::JobsManager_QT * jobs_manager); + virtual ~Summary(); + + void setModel(QStandardItemModel * model); + + void updateJobs(); + + public slots: + void rowsInserted(const QModelIndex & parent, int start, int end); + void rowsRemoved(const QModelIndex & parent, int start, int end); + void itemChanged(QStandardItem * item); + + protected: + QWidget* _parent; + QStandardItemModel * _model; + + BL::JobsManager_QT * _jobs_manager; + QLabel * _total_line; + QLabel * _created_line; + QLabel * _queued_line; + QLabel * _running_line; + QLabel * _finished_line; + }; +} + +#endif + diff --git a/src/genericgui/Makefile.am b/src/genericgui/Makefile.am new file mode 100644 index 0000000..c039365 --- /dev/null +++ b/src/genericgui/Makefile.am @@ -0,0 +1,64 @@ +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +libdir = $(prefix)/lib/salome + +lib_LTLIBRARIES = libBL_GenericGui.la + +libBL_GenericGui_la_SOURCES = BL_GenericGui.hxx BL_GenericGui.cxx \ + BL_JobsTable.hxx BL_JobsTable.cxx \ + BL_JobTab.hxx BL_JobTab.cxx \ + BL_Buttons.hxx BL_Buttons.cxx \ + BL_JobsManager_QT.hxx BL_JobsManager_QT.cxx \ + BL_QModelManager.hxx BL_QModelManager.cxx \ + BL_CreateJobWizard.hxx BL_CreateJobWizard.cxx \ + BL_Summary.hxx BL_Summary.cxx \ + BL_MachineCatalog.hxx BL_MachineCatalog.cxx + +nodist_libBL_GenericGui_la_SOURCES = BL_GenericGui_moc.cxx BL_JobsTable_moc.cxx \ + BL_JobTab_moc.cxx \ + BL_Buttons_moc.cxx BL_JobsManager_QT_moc.cxx \ + BL_QModelManager_moc.cxx BL_CreateJobWizard_moc.cxx \ + BL_Summary_moc.cxx BL_MachineCatalog_moc.cxx + +libBL_GenericGui_la_CXXFLAGS = $(qt4_cppflags) \ + -I$(top_srcdir)/src/bases \ + -I$(top_srcdir)/src/engine \ + -I$(KERNEL_ROOT_DIR)/include/salome \ + -I$(top_srcdir)/src/wrappers + +libBL_GenericGui_la_LDFLAGS = $(qt4_ldflags) + +libBL_GenericGui_la_LIBADD = -lQtGui -lQtCore -lQtWebKit \ + $(top_builddir)/src/bases/libBL_Bases.la \ + $(top_builddir)/src/engine/libBL_Engine.la + +SUFFIXES = .hxx _moc.cxx .qrc _qrc.cxx + +.hxx_moc.cxx : + $(QT_MOC) -p . -o $@ $< + +.qrc_qrc.cxx : + $(QT_RCC) -name $(*F) $< -o $@ + +clean-local-qt : + rm -f *_moc.cxx *_qrc.cxx ui_*.h + +clean-local: clean-local-qt + diff --git a/src/salomegui/BL_SalomeGui.cxx b/src/salomegui/BL_SalomeGui.cxx new file mode 100644 index 0000000..5895d94 --- /dev/null +++ b/src/salomegui/BL_SalomeGui.cxx @@ -0,0 +1,85 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + +#include "BL_SalomeGui.hxx" + +BL::SalomeGui::SalomeGui() : MainWindows_SALOME("JobManager"), + SalomeApp_Module("JobManager"), + LightApp_Module("JobManager") +{ + DEBTRACE("Creating BL::SalomeGui"); + _gengui = NULL; +} + +BL::SalomeGui::~SalomeGui() +{ + DEBTRACE("Destroying BL::SalomeGui"); +} + +void +BL::SalomeGui::initialize(CAM_Application* app) +{ + DEBTRACE("Entering in initialize"); + SalomeApp_Module::initialize(app); // MANDATORY -> Otherwise SISEGV... + BL::MainWindows_SALOME::initialize(getApp()); + + _gengui = new BL::GenericGui(this); + _gengui->createActions(); + _gengui->createMenus(); + _gengui->updateButtonsStates(); +} + +bool +BL::SalomeGui::activateModule(SUIT_Study* theStudy) +{ + DEBTRACE("Entering in BL::SalomeGui::activateModule"); + + bool bOk = SalomeApp_Module::activateModule(theStudy); + setMenuShown(true); + + _gengui->showDockWidgets(true); + return bOk; +} + +void +BL::SalomeGui::windows(QMap& theMap) const +{ + DEBTRACE("Entering in BL::SalomeGui::windows"); + theMap.clear(); + theMap.insert(SalomeApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea); +} + +bool +BL::SalomeGui::deactivateModule(SUIT_Study* theStudy) +{ + DEBTRACE("Entering in BL::SalomeGui::deactivateModule"); + + setMenuShown(false); + _gengui->showDockWidgets(false); + bool bOk = SalomeApp_Module::deactivateModule(theStudy); + return bOk; +} + +// --- Export the module +extern "C" +{ + CAM_Module* createModule() + { + return new BL::SalomeGui(); + } +} diff --git a/src/salomegui/BL_SalomeGui.hxx b/src/salomegui/BL_SalomeGui.hxx new file mode 100644 index 0000000..c72142d --- /dev/null +++ b/src/salomegui/BL_SalomeGui.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + +#ifndef _BL_SALOMEGUI_HXX_ +#define _BL_SALOMEGUI_HXX_ + +#include + +#include +#include + +#include "BL_MainWindows_SALOME.hxx" +#include "BL_GenericGui.hxx" +#include "BL_Traces.hxx" + +namespace BL +{ + class SalomeGui: virtual public MainWindows_SALOME + { + Q_OBJECT + + public: + SalomeGui(); + virtual ~SalomeGui(); + + void initialize( CAM_Application* app); // --- Call only once, at GUI module creation + void windows( QMap& theMap) const; // --- Default windows, called each time the module is activated + + public slots: + bool deactivateModule( SUIT_Study* theStudy); + bool activateModule( SUIT_Study* theStudy); + + protected: + BL::GenericGui * _gengui; + }; + +} + +#endif diff --git a/src/salomegui/Makefile.am b/src/salomegui/Makefile.am new file mode 100644 index 0000000..c916702 --- /dev/null +++ b/src/salomegui/Makefile.am @@ -0,0 +1,78 @@ +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +include $(top_srcdir)/src/bases/make_begin.am + +MOC_FILES = BL_SalomeGui_moc.cxx + +lib_LTLIBRARIES = libJOBMANAGER.la + +dist_libJOBMANAGER_la_SOURCES = BL_SalomeGui.hxx BL_SalomeGui.cxx + +nodist_libJOBMANAGER_la_SOURCES = $(MOC_FILES) + +libJOBMANAGER_la_CXXFLAGS = $(qt4_cppflags) \ + $(OMNIORB_INCLUDES) \ + -I$(KERNEL_ROOT_DIR)/include/salome \ + -I$(GUI_ROOT_DIR)/include/salome \ + -I$(top_srcdir)/src/genericgui \ + -I$(top_srcdir)/src/wrappers \ + -I$(top_srcdir)/src/engine \ + -I$(top_srcdir)/src/bases + +libJOBMANAGER_la_LDFLAGS = -L$(GUI_ROOT_DIR)/lib/salome \ + -L$(KERNEL_ROOT_DIR)/lib/salome \ + $(qt4_ldflags) + +libJOBMANAGER_la_LIBADD = $(qt4_libs) \ + $(top_builddir)/src/bases/libBL_Bases.la \ + $(top_builddir)/src/engine/libBL_Engine.la \ + $(top_builddir)/src/genericgui/libBL_GenericGui.la \ + $(top_builddir)/src/wrappers/libBL_Wrappers_SALOME.la \ + -lSalomeApp + +salomeinclude_HEADERS = BL_SalomeGui.hxx + +# resources files +LIBICONS = SalomeApp.xml jobmanager.png +dist_salomeres_DATA = ${ICONS} +ICONS = $(LIBICONS:%=resources/%) + +# -------------------------------------------- +# *.h --> *_moc.cxx +# -------------------------------------------- + +SUFFIXES = .hxx _moc.cxx .qrc _qrc.cxx + +.hxx_moc.cxx : + $(QT_MOC) -p . -o $@ $< + +.qrc_qrc.cxx : + $(QT_RCC) -name $(*F) $< -o $@ + +#.ui.h : +# $(QT_UIC) -o $@ $< + + +clean-local-qt : + rm -f *_moc.cxx *_qrc.cxx + + +clean-local: clean-local-qt + rm -f YACS_msg_en.qm YACS_msg_fr.qm diff --git a/src/salomegui/resources/SalomeApp.xml b/src/salomegui/resources/SalomeApp.xml new file mode 100644 index 0000000..c8e0933 --- /dev/null +++ b/src/salomegui/resources/SalomeApp.xml @@ -0,0 +1,31 @@ + + +
+ + + +
+
+ + +
+
diff --git a/src/salomegui/resources/jobmanager.png b/src/salomegui/resources/jobmanager.png new file mode 100644 index 0000000000000000000000000000000000000000..89d43e8fb50a01d551a59a0a5e9303d3ae033135 GIT binary patch literal 63360 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�!`!0A`%s7Z3-mE%h+oA3yqk|HeDs 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 literal 0 HcmV?d00001 diff --git a/src/standalone/Makefile.am b/src/standalone/Makefile.am new file mode 100644 index 0000000..e6c5d75 --- /dev/null +++ b/src/standalone/Makefile.am @@ -0,0 +1,23 @@ +bin_PROGRAMS = jobmanager_gui + +bin_SCRIPTS = start_jobmanager.sh + +jobmanager_gui_SOURCES = main.cxx + +jobmanager_gui_CXXFLAGS = $(qt4_cppflags) \ + -I$(top_srcdir)/src/bases \ + -I$(top_srcdir)/src/engine \ + -I$(KERNEL_ROOT_DIR)/include/salome \ + -I$(top_srcdir)/src/wrappers \ + -I$(top_srcdir)/src/genericgui + +jobmanager_gui_LDFLAGS = $(qt4_ldflags) + +jobmanager_gui_LDADD = -lQtGui -lQtCore \ + $(top_builddir)/src/genericgui/libBL_GenericGui.la \ + $(top_builddir)/src/engine/libBL_Engine.la \ + $(top_builddir)/src/wrappers/libBL_Wrappers_Qt.la \ + @OMNIORB_LIBS@ \ + -L$(KERNEL_ROOT_DIR)/lib/salome -lSalomeLifeCycleCORBA -lSalomeIDLKernel -lSalomeNS + +EXTRA_DIST = start_jobmanager.sh.in diff --git a/src/standalone/main.cxx b/src/standalone/main.cxx new file mode 100644 index 0000000..baf07c6 --- /dev/null +++ b/src/standalone/main.cxx @@ -0,0 +1,21 @@ +#include +#include "BL_GenericGui.hxx" +#include "BL_MainWindows_Qt.hxx" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QMainWindow main_window; + BL::MainWindows_Qt wrapper(&main_window); + BL::GenericGui * main_widget = new BL::GenericGui(&wrapper); + main_widget->createActions(); + main_widget->createMenus(); + main_widget->updateButtonsStates(); + + main_window.setWindowTitle("Standalone JobManager Gui"); + main_window.show(); + + return app.exec(); +} + diff --git a/src/standalone/start_jobmanager.sh.in b/src/standalone/start_jobmanager.sh.in new file mode 100644 index 0000000..4b94938 --- /dev/null +++ b/src/standalone/start_jobmanager.sh.in @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +usage() +{ + echo "Start JobManager GUI outside SALOME GUI" + echo "" + echo "Usage: $(basename $0) -a APPLIPATH [ -h ]" + echo "" + echo " -a APPLIPATH : Application Path where SALOME is launched " + echo " -h : Print this message" + echo "" +} + +while getopts 'a:h' OPTION + do + case $OPTION in + a)APPLIPATH="$OPTARG" ;; + h|?) usage + exit 1 ;; + esac + done + +if test "x${APPLIPATH}" == "x"; then + usage + exit 1 +fi + +JOBMANAGER_INSTALL_DIR=@prefix@/bin + +${APPLIPATH}/runSession ${JOBMANAGER_INSTALL_DIR}/jobmanager_gui diff --git a/src/wrappers/BL_MainWindows_Qt.cxx b/src/wrappers/BL_MainWindows_Qt.cxx new file mode 100644 index 0000000..ea7e5a2 --- /dev/null +++ b/src/wrappers/BL_MainWindows_Qt.cxx @@ -0,0 +1,77 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + +#include "BL_MainWindows_Qt.hxx" + +BL::MainWindows_Qt::MainWindows_Qt(QMainWindow * main_window) +{ + DEBTRACE("Creating BL::MainWindows_Qt"); + BL_ASSERT(main_window); + _main_window = main_window; + _menuId = 0; +} + +BL::MainWindows_Qt::~MainWindows_Qt() +{ + DEBTRACE("Destroying BL::MainWindows_Qt"); +} + +QMainWindow * +BL::MainWindows_Qt::getDockParent() +{ + return _main_window; +} + +QMainWindow * +BL::MainWindows_Qt::getTabParent() +{ + return _main_window; +} + +QAction* +BL::MainWindows_Qt::createAction(const QString& toolTip, + const QIcon& icon, + const QString& menu, + const QString& status, + const int shortCut, + QObject* parent, + bool checkable, + QObject* receiver, + const char* member) +{ + QAction * action = new QAction(icon, menu, parent); + action->setStatusTip(status); + action->setToolTip(toolTip); + if (receiver) + connect(action, SIGNAL(triggered()), receiver, member); + return action; +} + +int +BL::MainWindows_Qt::createTopMenu(const QString & menu_name) +{ + QMenu * new_menu = _main_window->menuBar()->addMenu(menu_name); + _menu_map[getMenuId()] = new_menu; + return 0; +} + +void +BL::MainWindows_Qt::addActionToMenu(QAction * action, int menu_id) +{ + _menu_map[menu_id]->addAction(action); +} diff --git a/src/wrappers/BL_MainWindows_Qt.hxx b/src/wrappers/BL_MainWindows_Qt.hxx new file mode 100644 index 0000000..550d6c5 --- /dev/null +++ b/src/wrappers/BL_MainWindows_Qt.hxx @@ -0,0 +1,58 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + + +#ifndef _BL_MAINWINDOWS_QT_HXX_ +#define _BL_MAINWINDOWS_QT_HXX_ + +#include "BL_MainWindows_Wrap.hxx" +#include + +namespace BL +{ + class MainWindows_Qt : public MainWindows_Wrap, public QObject + { + public: + MainWindows_Qt(QMainWindow * main_window); + virtual ~MainWindows_Qt(); + + virtual QMainWindow * getDockParent(); + virtual QMainWindow * getTabParent(); + + virtual QAction* createAction(const QString& toolTip, + const QIcon& icon, + const QString& menu, + const QString& status, + const int shortCut, + QObject* parent =0, + bool checkable = false, + QObject* receiver =0, + const char* member =0); + + virtual int createTopMenu(const QString & menu_name); + virtual void addActionToMenu(QAction * action, int menu_id); + + protected: + QMainWindow * _main_window; + int _menuId; + int getMenuId() { return _menuId++; } + std::map _menu_map; + }; +} + +#endif diff --git a/src/wrappers/BL_MainWindows_SALOME.cxx b/src/wrappers/BL_MainWindows_SALOME.cxx new file mode 100644 index 0000000..6a604b7 --- /dev/null +++ b/src/wrappers/BL_MainWindows_SALOME.cxx @@ -0,0 +1,100 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + +#include "BL_MainWindows_SALOME.hxx" + +BL::MainWindows_SALOME::MainWindows_SALOME(const QString & module_name) : + SalomeApp_Module(module_name), + LightApp_Module(module_name) +{ + DEBTRACE("Creating BL::MainWindows_SALOME"); + _actionId = 190; +} + +void +BL::MainWindows_SALOME::initialize(SalomeApp_Application * appli) +{ + DEBTRACE("Initialize BL::MainWindows_SALOME"); + BL_ASSERT(appli); + + _appli = appli; + _svm = new SUIT_ViewManager(_appli->activeStudy(), _appli->desktop(), new SUIT_ViewModel()); + _appli->addViewManager(_svm); + _viewWin = _svm->createViewWindow(); + + if (_viewWin && _appli->desktop()) + _viewWin->resize((int)(_appli->desktop()->width() * 0.6), (int)(_appli->desktop()->height() * 0.6 )); +} + +QString +BL::MainWindows_SALOME::engineIOR() const +{ + DEBTRACE("Entering in BL::SalomeGui::engineIOR"); + return _appli->defaultEngineIOR(); +} + +void +BL::MainWindows_SALOME::viewManagers(QStringList& list) const +{ + DEBTRACE("Entering in BL::SalomeGui::viewManagers"); + list.append(_svm->getType()); +} + + +BL::MainWindows_SALOME::~MainWindows_SALOME() +{ + DEBTRACE("Destroying BL::MainWindows_SALOME"); +} + +QMainWindow * +BL::MainWindows_SALOME::getDockParent() +{ + return _appli->desktop(); +} + +QMainWindow * +BL::MainWindows_SALOME::getTabParent() +{ + return _viewWin; +} + +QAction* +BL::MainWindows_SALOME::createAction(const QString& toolTip, + const QIcon& icon, + const QString& menu, + const QString& status, + const int shortCut, + QObject* parent, + bool checkable, + QObject* receiver, + const char* member) +{ + return SalomeApp_Module::createAction(getActionId(), toolTip, icon, menu, status, shortCut, parent, checkable, receiver, member); +} + +int +BL::MainWindows_SALOME::createTopMenu(const QString & menu_name) +{ + return createMenu(menu_name, -1); +} + +void +BL::MainWindows_SALOME::addActionToMenu(QAction * action, int menu_id) +{ + createMenu(action, menu_id); +} diff --git a/src/wrappers/BL_MainWindows_SALOME.hxx b/src/wrappers/BL_MainWindows_SALOME.hxx new file mode 100644 index 0000000..ec2ee35 --- /dev/null +++ b/src/wrappers/BL_MainWindows_SALOME.hxx @@ -0,0 +1,80 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + + +#ifndef _BL_MAINWINDOWS_SALOME_HXX_ +#define _BL_MAINWINDOWS_SALOME_HXX_ + +#include "BL_MainWindows_Wrap.hxx" + +#include +#include + +#include +#include +#include +#include + +namespace BL +{ + class MainWindows_SALOME : virtual public MainWindows_Wrap, + virtual public SalomeApp_Module + { + public: + MainWindows_SALOME(const QString & module_name); + virtual ~MainWindows_SALOME(); + + // mandatory by SalomeApp_Module + virtual QString engineIOR() const; + + // Usefull methods for good integration in SALOME + virtual void viewManagers( QStringList& list) const; // --- On ajoute nos viewManagers et ensuite LigthApp affiche le dernier + + // mandatory by MainWindows_Wrap + virtual QMainWindow * getDockParent(); + virtual QMainWindow * getTabParent(); + + virtual QAction* createAction(const QString& toolTip, + const QIcon& icon, + const QString& menu, + const QString& status, + const int shortCut, + QObject* parent =0, + bool checkable = false, + QObject* receiver =0, + const char* member =0); + + virtual int createTopMenu(const QString & menu_name); + virtual void addActionToMenu(QAction * action, int menu_id); + + // Usefull methods + virtual void initialize(SalomeApp_Application * appli); + + protected: + SalomeApp_Application * _appli; + SalomeApp_Module * _module; + SUIT_ViewManager * _svm; + SUIT_ViewWindow * _viewWin; + + int _actionId; + int getActionId() { return _actionId++; } + }; +} + +#endif + diff --git a/src/wrappers/BL_MainWindows_Wrap.hxx b/src/wrappers/BL_MainWindows_Wrap.hxx new file mode 100644 index 0000000..3d16e98 --- /dev/null +++ b/src/wrappers/BL_MainWindows_Wrap.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com + + +#ifndef _BL_MAINWINDOWS_WRAP_HXX_ +#define _BL_MAINWINDOWS_WRAP_HXX_ + +#include +#include "BL_Traces.hxx" + +namespace BL +{ + class MainWindows_Wrap + { + + public: + MainWindows_Wrap() {} + virtual ~MainWindows_Wrap() {} + + virtual QMainWindow * getDockParent() = 0; + virtual QMainWindow * getTabParent() = 0; + + virtual QAction* createAction(const QString& toolTip, + const QIcon& icon, + const QString& menu, + const QString& status, + const int shortCut, + QObject* parent =0, + bool checkable = false, + QObject* receiver =0, + const char* member =0) = 0; + + virtual int createTopMenu(const QString & menu_name) = 0; + virtual void addActionToMenu(QAction * action, int menu_id) = 0; + + }; +} + +#endif diff --git a/src/wrappers/Makefile.am b/src/wrappers/Makefile.am new file mode 100644 index 0000000..773d02e --- /dev/null +++ b/src/wrappers/Makefile.am @@ -0,0 +1,54 @@ +# Copyright (C) 2009 CEA/DEN, EDF 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/ or email : webmaster.salome@opencascade.com +# + +libdir = $(prefix)/lib/salome + +lib_LTLIBRARIES = libBL_Wrappers_Qt.la + +if HAS_GUI +lib_LTLIBRARIES += libBL_Wrappers_SALOME.la +endif + +libBL_Wrappers_Qt_la_SOURCES = BL_MainWindows_Wrap.hxx \ + BL_MainWindows_Qt.cxx BL_MainWindows_Qt.hxx + +nodist_libBL_Wrappers_Qt_la_SOURCES = + +libBL_Wrappers_Qt_la_CXXFLAGS = $(qt4_cppflags) -I$(top_srcdir)/src/bases + +libBL_Wrappers_Qt_la_LDFLAGS = $(qt4_ldflags) + +libBL_Wrappers_Qt_la_LIBADD = -lQtGui -lQtCore $(top_builddir)/src/bases/libBL_Bases.la + +########### + +libBL_Wrappers_SALOME_la_SOURCES = BL_MainWindows_Wrap.hxx \ + BL_MainWindows_SALOME.cxx BL_MainWindows_SALOME.hxx + +nodist_libBL_Wrappers_SALOME_la_SOURCES = + +libBL_Wrappers_SALOME_la_CXXFLAGS = $(qt4_cppflags) -I$(top_srcdir)/src/bases \ + $(OMNIORB_INCLUDES) \ + -I$(KERNEL_ROOT_DIR)/include/salome \ + -I$(GUI_ROOT_DIR)/include/salome + +libBL_Wrappers_SALOME_la_LDFLAGS = $(qt4_ldflags) + +libBL_Wrappers_SALOME_la_LIBADD = -lQtGui -lQtCore $(top_builddir)/src/bases/libBL_Bases.la + -- 2.39.2