##// END OF EJS Templates
Merge branch 'feature/SettingsWidget' into develop
Alexandre Leroux -
r472:6b7a5db1522f merge
parent child
Show More
@@ -0,0 +1,12
1 #ifndef SCIQLOP_COREGLOBAL_H
2 #define SCIQLOP_COREGLOBAL_H
3
4 #include <QtCore/QtGlobal>
5
6 #ifdef CORE_LIB
7 #define SCIQLOP_CORE_EXPORT Q_DECL_EXPORT
8 #else
9 #define SCIQLOP_CORE_EXPORT Q_DECL_IMPORT
10 #endif
11
12 #endif // SCIQLOP_COREGLOBAL_H
@@ -0,0 +1,21
1 #ifndef SCIQLOP_ISQPSETTINGSBINDABLE_H
2 #define SCIQLOP_ISQPSETTINGSBINDABLE_H
3
4 #include <QSettings>
5
6 /**
7 * @brief The ISqpSettingsBindable interface represents an object that can bind a variable
8 */
9 class ISqpSettingsBindable {
10
11 public:
12 virtual ~ISqpSettingsBindable() = default;
13
14 /// Loads settings into the object
15 virtual void loadSettings() = 0;
16
17 /// Saves settings from the object
18 virtual void saveSettings() const = 0;
19 };
20
21 #endif // SCIQLOP_ISQPSETTINGSBINDABLE_H
@@ -0,0 +1,18
1 #ifndef SCIQLOP_SQPSETTINGSDEFS_H
2 #define SCIQLOP_SQPSETTINGSDEFS_H
3
4 #include "CoreGlobal.h"
5
6 #include <QString>
7
8 // //////////////// //
9 // General settings //
10 // //////////////// //
11
12 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_INIT_KEY;
13 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE;
14
15 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_UPDATE_KEY;
16 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE;
17
18 #endif // SCIQLOP_SQPSETTINGSDEFS_H
@@ -0,0 +1,7
1 #include "Settings/SqpSettingsDefs.h"
2
3 const QString GENERAL_TOLERANCE_AT_INIT_KEY = QStringLiteral("toleranceInit");
4 const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE = 0.2;
5
6 const QString GENERAL_TOLERANCE_AT_UPDATE_KEY = QStringLiteral("toleranceUpdate");
7 const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE = 0.2;
@@ -0,0 +1,40
1 #ifndef SCIQLOP_SQPSETTINGSDIALOG_H
2 #define SCIQLOP_SQPSETTINGSDIALOG_H
3
4 #include "Settings/ISqpSettingsBindable.h"
5
6 #include <QDialog>
7
8 namespace Ui {
9 class SqpSettingsDialog;
10 } // Ui
11
12 /**
13 * @brief The SqpSettingsDialog class represents the dialog in which the parameters of SciQlop are
14 * set
15 */
16 class SqpSettingsDialog : public QDialog, public ISqpSettingsBindable {
17 Q_OBJECT
18
19 public:
20 explicit SqpSettingsDialog(QWidget *parent = 0);
21 virtual ~SqpSettingsDialog() noexcept;
22
23 /// @sa ISqpSettingsBindable::loadSettings()
24 void loadSettings() override final;
25
26 /// @sa ISqpSettingsBindable::saveSettings()
27 void saveSettings() const override final;
28
29 /**
30 * Registers a widget into the dialog
31 * @param name the name under which the widget will appear in the dialog
32 * @param widget the widget to register
33 */
34 void registerWidget(const QString &name, QWidget *widget) noexcept;
35
36 private:
37 Ui::SqpSettingsDialog *ui;
38 };
39
40 #endif // SCIQLOP_SQPSETTINGSDIALOG_H
@@ -0,0 +1,32
1 #ifndef SCIQLOP_SQPSETTINGSGENERALWIDGET_H
2 #define SCIQLOP_SQPSETTINGSGENERALWIDGET_H
3
4 #include "Settings/ISqpSettingsBindable.h"
5
6 #include <QWidget>
7
8 namespace Ui {
9 class SqpSettingsGeneralWidget;
10 } // Ui
11
12 /**
13 * @brief The SqpSettingsGeneralWidget class represents the general settings of SciQlop
14 */
15 class SqpSettingsGeneralWidget : public QWidget, public ISqpSettingsBindable {
16 Q_OBJECT
17
18 public:
19 explicit SqpSettingsGeneralWidget(QWidget *parent = 0);
20 virtual ~SqpSettingsGeneralWidget() noexcept;
21
22 /// @sa ISqpSettingsBindable::loadSettings()
23 void loadSettings() override final;
24
25 /// @sa ISqpSettingsBindable::saveSettings()
26 void saveSettings() const override final;
27
28 private:
29 Ui::SqpSettingsGeneralWidget *ui;
30 };
31
32 #endif // SCIQLOP_SQPSETTINGSGENERALWIDGET_H
@@ -0,0 +1,66
1 #include "Settings/SqpSettingsDialog.h"
2 #include "ui_SqpSettingsDialog.h"
3
4 namespace {
5
6 /**
7 * Performs a bind operation on widgets that can be binded to SciQlop settings
8 * @param widgets
9 * @param bind the bind operation
10 * @sa ISqpSettingsBindable
11 */
12 template <typename BindMethod>
13 void processBind(const QStackedWidget &widgets, BindMethod bind)
14 {
15 auto count = widgets.count();
16 for (auto i = 0; i < count; ++i) {
17 // Performs operation if widget is an ISqpSettingsBindable
18 if (auto sqpSettingsWidget = dynamic_cast<ISqpSettingsBindable *>(widgets.widget(i))) {
19 bind(*sqpSettingsWidget);
20 }
21 }
22 }
23
24 } // namespace
25
26 SqpSettingsDialog::SqpSettingsDialog(QWidget *parent)
27 : QDialog{parent}, ui{new Ui::SqpSettingsDialog}
28 {
29 ui->setupUi(this);
30
31 // Connection to change the current page to the selection of an entry in the list
32 connect(ui->listWidget, &QListWidget::currentRowChanged, ui->stackedWidget,
33 &QStackedWidget::setCurrentIndex);
34 }
35
36 SqpSettingsDialog::~SqpSettingsDialog() noexcept
37 {
38 delete ui;
39 }
40
41 void SqpSettingsDialog::loadSettings()
42 {
43 // Performs load on all widgets that can be binded to SciQlop settings
44 processBind(*ui->stackedWidget,
45 [](ISqpSettingsBindable &bindable) { bindable.loadSettings(); });
46 }
47
48 void SqpSettingsDialog::saveSettings() const
49 {
50 // Performs save on all widgets that can be binded to SciQlop settings
51 processBind(*ui->stackedWidget,
52 [](ISqpSettingsBindable &bindable) { bindable.saveSettings(); });
53 }
54
55 void SqpSettingsDialog::registerWidget(const QString &name, QWidget *widget) noexcept
56 {
57 auto newItem = new QListWidgetItem{ui->listWidget};
58 newItem->setText(name);
59
60 ui->stackedWidget->addWidget(widget);
61
62 // Selects widget if it's the first in the dialog
63 if (ui->listWidget->count() == 1) {
64 ui->listWidget->setCurrentItem(newItem);
65 }
66 }
@@ -0,0 +1,45
1 #include "Settings/SqpSettingsGeneralWidget.h"
2
3 #include "Settings/SqpSettingsDefs.h"
4
5 #include "ui_SqpSettingsGeneralWidget.h"
6
7 SqpSettingsGeneralWidget::SqpSettingsGeneralWidget(QWidget *parent)
8 : QWidget{parent}, ui{new Ui::SqpSettingsGeneralWidget}
9 {
10 ui->setupUi(this);
11 }
12
13 SqpSettingsGeneralWidget::~SqpSettingsGeneralWidget() noexcept
14 {
15 delete ui;
16 }
17
18 void SqpSettingsGeneralWidget::loadSettings()
19 {
20 QSettings settings{};
21
22 auto loadTolerance = [&settings](const QString &key, double defaultValue) {
23 // Tolerance is converted to percent
24 auto toleranceValue = settings.value(key, defaultValue).toDouble();
25 return toleranceValue * 100.;
26 };
27
28 ui->toleranceInitSpinBox->setValue(
29 loadTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE));
30 ui->toleranceUpdateSpinBox->setValue(
31 loadTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE));
32 }
33
34 void SqpSettingsGeneralWidget::saveSettings() const
35 {
36 QSettings settings{};
37
38 auto saveTolerance = [&settings](const QString &key, double value) {
39 // Tolerance is converted from percent
40 settings.setValue(key, value * 0.01);
41 };
42
43 saveTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, ui->toleranceInitSpinBox->value());
44 saveTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, ui->toleranceUpdateSpinBox->value());
45 }
@@ -0,0 +1,84
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
3 <class>SqpSettingsDialog</class>
4 <widget class="QDialog" name="SqpSettingsDialog">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>572</width>
10 <height>394</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>SciQlop Settings</string>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0">
18 <widget class="QListWidget" name="listWidget">
19 <property name="sizePolicy">
20 <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
21 <horstretch>0</horstretch>
22 <verstretch>0</verstretch>
23 </sizepolicy>
24 </property>
25 </widget>
26 </item>
27 <item row="0" column="1">
28 <widget class="QStackedWidget" name="stackedWidget">
29 <property name="sizePolicy">
30 <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
31 <horstretch>0</horstretch>
32 <verstretch>0</verstretch>
33 </sizepolicy>
34 </property>
35 </widget>
36 </item>
37 <item row="1" column="0" colspan="2">
38 <widget class="QDialogButtonBox" name="buttonBox">
39 <property name="orientation">
40 <enum>Qt::Horizontal</enum>
41 </property>
42 <property name="standardButtons">
43 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
44 </property>
45 </widget>
46 </item>
47 </layout>
48 </widget>
49 <resources/>
50 <connections>
51 <connection>
52 <sender>buttonBox</sender>
53 <signal>accepted()</signal>
54 <receiver>SqpSettingsDialog</receiver>
55 <slot>accept()</slot>
56 <hints>
57 <hint type="sourcelabel">
58 <x>248</x>
59 <y>254</y>
60 </hint>
61 <hint type="destinationlabel">
62 <x>157</x>
63 <y>274</y>
64 </hint>
65 </hints>
66 </connection>
67 <connection>
68 <sender>buttonBox</sender>
69 <signal>rejected()</signal>
70 <receiver>SqpSettingsDialog</receiver>
71 <slot>reject()</slot>
72 <hints>
73 <hint type="sourcelabel">
74 <x>316</x>
75 <y>260</y>
76 </hint>
77 <hint type="destinationlabel">
78 <x>286</x>
79 <y>274</y>
80 </hint>
81 </hints>
82 </connection>
83 </connections>
84 </ui>
@@ -0,0 +1,86
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
3 <class>SqpSettingsGeneralWidget</class>
4 <widget class="QWidget" name="SqpSettingsGeneralWidget">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>343</width>
10 <height>300</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Form</string>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0">
18 <widget class="QLabel" name="toleranceInitLabel">
19 <property name="text">
20 <string>Tolerance on first acquisition:</string>
21 </property>
22 </widget>
23 </item>
24 <item row="0" column="1">
25 <widget class="QDoubleSpinBox" name="toleranceInitSpinBox">
26 <property name="sizePolicy">
27 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
28 <horstretch>0</horstretch>
29 <verstretch>0</verstretch>
30 </sizepolicy>
31 </property>
32 <property name="suffix">
33 <string> %</string>
34 </property>
35 <property name="minimum">
36 <double>0.000000000000000</double>
37 </property>
38 <property name="maximum">
39 <double>500.000000000000000</double>
40 </property>
41 </widget>
42 </item>
43 <item row="1" column="0">
44 <widget class="QLabel" name="toleranceUpdateLabel">
45 <property name="text">
46 <string>Tolerance when updating acquisition:</string>
47 </property>
48 </widget>
49 </item>
50 <item row="1" column="1">
51 <widget class="QDoubleSpinBox" name="toleranceUpdateSpinBox">
52 <property name="sizePolicy">
53 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
54 <horstretch>0</horstretch>
55 <verstretch>0</verstretch>
56 </sizepolicy>
57 </property>
58 <property name="suffix">
59 <string> %</string>
60 </property>
61 <property name="minimum">
62 <double>0.000000000000000</double>
63 </property>
64 <property name="maximum">
65 <double>500.000000000000000</double>
66 </property>
67 </widget>
68 </item>
69 <item row="2" column="0">
70 <spacer name="verticalSpacer">
71 <property name="orientation">
72 <enum>Qt::Vertical</enum>
73 </property>
74 <property name="sizeHint" stdset="0">
75 <size>
76 <width>20</width>
77 <height>40</height>
78 </size>
79 </property>
80 </spacer>
81 </item>
82 </layout>
83 </widget>
84 <resources/>
85 <connections/>
86 </ui>
@@ -1,76 +1,79
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the QLop Software
3 3 -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include <QProcessEnvironment>
24 24 #include <QThread>
25 25 #include <SqpApplication.h>
26 26 #include <qglobal.h>
27 27
28 28 #include <Plugin/PluginManager.h>
29 29 #include <QDir>
30 30
31 #include <QLoggingCategory>
32
33 Q_LOGGING_CATEGORY(LOG_Main, "Main")
34
31 35 namespace {
32 36
33 37 /// Name of the directory containing the plugins
34 38
35 39 #if _WIN32 || _WIN64
36 40 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
37 41 #endif
38 42
39 43 } // namespace
40 44
41 45 int main(int argc, char *argv[])
42 46 {
43 47 SqpApplication a{argc, argv};
44 48 SqpApplication::setOrganizationName("LPP");
45 49 SqpApplication::setOrganizationDomain("lpp.fr");
46 50 SqpApplication::setApplicationName("SciQLop");
47 51 MainWindow w;
48 52 w.show();
49 53
50 54 // Loads plugins
51 55 auto pluginDir = QDir{sqpApp->applicationDirPath()};
52 56 #if _WIN32 || _WIN64
53 57 pluginDir.mkdir(PLUGIN_DIRECTORY_NAME);
54 58 pluginDir.cd(PLUGIN_DIRECTORY_NAME);
55 59 #endif
56 60
57 61
58 62 #if __unix || __APPLE
59 63 #if __x86_64__ || __ppc64__
60 64 if (!pluginDir.cd("../lib64/SciQlop")) {
61 65 pluginDir.cd("../lib64/sciqlop");
62 66 }
63 67 #else
64 68 if (!pluginDir.cd("../lib/SciQlop")) {
65 69 pluginDir.cd("../lib/sciqlop");
66 70 }
67 71 #endif
68 72 #endif
69 qCDebug(LOG_PluginManager())
70 << QObject::tr("Plugin directory: %1").arg(pluginDir.absolutePath());
73 qCDebug(LOG_Main()) << QObject::tr("Plugin directory: %1").arg(pluginDir.absolutePath());
71 74
72 75 PluginManager pluginManager{};
73 76 pluginManager.loadPlugins(pluginDir);
74 77
75 78 return a.exec();
76 79 }
@@ -1,269 +1,255
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLop Software
3 3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include "ui_MainWindow.h"
24 24
25 25 #include <DataSource/DataSourceController.h>
26 26 #include <DataSource/DataSourceWidget.h>
27 #include <Settings/SqpSettingsDialog.h>
28 #include <Settings/SqpSettingsGeneralWidget.h>
27 29 #include <SidePane/SqpSidePane.h>
28 30 #include <SqpApplication.h>
29 31 #include <Time/TimeController.h>
30 32 #include <TimeWidget/TimeWidget.h>
31 33 #include <Variable/Variable.h>
32 34 #include <Variable/VariableController.h>
33 35 #include <Visualization/VisualizationController.h>
34 36
35 37 #include <QAction>
36 38 #include <QDate>
37 39 #include <QDateTime>
38 40 #include <QDir>
39 41 #include <QFileDialog>
40 42 #include <QToolBar>
41 43 #include <QToolButton>
42 44 #include <memory.h>
43 45
44 //#include <omp.h>
45 //#include <network/filedownloader.h>
46 //#include <qlopdatabase.h>
47 //#include <qlopsettings.h>
48 //#include <qlopgui.h>
49 //#include <spacedata.h>
50 //#include "qlopcore.h"
51 //#include "qlopcodecmanager.h"
52 //#include "cdfcodec.h"
53 //#include "amdatxtcodec.h"
54 //#include <qlopplotmanager.h>
55
56 46 #include "iostream"
57 47
58 48 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
59 49
60 50 namespace {
61 51 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
62 52 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
63 53 const auto VIEWPLITTERINDEX = 2;
64 54 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
65 55 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
66 56 }
67 57
68 58 class MainWindow::MainWindowPrivate {
69 59 public:
60 explicit MainWindowPrivate(MainWindow *mainWindow)
61 : m_LastOpenLeftInspectorSize{},
62 m_LastOpenRightInspectorSize{},
63 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
64 m_SettingsDialog{new SqpSettingsDialog{mainWindow}}
65 {
66 }
67
70 68 QSize m_LastOpenLeftInspectorSize;
71 69 QSize m_LastOpenRightInspectorSize;
70 /// General settings widget. MainWindow has the ownership
71 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
72 /// Settings dialog. MainWindow has the ownership
73 SqpSettingsDialog *m_SettingsDialog;
72 74 };
73 75
74 76 MainWindow::MainWindow(QWidget *parent)
75 77 : QMainWindow{parent},
76 78 m_Ui{new Ui::MainWindow},
77 impl{spimpl::make_unique_impl<MainWindowPrivate>()}
79 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
78 80 {
79 81 m_Ui->setupUi(this);
80 82
81 83 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
82 84 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
83 85
84 86
85 87 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
86 88 auto openLeftInspectorAction = new QAction{QIcon{
87 89 ":/icones/previous.png",
88 90 },
89 91 tr("Show/hide the left inspector"), this};
90 92
91 93
92 94 auto spacerLeftTop = new QWidget{};
93 95 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
94 96
95 97 auto spacerLeftBottom = new QWidget{};
96 98 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
97 99
98 100 leftSidePane->addWidget(spacerLeftTop);
99 101 leftSidePane->addAction(openLeftInspectorAction);
100 102 leftSidePane->addWidget(spacerLeftBottom);
101 103
102 104
103 105 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
104 106 auto openRightInspectorAction = new QAction{QIcon{
105 107 ":/icones/next.png",
106 108 },
107 109 tr("Show/hide the right inspector"), this};
108 110
109 111 auto spacerRightTop = new QWidget{};
110 112 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
111 113
112 114 auto spacerRightBottom = new QWidget{};
113 115 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
114 116
115 117 rightSidePane->addWidget(spacerRightTop);
116 118 rightSidePane->addAction(openRightInspectorAction);
117 119 rightSidePane->addWidget(spacerRightBottom);
118 120
119 121 openLeftInspectorAction->setCheckable(true);
120 122 openRightInspectorAction->setCheckable(true);
121 123
122 124 auto openInspector = [this](bool checked, bool right, auto action) {
123 125
124 126 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
125 127
126 128 auto &lastInspectorSize
127 129 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
128 130
129 131 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
130 132 : m_Ui->leftMainInspectorWidget->size();
131 133
132 134 // Update of the last opened geometry
133 135 if (checked) {
134 136 lastInspectorSize = nextInspectorSize;
135 137 }
136 138
137 139 auto startSize = lastInspectorSize;
138 140 auto endSize = startSize;
139 141 endSize.setWidth(0);
140 142
141 143 auto splitterInspectorIndex
142 144 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
143 145
144 146 auto currentSizes = m_Ui->splitter->sizes();
145 147 if (checked) {
146 148 // adjust sizes individually here, e.g.
147 149 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
148 150 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
149 151 m_Ui->splitter->setSizes(currentSizes);
150 152 }
151 153 else {
152 154 // adjust sizes individually here, e.g.
153 155 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
154 156 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
155 157 m_Ui->splitter->setSizes(currentSizes);
156 158 }
157 159
158 160 };
159 161
160 162
161 163 connect(openLeftInspectorAction, &QAction::triggered,
162 164 [openInspector, openLeftInspectorAction](bool checked) {
163 165 openInspector(checked, false, openLeftInspectorAction);
164 166 });
165 167 connect(openRightInspectorAction, &QAction::triggered,
166 168 [openInspector, openRightInspectorAction](bool checked) {
167 169 openInspector(checked, true, openRightInspectorAction);
168 170 });
169 171
172 // //// //
173 // Menu //
174 // //// //
170 175 this->menuBar()->addAction(tr("File"));
176 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
177 toolsMenu->addAction(tr("Settings..."), [this]() {
178 // Loads settings
179 impl->m_SettingsDialog->loadSettings();
180
181 // Open settings dialog and save settings if the dialog is accepted
182 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
183 impl->m_SettingsDialog->saveSettings();
184 }
185
186 });
187
171 188 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
172 189
173 190 auto timeWidget = new TimeWidget{};
174 191 mainToolBar->addWidget(timeWidget);
175 192
193 // //////// //
194 // Settings //
195 // //////// //
196
197 // Registers "general settings" widget to the settings dialog
198 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
199 impl->m_GeneralSettingsWidget);
200
201 // /////////// //
202 // Connections //
203 // /////////// //
204
176 205 // Controllers / controllers connections
177 206 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpDateTime)),
178 207 &sqpApp->variableController(), SLOT(onDateTimeOnSelection(SqpDateTime)));
179 208
180 209 // Widgets / controllers connections
181 210
182 211 // DataSource
183 212 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
184 213 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
185 214
186 215 // Time
187 216 connect(timeWidget, SIGNAL(timeUpdated(SqpDateTime)), &sqpApp->timeController(),
188 217 SLOT(onTimeToUpdate(SqpDateTime)));
189 218
190 219 // Visualization
191 220 connect(&sqpApp->visualizationController(),
192 221 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
193 222 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
194 223
195 224 connect(&sqpApp->visualizationController(),
196 225 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)), m_Ui->view,
197 226 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)));
198 227
199 228 // Widgets / widgets connections
200 229
201 230 // For the following connections, we use DirectConnection to allow each widget that can
202 231 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
203 232 // The order of connections is also important, since it determines the order in which each
204 233 // widget will attach its menu
205 234 connect(
206 235 m_Ui->variableInspectorWidget,
207 236 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
208 237 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
209 238 Qt::DirectConnection);
210
211 /* QLopGUI::registerMenuBar(menuBar());
212 this->setWindowIcon(QIcon(":/sciqlopLOGO.svg"));
213 this->m_progressWidget = new QWidget();
214 this->m_progressLayout = new QVBoxLayout(this->m_progressWidget);
215 this->m_progressWidget->setLayout(this->m_progressLayout);
216 this->m_progressWidget->setWindowModality(Qt::WindowModal);
217 m_progressThreadIds = (int*) malloc(OMP_THREADS*sizeof(int));
218 for(int i=0;i<OMP_THREADS;i++)
219 {
220 this->m_progress.append(new QProgressBar(this->m_progressWidget));
221 this->m_progress.last()->setMinimum(0);
222 this->m_progress.last()->setMaximum(100);
223 this->m_progressLayout->addWidget(this->m_progress.last());
224 this->m_progressWidget->hide();
225 this->m_progressThreadIds[i] = -1;
226 }
227 this->m_progressWidget->setWindowTitle("Loading File");
228 const QList<QLopService*>ServicesToLoad=QList<QLopService*>()
229 << QLopCore::self()
230 << QLopPlotManager::self()
231 << QLopCodecManager::self()
232 << FileDownloader::self()
233 << QLopDataBase::self()
234 << SpaceData::self();
235
236 CDFCodec::registerToManager();
237 AMDATXTCodec::registerToManager();
238
239
240 for(int i=0;i<ServicesToLoad.count();i++)
241 {
242 qDebug()<<ServicesToLoad.at(i)->serviceName();
243 ServicesToLoad.at(i)->initialize(); //must be called before getGUI
244 QDockWidget* wdgt=ServicesToLoad.at(i)->getGUI();
245 if(wdgt)
246 {
247 wdgt->setAllowedAreas(Qt::AllDockWidgetAreas);
248 this->addDockWidget(Qt::TopDockWidgetArea,wdgt);
249 }
250 PythonQt::self()->getMainModule().addObject(ServicesToLoad.at(i)->serviceName(),(QObject*)ServicesToLoad.at(i));
251 }*/
252 239 }
253 240
254 241 MainWindow::~MainWindow()
255 242 {
256 243 }
257 244
258
259 245 void MainWindow::changeEvent(QEvent *e)
260 246 {
261 247 QMainWindow::changeEvent(e);
262 248 switch (e->type()) {
263 249 case QEvent::LanguageChange:
264 250 m_Ui->retranslateUi(this);
265 251 break;
266 252 default:
267 253 break;
268 254 }
269 255 }
@@ -1,153 +1,156
1 1
2 2 ## core - CMakeLists.txt
3 3 STRING(TOLOWER ${CMAKE_PROJECT_NAME} LIBRARY_PREFFIX)
4 4 SET(SQPCORE_LIBRARY_NAME "${LIBRARY_PREFFIX}_core${DEBUG_SUFFIX}")
5 5 SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/")
6 6 SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/")
7 7
8 8 # Include core directory
9 9 include_directories("${INCLUDES_DIR}")
10 10
11 11 # Set a variable to display a warning in the version files.
12 12 SET(SCIQLOP_CMAKE_GENERATION_WARNING "DON'T CHANGE THIS FILE. AUTOGENERATED BY CMAKE.")
13 13 # Generate the version file from the cmake version variables. The version
14 14 # variables are defined in the cmake/sciqlop_version.cmake file.
15 15 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/resources/Version.h.in"
16 16 "${INCLUDES_DIR}/Version.h")
17 17 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/resources/Version.cpp.in"
18 18 "${SOURCES_DIR}/Version.cpp")
19 19
20 20 # Find dependent modules
21 21 find_package(sciqlop-plugin)
22 22 INCLUDE_DIRECTORIES(${SCIQLOP-PLUGIN_INCLUDE_DIR})
23 23
24 24 #
25 25 # Find Qt modules
26 26 #
27 27 SCIQLOP_FIND_QT(Core Network)
28 28
29 29 #
30 30 # Compile the library library
31 31 #
32
33 ADD_DEFINITIONS(-DCORE_LIB)
34
32 35 FILE (GLOB_RECURSE MODULE_SOURCES
33 36 ${INCLUDES_DIR}/*.h
34 37 ${SOURCES_DIR}/*.c
35 38 ${SOURCES_DIR}/*.cpp
36 39 ${SOURCES_DIR}/*.h)
37 40
38 41 ADD_LIBRARY(${SQPCORE_LIBRARY_NAME} ${MODULE_SOURCES})
39 42 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
40 43 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
41 44 TARGET_LINK_LIBRARIES(${SQPCORE_LIBRARY_NAME})
42 45 qt5_use_modules(${SQPCORE_LIBRARY_NAME} Core Network)
43 46
44 47 INSTALL(TARGETS ${SQPCORE_LIBRARY_NAME}
45 48 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
46 49 LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}
47 50 ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR}
48 51 )
49 52
50 53 # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
51 54 # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order.
52 55 # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets
53 56 IF(BUILD_SHARED_LIBS)
54 57 SET_TARGET_PROPERTIES(${SQPCORE_LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS "SCIQLOP_EXPORT")
55 58 ELSE()
56 59 TARGET_COMPILE_DEFINITIONS(${SQPCORE_LIBRARY_NAME} PUBLIC "SCIQLOP_STATIC_LIBRARIES")
57 60 ENDIF()
58 61
59 62 # Set the variable to parent scope so that the other projects can copy the
60 63 # dependent shared libraries
61 64 SCIQLOP_SET_TO_PARENT_SCOPE(SQPCORE_LIBRARY_NAME)
62 65
63 66 # Copy extern shared libraries to the lib folder
64 67 SCIQLOP_COPY_TO_TARGET(LIBRARY ${SQPCORE_LIBRARY_NAME} ${EXTERN_SHARED_LIBRARIES})
65 68
66 69 # Add the files to the list of files to be analyzed
67 70 LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES})
68 71 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
69 72 # Vera++ exclusion files
70 73 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt)
71 74 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
72 75
73 76 #
74 77 # Compile the tests
75 78 #
76 79 IF(BUILD_TESTS)
77 80 INCLUDE_DIRECTORIES(${SOURCES_DIR})
78 81 FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp)
79 82 FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h)
80 83 SET( TEST_LIBRARIES ${SQPCORE_LIBRARY_NAME})
81 84
82 85 SET(TARGETS_COV)
83 86 FOREACH( testFile ${TESTS_SOURCES} )
84 87 GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY )
85 88 GET_FILENAME_COMPONENT( testName ${testFile} NAME_WE )
86 89
87 90 # Add to the list of sources files all the sources in the same
88 91 # directory that aren't another test
89 92 FILE (GLOB currentTestSources
90 93 ${testDirectory}/*.c
91 94 ${testDirectory}/*.cpp
92 95 ${testDirectory}/*.h)
93 96 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
94 97 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
95 98
96 99 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
97 100 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
98 101 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
99 102 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
100 103 qt5_use_modules(${testName} Test)
101 104
102 105 ADD_TEST( NAME ${testName} COMMAND ${testName} )
103 106
104 107 SCIQLOP_COPY_TO_TARGET(RUNTIME ${testName} ${EXTERN_SHARED_LIBRARIES})
105 108 set(Coverage_NAME ${testName})
106 109 if(UNIX)
107 110 SETUP_TARGET_FOR_COVERAGE(TARGET ${testName}_coverage OUTPUT ${testFile}-path NAME ${testFile} EXECUTABLE ${testName})
108 111 LIST( APPEND TARGETS_COV ${testName}_coverage)
109 112 endif(UNIX)
110 113
111 114 ENDFOREACH( testFile )
112 115
113 116 add_custom_target(coverage)
114 117
115 118 FOREACH( target_cov ${TARGETS_COV} )
116 119 add_custom_command(TARGET coverage PRE_BUILD COMMAND make ${target_cov})
117 120 ENDFOREACH( target_cov )
118 121
119 122 LIST(APPEND testFilesToFormat ${TESTS_SOURCES})
120 123 LIST(APPEND testFilesToFormat ${TESTS_HEADERS})
121 124 LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat})
122 125 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
123 126 ENDIF(BUILD_TESTS)
124 127
125 128 #
126 129 # Set the files that must be formatted by clang-format.
127 130 #
128 131 LIST (APPEND FORMATTING_INPUT_FILES ${MODULE_SOURCES})
129 132 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
130 133
131 134 #
132 135 # Set the directories that doxygen must browse to generate the
133 136 # documentation.
134 137 #
135 138 # Source directories:
136 139 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/docs")
137 140 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
138 141 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_INPUT_DIRS)
139 142 # Source directories to exclude from the documentation generation
140 143 #LIST (APPEND DOXYGEN_EXCLUDE_PATTERNS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir/*")
141 144 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_EXCLUDE_PATTERNS)
142 145
143 146 #
144 147 # Set the directories with the sources to analyze and propagate the
145 148 # modification to the parent scope
146 149 #
147 150 # Source directories to analyze:
148 151 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
149 152 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
150 153 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_INPUT_DIRS)
151 154 # Source directories to exclude from the analysis
152 155 #LIST (APPEND ANALYSIS_EXCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir")
153 156 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_EXCLUDE_DIRS)
@@ -1,72 +1,74
1 1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 2 #define SCIQLOP_IDATAPROVIDER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <memory>
5 7
6 8 #include <QObject>
7 9 #include <QUuid>
8 10
9 11 #include <Common/MetaTypes.h>
10 12
11 13 #include <Data/SqpDateTime.h>
12 14
13 15 #include <functional>
14 16
15 17 class DataProviderParameters;
16 18 class IDataSeries;
17 19 class QNetworkReply;
18 20 class QNetworkRequest;
19 21
20 22 /**
21 23 * @brief The IDataProvider interface aims to declare a data provider.
22 24 *
23 25 * A data provider is an entity that generates data and returns it according to various parameters
24 26 * (time interval, product to retrieve the data, etc.)
25 27 *
26 28 * @sa IDataSeries
27 29 */
28 class IDataProvider : public QObject {
30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
29 31
30 32 Q_OBJECT
31 33 public:
32 34 virtual ~IDataProvider() noexcept = default;
33 35
34 36 /**
35 37 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
36 38 */
37 39 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
38 40
39 41 /**
40 42 * @brief requestDataAborting stop data loading of the data identified by identifier
41 43 */
42 44 virtual void requestDataAborting(QUuid identifier) = 0;
43 45
44 46 signals:
45 47 /**
46 48 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
47 49 * identified by identifier
48 50 */
49 51 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
50 52 const SqpDateTime &dateTime);
51 53
52 54 /**
53 55 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
54 56 * identified by identifier
55 57 */
56 58 void dataProvidedProgress(QUuid identifier, double progress);
57 59
58 60
59 61 /**
60 62 * @brief requestConstructed send a request for the data identified by identifier
61 63 * @callback is the methode call by the reply of the request when it is finished.
62 64 */
63 65 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
64 66 std::function<void(QNetworkReply *, QUuid)> callback);
65 67 };
66 68
67 69 // Required for using shared_ptr in signals/slots
68 70 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
69 71 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
70 72 std::function<void(QNetworkReply *, QUuid)>)
71 73
72 74 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,23 +1,25
1 1 #ifndef SCIQLOP_SCALARSERIES_H
2 2 #define SCIQLOP_SCALARSERIES_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Data/DataSeries.h>
5 7
6 8 /**
7 9 * @brief The ScalarSeries class is the implementation for a data series representing a scalar.
8 10 */
9 class ScalarSeries : public DataSeries<1> {
11 class SCIQLOP_CORE_EXPORT ScalarSeries : public DataSeries<1> {
10 12 public:
11 13 /**
12 14 * Ctor with two vectors. The vectors must have the same size, otherwise a ScalarSeries with no
13 15 * values will be created.
14 16 * @param xAxisData x-axis data
15 17 * @param valuesData values data
16 18 */
17 19 explicit ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
18 20 const Unit &xAxisUnit, const Unit &valuesUnit);
19 21
20 22 std::unique_ptr<IDataSeries> clone() const;
21 23 };
22 24
23 25 #endif // SCIQLOP_SCALARSERIES_H
@@ -1,92 +1,94
1 1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 2 #define SCIQLOP_DATASOURCECONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <QLoggingCategory>
5 7 #include <QObject>
6 8 #include <QUuid>
7 9
8 10 #include <Common/spimpl.h>
9 11
10 12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
11 13
12 14 class DataSourceItem;
13 15 class IDataProvider;
14 16
15 17 /**
16 18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
17 19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
18 20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
19 21 * source) then others specifics method will be able to access it. You can load a data source driver
20 22 * plugin then create a data source.
21 23 */
22 class DataSourceController : public QObject {
24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
23 25 Q_OBJECT
24 26 public:
25 27 explicit DataSourceController(QObject *parent = 0);
26 28 virtual ~DataSourceController();
27 29
28 30 /**
29 31 * Registers a data source. The method delivers a unique id that can be used afterwards to
30 32 * access to the data source properties (structure, connection parameters, data provider, etc.)
31 33 * @param dataSourceName the name of the data source
32 34 * @return the unique id with which the data source has been registered
33 35 */
34 36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
35 37
36 38 /**
37 39 * Sets the structure of a data source. The controller takes ownership of the structure.
38 40 * @param dataSourceUid the unique id with which the data source has been registered into the
39 41 * controller. If it is invalid, the method has no effect.
40 42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
41 43 * @sa registerDataSource()
42 44 */
43 45 void setDataSourceItem(const QUuid &dataSourceUid,
44 46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
45 47
46 48 /**
47 49 * Sets the data provider used to retrieve data from of a data source. The controller takes
48 50 * ownership of the provider.
49 51 * @param dataSourceUid the unique id with which the data source has been registered into the
50 52 * controller. If it is invalid, the method has no effect.
51 53 * @param dataProvider the provider of the data source
52 54 * @sa registerDataSource()
53 55 */
54 56 void setDataProvider(const QUuid &dataSourceUid,
55 57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
56 58
57 59 /**
58 60 * Loads an item (product) as a variable in SciQlop
59 61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
60 62 * the data provider associated to the data source, and pass it to for the variable creation
61 63 * @param productItem the item to load
62 64 */
63 65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
64 66
65 67 public slots:
66 68 /// Manage init/end of the controller
67 69 void initialize();
68 70 void finalize();
69 71
70 72 signals:
71 73 /// Signal emitted when a structure has been set for a data source
72 74 void dataSourceItemSet(DataSourceItem *dataSourceItem);
73 75
74 76 /**
75 77 * Signal emitted when a variable creation is asked for a product
76 78 * @param variableName the name of the variable
77 79 * @param variableMetadata the metadata of the variable
78 80 * @param variableProvider the provider that will be used to retrieve the data of the variable
79 81 * (can be null)
80 82 */
81 83 void variableCreationRequested(const QString &variableName,
82 84 const QVariantHash &variableMetadata,
83 85 std::shared_ptr<IDataProvider> variableProvider);
84 86
85 87 private:
86 88 void waitForFinish();
87 89
88 90 class DataSourceControllerPrivate;
89 91 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
90 92 };
91 93
92 94 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,94 +1,96
1 1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 2 #define SCIQLOP_DATASOURCEITEM_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Common/spimpl.h>
5 7
6 8 #include <QVariant>
7 9 #include <QVector>
8 10
9 11 class DataSourceItemAction;
10 12
11 13 /**
12 14 * Possible types of an item
13 15 */
14 16 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
15 17
16 18 /**
17 19 * @brief The DataSourceItem class aims to represent a structure element of a data source.
18 20 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
19 21 * containing other DataSourceItem objects (children).
20 22 * For each DataSourceItem can be associated a set of data representing it.
21 23 */
22 class DataSourceItem {
24 class SCIQLOP_CORE_EXPORT DataSourceItem {
23 25 public:
24 26 /// Key associated with the name of the item
25 27 static const QString NAME_DATA_KEY;
26 28
27 29 explicit DataSourceItem(DataSourceItemType type, const QString &name);
28 30 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
29 31
30 32 /// @return the actions of the item as a vector
31 33 QVector<DataSourceItemAction *> actions() const noexcept;
32 34
33 35 /**
34 36 * Adds an action to the item. The item takes ownership of the action, and the action is
35 37 * automatically associated to the item
36 38 * @param action the action to add
37 39 */
38 40 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
39 41
40 42 /**
41 43 * Adds a child to the item. The item takes ownership of the child.
42 44 * @param child the child to add
43 45 */
44 46 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
45 47
46 48 /**
47 49 * Returns the item's child associated to an index
48 50 * @param childIndex the index to search
49 51 * @return a pointer to the child if index is valid, nullptr otherwise
50 52 */
51 53 DataSourceItem *child(int childIndex) const noexcept;
52 54
53 55 int childCount() const noexcept;
54 56
55 57 /**
56 58 * Get the data associated to a key
57 59 * @param key the key to search
58 60 * @return the data found if key is valid, default QVariant otherwise
59 61 */
60 62 QVariant data(const QString &key) const noexcept;
61 63
62 64 /// Gets all data
63 65 QVariantHash data() const noexcept;
64 66
65 67 bool isRoot() const noexcept;
66 68
67 69 QString name() const noexcept;
68 70
69 71 /**
70 72 * Get the item's parent
71 73 * @return a pointer to the parent if it exists, nullptr if the item is a root
72 74 */
73 75 DataSourceItem *parentItem() const noexcept;
74 76
75 77 /**
76 78 * Sets or appends a value to a key
77 79 * @param key the key
78 80 * @param value the value
79 81 * @param append if true, the value is added to the values already existing for the key,
80 82 * otherwise it replaces the existing values
81 83 */
82 84 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
83 85
84 86 DataSourceItemType type() const noexcept;
85 87
86 88 bool operator==(const DataSourceItem &other);
87 89 bool operator!=(const DataSourceItem &other);
88 90
89 91 private:
90 92 class DataSourceItemPrivate;
91 93 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
92 94 };
93 95
94 96 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,50 +1,52
1 1 #ifndef SCIQLOP_DATASOURCEITEMACTION_H
2 2 #define SCIQLOP_DATASOURCEITEMACTION_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Common/spimpl.h>
5 7
6 8 #include <QLoggingCategory>
7 9 #include <QObject>
8 10
9 11 #include <functional>
10 12
11 13 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceItemAction)
12 14
13 15 class DataSourceItem;
14 16
15 17 /**
16 18 * @brief The DataSourceItemAction class represents an action on a data source item.
17 19 *
18 20 * An action is a function that will be executed when the slot execute() is called.
19 21 */
20 class DataSourceItemAction : public QObject {
22 class SCIQLOP_CORE_EXPORT DataSourceItemAction : public QObject {
21 23
22 24 Q_OBJECT
23 25
24 26 public:
25 27 /// Signature of the function associated to the action
26 28 using ExecuteFunction = std::function<void(DataSourceItem &dataSourceItem)>;
27 29
28 30 /**
29 31 * Ctor
30 32 * @param name the name of the action
31 33 * @param fun the function that will be called when the action is executed
32 34 * @sa execute()
33 35 */
34 36 explicit DataSourceItemAction(const QString &name, ExecuteFunction fun);
35 37
36 38 QString name() const noexcept;
37 39
38 40 /// Sets the data source item concerned by the action
39 41 void setDataSourceItem(DataSourceItem *dataSourceItem) noexcept;
40 42
41 43 public slots:
42 44 /// Executes the action
43 45 void execute();
44 46
45 47 private:
46 48 class DataSourceItemActionPrivate;
47 49 spimpl::unique_impl_ptr<DataSourceItemActionPrivate> impl;
48 50 };
49 51
50 52 #endif // SCIQLOP_DATASOURCEITEMACTION_H
@@ -1,46 +1,48
1 1 #ifndef SCIQLOP_NETWORKCONTROLLER_H
2 2 #define SCIQLOP_NETWORKCONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <QLoggingCategory>
5 7 #include <QObject>
6 8 #include <QUuid>
7 9
8 10 #include <Common/spimpl.h>
9 11 #include <functional>
10 12
11 13 Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController)
12 14
13 15 class QNetworkReply;
14 16 class QNetworkRequest;
15 17
16 18 /**
17 19 * @brief The NetworkController class aims to handle all network connection of SciQlop.
18 20 */
19 class NetworkController : public QObject {
21 class SCIQLOP_CORE_EXPORT NetworkController : public QObject {
20 22 Q_OBJECT
21 23 public:
22 24 explicit NetworkController(QObject *parent = 0);
23 25
24 26 void initialize();
25 27 void finalize();
26 28
27 29 public slots:
28 30 /// Execute request and call callback when the reply is finished. Identifier is attached to the
29 31 /// callback
30 32 void onProcessRequested(const QNetworkRequest &request, QUuid identifier,
31 33 std::function<void(QNetworkReply *, QUuid)> callback);
32 34 /// Cancel the request of identifier
33 35 void onReplyCanceled(QUuid identifier);
34 36
35 37 signals:
36 38 void replyFinished(QNetworkReply *reply, QUuid identifier);
37 39 void replyDownloadProgress(QUuid identifier, double progress);
38 40
39 41 private:
40 42 void waitForFinish();
41 43
42 44 class NetworkControllerPrivate;
43 45 spimpl::unique_impl_ptr<NetworkControllerPrivate> impl;
44 46 };
45 47
46 48 #endif // SCIQLOP_NETWORKCONTROLLER_H
@@ -1,34 +1,36
1 1 #ifndef SCIQLOP_PLUGINMANAGER_H
2 2 #define SCIQLOP_PLUGINMANAGER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Common/spimpl.h>
5 7
6 8 #include <QLoggingCategory>
7 9
8 10 class QDir;
9 11
10 12 Q_DECLARE_LOGGING_CATEGORY(LOG_PluginManager)
11 13
12 14 /**
13 15 * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop.
14 16 */
15 class PluginManager {
17 class SCIQLOP_CORE_EXPORT PluginManager {
16 18 public:
17 19 explicit PluginManager();
18 20
19 21 /**
20 22 * Loads plugins into SciQlop. The loaded plugins are those located in the directory passed in
21 23 * parameter
22 24 * @param pluginDir the directory containing the plugins
23 25 */
24 26 void loadPlugins(const QDir &pluginDir);
25 27
26 28 /// @returns the number of plugins loaded
27 29 int nbPluginsLoaded() const noexcept;
28 30
29 31 private:
30 32 class PluginManagerPrivate;
31 33 spimpl::unique_impl_ptr<PluginManagerPrivate> impl;
32 34 };
33 35
34 36 #endif // SCIQLOP_PLUGINMANAGER_H
@@ -1,40 +1,42
1 1 #ifndef SCIQLOP_TIMECONTROLLER_H
2 2 #define SCIQLOP_TIMECONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Data/SqpDateTime.h>
5 7
6 8 #include <QLoggingCategory>
7 9 #include <QObject>
8 10
9 11 #include <Common/spimpl.h>
10 12
11 13
12 14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
13 15
14 16 /**
15 17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
16 18 */
17 class TimeController : public QObject {
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
18 20 Q_OBJECT
19 21 public:
20 22 explicit TimeController(QObject *parent = 0);
21 23
22 24 SqpDateTime dateTime() const noexcept;
23 25
24 26 signals:
25 27 /// Signal emitted to notify that time parameters has beed updated
26 28 void timeUpdated(SqpDateTime time);
27 29
28 30 public slots:
29 31 /// Slot called when a new dateTime has been defined.
30 32 void onTimeToUpdate(SqpDateTime dateTime);
31 33
32 34 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
33 35 void onTimeNotify();
34 36
35 37 private:
36 38 class TimeControllerPrivate;
37 39 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
38 40 };
39 41
40 42 #endif // SCIQLOP_TIMECONTROLLER_H
@@ -1,55 +1,57
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Data/SqpDateTime.h>
5 7
6 8 #include <QLoggingCategory>
7 9 #include <QObject>
8 10
9 11 #include <Common/MetaTypes.h>
10 12 #include <Common/spimpl.h>
11 13
12 14 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
13 15
14 16 class IDataSeries;
15 17 class QString;
16 18
17 19 /**
18 20 * @brief The Variable class represents a variable in SciQlop.
19 21 */
20 class Variable : public QObject {
22 class SCIQLOP_CORE_EXPORT Variable : public QObject {
21 23
22 24 Q_OBJECT
23 25
24 26 public:
25 27 explicit Variable(const QString &name, const SqpDateTime &dateTime,
26 28 const QVariantHash &metadata = {});
27 29
28 30 QString name() const noexcept;
29 31 SqpDateTime dateTime() const noexcept;
30 32 void setDateTime(const SqpDateTime &dateTime) noexcept;
31 33
32 34 /// @return the data of the variable, nullptr if there is no data
33 35 IDataSeries *dataSeries() const noexcept;
34 36
35 37 QVariantHash metadata() const noexcept;
36 38
37 39 bool contains(const SqpDateTime &dateTime) const noexcept;
38 40 bool intersect(const SqpDateTime &dateTime) const noexcept;
39 41 bool isInside(const SqpDateTime &dateTime) const noexcept;
40 42
41 43 public slots:
42 44 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
43 45
44 46 signals:
45 47 void updated();
46 48
47 49 private:
48 50 class VariablePrivate;
49 51 spimpl::unique_impl_ptr<VariablePrivate> impl;
50 52 };
51 53
52 54 // Required for using shared_ptr in signals/slots
53 55 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
54 56
55 57 #endif // SCIQLOP_VARIABLE_H
@@ -1,46 +1,45
1 1 #ifndef SCIQLOP_VARIABLECACHECONTROLLER_H
2 2 #define SCIQLOP_VARIABLECACHECONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <QLoggingCategory>
5 7 #include <QObject>
6 8
7 9 #include <Data/SqpDateTime.h>
8 10
9 11 #include <QLoggingCategory>
10 12
11 13 #include <Common/spimpl.h>
12 14
13 15 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheController)
14 16
15 17 class Variable;
16 18
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheController)
18
19
20 19 /// This class aims to store in the cache all of the dateTime already requested to the variable.
21 class VariableCacheController : public QObject {
20 class SCIQLOP_CORE_EXPORT VariableCacheController : public QObject {
22 21 Q_OBJECT
23 22 public:
24 23 explicit VariableCacheController(QObject *parent = 0);
25 24
26 25
27 26 void addDateTime(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
28 27
29 28 /// Clears cache concerning a variable
30 29 void clear(std::shared_ptr<Variable> variable) noexcept;
31 30
32 31 /// Return all of the SqpDataTime part of the dateTime whose are not in the cache
33 32 QVector<SqpDateTime> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
34 33 const SqpDateTime &dateTime);
35 34
36 35
37 36 QVector<SqpDateTime> dateCacheList(std::shared_ptr<Variable> variable) const noexcept;
38 37
39 38 void displayCache(std::shared_ptr<Variable> variable) const;
40 39
41 40 private:
42 41 class VariableCacheControllerPrivate;
43 42 spimpl::unique_impl_ptr<VariableCacheControllerPrivate> impl;
44 43 };
45 44
46 45 #endif // SCIQLOP_VARIABLECACHECONTROLLER_H
@@ -1,95 +1,97
1 1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 2 #define SCIQLOP_VARIABLECONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Data/SqpDateTime.h>
5 7
6 8 #include <QLoggingCategory>
7 9 #include <QObject>
8 10
9 11 #include <Common/spimpl.h>
10 12
11 13 class IDataProvider;
12 14 class QItemSelectionModel;
13 15 class TimeController;
14 16 class Variable;
15 17 class VariableModel;
16 18
17 19 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
18 20
19 21 /**
20 22 * @brief The VariableController class aims to handle the variables in SciQlop.
21 23 */
22 class VariableController : public QObject {
24 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
23 25 Q_OBJECT
24 26 public:
25 27 explicit VariableController(QObject *parent = 0);
26 28 virtual ~VariableController();
27 29
28 30 VariableModel *variableModel() noexcept;
29 31 QItemSelectionModel *variableSelectionModel() noexcept;
30 32
31 33 void setTimeController(TimeController *timeController) noexcept;
32 34
33 35 /**
34 36 * Deletes from the controller the variable passed in parameter.
35 37 *
36 38 * Delete a variable includes:
37 39 * - the deletion of the various references to the variable in SciQlop
38 40 * - the deletion of the model variable
39 41 * - the deletion of the provider associated with the variable
40 42 * - removing the cache associated with the variable
41 43 *
42 44 * @param variable the variable to delete from the controller.
43 45 */
44 46 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45 47
46 48 /**
47 49 * Deletes from the controller the variables passed in parameter.
48 50 * @param variables the variables to delete from the controller.
49 51 * @sa deleteVariable()
50 52 */
51 53 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
52 54
53 55 /**
54 56 * @brief abort the variable retrieve data progression
55 57 */
56 58 void abortProgress(std::shared_ptr<Variable> variable);
57 59
58 60 signals:
59 61 /// Signal emitted when a variable is about to be deleted from the controller
60 62 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
61 63
62 64 /// Signal emitted when a data acquisition is requested on a range for a variable
63 65 void rangeChanged(std::shared_ptr<Variable> variable, const SqpDateTime &range);
64 66
65 67 public slots:
66 68 /// Request the data loading of the variable whithin dateTime
67 69 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
68 70 /**
69 71 * Creates a new variable and adds it to the model
70 72 * @param name the name of the new variable
71 73 * @param metadata the metadata of the new variable
72 74 * @param provider the data provider for the new variable
73 75 */
74 76 void createVariable(const QString &name, const QVariantHash &metadata,
75 77 std::shared_ptr<IDataProvider> provider) noexcept;
76 78
77 79 /// Update the temporal parameters of every selected variable to dateTime
78 80 void onDateTimeOnSelection(const SqpDateTime &dateTime);
79 81
80 82
81 83 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
82 84
83 85 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
84 86
85 87 void initialize();
86 88 void finalize();
87 89
88 90 private:
89 91 void waitForFinish();
90 92
91 93 class VariableControllerPrivate;
92 94 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
93 95 };
94 96
95 97 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,79 +1,80
1 1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 2 #define SCIQLOP_VARIABLEMODEL_H
3 3
4 #include "CoreGlobal.h"
4 5
5 6 #include <Data/SqpDateTime.h>
6 7
7 8 #include <QAbstractTableModel>
8 9 #include <QLoggingCategory>
9 10
10 11 #include <Common/MetaTypes.h>
11 12 #include <Common/spimpl.h>
12 13
13 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14 15
15 16 enum VariableRoles { ProgressRole = Qt::UserRole };
16 17
17 18
18 19 class IDataSeries;
19 20 class Variable;
20 21
21 22 /**
22 23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
23 24 */
24 class VariableModel : public QAbstractTableModel {
25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
25 26 Q_OBJECT
26 27 public:
27 28 explicit VariableModel(QObject *parent = nullptr);
28 29
29 30 /**
30 31 * Creates a new variable in the model
31 32 * @param name the name of the new variable
32 33 * @param dateTime the dateTime of the new variable
33 34 * @param metadata the metadata associated to the new variable
34 35 * @return the pointer to the new variable
35 36 */
36 37 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
37 38 const QVariantHash &metadata) noexcept;
38 39
39 40 /**
40 41 * Deletes a variable from the model, if it exists
41 42 * @param variable the variable to delete
42 43 */
43 44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
44 45
45 46
46 47 std::shared_ptr<Variable> variable(int index) const;
47 48
48 49 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
49 50
50 51
51 52 // /////////////////////////// //
52 53 // QAbstractTableModel methods //
53 54 // /////////////////////////// //
54 55
55 56 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
56 57 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
57 58 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
58 59 virtual QVariant headerData(int section, Qt::Orientation orientation,
59 60 int role = Qt::DisplayRole) const override;
60 61
61 62
62 63 void abortProgress(const QModelIndex &index);
63 64
64 65 signals:
65 66 void abortProgessRequested(std::shared_ptr<Variable> variable);
66 67
67 68 private:
68 69 class VariableModelPrivate;
69 70 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
70 71
71 72 private slots:
72 73 /// Slot called when data of a variable has been updated
73 74 void onVariableUpdated() noexcept;
74 75 };
75 76
76 77 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
77 78 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
78 79
79 80 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,49 +1,51
1 1 #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H
2 2 #define SCIQLOP_VISUALIZATIONCONTROLLER_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Data/SqpDateTime.h>
5 7
6 8 #include <QLoggingCategory>
7 9 #include <QObject>
8 10 #include <QUuid>
9 11
10 12 #include <Common/spimpl.h>
11 13
12 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController)
13 15
14 16 class DataSourceItem;
15 17 class Variable;
16 18
17 19 /**
18 20 * @brief The VisualizationController class aims to make the link between SciQlop and its plugins.
19 21 * This is the intermediate class that SciQlop has to use in the way to connect a data source.
20 22 * Please first use register method to initialize a plugin specified by its metadata name (JSON
21 23 * plugin source) then others specifics method will be able to access it. You can load a data source
22 24 * driver plugin then create a data source.
23 25 */
24 class VisualizationController : public QObject {
26 class SCIQLOP_CORE_EXPORT VisualizationController : public QObject {
25 27 Q_OBJECT
26 28 public:
27 29 explicit VisualizationController(QObject *parent = 0);
28 30 virtual ~VisualizationController();
29 31
30 32 signals:
31 33 /// Signal emitted when a variable is about to be deleted from SciQlop
32 34 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
33 35
34 36 /// Signal emitted when a data acquisition is requested on a range for a variable
35 37 void rangeChanged(std::shared_ptr<Variable> variable, const SqpDateTime &range);
36 38
37 39 public slots:
38 40 /// Manage init/end of the controller
39 41 void initialize();
40 42 void finalize();
41 43
42 44 private:
43 45 void waitForFinish();
44 46
45 47 class VisualizationControllerPrivate;
46 48 spimpl::unique_impl_ptr<VisualizationControllerPrivate> impl;
47 49 };
48 50
49 51 #endif // SCIQLOP_VISUALIZATIONCONTROLLER_H
@@ -1,161 +1,161
1 1 #include "Visualization/VisualizationGraphHelper.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <Variable/Variable.h>
7 7
8 8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
9 9
10 10 namespace {
11 11
12 12 class SqpDataContainer : public QCPGraphDataContainer {
13 13 public:
14 14 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
15 15 };
16 16
17 17
18 18 /// Format for datetimes on a axis
19 19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20 20
21 21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 22 /// non-time data
23 23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
24 24 {
25 25 if (isTimeAxis) {
26 26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 28
29 29 return dateTicker;
30 30 }
31 31 else {
32 32 // default ticker
33 33 return QSharedPointer<QCPAxisTicker>::create();
34 34 }
35 35 }
36 36
37 37 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
38 38 const SqpDateTime &dateTime)
39 39 {
40 40 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
41 41 << QThread::currentThread()->objectName();
42 42 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
43 43 scalarSeries.lockRead();
44 44 {
45 45 const auto &xData = scalarSeries.xAxisData()->cdata();
46 46 const auto &valuesData = scalarSeries.valuesData()->cdata();
47 47
48 48 auto xDataBegin = xData.cbegin();
49 49 auto xDataEnd = xData.cend();
50 50
51 qCInfo(LOG_VisualizationGraphHelper())
52 << "TORM: Current points in cache" << xData.count();
51 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
52 << xData.count();
53 53
54 54 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
55 55 qcpGraph->setData(sqpDataContainer);
56 56
57 57 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, dateTime.m_TStart);
58 58 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, dateTime.m_TEnd);
59 59 auto distance = std::distance(xDataBegin, lowerIt);
60 60
61 61 auto valuesDataIt = valuesData.cbegin() + distance;
62 62 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt;
63 63 ++xAxisDataIt, ++valuesDataIt) {
64 64 sqpDataContainer->appendGraphData(QCPGraphData(*xAxisDataIt, *valuesDataIt));
65 65 }
66 66
67 qCInfo(LOG_VisualizationGraphHelper())
68 << "TORM: Current points displayed" << sqpDataContainer->size();
67 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
68 << sqpDataContainer->size();
69 69 }
70 70 scalarSeries.unlock();
71 71
72 72
73 73 // Display all data
74 74 component->parentPlot()->replot();
75 75 }
76 76 else {
77 77 /// @todo DEBUG
78 78 }
79 79 }
80 80
81 81 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
82 82 const SqpDateTime &dateTime)
83 83 {
84 84 auto component = plot.addGraph();
85 85
86 86 if (component) {
87 87 // // Graph data
88 88 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
89 89 true);
90 90
91 91 updateScalarData(component, scalarSeries, dateTime);
92 92
93 93 // Axes properties
94 94 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
95 95 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
96 96
97 97 auto setAxisProperties = [](auto axis, const auto &unit) {
98 98 // label (unit name)
99 99 axis->setLabel(unit.m_Name);
100 100
101 101 // ticker (depending on the type of unit)
102 102 axis->setTicker(axisTicker(unit.m_TimeUnit));
103 103 };
104 104 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
105 105 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
106 106
107 107 // Display all data
108 108 component->rescaleAxes();
109 109 plot.replot();
110 110 }
111 111 else {
112 112 qCDebug(LOG_VisualizationGraphHelper())
113 113 << QObject::tr("Can't create graph for the scalar series");
114 114 }
115 115
116 116 return component;
117 117 }
118 118
119 119 } // namespace
120 120
121 121 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
122 122 QCustomPlot &plot) noexcept
123 123 {
124 124 auto result = QVector<QCPAbstractPlottable *>{};
125 125
126 126 if (variable) {
127 127 // Gets the data series of the variable to call the creation of the right components
128 128 // according to its type
129 129 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
130 130 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
131 131 }
132 132 else {
133 133 qCDebug(LOG_VisualizationGraphHelper())
134 134 << QObject::tr("Can't create graph plottables : unmanaged data series type");
135 135 }
136 136 }
137 137 else {
138 138 qCDebug(LOG_VisualizationGraphHelper())
139 139 << QObject::tr("Can't create graph plottables : the variable is null");
140 140 }
141 141
142 142 return result;
143 143 }
144 144
145 145 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
146 146 IDataSeries *dataSeries, const SqpDateTime &dateTime)
147 147 {
148 148 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
149 149 if (plotableVect.size() == 1) {
150 150 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
151 151 }
152 152 else {
153 153 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
154 154 "Can't update Data of a scalarSeries because there is not only one component "
155 155 "associated");
156 156 }
157 157 }
158 158 else {
159 159 /// @todo DEBUG
160 160 }
161 161 }
@@ -1,401 +1,412
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphHelper.h"
4 4 #include "ui_VisualizationGraphWidget.h"
5 5
6 6 #include <Data/ArrayData.h>
7 7 #include <Data/IDataSeries.h>
8 #include <Settings/SqpSettingsDefs.h>
8 9 #include <SqpApplication.h>
9 10 #include <Variable/Variable.h>
10 11 #include <Variable/VariableController.h>
11 12
12 13 #include <unordered_map>
13 14
14 15 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15 16
16 17 namespace {
17 18
18 19 /// Key pressed to enable zoom on horizontal axis
19 20 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20 21
21 22 /// Key pressed to enable zoom on vertical axis
22 23 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23 24
25 /// Gets a tolerance value from application settings. If the setting can't be found, the default
26 /// value passed in parameter is returned
27 double toleranceValue(const QString &key, double defaultValue) noexcept
28 {
29 return QSettings{}.value(key, defaultValue).toDouble();
30 }
31
24 32 } // namespace
25 33
26 34 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27 35
28 36 explicit VisualizationGraphWidgetPrivate() : m_DoSynchronize{true}, m_IsCalibration{false} {}
29 37
30 38
31 39 // Return the operation when range changed
32 40 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
33 41
34 42 // 1 variable -> n qcpplot
35 43 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
36 44
37 45 bool m_DoSynchronize;
38 46 bool m_IsCalibration;
39 47 };
40 48
41 49 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
42 50 : QWidget{parent},
43 51 ui{new Ui::VisualizationGraphWidget},
44 52 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
45 53 {
46 54 ui->setupUi(this);
47 55
48 56 ui->graphNameLabel->setText(name);
49 57
50 58 // 'Close' options : widget is deleted when closed
51 59 setAttribute(Qt::WA_DeleteOnClose);
52 60 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
53 61 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
54 62
55 63 // Set qcpplot properties :
56 64 // - Drag (on x-axis) and zoom are enabled
57 65 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
58 66 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
59 67 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
60 68 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
61 69 connect(ui->widget, &QCustomPlot::mouseRelease, this,
62 70 &VisualizationGraphWidget::onMouseRelease);
63 71 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
64 72 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
65 73 &QCPAxis::rangeChanged),
66 74 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
67 75
68 76 // Activates menu when right clicking on the graph
69 77 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
70 78 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
71 79 &VisualizationGraphWidget::onGraphMenuRequested);
72 80
73 81 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
74 82 &VariableController::onRequestDataLoading);
75 83 }
76 84
77 85
78 86 VisualizationGraphWidget::~VisualizationGraphWidget()
79 87 {
80 88 delete ui;
81 89 }
82 90
83 91 void VisualizationGraphWidget::enableSynchronize(bool enable)
84 92 {
85 93 impl->m_DoSynchronize = enable;
86 94 }
87 95
88 96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
89 97 {
90 98 // Uses delegate to create the qcpplot components according to the variable
91 99 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
92 100
93 101 for (auto createdPlottable : qAsConst(createdPlottables)) {
94 102 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
95 103 }
96 104
97 105 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
98 106 }
99 107 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
100 108 {
101 109
102 110 // when adding a variable, we need to set its time range to the current graph range
103 111 auto grapheRange = ui->widget->xAxis->range();
104 112 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
105 113 variable->setDateTime(dateTime);
106 114
107 115 auto variableDateTimeWithTolerance = dateTime;
108 116
109 // add 20% tolerance for each side
110 auto tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
117 // add tolerance for each side
118 auto toleranceFactor
119 = toleranceValue(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE);
120 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
111 121 variableDateTimeWithTolerance.m_TStart -= tolerance;
112 122 variableDateTimeWithTolerance.m_TEnd += tolerance;
113 123
114 124 // Uses delegate to create the qcpplot components according to the variable
115 125 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 126
117 127 for (auto createdPlottable : qAsConst(createdPlottables)) {
118 128 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
119 129 }
120 130
121 131 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
122 132
123 133 // CHangement detected, we need to ask controller to request data loading
124 134 emit requestDataLoading(variable, variableDateTimeWithTolerance);
125 135 }
126 136
127 137 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
128 138 {
129 139 // Each component associated to the variable :
130 140 // - is removed from qcpplot (which deletes it)
131 141 // - is no longer referenced in the map
132 142 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
133 143 for (auto it = componentsIt.first; it != componentsIt.second;) {
134 144 ui->widget->removePlottable(it->second);
135 145 it = impl->m_VariableToPlotMultiMap.erase(it);
136 146 }
137 147
138 148 // Updates graph
139 149 ui->widget->replot();
140 150 }
141 151
142 152 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
143 153 const SqpDateTime &range)
144 154 {
145 155 // Note: in case of different axes that depends on variable, we could start with a code like
146 156 // that:
147 157 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
148 158 // for (auto it = componentsIt.first; it != componentsIt.second;) {
149 159 // }
150 160 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
151 161 ui->widget->replot();
152 162 }
153 163
154 164 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
155 165 {
156 166 auto grapheRange = ui->widget->xAxis->range();
157 167 return SqpDateTime{grapheRange.lower, grapheRange.upper};
158 168 }
159 169
160 170 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
161 171 {
162 172 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
163 173 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
164 174 ui->widget->replot();
165 175 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
166 176 }
167 177
168 178 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
169 179 {
170 180 if (visitor) {
171 181 visitor->visit(this);
172 182 }
173 183 else {
174 184 qCCritical(LOG_VisualizationGraphWidget())
175 185 << tr("Can't visit widget : the visitor is null");
176 186 }
177 187 }
178 188
179 189 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
180 190 {
181 191 /// @todo : for the moment, a graph can always accomodate a variable
182 192 Q_UNUSED(variable);
183 193 return true;
184 194 }
185 195
186 196 bool VisualizationGraphWidget::contains(const Variable &variable) const
187 197 {
188 198 // Finds the variable among the keys of the map
189 199 auto variablePtr = &variable;
190 200 auto findVariable
191 201 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
192 202
193 203 auto end = impl->m_VariableToPlotMultiMap.cend();
194 204 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
195 205 return it != end;
196 206 }
197 207
198 208 QString VisualizationGraphWidget::name() const
199 209 {
200 210 return ui->graphNameLabel->text();
201 211 }
202 212
203 213 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
204 214 {
205 215 QMenu graphMenu{};
206 216
207 217 // Iterates on variables (unique keys)
208 218 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
209 219 end = impl->m_VariableToPlotMultiMap.cend();
210 220 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
211 221 // 'Remove variable' action
212 222 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
213 223 [ this, var = it->first ]() { removeVariable(var); });
214 224 }
215 225
216 226 if (!graphMenu.isEmpty()) {
217 227 graphMenu.exec(mapToGlobal(pos));
218 228 }
219 229 }
220 230
221 231 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
222 232 {
223 233 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
224 234 << QThread::currentThread()->objectName();
225 235
226 236 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
227 237
228 238 auto zoomType = impl->getZoomType(t1, t2);
229 239 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
230 240 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
231 241
232 242 auto variable = it->first;
233 243 auto currentDateTime = dateTimeRange;
234 244
235 auto toleranceFactor = 0.2;
245 auto toleranceFactor = toleranceValue(GENERAL_TOLERANCE_AT_UPDATE_KEY,
246 GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
236 247 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
237 248 auto variableDateTimeWithTolerance = currentDateTime;
238 249 variableDateTimeWithTolerance.m_TStart -= tolerance;
239 250 variableDateTimeWithTolerance.m_TEnd += tolerance;
240 251
241 252 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
242 253 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
243 254 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
244 255 // If new range with tol is upper than variable datetime parameters. we need to request new
245 256 // data
246 257 if (!variable->contains(variableDateTimeWithTolerance)) {
247 258
248 259 auto variableDateTimeWithTolerance = currentDateTime;
249 260 if (!variable->isInside(currentDateTime)) {
250 261 auto variableDateTime = variable->dateTime();
251 262 if (variable->contains(variableDateTimeWithTolerance)) {
252 263 qCDebug(LOG_VisualizationGraphWidget())
253 264 << tr("TORM: Detection zoom in that need request:");
254 // add 10% tolerance for each side
265 // add tolerance for each side
255 266 tolerance
256 267 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
257 268 variableDateTimeWithTolerance.m_TStart -= tolerance;
258 269 variableDateTimeWithTolerance.m_TEnd += tolerance;
259 270 }
260 271 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
261 272 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
262 273
263 274 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
264 275 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
265 276 // Tolerance have to be added to the right
266 277 // add tolerance for right (end) side
267 278 tolerance
268 279 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
269 280 variableDateTimeWithTolerance.m_TEnd += tolerance;
270 281 }
271 282 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
272 283 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
273 284 auto diffStartToKeepDelta
274 285 = variableDateTime.m_TStart - currentDateTime.m_TStart;
275 286 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
276 287 // Tolerance have to be added to the left
277 288 // add tolerance for left (start) side
278 289 tolerance
279 290 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
280 291 variableDateTimeWithTolerance.m_TStart -= tolerance;
281 292 }
282 293 else {
283 294 qCCritical(LOG_VisualizationGraphWidget())
284 295 << tr("Detection anormal zoom detection: ");
285 296 }
286 297 }
287 298 else {
288 299 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
289 // add 10% tolerance for each side
300 // add tolerance for each side
290 301 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
291 302 variableDateTimeWithTolerance.m_TStart -= tolerance;
292 303 variableDateTimeWithTolerance.m_TEnd += tolerance;
293 304 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
294 305 }
295 306 if (!variable->contains(dateTimeRange)) {
296 307 qCDebug(LOG_VisualizationGraphWidget())
297 308 << "TORM: Modif on variable datetime detected" << currentDateTime;
298 309 variable->setDateTime(currentDateTime);
299 310 }
300 311
301 312 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
302 313 // CHangement detected, we need to ask controller to request data loading
303 314 emit requestDataLoading(variable, variableDateTimeWithTolerance);
304 315 }
305 316 else {
306 317 qCInfo(LOG_VisualizationGraphWidget())
307 318 << tr("TORM: Detection zoom in that doesn't need request: ");
308 319 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
309 320 }
310 321 }
311 322
312 323 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
313 324 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
314 325 qCDebug(LOG_VisualizationGraphWidget())
315 326 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
316 327 << QThread::currentThread()->objectName();
317 328 emit synchronize(dateTimeRange, oldDateTime, zoomType);
318 329 }
319 330 }
320 331
321 332 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
322 333 {
323 334 auto zoomOrientations = QFlags<Qt::Orientation>{};
324 335
325 336 // Lambda that enables a zoom orientation if the key modifier related to this orientation
326 337 // has
327 338 // been pressed
328 339 auto enableOrientation
329 340 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
330 341 auto orientationEnabled = event->modifiers().testFlag(modifier);
331 342 zoomOrientations.setFlag(orientation, orientationEnabled);
332 343 };
333 344 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
334 345 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
335 346
336 347 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
337 348 }
338 349
339 350 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
340 351 {
341 352 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
342 353 }
343 354
344 355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
345 356 {
346 357 impl->m_IsCalibration = false;
347 358 }
348 359
349 360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
350 361 {
351 362 // NOTE:
352 363 // We don't want to call the method for each component of a variable unitarily, but for
353 364 // all
354 365 // its components at once (eg its three components in the case of a vector).
355 366
356 367 // The unordered_multimap does not do this easily, so the question is whether to:
357 368 // - use an ordered_multimap and the algos of std to group the values by key
358 369 // - use a map (unique keys) and store as values directly the list of components
359 370
360 371 auto grapheRange = ui->widget->xAxis->range();
361 372 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
362 373
363 374 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
364 375 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
365 376 auto variable = it->first;
366 377 qCDebug(LOG_VisualizationGraphWidget())
367 378 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
368 379 << variable->dateTime();
369 380 qCDebug(LOG_VisualizationGraphWidget())
370 381 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 382 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
372 383
373 384 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
374 385 variable->dataSeries(), variable->dateTime());
375 386 }
376 387 }
377 388 }
378 389
379 390 VisualizationGraphWidgetZoomType
380 391 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
381 392 const QCPRange &t2)
382 393 {
383 394 // t1.lower <= t2.lower && t2.upper <= t1.upper
384 395 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
385 396 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
386 397 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
387 398 }
388 399 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
389 400 zoomType = VisualizationGraphWidgetZoomType::PanRight;
390 401 }
391 402 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
392 403 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
393 404 }
394 405 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
395 406 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
396 407 }
397 408 else {
398 409 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
399 410 }
400 411 return zoomType;
401 412 }
@@ -1,148 +1,147
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 5 #include <Data/DataProviderParameters.h>
6 6 #include <Network/NetworkController.h>
7 7 #include <SqpApplication.h>
8 8 #include <Variable/Variable.h>
9 9
10 10 #include <QNetworkAccessManager>
11 11 #include <QNetworkReply>
12 12 #include <QTemporaryFile>
13 13 #include <QThread>
14 14
15 15 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16 16
17 17 namespace {
18 18
19 19 /// URL format for a request on AMDA server. The parameters are as follows:
20 20 /// - %1: start date
21 21 /// - %2: end date
22 22 /// - %3: parameter id
23 23 const auto AMDA_URL_FORMAT = QStringLiteral(
24 24 "http://amda.irap.omp.eu/php/rest/"
25 25 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
26 26 "timeFormat=ISO8601&gzip=0");
27 27
28 28 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 29 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
30 30
31 31 /// Formats a time to a date that can be passed in URL
32 32 QString dateFormat(double sqpDateTime) noexcept
33 33 {
34 34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
35 35 return dateTime.toString(AMDA_TIME_FORMAT);
36 36 }
37 37
38 38 } // namespace
39 39
40 40 AmdaProvider::AmdaProvider()
41 41 {
42 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
43 << QThread::currentThread();
42 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
44 43 if (auto app = sqpApp) {
45 44 auto &networkController = app->networkController();
46 45 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
47 46 std::function<void(QNetworkReply *, QUuid)>)),
48 47 &networkController,
49 48 SLOT(onProcessRequested(QNetworkRequest, QUuid,
50 49 std::function<void(QNetworkReply *, QUuid)>)));
51 50
52 51
53 52 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
54 53 SIGNAL(dataProvidedProgress(QUuid, double)));
55 54 }
56 55 }
57 56
58 57 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
59 58 {
60 59 // NOTE: Try to use multithread if possible
61 60 const auto times = parameters.m_Times;
62 61 const auto data = parameters.m_Data;
63 62 for (const auto &dateTime : qAsConst(times)) {
64 63 retrieveData(token, dateTime, data);
65 64 }
66 65 }
67 66
68 67 void AmdaProvider::requestDataAborting(QUuid identifier)
69 68 {
70 69 if (auto app = sqpApp) {
71 70 auto &networkController = app->networkController();
72 71 networkController.onReplyCanceled(identifier);
73 72 }
74 73 }
75 74
76 75 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
77 76 {
78 77 // Retrieves product ID from data: if the value is invalid, no request is made
79 78 auto productId = data.value(AMDA_XML_ID_KEY).toString();
80 79 if (productId.isNull()) {
81 80 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
82 81 return;
83 82 }
84 83 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
85 84
86 85 // /////////// //
87 86 // Creates URL //
88 87 // /////////// //
89 88
90 89 auto startDate = dateFormat(dateTime.m_TStart);
91 90 auto endDate = dateFormat(dateTime.m_TEnd);
92 91
93 92 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
94 93 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
95 94 auto tempFile = std::make_shared<QTemporaryFile>();
96 95
97 96 // LAMBDA
98 97 auto httpDownloadFinished
99 98 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
100 99 Q_UNUSED(dataId);
101 100
102 101 // Don't do anything if the reply was abort
103 102 if (reply->error() != QNetworkReply::OperationCanceledError) {
104 103
105 104 if (tempFile) {
106 105 auto replyReadAll = reply->readAll();
107 106 if (!replyReadAll.isEmpty()) {
108 107 tempFile->write(replyReadAll);
109 108 }
110 109 tempFile->close();
111 110
112 111 // Parse results file
113 112 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
114 113 emit dataProvided(token, dataSeries, dateTime);
115 114 }
116 115 else {
117 116 /// @todo ALX : debug
118 117 }
119 118 }
120 119 }
121 120
122 121 };
123 122 auto httpFinishedLambda
124 123 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
125 124
126 125 // Don't do anything if the reply was abort
127 126 if (reply->error() != QNetworkReply::OperationCanceledError) {
128 127 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
129 128
130 129
131 130 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
132 131 << downloadFileUrl;
133 132 // Executes request for downloading file //
134 133
135 134 // Creates destination file
136 135 if (tempFile->open()) {
137 136 // Executes request
138 137 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
139 138 httpDownloadFinished);
140 139 }
141 140 }
142 141 };
143 142
144 143 // //////////////// //
145 144 // Executes request //
146 145 // //////////////// //
147 146 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
148 147 }
General Comments 0
You need to be logged in to leave comments. Login now