]> sigrok.org Git - pulseview.git/blobdiff - pv/view/ruler.cpp
Ruler: Recombined with CursorHeader
[pulseview.git] / pv / view / ruler.cpp
index ee521f0e82a1203438d8a7420ec2336baec89af4..7018c212db52f8b72f1449400b9160594a746dde 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-#include "ruler.hpp"
+#include <extdef.h>
 
+#include <QApplication>
+#include <QFontMetrics>
+#include <QMouseEvent>
+
+#include "ruler.hpp"
 #include "view.hpp"
-#include "pv/util.hpp"
 
-#include <extdef.h>
+#include <pv/util.hpp>
+#include <pv/widgets/popup.hpp>
 
 using namespace Qt;
 
+using std::shared_ptr;
+using std::vector;
+
 namespace pv {
 namespace view {
 
@@ -35,8 +43,12 @@ const int Ruler::MinorTickSubdivision = 4;
 
 const int Ruler::HoverArrowSize = 5;
 
+const int Ruler::Padding = 20;
+const int Ruler::BaselineOffset = 5;
+
 Ruler::Ruler(View &parent) :
-       MarginWidget(parent)
+       MarginWidget(parent),
+       text_height_(calculate_text_height())
 {
        setMouseTracking(true);
 
@@ -44,11 +56,25 @@ Ruler::Ruler(View &parent) :
                this, SLOT(hover_point_changed()));
 }
 
+void Ruler::clear_selection()
+{
+       const vector< shared_ptr<TimeItem> > items(view_.time_items());
+       for (auto &i : items)
+               i->select(false);
+       update();
+}
+
 QSize Ruler::sizeHint() const
 {
        return QSize(0, RulerHeight);
 }
 
+QSize Ruler::extended_size_hint() const
+{
+       return QSize(0, RulerHeight +
+               (text_height_ + Padding + BaselineOffset) / 2);
+}
+
 void Ruler::paintEvent(QPaintEvent*)
 {
        const int ValueMargin = 3;
@@ -59,9 +85,6 @@ void Ruler::paintEvent(QPaintEvent*)
        const double tick_period = view_.tick_period();
        const unsigned int prefix = view_.tick_prefix();
 
-       const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
-               AlignLeft | AlignTop, "8").height();
-
        // Draw the tick marks
        p.setPen(palette().color(foregroundRole()));
 
@@ -75,8 +98,8 @@ void Ruler::paintEvent(QPaintEvent*)
        int division = (int)round(first_minor_division -
                first_major_division * MinorTickSubdivision) - 1;
 
-       const int major_tick_y1 = text_height + ValueMargin * 2;
-       const int tick_y2 = height();
+       const int major_tick_y1 = text_height_ + ValueMargin * 2;
+       const int tick_y2 = RulerHeight;
        const int minor_tick_y1 = (major_tick_y1 + tick_y2) / 2;
 
        double x;
@@ -88,7 +111,7 @@ void Ruler::paintEvent(QPaintEvent*)
                if (division % MinorTickSubdivision == 0)
                {
                        // Draw a major tick
-                       p.drawText(x, ValueMargin, 0, text_height,
+                       p.drawText(x, ValueMargin, 0, text_height_,
                                AlignCenter | AlignTop | TextDontClip,
                                pv::util::format_time(t, prefix));
                        p.drawLine(QPointF(x, major_tick_y1),
@@ -107,6 +130,110 @@ void Ruler::paintEvent(QPaintEvent*)
 
        // Draw the hover mark
        draw_hover_mark(p);
+
+       // The cursor labels are not drawn with the arrows exactly on the
+       // bottom line of the widget, because then the selection shadow
+       // would be clipped away.
+       const QRect r = rect().adjusted(0, 0, 0, -BaselineOffset);
+
+       // Draw the items
+       const vector< shared_ptr<TimeItem> > items(view_.time_items());
+       for (auto &i : items)
+               i->paint_label(p, r);
+}
+
+void Ruler::mouseMoveEvent(QMouseEvent *e)
+{
+       mouse_point_ = e->pos();
+
+       if (!(e->buttons() & Qt::LeftButton))
+               return;
+
+       if ((e->pos() - mouse_down_point_).manhattanLength() <
+               QApplication::startDragDistance())
+               return;
+
+       // Do the drag
+       dragging_ = true;
+
+       const int delta = e->pos().x() - mouse_down_point_.x();
+       const vector< shared_ptr<TimeItem> > items(view_.time_items());
+       for (auto &i : items)
+               if (i->dragging())
+                       i->set_time(view_.offset() +
+                               (i->drag_point().x() + delta - 0.5) *
+                               view_.scale());
+}
+
+void Ruler::mousePressEvent(QMouseEvent *e)
+{
+       if (e->buttons() & Qt::LeftButton) {
+               mouse_down_point_ = e->pos();
+
+               mouse_down_item_.reset();
+
+               clear_selection();
+
+               const vector< shared_ptr<TimeItem> > items(view_.time_items());
+               for (auto i = items.rbegin(); i != items.rend(); i++)
+                       if ((*i)->label_rect(rect()).contains(e->pos())) {
+                               mouse_down_item_ = (*i);
+                               break;
+                       }
+
+               if (mouse_down_item_) {
+                       mouse_down_item_->select();
+                       mouse_down_item_->drag();
+               }
+
+               selection_changed();
+       }
+}
+
+void Ruler::mouseReleaseEvent(QMouseEvent *)
+{
+       using pv::widgets::Popup;
+
+       if (!dragging_ && mouse_down_item_) {
+               Popup *const p = mouse_down_item_->create_popup(&view_);
+               if (p) {
+                       const QPoint arrpos(mouse_down_item_->get_x(),
+                               height() - BaselineOffset);
+                       p->set_position(mapToGlobal(arrpos), Popup::Bottom);
+                       p->show();
+               }
+       }
+
+       dragging_ = false;
+       mouse_down_item_.reset();
+
+       const vector< shared_ptr<TimeItem> > items(view_.time_items());
+       for (auto &i : items)
+               i->drag_release();
+}
+
+void Ruler::leaveEvent(QEvent*)
+{
+       mouse_point_ = QPoint(-1, -1);
+       update();
+}
+
+void Ruler::mouseDoubleClickEvent(QMouseEvent *e)
+{
+       view_.add_flag(view_.offset() + ((double)e->x() + 0.5) * view_.scale());
+}
+
+void Ruler::keyPressEvent(QKeyEvent *e)
+{
+       assert(e);
+
+       if (e->key() == Qt::Key_Delete)
+       {
+               const vector< shared_ptr<TimeItem> > items(view_.time_items());
+               for (auto &i : items)
+                       if (i->selected())
+                               i->delete_pressed();
+       }
 }
 
 void Ruler::draw_hover_mark(QPainter &p)
@@ -119,7 +246,7 @@ void Ruler::draw_hover_mark(QPainter &p)
        p.setPen(QPen(Qt::NoPen));
        p.setBrush(QBrush(palette().color(foregroundRole())));
 
-       const int b = height() - 1;
+       const int b = RulerHeight;
        const QPointF points[] = {
                QPointF(x, b),
                QPointF(x - HoverArrowSize, b - HoverArrowSize),
@@ -128,6 +255,13 @@ void Ruler::draw_hover_mark(QPainter &p)
        p.drawPolygon(points, countof(points));
 }
 
+int Ruler::calculate_text_height()
+{
+       QFontMetrics fm(font());
+       return fm.boundingRect(0, 0, INT_MAX, INT_MAX,
+               Qt::AlignLeft | Qt::AlignTop, "8").height();
+}
+
 void Ruler::hover_point_changed()
 {
        update();