@@ -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 | 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 |
@@ -118,6 +119,7 FILE (GLOB_RECURSE core_SRCS | |||
|
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 |
@@ -5,6 +5,7 | |||
|
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> |
@@ -30,12 +31,13 public: | |||
|
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:: |
|
|
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>&); |
@@ -2,6 +2,7 | |||
|
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" |
@@ -60,13 +61,13 class VariableController2::VariableController2Private | |||
|
60 | 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 | 67 | QReadLocker lock{&_lock}; |
|
67 | 68 | for(const auto &var:_variables) |
|
68 | 69 | { |
|
69 |
vars. |
|
|
70 | vars.push_back(var); | |
|
70 | 71 | } |
|
71 | 72 | return vars; |
|
72 | 73 | } |
@@ -288,7 +289,7 public: | |||
|
288 | 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 | 294 | return _maps.variables(); |
|
294 | 295 | } |
@@ -331,7 +332,7 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &vari | |||
|
331 | 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 | 337 | return impl->variables(); |
|
337 | 338 | } |
@@ -345,3 +346,13 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, cons | |||
|
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