##// END OF EJS Templates
Add clang format from linux
perrinel -
r595:8e31780497af
parent child
Show More
@@ -1,274 +1,274
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 4 #include <Common/DateUtils.h>
5 5
6 6 #include <Data/IDataSeries.h>
7 7
8 8 #include <QSize>
9 9 #include <unordered_map>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12 12
13 13 namespace {
14 14
15 15 // Column indexes
16 16 const auto NAME_COLUMN = 0;
17 17 const auto TSTART_COLUMN = 1;
18 18 const auto TEND_COLUMN = 2;
19 19 const auto UNIT_COLUMN = 3;
20 20 const auto MISSION_COLUMN = 4;
21 21 const auto PLUGIN_COLUMN = 5;
22 22 const auto NB_COLUMNS = 6;
23 23
24 24 // Column properties
25 25 const auto DEFAULT_HEIGHT = 25;
26 26 const auto DEFAULT_WIDTH = 100;
27 27
28 28 struct ColumnProperties {
29 29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
30 30 int height = DEFAULT_HEIGHT)
31 31 : m_Name{name}, m_Width{width}, m_Height{height}
32 32 {
33 33 }
34 34
35 35 QString m_Name;
36 36 int m_Width;
37 37 int m_Height;
38 38 };
39 39
40 40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
41 41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
43 43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
44 44
45 45 /// Format for datetimes
46 46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
47 47
48 48
49 49 } // namespace
50 50
51 51 struct VariableModel::VariableModelPrivate {
52 52 /// Variables created in SciQlop
53 53 std::vector<std::shared_ptr<Variable> > m_Variables;
54 54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
55 55
56 56 /// Return the row index of the variable. -1 if it's not found
57 57 int indexOfVariable(Variable *variable) const noexcept;
58 58 };
59 59
60 60 VariableModel::VariableModel(QObject *parent)
61 61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
62 62 {
63 63 }
64 64
65 65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
66 66 const SqpRange &dateTime,
67 67 const QVariantHash &metadata) noexcept
68 68 {
69 69 auto insertIndex = rowCount();
70 70 beginInsertRows({}, insertIndex, insertIndex);
71 71
72 72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
73 73
74 74 impl->m_Variables.push_back(variable);
75 75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
76 76
77 77 endInsertRows();
78 78
79 79 return variable;
80 80 }
81 81
82 82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
83 83 {
84 84 if (!variable) {
85 85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
86 86 return;
87 87 }
88 88
89 89 // Finds variable in the model
90 90 auto begin = impl->m_Variables.cbegin();
91 91 auto end = impl->m_Variables.cend();
92 92 auto it = std::find(begin, end, variable);
93 93 if (it != end) {
94 94 auto removeIndex = std::distance(begin, it);
95 95
96 96 // Deletes variable
97 97 beginRemoveRows({}, removeIndex, removeIndex);
98 98 impl->m_Variables.erase(it);
99 99 endRemoveRows();
100 100 }
101 101 else {
102 102 qCritical(LOG_VariableModel())
103 103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
104 104 .arg(variable->name());
105 105 }
106 106
107 107 // Removes variable from progress map
108 108 impl->m_VariableToProgress.erase(variable);
109 109 }
110 110
111 111
112 112 std::shared_ptr<Variable> VariableModel::variable(int index) const
113 113 {
114 114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
115 115 }
116 116
117 117 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
118 118 {
119 119 if (progress > 0.0) {
120 120 impl->m_VariableToProgress[variable] = progress;
121 121 }
122 122 else {
123 123 impl->m_VariableToProgress.erase(variable);
124 124 }
125 125 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
126 126
127 127 emit dataChanged(modelIndex, modelIndex);
128 128 }
129 129
130 130 int VariableModel::columnCount(const QModelIndex &parent) const
131 131 {
132 132 Q_UNUSED(parent);
133 133
134 134 return NB_COLUMNS;
135 135 }
136 136
137 137 int VariableModel::rowCount(const QModelIndex &parent) const
138 138 {
139 139 Q_UNUSED(parent);
140 140
141 141 return impl->m_Variables.size();
142 142 }
143 143
144 144 QVariant VariableModel::data(const QModelIndex &index, int role) const
145 145 {
146 146 if (!index.isValid()) {
147 147 return QVariant{};
148 148 }
149 149
150 150 if (index.row() < 0 || index.row() >= rowCount()) {
151 151 return QVariant{};
152 152 }
153 153
154 154 if (role == Qt::DisplayRole) {
155 155 if (auto variable = impl->m_Variables.at(index.row()).get()) {
156 156 /// Lambda function that builds the variant to return for a time value
157 157 /// @param getValueFun function used to get for a data series the iterator on the entry
158 158 /// that contains the time value to display
159 159 auto dateTimeVariant = [variable](const auto &getValueFun) {
160 160 if (auto dataSeries = variable->dataSeries()) {
161 161 dataSeries->lockRead();
162 162 auto it = getValueFun(*dataSeries);
163 163 auto resVariant = (it != dataSeries->cend())
164 ? DateUtils::dateTime(it->x()).toString(DATETIME_FORMAT)
165 : QVariant{};
164 ? DateUtils::dateTime(it->x()).toString(DATETIME_FORMAT)
165 : QVariant{};
166 166 dataSeries->unlock();
167 167 return resVariant;
168 168 }
169 169 else {
170 170 return QVariant{};
171 171 }
172 172 };
173 173
174 174 switch (index.column()) {
175 175 case NAME_COLUMN:
176 176 return variable->name();
177 177 case TSTART_COLUMN:
178 178 // Shows the min value of the data series above the range tstart
179 179 return dateTimeVariant([min = variable->range().m_TStart](
180 180 const auto &dataSeries) { return dataSeries.minXAxisData(min); });
181 181 case TEND_COLUMN:
182 182 // Shows the max value of the data series under the range tend
183 183 return dateTimeVariant([max = variable->range().m_TEnd](
184 184 const auto &dataSeries) { return dataSeries.maxXAxisData(max); });
185 185 case UNIT_COLUMN:
186 186 return variable->metadata().value(QStringLiteral("units"));
187 187 case MISSION_COLUMN:
188 188 return variable->metadata().value(QStringLiteral("mission"));
189 189 case PLUGIN_COLUMN:
190 190 return variable->metadata().value(QStringLiteral("plugin"));
191 191 default:
192 192 // No action
193 193 break;
194 194 }
195 195
196 196 qWarning(LOG_VariableModel())
197 197 << tr("Can't get data (unknown column %1)").arg(index.column());
198 198 }
199 199 else {
200 200 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
201 201 }
202 202 }
203 203 else if (role == VariableRoles::ProgressRole) {
204 204 if (auto variable = impl->m_Variables.at(index.row())) {
205 205
206 206 auto it = impl->m_VariableToProgress.find(variable);
207 207 if (it != impl->m_VariableToProgress.cend()) {
208 208 return it->second;
209 209 }
210 210 }
211 211 }
212 212
213 213 return QVariant{};
214 214 }
215 215
216 216 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
217 217 {
218 218 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
219 219 return QVariant{};
220 220 }
221 221
222 222 if (orientation == Qt::Horizontal) {
223 223 auto propertiesIt = COLUMN_PROPERTIES.find(section);
224 224 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
225 225 // Role is either DisplayRole or SizeHintRole
226 226 return (role == Qt::DisplayRole)
227 227 ? QVariant{propertiesIt->m_Name}
228 228 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
229 229 }
230 230 else {
231 231 qWarning(LOG_VariableModel())
232 232 << tr("Can't get header data (unknown column %1)").arg(section);
233 233 }
234 234 }
235 235
236 236 return QVariant{};
237 237 }
238 238
239 239 void VariableModel::abortProgress(const QModelIndex &index)
240 240 {
241 241 if (auto variable = impl->m_Variables.at(index.row())) {
242 242 emit abortProgessRequested(variable);
243 243 }
244 244 }
245 245
246 246 void VariableModel::onVariableUpdated() noexcept
247 247 {
248 248 // Finds variable that has been updated in the model
249 249 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
250 250 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
251 251
252 252 if (updatedVariableIndex > -1) {
253 253 emit dataChanged(createIndex(updatedVariableIndex, 0),
254 254 createIndex(updatedVariableIndex, columnCount() - 1));
255 255 }
256 256 }
257 257 }
258 258
259 259 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
260 260 {
261 261 auto begin = std::cbegin(m_Variables);
262 262 auto end = std::cend(m_Variables);
263 263 auto it
264 264 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
265 265
266 266 if (it != end) {
267 267 // Gets the index of the variable in the model: we assume here that views have the same
268 268 // order as the model
269 269 return std::distance(begin, it);
270 270 }
271 271 else {
272 272 return -1;
273 273 }
274 274 }
@@ -1,259 +1,260
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3
4 4 #include "Visualization/IVisualizationWidgetVisitor.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "ui_VisualizationZoneWidget.h"
7 7
8 8 #include <Data/SqpRange.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <QUuid>
13 13 #include <SqpApplication.h>
14 14 #include <cmath>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17 17
18 18 namespace {
19 19
20 20 /// Minimum height for graph added in zones (in pixels)
21 21 const auto GRAPH_MINIMUM_HEIGHT = 300;
22 22
23 23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 24 /// the zone
25 25 QString defaultGraphName(const QLayout &layout)
26 26 {
27 27 auto count = 0;
28 28 for (auto i = 0; i < layout.count(); ++i) {
29 29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 30 count++;
31 31 }
32 32 }
33 33
34 34 return QObject::tr("Graph %1").arg(count + 1);
35 35 }
36 36
37 37 } // namespace
38 38
39 39 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
40 40
41 41 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
42 42 QUuid m_SynchronisationGroupId;
43 43 };
44 44
45 45 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
46 46 : QWidget{parent},
47 47 ui{new Ui::VisualizationZoneWidget},
48 48 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
49 49 {
50 50 ui->setupUi(this);
51 51
52 52 ui->zoneNameLabel->setText(name);
53 53
54 54 // 'Close' options : widget is deleted when closed
55 55 setAttribute(Qt::WA_DeleteOnClose);
56 56 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
57 57 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
58 58
59 59 // Synchronisation id
60 60 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
61 61 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
62 62 }
63 63
64 64 VisualizationZoneWidget::~VisualizationZoneWidget()
65 65 {
66 66 delete ui;
67 67 }
68 68
69 69 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
70 70 {
71 71 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
72 72 }
73 73
74 74 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
75 75 {
76 76 auto graphWidget = new VisualizationGraphWidget{
77 77 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
78 78
79 79
80 80 // Set graph properties
81 81 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
82 82 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
83 83
84 84
85 85 // Lambda to synchronize zone widget
86 86 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
87 87 const SqpRange &oldGraphRange) {
88 88
89 89 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
90 90 auto frameLayout = ui->visualizationZoneFrame->layout();
91 91 for (auto i = 0; i < frameLayout->count(); ++i) {
92 92 auto graphChild
93 93 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
94 94 if (graphChild && (graphChild != graphWidget)) {
95 95
96 96 auto graphChildRange = graphChild->graphRange();
97 97 switch (zoomType) {
98 98 case AcquisitionZoomType::ZoomIn: {
99 99 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
100 100 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
101 101 graphChildRange.m_TStart += deltaLeft;
102 102 graphChildRange.m_TEnd -= deltaRight;
103 103 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
104 104 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
105 105 << deltaLeft;
106 106 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
107 107 << deltaRight;
108 108 qCDebug(LOG_VisualizationZoneWidget())
109 109 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
110 110
111 111 break;
112 112 }
113 113
114 114 case AcquisitionZoomType::ZoomOut: {
115 115 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
116 116 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
117 117 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
118 118 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
119 119 << deltaLeft;
120 120 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
121 121 << deltaRight;
122 122 qCDebug(LOG_VisualizationZoneWidget())
123 123 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
124 124 graphChildRange.m_TStart -= deltaLeft;
125 125 graphChildRange.m_TEnd += deltaRight;
126 126 break;
127 127 }
128 128 case AcquisitionZoomType::PanRight: {
129 129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
130 130 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
131 131 graphChildRange.m_TStart += deltaRight;
132 132 graphChildRange.m_TEnd += deltaRight;
133 133 qCDebug(LOG_VisualizationZoneWidget())
134 134 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
135 135 break;
136 136 }
137 137 case AcquisitionZoomType::PanLeft: {
138 138 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
139 139 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
140 140 graphChildRange.m_TStart -= deltaLeft;
141 141 graphChildRange.m_TEnd -= deltaLeft;
142 142 break;
143 143 }
144 144 case AcquisitionZoomType::Unknown: {
145 145 qCDebug(LOG_VisualizationZoneWidget())
146 146 << tr("Impossible to synchronize: zoom type unknown");
147 147 break;
148 148 }
149 149 default:
150 150 qCCritical(LOG_VisualizationZoneWidget())
151 151 << tr("Impossible to synchronize: zoom type not take into account");
152 152 // No action
153 153 break;
154 154 }
155 155 graphChild->enableAcquisition(false);
156 156 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
157 157 << graphChild->graphRange();
158 158 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
159 159 << graphChildRange;
160 160 qCDebug(LOG_VisualizationZoneWidget())
161 161 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
162 162 graphChild->setGraphRange(graphChildRange);
163 163 graphChild->enableAcquisition(true);
164 164 }
165 165 }
166 166 };
167 167
168 168 // connection for synchronization
169 169 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
170 170 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
171 171 &VisualizationZoneWidget::onVariableAdded);
172 172
173 173 auto range = SqpRange{};
174 174
175 175 // Apply visitor to graph children
176 176 auto layout = ui->visualizationZoneFrame->layout();
177 177 if (layout->count() > 0) {
178 178 // Case of a new graph in a existant zone
179 179 if (auto visualizationGraphWidget
180 180 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
181 181 range = visualizationGraphWidget->graphRange();
182 182 }
183 183 }
184 184 else {
185 185 // Case of a new graph as the first of the zone
186 186 range = variable->range();
187 187 }
188 188
189 189 this->addGraph(graphWidget);
190 190
191 191 graphWidget->addVariable(variable, range);
192 192
193 193 // get y using variable range
194 194 if (auto dataSeries = variable->dataSeries()) {
195 195 dataSeries->lockRead();
196 auto valuesBounds = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
196 auto valuesBounds
197 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
197 198 auto end = dataSeries->cend();
198 199 if (valuesBounds.first != end && valuesBounds.second != end) {
199 200 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
200 201
201 202 auto minValue = rangeValue(valuesBounds.first->minValue());
202 203 auto maxValue = rangeValue(valuesBounds.second->maxValue());
203 204
204 205 graphWidget->setYRange(SqpRange{minValue, maxValue});
205 206 }
206 207 dataSeries->unlock();
207 208 }
208 209
209 210 return graphWidget;
210 211 }
211 212
212 213 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
213 214 {
214 215 if (visitor) {
215 216 visitor->visitEnter(this);
216 217
217 218 // Apply visitor to graph children
218 219 auto layout = ui->visualizationZoneFrame->layout();
219 220 for (auto i = 0; i < layout->count(); ++i) {
220 221 if (auto item = layout->itemAt(i)) {
221 222 // Widgets different from graphs are not visited (no action)
222 223 if (auto visualizationGraphWidget
223 224 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
224 225 visualizationGraphWidget->accept(visitor);
225 226 }
226 227 }
227 228 }
228 229
229 230 visitor->visitLeave(this);
230 231 }
231 232 else {
232 233 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
233 234 }
234 235 }
235 236
236 237 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
237 238 {
238 239 // A tab can always accomodate a variable
239 240 Q_UNUSED(variable);
240 241 return true;
241 242 }
242 243
243 244 bool VisualizationZoneWidget::contains(const Variable &variable) const
244 245 {
245 246 Q_UNUSED(variable);
246 247 return false;
247 248 }
248 249
249 250 QString VisualizationZoneWidget::name() const
250 251 {
251 252 return ui->zoneNameLabel->text();
252 253 }
253 254
254 255 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
255 256 {
256 257 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
257 258 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
258 259 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
259 260 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Status change > Approved

You need to be logged in to leave comments. Login now