@@ -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 |
@@ -80,6 +80,7 FILE (GLOB_RECURSE core_SRCS | |||||
80 | ./include/Visualization/VisualizationController.h |
|
80 | ./include/Visualization/VisualizationController.h | |
81 | ./include/PluginManager/PluginManager.h |
|
81 | ./include/PluginManager/PluginManager.h | |
82 | ./include/Variable/VariableModel.h |
|
82 | ./include/Variable/VariableModel.h | |
|
83 | ./include/Variable/VariableModel2.h | |||
83 | ./include/Variable/VariableAcquisitionWorker.h |
|
84 | ./include/Variable/VariableAcquisitionWorker.h | |
84 | ./include/Variable/VariableCacheStrategy.h |
|
85 | ./include/Variable/VariableCacheStrategy.h | |
85 | ./include/Variable/VariableSynchronizationGroup.h |
|
86 | ./include/Variable/VariableSynchronizationGroup.h | |
@@ -118,6 +119,7 FILE (GLOB_RECURSE core_SRCS | |||||
118 | ./src/Variable/VariableController.cpp |
|
119 | ./src/Variable/VariableController.cpp | |
119 | ./src/Variable/VariableController2.cpp |
|
120 | ./src/Variable/VariableController2.cpp | |
120 | ./src/Variable/VariableModel.cpp |
|
121 | ./src/Variable/VariableModel.cpp | |
|
122 | ./src/Variable/VariableModel2.cpp | |||
121 | ./src/Variable/VariableCacheController.cpp |
|
123 | ./src/Variable/VariableCacheController.cpp | |
122 | ./src/Variable/VariableSynchronizationGroup.cpp |
|
124 | ./src/Variable/VariableSynchronizationGroup.cpp | |
123 | ./src/Variable/VariableSynchronizationGroup2.cpp |
|
125 | ./src/Variable/VariableSynchronizationGroup2.cpp |
@@ -5,6 +5,7 | |||||
5 | #include <QObject> |
|
5 | #include <QObject> | |
6 | #include <QMutexLocker> |
|
6 | #include <QMutexLocker> | |
7 | #include <QUuid> |
|
7 | #include <QUuid> | |
|
8 | #include <QByteArray> | |||
8 | #include <QItemSelectionModel> |
|
9 | #include <QItemSelectionModel> | |
9 | #include <Common/spimpl.h> |
|
10 | #include <Common/spimpl.h> | |
10 | #include <Variable/Variable.h> |
|
11 | #include <Variable/Variable.h> | |
@@ -30,12 +31,13 public: | |||||
30 | void deleteVariable(const std::shared_ptr<Variable>& variable); |
|
31 | void deleteVariable(const std::shared_ptr<Variable>& variable); | |
31 | void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r); |
|
32 | void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r); | |
32 | void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r); |
|
33 | void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r); | |
33 |
const std:: |
|
34 | const std::vector<std::shared_ptr<Variable>> variables(); | |
34 |
|
35 | |||
35 | bool isReady(const std::shared_ptr<Variable>& variable); |
|
36 | bool isReady(const std::shared_ptr<Variable>& variable); | |
36 |
|
37 | |||
37 | void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with); |
|
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 | signals: |
|
42 | signals: | |
41 | void variableAdded(const std::shared_ptr<Variable>&); |
|
43 | void variableAdded(const std::shared_ptr<Variable>&); |
@@ -2,6 +2,7 | |||||
2 | #include <QThreadPool> |
|
2 | #include <QThreadPool> | |
3 | #include <QRunnable> |
|
3 | #include <QRunnable> | |
4 | #include <QObject> |
|
4 | #include <QObject> | |
|
5 | #include <QDataStream> | |||
5 |
|
6 | |||
6 | #include "Variable/VariableController2.h" |
|
7 | #include "Variable/VariableController2.h" | |
7 | #include "Variable/VariableSynchronizationGroup2.h" |
|
8 | #include "Variable/VariableSynchronizationGroup2.h" | |
@@ -60,13 +61,13 class VariableController2::VariableController2Private | |||||
60 | return _variables[variable]; |
|
61 | return _variables[variable]; | |
61 | } |
|
62 | } | |
62 |
|
63 | |||
63 |
inline const std:: |
|
64 | inline const std::vector<std::shared_ptr<Variable>> variables() | |
64 | { |
|
65 | { | |
65 |
std:: |
|
66 | std::vector<std::shared_ptr<Variable>> vars; | |
66 | QReadLocker lock{&_lock}; |
|
67 | QReadLocker lock{&_lock}; | |
67 | for(const auto &var:_variables) |
|
68 | for(const auto &var:_variables) | |
68 | { |
|
69 | { | |
69 |
vars. |
|
70 | vars.push_back(var); | |
70 | } |
|
71 | } | |
71 | return vars; |
|
72 | return vars; | |
72 | } |
|
73 | } | |
@@ -288,7 +289,7 public: | |||||
288 | _maps.synchronize(var, with); |
|
289 | _maps.synchronize(var, with); | |
289 | } |
|
290 | } | |
290 |
|
291 | |||
291 |
inline const std:: |
|
292 | inline const std::vector<std::shared_ptr<Variable>> variables() | |
292 | { |
|
293 | { | |
293 | return _maps.variables(); |
|
294 | return _maps.variables(); | |
294 | } |
|
295 | } | |
@@ -331,7 +332,7 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &vari | |||||
331 | impl->asyncChangeRange(variable, r); |
|
332 | impl->asyncChangeRange(variable, r); | |
332 | } |
|
333 | } | |
333 |
|
334 | |||
334 |
const std:: |
|
335 | const std::vector<std::shared_ptr<Variable> > VariableController2::variables() | |
335 | { |
|
336 | { | |
336 | return impl->variables(); |
|
337 | return impl->variables(); | |
337 | } |
|
338 | } | |
@@ -345,3 +346,13 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, cons | |||||
345 | { |
|
346 | { | |
346 | impl->synchronize(var, with); |
|
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