From c2353fab7d7d9042827e19a8273b743f3763fd48 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Mon, 11 Jun 2018 11:23:40 +0200 Subject: [PATCH] added mupp. Currently only build with cmake. --- CMakeLists.txt | 2 +- src/musredit_qt5/CMakeLists.txt | 1 + src/musredit_qt5/mupp/CMakeLists.txt | 88 + src/musredit_qt5/mupp/Pmupp.cpp | 1000 +++++++++ src/musredit_qt5/mupp/Pmupp.h | 151 ++ src/musredit_qt5/mupp/PmuppAdmin.cpp | 500 +++++ src/musredit_qt5/mupp/PmuppAdmin.h | 151 ++ src/musredit_qt5/mupp/PmuppGui.cpp | 1990 +++++++++++++++++ src/musredit_qt5/mupp/PmuppGui.h | 215 ++ src/musredit_qt5/mupp/PmuppScript.cpp | 706 ++++++ src/musredit_qt5/mupp/PmuppScript.h | 91 + .../configure_mupp_version_file.cmake.in | 30 + src/musredit_qt5/mupp/cmake/mupp_version.h.in | 11 + .../mupp/examples/2485_tf_histo.msr | 96 + .../mupp/examples/2486_tf_histo.msr | 96 + .../mupp/examples/2487_tf_histo.msr | 96 + .../mupp/examples/2488_tf_histo.msr | 96 + .../mupp/examples/2489_tf_histo.msr | 96 + .../mupp/examples/2490_tf_histo.msr | 96 + .../mupp/examples/2491_tf_histo.msr | 96 + .../mupp/examples/2492_tf_histo.msr | 96 + .../mupp/examples/2493_tf_histo.msr | 96 + .../mupp/examples/2494_tf_histo.msr | 96 + .../mupp/examples/2495_tf_histo.msr | 96 + .../mupp/examples/2496_tf_histo.msr | 96 + .../mupp/examples/2497_tf_histo.msr | 96 + .../mupp/examples/2498_tf_histo.msr | 96 + .../mupp/examples/2499_tf_histo.msr | 96 + .../mupp/examples/2500_tf_histo.msr | 96 + .../mupp/examples/2501_tf_histo.msr | 96 + .../mupp/examples/2502_tf_histo.msr | 96 + .../mupp/examples/2503_tf_histo.msr | 96 + .../mupp/examples/2504_tf_histo.msr | 96 + .../mupp/examples/2505_tf_histo.msr | 96 + .../mupp/examples/2506_tf_histo.msr | 96 + .../mupp/examples/2507_tf_histo.msr | 96 + .../mupp/examples/2508_tf_histo.msr | 96 + .../mupp/examples/2509_tf_histo.msr | 96 + .../mupp/examples/2510_tf_histo.msr | 96 + .../mupp/examples/2511_tf_histo.msr | 95 + .../mupp/examples/2512_tf_histo.msr | 95 + .../mupp/examples/2516_tf_histo.msr | 95 + .../mupp/examples/2517_tf_histo.msr | 95 + .../mupp/examples/2518_tf_histo.msr | 95 + .../mupp/examples/2519_tf_histo.msr | 96 + .../mupp/examples/2520_tf_histo.msr | 96 + .../mupp/examples/2521_tf_histo.msr | 96 + .../mupp/examples/2522_tf_histo.msr | 96 + .../mupp/examples/2523_tf_histo.msr | 96 + .../mupp/examples/2524_tf_histo.msr | 96 + .../mupp/examples/2525_tf_histo.msr | 96 + .../mupp/examples/2526_tf_histo.msr | 96 + .../mupp/examples/2527_tf_histo.msr | 96 + .../mupp/examples/2528_tf_histo.msr | 96 + .../mupp/examples/2529_tf_histo.msr | 96 + .../mupp/examples/2530_tf_histo.msr | 96 + .../mupp/examples/2531_tf_histo.msr | 96 + .../mupp/examples/2532_tf_histo.msr | 96 + .../mupp/examples/2533_tf_histo.msr | 96 + .../mupp/examples/2534_tf_histo.msr | 96 + .../mupp/examples/2535_tf_histo.msr | 96 + .../mupp/examples/2536_tf_histo.msr | 96 + .../mupp/examples/2537_tf_histo.msr | 96 + .../mupp/examples/2538_tf_histo.msr | 96 + .../mupp/examples/2539_tf_histo.msr | 96 + .../mupp/examples/2540_tf_histo.msr | 96 + .../mupp/examples/2541_tf_histo.msr | 96 + .../mupp/examples/2542_tf_histo.msr | 96 + .../mupp/examples/2543_tf_histo.msr | 96 + .../mupp/examples/2544_tf_histo.msr | 96 + .../mupp/examples/2545_tf_histo.msr | 96 + .../mupp/examples/2546_tf_histo.msr | 96 + .../mupp/examples/2547_tf_histo.msr | 96 + .../mupp/examples/2548_tf_histo.msr | 96 + .../mupp/examples/2549_tf_histo.msr | 96 + .../mupp/examples/2550_tf_histo.msr | 96 + .../mupp/examples/2551_tf_histo.msr | 96 + .../mupp/examples/2552_tf_histo.msr | 96 + .../YBCO-40nm-FC-E3p8keV-B10mT-Tscan.dat | 16 + .../YBCO-40nm-FC-E3p8keV-B10mT-Tscan.db | 390 ++++ .../YBCO-40nm-FC-E3p8keV-B150mT-Tscan.dat | 16 + .../YBCO-40nm-FC-E3p8keV-B150mT-Tscan.db | 390 ++++ .../examples/YBCO-40nm-T120K-FC150mT-Escan.db | 282 +++ .../examples/YBCO-40nm-T30K-FC150mT-Escan.db | 282 +++ .../examples/YBCO-40nm-T5K-FC150mT-Escan.db | 309 +++ .../examples/YBCO-40nm-T60K-FC150mT-Escan.db | 282 +++ .../mupp/examples/field-vs-energy.txt | 20 + .../mupp/icons/document-open-dark.svg | 14 + .../mupp/icons/document-open-plain.svg | 75 + src/musredit_qt5/mupp/icons/mupp-dark.svg | 199 ++ src/musredit_qt5/mupp/icons/mupp-plain.svg | 199 ++ src/musredit_qt5/mupp/icons/mupp.icns | Bin 0 -> 266246 bytes src/musredit_qt5/mupp/mupp.cpp | 436 ++++ src/musredit_qt5/mupp/mupp.h | 45 + src/musredit_qt5/mupp/mupp.qrc | 11 + src/musredit_qt5/mupp/mupp_startup.xml.in | 40 + src/musredit_qt5/mupp/plotter/CMakeLists.txt | 67 + src/musredit_qt5/mupp/plotter/PMuppCanvas.cpp | 656 ++++++ src/musredit_qt5/mupp/plotter/PMuppCanvas.h | 126 ++ .../mupp/plotter/PMuppCanvasLinkDef.h | 38 + .../mupp/plotter/PMuppStartupHandler.cpp | 458 ++++ .../mupp/plotter/PMuppStartupHandler.h | 90 + .../mupp/plotter/PMuppStartupHandlerLinkDef.h | 38 + src/musredit_qt5/mupp/plotter/mupp_plot.cpp | 134 ++ src/musredit_qt5/mupp/plotter/mupp_plot.h | 93 + 105 files changed, 15876 insertions(+), 1 deletion(-) create mode 100644 src/musredit_qt5/mupp/CMakeLists.txt create mode 100644 src/musredit_qt5/mupp/Pmupp.cpp create mode 100644 src/musredit_qt5/mupp/Pmupp.h create mode 100644 src/musredit_qt5/mupp/PmuppAdmin.cpp create mode 100644 src/musredit_qt5/mupp/PmuppAdmin.h create mode 100644 src/musredit_qt5/mupp/PmuppGui.cpp create mode 100644 src/musredit_qt5/mupp/PmuppGui.h create mode 100644 src/musredit_qt5/mupp/PmuppScript.cpp create mode 100644 src/musredit_qt5/mupp/PmuppScript.h create mode 100644 src/musredit_qt5/mupp/cmake/configure_mupp_version_file.cmake.in create mode 100644 src/musredit_qt5/mupp/cmake/mupp_version.h.in create mode 100644 src/musredit_qt5/mupp/examples/2485_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2486_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2487_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2488_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2489_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2490_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2491_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2492_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2493_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2494_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2495_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2496_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2497_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2498_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2499_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2500_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2501_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2502_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2503_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2504_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2505_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2506_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2507_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2508_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2509_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2510_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2511_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2512_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2516_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2517_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2518_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2519_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2520_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2521_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2522_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2523_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2524_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2525_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2526_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2527_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2528_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2529_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2530_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2531_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2532_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2533_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2534_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2535_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2536_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2537_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2538_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2539_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2540_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2541_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2542_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2543_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2544_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2545_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2546_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2547_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2548_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2549_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2550_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2551_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/2552_tf_histo.msr create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-FC-E3p8keV-B10mT-Tscan.dat create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-FC-E3p8keV-B10mT-Tscan.db create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-FC-E3p8keV-B150mT-Tscan.dat create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-FC-E3p8keV-B150mT-Tscan.db create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-T120K-FC150mT-Escan.db create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-T30K-FC150mT-Escan.db create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-T5K-FC150mT-Escan.db create mode 100644 src/musredit_qt5/mupp/examples/YBCO-40nm-T60K-FC150mT-Escan.db create mode 100644 src/musredit_qt5/mupp/examples/field-vs-energy.txt create mode 100644 src/musredit_qt5/mupp/icons/document-open-dark.svg create mode 100644 src/musredit_qt5/mupp/icons/document-open-plain.svg create mode 100644 src/musredit_qt5/mupp/icons/mupp-dark.svg create mode 100644 src/musredit_qt5/mupp/icons/mupp-plain.svg create mode 100644 src/musredit_qt5/mupp/icons/mupp.icns create mode 100644 src/musredit_qt5/mupp/mupp.cpp create mode 100644 src/musredit_qt5/mupp/mupp.h create mode 100644 src/musredit_qt5/mupp/mupp.qrc create mode 100644 src/musredit_qt5/mupp/mupp_startup.xml.in create mode 100644 src/musredit_qt5/mupp/plotter/CMakeLists.txt create mode 100644 src/musredit_qt5/mupp/plotter/PMuppCanvas.cpp create mode 100644 src/musredit_qt5/mupp/plotter/PMuppCanvas.h create mode 100644 src/musredit_qt5/mupp/plotter/PMuppCanvasLinkDef.h create mode 100644 src/musredit_qt5/mupp/plotter/PMuppStartupHandler.cpp create mode 100644 src/musredit_qt5/mupp/plotter/PMuppStartupHandler.h create mode 100644 src/musredit_qt5/mupp/plotter/PMuppStartupHandlerLinkDef.h create mode 100644 src/musredit_qt5/mupp/plotter/mupp_plot.cpp create mode 100644 src/musredit_qt5/mupp/plotter/mupp_plot.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 04cea31c..d3e23903 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # - musrfit cmake_minimum_required(VERSION 3.6) -project(musrfit VERSION 1.3.0 LANGUAGES C CXX) +project(musrfit VERSION 1.4.0 LANGUAGES C CXX) #--- musrfit specific options ------------------------------------------------- option(nexus "build optional NeXus support. Needed for ISIS" OFF) diff --git a/src/musredit_qt5/CMakeLists.txt b/src/musredit_qt5/CMakeLists.txt index a5c666ee..1d5d38f6 100644 --- a/src/musredit_qt5/CMakeLists.txt +++ b/src/musredit_qt5/CMakeLists.txt @@ -9,3 +9,4 @@ configure_file( add_subdirectory(musredit) add_subdirectory(musrStep) add_subdirectory(musrWiz) +add_subdirectory(mupp) diff --git a/src/musredit_qt5/mupp/CMakeLists.txt b/src/musredit_qt5/mupp/CMakeLists.txt new file mode 100644 index 00000000..935d019c --- /dev/null +++ b/src/musredit_qt5/mupp/CMakeLists.txt @@ -0,0 +1,88 @@ +#--- mupp for Qt > 5.0 -------------------------------------------------------- + +#--- Find includes in corresponding build directories ------------------------- +set(CMAKE_INCLUDE_CURRENT_DIR ON) +#--- instruct CMake to run moc automatically when needed ---------------------- +set(CMAKE_AUTOMOC ON) + +#--- define mupp version ------------------------------------------------------ +set(mupp_VERSION 0.9.0) + +#--- mupp_version.h generation - START ---------------------------------------- +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_mupp_version_file.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/configure_mupp_version_file.cmake + @ONLY +) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mupp_version.h + COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/configure_mupp_version_file.cmake + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/configure_mupp_version_file.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mupp_version.h.in + COMMENT "Configuring mupp_version.h" + VERBATIM +) + +add_custom_target( + configure_mupp_version ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/mupp_version.h +) +#--- mupp_version.h generation - END ------------------------------------------ + +add_subdirectory(plotter) + +qt5_add_resources(qrc_mupp.cpp mupp.qrc) +set_property(SOURCE qrc_mupp.cpp PROPERTY SKIP_AUTOMOC ON) # needed for cmake 3.x + +set(GENERATED_HEADER_FILES + mupp_version.h +) +set_property(SOURCE mupp_version.h PROPERTY SKIP_AUTOMOC ON) # needed for cmake 3.x + +set(SOURCE_FILES + mupp.cpp + PmuppAdmin.cpp + Pmupp.cpp + PmuppScript.cpp + PmuppGui.cpp +) + +if (APPLE) + set(RESOURCE_FILES icons/mupp.icns) + add_executable(mupp + MACOSX_BUNDLE ${GENERATED_HEADER_FILES} ${SOURCE_FILES} + qrc_mupp.cpp ${RESOURCE_FILES} + ) +else (APPLE) + add_executable(mupp ${GENERATED_HEADER_FILES} ${SOURCE_FILES} qrc_mupp.cpp) +endif (APPLE) + +#--- use the Widgets and XML modules from Qt5 --------------------------------- +target_link_libraries(mupp Qt5::Widgets Qt5::Xml) + +#--- if macOS make an app rather than just a command line executable ---------- +set_target_properties(mupp PROPERTIES + VERSION ${mupp_VERSION} +) +if (APPLE) + set_target_properties(mupp PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_BUNDLE_NAME "mupp" + MACOSX_BUNDLE_INFO_STRING "mupp is used to plot parameters from musrfit collections." + MACOSX_BUNDLE_ICON_FILE "mupp.icns" + MACOSX_BUNDLE_LONG_VERSION_STRING "${mupp_VERSION}" + MACOSX_FRAMEWORK_IDENTIFIER ch.psi.mupp + MACOSX_BUNDLE_COPYRIGHT "Andreas Suter" + RESOURCE "${RESOURCE_FILES}" + ) +endif (APPLE) + +#--- install ------------------------------------------------------------------ +if (APPLE) + install(TARGETS mupp BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}) +else (APPLE) + install(TARGETS mupp DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif (APPLE) diff --git a/src/musredit_qt5/mupp/Pmupp.cpp b/src/musredit_qt5/mupp/Pmupp.cpp new file mode 100644 index 00000000..3501835f --- /dev/null +++ b/src/musredit_qt5/mupp/Pmupp.cpp @@ -0,0 +1,1000 @@ +/*************************************************************************** + + Pmupp.cpp + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +***************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2007-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * 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. * + ***************************************************************************/ + +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Pmupp.h" + +#define PMUPP_UNDEF -1 +#define PMUPP_VALUE 0 +#define PMUPP_POSNEGERR 1 +#define PMUPP_POSERR 2 +#define PMUPP_NEGERR 3 +#define PMUPP_RUN 4 + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + * @brief PmuppParam::PmuppParam + */ +PmuppParam::PmuppParam() { + ResetParam(); +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppParam::PmuppParam + * @param name + * @param param + * @param posErr + */ +PmuppParam::PmuppParam(QString name, double param, double posErr) +{ + SetParam(name, param, posErr); +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppParam::PmuppParam + * @param name + * @param param + * @param posErr + * @param negErr + */ +PmuppParam::PmuppParam(QString name, double param, double posErr, double negErr) +{ + SetParam(name, param, posErr, negErr); +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppParam::ResetParam + */ +void PmuppParam::ResetParam() +{ + fName = ""; + fValue = MUPP_UNDEF; + fPosErr = MUPP_UNDEF; + fNegErr = MUPP_UNDEF; +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppParam::SetParam + * @param name + * @param param + * @param posErr + */ +void PmuppParam::SetParam(QString name, double param, double posErr) +{ + fName = name; + fValue = param; + fPosErr = posErr; +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppParam::SetParam + * @param name + * @param param + * @param posErr + * @param negErr + */ +void PmuppParam::SetParam(QString name, double param, double posErr, double negErr) +{ + fName = name; + fValue = param; + fPosErr = posErr; + fNegErr = negErr; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + * @brief PmuppRun::GetParam + * @param idx + * @return + */ +PmuppParam PmuppRun::GetParam(unsigned int idx) +{ + PmuppParam param; + + if (idx < (unsigned int)fParam.size()) + param = fParam[idx]; + + return param; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + * @brief PmuppCollection::GetRun + * @param idx + * @return + */ +PmuppRun PmuppCollection::GetRun(unsigned int idx) +{ + PmuppRun run; + + if (idx < (unsigned int)fRun.size()) + run = fRun[idx]; + + return run; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + * @brief PParamDataHandler::NewCollection + * @param name + */ +void PParamDataHandler::NewCollection(const QString name) +{ + PmuppCollection collection; + collection.SetName(name); + + fCollection.push_back(collection); +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::analyzeFileList + * @param fln + * @param collectionName + * @param arg + * @param workDir + * @return + */ +bool PParamDataHandler::analyzeFileList(const QStringList &fln, QString &collectionName, QStringList &arg, QString &workDir) +{ + // 1) check all the msr-files have the same structure: .msr with the same + // for all msr-files present. + QString ext(""); + QStringList run; + + QStringList tok; + int pos0=-1, pos1=-1; + QString flnCurrent(""), extCurrent(""), runStr(""); + bool ok; + + pos0 = fln[0].lastIndexOf("/"); + workDir = fln[0].left(pos0); + + for (int i=0; i and + pos0 = flnCurrent.indexOf("_"); + if (pos0 == -1) { + QMessageBox::critical(0, "ERROR", "msr-file name has a structure which cannot be handled.\n\ +It should be , where is the run number\n\ +and needs to start with a '_'."); + return false; + } + pos1 = flnCurrent.lastIndexOf("."); + if ((pos1 == -1) || (pos1 < pos0)) { + QMessageBox::critical(0, "ERROR", "msr-file name has a structure which cannot be handled.\n\ +It should be .msr, where is the run number\n\ +and needs to start with a '_'."); + return false; + } + + // get run number + runStr = flnCurrent.left(pos0); + runStr.toInt(&ok); // output not needed, only check that it is a number + if (!ok) { + QMessageBox::critical(0, "ERROR", QString("Found run number string '%1' which is not a number.").arg(runStr)); + return false; + } + run << runStr; + + // keep extension + if (i == 0) + ext = flnCurrent.mid(pos0, pos1-pos0); + else + extCurrent = flnCurrent.mid(pos0, pos1-pos0); + + // make sure all extensions are identical + if ((i>0) && (ext != extCurrent)) { + QMessageBox::critical(0, "ERROR", "Currently mixed msr-file extensions cannot be handled."); + return false; + } + } + + arg << "["; + for (int i=0; isetProcessEnvironment(env); + fProc->setWorkingDirectory(workDir); + fProc->start(cmd, arg); + if (!fProc->waitForFinished()) { + // error handling + QString msg(tr("Could not execute the output command: ")+cmd[0]); + QMessageBox::critical( 0, + tr("Fatal error"), + msg, + tr("Quit") ); + return false; + } + + // since the db-file should now be present, just load it + collection = ReadDbFile(pathName, valid); + if (!valid) { + cerr << endl; + cerr << "----" << endl; + cerr << "**ERROR** read db-file failure (" << pathName.toLatin1().data() << "." << endl; + cerr << "----" << endl; + return false; + } + collName.remove(".db"); + collection.SetPathName(pathName); + collection.SetName(collName); + fCollection.push_back(collection); + } else { // db-, dat-file list + for (int i=0; i headerInfo; + QVector headerCode; // 0=value, 1=pos/neg err, 2=pos err, 3=neg err, 4=run number + int code=PMUPP_UNDEF; + for (int i=0; i=fCollection.size())) { + valid = false; + return collection; + } + + return fCollection[idx]; +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::GetCollection + * @param idx + * @return + */ +PmuppCollection *PParamDataHandler::GetCollection(const int idx) +{ + if ((idx<0) || (idx>=fCollection.size())) { + return 0; + } + + return &fCollection[idx]; +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::GetCollection + * @param name + * @param valid + * @return + */ +PmuppCollection PParamDataHandler::GetCollection(const QString name, bool &valid) +{ + valid = true; + PmuppCollection collection; + + int idx=-1; + for (int i=0; i= 0) && (idx < fCollection.size())) + name = fCollection[idx].GetName(); + + return name; +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::GetValues + * @param collName + * @param paramName + * @return + */ +QVector PParamDataHandler::GetValues(QString collName, QString paramName) +{ + QVector data; + + // find collection with correct name + int idx=-1; + for (int i=0; i PParamDataHandler::GetPosErr(QString collName, QString paramName) +{ + QVector data; + + // find collection with correct name + int idx=-1; + for (int i=0; i PParamDataHandler::GetNegErr(QString collName, QString paramName) +{ + QVector data; + + // find collection with correct name + int idx=-1; + for (int i=0; i= fCollection.size()) + return; + + fCollection.replace(idx, coll); +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::Dump + */ +void PParamDataHandler::Dump() +{ + PmuppRun run; + PmuppParam param; + + for (int i=0; i +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" << endl; + cout << "debug> collection name: " << fCollection[i].GetName().toLatin1().data() << endl; + cout << "debug> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" << endl; + for (int j=0; j ----------------------------------" << endl; + run = fCollection[i].GetRun(j); + cout << "debug>> run number: " << run.GetNumber() << endl; + cout << "debug>> run name : " << run.GetName().toLatin1().data() << endl; + cout << "debug>> ---------------------------------" << endl; + for (int k=0; k>> " << param.GetName().toLatin1().data() << ": " << param.GetValue() << " -+ " << param.GetNegErr() << " / " << param.GetPosErr() << endl; + } + } + } +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::readFromStdOut + */ +void PParamDataHandler::readFromStdOut() +{ + qInfo() << fProc->readAllStandardOutput(); +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::readFromStdErr + */ +void PParamDataHandler::readFromStdErr() +{ + qInfo() << fProc->readAllStandardError(); +} + +//-------------------------------------------------------------------------- +/** + * @brief PParamDataHandler::processDone + * @param exitCode + * @param exitStatus + */ +void PParamDataHandler::processDone(int exitCode, QProcess::ExitStatus exitStatus) +{ + qInfo() << "in processDone()"; + if ((exitStatus == QProcess::CrashExit) && (exitCode != 0)) + qInfo() << "**ERROR** processDone: exitCode = " << exitCode << endl; +} diff --git a/src/musredit_qt5/mupp/Pmupp.h b/src/musredit_qt5/mupp/Pmupp.h new file mode 100644 index 00000000..524a9012 --- /dev/null +++ b/src/musredit_qt5/mupp/Pmupp.h @@ -0,0 +1,151 @@ +/*************************************************************************** + + Pmupp.h + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +***************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2007-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * 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. * + ***************************************************************************/ + +#ifndef _PMUPP_H_ +#define _PMUPP_H_ + +#include +#include +#include +#include +#include + +#define MUPP_UNDEF 1.0e99 + +class PmuppParam { + public: + PmuppParam(); + PmuppParam(QString name, double param, double posErr); + PmuppParam(QString name, double param, double posErr, double negErr); + + void ResetParam(); + void SetParam(QString name, double param, double posErr); + void SetParam(QString name, double param, double posErr, double negErr); + void SetName(QString name) { fName = name; } + void SetValue(double dval) { fValue = dval; } + void SetPosErr(double dval) { fPosErr = dval; } + void SetNegErr(double dval) { fNegErr = dval; } + + QString GetName() { return fName; } + double GetValue() { return fValue; } + double GetPosErr() { return fPosErr; } + double GetNegErr() { return fNegErr; } + + private: + QString fName; + double fValue; + double fPosErr; + double fNegErr; +}; + +class PmuppRun { + public: + PmuppRun() { fNumber = -1; fName=""; fParam.clear(); } + ~PmuppRun() { fNumber = -1; fName=""; fParam.clear(); } + + void Clear() { fNumber = -1; fName=""; fParam.clear(); } + void SetName(QString name) { fName = name; } + void SetNumber(int ival) { fNumber = ival; } + void AddParam(PmuppParam param) { fParam.push_back(param); } + + int GetNumber() { return fNumber; } + QString GetName() { return fName; } + int GetNoOfParam() { return fParam.size(); } + PmuppParam GetParam(unsigned int idx); + + private: + int fNumber; ///< run number + QString fName; + QVector fParam; +}; + +class PmuppCollection { + public: + PmuppCollection() { fPathName=""; fName = ""; fRun.clear(); } + + void SetPathName(QString pathName) { fPathName = pathName; } + void SetName (QString name) { fName = name; } + void AddRun(PmuppRun run) { fRun.push_back(run); } + + QString GetPathName() { return fPathName; } + QString GetName() { return fName; } + int GetNoOfRuns() { return fRun.size(); } + PmuppRun GetRun(unsigned int idx); + + private: + QString fPathName; + QString fName; + QVector fRun; +}; + +class PParamDataHandler : public QObject { + Q_OBJECT + + public: + PParamDataHandler() {} + + int GetNoOfCollections() { return fCollection.size(); } + void NewCollection(const QString name); + + bool ReadParamFile(const QStringList fln); + PmuppCollection ReadDbFile(const QString fln, bool &valid); + PmuppCollection ReadColumnParamFile(const QString fln, bool &valid); + + PmuppCollection GetCollection(const int idx, bool &valid); + PmuppCollection GetCollection(const QString name, bool &valid); + PmuppCollection *GetCollection(const int idx); + PmuppCollection *GetCollection(const QString name); + int GetCollectionIndex(const QString name); + QString GetCollectionName(const int idx); + + QVector GetValues(QString collName, QString paramName); + QVector GetPosErr(QString collName, QString paramName); + QVector GetNegErr(QString collName, QString paramName); + + void RemoveCollection(QString name); + void ReplaceCollection(PmuppCollection coll, int idx); + + void Dump(); + + signals: + void newData(); + + private: + QProcess *fProc; + QVector fCollection; + + bool analyzeFileList(const QStringList &fln, QString &collectionName, QStringList &arg, QString &workDir); + + private slots: + void readFromStdOut(); + void readFromStdErr(); + void processDone(int, QProcess::ExitStatus); +}; + +#endif // _PMUPP_H_ diff --git a/src/musredit_qt5/mupp/PmuppAdmin.cpp b/src/musredit_qt5/mupp/PmuppAdmin.cpp new file mode 100644 index 00000000..0e9e9493 --- /dev/null +++ b/src/musredit_qt5/mupp/PmuppAdmin.cpp @@ -0,0 +1,500 @@ +/**************************************************************************** + + PmuppAdmin.cpp + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +*****************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2010-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * 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. * + ***************************************************************************/ + +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "PmuppAdmin.h" + +//-------------------------------------------------------------------------- +// implementation of PmuppColor class +//-------------------------------------------------------------------------- +/** + * @brief PmuppColor::PmuppColor + */ +PmuppColor::PmuppColor() +{ + fName = "UnDef"; + fRed = -1; + fGreen = -1; + fBlue = -1; +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppColor::setRGB + * @param r + * @param g + * @param b + */ +void PmuppColor::setRGB(const int r, const int g, const int b) +{ + if ((r>=0) && (r<=255)) + fRed = r; + if ((g>=0) && (g<=255)) + fGreen = g; + if ((b>=0) && (b<=255)) + fBlue = b; +} + +//-------------------------------------------------------------------------- +// implementation of PmuppAdminXMLParser class +//-------------------------------------------------------------------------- +/** + *

