From: Soeren Apel Date: Mon, 27 Jan 2020 16:50:38 +0000 (+0100) Subject: Fix #1457 by adding markers, cursors and zero offset to session setup X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=e887fe9e6ede73b9fe9ace9c6bfd4f6a096eb3b2;p=pulseview.git Fix #1457 by adding markers, cursors and zero offset to session setup --- diff --git a/pv/globalsettings.cpp b/pv/globalsettings.cpp index 614b983c..10b344a4 100644 --- a/pv/globalsettings.cpp +++ b/pv/globalsettings.cpp @@ -17,8 +17,9 @@ * along with this program; if not, see . */ -#include "globalsettings.hpp" -#include "application.hpp" +#include +#include +#include #include #include @@ -30,9 +31,13 @@ #include #include +#include "globalsettings.hpp" +#include "application.hpp" + using std::map; using std::pair; using std::string; +using std::stringstream; using std::vector; namespace pv { @@ -370,4 +375,28 @@ Glib::VariantBase GlobalSettings::restore_variantbase(QSettings &settings) return ret_val; } +void GlobalSettings::store_timestamp(QSettings &settings, const char *name, const pv::util::Timestamp &ts) +{ + stringstream ss; + boost::archive::text_oarchive oa(ss); + oa << boost::serialization::make_nvp(name, ts); + settings.setValue(name, QString::fromStdString(ss.str())); +} + +pv::util::Timestamp GlobalSettings::restore_timestamp(QSettings &settings, const char *name) +{ + util::Timestamp result; + stringstream ss; + ss << settings.value(name).toString().toStdString(); + + try { + boost::archive::text_iarchive ia(ss); + ia >> boost::serialization::make_nvp(name, result); + } catch (boost::archive::archive_exception&) { + qDebug() << "Could not restore setting" << name; + } + + return result; +} + } // namespace pv diff --git a/pv/globalsettings.hpp b/pv/globalsettings.hpp index adb9168a..cf1921e8 100644 --- a/pv/globalsettings.hpp +++ b/pv/globalsettings.hpp @@ -30,6 +30,8 @@ #include #include +#include "util.hpp" + using std::map; using std::pair; using std::vector; @@ -122,13 +124,14 @@ public: void undo_tracked_changes(); static void store_gvariant(QSettings &settings, GVariant *v); - static GVariant* restore_gvariant(QSettings &settings); static void store_variantbase(QSettings &settings, Glib::VariantBase v); - static Glib::VariantBase restore_variantbase(QSettings &settings); + static void store_timestamp(QSettings &settings, const char *name, const pv::util::Timestamp &ts); + static pv::util::Timestamp restore_timestamp(QSettings &settings, const char *name); + private: static vector callbacks_; diff --git a/pv/session.cpp b/pv/session.cpp index 589ec333..b3f8ba87 100644 --- a/pv/session.cpp +++ b/pv/session.cpp @@ -17,9 +17,6 @@ * along with this program; if not, see . */ -#include -#include - #include #include #include @@ -27,9 +24,13 @@ #include +#include +#include + #include "devicemanager.hpp" #include "mainwindow.hpp" #include "session.hpp" +#include "util.hpp" #include "data/analog.hpp" #include "data/analogsegment.hpp" @@ -105,6 +106,7 @@ using Gst::ElementFactory; using Gst::Pipeline; #endif +using pv::util::Timestamp; using pv::views::trace::Signal; using pv::views::trace::AnalogSignal; using pv::views::trace::LogicSignal; @@ -193,13 +195,13 @@ bool Session::data_saved() const void Session::save_setup(QSettings &settings) const { - int decode_signals = 0, views = 0; + int i = 0; // Save channels and decoders for (const shared_ptr& base : signalbases_) { #ifdef ENABLE_DECODE if (base->is_decode_signal()) { - settings.beginGroup("decode_signal" + QString::number(decode_signals++)); + settings.beginGroup("decode_signal" + QString::number(i++)); base->save_settings(settings); settings.endGroup(); } else @@ -211,24 +213,54 @@ void Session::save_setup(QSettings &settings) const } } - settings.setValue("decode_signals", decode_signals); + settings.setValue("decode_signals", i); // Save view states and their signal settings // Note: main_view must be saved as view0 - settings.beginGroup("view" + QString::number(views++)); + i = 0; + settings.beginGroup("view" + QString::number(i++)); main_view_->save_settings(settings); settings.endGroup(); for (const shared_ptr& view : views_) { if (view != main_view_) { - settings.beginGroup("view" + QString::number(views++)); + settings.beginGroup("view" + QString::number(i++)); settings.setValue("type", view->get_type()); view->save_settings(settings); settings.endGroup(); } } - settings.setValue("views", views); + settings.setValue("views", i); + + i = 0; + shared_ptr tv = dynamic_pointer_cast(main_view_); + for (const shared_ptr& time_item : tv->time_items()) { + + const shared_ptr flag = + dynamic_pointer_cast(time_item); + if (flag) { + if (!flag->enabled()) + continue; + + settings.beginGroup("meta_obj" + QString::number(i++)); + settings.setValue("type", "time_marker"); + GlobalSettings::store_timestamp(settings, "time", flag->time()); + settings.setValue("text", flag->get_text()); + settings.endGroup(); + } + } + + if (tv->cursors_shown()) { + settings.beginGroup("meta_obj" + QString::number(i++)); + settings.setValue("type", "selection"); + const shared_ptr cp = tv->cursors(); + GlobalSettings::store_timestamp(settings, "start_time", cp->first()->time()); + GlobalSettings::store_timestamp(settings, "end_time", cp->second()->time()); + settings.endGroup(); + } + + settings.setValue("meta_objs", i); } void Session::save_settings(QSettings &settings) const @@ -324,13 +356,37 @@ void Session::restore_setup(QSettings &settings) settings.endGroup(); } + + // Restore meta objects like markers and cursors + int meta_objs = settings.value("meta_objs").toInt(); + + shared_ptr tv = dynamic_pointer_cast(main_view_); + for (int i = 0; i < meta_objs; i++) { + settings.beginGroup("meta_obj" + QString::number(i)); + const QString type = settings.value("type").toString(); + + if (type == "time_marker") { + Timestamp ts = GlobalSettings::restore_timestamp(settings, "time"); + shared_ptr flag = tv->add_flag(ts); + flag->set_text(settings.value("text").toString()); + } + + if (type == "selection") { + Timestamp start = GlobalSettings::restore_timestamp(settings, "start_time"); + Timestamp end = GlobalSettings::restore_timestamp(settings, "end_time"); + tv->set_cursors(start, end); + tv->show_cursors(); + } + + settings.endGroup(); + } } void Session::restore_settings(QSettings &settings) { shared_ptr device; - QString device_type = settings.value("device_type").toString(); + const QString device_type = settings.value("device_type").toString(); if (device_type == "hardware") { map dev_info; @@ -366,7 +422,7 @@ void Session::restore_settings(QSettings &settings) if ((device_type == "sessionfile") || (device_type == "inputfile")) { if (device_type == "sessionfile") { settings.beginGroup("device"); - QString filename = settings.value("filename").toString(); + const QString filename = settings.value("filename").toString(); settings.endGroup(); if (QFileInfo(filename).isReadable()) { diff --git a/pv/views/trace/flag.cpp b/pv/views/trace/flag.cpp index ea3cd609..b0518b64 100644 --- a/pv/views/trace/flag.cpp +++ b/pv/views/trace/flag.cpp @@ -73,6 +73,12 @@ QString Flag::get_text() const return s; } +void Flag::set_text(const QString &text) +{ + text_ = text; + view_.time_item_appearance_changed(true, false); +} + QRectF Flag::label_rect(const QRectF &rect) const { QRectF r; @@ -158,8 +164,7 @@ void Flag::on_delete() void Flag::on_text_changed(const QString &text) { - text_ = text; - view_.time_item_appearance_changed(true, false); + set_text(text); } } // namespace trace diff --git a/pv/views/trace/flag.hpp b/pv/views/trace/flag.hpp index 5edf90b0..e58771b8 100644 --- a/pv/views/trace/flag.hpp +++ b/pv/views/trace/flag.hpp @@ -67,6 +67,11 @@ public: */ virtual QString get_text() const override; + /** + * Sets the text to show in the marker. + */ + virtual void set_text(const QString &text) override; + virtual pv::widgets::Popup* create_popup(QWidget *parent) override; virtual QMenu* create_header_context_menu(QWidget *parent) override; diff --git a/pv/views/trace/ruler.cpp b/pv/views/trace/ruler.cpp index bebf5291..555794fc 100644 --- a/pv/views/trace/ruler.cpp +++ b/pv/views/trace/ruler.cpp @@ -158,6 +158,12 @@ void Ruler::contextMenuEvent(QContextMenuEvent *event) connect(set_zero_position, SIGNAL(triggered()), this, SLOT(on_setZeroPosition())); menu->addAction(set_zero_position); + if (view_.zero_offset().convert_to() != 0) { + QAction *const reset_zero_position = new QAction(tr("Reset zero point"), this); + connect(reset_zero_position, SIGNAL(triggered()), this, SLOT(on_resetZeroPosition())); + menu->addAction(reset_zero_position); + } + QAction *const toggle_hover_marker = new QAction(this); connect(toggle_hover_marker, SIGNAL(triggered()), this, SLOT(on_toggleHoverMarker())); menu->addAction(toggle_hover_marker); @@ -397,6 +403,11 @@ void Ruler::on_setZeroPosition() view_.set_zero_position(get_absolute_time_from_x_pos(mouse_down_point_.x())); } +void Ruler::on_resetZeroPosition() +{ + view_.reset_zero_position(); +} + void Ruler::on_toggleHoverMarker() { GlobalSettings settings; diff --git a/pv/views/trace/ruler.hpp b/pv/views/trace/ruler.hpp index 18a09d9b..9d708ce0 100644 --- a/pv/views/trace/ruler.hpp +++ b/pv/views/trace/ruler.hpp @@ -184,6 +184,7 @@ private Q_SLOTS: void on_createMarker(); void on_setZeroPosition(); + void on_resetZeroPosition(); void on_toggleHoverMarker(); private: diff --git a/pv/views/trace/timemarker.cpp b/pv/views/trace/timemarker.cpp index 9cb33a76..b428f602 100644 --- a/pv/views/trace/timemarker.cpp +++ b/pv/views/trace/timemarker.cpp @@ -105,6 +105,11 @@ QRectF TimeMarker::hit_box_rect(const ViewItemPaintParams &pp) const return QRectF(x - h / 2.0f, pp.top(), h, pp.height()); } +void TimeMarker::set_text(const QString &text) +{ + (void)text; +} + void TimeMarker::paint_label(QPainter &p, const QRect &rect, bool hover) { if (!enabled()) diff --git a/pv/views/trace/timemarker.hpp b/pv/views/trace/timemarker.hpp index 99c56d34..cd7c84d2 100644 --- a/pv/views/trace/timemarker.hpp +++ b/pv/views/trace/timemarker.hpp @@ -99,6 +99,11 @@ public: */ virtual QString get_text() const = 0; + /** + * Sets the text to show in the marker. + */ + virtual void set_text(const QString &text); + /** * Paints the marker's label to the ruler. * @param p The painter to draw with. diff --git a/pv/views/trace/view.cpp b/pv/views/trace/view.cpp index 15e65127..40ecc195 100644 --- a/pv/views/trace/view.cpp +++ b/pv/views/trace/view.cpp @@ -31,11 +31,8 @@ #include #include -#include -#include -#include - #include +#include #include #include #include @@ -84,7 +81,6 @@ using std::pair; using std::set; using std::set_difference; using std::shared_ptr; -using std::stringstream; using std::unordered_map; using std::unordered_set; using std::vector; @@ -276,6 +272,8 @@ void View::reset_view_state() scale_ = 1e-3; offset_ = 0; ruler_offset_ = 0; + zero_offset_ = 0; + custom_zero_offset_set_ = false; updating_scroll_ = false; settings_restored_ = false; always_zoom_to_fit_ = false; @@ -432,12 +430,12 @@ void View::save_settings(QSettings &settings) const settings.setValue("splitter_state", splitter_->saveState()); settings.setValue("segment_display_mode", segment_display_mode_); - { - stringstream ss; - boost::archive::text_oarchive oa(ss); - oa << boost::serialization::make_nvp("offset", offset_); - settings.setValue("offset", QString::fromStdString(ss.str())); - } + GlobalSettings::store_timestamp(settings, "offset", offset_); + + if (custom_zero_offset_set_) + GlobalSettings::store_timestamp(settings, "zero_offset", -zero_offset_); + else + settings.remove("zero_offset"); for (const shared_ptr& signal : signals_) { settings.beginGroup(signal->base()->internal_name()); @@ -455,20 +453,13 @@ void View::restore_settings(QSettings &settings) set_scale(settings.value("scale").toDouble()); if (settings.contains("offset")) { - util::Timestamp offset; - stringstream ss; - ss << settings.value("offset").toString().toStdString(); - - try { - boost::archive::text_iarchive ia(ss); - ia >> boost::serialization::make_nvp("offset", offset); - // This also updates ruler_offset_ - set_offset(offset); - } catch (boost::archive::archive_exception&) { - qDebug() << "Could not restore the view offset"; - } + // This also updates ruler_offset_ + set_offset(GlobalSettings::restore_timestamp(settings, "offset")); } + if (settings.contains("zero_offset")) + set_zero_position(GlobalSettings::restore_timestamp(settings, "zero_offset")); + if (settings.contains("splitter_state")) splitter_->restoreState(settings.value("splitter_state").toByteArray()); @@ -548,6 +539,7 @@ const Timestamp& View::ruler_offset() const void View::set_zero_position(const pv::util::Timestamp& position) { zero_offset_ = -position; + custom_zero_offset_set_ = true; // Force an immediate update of the offsets set_offset(offset_, true); @@ -558,6 +550,19 @@ void View::reset_zero_position() { zero_offset_ = 0; + // When enabled, the first trigger for this segment is used as the zero position + GlobalSettings settings; + bool trigger_is_zero_time = settings.value(GlobalSettings::Key_View_TriggerIsZeroTime).toBool(); + + if (trigger_is_zero_time) { + vector triggers = session_.get_triggers(current_segment_); + + if (triggers.size() > 0) + zero_offset_ = triggers.front(); + } + + custom_zero_offset_set_ = false; + // Force an immediate update of the offsets set_offset(offset_, true); ruler_->update(); @@ -676,12 +681,8 @@ void View::set_current_segment(uint32_t segment_id) for (util::Timestamp timestamp : triggers) trigger_markers_.push_back(make_shared(*this, timestamp)); - // When enabled, the first trigger for this segment is used as the zero position - GlobalSettings settings; - bool trigger_is_zero_time = settings.value(GlobalSettings::Key_View_TriggerIsZeroTime).toBool(); - - if (trigger_is_zero_time && (triggers.size() > 0)) - set_zero_position(triggers.front()); + if (!custom_zero_offset_set_) + reset_zero_position(); viewport_->update(); @@ -1088,15 +1089,8 @@ void View::trigger_event(int segment_id, util::Timestamp location) if ((uint32_t)segment_id != current_segment_) return; - // Set zero location if the Key_View_TriggerIsZeroTime setting is set and - // if this is the first trigger for this segment. - GlobalSettings settings; - bool trigger_is_zero_time = settings.value(GlobalSettings::Key_View_TriggerIsZeroTime).toBool(); - - size_t trigger_count = session_.get_triggers(current_segment_).size(); - - if (trigger_is_zero_time && trigger_count == 1) - set_zero_position(location); + if (!custom_zero_offset_set_) + reset_zero_position(); trigger_markers_.push_back(make_shared(*this, location)); } @@ -1831,7 +1825,8 @@ void View::capture_state_updated(int state) set_time_unit(util::TimeUnit::Samples); trigger_markers_.clear(); - set_zero_position(0); + if (!custom_zero_offset_set_) + set_zero_position(0); scale_at_acq_start_ = scale_; offset_at_acq_start_ = offset_; @@ -1914,12 +1909,7 @@ void View::on_segment_changed(int segment) void View::on_settingViewTriggerIsZeroTime_changed(const QVariant new_value) { - if (new_value.toBool()) { - // The first trigger for this segment is used as the zero position - vector triggers = session_.get_triggers(current_segment_); - if (triggers.size() > 0) - set_zero_position(triggers.front()); - } else + if (!custom_zero_offset_set_) reset_zero_position(); } diff --git a/pv/views/trace/view.hpp b/pv/views/trace/view.hpp index 2938d00f..c2cceb27 100644 --- a/pv/views/trace/view.hpp +++ b/pv/views/trace/view.hpp @@ -530,6 +530,8 @@ private: pv::util::Timestamp ruler_offset_; /// The offset of the zero point in seconds. pv::util::Timestamp zero_offset_; + /// Shows whether the user set a custom zero offset that we should keep + bool custom_zero_offset_set_; bool updating_scroll_; bool settings_restored_;