##// END OF EJS Templates
Adds a close button to a graph widget + calls close() method when clicked...
Alexandre Leroux -
r266:64be3fdecdc1
parent child
Show More
@@ -1,202 +1,200
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphHelper.h"
4 4 #include "ui_VisualizationGraphWidget.h"
5 5
6 6 #include <Data/ArrayData.h>
7 7 #include <Data/IDataSeries.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <unordered_map>
13 13
14 14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15 15
16 16 namespace {
17 17
18 18 /// Key pressed to enable zoom on horizontal axis
19 19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20 20
21 21 /// Key pressed to enable zoom on vertical axis
22 22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23 23
24 24 } // namespace
25 25
26 26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27 27
28 28 // 1 variable -> n qcpplot
29 29 std::unordered_multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *>
30 30 m_VariableToPlotMultiMap;
31 31 };
32 32
33 33 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
34 34 : QWidget{parent},
35 35 ui{new Ui::VisualizationGraphWidget},
36 36 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
37 37 {
38 38 ui->setupUi(this);
39 39
40 // qcpplot title
41 ui->widget->plotLayout()->insertRow(0);
42 ui->widget->plotLayout()->addElement(0, 0, new QCPTextElement{ui->widget, name});
40 ui->graphNameLabel->setText(name);
41
42 // 'Close' options : widget is deleted when closed
43 setAttribute(Qt::WA_DeleteOnClose);
44 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
45 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
43 46
44 47 // Set qcpplot properties :
45 48 // - Drag (on x-axis) and zoom are enabled
46 49 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
47 50 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
48 51 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
49 52 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
50 53 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
51 54 &QCPAxis::rangeChanged),
52 55 this, &VisualizationGraphWidget::onRangeChanged);
53 56 }
54 57
55 58
56 59 VisualizationGraphWidget::~VisualizationGraphWidget()
57 60 {
58 61 delete ui;
59 62 }
60 63
61 64 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
62 65 {
63 66 // Uses delegate to create the qcpplot components according to the variable
64 67 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
65 68
66 69 for (auto createdPlottable : qAsConst(createdPlottables)) {
67 70 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
68 71 }
69 72
70 73 connect(variable.get(), SIGNAL(dataCacheUpdated()), this, SLOT(onDataCacheVariableUpdated()));
71 74 }
72 75
73 76 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
74 77 {
75 78 if (visitor) {
76 79 visitor->visit(this);
77 80 }
78 81 else {
79 82 qCCritical(LOG_VisualizationGraphWidget())
80 83 << tr("Can't visit widget : the visitor is null");
81 84 }
82 85 }
83 86
84 87 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
85 88 {
86 89 /// @todo : for the moment, a graph can always accomodate a variable
87 90 Q_UNUSED(variable);
88 91 return true;
89 92 }
90 93
91 94 QString VisualizationGraphWidget::name() const
92 95 {
93 if (auto title = dynamic_cast<QCPTextElement *>(ui->widget->plotLayout()->elementAt(0))) {
94 return title->text();
95 }
96 else {
97 return QString{};
98 }
96 return ui->graphNameLabel->text();
99 97 }
100 98
101 99 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
102 100 {
103 101
104 102 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
105 103
106 104 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
107 105 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
108 106
109 107 auto variable = it->first;
110 108 qCInfo(LOG_VisualizationGraphWidget())
111 109 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
112 110 << variable->dataSeries()->xAxisData()->size();
113 111 auto dateTime = SqpDateTime{t2.lower, t2.upper};
114 112
115 113 if (!variable->contains(dateTime)) {
116 114
117 115 auto variableDateTimeWithTolerance = dateTime;
118 116 if (variable->intersect(dateTime)) {
119 117 auto variableDateTime = variable->dateTime();
120 118 if (variableDateTime.m_TStart < dateTime.m_TStart) {
121 119
122 120 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
123 121 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
124 122 // Tolerance have to be added to the right
125 123 // add 10% tolerance for right (end) side
126 124 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
127 125 variableDateTimeWithTolerance.m_TEnd += tolerance;
128 126 }
129 127 if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
130 128 auto diffStartToKeepDelta = dateTime.m_TStart - dateTime.m_TStart;
131 129 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
132 130 // Tolerance have to be added to the left
133 131 // add 10% tolerance for left (start) side
134 132 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
135 133 variableDateTimeWithTolerance.m_TStart -= tolerance;
136 134 }
137 135 }
138 136 else {
139 137 // add 10% tolerance for each side
140 138 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
141 139 variableDateTimeWithTolerance.m_TStart -= tolerance;
142 140 variableDateTimeWithTolerance.m_TEnd += tolerance;
143 141 }
144 142 variable->setDateTime(dateTime);
145 143
146 144 // CHangement detected, we need to ask controller to request data loading
147 145 sqpApp->variableController().requestDataLoading(variable,
148 146 variableDateTimeWithTolerance);
149 147 }
150 148 }
151 149 }
152 150
153 151 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
154 152 {
155 153 auto zoomOrientations = QFlags<Qt::Orientation>{};
156 154
157 155 // Lambda that enables a zoom orientation if the key modifier related to this orientation
158 156 // has
159 157 // been pressed
160 158 auto enableOrientation
161 159 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
162 160 auto orientationEnabled = event->modifiers().testFlag(modifier);
163 161 zoomOrientations.setFlag(orientation, orientationEnabled);
164 162 };
165 163 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
166 164 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
167 165
168 166 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
169 167 }
170 168
171 169 void VisualizationGraphWidget::onDataCacheVariableUpdated()
172 170 {
173 171 // NOTE:
174 172 // We don't want to call the method for each component of a variable unitarily, but for
175 173 // all
176 174 // its components at once (eg its three components in the case of a vector).
177 175
178 176 // The unordered_multimap does not do this easily, so the question is whether to:
179 177 // - use an ordered_multimap and the algos of std to group the values by key
180 178 // - use a map (unique keys) and store as values directly the list of components
181 179
182 180 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
183 181 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
184 182 auto variable = it->first;
185 183 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
186 184 variable->dataSeries(), variable->dateTime());
187 185 }
188 186 }
189 187
190 188 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
191 189 {
192 190 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
193 191
194 192 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
195 193
196 194 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
197 195 abstractPlotableVect.push_back(it->second);
198 196 }
199 197
200 198 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
201 199 variable->dateTime());
202 200 }
@@ -1,32 +1,83
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>VisualizationGraphWidget</class>
4 4 <widget class="QWidget" name="VisualizationGraphWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>400</width>
10 10 <height>300</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout">
17 17 <item>
18 <widget class="QCustomPlot" name="widget" native="true"/>
18 <widget class="QWidget" name="infobar" native="true">
19 <layout class="QHBoxLayout" name="horizontalLayout_2">
20 <property name="leftMargin">
21 <number>0</number>
22 </property>
23 <property name="topMargin">
24 <number>0</number>
25 </property>
26 <property name="rightMargin">
27 <number>0</number>
28 </property>
29 <property name="bottomMargin">
30 <number>0</number>
31 </property>
32 <item>
33 <widget class="QLabel" name="graphNameLabel">
34 <property name="styleSheet">
35 <string notr="true">font: 75 9pt &quot;MS Shell Dlg 2&quot;;</string>
36 </property>
37 <property name="text">
38 <string>TextLabel</string>
39 </property>
40 <property name="textFormat">
41 <enum>Qt::AutoText</enum>
42 </property>
43 <property name="alignment">
44 <set>Qt::AlignCenter</set>
45 </property>
46 </widget>
47 </item>
48 <item>
49 <widget class="QToolButton" name="closeButton">
50 <property name="styleSheet">
51 <string notr="true">background-color: transparent;</string>
52 </property>
53 <property name="text">
54 <string>Close</string>
55 </property>
56 </widget>
57 </item>
58 </layout>
59 </widget>
60 </item>
61 <item>
62 <widget class="QCustomPlot" name="widget" native="true">
63 <property name="sizePolicy">
64 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
65 <horstretch>0</horstretch>
66 <verstretch>0</verstretch>
67 </sizepolicy>
68 </property>
69 </widget>
19 70 </item>
20 71 </layout>
21 72 </widget>
22 73 <customwidgets>
23 74 <customwidget>
24 75 <class>QCustomPlot</class>
25 76 <extends>QWidget</extends>
26 77 <header>Visualization/qcustomplot.h</header>
27 78 <container>1</container>
28 79 </customwidget>
29 80 </customwidgets>
30 81 <resources/>
31 82 <connections/>
32 83 </ui>
General Comments 0
You need to be logged in to leave comments. Login now