]> sigrok.org Git - pulseview.git/blobdiff - pv/views/trace/trace.cpp
Implement MathSignal
[pulseview.git] / pv / views / trace / trace.cpp
index 7d8501122753aabe9f4d739d2dbea82d211fab5b..ecc1aecc901a8adb9599c34e34f69ee896399727 100644 (file)
@@ -26,7 +26,9 @@
 #include <QFormLayout>
 #include <QKeyEvent>
 #include <QLineEdit>
+#include <QMenu>
 
+#include "ruler.hpp"
 #include "trace.hpp"
 #include "tracepalette.hpp"
 #include "view.hpp"
@@ -48,17 +50,17 @@ const int Trace::LabelHitPadding = 2;
 const QColor Trace::BrightGrayBGColor = QColor(0, 0, 0, 10 * 255 / 100);
 const QColor Trace::DarkGrayBGColor = QColor(0, 0, 0, 15 * 255 / 100);
 
-Trace::Trace(shared_ptr<data::SignalBase> channel) :
-       base_(channel),
+Trace::Trace(shared_ptr<data::SignalBase> signal) :
+       base_(signal),
        axis_pen_(AxisPen),
        segment_display_mode_(ShowLastSegmentOnly),  // Will be overwritten by View
        current_segment_(0),
        popup_(nullptr),
        popup_form_(nullptr)
 {
-       connect(channel.get(), SIGNAL(name_changed(const QString&)),
+       connect(signal.get(), SIGNAL(name_changed(const QString&)),
                this, SLOT(on_name_changed(const QString&)));
-       connect(channel.get(), SIGNAL(color_changed(const QColor&)),
+       connect(signal.get(), SIGNAL(color_changed(const QColor&)),
                this, SLOT(on_color_changed(const QColor&)));
 
        GlobalSettings::add_change_handler(this);
@@ -78,6 +80,26 @@ shared_ptr<data::SignalBase> Trace::base() const
        return base_;
 }
 
+bool Trace::is_selectable(QPoint pos) const
+{
+       // True if the header was clicked, false if the trace area was clicked
+       const View *view = owner_->view();
+       assert(view);
+
+       return (pos.x() <= view->header_width());
+}
+
+bool Trace::is_draggable(QPoint pos) const
+{
+       // While the header label that belongs to this trace is draggable,
+       // the trace itself shall not be. Hence we return true if the header
+       // was clicked and false if the trace area was clicked
+       const View *view = owner_->view();
+       assert(view);
+
+       return (pos.x() <= view->header_width());
+}
+
 void Trace::set_segment_display_mode(SegmentDisplayMode mode)
 {
        segment_display_mode_ = mode;
@@ -90,6 +112,10 @@ void Trace::on_setting_changed(const QString &key, const QVariant &value)
 {
        if (key == GlobalSettings::Key_View_ShowHoverMarker)
                show_hover_marker_ = value.toBool();
+
+       // Force a repaint since many options alter the way traces look
+       if (owner_)
+               owner_->row_item_appearance_changed(false, true);
 }
 
 void Trace::paint_label(QPainter &p, const QRect &rect, bool hover)
@@ -149,9 +175,37 @@ void Trace::paint_label(QPainter &p, const QRect &rect, bool hover)
                Qt::AlignCenter | Qt::AlignVCenter, base_->name());
 }
 
-QMenu* Trace::create_context_menu(QWidget *parent)
+QMenu* Trace::create_header_context_menu(QWidget *parent)
 {
-       QMenu *const menu = ViewItem::create_context_menu(parent);
+       QMenu *const menu = ViewItem::create_header_context_menu(parent);
+
+       return menu;
+}
+
+QMenu* Trace::create_view_context_menu(QWidget *parent, QPoint &click_pos)
+{
+       context_menu_x_pos_ = click_pos.x();
+
+       // Get entries from default menu before adding our own
+       QMenu *const menu = new QMenu(parent);
+
+       QMenu* default_menu = TraceTreeItem::create_view_context_menu(parent, click_pos);
+       if (default_menu) {
+               for (QAction *action : default_menu->actions()) {  // clazy:exclude=range-loop
+                       menu->addAction(action);
+                       if (action->parent() == default_menu)
+                               action->setParent(menu);
+               }
+               delete default_menu;
+
+               // Add separator if needed
+               if (menu->actions().length() > 0)
+                       menu->addSeparator();
+       }
+
+       QAction *const create_marker_here = new QAction(tr("Create marker here"), this);
+       connect(create_marker_here, SIGNAL(triggered()), this, SLOT(on_create_marker_here()));
+       menu->addAction(create_marker_here);
 
        return menu;
 }
@@ -187,6 +241,20 @@ QRectF Trace::label_rect(const QRectF &rect) const
                label_size.height());
 }
 
