##// END OF EJS Templates
Quick variable model copied from existing one...
jeandet -
r21:5a50815a763f
parent child
Show More
@@ -0,0 +1,62
1 #ifndef SCIQLOP_VARIABLEMODEL2_H
2 #define SCIQLOP_VARIABLEMODEL2_H
3
4 #include "CoreGlobal.h"
5
6 #include <Data/DateTimeRange.h>
7
8 #include <QAbstractTableModel>
9 #include <QLoggingCategory>
10
11 #include <Common/MetaTypes.h>
12 #include <Common/spimpl.h>
13
14
15
16 class IDataSeries;
17 class Variable;
18 class VariableController2;
19
20 /**
21 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
22 */
23 class SCIQLOP_CORE_EXPORT VariableModel2 : public QAbstractTableModel {
24 enum VariableRoles { ProgressRole = Qt::UserRole };
25 Q_OBJECT
26 std::shared_ptr<VariableController2> _variableController;
27 public:
28 explicit VariableModel2(const std::shared_ptr<VariableController2>& variableController, QObject *parent = nullptr);
29
30 // /////////////////////////// //
31 // QAbstractTableModel methods //
32 // /////////////////////////// //
33
34 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
35 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
36 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
37 virtual QVariant headerData(int section, Qt::Orientation orientation,
38 int role = Qt::DisplayRole) const override;
39 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
40
41 // ///////////////// //
42 // Drag&Drop methods //
43 // ///////////////// //
44
45 virtual Qt::DropActions supportedDropActions() const override;
46 virtual Qt::DropActions supportedDragActions() const override;
47 virtual QStringList mimeTypes() const override;
48 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
49 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
50 const QModelIndex &parent) const override;
51 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
52 const QModelIndex &parent) override;
53
54
55 signals:
56
57 private slots:
58 /// Slot called when data of a variable has been updated
59 void variableUpdated() noexcept;
60 };
61
62 #endif // SCIQLOP_VARIABLEMODEL2_H
@@ -0,0 +1,250
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController2.h>
3 #include <Variable/VariableModel2.h>
4
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
8
9 #include <Data/IDataSeries.h>
10
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
13
14 #include <QMimeData>
15 #include <QSize>
16 #include <QTimer>
17 #include <unordered_map>
18
19 namespace {
20
21 // Column indexes
22 const auto NAME_COLUMN = 0;
23 const auto TSTART_COLUMN = 1;
24 const auto TEND_COLUMN = 2;
25 const auto NBPOINTS_COLUMN = 3;
26 const auto UNIT_COLUMN = 4;
27 const auto MISSION_COLUMN = 5;
28 const auto PLUGIN_COLUMN = 6;
29 const auto NB_COLUMNS = 7;
30
31 // Column properties
32 const auto DEFAULT_HEIGHT = 25;
33 const auto DEFAULT_WIDTH = 100;
34
35 struct ColumnProperties {
36 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
37 int height = DEFAULT_HEIGHT)
38 : m_Name{name}, m_Width{width}, m_Height{height}
39 {
40 }
41
42 QString m_Name;
43 int m_Width;
44 int m_Height;
45 };
46
47 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
48 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
49 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
50 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
51 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
52
53 QString uniqueName(const QString &defaultName,
54 const std::vector<std::shared_ptr<Variable> > &variables)
55 {
56 auto forbiddenNames = std::vector<QString>(variables.size());
57 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
58 [](const auto &variable) { return variable->name(); });
59 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
60 Q_ASSERT(!uniqueName.isEmpty());
61
62 return uniqueName;
63 }
64
65 } // namespace
66
67
68
69 VariableModel2::VariableModel2(const std::shared_ptr<VariableController2> &variableController, QObject *parent)
70 : QAbstractTableModel{parent}, _variableController{variableController}
71 {
72 }
73
74
75 int VariableModel2::columnCount(const QModelIndex &parent) const
76 {
77 Q_UNUSED(parent);
78
79 return NB_COLUMNS;
80 }
81
82 int VariableModel2::rowCount(const QModelIndex &parent) const
83 {
84 Q_UNUSED(parent);
85 return static_cast<int>(_variableController->variables().size());
86 }
87
88 QVariant VariableModel2::data(const QModelIndex &index, int role) const
89 {
90 if (!index.isValid()) {
91 return QVariant{};
92 }
93
94 if (index.row() < 0 || index.row() >= rowCount()) {
95 return QVariant{};
96 }
97
98 if (role == Qt::DisplayRole) {
99 if (auto variable = _variableController->variables()[index.row()]) {
100 switch (index.column()) {
101 case NAME_COLUMN:
102 return variable->name();
103 case TSTART_COLUMN: {
104 if(auto range = variable->realRange(); range.has_value())
105 return DateUtils::dateTime(range.value().m_TStart).toString(DATETIME_FORMAT);
106 return QVariant{};
107 }
108 case TEND_COLUMN: {
109 if(auto range = variable->realRange(); range.has_value())
110 return DateUtils::dateTime(range.value().m_TEnd).toString(DATETIME_FORMAT);
111 return QVariant{};
112 }
113 case NBPOINTS_COLUMN:
114 return variable->nbPoints();
115 case UNIT_COLUMN:
116 return variable->metadata().value(QStringLiteral("units"));
117 case MISSION_COLUMN:
118 return variable->metadata().value(QStringLiteral("mission"));
119 case PLUGIN_COLUMN:
120 return variable->metadata().value(QStringLiteral("plugin"));
121 default:
122 // No action
123 break;
124 }
125 }
126 }
127 else if (role == VariableRoles::ProgressRole) {
128 return QVariant{};
129 }
130
131 return QVariant{};
132 }
133
134 QVariant VariableModel2::headerData(int section, Qt::Orientation orientation, int role) const
135 {
136 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
137 return QVariant{};
138 }
139
140 if (orientation == Qt::Horizontal) {
141 auto propertiesIt = COLUMN_PROPERTIES.find(section);
142 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
143 // Role is either DisplayRole or SizeHintRole
144 return (role == Qt::DisplayRole)
145 ? QVariant{propertiesIt->m_Name}
146 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
147 }
148 else {
149 qWarning(LOG_VariableModel())
150 << tr("Can't get header data (unknown column %1)").arg(section);
151 }
152 }
153
154 return QVariant{};
155 }
156
157 Qt::ItemFlags VariableModel2::flags(const QModelIndex &index) const
158 {
159 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
160 }
161
162 Qt::DropActions VariableModel2::supportedDropActions() const
163 {
164 return Qt::CopyAction | Qt::MoveAction;
165 }
166
167 Qt::DropActions VariableModel2::supportedDragActions() const
168 {
169 return Qt::CopyAction | Qt::MoveAction;
170 }
171
172 QStringList VariableModel2::mimeTypes() const
173 {
174 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
175 }
176
177 QMimeData *VariableModel2::mimeData(const QModelIndexList &indexes) const
178 {
179 auto mimeData = new QMimeData;
180 std::vector<std::shared_ptr<Variable> > variables;
181
182 DateTimeRange firstTimeRange;
183 for (const auto &index : indexes) {
184 if (index.column() == 0) { // only the first column
185 auto variable = _variableController->variables()[index.row()];
186 if (variable.get() && index.isValid()) {
187
188 if (variables.size()==0) {
189 // Gets the range of the first variable
190 firstTimeRange = std::move(variable->range());
191 }
192 variables.push_back(variable);
193 }
194 }
195 }
196
197 auto variablesEncodedData = _variableController->mimeData(variables);
198 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
199
200 if (variables.size() == 1) {
201 // No time range MIME data if multiple variables are dragged
202 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
203 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
204 }
205
206 return mimeData;
207 }
208
209 bool VariableModel2::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
210 int column, const QModelIndex &parent) const
211 {
212 // drop of a product
213 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
214 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
215 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
216 }
217
218 bool VariableModel2::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
219 const QModelIndex &parent)
220 {
221 auto dropDone = false;
222
223 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
224 auto productList
225 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
226
227 for (auto metaData : productList) {
228 //emit requestVariable(metaData.toHash());
229 //@TODO No idea what this does
230 }
231
232 dropDone = true;
233 }
234 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
235 auto variable = _variableController->variables()[parent.row()];
236 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
237
238 _variableController->asyncChangeRange(variable, range);
239
240 dropDone = true;
241 }
242
243 return dropDone;
244 }
245
246 void VariableModel2::variableUpdated() noexcept
247 {
248
249 }
250
@@ -1,192 +1,194
1 1 cmake_minimum_required(VERSION 3.6)
2 2 project(SciQLOPCore CXX)
3 3
4 4 OPTION (CPPCHECK "Analyzes the source code with cppcheck" OFF)
5 5 OPTION (CLANG_TIDY "Analyzes the source code with Clang Tidy" OFF)
6 6 OPTION (IWYU "Analyzes the source code with Include What You Use" OFF)
7 7
8 8 OPTION (Catalog "builds catalog API" OFF)
9 9
10 10 set(CMAKE_CXX_STANDARD 17)
11 11
12 12 set(CMAKE_AUTOMOC ON)
13 13 #https://gitlab.kitware.com/cmake/cmake/issues/15227
14 14 #set(CMAKE_AUTOUIC ON)
15 15 if(POLICY CMP0071)
16 16 cmake_policy(SET CMP0071 OLD)
17 17 endif()
18 18 set(CMAKE_AUTORCC ON)
19 19 set(CMAKE_INCLUDE_CURRENT_DIR ON)
20 20
21 21 find_package(Qt5 COMPONENTS Core Widgets Network PrintSupport Svg Test REQUIRED)
22 22
23 23 find_package(pybind11 CONFIG QUIET)
24 24 if (NOT pybind11_FOUND)
25 25 execute_process(COMMAND git submodule init external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
26 26 execute_process(COMMAND git submodule update external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
27 27 add_subdirectory(external/pybind11)
28 28 endif()
29 29
30 30 macro(declare_test testname testexe sources libraries)
31 31 add_executable(${testexe} ${sources})
32 32 target_link_libraries(${testexe} ${libraries})
33 33 add_test(NAME ${testname} COMMAND ${testexe})
34 34 endmacro(declare_test)
35 35
36 36 enable_testing()
37 37
38 38 FILE (GLOB_RECURSE core_SRCS
39 39 ./include/DataSource/DataSourceItemMergeHelper.h
40 40 ./include/DataSource/DataSourceItemAction.h
41 41 ./include/DataSource/DataSourceItem.h
42 42 ./include/DataSource/DataSourceController.h
43 43 ./include/Common/SortUtils.h
44 44 ./include/Common/spimpl.h
45 45 ./include/Common/MimeTypesDef.h
46 46 ./include/Common/MetaTypes.h
47 47 ./include/Common/StringUtils.h
48 48 ./include/Common/SignalWaiter.h
49 49 ./include/Common/DateUtils.h
50 50 ./include/Common/Numeric.h
51 51 ./include/Common/deprecate.h
52 52 ./include/Common/containers.h
53 53 ./include/Common/debug.h
54 54 ./include/Plugin/IPlugin.h
55 55 ./include/Data/ArrayDataIterator.h
56 56 ./include/Data/VariableRequest.h
57 57 ./include/Data/VectorSeries.h
58 58 ./include/Data/DateTimeRange.h
59 59 ./include/Data/DateTimeRangeHelper.h
60 60 ./include/Data/ScalarSeries.h
61 61 ./include/Data/DataSeriesMergeHelper.h
62 62 ./include/Data/DataSeries.h
63 63 ./include/Data/AcquisitionDataPacket.h
64 64 ./include/Data/DataSeriesType.h
65 65 ./include/Data/AcquisitionRequest.h
66 66 ./include/Data/SqpIterator.h
67 67 ./include/Data/ArrayData.h
68 68 ./include/Data/DataSeriesIterator.h
69 69 ./include/Data/DataSeriesUtils.h
70 70 ./include/Data/SpectrogramSeries.h
71 71 ./include/Data/Unit.h
72 72 ./include/Data/DataProviderParameters.h
73 73 ./include/Data/OptionalAxis.h
74 74 ./include/Data/IDataProvider.h
75 75 ./include/Data/IDataSeries.h
76 76 ./include/Network/NetworkController.h
77 77 ./include/Network/Downloader.h
78 78 ./include/Version.h
79 79 ./include/CoreGlobal.h
80 80 ./include/Visualization/VisualizationController.h
81 81 ./include/PluginManager/PluginManager.h
82 82 ./include/Variable/VariableModel.h
83 ./include/Variable/VariableModel2.h
83 84 ./include/Variable/VariableAcquisitionWorker.h
84 85 ./include/Variable/VariableCacheStrategy.h
85 86 ./include/Variable/VariableSynchronizationGroup.h
86 87 ./include/Variable/VariableSynchronizationGroup2.h
87 88 ./include/Variable/ProportionalCacheStrategy.h
88 89 ./include/Variable/SingleThresholdCacheStrategy.h
89 90 ./include/Variable/VariableCacheStrategyFactory.h
90 91 ./include/Variable/Variable.h
91 92 ./include/Variable/VariableCacheController.h
92 93 ./include/Variable/VariableController.h
93 94 ./include/Variable/VariableController2.h
94 95 ./include/Variable/private/VCTransaction.h
95 96 ./include/Time/TimeController.h
96 97 ./include/Settings/ISqpSettingsBindable.h
97 98 ./include/Settings/SqpSettingsDefs.h
98 99
99 100 ./src/DataSource/DataSourceItem.cpp
100 101 ./src/DataSource/DataSourceItemAction.cpp
101 102 ./src/DataSource/DataSourceItemMergeHelper.cpp
102 103 ./src/DataSource/DataSourceController.cpp
103 104 ./src/Common/DateUtils.cpp
104 105 ./src/Common/MimeTypesDef.cpp
105 106 ./src/Common/StringUtils.cpp
106 107 ./src/Common/SignalWaiter.cpp
107 108 ./src/Data/ScalarSeries.cpp
108 109 ./src/Data/DataSeriesIterator.cpp
109 110 ./src/Data/OptionalAxis.cpp
110 111 ./src/Data/ArrayDataIterator.cpp
111 112 ./src/Data/SpectrogramSeries.cpp
112 113 ./src/Data/DataSeriesUtils.cpp
113 114 ./src/Data/VectorSeries.cpp
114 115 ./src/Network/NetworkController.cpp
115 116 ./src/Network/Downloader.cpp
116 117 ./src/Visualization/VisualizationController.cpp
117 118 ./src/PluginManager/PluginManager.cpp
118 119 ./src/Variable/VariableController.cpp
119 120 ./src/Variable/VariableController2.cpp
120 121 ./src/Variable/VariableModel.cpp
122 ./src/Variable/VariableModel2.cpp
121 123 ./src/Variable/VariableCacheController.cpp
122 124 ./src/Variable/VariableSynchronizationGroup.cpp
123 125 ./src/Variable/VariableSynchronizationGroup2.cpp
124 126 ./src/Variable/Variable.cpp
125 127 ./src/Variable/VariableAcquisitionWorker.cpp
126 128 ./src/Version.cpp
127 129 ./src/Time/TimeController.cpp
128 130 ./src/Settings/SqpSettingsDefs.cpp
129 131
130 132 )
131 133
132 134
133 135 IF(Catalog)
134 136 FILE (GLOB_RECURSE core_catalog_SRCS
135 137 ./src/Catalogue/CatalogueController.cpp
136 138 ./include/Catalogue/CatalogueController.h
137 139 )
138 140 ELSE()
139 141 FILE (GLOB_RECURSE core_catalog_SRCS
140 142 )
141 143 ENDIF(Catalog)
142 144
143 145 add_definitions(-DCORE_STATIC)
144 146 #add_definitions(-DHIDE_DEPRECATED)
145 147 add_definitions(-DSCIQLOP_CRASH_ON_ERROR)
146 148
147 149 add_library(sciqlopcore ${core_SRCS} ${core_catalog_SRCS})
148 150 SET_TARGET_PROPERTIES(sciqlopcore PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
149 151
150 152 target_include_directories(sciqlopcore PUBLIC
151 153 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
152 154 $<INSTALL_INTERFACE:include/SciQLOP>
153 155 )
154 156
155 157 target_link_libraries(sciqlopcore PUBLIC
156 158 Qt5::Core
157 159 Qt5::Network
158 160 )
159 161
160 162 if(Catalog)
161 163 target_link_libraries(sciqlopcore PUBLIC
162 164 catalogs
163 165 )
164 166 endif()
165 167
166 168
167 169 pybind11_add_module(sciqlopqt src/pybind11_wrappers/QtWrappers.cpp)
168 170 target_link_libraries(sciqlopqt PUBLIC Qt5::Core)
169 171
170 172 pybind11_add_module(pysciqlopcore src/pybind11_wrappers/CoreWrappers.cpp)
171 173 target_link_libraries(pysciqlopcore PUBLIC sciqlopcore)
172 174
173 175 add_library(pysciqlop src/pybind11_wrappers/pywrappers_common.h)
174 176 target_link_libraries(pysciqlop PUBLIC Qt5::Core)
175 177 target_include_directories(pysciqlop PUBLIC
176 178 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/pybind11_wrappers/>
177 179 $<INSTALL_INTERFACE:include/SciQLOP/py_wrappers>
178 180 )
179 181
180 182 SET_PROPERTY(GLOBAL PROPERTY CORE_PYTHON_PATH ${CMAKE_CURRENT_BINARY_DIR})
181 183
182 184
183 185 install(TARGETS sciqlopcore EXPORT SciQLOPCoreConfig
184 186 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
185 187 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
186 188 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
187 189
188 190 install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SciQLOP)
189 191 install(EXPORT SciQLOPCoreConfig DESTINATION share/SciQLOPCore/cmake)
190 192 export(TARGETS sciqlopcore FILE SciQLOPCoreConfig.cmake)
191 193
192 194 add_subdirectory(tests)
@@ -1,44 +1,46
1 1 #include <memory>
2 2 #include <vector>
3 3 #include <set>
4 4 #include <QHash>
5 5 #include <QObject>
6 6 #include <QMutexLocker>
7 7 #include <QUuid>
8 #include <QByteArray>
8 9 #include <QItemSelectionModel>
9 10 #include <Common/spimpl.h>
10 11 #include <Variable/Variable.h>
11 12 //#include <Variable/VariableSynchronizationGroup.h>
12 13 #include <Variable/VariableModel.h>
13 14 #include <Data/IDataProvider.h>
14 15 #include "Data/DateTimeRange.h"
15 16
16 17 class VariableController2: public QObject
17 18 {
18 19 class VariableController2Private;
19 20 Q_OBJECT
20 21
21 22 spimpl::unique_impl_ptr<VariableController2Private> impl;
22 23
23 24 public:
24 25 explicit VariableController2();
25 26 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
26 27 const std::shared_ptr<IDataProvider>& provider,
27 28 const DateTimeRange &range);
28 29
29 30 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable);
30 31 void deleteVariable(const std::shared_ptr<Variable>& variable);
31 32 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
32 33 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
33 const std::set<std::shared_ptr<Variable>> variables();
34 const std::vector<std::shared_ptr<Variable>> variables();
34 35
35 36 bool isReady(const std::shared_ptr<Variable>& variable);
36 37
37 38 void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with);
38 39
40 QByteArray mimeData(const std::vector<std::shared_ptr<Variable>> &variables) const;
39 41
40 42 signals:
41 43 void variableAdded(const std::shared_ptr<Variable>&);
42 44 void variableDeleted(const std::shared_ptr<Variable>&);
43 45
44 46 };
@@ -1,347 +1,358
1 1 #include <QQueue>
2 2 #include <QThreadPool>
3 3 #include <QRunnable>
4 4 #include <QObject>
5 #include <QDataStream>
5 6
6 7 #include "Variable/VariableController2.h"
7 8 #include "Variable/VariableSynchronizationGroup2.h"
8 9 #include <Common/containers.h>
9 10 #include <Common/debug.h>
10 11 #include <Data/DataProviderParameters.h>
11 12 #include <Data/DateTimeRangeHelper.h>
12 13 #include <Data/DateTimeRange.h>
13 14 #include <Variable/VariableCacheStrategyFactory.h>
14 15 #include <Variable/private/VCTransaction.h>
15 16 #include <QCoreApplication>
16 17
17 18
18 19
19 20 class VariableController2::VariableController2Private
20 21 {
21 22 struct threadSafeVaraiblesMaps
22 23 {
23 24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
24 25 {
25 26 QWriteLocker lock{&_lock};
26 27 _variables[*variable] = variable;
27 28 _providers[*variable] = provider;
28 29 _synchronizationGroups[*variable] = synchronizationGroup;
29 30 }
30 31
31 32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
32 33 {
33 34 QWriteLocker lock{&_lock};
34 35 _variables.remove(*variable);
35 36 _providers.remove(*variable);
36 37 _synchronizationGroups.remove(*variable);
37 38 }
38 39
39 40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
40 41 {
41 42 QWriteLocker lock{&_lock};
42 43 if(with.has_value())
43 44 {
44 45 auto newGroup = _synchronizationGroups[*with.value()];
45 46 newGroup->addVariable(*variable);
46 47 _synchronizationGroups[*variable] = newGroup;
47 48 }
48 49 else
49 50 {
50 51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
51 52 }
52 53 }
53 54
54 55 inline std::shared_ptr<Variable> variable(QUuid variable)
55 56 {
56 57 QReadLocker lock{&_lock};
57 58 [[unlikely]]
58 59 if(!_variables.contains(variable))
59 60 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
60 61 return _variables[variable];
61 62 }
62 63
63 inline const std::set<std::shared_ptr<Variable>> variables()
64 inline const std::vector<std::shared_ptr<Variable>> variables()
64 65 {
65 std::set<std::shared_ptr<Variable>> vars;
66 std::vector<std::shared_ptr<Variable>> vars;
66 67 QReadLocker lock{&_lock};
67 68 for(const auto &var:_variables)
68 69 {
69 vars.insert(var);
70 vars.push_back(var);
70 71 }
71 72 return vars;
72 73 }
73 74
74 75 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
75 76 {
76 77 QReadLocker lock{&_lock};
77 78 [[unlikely]]
78 79 if(!_providers.contains(variable))
79 80 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
80 81 return _providers[variable];
81 82 }
82 83
83 84 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
84 85 {
85 86 QReadLocker lock{&_lock};
86 87 [[unlikely]]
87 88 if(!_synchronizationGroups.contains(variable))
88 89 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
89 90 return _synchronizationGroups[variable];
90 91 }
91 92
92 93 inline bool has(const std::shared_ptr<Variable>& variable)
93 94 {
94 95 QReadLocker lock{&_lock};
95 96 return _variables.contains(*variable);
96 97 }
97 98
98 99 private:
99 100 QMap<QUuid,std::shared_ptr<Variable>> _variables;
100 101 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
101 102 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
102 103 QReadWriteLock _lock{QReadWriteLock::Recursive};
103 104 }_maps;
104 105 QThreadPool _ThreadPool;
105 106 VCTransactionsQueues _transactions;
106 107 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
107 108
108 109 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
109 110 {
110 111 if(transaction->done())
111 112 {
112 113 _transactions.complete(group);
113 114 }
114 115 this->_processTransactions();
115 116 }
116 117 void _processTransactions()
117 118 {
118 119 auto nextTransactions = _transactions.nextTransactions();
119 120 auto pendingTransactions = _transactions.pendingTransactions();
120 121 for( auto [groupID, newTransaction] : nextTransactions)
121 122 {
122 123 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
123 124 {
124 125 _transactions.start(groupID);
125 126 auto refVar = _maps.variable(newTransaction.value()->refVar);
126 127 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
127 128 for( auto const& [ID, range] : ranges)
128 129 {
129 130 auto provider = _maps.provider(ID);
130 131 auto variable = _maps.variable(ID);
131 132 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
132 133 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
133 134 QObject::connect(exe,
134 135 &TransactionExe::transactionComplete,
135 136 [groupID=groupID,transaction=newTransaction.value(),this]()
136 137 {
137 138 this->_transactionComplete(groupID, transaction);
138 139 }
139 140 );
140 141 _ThreadPool.start(exe);
141 142 }
142 143 }
143 144 }
144 145 }
145 146
146 147 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
147 148 {
148 149 std::map<QUuid,DateTimeRange> ranges;
149 150 if(!DateTimeRangeHelper::hasnan(r))
150 151 {
151 152 auto group = _maps.group(*refVar);
152 153 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
153 154 transformation.has_value())
154 155 {
155 156 for(auto varId:group->variables())
156 157 {
157 158 auto var = _maps.variable(varId);
158 159 auto newRange = var->range().transform(transformation.value());
159 160 ranges[varId] = newRange;
160 161 }
161 162 }
162 163 else // force new range to all variables -> may be weird if more than one var in the group
163 164 // @TODO ensure that there is no side effects
164 165 {
165 166 for(auto varId:group->variables())
166 167 {
167 168 auto var = _maps.variable(varId);
168 169 ranges[varId] = r;
169 170 }
170 171 }
171 172 }
172 173 else
173 174 {
174 175 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
175 176 }
176 177 return ranges;
177 178 }
178 179
179 180 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
180 181 {
181 182 DateTimeRange newCacheRange;
182 183 std::vector<DateTimeRange> missingRanges;
183 184 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
184 185 {
185 186 newCacheRange = _cacheStrategy->computeRange(r,r);
186 187 missingRanges = {newCacheRange};
187 188 }
188 189 else
189 190 {
190 191 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
191 192 missingRanges = newCacheRange - var->cacheRange();
192 193 }
193 194 return {missingRanges,newCacheRange};
194 195 }
195 196
196 197 void _changeRange(QUuid id, DateTimeRange r)
197 198 {
198 199 _changeRange(_maps.variable(id) ,r);
199 200 }
200 201 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
201 202 {
202 203 auto provider = _maps.provider(*var);
203 204 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
204 205 std::vector<IDataSeries*> data;
205 206 for(auto range:missingRanges)
206 207 {
207 208 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
208 209 }
209 210 var->updateData(data, r, newCacheRange, true);
210 211 }
211 212 public:
212 213 VariableController2Private(QObject* parent=Q_NULLPTR)
213 214 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
214 215 {
215 216 Q_UNUSED(parent);
216 217 this->_ThreadPool.setMaxThreadCount(32);
217 218 }
218 219
219 220 /*
220 221 * This dtor has to like this even if this is ugly, because default dtor would rely on
221 222 * declaration order to destruct members and that would always lead to regressions when
222 223 * modifying class members
223 224 */
224 225 ~VariableController2Private()
225 226 {
226 227 while (this->_ThreadPool.activeThreadCount())
227 228 {
228 229 this->_ThreadPool.waitForDone(100);
229 230 }
230 231 }
231 232
232 233 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
233 234 {
234 235 auto newVar = std::make_shared<Variable>(name,metadata);
235 236 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
236 237 _maps.addVariable(newVar,std::move(provider),group);
237 238 this->_transactions.addEntry(*group);
238 239 return newVar;
239 240 }
240 241
241 242 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
242 243 {
243 244 auto newVar = variable->clone();
244 245 _maps.synchronize(newVar,std::nullopt);
245 246 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
246 247 this->_transactions.addEntry(*_maps.group(*newVar));
247 248 return newVar;
248 249 }
249 250
250 251 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
251 252 {
252 253 return _transactions.active(*_maps.group(*variable));
253 254 }
254 255
255 256 void deleteVariable(const std::shared_ptr<Variable>& variable)
256 257 {
257 258 _maps.removeVariable(variable);
258 259 }
259 260
260 261 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
261 262 {
262 263 if(!DateTimeRangeHelper::hasnan(r))
263 264 {
264 265 auto group = _maps.group(*variable);
265 266 // Just overwrite next transaction
266 267 {
267 268 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
268 269 }
269 270 _processTransactions();
270 271 }
271 272 else
272 273 {
273 274 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
274 275 }
275 276 }
276 277
277 278 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
278 279 {
279 280 asyncChangeRange(variable,r);
280 281 while (hasPendingTransactions(variable))
281 282 {
282 283 QCoreApplication::processEvents();
283 284 }
284 285 }
285 286
286 287 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
287 288 {
288 289 _maps.synchronize(var, with);
289 290 }
290 291
291 inline const std::set<std::shared_ptr<Variable>> variables()
292 inline const std::vector<std::shared_ptr<Variable>> variables()
292 293 {
293 294 return _maps.variables();
294 295 }
295 296
296 297 };
297 298
298 299 VariableController2::VariableController2()
299 300 :impl{spimpl::make_unique_impl<VariableController2Private>()}
300 301 {}
301 302
302 303 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
303 304 {
304 305 auto var = impl->createVariable(name, metadata, provider);
305 306 emit variableAdded(var);
306 307 if(!DateTimeRangeHelper::hasnan(range))
307 308 impl->changeRange(var,range);
308 309 else
309 310 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
310 311 return var;
311 312 }
312 313
313 314 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
314 315 {
315 316 return impl->cloneVariable(variable);
316 317 }
317 318
318 319 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
319 320 {
320 321 impl->deleteVariable(variable);
321 322 emit variableDeleted(variable);
322 323 }
323 324
324 325 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
325 326 {
326 327 impl->changeRange(variable, r);
327 328 }
328 329
329 330 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
330 331 {
331 332 impl->asyncChangeRange(variable, r);
332 333 }
333 334
334 const std::set<std::shared_ptr<Variable> > VariableController2::variables()
335 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
335 336 {
336 337 return impl->variables();
337 338 }
338 339
339 340 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
340 341 {
341 342 return impl->hasPendingTransactions(variable);
342 343 }
343 344
344 345 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
345 346 {
346 347 impl->synchronize(var, with);
347 348 }
349
350 QByteArray VariableController2::mimeData(const std::vector<std::shared_ptr<Variable> > &variables) const
351 {
352 auto encodedData = QByteArray{};
353 QDataStream stream{&encodedData, QIODevice::WriteOnly};
354 for (auto &var : variables) {
355 stream << var->ID().toByteArray();
356 }
357 return encodedData;
358 }
General Comments 0
You need to be logged in to leave comments. Login now