@@ -0,0 +1,30 | |||||
|
1 | #ifndef SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H | |||
|
2 | #define SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H | |||
|
3 | ||||
|
4 | #include <Common/spimpl.h> | |||
|
5 | #include <QDialog> | |||
|
6 | ||||
|
7 | namespace Ui { | |||
|
8 | class VisualizationMultiZoneSelectionDialog; | |||
|
9 | } | |||
|
10 | ||||
|
11 | class VisualizationSelectionZoneItem; | |||
|
12 | ||||
|
13 | class VisualizationMultiZoneSelectionDialog : public QDialog { | |||
|
14 | Q_OBJECT | |||
|
15 | ||||
|
16 | public: | |||
|
17 | explicit VisualizationMultiZoneSelectionDialog(QWidget *parent = 0); | |||
|
18 | ~VisualizationMultiZoneSelectionDialog(); | |||
|
19 | ||||
|
20 | void setZones(const QVector<VisualizationSelectionZoneItem *> &zones); | |||
|
21 | QMap<VisualizationSelectionZoneItem *, bool> selectedZones() const; | |||
|
22 | ||||
|
23 | private: | |||
|
24 | Ui::VisualizationMultiZoneSelectionDialog *ui; | |||
|
25 | ||||
|
26 | class VisualizationMultiZoneSelectionDialogPrivate; | |||
|
27 | spimpl::unique_impl_ptr<VisualizationMultiZoneSelectionDialogPrivate> impl; | |||
|
28 | }; | |||
|
29 | ||||
|
30 | #endif // SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H |
@@ -0,0 +1,69 | |||||
|
1 | #include "Visualization/VisualizationMultiZoneSelectionDialog.h" | |||
|
2 | #include "ui_VisualizationMultiZoneSelectionDialog.h" | |||
|
3 | ||||
|
4 | #include "Common/DateUtils.h" | |||
|
5 | #include "Visualization/VisualizationSelectionZoneItem.h" | |||
|
6 | ||||
|
7 | const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss"); | |||
|
8 | ||||
|
9 | struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate { | |||
|
10 | QVector<VisualizationSelectionZoneItem *> m_Zones; | |||
|
11 | }; | |||
|
12 | ||||
|
13 | VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent) | |||
|
14 | : QDialog(parent, Qt::Tool), | |||
|
15 | ui(new Ui::VisualizationMultiZoneSelectionDialog), | |||
|
16 | impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()} | |||
|
17 | { | |||
|
18 | ui->setupUi(this); | |||
|
19 | ||||
|
20 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, | |||
|
21 | &VisualizationMultiZoneSelectionDialog::accept); | |||
|
22 | connect(ui->buttonBox, &QDialogButtonBox::rejected, this, | |||
|
23 | &VisualizationMultiZoneSelectionDialog::reject); | |||
|
24 | } | |||
|
25 | ||||
|
26 | VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog() | |||
|
27 | { | |||
|
28 | delete ui; | |||
|
29 | } | |||
|
30 | ||||
|
31 | void VisualizationMultiZoneSelectionDialog::setZones( | |||
|
32 | const QVector<VisualizationSelectionZoneItem *> &zones) | |||
|
33 | { | |||
|
34 | impl->m_Zones = zones; | |||
|
35 | ||||
|
36 | // Sorts the zones to display them in temporal order | |||
|
37 | std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) { | |||
|
38 | return zone1->range().m_TStart < zone2->range().m_TStart; | |||
|
39 | }); | |||
|
40 | ||||
|
41 | // Adds the zones in the listwidget | |||
|
42 | for (auto zone : impl->m_Zones) { | |||
|
43 | auto name = zone->name(); | |||
|
44 | if (!name.isEmpty()) { | |||
|
45 | name += tr(": "); | |||
|
46 | } | |||
|
47 | ||||
|
48 | auto range = zone->range(); | |||
|
49 | name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT); | |||
|
50 | name += " - "; | |||
|
51 | name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT); | |||
|
52 | ||||
|
53 | auto item = new QListWidgetItem(name, ui->listWidget); | |||
|
54 | item->setSelected(zone->selected()); | |||
|
55 | } | |||
|
56 | } | |||
|
57 | ||||
|
58 | QMap<VisualizationSelectionZoneItem *, bool> | |||
|
59 | VisualizationMultiZoneSelectionDialog::selectedZones() const | |||
|
60 | { | |||
|
61 | QMap<VisualizationSelectionZoneItem *, bool> selectedZones; | |||
|
62 | ||||
|
63 | for (auto i = 0; i < ui->listWidget->count(); ++i) { | |||
|
64 | auto item = ui->listWidget->item(i); | |||
|
65 | selectedZones[impl->m_Zones[i]] = item->isSelected(); | |||
|
66 | } | |||
|
67 | ||||
|
68 | return selectedZones; | |||
|
69 | } |
@@ -0,0 +1,47 | |||||
|
1 | <?xml version="1.0" encoding="UTF-8"?> | |||
|
2 | <ui version="4.0"> | |||
|
3 | <class>VisualizationMultiZoneSelectionDialog</class> | |||
|
4 | <widget class="QDialog" name="VisualizationMultiZoneSelectionDialog"> | |||
|
5 | <property name="geometry"> | |||
|
6 | <rect> | |||
|
7 | <x>0</x> | |||
|
8 | <y>0</y> | |||
|
9 | <width>270</width> | |||
|
10 | <height>175</height> | |||
|
11 | </rect> | |||
|
12 | </property> | |||
|
13 | <property name="windowTitle"> | |||
|
14 | <string>Select...</string> | |||
|
15 | </property> | |||
|
16 | <layout class="QVBoxLayout" name="verticalLayout"> | |||
|
17 | <property name="leftMargin"> | |||
|
18 | <number>0</number> | |||
|
19 | </property> | |||
|
20 | <property name="topMargin"> | |||
|
21 | <number>0</number> | |||
|
22 | </property> | |||
|
23 | <property name="rightMargin"> | |||
|
24 | <number>0</number> | |||
|
25 | </property> | |||
|
26 | <property name="bottomMargin"> | |||
|
27 | <number>0</number> | |||
|
28 | </property> | |||
|
29 | <item> | |||
|
30 | <widget class="QListWidget" name="listWidget"> | |||
|
31 | <property name="selectionMode"> | |||
|
32 | <enum>QAbstractItemView::ExtendedSelection</enum> | |||
|
33 | </property> | |||
|
34 | </widget> | |||
|
35 | </item> | |||
|
36 | <item> | |||
|
37 | <widget class="QDialogButtonBox" name="buttonBox"> | |||
|
38 | <property name="standardButtons"> | |||
|
39 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | |||
|
40 | </property> | |||
|
41 | </widget> | |||
|
42 | </item> | |||
|
43 | </layout> | |||
|
44 | </widget> | |||
|
45 | <resources/> | |||
|
46 | <connections/> | |||
|
47 | </ui> |
@@ -28,6 +28,10 public: | |||||
28 | void setEditionEnabled(bool value); |
|
28 | void setEditionEnabled(bool value); | |
29 | bool isEditionEnabled() const; |
|
29 | bool isEditionEnabled() const; | |
30 |
|
30 | |||
|
31 | /// Moves the item at the top of its QCPLayer. It will then receive the mouse events if multiple | |||
|
32 | /// items are stacked on top of each others. | |||
|
33 | void moveToTop(); | |||
|
34 | ||||
31 | Qt::CursorShape curshorShapeForPosition(const QPoint &position) const; |
|
35 | Qt::CursorShape curshorShapeForPosition(const QPoint &position) const; | |
32 | void setHovered(bool value); |
|
36 | void setHovered(bool value); | |
33 |
|
37 |
@@ -18,7 +18,8 gui_moc_headers = [ | |||||
18 | 'include/Visualization/VisualizationDragDropContainer.h', |
|
18 | 'include/Visualization/VisualizationDragDropContainer.h', | |
19 | 'include/Visualization/VisualizationDragWidget.h', |
|
19 | 'include/Visualization/VisualizationDragWidget.h', | |
20 | 'include/Visualization/ColorScaleEditor.h', |
|
20 | 'include/Visualization/ColorScaleEditor.h', | |
21 | 'include/Visualization/SelectionZoneAction.h' |
|
21 | 'include/Visualization/SelectionZoneAction.h', | |
|
22 | 'include/Visualization/VisualizationMultiZoneSelectionDialog.h' | |||
22 | ] |
|
23 | ] | |
23 |
|
24 | |||
24 | gui_ui_files = [ |
|
25 | gui_ui_files = [ | |
@@ -34,7 +35,8 gui_ui_files = [ | |||||
34 | 'ui/Visualization/VisualizationTabWidget.ui', |
|
35 | 'ui/Visualization/VisualizationTabWidget.ui', | |
35 | 'ui/Visualization/VisualizationWidget.ui', |
|
36 | 'ui/Visualization/VisualizationWidget.ui', | |
36 | 'ui/Visualization/VisualizationZoneWidget.ui', |
|
37 | 'ui/Visualization/VisualizationZoneWidget.ui', | |
37 | 'ui/Visualization/ColorScaleEditor.ui' |
|
38 | 'ui/Visualization/ColorScaleEditor.ui', | |
|
39 | 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui' | |||
38 | ] |
|
40 | ] | |
39 |
|
41 | |||
40 | gui_qresources = ['resources/sqpguiresources.qrc'] |
|
42 | gui_qresources = ['resources/sqpguiresources.qrc'] | |
@@ -88,7 +90,8 gui_sources = [ | |||||
88 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', |
|
90 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', | |
89 | 'src/Visualization/SelectionZoneAction.cpp', |
|
91 | 'src/Visualization/SelectionZoneAction.cpp', | |
90 | 'src/Visualization/ActionsGuiController.cpp', |
|
92 | 'src/Visualization/ActionsGuiController.cpp', | |
91 | 'src/Visualization/VisualizationActionManager.cpp' |
|
93 | 'src/Visualization/VisualizationActionManager.cpp', | |
|
94 | 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp' | |||
92 | ] |
|
95 | ] | |
93 |
|
96 | |||
94 | gui_inc = include_directories(['include']) |
|
97 | gui_inc = include_directories(['include']) |
@@ -4,6 +4,7 | |||||
4 | #include "Visualization/VisualizationDefs.h" |
|
4 | #include "Visualization/VisualizationDefs.h" | |
5 | #include "Visualization/VisualizationGraphHelper.h" |
|
5 | #include "Visualization/VisualizationGraphHelper.h" | |
6 | #include "Visualization/VisualizationGraphRenderingDelegate.h" |
|
6 | #include "Visualization/VisualizationGraphRenderingDelegate.h" | |
|
7 | #include "Visualization/VisualizationMultiZoneSelectionDialog.h" | |||
7 | #include "Visualization/VisualizationSelectionZoneItem.h" |
|
8 | #include "Visualization/VisualizationSelectionZoneItem.h" | |
8 | #include "Visualization/VisualizationSelectionZoneManager.h" |
|
9 | #include "Visualization/VisualizationSelectionZoneManager.h" | |
9 | #include "Visualization/VisualizationWidget.h" |
|
10 | #include "Visualization/VisualizationWidget.h" | |
@@ -170,6 +171,29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |||||
170 | return selectionZoneItemUnderCursor; |
|
171 | return selectionZoneItemUnderCursor; | |
171 | } |
|
172 | } | |
172 |
|
173 | |||
|
174 | QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos, | |||
|
175 | const QCustomPlot &plot) const | |||
|
176 | { | |||
|
177 | QVector<VisualizationSelectionZoneItem *> zones; | |||
|
178 | for (auto zone : m_SelectionZones) { | |||
|
179 | auto distanceToZone = zone->selectTest(pos, false); | |||
|
180 | if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) { | |||
|
181 | zones << zone; | |||
|
182 | } | |||
|
183 | } | |||
|
184 | ||||
|
185 | return zones; | |||
|
186 | } | |||
|
187 | ||||
|
188 | void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot) | |||
|
189 | { | |||
|
190 | if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) { | |||
|
191 | zone->moveToTop(); | |||
|
192 | m_SelectionZones.removeAll(zone); | |||
|
193 | m_SelectionZones.append(zone); | |||
|
194 | } | |||
|
195 | } | |||
|
196 | ||||
173 | QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const |
|
197 | QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const | |
174 | { |
|
198 | { | |
175 | auto axisX = plot.axisRect()->axis(QCPAxis::atBottom); |
|
199 | auto axisX = plot.axisRect()->axis(QCPAxis::atBottom); | |
@@ -902,15 +926,49 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept | |||||
902 | if (isSelectionZoneMode) { |
|
926 | if (isSelectionZoneMode) { | |
903 | auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER); |
|
927 | auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER); | |
904 | auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot()); |
|
928 | auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot()); | |
905 |
if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton |
|
929 | if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton | |
906 |
|
|
930 | && !impl->m_HasMovedMouse) { | |
907 | parentVisualizationWidget()->selectionZoneManager().select( |
|
931 | ||
908 | {selectionZoneItemUnderCursor}); |
|
932 | auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot()); | |
|
933 | if (zonesUnderCursor.count() > 1) { | |||
|
934 | // There are multiple zones under the mouse. | |||
|
935 | // Performs the selection with a selection dialog. | |||
|
936 | VisualizationMultiZoneSelectionDialog dialog{this}; | |||
|
937 | dialog.setZones(zonesUnderCursor); | |||
|
938 | dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20))); | |||
|
939 | dialog.activateWindow(); | |||
|
940 | dialog.raise(); | |||
|
941 | if (dialog.exec() == QDialog::Accepted) { | |||
|
942 | auto selection = dialog.selectedZones(); | |||
|
943 | ||||
|
944 | if (!isMultiSelectionClick) { | |||
|
945 | parentVisualizationWidget()->selectionZoneManager().clearSelection(); | |||
|
946 | } | |||
|
947 | ||||
|
948 | for (auto it = selection.cbegin(); it != selection.cend(); ++it) { | |||
|
949 | auto zone = it.key(); | |||
|
950 | auto isSelected = it.value(); | |||
|
951 | parentVisualizationWidget()->selectionZoneManager().setSelected(zone, | |||
|
952 | isSelected); | |||
|
953 | ||||
|
954 | if (isSelected) { | |||
|
955 | // Puts the zone on top of the stack so it can be moved or resized | |||
|
956 | impl->moveSelectionZoneOnTop(zone, plot()); | |||
|
957 | } | |||
|
958 | } | |||
|
959 | } | |||
909 | } |
|
960 | } | |
910 | else if (!impl->m_HasMovedMouse) { |
|
961 | else { | |
911 | parentVisualizationWidget()->selectionZoneManager().setSelected( |
|
962 | if (!isMultiSelectionClick) { | |
912 | selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected() |
|
963 | parentVisualizationWidget()->selectionZoneManager().select( | |
913 | || event->button() == Qt::RightButton); |
|
964 | {selectionZoneItemUnderCursor}); | |
|
965 | impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot()); | |||
|
966 | } | |||
|
967 | else { | |||
|
968 | parentVisualizationWidget()->selectionZoneManager().setSelected( | |||
|
969 | selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected() | |||
|
970 | || event->button() == Qt::RightButton); | |||
|
971 | } | |||
914 | } |
|
972 | } | |
915 | } |
|
973 | } | |
916 | else { |
|
974 | else { |
@@ -253,6 +253,11 bool VisualizationSelectionZoneItem::isEditionEnabled() const | |||||
253 | return impl->m_IsEditionEnabled; |
|
253 | return impl->m_IsEditionEnabled; | |
254 | } |
|
254 | } | |
255 |
|
255 | |||
|
256 | void VisualizationSelectionZoneItem::moveToTop() | |||
|
257 | { | |||
|
258 | moveToLayer(layer(), false); | |||
|
259 | } | |||
|
260 | ||||
256 | Qt::CursorShape |
|
261 | Qt::CursorShape | |
257 | VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const |
|
262 | VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const | |
258 | { |
|
263 | { | |
@@ -327,6 +332,8 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnRight( | |||||
327 |
|
332 | |||
328 | void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details) |
|
333 | void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details) | |
329 | { |
|
334 | { | |
|
335 | Q_UNUSED(details); | |||
|
336 | ||||
330 | if (isEditionEnabled() && event->button() == Qt::LeftButton) { |
|
337 | if (isEditionEnabled() && event->button() == Qt::LeftButton) { | |
331 | impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this); |
|
338 | impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this); | |
332 |
|
339 | |||
@@ -394,6 +401,8 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QP | |||||
394 |
|
401 | |||
395 | void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) |
|
402 | void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) | |
396 | { |
|
403 | { | |
|
404 | Q_UNUSED(startPos); | |||
|
405 | ||||
397 | if (isEditionEnabled()) { |
|
406 | if (isEditionEnabled()) { | |
398 | impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition; |
|
407 | impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition; | |
399 | } |
|
408 | } |
@@ -39,7 +39,7 void VisualizationSelectionZoneManager::clearSelection() | |||||
39 | { |
|
39 | { | |
40 | for (auto item : impl->m_SelectedItems) { |
|
40 | for (auto item : impl->m_SelectedItems) { | |
41 | item->setSelected(false); |
|
41 | item->setSelected(false); | |
42 | item->parentPlot()->replot(); |
|
42 | item->parentPlot()->replot(QCustomPlot::rpQueuedReplot); | |
43 | } |
|
43 | } | |
44 |
|
44 | |||
45 | impl->m_SelectedItems.clear(); |
|
45 | impl->m_SelectedItems.clear(); |
General Comments 0
You need to be logged in to leave comments.
Login now