@@ -0,0 +1,35 | |||
|
1 | #ifndef SCIQLOP_STRINGUTILS_H | |
|
2 | #define SCIQLOP_STRINGUTILS_H | |
|
3 | ||
|
4 | #include "CoreGlobal.h" | |
|
5 | ||
|
6 | #include <vector> | |
|
7 | ||
|
8 | class QString; | |
|
9 | ||
|
10 | /** | |
|
11 | * Utility class with methods for strings | |
|
12 | */ | |
|
13 | struct SCIQLOP_CORE_EXPORT StringUtils { | |
|
14 | /** | |
|
15 | * Generates a unique name from a default name and a set of forbidden names. | |
|
16 | * | |
|
17 | * Generating the unique name is done by adding an index to the default name and stopping at the | |
|
18 | * first index for which the generated name is not in the forbidden names. | |
|
19 | * | |
|
20 | * Examples (defaultName, forbiddenNames -> result): | |
|
21 | * - "FGM", {"FGM"} -> "FGM1" | |
|
22 | * - "FGM", {"ABC"} -> "FGM" | |
|
23 | * - "FGM", {"FGM", "FGM1"} -> "FGM2" | |
|
24 | * - "FGM", {"FGM", "FGM2"} -> "FGM1" | |
|
25 | * - "", {"ABC"} -> "1" | |
|
26 | * | |
|
27 | * @param defaultName the default name | |
|
28 | * @param forbiddenNames the set of forbidden names | |
|
29 | * @return the unique name generated | |
|
30 | */ | |
|
31 | static QString uniqueName(const QString &defaultName, | |
|
32 | const std::vector<QString> &forbiddenNames) noexcept; | |
|
33 | }; | |
|
34 | ||
|
35 | #endif // SCIQLOP_STRINGUTILS_H |
@@ -0,0 +1,30 | |||
|
1 | #include "Common/StringUtils.h" | |
|
2 | ||
|
3 | #include <QRegExp> | |
|
4 | #include <QString> | |
|
5 | ||
|
6 | #include <set> | |
|
7 | ||
|
8 | QString StringUtils::uniqueName(const QString &defaultName, | |
|
9 | const std::vector<QString> &forbiddenNames) noexcept | |
|
10 | { | |
|
11 | // Gets the base of the unique name to generate, by removing trailing number (for example, base | |
|
12 | // name of "FGM12" is "FGM") | |
|
13 | auto baseName = defaultName; | |
|
14 | baseName.remove(QRegExp{QStringLiteral("\\d*$")}); | |
|
15 | ||
|
16 | // Finds the unique name by adding an index to the base name and stops when the generated name | |
|
17 | // isn't forbidden | |
|
18 | QString newName{}; | |
|
19 | auto forbidden = true; | |
|
20 | for (auto i = 0; forbidden; ++i) { | |
|
21 | newName = (i == 0) ? baseName : baseName + QString::number(i); | |
|
22 | forbidden = newName.isEmpty() | |
|
23 | || std::any_of(forbiddenNames.cbegin(), forbiddenNames.cend(), | |
|
24 | [&newName](const auto &name) { | |
|
25 | return name.compare(newName, Qt::CaseInsensitive) == 0; | |
|
26 | }); | |
|
27 | } | |
|
28 | ||
|
29 | return newName; | |
|
30 | } |
@@ -0,0 +1,50 | |||
|
1 | #include <Common/StringUtils.h> | |
|
2 | ||
|
3 | #include <QObject> | |
|
4 | #include <QtTest> | |
|
5 | ||
|
6 | class TestStringUtils : public QObject { | |
|
7 | Q_OBJECT | |
|
8 | ||
|
9 | private slots: | |
|
10 | void testUniqueName_data(); | |
|
11 | void testUniqueName(); | |
|
12 | }; | |
|
13 | ||
|
14 | void TestStringUtils::testUniqueName_data() | |
|
15 | { | |
|
16 | // ////////////// // | |
|
17 | // Test structure // | |
|
18 | // ////////////// // | |
|
19 | ||
|
20 | QTest::addColumn<QString>("defaultName"); | |
|
21 | QTest::addColumn<std::vector<QString> >("forbiddenNames"); | |
|
22 | QTest::addColumn<QString>("expectedName"); | |
|
23 | ||
|
24 | // ////////// // | |
|
25 | // Test cases // | |
|
26 | // ////////// // | |
|
27 | ||
|
28 | QTest::newRow("uniqueName") << "FGM" << std::vector<QString>{"FGM2"} << "FGM"; | |
|
29 | QTest::newRow("uniqueName2") << "FGM2" << std::vector<QString>{"FGM", "FGM1", "FGM2"} << "FGM3"; | |
|
30 | QTest::newRow("uniqueName3") << "FGM1" << std::vector<QString>{"FGM1"} << "FGM"; | |
|
31 | QTest::newRow("uniqueName4") << "FGM" << std::vector<QString>{"FGM"} << "FGM1"; | |
|
32 | QTest::newRow("uniqueName5") << "FGM" << std::vector<QString>{"FGM", "FGM1", "FGM3"} << "FGM2"; | |
|
33 | QTest::newRow("uniqueName6") << "FGM" << std::vector<QString>{"A", "B", "C"} << "FGM"; | |
|
34 | QTest::newRow("uniqueName7") << "FGM" << std::vector<QString>{"fGm", "FGm1", "Fgm2"} << "FGM3"; | |
|
35 | QTest::newRow("uniqueName8") << "" << std::vector<QString>{"A", "B", "C"} << "1"; | |
|
36 | QTest::newRow("uniqueName9") << "24" << std::vector<QString>{"A", "B", "C"} << "1"; | |
|
37 | } | |
|
38 | ||
|
39 | void TestStringUtils::testUniqueName() | |
|
40 | { | |
|
41 | QFETCH(QString, defaultName); | |
|
42 | QFETCH(std::vector<QString>, forbiddenNames); | |
|
43 | QFETCH(QString, expectedName); | |
|
44 | ||
|
45 | auto result = StringUtils::uniqueName(defaultName, forbiddenNames); | |
|
46 | QCOMPARE(result, expectedName); | |
|
47 | } | |
|
48 | ||
|
49 | QTEST_MAIN(TestStringUtils) | |
|
50 | #include "TestStringUtils.moc" |
@@ -1,62 +1,63 | |||
|
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/VariableCacheStrategy.h', |
|
13 | 13 | 'include/Variable/VariableSynchronizationGroup.h', |
|
14 | 14 | 'include/Variable/VariableModel.h', |
|
15 | 15 | 'include/Visualization/VisualizationController.h' |
|
16 | 16 | ] |
|
17 | 17 | |
|
18 | 18 | |
|
19 | 19 | core_moc_files = qt5.preprocess(moc_headers : core_moc_headers) |
|
20 | 20 | |
|
21 | 21 | core_sources = [ |
|
22 | 22 | 'src/Common/DateUtils.cpp', |
|
23 | 'src/Common/StringUtils.cpp', | |
|
23 | 24 | 'src/Data/ScalarSeries.cpp', |
|
24 | 25 | 'src/Data/DataSeriesIterator.cpp', |
|
25 | 26 | 'src/Data/ArrayDataIterator.cpp', |
|
26 | 27 | 'src/Data/VectorSeries.cpp', |
|
27 | 28 | 'src/DataSource/DataSourceController.cpp', |
|
28 | 29 | 'src/DataSource/DataSourceItem.cpp', |
|
29 | 30 | 'src/DataSource/DataSourceItemAction.cpp', |
|
30 | 31 | 'src/Network/NetworkController.cpp', |
|
31 | 32 | 'src/Plugin/PluginManager.cpp', |
|
32 | 33 | 'src/Settings/SqpSettingsDefs.cpp', |
|
33 | 34 | 'src/Time/TimeController.cpp', |
|
34 | 35 | 'src/Variable/Variable.cpp', |
|
35 | 36 | 'src/Variable/VariableCacheController.cpp', |
|
36 | 37 | 'src/Variable/VariableController.cpp', |
|
37 | 38 | 'src/Variable/VariableAcquisitionWorker.cpp', |
|
38 | 39 | 'src/Variable/VariableCacheStrategy.cpp', |
|
39 | 40 | 'src/Variable/VariableSynchronizationGroup.cpp', |
|
40 | 41 | 'src/Variable/VariableModel.cpp', |
|
41 | 42 | 'src/Visualization/VisualizationController.cpp' |
|
42 | 43 | ] |
|
43 | 44 | |
|
44 | 45 | core_inc = include_directories(['include', '../plugin/include']) |
|
45 | 46 | |
|
46 | 47 | sciqlop_core_lib = library('sciqlopcore', |
|
47 | 48 | core_sources, |
|
48 | 49 | core_moc_files, |
|
49 | 50 | cpp_args : '-DCORE_LIB', |
|
50 | 51 | include_directories : core_inc, |
|
51 | 52 | dependencies : [qt5core, qt5network], |
|
52 | 53 | install : true |
|
53 | 54 | ) |
|
54 | 55 | |
|
55 | 56 | |
|
56 | 57 | sciqlop_core = declare_dependency(link_with : sciqlop_core_lib, |
|
57 | 58 | include_directories : core_inc, |
|
58 | 59 | dependencies : [qt5core, qt5network]) |
|
59 | 60 | |
|
60 | 61 | |
|
61 | 62 | subdir('tests') |
|
62 | 63 |
@@ -1,269 +1,284 | |||
|
1 | 1 | #include <Variable/Variable.h> |
|
2 | 2 | #include <Variable/VariableModel.h> |
|
3 | 3 | |
|
4 | 4 | #include <Common/DateUtils.h> |
|
5 | #include <Common/StringUtils.h> | |
|
5 | 6 | |
|
6 | 7 | #include <Data/IDataSeries.h> |
|
7 | 8 | |
|
8 | 9 | #include <QSize> |
|
9 | 10 | #include <unordered_map> |
|
10 | 11 | |
|
11 | 12 | Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel") |
|
12 | 13 | |
|
13 | 14 | namespace { |
|
14 | 15 | |
|
15 | 16 | // Column indexes |
|
16 | 17 | const auto NAME_COLUMN = 0; |
|
17 | 18 | const auto TSTART_COLUMN = 1; |
|
18 | 19 | const auto TEND_COLUMN = 2; |
|
19 | 20 | const auto UNIT_COLUMN = 3; |
|
20 | 21 | const auto MISSION_COLUMN = 4; |
|
21 | 22 | const auto PLUGIN_COLUMN = 5; |
|
22 | 23 | const auto NB_COLUMNS = 6; |
|
23 | 24 | |
|
24 | 25 | // Column properties |
|
25 | 26 | const auto DEFAULT_HEIGHT = 25; |
|
26 | 27 | const auto DEFAULT_WIDTH = 100; |
|
27 | 28 | |
|
28 | 29 | struct ColumnProperties { |
|
29 | 30 | ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH, |
|
30 | 31 | int height = DEFAULT_HEIGHT) |
|
31 | 32 | : m_Name{name}, m_Width{width}, m_Height{height} |
|
32 | 33 | { |
|
33 | 34 | } |
|
34 | 35 | |
|
35 | 36 | QString m_Name; |
|
36 | 37 | int m_Width; |
|
37 | 38 | int m_Height; |
|
38 | 39 | }; |
|
39 | 40 | |
|
40 | 41 | const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{ |
|
41 | 42 | {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}}, |
|
42 | 43 | {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}}, |
|
43 | 44 | {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}}; |
|
44 | 45 | |
|
45 | 46 | /// Format for datetimes |
|
46 | 47 | const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz"); |
|
47 | 48 | |
|
49 | QString uniqueName(const QString &defaultName, | |
|
50 | const std::vector<std::shared_ptr<Variable> > &variables) | |
|
51 | { | |
|
52 | auto forbiddenNames = std::vector<QString>(variables.size()); | |
|
53 | std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(), | |
|
54 | [](const auto &variable) { return variable->name(); }); | |
|
55 | auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames); | |
|
56 | Q_ASSERT(!uniqueName.isEmpty()); | |
|
57 | ||
|
58 | return uniqueName; | |
|
59 | } | |
|
48 | 60 | |
|
49 | 61 | } // namespace |
|
50 | 62 | |
|
51 | 63 | struct VariableModel::VariableModelPrivate { |
|
52 | 64 | /// Variables created in SciQlop |
|
53 | 65 | std::vector<std::shared_ptr<Variable> > m_Variables; |
|
54 | 66 | std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress; |
|
55 | 67 | |
|
56 | 68 | /// Return the row index of the variable. -1 if it's not found |
|
57 | 69 | int indexOfVariable(Variable *variable) const noexcept; |
|
58 | 70 | }; |
|
59 | 71 | |
|
60 | 72 | VariableModel::VariableModel(QObject *parent) |
|
61 | 73 | : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()} |
|
62 | 74 | { |
|
63 | 75 | } |
|
64 | 76 | |
|
65 | 77 | void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept |
|
66 | 78 | { |
|
67 | 79 | auto insertIndex = rowCount(); |
|
68 | 80 | beginInsertRows({}, insertIndex, insertIndex); |
|
69 | 81 | |
|
82 | // Generates unique name for the variable | |
|
83 | variable->setName(uniqueName(variable->name(), impl->m_Variables)); | |
|
84 | ||
|
70 | 85 | impl->m_Variables.push_back(variable); |
|
71 | 86 | connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated); |
|
72 | 87 | |
|
73 | 88 | endInsertRows(); |
|
74 | 89 | } |
|
75 | 90 | |
|
76 | 91 | std::shared_ptr<Variable> VariableModel::createVariable(const QString &name, |
|
77 | 92 | const SqpRange &dateTime, |
|
78 | 93 | const QVariantHash &metadata) noexcept |
|
79 | 94 | { |
|
80 | 95 | auto variable = std::make_shared<Variable>(name, dateTime, metadata); |
|
81 | 96 | addVariable(variable); |
|
82 | 97 | |
|
83 | 98 | return variable; |
|
84 | 99 | } |
|
85 | 100 | |
|
86 | 101 | void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept |
|
87 | 102 | { |
|
88 | 103 | if (!variable) { |
|
89 | 104 | qCCritical(LOG_Variable()) << "Can't delete a null variable from the model"; |
|
90 | 105 | return; |
|
91 | 106 | } |
|
92 | 107 | |
|
93 | 108 | // Finds variable in the model |
|
94 | 109 | auto begin = impl->m_Variables.cbegin(); |
|
95 | 110 | auto end = impl->m_Variables.cend(); |
|
96 | 111 | auto it = std::find(begin, end, variable); |
|
97 | 112 | if (it != end) { |
|
98 | 113 | auto removeIndex = std::distance(begin, it); |
|
99 | 114 | |
|
100 | 115 | // Deletes variable |
|
101 | 116 | beginRemoveRows({}, removeIndex, removeIndex); |
|
102 | 117 | impl->m_Variables.erase(it); |
|
103 | 118 | endRemoveRows(); |
|
104 | 119 | } |
|
105 | 120 | else { |
|
106 | 121 | qCritical(LOG_VariableModel()) |
|
107 | 122 | << tr("Can't delete variable %1 from the model: the variable is not in the model") |
|
108 | 123 | .arg(variable->name()); |
|
109 | 124 | } |
|
110 | 125 | |
|
111 | 126 | // Removes variable from progress map |
|
112 | 127 | impl->m_VariableToProgress.erase(variable); |
|
113 | 128 | } |
|
114 | 129 | |
|
115 | 130 | |
|
116 | 131 | std::shared_ptr<Variable> VariableModel::variable(int index) const |
|
117 | 132 | { |
|
118 | 133 | return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr; |
|
119 | 134 | } |
|
120 | 135 | |
|
121 | 136 | std::vector<std::shared_ptr<Variable> > VariableModel::variables() const |
|
122 | 137 | { |
|
123 | 138 | return impl->m_Variables; |
|
124 | 139 | } |
|
125 | 140 | |
|
126 | 141 | void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress) |
|
127 | 142 | { |
|
128 | 143 | if (progress > 0.0) { |
|
129 | 144 | impl->m_VariableToProgress[variable] = progress; |
|
130 | 145 | } |
|
131 | 146 | else { |
|
132 | 147 | impl->m_VariableToProgress.erase(variable); |
|
133 | 148 | } |
|
134 | 149 | auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN); |
|
135 | 150 | |
|
136 | 151 | emit dataChanged(modelIndex, modelIndex); |
|
137 | 152 | } |
|
138 | 153 | |
|
139 | 154 | int VariableModel::columnCount(const QModelIndex &parent) const |
|
140 | 155 | { |
|
141 | 156 | Q_UNUSED(parent); |
|
142 | 157 | |
|
143 | 158 | return NB_COLUMNS; |
|
144 | 159 | } |
|
145 | 160 | |
|
146 | 161 | int VariableModel::rowCount(const QModelIndex &parent) const |
|
147 | 162 | { |
|
148 | 163 | Q_UNUSED(parent); |
|
149 | 164 | |
|
150 | 165 | return impl->m_Variables.size(); |
|
151 | 166 | } |
|
152 | 167 | |
|
153 | 168 | QVariant VariableModel::data(const QModelIndex &index, int role) const |
|
154 | 169 | { |
|
155 | 170 | if (!index.isValid()) { |
|
156 | 171 | return QVariant{}; |
|
157 | 172 | } |
|
158 | 173 | |
|
159 | 174 | if (index.row() < 0 || index.row() >= rowCount()) { |
|
160 | 175 | return QVariant{}; |
|
161 | 176 | } |
|
162 | 177 | |
|
163 | 178 | if (role == Qt::DisplayRole) { |
|
164 | 179 | if (auto variable = impl->m_Variables.at(index.row()).get()) { |
|
165 | 180 | switch (index.column()) { |
|
166 | 181 | case NAME_COLUMN: |
|
167 | 182 | return variable->name(); |
|
168 | 183 | case TSTART_COLUMN: { |
|
169 | 184 | auto range = variable->realRange(); |
|
170 | 185 | return range != INVALID_RANGE |
|
171 | 186 | ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT) |
|
172 | 187 | : QVariant{}; |
|
173 | 188 | } |
|
174 | 189 | case TEND_COLUMN: { |
|
175 | 190 | auto range = variable->realRange(); |
|
176 | 191 | return range != INVALID_RANGE |
|
177 | 192 | ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT) |
|
178 | 193 | : QVariant{}; |
|
179 | 194 | } |
|
180 | 195 | case UNIT_COLUMN: |
|
181 | 196 | return variable->metadata().value(QStringLiteral("units")); |
|
182 | 197 | case MISSION_COLUMN: |
|
183 | 198 | return variable->metadata().value(QStringLiteral("mission")); |
|
184 | 199 | case PLUGIN_COLUMN: |
|
185 | 200 | return variable->metadata().value(QStringLiteral("plugin")); |
|
186 | 201 | default: |
|
187 | 202 | // No action |
|
188 | 203 | break; |
|
189 | 204 | } |
|
190 | 205 | |
|
191 | 206 | qWarning(LOG_VariableModel()) |
|
192 | 207 | << tr("Can't get data (unknown column %1)").arg(index.column()); |
|
193 | 208 | } |
|
194 | 209 | else { |
|
195 | 210 | qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)"); |
|
196 | 211 | } |
|
197 | 212 | } |
|
198 | 213 | else if (role == VariableRoles::ProgressRole) { |
|
199 | 214 | if (auto variable = impl->m_Variables.at(index.row())) { |
|
200 | 215 | |
|
201 | 216 | auto it = impl->m_VariableToProgress.find(variable); |
|
202 | 217 | if (it != impl->m_VariableToProgress.cend()) { |
|
203 | 218 | return it->second; |
|
204 | 219 | } |
|
205 | 220 | } |
|
206 | 221 | } |
|
207 | 222 | |
|
208 | 223 | return QVariant{}; |
|
209 | 224 | } |
|
210 | 225 | |
|
211 | 226 | QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const |
|
212 | 227 | { |
|
213 | 228 | if (role != Qt::DisplayRole && role != Qt::SizeHintRole) { |
|
214 | 229 | return QVariant{}; |
|
215 | 230 | } |
|
216 | 231 | |
|
217 | 232 | if (orientation == Qt::Horizontal) { |
|
218 | 233 | auto propertiesIt = COLUMN_PROPERTIES.find(section); |
|
219 | 234 | if (propertiesIt != COLUMN_PROPERTIES.cend()) { |
|
220 | 235 | // Role is either DisplayRole or SizeHintRole |
|
221 | 236 | return (role == Qt::DisplayRole) |
|
222 | 237 | ? QVariant{propertiesIt->m_Name} |
|
223 | 238 | : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}}; |
|
224 | 239 | } |
|
225 | 240 | else { |
|
226 | 241 | qWarning(LOG_VariableModel()) |
|
227 | 242 | << tr("Can't get header data (unknown column %1)").arg(section); |
|
228 | 243 | } |
|
229 | 244 | } |
|
230 | 245 | |
|
231 | 246 | return QVariant{}; |
|
232 | 247 | } |
|
233 | 248 | |
|
234 | 249 | void VariableModel::abortProgress(const QModelIndex &index) |
|
235 | 250 | { |
|
236 | 251 | if (auto variable = impl->m_Variables.at(index.row())) { |
|
237 | 252 | emit abortProgessRequested(variable); |
|
238 | 253 | } |
|
239 | 254 | } |
|
240 | 255 | |
|
241 | 256 | void VariableModel::onVariableUpdated() noexcept |
|
242 | 257 | { |
|
243 | 258 | // Finds variable that has been updated in the model |
|
244 | 259 | if (auto updatedVariable = dynamic_cast<Variable *>(sender())) { |
|
245 | 260 | auto updatedVariableIndex = impl->indexOfVariable(updatedVariable); |
|
246 | 261 | |
|
247 | 262 | if (updatedVariableIndex > -1) { |
|
248 | 263 | emit dataChanged(createIndex(updatedVariableIndex, 0), |
|
249 | 264 | createIndex(updatedVariableIndex, columnCount() - 1)); |
|
250 | 265 | } |
|
251 | 266 | } |
|
252 | 267 | } |
|
253 | 268 | |
|
254 | 269 | int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept |
|
255 | 270 | { |
|
256 | 271 | auto begin = std::cbegin(m_Variables); |
|
257 | 272 | auto end = std::cend(m_Variables); |
|
258 | 273 | auto it |
|
259 | 274 | = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; }); |
|
260 | 275 | |
|
261 | 276 | if (it != end) { |
|
262 | 277 | // Gets the index of the variable in the model: we assume here that views have the same |
|
263 | 278 | // order as the model |
|
264 | 279 | return std::distance(begin, it); |
|
265 | 280 | } |
|
266 | 281 | else { |
|
267 | 282 | return -1; |
|
268 | 283 | } |
|
269 | 284 | } |
@@ -1,18 +1,19 | |||
|
1 | 1 | |
|
2 | 2 | |
|
3 | 3 | tests = [ |
|
4 | [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'], | |
|
4 | 5 | [['Data/TestDataSeries.cpp'],'test_data','DataSeries test'], |
|
5 | 6 | [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'], |
|
6 | 7 | [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'], |
|
7 | 8 | [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'], |
|
8 | 9 | [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'], |
|
9 | 10 | [['Variable/TestVariable.cpp'],'test_variable','Variable test'] |
|
10 | 11 | ] |
|
11 | 12 | |
|
12 | 13 | foreach unit_test : tests |
|
13 | 14 | test_moc_files = qt5.preprocess(moc_sources : unit_test[0]) |
|
14 | 15 | test_exe = executable(unit_test[1],unit_test[0] , test_moc_files, |
|
15 | 16 | dependencies : [sciqlop_core, qt5test]) |
|
16 | 17 | test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])]) |
|
17 | 18 | endforeach |
|
18 | 19 |
General Comments 0
You need to be logged in to leave comments.
Login now