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