##// END OF EJS Templates
New methods to find a datasource item from its product ID_KEY
trabillard -
r1286:29270c1078f4
parent child
Show More
@@ -1,102 +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 /// Request the creation of a variable from the ID_DATA_KEY of a product
79 void requestVariable(const QString &datasourceIdKey);
80
81 /// Request the creation of a variable from metadata of a product
78 82 void requestVariable(const QVariantHash &productData);
79 83
80 84 signals:
81 85 /// Signal emitted when a structure has been set for a data source
82 86 void dataSourceItemSet(DataSourceItem *dataSourceItem);
83 87
84 88 /**
85 89 * Signal emitted when a variable creation is asked for a product
86 90 * @param variableName the name of the variable
87 91 * @param variableMetadata the metadata of the variable
88 92 * @param variableProvider the provider that will be used to retrieve the data of the variable
89 93 * (can be null)
90 94 */
91 95 void variableCreationRequested(const QString &variableName,
92 96 const QVariantHash &variableMetadata,
93 97 std::shared_ptr<IDataProvider> variableProvider);
94 98
95 99 private:
96 100 void waitForFinish();
97 101
98 102 class DataSourceControllerPrivate;
99 103 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
100 104 };
101 105
102 106 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,156 +1,164
1 1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 2 #define SCIQLOP_DATASOURCEITEM_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QVariant>
9 9 #include <QVector>
10 10
11 11 class DataSourceItemAction;
12 12
13 13 /**
14 14 * Possible types of an item
15 15 */
16 16 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
17 17
18 18 /**
19 19 * @brief The DataSourceItem class aims to represent a structure element of a data source.
20 20 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
21 21 * containing other DataSourceItem objects (children).
22 22 * For each DataSourceItem can be associated a set of data representing it.
23 23 */
24 24 class SCIQLOP_CORE_EXPORT DataSourceItem {
25 25 public:
26 26 /// Key associated with the name of the item
27 27 static const QString NAME_DATA_KEY;
28 28 /// Key associated with the plugin of the item
29 29 static const QString PLUGIN_DATA_KEY;
30 30 /// Key associated with a unique id of the plugin
31 31 static const QString ID_DATA_KEY;
32 32
33 33 explicit DataSourceItem(DataSourceItemType type, const QString &name);
34 34 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
35 35
36 36 std::unique_ptr<DataSourceItem> clone() const;
37 37
38 38 /// @return the actions of the item as a vector
39 39 QVector<DataSourceItemAction *> actions() const noexcept;
40 40
41 41 /**
42 42 * Adds an action to the item. The item takes ownership of the action, and the action is
43 43 * automatically associated to the item
44 44 * @param action the action to add
45 45 */
46 46 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
47 47
48 48 /**
49 49 * Adds a child to the item. The item takes ownership of the child.
50 50 * @param child the child to add
51 51 */
52 52 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
53 53
54 54 /**
55 55 * Returns the item's child associated to an index
56 56 * @param childIndex the index to search
57 57 * @return a pointer to the child if index is valid, nullptr otherwise
58 58 */
59 59 DataSourceItem *child(int childIndex) const noexcept;
60 60
61 61 int childCount() const noexcept;
62 62
63 63 /**
64 64 * Get the data associated to a key
65 65 * @param key the key to search
66 66 * @return the data found if key is valid, default QVariant otherwise
67 67 */
68 68 QVariant data(const QString &key) const noexcept;
69 69
70 70 /// Gets all data
71 71 QVariantHash data() const noexcept;
72 72
73 73 /**
74 74 * Merge in the item the source item passed as parameter.
75 75 *
76 76 * The merge is done by adding as child of the item the complete tree represented by the source
77 77 * item. If a part of the tree already exists in the item (based on the name of the nodes), it
78 78 * is merged by completing the existing tree by items "leaves" (products, components or nodes
79 79 * with no child).
80 80 *
81 81 * For example, with item representing the tree:
82 82 * R (root node)
83 83 * - N1 (node)
84 84 * -- N11 (node)
85 85 * --- P1 (product)
86 86 * --- P2 (product)
87 87 * - N2 (node)
88 88 *
89 89 * and the source item representing the tree:
90 90 * N1 (root node)
91 91 * - N11 (node)
92 92 * -- P3 (product)
93 93 * - N12 (node)
94 94 *
95 95 * The leaves of the source item to merge into the item are N1/N11/P3 and N1/N12 => we therefore
96 96 * have the following merge result:
97 97 * R
98 98 * - N1
99 99 * -- N11
100 100 * --- P1
101 101 * --- P2
102 102 * --- P3 (added leaf)
103 103 * -- N12 (added leaf)
104 104 *
105 105 * @param item the source item
106 106 * @remarks No control is performed on products or components that are merged into the same tree
107 107 * part (two products or components may have the same name)
108 108 * @remarks the merge is made by copy (source item is not changed and still exists after the
109 109 * operation)
110 110 */
111 111 void merge(const DataSourceItem &item);
112 112
113 113 bool isRoot() const noexcept;
114 114
115 115 QString name() const noexcept;
116 116
117 117 /**
118 118 * Get the item's parent
119 119 * @return a pointer to the parent if it exists, nullptr if the item is a root
120 120 */
121 121 DataSourceItem *parentItem() const noexcept;
122 122
123 123 /**
124 124 * Gets the item's root
125 125 * @return the top parent, the item itself if it's the root item
126 126 */
127 127 const DataSourceItem &rootItem() const noexcept;
128 128
129 129 /**
130 130 * Sets or appends a value to a key
131 131 * @param key the key
132 132 * @param value the value
133 133 * @param append if true, the value is added to the values already existing for the key,
134 134 * otherwise it replaces the existing values
135 135 */
136 136 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
137 137
138 138 DataSourceItemType type() const noexcept;
139 139
140 140 /**
141 141 * @brief Searches the first child matching the specified data.
142 142 * @param data The data to search.
143 143 * @param recursive So the search recursively.
144 144 * @return the item matching the data or nullptr if it was not found.
145 145 */
146 146 DataSourceItem *findItem(const QVariantHash &data, bool recursive);
147 147
148 /**
149 * @brief Searches the first child matching the specified \p ID_DATA_KEY in its metadata.
150 * @param id The id to search.
151 * @param recursive So the search recursively.
152 * @return the item matching the data or nullptr if it was not found.
153 */
154 DataSourceItem *findItem(const QString &datasourceIdKey, bool recursive);
155
148 156 bool operator==(const DataSourceItem &other);
149 157 bool operator!=(const DataSourceItem &other);
150 158
151 159 private:
152 160 class DataSourceItemPrivate;
153 161 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
154 162 };
155 163
156 164 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,169 +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
41 // Search for the first datasource item matching the specified ID_DATA_KEY
42 DataSourceItem *findDataSourceItem(const QString &datasourceIdKey)
43 {
44 DataSourceItem *sourceItem = nullptr;
45 for (const auto &item : m_DataSourceItems) {
46 sourceItem = item.second->findItem(datasourceIdKey, true);
47 if (sourceItem) {
48 break;
49 }
50 }
51
52 return sourceItem;
53 }
40 54 };
41 55
42 56 DataSourceController::DataSourceController(QObject *parent)
43 57 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
44 58 {
45 59 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
46 60 << QThread::currentThread();
47 61 }
48 62
49 63 DataSourceController::~DataSourceController()
50 64 {
51 65 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
52 66 << QThread::currentThread();
53 67 this->waitForFinish();
54 68 }
55 69
56 70 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
57 71 {
58 72 auto dataSourceUid = QUuid::createUuid();
59 73 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
60 74
61 75 return dataSourceUid;
62 76 }
63 77
64 78 void DataSourceController::setDataSourceItem(
65 79 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
66 80 {
67 81 if (!dataSourceItem) {
68 82 qCWarning(LOG_DataSourceController())
69 83 << tr("Data source item can't be registered (null item)");
70 84 return;
71 85 }
72 86
73 87 if (impl->m_DataSources.contains(dataSourceUid)) {
74 88 // The data provider is implicitly converted to a shared_ptr
75 89 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
76 90
77 91 // Retrieves the data source item to emit the signal with it
78 92 auto it = impl->m_DataSourceItems.find(dataSourceUid);
79 93 if (it != impl->m_DataSourceItems.end()) {
80 94 emit dataSourceItemSet(it->second.get());
81 95 }
82 96 }
83 97 else {
84 98 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
85 99 "data source has been registered with the uid")
86 100 .arg(dataSourceUid.toString());
87 101 }
88 102 }
89 103
90 104 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
91 105 std::unique_ptr<IDataProvider> dataProvider) noexcept
92 106 {
93 107 if (impl->m_DataSources.contains(dataSourceUid)) {
94 108 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
95 109 }
96 110 else {
97 111 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
98 112 "source has been registered with the uid")
99 113 .arg(dataSourceUid.toString());
100 114 }
101 115 }
102 116
103 117 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
104 118 const DataSourceItem &productItem) noexcept
105 119 {
106 120 if (productItem.type() == DataSourceItemType::PRODUCT
107 121 || productItem.type() == DataSourceItemType::COMPONENT) {
108 122 /// Retrieves the data provider of the data source (if any)
109 123 auto it = impl->m_DataProviders.find(dataSourceUid);
110 124 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
111 125
112 126 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
113 127 }
114 128 else {
115 129 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
116 130 }
117 131 }
118 132
119 133 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
120 134 {
121 135 QByteArray encodedData;
122 136 QDataStream stream{&encodedData, QIODevice::WriteOnly};
123 137
124 138 stream << productsData;
125 139
126 140 return encodedData;
127 141 }
128 142
129 143 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
130 144 {
131 145 QDataStream stream{mimeData};
132 146
133 147 QVariantList productList;
134 148 stream >> productList;
135 149
136 150 return productList;
137 151 }
138 152
139 153 void DataSourceController::initialize()
140 154 {
141 155 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
142 156 << QThread::currentThread();
143 157 impl->m_WorkingMutex.lock();
144 158 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
145 159 }
146 160
147 161 void DataSourceController::finalize()
148 162 {
149 163 impl->m_WorkingMutex.unlock();
150 164 }
151 165
166 void DataSourceController::requestVariable(const QString &datasourceIdKey)
167 {
168 auto sourceItem = impl->findDataSourceItem(datasourceIdKey);
169
170 if (sourceItem) {
171 auto sourceName = sourceItem->rootItem().name();
172 auto sourceId = impl->m_DataSources.key(sourceName);
173 loadProductItem(sourceId, *sourceItem);
174 }
175 else {
176 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
177 }
178 }
179
152 180 void DataSourceController::requestVariable(const QVariantHash &productData)
153 181 {
154 182 auto sourceItem = impl->findDataSourceItem(productData);
155 183
156 184 if (sourceItem) {
157 185 auto sourceName = sourceItem->rootItem().name();
158 186 auto sourceId = impl->m_DataSources.key(sourceName);
159 187 loadProductItem(sourceId, *sourceItem);
160 188 }
161 189 else {
162 190 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
163 191 }
164 192 }
165 193
166 194 void DataSourceController::waitForFinish()
167 195 {
168 196 QMutexLocker locker{&impl->m_WorkingMutex};
169 197 }
@@ -1,187 +1,205
1 1 #include <DataSource/DataSourceItem.h>
2 2 #include <DataSource/DataSourceItemAction.h>
3 3 #include <DataSource/DataSourceItemMergeHelper.h>
4 4
5 5 #include <QVector>
6 6
7 7 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
8 8 const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin");
9 9 const QString DataSourceItem::ID_DATA_KEY = QStringLiteral("uuid");
10 10
11 11 struct DataSourceItem::DataSourceItemPrivate {
12 12 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
13 13 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
14 14 {
15 15 }
16 16
17 17 DataSourceItem *m_Parent;
18 18 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
19 19 DataSourceItemType m_Type;
20 20 QVariantHash m_Data;
21 21 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
22 22 };
23 23
24 24 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
25 25 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
26 26 {
27 27 }
28 28
29 29 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
30 30 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
31 31 {
32 32 }
33 33
34 34 std::unique_ptr<DataSourceItem> DataSourceItem::clone() const
35 35 {
36 36 auto result = std::make_unique<DataSourceItem>(impl->m_Type, impl->m_Data);
37 37
38 38 // Clones children
39 39 for (const auto &child : impl->m_Children) {
40 40 result->appendChild(std::move(child->clone()));
41 41 }
42 42
43 43 // Clones actions
44 44 for (const auto &action : impl->m_Actions) {
45 45 result->addAction(std::move(action->clone()));
46 46 }
47 47
48 48 return result;
49 49 }
50 50
51 51 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
52 52 {
53 53 auto result = QVector<DataSourceItemAction *>{};
54 54
55 55 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
56 56 std::back_inserter(result), [](const auto &action) { return action.get(); });
57 57
58 58 return result;
59 59 }
60 60
61 61 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
62 62 {
63 63 action->setDataSourceItem(this);
64 64 impl->m_Actions.push_back(std::move(action));
65 65 }
66 66
67 67 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
68 68 {
69 69 child->impl->m_Parent = this;
70 70 impl->m_Children.push_back(std::move(child));
71 71 }
72 72
73 73 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
74 74 {
75 75 if (childIndex < 0 || childIndex >= childCount()) {
76 76 return nullptr;
77 77 }
78 78 else {
79 79 return impl->m_Children.at(childIndex).get();
80 80 }
81 81 }
82 82
83 83 int DataSourceItem::childCount() const noexcept
84 84 {
85 85 return impl->m_Children.size();
86 86 }
87 87
88 88 QVariant DataSourceItem::data(const QString &key) const noexcept
89 89 {
90 90 return impl->m_Data.value(key);
91 91 }
92 92
93 93 QVariantHash DataSourceItem::data() const noexcept
94 94 {
95 95 return impl->m_Data;
96 96 }
97 97
98 98 void DataSourceItem::merge(const DataSourceItem &item)
99 99 {
100 100 DataSourceItemMergeHelper::merge(item, *this);
101 101 }
102 102
103 103 bool DataSourceItem::isRoot() const noexcept
104 104 {
105 105 return impl->m_Parent == nullptr;
106 106 }
107 107
108 108 QString DataSourceItem::name() const noexcept
109 109 {
110 110 return data(NAME_DATA_KEY).toString();
111 111 }
112 112
113 113 DataSourceItem *DataSourceItem::parentItem() const noexcept
114 114 {
115 115 return impl->m_Parent;
116 116 }
117 117
118 118 const DataSourceItem &DataSourceItem::rootItem() const noexcept
119 119 {
120 120 return isRoot() ? *this : parentItem()->rootItem();
121 121 }
122 122
123 123 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
124 124 {
125 125 auto it = impl->m_Data.constFind(key);
126 126 if (append && it != impl->m_Data.constEnd()) {
127 127 // Case of an existing value to which we want to add to the new value
128 128 if (it->canConvert<QVariantList>()) {
129 129 auto variantList = it->value<QVariantList>();
130 130 variantList.append(value);
131 131
132 132 impl->m_Data.insert(key, variantList);
133 133 }
134 134 else {
135 135 impl->m_Data.insert(key, QVariantList{*it, value});
136 136 }
137 137 }
138 138 else {
139 139 // Other cases :
140 140 // - new value in map OR
141 141 // - replacement of an existing value (not appending)
142 142 impl->m_Data.insert(key, value);
143 143 }
144 144 }
145 145
146 146 DataSourceItemType DataSourceItem::type() const noexcept
147 147 {
148 148 return impl->m_Type;
149 149 }
150 150
151 151 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive)
152 152 {
153 153 for (const auto &child : impl->m_Children) {
154 154 if (child->impl->m_Data == data) {
155 155 return child.get();
156 156 }
157 157
158 158 if (recursive) {
159 159 if (auto foundItem = child->findItem(data, true)) {
160 160 return foundItem;
161 161 }
162 162 }
163 163 }
164 164
165 165 return nullptr;
166 166 }
167 167
168 DataSourceItem *DataSourceItem::findItem(const QString &datasourceIdKey, bool recursive)
169 {
170 for (const auto &child : impl->m_Children) {
171 auto childId = child->impl->m_Data.value(ID_DATA_KEY);
172 if (childId == datasourceIdKey) {
173 return child.get();
174 }
175
176 if (recursive) {
177 if (auto foundItem = child->findItem(datasourceIdKey, true)) {
178 return foundItem;
179 }
180 }
181 }
182
183 return nullptr;
184 }
185
168 186 bool DataSourceItem::operator==(const DataSourceItem &other)
169 187 {
170 188 // Compares items' attributes
171 189 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
172 190 // Compares contents of items' children
173 191 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
174 192 std::cbegin(other.impl->m_Children), std::cend(other.impl->m_Children),
175 193 [](const auto &itemChild, const auto &otherChild) {
176 194 return *itemChild == *otherChild;
177 195 });
178 196 }
179 197 else {
180 198 return false;
181 199 }
182 200 }
183 201
184 202 bool DataSourceItem::operator!=(const DataSourceItem &other)
185 203 {
186 204 return !(*this == other);
187 205 }
General Comments 0
You need to be logged in to leave comments. Login now