second_->set_time(time + delta);
}
+const pv::util::Timestamp CursorPair::time() const
+{
+ return (first_->time() + second_->time()) / 2.0f;
+}
+
float CursorPair::get_x() const
{
return (first_->get_x() + second_->get_x()) / 2.0f;
}
+const pv::util::Timestamp CursorPair::delta(const pv::util::Timestamp& other) const
+{
+ if (other < second_->time())
+ return other - first_->time();
+ else
+ return other - second_->time();
+}
+
QPoint CursorPair::drag_point(const QRect &rect) const
{
return first_->drag_point(rect);
*/
void set_time(const pv::util::Timestamp& time) override;
+ virtual const pv::util::Timestamp time() const override;
+
float get_x() const override;
+ virtual const pv::util::Timestamp delta(const pv::util::Timestamp& other) const override;
+
QPoint drag_point(const QRect &rect) const override;
pv::widgets::Popup* create_popup(QWidget *parent) override;
#include "timemarker.hpp"
#include "view.hpp"
+#include "ruler.hpp"
#include <QColor>
#include <QFormLayout>
#include <QLineEdit>
#include <QMenu>
+#include <QApplication>
#include <libsigrokcxx/libsigrokcxx.hpp>
QString Flag::get_text() const
{
- return text_;
+ const shared_ptr<TimeItem> ref_item = view_.get_reference_time_item();
+ if (ref_item == nullptr || ref_item.get() == this) {
+ return text_;
+ } else {
+ return Ruler::format_time_with_distance(
+ ref_item->time(), ref_item->delta(time_),
+ view_.tick_prefix(), view_.time_unit(), view_.tick_precision());
+ }
+}
+
+QRectF Flag::label_rect(const QRectF &rect) const
+{
+ const shared_ptr<TimeItem> ref_item = view_.get_reference_time_item();
+ if (ref_item == nullptr || ref_item.get() == this) {
+ return TimeMarker::label_rect(rect);
+
+ } else {
+ // TODO: Remove code duplication between here and cursor.cpp
+ const float x = get_x();
+
+ QFontMetrics m(QApplication::font());
+ QSize text_size = m.boundingRect(get_text()).size();
+
+ const QSizeF label_size(
+ text_size.width() + LabelPadding.width() * 2,
+ text_size.height() + LabelPadding.height() * 2);
+ const float top = rect.height() - label_size.height() -
+ TimeMarker::ArrowSize - 0.5f;
+ const float height = label_size.height();
+
+ const pv::util::Timestamp& delta = ref_item->delta(time_);
+
+ if (delta >= 0)
+ return QRectF(x, top, label_size.width(), height);
+ else
+ return QRectF(x - label_size.width(), top, label_size.width(), height);
+ }
}
pv::widgets::Popup* Flag::create_popup(QWidget *parent)
/**
* Returns true if the item is visible and enabled.
*/
- bool enabled() const;
+ virtual bool enabled() const override;
/**
* Gets the text to show in the marker.
*/
- QString get_text() const;
+ virtual QString get_text() const override;
- pv::widgets::Popup* create_popup(QWidget *parent);
+ virtual pv::widgets::Popup* create_popup(QWidget *parent) override;
- QMenu* create_header_context_menu(QWidget *parent);
+ virtual QMenu* create_header_context_menu(QWidget *parent) override;
- void delete_pressed();
+ virtual void delete_pressed() override;
+
+ QRectF label_rect(const QRectF &rect) const override;
private Q_SLOTS:
void on_delete();
if (i->selected())
i->delete_pressed();
}
+
+ ViewWidget::keyPressEvent(event);
}
} // namespace trace
time_items.begin(), time_items.end());
}
+void Ruler::item_hover(const shared_ptr<ViewItem> &item, QPoint pos)
+{
+ Q_UNUSED(pos);
+ hover_item_ = dynamic_pointer_cast<TimeItem>(item);
+}
+
+shared_ptr<TimeItem> Ruler::get_reference_item()
+{
+ if (mouse_modifiers_ & Qt::ShiftModifier)
+ return nullptr;
+
+ if (hover_item_ != nullptr)
+ return hover_item_;
+
+ shared_ptr<TimeItem> found(nullptr);
+ const vector< shared_ptr<TimeItem> > items(view_.time_items());
+ for (auto i = items.rbegin(); i != items.rend(); i++) {
+ if ((*i)->enabled() && (*i)->selected()) {
+ if (found == nullptr)
+ found = *i;
+ else
+ return nullptr; // Return null if multiple items are selected
+ }
+ }
+
+ return found;
+}
+
shared_ptr<ViewItem> Ruler::get_mouse_over_item(const QPoint &pt)
{
const vector< shared_ptr<TimeItem> > items(view_.time_items());
void Ruler::mouseDoubleClickEvent(QMouseEvent *event)
{
- view_.add_flag(get_absolute_time_from_x_pos(event->x()));
+ hover_item_ = view_.add_flag(get_absolute_time_from_x_pos(event->x()));
}
void Ruler::paintEvent(QPaintEvent*)
void Ruler::on_createMarker()
{
- view_.add_flag(get_absolute_time_from_x_pos(mouse_down_point_.x()));
+ hover_item_ = view_.add_flag(get_absolute_time_from_x_pos(mouse_down_point_.x()));
}
void Ruler::on_setZeroPosition()
pv::util::Timestamp get_ruler_time_from_absolute_time(const pv::util::Timestamp& abs_time) const;
pv::util::Timestamp get_absolute_time_from_ruler_time(const pv::util::Timestamp& ruler_time) const;
+ shared_ptr<TimeItem> get_reference_item();
+
protected:
virtual void contextMenuEvent(QContextMenuEvent *event) override;
void resizeEvent(QResizeEvent*) override;
+ virtual void item_hover(const shared_ptr<ViewItem> &item, QPoint pos) override;
private:
/**
*/
boost::optional<TickPositions> tick_position_cache_;
+ shared_ptr<TimeItem> hover_item_;
+
uint32_t context_menu_x_pos_;
};
*/
virtual void set_time(const pv::util::Timestamp& time) = 0;
+ virtual const pv::util::Timestamp time() const = 0;
+
virtual float get_x() const = 0;
+ virtual const pv::util::Timestamp delta(const pv::util::Timestamp& other) const = 0;
+
/**
* Drags the item to a delta relative to the drag point.
* @param delta the offset from the drag point.
{
}
-const pv::util::Timestamp& TimeMarker::time() const
+const pv::util::Timestamp TimeMarker::time() const
{
return time_;
}
return roundf(((time_ - view_.offset()) / view_.scale()).convert_to<float>()) + 0.5f;
}
+const pv::util::Timestamp TimeMarker::delta(const pv::util::Timestamp& other) const
+{
+ return other - time_;
+}
+
QPoint TimeMarker::drag_point(const QRect &rect) const
{
(void)rect;
/**
* Gets the time of the marker.
*/
- const pv::util::Timestamp& time() const;
+ virtual const pv::util::Timestamp time() const override;
/**
* Sets the time of the marker.
float get_x() const override;
+ virtual const pv::util::Timestamp delta(const pv::util::Timestamp& other) const override;
+
/**
* Gets the arrow-tip point of the time marker.
* @param rect the rectangle of the ruler area.
void TriggerMarker::set_time(const pv::util::Timestamp& time)
{
time_ = time;
-
view_.time_item_appearance_changed(true, true);
}
+const pv::util::Timestamp TriggerMarker::time() const
+{
+ return time_;
+}
+
float TriggerMarker::get_x() const
{
return ((time_ - view_.offset()) / view_.scale()).convert_to<float>();
}
+const pv::util::Timestamp TriggerMarker::delta(const pv::util::Timestamp& other) const
+{
+ return other - time_;
+}
+
QPoint TriggerMarker::drag_point(const QRect &rect) const
{
(void)rect;
*/
void set_time(const pv::util::Timestamp& time) override;
+ virtual const pv::util::Timestamp time() const override;
+
float get_x() const override;
+ virtual const pv::util::Timestamp delta(const pv::util::Timestamp& other) const override;
+
/**
* Gets the arrow-tip point of the time marker.
* @param rect the rectangle of the ruler area.
// Note: Place defaults in View::reset_view_state(), not here
splitter_(new QSplitter()),
- header_was_shrunk_(false), // The splitter remains unchanged after a reset, so this goes here
+ header_was_shrunk_(false), // The splitter remains unchanged after a reset, so this goes here
sticky_scrolling_(false) // Default setting is set in MainWindow::setup_ui()
{
QVBoxLayout *root_layout = new QVBoxLayout(this);
splitter_->setHandleWidth(1); // Don't show a visible rubber band
splitter_->setCollapsible(0, false); // Prevent the header from collapsing
splitter_->setCollapsible(1, false); // Prevent the traces from collapsing
- splitter_->setStretchFactor(0, 0); // Prevent the panes from being resized
- splitter_->setStretchFactor(1, 1); // when the entire view is resized
+ splitter_->setStretchFactor(0, 0); // Prevent the panes from being resized
+ splitter_->setStretchFactor(1, 1); // when the entire view is resized
splitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
viewport_->installEventFilter(this);
return items;
}
+shared_ptr<TimeItem> View::get_reference_time_item()
+{
+ return ruler_->get_reference_item();
+}
+
double View::scale() const
{
return scale_;
const Timestamp start_time = s->start_time();
left_time = left_time ?
min(*left_time, start_time) :
- start_time;
+ start_time;
right_time = right_time ?
max(*right_time, start_time + d->max_sample_count() / samplerate) :
- start_time + d->max_sample_count() / samplerate;
+ start_time + d->max_sample_count() / samplerate;
}
}
return cursors_;
}
-void View::add_flag(const Timestamp& time)
+shared_ptr<Flag> View::add_flag(const Timestamp& time)
{
- flags_.push_back(make_shared<Flag>(*this, time,
- QString("%1").arg(next_flag_text_)));
+ shared_ptr<Flag> flag = make_shared<Flag>(
+ *this, time, QString("%1").arg(next_flag_text_));
+ flags_.push_back(flag);
next_flag_text_ = (next_flag_text_ >= 'Z') ? 'A' :
(next_flag_text_ + 1);
time_item_appearance_changed(true, true);
+ return flag;
}
void View::remove_flag(shared_ptr<Flag> flag)
*/
vector< shared_ptr<TimeItem> > time_items() const;
+ shared_ptr<TimeItem> get_reference_time_item();
+
/**
* Returns the view time scale in seconds per pixel.
*/
/**
* Adds a new flag at a specified time.
*/
- void add_flag(const pv::util::Timestamp& time);
+ shared_ptr<Flag> add_flag(const pv::util::Timestamp& time);
/**
* Removes a flag from the list.
mouse_down_item_ = nullptr;
}
+void ViewWidget::keyReleaseEvent(QKeyEvent *event)
+{
+ // Update mouse_modifiers_ also if modifiers change, but pointer doesn't move
+ if (mouse_point_.x() >= 0 && mouse_point_.y() >= 0) // mouse is inside
+ mouse_modifiers_ = event->modifiers();
+ update();
+}
+
+void ViewWidget::keyPressEvent(QKeyEvent *event)
+{
+ // Update mouse_modifiers_ also if modifiers change, but pointer doesn't move
+ if (mouse_point_.x() >= 0 && mouse_point_.y() >= 0) // mouse is inside
+ mouse_modifiers_ = event->modifiers();
+ update();
+}
+
void ViewWidget::mouseMoveEvent(QMouseEvent *event)
{
assert(event);
mouse_point_ = event->pos();
+ mouse_modifiers_ = event->modifiers();
if (!event->buttons())
item_hover(get_mouse_over_item(event->pos()), event->pos());
void ViewWidget::leaveEvent(QEvent*)
{
mouse_point_ = QPoint(-1, -1);
+ mouse_modifiers_ = Qt::NoModifier;
+ item_hover(nullptr, QPoint());
update();
}
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+
void leaveEvent(QEvent *event);
public Q_SLOTS:
protected:
pv::views::trace::View &view_;
QPoint mouse_point_;
+ Qt::KeyboardModifiers mouse_modifiers_;
QPoint mouse_down_point_;
pv::util::Timestamp mouse_down_offset_;
shared_ptr<ViewItem> mouse_down_item_;