##// END OF EJS Templates
Removes compilation warnings (with Meson)
Alexandre Leroux -
r961:15899f42a907
parent child
Show More
@@ -1,139 +1,139
1 #ifndef SCIQLOP_SORTUTILS_H
1 #ifndef SCIQLOP_SORTUTILS_H
2 #define SCIQLOP_SORTUTILS_H
2 #define SCIQLOP_SORTUTILS_H
3
3
4 #include <algorithm>
4 #include <algorithm>
5 #include <cmath>
5 #include <cmath>
6 #include <numeric>
6 #include <numeric>
7 #include <vector>
7 #include <vector>
8
8
9 /**
9 /**
10 * Utility class with methods for sorting data
10 * Utility class with methods for sorting data
11 */
11 */
12 struct SortUtils {
12 struct SortUtils {
13 /**
13 /**
14 * Generates a vector representing the index of insertion of each data of a container if this
14 * Generates a vector representing the index of insertion of each data of a container if this
15 * one had to be sorted according to a comparison function.
15 * one had to be sorted according to a comparison function.
16 *
16 *
17 * For example:
17 * For example:
18 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
18 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
19 * result would be : {0; 3; 1; 4; 2}
19 * result would be : {0; 3; 1; 4; 2}
20 *
20 *
21 * @tparam Container the type of the container.
21 * @tparam Container the type of the container.
22 * @tparam Compare the type of the comparison function
22 * @tparam Compare the type of the comparison function
23 * @param container the container from which to generate the result. The container must have a
23 * @param container the container from which to generate the result. The container must have a
24 * at() method that returns a value associated to an index
24 * at() method that returns a value associated to an index
25 * @param compare the comparison function
25 * @param compare the comparison function
26 */
26 */
27 template <typename Container, typename Compare>
27 template <typename Container, typename Compare>
28 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
28 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
29 {
29 {
30 auto permutation = std::vector<int>{};
30 auto permutation = std::vector<int>{};
31 permutation.resize(container.size());
31 permutation.resize(container.size());
32
32
33 std::iota(permutation.begin(), permutation.end(), 0);
33 std::iota(permutation.begin(), permutation.end(), 0);
34 std::sort(permutation.begin(), permutation.end(),
34 std::sort(permutation.begin(), permutation.end(),
35 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
35 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
36 return permutation;
36 return permutation;
37 }
37 }
38
38
39 /**
39 /**
40 * Sorts a container according to indices passed in parameter. The number of data in the
40 * Sorts a container according to indices passed in parameter. The number of data in the
41 * container must be a multiple of the number of indices used to sort the container.
41 * container must be a multiple of the number of indices used to sort the container.
42 *
42 *
43 * Example 1:
43 * Example 1:
44 * container: {1, 2, 3, 4, 5, 6}
44 * container: {1, 2, 3, 4, 5, 6}
45 * sortPermutation: {1, 0}
45 * sortPermutation: {1, 0}
46 *
46 *
47 * Values will be sorted three by three, and the result will be:
47 * Values will be sorted three by three, and the result will be:
48 * {4, 5, 6, 1, 2, 3}
48 * {4, 5, 6, 1, 2, 3}
49 *
49 *
50 * Example 2:
50 * Example 2:
51 * container: {1, 2, 3, 4, 5, 6}
51 * container: {1, 2, 3, 4, 5, 6}
52 * sortPermutation: {2, 0, 1}
52 * sortPermutation: {2, 0, 1}
53 *
53 *
54 * Values will be sorted two by two, and the result will be:
54 * Values will be sorted two by two, and the result will be:
55 * {5, 6, 1, 2, 3, 4}
55 * {5, 6, 1, 2, 3, 4}
56 *
56 *
57 * @param container the container sorted
57 * @param container the container sorted
58 * @param sortPermutation the indices used to sort the container
58 * @param sortPermutation the indices used to sort the container
59 * @return the container sorted
59 * @return the container sorted
60 * @warning no verification is made on validity of sortPermutation (i.e. the vector has unique
60 * @warning no verification is made on validity of sortPermutation (i.e. the vector has unique
61 * indices and its range is [0 ; vector.size()[ )
61 * indices and its range is [0 ; vector.size()[ )
62 */
62 */
63 template <typename Container>
63 template <typename Container>
64 static Container sort(const Container &container, int nbValues,
64 static Container sort(const Container &container, int nbValues,
65 const std::vector<int> &sortPermutation)
65 const std::vector<int> &sortPermutation)
66 {
66 {
67 auto containerSize = container.size();
67 auto containerSize = container.size();
68 if (containerSize % nbValues != 0
68 if (containerSize % nbValues != 0
69 || ((containerSize / nbValues) != sortPermutation.size())) {
69 || ((containerSize / nbValues) != sortPermutation.size())) {
70 return Container{};
70 return Container{};
71 }
71 }
72
72
73 // Inits result
73 // Inits result
74 auto sortedData = Container{};
74 auto sortedData = Container{};
75 sortedData.reserve(containerSize);
75 sortedData.reserve(containerSize);
76
76
77 for (auto i = 0, componentIndex = 0, permutationIndex = 0; i < containerSize;
77 for (auto i = 0u, componentIndex = 0u, permutationIndex = 0u; i < containerSize;
78 ++i, componentIndex = i % nbValues, permutationIndex = i / nbValues) {
78 ++i, componentIndex = i % nbValues, permutationIndex = i / nbValues) {
79 auto insertIndex = sortPermutation.at(permutationIndex) * nbValues + componentIndex;
79 auto insertIndex = sortPermutation.at(permutationIndex) * nbValues + componentIndex;
80 sortedData.push_back(container.at(insertIndex));
80 sortedData.push_back(container.at(insertIndex));
81 }
81 }
82
82
83 return sortedData;
83 return sortedData;
84 }
84 }
85
85
86 /**
86 /**
87 * Compares two values that can be NaN. This method is intended to be used as a compare function
87 * Compares two values that can be NaN. This method is intended to be used as a compare function
88 * for searching min value by excluding NaN values.
88 * for searching min value by excluding NaN values.
89 *
89 *
90 * Examples of use:
90 * Examples of use:
91 * - f({1, 3, 2, 4, 5}) will return 1
91 * - f({1, 3, 2, 4, 5}) will return 1
92 * - f({NaN, 3, 2, 4, 5}) will return 2 (NaN is excluded)
92 * - f({NaN, 3, 2, 4, 5}) will return 2 (NaN is excluded)
93 * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded)
93 * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded)
94 * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value)
94 * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value)
95 *
95 *
96 * @param v1 first value
96 * @param v1 first value
97 * @param v2 second value
97 * @param v2 second value
98 * @return true if v1 < v2, false otherwise
98 * @return true if v1 < v2, false otherwise
99 * @sa std::min_element
99 * @sa std::min_element
100 */
100 */
101 template <typename T>
101 template <typename T>
102 static bool minCompareWithNaN(const T &v1, const T &v2)
102 static bool minCompareWithNaN(const T &v1, const T &v2)
103 {
103 {
104 // Table used with NaN values:
104 // Table used with NaN values:
105 // NaN < v2 -> false
105 // NaN < v2 -> false
106 // v1 < NaN -> true
106 // v1 < NaN -> true
107 // NaN < NaN -> false
107 // NaN < NaN -> false
108 // v1 < v2 -> v1 < v2
108 // v1 < v2 -> v1 < v2
109 return std::isnan(v1) ? false : std::isnan(v2) || (v1 < v2);
109 return std::isnan(v1) ? false : std::isnan(v2) || (v1 < v2);
110 }
110 }
111
111
112 /**
112 /**
113 * Compares two values that can be NaN. This method is intended to be used as a compare function
113 * Compares two values that can be NaN. This method is intended to be used as a compare function
114 * for searching max value by excluding NaN values.
114 * for searching max value by excluding NaN values.
115 *
115 *
116 * Examples of use:
116 * Examples of use:
117 * - f({1, 3, 2, 4, 5}) will return 5
117 * - f({1, 3, 2, 4, 5}) will return 5
118 * - f({1, 3, 2, 4, NaN}) will return 4 (NaN is excluded)
118 * - f({1, 3, 2, 4, NaN}) will return 4 (NaN is excluded)
119 * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded)
119 * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded)
120 * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value)
120 * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value)
121 *
121 *
122 * @param v1 first value
122 * @param v1 first value
123 * @param v2 second value
123 * @param v2 second value
124 * @return true if v1 < v2, false otherwise
124 * @return true if v1 < v2, false otherwise
125 * @sa std::max_element
125 * @sa std::max_element
126 */
126 */
127 template <typename T>
127 template <typename T>
128 static bool maxCompareWithNaN(const T &v1, const T &v2)
128 static bool maxCompareWithNaN(const T &v1, const T &v2)
129 {
129 {
130 // Table used with NaN values:
130 // Table used with NaN values:
131 // NaN < v2 -> true
131 // NaN < v2 -> true
132 // v1 < NaN -> false
132 // v1 < NaN -> false
133 // NaN < NaN -> false
133 // NaN < NaN -> false
134 // v1 < v2 -> v1 < v2
134 // v1 < v2 -> v1 < v2
135 return std::isnan(v1) ? true : !std::isnan(v2) && (v1 < v2);
135 return std::isnan(v1) ? true : !std::isnan(v2) && (v1 < v2);
136 }
136 }
137 };
137 };
138
138
139 #endif // SCIQLOP_SORTUTILS_H
139 #endif // SCIQLOP_SORTUTILS_H
@@ -1,31 +1,32
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGY_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
10
10
11 #include <QLoggingCategory>
11 #include <QLoggingCategory>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14 #include <utility>
14 #include <utility>
15
15
16
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
18
18
19 class Variable;
19 class Variable;
20
20
21 /// This class aims to hande the cache strategy.
21 /// This class aims to hande the cache strategy.
22 class SCIQLOP_CORE_EXPORT VariableCacheStrategy {
22 class SCIQLOP_CORE_EXPORT VariableCacheStrategy {
23
23
24 public:
24 public:
25 virtual ~VariableCacheStrategy() noexcept = default;
25 virtual std::pair<SqpRange, SqpRange> computeRange(const SqpRange &vRange,
26 virtual std::pair<SqpRange, SqpRange> computeRange(const SqpRange &vRange,
26 const SqpRange &rangeRequested)
27 const SqpRange &rangeRequested)
27 = 0;
28 = 0;
28 };
29 };
29
30
30
31
31 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
32 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
@@ -1,44 +1,46
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
3
3
4
4
5 #include <memory>
5 #include <memory>
6 #include <stdexcept>
6 #include <stdexcept>
7
7
8 #include "VariableCacheStrategy.h"
8 #include "VariableCacheStrategy.h"
9 #include "VariableSingleThresholdCacheStrategy.h"
9 #include "VariableSingleThresholdCacheStrategy.h"
10
10
11 #include <QLoggingCategory>
11 #include <QLoggingCategory>
12 #include <QString>
12 #include <QString>
13
13
14 Q_LOGGING_CATEGORY(LOG_VariableCacheStrategyFactory, "VariableCacheStrategyFactory")
14 Q_LOGGING_CATEGORY(LOG_VariableCacheStrategyFactory, "VariableCacheStrategyFactory")
15
15
16 enum class CacheStrategy { SingleThreshold, TwoThreashold };
16 enum class CacheStrategy { SingleThreshold, TwoThreashold };
17
17
18 class VariableCacheStrategyFactory {
18 class VariableCacheStrategyFactory {
19
19
20 using cacheStratPtr = std::unique_ptr<VariableCacheStrategy>;
20 using cacheStratPtr = std::unique_ptr<VariableCacheStrategy>;
21
21
22 public:
22 public:
23 static cacheStratPtr createCacheStrategy(CacheStrategy specificStrategy)
23 static cacheStratPtr createCacheStrategy(CacheStrategy specificStrategy)
24 {
24 {
25 switch (specificStrategy) {
25 switch (specificStrategy) {
26 case CacheStrategy::SingleThreshold: {
26 case CacheStrategy::SingleThreshold: {
27 return std::unique_ptr<VariableCacheStrategy>{
27 return std::unique_ptr<VariableCacheStrategy>{
28 new VariableSingleThresholdCacheStrategy{}};
28 new VariableSingleThresholdCacheStrategy{}};
29 break;
29 break;
30 }
30 }
31 case CacheStrategy::TwoThreashold: {
31 case CacheStrategy::TwoThreashold: {
32 qCCritical(LOG_VariableCacheStrategyFactory())
32 qCCritical(LOG_VariableCacheStrategyFactory())
33 << QObject::tr("cache strategy not implemented yet");
33 << QObject::tr("cache strategy not implemented yet");
34 break;
34 break;
35 }
35 }
36 default:
36 default:
37 qCCritical(LOG_VariableCacheStrategyFactory())
37 qCCritical(LOG_VariableCacheStrategyFactory())
38 << QObject::tr("Unknown cache strategy");
38 << QObject::tr("Unknown cache strategy");
39 }
39 }
40
41 return nullptr;
40 }
42 }
41 };
43 };
42
44
43
45
44 #endif // VARIABLECACHESTRATEGYFACTORY_H
46 #endif // VARIABLECACHESTRATEGYFACTORY_H
@@ -1,65 +1,64
1
1
2 core_moc_headers = [
2 core_moc_headers = [
3 'include/Data/IDataProvider.h',
3 'include/Data/IDataProvider.h',
4 'include/DataSource/DataSourceController.h',
4 'include/DataSource/DataSourceController.h',
5 'include/DataSource/DataSourceItemAction.h',
5 'include/DataSource/DataSourceItemAction.h',
6 'include/Network/NetworkController.h',
6 'include/Network/NetworkController.h',
7 'include/Time/TimeController.h',
7 'include/Time/TimeController.h',
8 'include/Variable/Variable.h',
8 'include/Variable/Variable.h',
9 'include/Variable/VariableCacheController.h',
9 'include/Variable/VariableCacheController.h',
10 'include/Variable/VariableController.h',
10 'include/Variable/VariableController.h',
11 'include/Variable/VariableAcquisitionWorker.h',
11 'include/Variable/VariableAcquisitionWorker.h',
12 'include/Variable/VariableCacheStrategy.h',
13 'include/Variable/VariableSynchronizationGroup.h',
12 'include/Variable/VariableSynchronizationGroup.h',
14 'include/Variable/VariableModel.h',
13 'include/Variable/VariableModel.h',
15 'include/Visualization/VisualizationController.h'
14 'include/Visualization/VisualizationController.h'
16 ]
15 ]
17
16
18
17
19 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
18 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
20
19
21 core_sources = [
20 core_sources = [
22 'src/Common/DateUtils.cpp',
21 'src/Common/DateUtils.cpp',
23 'src/Common/StringUtils.cpp',
22 'src/Common/StringUtils.cpp',
24 'src/Common/MimeTypesDef.cpp',
23 'src/Common/MimeTypesDef.cpp',
25 'src/Data/ScalarSeries.cpp',
24 'src/Data/ScalarSeries.cpp',
26 'src/Data/SpectrogramSeries.cpp',
25 'src/Data/SpectrogramSeries.cpp',
27 'src/Data/DataSeriesIterator.cpp',
26 'src/Data/DataSeriesIterator.cpp',
28 'src/Data/ArrayDataIterator.cpp',
27 'src/Data/ArrayDataIterator.cpp',
29 'src/Data/VectorSeries.cpp',
28 'src/Data/VectorSeries.cpp',
30 'src/Data/OptionalAxis.cpp',
29 'src/Data/OptionalAxis.cpp',
31 'src/DataSource/DataSourceController.cpp',
30 'src/DataSource/DataSourceController.cpp',
32 'src/DataSource/DataSourceItem.cpp',
31 'src/DataSource/DataSourceItem.cpp',
33 'src/DataSource/DataSourceItemAction.cpp',
32 'src/DataSource/DataSourceItemAction.cpp',
34 'src/Network/NetworkController.cpp',
33 'src/Network/NetworkController.cpp',
35 'src/Plugin/PluginManager.cpp',
34 'src/Plugin/PluginManager.cpp',
36 'src/Settings/SqpSettingsDefs.cpp',
35 'src/Settings/SqpSettingsDefs.cpp',
37 'src/Time/TimeController.cpp',
36 'src/Time/TimeController.cpp',
38 'src/Variable/Variable.cpp',
37 'src/Variable/Variable.cpp',
39 'src/Variable/VariableCacheController.cpp',
38 'src/Variable/VariableCacheController.cpp',
40 'src/Variable/VariableController.cpp',
39 'src/Variable/VariableController.cpp',
41 'src/Variable/VariableAcquisitionWorker.cpp',
40 'src/Variable/VariableAcquisitionWorker.cpp',
42 'src/Variable/VariableSynchronizationGroup.cpp',
41 'src/Variable/VariableSynchronizationGroup.cpp',
43 'src/Variable/VariableModel.cpp',
42 'src/Variable/VariableModel.cpp',
44 'src/Visualization/VisualizationController.cpp'
43 'src/Visualization/VisualizationController.cpp'
45 ]
44 ]
46
45
47 core_inc = include_directories(['include', '../plugin/include'])
46 core_inc = include_directories(['include', '../plugin/include'])
48
47
49 sciqlop_core_lib = library('sciqlopcore',
48 sciqlop_core_lib = library('sciqlopcore',
50 core_sources,
49 core_sources,
51 core_moc_files,
50 core_moc_files,
52 cpp_args : '-DCORE_LIB',
51 cpp_args : '-DCORE_LIB',
53 include_directories : core_inc,
52 include_directories : core_inc,
54 dependencies : [qt5core, qt5network],
53 dependencies : [qt5core, qt5network],
55 install : true
54 install : true
56 )
55 )
57
56
58
57
59 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
58 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
60 include_directories : core_inc,
59 include_directories : core_inc,
61 dependencies : [qt5core, qt5network])
60 dependencies : [qt5core, qt5network])
62
61
63
62
64 subdir('tests')
63 subdir('tests')
65
64
@@ -1,101 +1,99
1 #include <Data/OptionalAxis.h>
1 #include <Data/OptionalAxis.h>
2
2
3 #include "Data/ArrayData.h"
3 #include "Data/ArrayData.h"
4
4
5 OptionalAxis::OptionalAxis() : m_Defined{false}, m_Data{nullptr}, m_Unit{}
5 OptionalAxis::OptionalAxis() : m_Defined{false}, m_Data{nullptr}, m_Unit{}
6 {
6 {
7 }
7 }
8
8
9 OptionalAxis::OptionalAxis(std::shared_ptr<ArrayData<1> > data, Unit unit)
9 OptionalAxis::OptionalAxis(std::shared_ptr<ArrayData<1> > data, Unit unit)
10 : m_Defined{true}, m_Data{data}, m_Unit{std::move(unit)}
10 : m_Defined{true}, m_Data{data}, m_Unit{std::move(unit)}
11 {
11 {
12 if (m_Data == nullptr) {
12 if (m_Data == nullptr) {
13 throw std::invalid_argument{"Data can't be null for a defined axis"};
13 throw std::invalid_argument{"Data can't be null for a defined axis"};
14 }
14 }
15 }
15 }
16
16
17 OptionalAxis::OptionalAxis(const OptionalAxis &other)
17 OptionalAxis::OptionalAxis(const OptionalAxis &other)
18 : m_Defined{other.m_Defined},
18 : m_Defined{other.m_Defined},
19 m_Data{other.m_Data ? std::make_shared<ArrayData<1> >(*other.m_Data) : nullptr},
19 m_Data{other.m_Data ? std::make_shared<ArrayData<1> >(*other.m_Data) : nullptr},
20 m_Unit{other.m_Unit}
20 m_Unit{other.m_Unit}
21 {
21 {
22 }
22 }
23
23
24 OptionalAxis &OptionalAxis::operator=(OptionalAxis other)
24 OptionalAxis &OptionalAxis::operator=(OptionalAxis other)
25 {
25 {
26 std::swap(m_Defined, other.m_Defined);
26 std::swap(m_Defined, other.m_Defined);
27 std::swap(m_Data, other.m_Data);
27 std::swap(m_Data, other.m_Data);
28 std::swap(m_Unit, other.m_Unit);
28 std::swap(m_Unit, other.m_Unit);
29
29
30 return *this;
30 return *this;
31 }
31 }
32
32
33 bool OptionalAxis::isDefined() const
33 bool OptionalAxis::isDefined() const
34 {
34 {
35 return m_Defined;
35 return m_Defined;
36 }
36 }
37
37
38 double OptionalAxis::at(int index) const
38 double OptionalAxis::at(int index) const
39 {
39 {
40 if (m_Defined) {
40 if (m_Defined) {
41 return (index >= 0 && index < m_Data->size()) ? m_Data->at(index)
41 return (index >= 0 && index < m_Data->size()) ? m_Data->at(index)
42 : std::numeric_limits<double>::quiet_NaN();
42 : std::numeric_limits<double>::quiet_NaN();
43 }
43 }
44 else {
44 else {
45 return std::numeric_limits<double>::quiet_NaN();
45 return std::numeric_limits<double>::quiet_NaN();
46 }
46 }
47 }
47 }
48
48
49 std::pair<double, double> OptionalAxis::bounds() const
49 std::pair<double, double> OptionalAxis::bounds() const
50 {
50 {
51 if (!m_Defined || m_Data->size() == 0) {
51 if (!m_Defined || m_Data->size() == 0) {
52 return std::make_pair(std::numeric_limits<double>::quiet_NaN(),
52 return std::make_pair(std::numeric_limits<double>::quiet_NaN(),
53 std::numeric_limits<double>::quiet_NaN());
53 std::numeric_limits<double>::quiet_NaN());
54 }
54 }
55 else {
55 else {
56
56
57 auto minIt = std::min_element(
57 auto minIt = std::min_element(
58 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
58 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
59 return SortUtils::minCompareWithNaN(it1.first(), it2.first());
59 return SortUtils::minCompareWithNaN(it1.first(), it2.first());
60 });
60 });
61
61
62 // Gets the iterator on the max of all values data
62 // Gets the iterator on the max of all values data
63 auto maxIt = std::max_element(
63 auto maxIt = std::max_element(
64 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
64 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
65 return SortUtils::maxCompareWithNaN(it1.first(), it2.first());
65 return SortUtils::maxCompareWithNaN(it1.first(), it2.first());
66 });
66 });
67
67
68 auto pair = std::make_pair(minIt->first(), maxIt->first());
69
70 return std::make_pair(minIt->first(), maxIt->first());
68 return std::make_pair(minIt->first(), maxIt->first());
71 }
69 }
72 }
70 }
73
71
74 int OptionalAxis::size() const
72 int OptionalAxis::size() const
75 {
73 {
76 return m_Defined ? m_Data->size() : 0;
74 return m_Defined ? m_Data->size() : 0;
77 }
75 }
78
76
79 Unit OptionalAxis::unit() const
77 Unit OptionalAxis::unit() const
80 {
78 {
81 return m_Defined ? m_Unit : Unit{};
79 return m_Defined ? m_Unit : Unit{};
82 }
80 }
83
81
84 bool OptionalAxis::operator==(const OptionalAxis &other)
82 bool OptionalAxis::operator==(const OptionalAxis &other)
85 {
83 {
86 // Axis not defined
84 // Axis not defined
87 if (!m_Defined) {
85 if (!m_Defined) {
88 return !other.m_Defined;
86 return !other.m_Defined;
89 }
87 }
90
88
91 // Axis defined
89 // Axis defined
92 return m_Unit == other.m_Unit
90 return m_Unit == other.m_Unit
93 && std::equal(
91 && std::equal(
94 m_Data->cbegin(), m_Data->cend(), other.m_Data->cbegin(), other.m_Data->cend(),
92 m_Data->cbegin(), m_Data->cend(), other.m_Data->cbegin(), other.m_Data->cend(),
95 [](const auto &it1, const auto &it2) { return it1.values() == it2.values(); });
93 [](const auto &it1, const auto &it2) { return it1.values() == it2.values(); });
96 }
94 }
97
95
98 bool OptionalAxis::operator!=(const OptionalAxis &other)
96 bool OptionalAxis::operator!=(const OptionalAxis &other)
99 {
97 {
100 return !(*this == other);
98 return !(*this == other);
101 }
99 }
@@ -1,83 +1,83
1 #include "Data/VectorSeries.h"
1 #include "Data/VectorSeries.h"
2
2
3 namespace {
3 namespace {
4
4
5 /**
5 /**
6 * Flatten the three components of a vector to a single QVector that can be passed to an ArrayData
6 * Flatten the three components of a vector to a single QVector that can be passed to an ArrayData
7 *
7 *
8 * Example:
8 * Example:
9 * xValues = {1, 2, 3}
9 * xValues = {1, 2, 3}
10 * yValues = {4, 5, 6}
10 * yValues = {4, 5, 6}
11 * zValues = {7, 8, 9}
11 * zValues = {7, 8, 9}
12 *
12 *
13 * result = {1, 4, 7, 2, 5, 8, 3, 6, 9}
13 * result = {1, 4, 7, 2, 5, 8, 3, 6, 9}
14 *
14 *
15 * @param xValues the x-component values of the vector
15 * @param xValues the x-component values of the vector
16 * @param yValues the y-component values of the vector
16 * @param yValues the y-component values of the vector
17 * @param zValues the z-component values of the vector
17 * @param zValues the z-component values of the vector
18 * @return the single QVector
18 * @return the single QVector
19 * @remarks the three components are consumed
19 * @remarks the three components are consumed
20 * @sa ArrayData
20 * @sa ArrayData
21 */
21 */
22 std::vector<double> flatten(std::vector<double> xValues, std::vector<double> yValues,
22 std::vector<double> flatten(std::vector<double> xValues, std::vector<double> yValues,
23 std::vector<double> zValues)
23 std::vector<double> zValues)
24 {
24 {
25 if (xValues.size() != yValues.size() || xValues.size() != zValues.size()) {
25 if (xValues.size() != yValues.size() || xValues.size() != zValues.size()) {
26 /// @todo ALX : log
26 /// @todo ALX : log
27 return {};
27 return {};
28 }
28 }
29
29
30 auto result = std::vector<double>();
30 auto result = std::vector<double>();
31 result.reserve(xValues.size() * 3);
31 result.reserve(xValues.size() * 3);
32 for (int i = 0; i < xValues.size(); i++) {
32 for (auto i = 0u; i < xValues.size(); ++i) {
33 result.push_back(xValues[i]);
33 result.push_back(xValues[i]);
34 result.push_back(yValues[i]);
34 result.push_back(yValues[i]);
35 result.push_back(zValues[i]);
35 result.push_back(zValues[i]);
36 }
36 }
37
37
38 return result;
38 return result;
39 }
39 }
40
40
41 } // namespace
41 } // namespace
42
42
43 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData,
43 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData,
44 std::vector<double> yValuesData, std::vector<double> zValuesData,
44 std::vector<double> yValuesData, std::vector<double> zValuesData,
45 const Unit &xAxisUnit, const Unit &valuesUnit)
45 const Unit &xAxisUnit, const Unit &valuesUnit)
46 : VectorSeries{std::move(xAxisData), flatten(std::move(xValuesData), std::move(yValuesData),
46 : VectorSeries{std::move(xAxisData), flatten(std::move(xValuesData), std::move(yValuesData),
47 std::move(zValuesData)),
47 std::move(zValuesData)),
48 xAxisUnit, valuesUnit}
48 xAxisUnit, valuesUnit}
49 {
49 {
50 }
50 }
51
51
52 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData,
52 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData,
53 const Unit &xAxisUnit, const Unit &valuesUnit)
53 const Unit &xAxisUnit, const Unit &valuesUnit)
54 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
54 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
55 std::make_shared<ArrayData<2> >(std::move(valuesData), 3), valuesUnit}
55 std::make_shared<ArrayData<2> >(std::move(valuesData), 3), valuesUnit}
56 {
56 {
57 }
57 }
58
58
59 std::unique_ptr<IDataSeries> VectorSeries::clone() const
59 std::unique_ptr<IDataSeries> VectorSeries::clone() const
60 {
60 {
61 return std::make_unique<VectorSeries>(*this);
61 return std::make_unique<VectorSeries>(*this);
62 }
62 }
63
63
64 std::shared_ptr<IDataSeries> VectorSeries::subDataSeries(const SqpRange &range)
64 std::shared_ptr<IDataSeries> VectorSeries::subDataSeries(const SqpRange &range)
65 {
65 {
66 auto subXAxisData = std::vector<double>();
66 auto subXAxisData = std::vector<double>();
67 auto subValuesData = std::vector<double>();
67 auto subValuesData = std::vector<double>();
68
68
69 this->lockRead();
69 this->lockRead();
70 {
70 {
71 auto bounds = xAxisRange(range.m_TStart, range.m_TEnd);
71 auto bounds = xAxisRange(range.m_TStart, range.m_TEnd);
72 for (auto it = bounds.first; it != bounds.second; ++it) {
72 for (auto it = bounds.first; it != bounds.second; ++it) {
73 subXAxisData.push_back(it->x());
73 subXAxisData.push_back(it->x());
74 subValuesData.push_back(it->value(0));
74 subValuesData.push_back(it->value(0));
75 subValuesData.push_back(it->value(1));
75 subValuesData.push_back(it->value(1));
76 subValuesData.push_back(it->value(2));
76 subValuesData.push_back(it->value(2));
77 }
77 }
78 }
78 }
79 this->unlock();
79 this->unlock();
80
80
81 return std::make_shared<VectorSeries>(std::move(subXAxisData), std::move(subValuesData),
81 return std::make_shared<VectorSeries>(std::move(subXAxisData), std::move(subValuesData),
82 this->xAxisUnit(), this->valuesUnit());
82 this->xAxisUnit(), this->valuesUnit());
83 }
83 }
@@ -1,1060 +1,1063
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QDataStream>
15 #include <QDataStream>
16 #include <QMutex>
16 #include <QMutex>
17 #include <QThread>
17 #include <QThread>
18 #include <QUuid>
18 #include <QUuid>
19 #include <QtCore/QItemSelectionModel>
19 #include <QtCore/QItemSelectionModel>
20
20
21 #include <deque>
21 #include <deque>
22 #include <set>
22 #include <set>
23 #include <unordered_map>
23 #include <unordered_map>
24
24
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
26
26
27 namespace {
27 namespace {
28
28
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
30 const SqpRange &oldGraphRange)
30 const SqpRange &oldGraphRange)
31 {
31 {
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
33
33
34 auto varRangeRequested = varRange;
34 auto varRangeRequested = varRange;
35 switch (zoomType) {
35 switch (zoomType) {
36 case AcquisitionZoomType::ZoomIn: {
36 case AcquisitionZoomType::ZoomIn: {
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
39 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TStart += deltaLeft;
40 varRangeRequested.m_TEnd -= deltaRight;
40 varRangeRequested.m_TEnd -= deltaRight;
41 break;
41 break;
42 }
42 }
43
43
44 case AcquisitionZoomType::ZoomOut: {
44 case AcquisitionZoomType::ZoomOut: {
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
47 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TStart -= deltaLeft;
48 varRangeRequested.m_TEnd += deltaRight;
48 varRangeRequested.m_TEnd += deltaRight;
49 break;
49 break;
50 }
50 }
51 case AcquisitionZoomType::PanRight: {
51 case AcquisitionZoomType::PanRight: {
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
54 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TStart += deltaLeft;
55 varRangeRequested.m_TEnd += deltaRight;
55 varRangeRequested.m_TEnd += deltaRight;
56 break;
56 break;
57 }
57 }
58 case AcquisitionZoomType::PanLeft: {
58 case AcquisitionZoomType::PanLeft: {
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
61 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TStart -= deltaLeft;
62 varRangeRequested.m_TEnd -= deltaRight;
62 varRangeRequested.m_TEnd -= deltaRight;
63 break;
63 break;
64 }
64 }
65 case AcquisitionZoomType::Unknown: {
65 case AcquisitionZoomType::Unknown: {
66 qCCritical(LOG_VariableController())
66 qCCritical(LOG_VariableController())
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
68 break;
68 break;
69 }
69 }
70 default:
70 default:
71 qCCritical(LOG_VariableController()) << VariableController::tr(
71 qCCritical(LOG_VariableController()) << VariableController::tr(
72 "Impossible to synchronize: zoom type not take into account");
72 "Impossible to synchronize: zoom type not take into account");
73 // No action
73 // No action
74 break;
74 break;
75 }
75 }
76
76
77 return varRangeRequested;
77 return varRangeRequested;
78 }
78 }
79 }
79 }
80
80
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
82
82
83 struct VariableRequestHandler {
83 struct VariableRequestHandler {
84
84
85 VariableRequestHandler()
85 VariableRequestHandler()
86 {
86 {
87 m_CanUpdate = false;
87 m_CanUpdate = false;
88 m_State = VariableRequestHandlerState::OFF;
88 m_State = VariableRequestHandlerState::OFF;
89 }
89 }
90
90
91 QUuid m_VarId;
91 QUuid m_VarId;
92 VariableRequest m_RunningVarRequest;
92 VariableRequest m_RunningVarRequest;
93 VariableRequest m_PendingVarRequest;
93 VariableRequest m_PendingVarRequest;
94 VariableRequestHandlerState m_State;
94 VariableRequestHandlerState m_State;
95 bool m_CanUpdate;
95 bool m_CanUpdate;
96 };
96 };
97
97
98 struct VariableController::VariableControllerPrivate {
98 struct VariableController::VariableControllerPrivate {
99 explicit VariableControllerPrivate(VariableController *parent)
99 explicit VariableControllerPrivate(VariableController *parent)
100 : m_WorkingMutex{},
100 : m_WorkingMutex{},
101 m_VariableModel{new VariableModel{parent}},
101 m_VariableModel{new VariableModel{parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
105 CacheStrategy::SingleThreshold)},
105 CacheStrategy::SingleThreshold)},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
107 q{parent}
107 q{parent}
108 {
108 {
109
109
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
112 }
112 }
113
113
114
114
115 virtual ~VariableControllerPrivate()
115 virtual ~VariableControllerPrivate()
116 {
116 {
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
118 m_VariableAcquisitionWorkerThread.quit();
118 m_VariableAcquisitionWorkerThread.quit();
119 m_VariableAcquisitionWorkerThread.wait();
119 m_VariableAcquisitionWorkerThread.wait();
120 }
120 }
121
121
122
122
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
124 QUuid varRequestId);
124 QUuid varRequestId);
125
125
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
127 std::shared_ptr<IDataSeries>
127 std::shared_ptr<IDataSeries>
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
129
129
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
131
131
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
134 void updateVariables(QUuid varRequestId);
134 void updateVariables(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
138
138
139 QMutex m_WorkingMutex;
139 QMutex m_WorkingMutex;
140 /// Variable model. The VariableController has the ownership
140 /// Variable model. The VariableController has the ownership
141 VariableModel *m_VariableModel;
141 VariableModel *m_VariableModel;
142 QItemSelectionModel *m_VariableSelectionModel;
142 QItemSelectionModel *m_VariableSelectionModel;
143
143
144
144
145 TimeController *m_TimeController{nullptr};
145 TimeController *m_TimeController{nullptr};
146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
148 QThread m_VariableAcquisitionWorkerThread;
148 QThread m_VariableAcquisitionWorkerThread;
149
149
150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
151 m_VariableToProviderMap;
151 m_VariableToProviderMap;
152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
154 m_GroupIdToVariableSynchronizationGroupMap;
154 m_GroupIdToVariableSynchronizationGroupMap;
155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
157
157
158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
160
160
161 VariableController *q;
161 VariableController *q;
162 };
162 };
163
163
164
164
165 VariableController::VariableController(QObject *parent)
165 VariableController::VariableController(QObject *parent)
166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
167 {
167 {
168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
169 << QThread::currentThread();
169 << QThread::currentThread();
170
170
171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
172 &VariableController::onAbortProgressRequested);
172 &VariableController::onAbortProgressRequested);
173
173
174 connect(impl->m_VariableAcquisitionWorker.get(),
174 connect(impl->m_VariableAcquisitionWorker.get(),
175 &VariableAcquisitionWorker::variableCanceledRequested, this,
175 &VariableAcquisitionWorker::variableCanceledRequested, this,
176 &VariableController::onAbortAcquisitionRequested);
176 &VariableController::onAbortAcquisitionRequested);
177
177
178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
179 &VariableController::onDataProvided);
179 &VariableController::onDataProvided);
180 connect(impl->m_VariableAcquisitionWorker.get(),
180 connect(impl->m_VariableAcquisitionWorker.get(),
181 &VariableAcquisitionWorker::variableRequestInProgress, this,
181 &VariableAcquisitionWorker::variableRequestInProgress, this,
182 &VariableController::onVariableRetrieveDataInProgress);
182 &VariableController::onVariableRetrieveDataInProgress);
183
183
184
184
185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
189
189
190 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
190 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
191 &VariableController::onUpdateDateTime);
191 &VariableController::onUpdateDateTime);
192
192
193 impl->m_VariableAcquisitionWorkerThread.start();
193 impl->m_VariableAcquisitionWorkerThread.start();
194 }
194 }
195
195
196 VariableController::~VariableController()
196 VariableController::~VariableController()
197 {
197 {
198 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
198 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
199 << QThread::currentThread();
199 << QThread::currentThread();
200 this->waitForFinish();
200 this->waitForFinish();
201 }
201 }
202
202
203 VariableModel *VariableController::variableModel() noexcept
203 VariableModel *VariableController::variableModel() noexcept
204 {
204 {
205 return impl->m_VariableModel;
205 return impl->m_VariableModel;
206 }
206 }
207
207
208 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
208 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
209 {
209 {
210 return impl->m_VariableSelectionModel;
210 return impl->m_VariableSelectionModel;
211 }
211 }
212
212
213 void VariableController::setTimeController(TimeController *timeController) noexcept
213 void VariableController::setTimeController(TimeController *timeController) noexcept
214 {
214 {
215 impl->m_TimeController = timeController;
215 impl->m_TimeController = timeController;
216 }
216 }
217
217
218 std::shared_ptr<Variable>
218 std::shared_ptr<Variable>
219 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
219 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
220 {
220 {
221 if (impl->m_VariableModel->containsVariable(variable)) {
221 if (impl->m_VariableModel->containsVariable(variable)) {
222 // Clones variable
222 // Clones variable
223 auto duplicate = variable->clone();
223 auto duplicate = variable->clone();
224
224
225 // Adds clone to model
225 // Adds clone to model
226 impl->m_VariableModel->addVariable(duplicate);
226 impl->m_VariableModel->addVariable(duplicate);
227
227
228 // Generates clone identifier
228 // Generates clone identifier
229 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
229 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
230
230
231 // Registers provider
231 // Registers provider
232 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
232 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
233 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
233 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
234
234
235 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
235 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
236 if (duplicateProvider) {
236 if (duplicateProvider) {
237 impl->registerProvider(duplicateProvider);
237 impl->registerProvider(duplicateProvider);
238 }
238 }
239
239
240 return duplicate;
240 return duplicate;
241 }
241 }
242 else {
242 else {
243 qCCritical(LOG_VariableController())
243 qCCritical(LOG_VariableController())
244 << tr("Can't create duplicate of variable %1: variable not registered in the model")
244 << tr("Can't create duplicate of variable %1: variable not registered in the model")
245 .arg(variable->name());
245 .arg(variable->name());
246 return nullptr;
246 return nullptr;
247 }
247 }
248 }
248 }
249
249
250 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
250 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
251 {
251 {
252 if (!variable) {
252 if (!variable) {
253 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
253 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
254 return;
254 return;
255 }
255 }
256
256
257 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
257 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
258 // make some treatments before the deletion
258 // make some treatments before the deletion
259 emit variableAboutToBeDeleted(variable);
259 emit variableAboutToBeDeleted(variable);
260
260
261 // Deletes identifier
261 // Deletes identifier
262 impl->m_VariableToIdentifierMap.erase(variable);
262 impl->m_VariableToIdentifierMap.erase(variable);
263
263
264 // Deletes provider
264 // Deletes provider
265 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
265 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
266 qCDebug(LOG_VariableController())
266 qCDebug(LOG_VariableController())
267 << tr("Number of providers deleted for variable %1: %2")
267 << tr("Number of providers deleted for variable %1: %2")
268 .arg(variable->name(), QString::number(nbProvidersDeleted));
268 .arg(variable->name(), QString::number(nbProvidersDeleted));
269
269
270
270
271 // Deletes from model
271 // Deletes from model
272 impl->m_VariableModel->deleteVariable(variable);
272 impl->m_VariableModel->deleteVariable(variable);
273 }
273 }
274
274
275 void VariableController::deleteVariables(
275 void VariableController::deleteVariables(
276 const QVector<std::shared_ptr<Variable> > &variables) noexcept
276 const QVector<std::shared_ptr<Variable> > &variables) noexcept
277 {
277 {
278 for (auto variable : qAsConst(variables)) {
278 for (auto variable : qAsConst(variables)) {
279 deleteVariable(variable);
279 deleteVariable(variable);
280 }
280 }
281 }
281 }
282
282
283 QByteArray
283 QByteArray
284 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
284 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
285 {
285 {
286 auto encodedData = QByteArray{};
286 auto encodedData = QByteArray{};
287
287
288 QVariantList ids;
288 QVariantList ids;
289 for (auto &var : variables) {
289 for (auto &var : variables) {
290 auto itVar = impl->m_VariableToIdentifierMap.find(var);
290 auto itVar = impl->m_VariableToIdentifierMap.find(var);
291 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
291 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
292 qCCritical(LOG_VariableController())
292 qCCritical(LOG_VariableController())
293 << tr("Impossible to find the data for an unknown variable.");
293 << tr("Impossible to find the data for an unknown variable.");
294 }
294 }
295
295
296 ids << itVar->second.toByteArray();
296 ids << itVar->second.toByteArray();
297 }
297 }
298
298
299 QDataStream stream{&encodedData, QIODevice::WriteOnly};
299 QDataStream stream{&encodedData, QIODevice::WriteOnly};
300 stream << ids;
300 stream << ids;
301
301
302 return encodedData;
302 return encodedData;
303 }
303 }
304
304
305 QList<std::shared_ptr<Variable> >
305 QList<std::shared_ptr<Variable> >
306 VariableController::variablesForMimeData(const QByteArray &mimeData) const
306 VariableController::variablesForMimeData(const QByteArray &mimeData) const
307 {
307 {
308 auto variables = QList<std::shared_ptr<Variable> >{};
308 auto variables = QList<std::shared_ptr<Variable> >{};
309 QDataStream stream{mimeData};
309 QDataStream stream{mimeData};
310
310
311 QVariantList ids;
311 QVariantList ids;
312 stream >> ids;
312 stream >> ids;
313
313
314 for (auto id : ids) {
314 for (auto id : ids) {
315 auto uuid = QUuid{id.toByteArray()};
315 auto uuid = QUuid{id.toByteArray()};
316 auto var = impl->findVariable(uuid);
316 auto var = impl->findVariable(uuid);
317 variables << var;
317 variables << var;
318 }
318 }
319
319
320 return variables;
320 return variables;
321 }
321 }
322
322
323 std::shared_ptr<Variable>
323 std::shared_ptr<Variable>
324 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
324 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
325 std::shared_ptr<IDataProvider> provider) noexcept
325 std::shared_ptr<IDataProvider> provider) noexcept
326 {
326 {
327 if (!impl->m_TimeController) {
327 if (!impl->m_TimeController) {
328 qCCritical(LOG_VariableController())
328 qCCritical(LOG_VariableController())
329 << tr("Impossible to create variable: The time controller is null");
329 << tr("Impossible to create variable: The time controller is null");
330 return nullptr;
330 return nullptr;
331 }
331 }
332
332
333 auto range = impl->m_TimeController->dateTime();
333 auto range = impl->m_TimeController->dateTime();
334
334
335 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
335 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
336 auto varId = QUuid::createUuid();
336 auto varId = QUuid::createUuid();
337
337
338 // Create the handler
338 // Create the handler
339 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
339 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
340 varRequestHandler->m_VarId = varId;
340 varRequestHandler->m_VarId = varId;
341
341
342 impl->m_VarIdToVarRequestHandler.insert(
342 impl->m_VarIdToVarRequestHandler.insert(
343 std::make_pair(varId, std::move(varRequestHandler)));
343 std::make_pair(varId, std::move(varRequestHandler)));
344
344
345 // store the provider
345 // store the provider
346 impl->registerProvider(provider);
346 impl->registerProvider(provider);
347
347
348 // Associate the provider
348 // Associate the provider
349 impl->m_VariableToProviderMap[newVariable] = provider;
349 impl->m_VariableToProviderMap[newVariable] = provider;
350 impl->m_VariableToIdentifierMap[newVariable] = varId;
350 impl->m_VariableToIdentifierMap[newVariable] = varId;
351
351
352 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
352 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
353
353
354 // auto varRequestId = QUuid::createUuid();
354 // auto varRequestId = QUuid::createUuid();
355 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
355 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
356 // impl->processRequest(newVariable, range, varRequestId);
356 // impl->processRequest(newVariable, range, varRequestId);
357 // impl->updateVariableRequest(varRequestId);
357 // impl->updateVariableRequest(varRequestId);
358
358
359 return newVariable;
359 return newVariable;
360 }
360 }
361
362 qCCritical(LOG_VariableController()) << tr("Impossible to create variable");
363 return nullptr;
361 }
364 }
362
365
363 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
366 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
364 {
367 {
365 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
368 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
366 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
369 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
367 << QThread::currentThread()->objectName();
370 << QThread::currentThread()->objectName();
368 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
371 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
369
372
370 // NOTE we only permit the time modification for one variable
373 // NOTE we only permit the time modification for one variable
371 // DEPRECATED
374 // DEPRECATED
372 // auto variables = QVector<std::shared_ptr<Variable> >{};
375 // auto variables = QVector<std::shared_ptr<Variable> >{};
373 // for (const auto &selectedRow : qAsConst(selectedRows)) {
376 // for (const auto &selectedRow : qAsConst(selectedRows)) {
374 // if (auto selectedVariable =
377 // if (auto selectedVariable =
375 // impl->m_VariableModel->variable(selectedRow.row())) {
378 // impl->m_VariableModel->variable(selectedRow.row())) {
376 // variables << selectedVariable;
379 // variables << selectedVariable;
377
380
378 // // notify that rescale operation has to be done
381 // // notify that rescale operation has to be done
379 // emit rangeChanged(selectedVariable, dateTime);
382 // emit rangeChanged(selectedVariable, dateTime);
380 // }
383 // }
381 // }
384 // }
382 // if (!variables.isEmpty()) {
385 // if (!variables.isEmpty()) {
383 // this->onRequestDataLoading(variables, dateTime, synchro);
386 // this->onRequestDataLoading(variables, dateTime, synchro);
384 // }
387 // }
385 if (selectedRows.size() == 1) {
388 if (selectedRows.size() == 1) {
386
389
387 if (auto selectedVariable
390 if (auto selectedVariable
388 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
391 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
389
392
390 onUpdateDateTime(selectedVariable, dateTime);
393 onUpdateDateTime(selectedVariable, dateTime);
391 }
394 }
392 }
395 }
393 else if (selectedRows.size() > 1) {
396 else if (selectedRows.size() > 1) {
394 qCCritical(LOG_VariableController())
397 qCCritical(LOG_VariableController())
395 << tr("Impossible to set time for more than 1 variable in the same time");
398 << tr("Impossible to set time for more than 1 variable in the same time");
396 }
399 }
397 else {
400 else {
398 qCWarning(LOG_VariableController())
401 qCWarning(LOG_VariableController())
399 << tr("There is no variable selected to set the time one");
402 << tr("There is no variable selected to set the time one");
400 }
403 }
401 }
404 }
402
405
403 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
406 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
404 const SqpRange &dateTime)
407 const SqpRange &dateTime)
405 {
408 {
406 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
409 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
407 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
410 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
408 qCCritical(LOG_VariableController())
411 qCCritical(LOG_VariableController())
409 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
412 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
410 return;
413 return;
411 }
414 }
412
415
413 // notify that rescale operation has to be done
416 // notify that rescale operation has to be done
414 emit rangeChanged(variable, dateTime);
417 emit rangeChanged(variable, dateTime);
415
418
416 auto synchro
419 auto synchro
417 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
420 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
418
421
419 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
422 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
420 }
423 }
421
424
422 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
425 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
423 const SqpRange &cacheRangeRequested,
426 const SqpRange &cacheRangeRequested,
424 QVector<AcquisitionDataPacket> dataAcquired)
427 QVector<AcquisitionDataPacket> dataAcquired)
425 {
428 {
426 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
429 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
427 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
430 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
428 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
431 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
429 if (!varRequestId.isNull()) {
432 if (!varRequestId.isNull()) {
430 impl->updateVariables(varRequestId);
433 impl->updateVariables(varRequestId);
431 }
434 }
432 }
435 }
433
436
434 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
437 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
435 {
438 {
436 qCDebug(LOG_VariableController())
439 qCDebug(LOG_VariableController())
437 << "TORM: variableController::onVariableRetrieveDataInProgress"
440 << "TORM: variableController::onVariableRetrieveDataInProgress"
438 << QThread::currentThread()->objectName() << progress;
441 << QThread::currentThread()->objectName() << progress;
439 if (auto var = impl->findVariable(identifier)) {
442 if (auto var = impl->findVariable(identifier)) {
440 impl->m_VariableModel->setDataProgress(var, progress);
443 impl->m_VariableModel->setDataProgress(var, progress);
441 }
444 }
442 else {
445 else {
443 qCCritical(LOG_VariableController())
446 qCCritical(LOG_VariableController())
444 << tr("Impossible to notify progression of a null variable");
447 << tr("Impossible to notify progression of a null variable");
445 }
448 }
446 }
449 }
447
450
448 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
451 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
449 {
452 {
450 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
453 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
451 << QThread::currentThread()->objectName() << variable->name();
454 << QThread::currentThread()->objectName() << variable->name();
452
455
453 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
456 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
454 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
457 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
455 qCCritical(LOG_VariableController())
458 qCCritical(LOG_VariableController())
456 << tr("Impossible to onAbortProgressRequested request for unknown variable");
459 << tr("Impossible to onAbortProgressRequested request for unknown variable");
457 return;
460 return;
458 }
461 }
459
462
460 auto varId = itVar->second;
463 auto varId = itVar->second;
461
464
462 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
465 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
463 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
466 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
464 qCCritical(LOG_VariableController())
467 qCCritical(LOG_VariableController())
465 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
468 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
466 return;
469 return;
467 }
470 }
468
471
469 auto varHandler = itVarHandler->second.get();
472 auto varHandler = itVarHandler->second.get();
470
473
471 // case where a variable has a running request
474 // case where a variable has a running request
472 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
475 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
473 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
476 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
474 }
477 }
475 }
478 }
476
479
477 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
480 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
478 {
481 {
479 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
482 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
480 << QThread::currentThread()->objectName() << vIdentifier;
483 << QThread::currentThread()->objectName() << vIdentifier;
481
484
482 if (auto var = impl->findVariable(vIdentifier)) {
485 if (auto var = impl->findVariable(vIdentifier)) {
483 this->onAbortProgressRequested(var);
486 this->onAbortProgressRequested(var);
484 }
487 }
485 else {
488 else {
486 qCCritical(LOG_VariableController())
489 qCCritical(LOG_VariableController())
487 << tr("Impossible to abort Acquisition Requestof a null variable");
490 << tr("Impossible to abort Acquisition Requestof a null variable");
488 }
491 }
489 }
492 }
490
493
491 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
494 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
492 {
495 {
493 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
496 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
494 << QThread::currentThread()->objectName()
497 << QThread::currentThread()->objectName()
495 << synchronizationGroupId;
498 << synchronizationGroupId;
496 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
499 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
497 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
500 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
498 std::make_pair(synchronizationGroupId, vSynchroGroup));
501 std::make_pair(synchronizationGroupId, vSynchroGroup));
499 }
502 }
500
503
501 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
504 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
502 {
505 {
503 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
506 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
504 }
507 }
505
508
506 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
509 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
507 QUuid synchronizationGroupId)
510 QUuid synchronizationGroupId)
508
511
509 {
512 {
510 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
513 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
511 << synchronizationGroupId;
514 << synchronizationGroupId;
512 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
515 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
513 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
516 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
514 auto groupIdToVSGIt
517 auto groupIdToVSGIt
515 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
518 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
516 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
519 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
517 impl->m_VariableIdGroupIdMap.insert(
520 impl->m_VariableIdGroupIdMap.insert(
518 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
521 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
519 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
522 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
520 }
523 }
521 else {
524 else {
522 qCCritical(LOG_VariableController())
525 qCCritical(LOG_VariableController())
523 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
526 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
524 << variable->name();
527 << variable->name();
525 }
528 }
526 }
529 }
527 else {
530 else {
528 qCCritical(LOG_VariableController())
531 qCCritical(LOG_VariableController())
529 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
532 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
530 }
533 }
531 }
534 }
532
535
533 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
536 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
534 QUuid synchronizationGroupId)
537 QUuid synchronizationGroupId)
535 {
538 {
536 // Gets variable id
539 // Gets variable id
537 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
540 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
538 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
541 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
539 qCCritical(LOG_VariableController())
542 qCCritical(LOG_VariableController())
540 << tr("Can't desynchronize variable %1: variable identifier not found")
543 << tr("Can't desynchronize variable %1: variable identifier not found")
541 .arg(variable->name());
544 .arg(variable->name());
542 return;
545 return;
543 }
546 }
544
547
545 // Gets synchronization group
548 // Gets synchronization group
546 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
549 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
547 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
550 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
548 qCCritical(LOG_VariableController())
551 qCCritical(LOG_VariableController())
549 << tr("Can't desynchronize variable %1: unknown synchronization group")
552 << tr("Can't desynchronize variable %1: unknown synchronization group")
550 .arg(variable->name());
553 .arg(variable->name());
551 return;
554 return;
552 }
555 }
553
556
554 auto variableId = variableIt->second;
557 auto variableId = variableIt->second;
555
558
556 // Removes variable from synchronization group
559 // Removes variable from synchronization group
557 auto synchronizationGroup = groupIt->second;
560 auto synchronizationGroup = groupIt->second;
558 synchronizationGroup->removeVariableId(variableId);
561 synchronizationGroup->removeVariableId(variableId);
559
562
560 // Removes link between variable and synchronization group
563 // Removes link between variable and synchronization group
561 impl->m_VariableIdGroupIdMap.erase(variableId);
564 impl->m_VariableIdGroupIdMap.erase(variableId);
562 }
565 }
563
566
564 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
567 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
565 const SqpRange &range, bool synchronise)
568 const SqpRange &range, bool synchronise)
566 {
569 {
567 // variables is assumed synchronized
570 // variables is assumed synchronized
568 // TODO: Asser variables synchronization
571 // TODO: Asser variables synchronization
569 // we want to load data of the variable for the dateTime.
572 // we want to load data of the variable for the dateTime.
570 if (variables.isEmpty()) {
573 if (variables.isEmpty()) {
571 return;
574 return;
572 }
575 }
573
576
574 auto varRequestId = QUuid::createUuid();
577 auto varRequestId = QUuid::createUuid();
575 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
578 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
576 << QThread::currentThread()->objectName() << varRequestId
579 << QThread::currentThread()->objectName() << varRequestId
577 << range << synchronise;
580 << range << synchronise;
578
581
579 if (!synchronise) {
582 if (!synchronise) {
580 auto varIds = std::list<QUuid>{};
583 auto varIds = std::list<QUuid>{};
581 for (const auto &var : variables) {
584 for (const auto &var : variables) {
582 auto vId = impl->m_VariableToIdentifierMap.at(var);
585 auto vId = impl->m_VariableToIdentifierMap.at(var);
583 varIds.push_back(vId);
586 varIds.push_back(vId);
584 }
587 }
585 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
588 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
586 for (const auto &var : variables) {
589 for (const auto &var : variables) {
587 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
590 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
588 << varIds.size();
591 << varIds.size();
589 impl->processRequest(var, range, varRequestId);
592 impl->processRequest(var, range, varRequestId);
590 }
593 }
591 }
594 }
592 else {
595 else {
593 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
596 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
594 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
597 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
595 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
598 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
596 auto groupId = varIdToGroupIdIt->second;
599 auto groupId = varIdToGroupIdIt->second;
597
600
598 auto vSynchronizationGroup
601 auto vSynchronizationGroup
599 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
602 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
600 auto vSyncIds = vSynchronizationGroup->getIds();
603 auto vSyncIds = vSynchronizationGroup->getIds();
601
604
602 auto varIds = std::list<QUuid>{};
605 auto varIds = std::list<QUuid>{};
603 for (auto vId : vSyncIds) {
606 for (auto vId : vSyncIds) {
604 varIds.push_back(vId);
607 varIds.push_back(vId);
605 }
608 }
606 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
609 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
607
610
608 for (auto vId : vSyncIds) {
611 for (auto vId : vSyncIds) {
609 auto var = impl->findVariable(vId);
612 auto var = impl->findVariable(vId);
610
613
611 // Don't process already processed var
614 // Don't process already processed var
612 if (var != nullptr) {
615 if (var != nullptr) {
613 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
616 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
614 << varRequestId;
617 << varRequestId;
615 auto vSyncRangeRequested
618 auto vSyncRangeRequested
616 = variables.contains(var)
619 = variables.contains(var)
617 ? range
620 ? range
618 : computeSynchroRangeRequested(var->range(), range,
621 : computeSynchroRangeRequested(var->range(), range,
619 variables.first()->range());
622 variables.first()->range());
620 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
623 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
621 impl->processRequest(var, vSyncRangeRequested, varRequestId);
624 impl->processRequest(var, vSyncRangeRequested, varRequestId);
622 }
625 }
623 else {
626 else {
624 qCCritical(LOG_VariableController())
627 qCCritical(LOG_VariableController())
625
628
626 << tr("Impossible to synchronize a null variable");
629 << tr("Impossible to synchronize a null variable");
627 }
630 }
628 }
631 }
629 }
632 }
630 }
633 }
631
634
632 impl->updateVariables(varRequestId);
635 impl->updateVariables(varRequestId);
633 }
636 }
634
637
635
638
636 void VariableController::initialize()
639 void VariableController::initialize()
637 {
640 {
638 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
641 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
639 impl->m_WorkingMutex.lock();
642 impl->m_WorkingMutex.lock();
640 qCDebug(LOG_VariableController()) << tr("VariableController init END");
643 qCDebug(LOG_VariableController()) << tr("VariableController init END");
641 }
644 }
642
645
643 void VariableController::finalize()
646 void VariableController::finalize()
644 {
647 {
645 impl->m_WorkingMutex.unlock();
648 impl->m_WorkingMutex.unlock();
646 }
649 }
647
650
648 void VariableController::waitForFinish()
651 void VariableController::waitForFinish()
649 {
652 {
650 QMutexLocker locker{&impl->m_WorkingMutex};
653 QMutexLocker locker{&impl->m_WorkingMutex};
651 }
654 }
652
655
653 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
656 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
654 {
657 {
655 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
658 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
656 auto zoomType = AcquisitionZoomType::Unknown;
659 auto zoomType = AcquisitionZoomType::Unknown;
657 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
660 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
658 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
661 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
659 zoomType = AcquisitionZoomType::ZoomOut;
662 zoomType = AcquisitionZoomType::ZoomOut;
660 }
663 }
661 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
664 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
662 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
665 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
663 zoomType = AcquisitionZoomType::PanRight;
666 zoomType = AcquisitionZoomType::PanRight;
664 }
667 }
665 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
668 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
666 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
669 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
667 zoomType = AcquisitionZoomType::PanLeft;
670 zoomType = AcquisitionZoomType::PanLeft;
668 }
671 }
669 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
672 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
670 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
673 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
671 zoomType = AcquisitionZoomType::ZoomIn;
674 zoomType = AcquisitionZoomType::ZoomIn;
672 }
675 }
673 else {
676 else {
674 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
677 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
675 }
678 }
676 return zoomType;
679 return zoomType;
677 }
680 }
678
681
679 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
682 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
680 const SqpRange &rangeRequested,
683 const SqpRange &rangeRequested,
681 QUuid varRequestId)
684 QUuid varRequestId)
682 {
685 {
683 auto itVar = m_VariableToIdentifierMap.find(var);
686 auto itVar = m_VariableToIdentifierMap.find(var);
684 if (itVar == m_VariableToIdentifierMap.cend()) {
687 if (itVar == m_VariableToIdentifierMap.cend()) {
685 qCCritical(LOG_VariableController())
688 qCCritical(LOG_VariableController())
686 << tr("Impossible to process request for unknown variable");
689 << tr("Impossible to process request for unknown variable");
687 return;
690 return;
688 }
691 }
689
692
690 auto varId = itVar->second;
693 auto varId = itVar->second;
691
694
692 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
695 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
693 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
696 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
694 qCCritical(LOG_VariableController())
697 qCCritical(LOG_VariableController())
695 << tr("Impossible to process request for variable with unknown handler");
698 << tr("Impossible to process request for variable with unknown handler");
696 return;
699 return;
697 }
700 }
698
701
699 auto oldRange = var->range();
702 auto oldRange = var->range();
700
703
701 auto varHandler = itVarHandler->second.get();
704 auto varHandler = itVarHandler->second.get();
702
705
703 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
706 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
704 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
707 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
705 }
708 }
706
709
707 auto varRequest = VariableRequest{};
710 auto varRequest = VariableRequest{};
708 varRequest.m_VariableGroupId = varRequestId;
711 varRequest.m_VariableGroupId = varRequestId;
709 auto varStrategyRangesRequested
712 auto varStrategyRangesRequested
710 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
713 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
711 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
714 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
712 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
715 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
713
716
714 switch (varHandler->m_State) {
717 switch (varHandler->m_State) {
715 case VariableRequestHandlerState::OFF: {
718 case VariableRequestHandlerState::OFF: {
716 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
719 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
717 << varRequest.m_RangeRequested
720 << varRequest.m_RangeRequested
718 << varRequest.m_CacheRangeRequested;
721 << varRequest.m_CacheRangeRequested;
719 varHandler->m_RunningVarRequest = varRequest;
722 varHandler->m_RunningVarRequest = varRequest;
720 varHandler->m_State = VariableRequestHandlerState::RUNNING;
723 varHandler->m_State = VariableRequestHandlerState::RUNNING;
721 executeVarRequest(var, varRequest);
724 executeVarRequest(var, varRequest);
722 break;
725 break;
723 }
726 }
724 case VariableRequestHandlerState::RUNNING: {
727 case VariableRequestHandlerState::RUNNING: {
725 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
728 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
726 << varRequest.m_RangeRequested
729 << varRequest.m_RangeRequested
727 << varRequest.m_CacheRangeRequested;
730 << varRequest.m_CacheRangeRequested;
728 varHandler->m_State = VariableRequestHandlerState::PENDING;
731 varHandler->m_State = VariableRequestHandlerState::PENDING;
729 varHandler->m_PendingVarRequest = varRequest;
732 varHandler->m_PendingVarRequest = varRequest;
730 break;
733 break;
731 }
734 }
732 case VariableRequestHandlerState::PENDING: {
735 case VariableRequestHandlerState::PENDING: {
733 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
736 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
734 << varRequest.m_RangeRequested
737 << varRequest.m_RangeRequested
735 << varRequest.m_CacheRangeRequested;
738 << varRequest.m_CacheRangeRequested;
736 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
739 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
737 cancelVariableRequest(variableGroupIdToCancel);
740 cancelVariableRequest(variableGroupIdToCancel);
738 // Cancel variable can make state downgrade
741 // Cancel variable can make state downgrade
739 varHandler->m_State = VariableRequestHandlerState::PENDING;
742 varHandler->m_State = VariableRequestHandlerState::PENDING;
740 varHandler->m_PendingVarRequest = varRequest;
743 varHandler->m_PendingVarRequest = varRequest;
741
744
742 break;
745 break;
743 }
746 }
744 default:
747 default:
745 qCCritical(LOG_VariableController())
748 qCCritical(LOG_VariableController())
746 << QObject::tr("Unknown VariableRequestHandlerState");
749 << QObject::tr("Unknown VariableRequestHandlerState");
747 }
750 }
748 }
751 }
749
752
750 std::shared_ptr<Variable>
753 std::shared_ptr<Variable>
751 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
754 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
752 {
755 {
753 std::shared_ptr<Variable> var;
756 std::shared_ptr<Variable> var;
754 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
757 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
755
758
756 auto end = m_VariableToIdentifierMap.cend();
759 auto end = m_VariableToIdentifierMap.cend();
757 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
760 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
758 if (it != end) {
761 if (it != end) {
759 var = it->first;
762 var = it->first;
760 }
763 }
761 else {
764 else {
762 qCCritical(LOG_VariableController())
765 qCCritical(LOG_VariableController())
763 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
766 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
764 }
767 }
765
768
766 return var;
769 return var;
767 }
770 }
768
771
769 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
772 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
770 const QVector<AcquisitionDataPacket> acqDataPacketVector)
773 const QVector<AcquisitionDataPacket> acqDataPacketVector)
771 {
774 {
772 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
775 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
773 << acqDataPacketVector.size();
776 << acqDataPacketVector.size();
774 std::shared_ptr<IDataSeries> dataSeries;
777 std::shared_ptr<IDataSeries> dataSeries;
775 if (!acqDataPacketVector.isEmpty()) {
778 if (!acqDataPacketVector.isEmpty()) {
776 dataSeries = acqDataPacketVector[0].m_DateSeries;
779 dataSeries = acqDataPacketVector[0].m_DateSeries;
777 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
780 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
778 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
781 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
779 }
782 }
780 }
783 }
781 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
784 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
782 << acqDataPacketVector.size();
785 << acqDataPacketVector.size();
783 return dataSeries;
786 return dataSeries;
784 }
787 }
785
788
786 void VariableController::VariableControllerPrivate::registerProvider(
789 void VariableController::VariableControllerPrivate::registerProvider(
787 std::shared_ptr<IDataProvider> provider)
790 std::shared_ptr<IDataProvider> provider)
788 {
791 {
789 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
792 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
790 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
793 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
791 << provider->objectName();
794 << provider->objectName();
792 m_ProviderSet.insert(provider);
795 m_ProviderSet.insert(provider);
793 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
796 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
794 &VariableAcquisitionWorker::onVariableDataAcquired);
797 &VariableAcquisitionWorker::onVariableDataAcquired);
795 connect(provider.get(), &IDataProvider::dataProvidedProgress,
798 connect(provider.get(), &IDataProvider::dataProvidedProgress,
796 m_VariableAcquisitionWorker.get(),
799 m_VariableAcquisitionWorker.get(),
797 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
800 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
798 connect(provider.get(), &IDataProvider::dataProvidedFailed,
801 connect(provider.get(), &IDataProvider::dataProvidedFailed,
799 m_VariableAcquisitionWorker.get(),
802 m_VariableAcquisitionWorker.get(),
800 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
803 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
801 }
804 }
802 else {
805 else {
803 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
806 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
804 }
807 }
805 }
808 }
806
809
807 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
810 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
808 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
811 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
809 {
812 {
810 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
813 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
811 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
814 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
812 return QUuid();
815 return QUuid();
813 }
816 }
814
817
815 auto varHandler = itVarHandler->second.get();
818 auto varHandler = itVarHandler->second.get();
816 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
819 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
817 qCCritical(LOG_VariableController())
820 qCCritical(LOG_VariableController())
818 << tr("acceptVariableRequest impossible on a variable with OFF state");
821 << tr("acceptVariableRequest impossible on a variable with OFF state");
819 }
822 }
820
823
821 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
824 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
822 varHandler->m_CanUpdate = true;
825 varHandler->m_CanUpdate = true;
823
826
824 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
827 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
825 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
828 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
826 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
829 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
827 << m_VarGroupIdToVarIds.size();
830 << m_VarGroupIdToVarIds.size();
828
831
829 return varHandler->m_RunningVarRequest.m_VariableGroupId;
832 return varHandler->m_RunningVarRequest.m_VariableGroupId;
830 }
833 }
831
834
832 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
835 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
833 {
836 {
834 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
837 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
835 << QThread::currentThread()->objectName() << varRequestId;
838 << QThread::currentThread()->objectName() << varRequestId;
836
839
837 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
840 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
838 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
841 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
839 qCWarning(LOG_VariableController())
842 qCWarning(LOG_VariableController())
840 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
843 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
841 return;
844 return;
842 }
845 }
843
846
844 auto &varIds = varGroupIdToVarIdsIt->second;
847 auto &varIds = varGroupIdToVarIdsIt->second;
845 auto varIdsEnd = varIds.end();
848 auto varIdsEnd = varIds.end();
846 bool processVariableUpdate = true;
849 bool processVariableUpdate = true;
847 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
850 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
848 << varRequestId << varIds.size();
851 << varRequestId << varIds.size();
849 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
852 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
850 ++varIdsIt) {
853 ++varIdsIt) {
851 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
854 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
852 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
855 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
853 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
856 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
854 }
857 }
855 }
858 }
856
859
857 if (processVariableUpdate) {
860 if (processVariableUpdate) {
858 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
861 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
859 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
862 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
860 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
863 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
861 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
864 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
862 if (auto var = findVariable(*varIdsIt)) {
865 if (auto var = findVariable(*varIdsIt)) {
863 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
866 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
864 var->setRange(varRequest.m_RangeRequested);
867 var->setRange(varRequest.m_RangeRequested);
865 var->setCacheRange(varRequest.m_CacheRangeRequested);
868 var->setCacheRange(varRequest.m_CacheRangeRequested);
866 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
869 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
867 << varRequest.m_RangeRequested
870 << varRequest.m_RangeRequested
868 << varRequest.m_CacheRangeRequested;
871 << varRequest.m_CacheRangeRequested;
869 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
872 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
870 << var->nbPoints()
873 << var->nbPoints()
871 << varRequest.m_DataSeries->nbPoints();
874 << varRequest.m_DataSeries->nbPoints();
872 var->mergeDataSeries(varRequest.m_DataSeries);
875 var->mergeDataSeries(varRequest.m_DataSeries);
873 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
876 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
874 << var->nbPoints();
877 << var->nbPoints();
875
878
876 emit var->updated();
879 emit var->updated();
877 qCDebug(LOG_VariableController()) << tr("Update OK");
880 qCDebug(LOG_VariableController()) << tr("Update OK");
878 }
881 }
879 else {
882 else {
880 qCCritical(LOG_VariableController())
883 qCCritical(LOG_VariableController())
881 << tr("Impossible to update data to a null variable");
884 << tr("Impossible to update data to a null variable");
882 }
885 }
883 }
886 }
884 }
887 }
885 updateVariableRequest(varRequestId);
888 updateVariableRequest(varRequestId);
886
889
887 // cleaning varRequestId
890 // cleaning varRequestId
888 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
891 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
889 m_VarGroupIdToVarIds.erase(varRequestId);
892 m_VarGroupIdToVarIds.erase(varRequestId);
890 }
893 }
891 }
894 }
892
895
893
896
894 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
897 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
895 {
898 {
896 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
899 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
897 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
900 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
898 qCCritical(LOG_VariableController()) << QObject::tr(
901 qCCritical(LOG_VariableController()) << QObject::tr(
899 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
902 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
900
903
901 return;
904 return;
902 }
905 }
903
906
904 auto &varIds = varGroupIdToVarIdsIt->second;
907 auto &varIds = varGroupIdToVarIdsIt->second;
905 auto varIdsEnd = varIds.end();
908 auto varIdsEnd = varIds.end();
906 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
909 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
907 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
910 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
908 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
911 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
909
912
910 auto varHandler = itVarHandler->second.get();
913 auto varHandler = itVarHandler->second.get();
911 varHandler->m_CanUpdate = false;
914 varHandler->m_CanUpdate = false;
912
915
913
916
914 switch (varHandler->m_State) {
917 switch (varHandler->m_State) {
915 case VariableRequestHandlerState::OFF: {
918 case VariableRequestHandlerState::OFF: {
916 qCCritical(LOG_VariableController())
919 qCCritical(LOG_VariableController())
917 << QObject::tr("Impossible to update a variable with handler in OFF state");
920 << QObject::tr("Impossible to update a variable with handler in OFF state");
918 } break;
921 } break;
919 case VariableRequestHandlerState::RUNNING: {
922 case VariableRequestHandlerState::RUNNING: {
920 varHandler->m_State = VariableRequestHandlerState::OFF;
923 varHandler->m_State = VariableRequestHandlerState::OFF;
921 varHandler->m_RunningVarRequest = VariableRequest{};
924 varHandler->m_RunningVarRequest = VariableRequest{};
922 break;
925 break;
923 }
926 }
924 case VariableRequestHandlerState::PENDING: {
927 case VariableRequestHandlerState::PENDING: {
925 varHandler->m_State = VariableRequestHandlerState::RUNNING;
928 varHandler->m_State = VariableRequestHandlerState::RUNNING;
926 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
929 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
927 varHandler->m_PendingVarRequest = VariableRequest{};
930 varHandler->m_PendingVarRequest = VariableRequest{};
928 auto var = findVariable(itVarHandler->first);
931 auto var = findVariable(itVarHandler->first);
929 executeVarRequest(var, varHandler->m_RunningVarRequest);
932 executeVarRequest(var, varHandler->m_RunningVarRequest);
930 break;
933 break;
931 }
934 }
932 default:
935 default:
933 qCCritical(LOG_VariableController())
936 qCCritical(LOG_VariableController())
934 << QObject::tr("Unknown VariableRequestHandlerState");
937 << QObject::tr("Unknown VariableRequestHandlerState");
935 }
938 }
936 }
939 }
937 }
940 }
938 }
941 }
939
942
940
943
941 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
944 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
942 {
945 {
943 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
946 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
944
947
945 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
948 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
946 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
949 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
947 qCCritical(LOG_VariableController())
950 qCCritical(LOG_VariableController())
948 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
951 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
949 return;
952 return;
950 }
953 }
951
954
952 auto &varIds = varGroupIdToVarIdsIt->second;
955 auto &varIds = varGroupIdToVarIdsIt->second;
953 auto varIdsEnd = varIds.end();
956 auto varIdsEnd = varIds.end();
954 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
957 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
955 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
958 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
956 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
959 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
957
960
958 auto varHandler = itVarHandler->second.get();
961 auto varHandler = itVarHandler->second.get();
959 varHandler->m_VarId = QUuid{};
962 varHandler->m_VarId = QUuid{};
960 switch (varHandler->m_State) {
963 switch (varHandler->m_State) {
961 case VariableRequestHandlerState::OFF: {
964 case VariableRequestHandlerState::OFF: {
962 qCWarning(LOG_VariableController())
965 qCWarning(LOG_VariableController())
963 << QObject::tr("Impossible to cancel a variable with no running request");
966 << QObject::tr("Impossible to cancel a variable with no running request");
964 break;
967 break;
965 }
968 }
966 case VariableRequestHandlerState::RUNNING: {
969 case VariableRequestHandlerState::RUNNING: {
967
970
968 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
971 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
969 auto var = findVariable(itVarHandler->first);
972 auto var = findVariable(itVarHandler->first);
970 auto varProvider = m_VariableToProviderMap.at(var);
973 auto varProvider = m_VariableToProviderMap.at(var);
971 if (varProvider != nullptr) {
974 if (varProvider != nullptr) {
972 m_VariableAcquisitionWorker->abortProgressRequested(
975 m_VariableAcquisitionWorker->abortProgressRequested(
973 itVarHandler->first);
976 itVarHandler->first);
974 }
977 }
975 m_VariableModel->setDataProgress(var, 0.0);
978 m_VariableModel->setDataProgress(var, 0.0);
976 varHandler->m_CanUpdate = false;
979 varHandler->m_CanUpdate = false;
977 varHandler->m_State = VariableRequestHandlerState::OFF;
980 varHandler->m_State = VariableRequestHandlerState::OFF;
978 varHandler->m_RunningVarRequest = VariableRequest{};
981 varHandler->m_RunningVarRequest = VariableRequest{};
979 }
982 }
980 else {
983 else {
981 // TODO: log Impossible to cancel the running variable request beacause its
984 // TODO: log Impossible to cancel the running variable request beacause its
982 // varRequestId isn't not the canceled one
985 // varRequestId isn't not the canceled one
983 }
986 }
984 break;
987 break;
985 }
988 }
986 case VariableRequestHandlerState::PENDING: {
989 case VariableRequestHandlerState::PENDING: {
987 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
990 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
988 auto var = findVariable(itVarHandler->first);
991 auto var = findVariable(itVarHandler->first);
989 auto varProvider = m_VariableToProviderMap.at(var);
992 auto varProvider = m_VariableToProviderMap.at(var);
990 if (varProvider != nullptr) {
993 if (varProvider != nullptr) {
991 m_VariableAcquisitionWorker->abortProgressRequested(
994 m_VariableAcquisitionWorker->abortProgressRequested(
992 itVarHandler->first);
995 itVarHandler->first);
993 }
996 }
994 m_VariableModel->setDataProgress(var, 0.0);
997 m_VariableModel->setDataProgress(var, 0.0);
995 varHandler->m_CanUpdate = false;
998 varHandler->m_CanUpdate = false;
996 varHandler->m_State = VariableRequestHandlerState::RUNNING;
999 varHandler->m_State = VariableRequestHandlerState::RUNNING;
997 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
1000 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
998 varHandler->m_PendingVarRequest = VariableRequest{};
1001 varHandler->m_PendingVarRequest = VariableRequest{};
999 executeVarRequest(var, varHandler->m_RunningVarRequest);
1002 executeVarRequest(var, varHandler->m_RunningVarRequest);
1000 }
1003 }
1001 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1004 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1002 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1005 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1003 varHandler->m_PendingVarRequest = VariableRequest{};
1006 varHandler->m_PendingVarRequest = VariableRequest{};
1004 }
1007 }
1005 else {
1008 else {
1006 // TODO: log Impossible to cancel the variable request beacause its
1009 // TODO: log Impossible to cancel the variable request beacause its
1007 // varRequestId isn't not the canceled one
1010 // varRequestId isn't not the canceled one
1008 }
1011 }
1009 break;
1012 break;
1010 }
1013 }
1011 default:
1014 default:
1012 qCCritical(LOG_VariableController())
1015 qCCritical(LOG_VariableController())
1013 << QObject::tr("Unknown VariableRequestHandlerState");
1016 << QObject::tr("Unknown VariableRequestHandlerState");
1014 }
1017 }
1015 }
1018 }
1016 }
1019 }
1017 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1020 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1018 m_VarGroupIdToVarIds.erase(varRequestId);
1021 m_VarGroupIdToVarIds.erase(varRequestId);
1019 }
1022 }
1020
1023
1021 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1024 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1022 VariableRequest &varRequest)
1025 VariableRequest &varRequest)
1023 {
1026 {
1024 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1027 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1025
1028
1026 auto varId = m_VariableToIdentifierMap.at(var);
1029 auto varId = m_VariableToIdentifierMap.at(var);
1027
1030
1028 auto varCacheRange = var->cacheRange();
1031 auto varCacheRange = var->cacheRange();
1029 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1032 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1030 auto notInCacheRangeList
1033 auto notInCacheRangeList
1031 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1034 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1032 auto inCacheRangeList
1035 auto inCacheRangeList
1033 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1036 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1034
1037
1035 if (!notInCacheRangeList.empty()) {
1038 if (!notInCacheRangeList.empty()) {
1036
1039
1037 auto varProvider = m_VariableToProviderMap.at(var);
1040 auto varProvider = m_VariableToProviderMap.at(var);
1038 if (varProvider != nullptr) {
1041 if (varProvider != nullptr) {
1039 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1042 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1040 << varRequest.m_CacheRangeRequested;
1043 << varRequest.m_CacheRangeRequested;
1041 m_VariableAcquisitionWorker->pushVariableRequest(
1044 m_VariableAcquisitionWorker->pushVariableRequest(
1042 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1045 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1043 varRequest.m_CacheRangeRequested,
1046 varRequest.m_CacheRangeRequested,
1044 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1047 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1045 varProvider);
1048 varProvider);
1046 }
1049 }
1047 else {
1050 else {
1048 qCCritical(LOG_VariableController())
1051 qCCritical(LOG_VariableController())
1049 << "Impossible to provide data with a null provider";
1052 << "Impossible to provide data with a null provider";
1050 }
1053 }
1051
1054
1052 if (!inCacheRangeList.empty()) {
1055 if (!inCacheRangeList.empty()) {
1053 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1056 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1054 }
1057 }
1055 }
1058 }
1056 else {
1059 else {
1057 acceptVariableRequest(varId,
1060 acceptVariableRequest(varId,
1058 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1061 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1059 }
1062 }
1060 }
1063 }
@@ -1,394 +1,396
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableController.h>
3 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
8
8
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMimeData>
14 #include <QMimeData>
15 #include <QSize>
15 #include <QSize>
16 #include <QTimer>
16 #include <QTimer>
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
20
20
21 namespace {
21 namespace {
22
22
23 // Column indexes
23 // Column indexes
24 const auto NAME_COLUMN = 0;
24 const auto NAME_COLUMN = 0;
25 const auto TSTART_COLUMN = 1;
25 const auto TSTART_COLUMN = 1;
26 const auto TEND_COLUMN = 2;
26 const auto TEND_COLUMN = 2;
27 const auto NBPOINTS_COLUMN = 3;
27 const auto NBPOINTS_COLUMN = 3;
28 const auto UNIT_COLUMN = 4;
28 const auto UNIT_COLUMN = 4;
29 const auto MISSION_COLUMN = 5;
29 const auto MISSION_COLUMN = 5;
30 const auto PLUGIN_COLUMN = 6;
30 const auto PLUGIN_COLUMN = 6;
31 const auto NB_COLUMNS = 7;
31 const auto NB_COLUMNS = 7;
32
32
33 // Column properties
33 // Column properties
34 const auto DEFAULT_HEIGHT = 25;
34 const auto DEFAULT_HEIGHT = 25;
35 const auto DEFAULT_WIDTH = 100;
35 const auto DEFAULT_WIDTH = 100;
36
36
37 struct ColumnProperties {
37 struct ColumnProperties {
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
39 int height = DEFAULT_HEIGHT)
39 int height = DEFAULT_HEIGHT)
40 : m_Name{name}, m_Width{width}, m_Height{height}
40 : m_Name{name}, m_Width{width}, m_Height{height}
41 {
41 {
42 }
42 }
43
43
44 QString m_Name;
44 QString m_Name;
45 int m_Width;
45 int m_Width;
46 int m_Height;
46 int m_Height;
47 };
47 };
48
48
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
54
54
55 /// Format for datetimes
55 /// Format for datetimes
56 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
56 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
57
57
58 QString uniqueName(const QString &defaultName,
58 QString uniqueName(const QString &defaultName,
59 const std::vector<std::shared_ptr<Variable> > &variables)
59 const std::vector<std::shared_ptr<Variable> > &variables)
60 {
60 {
61 auto forbiddenNames = std::vector<QString>(variables.size());
61 auto forbiddenNames = std::vector<QString>(variables.size());
62 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
62 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
63 [](const auto &variable) { return variable->name(); });
63 [](const auto &variable) { return variable->name(); });
64 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
64 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
65 Q_ASSERT(!uniqueName.isEmpty());
65 Q_ASSERT(!uniqueName.isEmpty());
66
66
67 return uniqueName;
67 return uniqueName;
68 }
68 }
69
69
70 } // namespace
70 } // namespace
71
71
72 struct VariableModel::VariableModelPrivate {
72 struct VariableModel::VariableModelPrivate {
73 /// Variables created in SciQlop
73 /// Variables created in SciQlop
74 std::vector<std::shared_ptr<Variable> > m_Variables;
74 std::vector<std::shared_ptr<Variable> > m_Variables;
75 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
75 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
76 VariableController *m_VariableController;
76 VariableController *m_VariableController;
77
77
78 /// Return the row index of the variable. -1 if it's not found
78 /// Return the row index of the variable. -1 if it's not found
79 int indexOfVariable(Variable *variable) const noexcept;
79 int indexOfVariable(Variable *variable) const noexcept;
80 };
80 };
81
81
82 VariableModel::VariableModel(VariableController *parent)
82 VariableModel::VariableModel(VariableController *parent)
83 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
83 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
84 {
84 {
85 impl->m_VariableController = parent;
85 impl->m_VariableController = parent;
86 }
86 }
87
87
88 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
88 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
89 {
89 {
90 auto insertIndex = rowCount();
90 auto insertIndex = rowCount();
91 beginInsertRows({}, insertIndex, insertIndex);
91 beginInsertRows({}, insertIndex, insertIndex);
92
92
93 // Generates unique name for the variable
93 // Generates unique name for the variable
94 variable->setName(uniqueName(variable->name(), impl->m_Variables));
94 variable->setName(uniqueName(variable->name(), impl->m_Variables));
95
95
96 impl->m_Variables.push_back(variable);
96 impl->m_Variables.push_back(variable);
97 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
97 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
98
98
99 endInsertRows();
99 endInsertRows();
100 }
100 }
101
101
102 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
102 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
103 {
103 {
104 auto end = impl->m_Variables.cend();
104 auto end = impl->m_Variables.cend();
105 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
105 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
106 }
106 }
107
107
108 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
108 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
109 const QVariantHash &metadata) noexcept
109 const QVariantHash &metadata) noexcept
110 {
110 {
111 auto variable = std::make_shared<Variable>(name, metadata);
111 auto variable = std::make_shared<Variable>(name, metadata);
112 addVariable(variable);
112 addVariable(variable);
113
113
114 return variable;
114 return variable;
115 }
115 }
116
116
117 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
117 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
118 {
118 {
119 if (!variable) {
119 if (!variable) {
120 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
120 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
121 return;
121 return;
122 }
122 }
123
123
124 // Finds variable in the model
124 // Finds variable in the model
125 auto begin = impl->m_Variables.cbegin();
125 auto begin = impl->m_Variables.cbegin();
126 auto end = impl->m_Variables.cend();
126 auto end = impl->m_Variables.cend();
127 auto it = std::find(begin, end, variable);
127 auto it = std::find(begin, end, variable);
128 if (it != end) {
128 if (it != end) {
129 auto removeIndex = std::distance(begin, it);
129 auto removeIndex = std::distance(begin, it);
130
130
131 // Deletes variable
131 // Deletes variable
132 beginRemoveRows({}, removeIndex, removeIndex);
132 beginRemoveRows({}, removeIndex, removeIndex);
133 impl->m_Variables.erase(it);
133 impl->m_Variables.erase(it);
134 endRemoveRows();
134 endRemoveRows();
135 }
135 }
136 else {
136 else {
137 qCritical(LOG_VariableModel())
137 qCritical(LOG_VariableModel())
138 << tr("Can't delete variable %1 from the model: the variable is not in the model")
138 << tr("Can't delete variable %1 from the model: the variable is not in the model")
139 .arg(variable->name());
139 .arg(variable->name());
140 }
140 }
141
141
142 // Removes variable from progress map
142 // Removes variable from progress map
143 impl->m_VariableToProgress.erase(variable);
143 impl->m_VariableToProgress.erase(variable);
144 }
144 }
145
145
146
146
147 std::shared_ptr<Variable> VariableModel::variable(int index) const
147 std::shared_ptr<Variable> VariableModel::variable(int index) const
148 {
148 {
149 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
149 return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size())
150 ? impl->m_Variables[index]
151 : nullptr;
150 }
152 }
151
153
152 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
154 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
153 {
155 {
154 return impl->m_Variables;
156 return impl->m_Variables;
155 }
157 }
156
158
157 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
159 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
158 {
160 {
159 if (progress > 0.0) {
161 if (progress > 0.0) {
160 impl->m_VariableToProgress[variable] = progress;
162 impl->m_VariableToProgress[variable] = progress;
161 }
163 }
162 else {
164 else {
163 impl->m_VariableToProgress.erase(variable);
165 impl->m_VariableToProgress.erase(variable);
164 }
166 }
165 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
167 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
166
168
167 emit dataChanged(modelIndex, modelIndex);
169 emit dataChanged(modelIndex, modelIndex);
168 }
170 }
169
171
170 int VariableModel::columnCount(const QModelIndex &parent) const
172 int VariableModel::columnCount(const QModelIndex &parent) const
171 {
173 {
172 Q_UNUSED(parent);
174 Q_UNUSED(parent);
173
175
174 return NB_COLUMNS;
176 return NB_COLUMNS;
175 }
177 }
176
178
177 int VariableModel::rowCount(const QModelIndex &parent) const
179 int VariableModel::rowCount(const QModelIndex &parent) const
178 {
180 {
179 Q_UNUSED(parent);
181 Q_UNUSED(parent);
180
182
181 return impl->m_Variables.size();
183 return impl->m_Variables.size();
182 }
184 }
183
185
184 QVariant VariableModel::data(const QModelIndex &index, int role) const
186 QVariant VariableModel::data(const QModelIndex &index, int role) const
185 {
187 {
186 if (!index.isValid()) {
188 if (!index.isValid()) {
187 return QVariant{};
189 return QVariant{};
188 }
190 }
189
191
190 if (index.row() < 0 || index.row() >= rowCount()) {
192 if (index.row() < 0 || index.row() >= rowCount()) {
191 return QVariant{};
193 return QVariant{};
192 }
194 }
193
195
194 if (role == Qt::DisplayRole) {
196 if (role == Qt::DisplayRole) {
195 if (auto variable = impl->m_Variables.at(index.row()).get()) {
197 if (auto variable = impl->m_Variables.at(index.row()).get()) {
196 switch (index.column()) {
198 switch (index.column()) {
197 case NAME_COLUMN:
199 case NAME_COLUMN:
198 return variable->name();
200 return variable->name();
199 case TSTART_COLUMN: {
201 case TSTART_COLUMN: {
200 auto range = variable->realRange();
202 auto range = variable->realRange();
201 return range != INVALID_RANGE
203 return range != INVALID_RANGE
202 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
204 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
203 : QVariant{};
205 : QVariant{};
204 }
206 }
205 case TEND_COLUMN: {
207 case TEND_COLUMN: {
206 auto range = variable->realRange();
208 auto range = variable->realRange();
207 return range != INVALID_RANGE
209 return range != INVALID_RANGE
208 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
210 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
209 : QVariant{};
211 : QVariant{};
210 }
212 }
211 case NBPOINTS_COLUMN:
213 case NBPOINTS_COLUMN:
212 return variable->nbPoints();
214 return variable->nbPoints();
213 case UNIT_COLUMN:
215 case UNIT_COLUMN:
214 return variable->metadata().value(QStringLiteral("units"));
216 return variable->metadata().value(QStringLiteral("units"));
215 case MISSION_COLUMN:
217 case MISSION_COLUMN:
216 return variable->metadata().value(QStringLiteral("mission"));
218 return variable->metadata().value(QStringLiteral("mission"));
217 case PLUGIN_COLUMN:
219 case PLUGIN_COLUMN:
218 return variable->metadata().value(QStringLiteral("plugin"));
220 return variable->metadata().value(QStringLiteral("plugin"));
219 default:
221 default:
220 // No action
222 // No action
221 break;
223 break;
222 }
224 }
223
225
224 qWarning(LOG_VariableModel())
226 qWarning(LOG_VariableModel())
225 << tr("Can't get data (unknown column %1)").arg(index.column());
227 << tr("Can't get data (unknown column %1)").arg(index.column());
226 }
228 }
227 else {
229 else {
228 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
230 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
229 }
231 }
230 }
232 }
231 else if (role == VariableRoles::ProgressRole) {
233 else if (role == VariableRoles::ProgressRole) {
232 if (auto variable = impl->m_Variables.at(index.row())) {
234 if (auto variable = impl->m_Variables.at(index.row())) {
233
235
234 auto it = impl->m_VariableToProgress.find(variable);
236 auto it = impl->m_VariableToProgress.find(variable);
235 if (it != impl->m_VariableToProgress.cend()) {
237 if (it != impl->m_VariableToProgress.cend()) {
236 return it->second;
238 return it->second;
237 }
239 }
238 }
240 }
239 }
241 }
240
242
241 return QVariant{};
243 return QVariant{};
242 }
244 }
243
245
244 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
246 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
245 {
247 {
246 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
248 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
247 return QVariant{};
249 return QVariant{};
248 }
250 }
249
251
250 if (orientation == Qt::Horizontal) {
252 if (orientation == Qt::Horizontal) {
251 auto propertiesIt = COLUMN_PROPERTIES.find(section);
253 auto propertiesIt = COLUMN_PROPERTIES.find(section);
252 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
254 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
253 // Role is either DisplayRole or SizeHintRole
255 // Role is either DisplayRole or SizeHintRole
254 return (role == Qt::DisplayRole)
256 return (role == Qt::DisplayRole)
255 ? QVariant{propertiesIt->m_Name}
257 ? QVariant{propertiesIt->m_Name}
256 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
258 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
257 }
259 }
258 else {
260 else {
259 qWarning(LOG_VariableModel())
261 qWarning(LOG_VariableModel())
260 << tr("Can't get header data (unknown column %1)").arg(section);
262 << tr("Can't get header data (unknown column %1)").arg(section);
261 }
263 }
262 }
264 }
263
265
264 return QVariant{};
266 return QVariant{};
265 }
267 }
266
268
267 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
269 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
268 {
270 {
269 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
271 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
270 }
272 }
271
273
272 Qt::DropActions VariableModel::supportedDropActions() const
274 Qt::DropActions VariableModel::supportedDropActions() const
273 {
275 {
274 return Qt::CopyAction | Qt::MoveAction;
276 return Qt::CopyAction | Qt::MoveAction;
275 }
277 }
276
278
277 Qt::DropActions VariableModel::supportedDragActions() const
279 Qt::DropActions VariableModel::supportedDragActions() const
278 {
280 {
279 return Qt::CopyAction | Qt::MoveAction;
281 return Qt::CopyAction | Qt::MoveAction;
280 }
282 }
281
283
282 QStringList VariableModel::mimeTypes() const
284 QStringList VariableModel::mimeTypes() const
283 {
285 {
284 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
286 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
285 }
287 }
286
288
287 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
289 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
288 {
290 {
289 auto mimeData = new QMimeData;
291 auto mimeData = new QMimeData;
290
292
291 QList<std::shared_ptr<Variable> > variableList;
293 QList<std::shared_ptr<Variable> > variableList;
292
294
293
295
294 SqpRange firstTimeRange;
296 SqpRange firstTimeRange;
295 for (const auto &index : indexes) {
297 for (const auto &index : indexes) {
296 if (index.column() == 0) { // only the first column
298 if (index.column() == 0) { // only the first column
297 auto variable = impl->m_Variables.at(index.row());
299 auto variable = impl->m_Variables.at(index.row());
298 if (variable.get() && index.isValid()) {
300 if (variable.get() && index.isValid()) {
299
301
300 if (variableList.isEmpty()) {
302 if (variableList.isEmpty()) {
301 // Gets the range of the first variable
303 // Gets the range of the first variable
302 firstTimeRange = std::move(variable->range());
304 firstTimeRange = std::move(variable->range());
303 }
305 }
304
306
305 variableList << variable;
307 variableList << variable;
306 }
308 }
307 }
309 }
308 }
310 }
309
311
310 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
312 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
311 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
313 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
312
314
313 if (variableList.count() == 1) {
315 if (variableList.count() == 1) {
314 // No time range MIME data if multiple variables are dragged
316 // No time range MIME data if multiple variables are dragged
315 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
317 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
316 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
318 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
317 }
319 }
318
320
319 return mimeData;
321 return mimeData;
320 }
322 }
321
323
322 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
324 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
323 int column, const QModelIndex &parent) const
325 int column, const QModelIndex &parent) const
324 {
326 {
325 // drop of a product
327 // drop of a product
326 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
328 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
327 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
329 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
328 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
330 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
329 }
331 }
330
332
331 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
333 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
332 const QModelIndex &parent)
334 const QModelIndex &parent)
333 {
335 {
334 auto dropDone = false;
336 auto dropDone = false;
335
337
336 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
338 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
337
339
338 auto productList
340 auto productList
339 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
341 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
340
342
341 for (auto metaData : productList) {
343 for (auto metaData : productList) {
342 emit requestVariable(metaData.toHash());
344 emit requestVariable(metaData.toHash());
343 }
345 }
344
346
345 dropDone = true;
347 dropDone = true;
346 }
348 }
347 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
349 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
348 auto variable = this->variable(parent.row());
350 auto variable = this->variable(parent.row());
349 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
351 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
350
352
351 emit requestVariableRangeUpdate(variable, range);
353 emit requestVariableRangeUpdate(variable, range);
352
354
353 dropDone = true;
355 dropDone = true;
354 }
356 }
355
357
356 return dropDone;
358 return dropDone;
357 }
359 }
358
360
359 void VariableModel::abortProgress(const QModelIndex &index)
361 void VariableModel::abortProgress(const QModelIndex &index)
360 {
362 {
361 if (auto variable = impl->m_Variables.at(index.row())) {
363 if (auto variable = impl->m_Variables.at(index.row())) {
362 emit abortProgessRequested(variable);
364 emit abortProgessRequested(variable);
363 }
365 }
364 }
366 }
365
367
366 void VariableModel::onVariableUpdated() noexcept
368 void VariableModel::onVariableUpdated() noexcept
367 {
369 {
368 // Finds variable that has been updated in the model
370 // Finds variable that has been updated in the model
369 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
371 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
370 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
372 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
371
373
372 if (updatedVariableIndex > -1) {
374 if (updatedVariableIndex > -1) {
373 emit dataChanged(createIndex(updatedVariableIndex, 0),
375 emit dataChanged(createIndex(updatedVariableIndex, 0),
374 createIndex(updatedVariableIndex, columnCount() - 1));
376 createIndex(updatedVariableIndex, columnCount() - 1));
375 }
377 }
376 }
378 }
377 }
379 }
378
380
379 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
381 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
380 {
382 {
381 auto begin = std::cbegin(m_Variables);
383 auto begin = std::cbegin(m_Variables);
382 auto end = std::cend(m_Variables);
384 auto end = std::cend(m_Variables);
383 auto it
385 auto it
384 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
386 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
385
387
386 if (it != end) {
388 if (it != end) {
387 // Gets the index of the variable in the model: we assume here that views have the same
389 // Gets the index of the variable in the model: we assume here that views have the same
388 // order as the model
390 // order as the model
389 return std::distance(begin, it);
391 return std::distance(begin, it);
390 }
392 }
391 else {
393 else {
392 return -1;
394 return -1;
393 }
395 }
394 }
396 }
@@ -1,24 +1,24
1 #include "DataSeriesUtils.h"
1 #include "DataSeriesUtils.h"
2
2
3 void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData,
3 void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData,
4 const DataContainer &valuesData)
4 const DataContainer &valuesData)
5 {
5 {
6 QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(),
6 QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(),
7 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
7 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
8 QVERIFY(std::equal(
8 QVERIFY(std::equal(
9 first, last, valuesData.cbegin(), valuesData.cend(),
9 first, last, valuesData.cbegin(), valuesData.cend(),
10 [](const auto &it, const auto &expectedVal) { return it.value() == expectedVal; }));
10 [](const auto &it, const auto &expectedVal) { return it.value() == expectedVal; }));
11 }
11 }
12
12
13 void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, const std::vector<DataContainer> &valuesData)
13 void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, const std::vector<DataContainer> &valuesData)
14 {
14 {
15 QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(),
15 QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(),
16 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
16 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
17 for (auto i = 0; i < valuesData.size(); ++i) {
17 for (auto i = 0u; i < valuesData.size(); ++i) {
18 auto componentData = valuesData.at(i);
18 auto componentData = valuesData.at(i);
19
19
20 QVERIFY(std::equal(
20 QVERIFY(std::equal(
21 first, last, componentData.cbegin(), componentData.cend(),
21 first, last, componentData.cbegin(), componentData.cend(),
22 [i](const auto &it, const auto &expectedVal) { return it.value(i) == expectedVal; }));
22 [i](const auto &it, const auto &expectedVal) { return it.value(i) == expectedVal; }));
23 }
23 }
24 }
24 }
@@ -1,240 +1,240
1 #include "Data/ArrayData.h"
1 #include "Data/ArrayData.h"
2 #include <QObject>
2 #include <QObject>
3 #include <QtTest>
3 #include <QtTest>
4
4
5 using DataContainer = std::vector<double>;
5 using DataContainer = std::vector<double>;
6 using Container = std::vector<DataContainer>;
6 using Container = std::vector<DataContainer>;
7 using InputData = QPair<DataContainer, int>;
7 using InputData = QPair<DataContainer, int>;
8
8
9 namespace {
9 namespace {
10
10
11 InputData flatten(const Container &container)
11 InputData flatten(const Container &container)
12 {
12 {
13 if (container.empty()) {
13 if (container.empty()) {
14 return {};
14 return {};
15 }
15 }
16
16
17 // We assume here that each component of the container have the same size
17 // We assume here that each component of the container have the same size
18 auto containerSize = container.size();
18 auto containerSize = container.size();
19 auto componentSize = container.front().size();
19 auto componentSize = container.front().size();
20
20
21 auto result = DataContainer{};
21 auto result = DataContainer{};
22 result.reserve(componentSize * containerSize);
22 result.reserve(componentSize * containerSize);
23
23
24 for (auto i = 0; i < componentSize; ++i) {
24 for (auto i = 0u; i < componentSize; ++i) {
25 for (auto j = 0; j < containerSize; ++j) {
25 for (auto j = 0u; j < containerSize; ++j) {
26 result.push_back(container.at(j).at(i));
26 result.push_back(container.at(j).at(i));
27 }
27 }
28 }
28 }
29
29
30 return {result, static_cast<int>(containerSize)};
30 return {result, static_cast<int>(containerSize)};
31 }
31 }
32
32
33 void verifyArrayData(const ArrayData<2> &arrayData, const Container &expectedData)
33 void verifyArrayData(const ArrayData<2> &arrayData, const Container &expectedData)
34 {
34 {
35 auto verifyComponent = [&arrayData](const auto &componentData, const auto &equalFun) {
35 auto verifyComponent = [&arrayData](const auto &componentData, const auto &equalFun) {
36 QVERIFY(std::equal(arrayData.cbegin(), arrayData.cend(), componentData.cbegin(),
36 QVERIFY(std::equal(arrayData.cbegin(), arrayData.cend(), componentData.cbegin(),
37 componentData.cend(),
37 componentData.cend(),
38 [&equalFun](const auto &dataSeriesIt, const auto &expectedValue) {
38 [&equalFun](const auto &dataSeriesIt, const auto &expectedValue) {
39 return equalFun(dataSeriesIt, expectedValue);
39 return equalFun(dataSeriesIt, expectedValue);
40 }));
40 }));
41 };
41 };
42
42
43 for (auto i = 0; i < expectedData.size(); ++i) {
43 for (auto i = 0u; i < expectedData.size(); ++i) {
44 verifyComponent(expectedData.at(i), [i](const auto &seriesIt, const auto &value) {
44 verifyComponent(expectedData.at(i), [i](const auto &seriesIt, const auto &value) {
45 return seriesIt.at(i) == value;
45 return seriesIt.at(i) == value;
46 });
46 });
47 }
47 }
48 }
48 }
49
49
50 } // namespace
50 } // namespace
51
51
52 class TestTwoDimArrayData : public QObject {
52 class TestTwoDimArrayData : public QObject {
53 Q_OBJECT
53 Q_OBJECT
54 private slots:
54 private slots:
55 /// Tests @sa ArrayData ctor
55 /// Tests @sa ArrayData ctor
56 void testCtor_data();
56 void testCtor_data();
57 void testCtor();
57 void testCtor();
58
58
59 /// Tests @sa ArrayData::add()
59 /// Tests @sa ArrayData::add()
60 void testAdd_data();
60 void testAdd_data();
61 void testAdd();
61 void testAdd();
62
62
63 /// Tests @sa ArrayData::clear()
63 /// Tests @sa ArrayData::clear()
64 void testClear_data();
64 void testClear_data();
65 void testClear();
65 void testClear();
66
66
67 /// Tests @sa ArrayData::size()
67 /// Tests @sa ArrayData::size()
68 void testSize_data();
68 void testSize_data();
69 void testSize();
69 void testSize();
70
70
71 /// Tests @sa ArrayData::sort()
71 /// Tests @sa ArrayData::sort()
72 void testSort_data();
72 void testSort_data();
73 void testSort();
73 void testSort();
74 };
74 };
75
75
76 void TestTwoDimArrayData::testCtor_data()
76 void TestTwoDimArrayData::testCtor_data()
77 {
77 {
78 // Test structure
78 // Test structure
79 QTest::addColumn<InputData>("inputData"); // array data's input
79 QTest::addColumn<InputData>("inputData"); // array data's input
80 QTest::addColumn<bool>("success"); // array data has been successfully constructed
80 QTest::addColumn<bool>("success"); // array data has been successfully constructed
81 QTest::addColumn<Container>("expectedData"); // expected array data (when success)
81 QTest::addColumn<Container>("expectedData"); // expected array data (when success)
82
82
83 // Test cases
83 // Test cases
84 QTest::newRow("validInput") << flatten(Container{{1., 2., 3., 4., 5.},
84 QTest::newRow("validInput") << flatten(Container{{1., 2., 3., 4., 5.},
85 {6., 7., 8., 9., 10.},
85 {6., 7., 8., 9., 10.},
86 {11., 12., 13., 14., 15.}})
86 {11., 12., 13., 14., 15.}})
87 << true << Container{{1., 2., 3., 4., 5.},
87 << true << Container{{1., 2., 3., 4., 5.},
88 {6., 7., 8., 9., 10.},
88 {6., 7., 8., 9., 10.},
89 {11., 12., 13., 14., 15.}};
89 {11., 12., 13., 14., 15.}};
90 QTest::newRow("invalidInput (invalid data size") << InputData{{1., 2., 3., 4., 5., 6., 7.}, 3}
90 QTest::newRow("invalidInput (invalid data size") << InputData{{1., 2., 3., 4., 5., 6., 7.}, 3}
91 << false << Container{{}, {}, {}};
91 << false << Container{{}, {}, {}};
92 QTest::newRow("invalidInput (less than two components")
92 QTest::newRow("invalidInput (less than two components")
93 << flatten(Container{{1., 2., 3., 4., 5.}}) << false << Container{{}, {}, {}};
93 << flatten(Container{{1., 2., 3., 4., 5.}}) << false << Container{{}, {}, {}};
94 }
94 }
95
95
96 void TestTwoDimArrayData::testCtor()
96 void TestTwoDimArrayData::testCtor()
97 {
97 {
98 QFETCH(InputData, inputData);
98 QFETCH(InputData, inputData);
99 QFETCH(bool, success);
99 QFETCH(bool, success);
100
100
101 if (success) {
101 if (success) {
102 QFETCH(Container, expectedData);
102 QFETCH(Container, expectedData);
103
103
104 ArrayData<2> arrayData{inputData.first, inputData.second};
104 ArrayData<2> arrayData{inputData.first, inputData.second};
105 verifyArrayData(arrayData, expectedData);
105 verifyArrayData(arrayData, expectedData);
106 }
106 }
107 else {
107 else {
108 QVERIFY_EXCEPTION_THROWN(ArrayData<2>(inputData.first, inputData.second),
108 QVERIFY_EXCEPTION_THROWN(ArrayData<2>(inputData.first, inputData.second),
109 std::invalid_argument);
109 std::invalid_argument);
110 }
110 }
111 }
111 }
112
112
113 void TestTwoDimArrayData::testAdd_data()
113 void TestTwoDimArrayData::testAdd_data()
114 {
114 {
115 // Test structure
115 // Test structure
116 QTest::addColumn<InputData>("inputData"); // array's data input
116 QTest::addColumn<InputData>("inputData"); // array's data input
117 QTest::addColumn<InputData>("otherData"); // array data's input to merge with
117 QTest::addColumn<InputData>("otherData"); // array data's input to merge with
118 QTest::addColumn<bool>("prepend"); // prepend or append merge
118 QTest::addColumn<bool>("prepend"); // prepend or append merge
119 QTest::addColumn<Container>("expectedData"); // expected data after merge
119 QTest::addColumn<Container>("expectedData"); // expected data after merge
120
120
121 // Test cases
121 // Test cases
122 auto inputData = flatten(
122 auto inputData = flatten(
123 Container{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}});
123 Container{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}});
124
124
125 auto vectorContainer = flatten(Container{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}});
125 auto vectorContainer = flatten(Container{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}});
126 auto tensorContainer = flatten(Container{{6., 7., 8.},
126 auto tensorContainer = flatten(Container{{6., 7., 8.},
127 {16., 17., 18.},
127 {16., 17., 18.},
128 {26., 27., 28},
128 {26., 27., 28},
129 {36., 37., 38.},
129 {36., 37., 38.},
130 {46., 47., 48.},
130 {46., 47., 48.},
131 {56., 57., 58}});
131 {56., 57., 58}});
132
132
133 QTest::newRow("appendMerge") << inputData << vectorContainer << false
133 QTest::newRow("appendMerge") << inputData << vectorContainer << false
134 << Container{{1., 2., 3., 4., 5., 6., 7., 8.},
134 << Container{{1., 2., 3., 4., 5., 6., 7., 8.},
135 {11., 12., 13., 14., 15., 16., 17., 18.},
135 {11., 12., 13., 14., 15., 16., 17., 18.},
136 {21., 22., 23., 24., 25., 26., 27., 28}};
136 {21., 22., 23., 24., 25., 26., 27., 28}};
137 QTest::newRow("prependMerge") << inputData << vectorContainer << true
137 QTest::newRow("prependMerge") << inputData << vectorContainer << true
138 << Container{{6., 7., 8., 1., 2., 3., 4., 5.},
138 << Container{{6., 7., 8., 1., 2., 3., 4., 5.},
139 {16., 17., 18., 11., 12., 13., 14., 15.},
139 {16., 17., 18., 11., 12., 13., 14., 15.},
140 {26., 27., 28, 21., 22., 23., 24., 25.}};
140 {26., 27., 28, 21., 22., 23., 24., 25.}};
141 QTest::newRow("invalidMerge") << inputData << tensorContainer << false
141 QTest::newRow("invalidMerge") << inputData << tensorContainer << false
142 << Container{{1., 2., 3., 4., 5.},
142 << Container{{1., 2., 3., 4., 5.},
143 {11., 12., 13., 14., 15.},
143 {11., 12., 13., 14., 15.},
144 {21., 22., 23., 24., 25.}};
144 {21., 22., 23., 24., 25.}};
145 }
145 }
146
146
147 void TestTwoDimArrayData::testAdd()
147 void TestTwoDimArrayData::testAdd()
148 {
148 {
149 QFETCH(InputData, inputData);
149 QFETCH(InputData, inputData);
150 QFETCH(InputData, otherData);
150 QFETCH(InputData, otherData);
151 QFETCH(bool, prepend);
151 QFETCH(bool, prepend);
152 QFETCH(Container, expectedData);
152 QFETCH(Container, expectedData);
153
153
154 ArrayData<2> arrayData{inputData.first, inputData.second};
154 ArrayData<2> arrayData{inputData.first, inputData.second};
155 ArrayData<2> other{otherData.first, otherData.second};
155 ArrayData<2> other{otherData.first, otherData.second};
156
156
157 arrayData.add(other, prepend);
157 arrayData.add(other, prepend);
158
158
159 verifyArrayData(arrayData, expectedData);
159 verifyArrayData(arrayData, expectedData);
160 }
160 }
161
161
162 void TestTwoDimArrayData::testClear_data()
162 void TestTwoDimArrayData::testClear_data()
163 {
163 {
164 // Test structure
164 // Test structure
165 QTest::addColumn<InputData>("inputData"); // array data's input
165 QTest::addColumn<InputData>("inputData"); // array data's input
166
166
167 // Test cases
167 // Test cases
168 QTest::newRow("data1") << flatten(
168 QTest::newRow("data1") << flatten(
169 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}});
169 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}});
170 }
170 }
171
171
172 void TestTwoDimArrayData::testClear()
172 void TestTwoDimArrayData::testClear()
173 {
173 {
174 QFETCH(InputData, inputData);
174 QFETCH(InputData, inputData);
175
175
176 ArrayData<2> arrayData{inputData.first, inputData.second};
176 ArrayData<2> arrayData{inputData.first, inputData.second};
177 arrayData.clear();
177 arrayData.clear();
178
178
179 auto emptyData = Container(inputData.second, DataContainer{});
179 auto emptyData = Container(inputData.second, DataContainer{});
180 verifyArrayData(arrayData, emptyData);
180 verifyArrayData(arrayData, emptyData);
181 }
181 }
182
182
183 void TestTwoDimArrayData::testSize_data()
183 void TestTwoDimArrayData::testSize_data()
184 {
184 {
185 // Test structure
185 // Test structure
186 QTest::addColumn<InputData>("inputData"); // array data's input
186 QTest::addColumn<InputData>("inputData"); // array data's input
187 QTest::addColumn<int>("expectedSize"); // expected array data size
187 QTest::addColumn<int>("expectedSize"); // expected array data size
188
188
189 // Test cases
189 // Test cases
190 QTest::newRow("data1") << flatten(Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}}) << 5;
190 QTest::newRow("data1") << flatten(Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}}) << 5;
191 QTest::newRow("data2") << flatten(Container{{1., 2., 3., 4., 5.},
191 QTest::newRow("data2") << flatten(Container{{1., 2., 3., 4., 5.},
192 {6., 7., 8., 9., 10.},
192 {6., 7., 8., 9., 10.},
193 {11., 12., 13., 14., 15.}})
193 {11., 12., 13., 14., 15.}})
194 << 5;
194 << 5;
195 }
195 }
196
196
197 void TestTwoDimArrayData::testSize()
197 void TestTwoDimArrayData::testSize()
198 {
198 {
199 QFETCH(InputData, inputData);
199 QFETCH(InputData, inputData);
200 QFETCH(int, expectedSize);
200 QFETCH(int, expectedSize);
201
201
202 ArrayData<2> arrayData{inputData.first, inputData.second};
202 ArrayData<2> arrayData{inputData.first, inputData.second};
203 QVERIFY(arrayData.size() == expectedSize);
203 QVERIFY(arrayData.size() == expectedSize);
204 }
204 }
205
205
206 void TestTwoDimArrayData::testSort_data()
206 void TestTwoDimArrayData::testSort_data()
207 {
207 {
208 // Test structure
208 // Test structure
209 QTest::addColumn<InputData>("inputData"); // array data's input
209 QTest::addColumn<InputData>("inputData"); // array data's input
210 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
210 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
211 QTest::addColumn<Container>("expectedData"); // expected data after sorting
211 QTest::addColumn<Container>("expectedData"); // expected data after sorting
212
212
213 // Test cases
213 // Test cases
214 QTest::newRow("data1")
214 QTest::newRow("data1")
215 << flatten(
215 << flatten(
216 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
216 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
217 << std::vector<int>{0, 2, 3, 1, 4}
217 << std::vector<int>{0, 2, 3, 1, 4}
218 << Container{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
218 << Container{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
219 QTest::newRow("data2")
219 QTest::newRow("data2")
220 << flatten(
220 << flatten(
221 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
221 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
222 << std::vector<int>{2, 4, 3, 0, 1}
222 << std::vector<int>{2, 4, 3, 0, 1}
223 << Container{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
223 << Container{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
224 }
224 }
225
225
226 void TestTwoDimArrayData::testSort()
226 void TestTwoDimArrayData::testSort()
227 {
227 {
228 QFETCH(InputData, inputData);
228 QFETCH(InputData, inputData);
229 QFETCH(std::vector<int>, sortPermutation);
229 QFETCH(std::vector<int>, sortPermutation);
230 QFETCH(Container, expectedData);
230 QFETCH(Container, expectedData);
231
231
232 ArrayData<2> arrayData{inputData.first, inputData.second};
232 ArrayData<2> arrayData{inputData.first, inputData.second};
233 auto sortedArrayData = arrayData.sort(sortPermutation);
233 auto sortedArrayData = arrayData.sort(sortPermutation);
234 QVERIFY(sortedArrayData != nullptr);
234 QVERIFY(sortedArrayData != nullptr);
235
235
236 verifyArrayData(*sortedArrayData, expectedData);
236 verifyArrayData(*sortedArrayData, expectedData);
237 }
237 }
238
238
239 QTEST_MAIN(TestTwoDimArrayData)
239 QTEST_MAIN(TestTwoDimArrayData)
240 #include "TestTwoDimArrayData.moc"
240 #include "TestTwoDimArrayData.moc"
@@ -1,98 +1,95
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/DataSource/DataSourceTreeWidget.h',
5 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
6 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
7 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
8 'include/SqpApplication.h',
7 'include/SqpApplication.h',
9 'include/DragAndDrop/DragDropHelper.h',
10 'include/DragAndDrop/DragDropScroller.h',
8 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
12 'include/TimeWidget/TimeWidget.h',
10 'include/TimeWidget/TimeWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
14 'include/Variable/VariableInspectorTableView.h',
15 'include/Variable/RenameVariableDialog.h',
12 'include/Variable/RenameVariableDialog.h',
16 'include/Visualization/qcustomplot.h',
13 'include/Visualization/qcustomplot.h',
17 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationGraphWidget.h',
18 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
19 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationWidget.h',
20 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
21 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
22 'include/Visualization/VisualizationDragWidget.h'
19 'include/Visualization/VisualizationDragWidget.h'
23 ]
20 ]
24
21
25 gui_ui_files = [
22 gui_ui_files = [
26 'ui/DataSource/DataSourceWidget.ui',
23 'ui/DataSource/DataSourceWidget.ui',
27 'ui/Settings/SqpSettingsDialog.ui',
24 'ui/Settings/SqpSettingsDialog.ui',
28 'ui/Settings/SqpSettingsGeneralWidget.ui',
25 'ui/Settings/SqpSettingsGeneralWidget.ui',
29 'ui/SidePane/SqpSidePane.ui',
26 'ui/SidePane/SqpSidePane.ui',
30 'ui/TimeWidget/TimeWidget.ui',
27 'ui/TimeWidget/TimeWidget.ui',
31 'ui/Variable/VariableInspectorWidget.ui',
28 'ui/Variable/VariableInspectorWidget.ui',
32 'ui/Variable/RenameVariableDialog.ui',
29 'ui/Variable/RenameVariableDialog.ui',
33 'ui/Variable/VariableMenuHeaderWidget.ui',
30 'ui/Variable/VariableMenuHeaderWidget.ui',
34 'ui/Visualization/VisualizationGraphWidget.ui',
31 'ui/Visualization/VisualizationGraphWidget.ui',
35 'ui/Visualization/VisualizationTabWidget.ui',
32 'ui/Visualization/VisualizationTabWidget.ui',
36 'ui/Visualization/VisualizationWidget.ui',
33 'ui/Visualization/VisualizationWidget.ui',
37 'ui/Visualization/VisualizationZoneWidget.ui'
34 'ui/Visualization/VisualizationZoneWidget.ui'
38 ]
35 ]
39
36
40 gui_qresources = ['resources/sqpguiresources.qrc']
37 gui_qresources = ['resources/sqpguiresources.qrc']
41
38
42 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
39 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
43 ui_files : gui_ui_files,
40 ui_files : gui_ui_files,
44 qresources : gui_qresources)
41 qresources : gui_qresources)
45
42
46 gui_sources = [
43 gui_sources = [
47 'src/SqpApplication.cpp',
44 'src/SqpApplication.cpp',
48 'src/DragAndDrop/DragDropHelper.cpp',
45 'src/DragAndDrop/DragDropHelper.cpp',
49 'src/DragAndDrop/DragDropScroller.cpp',
46 'src/DragAndDrop/DragDropScroller.cpp',
50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
47 'src/DragAndDrop/DragDropTabSwitcher.cpp',
51 'src/Common/ColorUtils.cpp',
48 'src/Common/ColorUtils.cpp',
52 'src/Common/VisualizationDef.cpp',
49 'src/Common/VisualizationDef.cpp',
53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
50 'src/DataSource/DataSourceTreeWidgetItem.cpp',
54 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
51 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
55 'src/DataSource/DataSourceWidget.cpp',
52 'src/DataSource/DataSourceWidget.cpp',
56 'src/DataSource/DataSourceTreeWidget.cpp',
53 'src/DataSource/DataSourceTreeWidget.cpp',
57 'src/Settings/SqpSettingsDialog.cpp',
54 'src/Settings/SqpSettingsDialog.cpp',
58 'src/Settings/SqpSettingsGeneralWidget.cpp',
55 'src/Settings/SqpSettingsGeneralWidget.cpp',
59 'src/SidePane/SqpSidePane.cpp',
56 'src/SidePane/SqpSidePane.cpp',
60 'src/TimeWidget/TimeWidget.cpp',
57 'src/TimeWidget/TimeWidget.cpp',
61 'src/Variable/VariableInspectorWidget.cpp',
58 'src/Variable/VariableInspectorWidget.cpp',
62 'src/Variable/VariableInspectorTableView.cpp',
59 'src/Variable/VariableInspectorTableView.cpp',
63 'src/Variable/VariableMenuHeaderWidget.cpp',
60 'src/Variable/VariableMenuHeaderWidget.cpp',
64 'src/Variable/RenameVariableDialog.cpp',
61 'src/Variable/RenameVariableDialog.cpp',
65 'src/Visualization/VisualizationGraphHelper.cpp',
62 'src/Visualization/VisualizationGraphHelper.cpp',
66 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
63 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
67 'src/Visualization/VisualizationGraphWidget.cpp',
64 'src/Visualization/VisualizationGraphWidget.cpp',
68 'src/Visualization/VisualizationTabWidget.cpp',
65 'src/Visualization/VisualizationTabWidget.cpp',
69 'src/Visualization/VisualizationWidget.cpp',
66 'src/Visualization/VisualizationWidget.cpp',
70 'src/Visualization/VisualizationZoneWidget.cpp',
67 'src/Visualization/VisualizationZoneWidget.cpp',
71 'src/Visualization/qcustomplot.cpp',
68 'src/Visualization/qcustomplot.cpp',
72 'src/Visualization/QCustomPlotSynchronizer.cpp',
69 'src/Visualization/QCustomPlotSynchronizer.cpp',
73 'src/Visualization/operations/FindVariableOperation.cpp',
70 'src/Visualization/operations/FindVariableOperation.cpp',
74 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
71 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
75 'src/Visualization/operations/MenuBuilder.cpp',
72 'src/Visualization/operations/MenuBuilder.cpp',
76 'src/Visualization/operations/RemoveVariableOperation.cpp',
73 'src/Visualization/operations/RemoveVariableOperation.cpp',
77 'src/Visualization/operations/RescaleAxeOperation.cpp',
74 'src/Visualization/operations/RescaleAxeOperation.cpp',
78 'src/Visualization/VisualizationDragDropContainer.cpp',
75 'src/Visualization/VisualizationDragDropContainer.cpp',
79 'src/Visualization/VisualizationDragWidget.cpp',
76 'src/Visualization/VisualizationDragWidget.cpp',
80 'src/Visualization/AxisRenderingUtils.cpp',
77 'src/Visualization/AxisRenderingUtils.cpp',
81 'src/Visualization/PlottablesRenderingUtils.cpp',
78 'src/Visualization/PlottablesRenderingUtils.cpp',
82 'src/Visualization/MacScrollBarStyle.cpp'
79 'src/Visualization/MacScrollBarStyle.cpp'
83 ]
80 ]
84
81
85 gui_inc = include_directories(['include'])
82 gui_inc = include_directories(['include'])
86
83
87 sciqlop_gui_lib = library('sciqlopgui',
84 sciqlop_gui_lib = library('sciqlopgui',
88 gui_sources,
85 gui_sources,
89 gui_moc_files,
86 gui_moc_files,
90 include_directories : [gui_inc],
87 include_directories : [gui_inc],
91 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
88 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
92 install : true
89 install : true
93 )
90 )
94
91
95 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
92 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
96 include_directories : gui_inc,
93 include_directories : gui_inc,
97 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
94 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
98
95
@@ -1,163 +1,163
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <DragAndDrop/DragDropHelper.h>
5 #include <DragAndDrop/DragDropHelper.h>
6 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
7 #include <QThread>
7 #include <QThread>
8 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11 #include <Variable/VariableModel.h>
11 #include <Variable/VariableModel.h>
12 #include <Visualization/VisualizationController.h>
12 #include <Visualization/VisualizationController.h>
13
13
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
15
15
16 class SqpApplication::SqpApplicationPrivate {
16 class SqpApplication::SqpApplicationPrivate {
17 public:
17 public:
18 SqpApplicationPrivate()
18 SqpApplicationPrivate()
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
20 m_NetworkController{std::make_unique<NetworkController>()},
21 m_TimeController{std::make_unique<TimeController>()},
22 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_TimeController{std::make_unique<TimeController>()},
22 m_NetworkController{std::make_unique<NetworkController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
24 m_DragDropHelper{std::make_unique<DragDropHelper>()}
24 m_DragDropHelper{std::make_unique<DragDropHelper>()}
25 {
25 {
26 // /////////////////////////////// //
26 // /////////////////////////////// //
27 // Connections between controllers //
27 // Connections between controllers //
28 // /////////////////////////////// //
28 // /////////////////////////////// //
29
29
30 // VariableController <-> DataSourceController
30 // VariableController <-> DataSourceController
31 connect(m_DataSourceController.get(),
31 connect(m_DataSourceController.get(),
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)),
33 std::shared_ptr<IDataProvider>)),
34 m_VariableController.get(),
34 m_VariableController.get(),
35 SLOT(createVariable(const QString &, const QVariantHash &,
35 SLOT(createVariable(const QString &, const QVariantHash &,
36 std::shared_ptr<IDataProvider>)));
36 std::shared_ptr<IDataProvider>)));
37
37
38 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
38 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
39 m_DataSourceController.get(), &DataSourceController::requestVariable);
39 m_DataSourceController.get(), &DataSourceController::requestVariable);
40
40
41 // VariableController <-> VisualizationController
41 // VariableController <-> VisualizationController
42 connect(m_VariableController.get(),
42 connect(m_VariableController.get(),
43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
44 m_VisualizationController.get(),
44 m_VisualizationController.get(),
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
46
46
47 connect(m_VariableController.get(),
47 connect(m_VariableController.get(),
48 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
48 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
49 m_VisualizationController.get(),
49 m_VisualizationController.get(),
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
51
51
52
52
53 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
53 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
55 m_NetworkController->moveToThread(&m_NetworkControllerThread);
55 m_NetworkController->moveToThread(&m_NetworkControllerThread);
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
57 m_VariableController->moveToThread(&m_VariableControllerThread);
57 m_VariableController->moveToThread(&m_VariableControllerThread);
58 m_VariableControllerThread.setObjectName("VariableControllerThread");
58 m_VariableControllerThread.setObjectName("VariableControllerThread");
59 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
59 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
60 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
60 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
61
61
62
62
63 // Additionnal init
63 // Additionnal init
64 m_VariableController->setTimeController(m_TimeController.get());
64 m_VariableController->setTimeController(m_TimeController.get());
65 }
65 }
66
66
67 virtual ~SqpApplicationPrivate()
67 virtual ~SqpApplicationPrivate()
68 {
68 {
69 m_DataSourceControllerThread.quit();
69 m_DataSourceControllerThread.quit();
70 m_DataSourceControllerThread.wait();
70 m_DataSourceControllerThread.wait();
71
71
72 m_NetworkControllerThread.quit();
72 m_NetworkControllerThread.quit();
73 m_NetworkControllerThread.wait();
73 m_NetworkControllerThread.wait();
74
74
75 m_VariableControllerThread.quit();
75 m_VariableControllerThread.quit();
76 m_VariableControllerThread.wait();
76 m_VariableControllerThread.wait();
77
77
78 m_VisualizationControllerThread.quit();
78 m_VisualizationControllerThread.quit();
79 m_VisualizationControllerThread.wait();
79 m_VisualizationControllerThread.wait();
80 }
80 }
81
81
82 std::unique_ptr<DataSourceController> m_DataSourceController;
82 std::unique_ptr<DataSourceController> m_DataSourceController;
83 std::unique_ptr<VariableController> m_VariableController;
83 std::unique_ptr<VariableController> m_VariableController;
84 std::unique_ptr<TimeController> m_TimeController;
84 std::unique_ptr<TimeController> m_TimeController;
85 std::unique_ptr<NetworkController> m_NetworkController;
85 std::unique_ptr<NetworkController> m_NetworkController;
86 std::unique_ptr<VisualizationController> m_VisualizationController;
86 std::unique_ptr<VisualizationController> m_VisualizationController;
87 QThread m_DataSourceControllerThread;
87 QThread m_DataSourceControllerThread;
88 QThread m_NetworkControllerThread;
88 QThread m_NetworkControllerThread;
89 QThread m_VariableControllerThread;
89 QThread m_VariableControllerThread;
90 QThread m_VisualizationControllerThread;
90 QThread m_VisualizationControllerThread;
91
91
92 std::unique_ptr<DragDropHelper> m_DragDropHelper;
92 std::unique_ptr<DragDropHelper> m_DragDropHelper;
93 };
93 };
94
94
95
95
96 SqpApplication::SqpApplication(int &argc, char **argv)
96 SqpApplication::SqpApplication(int &argc, char **argv)
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
98 {
98 {
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
100
100
101 connect(&impl->m_DataSourceControllerThread, &QThread::started,
101 connect(&impl->m_DataSourceControllerThread, &QThread::started,
102 impl->m_DataSourceController.get(), &DataSourceController::initialize);
102 impl->m_DataSourceController.get(), &DataSourceController::initialize);
103 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
103 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
104 impl->m_DataSourceController.get(), &DataSourceController::finalize);
104 impl->m_DataSourceController.get(), &DataSourceController::finalize);
105
105
106 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
106 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
107 &NetworkController::initialize);
107 &NetworkController::initialize);
108 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
108 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
109 &NetworkController::finalize);
109 &NetworkController::finalize);
110
110
111 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
111 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
112 &VariableController::initialize);
112 &VariableController::initialize);
113 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
113 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
114 &VariableController::finalize);
114 &VariableController::finalize);
115
115
116 connect(&impl->m_VisualizationControllerThread, &QThread::started,
116 connect(&impl->m_VisualizationControllerThread, &QThread::started,
117 impl->m_VisualizationController.get(), &VisualizationController::initialize);
117 impl->m_VisualizationController.get(), &VisualizationController::initialize);
118 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
118 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
119 impl->m_VisualizationController.get(), &VisualizationController::finalize);
119 impl->m_VisualizationController.get(), &VisualizationController::finalize);
120
120
121 impl->m_DataSourceControllerThread.start();
121 impl->m_DataSourceControllerThread.start();
122 impl->m_NetworkControllerThread.start();
122 impl->m_NetworkControllerThread.start();
123 impl->m_VariableControllerThread.start();
123 impl->m_VariableControllerThread.start();
124 impl->m_VisualizationControllerThread.start();
124 impl->m_VisualizationControllerThread.start();
125 }
125 }
126
126
127 SqpApplication::~SqpApplication()
127 SqpApplication::~SqpApplication()
128 {
128 {
129 }
129 }
130
130
131 void SqpApplication::initialize()
131 void SqpApplication::initialize()
132 {
132 {
133 }
133 }
134
134
135 DataSourceController &SqpApplication::dataSourceController() noexcept
135 DataSourceController &SqpApplication::dataSourceController() noexcept
136 {
136 {
137 return *impl->m_DataSourceController;
137 return *impl->m_DataSourceController;
138 }
138 }
139
139
140 NetworkController &SqpApplication::networkController() noexcept
140 NetworkController &SqpApplication::networkController() noexcept
141 {
141 {
142 return *impl->m_NetworkController;
142 return *impl->m_NetworkController;
143 }
143 }
144
144
145 TimeController &SqpApplication::timeController() noexcept
145 TimeController &SqpApplication::timeController() noexcept
146 {
146 {
147 return *impl->m_TimeController;
147 return *impl->m_TimeController;
148 }
148 }
149
149
150 VariableController &SqpApplication::variableController() noexcept
150 VariableController &SqpApplication::variableController() noexcept
151 {
151 {
152 return *impl->m_VariableController;
152 return *impl->m_VariableController;
153 }
153 }
154
154
155 VisualizationController &SqpApplication::visualizationController() noexcept
155 VisualizationController &SqpApplication::visualizationController() noexcept
156 {
156 {
157 return *impl->m_VisualizationController;
157 return *impl->m_VisualizationController;
158 }
158 }
159
159
160 DragDropHelper &SqpApplication::dragDropHelper() noexcept
160 DragDropHelper &SqpApplication::dragDropHelper() noexcept
161 {
161 {
162 return *impl->m_DragDropHelper;
162 return *impl->m_DragDropHelper;
163 }
163 }
@@ -1,216 +1,216
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
2 #include "Visualization/operations/MenuBuilder.h"
2 #include "Visualization/operations/MenuBuilder.h"
3
3
4 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9
9
10 #include <QMenu>
10 #include <QMenu>
11 #include <QStack>
11 #include <QStack>
12
12
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14
14
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 explicit GenerateVariableMenuOperationPrivate(
16 explicit GenerateVariableMenuOperationPrivate(
17 QMenu *menu, std::shared_ptr<Variable> variable,
17 QMenu *menu, std::shared_ptr<Variable> variable,
18 std::set<IVisualizationWidget *> variableContainers)
18 std::set<IVisualizationWidget *> variableContainers)
19 : m_Variable{variable},
19 : m_Variable{variable},
20 m_VariableContainers{std::move(variableContainers)},
20 m_PlotMenuBuilder{menu},
21 m_PlotMenuBuilder{menu},
21 m_UnplotMenuBuilder{menu},
22 m_UnplotMenuBuilder{menu}
22 m_VariableContainers{std::move(variableContainers)}
23 {
23 {
24 }
24 }
25
25
26 void visitRootEnter()
26 void visitRootEnter()
27 {
27 {
28 // Creates the root menu
28 // Creates the root menu
29 if (auto plotMenu
29 if (auto plotMenu
30 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
30 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
31 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
31 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
32 }
32 }
33
33
34 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
34 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
35 }
35 }
36
36
37 void visitRootLeave()
37 void visitRootLeave()
38 {
38 {
39 // Closes the root menu
39 // Closes the root menu
40 m_PlotMenuBuilder.closeMenu();
40 m_PlotMenuBuilder.closeMenu();
41 m_UnplotMenuBuilder.closeMenu();
41 m_UnplotMenuBuilder.closeMenu();
42 }
42 }
43
43
44 void visitNodeEnter(const IVisualizationWidget &container)
44 void visitNodeEnter(const IVisualizationWidget &container)
45 {
45 {
46 // Opens a new menu associated to the node
46 // Opens a new menu associated to the node
47 m_PlotMenuBuilder.addMenu(container.name());
47 m_PlotMenuBuilder.addMenu(container.name());
48 m_UnplotMenuBuilder.addMenu(container.name());
48 m_UnplotMenuBuilder.addMenu(container.name());
49 }
49 }
50
50
51 template <typename ActionFun>
51 template <typename ActionFun>
52 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
52 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
53 ActionFun actionFunction)
53 ActionFun actionFunction)
54 {
54 {
55 if (isValidContainer(container)) {
55 if (isValidContainer(container)) {
56 m_PlotMenuBuilder.addSeparator();
56 m_PlotMenuBuilder.addSeparator();
57 m_PlotMenuBuilder.addAction(actionName, actionFunction);
57 m_PlotMenuBuilder.addAction(actionName, actionFunction);
58 }
58 }
59
59
60 // Closes the menu associated to the node
60 // Closes the menu associated to the node
61 m_PlotMenuBuilder.closeMenu();
61 m_PlotMenuBuilder.closeMenu();
62 }
62 }
63
63
64 void visitNodeLeaveUnplot()
64 void visitNodeLeaveUnplot()
65 {
65 {
66 // Closes the menu associated to the node
66 // Closes the menu associated to the node
67 m_UnplotMenuBuilder.closeMenu();
67 m_UnplotMenuBuilder.closeMenu();
68 }
68 }
69
69
70 template <typename ActionFun>
70 template <typename ActionFun>
71 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
71 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
72 ActionFun actionFunction)
72 ActionFun actionFunction)
73 {
73 {
74 if (isValidContainer(container)) {
74 if (isValidContainer(container)) {
75 m_PlotMenuBuilder.addAction(actionName, actionFunction);
75 m_PlotMenuBuilder.addAction(actionName, actionFunction);
76 }
76 }
77 }
77 }
78
78
79 template <typename ActionFun>
79 template <typename ActionFun>
80 void visitLeafUnplot(IVisualizationWidget *container, const QString &actionName,
80 void visitLeafUnplot(IVisualizationWidget *container, const QString &actionName,
81 ActionFun actionFunction)
81 ActionFun actionFunction)
82 {
82 {
83 // If the container contains the variable, we generate 'unplot' action
83 // If the container contains the variable, we generate 'unplot' action
84 if (m_VariableContainers.count(container) == 1) {
84 if (m_VariableContainers.count(container) == 1) {
85 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
85 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
86 }
86 }
87 }
87 }
88
88
89 bool isValidContainer(const IVisualizationWidget &container) const noexcept
89 bool isValidContainer(const IVisualizationWidget &container) const noexcept
90 {
90 {
91 // A container is valid if it can contain the variable and if the variable is not already
91 // A container is valid if it can contain the variable and if the variable is not already
92 // contained in another container
92 // contained in another container
93 return m_Variable && m_VariableContainers.size() == 0 && container.canDrop(*m_Variable);
93 return m_Variable && m_VariableContainers.size() == 0 && container.canDrop(*m_Variable);
94 }
94 }
95
95
96 std::shared_ptr<Variable> m_Variable;
96 std::shared_ptr<Variable> m_Variable;
97 std::set<IVisualizationWidget *> m_VariableContainers;
97 std::set<IVisualizationWidget *> m_VariableContainers;
98 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
98 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
99 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
99 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
100 };
100 };
101
101
102 GenerateVariableMenuOperation::GenerateVariableMenuOperation(
102 GenerateVariableMenuOperation::GenerateVariableMenuOperation(
103 QMenu *menu, std::shared_ptr<Variable> variable,
103 QMenu *menu, std::shared_ptr<Variable> variable,
104 std::set<IVisualizationWidget *> variableContainers)
104 std::set<IVisualizationWidget *> variableContainers)
105 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
105 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
106 menu, variable, std::move(variableContainers))}
106 menu, variable, std::move(variableContainers))}
107 {
107 {
108 }
108 }
109
109
110 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
110 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
111 {
111 {
112 // VisualizationWidget is not intended to accommodate a variable
112 // VisualizationWidget is not intended to accommodate a variable
113 Q_UNUSED(widget)
113 Q_UNUSED(widget)
114
114
115 // 'Plot' and 'Unplot' menus
115 // 'Plot' and 'Unplot' menus
116 impl->visitRootEnter();
116 impl->visitRootEnter();
117 }
117 }
118
118
119 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
119 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
120 {
120 {
121 // VisualizationWidget is not intended to accommodate a variable
121 // VisualizationWidget is not intended to accommodate a variable
122 Q_UNUSED(widget)
122 Q_UNUSED(widget)
123
123
124 // 'Plot' and 'Unplot' menus
124 // 'Plot' and 'Unplot' menus
125 impl->visitRootLeave();
125 impl->visitRootLeave();
126 }
126 }
127
127
128 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
128 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
129 {
129 {
130 if (tabWidget) {
130 if (tabWidget) {
131 // 'Plot' and 'Unplot' menus
131 // 'Plot' and 'Unplot' menus
132 impl->visitNodeEnter(*tabWidget);
132 impl->visitNodeEnter(*tabWidget);
133 }
133 }
134 else {
134 else {
135 qCCritical(LOG_GenerateVariableMenuOperation(),
135 qCCritical(LOG_GenerateVariableMenuOperation(),
136 "Can't visit enter VisualizationTabWidget : the widget is null");
136 "Can't visit enter VisualizationTabWidget : the widget is null");
137 }
137 }
138 }
138 }
139
139
140 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
140 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
141 {
141 {
142 if (tabWidget) {
142 if (tabWidget) {
143 // 'Plot' menu
143 // 'Plot' menu
144 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
144 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
145 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
145 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
146 if (auto var = varW.lock()) {
146 if (auto var = varW.lock()) {
147 tabWidget->createZone(var);
147 tabWidget->createZone(var);
148 }
148 }
149 });
149 });
150
150
151 // 'Unplot' menu
151 // 'Unplot' menu
152 impl->visitNodeLeaveUnplot();
152 impl->visitNodeLeaveUnplot();
153 }
153 }
154 else {
154 else {
155 qCCritical(LOG_GenerateVariableMenuOperation(),
155 qCCritical(LOG_GenerateVariableMenuOperation(),
156 "Can't visit leave VisualizationTabWidget : the widget is null");
156 "Can't visit leave VisualizationTabWidget : the widget is null");
157 }
157 }
158 }
158 }
159
159
160 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
160 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
161 {
161 {
162 if (zoneWidget) {
162 if (zoneWidget) {
163 // 'Plot' and 'Unplot' menus
163 // 'Plot' and 'Unplot' menus
164 impl->visitNodeEnter(*zoneWidget);
164 impl->visitNodeEnter(*zoneWidget);
165 }
165 }
166 else {
166 else {
167 qCCritical(LOG_GenerateVariableMenuOperation(),
167 qCCritical(LOG_GenerateVariableMenuOperation(),
168 "Can't visit enter VisualizationZoneWidget : the widget is null");
168 "Can't visit enter VisualizationZoneWidget : the widget is null");
169 }
169 }
170 }
170 }
171
171
172 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
172 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
173 {
173 {
174 if (zoneWidget) {
174 if (zoneWidget) {
175 // 'Plot' menu
175 // 'Plot' menu
176 impl->visitNodeLeavePlot(
176 impl->visitNodeLeavePlot(
177 *zoneWidget, QObject::tr("Open in a new graph"),
177 *zoneWidget, QObject::tr("Open in a new graph"),
178 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
178 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
179 if (auto var = varW.lock()) {
179 if (auto var = varW.lock()) {
180 zoneWidget->createGraph(var);
180 zoneWidget->createGraph(var);
181 }
181 }
182 });
182 });
183
183
184 // 'Unplot' menu
184 // 'Unplot' menu
185 impl->visitNodeLeaveUnplot();
185 impl->visitNodeLeaveUnplot();
186 }
186 }
187 else {
187 else {
188 qCCritical(LOG_GenerateVariableMenuOperation(),
188 qCCritical(LOG_GenerateVariableMenuOperation(),
189 "Can't visit leave VisualizationZoneWidget : the widget is null");
189 "Can't visit leave VisualizationZoneWidget : the widget is null");
190 }
190 }
191 }
191 }
192
192
193 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
193 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
194 {
194 {
195 if (graphWidget) {
195 if (graphWidget) {
196 // 'Plot' menu
196 // 'Plot' menu
197 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
197 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
198 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
198 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
199 if (auto var = varW.lock()) {
199 if (auto var = varW.lock()) {
200 graphWidget->addVariable(var, graphWidget->graphRange());
200 graphWidget->addVariable(var, graphWidget->graphRange());
201 }
201 }
202 });
202 });
203
203
204 // 'Unplot' menu
204 // 'Unplot' menu
205 impl->visitLeafUnplot(graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
205 impl->visitLeafUnplot(graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
206 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
206 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
207 if (auto var = varW.lock()) {
207 if (auto var = varW.lock()) {
208 graphWidget->removeVariable(var);
208 graphWidget->removeVariable(var);
209 }
209 }
210 });
210 });
211 }
211 }
212 else {
212 else {
213 qCCritical(LOG_GenerateVariableMenuOperation(),
213 qCCritical(LOG_GenerateVariableMenuOperation(),
214 "Can't visit VisualizationGraphWidget : the widget is null");
214 "Can't visit VisualizationGraphWidget : the widget is null");
215 }
215 }
216 }
216 }
@@ -1,387 +1,387
1 #include "AmdaResultParserHelper.h"
1 #include "AmdaResultParserHelper.h"
2
2
3 #include <Common/DateUtils.h>
3 #include <Common/DateUtils.h>
4 #include <Common/SortUtils.h>
4 #include <Common/SortUtils.h>
5
5
6 #include <Data/ScalarSeries.h>
6 #include <Data/ScalarSeries.h>
7 #include <Data/SpectrogramSeries.h>
7 #include <Data/SpectrogramSeries.h>
8 #include <Data/Unit.h>
8 #include <Data/Unit.h>
9 #include <Data/VectorSeries.h>
9 #include <Data/VectorSeries.h>
10
10
11 #include <QtCore/QDateTime>
11 #include <QtCore/QDateTime>
12 #include <QtCore/QRegularExpression>
12 #include <QtCore/QRegularExpression>
13
13
14 #include <functional>
14 #include <functional>
15
15
16 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
16 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
17
17
18 namespace {
18 namespace {
19
19
20 // ///////// //
20 // ///////// //
21 // Constants //
21 // Constants //
22 // ///////// //
22 // ///////// //
23
23
24 /// Separator between values in a result line
24 /// Separator between values in a result line
25 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
25 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
26
26
27 /// Format for dates in result files
27 /// Format for dates in result files
28 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
28 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
29
29
30 // /////// //
30 // /////// //
31 // Methods //
31 // Methods //
32 // /////// //
32 // /////// //
33
33
34 /**
34 /**
35 * Checks that the properties contain a specific unit and that this unit is valid
35 * Checks that the properties contain a specific unit and that this unit is valid
36 * @param properties the properties map in which to search unit
36 * @param properties the properties map in which to search unit
37 * @param key the key to search for the unit in the properties
37 * @param key the key to search for the unit in the properties
38 * @param errorMessage the error message to log in case the unit is invalid
38 * @param errorMessage the error message to log in case the unit is invalid
39 * @return true if the unit is valid, false it it's invalid or was not found in the properties
39 * @return true if the unit is valid, false it it's invalid or was not found in the properties
40 */
40 */
41 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
41 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
42 {
42 {
43 auto unit = properties.value(key).value<Unit>();
43 auto unit = properties.value(key).value<Unit>();
44 if (unit.m_Name.isEmpty()) {
44 if (unit.m_Name.isEmpty()) {
45 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
45 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
46 return false;
46 return false;
47 }
47 }
48
48
49 return true;
49 return true;
50 }
50 }
51
51
52 QDateTime dateTimeFromString(const QString &stringDate) noexcept
52 QDateTime dateTimeFromString(const QString &stringDate) noexcept
53 {
53 {
54 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
54 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
55 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
55 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
56 #else
56 #else
57 return QDateTime::fromString(stringDate, DATE_FORMAT);
57 return QDateTime::fromString(stringDate, DATE_FORMAT);
58 #endif
58 #endif
59 }
59 }
60
60
61 /// Converts a string date to a double date
61 /// Converts a string date to a double date
62 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
62 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
63 double doubleDate(const QString &stringDate) noexcept
63 double doubleDate(const QString &stringDate) noexcept
64 {
64 {
65 // Format: yyyy-MM-ddThh:mm:ss.zzz
65 // Format: yyyy-MM-ddThh:mm:ss.zzz
66 auto dateTime = dateTimeFromString(stringDate);
66 auto dateTime = dateTimeFromString(stringDate);
67 dateTime.setTimeSpec(Qt::UTC);
67 dateTime.setTimeSpec(Qt::UTC);
68 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
68 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
69 : std::numeric_limits<double>::quiet_NaN();
69 : std::numeric_limits<double>::quiet_NaN();
70 }
70 }
71
71
72 /**
72 /**
73 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
73 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
74 * @param xAxisData the vector in which to store the x-axis data extracted
74 * @param xAxisData the vector in which to store the x-axis data extracted
75 * @param valuesData the vector in which to store the value extracted
75 * @param valuesData the vector in which to store the value extracted
76 * @param line the line to read to extract the property
76 * @param line the line to read to extract the property
77 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
77 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
78 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
78 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
79 * and inserted first, then the value of the first column, and finally the value of the second
79 * and inserted first, then the value of the first column, and finally the value of the second
80 * column.
80 * column.
81 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
81 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
82 * value is -1, then this value is considered as invalid and converted to NaN
82 * value is -1, then this value is considered as invalid and converted to NaN
83 */
83 */
84 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
84 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
85 const QString &line, const std::vector<int> &valuesIndexes,
85 const QString &line, const std::vector<int> &valuesIndexes,
86 double fillValue = std::numeric_limits<double>::quiet_NaN())
86 double fillValue = std::numeric_limits<double>::quiet_NaN())
87 {
87 {
88 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
88 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
89
89
90 // Checks that the line contains expected number of values + x-axis value
90 // Checks that the line contains expected number of values + x-axis value
91 if (lineData.size() == valuesIndexes.size() + 1) {
91 if (static_cast<size_t>(lineData.size()) == valuesIndexes.size() + 1) {
92 // X : the data is converted from date to double (in secs)
92 // X : the data is converted from date to double (in secs)
93 auto x = doubleDate(lineData.at(0));
93 auto x = doubleDate(lineData.at(0));
94
94
95 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
95 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
96 if (!std::isnan(x)) {
96 if (!std::isnan(x)) {
97 xAxisData.push_back(x);
97 xAxisData.push_back(x);
98
98
99 // Values
99 // Values
100 for (auto valueIndex : valuesIndexes) {
100 for (auto valueIndex : valuesIndexes) {
101 bool valueOk;
101 bool valueOk;
102 // we use valueIndex + 1 to skip column 0 (x-axis value)
102 // we use valueIndex + 1 to skip column 0 (x-axis value)
103 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
103 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
104
104
105 if (!valueOk) {
105 if (!valueOk) {
106 qCWarning(LOG_AmdaResultParserHelper())
106 qCWarning(LOG_AmdaResultParserHelper())
107 << QObject::tr(
107 << QObject::tr(
108 "Value from (line %1, column %2) is invalid and will be "
108 "Value from (line %1, column %2) is invalid and will be "
109 "converted to NaN")
109 "converted to NaN")
110 .arg(line, valueIndex);
110 .arg(line, valueIndex);
111 value = std::numeric_limits<double>::quiet_NaN();
111 value = std::numeric_limits<double>::quiet_NaN();
112 }
112 }
113
113
114 // Handles fill value
114 // Handles fill value
115 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
115 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
116 value = std::numeric_limits<double>::quiet_NaN();
116 value = std::numeric_limits<double>::quiet_NaN();
117 }
117 }
118
118
119 valuesData.push_back(value);
119 valuesData.push_back(value);
120 }
120 }
121 }
121 }
122 else {
122 else {
123 qCWarning(LOG_AmdaResultParserHelper())
123 qCWarning(LOG_AmdaResultParserHelper())
124 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
124 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
125 }
125 }
126 }
126 }
127 else {
127 else {
128 qCWarning(LOG_AmdaResultParserHelper())
128 qCWarning(LOG_AmdaResultParserHelper())
129 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
129 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
130 }
130 }
131 }
131 }
132
132
133 /**
133 /**
134 * Reads a line from the AMDA file and tries to extract a property from it
134 * Reads a line from the AMDA file and tries to extract a property from it
135 * @param properties the properties map in which to put the property extracted from the line
135 * @param properties the properties map in which to put the property extracted from the line
136 * @param key the key to which the property is added in the properties map
136 * @param key the key to which the property is added in the properties map
137 * @param line the line to read to extract the property
137 * @param line the line to read to extract the property
138 * @param regex the expected regex to extract the property. If the line matches this regex, the
138 * @param regex the expected regex to extract the property. If the line matches this regex, the
139 * property is generated
139 * property is generated
140 * @param fun the function used to generate the property
140 * @param fun the function used to generate the property
141 * @return true if the property could be generated, false if the line does not match the regex, or
141 * @return true if the property could be generated, false if the line does not match the regex, or
142 * if a property has already been generated for the key
142 * if a property has already been generated for the key
143 */
143 */
144 template <typename GeneratePropertyFun>
144 template <typename GeneratePropertyFun>
145 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
145 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
146 const QRegularExpression &regex, GeneratePropertyFun fun)
146 const QRegularExpression &regex, GeneratePropertyFun fun)
147 {
147 {
148 if (properties.contains(key)) {
148 if (properties.contains(key)) {
149 return false;
149 return false;
150 }
150 }
151
151
152 auto match = regex.match(line);
152 auto match = regex.match(line);
153 if (match.hasMatch()) {
153 if (match.hasMatch()) {
154 properties.insert(key, fun(match));
154 properties.insert(key, fun(match));
155 }
155 }
156
156
157 return match.hasMatch();
157 return match.hasMatch();
158 }
158 }
159
159
160 /**
160 /**
161 * Reads a line from the AMDA file and tries to extract a double from it
161 * Reads a line from the AMDA file and tries to extract a double from it
162 * @sa tryReadProperty()
162 * @sa tryReadProperty()
163 */
163 */
164 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
164 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
165 const QRegularExpression &regex)
165 const QRegularExpression &regex)
166 {
166 {
167 return tryReadProperty(properties, key, line, regex, [](const auto &match) {
167 return tryReadProperty(properties, key, line, regex, [](const auto &match) {
168 bool ok;
168 bool ok;
169
169
170 // If the value can't be converted to double, it is set to NaN
170 // If the value can't be converted to double, it is set to NaN
171 auto doubleValue = match.captured(1).toDouble(&ok);
171 auto doubleValue = match.captured(1).toDouble(&ok);
172 if (!ok) {
172 if (!ok) {
173 doubleValue = std::numeric_limits<double>::quiet_NaN();
173 doubleValue = std::numeric_limits<double>::quiet_NaN();
174 }
174 }
175
175
176 return QVariant::fromValue(doubleValue);
176 return QVariant::fromValue(doubleValue);
177 });
177 });
178 }
178 }
179
179
180 /**
180 /**
181 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
181 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
182 * @param sep the separator of double values in the line
182 * @param sep the separator of double values in the line
183 * @sa tryReadProperty()
183 * @sa tryReadProperty()
184 */
184 */
185 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
185 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
186 const QRegularExpression &regex, const QString &sep = QStringLiteral(","))
186 const QRegularExpression &regex, const QString &sep = QStringLiteral(","))
187 {
187 {
188 return tryReadProperty(properties, key, line, regex, [sep](const auto &match) {
188 return tryReadProperty(properties, key, line, regex, [sep](const auto &match) {
189 std::vector<double> doubleValues{};
189 std::vector<double> doubleValues{};
190
190
191 // If the value can't be converted to double, it is set to NaN
191 // If the value can't be converted to double, it is set to NaN
192 auto values = match.captured(1).split(sep);
192 auto values = match.captured(1).split(sep);
193 for (auto value : values) {
193 for (auto value : values) {
194 bool ok;
194 bool ok;
195
195
196 auto doubleValue = value.toDouble(&ok);
196 auto doubleValue = value.toDouble(&ok);
197 if (!ok) {
197 if (!ok) {
198 doubleValue = std::numeric_limits<double>::quiet_NaN();
198 doubleValue = std::numeric_limits<double>::quiet_NaN();
199 }
199 }
200
200
201 doubleValues.push_back(doubleValue);
201 doubleValues.push_back(doubleValue);
202 }
202 }
203
203
204 return QVariant::fromValue(doubleValues);
204 return QVariant::fromValue(doubleValues);
205 });
205 });
206 }
206 }
207
207
208 /**
208 /**
209 * Reads a line from the AMDA file and tries to extract a unit from it
209 * Reads a line from the AMDA file and tries to extract a unit from it
210 * @sa tryReadProperty()
210 * @sa tryReadProperty()
211 */
211 */
212 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
212 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
213 const QRegularExpression &regex, bool timeUnit = false)
213 const QRegularExpression &regex, bool timeUnit = false)
214 {
214 {
215 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
215 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
216 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
216 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
217 });
217 });
218 }
218 }
219
219
220 } // namespace
220 } // namespace
221
221
222 // ////////////////// //
222 // ////////////////// //
223 // ScalarParserHelper //
223 // ScalarParserHelper //
224 // ////////////////// //
224 // ////////////////// //
225
225
226 bool ScalarParserHelper::checkProperties()
226 bool ScalarParserHelper::checkProperties()
227 {
227 {
228 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
228 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
229 QObject::tr("The x-axis unit could not be found in the file"));
229 QObject::tr("The x-axis unit could not be found in the file"));
230 }
230 }
231
231
232 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
232 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
233 {
233 {
234 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
234 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
235 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
235 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
236 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
236 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
237 }
237 }
238
238
239 void ScalarParserHelper::readPropertyLine(const QString &line)
239 void ScalarParserHelper::readPropertyLine(const QString &line)
240 {
240 {
241 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
241 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
242 }
242 }
243
243
244 void ScalarParserHelper::readResultLine(const QString &line)
244 void ScalarParserHelper::readResultLine(const QString &line)
245 {
245 {
246 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
246 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
247 }
247 }
248
248
249 std::vector<int> ScalarParserHelper::valuesIndexes() const
249 std::vector<int> ScalarParserHelper::valuesIndexes() const
250 {
250 {
251 // Only one value to read
251 // Only one value to read
252 static auto result = std::vector<int>{0};
252 static auto result = std::vector<int>{0};
253 return result;
253 return result;
254 }
254 }
255
255
256 // /////////////////////// //
256 // /////////////////////// //
257 // SpectrogramParserHelper //
257 // SpectrogramParserHelper //
258 // /////////////////////// //
258 // /////////////////////// //
259
259
260 bool SpectrogramParserHelper::checkProperties()
260 bool SpectrogramParserHelper::checkProperties()
261 {
261 {
262 // Generates y-axis data from bands extracted (take the middle of the intervals)
262 // Generates y-axis data from bands extracted (take the middle of the intervals)
263 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
263 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
264 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
264 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
265
265
266 if (minBands.size() != maxBands.size()) {
266 if (minBands.size() != maxBands.size()) {
267 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
267 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
268 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
268 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
269 return false;
269 return false;
270 }
270 }
271
271
272 std::transform(
272 std::transform(
273 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
273 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
274 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
274 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
275
275
276 // Generates values indexes, i.e. the order in which each value will be retrieved (in ascending
276 // Generates values indexes, i.e. the order in which each value will be retrieved (in ascending
277 // order of the associated bands)
277 // order of the associated bands)
278 m_ValuesIndexes = SortUtils::sortPermutation(m_YAxisData, std::less<double>());
278 m_ValuesIndexes = SortUtils::sortPermutation(m_YAxisData, std::less<double>());
279
279
280 // Sorts y-axis data accoding to the ascending order
280 // Sorts y-axis data accoding to the ascending order
281 m_YAxisData = SortUtils::sort(m_YAxisData, 1, m_ValuesIndexes);
281 m_YAxisData = SortUtils::sort(m_YAxisData, 1, m_ValuesIndexes);
282
282
283 // Sets fill value
283 // Sets fill value
284 m_FillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
284 m_FillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
285
285
286 /// @todo: handle min/max samplings?
286 /// @todo: handle min/max samplings?
287
287
288 return true;
288 return true;
289 }
289 }
290
290
291 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
291 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
292 {
292 {
293 return std::make_shared<SpectrogramSeries>(
293 return std::make_shared<SpectrogramSeries>(
294 std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData),
294 std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData),
295 Unit{"t", true}, // x-axis unit is always a time unit
295 Unit{"t", true}, // x-axis unit is always a time unit
296 m_Properties.value(Y_AXIS_UNIT_PROPERTY).value<Unit>(),
296 m_Properties.value(Y_AXIS_UNIT_PROPERTY).value<Unit>(),
297 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
297 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
298 }
298 }
299
299
300 void SpectrogramParserHelper::readPropertyLine(const QString &line)
300 void SpectrogramParserHelper::readPropertyLine(const QString &line)
301 {
301 {
302 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
302 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
303 // property has been generated for the line), the line is treated as processed and the other
303 // property has been generated for the line), the line is treated as processed and the other
304 // functions are not called
304 // functions are not called
305 std::vector<std::function<bool()> > functions{
305 std::vector<std::function<bool()> > functions{
306 // values unit
306 // values unit
307 [&] {
307 [&] {
308 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
308 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
309 SPECTROGRAM_VALUES_UNIT_REGEX);
309 SPECTROGRAM_VALUES_UNIT_REGEX);
310 },
310 },
311 // y-axis unit
311 // y-axis unit
312 [&] {
312 [&] {
313 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
313 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
314 SPECTROGRAM_Y_AXIS_UNIT_REGEX);
314 SPECTROGRAM_Y_AXIS_UNIT_REGEX);
315 },
315 },
316 // min sampling
316 // min sampling
317 [&] {
317 [&] {
318 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
318 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
319 SPECTROGRAM_MIN_SAMPLING_REGEX);
319 SPECTROGRAM_MIN_SAMPLING_REGEX);
320 },
320 },
321 // max sampling
321 // max sampling
322 [&] {
322 [&] {
323 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
323 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
324 SPECTROGRAM_MAX_SAMPLING_REGEX);
324 SPECTROGRAM_MAX_SAMPLING_REGEX);
325 },
325 },
326 // fill value
326 // fill value
327 [&] {
327 [&] {
328 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
328 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
329 SPECTROGRAM_FILL_VALUE_REGEX);
329 SPECTROGRAM_FILL_VALUE_REGEX);
330 },
330 },
331 // min bounds of each band
331 // min bounds of each band
332 [&] {
332 [&] {
333 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
333 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
334 SPECTROGRAM_MIN_BANDS_REGEX);
334 SPECTROGRAM_MIN_BANDS_REGEX);
335 },
335 },
336 // max bounds of each band
336 // max bounds of each band
337 [&] {
337 [&] {
338 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
338 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
339 SPECTROGRAM_MAX_BANDS_REGEX);
339 SPECTROGRAM_MAX_BANDS_REGEX);
340 }};
340 }};
341
341
342 for (auto function : functions) {
342 for (auto function : functions) {
343 // Stops at the first function that is valid
343 // Stops at the first function that is valid
344 if (function()) {
344 if (function()) {
345 return;
345 return;
346 }
346 }
347 }
347 }
348 }
348 }
349
349
350 void SpectrogramParserHelper::readResultLine(const QString &line)
350 void SpectrogramParserHelper::readResultLine(const QString &line)
351 {
351 {
352 tryReadResult(m_XAxisData, m_ValuesData, line, m_ValuesIndexes, m_FillValue);
352 tryReadResult(m_XAxisData, m_ValuesData, line, m_ValuesIndexes, m_FillValue);
353 }
353 }
354
354
355 // ////////////////// //
355 // ////////////////// //
356 // VectorParserHelper //
356 // VectorParserHelper //
357 // ////////////////// //
357 // ////////////////// //
358
358
359 bool VectorParserHelper::checkProperties()
359 bool VectorParserHelper::checkProperties()
360 {
360 {
361 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
361 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
362 QObject::tr("The x-axis unit could not be found in the file"));
362 QObject::tr("The x-axis unit could not be found in the file"));
363 }
363 }
364
364
365 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
365 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
366 {
366 {
367 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
367 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
368 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
368 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
369 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
369 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
370 }
370 }
371
371
372 void VectorParserHelper::readPropertyLine(const QString &line)
372 void VectorParserHelper::readPropertyLine(const QString &line)
373 {
373 {
374 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
374 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
375 }
375 }
376
376
377 void VectorParserHelper::readResultLine(const QString &line)
377 void VectorParserHelper::readResultLine(const QString &line)
378 {
378 {
379 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
379 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
380 }
380 }
381
381
382 std::vector<int> VectorParserHelper::valuesIndexes() const
382 std::vector<int> VectorParserHelper::valuesIndexes() const
383 {
383 {
384 // 3 values to read, in order in the file (x, y, z)
384 // 3 values to read, in order in the file (x, y, z)
385 static auto result = std::vector<int>{0, 1, 2};
385 static auto result = std::vector<int>{0, 1, 2};
386 return result;
386 return result;
387 }
387 }
General Comments 0
You need to be logged in to leave comments. Login now