PulseView  0.3.0
A Qt-based sigrok GUI
viewwidget.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
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.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <QApplication>
22 #include <QMouseEvent>
23 #include <QTouchEvent>
24 
25 #include "tracetreeitem.hpp"
26 #include "view.hpp"
27 #include "viewwidget.hpp"
28 
29 using std::any_of;
30 using std::shared_ptr;
31 using std::vector;
32 
33 namespace pv {
34 namespace view {
35 
37  QWidget(&parent),
38  view_(parent),
39  item_dragging_(false)
40 {
41  setFocusPolicy(Qt::ClickFocus);
42  setAttribute(Qt::WA_AcceptTouchEvents, true);
43  setMouseTracking(true);
44 }
45 
47 {
48  const auto items = this->items();
49  for (auto &i : items)
50  i->select(false);
51 }
52 
53 void ViewWidget::item_hover(const shared_ptr<ViewItem> &item)
54 {
55  (void)item;
56 }
57 
58 void ViewWidget::item_clicked(const shared_ptr<ViewItem> &item)
59 {
60  (void)item;
61 }
62 
64 {
65  const vector< shared_ptr<TimeItem> > items(view_.time_items());
66  const vector< shared_ptr<TraceTreeItem> > trace_tree_items(
68 
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(); });
72 
73  const bool any_time_items_selected = any_of(items.begin(), items.end(),
74  [](const shared_ptr<TimeItem> &i) { return i->selected(); });
75 
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)
80  if (r->dragging()) {
81  if (!item_owner)
82  item_owner = r->owner();
83  else if (item_owner != r->owner())
84  return false;
85  }
86 
87  return true;
88  } else if (any_time_items_selected && !any_row_items_selected) {
89  return true;
90  }
91 
92  // A background drag is beginning
93  return true;
94 }
95 
97 {
98  return mouse_down_point_.x() != INT_MIN &&
99  mouse_down_point_.y() != INT_MIN;
100 }
101 
102 void ViewWidget::drag_items(const QPoint &delta)
103 {
104  bool item_dragged = false;
105 
106  // Drag the row items
107  const vector< shared_ptr<RowItem> > row_items(
109  for (shared_ptr<RowItem> r : row_items)
110  if (r->dragging()) {
111  r->drag_by(delta);
112 
113  // Ensure the trace is selected
114  r->select();
115 
116  item_dragged = true;
117  }
118 
119  // If an item is being dragged, update the stacking
120  TraceTreeItemOwner *item_owner = nullptr;
121  const vector< shared_ptr<TraceTreeItem> > trace_tree_items(
123  for (shared_ptr<TraceTreeItem> i : trace_tree_items)
124  if (i->dragging())
125  item_owner = i->owner();
126 
127  if (item_owner) {
128  item_owner->restack_items();
129  for (shared_ptr<TraceTreeItem> i : trace_tree_items)
130  i->animate_to_layout_v_offset();
131  }
132 
133  // Drag the time items
134  const vector< shared_ptr<TimeItem> > items(view_.time_items());
135  for (auto &i : items)
136  if (i->dragging()) {
137  i->drag_by(delta);
138  item_dragged = true;
139  }
140 
141  // Do the background drag
142  if (!item_dragged)
143  drag_by(delta);
144 }
145 
147 {
148 }
149 
150 void ViewWidget::drag_by(const QPoint &delta)
151 {
152  (void)delta;
153 }
154 
156 {
157 }
158 
159 void ViewWidget::mouse_left_press_event(QMouseEvent *event)
160 {
161  (void)event;
162 
163  const bool ctrl_pressed =
164  QApplication::keyboardModifiers() & Qt::ControlModifier;
165 
166  // Clear selection if control is not pressed and this item is unselected
167  if ((!mouse_down_item_ || !mouse_down_item_->selected()) &&
168  !ctrl_pressed)
169  clear_selection();
170 
171  // Set the signal selection state if the item has been clicked
172  if (mouse_down_item_) {
173  if (ctrl_pressed)
174  mouse_down_item_->select(!mouse_down_item_->selected());
175  else
176  mouse_down_item_->select(true);
177  }
178 
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)
183  if (i->selected()) {
184  item_dragged = true;
185  i->drag();
186  }
187 
188  // Do the background drag
189  if (!item_dragged)
190  drag();
191 
193 }
194 
195 void ViewWidget::mouse_left_release_event(QMouseEvent *event)
196 {
197  assert(event);
198 
199  auto items = this->items();
200  const bool ctrl_pressed =
201  QApplication::keyboardModifiers() & Qt::ControlModifier;
202 
203  // Unselect everything if control is not pressed
204  const shared_ptr<ViewItem> mouse_over =
205  get_mouse_over_item(event->pos());
206 
207  for (auto &i : items)
208  i->drag_release();
209 
210  if (item_dragging_)
212  else {
213  if (!ctrl_pressed) {
214  for (shared_ptr<ViewItem> i : items)
215  if (mouse_down_item_ != i)
216  i->select(false);
217 
218  if (mouse_down_item_)
220  }
221  }
222 
223  item_dragging_ = false;
224 }
225 
226 bool ViewWidget::touch_event(QTouchEvent *e)
227 {
228  (void)e;
229  return false;
230 }
231 
232 bool ViewWidget::event(QEvent *event)
233 {
234  switch (event->type()) {
235  case QEvent::TouchBegin:
236  case QEvent::TouchUpdate:
237  case QEvent::TouchEnd:
238  if (touch_event(static_cast<QTouchEvent *>(event)))
239  return true;
240  break;
241 
242  default:
243  break;
244  }
245 
246  return QWidget::event(event);
247 }
248 
249 void ViewWidget::mousePressEvent(QMouseEvent *event)
250 {
251  assert(event);
252 
253  mouse_down_point_ = event->pos();
254  mouse_down_item_ = get_mouse_over_item(event->pos());
255 
256  if (event->button() & Qt::LeftButton)
257  mouse_left_press_event(event);
258 }
259 
260 void ViewWidget::mouseReleaseEvent(QMouseEvent *event)
261 {
262  assert(event);
263  if (event->button() & Qt::LeftButton)
265 
266  mouse_down_point_ = QPoint(INT_MIN, INT_MIN);
267  mouse_down_item_ = nullptr;
268 }
269 
270 void ViewWidget::mouseMoveEvent(QMouseEvent *e)
271 {
272  assert(e);
273  mouse_point_ = e->pos();
274 
275  if (!e->buttons())
276  item_hover(get_mouse_over_item(e->pos()));
277  else if (e->buttons() & Qt::LeftButton) {
278  if (!item_dragging_) {
279  if ((e->pos() - mouse_down_point_).manhattanLength() <
280  QApplication::startDragDistance())
281  return;
282 
283  if (!accept_drag())
284  return;
285 
286  item_dragging_ = true;
287  }
288 
289  // Do the drag
290  drag_items(e->pos() - mouse_down_point_);
291  }
292 }
293 
295 {
296  mouse_point_ = QPoint(-1, -1);
297  update();
298 }
299 
300 } // namespace view
301 } // namespace pv
virtual void item_clicked(const std::shared_ptr< pv::view::ViewItem > &item)
Definition: viewwidget.cpp:58
bool accept_drag() const
Definition: viewwidget.cpp:63
void restack_all_trace_tree_items()
Definition: view.cpp:532
void drag_items(const QPoint &delta)
Definition: viewwidget.cpp:102
std::vector< std::shared_ptr< T > > list_by_type()
virtual std::vector< std::shared_ptr< pv::view::ViewItem > > items()=0
pv::view::View & view_
Definition: viewwidget.hpp:142
ViewWidget(View &parent)
Definition: viewwidget.cpp:36
virtual void drag()
Definition: viewwidget.cpp:146
void leaveEvent(QEvent *event)
Definition: viewwidget.cpp:294
virtual std::shared_ptr< pv::view::ViewItem > get_mouse_over_item(const QPoint &pt)=0
bool mouse_down() const
Definition: viewwidget.cpp:96
bool event(QEvent *event)
Definition: viewwidget.cpp:232
virtual void item_hover(const std::shared_ptr< pv::view::ViewItem > &item)
Definition: viewwidget.cpp:53
virtual void drag_release()
Definition: viewwidget.cpp:155
std::shared_ptr< ViewItem > mouse_down_item_
Definition: viewwidget.hpp:145
std::vector< std::shared_ptr< TimeItem > > time_items() const
Definition: view.cpp:206
void mousePressEvent(QMouseEvent *event)
Definition: viewwidget.cpp:249
virtual void drag_by(const QPoint &delta)
Definition: viewwidget.cpp:150
virtual bool touch_event(QTouchEvent *e)
Definition: viewwidget.cpp:226
void mouse_left_press_event(QMouseEvent *event)
Definition: viewwidget.cpp:159
void mouseReleaseEvent(QMouseEvent *event)
Definition: viewwidget.cpp:260
void mouse_left_release_event(QMouseEvent *event)
Definition: viewwidget.cpp:195
void mouseMoveEvent(QMouseEvent *event)
Definition: viewwidget.cpp:270