+QRectF Trace::hit_box_rect(const ViewItemPaintParams &pp) const
+{
+       // This one is only for the trace itself, excluding the header area
+       const View *view = owner_->view();
+       assert(view);
+
+       pair<int, int> extents = v_extents();
+       const int top = pp.top() + get_visual_y() + extents.first;
+       const int height = extents.second - extents.first;
+
+       return QRectF(pp.left() + view->header_width(), top,
+               pp.width() - view->header_width(), height);
+}
+
 void Trace::set_current_segment(const int segment)
 {
        current_segment_ = segment;
@@ -224,12 +292,13 @@ void Trace::paint_back(QPainter &p, ViewItemPaintParams &pp)
 
 void Trace::paint_axis(QPainter &p, ViewItemPaintParams &pp, int y)
 {
+       bool was_antialiased = p.testRenderHint(QPainter::Antialiasing);
        p.setRenderHint(QPainter::Antialiasing, false);
 
        p.setPen(axis_pen_);
        p.drawLine(QPointF(pp.left(), y), QPointF(pp.right(), y));
 
-       p.setRenderHint(QPainter::Antialiasing, true);
+       p.setRenderHint(QPainter::Antialiasing, was_antialiased);
 }
 
 void Trace::add_color_option(QWidget *parent, QFormLayout *form)
@@ -260,10 +329,11 @@ void Trace::paint_hover_marker(QPainter &p)
 
        const pair<int, int> extents = v_extents();
 
+       bool was_antialiased = p.testRenderHint(QPainter::Antialiasing);
        p.setRenderHint(QPainter::Antialiasing, false);
        p.drawLine(x, get_visual_y() + extents.first,
                x, get_visual_y() + extents.second);
-       p.setRenderHint(QPainter::Antialiasing, true);
+       p.setRenderHint(QPainter::Antialiasing, was_antialiased);
 }
 
 void Trace::create_popup_form()
@@ -276,13 +346,28 @@ void Trace::create_popup_form()
        // handled, leaving the parent popup_ time to handle the change.
        if (popup_form_) {
                QWidget *suicidal = new QWidget();
-               suicidal->setLayout(popup_form_);
+               suicidal->setLayout(popup_->layout());
                suicidal->deleteLater();
        }
 
        // Repopulate the popup
-       popup_form_ = new QFormLayout(popup_);
-       popup_->setLayout(popup_form_);
+       widgets::QWidthAdjustingScrollArea* scrollarea = new widgets::QWidthAdjustingScrollArea();
+       QWidget* scrollarea_content = new QWidget(scrollarea);
+
+       scrollarea->setWidget(scrollarea_content);
+       scrollarea->setWidgetResizable(true);
+       scrollarea->setContentsMargins(0, 0, 0, 0);
+       scrollarea->setFrameShape(QFrame::NoFrame);
+       scrollarea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+       scrollarea_content->setContentsMargins(0, 0, 0, 0);
+
+       popup_->setLayout(new QVBoxLayout());
+       popup_->layout()->addWidget(scrollarea);
+       popup_->layout()->setContentsMargins(0, 0, 0, 0);
+
+       popup_form_ = new QFormLayout(scrollarea_content);
+       popup_form_->setSizeConstraint(QLayout::SetMinAndMaxSize);
+
        populate_popup_form(popup_, popup_form_);
 }
 
@@ -335,6 +420,17 @@ void Trace::on_coloredit_changed(const QColor &color)
        base_->set_color(color);
 }
 
+void Trace::on_create_marker_here() const
+{
+       View *view = owner_->view();
+       assert(view);
+
+       const Ruler *ruler = view->ruler();
+       QPoint p = ruler->mapFrom(view, QPoint(context_menu_x_pos_, 0));
+
+       view->add_flag(ruler->get_absolute_time_from_x_pos(p.x()));
+}
+
 } // namespace trace
 } // namespace views
 } // namespace pv