##// END OF EJS Templates
Inits merge method of two items
Alexandre Leroux -
r1031:b92faa6e4b21
parent child
Show More
@@ -0,0 +1,15
1 #ifndef SCIQLOP_DATASOURCEITEMMERGEHELPER_H
2 #define SCIQLOP_DATASOURCEITEMMERGEHELPER_H
3
4 class DataSourceItem;
5
6 /**
7 * @brief The DataSourceItemMergeHelper struct is used to merge two data source items
8 * @sa DataSourceItem::merge()
9 */
10 struct DataSourceItemMergeHelper {
11 /// Merges source item into dest item
12 static void merge(const DataSourceItem &source, DataSourceItem &dest);
13 };
14
15 #endif // SCIQLOP_DATASOURCEITEMMERGEHELPER_H
@@ -0,0 +1,8
1 #include "DataSource/DataSourceItemMergeHelper.h"
2
3 #include <DataSource/DataSourceItem.h>
4
5 void DataSourceItemMergeHelper::merge(const DataSourceItem &source, DataSourceItem &dest)
6 {
7 /// @todo ALX
8 }
@@ -1,110 +1,150
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
29 29 explicit DataSourceItem(DataSourceItemType type, const QString &name);
30 30 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
31 31
32 32 /// @return the actions of the item as a vector
33 33 QVector<DataSourceItemAction *> actions() const noexcept;
34 34
35 35 /**
36 36 * Adds an action to the item. The item takes ownership of the action, and the action is
37 37 * automatically associated to the item
38 38 * @param action the action to add
39 39 */
40 40 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
41 41
42 42 /**
43 43 * Adds a child to the item. The item takes ownership of the child.
44 44 * @param child the child to add
45 45 */
46 46 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
47 47
48 48 /**
49 49 * Returns the item's child associated to an index
50 50 * @param childIndex the index to search
51 51 * @return a pointer to the child if index is valid, nullptr otherwise
52 52 */
53 53 DataSourceItem *child(int childIndex) const noexcept;
54 54
55 55 int childCount() const noexcept;
56 56
57 57 /**
58 58 * Get the data associated to a key
59 59 * @param key the key to search
60 60 * @return the data found if key is valid, default QVariant otherwise
61 61 */
62 62 QVariant data(const QString &key) const noexcept;
63 63
64 64 /// Gets all data
65 65 QVariantHash data() const noexcept;
66 66
67 /**
68 * Merge in the item the source item passed as parameter.
69 *
70 * The merge is done by adding as child of the item the complete tree represented by the source
71 * item. If a part of the tree already exists in the item (based on the name of the nodes), it
72 * is merged by completing the existing tree by items "leaves" (products, components or nodes
73 * with no child).
74 *
75 * For example, with item representing the tree:
76 * R (root node)
77 * - N1 (node)
78 * -- N11 (node)
79 * --- P1 (product)
80 * --- P2 (product)
81 * - N2 (node)
82 *
83 * and the source item representing the tree:
84 * N1 (root node)
85 * - N11 (node)
86 * -- P3 (product)
87 * - N12 (node)
88 *
89 * The leaves of the source item to merge into the item are N1/N11/P3 and N1/N12 => we therefore
90 * have the following merge result:
91 * R
92 * - N1
93 * -- N11
94 * --- P1
95 * --- P2
96 * --- P3 (added leaf)
97 * -- N12 (added leaf)
98 *
99 * @param item the source item
100 * @remarks No control is performed on products or components that are merged into the same tree
101 * part (two products or components may have the same name)
102 * @remarks the merge is made by copy (source item is not changed and still exists after the
103 * operation)
104 */
105 void merge(const DataSourceItem &item);
106
67 107 bool isRoot() const noexcept;
68 108
69 109 QString name() const noexcept;
70 110
71 111 /**
72 112 * Get the item's parent
73 113 * @return a pointer to the parent if it exists, nullptr if the item is a root
74 114 */
75 115 DataSourceItem *parentItem() const noexcept;
76 116
77 117 /**
78 118 * Gets the item's root
79 119 * @return the top parent, the item itself if it's the root item
80 120 */
81 121 const DataSourceItem &rootItem() const noexcept;
82 122
83 123 /**
84 124 * Sets or appends a value to a key
85 125 * @param key the key
86 126 * @param value the value
87 127 * @param append if true, the value is added to the values already existing for the key,
88 128 * otherwise it replaces the existing values
89 129 */
90 130 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
91 131
92 132 DataSourceItemType type() const noexcept;
93 133
94 134 /**
95 135 * @brief Searches the first child matching the specified data.
96 136 * @param data The data to search.
97 137 * @param recursive So the search recursively.
98 138 * @return the item matching the data or nullptr if it was not found.
99 139 */
100 140 DataSourceItem *findItem(const QVariantHash &data, bool recursive);
101 141
102 142 bool operator==(const DataSourceItem &other);
103 143 bool operator!=(const DataSourceItem &other);
104 144
105 145 private:
106 146 class DataSourceItemPrivate;
107 147 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
108 148 };
109 149
110 150 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,65 +1,66
1 1
2 2 core_moc_headers = [
3 3 'include/Data/IDataProvider.h',
4 4 'include/DataSource/DataSourceController.h',
5 5 'include/DataSource/DataSourceItemAction.h',
6 6 'include/Network/NetworkController.h',
7 7 'include/Time/TimeController.h',
8 8 'include/Variable/Variable.h',
9 9 'include/Variable/VariableCacheController.h',
10 10 'include/Variable/VariableController.h',
11 11 'include/Variable/VariableAcquisitionWorker.h',
12 12 'include/Variable/VariableSynchronizationGroup.h',
13 13 'include/Variable/VariableModel.h',
14 14 'include/Visualization/VisualizationController.h'
15 15 ]
16 16
17 17
18 18 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
19 19
20 20 core_sources = [
21 21 'src/Common/DateUtils.cpp',
22 22 'src/Common/StringUtils.cpp',
23 23 'src/Common/MimeTypesDef.cpp',
24 24 'src/Data/ScalarSeries.cpp',
25 25 'src/Data/SpectrogramSeries.cpp',
26 26 'src/Data/DataSeriesIterator.cpp',
27 27 'src/Data/ArrayDataIterator.cpp',
28 28 'src/Data/VectorSeries.cpp',
29 29 'src/Data/OptionalAxis.cpp',
30 30 'src/Data/DataSeriesUtils.cpp',
31 31 'src/DataSource/DataSourceController.cpp',
32 32 'src/DataSource/DataSourceItem.cpp',
33 33 'src/DataSource/DataSourceItemAction.cpp',
34 'src/DataSource/DataSourceItemMergeHelper.cpp',
34 35 'src/Network/NetworkController.cpp',
35 36 'src/Plugin/PluginManager.cpp',
36 37 'src/Settings/SqpSettingsDefs.cpp',
37 38 'src/Time/TimeController.cpp',
38 39 'src/Variable/Variable.cpp',
39 40 'src/Variable/VariableCacheController.cpp',
40 41 'src/Variable/VariableController.cpp',
41 42 'src/Variable/VariableAcquisitionWorker.cpp',
42 43 'src/Variable/VariableSynchronizationGroup.cpp',
43 44 'src/Variable/VariableModel.cpp',
44 45 'src/Visualization/VisualizationController.cpp'
45 46 ]
46 47
47 48 core_inc = include_directories(['include', '../plugin/include'])
48 49
49 50 sciqlop_core_lib = library('sciqlopcore',
50 51 core_sources,
51 52 core_moc_files,
52 53 cpp_args : '-DCORE_LIB',
53 54 include_directories : core_inc,
54 55 dependencies : [qt5core, qt5network],
55 56 install : true
56 57 )
57 58
58 59
59 60 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
60 61 include_directories : core_inc,
61 62 dependencies : [qt5core, qt5network])
62 63
63 64
64 65 subdir('tests')
65 66
@@ -1,162 +1,168
1 1 #include <DataSource/DataSourceItem.h>
2 2 #include <DataSource/DataSourceItemAction.h>
3 #include <DataSource/DataSourceItemMergeHelper.h>
3 4
4 5 #include <QVector>
5 6
6 7 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
7 8
8 9 struct DataSourceItem::DataSourceItemPrivate {
9 10 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
10 11 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
11 12 {
12 13 }
13 14
14 15 DataSourceItem *m_Parent;
15 16 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
16 17 DataSourceItemType m_Type;
17 18 QVariantHash m_Data;
18 19 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
19 20 };
20 21
21 22 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
22 23 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
23 24 {
24 25 }
25 26
26 27 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
27 28 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
28 29 {
29 30 }
30 31
31 32 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
32 33 {
33 34 auto result = QVector<DataSourceItemAction *>{};
34 35
35 36 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
36 37 std::back_inserter(result), [](const auto &action) { return action.get(); });
37 38
38 39 return result;
39 40 }
40 41
41 42 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
42 43 {
43 44 action->setDataSourceItem(this);
44 45 impl->m_Actions.push_back(std::move(action));
45 46 }
46 47
47 48 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
48 49 {
49 50 child->impl->m_Parent = this;
50 51 impl->m_Children.push_back(std::move(child));
51 52 }
52 53
53 54 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
54 55 {
55 56 if (childIndex < 0 || childIndex >= childCount()) {
56 57 return nullptr;
57 58 }
58 59 else {
59 60 return impl->m_Children.at(childIndex).get();
60 61 }
61 62 }
62 63
63 64 int DataSourceItem::childCount() const noexcept
64 65 {
65 66 return impl->m_Children.size();
66 67 }
67 68
68 69 QVariant DataSourceItem::data(const QString &key) const noexcept
69 70 {
70 71 return impl->m_Data.value(key);
71 72 }
72 73
73 74 QVariantHash DataSourceItem::data() const noexcept
74 75 {
75 76 return impl->m_Data;
76 77 }
77 78
79 void DataSourceItem::merge(const DataSourceItem &item)
80 {
81 DataSourceItemMergeHelper::merge(item, *this);
82 }
83
78 84 bool DataSourceItem::isRoot() const noexcept
79 85 {
80 86 return impl->m_Parent == nullptr;
81 87 }
82 88
83 89 QString DataSourceItem::name() const noexcept
84 90 {
85 91 return data(NAME_DATA_KEY).toString();
86 92 }
87 93
88 94 DataSourceItem *DataSourceItem::parentItem() const noexcept
89 95 {
90 96 return impl->m_Parent;
91 97 }
92 98
93 99 const DataSourceItem &DataSourceItem::rootItem() const noexcept
94 100 {
95 101 return isRoot() ? *this : parentItem()->rootItem();
96 102 }
97 103
98 104 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
99 105 {
100 106 auto it = impl->m_Data.constFind(key);
101 107 if (append && it != impl->m_Data.constEnd()) {
102 108 // Case of an existing value to which we want to add to the new value
103 109 if (it->canConvert<QVariantList>()) {
104 110 auto variantList = it->value<QVariantList>();
105 111 variantList.append(value);
106 112
107 113 impl->m_Data.insert(key, variantList);
108 114 }
109 115 else {
110 116 impl->m_Data.insert(key, QVariantList{*it, value});
111 117 }
112 118 }
113 119 else {
114 120 // Other cases :
115 121 // - new value in map OR
116 122 // - replacement of an existing value (not appending)
117 123 impl->m_Data.insert(key, value);
118 124 }
119 125 }
120 126
121 127 DataSourceItemType DataSourceItem::type() const noexcept
122 128 {
123 129 return impl->m_Type;
124 130 }
125 131
126 132 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive)
127 133 {
128 134 for (const auto &child : impl->m_Children) {
129 135 if (child->impl->m_Data == data) {
130 136 return child.get();
131 137 }
132 138
133 139 if (recursive) {
134 140 if (auto foundItem = child->findItem(data, true)) {
135 141 return foundItem;
136 142 }
137 143 }
138 144 }
139 145
140 146 return nullptr;
141 147 }
142 148
143 149 bool DataSourceItem::operator==(const DataSourceItem &other)
144 150 {
145 151 // Compares items' attributes
146 152 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
147 153 // Compares contents of items' children
148 154 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
149 155 std::cbegin(other.impl->m_Children),
150 156 [](const auto &itemChild, const auto &otherChild) {
151 157 return *itemChild == *otherChild;
152 158 });
153 159 }
154 160 else {
155 161 return false;
156 162 }
157 163 }
158 164
159 165 bool DataSourceItem::operator!=(const DataSourceItem &other)
160 166 {
161 167 return !(*this == other);
162 168 }
General Comments 0
You need to be logged in to leave comments. Login now