##// END OF EJS Templates
@@ -1,74 +1,76
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the QLop Software
3 3 -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include <QProcessEnvironment>
24 24 #include <QThread>
25 25 #include <SqpApplication.h>
26 26 #include <qglobal.h>
27 27
28 28 #include <Plugin/PluginManager.h>
29 29 #include <QDir>
30 30
31 31 namespace {
32 32
33 33 /// Name of the directory containing the plugins
34 34
35 35 #if _WIN32 || _WIN64
36 36 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
37 37 #endif
38 38
39 39 } // namespace
40 40
41 41 int main(int argc, char *argv[])
42 42 {
43 43 SqpApplication a{argc, argv};
44 44 SqpApplication::setOrganizationName("LPP");
45 45 SqpApplication::setOrganizationDomain("lpp.fr");
46 46 SqpApplication::setApplicationName("SciQLop");
47 47 MainWindow w;
48 48 w.show();
49 49
50 50 // Loads plugins
51 51 auto pluginDir = QDir{sqpApp->applicationDirPath()};
52 52 #if _WIN32 || _WIN64
53 53 pluginDir.mkdir(PLUGIN_DIRECTORY_NAME);
54 54 pluginDir.cd(PLUGIN_DIRECTORY_NAME);
55 55 #endif
56 56
57 57
58 58 #if __GNUC__
59 59 #if __x86_64__ || __ppc64__
60 60 if (!pluginDir.cd("../lib64/SciQlop")) {
61 61 pluginDir.cd("../lib64/sciqlop");
62 62 }
63 63 #else
64 __x86_64__ || __ppc64__ if (!pluginDir.cd("../lib/SciQlop")) { pluginDir.cd("../lib/sciqlop"); }
64 if (!pluginDir.cd("../lib/SciQlop")) {
65 pluginDir.cd("../lib/sciqlop");
66 }
65 67 #endif
66 68 #endif
67 69 qCDebug(LOG_PluginManager())
68 70 << QObject::tr("Plugin directory: %1").arg(pluginDir.absolutePath());
69 71
70 72 PluginManager pluginManager{};
71 73 pluginManager.loadPlugins(pluginDir);
72 74
73 75 return a.exec();
74 76 }
@@ -1,26 +1,25
1 1 #ifndef SCIQLOP_IVISUALIZATIONWIDGET_H
2 2 #define SCIQLOP_IVISUALIZATIONWIDGET_H
3 3
4 4 #include "Visualization/IVariableContainer.h"
5 5
6 6 #include <QString>
7 7 #include <memory>
8 8
9 9 class IVisualizationWidgetVisitor;
10 10
11 11 /**
12 12 * @brief The IVisualizationWidget handles the visualization widget.
13 13 */
14 14 class IVisualizationWidget : public IVariableContainer {
15 15
16 16 public:
17 17 virtual ~IVisualizationWidget() = default;
18 18
19 19 /// Initializes the plugin
20 20 virtual void accept(IVisualizationWidgetVisitor *visitor) = 0;
21 virtual void close() = 0;
22 21 virtual QString name() const = 0;
23 22 };
24 23
25 24
26 25 #endif // SCIQLOP_IVISUALIZATIONWIDGET_H
@@ -1,56 +1,59
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 #include <memory>
10 10
11 11 #include <Common/spimpl.h>
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 14
15 15 class QCPRange;
16 16 class Variable;
17 17
18 18 namespace Ui {
19 19 class VisualizationGraphWidget;
20 20 } // namespace Ui
21 21
22 22 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
23 23 Q_OBJECT
24 24
25 25 public:
26 26 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
27 27 virtual ~VisualizationGraphWidget();
28 28
29 29 void addVariable(std::shared_ptr<Variable> variable);
30 /// Removes a variable from the graph
31 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
30 32
31 33 // IVisualizationWidget interface
32 34 void accept(IVisualizationWidgetVisitor *visitor) override;
33 35 bool canDrop(const Variable &variable) const override;
34 void close() override;
35 36 QString name() const override;
36 37
37 38 void updateDisplay(std::shared_ptr<Variable> variable);
38 39
39 40
40 41 private:
41 42 Ui::VisualizationGraphWidget *ui;
42 43
43 44 class VisualizationGraphWidgetPrivate;
44 45 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
45 46
46 47 private slots:
48 /// Slot called when right clicking on the graph (displays a menu)
49 void onGraphMenuRequested(const QPoint &pos) noexcept;
47 50
48 51 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
49 52
50 53 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
51 54 void onMouseWheel(QWheelEvent *event) noexcept;
52 55
53 56 void onDataCacheVariableUpdated();
54 57 };
55 58
56 59 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,54 +1,50
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QWidget>
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12 12
13 13 class Variable;
14 14 class VisualizationZoneWidget;
15 15
16 16 namespace Ui {
17 17 class VisualizationTabWidget;
18 18 } // namespace Ui
19 19
20 20 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
21 21 Q_OBJECT
22 22
23 23 public:
24 24 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
25 25 virtual ~VisualizationTabWidget();
26 26
27 27 /// Add a zone widget
28 28 void addZone(VisualizationZoneWidget *zoneWidget);
29 29
30 30 /**
31 31 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
32 32 * zone.
33 33 * @param variable the variable for which to create the zone
34 34 * @return the pointer to the created zone
35 35 */
36 36 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
37 37
38 /// Remove a zone
39 void removeZone(VisualizationZoneWidget *zone);
40
41 38 // IVisualizationWidget interface
42 39 void accept(IVisualizationWidgetVisitor *visitor) override;
43 40 bool canDrop(const Variable &variable) const override;
44 void close() override;
45 41 QString name() const override;
46 42
47 43 private:
48 44 Ui::VisualizationTabWidget *ui;
49 45
50 46 class VisualizationTabWidgetPrivate;
51 47 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
52 48 };
53 49
54 50 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,53 +1,43
1 1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
10 10
11 11 class QMenu;
12 12 class Variable;
13 13 class VisualizationTabWidget;
14 14
15 15 namespace Ui {
16 16 class VisualizationWidget;
17 17 } // namespace Ui
18 18
19 19 class VisualizationWidget : public QWidget, public IVisualizationWidget {
20 20 Q_OBJECT
21 21
22 22 public:
23 23 explicit VisualizationWidget(QWidget *parent = 0);
24 24 virtual ~VisualizationWidget();
25 25
26 /// Add a zone widget
27 virtual void addTab(VisualizationTabWidget *tabWidget);
28
29 /// Create a tab using a Variable
30 VisualizationTabWidget *createTab();
31
32 /// Remove a tab
33 void removeTab(VisualizationTabWidget *tab);
34
35 26 // IVisualizationWidget interface
36 27 void accept(IVisualizationWidgetVisitor *visitor) override;
37 28 bool canDrop(const Variable &variable) const override;
38 void close() override;
39 29 QString name() const override;
40 30
41 31 public slots:
42 32 /**
43 33 * Attaches to a menu the menu relating to the visualization of a variable
44 34 * @param menu the parent menu of the generated menu
45 35 * @param variable the variable for which to generate the menu
46 36 */
47 37 void attachVariableMenu(QMenu *menu, std::shared_ptr<Variable> variable) noexcept;
48 38
49 39 private:
50 40 Ui::VisualizationWidget *ui;
51 41 };
52 42
53 43 #endif // VISUALIZATIONWIDGET_H
@@ -1,48 +1,44
1 1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
10 10
11 11 namespace Ui {
12 12 class VisualizationZoneWidget;
13 13 } // Ui
14 14
15 15 class Variable;
16 16 class VisualizationGraphWidget;
17 17
18 18 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
19 19 Q_OBJECT
20 20
21 21 public:
22 22 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
23 23 virtual ~VisualizationZoneWidget();
24 24
25 25 /// Add a graph widget
26 26 void addGraph(VisualizationGraphWidget *graphWidget);
27 27
28 28 /**
29 29 * Creates a graph using a variable. The variable will be displayed in the new graph.
30 30 * @param variable the variable for which to create the graph
31 31 * @return the pointer to the created graph
32 32 */
33 33 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
34 34
35 /// Remove a graph
36 void removeGraph(VisualizationGraphWidget *graph);
37
38 35 // IVisualizationWidget interface
39 36 void accept(IVisualizationWidgetVisitor *visitor) override;
40 37 bool canDrop(const Variable &variable) const override;
41 void close() override;
42 38 QString name() const override;
43 39
44 40 private:
45 41 Ui::VisualizationZoneWidget *ui;
46 42 };
47 43
48 44 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,208 +1,237
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 std::unordered_multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *>
30 m_VariableToPlotMultiMap;
29 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
31 30 };
32 31
33 32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
34 33 : QWidget{parent},
35 34 ui{new Ui::VisualizationGraphWidget},
36 35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
37 36 {
38 37 ui->setupUi(this);
39 38
40 // qcpplot title
41 ui->widget->plotLayout()->insertRow(0);
42 ui->widget->plotLayout()->addElement(0, 0, new QCPTextElement{ui->widget, name});
39 ui->graphNameLabel->setText(name);
40
41 // 'Close' options : widget is deleted when closed
42 setAttribute(Qt::WA_DeleteOnClose);
43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
43 45
44 46 // Set qcpplot properties :
45 47 // - Drag (on x-axis) and zoom are enabled
46 48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
47 49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
48 50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
49 51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
50 52 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
51 53 &QCPAxis::rangeChanged),
52 54 this, &VisualizationGraphWidget::onRangeChanged);
55
56 // Activates menu when right clicking on the graph
57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
59 &VisualizationGraphWidget::onGraphMenuRequested);
53 60 }
54 61
55 62
56 63 VisualizationGraphWidget::~VisualizationGraphWidget()
57 64 {
58 65 delete ui;
59 66 }
60 67
61 68 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
62 69 {
63 70 // Uses delegate to create the qcpplot components according to the variable
64 71 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
65 72
66 73 for (auto createdPlottable : qAsConst(createdPlottables)) {
67 74 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
68 75 }
69 76
70 77 connect(variable.get(), SIGNAL(dataCacheUpdated()), this, SLOT(onDataCacheVariableUpdated()));
71 78 }
72 79
80 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
81 {
82 // Each component associated to the variable :
83 // - is removed from qcpplot (which deletes it)
84 // - is no longer referenced in the map
85 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
86 for (auto it = componentsIt.first; it != componentsIt.second;) {
87 ui->widget->removePlottable(it->second);
88 it = impl->m_VariableToPlotMultiMap.erase(it);
89 }
90
91 // Updates graph
92 ui->widget->replot();
93 }
94
73 95 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
74 96 {
75 97 if (visitor) {
76 98 visitor->visit(this);
77 99 }
78 100 else {
79 101 qCCritical(LOG_VisualizationGraphWidget())
80 102 << tr("Can't visit widget : the visitor is null");
81 103 }
82 104 }
83 105
84 106 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
85 107 {
86 108 /// @todo : for the moment, a graph can always accomodate a variable
87 109 Q_UNUSED(variable);
88 110 return true;
89 111 }
90 112
91 void VisualizationGraphWidget::close()
113 QString VisualizationGraphWidget::name() const
92 114 {
93 // The main view cannot be directly closed.
94 return;
115 return ui->graphNameLabel->text();
95 116 }
96 117
97 QString VisualizationGraphWidget::name() const
118 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
98 119 {
99 if (auto title = dynamic_cast<QCPTextElement *>(ui->widget->plotLayout()->elementAt(0))) {
100 return title->text();
120 QMenu graphMenu{};
121
122 // Iterates on variables (unique keys)
123 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
124 end = impl->m_VariableToPlotMultiMap.cend();
125 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
126 // 'Remove variable' action
127 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
128 [ this, var = it->first ]() { removeVariable(var); });
101 129 }
102 else {
103 return QString{};
130
131 if (!graphMenu.isEmpty()) {
132 graphMenu.exec(mapToGlobal(pos));
104 133 }
105 134 }
106 135
107 136 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
108 137 {
109 138
110 139 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
111 140
112 141 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
113 142 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
114 143
115 144 auto variable = it->first;
116 145 qCInfo(LOG_VisualizationGraphWidget())
117 146 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
118 147 << variable->dataSeries()->xAxisData()->size();
119 148 auto dateTime = SqpDateTime{t2.lower, t2.upper};
120 149
121 150 if (!variable->contains(dateTime)) {
122 151
123 152 auto variableDateTimeWithTolerance = dateTime;
124 153 if (variable->intersect(dateTime)) {
125 154 auto variableDateTime = variable->dateTime();
126 155 if (variableDateTime.m_TStart < dateTime.m_TStart) {
127 156
128 157 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
129 158 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
130 159 // Tolerance have to be added to the right
131 160 // add 10% tolerance for right (end) side
132 161 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
133 162 variableDateTimeWithTolerance.m_TEnd += tolerance;
134 163 }
135 164 if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
136 165 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
137 166 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
138 167 // Tolerance have to be added to the left
139 168 // add 10% tolerance for left (start) side
140 169 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
141 170 variableDateTimeWithTolerance.m_TStart -= tolerance;
142 171 }
143 172 }
144 173 else {
145 174 // add 10% tolerance for each side
146 175 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
147 176 variableDateTimeWithTolerance.m_TStart -= tolerance;
148 177 variableDateTimeWithTolerance.m_TEnd += tolerance;
149 178 }
150 179 variable->setDateTime(dateTime);
151 180
152 181 // CHangement detected, we need to ask controller to request data loading
153 182 sqpApp->variableController().requestDataLoading(variable,
154 183 variableDateTimeWithTolerance);
155 184 }
156 185 }
157 186 }
158 187
159 188 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
160 189 {
161 190 auto zoomOrientations = QFlags<Qt::Orientation>{};
162 191
163 192 // Lambda that enables a zoom orientation if the key modifier related to this orientation
164 193 // has
165 194 // been pressed
166 195 auto enableOrientation
167 196 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
168 197 auto orientationEnabled = event->modifiers().testFlag(modifier);
169 198 zoomOrientations.setFlag(orientation, orientationEnabled);
170 199 };
171 200 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
172 201 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
173 202
174 203 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
175 204 }
176 205
177 206 void VisualizationGraphWidget::onDataCacheVariableUpdated()
178 207 {
179 208 // NOTE:
180 209 // We don't want to call the method for each component of a variable unitarily, but for
181 210 // all
182 211 // its components at once (eg its three components in the case of a vector).
183 212
184 213 // The unordered_multimap does not do this easily, so the question is whether to:
185 214 // - use an ordered_multimap and the algos of std to group the values by key
186 215 // - use a map (unique keys) and store as values directly the list of components
187 216
188 217 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
189 218 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
190 219 auto variable = it->first;
191 220 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
192 221 variable->dataSeries(), variable->dateTime());
193 222 }
194 223 }
195 224
196 225 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
197 226 {
198 227 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
199 228
200 229 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
201 230
202 231 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
203 232 abstractPlotableVect.push_back(it->second);
204 233 }
205 234
206 235 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
207 236 variable->dateTime());
208 237 }
@@ -1,105 +1,98
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 6
7 7 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
8 8
9 9 namespace {
10 10
11 11 /// Generates a default name for a new zone, according to the number of zones already displayed in
12 12 /// the tab
13 13 QString defaultZoneName(const QLayout &layout)
14 14 {
15 15 auto count = 0;
16 16 for (auto i = 0; i < layout.count(); ++i) {
17 17 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
18 18 count++;
19 19 }
20 20 }
21 21
22 22 return QObject::tr("Zone %1").arg(count + 1);
23 23 }
24 24
25 25 } // namespace
26 26
27 27 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
28 28 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
29 29
30 30 QString m_Name;
31 31 };
32 32
33 33 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
34 34 : QWidget{parent},
35 35 ui{new Ui::VisualizationTabWidget},
36 36 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
37 37 {
38 38 ui->setupUi(this);
39
40 // Widget is deleted when closed
41 setAttribute(Qt::WA_DeleteOnClose);
39 42 }
40 43
41 44 VisualizationTabWidget::~VisualizationTabWidget()
42 45 {
43 46 delete ui;
44 47 }
45 48
46 49 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
47 50 {
48 51 this->layout()->addWidget(zoneWidget);
49 52 }
50 53
51 54 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
52 55 {
53 56 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(*layout()), this};
54 57 this->addZone(zoneWidget);
55 58
56 59 // Creates a new graph into the zone
57 60 zoneWidget->createGraph(variable);
58 61
59 62 return zoneWidget;
60 63 }
61 64
62 void VisualizationTabWidget::removeZone(VisualizationZoneWidget *zone)
63 {
64 }
65
66 65 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
67 66 {
68 67 if (visitor) {
69 68 visitor->visitEnter(this);
70 69
71 70 // Apply visitor to zone children
72 71 for (auto i = 0; i < layout()->count(); ++i) {
73 72 if (auto item = layout()->itemAt(i)) {
74 73 // Widgets different from zones are not visited (no action)
75 74 if (auto visualizationZoneWidget
76 75 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
77 76 visualizationZoneWidget->accept(visitor);
78 77 }
79 78 }
80 79 }
81 80
82 81 visitor->visitLeave(this);
83 82 }
84 83 else {
85 84 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
86 85 }
87 86 }
88 87
89 88 bool VisualizationTabWidget::canDrop(const Variable &variable) const
90 89 {
91 90 // A tab can always accomodate a variable
92 91 Q_UNUSED(variable);
93 92 return true;
94 93 }
95 94
96 void VisualizationTabWidget::close()
97 {
98 // The main view cannot be directly closed.
99 return;
100 }
101
102 95 QString VisualizationTabWidget::name() const
103 96 {
104 97 return impl->m_Name;
105 98 }
@@ -1,131 +1,115
1 1 #include "Visualization/VisualizationWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphWidget.h"
4 4 #include "Visualization/VisualizationTabWidget.h"
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 6 #include "Visualization/operations/GenerateVariableMenuOperation.h"
7 7 #include "Visualization/qcustomplot.h"
8 8
9 9 #include "ui_VisualizationWidget.h"
10 10
11 11 #include <QToolButton>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
14 14
15 15 VisualizationWidget::VisualizationWidget(QWidget *parent)
16 16 : QWidget{parent}, ui{new Ui::VisualizationWidget}
17 17 {
18 18 ui->setupUi(this);
19 19
20 20 auto addTabViewButton = new QToolButton{ui->tabWidget};
21 21 addTabViewButton->setText(tr("Add View"));
22 22 addTabViewButton->setCursor(Qt::ArrowCursor);
23 23 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
24 24
25 25 auto enableMinimumCornerWidgetSize = [this](bool enable) {
26 26
27 27 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
28 28 auto width = enable ? tabViewCornerWidget->width() : 0;
29 29 auto height = enable ? tabViewCornerWidget->height() : 0;
30 30 tabViewCornerWidget->setMinimumHeight(height);
31 31 tabViewCornerWidget->setMinimumWidth(width);
32 32 ui->tabWidget->setMinimumHeight(height);
33 33 ui->tabWidget->setMinimumWidth(width);
34 34 };
35 35
36 36 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
37 37 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
38 38 ui->tabWidget};
39 39 auto index = ui->tabWidget->addTab(widget, widget->name());
40 40 if (ui->tabWidget->count() > 0) {
41 41 enableMinimumCornerWidgetSize(false);
42 42 }
43 43 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
44 44 };
45 45
46 46 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
47 47 if (ui->tabWidget->count() == 1) {
48 48 enableMinimumCornerWidgetSize(true);
49 49 }
50 50
51 // Removes widget from tab and closes it
52 auto widget = ui->tabWidget->widget(index);
51 53 ui->tabWidget->removeTab(index);
54 if (widget) {
55 widget->close();
56 }
57
52 58 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
53 59
54 60 };
55 61
56 62 ui->tabWidget->setTabsClosable(true);
57 63
58 64 connect(addTabViewButton, &QToolButton::clicked, addTabView);
59 65 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
60 66
61 67 // Adds default tab
62 68 addTabView();
63 69 }
64 70
65 71 VisualizationWidget::~VisualizationWidget()
66 72 {
67 73 delete ui;
68 74 }
69 75
70 void VisualizationWidget::addTab(VisualizationTabWidget *tabWidget)
71 {
72 // NOTE: check is this method has to be deleted because of its dupplicated version visible as
73 // lambda function (in the constructor)
74 }
75
76 VisualizationTabWidget *VisualizationWidget::createTab()
77 {
78 }
79
80 void VisualizationWidget::removeTab(VisualizationTabWidget *tab)
81 {
82 // NOTE: check is this method has to be deleted because of its dupplicated version visible as
83 // lambda function (in the constructor)
84 }
85
86 76 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
87 77 {
88 78 if (visitor) {
89 79 visitor->visitEnter(this);
90 80
91 81 // Apply visitor for tab children
92 82 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
93 83 // Widgets different from tabs are not visited (no action)
94 84 if (auto visualizationTabWidget
95 85 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
96 86 visualizationTabWidget->accept(visitor);
97 87 }
98 88 }
99 89
100 90 visitor->visitLeave(this);
101 91 }
102 92 else {
103 93 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
104 94 }
105 95 }
106 96
107 97 bool VisualizationWidget::canDrop(const Variable &variable) const
108 98 {
109 99 // The main widget can never accomodate a variable
110 100 Q_UNUSED(variable);
111 101 return false;
112 102 }
113 103
114 void VisualizationWidget::close()
115 {
116 // The main view cannot be directly closed.
117 return;
118 }
119
120 104 QString VisualizationWidget::name() const
121 105 {
122 106 return QStringLiteral("MainView");
123 107 }
124 108
125 109 void VisualizationWidget::attachVariableMenu(QMenu *menu,
126 110 std::shared_ptr<Variable> variable) noexcept
127 111 {
128 112 // Generates the actions that make it possible to visualize the variable
129 113 auto generateVariableMenuOperation = GenerateVariableMenuOperation{menu, variable};
130 114 accept(&generateVariableMenuOperation);
131 115 }
@@ -1,100 +1,97
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationZoneWidget.h"
4 4
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6
7 #include <SqpApplication.h>
8
7 9 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
8 10
9 11 namespace {
10 12
11 13 /// Generates a default name for a new graph, according to the number of graphs already displayed in
12 14 /// the zone
13 15 QString defaultGraphName(const QLayout &layout)
14 16 {
15 17 auto count = 0;
16 18 for (auto i = 0; i < layout.count(); ++i) {
17 19 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
18 20 count++;
19 21 }
20 22 }
21 23
22 24 return QObject::tr("Graph %1").arg(count + 1);
23 25 }
24 26
25 27 } // namespace
26 28
27 29 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
28 30 : QWidget{parent}, ui{new Ui::VisualizationZoneWidget}
29 31 {
30 32 ui->setupUi(this);
31 33
32 34 ui->zoneNameLabel->setText(name);
35
36 // 'Close' options : widget is deleted when closed
37 setAttribute(Qt::WA_DeleteOnClose);
38 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
39 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
33 40 }
34 41
35 42 VisualizationZoneWidget::~VisualizationZoneWidget()
36 43 {
37 44 delete ui;
38 45 }
39 46
40 47 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
41 48 {
42 49 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
43 50 }
44 51
45 52 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
46 53 {
47 54 auto graphWidget = new VisualizationGraphWidget{
48 55 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
49 56 this->addGraph(graphWidget);
50 57
51 58 graphWidget->addVariable(variable);
52 59
53 60 return graphWidget;
54 61 }
55 62
56 void VisualizationZoneWidget::removeGraph(VisualizationGraphWidget *graph)
57 {
58 }
59
60 63 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
61 64 {
62 65 if (visitor) {
63 66 visitor->visitEnter(this);
64 67
65 68 // Apply visitor to graph children
66 69 auto layout = ui->visualizationZoneFrame->layout();
67 70 for (auto i = 0; i < layout->count(); ++i) {
68 71 if (auto item = layout->itemAt(i)) {
69 72 // Widgets different from graphs are not visited (no action)
70 73 if (auto visualizationGraphWidget
71 74 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
72 75 visualizationGraphWidget->accept(visitor);
73 76 }
74 77 }
75 78 }
76 79
77 80 visitor->visitLeave(this);
78 81 }
79 82 else {
80 83 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
81 84 }
82 85 }
83 86
84 87 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
85 88 {
86 89 // A tab can always accomodate a variable
87 90 Q_UNUSED(variable);
88 91 return true;
89 92 }
90 93
91 void VisualizationZoneWidget::close()
92 {
93 // The main view cannot be directly closed.
94 return;
95 }
96
97 94 QString VisualizationZoneWidget::name() const
98 95 {
99 96 return ui->zoneNameLabel->text();
100 97 }
@@ -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>
@@ -1,76 +1,86
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>VisualizationZoneWidget</class>
4 4 <widget class="QWidget" name="VisualizationZoneWidget">
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_2">
17 17 <item>
18 18 <widget class="QWidget" name="infobar" native="true">
19 19 <property name="sizePolicy">
20 20 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
21 21 <horstretch>0</horstretch>
22 22 <verstretch>0</verstretch>
23 23 </sizepolicy>
24 24 </property>
25 25 <layout class="QHBoxLayout" name="horizontalLayout">
26 26 <property name="leftMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <property name="topMargin">
30 30 <number>0</number>
31 31 </property>
32 32 <property name="rightMargin">
33 33 <number>0</number>
34 34 </property>
35 35 <property name="bottomMargin">
36 36 <number>0</number>
37 37 </property>
38 38 <item>
39 39 <widget class="QLabel" name="zoneNameLabel">
40 40 <property name="styleSheet">
41 41 <string notr="true">color: rgb(127, 127, 127);
42 42 </string>
43 43 </property>
44 44 <property name="text">
45 45 <string>TextLabel</string>
46 46 </property>
47 47 </widget>
48 48 </item>
49 <item>
50 <widget class="QToolButton" name="closeButton">
51 <property name="styleSheet">
52 <string notr="true">background-color: transparent;</string>
53 </property>
54 <property name="text">
55 <string>Close</string>
56 </property>
57 </widget>
58 </item>
49 59 </layout>
50 60 </widget>
51 61 </item>
52 62 <item>
53 63 <widget class="QFrame" name="visualizationZoneFrame">
54 64 <property name="sizePolicy">
55 65 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
56 66 <horstretch>0</horstretch>
57 67 <verstretch>0</verstretch>
58 68 </sizepolicy>
59 69 </property>
60 70 <property name="frameShape">
61 71 <enum>QFrame::Box</enum>
62 72 </property>
63 73 <property name="frameShadow">
64 74 <enum>QFrame::Raised</enum>
65 75 </property>
66 76 <property name="lineWidth">
67 77 <number>1</number>
68 78 </property>
69 79 <layout class="QVBoxLayout" name="verticalLayout"/>
70 80 </widget>
71 81 </item>
72 82 </layout>
73 83 </widget>
74 84 <resources/>
75 85 <connections/>
76 86 </ui>
General Comments 0
You need to be logged in to leave comments. Login now