2 * This file is part of the PulseView project.
4 * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <QApplication>
21 #include <QMouseEvent>
22 #include <QTouchEvent>
24 #include "tracetreeitem.hpp"
26 #include "viewwidget.hpp"
29 using std::shared_ptr
;
36 ViewWidget::ViewWidget(View
&parent
) :
41 setFocusPolicy(Qt::ClickFocus
);
42 setAttribute(Qt::WA_AcceptTouchEvents
, true);
43 setMouseTracking(true);
46 void ViewWidget::clear_selection()
48 const auto items
= this->items();
53 void ViewWidget::item_hover(const shared_ptr
<ViewItem
> &item
)
58 void ViewWidget::item_clicked(const shared_ptr
<ViewItem
> &item
)
63 bool ViewWidget::accept_drag() const
65 const vector
< shared_ptr
<TimeItem
> > items(view_
.time_items());
66 const vector
< shared_ptr
<TraceTreeItem
> > trace_tree_items(
67 view_
.list_by_type
<TraceTreeItem
>());
69 const bool any_row_items_selected
= any_of(
70 trace_tree_items
.begin(), trace_tree_items
.end(),
71 [](const shared_ptr
<TraceTreeItem
> &r
) { return r
->selected(); });
73 const bool any_time_items_selected
= any_of(items
.begin(), items
.end(),
74 [](const shared_ptr
<TimeItem
> &i
) { return i
->selected(); });
76 if (any_row_items_selected
&& !any_time_items_selected
) {
77 // Check all the drag items share a common owner
78 TraceTreeItemOwner
*item_owner
= nullptr;
79 for (shared_ptr
<TraceTreeItem
> r
: trace_tree_items
)
82 item_owner
= r
->owner();
83 else if (item_owner
!= r
->owner())
88 } else if (any_time_items_selected
&& !any_row_items_selected
) {
92 // A background drag is beginning
96 bool ViewWidget::mouse_down() const
98 return mouse_down_point_
.x() != INT_MIN
&&
99 mouse_down_point_
.y() != INT_MIN
;
102 void ViewWidget::drag_items(const QPoint
&delta
)
104 bool item_dragged
= false;
106 // Drag the row items
107 const vector
< shared_ptr
<RowItem
> > row_items(
108 view_
.list_by_type
<RowItem
>());
109 for (shared_ptr
<RowItem
> r
: row_items
)
113 // Ensure the trace is selected
119 // If an item is being dragged, update the stacking
120 TraceTreeItemOwner
*item_owner
= nullptr;
121 const vector
< shared_ptr
<TraceTreeItem
> > trace_tree_items(
122 view_
.list_by_type
<TraceTreeItem
>());
123 for (shared_ptr
<TraceTreeItem
> i
: trace_tree_items
)
125 item_owner
= i
->owner();
128 item_owner
->restack_items();
129 for (shared_ptr
<TraceTreeItem
> i
: trace_tree_items
)
130 i
->animate_to_layout_v_offset();
133 // Drag the time items
134 const vector
< shared_ptr
<TimeItem
> > items(view_
.time_items());
135 for (auto &i
: items
)
141 // Do the background drag
146 void ViewWidget::drag()
150 void ViewWidget::drag_by(const QPoint
&delta
)
155 void ViewWidget::drag_release()
159 void ViewWidget::mouse_left_press_event(QMouseEvent
*event
)
163 const bool ctrl_pressed
=
164 QApplication::keyboardModifiers() & Qt::ControlModifier
;
166 // Clear selection if control is not pressed and this item is unselected
167 if ((!mouse_down_item_
|| !mouse_down_item_
->selected()) &&
171 // Set the signal selection state if the item has been clicked
172 if (mouse_down_item_
) {
174 mouse_down_item_
->select(!mouse_down_item_
->selected());
176 mouse_down_item_
->select(true);
179 // Save the offsets of any signals which will be dragged
180 bool item_dragged
= false;
181 const auto items
= this->items();
182 for (auto &i
: items
)
188 // Do the background drag
195 void ViewWidget::mouse_left_release_event(QMouseEvent
*event
)
199 auto items
= this->items();
200 const bool ctrl_pressed
=
201 QApplication::keyboardModifiers() & Qt::ControlModifier
;
203 // Unselect everything if control is not pressed
204 const shared_ptr
<ViewItem
> mouse_over
=
205 get_mouse_over_item(event
->pos());
207 for (auto &i
: items
)
211 view_
.restack_all_trace_tree_items();
214 for (shared_ptr
<ViewItem
> i
: items
)
215 if (mouse_down_item_
!= i
)
218 if (mouse_down_item_
)
219 item_clicked(mouse_down_item_
);
223 item_dragging_
= false;
226 bool ViewWidget::touch_event(QTouchEvent
*event
)
233 bool ViewWidget::event(QEvent
*event
)
235 switch (event
->type()) {
236 case QEvent::TouchBegin
:
237 case QEvent::TouchUpdate
:
238 case QEvent::TouchEnd
:
239 if (touch_event(static_cast<QTouchEvent
*>(event
)))
247 return QWidget::event(event
);
250 void ViewWidget::mousePressEvent(QMouseEvent
*event
)
254 /* Ignore right click events as they will open context menus when
255 * used on trace labels. Those menus prevent ViewWidget::mouseReleaseEvent()
256 * to be triggered upon button release, making mouse_down_item_
257 * hold the last reference to a view item that might have been deleted
258 * from the context menu, preventing it from being freed as intended.
260 if (event
->button() & Qt::LeftButton
) {
261 mouse_down_point_
= event
->pos();
262 mouse_down_item_
= get_mouse_over_item(event
->pos());
263 mouse_left_press_event(event
);
267 void ViewWidget::mouseReleaseEvent(QMouseEvent
*event
)
271 if (event
->button() & Qt::LeftButton
)
272 mouse_left_release_event(event
);
274 mouse_down_point_
= QPoint(INT_MIN
, INT_MIN
);
275 mouse_down_item_
= nullptr;
278 void ViewWidget::mouseMoveEvent(QMouseEvent
*event
)
281 mouse_point_
= event
->pos();
283 if (!event
->buttons())
284 item_hover(get_mouse_over_item(event
->pos()));
285 else if (event
->buttons() & Qt::LeftButton
) {
286 if (!item_dragging_
) {
287 if ((event
->pos() - mouse_down_point_
).manhattanLength() <
288 QApplication::startDragDistance())
294 item_dragging_
= true;
298 drag_items(event
->pos() - mouse_down_point_
);
302 void ViewWidget::leaveEvent(QEvent
*)
304 mouse_point_
= QPoint(-1, -1);
308 } // namespace TraceView