Header: Fixed dragging glitches
[pulseview.git] / pv / view / header.cpp
index ffe05a1c674335f92479e85997d69ec0347cc46b..9ba4cf8f8814088749cf20b1909dee6cfec50e7e 100644 (file)
@@ -136,70 +136,78 @@ void Header::paintEvent(QPaintEvent*)
        painter.end();
 }
 
+void Header::mouseLeftPressEvent(QMouseEvent *event)
+{
+       const bool ctrl_pressed =
+               QApplication::keyboardModifiers() & Qt::ControlModifier;
+
+       // Clear selection if control is not pressed and this item is unselected
+       const shared_ptr<RowItem> mouse_over =
+               get_mouse_over_row_item(event->pos());
+       if (!ctrl_pressed && (!mouse_over || !mouse_over->selected()))
+               for (shared_ptr<RowItem> r : _view)
+                       r->select(false);
+
+       // Set the signal selection state if the item has been clicked
+       if (mouse_over) {
+               if (ctrl_pressed)
+                       mouse_over->select(!mouse_over->selected());
+               else
+                       mouse_over->select(true);
+       }
+
+       // Save the offsets of any signals which will be dragged
+       _mouse_down_point = event->pos();
+       for (const shared_ptr<RowItem> r : _view)
+               if (r->selected())
+                       _drag_row_items.push_back(
+                               make_pair(r, r->v_offset()));
+
+       selection_changed();
+       update();
+}
+
 void Header::mousePressEvent(QMouseEvent *event)
 {
        assert(event);
+       if (event->button() & Qt::LeftButton)
+               mouseLeftPressEvent(event);
+}
 
-       if (event->button() & Qt::LeftButton) {
-               _mouse_down_point = event->pos();
+void Header::mouseLeftReleaseEvent(QMouseEvent *event)
+{
+       assert(event);
 
-               // Save the offsets of any signals which will be dragged
-               for (const shared_ptr<RowItem> r : _view)
-                       if (r->selected())
-                               _drag_row_items.push_back(
-                                       make_pair(r, r->v_offset()));
-       }
+       const bool ctrl_pressed =
+               QApplication::keyboardModifiers() & Qt::ControlModifier;
 
-       // Select the signal if it has been clicked
-       const shared_ptr<RowItem> mouse_over_row_item =
+       // Unselect everything if control is not pressed
+       const shared_ptr<RowItem> mouse_over =
                get_mouse_over_row_item(event->pos());
-       if (mouse_over_row_item) {
-               if (mouse_over_row_item->selected())
-                       mouse_over_row_item->select(false);
-               else {
-                       mouse_over_row_item->select(true);
-
-                       if (~QApplication::keyboardModifiers() &
-                               Qt::ControlModifier)
-                               _drag_row_items.clear();
-
-                       // Add the signal to the drag list
-                       if (event->button() & Qt::LeftButton)
-                               _drag_row_items.push_back(
-                                       make_pair(mouse_over_row_item,
-                                       mouse_over_row_item->v_offset()));
-               }
-       }
 
-       if (~QApplication::keyboardModifiers() & Qt::ControlModifier) {
-               // Unselect all other signals because the Ctrl is not
-               // pressed
-               for (const shared_ptr<RowItem> r : _view)
-                       if (r != mouse_over_row_item)
-                               r->select(false);
+       if (_dragging)
+               _view.normalize_layout();
+       else
+       {
+               if (!ctrl_pressed) {
+                       for (shared_ptr<RowItem> r : _view)
+                               if (mouse_over != r)
+                                       r->select(false);
+
+                       if (mouse_over)
+                               show_popup(mouse_over);
+               }
        }
 
-       selection_changed();
-       update();
+       _dragging = false;
+       _drag_row_items.clear();
 }
 
 void Header::mouseReleaseEvent(QMouseEvent *event)
 {
        assert(event);
-       if (event->button() == Qt::LeftButton) {
-               if (_dragging)
-                       _view.normalize_layout();
-               else
-               {
-                       const shared_ptr<RowItem> mouse_over_row_item =
-                               get_mouse_over_row_item(event->pos());
-                       if (mouse_over_row_item)
-                               show_popup(mouse_over_row_item);
-               }
-
-               _dragging = false;
-               _drag_row_items.clear();
-       }
+       if (event->button() & Qt::LeftButton)
+               mouseLeftReleaseEvent(event);
 }
 
 void Header::mouseMoveEvent(QMouseEvent *event)
@@ -214,29 +222,40 @@ void Header::mouseMoveEvent(QMouseEvent *event)
                QApplication::startDragDistance())
                return;
 
-       // Move the signals if we are dragging
-       if (!_drag_row_items.empty())
-       {
-               _dragging = true;
+       // Check the list of dragging items is not empty
+       if (_drag_row_items.empty())
+               return;
 
-               const int delta = event->pos().y() - _mouse_down_point.y();
+       // Check all the drag items share a common owner
+       const shared_ptr<RowItem> first_row_item(
+               _drag_row_items.front().first);
+       for (const auto &r : _drag_row_items) {
+               const shared_ptr<RowItem> row_item(r.first);
+               assert(row_item);
 
-               for (auto i = _drag_row_items.begin();
-                       i != _drag_row_items.end(); i++) {
-                       const std::shared_ptr<RowItem> row_item((*i).first);
-                       if (row_item) {
-                               const int y = (*i).second + delta;
-                               row_item->set_v_offset(y);
+               if (row_item->owner() != first_row_item->owner())
+                       return;
+       }
 
-                               // Ensure the trace is selected
-                               row_item->select();
-                       }
-                       
-               }
+       // Do the drag
+       _dragging = true;
 
-               signals_moved();
+       const int delta = event->pos().y() - _mouse_down_point.y();
+
+       for (auto i = _drag_row_items.begin();
+               i != _drag_row_items.end(); i++) {
+               const std::shared_ptr<RowItem> row_item((*i).first);
+               if (row_item) {
+                       const int y = (*i).second + delta;
+                       row_item->set_v_offset(y);
+
+                       // Ensure the trace is selected
+                       row_item->select();
+               }
        }
 
+       signals_moved();
+
        update();
 }