@@ -0,0 +1,26 | |||||
|
1 | include_directories(include) | |||
|
2 | FILE (GLOB_RECURSE python_providers | |||
|
3 | include/*.h | |||
|
4 | src/*.cpp | |||
|
5 | resources/*.qrc | |||
|
6 | ) | |||
|
7 | ||||
|
8 | add_definitions(-DQT_PLUGIN) | |||
|
9 | add_definitions(-DSCIQLOP_PLUGIN_JSON_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/python_providers.json") | |||
|
10 | if(NOT BUILD_SHARED_LIBS) | |||
|
11 | add_definitions(-DQT_STATICPLUGIN) | |||
|
12 | endif() | |||
|
13 | ||||
|
14 | add_library(python_providers ${python_providers}) | |||
|
15 | SET_TARGET_PROPERTIES(python_providers PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) | |||
|
16 | ||||
|
17 | target_link_libraries(python_providers PUBLIC sciqlopgui) | |||
|
18 | target_link_libraries(python_providers PRIVATE pybind11::embed) | |||
|
19 | ADD_DEFINITIONS(-DQT_NO_KEYWORDS) | |||
|
20 | install(TARGETS python_providers | |||
|
21 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop | |||
|
22 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop | |||
|
23 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | |||
|
24 | ||||
|
25 | include(sciqlop_tests) | |||
|
26 |
@@ -0,0 +1,25 | |||||
|
1 | #ifndef PYTHON_PROVIDERS_H | |||
|
2 | #define PYTHON_PROVIDERS_H | |||
|
3 | ||||
|
4 | #include <Plugin/IPlugin.h> | |||
|
5 | ||||
|
6 | ||||
|
7 | #include <memory> | |||
|
8 | ||||
|
9 | #ifndef SCIQLOP_PLUGIN_JSON_FILE_PATH | |||
|
10 | #define SCIQLOP_PLUGIN_JSON_FILE_PATH "python_providers.json" | |||
|
11 | #endif | |||
|
12 | ||||
|
13 | class DataSourceItem; | |||
|
14 | ||||
|
15 | class PythonProviders : public QObject, public IPlugin | |||
|
16 | { | |||
|
17 | Q_OBJECT | |||
|
18 | Q_INTERFACES(IPlugin) | |||
|
19 | Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE SCIQLOP_PLUGIN_JSON_FILE_PATH) | |||
|
20 | public: | |||
|
21 | /// @sa IPlugin::initialize() | |||
|
22 | void initialize() override; | |||
|
23 | }; | |||
|
24 | ||||
|
25 | #endif // PYTHON_PROVIDERS_H |
@@ -0,0 +1,9 | |||||
|
1 | #include "python_providers.h" | |||
|
2 | #include <pybind11/embed.h> | |||
|
3 | namespace py = pybind11; | |||
|
4 | ||||
|
5 | void PythonProviders::initialize() | |||
|
6 | { | |||
|
7 | py::scoped_interpreter guard {}; | |||
|
8 | py::print("Hello, World!"); | |||
|
9 | } |
@@ -1,41 +1,42 | |||||
1 | include_directories(include) |
|
1 | include_directories(include) | |
2 |
|
2 | |||
3 | FILE (GLOB_RECURSE app_SRCS |
|
3 | FILE (GLOB_RECURSE app_SRCS | |
4 | include/*.h |
|
4 | include/*.h | |
5 | src/*.cpp |
|
5 | src/*.cpp | |
6 | resources/*.qrc |
|
6 | resources/*.qrc | |
7 | ) |
|
7 | ) | |
8 |
|
8 | |||
9 | QT5_WRAP_UI(UiGenerated_SRCS |
|
9 | QT5_WRAP_UI(UiGenerated_SRCS | |
10 | ui/MainWindow.ui |
|
10 | ui/MainWindow.ui | |
11 | ) |
|
11 | ) | |
12 |
|
12 | |||
13 | add_executable(sciqlopapp WIN32 ${app_SRCS} ${UiGenerated_SRCS}) |
|
13 | add_executable(sciqlopapp WIN32 ${app_SRCS} ${UiGenerated_SRCS}) | |
14 | if(NOT BUILD_SHARED_LIBS) |
|
14 | if(NOT BUILD_SHARED_LIBS) | |
15 | add_definitions(-DQT_STATICPLUGIN) |
|
15 | add_definitions(-DQT_STATICPLUGIN) | |
16 | if(BUILD_PLUGINS) |
|
16 | if(BUILD_PLUGINS) | |
17 | target_link_libraries(sciqlopapp mockplugin) |
|
17 | target_link_libraries(sciqlopapp mockplugin) | |
18 | target_link_libraries(sciqlopapp amdaplugin) |
|
18 | #target_link_libraries(sciqlopapp amdaplugin) | |
|
19 | target_link_libraries(sciqlopapp python_providers) | |||
19 | endif() |
|
20 | endif() | |
20 | endif() |
|
21 | endif() | |
21 |
|
22 | |||
22 | if(NOT BUILD_PLUGINS) |
|
23 | if(NOT BUILD_PLUGINS) | |
23 | add_definitions(-DSQP_NO_PLUGINS) |
|
24 | add_definitions(-DSQP_NO_PLUGINS) | |
24 | endif() |
|
25 | endif() | |
25 |
|
26 | |||
26 | target_link_libraries(sciqlopapp |
|
27 | target_link_libraries(sciqlopapp | |
27 | Qt5::Core |
|
28 | Qt5::Core | |
28 | Qt5::Widgets |
|
29 | Qt5::Widgets | |
29 | Qt5::Network |
|
30 | Qt5::Network | |
30 | Qt5::PrintSupport |
|
31 | Qt5::PrintSupport | |
31 | Qt5::Svg |
|
32 | Qt5::Svg | |
32 | sciqlopgui |
|
33 | sciqlopgui | |
33 | sciqlopcore |
|
34 | sciqlopcore | |
34 | ) |
|
35 | ) | |
35 |
|
36 | |||
36 | install(TARGETS sciqlopapp DESTINATION ${CMAKE_INSTALL_BINDIR}) |
|
37 | install(TARGETS sciqlopapp DESTINATION ${CMAKE_INSTALL_BINDIR}) | |
37 | install(FILES resources/SciQLOP.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) |
|
38 | install(FILES resources/SciQLOP.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) | |
38 | install(FILES resources/SciQLOP.appdata.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/) |
|
39 | install(FILES resources/SciQLOP.appdata.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/) | |
39 | install(FILES resources/sciqlopLOGO.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/SciQLOP/icons/) |
|
40 | install(FILES resources/sciqlopLOGO.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/SciQLOP/icons/) | |
40 |
|
41 | |||
41 |
|
42 |
@@ -1,99 +1,100 | |||||
1 | /*------------------------------------------------------------------------------ |
|
1 | /*------------------------------------------------------------------------------ | |
2 | -- This file is a part of the QLop Software |
|
2 | -- This file is a part of the QLop Software | |
3 | -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS |
|
3 | -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS | |
4 | -- |
|
4 | -- | |
5 | -- This program is free software; you can redistribute it and/or modify |
|
5 | -- This program is free software; you can redistribute it and/or modify | |
6 | -- it under the terms of the GNU General Public License as published by |
|
6 | -- it under the terms of the GNU General Public License as published by | |
7 | -- the Free Software Foundation; either version 2 of the License, or |
|
7 | -- the Free Software Foundation; either version 2 of the License, or | |
8 | -- (at your option) any later version. |
|
8 | -- (at your option) any later version. | |
9 | -- |
|
9 | -- | |
10 | -- This program is distributed in the hope that it will be useful, |
|
10 | -- This program is distributed in the hope that it will be useful, | |
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | -- GNU General Public License for more details. |
|
13 | -- GNU General Public License for more details. | |
14 | -- |
|
14 | -- | |
15 | -- You should have received a copy of the GNU General Public License |
|
15 | -- You should have received a copy of the GNU General Public License | |
16 | -- along with this program; if not, write to the Free Software |
|
16 | -- along with this program; if not, write to the Free Software | |
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | -------------------------------------------------------------------------------*/ |
|
18 | -------------------------------------------------------------------------------*/ | |
19 | /*-- Author : Alexis Jeandet |
|
19 | /*-- Author : Alexis Jeandet | |
20 | -- Mail : alexis.jeandet@member.fsf.org |
|
20 | -- Mail : alexis.jeandet@member.fsf.org | |
21 | ----------------------------------------------------------------------------*/ |
|
21 | ----------------------------------------------------------------------------*/ | |
22 | #include "MainWindow.h" |
|
22 | #include "MainWindow.h" | |
23 | #include <QProcessEnvironment> |
|
23 | #include <QProcessEnvironment> | |
24 | #include <QThread> |
|
24 | #include <QThread> | |
25 | #include <SqpApplication.h> |
|
25 | #include <SqpApplication.h> | |
26 | #include <qglobal.h> |
|
26 | #include <qglobal.h> | |
27 |
|
27 | |||
28 | #include <PluginManager/PluginManager.h> |
|
28 | #include <PluginManager/PluginManager.h> | |
29 | #include <QDir> |
|
29 | #include <QDir> | |
30 | #include <QtPlugin> |
|
30 | #include <QtPlugin> | |
31 |
|
31 | |||
32 | #include <QLoggingCategory> |
|
32 | #include <QLoggingCategory> | |
33 |
|
33 | |||
34 | Q_LOGGING_CATEGORY(LOG_Main, "Main") |
|
34 | Q_LOGGING_CATEGORY(LOG_Main, "Main") | |
35 |
|
35 | |||
36 | namespace |
|
36 | namespace | |
37 | { |
|
37 | { | |
38 |
|
38 | |||
39 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); |
|
39 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); | |
40 |
|
40 | |||
41 |
|
41 | |||
42 | } // namespace |
|
42 | } // namespace | |
43 |
|
43 | |||
44 | int main(int argc, char* argv[]) |
|
44 | int main(int argc, char* argv[]) | |
45 | { |
|
45 | { | |
46 | #ifdef QT_STATICPLUGIN |
|
46 | #ifdef QT_STATICPLUGIN | |
47 | #ifndef SQP_NO_PLUGINS |
|
47 | #ifndef SQP_NO_PLUGINS | |
48 | Q_IMPORT_PLUGIN(MockPlugin) |
|
48 | Q_IMPORT_PLUGIN(MockPlugin) | |
49 |
Q_IMPORT_PLUGIN( |
|
49 | Q_IMPORT_PLUGIN(PythonProviders) | |
50 | Q_INIT_RESOURCE(amdaresources); |
|
50 | // Q_IMPORT_PLUGIN(AmdaPlugin) | |
|
51 | // Q_INIT_RESOURCE(amdaresources); | |||
51 | #endif |
|
52 | #endif | |
52 | #endif |
|
53 | #endif | |
53 | Q_INIT_RESOURCE(sqpguiresources); |
|
54 | Q_INIT_RESOURCE(sqpguiresources); | |
54 |
|
55 | |||
55 | SqpApplication::setOrganizationName("LPP"); |
|
56 | SqpApplication::setOrganizationName("LPP"); | |
56 | SqpApplication::setOrganizationDomain("lpp.fr"); |
|
57 | SqpApplication::setOrganizationDomain("lpp.fr"); | |
57 | SqpApplication::setApplicationName("SciQLop"); |
|
58 | SqpApplication::setApplicationName("SciQLop"); | |
58 |
|
59 | |||
59 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); |
|
60 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); | |
60 |
|
61 | |||
61 | SqpApplication a { argc, argv }; |
|
62 | SqpApplication a { argc, argv }; | |
62 |
|
63 | |||
63 | MainWindow w; |
|
64 | MainWindow w; | |
64 | w.show(); |
|
65 | w.show(); | |
65 |
|
66 | |||
66 | // Loads plugins |
|
67 | // Loads plugins | |
67 | auto pluginDir = QDir { a.applicationDirPath() }; |
|
68 | auto pluginDir = QDir { a.applicationDirPath() }; | |
68 | auto pluginLookupPath = { |
|
69 | auto pluginLookupPath = { | |
69 | #if _WIN32 || _WIN64 |
|
70 | #if _WIN32 || _WIN64 | |
70 | a.applicationDirPath() + "/SciQLop" |
|
71 | a.applicationDirPath() + "/SciQLop" | |
71 | #else |
|
72 | #else | |
72 | a.applicationDirPath() + "/../lib64/SciQLop", |
|
73 | a.applicationDirPath() + "/../lib64/SciQLop", | |
73 | a.applicationDirPath() + "/../lib64/sciqlop", |
|
74 | a.applicationDirPath() + "/../lib64/sciqlop", | |
74 | a.applicationDirPath() + "/../lib/SciQLop", |
|
75 | a.applicationDirPath() + "/../lib/SciQLop", | |
75 | a.applicationDirPath() + "/../lib/sciqlop", |
|
76 | a.applicationDirPath() + "/../lib/sciqlop", | |
76 | #endif |
|
77 | #endif | |
77 | }; |
|
78 | }; | |
78 |
|
79 | |||
79 | #if _WIN32 || _WIN64 |
|
80 | #if _WIN32 || _WIN64 | |
80 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); |
|
81 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); | |
81 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); |
|
82 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); | |
82 | #endif |
|
83 | #endif | |
83 |
|
84 | |||
84 | PluginManager pluginManager {}; |
|
85 | PluginManager pluginManager {}; | |
85 |
|
86 | |||
86 | for (auto&& path : pluginLookupPath) |
|
87 | for (auto&& path : pluginLookupPath) | |
87 | { |
|
88 | { | |
88 | QDir directory { path }; |
|
89 | QDir directory { path }; | |
89 | if (directory.exists()) |
|
90 | if (directory.exists()) | |
90 | { |
|
91 | { | |
91 | qCDebug(LOG_Main()) |
|
92 | qCDebug(LOG_Main()) | |
92 | << QObject::tr("Plugin directory: %1").arg(directory.absolutePath()); |
|
93 | << QObject::tr("Plugin directory: %1").arg(directory.absolutePath()); | |
93 | pluginManager.loadPlugins(directory); |
|
94 | pluginManager.loadPlugins(directory); | |
94 | } |
|
95 | } | |
95 | } |
|
96 | } | |
96 | pluginManager.loadStaticPlugins(); |
|
97 | pluginManager.loadStaticPlugins(); | |
97 |
|
98 | |||
98 | return a.exec(); |
|
99 | return a.exec(); | |
99 | } |
|
100 | } |
@@ -1,395 +1,395 | |||||
1 | /*------------------------------------------------------------------------------ |
|
1 | /*------------------------------------------------------------------------------ | |
2 | -- This file is a part of the SciQLop Software |
|
2 | -- This file is a part of the SciQLop Software | |
3 | -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS |
|
3 | -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS | |
4 | -- |
|
4 | -- | |
5 | -- This program is free software; you can redistribute it and/or modify |
|
5 | -- This program is free software; you can redistribute it and/or modify | |
6 | -- it under the terms of the GNU General Public License as published by |
|
6 | -- it under the terms of the GNU General Public License as published by | |
7 | -- the Free Software Foundation; either version 2 of the License, or |
|
7 | -- the Free Software Foundation; either version 2 of the License, or | |
8 | -- (at your option) any later version. |
|
8 | -- (at your option) any later version. | |
9 | -- |
|
9 | -- | |
10 | -- This program is distributed in the hope that it will be useful, |
|
10 | -- This program is distributed in the hope that it will be useful, | |
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | -- GNU General Public License for more details. |
|
13 | -- GNU General Public License for more details. | |
14 | -- |
|
14 | -- | |
15 | -- You should have received a copy of the GNU General Public License |
|
15 | -- You should have received a copy of the GNU General Public License | |
16 | -- along with this program; if not, write to the Free Software |
|
16 | -- along with this program; if not, write to the Free Software | |
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | -------------------------------------------------------------------------------*/ |
|
18 | -------------------------------------------------------------------------------*/ | |
19 | /*-- Author : Alexis Jeandet |
|
19 | /*-- Author : Alexis Jeandet | |
20 | -- Mail : alexis.jeandet@member.fsf.org |
|
20 | -- Mail : alexis.jeandet@member.fsf.org | |
21 | ----------------------------------------------------------------------------*/ |
|
21 | ----------------------------------------------------------------------------*/ | |
22 | #include "MainWindow.h" |
|
22 | #include "MainWindow.h" | |
23 | #include "ui_MainWindow.h" |
|
23 | #include "ui_MainWindow.h" | |
24 |
|
24 | |||
25 | #include <Catalogue/CatalogueController.h> |
|
25 | #include <Catalogue/CatalogueController.h> | |
26 | //#include <Catalogue/CatalogueExplorer.h> |
|
26 | //#include <Catalogue/CatalogueExplorer.h> | |
27 | #include <DataSource/DataSourceController.h> |
|
27 | #include <DataSource/DataSourceController.h> | |
28 | #include <DataSource/DataSourceWidget.h> |
|
28 | #include <DataSource/DataSourceWidget.h> | |
29 | #include <Settings/SqpSettingsDialog.h> |
|
29 | #include <Settings/SqpSettingsDialog.h> | |
30 | #include <Settings/SqpSettingsGeneralWidget.h> |
|
30 | #include <Settings/SqpSettingsGeneralWidget.h> | |
31 | #include <SidePane/SqpSidePane.h> |
|
31 | #include <SidePane/SqpSidePane.h> | |
32 | #include <SqpApplication.h> |
|
32 | #include <SqpApplication.h> | |
33 | #include <Time/TimeController.h> |
|
33 | #include <Time/TimeController.h> | |
34 | #include <TimeWidget/TimeWidget.h> |
|
34 | #include <TimeWidget/TimeWidget.h> | |
35 | #include <Visualization/VisualizationController.h> |
|
35 | #include <Visualization/VisualizationController.h> | |
36 |
|
36 | |||
37 | #include <QAction> |
|
37 | #include <QAction> | |
38 | #include <QCloseEvent> |
|
38 | #include <QCloseEvent> | |
39 | #include <QDate> |
|
39 | #include <QDate> | |
40 | #include <QDir> |
|
40 | #include <QDir> | |
41 | #include <QFileDialog> |
|
41 | #include <QFileDialog> | |
42 | #include <QMessageBox> |
|
42 | #include <QMessageBox> | |
43 | #include <QToolBar> |
|
43 | #include <QToolBar> | |
44 | #include <QToolButton> |
|
44 | #include <QToolButton> | |
45 | #include <memory.h> |
|
45 | #include <memory.h> | |
46 |
|
46 | |||
47 | #include "iostream" |
|
47 | #include "iostream" | |
48 |
|
48 | |||
49 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") |
|
49 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") | |
50 |
|
50 | |||
51 | namespace |
|
51 | namespace | |
52 | { |
|
52 | { | |
53 | const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0; |
|
53 | const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0; | |
54 | const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1; |
|
54 | const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1; | |
55 | const auto VIEWPLITTERINDEX = 2; |
|
55 | const auto VIEWPLITTERINDEX = 2; | |
56 | const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3; |
|
56 | const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3; | |
57 | const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4; |
|
57 | const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4; | |
58 | } |
|
58 | } | |
59 |
|
59 | |||
60 | class MainWindow::MainWindowPrivate |
|
60 | class MainWindow::MainWindowPrivate | |
61 | { |
|
61 | { | |
62 | public: |
|
62 | public: | |
63 | explicit MainWindowPrivate(MainWindow* mainWindow) |
|
63 | explicit MainWindowPrivate(MainWindow* mainWindow) | |
64 | : m_LastOpenLeftInspectorSize {} |
|
64 | : m_LastOpenLeftInspectorSize {} | |
65 | , m_LastOpenRightInspectorSize {} |
|
65 | , m_LastOpenRightInspectorSize {} | |
66 | , m_GeneralSettingsWidget { new SqpSettingsGeneralWidget { mainWindow } } |
|
66 | , m_GeneralSettingsWidget { new SqpSettingsGeneralWidget { mainWindow } } | |
67 | , m_SettingsDialog { new SqpSettingsDialog { mainWindow } } |
|
67 | , m_SettingsDialog { new SqpSettingsDialog { mainWindow } } | |
68 | //, m_CatalogExplorer { new CatalogueExplorer { mainWindow } } |
|
68 | //, m_CatalogExplorer { new CatalogueExplorer { mainWindow } } | |
69 | { |
|
69 | { | |
70 | } |
|
70 | } | |
71 |
|
71 | |||
72 | QSize m_LastOpenLeftInspectorSize; |
|
72 | QSize m_LastOpenLeftInspectorSize; | |
73 | QSize m_LastOpenRightInspectorSize; |
|
73 | QSize m_LastOpenRightInspectorSize; | |
74 | /// General settings widget. MainWindow has the ownership |
|
74 | /// General settings widget. MainWindow has the ownership | |
75 | SqpSettingsGeneralWidget* m_GeneralSettingsWidget; |
|
75 | SqpSettingsGeneralWidget* m_GeneralSettingsWidget; | |
76 | /// Settings dialog. MainWindow has the ownership |
|
76 | /// Settings dialog. MainWindow has the ownership | |
77 | SqpSettingsDialog* m_SettingsDialog; |
|
77 | SqpSettingsDialog* m_SettingsDialog; | |
78 | /// Catalogue dialog. MainWindow has the ownership |
|
78 | /// Catalogue dialog. MainWindow has the ownership | |
79 | // CatalogueExplorer* m_CatalogExplorer; |
|
79 | // CatalogueExplorer* m_CatalogExplorer; | |
80 |
|
80 | |||
81 | bool checkDataToSave(QWidget* parentWidget); |
|
81 | bool checkDataToSave(QWidget* parentWidget); | |
82 | }; |
|
82 | }; | |
83 |
|
83 | |||
84 | MainWindow::MainWindow(QWidget* parent) |
|
84 | MainWindow::MainWindow(QWidget* parent) | |
85 | : QMainWindow { parent } |
|
85 | : QMainWindow { parent } | |
86 | , m_Ui { new Ui::MainWindow } |
|
86 | , m_Ui { new Ui::MainWindow } | |
87 | , impl { spimpl::make_unique_impl<MainWindowPrivate>(this) } |
|
87 | , impl { spimpl::make_unique_impl<MainWindowPrivate>(this) } | |
88 | { |
|
88 | { | |
89 | m_Ui->setupUi(this); |
|
89 | m_Ui->setupUi(this); | |
90 |
|
90 | |||
91 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
91 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); | |
92 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
92 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); | |
93 |
|
93 | |||
94 | // impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view); |
|
94 | // impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view); | |
95 |
|
95 | |||
96 |
|
96 | |||
97 | auto spacerLeftTop = new QWidget {}; |
|
97 | auto spacerLeftTop = new QWidget {}; | |
98 | spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
98 | spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
99 |
|
99 | |||
100 | auto spacerLeftBottom = new QWidget {}; |
|
100 | auto spacerLeftBottom = new QWidget {}; | |
101 | spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
101 | spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
102 |
|
102 | |||
103 |
|
103 | |||
104 | auto spacerRightTop = new QWidget {}; |
|
104 | auto spacerRightTop = new QWidget {}; | |
105 | spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
105 | spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
106 |
|
106 | |||
107 | auto spacerRightBottom = new QWidget {}; |
|
107 | auto spacerRightBottom = new QWidget {}; | |
108 | spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
108 | spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
109 |
|
109 | |||
110 |
|
110 | |||
111 | auto openInspector = [this](bool checked, bool right, auto action) { |
|
111 | auto openInspector = [this](bool checked, bool right, auto action) { | |
112 | action->setIcon( |
|
112 | action->setIcon( | |
113 | QIcon { (checked ^ right) ? ":/icones/next.png" : ":/icones/previous.png" }); |
|
113 | QIcon { (checked ^ right) ? ":/icones/next.png" : ":/icones/previous.png" }); | |
114 |
|
114 | |||
115 | auto& lastInspectorSize |
|
115 | auto& lastInspectorSize | |
116 | = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; |
|
116 | = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; | |
117 |
|
117 | |||
118 | auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() |
|
118 | auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() | |
119 | : m_Ui->leftMainInspectorWidget->size(); |
|
119 | : m_Ui->leftMainInspectorWidget->size(); | |
120 |
|
120 | |||
121 | // Update of the last opened geometry |
|
121 | // Update of the last opened geometry | |
122 | if (checked) |
|
122 | if (checked) | |
123 | { |
|
123 | { | |
124 | lastInspectorSize = nextInspectorSize; |
|
124 | lastInspectorSize = nextInspectorSize; | |
125 | } |
|
125 | } | |
126 |
|
126 | |||
127 | auto startSize = lastInspectorSize; |
|
127 | auto startSize = lastInspectorSize; | |
128 | auto endSize = startSize; |
|
128 | auto endSize = startSize; | |
129 | endSize.setWidth(0); |
|
129 | endSize.setWidth(0); | |
130 |
|
130 | |||
131 | auto splitterInspectorIndex |
|
131 | auto splitterInspectorIndex | |
132 | = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; |
|
132 | = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; | |
133 |
|
133 | |||
134 | auto currentSizes = m_Ui->splitter->sizes(); |
|
134 | auto currentSizes = m_Ui->splitter->sizes(); | |
135 | if (checked) |
|
135 | if (checked) | |
136 | { |
|
136 | { | |
137 | // adjust sizes individually here, e.g. |
|
137 | // adjust sizes individually here, e.g. | |
138 | currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); |
|
138 | currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); | |
139 | currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); |
|
139 | currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); | |
140 | m_Ui->splitter->setSizes(currentSizes); |
|
140 | m_Ui->splitter->setSizes(currentSizes); | |
141 | } |
|
141 | } | |
142 | else |
|
142 | else | |
143 | { |
|
143 | { | |
144 | // adjust sizes individually here, e.g. |
|
144 | // adjust sizes individually here, e.g. | |
145 | currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); |
|
145 | currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); | |
146 | currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); |
|
146 | currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); | |
147 | m_Ui->splitter->setSizes(currentSizes); |
|
147 | m_Ui->splitter->setSizes(currentSizes); | |
148 | } |
|
148 | } | |
149 | }; |
|
149 | }; | |
150 |
|
150 | |||
151 |
|
151 | |||
152 | // //////////////// // |
|
152 | // //////////////// // | |
153 | // Menu and Toolbar // |
|
153 | // Menu and Toolbar // | |
154 | // //////////////// // |
|
154 | // //////////////// // | |
155 | this->menuBar()->addAction(tr("File")); |
|
155 | this->menuBar()->addAction(tr("File")); | |
156 | auto toolsMenu = this->menuBar()->addMenu(tr("Tools")); |
|
156 | auto toolsMenu = this->menuBar()->addMenu(tr("Tools")); | |
157 | toolsMenu->addAction(tr("Settings..."), [this]() { |
|
157 | toolsMenu->addAction(tr("Settings..."), [this]() { | |
158 | // Loads settings |
|
158 | // Loads settings | |
159 | impl->m_SettingsDialog->loadSettings(); |
|
159 | impl->m_SettingsDialog->loadSettings(); | |
160 |
|
160 | |||
161 | // Open settings dialog and save settings if the dialog is accepted |
|
161 | // Open settings dialog and save settings if the dialog is accepted | |
162 | if (impl->m_SettingsDialog->exec() == QDialog::Accepted) |
|
162 | if (impl->m_SettingsDialog->exec() == QDialog::Accepted) | |
163 | { |
|
163 | { | |
164 | impl->m_SettingsDialog->saveSettings(); |
|
164 | impl->m_SettingsDialog->saveSettings(); | |
165 | } |
|
165 | } | |
166 | }); |
|
166 | }); | |
167 |
|
167 | |||
168 | auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); |
|
168 | auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); | |
169 |
|
169 | |||
170 | auto timeWidget = new TimeWidget {}; |
|
170 | auto timeWidget = new TimeWidget {}; | |
171 | mainToolBar->addWidget(timeWidget); |
|
171 | mainToolBar->addWidget(timeWidget); | |
172 |
|
172 | |||
173 | // Interaction modes |
|
173 | // Interaction modes | |
174 | auto actionPointerMode = new QAction { QIcon(":/icones/pointer.png"), "Move", this }; |
|
174 | auto actionPointerMode = new QAction { QIcon(":/icones/pointer.png"), "Move", this }; | |
175 | actionPointerMode->setCheckable(true); |
|
175 | actionPointerMode->setCheckable(true); | |
176 | actionPointerMode->setChecked( |
|
176 | actionPointerMode->setChecked( | |
177 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None); |
|
177 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None); | |
178 | connect(actionPointerMode, &QAction::triggered, |
|
178 | connect(actionPointerMode, &QAction::triggered, | |
179 | []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); }); |
|
179 | []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); }); | |
180 |
|
180 | |||
181 | auto actionZoomMode = new QAction { QIcon(":/icones/zoom.png"), "Zoom", this }; |
|
181 | auto actionZoomMode = new QAction { QIcon(":/icones/zoom.png"), "Zoom", this }; | |
182 | actionZoomMode->setCheckable(true); |
|
182 | actionZoomMode->setCheckable(true); | |
183 | actionZoomMode->setChecked( |
|
183 | actionZoomMode->setChecked( | |
184 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox); |
|
184 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox); | |
185 | connect(actionZoomMode, &QAction::triggered, |
|
185 | connect(actionZoomMode, &QAction::triggered, | |
186 | []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox); }); |
|
186 | []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox); }); | |
187 |
|
187 | |||
188 | auto actionOrganisationMode = new QAction { QIcon(":/icones/drag.png"), "Organize", this }; |
|
188 | auto actionOrganisationMode = new QAction { QIcon(":/icones/drag.png"), "Organize", this }; | |
189 | actionOrganisationMode->setCheckable(true); |
|
189 | actionOrganisationMode->setCheckable(true); | |
190 | actionOrganisationMode->setChecked( |
|
190 | actionOrganisationMode->setChecked( | |
191 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop); |
|
191 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop); | |
192 | connect(actionOrganisationMode, &QAction::triggered, []() { |
|
192 | connect(actionOrganisationMode, &QAction::triggered, []() { | |
193 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop); |
|
193 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop); | |
194 | }); |
|
194 | }); | |
195 |
|
195 | |||
196 | auto actionZonesMode = new QAction { QIcon(":/icones/rectangle.png"), "Zones", this }; |
|
196 | auto actionZonesMode = new QAction { QIcon(":/icones/rectangle.png"), "Zones", this }; | |
197 | actionZonesMode->setCheckable(true); |
|
197 | actionZonesMode->setCheckable(true); | |
198 | actionZonesMode->setChecked( |
|
198 | actionZonesMode->setChecked( | |
199 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones); |
|
199 | sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones); | |
200 | connect(actionZonesMode, &QAction::triggered, []() { |
|
200 | connect(actionZonesMode, &QAction::triggered, []() { | |
201 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones); |
|
201 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones); | |
202 | }); |
|
202 | }); | |
203 |
|
203 | |||
204 | auto modeActionGroup = new QActionGroup { this }; |
|
204 | auto modeActionGroup = new QActionGroup { this }; | |
205 | modeActionGroup->addAction(actionZoomMode); |
|
205 | modeActionGroup->addAction(actionZoomMode); | |
206 | modeActionGroup->addAction(actionZonesMode); |
|
206 | modeActionGroup->addAction(actionZonesMode); | |
207 | modeActionGroup->addAction(actionOrganisationMode); |
|
207 | modeActionGroup->addAction(actionOrganisationMode); | |
208 | modeActionGroup->addAction(actionPointerMode); |
|
208 | modeActionGroup->addAction(actionPointerMode); | |
209 | modeActionGroup->setExclusive(true); |
|
209 | modeActionGroup->setExclusive(true); | |
210 |
|
210 | |||
211 | mainToolBar->addSeparator(); |
|
211 | mainToolBar->addSeparator(); | |
212 | mainToolBar->addAction(actionPointerMode); |
|
212 | mainToolBar->addAction(actionPointerMode); | |
213 | mainToolBar->addAction(actionZoomMode); |
|
213 | mainToolBar->addAction(actionZoomMode); | |
214 | mainToolBar->addAction(actionOrganisationMode); |
|
214 | mainToolBar->addAction(actionOrganisationMode); | |
215 | mainToolBar->addAction(actionZonesMode); |
|
215 | mainToolBar->addAction(actionZonesMode); | |
216 | mainToolBar->addSeparator(); |
|
216 | mainToolBar->addSeparator(); | |
217 |
|
217 | |||
218 | // Cursors |
|
218 | // Cursors | |
219 | auto btnCursor = new QToolButton { this }; |
|
219 | auto btnCursor = new QToolButton { this }; | |
220 | btnCursor->setIcon(QIcon(":/icones/cursor.png")); |
|
220 | btnCursor->setIcon(QIcon(":/icones/cursor.png")); | |
221 | btnCursor->setText("Cursor"); |
|
221 | btnCursor->setText("Cursor"); | |
222 | btnCursor->setToolTip("Cursor"); |
|
222 | btnCursor->setToolTip("Cursor"); | |
223 | btnCursor->setPopupMode(QToolButton::InstantPopup); |
|
223 | btnCursor->setPopupMode(QToolButton::InstantPopup); | |
224 | auto cursorMenu = new QMenu("CursorMenu", this); |
|
224 | auto cursorMenu = new QMenu("CursorMenu", this); | |
225 | btnCursor->setMenu(cursorMenu); |
|
225 | btnCursor->setMenu(cursorMenu); | |
226 |
|
226 | |||
227 | auto noCursorAction = cursorMenu->addAction("No Cursor"); |
|
227 | auto noCursorAction = cursorMenu->addAction("No Cursor"); | |
228 | noCursorAction->setCheckable(true); |
|
228 | noCursorAction->setCheckable(true); | |
229 | noCursorAction->setChecked( |
|
229 | noCursorAction->setChecked( | |
230 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::NoCursor); |
|
230 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::NoCursor); | |
231 | connect(noCursorAction, &QAction::triggered, |
|
231 | connect(noCursorAction, &QAction::triggered, | |
232 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); }); |
|
232 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); }); | |
233 |
|
233 | |||
234 | cursorMenu->addSeparator(); |
|
234 | cursorMenu->addSeparator(); | |
235 | auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor"); |
|
235 | auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor"); | |
236 | verticalCursorAction->setCheckable(true); |
|
236 | verticalCursorAction->setCheckable(true); | |
237 | verticalCursorAction->setChecked( |
|
237 | verticalCursorAction->setChecked( | |
238 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Vertical); |
|
238 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Vertical); | |
239 | connect(verticalCursorAction, &QAction::triggered, |
|
239 | connect(verticalCursorAction, &QAction::triggered, | |
240 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); }); |
|
240 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); }); | |
241 |
|
241 | |||
242 | auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor"); |
|
242 | auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor"); | |
243 | temporalCursorAction->setCheckable(true); |
|
243 | temporalCursorAction->setCheckable(true); | |
244 | temporalCursorAction->setChecked( |
|
244 | temporalCursorAction->setChecked( | |
245 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Temporal); |
|
245 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Temporal); | |
246 | connect(temporalCursorAction, &QAction::triggered, |
|
246 | connect(temporalCursorAction, &QAction::triggered, | |
247 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); }); |
|
247 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); }); | |
248 |
|
248 | |||
249 | auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor"); |
|
249 | auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor"); | |
250 | horizontalCursorAction->setCheckable(true); |
|
250 | horizontalCursorAction->setCheckable(true); | |
251 | horizontalCursorAction->setChecked( |
|
251 | horizontalCursorAction->setChecked( | |
252 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Horizontal); |
|
252 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Horizontal); | |
253 | connect(horizontalCursorAction, &QAction::triggered, |
|
253 | connect(horizontalCursorAction, &QAction::triggered, | |
254 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); }); |
|
254 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); }); | |
255 |
|
255 | |||
256 | auto crossCursorAction = cursorMenu->addAction("Cross Cursor"); |
|
256 | auto crossCursorAction = cursorMenu->addAction("Cross Cursor"); | |
257 | crossCursorAction->setCheckable(true); |
|
257 | crossCursorAction->setCheckable(true); | |
258 | crossCursorAction->setChecked( |
|
258 | crossCursorAction->setChecked( | |
259 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Cross); |
|
259 | sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Cross); | |
260 | connect(crossCursorAction, &QAction::triggered, |
|
260 | connect(crossCursorAction, &QAction::triggered, | |
261 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); }); |
|
261 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); }); | |
262 |
|
262 | |||
263 | mainToolBar->addWidget(btnCursor); |
|
263 | mainToolBar->addWidget(btnCursor); | |
264 |
|
264 | |||
265 | auto cursorModeActionGroup = new QActionGroup { this }; |
|
265 | auto cursorModeActionGroup = new QActionGroup { this }; | |
266 | cursorModeActionGroup->setExclusive(true); |
|
266 | cursorModeActionGroup->setExclusive(true); | |
267 | cursorModeActionGroup->addAction(noCursorAction); |
|
267 | cursorModeActionGroup->addAction(noCursorAction); | |
268 | cursorModeActionGroup->addAction(verticalCursorAction); |
|
268 | cursorModeActionGroup->addAction(verticalCursorAction); | |
269 | cursorModeActionGroup->addAction(temporalCursorAction); |
|
269 | cursorModeActionGroup->addAction(temporalCursorAction); | |
270 | cursorModeActionGroup->addAction(horizontalCursorAction); |
|
270 | cursorModeActionGroup->addAction(horizontalCursorAction); | |
271 | cursorModeActionGroup->addAction(crossCursorAction); |
|
271 | cursorModeActionGroup->addAction(crossCursorAction); | |
272 |
|
272 | |||
273 | // Catalog |
|
273 | // Catalog | |
274 | mainToolBar->addSeparator(); |
|
274 | mainToolBar->addSeparator(); | |
275 | // mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues", |
|
275 | // mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues", | |
276 | // [this]() { impl->m_CatalogExplorer->show(); }); |
|
276 | // [this]() { impl->m_CatalogExplorer->show(); }); | |
277 |
|
277 | |||
278 | // //////// // |
|
278 | // //////// // | |
279 | // Settings // |
|
279 | // Settings // | |
280 | // //////// // |
|
280 | // //////// // | |
281 |
|
281 | |||
282 | // Registers "general settings" widget to the settings dialog |
|
282 | // Registers "general settings" widget to the settings dialog | |
283 | impl->m_SettingsDialog->registerWidget( |
|
283 | impl->m_SettingsDialog->registerWidget( | |
284 | QStringLiteral("General"), impl->m_GeneralSettingsWidget); |
|
284 | QStringLiteral("General"), impl->m_GeneralSettingsWidget); | |
285 |
|
285 | |||
286 | // /////////// // |
|
286 | // /////////// // | |
287 | // Connections // |
|
287 | // Connections // | |
288 | // /////////// // |
|
288 | // /////////// // | |
289 |
|
289 | |||
290 | // Controllers / controllers connections |
|
290 | // Controllers / controllers connections | |
291 | // connect(&sqpApp->timeController(), SIGNAL(timeUpdated(DateTimeRange)), |
|
291 | // connect(&sqpApp->timeController(), SIGNAL(timeUpdated(DateTimeRange)), | |
292 | // &sqpApp->variableController(), |
|
292 | // &sqpApp->variableController(), | |
293 | // SLOT(onDateTimeOnSelection(DateTimeRange))); |
|
293 | // SLOT(onDateTimeOnSelection(DateTimeRange))); | |
294 |
|
294 | |||
295 | // Widgets / controllers connections |
|
295 | // Widgets / controllers connections | |
296 |
|
296 | |||
297 | // DataSource |
|
297 | // DataSource | |
298 | connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem*)), |
|
298 | connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem*)), | |
299 | m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem*))); |
|
299 | m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem*))); | |
300 |
|
300 | |||
301 | // Time |
|
301 | // Time | |
302 | connect(timeWidget, SIGNAL(timeUpdated(DateTimeRange)), &sqpApp->timeController(), |
|
302 | connect(timeWidget, SIGNAL(timeUpdated(DateTimeRange)), &sqpApp->timeController(), | |
303 | SLOT(onTimeToUpdate(DateTimeRange))); |
|
303 | SLOT(onTimeToUpdate(DateTimeRange))); | |
304 |
|
304 | |||
305 | // Visualization |
|
305 | // Visualization | |
306 | connect(&sqpApp->visualizationController(), |
|
306 | connect(&sqpApp->visualizationController(), | |
307 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view, |
|
307 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable2>)), m_Ui->view, | |
308 | SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>))); |
|
308 | SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable2>))); | |
309 |
|
309 | |||
310 | connect(&sqpApp->visualizationController(), |
|
310 | connect(&sqpApp->visualizationController(), | |
311 | SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange&)), m_Ui->view, |
|
311 | SIGNAL(rangeChanged(std::shared_ptr<Variable2>, const DateTimeRange&)), m_Ui->view, | |
312 | SLOT(onRangeChanged(std::shared_ptr<Variable>, const DateTimeRange&))); |
|
312 | SLOT(onRangeChanged(std::shared_ptr<Variable2>, const DateTimeRange&))); | |
313 |
|
313 | |||
314 | // Widgets / widgets connections |
|
314 | // Widgets / widgets connections | |
315 |
|
315 | |||
316 | // For the following connections, we use DirectConnection to allow each widget that can |
|
316 | // For the following connections, we use DirectConnection to allow each widget that can | |
317 | // potentially attach a menu to the variable's menu to do so before this menu is displayed. |
|
317 | // potentially attach a menu to the variable's menu to do so before this menu is displayed. | |
318 | // The order of connections is also important, since it determines the order in which each |
|
318 | // The order of connections is also important, since it determines the order in which each | |
319 | // widget will attach its menu |
|
319 | // widget will attach its menu | |
320 | connect(m_Ui->variableInspectorWidget, |
|
320 | connect(m_Ui->variableInspectorWidget, | |
321 | SIGNAL(tableMenuAboutToBeDisplayed(QMenu*, const QVector<std::shared_ptr<Variable>>&)), |
|
321 | SIGNAL(tableMenuAboutToBeDisplayed(QMenu*, const QVector<std::shared_ptr<Variable>>&)), | |
322 | m_Ui->view, SLOT(attachVariableMenu(QMenu*, const QVector<std::shared_ptr<Variable>>&)), |
|
322 | m_Ui->view, SLOT(attachVariableMenu(QMenu*, const QVector<std::shared_ptr<Variable>>&)), | |
323 | Qt::DirectConnection); |
|
323 | Qt::DirectConnection); | |
324 | } |
|
324 | } | |
325 |
|
325 | |||
326 | MainWindow::~MainWindow() {} |
|
326 | MainWindow::~MainWindow() {} | |
327 |
|
327 | |||
328 | void MainWindow::changeEvent(QEvent* e) |
|
328 | void MainWindow::changeEvent(QEvent* e) | |
329 | { |
|
329 | { | |
330 | QMainWindow::changeEvent(e); |
|
330 | QMainWindow::changeEvent(e); | |
331 | switch (e->type()) |
|
331 | switch (e->type()) | |
332 | { |
|
332 | { | |
333 | case QEvent::LanguageChange: |
|
333 | case QEvent::LanguageChange: | |
334 | m_Ui->retranslateUi(this); |
|
334 | m_Ui->retranslateUi(this); | |
335 | break; |
|
335 | break; | |
336 | default: |
|
336 | default: | |
337 | break; |
|
337 | break; | |
338 | } |
|
338 | } | |
339 | } |
|
339 | } | |
340 |
|
340 | |||
341 | void MainWindow::closeEvent(QCloseEvent* event) |
|
341 | void MainWindow::closeEvent(QCloseEvent* event) | |
342 | { |
|
342 | { | |
343 | if (!impl->checkDataToSave(this)) |
|
343 | if (!impl->checkDataToSave(this)) | |
344 | { |
|
344 | { | |
345 | event->ignore(); |
|
345 | event->ignore(); | |
346 | } |
|
346 | } | |
347 | else |
|
347 | else | |
348 | { |
|
348 | { | |
349 | event->accept(); |
|
349 | event->accept(); | |
350 | } |
|
350 | } | |
351 | } |
|
351 | } | |
352 |
|
352 | |||
353 | void MainWindow::keyPressEvent(QKeyEvent* event) |
|
353 | void MainWindow::keyPressEvent(QKeyEvent* event) | |
354 | { |
|
354 | { | |
355 | switch (event->key()) |
|
355 | switch (event->key()) | |
356 | { |
|
356 | { | |
357 | case Qt::Key_F11: |
|
357 | case Qt::Key_F11: | |
358 | if (this->isFullScreen()) |
|
358 | if (this->isFullScreen()) | |
359 | { |
|
359 | { | |
360 | this->showNormal(); |
|
360 | this->showNormal(); | |
361 | } |
|
361 | } | |
362 | else |
|
362 | else | |
363 | { |
|
363 | { | |
364 | this->showFullScreen(); |
|
364 | this->showFullScreen(); | |
365 | } |
|
365 | } | |
366 | break; |
|
366 | break; | |
367 | default: |
|
367 | default: | |
368 | break; |
|
368 | break; | |
369 | } |
|
369 | } | |
370 | } |
|
370 | } | |
371 |
|
371 | |||
372 | bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget* parentWidget) |
|
372 | bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget* parentWidget) | |
373 | { |
|
373 | { | |
374 | // auto hasChanges = sqpApp->catalogueController().hasChanges(); |
|
374 | // auto hasChanges = sqpApp->catalogueController().hasChanges(); | |
375 | // if (hasChanges) |
|
375 | // if (hasChanges) | |
376 | // { |
|
376 | // { | |
377 | // // There are some unsaved changes |
|
377 | // // There are some unsaved changes | |
378 | // switch (QMessageBox::question(parentWidget, tr("Save changes"), |
|
378 | // switch (QMessageBox::question(parentWidget, tr("Save changes"), | |
379 | // tr("The catalogue controller has unsaved changes.\nDo you want to save them ?"), |
|
379 | // tr("The catalogue controller has unsaved changes.\nDo you want to save them ?"), | |
380 | // QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel, |
|
380 | // QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel, | |
381 | // QMessageBox::SaveAll)) |
|
381 | // QMessageBox::SaveAll)) | |
382 | // { |
|
382 | // { | |
383 | // case QMessageBox::SaveAll: |
|
383 | // case QMessageBox::SaveAll: | |
384 | // sqpApp->catalogueController().saveAll(); |
|
384 | // sqpApp->catalogueController().saveAll(); | |
385 | // break; |
|
385 | // break; | |
386 | // case QMessageBox::Discard: |
|
386 | // case QMessageBox::Discard: | |
387 | // break; |
|
387 | // break; | |
388 | // case QMessageBox::Cancel: |
|
388 | // case QMessageBox::Cancel: | |
389 | // default: |
|
389 | // default: | |
390 | // return false; |
|
390 | // return false; | |
391 | // } |
|
391 | // } | |
392 | // } |
|
392 | // } | |
393 |
|
393 | |||
394 | return true; |
|
394 | return true; | |
395 | } |
|
395 | } |
@@ -1,1 +1,1 | |||||
1 | Subproject commit cc26524fb5d10feca3820e6921c9cd3cfb1a3591 |
|
1 | Subproject commit 00ce7df31d3e11df8a418988c601247f6dc64d13 |
@@ -1,90 +1,90 | |||||
1 | #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H |
|
1 | #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H | |
2 | #define SCIQLOP_VISUALIZATIONTABWIDGET_H |
|
2 | #define SCIQLOP_VISUALIZATIONTABWIDGET_H | |
3 |
|
3 | |||
4 | #include "Visualization/IVisualizationWidget.h" |
|
4 | #include "Visualization/IVisualizationWidget.h" | |
5 |
|
5 | |||
6 | #include <Common/spimpl.h> |
|
6 | #include <Common/spimpl.h> | |
7 |
|
7 | |||
8 | #include <QLoggingCategory> |
|
8 | #include <QLoggingCategory> | |
9 | #include <QMimeData> |
|
9 | #include <QMimeData> | |
10 | #include <QWidget> |
|
10 | #include <QWidget> | |
11 |
|
11 | |||
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget) |
|
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget) | |
13 |
|
13 | |||
14 | class Variable; |
|
14 | class Variable2; | |
15 | class VisualizationZoneWidget; |
|
15 | class VisualizationZoneWidget; | |
16 |
|
16 | |||
17 | namespace Ui |
|
17 | namespace Ui | |
18 | { |
|
18 | { | |
19 | class VisualizationTabWidget; |
|
19 | class VisualizationTabWidget; | |
20 | } // namespace Ui |
|
20 | } // namespace Ui | |
21 |
|
21 | |||
22 | class VisualizationTabWidget : public QWidget, public IVisualizationWidget |
|
22 | class VisualizationTabWidget : public QWidget, public IVisualizationWidget | |
23 | { |
|
23 | { | |
24 | Q_OBJECT |
|
24 | Q_OBJECT | |
25 |
|
25 | |||
26 | public: |
|
26 | public: | |
27 | explicit VisualizationTabWidget(const QString& name = {}, QWidget* parent = 0); |
|
27 | explicit VisualizationTabWidget(const QString& name = {}, QWidget* parent = 0); | |
28 | virtual ~VisualizationTabWidget(); |
|
28 | virtual ~VisualizationTabWidget(); | |
29 |
|
29 | |||
30 | /// Adds a zone widget |
|
30 | /// Adds a zone widget | |
31 | void addZone(VisualizationZoneWidget* zoneWidget); |
|
31 | void addZone(VisualizationZoneWidget* zoneWidget); | |
32 |
|
32 | |||
33 | /// Inserts a zone widget at the specified position |
|
33 | /// Inserts a zone widget at the specified position | |
34 | void insertZone(int index, VisualizationZoneWidget* zoneWidget); |
|
34 | void insertZone(int index, VisualizationZoneWidget* zoneWidget); | |
35 |
|
35 | |||
36 | /// Returns the list of zone widget names in the order they are displayed |
|
36 | /// Returns the list of zone widget names in the order they are displayed | |
37 | QStringList availableZoneWidgets() const; |
|
37 | QStringList availableZoneWidgets() const; | |
38 |
|
38 | |||
39 | /// Returns the zone with the specified name. |
|
39 | /// Returns the zone with the specified name. | |
40 | /// If multiple zone with the same name exist, the first one is returned. |
|
40 | /// If multiple zone with the same name exist, the first one is returned. | |
41 | VisualizationZoneWidget* getZoneWithName(const QString& zoneName); |
|
41 | VisualizationZoneWidget* getZoneWithName(const QString& zoneName); | |
42 |
|
42 | |||
43 | /** |
|
43 | /** | |
44 | * Creates a zone using a variable. The variable will be displayed in a new graph of the new |
|
44 | * Creates a zone using a variable. The variable will be displayed in a new graph of the new | |
45 | * zone. The zone is added at the end. |
|
45 | * zone. The zone is added at the end. | |
46 | * @param variable the variable for which to create the zone |
|
46 | * @param variable the variable for which to create the zone | |
47 | * @return the pointer to the created zone |
|
47 | * @return the pointer to the created zone | |
48 | */ |
|
48 | */ | |
49 | VisualizationZoneWidget* createZone(std::shared_ptr<Variable2> variable); |
|
49 | VisualizationZoneWidget* createZone(std::shared_ptr<Variable2> variable); | |
50 |
|
50 | |||
51 | /** |
|
51 | /** | |
52 | * Creates a zone using a list of variables. The variables will be displayed in a new graph of |
|
52 | * Creates a zone using a list of variables. The variables will be displayed in a new graph of | |
53 | * the new zone. The zone is inserted at the specified index. |
|
53 | * the new zone. The zone is inserted at the specified index. | |
54 | * @param variables the variables for which to create the zone |
|
54 | * @param variables the variables for which to create the zone | |
55 | * @param index The index where the zone should be inserted in the layout |
|
55 | * @param index The index where the zone should be inserted in the layout | |
56 | * @return the pointer to the created zone |
|
56 | * @return the pointer to the created zone | |
57 | */ |
|
57 | */ | |
58 | VisualizationZoneWidget* createZone( |
|
58 | VisualizationZoneWidget* createZone( | |
59 | const std::vector<std::shared_ptr<Variable2>>& variables, int index); |
|
59 | const std::vector<std::shared_ptr<Variable2>>& variables, int index); | |
60 |
|
60 | |||
61 | /** |
|
61 | /** | |
62 | * Creates a zone which is empty (no variables). The zone is inserted at the specified index. |
|
62 | * Creates a zone which is empty (no variables). The zone is inserted at the specified index. | |
63 | * @param index The index where the zone should be inserted in the layout |
|
63 | * @param index The index where the zone should be inserted in the layout | |
64 | * @return the pointer to the created zone |
|
64 | * @return the pointer to the created zone | |
65 | */ |
|
65 | */ | |
66 | VisualizationZoneWidget* createEmptyZone(int index); |
|
66 | VisualizationZoneWidget* createEmptyZone(int index); | |
67 |
|
67 | |||
68 | // IVisualizationWidget interface |
|
68 | // IVisualizationWidget interface | |
69 | void accept(IVisualizationWidgetVisitor* visitor) override; |
|
69 | void accept(IVisualizationWidgetVisitor* visitor) override; | |
70 | bool canDrop(Variable2& variable) const override; |
|
70 | bool canDrop(Variable2& variable) const override; | |
71 | bool contains(Variable2& variable) const override; |
|
71 | bool contains(Variable2& variable) const override; | |
72 | QString name() const override; |
|
72 | QString name() const override; | |
73 |
|
73 | |||
74 | protected: |
|
74 | protected: | |
75 | void closeEvent(QCloseEvent* event) override; |
|
75 | void closeEvent(QCloseEvent* event) override; | |
76 |
|
76 | |||
77 | private: |
|
77 | private: | |
78 | /// @return the layout of tab in which zones are added |
|
78 | /// @return the layout of tab in which zones are added | |
79 | QLayout& tabLayout() const noexcept; |
|
79 | QLayout& tabLayout() const noexcept; | |
80 |
|
80 | |||
81 | Ui::VisualizationTabWidget* ui; |
|
81 | Ui::VisualizationTabWidget* ui; | |
82 |
|
82 | |||
83 | class VisualizationTabWidgetPrivate; |
|
83 | class VisualizationTabWidgetPrivate; | |
84 | spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl; |
|
84 | spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl; | |
85 |
|
85 | |||
86 | private slots: |
|
86 | private slots: | |
87 | void dropMimeData(int index, const QMimeData* mimeData); |
|
87 | void dropMimeData(int index, const QMimeData* mimeData); | |
88 | }; |
|
88 | }; | |
89 |
|
89 | |||
90 | #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H |
|
90 | #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H |
@@ -1,442 +1,445 | |||||
1 | #include "Visualization/VisualizationGraphHelper.h" |
|
1 | #include "Visualization/VisualizationGraphHelper.h" | |
2 | #include "Visualization/qcustomplot.h" |
|
2 | #include "Visualization/qcustomplot.h" | |
3 |
|
3 | |||
4 | #include <Data/ScalarTimeSerie.h> |
|
4 | #include <Data/ScalarTimeSerie.h> | |
5 | #include <Data/SpectrogramTimeSerie.h> |
|
5 | #include <Data/SpectrogramTimeSerie.h> | |
6 | #include <Data/VectorTimeSerie.h> |
|
6 | #include <Data/VectorTimeSerie.h> | |
7 |
|
7 | |||
8 | #include <Variable/Variable2.h> |
|
8 | #include <Variable/Variable2.h> | |
9 |
|
9 | |||
10 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") |
|
10 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") | |
11 |
|
11 | |||
12 | namespace |
|
12 | namespace | |
13 | { |
|
13 | { | |
14 |
|
14 | |||
15 | class SqpDataContainer : public QCPGraphDataContainer |
|
15 | class SqpDataContainer : public QCPGraphDataContainer | |
16 | { |
|
16 | { | |
17 | public: |
|
17 | public: | |
18 | void appendGraphData(const QCPGraphData& data) { mData.append(data); } |
|
18 | void appendGraphData(const QCPGraphData& data) { mData.append(data); } | |
19 | }; |
|
19 | }; | |
20 |
|
20 | |||
21 | /** |
|
21 | /** | |
22 | * Struct used to create plottables, depending on the type of the data series from which to create |
|
22 | * Struct used to create plottables, depending on the type of the data series from which to create | |
23 | * them |
|
23 | * them | |
24 | * @tparam T the data series' type |
|
24 | * @tparam T the data series' type | |
25 | * @remarks Default implementation can't create plottables |
|
25 | * @remarks Default implementation can't create plottables | |
26 | */ |
|
26 | */ | |
27 | template <typename T, typename Enabled = void> |
|
27 | template <typename T, typename Enabled = void> | |
28 | struct PlottablesCreator |
|
28 | struct PlottablesCreator | |
29 | { |
|
29 | { | |
30 | static PlottablesMap createPlottables(QCustomPlot&) { return {}; } |
|
30 | static PlottablesMap createPlottables(QCustomPlot&) { return {}; } | |
31 | }; |
|
31 | }; | |
32 |
|
32 | |||
33 | PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs) |
|
33 | PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs) | |
34 | { |
|
34 | { | |
35 | PlottablesMap result {}; |
|
35 | PlottablesMap result {}; | |
36 |
|
36 | |||
37 | // Creates {nbGraphs} QCPGraph to add to the plot |
|
37 | // Creates {nbGraphs} QCPGraph to add to the plot | |
38 | for (auto i = 0; i < nbGraphs; ++i) |
|
38 | for (auto i = 0; i < nbGraphs; ++i) | |
39 | { |
|
39 | { | |
40 | auto graph = plot.addGraph(); |
|
40 | auto graph = plot.addGraph(); | |
41 | result.insert({ i, graph }); |
|
41 | result.insert({ i, graph }); | |
42 | } |
|
42 | } | |
43 |
|
43 | |||
44 | plot.replot(); |
|
44 | plot.replot(); | |
45 |
|
45 | |||
46 | return result; |
|
46 | return result; | |
47 | } |
|
47 | } | |
48 |
|
48 | |||
49 | /** |
|
49 | /** | |
50 | * Specialization of PlottablesCreator for scalars |
|
50 | * Specialization of PlottablesCreator for scalars | |
51 | * @sa ScalarSeries |
|
51 | * @sa ScalarSeries | |
52 | */ |
|
52 | */ | |
53 | template <typename T> |
|
53 | template <typename T> | |
54 | struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>> |
|
54 | struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>> | |
55 | { |
|
55 | { | |
56 | static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 1); } |
|
56 | static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 1); } | |
57 | }; |
|
57 | }; | |
58 |
|
58 | |||
59 | /** |
|
59 | /** | |
60 | * Specialization of PlottablesCreator for vectors |
|
60 | * Specialization of PlottablesCreator for vectors | |
61 | * @sa VectorSeries |
|
61 | * @sa VectorSeries | |
62 | */ |
|
62 | */ | |
63 | template <typename T> |
|
63 | template <typename T> | |
64 | struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>> |
|
64 | struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>> | |
65 | { |
|
65 | { | |
66 | static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 3); } |
|
66 | static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 3); } | |
67 | }; |
|
67 | }; | |
68 |
|
68 | |||
69 | /** |
|
69 | /** | |
70 | * Specialization of PlottablesCreator for spectrograms |
|
70 | * Specialization of PlottablesCreator for spectrograms | |
71 | * @sa SpectrogramSeries |
|
71 | * @sa SpectrogramSeries | |
72 | */ |
|
72 | */ | |
73 | template <typename T> |
|
73 | template <typename T> | |
74 | struct PlottablesCreator<T, |
|
74 | struct PlottablesCreator<T, | |
75 | typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>> |
|
75 | typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>> | |
76 | { |
|
76 | { | |
77 | static PlottablesMap createPlottables(QCustomPlot& plot) |
|
77 | static PlottablesMap createPlottables(QCustomPlot& plot) | |
78 | { |
|
78 | { | |
79 | PlottablesMap result {}; |
|
79 | PlottablesMap result {}; | |
80 | result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } }); |
|
80 | result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } }); | |
81 |
|
81 | |||
82 | plot.replot(); |
|
82 | plot.replot(); | |
83 |
|
83 | |||
84 | return result; |
|
84 | return result; | |
85 | } |
|
85 | } | |
86 | }; |
|
86 | }; | |
87 |
|
87 | |||
88 | /** |
|
88 | /** | |
89 | * Struct used to update plottables, depending on the type of the data series from which to update |
|
89 | * Struct used to update plottables, depending on the type of the data series from which to update | |
90 | * them |
|
90 | * them | |
91 | * @tparam T the data series' type |
|
91 | * @tparam T the data series' type | |
92 | * @remarks Default implementation can't update plottables |
|
92 | * @remarks Default implementation can't update plottables | |
93 | */ |
|
93 | */ | |
94 | template <typename T, typename Enabled = void> |
|
94 | template <typename T, typename Enabled = void> | |
95 | struct PlottablesUpdater |
|
95 | struct PlottablesUpdater | |
96 | { |
|
96 | { | |
97 | static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&) |
|
97 | static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&) | |
98 | { |
|
98 | { | |
99 | qCCritical(LOG_VisualizationGraphHelper()) |
|
99 | qCCritical(LOG_VisualizationGraphHelper()) | |
100 | << QObject::tr("Can't set plot y-axis range: unmanaged data series type"); |
|
100 | << QObject::tr("Can't set plot y-axis range: unmanaged data series type"); | |
101 | } |
|
101 | } | |
102 |
|
102 | |||
103 | static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool) |
|
103 | static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool) | |
104 | { |
|
104 | { | |
105 | qCCritical(LOG_VisualizationGraphHelper()) |
|
105 | qCCritical(LOG_VisualizationGraphHelper()) | |
106 | << QObject::tr("Can't update plottables: unmanaged data series type"); |
|
106 | << QObject::tr("Can't update plottables: unmanaged data series type"); | |
107 | } |
|
107 | } | |
108 | }; |
|
108 | }; | |
109 |
|
109 | |||
110 | /** |
|
110 | /** | |
111 | * Specialization of PlottablesUpdater for scalars and vectors |
|
111 | * Specialization of PlottablesUpdater for scalars and vectors | |
112 | * @sa ScalarSeries |
|
112 | * @sa ScalarSeries | |
113 | * @sa VectorSeries |
|
113 | * @sa VectorSeries | |
114 | */ |
|
114 | */ | |
115 | template <typename T> |
|
115 | template <typename T> | |
116 | struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>> |
|
116 | struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>> | |
117 | { |
|
117 | { | |
118 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) |
|
118 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) | |
119 | { |
|
119 | { | |
120 | auto minValue = 0., maxValue = 0.; |
|
120 | auto minValue = 0., maxValue = 0.; | |
121 | if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries)) |
|
121 | if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries)) | |
122 | { |
|
122 | { | |
123 | maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v(); |
|
123 | if (serie->size()) | |
124 | minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v(); |
|
124 | { | |
|
125 | maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v(); | |||
|
126 | minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v(); | |||
|
127 | } | |||
125 | } |
|
128 | } | |
126 | plot.yAxis->setRange(QCPRange { minValue, maxValue }); |
|
129 | plot.yAxis->setRange(QCPRange { minValue, maxValue }); | |
127 | } |
|
130 | } | |
128 |
|
131 | |||
129 | static void updatePlottables( |
|
132 | static void updatePlottables( | |
130 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) |
|
133 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) | |
131 | { |
|
134 | { | |
132 |
|
135 | |||
133 | // For each plottable to update, resets its data |
|
136 | // For each plottable to update, resets its data | |
134 | for (const auto& plottable : plottables) |
|
137 | for (const auto& plottable : plottables) | |
135 | { |
|
138 | { | |
136 | if (auto graph = dynamic_cast<QCPGraph*>(plottable.second)) |
|
139 | if (auto graph = dynamic_cast<QCPGraph*>(plottable.second)) | |
137 | { |
|
140 | { | |
138 | auto dataContainer = QSharedPointer<SqpDataContainer>::create(); |
|
141 | auto dataContainer = QSharedPointer<SqpDataContainer>::create(); | |
139 | if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries)) |
|
142 | if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries)) | |
140 | { |
|
143 | { | |
141 | std::for_each( |
|
144 | std::for_each( | |
142 | std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) { |
|
145 | std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) { | |
143 | dataContainer->appendGraphData(QCPGraphData(value.t(), value.v())); |
|
146 | dataContainer->appendGraphData(QCPGraphData(value.t(), value.v())); | |
144 | }); |
|
147 | }); | |
145 | } |
|
148 | } | |
146 | graph->setData(dataContainer); |
|
149 | graph->setData(dataContainer); | |
147 | } |
|
150 | } | |
148 | } |
|
151 | } | |
149 |
|
152 | |||
150 | if (!plottables.empty()) |
|
153 | if (!plottables.empty()) | |
151 | { |
|
154 | { | |
152 | auto plot = plottables.begin()->second->parentPlot(); |
|
155 | auto plot = plottables.begin()->second->parentPlot(); | |
153 |
|
156 | |||
154 | if (rescaleAxes) |
|
157 | if (rescaleAxes) | |
155 | { |
|
158 | { | |
156 | plot->rescaleAxes(); |
|
159 | plot->rescaleAxes(); | |
157 | } |
|
160 | } | |
158 | } |
|
161 | } | |
159 | } |
|
162 | } | |
160 | }; |
|
163 | }; | |
161 |
|
164 | |||
162 |
|
165 | |||
163 | template <typename T> |
|
166 | template <typename T> | |
164 | struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>> |
|
167 | struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>> | |
165 | { |
|
168 | { | |
166 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) |
|
169 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) | |
167 | { |
|
170 | { | |
168 | double minValue = 0., maxValue = 0.; |
|
171 | double minValue = 0., maxValue = 0.; | |
169 | if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries)) |
|
172 | if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries)) | |
170 | { |
|
173 | { | |
171 | std::for_each( |
|
174 | std::for_each( | |
172 | std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) { |
|
175 | std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) { | |
173 | minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z }); |
|
176 | minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z }); | |
174 | maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z }); |
|
177 | maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z }); | |
175 | }); |
|
178 | }); | |
176 | } |
|
179 | } | |
177 |
|
180 | |||
178 | plot.yAxis->setRange(QCPRange { minValue, maxValue }); |
|
181 | plot.yAxis->setRange(QCPRange { minValue, maxValue }); | |
179 | } |
|
182 | } | |
180 |
|
183 | |||
181 | static void updatePlottables( |
|
184 | static void updatePlottables( | |
182 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) |
|
185 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) | |
183 | { |
|
186 | { | |
184 |
|
187 | |||
185 | // For each plottable to update, resets its data |
|
188 | // For each plottable to update, resets its data | |
186 | for (const auto& plottable : plottables) |
|
189 | for (const auto& plottable : plottables) | |
187 | { |
|
190 | { | |
188 | if (auto graph = dynamic_cast<QCPGraph*>(plottable.second)) |
|
191 | if (auto graph = dynamic_cast<QCPGraph*>(plottable.second)) | |
189 | { |
|
192 | { | |
190 | auto dataContainer = QSharedPointer<SqpDataContainer>::create(); |
|
193 | auto dataContainer = QSharedPointer<SqpDataContainer>::create(); | |
191 | if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries)) |
|
194 | if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries)) | |
192 | { |
|
195 | { | |
193 | switch (plottable.first) |
|
196 | switch (plottable.first) | |
194 | { |
|
197 | { | |
195 | case 0: |
|
198 | case 0: | |
196 | std::for_each(std::begin(*serie), std::end(*serie), |
|
199 | std::for_each(std::begin(*serie), std::end(*serie), | |
197 | [&dataContainer](const auto& value) { |
|
200 | [&dataContainer](const auto& value) { | |
198 | dataContainer->appendGraphData( |
|
201 | dataContainer->appendGraphData( | |
199 | QCPGraphData(value.t(), value.v().x)); |
|
202 | QCPGraphData(value.t(), value.v().x)); | |
200 | }); |
|
203 | }); | |
201 | break; |
|
204 | break; | |
202 | case 1: |
|
205 | case 1: | |
203 | std::for_each(std::begin(*serie), std::end(*serie), |
|
206 | std::for_each(std::begin(*serie), std::end(*serie), | |
204 | [&dataContainer](const auto& value) { |
|
207 | [&dataContainer](const auto& value) { | |
205 | dataContainer->appendGraphData( |
|
208 | dataContainer->appendGraphData( | |
206 | QCPGraphData(value.t(), value.v().y)); |
|
209 | QCPGraphData(value.t(), value.v().y)); | |
207 | }); |
|
210 | }); | |
208 | break; |
|
211 | break; | |
209 | case 2: |
|
212 | case 2: | |
210 | std::for_each(std::begin(*serie), std::end(*serie), |
|
213 | std::for_each(std::begin(*serie), std::end(*serie), | |
211 | [&dataContainer](const auto& value) { |
|
214 | [&dataContainer](const auto& value) { | |
212 | dataContainer->appendGraphData( |
|
215 | dataContainer->appendGraphData( | |
213 | QCPGraphData(value.t(), value.v().z)); |
|
216 | QCPGraphData(value.t(), value.v().z)); | |
214 | }); |
|
217 | }); | |
215 | break; |
|
218 | break; | |
216 | default: |
|
219 | default: | |
217 | break; |
|
220 | break; | |
218 | } |
|
221 | } | |
219 | } |
|
222 | } | |
220 | graph->setData(dataContainer); |
|
223 | graph->setData(dataContainer); | |
221 | } |
|
224 | } | |
222 | } |
|
225 | } | |
223 |
|
226 | |||
224 | if (!plottables.empty()) |
|
227 | if (!plottables.empty()) | |
225 | { |
|
228 | { | |
226 | auto plot = plottables.begin()->second->parentPlot(); |
|
229 | auto plot = plottables.begin()->second->parentPlot(); | |
227 |
|
230 | |||
228 | if (rescaleAxes) |
|
231 | if (rescaleAxes) | |
229 | { |
|
232 | { | |
230 | plot->rescaleAxes(); |
|
233 | plot->rescaleAxes(); | |
231 | } |
|
234 | } | |
232 | } |
|
235 | } | |
233 | } |
|
236 | } | |
234 | }; |
|
237 | }; | |
235 |
|
238 | |||
236 | /** |
|
239 | /** | |
237 | * Specialization of PlottablesUpdater for spectrograms |
|
240 | * Specialization of PlottablesUpdater for spectrograms | |
238 | * @sa SpectrogramSeries |
|
241 | * @sa SpectrogramSeries | |
239 | */ |
|
242 | */ | |
240 | template <typename T> |
|
243 | template <typename T> | |
241 | struct PlottablesUpdater<T, |
|
244 | struct PlottablesUpdater<T, | |
242 | typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>> |
|
245 | typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>> | |
243 | { |
|
246 | { | |
244 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) |
|
247 | static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot) | |
245 | { |
|
248 | { | |
246 | // TODO |
|
249 | // TODO | |
247 | // double min, max; |
|
250 | // double min, max; | |
248 | // std::tie(min, max) = dataSeries.yBounds(); |
|
251 | // std::tie(min, max) = dataSeries.yBounds(); | |
249 |
|
252 | |||
250 | // if (!std::isnan(min) && !std::isnan(max)) |
|
253 | // if (!std::isnan(min) && !std::isnan(max)) | |
251 | // { |
|
254 | // { | |
252 | // plot.yAxis->setRange(QCPRange { min, max }); |
|
255 | // plot.yAxis->setRange(QCPRange { min, max }); | |
253 | // } |
|
256 | // } | |
254 | } |
|
257 | } | |
255 |
|
258 | |||
256 | static void updatePlottables( |
|
259 | static void updatePlottables( | |
257 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) |
|
260 | T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) | |
258 | { |
|
261 | { | |
259 | // TODO |
|
262 | // TODO | |
260 | // if (plottables.empty()) |
|
263 | // if (plottables.empty()) | |
261 | // { |
|
264 | // { | |
262 | // qCDebug(LOG_VisualizationGraphHelper()) |
|
265 | // qCDebug(LOG_VisualizationGraphHelper()) | |
263 | // << QObject::tr("Can't update spectrogram: no colormap has been |
|
266 | // << QObject::tr("Can't update spectrogram: no colormap has been | |
264 | // associated"); |
|
267 | // associated"); | |
265 | // return; |
|
268 | // return; | |
266 | // } |
|
269 | // } | |
267 |
|
270 | |||
268 | // // Gets the colormap to update (normally there is only one colormap) |
|
271 | // // Gets the colormap to update (normally there is only one colormap) | |
269 | // Q_ASSERT(plottables.size() == 1); |
|
272 | // Q_ASSERT(plottables.size() == 1); | |
270 | // auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0)); |
|
273 | // auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0)); | |
271 | // Q_ASSERT(colormap != nullptr); |
|
274 | // Q_ASSERT(colormap != nullptr); | |
272 |
|
275 | |||
273 | // dataSeries.lockRead(); |
|
276 | // dataSeries.lockRead(); | |
274 |
|
277 | |||
275 | // // Processing spectrogram data for display in QCustomPlot |
|
278 | // // Processing spectrogram data for display in QCustomPlot | |
276 | // auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd); |
|
279 | // auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd); | |
277 |
|
280 | |||
278 | // // Computes logarithmic y-axis resolution for the spectrogram |
|
281 | // // Computes logarithmic y-axis resolution for the spectrogram | |
279 | // auto yData = its.first->y(); |
|
282 | // auto yData = its.first->y(); | |
280 | // auto yResolution = DataSeriesUtils::resolution(yData.begin(), yData.end(), true); |
|
283 | // auto yResolution = DataSeriesUtils::resolution(yData.begin(), yData.end(), true); | |
281 |
|
284 | |||
282 | // // Generates mesh for colormap |
|
285 | // // Generates mesh for colormap | |
283 | // auto mesh = DataSeriesUtils::regularMesh(its.first, its.second, |
|
286 | // auto mesh = DataSeriesUtils::regularMesh(its.first, its.second, | |
284 | // DataSeriesUtils::Resolution { dataSeries.xResolution() }, yResolution); |
|
287 | // DataSeriesUtils::Resolution { dataSeries.xResolution() }, yResolution); | |
285 |
|
288 | |||
286 | // dataSeries.unlock(); |
|
289 | // dataSeries.unlock(); | |
287 |
|
290 | |||
288 | // colormap->data()->setSize(mesh.m_NbX, mesh.m_NbY); |
|
291 | // colormap->data()->setSize(mesh.m_NbX, mesh.m_NbY); | |
289 | // if (!mesh.isEmpty()) |
|
292 | // if (!mesh.isEmpty()) | |
290 | // { |
|
293 | // { | |
291 | // colormap->data()->setRange(QCPRange { mesh.m_XMin, mesh.xMax() }, |
|
294 | // colormap->data()->setRange(QCPRange { mesh.m_XMin, mesh.xMax() }, | |
292 | // // y-axis range is converted to linear values |
|
295 | // // y-axis range is converted to linear values | |
293 | // QCPRange { std::pow(10, mesh.m_YMin), std::pow(10, mesh.yMax()) }); |
|
296 | // QCPRange { std::pow(10, mesh.m_YMin), std::pow(10, mesh.yMax()) }); | |
294 |
|
297 | |||
295 | // // Sets values |
|
298 | // // Sets values | |
296 | // auto index = 0; |
|
299 | // auto index = 0; | |
297 | // for (auto it = mesh.m_Data.begin(), end = mesh.m_Data.end(); it != end; ++it, |
|
300 | // for (auto it = mesh.m_Data.begin(), end = mesh.m_Data.end(); it != end; ++it, | |
298 | // ++index) |
|
301 | // ++index) | |
299 | // { |
|
302 | // { | |
300 | // auto xIndex = index % mesh.m_NbX; |
|
303 | // auto xIndex = index % mesh.m_NbX; | |
301 | // auto yIndex = index / mesh.m_NbX; |
|
304 | // auto yIndex = index / mesh.m_NbX; | |
302 |
|
305 | |||
303 | // colormap->data()->setCell(xIndex, yIndex, *it); |
|
306 | // colormap->data()->setCell(xIndex, yIndex, *it); | |
304 |
|
307 | |||
305 | // // Makes the NaN values to be transparent in the colormap |
|
308 | // // Makes the NaN values to be transparent in the colormap | |
306 | // if (std::isnan(*it)) |
|
309 | // if (std::isnan(*it)) | |
307 | // { |
|
310 | // { | |
308 | // colormap->data()->setAlpha(xIndex, yIndex, 0); |
|
311 | // colormap->data()->setAlpha(xIndex, yIndex, 0); | |
309 | // } |
|
312 | // } | |
310 | // } |
|
313 | // } | |
311 | // } |
|
314 | // } | |
312 |
|
315 | |||
313 | // // Rescales axes |
|
316 | // // Rescales axes | |
314 | // auto plot = colormap->parentPlot(); |
|
317 | // auto plot = colormap->parentPlot(); | |
315 |
|
318 | |||
316 | // if (rescaleAxes) |
|
319 | // if (rescaleAxes) | |
317 | // { |
|
320 | // { | |
318 | // plot->rescaleAxes(); |
|
321 | // plot->rescaleAxes(); | |
319 | // } |
|
322 | // } | |
320 | } |
|
323 | } | |
321 | }; |
|
324 | }; | |
322 |
|
325 | |||
323 | /** |
|
326 | /** | |
324 | * Helper used to create/update plottables |
|
327 | * Helper used to create/update plottables | |
325 | */ |
|
328 | */ | |
326 | struct IPlottablesHelper |
|
329 | struct IPlottablesHelper | |
327 | { |
|
330 | { | |
328 | virtual ~IPlottablesHelper() noexcept = default; |
|
331 | virtual ~IPlottablesHelper() noexcept = default; | |
329 | virtual PlottablesMap create(QCustomPlot& plot) const = 0; |
|
332 | virtual PlottablesMap create(QCustomPlot& plot) const = 0; | |
330 | virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0; |
|
333 | virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0; | |
331 | virtual void update( |
|
334 | virtual void update( | |
332 | PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0; |
|
335 | PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0; | |
333 | }; |
|
336 | }; | |
334 |
|
337 | |||
335 | /** |
|
338 | /** | |
336 | * Default implementation of IPlottablesHelper, which takes data series to create/update plottables |
|
339 | * Default implementation of IPlottablesHelper, which takes data series to create/update plottables | |
337 | * @tparam T the data series' type |
|
340 | * @tparam T the data series' type | |
338 | */ |
|
341 | */ | |
339 | template <typename T> |
|
342 | template <typename T> | |
340 | struct PlottablesHelper : public IPlottablesHelper |
|
343 | struct PlottablesHelper : public IPlottablesHelper | |
341 | { |
|
344 | { | |
342 | explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries { dataSeries } {} |
|
345 | explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries { dataSeries } {} | |
343 |
|
346 | |||
344 | PlottablesMap create(QCustomPlot& plot) const override |
|
347 | PlottablesMap create(QCustomPlot& plot) const override | |
345 | { |
|
348 | { | |
346 | return PlottablesCreator<T>::createPlottables(plot); |
|
349 | return PlottablesCreator<T>::createPlottables(plot); | |
347 | } |
|
350 | } | |
348 |
|
351 | |||
349 | void update( |
|
352 | void update( | |
350 | PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override |
|
353 | PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override | |
351 | { |
|
354 | { | |
352 | if (m_DataSeries) |
|
355 | if (m_DataSeries) | |
353 | { |
|
356 | { | |
354 | PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes); |
|
357 | PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes); | |
355 | } |
|
358 | } | |
356 | else |
|
359 | else | |
357 | { |
|
360 | { | |
358 | qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency " |
|
361 | qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency " | |
359 | "between the type of data series and the " |
|
362 | "between the type of data series and the " | |
360 | "type supposed"; |
|
363 | "type supposed"; | |
361 | } |
|
364 | } | |
362 | } |
|
365 | } | |
363 |
|
366 | |||
364 | void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override |
|
367 | void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override | |
365 | { |
|
368 | { | |
366 | if (m_DataSeries) |
|
369 | if (m_DataSeries) | |
367 | { |
|
370 | { | |
368 | PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot); |
|
371 | PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot); | |
369 | } |
|
372 | } | |
370 | else |
|
373 | else | |
371 | { |
|
374 | { | |
372 | qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency " |
|
375 | qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency " | |
373 | "between the type of data series and the " |
|
376 | "between the type of data series and the " | |
374 | "type supposed"; |
|
377 | "type supposed"; | |
375 | } |
|
378 | } | |
376 | } |
|
379 | } | |
377 |
|
380 | |||
378 | std::shared_ptr<T> m_DataSeries; |
|
381 | std::shared_ptr<T> m_DataSeries; | |
379 | }; |
|
382 | }; | |
380 |
|
383 | |||
381 | /// Creates IPlottablesHelper according to the type of data series a variable holds |
|
384 | /// Creates IPlottablesHelper according to the type of data series a variable holds | |
382 | std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept |
|
385 | std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept | |
383 | { |
|
386 | { | |
384 | switch (variable->type()) |
|
387 | switch (variable->type()) | |
385 | { |
|
388 | { | |
386 | case DataSeriesType::SCALAR: |
|
389 | case DataSeriesType::SCALAR: | |
387 | return std::make_unique<PlottablesHelper<ScalarTimeSerie>>( |
|
390 | return std::make_unique<PlottablesHelper<ScalarTimeSerie>>( | |
388 | std::dynamic_pointer_cast<ScalarTimeSerie>(variable->data())); |
|
391 | std::dynamic_pointer_cast<ScalarTimeSerie>(variable->data())); | |
389 | case DataSeriesType::SPECTROGRAM: |
|
392 | case DataSeriesType::SPECTROGRAM: | |
390 | return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>( |
|
393 | return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>( | |
391 | std::dynamic_pointer_cast<SpectrogramTimeSerie>(variable->data())); |
|
394 | std::dynamic_pointer_cast<SpectrogramTimeSerie>(variable->data())); | |
392 | case DataSeriesType::VECTOR: |
|
395 | case DataSeriesType::VECTOR: | |
393 | return std::make_unique<PlottablesHelper<VectorTimeSerie>>( |
|
396 | return std::make_unique<PlottablesHelper<VectorTimeSerie>>( | |
394 | std::dynamic_pointer_cast<VectorTimeSerie>(variable->data())); |
|
397 | std::dynamic_pointer_cast<VectorTimeSerie>(variable->data())); | |
395 | default: |
|
398 | default: | |
396 | // Creates default helper |
|
399 | // Creates default helper | |
397 | break; |
|
400 | break; | |
398 | } |
|
401 | } | |
399 |
|
402 | |||
400 | return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr); |
|
403 | return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr); | |
401 | } |
|
404 | } | |
402 |
|
405 | |||
403 | } // namespace |
|
406 | } // namespace | |
404 |
|
407 | |||
405 | PlottablesMap VisualizationGraphHelper::create( |
|
408 | PlottablesMap VisualizationGraphHelper::create( | |
406 | std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept |
|
409 | std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept | |
407 | { |
|
410 | { | |
408 | if (variable) |
|
411 | if (variable) | |
409 | { |
|
412 | { | |
410 | auto helper = createHelper(variable); |
|
413 | auto helper = createHelper(variable); | |
411 | auto plottables = helper->create(plot); |
|
414 | auto plottables = helper->create(plot); | |
412 | return plottables; |
|
415 | return plottables; | |
413 | } |
|
416 | } | |
414 | else |
|
417 | else | |
415 | { |
|
418 | { | |
416 | qCDebug(LOG_VisualizationGraphHelper()) |
|
419 | qCDebug(LOG_VisualizationGraphHelper()) | |
417 | << QObject::tr("Can't create graph plottables : the variable is null"); |
|
420 | << QObject::tr("Can't create graph plottables : the variable is null"); | |
418 | return PlottablesMap {}; |
|
421 | return PlottablesMap {}; | |
419 | } |
|
422 | } | |
420 | } |
|
423 | } | |
421 |
|
424 | |||
422 | void VisualizationGraphHelper::setYAxisRange( |
|
425 | void VisualizationGraphHelper::setYAxisRange( | |
423 | std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept |
|
426 | std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept | |
424 | { |
|
427 | { | |
425 | if (variable) |
|
428 | if (variable) | |
426 | { |
|
429 | { | |
427 | auto helper = createHelper(variable); |
|
430 | auto helper = createHelper(variable); | |
428 | helper->setYAxisRange(variable->range(), plot); |
|
431 | helper->setYAxisRange(variable->range(), plot); | |
429 | } |
|
432 | } | |
430 | else |
|
433 | else | |
431 | { |
|
434 | { | |
432 | qCDebug(LOG_VisualizationGraphHelper()) |
|
435 | qCDebug(LOG_VisualizationGraphHelper()) | |
433 | << QObject::tr("Can't set y-axis range of plot: the variable is null"); |
|
436 | << QObject::tr("Can't set y-axis range of plot: the variable is null"); | |
434 | } |
|
437 | } | |
435 | } |
|
438 | } | |
436 |
|
439 | |||
437 | void VisualizationGraphHelper::updateData( |
|
440 | void VisualizationGraphHelper::updateData( | |
438 | PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime) |
|
441 | PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime) | |
439 | { |
|
442 | { | |
440 | auto helper = createHelper(variable); |
|
443 | auto helper = createHelper(variable); | |
441 | helper->update(plottables, dateTime); |
|
444 | helper->update(plottables, dateTime); | |
442 | } |
|
445 | } |
@@ -1,3 +1,4 | |||||
1 | add_subdirectory(mockplugin) |
|
1 | add_subdirectory(mockplugin) | |
2 |
add_subdirectory( |
|
2 | add_subdirectory(python_providers) | |
3 |
add_subdirectory( |
|
3 | #add_subdirectory(amda) | |
|
4 | #add_subdirectory(generic_ws) |
@@ -1,30 +1,30 | |||||
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 | { | |||
21 | Q_OBJECT |
|
22 | Q_OBJECT | |
22 | public: |
|
23 | public: | |
23 | explicit AmdaProvider(); |
|
24 | explicit AmdaProvider(); | |
24 | std::shared_ptr<IDataProvider> clone() const override; |
|
25 | std::shared_ptr<IDataProvider> clone() const override; | |
25 |
|
26 | |||
26 |
virtual |
|
27 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override; | |
27 |
|
||||
28 | }; |
|
28 | }; | |
29 |
|
29 | |||
30 | #endif // SCIQLOP_AMDAPROVIDER_H |
|
30 | #endif // SCIQLOP_AMDAPROVIDER_H |
@@ -1,88 +1,85 | |||||
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 | #include "AmdaServer.h" | |
5 |
|
5 | |||
6 | #include <Common/DateUtils.h> |
|
6 | #include <Common/DateUtils.h> | |
7 | #include <Data/DataProviderParameters.h> |
|
7 | #include <Data/DataProviderParameters.h> | |
8 | #include <Network/NetworkController.h> |
|
8 | #include <Network/NetworkController.h> | |
9 | #include <SqpApplication.h> |
|
9 | #include <SqpApplication.h> | |
10 | #include <Variable/Variable.h> |
|
|||
11 |
|
10 | |||
|
11 | #include <Network/Downloader.h> | |||
|
12 | #include <QJsonDocument> | |||
12 | #include <QNetworkAccessManager> |
|
13 | #include <QNetworkAccessManager> | |
13 | #include <QNetworkReply> |
|
14 | #include <QNetworkReply> | |
14 | #include <QTemporaryFile> |
|
15 | #include <QTemporaryFile> | |
15 | #include <QThread> |
|
16 | #include <QThread> | |
16 | #include <QJsonDocument> |
|
|||
17 | #include <Network/Downloader.h> |
|
|||
18 |
|
17 | |||
19 | Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider") |
|
18 | Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider") | |
20 |
|
19 | |||
21 |
namespace |
|
20 | namespace | |
|
21 | { | |||
22 |
|
22 | |||
23 | /// URL format for a request on AMDA server. The parameters are as follows: |
|
23 | /// URL format for a request on AMDA server. The parameters are as follows: | |
24 | /// - %1: server URL |
|
24 | /// - %1: server URL | |
25 | /// - %2: start date |
|
25 | /// - %2: start date | |
26 | /// - %3: end date |
|
26 | /// - %3: end date | |
27 | /// - %4: parameter id |
|
27 | /// - %4: parameter id | |
28 | /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/ |
|
28 | /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/ | |
29 | const auto AMDA_URL_FORMAT = QStringLiteral( |
|
29 | const auto AMDA_URL_FORMAT = QStringLiteral( | |
30 | "http://%1/php/rest/" |
|
30 | "http://%1/php/rest/" | |
31 | "getParameter.php?startTime=%2&stopTime=%3¶meterID=%4&outputFormat=ASCII&" |
|
31 | "getParameter.php?startTime=%2&stopTime=%3¶meterID=%4&outputFormat=ASCII&" | |
32 | "timeFormat=ISO8601&gzip=0"); |
|
32 | "timeFormat=ISO8601&gzip=0"); | |
33 |
|
33 | |||
34 | const auto AMDA_URL_FORMAT_WITH_TOKEN = QStringLiteral( |
|
34 | const auto AMDA_URL_FORMAT_WITH_TOKEN = QStringLiteral( | |
35 | "http://%1/php/rest/" |
|
35 | "http://%1/php/rest/" | |
36 | "getParameter.php?startTime=%2&stopTime=%3¶meterID=%4&outputFormat=ASCII&" |
|
36 | "getParameter.php?startTime=%2&stopTime=%3¶meterID=%4&outputFormat=ASCII&" | |
37 | "timeFormat=ISO8601&gzip=0&" |
|
37 | "timeFormat=ISO8601&gzip=0&" | |
38 | "token=%5"); |
|
38 | "token=%5"); | |
39 |
|
39 | |||
40 | const auto AMDA_TOKEN_URL_FORMAT = QStringLiteral( |
|
40 | const auto AMDA_TOKEN_URL_FORMAT = QStringLiteral( | |
41 | "http://%1/php/rest/" |
|
41 | "http://%1/php/rest/" | |
42 | "auth.php"); |
|
42 | "auth.php"); | |
43 |
|
43 | |||
44 | /// Dates format passed in the URL (e.g 2013-09-23T09:00) |
|
44 | /// Dates format passed in the URL (e.g 2013-09-23T09:00) | |
45 | const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss"); |
|
45 | const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss"); | |
46 |
|
46 | |||
47 | /// Formats a time to a date that can be passed in URL |
|
47 | /// Formats a time to a date that can be passed in URL | |
48 | QString dateFormat(double sqpRange) noexcept |
|
48 | QString dateFormat(double sqpRange) noexcept | |
49 | { |
|
49 | { | |
50 | auto dateTime = DateUtils::dateTime(sqpRange); |
|
50 | auto dateTime = DateUtils::dateTime(sqpRange); | |
51 | return dateTime.toString(AMDA_TIME_FORMAT); |
|
51 | return dateTime.toString(AMDA_TIME_FORMAT); | |
52 | } |
|
52 | } | |
53 |
|
53 | |||
54 |
|
54 | |||
55 | } // namespace |
|
55 | } // namespace | |
56 |
|
56 | |||
57 | AmdaProvider::AmdaProvider() |
|
57 | AmdaProvider::AmdaProvider() {} | |
58 | { |
|
|||
59 |
|
||||
60 | } |
|
|||
61 |
|
58 | |||
62 | std::shared_ptr<IDataProvider> AmdaProvider::clone() const |
|
59 | std::shared_ptr<IDataProvider> AmdaProvider::clone() const | |
63 | { |
|
60 | { | |
64 | // No copy is made in the clone |
|
61 | // No copy is made in the clone | |
65 | return std::make_shared<AmdaProvider>(); |
|
62 | return std::make_shared<AmdaProvider>(); | |
66 | } |
|
63 | } | |
67 |
|
64 | |||
68 |
|
|
65 | TimeSeries::ITimeSerie* AmdaProvider::getData(const DataProviderParameters& parameters) | |
69 | { |
|
66 | { | |
70 | auto range = parameters.m_Range; |
|
67 | auto range = parameters.m_Range; | |
71 | auto metaData = parameters.m_Data; |
|
68 | auto metaData = parameters.m_Data; | |
72 | auto productId = metaData.value(AMDA_XML_ID_KEY).toString(); |
|
69 | auto productId = metaData.value(AMDA_XML_ID_KEY).toString(); | |
73 | auto productValueType |
|
70 | auto productValueType | |
74 | = DataSeriesTypeUtils::fromString(metaData.value(AMDA_DATA_TYPE_KEY).toString()); |
|
71 | = DataSeriesTypeUtils::fromString(metaData.value(AMDA_DATA_TYPE_KEY).toString()); | |
75 | auto startDate = dateFormat(range.m_TStart); |
|
72 | auto startDate = dateFormat(range.m_TStart); | |
76 | auto endDate = dateFormat(range.m_TEnd); |
|
73 | auto endDate = dateFormat(range.m_TEnd); | |
77 | QVariantHash urlProperties{{AMDA_SERVER_KEY, metaData.value(AMDA_SERVER_KEY)}}; |
|
74 | QVariantHash urlProperties { { AMDA_SERVER_KEY, metaData.value(AMDA_SERVER_KEY) } }; | |
78 | auto token_url = QString{AMDA_TOKEN_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties)); |
|
75 | auto token_url | |
|
76 | = QString { AMDA_TOKEN_URL_FORMAT }.arg(AmdaServer::instance().url(urlProperties)); | |||
79 | auto response = Downloader::get(token_url); |
|
77 | auto response = Downloader::get(token_url); | |
80 | auto url = QString{AMDA_URL_FORMAT_WITH_TOKEN}.arg(AmdaServer::instance().url(urlProperties), |
|
78 | auto url = QString { AMDA_URL_FORMAT_WITH_TOKEN }.arg(AmdaServer::instance().url(urlProperties), | |
81 |
|
|
79 | startDate, endDate, productId, QString(response.data())); | |
82 | response = Downloader::get(url); |
|
80 | response = Downloader::get(url); | |
83 | auto test = QJsonDocument::fromJson(response.data()); |
|
81 | auto test = QJsonDocument::fromJson(response.data()); | |
84 | url = test["dataFileURLs"].toString(); |
|
82 | url = test["dataFileURLs"].toString(); | |
85 | response = Downloader::get(url); |
|
83 | response = Downloader::get(url); | |
86 |
return |
|
84 | return nullptr; // AmdaResultParser::readTxt(QTextStream { response.data() }, productValueType); | |
87 | } |
|
85 | } | |
88 |
|
@@ -1,150 +1,149 | |||||
1 | #include "AmdaResultParser.h" |
|
1 | #include "AmdaResultParser.h" | |
2 |
|
2 | |||
3 | #include "AmdaResultParserHelper.h" |
|
3 | #include "AmdaResultParserHelper.h" | |
4 |
|
4 | |||
5 | #include <QFile> |
|
5 | #include <QFile> | |
6 |
|
6 | |||
7 | #include <Data/IDataSeries.h> |
|
|||
8 | #include <cmath> |
|
7 | #include <cmath> | |
9 |
|
8 | |||
10 | Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser") |
|
9 | Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser") | |
11 |
|
10 | |||
12 | namespace |
|
11 | namespace | |
13 | { |
|
12 | { | |
14 |
|
13 | |||
15 | /// Message in result file when the file was not found on server |
|
14 | /// Message in result file when the file was not found on server | |
16 | const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found"); |
|
15 | const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found"); | |
17 |
|
16 | |||
18 | /// Checks if a line is a comment line |
|
17 | /// Checks if a line is a comment line | |
19 | bool isCommentLine(const QString& line) |
|
18 | bool isCommentLine(const QString& line) | |
20 | { |
|
19 | { | |
21 | return line.startsWith("#"); |
|
20 | return line.startsWith("#"); | |
22 | } |
|
21 | } | |
23 |
|
22 | |||
24 | /** |
|
23 | /** | |
25 | * Creates helper that will be used to read AMDA file, according to the type passed as parameter |
|
24 | * Creates helper that will be used to read AMDA file, according to the type passed as parameter | |
26 | * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...) |
|
25 | * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...) | |
27 | * @return the helper created |
|
26 | * @return the helper created | |
28 | */ |
|
27 | */ | |
29 | std::unique_ptr<IAmdaResultParserHelper> createHelper(DataSeriesType valueType) |
|
28 | std::unique_ptr<IAmdaResultParserHelper> createHelper(DataSeriesType valueType) | |
30 | { |
|
29 | { | |
31 | switch (valueType) |
|
30 | switch (valueType) | |
32 | { |
|
31 | { | |
33 | case DataSeriesType::SCALAR: |
|
32 | case DataSeriesType::SCALAR: | |
34 | return std::make_unique<ScalarParserHelper>(); |
|
33 | return std::make_unique<ScalarParserHelper>(); | |
35 | case DataSeriesType::SPECTROGRAM: |
|
34 | case DataSeriesType::SPECTROGRAM: | |
36 | return std::make_unique<SpectrogramParserHelper>(); |
|
35 | return std::make_unique<SpectrogramParserHelper>(); | |
37 | case DataSeriesType::VECTOR: |
|
36 | case DataSeriesType::VECTOR: | |
38 | return std::make_unique<VectorParserHelper>(); |
|
37 | return std::make_unique<VectorParserHelper>(); | |
39 | case DataSeriesType::NONE: |
|
38 | case DataSeriesType::NONE: | |
40 | // Invalid case |
|
39 | // Invalid case | |
41 | break; |
|
40 | break; | |
42 | } |
|
41 | } | |
43 |
|
42 | |||
44 | // Invalid cases |
|
43 | // Invalid cases | |
45 | qCCritical(LOG_AmdaResultParser()) |
|
44 | qCCritical(LOG_AmdaResultParser()) | |
46 | << QObject::tr("Can't create helper to read result file: unsupported type"); |
|
45 | << QObject::tr("Can't create helper to read result file: unsupported type"); | |
47 | return nullptr; |
|
46 | return nullptr; | |
48 | } |
|
47 | } | |
49 |
|
48 | |||
50 | /** |
|
49 | /** | |
51 | * Reads properties of the stream passed as parameter |
|
50 | * Reads properties of the stream passed as parameter | |
52 | * @param helper the helper used to read properties line by line |
|
51 | * @param helper the helper used to read properties line by line | |
53 | * @param stream the stream to read |
|
52 | * @param stream the stream to read | |
54 | */ |
|
53 | */ | |
55 | void readProperties(IAmdaResultParserHelper& helper, QTextStream& stream) |
|
54 | void readProperties(IAmdaResultParserHelper& helper, QTextStream& stream) | |
56 | { |
|
55 | { | |
57 | // Searches properties in the comment lines (as long as the reading has not reached the data) |
|
56 | // Searches properties in the comment lines (as long as the reading has not reached the data) | |
58 | // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) { |
|
57 | // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) { | |
59 | QString line {}; |
|
58 | QString line {}; | |
60 | while (stream.readLineInto(&line) && isCommentLine(line)) |
|
59 | while (stream.readLineInto(&line) && isCommentLine(line)) | |
61 | { |
|
60 | { | |
62 | helper.readPropertyLine(line); |
|
61 | helper.readPropertyLine(line); | |
63 | } |
|
62 | } | |
64 | } |
|
63 | } | |
65 |
|
64 | |||
66 | /** |
|
65 | /** | |
67 | * Reads results of the stream passed as parameter |
|
66 | * Reads results of the stream passed as parameter | |
68 | * @param helper the helper used to read results line by line |
|
67 | * @param helper the helper used to read results line by line | |
69 | * @param stream the stream to read |
|
68 | * @param stream the stream to read | |
70 | */ |
|
69 | */ | |
71 | void readResults(IAmdaResultParserHelper& helper, QTextStream& stream) |
|
70 | void readResults(IAmdaResultParserHelper& helper, QTextStream& stream) | |
72 | { |
|
71 | { | |
73 | QString line {}; |
|
72 | QString line {}; | |
74 |
|
73 | |||
75 | // Skip comment lines |
|
74 | // Skip comment lines | |
76 | while (stream.readLineInto(&line) && isCommentLine(line)) |
|
75 | while (stream.readLineInto(&line) && isCommentLine(line)) | |
77 | { |
|
76 | { | |
78 | } |
|
77 | } | |
79 |
|
78 | |||
80 | if (!stream.atEnd()) |
|
79 | if (!stream.atEnd()) | |
81 | { |
|
80 | { | |
82 | do |
|
81 | do | |
83 | { |
|
82 | { | |
84 | helper.readResultLine(line); |
|
83 | helper.readResultLine(line); | |
85 | } while (stream.readLineInto(&line)); |
|
84 | } while (stream.readLineInto(&line)); | |
86 | } |
|
85 | } | |
87 | } |
|
86 | } | |
88 |
|
87 | |||
89 | } // namespace |
|
88 | } // namespace | |
90 |
|
89 | |||
91 | std::shared_ptr<IDataSeries> AmdaResultParser::readTxt( |
|
90 | std::shared_ptr<IDataSeries> AmdaResultParser::readTxt( | |
92 | const QString& filePath, DataSeriesType type) noexcept |
|
91 | const QString& filePath, DataSeriesType type) noexcept | |
93 | { |
|
92 | { | |
94 | if (type == DataSeriesType::NONE) |
|
93 | if (type == DataSeriesType::NONE) | |
95 | { |
|
94 | { | |
96 | qCCritical(LOG_AmdaResultParser()) |
|
95 | qCCritical(LOG_AmdaResultParser()) | |
97 | << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown"); |
|
96 | << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown"); | |
98 | return nullptr; |
|
97 | return nullptr; | |
99 | } |
|
98 | } | |
100 |
|
99 | |||
101 | QFile file { filePath }; |
|
100 | QFile file { filePath }; | |
102 |
|
101 | |||
103 | if (!file.open(QFile::ReadOnly | QIODevice::Text)) |
|
102 | if (!file.open(QFile::ReadOnly | QIODevice::Text)) | |
104 | { |
|
103 | { | |
105 | qCCritical(LOG_AmdaResultParser()) |
|
104 | qCCritical(LOG_AmdaResultParser()) | |
106 | << QObject::tr("Can't retrieve AMDA data from file %1: %2") |
|
105 | << QObject::tr("Can't retrieve AMDA data from file %1: %2") | |
107 | .arg(filePath, file.errorString()); |
|
106 | .arg(filePath, file.errorString()); | |
108 | return nullptr; |
|
107 | return nullptr; | |
109 | } |
|
108 | } | |
110 |
|
109 | |||
111 | return std::shared_ptr<IDataSeries> { AmdaResultParser::readTxt(QTextStream { &file }, type) }; |
|
110 | return std::shared_ptr<IDataSeries> { AmdaResultParser::readTxt(QTextStream { &file }, type) }; | |
112 | } |
|
111 | } | |
113 |
|
112 | |||
114 | IDataSeries* AmdaResultParser::readTxt(QTextStream stream, DataSeriesType type) noexcept |
|
113 | IDataSeries* AmdaResultParser::readTxt(QTextStream stream, DataSeriesType type) noexcept | |
115 | { |
|
114 | { | |
116 | if (type == DataSeriesType::NONE) |
|
115 | if (type == DataSeriesType::NONE) | |
117 | { |
|
116 | { | |
118 | return nullptr; |
|
117 | return nullptr; | |
119 | } |
|
118 | } | |
120 |
|
119 | |||
121 | // Checks if the file was found on the server |
|
120 | // Checks if the file was found on the server | |
122 | auto firstLine = stream.readLine(); |
|
121 | auto firstLine = stream.readLine(); | |
123 | if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) |
|
122 | if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) | |
124 | { |
|
123 | { | |
125 | return nullptr; |
|
124 | return nullptr; | |
126 | } |
|
125 | } | |
127 |
|
126 | |||
128 | auto helper = createHelper(type); |
|
127 | auto helper = createHelper(type); | |
129 | Q_ASSERT(helper != nullptr); |
|
128 | Q_ASSERT(helper != nullptr); | |
130 |
|
129 | |||
131 | // Reads header file to retrieve properties |
|
130 | // Reads header file to retrieve properties | |
132 | stream.seek(0); // returns to the beginning of the file |
|
131 | stream.seek(0); // returns to the beginning of the file | |
133 | readProperties(*helper, stream); |
|
132 | readProperties(*helper, stream); | |
134 |
|
133 | |||
135 | // Checks properties |
|
134 | // Checks properties | |
136 | if (helper->checkProperties()) |
|
135 | if (helper->checkProperties()) | |
137 | { |
|
136 | { | |
138 | // Reads results |
|
137 | // Reads results | |
139 | // AMDA V2: remove line |
|
138 | // AMDA V2: remove line | |
140 | stream.seek(0); // returns to the beginning of the file |
|
139 | stream.seek(0); // returns to the beginning of the file | |
141 | readResults(*helper, stream); |
|
140 | readResults(*helper, stream); | |
142 |
|
141 | |||
143 | // Creates data series |
|
142 | // Creates data series | |
144 | return helper->createSeries(); |
|
143 | return helper->createSeries(); | |
145 | } |
|
144 | } | |
146 | else |
|
145 | else | |
147 | { |
|
146 | { | |
148 | return nullptr; |
|
147 | return nullptr; | |
149 | } |
|
148 | } | |
150 | } |
|
149 | } |
@@ -1,128 +1,131 | |||||
1 | #ifndef SCIQLOP_FUZZINGDEFS_H |
|
1 | #ifndef SCIQLOP_FUZZINGDEFS_H | |
2 | #define SCIQLOP_FUZZINGDEFS_H |
|
2 | #define SCIQLOP_FUZZINGDEFS_H | |
3 |
|
3 | |||
4 | #include <Data/DateTimeRange.h> |
|
4 | #include <Data/DateTimeRange.h> | |
5 |
|
5 | |||
6 | #include <QString> |
|
6 | #include <QString> | |
7 | #include <QUuid> |
|
7 | #include <QUuid> | |
8 | #include <QVariantHash> |
|
8 | #include <QVariantHash> | |
9 |
|
9 | |||
10 | #include <memory> |
|
10 | #include <memory> | |
11 | #include <set> |
|
11 | #include <set> | |
12 |
|
12 | |||
13 | // /////// // |
|
13 | // /////// // | |
14 | // Aliases // |
|
14 | // Aliases // | |
15 | // /////// // |
|
15 | // /////// // | |
16 |
|
16 | |||
17 | using MetadataPool = std::vector<QVariantHash>; |
|
17 | using MetadataPool = std::vector<QVariantHash>; | |
18 | Q_DECLARE_METATYPE(MetadataPool) |
|
18 | Q_DECLARE_METATYPE(MetadataPool) | |
19 |
|
19 | |||
20 | using Properties = QVariantHash; |
|
20 | using Properties = QVariantHash; | |
21 |
|
21 | |||
22 | // ///////// // |
|
22 | // ///////// // | |
23 | // Constants // |
|
23 | // Constants // | |
24 | // ///////// // |
|
24 | // ///////// // | |
25 |
|
25 | |||
26 | /// Timeout set for data acquisition for an operation (in ms) |
|
26 | /// Timeout set for data acquisition for an operation (in ms) | |
27 | extern const QString ACQUISITION_TIMEOUT_PROPERTY; |
|
27 | extern const QString ACQUISITION_TIMEOUT_PROPERTY; | |
28 |
|
28 | |||
29 | /// Max number of operations to generate |
|
29 | /// Max number of operations to generate | |
30 | extern const QString NB_MAX_OPERATIONS_PROPERTY; |
|
30 | extern const QString NB_MAX_OPERATIONS_PROPERTY; | |
31 |
|
31 | |||
32 | /// Max number of sync groups to create through operations |
|
32 | /// Max number of sync groups to create through operations | |
33 | extern const QString NB_MAX_SYNC_GROUPS_PROPERTY; |
|
33 | extern const QString NB_MAX_SYNC_GROUPS_PROPERTY; | |
34 |
|
34 | |||
35 | /// Max number of variables to manipulate through operations |
|
35 | /// Max number of variables to manipulate through operations | |
36 | extern const QString NB_MAX_VARIABLES_PROPERTY; |
|
36 | extern const QString NB_MAX_VARIABLES_PROPERTY; | |
37 |
|
37 | |||
38 | /// Set of operations available for the test |
|
38 | /// Set of operations available for the test | |
39 | extern const QString AVAILABLE_OPERATIONS_PROPERTY; |
|
39 | extern const QString AVAILABLE_OPERATIONS_PROPERTY; | |
40 |
|
40 | |||
41 | /// Tolerance used for variable's cache (in ratio) |
|
41 | /// Tolerance used for variable's cache (in ratio) | |
42 | extern const QString CACHE_TOLERANCE_PROPERTY; |
|
42 | extern const QString CACHE_TOLERANCE_PROPERTY; | |
43 |
|
43 | |||
44 | /// Range with which the timecontroller is initialized |
|
44 | /// Range with which the timecontroller is initialized | |
45 | extern const QString INITIAL_RANGE_PROPERTY; |
|
45 | extern const QString INITIAL_RANGE_PROPERTY; | |
46 |
|
46 | |||
47 | /// Max range that an operation can reach |
|
47 | /// Max range that an operation can reach | |
48 | extern const QString MAX_RANGE_PROPERTY; |
|
48 | extern const QString MAX_RANGE_PROPERTY; | |
49 |
|
49 | |||
50 | /// Set of metadata that can be associated to a variable |
|
50 | /// Set of metadata that can be associated to a variable | |
51 | extern const QString METADATA_POOL_PROPERTY; |
|
51 | extern const QString METADATA_POOL_PROPERTY; | |
52 |
|
52 | |||
53 | /// Provider used to retrieve data |
|
53 | /// Provider used to retrieve data | |
54 | extern const QString PROVIDER_PROPERTY; |
|
54 | extern const QString PROVIDER_PROPERTY; | |
55 |
|
55 | |||
56 | /// Min/max times left for an operation to execute |
|
56 | /// Min/max times left for an operation to execute | |
57 | extern const QString OPERATION_DELAY_BOUNDS_PROPERTY; |
|
57 | extern const QString OPERATION_DELAY_BOUNDS_PROPERTY; | |
58 |
|
58 | |||
59 | /// Validators used to validate an operation |
|
59 | /// Validators used to validate an operation | |
60 | extern const QString VALIDATORS_PROPERTY; |
|
60 | extern const QString VALIDATORS_PROPERTY; | |
61 |
|
61 | |||
62 | /// Min/max number of operations to execute before calling validation of the current test's state |
|
62 | /// Min/max number of operations to execute before calling validation of the current test's state | |
63 | extern const QString VALIDATION_FREQUENCY_BOUNDS_PROPERTY; |
|
63 | extern const QString VALIDATION_FREQUENCY_BOUNDS_PROPERTY; | |
64 |
|
64 | |||
65 | // /////// // |
|
65 | // /////// // | |
66 | // Structs // |
|
66 | // Structs // | |
67 | // /////// // |
|
67 | // /////// // | |
68 |
|
68 | |||
69 | class Variable; |
|
69 | class Variable; | |
70 |
struct VariableState |
|
70 | struct VariableState | |
71 | std::shared_ptr<Variable> m_Variable{nullptr}; |
|
71 | { | |
72 | DateTimeRange m_Range{INVALID_RANGE}; |
|
72 | std::shared_ptr<Variable> m_Variable { nullptr }; | |
|
73 | DateTimeRange m_Range { INVALID_RANGE }; | |||
73 | }; |
|
74 | }; | |
74 |
|
75 | |||
75 | using VariableId = int; |
|
76 | using VariableId = int; | |
76 | using VariablesPool = std::map<VariableId, VariableState>; |
|
77 | using VariablesPool = std::map<VariableId, VariableState>; | |
77 |
|
78 | |||
78 | /** |
|
79 | /** | |
79 | * Defines a synchronization group for a fuzzing state. A group reports the variables synchronized |
|
80 | * Defines a synchronization group for a fuzzing state. A group reports the variables synchronized | |
80 | * with each other, and the current range of the group (i.e. range of the last synchronized variable |
|
81 | * with each other, and the current range of the group (i.e. range of the last synchronized variable | |
81 | * that has been moved) |
|
82 | * that has been moved) | |
82 | */ |
|
83 | */ | |
83 |
struct SyncGroup |
|
84 | struct SyncGroup | |
84 | std::set<VariableId> m_Variables{}; |
|
85 | { | |
85 | DateTimeRange m_Range{INVALID_RANGE}; |
|
86 | std::set<VariableId> m_Variables {}; | |
|
87 | DateTimeRange m_Range { INVALID_RANGE }; | |||
86 | }; |
|
88 | }; | |
87 |
|
89 | |||
88 | using SyncGroupId = QUuid; |
|
90 | using SyncGroupId = QUuid; | |
89 | using SyncGroupsPool = std::map<SyncGroupId, SyncGroup>; |
|
91 | using SyncGroupsPool = std::map<SyncGroupId, SyncGroup>; | |
90 |
|
92 | |||
91 | /** |
|
93 | /** | |
92 | * Defines a current state during a fuzzing state. It contains all the variables manipulated during |
|
94 | * Defines a current state during a fuzzing state. It contains all the variables manipulated during | |
93 | * the test, as well as the synchronization status of these variables. |
|
95 | * the test, as well as the synchronization status of these variables. | |
94 | */ |
|
96 | */ | |
95 |
struct FuzzingState |
|
97 | struct FuzzingState | |
96 | const SyncGroup &syncGroup(SyncGroupId id) const; |
|
98 | { | |
97 |
SyncGroup |
|
99 | const SyncGroup& syncGroup(SyncGroupId id) const; | |
|
100 | SyncGroup& syncGroup(SyncGroupId id); | |||
98 |
|
101 | |||
99 |
const VariableState |
|
102 | const VariableState& variableState(VariableId id) const; | |
100 |
VariableState |
|
103 | VariableState& variableState(VariableId id); | |
101 |
|
104 | |||
102 | /// @return the identifier of the synchronization group in which the variable passed in |
|
105 | /// @return the identifier of the synchronization group in which the variable passed in | |
103 | /// parameter is located. If the variable is not in any group, returns an invalid identifier |
|
106 | /// parameter is located. If the variable is not in any group, returns an invalid identifier | |
104 | SyncGroupId syncGroupId(VariableId variableId) const; |
|
107 | SyncGroupId syncGroupId(VariableId variableId) const; | |
105 |
|
108 | |||
106 | /// @return the set of synchronization group identifiers |
|
109 | /// @return the set of synchronization group identifiers | |
107 | std::vector<SyncGroupId> syncGroupsIds() const; |
|
110 | std::vector<SyncGroupId> syncGroupsIds() const; | |
108 |
|
111 | |||
109 | /// Updates fuzzing state according to a variable synchronization |
|
112 | /// Updates fuzzing state according to a variable synchronization | |
110 | /// @param variableId the variable that is synchronized |
|
113 | /// @param variableId the variable that is synchronized | |
111 | /// @param syncGroupId the synchronization group |
|
114 | /// @param syncGroupId the synchronization group | |
112 | void synchronizeVariable(VariableId variableId, SyncGroupId syncGroupId); |
|
115 | void synchronizeVariable(VariableId variableId, SyncGroupId syncGroupId); | |
113 |
|
116 | |||
114 | /// Updates fuzzing state according to a variable desynchronization |
|
117 | /// Updates fuzzing state according to a variable desynchronization | |
115 | /// @param variableId the variable that is desynchronized |
|
118 | /// @param variableId the variable that is desynchronized | |
116 | /// @param syncGroupId the synchronization group from which to remove the variable |
|
119 | /// @param syncGroupId the synchronization group from which to remove the variable | |
117 | void desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId); |
|
120 | void desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId); | |
118 |
|
121 | |||
119 | /// Updates the range of a variable and all variables to which it is synchronized |
|
122 | /// Updates the range of a variable and all variables to which it is synchronized | |
120 | /// @param the variable for which to affect the range |
|
123 | /// @param the variable for which to affect the range | |
121 | /// @param the range to affect |
|
124 | /// @param the range to affect | |
122 |
void updateRanges(VariableId variableId, const DateTimeRange |
|
125 | void updateRanges(VariableId variableId, const DateTimeRange& newRange); | |
123 |
|
126 | |||
124 | VariablesPool m_VariablesPool; |
|
127 | VariablesPool m_VariablesPool; | |
125 | SyncGroupsPool m_SyncGroupsPool; |
|
128 | SyncGroupsPool m_SyncGroupsPool; | |
126 | }; |
|
129 | }; | |
127 |
|
130 | |||
128 | #endif // SCIQLOP_FUZZINGDEFS_H |
|
131 | #endif // SCIQLOP_FUZZINGDEFS_H |
@@ -1,31 +1,32 | |||||
1 | #ifndef SCIQLOP_COSINUSPROVIDER_H |
|
1 | #ifndef SCIQLOP_COSINUSPROVIDER_H | |
2 | #define SCIQLOP_COSINUSPROVIDER_H |
|
2 | #define SCIQLOP_COSINUSPROVIDER_H | |
3 |
|
3 | |||
4 | #include "MockPluginGlobal.h" |
|
4 | #include "MockPluginGlobal.h" | |
5 |
|
5 | |||
6 | #include <Data/IDataProvider.h> |
|
6 | #include <Data/IDataProvider.h> | |
7 |
|
7 | |||
8 | #include <QLoggingCategory> |
|
8 | #include <QLoggingCategory> | |
9 | #include <QUuid> |
|
9 | #include <QUuid> | |
10 |
|
10 | |||
11 | #include <QHash> |
|
11 | #include <QHash> | |
12 |
|
12 | |||
13 | /** |
|
13 | /** | |
14 | * @brief The CosinusProvider class is an example of how a data provider can generate data |
|
14 | * @brief The CosinusProvider class is an example of how a data provider can generate data | |
15 | */ |
|
15 | */ | |
16 |
class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider |
|
16 | class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider | |
|
17 | { | |||
17 | public: |
|
18 | public: | |
18 | std::shared_ptr<IDataProvider> clone() const override; |
|
19 | std::shared_ptr<IDataProvider> clone() const override; | |
19 |
|
20 | |||
20 |
virtual |
|
21 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override; | |
21 |
|
22 | |||
22 | private: |
|
23 | private: | |
23 | std::shared_ptr<IDataSeries> |
|
24 | std::shared_ptr<IDataSeries> retrieveData( | |
24 |
|
|
25 | QUuid acqIdentifier, const DateTimeRange& dataRangeRequested, const QVariantHash& data); | |
25 |
|
26 | |||
26 |
|
|
27 | TimeSeries::ITimeSerie* _generate(const DateTimeRange& range, const QVariantHash& metaData); | |
27 |
|
28 | |||
28 | QHash<QUuid, bool> m_VariableToEnableProvider; |
|
29 | QHash<QUuid, bool> m_VariableToEnableProvider; | |
29 | }; |
|
30 | }; | |
30 |
|
31 | |||
31 | #endif // SCIQLOP_COSINUSPROVIDER_H |
|
32 | #endif // SCIQLOP_COSINUSPROVIDER_H |
@@ -1,204 +1,87 | |||||
1 | #include "CosinusProvider.h" |
|
1 | #include "CosinusProvider.h" | |
2 | #include "MockDefs.h" |
|
2 | #include "MockDefs.h" | |
3 |
|
3 | |||
4 | #include <Data/DataProviderParameters.h> |
|
4 | #include <Data/DataProviderParameters.h> | |
5 |
#include <Data/ScalarSerie |
|
5 | #include <Data/ScalarTimeSerie.h> | |
6 |
#include <Data/SpectrogramSerie |
|
6 | #include <Data/SpectrogramTimeSerie.h> | |
7 |
#include <Data/VectorSerie |
|
7 | #include <Data/VectorTimeSerie.h> | |
8 |
|
8 | |||
9 | #include <cmath> |
|
9 | #include <cmath> | |
10 | #include <set> |
|
10 | #include <set> | |
11 |
|
11 | |||
12 | #include <QFuture> |
|
12 | #include <QFuture> | |
13 | #include <QThread> |
|
13 | #include <QThread> | |
14 | #include <QtConcurrent/QtConcurrent> |
|
14 | #include <QtConcurrent/QtConcurrent> | |
15 |
|
15 | |||
16 |
|
16 | |||
17 |
namespace |
|
17 | namespace | |
|
18 | { | |||
18 |
|
19 | |||
19 | /// Number of bands generated for a spectrogram |
|
20 | /// Number of bands generated for a spectrogram | |
20 | const auto SPECTROGRAM_NUMBER_BANDS = 30; |
|
21 | const auto SPECTROGRAM_NUMBER_BANDS = 30; | |
21 |
|
22 | |||
22 | /// Bands for which to generate NaN values for a spectrogram |
|
23 | /// Bands for which to generate NaN values for a spectrogram | |
23 | const auto SPECTROGRAM_NAN_BANDS = std::set<int>{1, 3, 10, 20}; |
|
24 | const auto SPECTROGRAM_NAN_BANDS = std::set<int> { 1, 3, 10, 20 }; | |
24 |
|
25 | |||
25 | /// Bands for which to generate zeros for a spectrogram |
|
26 | /// Bands for which to generate zeros for a spectrogram | |
26 | const auto SPECTROGRAM_ZERO_BANDS = std::set<int>{2, 15, 19, 29}; |
|
27 | const auto SPECTROGRAM_ZERO_BANDS = std::set<int> { 2, 15, 19, 29 }; | |
27 |
|
||||
28 | /// Abstract cosinus type |
|
|||
29 | struct ICosinusType { |
|
|||
30 | virtual ~ICosinusType() = default; |
|
|||
31 | /// @return the number of components generated for the type |
|
|||
32 | virtual std::size_t componentCount() const = 0; |
|
|||
33 | /// @return the data series created for the type |
|
|||
34 | virtual IDataSeries* createDataSeries(std::vector<double> xAxisData, |
|
|||
35 | std::vector<double> valuesData) const = 0; |
|
|||
36 | /// Generates values (one value per component) |
|
|||
37 | /// @param x the x-axis data used to generate values |
|
|||
38 | /// @param values the vector in which to insert the generated values |
|
|||
39 | /// @param dataIndex the index of insertion of the generated values |
|
|||
40 | /// |
|
|||
41 | virtual void generateValues(double x, std::vector<double> &values, int dataIndex) const = 0; |
|
|||
42 | }; |
|
|||
43 |
|
||||
44 | struct ScalarCosinus : public ICosinusType { |
|
|||
45 | std::size_t componentCount() const override { return 1; } |
|
|||
46 |
|
||||
47 | IDataSeries* createDataSeries(std::vector<double> xAxisData, |
|
|||
48 | std::vector<double> valuesData) const override |
|
|||
49 | { |
|
|||
50 | return new ScalarSeries(std::move(xAxisData), std::move(valuesData), |
|
|||
51 | Unit{QStringLiteral("t"), true}, Unit{}); |
|
|||
52 | } |
|
|||
53 |
|
||||
54 | void generateValues(double x, std::vector<double> &values, int dataIndex) const override |
|
|||
55 | { |
|
|||
56 | values[dataIndex] = std::cos(x); |
|
|||
57 | } |
|
|||
58 | }; |
|
|||
59 |
|
||||
60 | struct SpectrogramCosinus : public ICosinusType { |
|
|||
61 | /// Ctor with y-axis |
|
|||
62 | explicit SpectrogramCosinus(std::vector<double> yAxisData, Unit yAxisUnit, Unit valuesUnit) |
|
|||
63 | : m_YAxisData{std::move(yAxisData)}, |
|
|||
64 | m_YAxisUnit{std::move(yAxisUnit)}, |
|
|||
65 | m_ValuesUnit{std::move(valuesUnit)} |
|
|||
66 | { |
|
|||
67 | } |
|
|||
68 |
|
||||
69 | std::size_t componentCount() const override { return m_YAxisData.size(); } |
|
|||
70 |
|
||||
71 | IDataSeries* createDataSeries(std::vector<double> xAxisData, |
|
|||
72 | std::vector<double> valuesData) const override |
|
|||
73 | { |
|
|||
74 | return new SpectrogramSeries( |
|
|||
75 | std::move(xAxisData), m_YAxisData, std::move(valuesData), |
|
|||
76 | Unit{QStringLiteral("t"), true}, m_YAxisUnit, m_ValuesUnit); |
|
|||
77 | } |
|
|||
78 |
|
||||
79 | void generateValues(double x, std::vector<double> &values, int dataIndex) const override |
|
|||
80 | { |
|
|||
81 | auto componentCount = this->componentCount(); |
|
|||
82 | for (int i = 0; i < componentCount; ++i) { |
|
|||
83 | auto y = m_YAxisData[i]; |
|
|||
84 |
|
||||
85 | double value; |
|
|||
86 |
|
||||
87 | // if (SPECTROGRAM_ZERO_BANDS.find(y) != SPECTROGRAM_ZERO_BANDS.end()) { |
|
|||
88 | // value = 0.; |
|
|||
89 | // } |
|
|||
90 | // else if (SPECTROGRAM_NAN_BANDS.find(y) != SPECTROGRAM_NAN_BANDS.end()) { |
|
|||
91 | // value = std::numeric_limits<double>::quiet_NaN(); |
|
|||
92 | // } |
|
|||
93 | // else |
|
|||
94 | { |
|
|||
95 | // Generates value for non NaN/zero bands |
|
|||
96 | //auto r = 3 * std::sqrt(x * x + y * y) + 1e-2; |
|
|||
97 | //value = 2 * x * (std::cos(r + 2) / r - std::sin(r + 2) / r); |
|
|||
98 | value = x + 10*y; |
|
|||
99 | } |
|
|||
100 |
|
||||
101 | values[componentCount * dataIndex + i] = value; |
|
|||
102 | } |
|
|||
103 | } |
|
|||
104 |
|
||||
105 | std::vector<double> m_YAxisData; |
|
|||
106 | Unit m_YAxisUnit; |
|
|||
107 | Unit m_ValuesUnit; |
|
|||
108 | }; |
|
|||
109 |
|
||||
110 | struct VectorCosinus : public ICosinusType { |
|
|||
111 | std::size_t componentCount() const override { return 3; } |
|
|||
112 |
|
28 | |||
113 | IDataSeries* createDataSeries(std::vector<double> xAxisData, |
|
|||
114 | std::vector<double> valuesData) const override |
|
|||
115 | { |
|
|||
116 | return new VectorSeries(std::move(xAxisData), std::move(valuesData), |
|
|||
117 | Unit{QStringLiteral("t"), true}, Unit{}); |
|
|||
118 | } |
|
|||
119 |
|
||||
120 | void generateValues(double x, std::vector<double> &values, int dataIndex) const override |
|
|||
121 | { |
|
|||
122 | // Generates value for each component: cos(x), cos(x)/2, cos(x)/3 |
|
|||
123 | auto xValue = std::cos(x); |
|
|||
124 | auto componentCount = this->componentCount(); |
|
|||
125 | for (auto i = 0; i < componentCount; ++i) { |
|
|||
126 | values[componentCount * dataIndex + i] = xValue / (i + 1); |
|
|||
127 | } |
|
|||
128 | } |
|
|||
129 | }; |
|
|||
130 |
|
||||
131 | /// Converts string to cosinus type |
|
|||
132 | /// @return the cosinus type if the string could be converted, nullptr otherwise |
|
|||
133 | std::unique_ptr<ICosinusType> cosinusType(const QString &type) noexcept |
|
|||
134 | { |
|
|||
135 | if (type.compare(QStringLiteral("scalar"), Qt::CaseInsensitive) == 0) { |
|
|||
136 | return std::make_unique<ScalarCosinus>(); |
|
|||
137 | } |
|
|||
138 | else if (type.compare(QStringLiteral("spectrogram"), Qt::CaseInsensitive) == 0) { |
|
|||
139 | // Generates default y-axis data for spectrogram [0., 1., 2., ...] |
|
|||
140 | std::vector<double> yAxisData(SPECTROGRAM_NUMBER_BANDS); |
|
|||
141 | std::iota(yAxisData.begin(), yAxisData.end(), 1.); |
|
|||
142 | for (auto & v:yAxisData) |
|
|||
143 | { |
|
|||
144 | v = std::pow(2,v); |
|
|||
145 | } |
|
|||
146 | return std::make_unique<SpectrogramCosinus>(std::move(yAxisData), Unit{"eV"}, |
|
|||
147 | Unit{"eV/(cm^2-s-sr-eV)"}); |
|
|||
148 | } |
|
|||
149 | else if (type.compare(QStringLiteral("vector"), Qt::CaseInsensitive) == 0) { |
|
|||
150 | return std::make_unique<VectorCosinus>(); |
|
|||
151 | } |
|
|||
152 | else { |
|
|||
153 | return nullptr; |
|
|||
154 | } |
|
|||
155 | } |
|
|||
156 |
|
29 | |||
157 | } // namespace |
|
30 | } // namespace | |
158 |
|
31 | |||
159 | std::shared_ptr<IDataProvider> CosinusProvider::clone() const |
|
32 | std::shared_ptr<IDataProvider> CosinusProvider::clone() const | |
160 | { |
|
33 | { | |
161 | // No copy is made in clone |
|
34 | // No copy is made in clone | |
162 | return std::make_shared<CosinusProvider>(); |
|
35 | return std::make_shared<CosinusProvider>(); | |
163 | } |
|
36 | } | |
164 |
|
37 | |||
165 | IDataSeries *CosinusProvider::_generate(const DateTimeRange &range, const QVariantHash &metaData) |
|
38 | TimeSeries::ITimeSerie* CosinusProvider::_generate( | |
|
39 | const DateTimeRange& range, const QVariantHash& metaData) | |||
166 | { |
|
40 | { | |
167 | auto dataIndex = 0; |
|
|||
168 |
|
||||
169 | // Retrieves cosinus type |
|
41 | // Retrieves cosinus type | |
170 | auto typeVariant = metaData.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE); |
|
42 | auto typeVariant = metaData.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE); | |
171 | auto type = cosinusType(typeVariant.toString()); |
|
|||
172 | auto freqVariant = metaData.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE); |
|
43 | auto freqVariant = metaData.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE); | |
|
44 | const auto fs = 200.; | |||
173 | double freq = freqVariant.toDouble(); |
|
45 | double freq = freqVariant.toDouble(); | |
174 | double start = std::ceil(range.m_TStart * freq); |
|
46 | double start = std::ceil(range.m_TStart * freq); | |
175 | double end = std::floor(range.m_TEnd * freq); |
|
47 | double end = std::floor(range.m_TEnd * freq); | |
176 |
if (end < start) |
|
48 | if (end < start) | |
|
49 | { | |||
177 | std::swap(start, end); |
|
50 | std::swap(start, end); | |
178 | } |
|
51 | } | |
179 | std::size_t dataCount = static_cast<std::size_t>(end - start + 1); |
|
52 | std::size_t dataCount = static_cast<std::size_t>(end - start + 1); | |
180 | std::size_t componentCount = type->componentCount(); |
|
53 | if (typeVariant.toString() == QStringLiteral("scalar")) | |
181 |
|
||||
182 | auto xAxisData = std::vector<double>{}; |
|
|||
183 | xAxisData.resize(dataCount); |
|
|||
184 |
|
||||
185 | auto valuesData = std::vector<double>{}; |
|
|||
186 | valuesData.resize(dataCount * componentCount); |
|
|||
187 |
|
||||
188 | int progress = 0; |
|
|||
189 | auto progressEnd = dataCount; |
|
|||
190 | for (auto time = start; time <= end; ++time, ++dataIndex) |
|
|||
191 | { |
|
54 | { | |
192 | const auto x = time / freq; |
|
55 | auto ts = new ScalarTimeSerie(dataCount); | |
193 | xAxisData[dataIndex] = x; |
|
56 | std::generate( | |
194 | // Generates values (depending on the type) |
|
57 | std::begin(*ts), std::end(*ts), [range, freq, fs, dt = 1. / freq, i = 0.]() mutable { | |
195 | type->generateValues(x, valuesData, dataIndex); |
|
58 | auto t = range.m_TStart + i * dt; | |
|
59 | i++; | |||
|
60 | return std::pair<double, double> { t, std::cos(2 * 3.14 * freq / fs * t) }; | |||
|
61 | }); | |||
|
62 | return ts; | |||
196 | } |
|
63 | } | |
197 | return type->createDataSeries(std::move(xAxisData), std::move(valuesData)); |
|
64 | if (typeVariant.toString() == QStringLiteral("vector")) | |
|
65 | { | |||
|
66 | auto ts = new VectorTimeSerie(dataCount); | |||
|
67 | std::generate( | |||
|
68 | std::begin(*ts), std::end(*ts), [range, freq, fs, dt = 1. / freq, i = 0.]() mutable { | |||
|
69 | auto t = range.m_TStart + i * dt; | |||
|
70 | i++; | |||
|
71 | return std::pair<double, VectorTimeSerie::raw_value_type> { t, | |||
|
72 | { std::cos(2 * 3.14 * freq / fs * t), std::sin(2 * 3.14 * freq / fs * t), | |||
|
73 | std::cos(2 * 3.14 * freq / fs * t) * std::sin(2 * 3.14 * freq / fs * t) } }; | |||
|
74 | }); | |||
|
75 | return ts; | |||
|
76 | } | |||
|
77 | if (typeVariant.toString() == QStringLiteral("spectrogram")) | |||
|
78 | { | |||
|
79 | return nullptr; | |||
|
80 | } | |||
|
81 | return nullptr; | |||
198 | } |
|
82 | } | |
199 |
|
83 | |||
200 |
|
|
84 | TimeSeries::ITimeSerie* CosinusProvider::getData(const DataProviderParameters& parameters) | |
201 | { |
|
85 | { | |
202 | return _generate(parameters.m_Range, parameters.m_Data); |
|
86 | return _generate(parameters.m_Range, parameters.m_Data); | |
203 | } |
|
87 | } | |
204 |
|
@@ -1,85 +1,86 | |||||
1 | /*------------------------------------------------------------------------------ |
|
1 | /*------------------------------------------------------------------------------ | |
2 | -- This file is a part of the SciQLOP Software |
|
2 | -- This file is a part of the SciQLOP Software | |
3 | -- Copyright (C) 2018, Plasma Physics Laboratory - CNRS |
|
3 | -- Copyright (C) 2018, Plasma Physics Laboratory - CNRS | |
4 | -- |
|
4 | -- | |
5 | -- This program is free software; you can redistribute it and/or modify |
|
5 | -- This program is free software; you can redistribute it and/or modify | |
6 | -- it under the terms of the GNU General Public License as published by |
|
6 | -- it under the terms of the GNU General Public License as published by | |
7 | -- the Free Software Foundation; either version 2 of the License, or |
|
7 | -- the Free Software Foundation; either version 2 of the License, or | |
8 | -- (at your option) any later version. |
|
8 | -- (at your option) any later version. | |
9 | -- |
|
9 | -- | |
10 | -- This program is distributed in the hope that it will be useful, |
|
10 | -- This program is distributed in the hope that it will be useful, | |
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | -- GNU General Public License for more details. |
|
13 | -- GNU General Public License for more details. | |
14 | -- |
|
14 | -- | |
15 | -- You should have received a copy of the GNU General Public License |
|
15 | -- You should have received a copy of the GNU General Public License | |
16 | -- along with this program; if not, write to the Free Software |
|
16 | -- along with this program; if not, write to the Free Software | |
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | -------------------------------------------------------------------------------*/ |
|
18 | -------------------------------------------------------------------------------*/ | |
19 | /*-- Author : Alexis Jeandet |
|
19 | /*-- Author : Alexis Jeandet | |
20 | -- Mail : alexis.jeandet@member.fsf.org |
|
20 | -- Mail : alexis.jeandet@member.fsf.org | |
21 | ----------------------------------------------------------------------------*/ |
|
21 | ----------------------------------------------------------------------------*/ | |
22 | #include <string> |
|
|||
23 | #include <sstream> |
|
|||
24 | #include <memory> |
|
22 | #include <memory> | |
|
23 | #include <sstream> | |||
|
24 | #include <string> | |||
25 |
|
25 | |||
26 |
#include <pybind11/ |
|
26 | #include <pybind11/chrono.h> | |
27 | #include <pybind11/operators.h> |
|
|||
28 | #include <pybind11/embed.h> |
|
27 | #include <pybind11/embed.h> | |
29 | #include <pybind11/numpy.h> |
|
28 | #include <pybind11/numpy.h> | |
30 |
#include <pybind11/ |
|
29 | #include <pybind11/operators.h> | |
|
30 | #include <pybind11/pybind11.h> | |||
31 |
|
31 | |||
|
32 | #include <Common/DateUtils.h> | |||
|
33 | #include <Data/DataSeriesType.h> | |||
|
34 | #include <Data/DateTimeRange.h> | |||
32 | #include <SqpApplication.h> |
|
35 | #include <SqpApplication.h> | |
33 | #include <Variable/VariableController2.h> |
|
|||
34 | #include <Time/TimeController.h> |
|
36 | #include <Time/TimeController.h> | |
35 | #include <Data/DateTimeRange.h> |
|
37 | #include <Variable/VariableController2.h> | |
36 | #include <Data/DataSeriesType.h> |
|
|||
37 | #include <Common/DateUtils.h> |
|
|||
38 | #include <Variable/Variable.h> |
|
|||
39 | #include <Data/ScalarSeries.h> |
|
|||
40 | #include <Data/VectorSeries.h> |
|
|||
41 |
|
38 | |||
42 | #include <MockPlugin.h> |
|
|||
43 | #include <CosinusProvider.h> |
|
39 | #include <CosinusProvider.h> | |
|
40 | #include <MockPlugin.h> | |||
44 |
|
41 | |||
45 | #include <QFile> |
|
42 | #include <QFile> | |
46 |
|
43 | |||
47 | #include <pywrappers_common.h> |
|
|||
48 | #include <CoreWrappers.h> |
|
44 | #include <CoreWrappers.h> | |
49 |
|
45 | #include <pywrappers_common.h> | ||
50 |
|
46 | |||
51 |
|
47 | |||
52 | using namespace std::chrono; |
|
48 | using namespace std::chrono; | |
53 | namespace py = pybind11; |
|
49 | namespace py = pybind11; | |
54 |
|
50 | |||
55 |
|
51 | |||
56 |
|
52 | PYBIND11_MODULE(pytestmockplugin, m) | ||
57 | PYBIND11_MODULE(pytestmockplugin, m){ |
|
53 | { | |
58 |
|
54 | |||
59 | int argc = 0; |
|
55 | int argc = 0; | |
60 |
char |
|
56 | char** argv = nullptr; | |
61 | SqpApplication::setOrganizationName("LPP"); |
|
57 | SqpApplication::setOrganizationName("LPP"); | |
62 | SqpApplication::setOrganizationDomain("lpp.fr"); |
|
58 | SqpApplication::setOrganizationDomain("lpp.fr"); | |
63 | SqpApplication::setApplicationName("SciQLop"); |
|
59 | SqpApplication::setApplicationName("SciQLop"); | |
64 | static SqpApplication app(argc, argv); |
|
60 | static SqpApplication app(argc, argv); | |
65 |
|
61 | |||
66 | auto qtmod = py::module::import("sciqlopqt"); |
|
62 | auto qtmod = py::module::import("sciqlopqt"); | |
67 | auto sciqlopmod = py::module::import("pysciqlopcore"); |
|
63 | auto sciqlopmod = py::module::import("pysciqlopcore"); | |
68 |
|
64 | |||
69 | m.doc() = ""; |
|
65 | m.doc() = ""; | |
70 |
|
66 | |||
71 |
py::class_<VariableController2>(m, "VariableController2") |
|
67 | py::class_<VariableController2>(m, "VariableController2") | |
72 | std::shared_ptr<IDataProvider> provider, const DateTimeRange& range){ |
|
68 | .def_static("createVariable", | |
73 | return sqpApp->variableController().createVariable(name, {{"cosinusType", "spectrogram"}, {"cosinusFrequency", "0.1"}}, provider, range); |
|
69 | [](const QString& name, std::shared_ptr<IDataProvider> provider, | |
|
70 | const DateTimeRange& range) { | |||
|
71 | return sqpApp->variableController().createVariable(name, | |||
|
72 | { { "cosinusType", "spectrogram" }, { "cosinusFrequency", "0.1" } }, provider, | |||
|
73 | range); | |||
|
74 | }); | |||
|
75 | ||||
|
76 | py::class_<TimeController>(m, "TimeController").def_static("setTime", [](DateTimeRange range) { | |||
|
77 | sqpApp->timeController().setDateTimeRange(range); | |||
74 | }); |
|
78 | }); | |
75 |
|
79 | |||
76 | py::class_<TimeController>(m,"TimeController") |
|
|||
77 | .def_static("setTime", [](DateTimeRange range){sqpApp->timeController().setDateTimeRange(range);}); |
|
|||
78 |
|
||||
79 | auto mock_provider = std::make_shared<CosinusProvider>(); |
|
80 | auto mock_provider = std::make_shared<CosinusProvider>(); | |
80 |
m.def("mock_provider",[mock_provider](){return mock_provider;}, |
|
81 | m.def("mock_provider", [mock_provider]() { return mock_provider; }, | |
81 |
|
82 | py::return_value_policy::copy); | ||
82 | py::class_<CosinusProvider, std::shared_ptr<CosinusProvider>, IDataProvider>(m, "CosinusProvider"); |
|
|||
83 |
|
83 | |||
|
84 | py::class_<CosinusProvider, std::shared_ptr<CosinusProvider>, IDataProvider>( | |||
|
85 | m, "CosinusProvider"); | |||
84 | } |
|
86 | } | |
85 |
|
General Comments 0
You need to be logged in to leave comments.
Login now