XML Parser class for the mupp administration file. + * + * \param admin pointer to an admin class instance. + */ +PmuppAdminXMLParser::PmuppAdminXMLParser(PmuppAdmin *admin) : fAdmin(admin) +{ + fKeyWord = eEmpty; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called at the beginning of the XML parsing process. + */ +bool PmuppAdminXMLParser::startDocument() +{ + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called when a new XML tag is found. Here it is used + * to set a tag for filtering afterwards the content. + * + * \param qName name of the XML tag. + */ +bool PmuppAdminXMLParser::startElement( const QString&, const QString&, + const QString& qName, + const QXmlAttributes& ) +{ + if (qName == "marker") { + fKeyWord = eMarker; + } else if (qName == "color") { + fKeyWord = eColor; + } + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called when the end XML tag is found. It is used to + * put the filtering tag to 'empty'. It also resets the fFunc flag in case + * the entry was a theory function. + * + * \param qName name of the element. + */ +bool PmuppAdminXMLParser::endElement( const QString&, const QString&, const QString& ) +{ + fKeyWord = eEmpty; + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

This routine delivers the content of an XML tag. It fills the + * content into the load data structure. + * + * \param str keeps the content of the XML tag. + */ +bool PmuppAdminXMLParser::characters(const QString& str) +{ + bool ok; + int ival, r, g, b; + double dval; + QString name(""); + QStringList tok; + + switch (fKeyWord) { + case eMarker: + tok = str.split(",", QString::SkipEmptyParts); + + if ((tok.count() != 1) && (tok.count() != 2)) { + return false; + } + + ival = tok[0].toInt(&ok); + if (!ok) + return false; + + dval = 1.0; + if (tok.count() == 2) { + dval = tok[1].toDouble(&ok); + if (!ok) + return false; + } + fAdmin->setMarker(ival, dval); + break; + case eColor: + tok = str.split(",", QString::SkipEmptyParts); + + if ((tok.count() != 3) && (tok.count() != 4)) { + return false; + } + ival = tok[0].toInt(&ok); + if (!ok) + return false; + r = ival; + ival = tok[1].toInt(&ok); + if (!ok) + return false; + g = ival; + ival = tok[2].toInt(&ok); + if (!ok) + return false; + b = ival; + if (tok.count() == 4) + name = tok[3]; + fAdmin->setColor(r, g, b, name); + break; + default: + break; + } + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Called at the end of the XML parse process. It checks if default paths + * contain system variables, and if so expand them for the further use. + */ +bool PmuppAdminXMLParser::endDocument() +{ + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report XML warnings. + * + * \param exception holds the information of the XML warning + */ +bool PmuppAdminXMLParser::warning( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**WARNING** while parsing mupp_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**WARNING MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::warning(0, "WARNING", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report recoverable XML errors. + * + * \param exception holds the information of the XML recoverable errors. + */ +bool PmuppAdminXMLParser::error( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**ERROR** while parsing mupp_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**ERROR MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::critical(0, "ERROR", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report fatal XML errors. + * + * \param exception holds the information of the XML fatal errors. + */ +bool PmuppAdminXMLParser::fatalError( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**FATAL ERROR** while parsing mupp_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**FATAL ERROR MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::critical(0, "FATAL ERROR", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//-------------------------------------------------------------------------- +// implementation of PmuppAdmin class +//-------------------------------------------------------------------------- +/** + *

Initializes that PmuppAdmin object, and calls the XML parser which feeds + * the object variables. + */ +PmuppAdmin::PmuppAdmin() : QObject() +{ + // XML Parser part + // 1st: check local directory + QString path = QString("./"); + QString fln = QString("mupp_startup.xml"); + QString pathFln = path + fln; + QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); + if (!QFile::exists(pathFln)) { + // 2nd: check $HOME/.musrfit/mupp/mupp_startup.xml + path = procEnv.value("HOME", ""); + pathFln = path + "/.musrfit/mupp/" + fln; + if (!QFile::exists(pathFln)) { + // 3rd: check $MUSRFITPATH/mupp_startup.xml + path = procEnv.value("MUSRFITPATH", ""); + pathFln = path + "/" + fln; + if (!QFile::exists(pathFln)) { + // 4th: check $ROOTSYS/bin/mupp_startup.xml + path = procEnv.value("ROOTSYS", ""); + pathFln = path + "/bin/" + fln; + if (!QFile::exists(pathFln)) { + // 5th: not found anywhere hence create it + path = procEnv.value("HOME", ""); + pathFln = path + "/.musrfit/mupp/" + fln; + createMuppStartupFile(); + } + } + } + } + + if (QFile::exists(pathFln)) { // administration file present + PmuppAdminXMLParser handler(this); + QFile xmlFile(pathFln); + QXmlInputSource source( &xmlFile ); + QXmlSimpleReader reader; + reader.setContentHandler( &handler ); + reader.setErrorHandler( &handler ); + if (!reader.parse( source )) { + QMessageBox::critical(0, "ERROR", + "Error parsing mupp_startup.xml settings file.\nProbably a few things will not work porperly.\nPlease fix this first.", + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + } else { + QMessageBox::critical(0, "ERROR", + "Couldn't find the mupp_startup.xml settings file.\nProbably a few things will not work porperly.\nPlease fix this first.", + QMessageBox::Ok, QMessageBox::NoButton); + return; + } +} + +//-------------------------------------------------------------------------- +/** + *

Destructor + */ +PmuppAdmin::~PmuppAdmin() +{ + // nothing to be done for now +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppAdmin::getMarker + * @param idx + * @return + */ +PmuppMarker PmuppAdmin::getMarker(int idx) { + PmuppMarker marker; + + if (idx >= fMarker.size()) + return marker; + + return fMarker[idx]; +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppAdmin::getColor + * @param name + * @param r + * @param g + * @param b + */ +void PmuppAdmin::getColor(QString name, int &r, int &g, int &b) +{ + int idx=-1; + for (int i=0; ifColor.size())) { + r = -1; + g = -1; + b = -1; + } else { + fColor[idx].getRGB(r, g, b); + } +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppAdmin::setMaker + * @param marker + * @param size + */ +void PmuppAdmin::setMarker(int marker, double size) +{ + PmuppMarker markerObj; + + // make sure marker is in proper range + if ((marker<1) || (marker>49)) { + QMessageBox::warning(0, "WARNING", QString("Found Marker (%1) not in the expected range.\nWill ignore it.").arg(marker)); + return; + } + markerObj.setMarker(marker); + markerObj.setMarkerSize(size); + + fMarker.push_back(markerObj); +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppAdmin::setColor + * @param r + * @param g + * @param b + * @param name + */ +void PmuppAdmin::setColor(int r, int g, int b, QString name) +{ + if (((r<0) || (r>255)) || + ((g<0) || (g>255)) || + ((b<0) || (b>255))) { + QMessageBox::warning(0, "WARNING", QString("Found Color (%1,%2,%3) not in the expected range.\nWill ignore it.").arg(r).arg(g).arg(b)); + return; + } + + PmuppColor color; + color.setName(name); + color.setRGB(r,g,b); + + fColor.push_back(color); +} + +//-------------------------------------------------------------------------- +/** + * @brief PmuppAdmin::createMuppStartupFile + */ +void PmuppAdmin::createMuppStartupFile() +{ + // get $HOME + QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); + QString pathName = procEnv.value("HOME", ""); + pathName += "/.musrfit/mupp"; + + // check if the directory $HOME/.musrfit/mupp exists if not create it + QDir dir(pathName); + if (!dir.exists()) { + // directory $HOME/.musrfit/mupp does not exist hence create it + dir.mkpath(pathName); + } + + // create default mupp_startup.xml file in $HOME/.musrfit/mupp + pathName += "/mupp_startup.xml"; + + // get the default mupp_startup.xml.in from the internal resources + QFile fres(":/mupp_startup.xml.in"); + if (!fres.exists()) { + QString msg = QString("Neither couldn't find nor create mupp_startup.xml. Things are likely not to work."); + QMessageBox::critical(0, "ERROR", msg); + return; + } + + if (!fres.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString msg = QString("Couldn't open internal resource file mupp_startup.xml.in. Things are likely not to work."); + QMessageBox::critical(0, "ERROR", msg); + return; + } + // text stream for fres + QTextStream fin(&fres); + + // mupp_startup.xml default file + QFile file(pathName); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + return; + + // text stream for file + QTextStream fout(&file); + + QString line; + while (!fin.atEnd()) { + line = fin.readLine(); + fout << line << endl; + } + + file.close(); + fres.close(); +} + +//-------------------------------------------------------------------------- +// END +//-------------------------------------------------------------------------- diff --git a/src/musredit_qt5/mupp/PmuppAdmin.h b/src/musredit_qt5/mupp/PmuppAdmin.h new file mode 100644 index 00000000..46f440b5 --- /dev/null +++ b/src/musredit_qt5/mupp/PmuppAdmin.h @@ -0,0 +1,151 @@ +/**************************************************************************** + + PmuppAdmin.h + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +*****************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2010-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * 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. * + ***************************************************************************/ + +#ifndef _PMUPPADMIN_H_ +#define _PMUPPADMIN_H_ + +#include +#include +#include +#include +#include + +class PmuppAdmin; + +//--------------------------------------------------------------------------- +/** + * @brief The PmuppColor class + */ +class PmuppColor { + public: + PmuppColor(); + virtual ~PmuppColor() {} + + QString getName() { return fName; } + void getRGB(int &r, int &g, int &b) { r=fRed; g=fGreen; b=fBlue; } + + void setName(const QString name) { fName = name; } + void setRGB(const int r, const int g, const int b); + + private: + QString fName; + int fRed; + int fGreen; + int fBlue; +}; + +//--------------------------------------------------------------------------- +/** + * @brief The PmuppMarker class + */ +class PmuppMarker { + public: + PmuppMarker() { fMarker = 20; fMarkerSize = 1.0; } + PmuppMarker(int marker, double size) : fMarker(marker), fMarkerSize(size) {} + virtual ~PmuppMarker() {} + + void getMarker(int &marker, double &size) { marker = fMarker; size = fMarkerSize; } + int getMarker() { return fMarker; } + double getMarkerSize() { return fMarkerSize; } + + void setMarker(int marker) { fMarker = marker; } + void setMarkerSize(double size) { fMarkerSize = size; } + + private: + int fMarker; + double fMarkerSize; +}; + +//--------------------------------------------------------------------------- +/** + * PAdminXMLParser is an XML parser class used to handle the mupp startup + * XML-file called mupp_startup.xml. This startup file contains + * necessary informations about executable pathes, online help informations, + * default font sizes, etc. + */ +class PmuppAdminXMLParser : public QXmlDefaultHandler +{ + public: + PmuppAdminXMLParser(PmuppAdmin*); + virtual ~PmuppAdminXMLParser() {} + + private: + enum EAdminKeyWords {eEmpty, eMarker, eColor}; + + bool startDocument(); + bool startElement( const QString&, const QString&, const QString& , + const QXmlAttributes& ); + bool endElement( const QString&, const QString&, const QString& ); + + bool characters(const QString&); + bool endDocument(); + + bool warning( const QXmlParseException & exception ); + bool error( const QXmlParseException & exception ); + bool fatalError( const QXmlParseException & exception ); + + EAdminKeyWords fKeyWord; ///< key word tag to know how to handle the content + PmuppAdmin *fAdmin; ///< a pointer to the main administration class object +}; + +//--------------------------------------------------------------------------- +/** + * The PMuppAdmin class is handling the informations contained in the XML startup file, + * mupp_startup.xml. This startup file contains + * necessary informations like marker style, marker color, etc. The XML parsing is done + * with the help of the PmuppAdminXMLParser class. + */ +class PmuppAdmin : public QObject +{ + public: + PmuppAdmin(); + virtual ~PmuppAdmin(); + + int getNoOfMarkers() { return fMarker.size(); } + QVector getMarkers() { return fMarker; } + PmuppMarker getMarker(int idx); + + int getNoOfColors() { return fColor.size(); } + QVector getColors() { return fColor; } + void getColor(QString name, int &r, int &g, int &b); + void getColor(int idx, int &r, int &g, int &b); + + void setMarker(int marker, double size); + void setColor(int r, int g, int b, QString name=""); + + private: + friend class PmuppAdminXMLParser; + + QVector fMarker; + QVector fColor; + + void createMuppStartupFile(); ///< create default mupp_startup.xml +}; + +#endif // _PMUPPADMIN_H_ diff --git a/src/musredit_qt5/mupp/PmuppGui.cpp b/src/musredit_qt5/mupp/PmuppGui.cpp new file mode 100644 index 00000000..fa3e1480 --- /dev/null +++ b/src/musredit_qt5/mupp/PmuppGui.cpp @@ -0,0 +1,1990 @@ +/*************************************************************************** + + PmuppGui.cpp + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +***************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2007-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * 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. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mupp_version.h" +#include "PmuppGui.h" + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::init + */ +void PmuppXY::init() +{ + fCollectionTag = -1; + fXlabel = ""; + fYlabel.clear(); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::setYlabel + * @param idx + * @param str + */ +void PmuppXY::setYlabel(int idx, QString str) +{ + if (idx >= fYlabel.size()) + return; + + fYlabel[idx] = str; +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::removeYlabel + * @param idx + */ +void PmuppXY::removeYlabel(int idx) +{ + if (idx >= fYlabel.size()) + return; + + fYlabel.remove(idx); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::removeYlabel + * @param str + */ +void PmuppXY::removeYlabel(QString str) +{ + for (int i=0; i= fYlabel.size()) + return QString(""); + + return fYlabel[idx]; +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::getXlabelIdx + * @return + */ +int PmuppXY::getXlabelIdx() +{ + QString str = fXlabel; + + // remove trailing '-)' + int idx = fXlabel.lastIndexOf("-)"); + if (idx == -1) + return -1; + str.remove(idx, str.length()-idx); + + // remove everything up to '(-' + idx = fXlabel.indexOf("(-"); + if (idx == -1) + return -1; + idx += 2; + str.remove(0, idx); + + bool ok; + idx = str.toInt(&ok); + if (!ok) + return -1; + + return idx; +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppXY::getYlabelIdx + * @param idx + * @return + */ +int PmuppXY::getYlabelIdx(int idx) +{ + if (idx >= fYlabel.size()) + return -1; + + QString str = fYlabel[idx]; + + // remove trailing '-)' + int iidx = fXlabel.lastIndexOf("-)"); + if (iidx == -1) + return -1; + str.remove(iidx, str.length()-iidx); + + // remove everything up to '(-' + iidx = fXlabel.indexOf("(-"); + if (iidx == -1) + return -1; + iidx += 2; + str.remove(0, iidx); + + bool ok; + iidx = str.toInt(&ok); + if (!ok) + return -1; + + return iidx; +} + +//---------------------------------------------------------------------------------------------------- +/** + *

Constructor + * + * \param fln file names to be loaded + * \param parent pointer to the parent object + * \param f qt windows flags + */ +PmuppGui::PmuppGui( QStringList fln, QWidget *parent, Qt::WindowFlags f ) + : QMainWindow( parent, f ) +{ + QDateTime dt = QDateTime::currentDateTime(); + fDatime = dt.toTime_t(); + + fMuppPlot = 0; + + fMacroPath = QString("./"); + fMacroName = QString(""); + + readCmdHistory(); + + fAdmin = new PmuppAdmin(); + + fParamDataHandler = new PParamDataHandler(); + bool dataAtStartup = false; + if (fln.size() > 0) { + if (fln[0].contains(".msr")) { + // get collection Name + QString collName = QString("collName0"); + fParamDataHandler->NewCollection(collName); + } + if (!fParamDataHandler->ReadParamFile(fln)) { + // parameter file(s) is/are not valid + } else { + dataAtStartup = true; // delay to deal with the data sets until the GUI is ready to do so + } + } + + getTheme(); + + QString iconName(""); + if (fDarkTheme) + iconName = QString(":/icons/mupp-dark.svg"); + else + iconName = QString(":/icons/mupp-plain.svg"); + setWindowIcon( QIcon( QPixmap(iconName) ) ); + + // setup menus + setupFileActions(); + setupToolActions(); + setupHelpActions(); + + // create central widget + fCentralWidget = new QWidget(this); + + // setup widgets + fBoxLayout_Main = new QBoxLayout(QBoxLayout::TopToBottom); + fBoxLayout_Main->setGeometry(QRect(10, 40, 600, 400)); + + fBoxLayout_Top = new QBoxLayout(QBoxLayout::LeftToRight); + fGridLayout_Left = new QGridLayout(); + fGridLayout_Right = new QGridLayout(); + fBoxLayout_Cmd = new QBoxLayout(QBoxLayout::LeftToRight); + + // label for the collection/parameter list widgets + fColLabel = new QLabel(this); + fColLabel->setText("Collection -> Parameter"); + fColLabel->setMaximumHeight(15); + + // central widget for the collection/parameter list widgets + fColParamSplitter = new QSplitter(Qt::Horizontal, this); + fColParamSplitter->setMinimumSize(550,330); + + fColList = new QListWidget(this); + fColList->setSelectionMode(QAbstractItemView::ExtendedSelection); + + fParamList = new QListWidget(this); + // the next two lines enable drag and drop facility (drag) + fParamList->setSelectionMode(QAbstractItemView::SingleSelection); + fParamList->setDragEnabled(true); + + fColParamSplitter->addWidget(fColList); + fColParamSplitter->addWidget(fParamList); + + fRemoveCollection = new QPushButton("Remove Collection", this); + fRefreshCollection = new QPushButton("Refresh Collection", this); + + fGridLayout_Left->addWidget(fColLabel, 1, 1, 1, 2); + fGridLayout_Left->addWidget(fColParamSplitter, 2, 1, 1, 2); + fGridLayout_Left->addWidget(fRemoveCollection, 3, 1); + fGridLayout_Left->addWidget(fRefreshCollection, 3, 2); + + // X-axis + fXaxisLabel = new QLabel("x-axis"); + fViewX = new QListWidget(this); + // the next two lines enable drag and drop facility (copy drop) + fViewX->viewport()->setAcceptDrops(true); + fViewX->setDropIndicatorShown(true); + + fAddX = new QPushButton("add X", this); + fRemoveX = new QPushButton("remove X", this); + + // Y-axis + fYaxisLabel = new QLabel("y-axis"); + fViewY = new QListWidget(this); + // the next two lines enable drag and drop facility (copy drop) + fViewY->viewport()->setAcceptDrops(true); + fViewY->setDropIndicatorShown(true); + + fAddY = new QPushButton("add Y", this); + fRemoveY = new QPushButton("remove Y", this); + + // 2 column button's for the right grid + fAddDitto = new QPushButton("Add Ditto", this); + fPlot = new QPushButton("Plot", this); + + fGridLayout_Right->addWidget(fXaxisLabel, 1, 1); + fGridLayout_Right->addWidget(fYaxisLabel, 1, 2); + fGridLayout_Right->addWidget(fViewX, 2, 1); + fGridLayout_Right->addWidget(fViewY, 2, 2); + fGridLayout_Right->addWidget(fAddX, 3, 1); + fGridLayout_Right->addWidget(fAddY, 3, 2); + fGridLayout_Right->addWidget(fRemoveX, 4, 1); + fGridLayout_Right->addWidget(fRemoveY, 4, 2); + fGridLayout_Right->addWidget(fAddDitto, 5, 1, 1, 2); + fGridLayout_Right->addWidget(fPlot, 6, 1, 1, 2); + + fBoxLayout_Top->addLayout(fGridLayout_Left); + fBoxLayout_Top->addLayout(fGridLayout_Right); + + fCmdLine = new QLineEdit(this); + fCmdLine->installEventFilter(this); + fCmdLine->setText("$ "); + fCmdLine->setFocus(); // sets the keyboard focus + fExitButton = new QPushButton("E&xit", this); + + fBoxLayout_Cmd = new QBoxLayout(QBoxLayout::LeftToRight); + fBoxLayout_Cmd->addWidget(fCmdLine); + fBoxLayout_Cmd->addWidget(fExitButton); + + QFrame* hline = new QFrame(); + hline->setFrameShape(QFrame::HLine); + hline->setFrameShadow(QFrame::Sunken); + + fBoxLayout_Main->addLayout(fBoxLayout_Top); + fBoxLayout_Main->addWidget(hline); + fBoxLayout_Main->addLayout(fBoxLayout_Cmd); + + // establish all the necessary signal/slots + connect(fRefreshCollection, SIGNAL( pressed() ), this, SLOT( refresh() )); + connect(fRemoveCollection, SIGNAL( pressed() ), this, SLOT( remove() )); + connect(fAddX, SIGNAL( pressed() ), this, SLOT( addX() )); + connect(fAddY, SIGNAL( pressed() ), this, SLOT( addY() )); + connect(fRemoveX, SIGNAL( pressed() ), this, SLOT( removeX() )); + connect(fRemoveY, SIGNAL( pressed() ), this, SLOT( removeY() )); + connect(fAddDitto, SIGNAL( pressed() ), this, SLOT( addDitto() )); + connect(fPlot, SIGNAL( pressed()), this, SLOT( plot()) ); + connect(fCmdLine, SIGNAL ( returnPressed() ), this, SLOT( handleCmds() )); + connect(fExitButton, SIGNAL( pressed() ), this, SLOT( aboutToQuit() )); + + connect(fColList, SIGNAL( currentRowChanged(int) ), this, SLOT( updateParamList(int) )); + connect(fColList, SIGNAL( itemDoubleClicked(QListWidgetItem*) ), this, SLOT( editCollName(QListWidgetItem*) )); + + connect(fViewX, SIGNAL( currentRowChanged(int) ), this, SLOT( refreshY() )); + connect(fViewX, SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewX(QListWidgetItem*) )); + connect(fViewY, SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewY(QListWidgetItem*) )); + + // deal with parameter data specifics + if (dataAtStartup) + handleNewData(); + + connect(fParamDataHandler, SIGNAL( newData() ), this, SLOT( handleNewData() )); + + fCentralWidget->setLayout(fBoxLayout_Main); + setCentralWidget(fCentralWidget); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::~PmuppGui + */ +PmuppGui::~PmuppGui() +{ + // all relevant clean up job are done in ::aboutToQuit() +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::aboutToQuit + */ +void PmuppGui::aboutToQuit() +{ + // kill mupp_plot if active + if (fMuppPlot) { + if (fMuppPlot->state() != QProcess::NotRunning) { + fMuppPlot->terminate(); + } + } + + // remove message queue + key_t key; + int flags, msqid; + + // generate the ICP message queue key + key = ftok(QCoreApplication::applicationFilePath().toLatin1().data(), 1); + + if (key != -1) { + // set the necessary IPC message queue flags + flags = IPC_CREAT; + + // open the message queue + msqid = msgget(key, flags | S_IRUSR | S_IWUSR); + if (msqid != -1) { + if (msgctl(msqid, IPC_RMID, NULL) == -1) { + cerr << "**ERROR** couldn't removed the message queue (msqid=" << msqid << ")." << endl << endl; + } + } + } + + // clean up temporary plot files + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString pathName = QString("%1/.musrfit/mupp/_mupp_%2.dat").arg(env.value("HOME")).arg(fDatime); + pathName = QString("%1/.musrfit/mupp/_mupp_ftok.dat").arg(env.value("HOME")); + + // needed for clean up and to save the cmd history + writeCmdHistory(); + + if (fParamDataHandler) { + delete fParamDataHandler; + fParamDataHandler = 0; + } + + if (fAdmin) { + delete fAdmin; + fAdmin = 0; + } + + exit(0); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::setupFileActions + */ +void PmuppGui::setupFileActions() +{ + QToolBar *tb = new QToolBar( this ); + tb->setWindowTitle( "File Actions" ); + addToolBar( tb ); + + QMenu *menu = new QMenu( tr( "F&ile" ), this ); + menuBar()->addMenu( menu ); + + QAction *a; + + QString iconName(""); + if (fDarkTheme) + iconName = QString(":/icons/document-open-dark.svg"); + else + iconName = QString(":/icons/document-open-plain.svg"); + a = new QAction( QIcon( QPixmap(iconName) ), tr( "&Open..." ), this ); + a->setShortcut( tr("Ctrl+O") ); + a->setStatusTip( tr("Open a musrfit parameter file.") ); + connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) ); + menu->addAction(a); + if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu) + iconName = QString(":/icons/document-open-plain.svg"); + a = new QAction( QIcon( QPixmap(iconName) ), tr( "&New..." ), this ); + connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) ); + } + tb->addAction(a); + + a = new QAction( tr( "E&xit" ), this ); + a->setShortcut( tr("Ctrl+Q") ); + a->setStatusTip( tr("Exit Program") ); + connect( a, SIGNAL( triggered() ), this, SLOT( fileExit() ) ); + menu->addAction(a); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::setupToolActions + */ +void PmuppGui::setupToolActions() +{ + QMenu *menu = new QMenu( tr( "&Tools" ), this ); + menuBar()->addMenu( menu ); + + QAction *a; + + a = new QAction(tr( "Plot ..." ), this ); + a->setStatusTip( tr("Plot x/y parameters") ); + connect( a, SIGNAL( triggered() ), this, SLOT( plot() ) ); + menu->addAction(a); + + a = new QAction(tr( "Create ROOT Macro ..." ), this ); + a->setStatusTip( tr("Creates a ROOT Macro with the given x/y parameters") ); + connect( a, SIGNAL( triggered() ), this, SLOT( createMacro() ) ); + menu->addAction(a); + + menu->addSeparator(); + + a = new QAction(tr( "Dump Collections ..." ), this ); + a->setStatusTip( tr("Dump all collections") ); + connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpCollections() ) ); + menu->addAction(a); + + a = new QAction(tr( "Dump XY ..." ), this ); + a->setStatusTip( tr("Dump XY parameter list") ); + connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpXY() ) ); + menu->addAction(a); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::setupHelpActions + */ +void PmuppGui::setupHelpActions() +{ + QMenu *menu = new QMenu( tr( "&Help" ), this ); + menuBar()->addMenu( menu ); + + QAction *a; +/* + a = new QAction(tr( "Contents ..." ), this ); + a->setStatusTip( tr("Help Contents") ); + connect( a, SIGNAL( triggered() ), this, SLOT( helpContents() )); + menu->addAction(a); +*/ + + a = new QAction( tr( "Cmd's" ), this ); + a->setStatusTip( tr( "Lists the command line commands" ) ); + connect( a, SIGNAL( triggered() ), this, SLOT( helpCmds() )); + menu->addAction(a); + + a = new QAction( tr( "Author(s) ..." ), this ); + a->setStatusTip( tr( "About the Author(s)") ); + connect( a, SIGNAL( triggered() ), this, SLOT( helpAbout() )); + menu->addAction(a); + + a = new QAction( tr( "About Qt..." ), this ); + a->setStatusTip( tr( "Help About Qt") ); + connect( a, SIGNAL( triggered() ), this, SLOT( helpAboutQt() )); + menu->addAction(a); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::fileOpen + */ +void PmuppGui::fileOpen() +{ + QStringList list = QFileDialog::getOpenFileNames( + this, + "muSR Parameter Files", + "./", + "db-files (*.db);; All Params (*.msr *.db *.dat);; Msr-Files (*.msr);; dat-Files (*.dat);; All (*)"); + + if (list.count() == 0) + return; + + bool msrPresent = false; + bool dbPresent = false; + for (int i=0; iReadParamFile(list); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::fileExit + */ +void PmuppGui::fileExit() +{ + qApp->quit(); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::toolDump + */ +void PmuppGui::toolDumpCollections() +{ + if (fParamDataHandler->GetNoOfCollections()) { + fParamDataHandler->Dump(); + } else { + QMessageBox::warning(this, "dump collections", "no collections present"); + } +} + +//---------------------------------------------------------------------------------------------------- +void PmuppGui::toolDumpXY() +{ + if (fXY.size() > 0) { + for (int i=0; i<-><-><-><-><-><-><-><-><->"; + qInfo() << i << ": collection tag: " << fXY[i].getCollectionTag(); + qInfo() << " x-param: " << fXY[i].getXlabel(); + for (int j=0; jhelp: this help.
"\ + "exit/quit: close mupp.
"\ + "load: calls the open file dialog.
"\ + "dump collections: dumps all currently loaded collections.
"\ + "dump XY: dumps X/Y tree.
"\ + "refresh: refresh the currently selected collection.
"\ + "plot: plot the X/Y data.
"\ + "macro <fln>: saves the X/Y data as a ROOT macro (*.C).
"\ + "path <macroPath>: sets the path to the place where the macros will be saved.
"\ + "select collection <nn>: select collection in GUI.
"\ + "    <nn> is either the collection name or the row number.
"\ + "flush: flush the history buffer."); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::helpAbout + */ +void PmuppGui::helpAbout() +{ + QMessageBox::information(this, "about", QString("mupp: created by Andreas Suter.\nVersion: %1\nBranch: %2\nHash: %3").arg(MUPP_VERSION).arg(GIT_BRANCH).arg(GIT_COMMIT_HASH)); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::helpAboutQt + */ +void PmuppGui::helpAboutQt() +{ + QMessageBox::aboutQt(this); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::eventFilter + * @param o + * @param e + * @return + */ +bool PmuppGui::eventFilter(QObject *o, QEvent *e) +{ + static int idx = fCmdHistory.size(); + + if (e->type() == QEvent::KeyPress) { + QKeyEvent *k = static_cast(e); + int key = k->key(); + if (key == Qt::Key_Up) { + if (idx > 0) + idx--; + if (idx < fCmdHistory.size()) + fCmdLine->setText(fCmdHistory[idx]); + } else if (key == Qt::Key_Down) { + if (idx < fCmdHistory.size()) + idx++; + if (idx < fCmdHistory.size()) + fCmdLine->setText(fCmdHistory[idx]); + else + fCmdLine->setText("$ "); + } else if (key == Qt::Key_Return) { + QString cmd = fCmdLine->text(); + bool found = false; + for (int i=0; i= 50) + fCmdHistory.removeFirst(); + fCmdHistory.push_back(cmd); + } + } + return false; + } + + // make sure the base class can handle all the events not handled here + return QMainWindow::eventFilter(o, e); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::getTheme + */ +void PmuppGui::getTheme() +{ + fDarkTheme = false; // true if theme is dark + fDarkToolBarIcon = false; // needed for ubuntu dark since there the menu icons are dark, however the toolbar icons are plain! + + QString str = QIcon::themeName(); + + if (str.contains("dark", Qt::CaseInsensitive)) { + fDarkTheme = true; + if (str.contains("ubuntu", Qt::CaseInsensitive)) { + fDarkToolBarIcon = false; + } else { + fDarkToolBarIcon = true; + } + } +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::readCmdHistory + */ +void PmuppGui::readCmdHistory() +{ + QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); + QString home = procEnv.value("HOME", ""); + if (home.isEmpty()) + return; + + QString pathName = home + "/.musrfit/mupp/mupp_history.txt"; + + QFile file(pathName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + cerr << endl; + cerr << "***********" << endl; + cerr << "**WARNING** readCmdHistory(): couldn't open mupp_history.txt for reading ..." << endl;; + cerr << "***********" << endl; + return; + } + + QTextStream fin(&file); + + fCmdHistory.clear(); + QString line; + while (!fin.atEnd()) { + line = fin.readLine(); + if (line.startsWith("%") || line.isEmpty()) + continue; + fCmdHistory.push_back(line); + } +} + +//---------------------------------------------------------------------------------------------------- +void PmuppGui::writeCmdHistory() +{ + if (fCmdHistory.size() == 0) + return; + + QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); + QString home = procEnv.value("HOME", ""); + if (home.isEmpty()) + return; + + QString pathName = home + "/.musrfit/mupp/"; + QDir dir(pathName); + if (!dir.exists()) { + // directory $HOME/.musrfit/musredit does not exist hence create it + dir.mkpath(pathName); + } + pathName += "mupp_history.txt"; + + QFile file(pathName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + return; + + QTextStream fout(&file); + + // write header + QDateTime dt = QDateTime::currentDateTime(); + fout << "% mupp history file" << endl; + fout << "% " << dt.toString("HH:mm:ss - yy/MM/dd") << endl; + + // write history + for (int i=0; icurrentItem(); + if (item == 0) + return; + QString label = item->text(); + + QString pathName(""); + int collIdx=-1; + + for (int i=0; iGetNoOfCollections(); i++) { + if (fParamDataHandler->GetCollection(i)->GetName() == label) { // found collection + pathName = fParamDataHandler->GetCollection(i)->GetPathName(); + collIdx = i; + break; + } + } + + // re-load collection + PmuppCollection coll; + bool ok=false; + if (pathName.endsWith(".db")) { + coll = fParamDataHandler->ReadDbFile(pathName, ok); + if (!ok) { + QMessageBox::critical(this, "ERROR - REFRESH", + QString("Couldn't refresh %1\nFile corrupted?!").arg(fParamDataHandler->GetCollection(collIdx)->GetName())); + return; + } + } else if (pathName.endsWith(".dat")) { + coll = fParamDataHandler->ReadColumnParamFile(pathName, ok); + if (!ok) { + QMessageBox::critical(this, "ERROR - REFRESH", + QString("Couldn't refresh %1\nFile corrupted?!").arg(fParamDataHandler->GetCollection(collIdx)->GetName())); + return; + } + } else { + QMessageBox::critical(this, "ERROR - REFRESH", + QString("Couldn't refresh %1").arg(fParamDataHandler->GetCollection(collIdx)->GetName())); + return; + } + + QString collName = pathName; + int pos = collName.lastIndexOf("/"); + collName.remove(0, pos+1); + coll.SetName(collName); + coll.SetPathName(pathName); + fParamDataHandler->ReplaceCollection(coll, collIdx); + + // update the parameter list (GUI) + updateParamList(collIdx); + + // update XY list (GUI) + updateXYListGui(); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::remove + */ +void PmuppGui::remove() +{ + // get current collection + QListWidgetItem *item = fColList->currentItem(); + if (item == 0) + return; + + QString collName = item->text(); + + // remove it from the list widget but keep the index for further use + int idx = fColList->row(item); + fColList->removeItemWidget(item); + delete item; + + // remove it from the collection handler + fParamDataHandler->RemoveCollection(collName); + + // next it is necessary to update the XY-parameter list + updateXYList(fColList->currentRow()); + + // if there no collections left remove all the parameters from the X/Y list + if (fColList->count() == 0) { + fViewX->clear(); + fViewY->clear(); + return; + } + + // select the row before the delete one if possible + if (idx > 0) + idx -= 1; + fColList->setCurrentRow(idx, QItemSelectionModel::Select); + + // update the parameter list (GUI) + updateParamList(idx); + + // update XY list (GUI) + updateXYListGui(); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::addX + */ +void PmuppGui::addX() +{ + // get the parameter name from the parameter list widget + QListWidgetItem *item = fParamList->currentItem(); + if (item == 0) + return; + QString paramName = item->text(); + int idx = fColList->currentRow(); + QString xLabel = QString("%1 (-%2-)").arg(paramName).arg(idx); + + // check if it is not already present + for (int i=0; icount(); i++) { + if (fViewX->item(i)->text() == xLabel) + return; + } + + // set the parameter name on the view X list widget + fViewX->addItem(xLabel); + fViewX->setCurrentRow(fViewX->count()-1); + + // add the item to the XY list + PmuppXY xyItem; + xyItem.setCollectionTag(idx); + xyItem.setXlabel(xLabel); + + fXY.push_back(xyItem); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::addY + */ +void PmuppGui::addY() +{ + // get the parameter name from the parameter list widget + QListWidgetItem *item = fParamList->currentItem(); + if (item == 0) + return; + QString paramName = item->text(); + int idx = fColList->currentRow(); + QString yLabel = QString("%1 (-%2-)").arg(paramName).arg(idx); + + // make sure that any x-parameter selection is already present + if (fViewX->count() == 0) { + QMessageBox::warning(this, "**WARNING**", "It is compulsory to have at least one x-parameter set\nbefore trying to add a y-parameter."); + return; + } + + // check if collection of x- and y-parameter selection correspond + idx=getXlabelIndex(fViewX->currentItem()->text()); + if (idx == -1) + return; + if (fXY[idx].getCollectionTag() != fColList->currentRow()) { + QMessageBox::warning(this, "**WARNING**", "x/y parameters need to originate from the same collection."); + return; + } + + // check if it is not already present + for (int i=0; icount(); i++) { + if (fViewY->item(i)->text() == yLabel) + return; + } + + // set the parameter name on the view Y list widget + fViewY->addItem(yLabel); + + // add the item to the XY list + idx=getXlabelIndex(fViewX->currentItem()->text()); + if (idx == -1) + return; + + fXY[idx].addYlabel(yLabel); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::removeX + */ +void PmuppGui::removeX() +{ + QListWidgetItem *item = fViewX->currentItem(); + if (item == 0) + return; + + int idx=getXlabelIndex(item->text()); + if (idx == -1) + return; + fXY.remove(idx); + + fViewX->removeItemWidget(item); + delete item; +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::removeY + */ +void PmuppGui::removeY() +{ + QListWidgetItem *item = fViewY->currentItem(); + if (item == 0) + return; + + // find y in XY and remove it + QString xLabel = fViewX->currentItem()->text(); + QString yLabel = item->text(); + int idx = getXlabelIndex(xLabel); + if (idx == -1) + return; + fXY[idx].removeYlabel(yLabel); + + fViewY->removeItemWidget(item); + delete item; +} + + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::addDitto + */ +void PmuppGui::addDitto() +{ + if (fXY.size() == 0) { + QMessageBox::critical(this, "ERROR", "No x/y items present.\nTherefore nothing to be done."); + return; + } + + if (!allXYEqual()) { + QMessageBox::critical(this, "ERROR", "Multiple unequal sets of x/y items present.\nDo not know how to handle."); + return; + } + + // get the selected items from the collection + QList items = fColList->selectedItems(); + if (items.count() == 0) { // no selections present hence drop out + return; + } + + // verify that all selected items have corresponding x/y values + bool ok=false; + PmuppCollection muCol; + PmuppRun muRun; + for (int i=0; iGetCollection(items[i]->text(), ok); + if (!ok) + return; + muRun = muCol.GetRun(0); + // check x-values + if (!findValue(muRun, kXaxis)) + return; + // check y-values + if (!findValue(muRun, kYaxis)) + return; + } + + // populate all necessary x- and y-values for all selected collections + PmuppXY muXY = fXY[0]; + int idx; + for (int i=0; irow(items[i]); + if (indexAlreadyPresent(idx)) + continue; + replaceIndex(muXY, idx); + fXY.push_back(muXY); + // add x-axis view + fViewX->addItem(muXY.getXlabel()); + fViewX->setCurrentRow(fViewX->count()-1); + } + + // un-select the collecion list + fColList->clearSelection(); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PmuppGui::findValue + * @param run + * @param tag + * @return + */ +bool PmuppGui::findValue(PmuppRun &run, EAxis tag) +{ + bool result = false; + + if (tag == kXaxis) { + for (int i=0; i (-#-)' and + // all

: set the load path to . Bash variables like" << endl; + cout << " $HOME are accepted." << endl; + cout << " load : will load a collection . Currently *.db and *.dat" << endl; + cout << " are handled." << endl; + cout << " selectAll : will select all loaded collections. Thie means every plot" << endl; + cout << " of variable x/y will be carried out to ALL collections." << endl; + cout << " select : selects collection , where is either the number" << endl; + cout << " of the collections, or its name, e.g. " << endl; + cout << " select YBCO-40nm-T5K-FC150mT-Escan.db" << endl; + cout << " addX