##// END OF EJS Templates
Merge branch 'feature/CatalogueGuiPart5' into develop
trabillard -
r1349:aa6b3e9d2907 merge
parent child
Show More
@@ -0,0 +1,26
1 #ifndef SCIQLOP_DATASERIESTYPE_H
2 #define SCIQLOP_DATASERIESTYPE_H
3
4 #include <QString>
5
6 enum class DataSeriesType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN };
7
8 struct DataSeriesTypeUtils {
9 static DataSeriesType fromString(const QString &type)
10 {
11 if (type == QStringLiteral("scalar")) {
12 return DataSeriesType::SCALAR;
13 }
14 else if (type == QStringLiteral("spectrogram")) {
15 return DataSeriesType::SPECTROGRAM;
16 }
17 else if (type == QStringLiteral("vector")) {
18 return DataSeriesType::VECTOR;
19 }
20 else {
21 return DataSeriesType::UNKNOWN;
22 }
23 }
24 };
25
26 #endif // SCIQLOP_DATASERIESTYPE_H
@@ -386,8 +386,8 bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget *parentWidget)
386 386 if (hasChanges) {
387 387 // There are some unsaved changes
388 388 switch (QMessageBox::question(
389 parentWidget, "Save changes",
390 tr("The catalogue controller unsaved changes.\nDo you want to save them ?"),
389 parentWidget, tr("Save changes"),
390 tr("The catalogue controller has unsaved changes.\nDo you want to save them ?"),
391 391 QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel,
392 392 QMessageBox::SaveAll)) {
393 393 case QMessageBox::SaveAll:
@@ -75,6 +75,10 public slots:
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 requestVariableFromProductIdKey(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:
@@ -145,6 +145,14 public:
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
@@ -4,6 +4,7
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DataSeriesIterator.h>
7 #include <Data/DataSeriesType.h>
7 8 #include <Data/SqpRange.h>
8 9
9 10 #include <QLoggingCategory>
@@ -54,6 +55,9 public:
54 55 /// @return the data of the variable, nullptr if there is no data
55 56 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
56 57
58 /// @return the type of data that the variable holds
59 DataSeriesType type() const noexcept;
60
57 61 QVariantHash metadata() const noexcept;
58 62
59 63 bool contains(const SqpRange &range) const noexcept;
@@ -76,6 +80,8 public:
76 80
77 81 signals:
78 82 void updated();
83 /// Signal emitted when when the data series of the variable is loaded for the first time
84 void dataInitialized();
79 85
80 86 private:
81 87 class VariablePrivate;
@@ -48,26 +48,6 public:
48 48 */
49 49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50 50
51 /**
52 * Deletes from the controller the variable passed in parameter.
53 *
54 * Delete a variable includes:
55 * - the deletion of the various references to the variable in SciQlop
56 * - the deletion of the model variable
57 * - the deletion of the provider associated with the variable
58 * - removing the cache associated with the variable
59 *
60 * @param variable the variable to delete from the controller.
61 */
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
63
64 /**
65 * Deletes from the controller the variables passed in parameter.
66 * @param variables the variables to delete from the controller.
67 * @sa deleteVariable()
68 */
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
70
71 51 /// Returns the MIME data associated to a list of variables
72 52 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
73 53
@@ -89,7 +69,29 signals:
89 69 /// validated, canceled, or failed)
90 70 void acquisitionFinished();
91 71
72 void variableAdded(const std::shared_ptr<Variable> &variable);
73
92 74 public slots:
75 /**
76 * Deletes from the controller the variable passed in parameter.
77 *
78 * Delete a variable includes:
79 * - the deletion of the various references to the variable in SciQlop
80 * - the deletion of the model variable
81 * - the deletion of the provider associated with the variable
82 * - removing the cache associated with the variable
83 *
84 * @param variable the variable to delete from the controller.
85 */
86 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
87
88 /**
89 * Deletes from the controller the variables passed in parameter.
90 * @param variables the variables to delete from the controller.
91 * @sa deleteVariable()
92 */
93 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
94
93 95 /// Request the data loading of the variable whithin range
94 96 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
95 97 bool synchronise);
@@ -37,6 +37,20 public:
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)
@@ -149,6 +163,20 void DataSourceController::finalize()
149 163 impl->m_WorkingMutex.unlock();
150 164 }
151 165
166 void DataSourceController::requestVariableFromProductIdKey(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);
@@ -165,6 +165,24 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursiv
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
@@ -9,6 +9,29
9 9
10 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 11
12 namespace {
13
14 /**
15 * Searches in metadata for a value that can be converted to DataSeriesType
16 * @param metadata the metadata where to search
17 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
18 * @sa DataSeriesType
19 */
20 DataSeriesType findDataSeriesType(const QVariantHash &metadata)
21 {
22 auto dataSeriesType = DataSeriesType::UNKNOWN;
23
24 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
25 for (auto it = metadata.cbegin(), end = metadata.cend();
26 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
27 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
28 }
29
30 return dataSeriesType;
31 }
32
33 } // namespace
34
12 35 struct Variable::VariablePrivate {
13 36 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
14 37 : m_Name{name},
@@ -17,7 +40,8 struct Variable::VariablePrivate {
17 40 m_Metadata{metadata},
18 41 m_DataSeries{nullptr},
19 42 m_RealRange{INVALID_RANGE},
20 m_NbPoints{0}
43 m_NbPoints{0},
44 m_Type{findDataSeriesType(m_Metadata)}
21 45 {
22 46 }
23 47
@@ -28,7 +52,8 struct Variable::VariablePrivate {
28 52 m_Metadata{other.m_Metadata},
29 53 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
30 54 m_RealRange{other.m_RealRange},
31 m_NbPoints{other.m_NbPoints}
55 m_NbPoints{other.m_NbPoints},
56 m_Type{findDataSeriesType(m_Metadata)}
32 57 {
33 58 }
34 59
@@ -75,6 +100,7 struct Variable::VariablePrivate {
75 100 std::shared_ptr<IDataSeries> m_DataSeries;
76 101 SqpRange m_RealRange;
77 102 int m_NbPoints;
103 DataSeriesType m_Type;
78 104
79 105 QReadWriteLock m_Lock;
80 106 };
@@ -161,16 +187,23 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
161 187 return;
162 188 }
163 189
190 auto dataInit = false;
191
164 192 // Add or merge the data
165 193 impl->lockWrite();
166 194 if (!impl->m_DataSeries) {
167 195 impl->m_DataSeries = dataSeries->clone();
196 dataInit = true;
168 197 }
169 198 else {
170 199 impl->m_DataSeries->merge(dataSeries.get());
171 200 }
172 201 impl->purgeDataSeries();
173 202 impl->unlock();
203
204 if (dataInit) {
205 emit dataInitialized();
206 }
174 207 }
175 208
176 209
@@ -183,6 +216,15 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
183 216 return dataSeries;
184 217 }
185 218
219 DataSeriesType Variable::type() const noexcept
220 {
221 impl->lockRead();
222 auto type = impl->m_Type;
223 impl->unlock();
224
225 return type;
226 }
227
186 228 QVariantHash Variable::metadata() const noexcept
187 229 {
188 230 impl->lockRead();
@@ -373,6 +373,8 VariableController::createVariable(const QString &name, const QVariantHash &meta
373 373 // impl->processRequest(newVariable, range, varRequestId);
374 374 // impl->updateVariableRequest(varRequestId);
375 375
376 emit variableAdded(newVariable);
377
376 378 return newVariable;
377 379 }
378 380
@@ -9,6 +9,7 class DBCatalogue;
9 9 class DBEvent;
10 10 class DBEventProduct;
11 11 class VisualizationWidget;
12 class VisualizationSelectionZoneItem;
12 13
13 14 namespace Ui {
14 15 class CatalogueEventsWidget;
@@ -21,10 +22,13 class CatalogueEventsWidget : public QWidget {
21 22
22 23 signals:
23 24 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
25 void eventsRemoved(const QVector<std::shared_ptr<DBEvent> > &event);
24 26 void eventProductsSelected(
25 27 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
26 28 &eventproducts);
27 29 void selectionCleared();
30 void selectionZoneAdded(const std::shared_ptr<DBEvent> &event, const QString &productId,
31 VisualizationSelectionZoneItem *selectionZone);
28 32
29 33 public:
30 34 explicit CatalogueEventsWidget(QWidget *parent = 0);
@@ -39,6 +43,8 public:
39 43 bool isAllEventsDisplayed() const;
40 44 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
41 45
46 void refreshEvent(const std::shared_ptr<DBEvent> &event);
47
42 48 public slots:
43 49 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
44 50 void populateWithAllEvents();
@@ -12,6 +12,10 class CatalogueEventsWidget;
12 12 class CatalogueSideBarWidget;
13 13
14 14 class VisualizationWidget;
15 class VisualizationSelectionZoneItem;
16
17 class DBEvent;
18
15 19
16 20 class CatalogueExplorer : public QDialog {
17 21 Q_OBJECT
@@ -25,6 +29,10 public:
25 29 CatalogueEventsWidget &eventsWidget() const;
26 30 CatalogueSideBarWidget &sideBarWidget() const;
27 31
32 void clearSelectionZones();
33 void addSelectionZoneItem(const std::shared_ptr<DBEvent> &event, const QString &productId,
34 VisualizationSelectionZoneItem *selectionZone);
35
28 36 private:
29 37 Ui::CatalogueExplorer *ui;
30 38
@@ -36,6 +36,8 public:
36 36 const std::shared_ptr<DBEventProduct> &eventProduct);
37 37 void setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue);
38 38
39 void refresh();
40
39 41 public slots:
40 42 void showPage(Page page);
41 43
@@ -12,6 +12,7 class IDataSeries;
12 12 class QCPAxis;
13 13 class QCustomPlot;
14 14 class SqpColorScale;
15 class Variable;
15 16
16 17 /// Formats a data value according to the axis on which it is present
17 18 QString formatValue(double value, const QCPAxis &axis);
@@ -27,11 +28,17 struct IAxisHelper {
27 28 /// @param plot the plot for which to set axe properties
28 29 /// @param colorScale the color scale for which to set properties
29 30 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
31
32 /// Set the units of the plot's axes and the color scale associated to plot passed as
33 /// parameters
34 /// @param plot the plot for which to set axe units
35 /// @param colorScale the color scale for which to set unit
36 virtual void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
30 37 };
31 38
32 39 struct IAxisHelperFactory {
33 /// Creates IAxisHelper according to a data series
34 static std::unique_ptr<IAxisHelper> create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
40 /// Creates IPlottablesHelper according to the type of data series a variable holds
41 static std::unique_ptr<IAxisHelper> create(const Variable &variable) noexcept;
35 42 };
36 43
37 44 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,6 +1,8
1 1 #ifndef SCIQLOP_PLOTTABLESRENDERINGUTILS_H
2 2 #define SCIQLOP_PLOTTABLESRENDERINGUTILS_H
3 3
4 #include <Data/DataSeriesType.h>
5
4 6 #include <Visualization/VisualizationDefs.h>
5 7
6 8 #include <memory>
@@ -9,9 +11,9
9 11
10 12 Q_DECLARE_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils)
11 13
12 class IDataSeries;
13 14 class QCPColorScale;
14 15 class QCustomPlot;
16 class Variable;
15 17
16 18 /**
17 19 * Helper used to handle plottables rendering
@@ -25,9 +27,8 struct IPlottablesHelper {
25 27 };
26 28
27 29 struct IPlottablesHelperFactory {
28 /// Creates IPlottablesHelper according to a data series
29 static std::unique_ptr<IPlottablesHelper>
30 create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
30 /// Creates IPlottablesHelper according to the type of data series a variable holds
31 static std::unique_ptr<IPlottablesHelper> create(const Variable &variable) noexcept;
31 32 };
32 33
33 34 #endif // SCIQLOP_PLOTTABLESRENDERINGUTILS_H
@@ -32,7 +32,7 struct VisualizationGraphHelper {
32 32 */
33 33 static PlottablesMap create(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
34 34
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
36 36 const SqpRange &dateTime);
37 37
38 38 static void setYAxisRange(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
@@ -9,6 +9,7 class IDataSeries;
9 9 class QCustomPlot;
10 10 class QMouseEvent;
11 11 class Unit;
12 class Variable;
12 13 class VisualizationGraphWidget;
13 14
14 15 class VisualizationGraphRenderingDelegate {
@@ -23,13 +24,14 public:
23 24 /// Updates rendering when data of plot changed
24 25 void onPlotUpdated() noexcept;
25 26
26 /// Sets properties of the plot's axes from the data series passed as parameter
27 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
27 /// Sets units of the plot's axes according to the properties of the variable passed as
28 /// parameter
29 void setAxesUnits(const Variable &variable) noexcept;
28 30
29 /// Sets rendering properties of the plottables passed as parameter, from the data series that
31 /// Sets graph properties of the plottables passed as parameter, from the variable that
30 32 /// generated these
31 void setPlottablesProperties(std::shared_ptr<IDataSeries> dataSeries,
32 PlottablesMap &plottables) noexcept;
33 void setGraphProperties(const Variable &variable, PlottablesMap &plottables) noexcept;
34
33 35
34 36 /// Shows or hides graph overlay (name, close button, etc.)
35 37 void showGraphOverlay(bool show) noexcept;
@@ -69,13 +69,16 public:
69 69 /// Sets the y-axis range based on the data of a variable
70 70 void setYRange(std::shared_ptr<Variable> variable);
71 71 SqpRange graphRange() const noexcept;
72 void setGraphRange(const SqpRange &range);
72 void setGraphRange(const SqpRange &range, bool calibration = false);
73 void setAutoRangeOnVariableInitialization(bool value);
73 74
74 75 // Zones
75 76 /// Returns the ranges of all the selection zones on the graph
76 77 QVector<SqpRange> selectionZoneRanges() const;
77 78 /// Adds new selection zones in the graph
78 79 void addSelectionZones(const QVector<SqpRange> &ranges);
80 /// Adds a new selection zone in the graph
81 VisualizationSelectionZoneItem *addSelectionZone(const QString &name, const SqpRange &range);
79 82 /// Removes the specified selection zone
80 83 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
81 84
@@ -8,6 +8,11
8 8 class VisualizationGraphWidget;
9 9
10 10 class VisualizationSelectionZoneItem : public QCPItemRect {
11 Q_OBJECT
12
13 signals:
14 /// Signal emitted when the zone range is edited manually
15 void rangeEdited(const SqpRange &range);
11 16
12 17 public:
13 18 VisualizationSelectionZoneItem(QCustomPlot *plot);
@@ -20,6 +20,7 gui_moc_headers = [
20 20 'include/Visualization/VisualizationDragDropContainer.h',
21 21 'include/Visualization/VisualizationDragWidget.h',
22 22 'include/Visualization/ColorScaleEditor.h',
23 'include/Visualization/VisualizationSelectionZoneItem.h',
23 24 'include/Actions/SelectionZoneAction.h',
24 25 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
25 26 'include/Catalogue/CatalogueExplorer.h',
@@ -48,14 +48,18 struct CatalogueActionManager::CatalogueActionManagerPrivate {
48 48 auto eventProduct = std::make_shared<DBEventProduct>();
49 49 eventProduct->setEvent(*event);
50 50
51 auto productId
52 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
53
51 54 auto zoneRange = zone->range();
52 55 eventProduct->setTStart(zoneRange.m_TStart);
53 56 eventProduct->setTEnd(zoneRange.m_TEnd);
54 57
55 eventProduct->setProductId(
56 var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString());
58 eventProduct->setProductId(productId);
57 59
58 60 productList.push_back(*eventProduct);
61
62 m_CatalogueExplorer->addSelectionZoneItem(event, productId, zone);
59 63 }
60 64 }
61 65
@@ -6,7 +6,13
6 6 #include <Catalogue/CatalogueExplorerHelper.h>
7 7 #include <CatalogueDao.h>
8 8 #include <DBCatalogue.h>
9 #include <DBEventProduct.h>
10 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceItem.h>
9 12 #include <SqpApplication.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
15 #include <Visualization/VisualizationGraphWidget.h>
10 16 #include <Visualization/VisualizationTabWidget.h>
11 17 #include <Visualization/VisualizationWidget.h>
12 18 #include <Visualization/VisualizationZoneWidget.h>
@@ -21,6 +27,9 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
21 27 /// Fixed size of the validation column
22 28 const auto VALIDATION_COLUMN_SIZE = 35;
23 29
30 /// Percentage added to the range of a event when it is displayed
31 const auto EVENT_RANGE_MARGE = 30; // in %
32
24 33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
25 34
26 35 CatalogueEventsModel *m_Model = nullptr;
@@ -28,6 +37,7 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
28 37 QString m_ZoneForGraphMode;
29 38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
30 39 bool m_AllEventDisplayed = false;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
31 41
32 42 VisualizationWidget *m_VisualizationWidget = nullptr;
33 43
@@ -178,31 +188,134 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
178 188 }
179 189 }
180 190
181 void updateForGraphMode(QTreeView *treeView)
191 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
182 192 {
183 auto selectedRows = treeView->selectionModel()->selectedRows();
184
185 if (selectedRows.count() == 1) {
186 auto event = m_Model->getEvent(selectedRows.first());
187 if (m_VisualizationWidget) {
188 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
189 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
190 // TODO
191 }
192 }
193 else {
194 qCWarning(LOG_CatalogueEventsWidget())
195 << "updateGraphMode: no tab found in the visualization";
196 }
197 }
198 else {
199 qCWarning(LOG_CatalogueEventsWidget())
200 << "updateGraphMode: visualization widget not found";
193 // Retrieves the range of each product and the maximum size
194 QVector<SqpRange> graphRanges;
195 double maxDt = 0;
196 for (auto eventProduct : event->getEventProducts()) {
197 SqpRange eventRange;
198 eventRange.m_TStart = eventProduct.getTStart();
199 eventRange.m_TEnd = eventProduct.getTEnd();
200 graphRanges << eventRange;
201
202 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
203 if (dt > maxDt) {
204 maxDt = dt;
201 205 }
202 206 }
203 else {
207
208 // Adds the marge
209 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
210
211 // Corrects the graph ranges so that they all have the same size
212 QVector<SqpRange> correctedGraphRanges;
213 for (auto range : graphRanges) {
214 auto dt = range.m_TEnd - range.m_TStart;
215 auto diff = qAbs((maxDt - dt) / 2.0);
216
217 SqpRange correctedRange;
218 correctedRange.m_TStart = range.m_TStart - diff;
219 correctedRange.m_TEnd = range.m_TEnd + diff;
220
221 correctedGraphRanges << correctedRange;
222 }
223
224 return correctedGraphRanges;
225 }
226
227 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
228 {
229 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
230 if (selectedRows.count() != 1) {
204 231 qCWarning(LOG_CatalogueEventsWidget())
205 232 << "updateGraphMode: not compatible with multiple events selected";
233 return;
234 }
235
236 if (!m_VisualizationWidget) {
237 qCWarning(LOG_CatalogueEventsWidget())
238 << "updateGraphMode: visualization widget not found";
239 return;
240 }
241
242 auto event = m_Model->getEvent(selectedRows.first());
243 if (!event) {
244 // A event product is probably selected
245 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
246 return;
247 }
248
249 auto tab = m_VisualizationWidget->currentTabWidget();
250 if (!tab) {
251 qCWarning(LOG_CatalogueEventsWidget())
252 << "updateGraphMode: no tab found in the visualization";
253 return;
254 }
255
256 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
257 if (!zone) {
258 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
259 return;
260 }
261
262 // Close the previous graph and delete the asociated variables
263 for (auto graph : m_CustomGraphs) {
264 graph->close();
265 auto variables = graph->variables().toVector();
266
267 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
268 Qt::QueuedConnection,
269 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
270 }
271 m_CustomGraphs.clear();
272
273 // Calculates the range of each graph which will be created
274 auto graphRange = getGraphRanges(event);
275
276 // Loops through the event products and create the graph
277 auto itRange = graphRange.cbegin();
278 for (auto eventProduct : event->getEventProducts()) {
279 auto productId = eventProduct.getProductId();
280
281 auto range = *itRange;
282 ++itRange;
283
284 SqpRange productRange;
285 productRange.m_TStart = eventProduct.getTStart();
286 productRange.m_TEnd = eventProduct.getTEnd();
287
288 auto context = new QObject{catalogueEventWidget};
289 QObject::connect(
290 &sqpApp->variableController(), &VariableController::variableAdded, context,
291 [this, catalogueEventWidget, zone, context, event, range, productRange,
292 productId](auto variable) {
293
294 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
295 == productId) {
296 auto graph = zone->createGraph(variable);
297 graph->setAutoRangeOnVariableInitialization(false);
298
299 auto selectionZone
300 = graph->addSelectionZone(event->getName(), productRange);
301 emit catalogueEventWidget->selectionZoneAdded(event, productId,
302 selectionZone);
303 m_CustomGraphs << graph;
304
305 graph->setGraphRange(range, true);
306
307 // Removes the graph from the graph list if it is closed manually
308 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
309 [this, graph]() { m_CustomGraphs.removeAll(graph); });
310
311 delete context; // removes the connection
312 }
313 },
314 Qt::QueuedConnection);
315
316 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
317 "requestVariableFromProductIdKey", Qt::QueuedConnection,
318 Q_ARG(QString, productId));
206 319 }
207 320 }
208 321
@@ -256,7 +369,7 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
256 369 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
257 370 .value(0);
258 371
259 impl->updateForGraphMode(ui->treeView);
372 impl->updateForGraphMode(this);
260 373 }
261 374 });
262 375
@@ -268,7 +381,7 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
268 381 if (!events.isEmpty() && eventProducts.isEmpty()) {
269 382
270 383 if (QMessageBox::warning(this, tr("Remove Event(s)"),
271 tr("The selected event(s) will be completly removed "
384 tr("The selected event(s) will be permanently removed "
272 385 "from the repository!\nAre you sure you want to continue?"),
273 386 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
274 387 == QMessageBox::Yes) {
@@ -277,6 +390,8 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
277 390 sqpApp->catalogueController().removeEvent(event);
278 391 impl->removeEvent(event, ui->treeView);
279 392 }
393
394 emit this->eventsRemoved(events);
280 395 }
281 396 }
282 397 });
@@ -295,7 +410,7 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
295 410 impl->updateForTimeMode(ui->treeView);
296 411 }
297 412 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
298 impl->updateForGraphMode(ui->treeView);
413 impl->updateForGraphMode(this);
299 414 }
300 415
301 416 QVector<std::shared_ptr<DBEvent> > events;
@@ -398,6 +513,11 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &eve
398 513 return impl->m_Model->indexOf(event).isValid();
399 514 }
400 515
516 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
517 {
518 impl->m_Model->refreshEvent(event, true);
519 }
520
401 521 void CatalogueEventsWidget::populateWithCatalogues(
402 522 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
403 523 {
@@ -4,13 +4,22
4 4 #include <Catalogue/CatalogueActionManager.h>
5 5 #include <Catalogue/CatalogueController.h>
6 6 #include <SqpApplication.h>
7 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
7 9 #include <Visualization/VisualizationWidget.h>
8 10
9 11 #include <DBCatalogue.h>
10 12 #include <DBEvent.h>
13 #include <DBEventProduct.h>
14
15 #include <unordered_map>
11 16
12 17 struct CatalogueExplorer::CatalogueExplorerPrivate {
13 18 CatalogueActionManager m_ActionManager;
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
20 m_SelectionZonesPerEvents;
21
22 QMetaObject::Connection m_Conn;
14 23
15 24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
16 25 : m_ActionManager(catalogueExplorer)
@@ -27,6 +36,7 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
27 36
28 37 impl->m_ActionManager.installSelectionZoneActions();
29 38
39 // Updates events and inspector when something is selected in the catalogue widget
30 40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
31 41 if (catalogues.count() == 1) {
32 42 ui->inspector->setCatalogue(catalogues.first());
@@ -66,6 +76,7 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
66 76 ui->events->clear();
67 77 });
68 78
79 // Updates the inspectot when something is selected in the events
69 80 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
70 81 if (events.count() == 1) {
71 82 ui->inspector->setEvent(events.first());
@@ -88,6 +99,27 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
88 99 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
89 100 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
90 101
102 // Manage Selection Zones associated to events
103 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
104 [this](auto event, auto productId, auto zone) {
105 this->addSelectionZoneItem(event, productId, zone);
106 });
107
108 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
109 for (auto event : events) {
110 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
111 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
112 for (auto selectionZone : associatedSelectionZonesIt->second) {
113 auto parentGraph = selectionZone->parentGraphWidget();
114 parentGraph->removeSelectionZone(selectionZone);
115 }
116
117 impl->m_SelectionZonesPerEvents.erase(event);
118 }
119 }
120 });
121
122 // Updates changes from the inspector
91 123 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
92 124 sqpApp->catalogueController().updateCatalogue(catalogue);
93 125 ui->catalogues->setCatalogueChanges(catalogue, true);
@@ -107,6 +139,7 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
107 139
108 140 CatalogueExplorer::~CatalogueExplorer()
109 141 {
142 disconnect(impl->m_Conn);
110 143 delete ui;
111 144 }
112 145
@@ -124,3 +157,37 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
124 157 {
125 158 return *ui->catalogues;
126 159 }
160
161 void CatalogueExplorer::clearSelectionZones()
162 {
163 impl->m_SelectionZonesPerEvents.clear();
164 }
165
166 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
167 const QString &productId,
168 VisualizationSelectionZoneItem *selectionZone)
169 {
170 impl->m_SelectionZonesPerEvents[event] << selectionZone;
171 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
172 [event, productId, this](auto range) {
173 auto productList = event->getEventProducts();
174 for (auto &product : productList) {
175 if (product.getProductId() == productId) {
176 product.setTStart(range.m_TStart);
177 product.setTEnd(range.m_TEnd);
178 }
179 }
180 event->setEventProducts(productList);
181 sqpApp->catalogueController().updateEvent(event);
182 ui->events->refreshEvent(event);
183 ui->events->setEventChanges(event, true);
184 ui->inspector->refresh();
185 });
186
187 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
188 [event, selectionZone, this]() {
189 if (!impl->m_SelectionZonesPerEvents.empty()) {
190 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
191 }
192 });
193 }
@@ -209,3 +209,19 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &
209 209
210 210 blockSignals(false);
211 211 }
212
213 void CatalogueInspectorWidget::refresh()
214 {
215 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
216 case Page::CatalogueProperties:
217 setCatalogue(impl->m_DisplayedCatalogue);
218 break;
219 case Page::EventProperties: {
220 auto isEventShowed = ui->leEventName->isEnabled();
221 setEvent(impl->m_DisplayedEvent);
222 if (!isEventShowed && impl->m_DisplayedEvent) {
223 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
224 }
225 }
226 }
227 }
@@ -7,6 +7,7
7 7 #include "Visualization/VisualizationWidget.h"
8 8 #include "Visualization/operations/FindVariableOperation.h"
9 9
10 #include "DataSource/DataSourceController.h"
10 11 #include "Variable/Variable.h"
11 12 #include "Variable/VariableController.h"
12 13
@@ -286,11 +287,22 bool DragDropGuiController::checkMimeDataForVisualization(
286 287 // result = false: cannot drop multiple variables in the visualisation
287 288 }
288 289 }
290 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
291 auto productDataList = sqpApp->dataSourceController().productsDataForMimeData(
292 mimeData->data(MIME_TYPE_PRODUCT_LIST));
293 if (productDataList.count() == 1) {
294 result = true;
295 }
296 else {
297 // result = false: cannot drop multiple products in the visualisation
298 }
299 }
289 300 else {
290 301 // Other MIME data
291 302 // no special rules, accepted by default
292 303 result = true;
293 304 }
294 305
306
295 307 return result;
296 308 }
@@ -4,6 +4,8
4 4 #include <Data/SpectrogramSeries.h>
5 5 #include <Data/VectorSeries.h>
6 6
7 #include <Variable/Variable.h>
8
7 9 #include <Visualization/SqpColorScale.h>
8 10 #include <Visualization/qcustomplot.h>
9 11
@@ -68,11 +70,17 void setAxisProperties(QCPAxis &axis, const Unit &unit,
68 70 */
69 71 template <typename T, typename Enabled = void>
70 72 struct AxisSetter {
71 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
73 static void setProperties(QCustomPlot &, SqpColorScale &)
72 74 {
73 75 // Default implementation does nothing
74 76 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
75 77 }
78
79 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
80 {
81 // Default implementation does nothing
82 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
83 }
76 84 };
77 85
78 86 /**
@@ -83,7 +91,12 struct AxisSetter {
83 91 template <typename T>
84 92 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
85 93 or std::is_base_of<VectorSeries, T>::value> > {
86 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
94 static void setProperties(QCustomPlot &, SqpColorScale &)
95 {
96 // Nothing to do
97 }
98
99 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
87 100 {
88 101 dataSeries.lockRead();
89 102 auto xAxisUnit = dataSeries.xAxisUnit();
@@ -101,17 +114,8 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>:
101 114 */
102 115 template <typename T>
103 116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
104 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
105 118 {
106 dataSeries.lockRead();
107 auto xAxisUnit = dataSeries.xAxisUnit();
108 auto yAxisUnit = dataSeries.yAxisUnit();
109 auto valuesUnit = dataSeries.valuesUnit();
110 dataSeries.unlock();
111
112 setAxisProperties(*plot.xAxis, xAxisUnit);
113 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
114
115 119 // Displays color scale in plot
116 120 plot.plotLayout()->insertRow(0);
117 121 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
@@ -125,9 +129,21 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
125 129 }
126 130
127 131 // Set color scale properties
128 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
129 132 colorScale.m_AutomaticThreshold = true;
130 133 }
134
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
136 {
137 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
142
143 setAxisProperties(*plot.xAxis, xAxisUnit);
144 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
145 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
146 }
131 147 };
132 148
133 149 /**
@@ -136,14 +152,25 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
136 152 */
137 153 template <typename T>
138 154 struct AxisHelper : public IAxisHelper {
139 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
155 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
140 156
141 157 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
142 158 {
143 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
159 AxisSetter<T>::setProperties(plot, colorScale);
144 160 }
145 161
146 T &m_DataSeries;
162 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 {
164 if (m_DataSeries) {
165 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
166 }
167 else {
168 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
169 "type of data series and the type supposed";
170 }
171 }
172
173 std::shared_ptr<T> m_DataSeries;
147 174 };
148 175
149 176 } // namespace
@@ -159,19 +186,22 QString formatValue(double value, const QCPAxis &axis)
159 186 }
160 187 }
161 188
162 std::unique_ptr<IAxisHelper>
163 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
189 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
164 190 {
165 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
166 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
167 }
168 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
169 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
170 }
171 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
172 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
173 }
174 else {
175 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
191 switch (variable.type()) {
192 case DataSeriesType::SCALAR:
193 return std::make_unique<AxisHelper<ScalarSeries> >(
194 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
195 case DataSeriesType::SPECTROGRAM:
196 return std::make_unique<AxisHelper<SpectrogramSeries> >(
197 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
198 case DataSeriesType::VECTOR:
199 return std::make_unique<AxisHelper<VectorSeries> >(
200 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
201 default:
202 // Creates default helper
203 break;
176 204 }
205
206 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
177 207 }
@@ -6,6 +6,8
6 6 #include <Data/SpectrogramSeries.h>
7 7 #include <Data/VectorSeries.h>
8 8
9 #include <Variable/Variable.h>
10
9 11 #include <Visualization/qcustomplot.h>
10 12
11 13 Q_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils, "PlottablesRenderingUtils")
@@ -17,7 +19,7 namespace {
17 19 */
18 20 template <typename T, typename Enabled = void>
19 21 struct PlottablesSetter {
20 static void setProperties(T &, PlottablesMap &)
22 static void setProperties(PlottablesMap &)
21 23 {
22 24 // Default implementation does nothing
23 25 qCCritical(LOG_PlottablesRenderingUtils())
@@ -33,20 +35,25 struct PlottablesSetter {
33 35 template <typename T>
34 36 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
35 37 or std::is_base_of<VectorSeries, T>::value> > {
36 static void setProperties(T &dataSeries, PlottablesMap &plottables)
38 static void setProperties(PlottablesMap &plottables)
37 39 {
38 // Gets the number of components of the data series
39 dataSeries.lockRead();
40 auto componentCount = dataSeries.valuesData()->componentCount();
41 dataSeries.unlock();
40 // Finds the plottable with the highest index to determine the number of colors to generate
41 auto end = plottables.cend();
42 auto maxPlottableIndexIt
43 = std::max_element(plottables.cbegin(), end, [](const auto &it1, const auto &it2) {
44 return it1.first < it2.first;
45 });
46 auto componentCount = maxPlottableIndexIt != end ? maxPlottableIndexIt->first + 1 : 0;
42 47
43 48 // Generates colors for each component
44 49 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
45 50
46 51 // For each component of the data series, creates a QCPGraph to add to the plot
47 52 for (auto i = 0; i < componentCount; ++i) {
48 auto graph = plottables.at(i);
49 graph->setPen(QPen{colors.at(i)});
53 auto graphIt = plottables.find(i);
54 if (graphIt != end) {
55 graphIt->second->setPen(QPen{colors.at(i)});
56 }
50 57 }
51 58 }
52 59 };
@@ -58,7 +65,7 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSerie
58 65 template <typename T>
59 66 struct PlottablesSetter<T,
60 67 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
61 static void setProperties(T &, PlottablesMap &plottables)
68 static void setProperties(PlottablesMap &plottables)
62 69 {
63 70 // Checks that for a spectrogram there is only one plottable, that is a colormap
64 71 if (plottables.size() != 1) {
@@ -92,31 +99,28 struct PlottablesSetter<T,
92 99 */
93 100 template <typename T>
94 101 struct PlottablesHelper : public IPlottablesHelper {
95 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
96
97 102 void setProperties(PlottablesMap &plottables) override
98 103 {
99 PlottablesSetter<T>::setProperties(m_DataSeries, plottables);
104 PlottablesSetter<T>::setProperties(plottables);
100 105 }
101
102 T &m_DataSeries;
103 106 };
104 107
105 108 } // namespace
106 109
107 110 std::unique_ptr<IPlottablesHelper>
108 IPlottablesHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
111 IPlottablesHelperFactory::create(const Variable &variable) noexcept
109 112 {
110 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
111 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
112 }
113 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
114 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
115 }
116 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
117 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
118 }
119 else {
120 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
113 switch (variable.type()) {
114 case DataSeriesType::SCALAR:
115 return std::make_unique<PlottablesHelper<ScalarSeries> >();
116 case DataSeriesType::SPECTROGRAM:
117 return std::make_unique<PlottablesHelper<SpectrogramSeries> >();
118 case DataSeriesType::VECTOR:
119 return std::make_unique<PlottablesHelper<VectorSeries> >();
120 default:
121 // Returns default helper
122 break;
121 123 }
124
125 return std::make_unique<PlottablesHelper<IDataSeries> >();
122 126 }
@@ -25,7 +25,7 public:
25 25 */
26 26 template <typename T, typename Enabled = void>
27 27 struct PlottablesCreator {
28 static PlottablesMap createPlottables(T &, QCustomPlot &)
28 static PlottablesMap createPlottables(QCustomPlot &)
29 29 {
30 30 qCCritical(LOG_DataSeries())
31 31 << QObject::tr("Can't create plottables: unmanaged data series type");
@@ -33,34 +33,37 struct PlottablesCreator {
33 33 }
34 34 };
35 35
36 PlottablesMap createGraphs(QCustomPlot &plot, int nbGraphs)
37 {
38 PlottablesMap result{};
39
40 // Creates {nbGraphs} QCPGraph to add to the plot
41 for (auto i = 0; i < nbGraphs; ++i) {
42 auto graph = plot.addGraph();
43 result.insert({i, graph});
44 }
45
46 plot.replot();
47
48 return result;
49 }
50
36 51 /**
37 * Specialization of PlottablesCreator for scalars and vectors
52 * Specialization of PlottablesCreator for scalars
38 53 * @sa ScalarSeries
39 * @sa VectorSeries
40 54 */
41 55 template <typename T>
42 struct PlottablesCreator<T,
43 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
44 or std::is_base_of<VectorSeries, T>::value> > {
45 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
46 {
47 PlottablesMap result{};
48
49 // Gets the number of components of the data series
50 dataSeries.lockRead();
51 auto componentCount = dataSeries.valuesData()->componentCount();
52 dataSeries.unlock();
53
54 // For each component of the data series, creates a QCPGraph to add to the plot
55 for (auto i = 0; i < componentCount; ++i) {
56 auto graph = plot.addGraph();
57 result.insert({i, graph});
58 }
59
60 plot.replot();
56 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value> > {
57 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 1); }
58 };
61 59
62 return result;
63 }
60 /**
61 * Specialization of PlottablesCreator for vectors
62 * @sa VectorSeries
63 */
64 template <typename T>
65 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorSeries, T>::value> > {
66 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 3); }
64 67 };
65 68
66 69 /**
@@ -70,7 +73,7 struct PlottablesCreator<T,
70 73 template <typename T>
71 74 struct PlottablesCreator<T,
72 75 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
73 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
76 static PlottablesMap createPlottables(QCustomPlot &plot)
74 77 {
75 78 PlottablesMap result{};
76 79 result.insert({0, new QCPColorMap{plot.xAxis, plot.yAxis}});
@@ -264,41 +267,59 struct IPlottablesHelper {
264 267 */
265 268 template <typename T>
266 269 struct PlottablesHelper : public IPlottablesHelper {
267 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
270 explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
268 271
269 272 PlottablesMap create(QCustomPlot &plot) const override
270 273 {
271 return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
274 return PlottablesCreator<T>::createPlottables(plot);
272 275 }
273 276
274 277 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
275 278 {
276 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
279 if (m_DataSeries) {
280 PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes);
281 }
282 else {
283 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
284 "between the type of data series and the "
285 "type supposed";
286 }
277 287 }
278 288
279 289 void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const override
280 290 {
281 return PlottablesUpdater<T>::setPlotYAxisRange(m_DataSeries, xAxisRange, plot);
291 if (m_DataSeries) {
292 PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot);
293 }
294 else {
295 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
296 "between the type of data series and the "
297 "type supposed";
298 }
282 299 }
283 300
284 T &m_DataSeries;
301 std::shared_ptr<T> m_DataSeries;
285 302 };
286 303
287 /// Creates IPlottablesHelper according to a data series
288 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
304 /// Creates IPlottablesHelper according to the type of data series a variable holds
305 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable> variable) noexcept
289 306 {
290 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
291 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
292 }
293 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
294 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
295 }
296 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
297 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
298 }
299 else {
300 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
307 switch (variable->type()) {
308 case DataSeriesType::SCALAR:
309 return std::make_unique<PlottablesHelper<ScalarSeries> >(
310 std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries()));
311 case DataSeriesType::SPECTROGRAM:
312 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(
313 std::dynamic_pointer_cast<SpectrogramSeries>(variable->dataSeries()));
314 case DataSeriesType::VECTOR:
315 return std::make_unique<PlottablesHelper<VectorSeries> >(
316 std::dynamic_pointer_cast<VectorSeries>(variable->dataSeries()));
317 default:
318 // Creates default helper
319 break;
301 320 }
321
322 return std::make_unique<PlottablesHelper<IDataSeries> >(nullptr);
302 323 }
303 324
304 325 } // namespace
@@ -307,7 +328,7 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variabl
307 328 QCustomPlot &plot) noexcept
308 329 {
309 330 if (variable) {
310 auto helper = createHelper(variable->dataSeries());
331 auto helper = createHelper(variable);
311 332 auto plottables = helper->create(plot);
312 333 return plottables;
313 334 }
@@ -322,7 +343,7 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
322 343 QCustomPlot &plot) noexcept
323 344 {
324 345 if (variable) {
325 auto helper = createHelper(variable->dataSeries());
346 auto helper = createHelper(variable);
326 347 helper->setYAxisRange(variable->range(), plot);
327 348 }
328 349 else {
@@ -332,9 +353,9 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
332 353 }
333 354
334 355 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
335 std::shared_ptr<IDataSeries> dataSeries,
356 std::shared_ptr<Variable> variable,
336 357 const SqpRange &dateTime)
337 358 {
338 auto helper = createHelper(dataSeries);
359 auto helper = createHelper(variable);
339 360 helper->update(plottables, dateTime);
340 361 }
@@ -9,6 +9,7
9 9 #include <Common/DateUtils.h>
10 10
11 11 #include <Data/IDataSeries.h>
12 #include <Variable/Variable.h>
12 13
13 14 #include <SqpApplication.h>
14 15
@@ -302,14 +303,14 void VisualizationGraphRenderingDelegate::onPlotUpdated() noexcept
302 303 impl->m_Plot.replot();
303 304 }
304 305
305 void VisualizationGraphRenderingDelegate::setAxesProperties(
306 std::shared_ptr<IDataSeries> dataSeries) noexcept
306 void VisualizationGraphRenderingDelegate::setAxesUnits(const Variable &variable) noexcept
307 307 {
308 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
309 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
310 308
311 auto axisHelper = IAxisHelperFactory::create(dataSeries);
312 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
309 auto axisHelper = IAxisHelperFactory::create(variable);
310 axisHelper->setUnits(impl->m_Plot, impl->m_ColorScale);
311
312 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
313 impl->m_XAxisLabel = impl->m_Plot.xAxis->label();
313 314
314 315 // Updates x-axis state
315 316 impl->updateXAxisState();
@@ -317,10 +318,15 void VisualizationGraphRenderingDelegate::setAxesProperties(
317 318 impl->m_Plot.layer(AXES_LAYER)->replot();
318 319 }
319 320
320 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
321 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
321 void VisualizationGraphRenderingDelegate::setGraphProperties(const Variable &variable,
322 PlottablesMap &plottables) noexcept
322 323 {
323 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
324 // Axes' properties
325 auto axisHelper = IAxisHelperFactory::create(variable);
326 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
327
328 // Plottables' properties
329 auto plottablesHelper = IPlottablesHelperFactory::create(variable);
324 330 plottablesHelper->setProperties(plottables);
325 331 }
326 332
@@ -65,10 +65,10 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
65 65 {
66 66 }
67 67
68 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
68 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
69 69 const SqpRange &range)
70 70 {
71 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
71 VisualizationGraphHelper::updateData(plottables, variable, range);
72 72
73 73 // Prevents that data has changed to update rendering
74 74 m_RenderingDelegate->onPlotUpdated();
@@ -94,6 +94,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
94 94
95 95 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
96 96
97 bool m_VariableAutoRangeOnInit = true;
98
97 99 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
98 100 {
99 101 removeDrawingRect(plot);
@@ -294,28 +296,48 void VisualizationGraphWidget::setFlags(GraphFlags flags)
294 296
295 297 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
296 298 {
297 // Uses delegate to create the qcpplot components according to the variable
298 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
299
300 if (auto dataSeries = variable->dataSeries()) {
301 // Set axes properties according to the units of the data series
302 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
299 /// Lambda used to set graph's units and range according to the variable passed in parameter
300 auto loadRange = [this](std::shared_ptr<Variable> variable, const SqpRange &range) {
301 impl->m_RenderingDelegate->setAxesUnits(*variable);
303 302
304 // Sets rendering properties for the new plottables
305 // Warning: this method must be called after setAxesProperties(), as it can access to some
306 // axes properties that have to be initialized
307 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
308 }
303 this->setFlags(GraphFlag::DisableAll);
304 setGraphRange(range);
305 this->setFlags(GraphFlag::EnableAll);
309 306
310 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
307 emit requestDataLoading({variable}, range, false);
308 };
311 309
312 310 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
313 311
314 this->setFlags(GraphFlag::DisableAll);
315 this->setGraphRange(range);
316 this->setFlags(GraphFlag::EnableAll);
312 // Calls update of graph's range and units when the data of the variable have been initialized.
313 // Note: we use QueuedConnection here as the update event must be called in the UI thread
314 connect(variable.get(), &Variable::dataInitialized, this,
315 [ varW = std::weak_ptr<Variable>{variable}, range, loadRange, this ]() {
316 if (auto var = varW.lock()) {
317 // If the variable is the first added in the graph, we load its range
318 auto firstVariableInGraph = range == INVALID_RANGE;
319 auto loadedRange = graphRange();
320 if (impl->m_VariableAutoRangeOnInit) {
321 loadedRange = firstVariableInGraph ? var->range() : range;
322 }
323 loadRange(var, loadedRange);
324 setYRange(var);
325 }
326 },
327 Qt::QueuedConnection);
328
329 // Uses delegate to create the qcpplot components according to the variable
330 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
331
332 // Sets graph properties
333 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
334
335 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
317 336
318 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
337 // If the variable already has its data loaded, load its units and its range in the graph
338 if (variable->dataSeries() != nullptr) {
339 loadRange(variable, range);
340 }
319 341
320 342 emit variableAdded(variable);
321 343 }
@@ -371,14 +393,29 SqpRange VisualizationGraphWidget::graphRange() const noexcept
371 393 return SqpRange{graphRange.lower, graphRange.upper};
372 394 }
373 395
374 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
396 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibration)
375 397 {
376 398 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
399
400 if (calibration) {
401 impl->m_IsCalibration = true;
402 }
403
377 404 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
378 405 ui->widget->replot();
406
407 if (calibration) {
408 impl->m_IsCalibration = false;
409 }
410
379 411 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
380 412 }
381 413
414 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
415 {
416 impl->m_VariableAutoRangeOnInit = value;
417 }
418
382 419 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
383 420 {
384 421 QVector<SqpRange> ranges;
@@ -401,6 +438,20 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges
401 438 plot().replot(QCustomPlot::rpQueuedReplot);
402 439 }
403 440
441 VisualizationSelectionZoneItem *VisualizationGraphWidget::addSelectionZone(const QString &name,
442 const SqpRange &range)
443 {
444 // note: ownership is transfered to QCustomPlot
445 auto zone = new VisualizationSelectionZoneItem(&plot());
446 zone->setName(name);
447 zone->setRange(range.m_TStart, range.m_TEnd);
448 impl->addSelectionZone(zone);
449
450 plot().replot(QCustomPlot::rpQueuedReplot);
451
452 return zone;
453 }
454
404 455 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
405 456 {
406 457 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
@@ -989,7 +1040,7 void VisualizationGraphWidget::onDataCacheVariableUpdated()
989 1040 qCDebug(LOG_VisualizationGraphWidget())
990 1041 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
991 1042 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
992 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
1043 impl->updateData(variableEntry.second, variable, variable->range());
993 1044 }
994 1045 }
995 1046 }
@@ -999,6 +1050,6 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> v
999 1050 {
1000 1051 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1001 1052 if (it != impl->m_VariableToPlotMultiMap.end()) {
1002 impl->updateData(it->second, variable->dataSeries(), range);
1053 impl->updateData(it->second, variable, range);
1003 1054 }
1004 1055 }
@@ -388,8 +388,11 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QP
388 388 break;
389 389 }
390 390
391 emit rangeEdited(range());
392
391 393 for (auto associatedZone : impl->m_AssociatedEditedZones) {
392 394 associatedZone->parentPlot()->replot();
395 emit associatedZone->rangeEdited(associatedZone->range());
393 396 }
394 397 }
395 398 else {
@@ -7,6 +7,7
7 7
8 8 #include "Visualization/MacScrollBarStyle.h"
9 9
10 #include "DataSource/DataSourceController.h"
10 11 #include "Variable/VariableController.h"
11 12
12 13 #include "Common/MimeTypesDef.h"
@@ -69,6 +70,8 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
69 70 void dropZone(int index, VisualizationTabWidget *tabWidget);
70 71 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
71 72 VisualizationTabWidget *tabWidget);
73 void dropProducts(const QVariantList &productsMetaData, int index,
74 VisualizationTabWidget *tabWidget);
72 75 };
73 76
74 77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
@@ -91,6 +94,8 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
91 94 VisualizationDragDropContainer::DropBehavior::Inserted);
92 95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
93 96 VisualizationDragDropContainer::DropBehavior::Inserted);
97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
98 VisualizationDragDropContainer::DropBehavior::Inserted);
94 99
95 100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
96 101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
@@ -229,6 +234,11 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
229 234 mimeData->data(MIME_TYPE_VARIABLE_LIST));
230 235 impl->dropVariables(variables, index, this);
231 236 }
237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
238 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
239 mimeData->data(MIME_TYPE_PRODUCT_LIST));
240 impl->dropProducts(productsData, index, this);
241 }
232 242 else {
233 243 qCWarning(LOG_VisualizationZoneWidget())
234 244 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
@@ -352,3 +362,28 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
352 362
353 363 tabWidget->createZone(variables, index);
354 364 }
365
366 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
368 {
369 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
370 // compatible variable here
371 if (productsMetaData.count() != 1) {
372 qCWarning(LOG_VisualizationZoneWidget())
373 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
374 "aborted.");
375 return;
376 }
377
378 auto context = new QObject{tabWidget};
379 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
380 [this, index, tabWidget, context](auto variable) {
381 tabWidget->createZone({variable}, index);
382 delete context; // removes the connection
383 },
384 Qt::QueuedConnection);
385
386 auto productData = productsMetaData.first().toHash();
387 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
388 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
389 }
@@ -10,6 +10,7
10 10 #include "Common/VisualizationDef.h"
11 11
12 12 #include <Data/SqpRange.h>
13 #include <DataSource/DataSourceController.h>
13 14 #include <Time/TimeController.h>
14 15 #include <Variable/Variable.h>
15 16 #include <Variable/VariableController.h>
@@ -78,6 +79,8 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
78 79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
79 80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
80 81 VisualizationZoneWidget *zoneWidget);
82 void dropProducts(const QVariantList &productsData, int index,
83 VisualizationZoneWidget *zoneWidget);
81 84 };
82 85
83 86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
@@ -94,6 +97,8 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
94 97 VisualizationDragDropContainer::DropBehavior::Inserted);
95 98 ui->dragDropContainer->setMimeType(
96 99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
100 ui->dragDropContainer->setMimeType(
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
97 102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
98 103 VisualizationDragDropContainer::DropBehavior::Merged);
99 104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
@@ -477,6 +482,11 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
477 482 mimeData->data(MIME_TYPE_VARIABLE_LIST));
478 483 impl->dropVariables(variables, index, this);
479 484 }
485 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
486 auto products = sqpApp->dataSourceController().productsDataForMimeData(
487 mimeData->data(MIME_TYPE_PRODUCT_LIST));
488 impl->dropProducts(products, index, this);
489 }
480 490 else {
481 491 qCWarning(LOG_VisualizationZoneWidget())
482 492 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
@@ -502,6 +512,22 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
502 512 graphWidget->addVariable(var, graphWidget->graphRange());
503 513 }
504 514 }
515 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
516 auto products = sqpApp->dataSourceController().productsDataForMimeData(
517 mimeData->data(MIME_TYPE_PRODUCT_LIST));
518
519 auto context = new QObject{this};
520 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
521 [this, graphWidget, context](auto variable) {
522 graphWidget->addVariable(variable, graphWidget->graphRange());
523 delete context; // removes the connection
524 },
525 Qt::QueuedConnection);
526
527 auto productData = products.first().toHash();
528 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
529 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
530 }
505 531 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
506 532 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
507 533 graphWidget->setGraphRange(range);
@@ -599,3 +625,28 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
599 625
600 626 zoneWidget->createGraph(variables, index);
601 627 }
628
629 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
630 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
631 {
632 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
633 // compatible variable here
634 if (productsData.count() != 1) {
635 qCWarning(LOG_VisualizationZoneWidget())
636 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
637 "aborted.");
638 return;
639 }
640
641 auto context = new QObject{zoneWidget};
642 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
643 [this, index, zoneWidget, context](auto variable) {
644 zoneWidget->createGraph(variable, index);
645 delete context; // removes the connection
646 },
647 Qt::QueuedConnection);
648
649 auto productData = productsData.first().toHash();
650 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
651 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
652 }
@@ -85,9 +85,6
85 85 </item>
86 86 <item>
87 87 <widget class="QToolButton" name="btnChart">
88 <property name="enabled">
89 <bool>false</bool>
90 </property>
91 88 <property name="text">
92 89 <string>G</string>
93 90 </property>
@@ -3,6 +3,8
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 #include <Data/DataSeriesType.h>
7
6 8 #include <QLoggingCategory>
7 9
8 10 #include <memory>
@@ -12,10 +14,8 class IDataSeries;
12 14 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser)
13 15
14 16 struct SCIQLOP_AMDA_EXPORT AmdaResultParser {
15 enum class ValueType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN };
16
17 17 static std::shared_ptr<IDataSeries> readTxt(const QString &filePath,
18 ValueType valueType) noexcept;
18 DataSeriesType valueType) noexcept;
19 19 };
20 20
21 21 #endif // SCIQLOP_AMDARESULTPARSER_H
@@ -39,21 +39,6 QString dateFormat(double sqpRange) noexcept
39 39 return dateTime.toString(AMDA_TIME_FORMAT);
40 40 }
41 41
42 AmdaResultParser::ValueType valueType(const QString &valueType)
43 {
44 if (valueType == QStringLiteral("scalar")) {
45 return AmdaResultParser::ValueType::SCALAR;
46 }
47 else if (valueType == QStringLiteral("spectrogram")) {
48 return AmdaResultParser::ValueType::SPECTROGRAM;
49 }
50 else if (valueType == QStringLiteral("vector")) {
51 return AmdaResultParser::ValueType::VECTOR;
52 }
53 else {
54 return AmdaResultParser::ValueType::UNKNOWN;
55 }
56 }
57 42
58 43 } // namespace
59 44
@@ -171,7 +156,8 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVa
171 156
172 157 // Retrieves the data type that determines whether the expected format for the result file is
173 158 // scalar, vector...
174 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
159 auto productValueType
160 = DataSeriesTypeUtils::fromString(data.value(AMDA_DATA_TYPE_KEY).toString());
175 161
176 162 // /////////// //
177 163 // Creates URL //
@@ -24,16 +24,16 bool isCommentLine(const QString &line)
24 24 * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...)
25 25 * @return the helper created
26 26 */
27 std::unique_ptr<IAmdaResultParserHelper> createHelper(AmdaResultParser::ValueType valueType)
27 std::unique_ptr<IAmdaResultParserHelper> createHelper(DataSeriesType valueType)
28 28 {
29 29 switch (valueType) {
30 case AmdaResultParser::ValueType::SCALAR:
30 case DataSeriesType::SCALAR:
31 31 return std::make_unique<ScalarParserHelper>();
32 case AmdaResultParser::ValueType::SPECTROGRAM:
32 case DataSeriesType::SPECTROGRAM:
33 33 return std::make_unique<SpectrogramParserHelper>();
34 case AmdaResultParser::ValueType::VECTOR:
34 case DataSeriesType::VECTOR:
35 35 return std::make_unique<VectorParserHelper>();
36 case AmdaResultParser::ValueType::UNKNOWN:
36 case DataSeriesType::UNKNOWN:
37 37 // Invalid case
38 38 break;
39 39 }
@@ -82,9 +82,9 void readResults(IAmdaResultParserHelper &helper, QTextStream &stream)
82 82 } // namespace
83 83
84 84 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
85 ValueType valueType) noexcept
85 DataSeriesType type) noexcept
86 86 {
87 if (valueType == ValueType::UNKNOWN) {
87 if (type == DataSeriesType::UNKNOWN) {
88 88 qCCritical(LOG_AmdaResultParser())
89 89 << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
90 90 return nullptr;
@@ -110,7 +110,7 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
110 110 return nullptr;
111 111 }
112 112
113 auto helper = createHelper(valueType);
113 auto helper = createHelper(type);
114 114 Q_ASSERT(helper != nullptr);
115 115
116 116 // Reads header file to retrieve properties
@@ -115,7 +115,7 void TestAmdaAcquisition::testAcquisition()
115 115 // Retrieves data file
116 116 QFETCH(QString, dataFilename);
117 117 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
118 auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR);
118 auto results = AmdaResultParser::readTxt(filePath, DataSeriesType::SCALAR);
119 119
120 120 /// Lambda used to validate a variable at each step
121 121 auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) {
@@ -187,7 +187,7 private:
187 187 }
188 188
189 189 template <typename T>
190 void testRead(AmdaResultParser::ValueType valueType)
190 void testRead(DataSeriesType valueType)
191 191 {
192 192 QFETCH(QString, inputFileName);
193 193 QFETCH(ExpectedResults<T>, expectedResults);
@@ -319,7 +319,7 void TestAmdaResultParser::testReadScalarTxt_data()
319 319
320 320 void TestAmdaResultParser::testReadScalarTxt()
321 321 {
322 testRead<ScalarSeries>(AmdaResultParser::ValueType::SCALAR);
322 testRead<ScalarSeries>(DataSeriesType::SCALAR);
323 323 }
324 324
325 325 void TestAmdaResultParser::testReadSpectrogramTxt_data()
@@ -533,7 +533,7 void TestAmdaResultParser::testReadSpectrogramTxt_data()
533 533
534 534 void TestAmdaResultParser::testReadSpectrogramTxt()
535 535 {
536 testRead<SpectrogramSeries>(AmdaResultParser::ValueType::SPECTROGRAM);
536 testRead<SpectrogramSeries>(DataSeriesType::SPECTROGRAM);
537 537 }
538 538
539 539 void TestAmdaResultParser::testReadVectorTxt_data()
@@ -572,7 +572,7 void TestAmdaResultParser::testReadVectorTxt_data()
572 572
573 573 void TestAmdaResultParser::testReadVectorTxt()
574 574 {
575 testRead<VectorSeries>(AmdaResultParser::ValueType::VECTOR);
575 testRead<VectorSeries>(DataSeriesType::VECTOR);
576 576 }
577 577
578 578 QTEST_MAIN(TestAmdaResultParser)
General Comments 0
You need to be logged in to leave comments. Login now