##// END OF EJS Templates
Merge branch 'feature/CompilFlagServer' into develop
Alexandre Leroux -
r1155:2e3c32b33d04 merge
parent child
Show More
@@ -0,0 +1,35
1 #ifndef SCIQLOP_AMDASERVER_H
2 #define SCIQLOP_AMDASERVER_H
3
4 #include <QLoggingCategory>
5
6 #include <memory>
7
8 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaServer)
9
10 // Directive used to determine the active AMDA server
11 #ifndef SCIQLOP_AMDA_SERVER
12 #define SCIQLOP_AMDA_SERVER "default"
13 #endif
14
15 /**
16 * @brief The AmdaServer class represents the server used to retrieve AMDA data (singleton).
17 *
18 * The server instance is initialized at compile time, as defined by the AMDA_SERVER value.
19 */
20 class AmdaServer {
21 public:
22 /// @return the unique instance of the AMDA server
23 static AmdaServer &instance();
24
25 virtual ~AmdaServer() noexcept = default;
26
27 /// @return the name of the server
28 virtual QString name() const = 0;
29
30 /// @param properties used to generate url
31 /// @return the url of the server (used to retrieve data)
32 virtual QString url(const QVariantHash &properties = {}) const = 0;
33 };
34
35 #endif // SCIQLOP_AMDASERVER_H
@@ -0,0 +1,99
1 #include "AmdaServer.h"
2
3 #include "AmdaDefs.h"
4
5 Q_LOGGING_CATEGORY(LOG_AmdaServer, "AmdaServer")
6
7 namespace {
8
9 /// URL of the default AMDA server
10 const auto AMDA_DEFAULT_SERVER_URL = QStringLiteral("amda.irap.omp.eu");
11
12 /// URL of the AMDA test server
13 const auto AMDA_TEST_SERVER_URL = QStringLiteral("amdatest.irap.omp.eu");
14
15 /// Port used for local server
16 const auto AMDA_LOCAL_SERVER_PORT = 6543;
17
18 /// URL of the local server
19 const auto AMDA_LOCAL_SERVER_URL
20 = QString{"localhost:%1"}.arg(QString::number(AMDA_LOCAL_SERVER_PORT));
21
22 /// Default AMDA server
23 struct AmdaDefaultServer : public AmdaServer {
24 public:
25 QString name() const override { return QStringLiteral("AMDA (default)"); }
26 QString url(const QVariantHash &properties) const override
27 {
28 Q_UNUSED(properties);
29 return AMDA_DEFAULT_SERVER_URL;
30 }
31 };
32
33 /// Alternative AMDA server (tests)
34 struct AmdaTestServer : public AmdaServer {
35 public:
36 QString name() const override { return QStringLiteral("AMDA (test)"); }
37 QString url(const QVariantHash &properties) const override
38 {
39 Q_UNUSED(properties);
40 return AMDA_TEST_SERVER_URL;
41 }
42 };
43
44 /// Hybrid AMDA server: use both of default and test server.
45 /// The server used is relative to each product for which to retrieve url, according to its "server"
46 /// property
47 struct AmdaHybridServer : public AmdaServer {
48 public:
49 QString name() const override { return QStringLiteral("AMDA (hybrid)"); }
50 QString url(const QVariantHash &properties) const override
51 {
52 // Reads "server" property to determine which server url to use
53 auto server = properties.value(AMDA_SERVER_KEY).toString();
54 return server == QString{"amdatest"} ? AMDA_TEST_SERVER_URL : AMDA_DEFAULT_SERVER_URL;
55 }
56 };
57
58 /// Local AMDA server: use local python server to simulate AMDA requests
59 struct AmdaLocalServer : public AmdaServer {
60 public:
61 QString name() const override { return AMDA_LOCAL_SERVER_URL; }
62 QString url(const QVariantHash &properties) const override
63 {
64 Q_UNUSED(properties);
65 return AMDA_LOCAL_SERVER_URL;
66 }
67 };
68
69 /// @return an AMDA server instance created from the name of the server passed in parameter. If the
70 /// name does not match any known server, a default server instance is created
71 std::unique_ptr<AmdaServer> createInstance(const QString &server)
72 {
73 if (server == QString{"amdatest"}) {
74 return std::make_unique<AmdaTestServer>();
75 }
76 else if (server == QString{"hybrid"}) {
77 return std::make_unique<AmdaHybridServer>();
78 }
79 else if (server == QString{"localhost"}) {
80 return std::make_unique<AmdaLocalServer>();
81 }
82 else {
83 if (server != QString{"default"}) {
84 qCWarning(LOG_AmdaServer())
85 << QObject::tr("Unknown server '%1': default AMDA server will be used").arg(server);
86 }
87
88 return std::make_unique<AmdaDefaultServer>();
89 }
90 }
91
92 } // namespace
93
94 AmdaServer &AmdaServer::instance()
95 {
96 // Creates instance depending on the SCIQLOP_AMDA_SERVER value at compile time
97 static auto instance = createInstance(SCIQLOP_AMDA_SERVER);
98 return *instance;
99 }
@@ -0,0 +1,5
1 AmdaResultParser\.h:\d+:.*IPSIS_S01.*
2 AmdaResultParserHelper\.h:\d+:.*IPSIS_S01.*
3
4 AmdaProvider\.cpp:\d+:.*IPSIS_S04_VARIABLE.*found: QStringLiteral
5 AmdaResultParserHelper\.cpp:\d+:.*IPSIS_S04_VARIABLE.*found: QT_VERSION_CHECK No newline at end of file
@@ -1,65 +1,74
1
1
2 if(BUILD_TESTS)
2 if(BUILD_TESTS)
3 INCLUDE ("cmake/sciqlop_code_coverage.cmake")
3 INCLUDE ("cmake/sciqlop_code_coverage.cmake")
4 APPEND_COVERAGE_COMPILER_FLAGS()
4 APPEND_COVERAGE_COMPILER_FLAGS()
5 endif(BUILD_TESTS)
5 endif(BUILD_TESTS)
6
6
7 #
7 #
8 # Compile the diffents modules
8 # Compile the diffents modules
9 #
9 #
10 set(sciqlop-plugin_DIR "${CMAKE_SOURCE_DIR}/plugin/cmake")
10 set(sciqlop-plugin_DIR "${CMAKE_SOURCE_DIR}/plugin/cmake")
11 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-plugin_DIR}")
11 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-plugin_DIR}")
12 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugin")
12 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugin")
13
13
14 set(sciqlop-core_DIR "${CMAKE_SOURCE_DIR}/core/cmake")
14 set(sciqlop-core_DIR "${CMAKE_SOURCE_DIR}/core/cmake")
15 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-core_DIR}")
15 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-core_DIR}")
16 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
16 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
17
17
18 set(sciqlop-gui_DIR "${CMAKE_SOURCE_DIR}/gui/cmake")
18 set(sciqlop-gui_DIR "${CMAKE_SOURCE_DIR}/gui/cmake")
19 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-gui_DIR}")
19 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-gui_DIR}")
20 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/gui")
20 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/gui")
21
21
22 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/app")
22 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/app")
23
23
24 OPTION (BUILD_PLUGINS "Build the plugins" OFF)
24 OPTION (BUILD_PLUGINS "Build the plugins" OFF)
25 IF(BUILD_PLUGINS)
25 IF(BUILD_PLUGINS)
26 set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake")
26 set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake")
27 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}")
27 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}")
28 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin")
28 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin")
29
29
30 # Sets AMDA server that will be used during execution.
31 # Available values are:
32 # - "default": default AMDA server
33 # - "amdatest": AMDA test server
34 # - "hybrid": use both the default server and the test server (the server used is relative to each product, according to its "server" property in the JSON file)
35 # - "localhost": use local AMDA server
36 # Any other value will lead to the use of the default server
37 ADD_DEFINITIONS(-DSCIQLOP_AMDA_SERVER="hybrid")
38
30 set(sciqlop-amda_DIR "${CMAKE_SOURCE_DIR}/plugins/amda/cmake")
39 set(sciqlop-amda_DIR "${CMAKE_SOURCE_DIR}/plugins/amda/cmake")
31 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-amda_DIR}")
40 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-amda_DIR}")
32 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/amda")
41 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/amda")
33
42
34 # Temporary target to copy to plugins dir
43 # Temporary target to copy to plugins dir
35 find_package(sciqlop-mockplugin)
44 find_package(sciqlop-mockplugin)
36 find_package(sciqlop-amda)
45 find_package(sciqlop-amda)
37 ADD_CUSTOM_TARGET(plugins
46 ADD_CUSTOM_TARGET(plugins
38 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}"
47 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}"
39 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-AMDA_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-AMDA_LIBRARIES_NAME}"
48 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-AMDA_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-AMDA_LIBRARIES_NAME}"
40 )
49 )
41 ENDIF(BUILD_PLUGINS)
50 ENDIF(BUILD_PLUGINS)
42
51
43 # LOGGER
52 # LOGGER
44 set(QTLOGGING_INI_FILE "${CMAKE_SOURCE_DIR}/config/QtProject/qtlogging.ini")
53 set(QTLOGGING_INI_FILE "${CMAKE_SOURCE_DIR}/config/QtProject/qtlogging.ini")
45 FILE(COPY ${QTLOGGING_INI_FILE} DESTINATION ${CONFIG_OUTPUT_PATH})
54 FILE(COPY ${QTLOGGING_INI_FILE} DESTINATION ${CONFIG_OUTPUT_PATH})
46
55
47
56
48 #
57 #
49 # Code formatting
58 # Code formatting
50 #
59 #
51 # Vera++ exclusion files
60 # Vera++ exclusion files
52 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/formatting/vera-exclusions/exclusions.txt)
61 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/formatting/vera-exclusions/exclusions.txt)
53 #SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
62 #SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
54 INCLUDE ("cmake/sciqlop_formatting.cmake")
63 INCLUDE ("cmake/sciqlop_formatting.cmake")
55
64
56 #
65 #
57 # Documentation generation
66 # Documentation generation
58 #
67 #
59 INCLUDE ("cmake/sciqlop_doxygen.cmake")
68 INCLUDE ("cmake/sciqlop_doxygen.cmake")
60
69
61 #
70 #
62 # Source code analysis
71 # Source code analysis
63 #
72 #
64 INCLUDE ("cmake/sciqlop_code_analysis.cmake")
73 INCLUDE ("cmake/sciqlop_code_analysis.cmake")
65 INCLUDE ("cmake/sciqlop_code_cppcheck.cmake")
74 INCLUDE ("cmake/sciqlop_code_cppcheck.cmake")
@@ -1,37 +1,46
1 project('SciQLOP', 'cpp',default_options : ['cpp_std=c++14'])
1 project('SciQLOP', 'cpp',default_options : ['cpp_std=c++14'])
2
2
3 qt5 = import('qt5')
3 qt5 = import('qt5')
4 qt5core = dependency('qt5', modules : 'Core')
4 qt5core = dependency('qt5', modules : 'Core')
5 qt5widgets = dependency('qt5', modules : 'Widgets')
5 qt5widgets = dependency('qt5', modules : 'Widgets')
6 qt5gui = dependency('qt5', modules : 'Gui')
6 qt5gui = dependency('qt5', modules : 'Gui')
7 qt5svg = dependency('qt5', modules : 'Svg')
7 qt5svg = dependency('qt5', modules : 'Svg')
8 qt5xml = dependency('qt5', modules : 'Xml')
8 qt5xml = dependency('qt5', modules : 'Xml')
9 qt5network = dependency('qt5', modules : 'Network')
9 qt5network = dependency('qt5', modules : 'Network')
10 qt5printsupport = dependency('qt5', modules : 'PrintSupport')
10 qt5printsupport = dependency('qt5', modules : 'PrintSupport')
11 qt5test = dependency('qt5', modules : 'Test')
11 qt5test = dependency('qt5', modules : 'Test')
12
12
13 moc = find_program('moc-qt5','moc')
13 moc = find_program('moc-qt5','moc')
14 rcc = find_program('rcc-qt5','rcc')
14 rcc = find_program('rcc-qt5','rcc')
15
15
16 if build_machine.system()=='darwin'
16 if build_machine.system()=='darwin'
17 add_global_link_arguments('-headerpad_max_install_names', language : 'cpp')
17 add_global_link_arguments('-headerpad_max_install_names', language : 'cpp')
18 install_data('build_cfg/mac/sciqlopLOGO.icns', install_dir : 'Contents/Resources')
18 install_data('build_cfg/mac/sciqlopLOGO.icns', install_dir : 'Contents/Resources')
19 install_data('build_cfg/mac/Info.plist', install_dir : 'Contents')
19 install_data('build_cfg/mac/Info.plist', install_dir : 'Contents')
20 meson.add_install_script('build_cfg/mac/install_script.sh')
20 meson.add_install_script('build_cfg/mac/install_script.sh')
21 elif host_machine.system()=='windows'
21 elif host_machine.system()=='windows'
22 meson.add_install_script('build_cfg/windows/install_script.sh')
22 meson.add_install_script('build_cfg/windows/install_script.sh')
23 endif
23 endif
24
24
25 # Sets AMDA server that will be used during execution.
26 # Available values are:
27 # - "default": default AMDA server
28 # - "amdatest": AMDA test server
29 # - "hybrid": use both the default server and the test server (the server used is relative to each product, according to its "server" property in the JSON file)
30 # - "localhost": use local AMDA server
31 # Any other value will lead to the use of the default server
32 add_project_arguments('-DSCIQLOP_AMDA_SERVER="hybrid"', language : 'cpp')
33
25 subdir('core')
34 subdir('core')
26 subdir('gui')
35 subdir('gui')
27 subdir('app')
36 subdir('app')
28 subdir('plugins')
37 subdir('plugins')
29
38
30 cppcheck = find_program('cppcheck', required : false)
39 cppcheck = find_program('cppcheck', required : false)
31
40
32 if cppcheck.found()
41 if cppcheck.found()
33 run_target('cppcheck',
42 run_target('cppcheck',
34 command : [cppcheck, '--enable=all',
43 command : [cppcheck, '--enable=all',
35 '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]
44 '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]
36 )
45 )
37 endif
46 endif
@@ -1,167 +1,167
1 ## amda - CMakeLists.txt
1 ## amda - CMakeLists.txt
2 STRING(TOLOWER ${CMAKE_PROJECT_NAME} LIBRARY_PREFFIX)
2 STRING(TOLOWER ${CMAKE_PROJECT_NAME} LIBRARY_PREFFIX)
3 SET(SQPAMDA_LIBRARY_NAME "${LIBRARY_PREFFIX}_amda${DEBUG_SUFFIX}")
3 SET(SQPAMDA_LIBRARY_NAME "${LIBRARY_PREFFIX}_amda${DEBUG_SUFFIX}")
4 SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
4 SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
5 SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
5 SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
6 SET(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
6 SET(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
7 SET(TESTS_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests-resources")
7 SET(TESTS_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests-resources")
8
8
9 # Include amda directory
9 # Include amda directory
10 INCLUDE_DIRECTORIES(${INCLUDES_DIR})
10 INCLUDE_DIRECTORIES(${INCLUDES_DIR})
11 INCLUDE_DIRECTORIES(${RESOURCES_DIR})
11 INCLUDE_DIRECTORIES(${RESOURCES_DIR})
12
12
13 #
13 #
14 # Find Qt modules
14 # Find Qt modules
15 #
15 #
16 SCIQLOP_FIND_QT(Core Widgets Network)
16 SCIQLOP_FIND_QT(Core Widgets Network)
17
17
18 #
18 #
19 # Find dependent libraries
19 # Find dependent libraries
20 # ========================
20 # ========================
21
21
22 # sciqlop plugin
22 # sciqlop plugin
23 find_package(sciqlop-plugin)
23 find_package(sciqlop-plugin)
24 INCLUDE_DIRECTORIES(${SCIQLOP-PLUGIN_INCLUDE_DIR})
24 INCLUDE_DIRECTORIES(${SCIQLOP-PLUGIN_INCLUDE_DIR})
25
25
26 # sciqlop core
26 # sciqlop core
27 find_package(sciqlop-core)
27 find_package(sciqlop-core)
28 INCLUDE_DIRECTORIES(${SCIQLOP-CORE_INCLUDE_DIR})
28 INCLUDE_DIRECTORIES(${SCIQLOP-CORE_INCLUDE_DIR})
29 list(APPEND LIBRARIES ${SCIQLOP-CORE_LIBRARIES})
29 list(APPEND LIBRARIES ${SCIQLOP-CORE_LIBRARIES})
30
30
31 # sciqlop gui
31 # sciqlop gui
32 find_package(sciqlop-gui)
32 find_package(sciqlop-gui)
33 INCLUDE_DIRECTORIES(${SCIQLOP-GUI_INCLUDE_DIR})
33 INCLUDE_DIRECTORIES(${SCIQLOP-GUI_INCLUDE_DIR})
34 list(APPEND LIBRARIES ${SCIQLOP-GUI_LIBRARIES})
34 list(APPEND LIBRARIES ${SCIQLOP-GUI_LIBRARIES})
35
35
36 # Description file
36 # Description file
37 FILE (GLOB_RECURSE PLUGIN_FILE ${RESOURCES_DIR}/amda.json)
37 FILE (GLOB_RECURSE PLUGIN_FILE ${RESOURCES_DIR}/amda.json)
38
38
39 # Resources files
39 # Resources files
40 FILE (GLOB_RECURSE PROJECT_RESOURCES ${RESOURCES_DIR}/*.qrc)
40 FILE (GLOB_RECURSE PROJECT_RESOURCES ${RESOURCES_DIR}/*.qrc)
41
41
42 #
42 #
43 # Compile the library
43 # Compile the library
44 #
44 #
45
45
46 ADD_DEFINITIONS(-DAMDA_LIB)
46 ADD_DEFINITIONS(-DAMDA_LIB)
47
47
48 FILE (GLOB_RECURSE MODULE_SOURCES
48 FILE (GLOB_RECURSE MODULE_SOURCES
49 ${INCLUDES_DIR}/*.h
49 ${INCLUDES_DIR}/*.h
50 ${SOURCES_DIR}/*.c
50 ${SOURCES_DIR}/*.c
51 ${SOURCES_DIR}/*.cpp
51 ${SOURCES_DIR}/*.cpp
52 ${SOURCES_DIR}/*.h
52 ${SOURCES_DIR}/*.h
53 ${PLUGIN_FILE})
53 ${PLUGIN_FILE})
54
54
55 QT5_ADD_RESOURCES(RCC_AMDA
55 QT5_ADD_RESOURCES(RCC_AMDA
56 ${PROJECT_RESOURCES}
56 ${PROJECT_RESOURCES}
57 )
57 )
58
58
59 ADD_LIBRARY(${SQPAMDA_LIBRARY_NAME} ${MODULE_SOURCES} ${RCC_AMDA})
59 ADD_LIBRARY(${SQPAMDA_LIBRARY_NAME} ${MODULE_SOURCES} ${RCC_AMDA})
60 set_property(TARGET ${SQPAMDA_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
60 set_property(TARGET ${SQPAMDA_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
61 set_property(TARGET ${SQPAMDA_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
61 set_property(TARGET ${SQPAMDA_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
62
62
63 INSTALL(TARGETS ${SQPAMDA_LIBRARY_NAME}
63 INSTALL(TARGETS ${SQPAMDA_LIBRARY_NAME}
64 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
64 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
65 LIBRARY DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR}
65 LIBRARY DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR}
66 ARCHIVE DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR}
66 ARCHIVE DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR}
67 )
67 )
68
68
69
69
70 TARGET_LINK_LIBRARIES(${SQPAMDA_LIBRARY_NAME} ${LIBRARIES})
70 TARGET_LINK_LIBRARIES(${SQPAMDA_LIBRARY_NAME} ${LIBRARIES})
71 qt5_use_modules(${SQPAMDA_LIBRARY_NAME} Core Widgets Network)
71 qt5_use_modules(${SQPAMDA_LIBRARY_NAME} Core Widgets Network)
72
72
73 add_dependencies(${SQPAMDA_LIBRARY_NAME} ${SQPPLUGIN_LIBRARY_NAME} ${SQPGUI_LIBRARY_NAME} ${SQPCORE_LIBRARY_NAME})
73 add_dependencies(${SQPAMDA_LIBRARY_NAME} ${SQPPLUGIN_LIBRARY_NAME} ${SQPGUI_LIBRARY_NAME} ${SQPCORE_LIBRARY_NAME})
74
74
75 # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
75 # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
76 # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order.
76 # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order.
77 # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets
77 # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets
78 IF(BUILD_SHARED_LIBS)
78 IF(BUILD_SHARED_LIBS)
79 SET_TARGET_PROPERTIES(${SQPAMDA_LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS "SCIQLOP_EXPORT")
79 SET_TARGET_PROPERTIES(${SQPAMDA_LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS "SCIQLOP_EXPORT")
80 ELSE()
80 ELSE()
81 TARGET_COMPILE_DEFINITIONS(${SQPAMDA_LIBRARY_NAME} PUBLIC "SCIQLOP_STATIC_LIBRARIES")
81 TARGET_COMPILE_DEFINITIONS(${SQPAMDA_LIBRARY_NAME} PUBLIC "SCIQLOP_STATIC_LIBRARIES")
82 ENDIF()
82 ENDIF()
83
83
84 # Set the variable to parent scope so that the other projects can copy the
84 # Set the variable to parent scope so that the other projects can copy the
85 # dependent shared libraries
85 # dependent shared libraries
86 SCIQLOP_SET_TO_PARENT_SCOPE(SQPAMDA_LIBRARY_NAME)
86 SCIQLOP_SET_TO_PARENT_SCOPE(SQPAMDA_LIBRARY_NAME)
87
87
88 # Copy extern shared libraries to the lib folder
88 # Copy extern shared libraries to the lib folder
89 SCIQLOP_COPY_TO_TARGET(LIBRARY ${SQPAMDA_LIBRARY_NAME} ${EXTERN_SHARED_LIBRARIES})
89 SCIQLOP_COPY_TO_TARGET(LIBRARY ${SQPAMDA_LIBRARY_NAME} ${EXTERN_SHARED_LIBRARIES})
90
90
91 # Add the files to the list of files to be analyzed
91 # Add the files to the list of files to be analyzed
92 LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES})
92 LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES})
93 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
93 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
94 # Vera++ exclusion files
94 # Vera++ exclusion files
95 #LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt)
95 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt)
96 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
96 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
97
97
98 #
98 #
99 # Compile the tests
99 # Compile the tests
100 #
100 #
101 IF(BUILD_TESTS)
101 IF(BUILD_TESTS)
102 INCLUDE_DIRECTORIES(${SOURCES_DIR})
102 INCLUDE_DIRECTORIES(${SOURCES_DIR})
103 FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp)
103 FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp)
104 FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h)
104 FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h)
105 SET( TEST_LIBRARIES ${SQPAMDA_LIBRARY_NAME})
105 SET( TEST_LIBRARIES ${SQPAMDA_LIBRARY_NAME})
106
106
107 FOREACH( testFile ${TESTS_SOURCES} )
107 FOREACH( testFile ${TESTS_SOURCES} )
108 GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY )
108 GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY )
109 GET_FILENAME_COMPONENT( testName ${testFile} NAME_WE )
109 GET_FILENAME_COMPONENT( testName ${testFile} NAME_WE )
110
110
111 # Add to the list of sources files all the sources in the same
111 # Add to the list of sources files all the sources in the same
112 # directory that aren't another test
112 # directory that aren't another test
113 FILE (GLOB currentTestSources
113 FILE (GLOB currentTestSources
114 ${testDirectory}/*.c
114 ${testDirectory}/*.c
115 ${testDirectory}/*.cpp
115 ${testDirectory}/*.cpp
116 ${testDirectory}/*.h)
116 ${testDirectory}/*.h)
117 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
117 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
118 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
118 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
119
119
120 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
120 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
121 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
121 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
122 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
122 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
123 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
123 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
124 qt5_use_modules(${testName} Test)
124 qt5_use_modules(${testName} Test)
125
125
126 ADD_TEST( NAME ${testName} COMMAND ${testName} )
126 ADD_TEST( NAME ${testName} COMMAND ${testName} )
127
127
128 SCIQLOP_COPY_TO_TARGET(RUNTIME ${testName} ${EXTERN_SHARED_LIBRARIES})
128 SCIQLOP_COPY_TO_TARGET(RUNTIME ${testName} ${EXTERN_SHARED_LIBRARIES})
129 ENDFOREACH( testFile )
129 ENDFOREACH( testFile )
130
130
131 LIST(APPEND testFilesToFormat ${TESTS_SOURCES})
131 LIST(APPEND testFilesToFormat ${TESTS_SOURCES})
132 LIST(APPEND testFilesToFormat ${TESTS_HEADERS})
132 LIST(APPEND testFilesToFormat ${TESTS_HEADERS})
133 LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat})
133 LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat})
134 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
134 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
135
135
136 ADD_DEFINITIONS(-DAMDA_TESTS_RESOURCES_DIR="${TESTS_RESOURCES_DIR}")
136 ADD_DEFINITIONS(-DAMDA_TESTS_RESOURCES_DIR="${TESTS_RESOURCES_DIR}")
137 ENDIF(BUILD_TESTS)
137 ENDIF(BUILD_TESTS)
138
138
139 #
139 #
140 # Set the files that must be formatted by clang-format.
140 # Set the files that must be formatted by clang-format.
141 #
141 #
142 LIST (APPEND FORMATTING_INPUT_FILES ${MODULE_SOURCES})
142 LIST (APPEND FORMATTING_INPUT_FILES ${MODULE_SOURCES})
143 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
143 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
144
144
145 #
145 #
146 # Set the directories that doxygen must browse to generate the
146 # Set the directories that doxygen must browse to generate the
147 # documentation.
147 # documentation.
148 #
148 #
149 # Source directories:
149 # Source directories:
150 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/docs")
150 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/docs")
151 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
151 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
152 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_INPUT_DIRS)
152 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_INPUT_DIRS)
153 # Source directories to exclude from the documentation generation
153 # Source directories to exclude from the documentation generation
154 #LIST (APPEND DOXYGEN_EXCLUDE_PATTERNS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir/*")
154 #LIST (APPEND DOXYGEN_EXCLUDE_PATTERNS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir/*")
155 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_EXCLUDE_PATTERNS)
155 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_EXCLUDE_PATTERNS)
156
156
157 #
157 #
158 # Set the directories with the sources to analyze and propagate the
158 # Set the directories with the sources to analyze and propagate the
159 # modification to the parent scope
159 # modification to the parent scope
160 #
160 #
161 # Source directories to analyze:
161 # Source directories to analyze:
162 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
162 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
163 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
163 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
164 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_INPUT_DIRS)
164 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_INPUT_DIRS)
165 # Source directories to exclude from the analysis
165 # Source directories to exclude from the analysis
166 #LIST (APPEND ANALYSIS_EXCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir")
166 #LIST (APPEND ANALYSIS_EXCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir")
167 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_EXCLUDE_DIRS)
167 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_EXCLUDE_DIRS)
@@ -1,29 +1,29
1 #ifndef SCIQLOP_AMDAPLUGIN_H
1 #ifndef SCIQLOP_AMDAPLUGIN_H
2 #define SCIQLOP_AMDAPLUGIN_H
2 #define SCIQLOP_AMDAPLUGIN_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Plugin/IPlugin.h>
6 #include <Plugin/IPlugin.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaPlugin)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaPlugin)
13
13
14 #ifndef PLUGIN_JSON_FILE_PATH
14 #ifndef SCIQLOP_PLUGIN_JSON_FILE_PATH
15 #define PLUGIN_JSON_FILE_PATH "amda.json"
15 #define SCIQLOP_PLUGIN_JSON_FILE_PATH "amda.json"
16 #endif
16 #endif
17
17
18 class DataSourceItem;
18 class DataSourceItem;
19
19
20 class SCIQLOP_AMDA_EXPORT AmdaPlugin : public QObject, public IPlugin {
20 class SCIQLOP_AMDA_EXPORT AmdaPlugin : public QObject, public IPlugin {
21 Q_OBJECT
21 Q_OBJECT
22 Q_INTERFACES(IPlugin)
22 Q_INTERFACES(IPlugin)
23 Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE PLUGIN_JSON_FILE_PATH)
23 Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE SCIQLOP_PLUGIN_JSON_FILE_PATH)
24 public:
24 public:
25 /// @sa IPlugin::initialize()
25 /// @sa IPlugin::initialize()
26 void initialize() override;
26 void initialize() override;
27 };
27 };
28
28
29 #endif // SCIQLOP_AMDAPLUGIN_H
29 #endif // SCIQLOP_AMDAPLUGIN_H
@@ -1,44 +1,44
1 #ifndef SCIQLOP_AMDAPROVIDER_H
1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10 #include <map>
10 #include <map>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
13
13
14 class QNetworkReply;
14 class QNetworkReply;
15 class QNetworkRequest;
15 class QNetworkRequest;
16
16
17 /**
17 /**
18 * @brief The AmdaProvider class is an example of how a data provider can generate data
18 * @brief The AmdaProvider class is an example of how a data provider can generate data
19 */
19 */
20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
21 Q_OBJECT
21 Q_OBJECT
22 public:
22 public:
23 explicit AmdaProvider();
23 explicit AmdaProvider();
24 std::shared_ptr<IDataProvider> clone() const override;
24 std::shared_ptr<IDataProvider> clone() const override;
25
25
26 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
26 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
27
27
28 void requestDataAborting(QUuid acqIdentifier) override;
28 void requestDataAborting(QUuid acqIdentifier) override;
29
29
30 private slots:
31 void onReplyDownloadProgress(QUuid acqIdentifier,
32 std::shared_ptr<QNetworkRequest> networkRequest, double progress);
33
34 private:
30 private:
35 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
31 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
36
32
37 void updateRequestProgress(QUuid acqIdentifier, std::shared_ptr<QNetworkRequest> request,
33 void updateRequestProgress(QUuid acqIdentifier, std::shared_ptr<QNetworkRequest> request,
38 double progress);
34 double progress);
39
35
40 std::map<QUuid, std::map<std::shared_ptr<QNetworkRequest>, double> >
36 std::map<QUuid, std::map<std::shared_ptr<QNetworkRequest>, double> >
41 m_AcqIdToRequestProgressMap;
37 m_AcqIdToRequestProgressMap;
38
39 private slots:
40 void onReplyDownloadProgress(QUuid acqIdentifier,
41 std::shared_ptr<QNetworkRequest> networkRequest, double progress);
42 };
42 };
43
43
44 #endif // SCIQLOP_AMDAPROVIDER_H
44 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,76 +1,79
1 #ifndef SCIQLOP_AMDARESULTPARSERDEFS_H
1 #ifndef SCIQLOP_AMDARESULTPARSERDEFS_H
2 #define SCIQLOP_AMDARESULTPARSERDEFS_H
2 #define SCIQLOP_AMDARESULTPARSERDEFS_H
3
3
4 #include <QtCore/QRegularExpression>
4 #include <QtCore/QRegularExpression>
5 #include <QtCore/QString>
5 #include <QtCore/QString>
6 #include <QtCore/QVariantHash>
6 #include <QtCore/QVariantHash>
7
7
8 // ////////// //
8 // ////////// //
9 // Properties //
9 // Properties //
10 // ////////// //
10 // ////////// //
11
11
12 /// Alias to represent properties read in the header of AMDA file
12 /// Alias to represent properties read in the header of AMDA file
13 using Properties = QVariantHash;
13 using Properties = QVariantHash;
14
14
15 extern const QString END_TIME_PROPERTY;
15 extern const QString END_TIME_PROPERTY;
16 extern const QString FILL_VALUE_PROPERTY;
16 extern const QString FILL_VALUE_PROPERTY;
17 extern const QString MAX_BANDS_PROPERTY;
17 extern const QString MAX_BANDS_PROPERTY;
18 extern const QString MIN_BANDS_PROPERTY;
18 extern const QString MIN_BANDS_PROPERTY;
19 extern const QString MAX_SAMPLING_PROPERTY;
19 extern const QString MAX_SAMPLING_PROPERTY;
20 extern const QString MIN_SAMPLING_PROPERTY;
20 extern const QString MIN_SAMPLING_PROPERTY;
21 extern const QString START_TIME_PROPERTY;
21 extern const QString START_TIME_PROPERTY;
22 extern const QString X_AXIS_UNIT_PROPERTY;
22 extern const QString X_AXIS_UNIT_PROPERTY;
23 extern const QString Y_AXIS_UNIT_PROPERTY;
23 extern const QString Y_AXIS_UNIT_PROPERTY;
24 extern const QString VALUES_UNIT_PROPERTY;
24 extern const QString VALUES_UNIT_PROPERTY;
25
25
26 // /////////////////// //
26 // /////////////////// //
27 // Regular expressions //
27 // Regular expressions //
28 // /////////////////// //
28 // /////////////////// //
29
29
30 // AMDA V2
30 // AMDA V2
31 // /// Regex to find the header of the data in the file. This header indicates the end of comments
31 // /// Regex to find the header of the data in the file. This header indicates the end of comments
32 // in the file
32 // in the file
33 // const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")};
33 // const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")};
34
34
35 // AMDA V2
35 // AMDA V2
36 // /// ... PARAMETER_UNITS : nT ...
36 // /// ... PARAMETER_UNITS : nT ...
37 // /// ... PARAMETER_UNITS:nT ...
37 // /// ... PARAMETER_UNITS:nT ...
38 // /// ... PARAMETER_UNITS: mΒ² ...
38 // /// ... PARAMETER_UNITS: mΒ² ...
39 // /// ... PARAMETER_UNITS : m/s ...
39 // /// ... PARAMETER_UNITS : m/s ...
40 // const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")};
40 // const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")};
41
41
42 /// Regex to find x-axis unit in a line. Examples of valid lines:
42 /// Regex to find x-axis unit in a line. Examples of valid lines:
43 /// ... - Units : nT - ...
43 /// ... - Units : nT - ...
44 /// ... -Units:nT- ...
44 /// ... -Units:nT- ...
45 /// ... -Units: mΒ²- ...
45 /// ... -Units: mΒ²- ...
46 /// ... - Units : m/s - ...
46 /// ... - Units : m/s - ...
47 extern const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX;
47 extern const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX;
48
48
49 /// Alternative regex to find x-axis unit in a line
50 extern const QRegularExpression ALTERNATIVE_X_AXIS_UNIT_REGEX;
51
49 /// Regex to find end time of data in a line for a spectrogram
52 /// Regex to find end time of data in a line for a spectrogram
50 extern const QRegularExpression SPECTROGRAM_END_TIME_REGEX;
53 extern const QRegularExpression SPECTROGRAM_END_TIME_REGEX;
51
54
52 /// Regex to find fill value used in a line for a spectrogram
55 /// Regex to find fill value used in a line for a spectrogram
53 extern const QRegularExpression SPECTROGRAM_FILL_VALUE_REGEX;
56 extern const QRegularExpression SPECTROGRAM_FILL_VALUE_REGEX;
54
57
55 /// Regex to find max bands in a line for a spectrogram
58 /// Regex to find max bands in a line for a spectrogram
56 extern const QRegularExpression SPECTROGRAM_MAX_BANDS_REGEX;
59 extern const QRegularExpression SPECTROGRAM_MAX_BANDS_REGEX;
57
60
58 /// Regex to find min bands in a line for a spectrogram
61 /// Regex to find min bands in a line for a spectrogram
59 extern const QRegularExpression SPECTROGRAM_MIN_BANDS_REGEX;
62 extern const QRegularExpression SPECTROGRAM_MIN_BANDS_REGEX;
60
63
61 /// Regex to find max x-axis sampling in a line for a spectrogram
64 /// Regex to find max x-axis sampling in a line for a spectrogram
62 extern const QRegularExpression SPECTROGRAM_MAX_SAMPLING_REGEX;
65 extern const QRegularExpression SPECTROGRAM_MAX_SAMPLING_REGEX;
63
66
64 /// Regex to find min x-axis sampling in a line for a spectrogram
67 /// Regex to find min x-axis sampling in a line for a spectrogram
65 extern const QRegularExpression SPECTROGRAM_MIN_SAMPLING_REGEX;
68 extern const QRegularExpression SPECTROGRAM_MIN_SAMPLING_REGEX;
66
69
67 /// Regex to find start time of data in a line for a spectrogram
70 /// Regex to find start time of data in a line for a spectrogram
68 extern const QRegularExpression SPECTROGRAM_START_TIME_REGEX;
71 extern const QRegularExpression SPECTROGRAM_START_TIME_REGEX;
69
72
70 /// Regex to find y-axis unit in a line for a spectrogram
73 /// Regex to find y-axis unit in a line for a spectrogram
71 extern const QRegularExpression SPECTROGRAM_Y_AXIS_UNIT_REGEX;
74 extern const QRegularExpression SPECTROGRAM_Y_AXIS_UNIT_REGEX;
72
75
73 /// Regex to find values unit in a line for a spectrogram
76 /// Regex to find values unit in a line for a spectrogram
74 extern const QRegularExpression SPECTROGRAM_VALUES_UNIT_REGEX;
77 extern const QRegularExpression SPECTROGRAM_VALUES_UNIT_REGEX;
75
78
76 #endif // SCIQLOP_AMDARESULTPARSERDEFS_H
79 #endif // SCIQLOP_AMDARESULTPARSERDEFS_H
@@ -1,75 +1,76
1
1
2 amdaplugin_moc_headers = [
2 amdaplugin_moc_headers = [
3 'include/AmdaPlugin.h',
3 'include/AmdaPlugin.h',
4 'include/AmdaProvider.h'
4 'include/AmdaProvider.h'
5 ]
5 ]
6
6
7 amdaplugin_sources = [
7 amdaplugin_sources = [
8 'src/AmdaDefs.cpp',
8 'src/AmdaDefs.cpp',
9 'src/AmdaParser.cpp',
9 'src/AmdaParser.cpp',
10 'src/AmdaPlugin.cpp',
10 'src/AmdaPlugin.cpp',
11 'src/AmdaProvider.cpp',
11 'src/AmdaProvider.cpp',
12 'src/AmdaResultParser.cpp',
12 'src/AmdaResultParser.cpp',
13 'src/AmdaResultParserDefs.cpp',
13 'src/AmdaResultParserDefs.cpp',
14 'src/AmdaResultParserHelper.cpp'
14 'src/AmdaResultParserHelper.cpp',
15 'src/AmdaServer.cpp'
15 ]
16 ]
16
17
17 amdaplugin_ui_files = []
18 amdaplugin_ui_files = []
18 amdaplugin_resources_files = [
19 amdaplugin_resources_files = [
19 'resources/amdaresources.qrc'
20 'resources/amdaresources.qrc'
20 ]
21 ]
21
22
22 amdaplugin_inc = include_directories(['include', '../../plugin/include'])
23 amdaplugin_inc = include_directories(['include', '../../plugin/include'])
23
24
24 moc_gen = generator(moc,
25 moc_gen = generator(moc,
25 output : 'moc_@BASENAME@.cpp',
26 output : 'moc_@BASENAME@.cpp',
26 arguments : ['@INPUT@',
27 arguments : ['@INPUT@',
27 '-DPLUGIN_JSON_FILE_PATH="'+meson.source_root()+'/plugins/amda/resources/amda.json"',
28 '-DSCIQLOP_PLUGIN_JSON_FILE_PATH="'+meson.source_root()+'/plugins/amda/resources/amda.json"',
28 '-I', meson.current_source_dir()+'/include',
29 '-I', meson.current_source_dir()+'/include',
29 '-I', meson.current_source_dir()+'/../../plugin/include',
30 '-I', meson.current_source_dir()+'/../../plugin/include',
30 '-o', '@OUTPUT@'])
31 '-o', '@OUTPUT@'])
31
32
32 rcc_gen = generator(rcc,
33 rcc_gen = generator(rcc,
33 output : 'qrc_@BASENAME@.cpp',
34 output : 'qrc_@BASENAME@.cpp',
34 arguments : ['--name=@BASENAME@"',
35 arguments : ['--name=@BASENAME@"',
35 '--output',
36 '--output',
36 '@OUTPUT@',
37 '@OUTPUT@',
37 '@INPUT@'])
38 '@INPUT@'])
38
39
39 amdaplugin_moc_plugin_files = moc_gen.process(amdaplugin_moc_headers)
40 amdaplugin_moc_plugin_files = moc_gen.process(amdaplugin_moc_headers)
40
41
41 amdaplugin_rcc_plugin_files = rcc_gen.process(amdaplugin_resources_files)
42 amdaplugin_rcc_plugin_files = rcc_gen.process(amdaplugin_resources_files)
42
43
43 #amdaplugin_rcc_plugin_files = qt5.preprocess(
44 #amdaplugin_rcc_plugin_files = qt5.preprocess(
44 # qresources : amdaplugin_resources_files)
45 # qresources : amdaplugin_resources_files)
45
46
46 amdaplugin_moc_files = qt5.preprocess(
47 amdaplugin_moc_files = qt5.preprocess(
47 ui_files : amdaplugin_ui_files)
48 ui_files : amdaplugin_ui_files)
48
49
49 sciqlop_amdaplugin = library('amdaplugin',
50 sciqlop_amdaplugin = library('amdaplugin',
50 amdaplugin_sources,
51 amdaplugin_sources,
51 amdaplugin_moc_files,
52 amdaplugin_moc_files,
52 amdaplugin_rcc_plugin_files,
53 amdaplugin_rcc_plugin_files,
53 amdaplugin_moc_plugin_files,
54 amdaplugin_moc_plugin_files,
54 cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'],
55 cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'],
55 include_directories : [amdaplugin_inc],
56 include_directories : [amdaplugin_inc],
56 dependencies : [sciqlop_core, sciqlop_gui],
57 dependencies : [sciqlop_core, sciqlop_gui],
57 install : true
58 install : true
58 )
59 )
59
60
60
61
61 tests = [
62 tests = [
62 [['tests/TestAmdaParser.cpp'],'test_amda_parser','AMDA parser test'],
63 [['tests/TestAmdaParser.cpp'],'test_amda_parser','AMDA parser test'],
63 [['tests/TestAmdaResultParser.cpp'],'test_amda_result_parser','AMDA result parser test'],
64 [['tests/TestAmdaResultParser.cpp'],'test_amda_result_parser','AMDA result parser test'],
64 [['tests/TestAmdaAcquisition.cpp'],'test_amda_acquisition','AMDA Acquisition test']
65 [['tests/TestAmdaAcquisition.cpp'],'test_amda_acquisition','AMDA Acquisition test']
65 ]
66 ]
66
67
67 foreach unit_test : tests
68 foreach unit_test : tests
68 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
69 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
69 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
70 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
70 link_with : [sciqlop_amdaplugin],
71 link_with : [sciqlop_amdaplugin],
71 include_directories : [amdaplugin_inc],
72 include_directories : [amdaplugin_inc],
72 cpp_args : ['-DAMDA_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/tests-resources"'],
73 cpp_args : ['-DAMDA_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/tests-resources"'],
73 dependencies : [sciqlop_core, sciqlop_gui, qt5test])
74 dependencies : [sciqlop_core, sciqlop_gui, qt5test])
74 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])], timeout: 3 * 60)
75 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])], timeout: 3 * 60)
75 endforeach
76 endforeach
@@ -1,77 +1,78
1 #include "AmdaPlugin.h"
1 #include "AmdaPlugin.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaParser.h"
3 #include "AmdaParser.h"
4 #include "AmdaProvider.h"
4 #include "AmdaProvider.h"
5 #include "AmdaServer.h"
5
6
6 #include <DataSource/DataSourceController.h>
7 #include <DataSource/DataSourceController.h>
7 #include <DataSource/DataSourceItem.h>
8 #include <DataSource/DataSourceItem.h>
8 #include <DataSource/DataSourceItemAction.h>
9 #include <DataSource/DataSourceItemAction.h>
9
10
10 #include <SqpApplication.h>
11 #include <SqpApplication.h>
11
12
12 Q_LOGGING_CATEGORY(LOG_AmdaPlugin, "AmdaPlugin")
13 Q_LOGGING_CATEGORY(LOG_AmdaPlugin, "AmdaPlugin")
13
14
14 namespace {
15 namespace {
15
16
16 /// Name of the data source
17 const auto DATA_SOURCE_NAME = QStringLiteral("AMDA");
18
19 /// Path of the file used to generate the data source item for AMDA
17 /// Path of the file used to generate the data source item for AMDA
20 const auto JSON_FILE_PATH = QStringLiteral(":/samples/AmdaSampleV3.json");
18 const auto JSON_FILE_PATH = QStringLiteral(":/samples/AmdaSampleV3.json");
21
19
22 void associateActions(DataSourceItem &item, const QUuid &dataSourceUid)
20 void associateActions(DataSourceItem &item, const QUuid &dataSourceUid)
23 {
21 {
24 auto addLoadAction = [&item, dataSourceUid](const QString &label) {
22 auto addLoadAction = [&item, dataSourceUid](const QString &label) {
25 item.addAction(
23 item.addAction(
26 std::make_unique<DataSourceItemAction>(label, [dataSourceUid](DataSourceItem &item) {
24 std::make_unique<DataSourceItemAction>(label, [dataSourceUid](DataSourceItem &item) {
27 if (auto app = sqpApp) {
25 if (auto app = sqpApp) {
28 app->dataSourceController().loadProductItem(dataSourceUid, item);
26 app->dataSourceController().loadProductItem(dataSourceUid, item);
29 }
27 }
30 }));
28 }));
31 };
29 };
32
30
33 const auto itemType = item.type();
31 const auto itemType = item.type();
34 if (itemType == DataSourceItemType::PRODUCT || itemType == DataSourceItemType::COMPONENT) {
32 if (itemType == DataSourceItemType::PRODUCT || itemType == DataSourceItemType::COMPONENT) {
35 // Adds plugin name to item metadata
33 // Adds plugin name to item metadata
36 item.setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME);
34 item.setData(DataSourceItem::PLUGIN_DATA_KEY, AmdaServer::instance().name());
37
35
38 // Adds load action
36 // Adds load action
39 auto actionLabel = QObject::tr(
37 auto actionLabel = QObject::tr(
40 itemType == DataSourceItemType::PRODUCT ? "Load %1 product" : "Load %1 component");
38 itemType == DataSourceItemType::PRODUCT ? "Load %1 product" : "Load %1 component");
41 addLoadAction(actionLabel.arg(item.name()));
39 addLoadAction(actionLabel.arg(item.name()));
42 }
40 }
43
41
44 auto count = item.childCount();
42 auto count = item.childCount();
45 for (auto i = 0; i < count; ++i) {
43 for (auto i = 0; i < count; ++i) {
46 if (auto child = item.child(i)) {
44 if (auto child = item.child(i)) {
47 associateActions(*child, dataSourceUid);
45 associateActions(*child, dataSourceUid);
48 }
46 }
49 }
47 }
50 }
48 }
51
49
52 } // namespace
50 } // namespace
53
51
54 void AmdaPlugin::initialize()
52 void AmdaPlugin::initialize()
55 {
53 {
56 if (auto app = sqpApp) {
54 if (auto app = sqpApp) {
55 auto dataSourceName = AmdaServer::instance().name();
56
57 // Registers to the data source controller
57 // Registers to the data source controller
58 auto &dataSourceController = app->dataSourceController();
58 auto &dataSourceController = app->dataSourceController();
59 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
59 auto dataSourceUid = dataSourceController.registerDataSource(dataSourceName);
60
60
61 // Sets data source tree
61 // Sets data source tree
62 if (auto dataSourceItem = AmdaParser::readJson(JSON_FILE_PATH)) {
62 if (auto dataSourceItem = AmdaParser::readJson(JSON_FILE_PATH)) {
63 associateActions(*dataSourceItem, dataSourceUid);
63 dataSourceItem->setData(DataSourceItem::NAME_DATA_KEY, dataSourceName);
64
64
65 associateActions(*dataSourceItem, dataSourceUid);
65 dataSourceController.setDataSourceItem(dataSourceUid, std::move(dataSourceItem));
66 dataSourceController.setDataSourceItem(dataSourceUid, std::move(dataSourceItem));
66 }
67 }
67 else {
68 else {
68 qCCritical(LOG_AmdaPlugin()) << tr("No data source item could be generated for AMDA");
69 qCCritical(LOG_AmdaPlugin()) << tr("No data source item could be generated for AMDA");
69 }
70 }
70
71
71 // Sets data provider
72 // Sets data provider
72 dataSourceController.setDataProvider(dataSourceUid, std::make_unique<AmdaProvider>());
73 dataSourceController.setDataProvider(dataSourceUid, std::make_unique<AmdaProvider>());
73 }
74 }
74 else {
75 else {
75 qCWarning(LOG_AmdaPlugin()) << tr("Can't access to SciQlop application");
76 qCWarning(LOG_AmdaPlugin()) << tr("Can't access to SciQlop application");
76 }
77 }
77 }
78 }
@@ -1,307 +1,288
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
4 #include "AmdaServer.h"
4
5
5 #include <Common/DateUtils.h>
6 #include <Common/DateUtils.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/DataProviderParameters.h>
7 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
8 #include <SqpApplication.h>
9 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
10
11
11 #include <QNetworkAccessManager>
12 #include <QNetworkAccessManager>
12 #include <QNetworkReply>
13 #include <QNetworkReply>
13 #include <QTemporaryFile>
14 #include <QTemporaryFile>
14 #include <QThread>
15 #include <QThread>
15
16
16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17
18
18 namespace {
19 namespace {
19
20
20 /// URL of the default AMDA server
21 const auto AMDA_SERVER_URL = QStringLiteral("amda.irap.omp.eu");
22
23 /// URL of the AMDA test server
24 const auto AMDA_TEST_SERVER_URL = QStringLiteral("amdatest.irap.omp.eu");
25
26 /// URL format for a request on AMDA server. The parameters are as follows:
21 /// URL format for a request on AMDA server. The parameters are as follows:
27 /// - %1: server URL
22 /// - %1: server URL
28 /// - %2: start date
23 /// - %2: start date
29 /// - %3: end date
24 /// - %3: end date
30 /// - %4: parameter id
25 /// - %4: parameter id
31 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
26 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
32 const auto AMDA_URL_FORMAT = QStringLiteral(
27 const auto AMDA_URL_FORMAT = QStringLiteral(
33 "http://%1/php/rest/"
28 "http://%1/php/rest/"
34 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
29 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
35 "timeFormat=ISO8601&gzip=0");
30 "timeFormat=ISO8601&gzip=0");
36
31
37 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
32 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
38 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
33 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
39
34
40 /// Formats a time to a date that can be passed in URL
35 /// Formats a time to a date that can be passed in URL
41 QString dateFormat(double sqpRange) noexcept
36 QString dateFormat(double sqpRange) noexcept
42 {
37 {
43 auto dateTime = DateUtils::dateTime(sqpRange);
38 auto dateTime = DateUtils::dateTime(sqpRange);
44 return dateTime.toString(AMDA_TIME_FORMAT);
39 return dateTime.toString(AMDA_TIME_FORMAT);
45 }
40 }
46
41
47 /// Returns the URL of the AMDA server queried for requests, depending on the type of server passed
48 /// as a parameter
49 QString serverURL(const QString &server)
50 {
51 if (server == QString{"amdatest"}) {
52 return AMDA_TEST_SERVER_URL;
53 }
54 else {
55 return AMDA_SERVER_URL;
56 }
57 }
58
59 AmdaResultParser::ValueType valueType(const QString &valueType)
42 AmdaResultParser::ValueType valueType(const QString &valueType)
60 {
43 {
61 if (valueType == QStringLiteral("scalar")) {
44 if (valueType == QStringLiteral("scalar")) {
62 return AmdaResultParser::ValueType::SCALAR;
45 return AmdaResultParser::ValueType::SCALAR;
63 }
46 }
64 else if (valueType == QStringLiteral("spectrogram")) {
47 else if (valueType == QStringLiteral("spectrogram")) {
65 return AmdaResultParser::ValueType::SPECTROGRAM;
48 return AmdaResultParser::ValueType::SPECTROGRAM;
66 }
49 }
67 else if (valueType == QStringLiteral("vector")) {
50 else if (valueType == QStringLiteral("vector")) {
68 return AmdaResultParser::ValueType::VECTOR;
51 return AmdaResultParser::ValueType::VECTOR;
69 }
52 }
70 else {
53 else {
71 return AmdaResultParser::ValueType::UNKNOWN;
54 return AmdaResultParser::ValueType::UNKNOWN;
72 }
55 }
73 }
56 }
74
57
75 } // namespace
58 } // namespace
76
59
77 AmdaProvider::AmdaProvider()
60 AmdaProvider::AmdaProvider()
78 {
61 {
79 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
62 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
80 if (auto app = sqpApp) {
63 if (auto app = sqpApp) {
81 auto &networkController = app->networkController();
64 auto &networkController = app->networkController();
82 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
65 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
83 std::function<void(QNetworkReply *, QUuid)>)),
66 std::function<void(QNetworkReply *, QUuid)>)),
84 &networkController,
67 &networkController,
85 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
68 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
86 std::function<void(QNetworkReply *, QUuid)>)));
69 std::function<void(QNetworkReply *, QUuid)>)));
87
70
88
71
89 connect(&sqpApp->networkController(),
72 connect(&sqpApp->networkController(),
90 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
73 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
91 this,
74 this,
92 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
75 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
93 }
76 }
94 }
77 }
95
78
96 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
79 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
97 {
80 {
98 // No copy is made in the clone
81 // No copy is made in the clone
99 return std::make_shared<AmdaProvider>();
82 return std::make_shared<AmdaProvider>();
100 }
83 }
101
84
102 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
85 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
103 {
86 {
104 // NOTE: Try to use multithread if possible
87 // NOTE: Try to use multithread if possible
105 const auto times = parameters.m_Times;
88 const auto times = parameters.m_Times;
106 const auto data = parameters.m_Data;
89 const auto data = parameters.m_Data;
107 for (const auto &dateTime : qAsConst(times)) {
90 for (const auto &dateTime : qAsConst(times)) {
108 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
91 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
109 << dateTime;
92 << dateTime;
110 this->retrieveData(acqIdentifier, dateTime, data);
93 this->retrieveData(acqIdentifier, dateTime, data);
111
94
112
95
113 // TORM when AMDA will support quick asynchrone request
96 // TORM when AMDA will support quick asynchrone request
114 QThread::msleep(1000);
97 QThread::msleep(1000);
115 }
98 }
116 }
99 }
117
100
118 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
101 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
119 {
102 {
120 if (auto app = sqpApp) {
103 if (auto app = sqpApp) {
121 auto &networkController = app->networkController();
104 auto &networkController = app->networkController();
122 networkController.onReplyCanceled(acqIdentifier);
105 networkController.onReplyCanceled(acqIdentifier);
123 }
106 }
124 }
107 }
125
108
126 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
109 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
127 std::shared_ptr<QNetworkRequest> networkRequest,
110 std::shared_ptr<QNetworkRequest> networkRequest,
128 double progress)
111 double progress)
129 {
112 {
130 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
113 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
131 << networkRequest.get() << progress;
114 << networkRequest.get() << progress;
132 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
115 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
133 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
116 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
134
117
135 // Update the progression for the current request
118 // Update the progression for the current request
136 auto requestPtr = networkRequest;
119 auto requestPtr = networkRequest;
137 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
120 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
138
121
139 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
122 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
140 auto requestProgressMapEnd = requestProgressMap.end();
123 auto requestProgressMapEnd = requestProgressMap.end();
141 auto requestProgressMapIt
124 auto requestProgressMapIt
142 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
125 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
143
126
144 if (requestProgressMapIt != requestProgressMapEnd) {
127 if (requestProgressMapIt != requestProgressMapEnd) {
145 requestProgressMapIt->second = progress;
128 requestProgressMapIt->second = progress;
146 }
129 }
147 else {
130 else {
148 // This case can happened when a progression is send after the request has been
131 // This case can happened when a progression is send after the request has been
149 // finished.
132 // finished.
150 // Generaly the case when aborting a request
133 // Generaly the case when aborting a request
151 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
134 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
152 << networkRequest.get() << progress;
135 << networkRequest.get() << progress;
153 }
136 }
154
137
155 // Compute the current final progress and notify it
138 // Compute the current final progress and notify it
156 double finalProgress = 0.0;
139 double finalProgress = 0.0;
157
140
158 auto fraq = requestProgressMap.size();
141 auto fraq = requestProgressMap.size();
159
142
160 for (auto requestProgress : requestProgressMap) {
143 for (auto requestProgress : requestProgressMap) {
161 finalProgress += requestProgress.second;
144 finalProgress += requestProgress.second;
162 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
145 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
163 << finalProgress << requestProgress.second;
146 << finalProgress << requestProgress.second;
164 }
147 }
165
148
166 if (fraq > 0) {
149 if (fraq > 0) {
167 finalProgress = finalProgress / fraq;
150 finalProgress = finalProgress / fraq;
168 }
151 }
169
152
170 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
153 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
171 emit dataProvidedProgress(acqIdentifier, finalProgress);
154 emit dataProvidedProgress(acqIdentifier, finalProgress);
172 }
155 }
173 else {
156 else {
174 // This case can happened when a progression is send after the request has been finished.
157 // This case can happened when a progression is send after the request has been finished.
175 // Generaly the case when aborting a request
158 // Generaly the case when aborting a request
176 emit dataProvidedProgress(acqIdentifier, 100.0);
159 emit dataProvidedProgress(acqIdentifier, 100.0);
177 }
160 }
178 }
161 }
179
162
180 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
163 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
181 {
164 {
182 // Retrieves product ID from data: if the value is invalid, no request is made
165 // Retrieves product ID from data: if the value is invalid, no request is made
183 auto productId = data.value(AMDA_XML_ID_KEY).toString();
166 auto productId = data.value(AMDA_XML_ID_KEY).toString();
184 if (productId.isNull()) {
167 if (productId.isNull()) {
185 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
168 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
186 return;
169 return;
187 }
170 }
188
171
189 // Retrieves the data type that determines whether the expected format for the result file is
172 // Retrieves the data type that determines whether the expected format for the result file is
190 // scalar, vector...
173 // scalar, vector...
191 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
174 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
192
175
193 // Gets the server being queried to retrieve the product. It's then used to set the server URL
194 auto productServer = data.value(AMDA_SERVER_KEY).toString();
195
196 // /////////// //
176 // /////////// //
197 // Creates URL //
177 // Creates URL //
198 // /////////// //
178 // /////////// //
199
179
200 auto startDate = dateFormat(dateTime.m_TStart);
180 auto startDate = dateFormat(dateTime.m_TStart);
201 auto endDate = dateFormat(dateTime.m_TEnd);
181 auto endDate = dateFormat(dateTime.m_TEnd);
202
182
203 auto url = QUrl{
183 QVariantHash urlProperties{{AMDA_SERVER_KEY, data.value(AMDA_SERVER_KEY)}};
204 QString{AMDA_URL_FORMAT}.arg(serverURL(productServer), startDate, endDate, productId)};
184 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties),
185 startDate, endDate, productId)};
205 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
186 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
206 auto tempFile = std::make_shared<QTemporaryFile>();
187 auto tempFile = std::make_shared<QTemporaryFile>();
207
188
208 // LAMBDA
189 // LAMBDA
209 auto httpDownloadFinished = [this, dateTime, tempFile,
190 auto httpDownloadFinished = [this, dateTime, tempFile,
210 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
191 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
211
192
212 // Don't do anything if the reply was abort
193 // Don't do anything if the reply was abort
213 if (reply->error() == QNetworkReply::NoError) {
194 if (reply->error() == QNetworkReply::NoError) {
214
195
215 if (tempFile) {
196 if (tempFile) {
216 auto replyReadAll = reply->readAll();
197 auto replyReadAll = reply->readAll();
217 if (!replyReadAll.isEmpty()) {
198 if (!replyReadAll.isEmpty()) {
218 tempFile->write(replyReadAll);
199 tempFile->write(replyReadAll);
219 }
200 }
220 tempFile->close();
201 tempFile->close();
221
202
222 // Parse results file
203 // Parse results file
223 if (auto dataSeries
204 if (auto dataSeries
224 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
205 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
225 emit dataProvided(dataId, dataSeries, dateTime);
206 emit dataProvided(dataId, dataSeries, dateTime);
226 }
207 }
227 else {
208 else {
228 /// @todo ALX : debug
209 /// @todo ALX : debug
229 emit dataProvidedFailed(dataId);
210 emit dataProvidedFailed(dataId);
230 }
211 }
231 }
212 }
232 m_AcqIdToRequestProgressMap.erase(dataId);
213 m_AcqIdToRequestProgressMap.erase(dataId);
233 }
214 }
234 else {
215 else {
235 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
216 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
236 emit dataProvidedFailed(dataId);
217 emit dataProvidedFailed(dataId);
237 }
218 }
238
219
239 };
220 };
240 auto httpFinishedLambda
221 auto httpFinishedLambda
241 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
222 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
242
223
243 // Don't do anything if the reply was abort
224 // Don't do anything if the reply was abort
244 if (reply->error() == QNetworkReply::NoError) {
225 if (reply->error() == QNetworkReply::NoError) {
245 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
226 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
246
227
247 qCInfo(LOG_AmdaProvider())
228 qCInfo(LOG_AmdaProvider())
248 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
229 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
249 // Executes request for downloading file //
230 // Executes request for downloading file //
250
231
251 // Creates destination file
232 // Creates destination file
252 if (tempFile->open()) {
233 if (tempFile->open()) {
253 // Executes request and store the request for progression
234 // Executes request and store the request for progression
254 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
235 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
255 updateRequestProgress(dataId, request, 0.0);
236 updateRequestProgress(dataId, request, 0.0);
256 emit requestConstructed(request, dataId, httpDownloadFinished);
237 emit requestConstructed(request, dataId, httpDownloadFinished);
257 }
238 }
258 else {
239 else {
259 emit dataProvidedFailed(dataId);
240 emit dataProvidedFailed(dataId);
260 }
241 }
261 }
242 }
262 else {
243 else {
263 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
244 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
264 m_AcqIdToRequestProgressMap.erase(dataId);
245 m_AcqIdToRequestProgressMap.erase(dataId);
265 emit dataProvidedFailed(dataId);
246 emit dataProvidedFailed(dataId);
266 }
247 }
267 };
248 };
268
249
269 // //////////////// //
250 // //////////////// //
270 // Executes request //
251 // Executes request //
271 // //////////////// //
252 // //////////////// //
272
253
273 auto request = std::make_shared<QNetworkRequest>(url);
254 auto request = std::make_shared<QNetworkRequest>(url);
274 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
255 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
275 updateRequestProgress(token, request, 0.0);
256 updateRequestProgress(token, request, 0.0);
276
257
277 emit requestConstructed(request, token, httpFinishedLambda);
258 emit requestConstructed(request, token, httpFinishedLambda);
278 }
259 }
279
260
280 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
261 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
281 std::shared_ptr<QNetworkRequest> request, double progress)
262 std::shared_ptr<QNetworkRequest> request, double progress)
282 {
263 {
283 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
264 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
284 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
265 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
285 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
266 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
286 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
267 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
287 auto requestProgressMapIt = requestProgressMap.find(request);
268 auto requestProgressMapIt = requestProgressMap.find(request);
288 if (requestProgressMapIt != requestProgressMap.end()) {
269 if (requestProgressMapIt != requestProgressMap.end()) {
289 requestProgressMapIt->second = progress;
270 requestProgressMapIt->second = progress;
290 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
271 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
291 << acqIdentifier << request.get() << progress;
272 << acqIdentifier << request.get() << progress;
292 }
273 }
293 else {
274 else {
294 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
275 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
295 << request.get() << progress;
276 << request.get() << progress;
296 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
277 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
297 }
278 }
298 }
279 }
299 else {
280 else {
300 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
281 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
301 << acqIdentifier << request.get() << progress;
282 << acqIdentifier << request.get() << progress;
302 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
283 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
303 requestProgressMap.insert(std::make_pair(request, progress));
284 requestProgressMap.insert(std::make_pair(request, progress));
304 m_AcqIdToRequestProgressMap.insert(
285 m_AcqIdToRequestProgressMap.insert(
305 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
286 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
306 }
287 }
307 }
288 }
@@ -1,42 +1,49
1 #include "AmdaResultParserDefs.h"
1 #include "AmdaResultParserDefs.h"
2
2
3 const QString END_TIME_PROPERTY = QStringLiteral("endTime");
3 const QString END_TIME_PROPERTY = QStringLiteral("endTime");
4 const QString FILL_VALUE_PROPERTY = QStringLiteral("fillValue");
4 const QString FILL_VALUE_PROPERTY = QStringLiteral("fillValue");
5 const QString MAX_BANDS_PROPERTY = QStringLiteral("maxBands");
5 const QString MAX_BANDS_PROPERTY = QStringLiteral("maxBands");
6 const QString MIN_BANDS_PROPERTY = QStringLiteral("minBands");
6 const QString MIN_BANDS_PROPERTY = QStringLiteral("minBands");
7 const QString MAX_SAMPLING_PROPERTY = QStringLiteral("maxSampling");
7 const QString MAX_SAMPLING_PROPERTY = QStringLiteral("maxSampling");
8 const QString MIN_SAMPLING_PROPERTY = QStringLiteral("minSampling");
8 const QString MIN_SAMPLING_PROPERTY = QStringLiteral("minSampling");
9 const QString START_TIME_PROPERTY = QStringLiteral("startTime");
9 const QString START_TIME_PROPERTY = QStringLiteral("startTime");
10 const QString X_AXIS_UNIT_PROPERTY = QStringLiteral("xAxisUnit");
10 const QString X_AXIS_UNIT_PROPERTY = QStringLiteral("xAxisUnit");
11 const QString Y_AXIS_UNIT_PROPERTY = QStringLiteral("yAxisUnit");
11 const QString Y_AXIS_UNIT_PROPERTY = QStringLiteral("yAxisUnit");
12 const QString VALUES_UNIT_PROPERTY = QStringLiteral("valuesUnit");
12 const QString VALUES_UNIT_PROPERTY = QStringLiteral("valuesUnit");
13
13
14 namespace {
15
16 const auto PARAMETER_UNITS_REGEX
17 = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.*)")};
18 }
19
14 const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX
20 const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX
15 = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
21 = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
16
22
23 const QRegularExpression ALTERNATIVE_X_AXIS_UNIT_REGEX = PARAMETER_UNITS_REGEX;
24
17 const QRegularExpression SPECTROGRAM_END_TIME_REGEX
25 const QRegularExpression SPECTROGRAM_END_TIME_REGEX
18 = QRegularExpression{QStringLiteral("\\s*INTERVAL_STOP\\s*:\\s*(.*)")};
26 = QRegularExpression{QStringLiteral("\\s*INTERVAL_STOP\\s*:\\s*(.*)")};
19
27
20 const QRegularExpression SPECTROGRAM_FILL_VALUE_REGEX
28 const QRegularExpression SPECTROGRAM_FILL_VALUE_REGEX
21 = QRegularExpression{QStringLiteral("\\s*PARAMETER_FILL_VALUE\\s*:\\s*(.*)")};
29 = QRegularExpression{QStringLiteral("\\s*PARAMETER_FILL_VALUE\\s*:\\s*(.*)")};
22
30
23 const QRegularExpression SPECTROGRAM_MAX_BANDS_REGEX
31 const QRegularExpression SPECTROGRAM_MAX_BANDS_REGEX
24 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_MAX_VALUES\\[0\\]\\s*:\\s*(.*)")};
32 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_MAX_VALUES\\[0\\]\\s*:\\s*(.*)")};
25
33
26 const QRegularExpression SPECTROGRAM_MIN_BANDS_REGEX
34 const QRegularExpression SPECTROGRAM_MIN_BANDS_REGEX
27 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_MIN_VALUES\\[0\\]\\s*:\\s*(.*)")};
35 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_MIN_VALUES\\[0\\]\\s*:\\s*(.*)")};
28
36
29 const QRegularExpression SPECTROGRAM_MAX_SAMPLING_REGEX
37 const QRegularExpression SPECTROGRAM_MAX_SAMPLING_REGEX
30 = QRegularExpression{QStringLiteral("\\s*DATASET_MAX_SAMPLING\\s*:\\s*(.*)")};
38 = QRegularExpression{QStringLiteral("\\s*DATASET_MAX_SAMPLING\\s*:\\s*(.*)")};
31
39
32 const QRegularExpression SPECTROGRAM_MIN_SAMPLING_REGEX
40 const QRegularExpression SPECTROGRAM_MIN_SAMPLING_REGEX
33 = QRegularExpression{QStringLiteral("\\s*DATASET_MIN_SAMPLING\\s*:\\s*(.*)")};
41 = QRegularExpression{QStringLiteral("\\s*DATASET_MIN_SAMPLING\\s*:\\s*(.*)")};
34
42
35 const QRegularExpression SPECTROGRAM_START_TIME_REGEX
43 const QRegularExpression SPECTROGRAM_START_TIME_REGEX
36 = QRegularExpression{QStringLiteral("\\s*INTERVAL_START\\s*:\\s*(.*)")};
44 = QRegularExpression{QStringLiteral("\\s*INTERVAL_START\\s*:\\s*(.*)")};
37
45
38 const QRegularExpression SPECTROGRAM_Y_AXIS_UNIT_REGEX
46 const QRegularExpression SPECTROGRAM_Y_AXIS_UNIT_REGEX
39 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_UNITS\\[0\\]\\s*:\\s*(.*)")};
47 = QRegularExpression{QStringLiteral("\\s*PARAMETER_TABLE_UNITS\\[0\\]\\s*:\\s*(.*)")};
40
48
41 const QRegularExpression SPECTROGRAM_VALUES_UNIT_REGEX
49 const QRegularExpression SPECTROGRAM_VALUES_UNIT_REGEX = PARAMETER_UNITS_REGEX;
42 = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.*)")};
@@ -1,423 +1,432
1 #include "AmdaResultParserHelper.h"
1 #include "AmdaResultParserHelper.h"
2
2
3 #include <Common/DateUtils.h>
3 #include <Common/DateUtils.h>
4 #include <Common/SortUtils.h>
4 #include <Common/SortUtils.h>
5
5
6 #include <Data/DataSeriesUtils.h>
6 #include <Data/DataSeriesUtils.h>
7 #include <Data/ScalarSeries.h>
7 #include <Data/ScalarSeries.h>
8 #include <Data/SpectrogramSeries.h>
8 #include <Data/SpectrogramSeries.h>
9 #include <Data/Unit.h>
9 #include <Data/Unit.h>
10 #include <Data/VectorSeries.h>
10 #include <Data/VectorSeries.h>
11
11
12 #include <QtCore/QDateTime>
12 #include <QtCore/QDateTime>
13 #include <QtCore/QRegularExpression>
13 #include <QtCore/QRegularExpression>
14
14
15 #include <functional>
15 #include <functional>
16
16
17 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
17 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
18
18
19 namespace {
19 namespace {
20
20
21 // ///////// //
21 // ///////// //
22 // Constants //
22 // Constants //
23 // ///////// //
23 // ///////// //
24
24
25 /// Separator between values in a result line
25 /// Separator between values in a result line
26 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
26 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
27
27
28 /// Format for dates in result files
28 /// Format for dates in result files
29 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
29 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
30
30
31 // /////// //
31 // /////// //
32 // Methods //
32 // Methods //
33 // /////// //
33 // /////// //
34
34
35 /**
35 /**
36 * Checks that the properties contain a specific unit and that this unit is valid
36 * Checks that the properties contain a specific unit and that this unit is valid
37 * @param properties the properties map in which to search unit
37 * @param properties the properties map in which to search unit
38 * @param key the key to search for the unit in the properties
38 * @param key the key to search for the unit in the properties
39 * @param errorMessage the error message to log in case the unit is invalid
39 * @param errorMessage the error message to log in case the unit is invalid
40 * @return true if the unit is valid, false it it's invalid or was not found in the properties
40 * @return true if the unit is valid, false it it's invalid or was not found in the properties
41 */
41 */
42 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
42 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
43 {
43 {
44 auto unit = properties.value(key).value<Unit>();
44 auto unit = properties.value(key).value<Unit>();
45 if (unit.m_Name.isEmpty()) {
45 if (unit.m_Name.isEmpty()) {
46 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
46 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
47 return false;
47 return false;
48 }
48 }
49
49
50 return true;
50 return true;
51 }
51 }
52
52
53 QDateTime dateTimeFromString(const QString &stringDate) noexcept
53 QDateTime dateTimeFromString(const QString &stringDate) noexcept
54 {
54 {
55 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
55 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
56 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
56 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
57 #else
57 #else
58 return QDateTime::fromString(stringDate, DATE_FORMAT);
58 return QDateTime::fromString(stringDate, DATE_FORMAT);
59 #endif
59 #endif
60 }
60 }
61
61
62 /// Converts a string date to a double date
62 /// Converts a string date to a double date
63 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
63 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
64 double doubleDate(const QString &stringDate) noexcept
64 double doubleDate(const QString &stringDate) noexcept
65 {
65 {
66 // Format: yyyy-MM-ddThh:mm:ss.zzz
66 // Format: yyyy-MM-ddThh:mm:ss.zzz
67 auto dateTime = dateTimeFromString(stringDate);
67 auto dateTime = dateTimeFromString(stringDate);
68 dateTime.setTimeSpec(Qt::UTC);
68 dateTime.setTimeSpec(Qt::UTC);
69 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
69 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
70 : std::numeric_limits<double>::quiet_NaN();
70 : std::numeric_limits<double>::quiet_NaN();
71 }
71 }
72
72
73 /**
73 /**
74 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
74 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
75 * @param xAxisData the vector in which to store the x-axis data extracted
75 * @param xAxisData the vector in which to store the x-axis data extracted
76 * @param valuesData the vector in which to store the value extracted
76 * @param valuesData the vector in which to store the value extracted
77 * @param line the line to read to extract the property
77 * @param line the line to read to extract the property
78 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
78 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
79 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
79 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
80 * and inserted first, then the value of the first column, and finally the value of the second
80 * and inserted first, then the value of the first column, and finally the value of the second
81 * column.
81 * column.
82 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
82 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
83 * value is -1, then this value is considered as invalid and converted to NaN
83 * value is -1, then this value is considered as invalid and converted to NaN
84 */
84 */
85 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
85 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
86 const QString &line, const std::vector<int> &valuesIndexes,
86 const QString &line, const std::vector<int> &valuesIndexes,
87 double fillValue = std::numeric_limits<double>::quiet_NaN())
87 double fillValue = std::numeric_limits<double>::quiet_NaN())
88 {
88 {
89 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
89 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
90
90
91 // Checks that the line contains expected number of values + x-axis value
91 // Checks that the line contains expected number of values + x-axis value
92 if (static_cast<size_t>(lineData.size()) == valuesIndexes.size() + 1) {
92 if (static_cast<size_t>(lineData.size()) == valuesIndexes.size() + 1) {
93 // X : the data is converted from date to double (in secs)
93 // X : the data is converted from date to double (in secs)
94 auto x = doubleDate(lineData.at(0));
94 auto x = doubleDate(lineData.at(0));
95
95
96 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
96 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
97 if (!std::isnan(x)) {
97 if (!std::isnan(x)) {
98 xAxisData.push_back(x);
98 xAxisData.push_back(x);
99
99
100 // Values
100 // Values
101 for (auto valueIndex : valuesIndexes) {
101 for (auto valueIndex : valuesIndexes) {
102 bool valueOk;
102 bool valueOk;
103 // we use valueIndex + 1 to skip column 0 (x-axis value)
103 // we use valueIndex + 1 to skip column 0 (x-axis value)
104 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
104 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
105
105
106 if (!valueOk) {
106 if (!valueOk) {
107 qCWarning(LOG_AmdaResultParserHelper())
107 qCWarning(LOG_AmdaResultParserHelper())
108 << QObject::tr(
108 << QObject::tr(
109 "Value from (line %1, column %2) is invalid and will be "
109 "Value from (line %1, column %2) is invalid and will be "
110 "converted to NaN")
110 "converted to NaN")
111 .arg(line, valueIndex);
111 .arg(line, valueIndex);
112 value = std::numeric_limits<double>::quiet_NaN();
112 value = std::numeric_limits<double>::quiet_NaN();
113 }
113 }
114
114
115 // Handles fill value
115 // Handles fill value
116 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
116 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
117 value = std::numeric_limits<double>::quiet_NaN();
117 value = std::numeric_limits<double>::quiet_NaN();
118 }
118 }
119
119
120 valuesData.push_back(value);
120 valuesData.push_back(value);
121 }
121 }
122 }
122 }
123 else {
123 else {
124 qCWarning(LOG_AmdaResultParserHelper())
124 qCWarning(LOG_AmdaResultParserHelper())
125 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
125 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
126 }
126 }
127 }
127 }
128 else {
128 else {
129 qCWarning(LOG_AmdaResultParserHelper())
129 qCWarning(LOG_AmdaResultParserHelper())
130 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
130 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
131 }
131 }
132 }
132 }
133
133
134 /**
134 /**
135 * Reads a line from the AMDA file and tries to extract a property from it
135 * Reads a line from the AMDA file and tries to extract a property from it
136 * @param properties the properties map in which to put the property extracted from the line
136 * @param properties the properties map in which to put the property extracted from the line
137 * @param key the key to which the property is added in the properties map
137 * @param key the key to which the property is added in the properties map
138 * @param line the line to read to extract the property
138 * @param line the line to read to extract the property
139 * @param regex the expected regex to extract the property. If the line matches this regex, the
139 * @param regexes the expected regexes to extract the property. If the line matches one regex, the
140 * property is generated
140 * property is generated
141 * @param fun the function used to generate the property
141 * @param fun the function used to generate the property
142 * @return true if the property could be generated, false if the line does not match the regex, or
142 * @return true if the property could be generated, false if the line does not match the regex, or
143 * if a property has already been generated for the key
143 * if a property has already been generated for the key
144 */
144 */
145 template <typename GeneratePropertyFun>
145 template <typename GeneratePropertyFun>
146 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
146 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
147 const QRegularExpression &regex, GeneratePropertyFun fun)
147 const std::vector<QRegularExpression> &regexes, GeneratePropertyFun fun)
148 {
148 {
149 if (properties.contains(key)) {
149 if (properties.contains(key)) {
150 return false;
150 return false;
151 }
151 }
152
152
153 auto match = regex.match(line);
153 // Searches for a match among all possible regexes
154 if (match.hasMatch()) {
154 auto hasMatch = false;
155 properties.insert(key, fun(match));
155 for (auto regexIt = regexes.cbegin(), end = regexes.cend(); regexIt != end && !hasMatch;
156 ++regexIt) {
157 auto match = regexIt->match(line);
158 auto hasMatch = match.hasMatch();
159 if (hasMatch) {
160 properties.insert(key, fun(match));
161 }
156 }
162 }
157
163
158 return match.hasMatch();
164 return hasMatch;
159 }
165 }
160
166
161 /**
167 /**
162 * Reads a line from the AMDA file and tries to extract a data from it. Date is converted to double
168 * Reads a line from the AMDA file and tries to extract a data from it. Date is converted to double
163 * @sa tryReadProperty()
169 * @sa tryReadProperty()
164 */
170 */
165 bool tryReadDate(Properties &properties, const QString &key, const QString &line,
171 bool tryReadDate(Properties &properties, const QString &key, const QString &line,
166 const QRegularExpression &regex, bool timeUnit = false)
172 const std::vector<QRegularExpression> &regexes, bool timeUnit = false)
167 {
173 {
168 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
174 return tryReadProperty(properties, key, line, regexes, [timeUnit](const auto &match) {
169 return QVariant::fromValue(doubleDate(match.captured(1)));
175 return QVariant::fromValue(doubleDate(match.captured(1)));
170 });
176 });
171 }
177 }
172
178
173 /**
179 /**
174 * Reads a line from the AMDA file and tries to extract a double from it
180 * Reads a line from the AMDA file and tries to extract a double from it
175 * @sa tryReadProperty()
181 * @sa tryReadProperty()
176 */
182 */
177 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
183 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
178 const QRegularExpression &regex)
184 const std::vector<QRegularExpression> &regexes)
179 {
185 {
180 return tryReadProperty(properties, key, line, regex, [](const auto &match) {
186 return tryReadProperty(properties, key, line, regexes, [](const auto &match) {
181 bool ok;
187 bool ok;
182
188
183 // If the value can't be converted to double, it is set to NaN
189 // If the value can't be converted to double, it is set to NaN
184 auto doubleValue = match.captured(1).toDouble(&ok);
190 auto doubleValue = match.captured(1).toDouble(&ok);
185 if (!ok) {
191 if (!ok) {
186 doubleValue = std::numeric_limits<double>::quiet_NaN();
192 doubleValue = std::numeric_limits<double>::quiet_NaN();
187 }
193 }
188
194
189 return QVariant::fromValue(doubleValue);
195 return QVariant::fromValue(doubleValue);
190 });
196 });
191 }
197 }
192
198
193 /**
199 /**
194 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
200 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
195 * @param sep the separator of double values in the line
201 * @param sep the separator of double values in the line
196 * @sa tryReadProperty()
202 * @sa tryReadProperty()
197 */
203 */
198 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
204 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
199 const QRegularExpression &regex, const QString &sep = QStringLiteral(","))
205 const std::vector<QRegularExpression> &regexes,
206 const QString &sep = QStringLiteral(","))
200 {
207 {
201 return tryReadProperty(properties, key, line, regex, [sep](const auto &match) {
208 return tryReadProperty(properties, key, line, regexes, [sep](const auto &match) {
202 std::vector<double> doubleValues{};
209 std::vector<double> doubleValues{};
203
210
204 // If the value can't be converted to double, it is set to NaN
211 // If the value can't be converted to double, it is set to NaN
205 auto values = match.captured(1).split(sep);
212 auto values = match.captured(1).split(sep);
206 for (auto value : values) {
213 for (auto value : values) {
207 bool ok;
214 bool ok;
208
215
209 auto doubleValue = value.toDouble(&ok);
216 auto doubleValue = value.toDouble(&ok);
210 if (!ok) {
217 if (!ok) {
211 doubleValue = std::numeric_limits<double>::quiet_NaN();
218 doubleValue = std::numeric_limits<double>::quiet_NaN();
212 }
219 }
213
220
214 doubleValues.push_back(doubleValue);
221 doubleValues.push_back(doubleValue);
215 }
222 }
216
223
217 return QVariant::fromValue(doubleValues);
224 return QVariant::fromValue(doubleValues);
218 });
225 });
219 }
226 }
220
227
221 /**
228 /**
222 * Reads a line from the AMDA file and tries to extract a unit from it
229 * Reads a line from the AMDA file and tries to extract a unit from it
223 * @sa tryReadProperty()
230 * @sa tryReadProperty()
224 */
231 */
225 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
232 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
226 const QRegularExpression &regex, bool timeUnit = false)
233 const std::vector<QRegularExpression> &regexes, bool timeUnit = false)
227 {
234 {
228 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
235 return tryReadProperty(properties, key, line, regexes, [timeUnit](const auto &match) {
229 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
236 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
230 });
237 });
231 }
238 }
232
239
233 } // namespace
240 } // namespace
234
241
235 // ////////////////// //
242 // ////////////////// //
236 // ScalarParserHelper //
243 // ScalarParserHelper //
237 // ////////////////// //
244 // ////////////////// //
238
245
239 bool ScalarParserHelper::checkProperties()
246 bool ScalarParserHelper::checkProperties()
240 {
247 {
241 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
248 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
242 QObject::tr("The x-axis unit could not be found in the file"));
249 QObject::tr("The x-axis unit could not be found in the file"));
243 }
250 }
244
251
245 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
252 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
246 {
253 {
247 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
254 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
248 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
255 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
249 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
256 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
250 }
257 }
251
258
252 void ScalarParserHelper::readPropertyLine(const QString &line)
259 void ScalarParserHelper::readPropertyLine(const QString &line)
253 {
260 {
254 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
261 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line,
262 {DEFAULT_X_AXIS_UNIT_REGEX, ALTERNATIVE_X_AXIS_UNIT_REGEX}, true);
255 }
263 }
256
264
257 void ScalarParserHelper::readResultLine(const QString &line)
265 void ScalarParserHelper::readResultLine(const QString &line)
258 {
266 {
259 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
267 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
260 }
268 }
261
269
262 std::vector<int> ScalarParserHelper::valuesIndexes() const
270 std::vector<int> ScalarParserHelper::valuesIndexes() const
263 {
271 {
264 // Only one value to read
272 // Only one value to read
265 static auto result = std::vector<int>{0};
273 static auto result = std::vector<int>{0};
266 return result;
274 return result;
267 }
275 }
268
276
269 // /////////////////////// //
277 // /////////////////////// //
270 // SpectrogramParserHelper //
278 // SpectrogramParserHelper //
271 // /////////////////////// //
279 // /////////////////////// //
272
280
273 bool SpectrogramParserHelper::checkProperties()
281 bool SpectrogramParserHelper::checkProperties()
274 {
282 {
275 // Generates y-axis data from bands extracted (take the middle of the intervals)
283 // Generates y-axis data from bands extracted (take the middle of the intervals)
276 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
284 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
277 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
285 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
278
286
279 if (minBands.size() < 2 || minBands.size() != maxBands.size()) {
287 if (minBands.size() < 2 || minBands.size() != maxBands.size()) {
280 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
288 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
281 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
289 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
282 return false;
290 return false;
283 }
291 }
284
292
285 std::transform(
293 std::transform(
286 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
294 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
287 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
295 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
288
296
289 // Generates values indexes, i.e. the order in which each value will be retrieved (in ascending
297 // Generates values indexes, i.e. the order in which each value will be retrieved (in ascending
290 // order of the associated bands)
298 // order of the associated bands)
291 m_ValuesIndexes = SortUtils::sortPermutation(m_YAxisData, std::less<double>());
299 m_ValuesIndexes = SortUtils::sortPermutation(m_YAxisData, std::less<double>());
292
300
293 // Sorts y-axis data accoding to the ascending order
301 // Sorts y-axis data accoding to the ascending order
294 m_YAxisData = SortUtils::sort(m_YAxisData, 1, m_ValuesIndexes);
302 m_YAxisData = SortUtils::sort(m_YAxisData, 1, m_ValuesIndexes);
295
303
296 // Sets fill value
304 // Sets fill value
297 m_FillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
305 m_FillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
298
306
299 return true;
307 return true;
300 }
308 }
301
309
302 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
310 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
303 {
311 {
304 // Before creating the series, we handle its data holes
312 // Before creating the series, we handle its data holes
305 handleDataHoles();
313 handleDataHoles();
306
314
307 return std::make_shared<SpectrogramSeries>(
315 return std::make_shared<SpectrogramSeries>(
308 std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData),
316 std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData),
309 Unit{"t", true}, // x-axis unit is always a time unit
317 Unit{"t", true}, // x-axis unit is always a time unit
310 m_Properties.value(Y_AXIS_UNIT_PROPERTY).value<Unit>(),
318 m_Properties.value(Y_AXIS_UNIT_PROPERTY).value<Unit>(),
311 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>(),
319 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>(),
312 m_Properties.value(MIN_SAMPLING_PROPERTY).value<double>());
320 m_Properties.value(MIN_SAMPLING_PROPERTY).value<double>());
313 }
321 }
314
322
315 void SpectrogramParserHelper::readPropertyLine(const QString &line)
323 void SpectrogramParserHelper::readPropertyLine(const QString &line)
316 {
324 {
317 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
325 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
318 // property has been generated for the line), the line is treated as processed and the other
326 // property has been generated for the line), the line is treated as processed and the other
319 // functions are not called
327 // functions are not called
320 std::vector<std::function<bool()> > functions{
328 std::vector<std::function<bool()> > functions{
321 // values unit
329 // values unit
322 [&] {
330 [&] {
323 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
331 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
324 SPECTROGRAM_VALUES_UNIT_REGEX);
332 {SPECTROGRAM_VALUES_UNIT_REGEX});
325 },
333 },
326 // y-axis unit
334 // y-axis unit
327 [&] {
335 [&] {
328 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
336 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
329 SPECTROGRAM_Y_AXIS_UNIT_REGEX);
337 {SPECTROGRAM_Y_AXIS_UNIT_REGEX});
330 },
338 },
331 // min sampling
339 // min sampling
332 [&] {
340 [&] {
333 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
341 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
334 SPECTROGRAM_MIN_SAMPLING_REGEX);
342 {SPECTROGRAM_MIN_SAMPLING_REGEX});
335 },
343 },
336 // max sampling
344 // max sampling
337 [&] {
345 [&] {
338 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
346 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
339 SPECTROGRAM_MAX_SAMPLING_REGEX);
347 {SPECTROGRAM_MAX_SAMPLING_REGEX});
340 },
348 },
341 // fill value
349 // fill value
342 [&] {
350 [&] {
343 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
351 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
344 SPECTROGRAM_FILL_VALUE_REGEX);
352 {SPECTROGRAM_FILL_VALUE_REGEX});
345 },
353 },
346 // min bounds of each band
354 // min bounds of each band
347 [&] {
355 [&] {
348 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
356 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
349 SPECTROGRAM_MIN_BANDS_REGEX);
357 {SPECTROGRAM_MIN_BANDS_REGEX});
350 },
358 },
351 // max bounds of each band
359 // max bounds of each band
352 [&] {
360 [&] {
353 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
361 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
354 SPECTROGRAM_MAX_BANDS_REGEX);
362 {SPECTROGRAM_MAX_BANDS_REGEX});
355 },
363 },
356 // start time of data
364 // start time of data
357 [&] {
365 [&] {
358 return tryReadDate(m_Properties, START_TIME_PROPERTY, line,
366 return tryReadDate(m_Properties, START_TIME_PROPERTY, line,
359 SPECTROGRAM_START_TIME_REGEX);
367 {SPECTROGRAM_START_TIME_REGEX});
360 },
368 },
361 // end time of data
369 // end time of data
362 [&] {
370 [&] {
363 return tryReadDate(m_Properties, END_TIME_PROPERTY, line, SPECTROGRAM_END_TIME_REGEX);
371 return tryReadDate(m_Properties, END_TIME_PROPERTY, line, {SPECTROGRAM_END_TIME_REGEX});
364 }};
372 }};
365
373
366 for (auto function : functions) {
374 for (auto function : functions) {
367 // Stops at the first function that is valid
375 // Stops at the first function that is valid
368 if (function()) {
376 if (function()) {
369 return;
377 return;
370 }
378 }
371 }
379 }
372 }
380 }
373
381
374 void SpectrogramParserHelper::readResultLine(const QString &line)
382 void SpectrogramParserHelper::readResultLine(const QString &line)
375 {
383 {
376 tryReadResult(m_XAxisData, m_ValuesData, line, m_ValuesIndexes, m_FillValue);
384 tryReadResult(m_XAxisData, m_ValuesData, line, m_ValuesIndexes, m_FillValue);
377 }
385 }
378
386
379 void SpectrogramParserHelper::handleDataHoles()
387 void SpectrogramParserHelper::handleDataHoles()
380 {
388 {
381 // Fills data holes according to the max resolution found in the AMDA file
389 // Fills data holes according to the max resolution found in the AMDA file
382 auto resolution = m_Properties.value(MAX_SAMPLING_PROPERTY).value<double>();
390 auto resolution = m_Properties.value(MAX_SAMPLING_PROPERTY).value<double>();
383 auto fillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
391 auto fillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
384 auto minBound = m_Properties.value(START_TIME_PROPERTY).value<double>();
392 auto minBound = m_Properties.value(START_TIME_PROPERTY).value<double>();
385 auto maxBound = m_Properties.value(END_TIME_PROPERTY).value<double>();
393 auto maxBound = m_Properties.value(END_TIME_PROPERTY).value<double>();
386
394
387 DataSeriesUtils::fillDataHoles(m_XAxisData, m_ValuesData, resolution, fillValue, minBound,
395 DataSeriesUtils::fillDataHoles(m_XAxisData, m_ValuesData, resolution, fillValue, minBound,
388 maxBound);
396 maxBound);
389 }
397 }
390
398
391 // ////////////////// //
399 // ////////////////// //
392 // VectorParserHelper //
400 // VectorParserHelper //
393 // ////////////////// //
401 // ////////////////// //
394
402
395 bool VectorParserHelper::checkProperties()
403 bool VectorParserHelper::checkProperties()
396 {
404 {
397 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
405 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
398 QObject::tr("The x-axis unit could not be found in the file"));
406 QObject::tr("The x-axis unit could not be found in the file"));
399 }
407 }
400
408
401 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
409 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
402 {
410 {
403 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
411 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
404 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
412 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
405 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
413 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
406 }
414 }
407
415
408 void VectorParserHelper::readPropertyLine(const QString &line)
416 void VectorParserHelper::readPropertyLine(const QString &line)
409 {
417 {
410 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
418 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line,
419 {DEFAULT_X_AXIS_UNIT_REGEX, ALTERNATIVE_X_AXIS_UNIT_REGEX}, true);
411 }
420 }
412
421
413 void VectorParserHelper::readResultLine(const QString &line)
422 void VectorParserHelper::readResultLine(const QString &line)
414 {
423 {
415 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
424 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
416 }
425 }
417
426
418 std::vector<int> VectorParserHelper::valuesIndexes() const
427 std::vector<int> VectorParserHelper::valuesIndexes() const
419 {
428 {
420 // 3 values to read, in order in the file (x, y, z)
429 // 3 values to read, in order in the file (x, y, z)
421 static auto result = std::vector<int>{0, 1, 2};
430 static auto result = std::vector<int>{0, 1, 2};
422 return result;
431 return result;
423 }
432 }
General Comments 0
You need to be logged in to leave comments. Login now