@@ -0,0 +1,57 | |||||
|
1 | #pragma once | |||
|
2 | #include "cpp_utils.h" | |||
|
3 | #include "types_detectors.h" | |||
|
4 | ||||
|
5 | #include <algorithm> | |||
|
6 | #include <iomanip> | |||
|
7 | #include <iostream> | |||
|
8 | ||||
|
9 | HAS_METHOD(name) | |||
|
10 | HAS_METHOD(text) | |||
|
11 | HAS_METHOD(toStdString) | |||
|
12 | ||||
|
13 | template<typename T> std::string _get_name(const T& item) | |||
|
14 | { | |||
|
15 | if constexpr(has_name<T>) { return _get_name(item.name()); } | |||
|
16 | else if constexpr(has_text<T>) | |||
|
17 | { | |||
|
18 | return _get_name(item.text(0)); | |||
|
19 | } | |||
|
20 | else if constexpr(has_toStdString<T>) | |||
|
21 | { | |||
|
22 | return _get_name(item.toStdString()); | |||
|
23 | } | |||
|
24 | else | |||
|
25 | { | |||
|
26 | return item; | |||
|
27 | } | |||
|
28 | } | |||
|
29 | ||||
|
30 | template<typename T> | |||
|
31 | void _print_tree(const T& tree, int indent_increment, int indent_lvl) | |||
|
32 | { | |||
|
33 | auto print_lambda = [&indent_lvl, &indent_increment](const auto& node) { | |||
|
34 | indent_lvl * [indent_increment](){std::cout <<"│"<< std::string(indent_increment, ' ');}; | |||
|
35 | std::cout << "├"; | |||
|
36 | (indent_increment-1) * [](){std::cout <<"─";}; | |||
|
37 | std::cout << " "<< _get_name(to_value(node)) << std::endl; | |||
|
38 | print_tree(to_value(node), indent_increment, indent_lvl+1); | |||
|
39 | }; | |||
|
40 | if constexpr(is_qt_tree_item<T>::value) | |||
|
41 | { | |||
|
42 | for(int i = 0; i < tree.childCount(); i++) | |||
|
43 | { | |||
|
44 | print_lambda(tree.child(i)); | |||
|
45 | } | |||
|
46 | } | |||
|
47 | else | |||
|
48 | { | |||
|
49 | std::for_each(std::cbegin(tree), std::cend(tree), print_lambda); | |||
|
50 | } | |||
|
51 | } | |||
|
52 | ||||
|
53 | template<typename T> | |||
|
54 | void print_tree(const T& tree, int indent_increment = 3, int indent_lvl = 0) | |||
|
55 | { | |||
|
56 | _print_tree(to_value(tree), indent_increment, indent_lvl); | |||
|
57 | } |
@@ -0,0 +1,40 | |||||
|
1 | #pragma once | |||
|
2 | #include <type_traits> | |||
|
3 | ||||
|
4 | template<typename T, typename = void> struct is_smart_ptr : std::false_type | |||
|
5 | {}; | |||
|
6 | template<typename T> | |||
|
7 | struct is_smart_ptr<T, decltype(std::declval<T>().get(), | |||
|
8 | std::declval<T>().reset())> : std::true_type | |||
|
9 | {}; | |||
|
10 | ||||
|
11 | template<typename T, typename = void> struct is_qt_tree_item : std::false_type | |||
|
12 | {}; | |||
|
13 | template<typename T> | |||
|
14 | struct is_qt_tree_item<T, decltype(std::declval<T>().takeChildren(), | |||
|
15 | std::declval<T>().parent(), | |||
|
16 | std::declval<T>().addChild(nullptr))> | |||
|
17 | : std::true_type | |||
|
18 | {}; | |||
|
19 | ||||
|
20 | template<typename T, typename = void> struct has_name_method : std::false_type | |||
|
21 | {}; | |||
|
22 | template<typename T> | |||
|
23 | struct has_name_method<T, decltype(std::declval<T>().name(), | |||
|
24 | std::declval<void>())> : std::true_type | |||
|
25 | {}; | |||
|
26 | ||||
|
27 | template<typename T, typename = void> struct has_text_method : std::false_type | |||
|
28 | {}; | |||
|
29 | template<typename T> | |||
|
30 | struct has_text_method<T, decltype(std::declval<T>().text(), | |||
|
31 | std::declval<void>())> : std::true_type | |||
|
32 | {}; | |||
|
33 | ||||
|
34 | ||||
|
35 | template<typename T, typename = void> struct has_tostdstring_method : std::false_type | |||
|
36 | {}; | |||
|
37 | template<typename T> | |||
|
38 | struct has_tostdstring_method<T, decltype(std::declval<T>().toStdString(), | |||
|
39 | std::declval<void>())> : std::true_type | |||
|
40 | {}; |
@@ -1,6 +1,8 | |||||
1 | #ifndef CPP_UTILS_H |
|
1 | #ifndef CPP_UTILS_H | |
2 | #define CPP_UTILS_H |
|
2 | #define CPP_UTILS_H | |
3 |
|
3 | |||
|
4 | #include "types_detectors.h" | |||
|
5 | ||||
4 | #include <functional> |
|
6 | #include <functional> | |
5 | #include <tuple> |
|
7 | #include <tuple> | |
6 | #include <type_traits> |
|
8 | #include <type_traits> | |
@@ -34,4 +36,31 template<typename T> constexpr T diff(const std::pair<T, T>& p) | |||||
34 | return p.second - p.first; |
|
36 | return p.second - p.first; | |
35 | } |
|
37 | } | |
36 |
|
38 | |||
|
39 | template<typename T> constexpr auto const& to_value(const T& item) | |||
|
40 | { | |||
|
41 | if constexpr(std::is_pointer_v<std::remove_reference_t<std::remove_cv_t<T>>>) | |||
|
42 | { return *item; } | |||
|
43 | else | |||
|
44 | { | |||
|
45 | if constexpr(is_smart_ptr<T>::value) { return *item.get(); } | |||
|
46 | else | |||
|
47 | { | |||
|
48 | return item; | |||
|
49 | } | |||
|
50 | } | |||
|
51 | } | |||
|
52 | ||||
|
53 | template<typename T> void repeat_n(T func, int number) | |||
|
54 | { | |||
|
55 | for(int i = 0; i < number; i++) | |||
|
56 | func(); | |||
|
57 | } | |||
|
58 | ||||
|
59 | inline int operator*(int number, const std::function<void(void)>& func) | |||
|
60 | { | |||
|
61 | for(int i = 0; i < number; i++) | |||
|
62 | func(); | |||
|
63 | return number; | |||
|
64 | } | |||
|
65 | ||||
37 | #endif // CPP_UTILS_H |
|
66 | #endif // CPP_UTILS_H |
@@ -29,6 +29,9 DEPRECATE(class QNetworkReply; class QNetworkRequest;) | |||||
29 | class SCIQLOP_CORE_EXPORT IDataProvider : public QObject |
|
29 | class SCIQLOP_CORE_EXPORT IDataProvider : public QObject | |
30 | { |
|
30 | { | |
31 | Q_OBJECT |
|
31 | Q_OBJECT | |
|
32 | ||||
|
33 | QUuid _id=QUuid::createUuid(); | |||
|
34 | ||||
32 | public: |
|
35 | public: | |
33 | virtual ~IDataProvider() noexcept = default; |
|
36 | virtual ~IDataProvider() noexcept = default; | |
34 | // virtual std::shared_ptr<IDataProvider> clone() const = 0; |
|
37 | // virtual std::shared_ptr<IDataProvider> clone() const = 0; | |
@@ -37,6 +40,12 public: | |||||
37 | virtual TimeSeries::ITimeSerie* |
|
40 | virtual TimeSeries::ITimeSerie* | |
38 | getData(const DataProviderParameters& parameters) = 0; |
|
41 | getData(const DataProviderParameters& parameters) = 0; | |
39 |
|
42 | |||
|
43 | QUuid id() const { return _id; } | |||
|
44 | QString name() | |||
|
45 | { | |||
|
46 | return QString("%1-%2").arg(this->metaObject()->className()).arg(id().toString()); | |||
|
47 | } | |||
|
48 | ||||
40 | signals: |
|
49 | signals: | |
41 |
|
50 | |||
42 | void progress(QUuid requestID, double progress); |
|
51 | void progress(QUuid requestID, double progress); |
@@ -35,6 +35,9 public: | |||||
35 | */ |
|
35 | */ | |
36 | QUuid registerDataSource(const QString &dataSourceName) noexcept; |
|
36 | QUuid registerDataSource(const QString &dataSourceName) noexcept; | |
37 |
|
37 | |||
|
38 | // should deprecate both registerDataSource and setDataProvider | |||
|
39 | void registerProvider(IDataProvider* provider) noexcept; | |||
|
40 | ||||
38 | /** |
|
41 | /** | |
39 | * Sets the structure of a data source. The controller takes ownership of the structure. |
|
42 | * Sets the structure of a data source. The controller takes ownership of the structure. | |
40 | * @param dataSourceUid the unique id with which the data source has been registered into the |
|
43 | * @param dataSourceUid the unique id with which the data source has been registered into the | |
@@ -45,6 +48,9 public: | |||||
45 | void setDataSourceItem(const QUuid &dataSourceUid, |
|
48 | void setDataSourceItem(const QUuid &dataSourceUid, | |
46 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept; |
|
49 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept; | |
47 |
|
50 | |||
|
51 | void setDataSourceItem(const QUuid &dataSourceUid, | |||
|
52 | const QString &path, const QMap<QString, QString>& metaData) noexcept; | |||
|
53 | ||||
48 | /** |
|
54 | /** | |
49 | * Sets the data provider used to retrieve data from of a data source. The controller takes |
|
55 | * Sets the data provider used to retrieve data from of a data source. The controller takes | |
50 | * ownership of the provider. |
|
56 | * ownership of the provider. |
@@ -4,8 +4,11 | |||||
4 | #include "CoreGlobal.h" |
|
4 | #include "CoreGlobal.h" | |
5 |
|
5 | |||
6 | #include <Common/spimpl.h> |
|
6 | #include <Common/spimpl.h> | |
|
7 | #include <Common/trees.h> | |||
7 | #include <QVariant> |
|
8 | #include <QVariant> | |
8 | #include <QVector> |
|
9 | #include <QVector> | |
|
10 | #include <iostream> | |||
|
11 | #include <iomanip> | |||
9 |
|
12 | |||
10 | class DataSourceItemAction; |
|
13 | class DataSourceItemAction; | |
11 |
|
14 | |||
@@ -19,6 +22,8 enum class DataSourceItemType | |||||
19 | COMPONENT |
|
22 | COMPONENT | |
20 | }; |
|
23 | }; | |
21 |
|
24 | |||
|
25 | ||||
|
26 | ||||
22 | /** |
|
27 | /** | |
23 | * @brief The DataSourceItem class aims to represent a structure element of a |
|
28 | * @brief The DataSourceItem class aims to represent a structure element of a | |
24 | * data source. A data source has a tree structure that is made up of a main |
|
29 | * data source. A data source has a tree structure that is made up of a main | |
@@ -28,7 +33,10 enum class DataSourceItemType | |||||
28 | */ |
|
33 | */ | |
29 | class SCIQLOP_CORE_EXPORT DataSourceItem |
|
34 | class SCIQLOP_CORE_EXPORT DataSourceItem | |
30 | { |
|
35 | { | |
|
36 | ||||
31 | public: |
|
37 | public: | |
|
38 | using iterator_type = decltype (std::begin(std::declval<std::vector<std::unique_ptr<DataSourceItem>>>())); | |||
|
39 | using const_iterator_type = decltype (std::cbegin(std::declval<std::vector<std::unique_ptr<DataSourceItem>>>())); | |||
32 | /// Key associated with the name of the item |
|
40 | /// Key associated with the name of the item | |
33 | static const QString NAME_DATA_KEY; |
|
41 | static const QString NAME_DATA_KEY; | |
34 | /// Key associated with the plugin of the item |
|
42 | /// Key associated with the plugin of the item | |
@@ -167,6 +175,12 public: | |||||
167 | bool operator==(const DataSourceItem& other); |
|
175 | bool operator==(const DataSourceItem& other); | |
168 | bool operator!=(const DataSourceItem& other); |
|
176 | bool operator!=(const DataSourceItem& other); | |
169 |
|
177 | |||
|
178 | iterator_type begin() noexcept; | |||
|
179 | iterator_type end() noexcept; | |||
|
180 | const_iterator_type begin()const noexcept; | |||
|
181 | const_iterator_type end()const noexcept; | |||
|
182 | const_iterator_type cbegin()const noexcept; | |||
|
183 | const_iterator_type cend()const noexcept; | |||
170 | private: |
|
184 | private: | |
171 | class DataSourceItemPrivate; |
|
185 | class DataSourceItemPrivate; | |
172 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; |
|
186 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; |
@@ -1,3 +1,4 | |||||
|
1 | #pragma once | |||
1 | #include "Variable/VariableSynchronizationGroup2.h" |
|
2 | #include "Variable/VariableSynchronizationGroup2.h" | |
2 |
|
3 | |||
3 | #include <Common/containers.h> |
|
4 | #include <Common/containers.h> |
@@ -1,197 +1,298 | |||||
1 | #include "DataSource/DataSourceController.h" |
|
1 | #include "DataSource/DataSourceController.h" | |
|
2 | ||||
2 | #include "DataSource/DataSourceItem.h" |
|
3 | #include "DataSource/DataSourceItem.h" | |
|
4 | #include "DataSource/DataSourceItemAction.h" | |||
3 |
|
5 | |||
|
6 | #include <Common/containers.h> | |||
4 | #include <Data/IDataProvider.h> |
|
7 | #include <Data/IDataProvider.h> | |
5 |
|
||||
6 | #include <QMutex> |
|
|||
7 | #include <QThread> |
|
|||
8 |
|
||||
9 | #include <QDataStream> |
|
8 | #include <QDataStream> | |
10 | #include <QDir> |
|
9 | #include <QDir> | |
|
10 | #include <QMutex> | |||
11 | #include <QStandardPaths> |
|
11 | #include <QStandardPaths> | |
|
12 | #include <QThread> | |||
12 |
|
13 | |||
13 | Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController") |
|
14 | Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController") | |
14 |
|
15 | |||
15 | class DataSourceController::DataSourceControllerPrivate { |
|
16 | std::unique_ptr<DataSourceItem> make_folder_item(const QString& name) | |
|
17 | { | |||
|
18 | return std::make_unique<DataSourceItem>(DataSourceItemType::NODE, name); | |||
|
19 | } | |||
|
20 | ||||
|
21 | template<typename T> | |||
|
22 | DataSourceItem* make_path_items(const T& path_list_begin, | |||
|
23 | const T& path_list_end, DataSourceItem* root) | |||
|
24 | { | |||
|
25 | std::for_each(path_list_begin, path_list_end, | |||
|
26 | [&root](const auto& folder_name) mutable { | |||
|
27 | auto folder_ptr = root->findItem(folder_name); | |||
|
28 | if(folder_ptr == nullptr) | |||
|
29 | { | |||
|
30 | auto folder = make_folder_item(folder_name); | |||
|
31 | folder_ptr = folder.get(); | |||
|
32 | root->appendChild(std::move(folder)); | |||
|
33 | } | |||
|
34 | root = folder_ptr; | |||
|
35 | }); | |||
|
36 | return root; | |||
|
37 | } | |||
|
38 | ||||
|
39 | std::unique_ptr<DataSourceItem> | |||
|
40 | make_product_item(const QVariantHash& metaData, const QUuid& dataSourceUid, | |||
|
41 | const QString& DATA_SOURCE_NAME, DataSourceController* dc) | |||
|
42 | { | |||
|
43 | auto result = | |||
|
44 | std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, metaData); | |||
|
45 | ||||
|
46 | // Adds plugin name to product metadata | |||
|
47 | result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); | |||
|
48 | result->setData(DataSourceItem::ID_DATA_KEY, | |||
|
49 | metaData.value(DataSourceItem::NAME_DATA_KEY)); | |||
|
50 | ||||
|
51 | auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); | |||
|
52 | ||||
|
53 | // Add action to load product from DataSourceController | |||
|
54 | result->addAction(std::make_unique<DataSourceItemAction>( | |||
|
55 | QObject::tr("Load %1 product").arg(productName), | |||
|
56 | [productName, dataSourceUid, dc](DataSourceItem& item) { | |||
|
57 | if(dc) { dc->loadProductItem(dataSourceUid, item); } | |||
|
58 | })); | |||
|
59 | ||||
|
60 | return result; | |||
|
61 | } | |||
|
62 | ||||
|
63 | class DataSourceController::DataSourceControllerPrivate | |||
|
64 | { | |||
16 | public: |
|
65 | public: | |
17 |
|
|
66 | QMutex m_WorkingMutex; | |
18 |
|
|
67 | /// Data sources registered | |
19 |
|
|
68 | QHash<QUuid, QString> m_DataSources; | |
20 |
|
|
69 | /// Data sources structures | |
21 |
|
|
70 | std::map<QUuid, std::unique_ptr<DataSourceItem>> m_DataSourceItems; | |
22 |
|
|
71 | /// Data providers registered | |
23 |
|
|
72 | /// @remarks Data providers are stored as shared_ptr as they can be sent to a | |
24 |
|
|
73 | /// variable and continue to live without necessarily the data source | |
25 | std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders; |
|
74 | /// controller | |
26 |
|
75 | std::map<QUuid, std::shared_ptr<IDataProvider>> m_DataProviders; | ||
27 | // Search for the first datasource item matching the specified data |
|
76 | ||
28 | DataSourceItem *findDataSourceItem(const QVariantHash &data) |
|
77 | // Search for the first datasource item matching the specified data | |
|
78 | DataSourceItem* findDataSourceItem(const QVariantHash& data) | |||
|
79 | { | |||
|
80 | DataSourceItem* sourceItem = nullptr; | |||
|
81 | for(const auto& item : m_DataSourceItems) | |||
29 | { |
|
82 | { | |
30 | DataSourceItem *sourceItem = nullptr; |
|
83 | sourceItem = item.second->findItem(data, true); | |
31 | for (const auto &item : m_DataSourceItems) { |
|
84 | if(sourceItem) { break; } | |
32 | sourceItem = item.second->findItem(data, true); |
|
|||
33 | if (sourceItem) { |
|
|||
34 | break; |
|
|||
35 | } |
|
|||
36 | } |
|
|||
37 |
|
||||
38 | return sourceItem; |
|
|||
39 | } |
|
85 | } | |
40 |
|
86 | |||
41 | // Search for the first datasource item matching the specified ID_DATA_KEY |
|
87 | return sourceItem; | |
42 | DataSourceItem *findDataSourceItem(const QString &datasourceIdKey) |
|
88 | } | |
|
89 | ||||
|
90 | // Search for the first datasource item matching the specified ID_DATA_KEY | |||
|
91 | DataSourceItem* findDataSourceItem(const QString& datasourceIdKey) | |||
|
92 | { | |||
|
93 | DataSourceItem* sourceItem = nullptr; | |||
|
94 | for(const auto& item : m_DataSourceItems) | |||
43 | { |
|
95 | { | |
44 | DataSourceItem *sourceItem = nullptr; |
|
96 | sourceItem = item.second->findItem(datasourceIdKey, true); | |
45 | for (const auto &item : m_DataSourceItems) { |
|
97 | if(sourceItem) { break; } | |
46 | sourceItem = item.second->findItem(datasourceIdKey, true); |
|
|||
47 | if (sourceItem) { |
|
|||
48 | break; |
|
|||
49 | } |
|
|||
50 | } |
|
|||
51 |
|
||||
52 | return sourceItem; |
|
|||
53 | } |
|
98 | } | |
|
99 | ||||
|
100 | return sourceItem; | |||
|
101 | } | |||
54 | }; |
|
102 | }; | |
55 |
|
103 | |||
56 |
DataSourceController::DataSourceController(QObject |
|
104 | DataSourceController::DataSourceController(QObject* parent) | |
57 |
|
|
105 | : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()} | |
58 | { |
|
106 | { | |
59 |
|
|
107 | qCDebug(LOG_DataSourceController()) | |
60 | << QThread::currentThread(); |
|
108 | << tr("DataSourceController construction") << QThread::currentThread(); | |
61 | } |
|
109 | } | |
62 |
|
110 | |||
63 | DataSourceController::~DataSourceController() |
|
111 | DataSourceController::~DataSourceController() | |
64 | { |
|
112 | { | |
65 |
|
|
113 | qCDebug(LOG_DataSourceController()) | |
66 | << QThread::currentThread(); |
|
114 | << tr("DataSourceController destruction") << QThread::currentThread(); | |
67 |
|
|
115 | this->waitForFinish(); | |
68 | } |
|
116 | } | |
69 |
|
117 | |||
70 |
QUuid DataSourceController::registerDataSource( |
|
118 | QUuid DataSourceController::registerDataSource( | |
|
119 | const QString& dataSourceName) noexcept | |||
71 | { |
|
120 | { | |
72 |
|
|
121 | auto dataSourceUid = QUuid::createUuid(); | |
73 |
|
|
122 | impl->m_DataSources.insert(dataSourceUid, dataSourceName); | |
74 |
|
123 | |||
75 |
|
|
124 | return dataSourceUid; | |
|
125 | } | |||
|
126 | ||||
|
127 | void DataSourceController::registerProvider(IDataProvider *provider) noexcept | |||
|
128 | { | |||
|
129 | impl->m_DataSources.insert(provider->id(), provider->name()); | |||
|
130 | impl->m_DataProviders.insert({provider->id(), std::unique_ptr<IDataProvider>{provider}}); | |||
|
131 | // TODO rethink this, I don't get why we have to do this crap | |||
|
132 | // why do we need a root node for each provider | |||
|
133 | setDataSourceItem(provider->id(),make_folder_item(provider->name())); | |||
76 | } |
|
134 | } | |
77 |
|
135 | |||
78 | void DataSourceController::setDataSourceItem( |
|
136 | void DataSourceController::setDataSourceItem( | |
79 | const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept |
|
137 | const QUuid& dataSourceUid, | |
|
138 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept | |||
80 | { |
|
139 | { | |
81 |
|
|
140 | if(!dataSourceItem) | |
82 | qCWarning(LOG_DataSourceController()) |
|
141 | { | |
83 | << tr("Data source item can't be registered (null item)"); |
|
142 | qCWarning(LOG_DataSourceController()) | |
84 | return; |
|
143 | << tr("Data source item can't be registered (null item)"); | |
85 | } |
|
144 | return; | |
|
145 | } | |||
|
146 | ||||
|
147 | if(impl->m_DataSources.contains(dataSourceUid)) | |||
|
148 | { | |||
|
149 | // The data provider is implicitly converted to a shared_ptr | |||
|
150 | impl->m_DataSourceItems.insert( | |||
|
151 | std::make_pair(dataSourceUid, std::move(dataSourceItem))); | |||
|
152 | ||||
|
153 | // Retrieves the data source item to emit the signal with it | |||
|
154 | auto it = impl->m_DataSourceItems.find(dataSourceUid); | |||
|
155 | if(it != impl->m_DataSourceItems.end()) | |||
|
156 | { emit dataSourceItemSet(it->second.get()); } | |||
|
157 | } | |||
|
158 | else | |||
|
159 | { | |||
|
160 | qCWarning(LOG_DataSourceController()) | |||
|
161 | << tr("Can't set data source item for uid %1 : no " | |||
|
162 | "data source has been registered with the uid") | |||
|
163 | .arg(dataSourceUid.toString()); | |||
|
164 | } | |||
|
165 | } | |||
86 |
|
166 | |||
87 | if (impl->m_DataSources.contains(dataSourceUid)) { |
|
|||
88 | // The data provider is implicitly converted to a shared_ptr |
|
|||
89 | impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem))); |
|
|||
90 |
|
167 | |||
91 | // Retrieves the data source item to emit the signal with it |
|
|||
92 | auto it = impl->m_DataSourceItems.find(dataSourceUid); |
|
|||
93 | if (it != impl->m_DataSourceItems.end()) { |
|
|||
94 | emit dataSourceItemSet(it->second.get()); |
|
|||
95 | } |
|
|||
96 | } |
|
|||
97 | else { |
|
|||
98 | qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no " |
|
|||
99 | "data source has been registered with the uid") |
|
|||
100 | .arg(dataSourceUid.toString()); |
|
|||
101 | } |
|
|||
102 | } |
|
|||
103 |
|
168 | |||
104 |
void DataSourceController::setData |
|
169 | void DataSourceController::setDataSourceItem(const QUuid& dataSourceUid, const QString& path, | |
105 | std::unique_ptr<IDataProvider> dataProvider) noexcept |
|
170 | const QMap<QString, QString> &metaData) noexcept | |
106 | { |
|
171 | { | |
107 |
|
|
172 | if(auto it = impl->m_DataSourceItems.find(dataSourceUid); | |
108 | impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider))); |
|
173 | it != impl->m_DataSourceItems.end()) | |
109 | } |
|
174 | { | |
110 | else { |
|
175 | auto path_list = path.split('/', QString::SkipEmptyParts); | |
111 | qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data " |
|
176 | auto name = *(std::cend(path_list) - 1); | |
112 | "source has been registered with the uid") |
|
177 | auto path_item = make_path_items( | |
113 | .arg(dataSourceUid.toString()); |
|
178 | std::cbegin(path_list), std::cend(path_list) - 1, it->second.get()); | |
|
179 | QVariantHash meta_data{{DataSourceItem::NAME_DATA_KEY, name}}; | |||
|
180 | for(auto& key : metaData.keys()) | |||
|
181 | { | |||
|
182 | meta_data[key] = metaData[key]; | |||
114 | } |
|
183 | } | |
|
184 | path_item->appendChild( | |||
|
185 | make_product_item(meta_data, dataSourceUid, "test", this)); | |||
|
186 | emit dataSourceItemSet(it->second.get()); | |||
|
187 | } | |||
115 | } |
|
188 | } | |
116 |
|
189 | |||
117 |
void DataSourceController:: |
|
190 | void DataSourceController::setDataProvider( | |
118 | const DataSourceItem &productItem) noexcept |
|
191 | const QUuid& dataSourceUid, | |
|
192 | std::unique_ptr<IDataProvider> dataProvider) noexcept | |||
119 | { |
|
193 | { | |
120 | if (productItem.type() == DataSourceItemType::PRODUCT |
|
194 | if(impl->m_DataSources.contains(dataSourceUid)) | |
121 | || productItem.type() == DataSourceItemType::COMPONENT) { |
|
195 | { | |
122 | /// Retrieves the data provider of the data source (if any) |
|
196 | impl->m_DataProviders.insert( | |
123 | auto it = impl->m_DataProviders.find(dataSourceUid); |
|
197 | std::make_pair(dataSourceUid, std::move(dataProvider))); | |
124 | auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr; |
|
198 | } | |
|
199 | else | |||
|
200 | { | |||
|
201 | qCWarning(LOG_DataSourceController()) | |||
|
202 | << tr("Can't set data provider for uid %1 : no data " | |||
|
203 | "source has been registered with the uid") | |||
|
204 | .arg(dataSourceUid.toString()); | |||
|
205 | } | |||
|
206 | } | |||
125 |
|
207 | |||
126 | emit createVariable(productItem.name(), productItem.data(), dataProvider); |
|
208 | void DataSourceController::loadProductItem( | |
127 | } |
|
209 | const QUuid& dataSourceUid, const DataSourceItem& productItem) noexcept | |
128 | else { |
|
210 | { | |
129 | qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product"); |
|
211 | if(productItem.type() == DataSourceItemType::PRODUCT || | |
130 | } |
|
212 | productItem.type() == DataSourceItemType::COMPONENT) | |
|
213 | { | |||
|
214 | /// Retrieves the data provider of the data source (if any) | |||
|
215 | auto it = impl->m_DataProviders.find(dataSourceUid); | |||
|
216 | auto dataProvider = | |||
|
217 | (it != impl->m_DataProviders.end()) ? it->second : nullptr; | |||
|
218 | ||||
|
219 | emit createVariable(productItem.name(), productItem.data(), dataProvider); | |||
|
220 | } | |||
|
221 | else | |||
|
222 | { | |||
|
223 | qCWarning(LOG_DataSourceController()) | |||
|
224 | << tr("Can't load an item that is not a product"); | |||
|
225 | } | |||
131 | } |
|
226 | } | |
132 |
|
227 | |||
133 | QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) |
|
228 | QByteArray | |
|
229 | DataSourceController::mimeDataForProductsData(const QVariantList& productsData) | |||
134 | { |
|
230 | { | |
135 |
|
|
231 | QByteArray encodedData; | |
136 |
|
|
232 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |
137 |
|
233 | |||
138 |
|
|
234 | stream << productsData; | |
139 |
|
235 | |||
140 |
|
|
236 | return encodedData; | |
141 | } |
|
237 | } | |
142 |
|
238 | |||
143 | QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) |
|
239 | QVariantList | |
|
240 | DataSourceController::productsDataForMimeData(const QByteArray& mimeData) | |||
144 | { |
|
241 | { | |
145 |
|
|
242 | QDataStream stream{mimeData}; | |
146 |
|
243 | |||
147 |
|
|
244 | QVariantList productList; | |
148 |
|
|
245 | stream >> productList; | |
149 |
|
246 | |||
150 |
|
|
247 | return productList; | |
151 | } |
|
248 | } | |
152 |
|
249 | |||
153 | void DataSourceController::initialize() |
|
250 | void DataSourceController::initialize() | |
154 | { |
|
251 | { | |
155 |
|
|
252 | qCDebug(LOG_DataSourceController()) | |
156 | << QThread::currentThread(); |
|
253 | << tr("DataSourceController init") << QThread::currentThread(); | |
157 |
|
|
254 | impl->m_WorkingMutex.lock(); | |
158 |
|
|
255 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END"); | |
159 | } |
|
256 | } | |
160 |
|
257 | |||
161 | void DataSourceController::finalize() |
|
258 | void DataSourceController::finalize() { impl->m_WorkingMutex.unlock(); } | |
162 | { |
|
|||
163 | impl->m_WorkingMutex.unlock(); |
|
|||
164 | } |
|
|||
165 |
|
259 | |||
166 |
void DataSourceController::requestVariableFromProductIdKey( |
|
260 | void DataSourceController::requestVariableFromProductIdKey( | |
|
261 | const QString& datasourceIdKey) | |||
167 | { |
|
262 | { | |
168 |
|
|
263 | auto sourceItem = impl->findDataSourceItem(datasourceIdKey); | |
169 |
|
264 | |||
170 |
|
|
265 | if(sourceItem) | |
171 | auto sourceName = sourceItem->rootItem().name(); |
|
266 | { | |
172 | auto sourceId = impl->m_DataSources.key(sourceName); |
|
267 | auto sourceName = sourceItem->rootItem().name(); | |
173 | loadProductItem(sourceId, *sourceItem); |
|
268 | auto sourceId = impl->m_DataSources.key(sourceName); | |
174 | } |
|
269 | loadProductItem(sourceId, *sourceItem); | |
175 | else { |
|
270 | } | |
176 | qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found"); |
|
271 | else | |
177 | } |
|
272 | { | |
|
273 | qCWarning(LOG_DataSourceController()) | |||
|
274 | << tr("requestVariable, product data not found"); | |||
|
275 | } | |||
178 | } |
|
276 | } | |
179 |
|
277 | |||
180 |
void DataSourceController::requestVariable(const QVariantHash |
|
278 | void DataSourceController::requestVariable(const QVariantHash& productData) | |
181 | { |
|
279 | { | |
182 |
|
|
280 | auto sourceItem = impl->findDataSourceItem(productData); | |
183 |
|
281 | |||
184 |
|
|
282 | if(sourceItem) | |
185 | auto sourceName = sourceItem->rootItem().name(); |
|
283 | { | |
186 | auto sourceId = impl->m_DataSources.key(sourceName); |
|
284 | auto sourceName = sourceItem->rootItem().name(); | |
187 | loadProductItem(sourceId, *sourceItem); |
|
285 | auto sourceId = impl->m_DataSources.key(sourceName); | |
188 | } |
|
286 | loadProductItem(sourceId, *sourceItem); | |
189 | else { |
|
287 | } | |
190 | qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found"); |
|
288 | else | |
191 | } |
|
289 | { | |
|
290 | qCWarning(LOG_DataSourceController()) | |||
|
291 | << tr("requestVariable, product data not found"); | |||
|
292 | } | |||
192 | } |
|
293 | } | |
193 |
|
294 | |||
194 | void DataSourceController::waitForFinish() |
|
295 | void DataSourceController::waitForFinish() | |
195 | { |
|
296 | { | |
196 |
|
|
297 | QMutexLocker locker{&impl->m_WorkingMutex}; | |
197 | } |
|
298 | } |
@@ -17,8 +17,14 struct DataSourceItem::DataSourceItemPrivate | |||||
17 | DataSourceItem* m_Parent; |
|
17 | DataSourceItem* m_Parent; | |
18 | std::vector<std::unique_ptr<DataSourceItem>> m_Children; |
|
18 | std::vector<std::unique_ptr<DataSourceItem>> m_Children; | |
19 | DataSourceItemType m_Type; |
|
19 | DataSourceItemType m_Type; | |
|
20 | //TODO check if QVariant is really wise here, looks quite overkill | |||
|
21 | // maybe a simple map<string,string> could be enough | |||
20 | QVariantHash m_Data; |
|
22 | QVariantHash m_Data; | |
21 | std::vector<std::unique_ptr<DataSourceItemAction>> m_Actions; |
|
23 | std::vector<std::unique_ptr<DataSourceItemAction>> m_Actions; | |
|
24 | auto begin()noexcept{return m_Children.begin();} | |||
|
25 | auto end()noexcept{return m_Children.end();} | |||
|
26 | auto cbegin()const noexcept{return m_Children.cbegin();} | |||
|
27 | auto cend()const noexcept{return m_Children.cend();} | |||
22 | }; |
|
28 | }; | |
23 |
|
29 | |||
24 | DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) |
|
30 | DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) | |
@@ -219,3 +225,33 bool DataSourceItem::operator!=(const DataSourceItem& other) | |||||
219 | { |
|
225 | { | |
220 | return !(*this == other); |
|
226 | return !(*this == other); | |
221 | } |
|
227 | } | |
|
228 | ||||
|
229 | DataSourceItem::iterator_type DataSourceItem::begin() noexcept | |||
|
230 | { | |||
|
231 | return impl->begin(); | |||
|
232 | } | |||
|
233 | ||||
|
234 | DataSourceItem::iterator_type DataSourceItem::end() noexcept | |||
|
235 | { | |||
|
236 | return impl->end(); | |||
|
237 | } | |||
|
238 | ||||
|
239 | DataSourceItem::const_iterator_type DataSourceItem::cbegin() const noexcept | |||
|
240 | { | |||
|
241 | return impl->cbegin(); | |||
|
242 | } | |||
|
243 | ||||
|
244 | DataSourceItem::const_iterator_type DataSourceItem::cend() const noexcept | |||
|
245 | { | |||
|
246 | return impl->cend(); | |||
|
247 | } | |||
|
248 | ||||
|
249 | DataSourceItem::const_iterator_type DataSourceItem::begin() const noexcept | |||
|
250 | { | |||
|
251 | return impl->cbegin(); | |||
|
252 | } | |||
|
253 | ||||
|
254 | DataSourceItem::const_iterator_type DataSourceItem::end() const noexcept | |||
|
255 | { | |||
|
256 | return impl->cend(); | |||
|
257 | } |
@@ -2,54 +2,54 | |||||
2 |
|
2 | |||
3 | #include <DataSource/DataSourceItem.h> |
|
3 | #include <DataSource/DataSourceItem.h> | |
4 |
|
4 | |||
5 |
namespace |
|
5 | namespace | |
6 |
|
||||
7 | /** |
|
|||
8 | * Finds in a tree an item similar to the item passed in parameter |
|
|||
9 | * @param item the item for which to find a similar item |
|
|||
10 | * @param root the root item of the tree |
|
|||
11 | * @return the similar item if found, nullptr otherwise |
|
|||
12 | */ |
|
|||
13 | DataSourceItem *findSimilarItem(const DataSourceItem &item, const DataSourceItem &root) |
|
|||
14 | { |
|
6 | { | |
|
7 | /** | |||
|
8 | * Finds in a tree an item similar to the item passed in parameter | |||
|
9 | * @param item the item for which to find a similar item | |||
|
10 | * @param root the root item of the tree | |||
|
11 | * @return the similar item if found, nullptr otherwise | |||
|
12 | */ | |||
|
13 | DataSourceItem* findSimilarItem(const DataSourceItem& item, | |||
|
14 | const DataSourceItem& root) | |||
|
15 | { | |||
15 | // An item is considered similar to the another item if: |
|
16 | // An item is considered similar to the another item if: | |
16 | // - the items are both nodes AND |
|
17 | // - the items are both nodes AND | |
17 | // - the names of the items are identical |
|
18 | // - the names of the items are identical | |
18 |
|
19 | |||
19 |
if |
|
20 | if(item.type() != DataSourceItemType::NODE) { return nullptr; } | |
20 | return nullptr; |
|
|||
21 | } |
|
|||
22 |
|
||||
23 | DataSourceItem *result{nullptr}; |
|
|||
24 | bool found{false}; |
|
|||
25 | for (auto i = 0, count = root.childCount(); i < count && !found; ++i) { |
|
|||
26 | auto child = root.child(i); |
|
|||
27 |
|
21 | |||
28 | found = child->type() == DataSourceItemType::NODE |
|
22 | auto similar_item = std::find_if( | |
29 | && QString::compare(child->name(), item.name(), Qt::CaseInsensitive) == 0; |
|
23 | std::cbegin(root), std::cend(root), [&item](const auto& child) { | |
30 | if (found) { |
|
24 | return child->type() == DataSourceItemType::NODE && | |
31 | result = child; |
|
25 | QString::compare(child->name(), item.name(), | |
32 | } |
|
26 | Qt::CaseInsensitive) == 0; | |
33 | } |
|
27 | }); | |
34 |
|
28 | if(similar_item == std::cend(root)) return nullptr; | ||
35 |
return |
|
29 | return similar_item->get(); | |
36 | } |
|
30 | } | |
37 |
|
31 | |||
38 | } // namespace |
|
32 | } // namespace | |
39 |
|
33 | |||
40 |
void DataSourceItemMergeHelper::merge(const DataSourceItem |
|
34 | void DataSourceItemMergeHelper::merge(const DataSourceItem& source, | |
|
35 | DataSourceItem& dest) | |||
41 | { |
|
36 | { | |
42 |
|
|
37 | // Checks if the source item can be merged into the destination item (i.e. | |
43 |
|
|
38 | // there is a child item similar to the source item) | |
44 |
|
|
39 | if(auto subItem = findSimilarItem(source, dest)) | |
45 | // If there is an item similar to the source item, applies the merge recursively |
|
40 | { | |
46 | for (auto i = 0, count = source.childCount(); i < count; ++i) { |
|
41 | // If there is an item similar to the source item, applies the merge | |
47 | merge(*source.child(i), *subItem); |
|
42 | // recursively | |
48 | } |
|
43 | std::for_each(std::cbegin(source), std::cend(source), | |
49 | } |
|
44 | [subItem](auto& child) { merge(*child.get(), *subItem); }); | |
50 | else { |
|
45 | } | |
51 | // If no item is similar to the source item, the item is copied as the child of the |
|
46 | else | |
52 | // destination item |
|
47 | { | |
53 | dest.appendChild(source.clone()); |
|
48 | // If no item is similar to the source item, the item is copied as the child | |
54 | } |
|
49 | // of the destination item | |
|
50 | if(std::cend(dest) == std::find_if(std::cbegin(dest), std::cend(dest), | |||
|
51 | [&source](const auto& child) | |||
|
52 | {return source.type() != DataSourceItemType::NODE && source.name()==child->name() && source.data()==child->data();})) | |||
|
53 | dest.appendChild(source.clone()); | |||
|
54 | } | |||
55 | } |
|
55 | } |
@@ -226,7 +226,7 class VariableController2::VariableController2Private | |||||
226 | } |
|
226 | } | |
227 | else // force new range to all variables -> may be weird if more than one |
|
227 | else // force new range to all variables -> may be weird if more than one | |
228 | // var in the group |
|
228 | // var in the group | |
229 |
// |
|
229 | // TODO ensure that there is no side effects | |
230 | { |
|
230 | { | |
231 | for(auto varId : group->variables()) |
|
231 | for(auto varId : group->variables()) | |
232 | { |
|
232 | { |
General Comments 0
You need to be logged in to leave comments.
Login now