##// END OF EJS Templates
Removed bad dependency between VC and VariableModel, moved mime stuff...
jeandet -
r27:c08d1b8ad297
parent child
Show More
@@ -1,106 +1,106
1 1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 2 #define SCIQLOP_DATASOURCECONTROLLER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QObject>
8 8 #include <QUuid>
9 9
10 10 #include <Common/spimpl.h>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
13 13
14 14 class DataSourceItem;
15 15 class IDataProvider;
16 16
17 17 /**
18 18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
19 19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
20 20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
21 21 * source) then others specifics method will be able to access it. You can load a data source driver
22 22 * plugin then create a data source.
23 23 */
24 24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
25 25 Q_OBJECT
26 26 public:
27 27 explicit DataSourceController(QObject *parent = 0);
28 28 virtual ~DataSourceController();
29 29
30 30 /**
31 31 * Registers a data source. The method delivers a unique id that can be used afterwards to
32 32 * access to the data source properties (structure, connection parameters, data provider, etc.)
33 33 * @param dataSourceName the name of the data source
34 34 * @return the unique id with which the data source has been registered
35 35 */
36 36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
37 37
38 38 /**
39 39 * Sets the structure of a data source. The controller takes ownership of the structure.
40 40 * @param dataSourceUid the unique id with which the data source has been registered into the
41 41 * controller. If it is invalid, the method has no effect.
42 42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
43 43 * @sa registerDataSource()
44 44 */
45 45 void setDataSourceItem(const QUuid &dataSourceUid,
46 46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
47 47
48 48 /**
49 49 * Sets the data provider used to retrieve data from of a data source. The controller takes
50 50 * ownership of the provider.
51 51 * @param dataSourceUid the unique id with which the data source has been registered into the
52 52 * controller. If it is invalid, the method has no effect.
53 53 * @param dataProvider the provider of the data source
54 54 * @sa registerDataSource()
55 55 */
56 56 void setDataProvider(const QUuid &dataSourceUid,
57 57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
58 58
59 59 /**
60 60 * Loads an item (product) as a variable in SciQlop
61 61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
62 62 * the data provider associated to the data source, and pass it to for the variable creation
63 63 * @param productItem the item to load
64 64 */
65 65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
66 66
67 67 /// Returns the MIME data associated to a list of product meta data
68 68 static QByteArray mimeDataForProductsData(const QVariantList &productsData);
69 69
70 70 /// Returns the list of meta data contained in a MIME data
71 71 static QVariantList productsDataForMimeData(const QByteArray &mimeData);
72 72
73 73 public slots:
74 74 /// Manage init/end of the controller
75 75 void initialize();
76 76 void finalize();
77 77
78 78 /// Request the creation of a variable from the ID_DATA_KEY of a product
79 79 void requestVariableFromProductIdKey(const QString &datasourceIdKey);
80 80
81 81 /// Request the creation of a variable from metadata of a product
82 82 void requestVariable(const QVariantHash &productData);
83 83
84 84 signals:
85 85 /// Signal emitted when a structure has been set for a data source
86 86 void dataSourceItemSet(DataSourceItem *dataSourceItem);
87 87
88 88 /**
89 89 * Signal emitted when a variable creation is asked for a product
90 90 * @param variableName the name of the variable
91 91 * @param variableMetadata the metadata of the variable
92 92 * @param variableProvider the provider that will be used to retrieve the data of the variable
93 93 * (can be null)
94 94 */
95 void variableCreationRequested(const QString &variableName,
95 void createVariable(const QString &variableName,
96 96 const QVariantHash &variableMetadata,
97 97 std::shared_ptr<IDataProvider> variableProvider);
98 98
99 99 private:
100 100 void waitForFinish();
101 101
102 102 class DataSourceControllerPrivate;
103 103 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
104 104 };
105 105
106 106 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,110 +1,135
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 4 #include <optional>
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QObject>
8 8 #include <QUuid>
9 9 #include <QReadWriteLock>
10 #include <QDataStream>
10 11
11 12 #include "CoreGlobal.h"
12 13 #include <Data/DataSeriesIterator.h>
13 14 #include <Data/DataSeriesType.h>
14 15 #include <Data/DateTimeRange.h>
15 16
16 17
17 18 #include <Common/deprecate.h>
18 19 #include <Common/MetaTypes.h>
19 20 #include <Common/spimpl.h>
20 21
21 22 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
22 23
23 24 class IDataSeries;
24 25 class QString;
25 26
26 27 /**
27 28 * @brief The Variable class represents a variable in SciQlop.
28 29 */
29 30 class SCIQLOP_CORE_EXPORT Variable : public QObject {
30 31
31 32 Q_OBJECT
32 33
33 34 public:
34 35 explicit Variable(const QString &name, const QVariantHash &metadata = {});
35 36
36 37 /// Copy ctor
37 38 explicit Variable(const Variable &other);
38 39
39 40 std::shared_ptr<Variable> clone() const;
40 41
41 42 QString name() const noexcept;
42 43 void setName(const QString &name) noexcept;
43 44 DateTimeRange range() const noexcept;
44 45 void setRange(const DateTimeRange &range, bool notify=false) noexcept;
45 46 DateTimeRange cacheRange() const noexcept;
46 47 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
47 48
48 49 /// @return the number of points hold by the variable. The number of points is updated each time
49 50 /// the data series changes
50 51 unsigned int nbPoints() const noexcept;
51 52
52 53 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
53 54 /// series between the range of the variable. The real range is updated each time the variable
54 55 /// range or the data series changed
55 56 /// @return the real range, invalid range if the data series is null or empty
56 57 /// @sa setDataSeries()
57 58 /// @sa setRange()
58 59 std::optional<DateTimeRange> realRange() const noexcept;
59 60
60 61 /// @return the data of the variable, nullptr if there is no data
61 62 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
62 63
63 64 /// @return the type of data that the variable holds
64 65 DataSeriesType type() const noexcept;
65 66
66 67 QVariantHash metadata() const noexcept;
67 68
68 69 void updateData(const std::vector<IDataSeries*>& dataSeries,
69 70 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
70 71 bool notify=true);
71 72
73 static QByteArray mimeData(const std::vector<std::shared_ptr<Variable> > &variables)
74 {
75 auto encodedData = QByteArray{};
76 QDataStream stream{&encodedData, QIODevice::WriteOnly};
77 for (auto &var : variables) {
78 stream << var->ID().toByteArray();
79 }
80 return encodedData;
81 }
82
83 static std::vector<QUuid> variablesIDs(QByteArray mimeData)
84 {
85 std::vector<QUuid> variables;
86 QDataStream stream{mimeData};
87
88 QVariantList ids;
89 stream >> ids;
90
91 for (const auto& id : ids) {
92 variables.emplace_back (id.toByteArray());
93 }
94 return variables;
95 }
96
72 97 DEPRECATE(
73 98
74 99 bool contains(const DateTimeRange &range) const noexcept;
75 100 bool intersect(const DateTimeRange &range) const noexcept;
76 101 bool isInside(const DateTimeRange &range) const noexcept;
77 102
78 103 bool cacheContains(const DateTimeRange &range) const noexcept;
79 104 bool cacheIntersect(const DateTimeRange &range) const noexcept;
80 105 bool cacheIsInside(const DateTimeRange &range) const noexcept;
81 106 QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &range) const noexcept;
82 107 QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &range) const noexcept;
83 108 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
84 109 static QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &oldRange,
85 110 const DateTimeRange &nextRange);
86 111
87 112 static QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &oldRange,
88 113 const DateTimeRange &nextRange);
89 114 )
90 115
91 116 operator QUuid() {return _uuid;}
92 117 QUuid ID(){return _uuid;}
93 118 signals:
94 119 void updated();
95 120 DEPRECATE(
96 121 /// Signal emitted when when the data series of the variable is loaded for the first time
97 122 void dataInitialized();
98 123 )
99 124 private:
100 125 class VariablePrivate;
101 126 spimpl::unique_impl_ptr<VariablePrivate> impl;
102 127 QUuid _uuid;
103 128 QReadWriteLock m_lock;
104 129 };
105 130
106 131 // Required for using shared_ptr in signals/slots
107 132 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
108 133 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
109 134
110 135 #endif // SCIQLOP_VARIABLE_H
@@ -1,54 +1,52
1 1 #ifndef VARIABLECONTROLLER2_H
2 2 #define VARIABLECONTROLLER2_H
3 3 #include <memory>
4 4 #include <vector>
5 5 #include <set>
6 6 #include <QHash>
7 7 #include <QObject>
8 8 #include <QMutexLocker>
9 9 #include <QUuid>
10 10 #include <QByteArray>
11 11 #include <QItemSelectionModel>
12 12 #include <Common/spimpl.h>
13 13 #include <Variable/Variable.h>
14 14 #include <Data/IDataProvider.h>
15 15 #include "Data/DateTimeRange.h"
16 16
17 17 class VariableController2: public QObject
18 18 {
19 19 class VariableController2Private;
20 20 Q_OBJECT
21 21
22 22 spimpl::unique_impl_ptr<VariableController2Private> impl;
23 23
24 24 public:
25 25 explicit VariableController2();
26 26 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
27 27 const std::shared_ptr<IDataProvider>& provider,
28 28 const DateTimeRange &range);
29 29
30 30 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable);
31 31 void deleteVariable(const std::shared_ptr<Variable>& variable);
32 32 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
33 33 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
34 34 const std::vector<std::shared_ptr<Variable>> variables();
35 35
36 36 bool isReady(const std::shared_ptr<Variable>& variable);
37 37
38 38 void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with);
39 39
40 //This should be somewhere else VC has nothing to do with MIMEData
41 QByteArray mimeData(const std::vector<std::shared_ptr<Variable>> &variables) const;
42 const std::vector<std::shared_ptr<Variable>> variables(QByteArray mimeData);
40 const std::vector<std::shared_ptr<Variable>> variables(const std::vector<QUuid>& ids);
43 41
44 42 const std::shared_ptr<Variable>& operator[] (int index) const;
45 43 std::shared_ptr<Variable> operator[] (int index);
46 44
47 45
48 46 signals:
49 47 void variableAdded(const std::shared_ptr<Variable>&);
50 48 void variableDeleted(const std::shared_ptr<Variable>&);
51 49
52 50 };
53 51
54 52 #endif //VARIABLECONTROLLER2_H
@@ -1,63 +1,66
1 1 #ifndef SCIQLOP_VARIABLEMODEL2_H
2 2 #define SCIQLOP_VARIABLEMODEL2_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DateTimeRange.h>
7 7
8 8 #include <QAbstractTableModel>
9 9 #include <QLoggingCategory>
10 10
11 11 #include <Common/MetaTypes.h>
12 12 #include <Common/spimpl.h>
13 13
14 14
15 15
16 16 class IDataSeries;
17 17 class Variable;
18 18 class VariableController2;
19 19
20 20 enum VariableRoles { ProgressRole = Qt::UserRole };
21 21
22 22 /**
23 23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 24 */
25 25 class SCIQLOP_CORE_EXPORT VariableModel2 : public QAbstractTableModel {
26 26 Q_OBJECT
27 std::shared_ptr<VariableController2> _variableController;
27 // read only mirror of VariableController2 content
28 std::vector<std::shared_ptr<Variable>> _variables;
28 29 public:
29 explicit VariableModel2(const std::shared_ptr<VariableController2>& variableController, QObject *parent = nullptr);
30 explicit VariableModel2(QObject *parent = nullptr);
30 31
31 32 // /////////////////////////// //
32 33 // QAbstractTableModel methods //
33 34 // /////////////////////////// //
34 35
35 36 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
36 37 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
37 38 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
38 39 virtual QVariant headerData(int section, Qt::Orientation orientation,
39 40 int role = Qt::DisplayRole) const override;
40 41 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
41 42
42 43 // ///////////////// //
43 44 // Drag&Drop methods //
44 45 // ///////////////// //
45 46
46 47 virtual Qt::DropActions supportedDropActions() const override;
47 48 virtual Qt::DropActions supportedDragActions() const override;
48 49 virtual QStringList mimeTypes() const override;
49 50 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
50 51 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
51 52 const QModelIndex &parent) const override;
52 53 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
53 54 const QModelIndex &parent) override;
54 55
55
56 56 signals:
57
58 private slots:
57 void createVariable(const QVariantHash &productData);
58 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
59 public slots:
59 60 /// Slot called when data of a variable has been updated
60 61 void variableUpdated() noexcept;
62 void variableAdded(const std::shared_ptr<Variable>&);
63 void variableDeleted(const std::shared_ptr<Variable>&);
61 64 };
62 65
63 66 #endif // SCIQLOP_VARIABLEMODEL2_H
@@ -1,197 +1,197
1 1 #include "DataSource/DataSourceController.h"
2 2 #include "DataSource/DataSourceItem.h"
3 3
4 4 #include <Data/IDataProvider.h>
5 5
6 6 #include <QMutex>
7 7 #include <QThread>
8 8
9 9 #include <QDataStream>
10 10 #include <QDir>
11 11 #include <QStandardPaths>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
14 14
15 15 class DataSourceController::DataSourceControllerPrivate {
16 16 public:
17 17 QMutex m_WorkingMutex;
18 18 /// Data sources registered
19 19 QHash<QUuid, QString> m_DataSources;
20 20 /// Data sources structures
21 21 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
22 22 /// Data providers registered
23 23 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
24 24 /// continue to live without necessarily the data source controller
25 25 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
26 26
27 27 // Search for the first datasource item matching the specified data
28 28 DataSourceItem *findDataSourceItem(const QVariantHash &data)
29 29 {
30 30 DataSourceItem *sourceItem = nullptr;
31 31 for (const auto &item : m_DataSourceItems) {
32 32 sourceItem = item.second->findItem(data, true);
33 33 if (sourceItem) {
34 34 break;
35 35 }
36 36 }
37 37
38 38 return sourceItem;
39 39 }
40 40
41 41 // Search for the first datasource item matching the specified ID_DATA_KEY
42 42 DataSourceItem *findDataSourceItem(const QString &datasourceIdKey)
43 43 {
44 44 DataSourceItem *sourceItem = nullptr;
45 45 for (const auto &item : m_DataSourceItems) {
46 46 sourceItem = item.second->findItem(datasourceIdKey, true);
47 47 if (sourceItem) {
48 48 break;
49 49 }
50 50 }
51 51
52 52 return sourceItem;
53 53 }
54 54 };
55 55
56 56 DataSourceController::DataSourceController(QObject *parent)
57 57 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
58 58 {
59 59 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
60 60 << QThread::currentThread();
61 61 }
62 62
63 63 DataSourceController::~DataSourceController()
64 64 {
65 65 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
66 66 << QThread::currentThread();
67 67 this->waitForFinish();
68 68 }
69 69
70 70 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
71 71 {
72 72 auto dataSourceUid = QUuid::createUuid();
73 73 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
74 74
75 75 return dataSourceUid;
76 76 }
77 77
78 78 void DataSourceController::setDataSourceItem(
79 79 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
80 80 {
81 81 if (!dataSourceItem) {
82 82 qCWarning(LOG_DataSourceController())
83 83 << tr("Data source item can't be registered (null item)");
84 84 return;
85 85 }
86 86
87 87 if (impl->m_DataSources.contains(dataSourceUid)) {
88 88 // The data provider is implicitly converted to a shared_ptr
89 89 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
90 90
91 91 // Retrieves the data source item to emit the signal with it
92 92 auto it = impl->m_DataSourceItems.find(dataSourceUid);
93 93 if (it != impl->m_DataSourceItems.end()) {
94 94 emit dataSourceItemSet(it->second.get());
95 95 }
96 96 }
97 97 else {
98 98 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
99 99 "data source has been registered with the uid")
100 100 .arg(dataSourceUid.toString());
101 101 }
102 102 }
103 103
104 104 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
105 105 std::unique_ptr<IDataProvider> dataProvider) noexcept
106 106 {
107 107 if (impl->m_DataSources.contains(dataSourceUid)) {
108 108 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
109 109 }
110 110 else {
111 111 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
112 112 "source has been registered with the uid")
113 113 .arg(dataSourceUid.toString());
114 114 }
115 115 }
116 116
117 117 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
118 118 const DataSourceItem &productItem) noexcept
119 119 {
120 120 if (productItem.type() == DataSourceItemType::PRODUCT
121 121 || productItem.type() == DataSourceItemType::COMPONENT) {
122 122 /// Retrieves the data provider of the data source (if any)
123 123 auto it = impl->m_DataProviders.find(dataSourceUid);
124 124 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
125 125
126 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
126 emit createVariable(productItem.name(), productItem.data(), dataProvider);
127 127 }
128 128 else {
129 129 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
130 130 }
131 131 }
132 132
133 133 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
134 134 {
135 135 QByteArray encodedData;
136 136 QDataStream stream{&encodedData, QIODevice::WriteOnly};
137 137
138 138 stream << productsData;
139 139
140 140 return encodedData;
141 141 }
142 142
143 143 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
144 144 {
145 145 QDataStream stream{mimeData};
146 146
147 147 QVariantList productList;
148 148 stream >> productList;
149 149
150 150 return productList;
151 151 }
152 152
153 153 void DataSourceController::initialize()
154 154 {
155 155 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
156 156 << QThread::currentThread();
157 157 impl->m_WorkingMutex.lock();
158 158 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
159 159 }
160 160
161 161 void DataSourceController::finalize()
162 162 {
163 163 impl->m_WorkingMutex.unlock();
164 164 }
165 165
166 166 void DataSourceController::requestVariableFromProductIdKey(const QString &datasourceIdKey)
167 167 {
168 168 auto sourceItem = impl->findDataSourceItem(datasourceIdKey);
169 169
170 170 if (sourceItem) {
171 171 auto sourceName = sourceItem->rootItem().name();
172 172 auto sourceId = impl->m_DataSources.key(sourceName);
173 173 loadProductItem(sourceId, *sourceItem);
174 174 }
175 175 else {
176 176 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
177 177 }
178 178 }
179 179
180 180 void DataSourceController::requestVariable(const QVariantHash &productData)
181 181 {
182 182 auto sourceItem = impl->findDataSourceItem(productData);
183 183
184 184 if (sourceItem) {
185 185 auto sourceName = sourceItem->rootItem().name();
186 186 auto sourceId = impl->m_DataSources.key(sourceName);
187 187 loadProductItem(sourceId, *sourceItem);
188 188 }
189 189 else {
190 190 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
191 191 }
192 192 }
193 193
194 194 void DataSourceController::waitForFinish()
195 195 {
196 196 QMutexLocker locker{&impl->m_WorkingMutex};
197 197 }
@@ -1,403 +1,392
1 1 #include <QQueue>
2 2 #include <QThreadPool>
3 3 #include <QRunnable>
4 4 #include <QObject>
5 5 #include <QDataStream>
6 6
7 7 #include "Variable/VariableController2.h"
8 8 #include "Variable/VariableSynchronizationGroup2.h"
9 9 #include <Common/containers.h>
10 10 #include <Common/debug.h>
11 11 #include <Data/DataProviderParameters.h>
12 12 #include <Data/DateTimeRangeHelper.h>
13 13 #include <Data/DateTimeRange.h>
14 14 #include <Variable/VariableCacheStrategyFactory.h>
15 15 #include <Variable/private/VCTransaction.h>
16 16 #include <QCoreApplication>
17 17
18 18
19 19
20 20 class VariableController2::VariableController2Private
21 21 {
22 22 struct threadSafeVaraiblesMaps
23 23 {
24 24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
25 25 {
26 26 QWriteLocker lock{&_lock};
27 27 _variables[*variable] = variable;
28 28 _providers[*variable] = provider;
29 29 _synchronizationGroups[*variable] = synchronizationGroup;
30 30 }
31 31
32 32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
33 33 {
34 34 QWriteLocker lock{&_lock};
35 _variables.remove(*variable);
35 _variables.erase(*variable);
36 36 _providers.remove(*variable);
37 37 _synchronizationGroups.remove(*variable);
38 38 }
39 39
40 40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
41 41 {
42 42 QWriteLocker lock{&_lock};
43 43 if(with.has_value())
44 44 {
45 45 auto newGroup = _synchronizationGroups[*with.value()];
46 46 newGroup->addVariable(*variable);
47 47 _synchronizationGroups[*variable] = newGroup;
48 48 }
49 49 else
50 50 {
51 51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
52 52 }
53 53 }
54 54
55 55 inline std::shared_ptr<Variable> variable(QUuid variable)
56 56 {
57 57 QReadLocker lock{&_lock};
58 auto it = _variables.find(variable);
58 59 [[unlikely]]
59 if(!_variables.contains(variable))
60 if(it==_variables.end())
60 61 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
61 return _variables[variable];
62 return (*it).second;
62 63 }
63 64
64 65 inline std::shared_ptr<Variable> variable(int index)
65 66 {
66 67 QReadLocker lock{&_lock};
67 68 [[unlikely]]
68 69 if(!_variables.size() > index)
69 70 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
70 return _variables.values()[index];
71 auto it = _variables.cbegin();
72 while (index!=0) {
73 index-=1;
74 it++;
75 }
76 return (*it).second;
71 77 }
72 78
73 79 inline const std::vector<std::shared_ptr<Variable>> variables()
74 80 {
75 81 std::vector<std::shared_ptr<Variable>> vars;
76 82 QReadLocker lock{&_lock};
77 for(const auto &var:_variables)
83 for(const auto&[id, var]:_variables)
78 84 {
79 85 vars.push_back(var);
80 86 }
81 87 return vars;
82 88 }
83 89
84 90 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
85 91 {
86 92 QReadLocker lock{&_lock};
87 93 [[unlikely]]
88 94 if(!_providers.contains(variable))
89 95 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
90 96 return _providers[variable];
91 97 }
92 98
93 99 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
94 100 {
95 101 QReadLocker lock{&_lock};
96 102 [[unlikely]]
97 103 if(!_synchronizationGroups.contains(variable))
98 104 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
99 105 return _synchronizationGroups[variable];
100 106 }
101 107
102 108 inline bool has(const std::shared_ptr<Variable>& variable)
103 109 {
104 110 QReadLocker lock{&_lock};
105 return _variables.contains(*variable);
111 return _variables.find(*variable)==_variables.end();
106 112 }
107 113
108 114 private:
109 QMap<QUuid,std::shared_ptr<Variable>> _variables;
115 std::map<QUuid,std::shared_ptr<Variable>> _variables;
110 116 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
111 117 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
112 118 QReadWriteLock _lock{QReadWriteLock::Recursive};
113 119 }_maps;
114 120 QThreadPool _ThreadPool;
115 121 VCTransactionsQueues _transactions;
116 122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
117 123
118 124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
119 125 {
120 126 if(transaction->done())
121 127 {
122 128 _transactions.complete(group);
123 129 }
124 130 this->_processTransactions();
125 131 }
126 132 void _processTransactions()
127 133 {
128 134 auto nextTransactions = _transactions.nextTransactions();
129 135 auto pendingTransactions = _transactions.pendingTransactions();
130 136 for( auto [groupID, newTransaction] : nextTransactions)
131 137 {
132 138 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
133 139 {
134 140 _transactions.start(groupID);
135 141 auto refVar = _maps.variable(newTransaction.value()->refVar);
136 142 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
137 143 for( auto const& [ID, range] : ranges)
138 144 {
139 145 auto provider = _maps.provider(ID);
140 146 auto variable = _maps.variable(ID);
141 147 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
142 148 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
143 149 QObject::connect(exe,
144 150 &TransactionExe::transactionComplete,
145 151 [groupID=groupID,transaction=newTransaction.value(),this]()
146 152 {
147 153 this->_transactionComplete(groupID, transaction);
148 154 }
149 155 );
150 156 _ThreadPool.start(exe);
151 157 }
152 158 }
153 159 }
154 160 }
155 161
156 162 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
157 163 {
158 164 std::map<QUuid,DateTimeRange> ranges;
159 165 if(!DateTimeRangeHelper::hasnan(r))
160 166 {
161 167 auto group = _maps.group(*refVar);
162 168 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
163 169 transformation.has_value())
164 170 {
165 171 for(auto varId:group->variables())
166 172 {
167 173 auto var = _maps.variable(varId);
168 174 auto newRange = var->range().transform(transformation.value());
169 175 ranges[varId] = newRange;
170 176 }
171 177 }
172 178 else // force new range to all variables -> may be weird if more than one var in the group
173 179 // @TODO ensure that there is no side effects
174 180 {
175 181 for(auto varId:group->variables())
176 182 {
177 183 auto var = _maps.variable(varId);
178 184 ranges[varId] = r;
179 185 }
180 186 }
181 187 }
182 188 else
183 189 {
184 190 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
185 191 }
186 192 return ranges;
187 193 }
188 194
189 195 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
190 196 {
191 197 DateTimeRange newCacheRange;
192 198 std::vector<DateTimeRange> missingRanges;
193 199 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
194 200 {
195 201 newCacheRange = _cacheStrategy->computeRange(r,r);
196 202 missingRanges = {newCacheRange};
197 203 }
198 204 else
199 205 {
200 206 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
201 207 missingRanges = newCacheRange - var->cacheRange();
202 208 }
203 209 return {missingRanges,newCacheRange};
204 210 }
205 211
206 212 void _changeRange(QUuid id, DateTimeRange r)
207 213 {
208 214 _changeRange(_maps.variable(id) ,r);
209 215 }
210 216 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
211 217 {
212 218 auto provider = _maps.provider(*var);
213 219 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
214 220 std::vector<IDataSeries*> data;
215 221 for(auto range:missingRanges)
216 222 {
217 223 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
218 224 }
219 225 var->updateData(data, r, newCacheRange, true);
220 226 }
221 227 public:
222 228 VariableController2Private(QObject* parent=Q_NULLPTR)
223 229 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
224 230 {
225 231 Q_UNUSED(parent);
226 232 this->_ThreadPool.setMaxThreadCount(32);
227 233 }
228 234
229 235 /*
230 236 * This dtor has to like this even if this is ugly, because default dtor would rely on
231 237 * declaration order to destruct members and that would always lead to regressions when
232 238 * modifying class members
233 239 */
234 240 ~VariableController2Private()
235 241 {
236 242 while (this->_ThreadPool.activeThreadCount())
237 243 {
238 244 this->_ThreadPool.waitForDone(100);
239 245 }
240 246 }
241 247
242 248 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
243 249 {
244 250 auto newVar = std::make_shared<Variable>(name,metadata);
245 251 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
246 252 _maps.addVariable(newVar,std::move(provider),group);
247 253 this->_transactions.addEntry(*group);
248 254 return newVar;
249 255 }
250 256
251 257 std::shared_ptr<Variable> variable(QUuid ID)
252 258 {
253 259 return _maps.variable(ID);
254 260 }
255 261
256 262 std::shared_ptr<Variable> variable(int index)
257 263 {
258 264 return _maps.variable(index);
259 265 }
260 266
261 267 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
262 268 {
263 269 auto newVar = variable->clone();
264 270 _maps.synchronize(newVar,std::nullopt);
265 271 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
266 272 this->_transactions.addEntry(*_maps.group(*newVar));
267 273 return newVar;
268 274 }
269 275
270 276 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
271 277 {
272 278 return _transactions.active(*_maps.group(*variable));
273 279 }
274 280
275 281 void deleteVariable(const std::shared_ptr<Variable>& variable)
276 282 {
277 283 _maps.removeVariable(variable);
278 284 }
279 285
280 286 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
281 287 {
282 288 if(!DateTimeRangeHelper::hasnan(r))
283 289 {
284 290 auto group = _maps.group(*variable);
285 291 // Just overwrite next transaction
286 292 {
287 293 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
288 294 }
289 295 _processTransactions();
290 296 }
291 297 else
292 298 {
293 299 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
294 300 }
295 301 }
296 302
297 303 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
298 304 {
299 305 asyncChangeRange(variable,r);
300 306 while (hasPendingTransactions(variable))
301 307 {
302 308 QCoreApplication::processEvents();
303 309 }
304 310 }
305 311
306 312 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
307 313 {
308 314 _maps.synchronize(var, with);
309 315 }
310 316
311 317 inline const std::vector<std::shared_ptr<Variable>> variables()
312 318 {
313 319 return _maps.variables();
314 320 }
315 321
316 322 };
317 323
318 324 VariableController2::VariableController2()
319 325 :impl{spimpl::make_unique_impl<VariableController2Private>()}
320 326 {}
321 327
322 328 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
323 329 {
324 330 auto var = impl->createVariable(name, metadata, provider);
325 331 emit variableAdded(var);
326 332 if(!DateTimeRangeHelper::hasnan(range))
327 333 impl->changeRange(var,range);
328 334 else
329 335 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
330 336 return var;
331 337 }
332 338
333 339 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
334 340 {
335 341 return impl->cloneVariable(variable);
336 342 }
337 343
338 344 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
339 345 {
340 346 impl->deleteVariable(variable);
341 347 emit variableDeleted(variable);
342 348 }
343 349
344 350 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
345 351 {
346 352 impl->changeRange(variable, r);
347 353 }
348 354
349 355 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
350 356 {
351 357 impl->asyncChangeRange(variable, r);
352 358 }
353 359
354 360 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
355 361 {
356 362 return impl->variables();
357 363 }
358 364
359 365 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
360 366 {
361 367 return impl->hasPendingTransactions(variable);
362 368 }
363 369
364 370 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
365 371 {
366 372 impl->synchronize(var, with);
367 373 }
368 374
369 QByteArray VariableController2::mimeData(const std::vector<std::shared_ptr<Variable> > &variables) const
370 {
371 auto encodedData = QByteArray{};
372 QDataStream stream{&encodedData, QIODevice::WriteOnly};
373 for (auto &var : variables) {
374 stream << var->ID().toByteArray();
375 }
376 return encodedData;
377 }
378
379 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(QByteArray mimeData)
375 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
380 376 {
381 377 std::vector<std::shared_ptr<Variable>> variables;
382 QDataStream stream{mimeData};
383
384 QVariantList ids;
385 stream >> ids;
386
387 378 for (const auto& id : ids) {
388 auto uuid = QUuid{id.toByteArray()};
389 variables.push_back (impl->variable(uuid));
379 variables.push_back(impl->variable(id));
390 380 }
391
392 381 return variables;
393 382 }
394 383
395 384 const std::shared_ptr<Variable> &VariableController2::operator[](int index) const
396 385 {
397 386 return impl->variable (index);
398 387 }
399 388
400 389 std::shared_ptr<Variable> VariableController2::operator[](int index)
401 390 {
402 391 return impl->variable (index);
403 392 }
@@ -1,246 +1,270
1 #include <QMimeData>
2 #include <QSize>
3 #include <QTimer>
4 #include <unordered_map>
5
1 6 #include <Variable/Variable.h>
2 7 #include <Variable/VariableController2.h>
3 8 #include <Variable/VariableModel2.h>
4 9
5 10 #include <Common/DateUtils.h>
6 11 #include <Common/MimeTypesDef.h>
7 12 #include <Common/StringUtils.h>
13 #include <Common/containers.h>
8 14
9 15 #include <Data/IDataSeries.h>
10 16
11 17 #include <DataSource/DataSourceController.h>
12 18 #include <Time/TimeController.h>
13 19
14 #include <QMimeData>
15 #include <QSize>
16 #include <QTimer>
17 #include <unordered_map>
18
19 20 namespace {
20 21
21 22 // Column indexes
22 23 const auto NAME_COLUMN = 0;
23 24 const auto TSTART_COLUMN = 1;
24 25 const auto TEND_COLUMN = 2;
25 26 const auto NBPOINTS_COLUMN = 3;
26 27 const auto UNIT_COLUMN = 4;
27 28 const auto MISSION_COLUMN = 5;
28 29 const auto PLUGIN_COLUMN = 6;
29 30 const auto NB_COLUMNS = 7;
30 31
31 32 // Column properties
32 33 const auto DEFAULT_HEIGHT = 25;
33 34 const auto DEFAULT_WIDTH = 100;
34 35
35 36 struct ColumnProperties {
36 37 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
37 38 int height = DEFAULT_HEIGHT)
38 39 : m_Name{name}, m_Width{width}, m_Height{height}
39 40 {
40 41 }
41 42
42 43 QString m_Name;
43 44 int m_Width;
44 45 int m_Height;
45 46 };
46 47
47 48 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
48 49 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
49 50 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
50 51 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
51 52 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
52 53
53 54 QString uniqueName(const QString &defaultName,
54 55 const std::vector<std::shared_ptr<Variable> > &variables)
55 56 {
56 57 auto forbiddenNames = std::vector<QString>(variables.size());
57 58 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
58 59 [](const auto &variable) { return variable->name(); });
59 60 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
60 61 Q_ASSERT(!uniqueName.isEmpty());
61 62
62 63 return uniqueName;
63 64 }
64 65
65 66 } // namespace
66 67
67 68
68 69
69 VariableModel2::VariableModel2(const std::shared_ptr<VariableController2> &variableController, QObject *parent)
70 : QAbstractTableModel{parent}, _variableController{variableController}
70 VariableModel2::VariableModel2(QObject *parent)
71 : QAbstractTableModel{parent}
71 72 {
72 73 }
73 74
74 75
75 76 int VariableModel2::columnCount(const QModelIndex &parent) const
76 77 {
77 78 Q_UNUSED(parent);
78 79
79 80 return NB_COLUMNS;
80 81 }
81 82
82 83 int VariableModel2::rowCount(const QModelIndex &parent) const
83 84 {
84 85 Q_UNUSED(parent);
85 return static_cast<int>(_variableController->variables().size());
86 return _variables.size();
86 87 }
87 88
88 89 QVariant VariableModel2::data(const QModelIndex &index, int role) const
89 90 {
90 91 if (!index.isValid()) {
91 92 return QVariant{};
92 93 }
93 94
94 95 if (index.row() < 0 || index.row() >= rowCount()) {
95 96 return QVariant{};
96 97 }
97 98
98 99 if (role == Qt::DisplayRole) {
99 if (auto variable = _variableController->variables()[index.row()]) {
100 if (auto variable = _variables[index.row()]) {
100 101 switch (index.column()) {
101 102 case NAME_COLUMN:
102 103 return variable->name();
103 104 case TSTART_COLUMN: {
104 105 if(auto range = variable->realRange(); range.has_value())
105 106 return DateUtils::dateTime(range.value().m_TStart).toString(DATETIME_FORMAT);
106 107 return QVariant{};
107 108 }
108 109 case TEND_COLUMN: {
109 110 if(auto range = variable->realRange(); range.has_value())
110 111 return DateUtils::dateTime(range.value().m_TEnd).toString(DATETIME_FORMAT);
111 112 return QVariant{};
112 113 }
113 114 case NBPOINTS_COLUMN:
114 115 return variable->nbPoints();
115 116 case UNIT_COLUMN:
116 117 return variable->metadata().value(QStringLiteral("units"));
117 118 case MISSION_COLUMN:
118 119 return variable->metadata().value(QStringLiteral("mission"));
119 120 case PLUGIN_COLUMN:
120 121 return variable->metadata().value(QStringLiteral("plugin"));
121 122 default:
122 123 // No action
123 124 break;
124 125 }
125 126 }
126 127 }
127 128 else if (role == VariableRoles::ProgressRole) {
128 129 return QVariant{};
129 130 }
130 131
131 132 return QVariant{};
132 133 }
133 134
134 135 QVariant VariableModel2::headerData(int section, Qt::Orientation orientation, int role) const
135 136 {
136 137 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
137 138 return QVariant{};
138 139 }
139 140
140 141 if (orientation == Qt::Horizontal) {
141 142 auto propertiesIt = COLUMN_PROPERTIES.find(section);
142 143 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
143 144 // Role is either DisplayRole or SizeHintRole
144 145 return (role == Qt::DisplayRole)
145 146 ? QVariant{propertiesIt->m_Name}
146 147 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
147 148 }
148 149 }
149 150
150 151 return QVariant{};
151 152 }
152 153
153 154 Qt::ItemFlags VariableModel2::flags(const QModelIndex &index) const
154 155 {
155 156 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
156 157 }
157 158
158 159 Qt::DropActions VariableModel2::supportedDropActions() const
159 160 {
160 161 return Qt::CopyAction | Qt::MoveAction;
161 162 }
162 163
163 164 Qt::DropActions VariableModel2::supportedDragActions() const
164 165 {
165 166 return Qt::CopyAction | Qt::MoveAction;
166 167 }
167 168
168 169 QStringList VariableModel2::mimeTypes() const
169 170 {
170 171 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
171 172 }
172 173
173 174 QMimeData *VariableModel2::mimeData(const QModelIndexList &indexes) const
174 175 {
175 176 auto mimeData = new QMimeData;
176 177 std::vector<std::shared_ptr<Variable> > variables;
177 178
178 179 DateTimeRange firstTimeRange;
179 180 for (const auto &index : indexes) {
180 181 if (index.column() == 0) { // only the first column
181 auto variable = _variableController->variables()[index.row()];
182 auto variable = _variables[index.row()];
182 183 if (variable.get() && index.isValid()) {
183 184
184 185 if (variables.size()==0) {
185 186 // Gets the range of the first variable
186 firstTimeRange = std::move(variable->range());
187 firstTimeRange = variable->range();
187 188 }
188 189 variables.push_back(variable);
189 190 }
190 191 }
191 192 }
192 193
193 auto variablesEncodedData = _variableController->mimeData(variables);
194 auto variablesEncodedData = Variable::mimeData(variables);
194 195 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
195 196
196 197 if (variables.size() == 1) {
197 198 // No time range MIME data if multiple variables are dragged
198 199 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
199 200 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
200 201 }
201 202
202 203 return mimeData;
203 204 }
204 205
205 206 bool VariableModel2::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
206 207 int column, const QModelIndex &parent) const
207 208 {
209 Q_UNUSED(column);
208 210 // drop of a product
209 211 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
210 212 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
211 213 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
212 214 }
213 215
214 216 bool VariableModel2::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
215 217 const QModelIndex &parent)
216 218 {
217 219 auto dropDone = false;
218 220
219 221 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
220 222 auto productList
221 223 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
222 224
223 225 for (auto metaData : productList) {
224 //emit requestVariable(metaData.toHash());
225 //@TODO No idea what this does
226 emit createVariable(metaData.toHash());
226 227 }
227 228
228 229 dropDone = true;
229 230 }
230 231 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
231 auto variable = _variableController->variables()[parent.row()];
232 auto variable = _variables[parent.row()];
232 233 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
233 234
234 _variableController->asyncChangeRange(variable, range);
235 emit asyncChangeRange(variable, range);
235 236
236 237 dropDone = true;
237 238 }
238 239
239 240 return dropDone;
240 241 }
241 242
242 243 void VariableModel2::variableUpdated() noexcept
243 244 {
245 emit dataChanged(QModelIndex(),QModelIndex());
246 }
244 247
248 void VariableModel2::variableAdded(const std::shared_ptr<Variable> & variable)
249 {
250 if(!SciQLop::containers::contains(_variables,variable))
251 {
252 beginInsertRows(QModelIndex(), this->_variables.size(), this->_variables.size());
253 this->_variables.push_back(variable);
254 endInsertRows();
255 connect(variable.get(),&Variable::updated,this,&VariableModel2::variableUpdated);
256 }
257 }
258
259 void VariableModel2::variableDeleted(const std::shared_ptr<Variable> &variable)
260 {
261 auto it = std::find(_variables.begin(), _variables.end(), variable);
262 if (it != _variables.end())
263 {
264 auto index = std::distance(_variables.begin(), it);
265 beginRemoveRows(QModelIndex(), index, index);
266 _variables.erase(it);
267 endRemoveRows();
268 }
245 269 }
246 270
General Comments 0
You need to be logged in to leave comments. Login now