]> sigrok.org Git - pulseview.git/blobdiff - pv/views/trace/logicsignal.cpp
Session: Fix issue #67 by improving error handling
[pulseview.git] / pv / views / trace / logicsignal.cpp
index a5d0a5987774436e178b0e3f250ce46633538d7d..732d46d2d9e82e86e933a71b6c41760951ae4227 100644 (file)
@@ -70,19 +70,6 @@ const QColor LogicSignal::HighColor(0x00, 0xC0, 0x00);
 const QColor LogicSignal::LowColor(0xC0, 0x00, 0x00);
 const QColor LogicSignal::SamplingPointColor(0x77, 0x77, 0x77);
 
-const QColor LogicSignal::SignalColors[10] = {
-       QColor(0x16, 0x19, 0x1A),       // Black
-       QColor(0x8F, 0x52, 0x02),       // Brown
-       QColor(0xCC, 0x00, 0x00),       // Red
-       QColor(0xF5, 0x79, 0x00),       // Orange
-       QColor(0xED, 0xD4, 0x00),       // Yellow
-       QColor(0x73, 0xD2, 0x16),       // Green
-       QColor(0x34, 0x65, 0xA4),       // Blue
-       QColor(0x75, 0x50, 0x7B),       // Violet
-       QColor(0x88, 0x8A, 0x85),       // Grey
-       QColor(0xEE, 0xEE, 0xEC),       // White
-};
-
 QColor LogicSignal::TriggerMarkerBackgroundColor = QColor(0xED, 0xD4, 0x00);
 const int LogicSignal::TriggerMarkerPadding = 2;
 const char* LogicSignal::TriggerMarkerIcons[8] = {
@@ -99,12 +86,8 @@ const char* LogicSignal::TriggerMarkerIcons[8] = {
 QCache<QString, const QIcon> LogicSignal::icon_cache_;
 QCache<QString, const QPixmap> LogicSignal::pixmap_cache_;
 
-LogicSignal::LogicSignal(
-       pv::Session &session,
-       shared_ptr<devices::Device> device,
-       shared_ptr<data::SignalBase> base) :
+LogicSignal::LogicSignal(pv::Session &session, shared_ptr<data::SignalBase> base) :
        Signal(session, base),
-       device_(device),
        trigger_types_(get_trigger_types()),
        trigger_none_(nullptr),
        trigger_rising_(nullptr),
@@ -113,45 +96,46 @@ LogicSignal::LogicSignal(
        trigger_low_(nullptr),
        trigger_change_(nullptr)
 {
-       shared_ptr<Trigger> trigger;
-
-       base_->set_color(SignalColors[base->index() % countof(SignalColors)]);
+       GlobalSettings settings;
+       signal_height_ = settings.value(GlobalSettings::Key_View_DefaultLogicHeight).toInt();
+       show_sampling_points_ =
+               settings.value(GlobalSettings::Key_View_ShowSamplingPoints).toBool();
+       fill_high_areas_ =
+               settings.value(GlobalSettings::Key_View_FillSignalHighAreas).toBool();
+       high_fill_color_ = QColor::fromRgba(settings.value(
+               GlobalSettings::Key_View_FillSignalHighAreaColor).value<uint32_t>());
 
-       GlobalSettings gs;
-       signal_height_ = gs.value(GlobalSettings::Key_View_DefaultLogicHeight).toInt();
+       update_logic_level_offsets();
 
        /* Populate this channel's trigger setting with whatever we
         * find in the current session trigger, if anything. */
        trigger_match_ = nullptr;
-       if ((trigger = session_.session()->trigger()))
+       if (shared_ptr<Trigger> trigger = session_.session()->trigger())
                for (auto stage : trigger->stages())
                        for (auto match : stage->matches())
                                if (match->channel() == base_->channel())
                                        trigger_match_ = match->type();
 }
 
-shared_ptr<pv::data::SignalData> LogicSignal::data() const
+std::map<QString, QVariant> LogicSignal::save_settings() const
 {
-       return base_->logic_data();
-}
+       std::map<QString, QVariant> result;
 
-shared_ptr<pv::data::Logic> LogicSignal::logic_data() const
-{
-       return base_->logic_data();
-}
+       result["trace_height"] = signal_height_;
 
-void LogicSignal::save_settings(QSettings &settings) const
-{
-       settings.setValue("trace_height", signal_height_);
+       return result;
 }
 
-void LogicSignal::restore_settings(QSettings &settings)
+void LogicSignal::restore_settings(std::map<QString, QVariant> settings)
 {
-       if (settings.contains("trace_height")) {
+       auto entry = settings.find("trace_height");
+       if (entry != settings.end()) {
                const int old_height = signal_height_;
-               signal_height_ = settings.value("trace_height").toInt();
+               signal_height_ = settings["trace_height"].toInt();
 
                if ((signal_height_ != old_height) && owner_) {
+                       update_logic_level_offsets();
+
                        // Call order is important, otherwise the lazy event handler won't work
                        owner_->extents_changed(false, true);
                        owner_->row_item_appearance_changed(false, true);
@@ -180,8 +164,9 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
        if (!base_->enabled())
                return;
 
-       const float low_offset = y + 0.5f;
-       const float high_offset = low_offset - signal_height_;
+       const float low_offset = y + low_level_offset_;
+       const float high_offset = y + high_level_offset_;
+       const float fill_height = low_offset - high_offset;
 
        shared_ptr<LogicSegment> segment = get_logic_segment_to_paint();
        if (!segment || (segment->get_sample_count() == 0))
@@ -207,7 +192,7 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                (int64_t)0), last_sample);
 
        segment->get_subsampled_edges(edges, start_sample, end_sample,
-               samples_per_pixel / Oversampling, base_->index());
+               samples_per_pixel / Oversampling, base_->logic_bit_index());
        assert(edges.size() >= 2);
 
        const float first_sample_x =
@@ -216,11 +201,7 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                pp.left() + (edges.back().first / samples_per_pixel - pixels_offset);
 
        // Check whether we need to paint the sampling points
-       GlobalSettings settings;
-       const bool show_sampling_points =
-               settings.value(GlobalSettings::Key_View_ShowSamplingPoints).toBool() &&
-               (samples_per_pixel < 0.25);
-
+       const bool show_sampling_points = show_sampling_points_ && (samples_per_pixel < 0.25);
        vector<QRectF> sampling_points;
        float sampling_point_x = first_sample_x;
        int64_t sampling_point_sample = start_sample;
@@ -229,9 +210,6 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
        if (show_sampling_points)
                sampling_points.reserve(end_sample - start_sample + 1);
 
-       // Check whether we need to fill the high areas
-       const bool fill_high_areas =
-               settings.value(GlobalSettings::Key_View_FillSignalHighAreas).toBool();
        vector<QRectF> high_rects;
        float rising_edge_x;
        bool rising_edge_seen = false;
@@ -256,13 +234,12 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                const float x = pp.left() + ((*i).first / samples_per_pixel - pixels_offset);
                *line++ = QLineF(x, high_offset, x, low_offset);
 
-               if (fill_high_areas) {
+               if (fill_high_areas_) {
                        // Any edge terminates a high area
                        if (rising_edge_seen) {
                                const int width = x - rising_edge_x;
                                if (width > 0)
-                                       high_rects.emplace_back(rising_edge_x, high_offset,
-                                               width, signal_height_);
+                                       high_rects.emplace_back(rising_edge_x, high_offset, width, fill_height);
                                rising_edge_seen = false;
                        }
 
@@ -294,16 +271,14 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                        sampling_point_x += pixels_per_sample;
                };
 
-       if (fill_high_areas) {
+       if (fill_high_areas_) {
                // Add last high rectangle if the signal is still high at the end of the trace
                if (rising_edge_seen && (edges.cend() - 1)->second)
                        high_rects.emplace_back(rising_edge_x, high_offset,
                                last_sample_x - rising_edge_x, signal_height_);
 
-               const QColor fill_color = QColor::fromRgba(settings.value(
-                       GlobalSettings::Key_View_FillSignalHighAreaColor).value<uint32_t>());
-               p.setPen(fill_color);
-               p.setBrush(fill_color);
+               p.setPen(high_fill_color_);
+               p.setBrush(high_fill_color_);
                p.drawRects((const QRectF*)(high_rects.data()), high_rects.size());
        }
 
@@ -426,12 +401,11 @@ shared_ptr<pv::data::LogicSegment> LogicSignal::get_logic_segment_to_paint() con
                base_->logic_data()->logic_segments();
 
        if (!segments.empty()) {
-               if (segment_display_mode_ == ShowLastSegmentOnly) {
+               if (segment_display_mode_ == ShowLastSegmentOnly)
                        segment = segments.back();
-               }
 
-       if ((segment_display_mode_ == ShowSingleSegmentOnly) ||
-               (segment_display_mode_ == ShowLastCompleteSegmentOnly)) {
+               if ((segment_display_mode_ == ShowSingleSegmentOnly) ||
+                       (segment_display_mode_ == ShowLastCompleteSegmentOnly)) {
                        try {
                                segment = segments.at(current_segment_);
                        } catch (out_of_range&) {
@@ -479,10 +453,10 @@ void LogicSignal::init_trigger_actions(QWidget *parent)
 const vector<int32_t> LogicSignal::get_trigger_types() const
 {
        // We may not be associated with a device
-       if (!device_)
+       if (!session_.device())
                return vector<int32_t>();
 
-       const auto sr_dev = device_->device();
+       const auto sr_dev = session_.device()->device();
        if (sr_dev->config_check(ConfigKey::TRIGGER_MATCH, Capability::LIST)) {
                const Glib::VariantContainerBase gvar =
                        sr_dev->config_list(ConfigKey::TRIGGER_MATCH);
@@ -583,7 +557,7 @@ void LogicSignal::populate_popup_form(QWidget *parent, QFormLayout *form)
 
                // Only allow triggers to be changed when we're stopped
                if (session_.get_capture_state() != Session::Stopped)
-                       for (QAction* action : trigger_bar_->findChildren<QAction*>())
+                       for (QAction* action : trigger_bar_->findChildren<QAction*>())  // clazy:exclude=range-loop
                                action->setEnabled(false);
 
                form->addRow(tr("Trigger"), trigger_bar_);
@@ -650,6 +624,26 @@ const QPixmap* LogicSignal::get_pixmap(const char *path)
        return pixmap_cache_.take(path);
 }
 
+void LogicSignal::update_logic_level_offsets()
+{
+       low_level_offset_ = 0.5f;
+       high_level_offset_ = low_level_offset_ - signal_height_;
+}
+
+void LogicSignal::on_setting_changed(const QString &key, const QVariant &value)
+{
+       Signal::on_setting_changed(key, value);
+
+       if (key == GlobalSettings::Key_View_ShowSamplingPoints)
+               show_sampling_points_ = value.toBool();
+
+       if (key == GlobalSettings::Key_View_FillSignalHighAreas)
+               fill_high_areas_ = value.toBool();
+
+       if (key == GlobalSettings::Key_View_FillSignalHighAreaColor)
+               high_fill_color_ = QColor::fromRgba(value.value<uint32_t>());
+}
+
 void LogicSignal::on_trigger()
 {
        QAction *action;
@@ -668,6 +662,8 @@ void LogicSignal::on_signal_height_changed(int height)
        signal_height_ = height;
 
        if (owner_) {
+               update_logic_level_offsets();
+
                // Call order is important, otherwise the lazy event handler won't work
                owner_->extents_changed(false, true);
                owner_->row_item_appearance_changed(false, true);