From 2543cd4e271ff13898080d011a8fdbc13da77655 Mon Sep 17 00:00:00 2001 From: Soeren Apel Date: Wed, 10 Oct 2018 18:08:40 +0200 Subject: [PATCH] Ruler: Add context menu with "Create marker here" entry --- manual/analysis.txt | 5 ++- pv/views/trace/ruler.cpp | 92 +++++++++++++++++++++++++--------------- pv/views/trace/ruler.hpp | 44 ++++++++++--------- test/view/ruler.cpp | 6 +-- 4 files changed, 89 insertions(+), 58 deletions(-) diff --git a/manual/analysis.txt b/manual/analysis.txt index deb31d7..034f969 100644 --- a/manual/analysis.txt +++ b/manual/analysis.txt @@ -43,8 +43,9 @@ image::pv_cursors_markers.png[] Markers are movable indicators that you can create wherever you like on the time scale - just double-click on it and it'll create one for you where your -mouse cursor is at the time. You can click on its label and you'll have the -option to change its name, or drag it to reposition it. +mouse cursor is at the time, or use the context menu when right-clicking. +You can click on its label and you'll have the option to change its name, or +drag it to reposition it. [NOTE] For timing comparison purposes, you can also enable a vertical marker line that diff --git a/pv/views/trace/ruler.cpp b/pv/views/trace/ruler.cpp index 63d3d23..7688f2b 100644 --- a/pv/views/trace/ruler.cpp +++ b/pv/views/trace/ruler.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "ruler.hpp" @@ -111,6 +112,30 @@ QString Ruler::format_time_with_distance( return pv::util::format_time_minutes(t, precision, sign); } +pv::util::Timestamp Ruler::get_time_from_x_pos(uint32_t x) +{ + return view_.ruler_offset() + ((double)x + 0.5) * view_.scale(); +} + +void Ruler::contextMenuEvent(QContextMenuEvent *event) +{ + context_menu_x_pos_ = event->pos().x(); + + QMenu *const menu = new QMenu(this); + + QAction *const create_marker = new QAction(tr("Create marker here"), this); + connect(create_marker, SIGNAL(triggered()), this, SLOT(on_createMarker())); + menu->addAction(create_marker); + + menu->popup(event->globalPos()); +} + +void Ruler::resizeEvent(QResizeEvent*) +{ + // the tick calculation depends on the width of this widget + invalidate_tick_position_cache(); +} + vector< shared_ptr > Ruler::items() { const vector< shared_ptr > time_items(view_.time_items()); @@ -127,6 +152,11 @@ shared_ptr Ruler::get_mouse_over_item(const QPoint &pt) return nullptr; } +void Ruler::mouseDoubleClickEvent(QMouseEvent *event) +{ + view_.add_flag(get_time_from_x_pos(event->x())); +} + void Ruler::paintEvent(QPaintEvent*) { if (!tick_position_cache_) { @@ -199,7 +229,32 @@ void Ruler::paintEvent(QPaintEvent*) } } -Ruler::TickPositions Ruler::calculate_tick_positions( +void Ruler::draw_hover_mark(QPainter &p, int text_height) +{ + const int x = view_.hover_point().x(); + + if (x == -1) + return; + + p.setPen(QPen(Qt::NoPen)); + p.setBrush(QBrush(palette().color(foregroundRole()))); + + const int b = RulerHeight * text_height; + const float hover_arrow_size = HoverArrowSize * text_height; + const QPointF points[] = { + QPointF(x, b), + QPointF(x - hover_arrow_size, b - hover_arrow_size), + QPointF(x + hover_arrow_size, b - hover_arrow_size) + }; + p.drawPolygon(points, countof(points)); +} + +int Ruler::calculate_text_height() const +{ + return QFontMetrics(font()).ascent(); +} + +TickPositions Ruler::calculate_tick_positions( const pv::util::Timestamp& major_period, const pv::util::Timestamp& offset, const double scale, @@ -237,36 +292,6 @@ Ruler::TickPositions Ruler::calculate_tick_positions( return tp; } -void Ruler::mouseDoubleClickEvent(QMouseEvent *event) -{ - view_.add_flag(view_.ruler_offset() + ((double)event->x() + 0.5) * view_.scale()); -} - -void Ruler::draw_hover_mark(QPainter &p, int text_height) -{ - const int x = view_.hover_point().x(); - - if (x == -1) - return; - - p.setPen(QPen(Qt::NoPen)); - p.setBrush(QBrush(palette().color(foregroundRole()))); - - const int b = RulerHeight * text_height; - const float hover_arrow_size = HoverArrowSize * text_height; - const QPointF points[] = { - QPointF(x, b), - QPointF(x - hover_arrow_size, b - hover_arrow_size), - QPointF(x + hover_arrow_size, b - hover_arrow_size) - }; - p.drawPolygon(points, countof(points)); -} - -int Ruler::calculate_text_height() const -{ - return QFontMetrics(font()).ascent(); -} - void Ruler::hover_point_changed(const QPoint &hp) { (void)hp; @@ -279,10 +304,9 @@ void Ruler::invalidate_tick_position_cache() tick_position_cache_ = boost::none; } -void Ruler::resizeEvent(QResizeEvent*) +void Ruler::on_createMarker() { - // the tick calculation depends on the width of this widget - invalidate_tick_position_cache(); + view_.add_flag(get_time_from_x_pos(context_menu_x_pos_)); } } // namespace trace diff --git a/pv/views/trace/ruler.hpp b/pv/views/trace/ruler.hpp index 448204b..61e622a 100644 --- a/pv/views/trace/ruler.hpp +++ b/pv/views/trace/ruler.hpp @@ -46,6 +46,12 @@ namespace trace { class TimeItem; class ViewItem; +struct TickPositions +{ + vector> major; + vector minor; +}; + /** * The Ruler class manages and displays the time scale above the trace canvas. * It may also contain @ref TimeItem instances used to identify or highlight @@ -69,7 +75,6 @@ private: public: Ruler(View &parent); -public: QSize sizeHint() const override; /** @@ -112,6 +117,12 @@ public: unsigned precision = 0, bool sign = true); + pv::util::Timestamp get_time_from_x_pos(uint32_t x); + +protected: + virtual void contextMenuEvent(QContextMenuEvent *event) override; + void resizeEvent(QResizeEvent*) override; + private: /** * Gets the time items. @@ -126,10 +137,10 @@ private: */ shared_ptr get_mouse_over_item(const QPoint &pt) override; - void paintEvent(QPaintEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *event) override; + /** * Draw a hover arrow under the cursor position. * @param p The painter to draw into. @@ -139,18 +150,6 @@ private: int calculate_text_height() const; - struct TickPositions - { - vector> major; - vector minor; - }; - - /** - * Holds the tick positions so that they don't have to be recalculated on - * every redraw. Set by 'paintEvent()' when needed. - */ - boost::optional tick_position_cache_; - /** * Calculates the major and minor tick positions. * @@ -171,14 +170,21 @@ private: const unsigned int minor_tick_count, function format_function); -protected: - void resizeEvent(QResizeEvent*) override; - private Q_SLOTS: void hover_point_changed(const QPoint &hp); - // Resets the 'tick_position_cache_'. void invalidate_tick_position_cache(); + + void on_createMarker(); + +private: + /** + * Holds the tick positions so that they don't have to be recalculated on + * every redraw. Set by 'paintEvent()' when needed. + */ + boost::optional tick_position_cache_; + + uint32_t context_menu_x_pos_; }; } // namespace trace diff --git a/test/view/ruler.cpp b/test/view/ruler.cpp index 3984e97..5cef38d 100644 --- a/test/view/ruler.cpp +++ b/test/view/ruler.cpp @@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(tick_position_test_0) const int width(500); const unsigned int minor_tick_count(4); - const Ruler::TickPositions ts = Ruler::calculate_tick_positions( + const TickPositions ts = Ruler::calculate_tick_positions( major_period, offset, scale, width, minor_tick_count, format); BOOST_REQUIRE_EQUAL(ts.major.size(), 6); @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(tick_position_test_1) const int width(500); const unsigned int minor_tick_count(4); - const Ruler::TickPositions ts = Ruler::calculate_tick_positions( + const TickPositions ts = Ruler::calculate_tick_positions( major_period, offset, scale, width, minor_tick_count, format); BOOST_REQUIRE_EQUAL(ts.major.size(), 5); @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(tick_position_test_2) const int width(580); const unsigned int minor_tick_count(4); - const Ruler::TickPositions ts = Ruler::calculate_tick_positions( + const TickPositions ts = Ruler::calculate_tick_positions( major_period, offset, scale, width, minor_tick_count, format); const double mp = 5; -- 2.30.2