]> sigrok.org Git - pulseview.git/commitdiff
Implement "fill logic signal high areas" feature
authorSoeren Apel <redacted>
Sat, 13 Oct 2018 19:13:24 +0000 (21:13 +0200)
committerSoeren Apel <redacted>
Sat, 13 Oct 2018 19:49:17 +0000 (21:49 +0200)
pv/dialogs/settings.cpp
pv/dialogs/settings.hpp
pv/globalsettings.cpp
pv/globalsettings.hpp
pv/views/trace/analogsignal.cpp
pv/views/trace/logicsignal.cpp
pv/widgets/colorbutton.cpp
pv/widgets/colorbutton.hpp

index bc6688c22a40dafb7f9a86c903516b524de44fb3..ad4fd4a5f6c31519175e3877457179bd8c9340d9 100644 (file)
@@ -46,6 +46,7 @@
 #include "pv/devicemanager.hpp"
 #include "pv/globalsettings.hpp"
 #include "pv/logging.hpp"
+#include "pv/widgets/colorbutton.hpp"
 
 #include <libsigrokcxx/libsigrokcxx.hpp>
 
@@ -54,6 +55,7 @@
 #endif
 
 using std::shared_ptr;
+using pv::widgets::ColorButton;
 
 namespace pv {
 namespace dialogs {
@@ -229,6 +231,17 @@ QWidget *Settings::get_view_settings_form(QWidget *parent) const
                SLOT(on_view_showSamplingPoints_changed(int)));
        trace_view_layout->addRow(tr("Show data &sampling points"), cb);
 
+       cb = create_checkbox(GlobalSettings::Key_View_FillSignalHighAreas,
+               SLOT(on_view_fillSignalHighAreas_changed(int)));
+       trace_view_layout->addRow(tr("Fill high areas of logic signals"), cb);
+
+       ColorButton* high_fill_cb = new ColorButton(parent);
+       high_fill_cb->set_color(QColor::fromRgba(
+               settings.value(GlobalSettings::Key_View_FillSignalHighAreaColor).value<uint32_t>()));
+       connect(high_fill_cb, SIGNAL(selected(QColor)),
+               this, SLOT(on_view_fillSignalHighAreaColor_changed(QColor)));
+       trace_view_layout->addRow(tr("Fill high areas of logic signals"), high_fill_cb);
+
        cb = create_checkbox(GlobalSettings::Key_View_ShowAnalogMinorGrid,
                SLOT(on_view_showAnalogMinorGrid_changed(int)));
        trace_view_layout->addRow(tr("Show analog minor grid in addition to div grid"), cb);
@@ -530,6 +543,18 @@ void Settings::on_view_showSamplingPoints_changed(int state)
        settings.setValue(GlobalSettings::Key_View_ShowSamplingPoints, state ? true : false);
 }
 
+void Settings::on_view_fillSignalHighAreas_changed(int state)
+{
+       GlobalSettings settings;
+       settings.setValue(GlobalSettings::Key_View_FillSignalHighAreas, state ? true : false);
+}
+
+void Settings::on_view_fillSignalHighAreaColor_changed(QColor color)
+{
+       GlobalSettings settings;
+       settings.setValue(GlobalSettings::Key_View_FillSignalHighAreaColor, color.rgba());
+}
+
 void Settings::on_view_showAnalogMinorGrid_changed(int state)
 {
        GlobalSettings settings;
index f68b31dd69cbff058079224dcae6e7de084fabdc..f5efe35342b5e35ac82fb0786d66b4328b64b97a 100644 (file)
@@ -21,6 +21,7 @@
 #define PULSEVIEW_PV_SETTINGS_HPP
 
 #include <QCheckBox>
+#include <QColor>
 #include <QDialog>
 #include <QListWidget>
 #include <QPlainTextEdit>
@@ -62,6 +63,8 @@ private Q_SLOTS:
        void on_view_coloredBG_changed(int state);
        void on_view_stickyScrolling_changed(int state);
        void on_view_showSamplingPoints_changed(int state);
+       void on_view_fillSignalHighAreas_changed(int state);
+       void on_view_fillSignalHighAreaColor_changed(QColor color);
        void on_view_showAnalogMinorGrid_changed(int state);
        void on_view_showHoverMarker_changed(int state);
        void on_view_snapDistance_changed(int value);
index df44162fe3372de01f626e731b928c086eebaae3..b8f4462c254375654bfbc01e512faaf8835cb77e 100644 (file)
@@ -20,6 +20,7 @@
 #include "globalsettings.hpp"
 
 #include <QApplication>
+#include <QColor>
 #include <QDebug>
 #include <QFontMetrics>
 #include <QString>
@@ -36,6 +37,8 @@ const QString GlobalSettings::Key_View_TriggerIsZeroTime = "View_TriggerIsZeroTi
 const QString GlobalSettings::Key_View_ColoredBG = "View_ColoredBG";
 const QString GlobalSettings::Key_View_StickyScrolling = "View_StickyScrolling";
 const QString GlobalSettings::Key_View_ShowSamplingPoints = "View_ShowSamplingPoints";
+const QString GlobalSettings::Key_View_FillSignalHighAreas = "View_FillSignalHighAreas";
+const QString GlobalSettings::Key_View_FillSignalHighAreaColor = "View_FillSignalHighAreaColor";
 const QString GlobalSettings::Key_View_ShowAnalogMinorGrid = "View_ShowAnalogMinorGrid";
 const QString GlobalSettings::Key_View_ConversionThresholdDispMode = "View_ConversionThresholdDispMode";
 const QString GlobalSettings::Key_View_DefaultDivHeight = "View_DefaultDivHeight";
@@ -71,6 +74,13 @@ void GlobalSettings::set_defaults_where_needed()
        if (!contains(Key_View_ShowSamplingPoints))
                setValue(Key_View_ShowSamplingPoints, true);
 
+       // Enable filling logic signal high areas by default
+       if (!contains(Key_View_FillSignalHighAreas))
+               setValue(Key_View_FillSignalHighAreas, true);
+       if (!contains(Key_View_FillSignalHighAreaColor))
+               setValue(Key_View_FillSignalHighAreaColor,
+                       QColor(0, 0, 0, 5 * 256 / 100).rgba());
+
        if (!contains(Key_View_DefaultDivHeight))
                setValue(Key_View_DefaultDivHeight,
                3 * QFontMetrics(QApplication::font()).height());
index 4f07955adb35200d9130f654f71894744cfacd54..6e027d782c97dd3e4a449e72282fa8c2ad55e646 100644 (file)
@@ -52,6 +52,8 @@ public:
        static const QString Key_View_ColoredBG;
        static const QString Key_View_StickyScrolling;
        static const QString Key_View_ShowSamplingPoints;
+       static const QString Key_View_FillSignalHighAreas;
+       static const QString Key_View_FillSignalHighAreaColor;
        static const QString Key_View_ShowAnalogMinorGrid;
        static const QString Key_View_ConversionThresholdDispMode;
        static const QString Key_View_DefaultDivHeight;
index 0419b03b698eb208496e15b75957c2eb8b6d9663..be0abbf183aa78d30cd3748a8f578a0e5a06b5d4 100644 (file)
@@ -537,6 +537,7 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
        const int nh = min(neg_vdivs_, 1) * div_height_;
        const float high_offset = y - ph + signal_margin + 0.5f;
        const float low_offset = y + nh - signal_margin - 0.5f;
+       const float signal_height = low_offset - high_offset;
 
        shared_ptr<pv::data::LogicSegment> segment = get_logic_segment_to_paint();
        if (!segment || (segment->get_sample_count() == 0))
@@ -565,6 +566,11 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
                samples_per_pixel / LogicSignal::Oversampling, 0);
        assert(edges.size() >= 2);
 
+       const float first_sample_x =
+               pp.left() + (edges.front().first / samples_per_pixel - pixels_offset);
+       const float last_sample_x =
+               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 =
@@ -572,14 +578,18 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
                (samples_per_pixel < 0.25);
 
        vector<QRectF> sampling_points;
-       float sampling_point_x = 0.0f;
+       float sampling_point_x = first_sample_x;
        int64_t sampling_point_sample = start_sample;
        const int w = 2;
 
-       if (show_sampling_points) {
+       if (show_sampling_points)
                sampling_points.reserve(end_sample - start_sample + 1);
-               sampling_point_x = (edges.cbegin()->first / samples_per_pixel - pixels_offset) + pp.left();
-       }
+
+       // Check whether we need to fill the high areas
+       const bool fill_high_areas =
+               settings.value(GlobalSettings::Key_View_FillSignalHighAreas).toBool();
+       float high_start_x;
+       vector<QRectF> high_rects;
 
        // Paint the edges
        const unsigned int edge_count = edges.size() - 2;
@@ -591,6 +601,14 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
                        pixels_offset) + pp.left();
                *line++ = QLineF(x, high_offset, x, low_offset);
 
+               if (fill_high_areas) {
+                       if ((*i).second)
+                               high_start_x = x;
+                       else
+                               high_rects.emplace_back(high_start_x, high_offset,
+                                       x - high_start_x, signal_height);
+               }
+
                if (show_sampling_points)
                        while (sampling_point_sample < (*i).first) {
                                const float y = (*i).second ? low_offset : high_offset;
@@ -612,6 +630,19 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
                        sampling_point_x += pixels_per_sample;
                };
 
+       if (fill_high_areas) {
+               // Add last high rectangle if the signal is still high at the end of the view
+               if ((edges.cend() - 1)->second)
+                       high_rects.emplace_back(high_start_x, high_offset,
+                               last_sample_x - high_start_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.drawRects((const QRectF*)(high_rects.data()), high_rects.size());
+       }
+
        p.setPen(LogicSignal::EdgeColor);
        p.drawLines(edge_lines, edge_count);
        delete[] edge_lines;
index 6a9bf432a07157c2a2e7713e60dbd7972c8abd8f..8d2e1384526700098b33c37e6835aa44a1277344 100644 (file)
@@ -180,8 +180,8 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
        if (!base_->enabled())
                return;
 
-       const float high_offset = y - signal_height_ + 0.5f;
        const float low_offset = y + 0.5f;
+       const float high_offset = low_offset - signal_height_;
 
        shared_ptr<LogicSegment> segment = get_logic_segment_to_paint();
        if (!segment || (segment->get_sample_count() == 0))
@@ -210,6 +210,11 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                samples_per_pixel / Oversampling, base_->index());
        assert(edges.size() >= 2);
 
+       const float first_sample_x =
+               pp.left() + (edges.front().first / samples_per_pixel - pixels_offset);
+       const float last_sample_x =
+               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 =
@@ -217,25 +222,40 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                (samples_per_pixel < 0.25);
 
        vector<QRectF> sampling_points;
-       float sampling_point_x = 0.0f;
+       float sampling_point_x = first_sample_x;
        int64_t sampling_point_sample = start_sample;
        const int w = 2;
 
-       if (show_sampling_points) {
+       if (show_sampling_points)
                sampling_points.reserve(end_sample - start_sample + 1);
-               sampling_point_x = (edges.cbegin()->first / samples_per_pixel - pixels_offset) + pp.left();
-       }
+
+       // Check whether we need to fill the high areas
+       const bool fill_high_areas =
+               settings.value(GlobalSettings::Key_View_FillSignalHighAreas).toBool();
+       float high_start_x;
+       vector<QRectF> high_rects;
 
        // Paint the edges
        const unsigned int edge_count = edges.size() - 2;
        QLineF *const edge_lines = new QLineF[edge_count];
        line = edge_lines;
 
+       if (edges.front().second)
+               high_start_x = first_sample_x;  // Beginning of signal is high
+
        for (auto i = edges.cbegin() + 1; i != edges.cend() - 1; i++) {
                const float x = ((*i).first / samples_per_pixel -
                        pixels_offset) + pp.left();
                *line++ = QLineF(x, high_offset, x, low_offset);
 
+               if (fill_high_areas) {
+                       if ((*i).second)
+                               high_start_x = x;
+                       else
+                               high_rects.emplace_back(high_start_x, high_offset,
+                                       x - high_start_x, signal_height_);
+               }
+
                if (show_sampling_points)
                        while (sampling_point_sample < (*i).first) {
                                const float y = (*i).second ? low_offset : high_offset;
@@ -257,6 +277,19 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
                        sampling_point_x += pixels_per_sample;
                };
 
+       if (fill_high_areas) {
+               // Add last high rectangle if the signal is still high at the end of the view
+               if ((edges.cend() - 1)->second)
+                       high_rects.emplace_back(high_start_x, high_offset,
+                               last_sample_x - high_start_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.drawRects((const QRectF*)(high_rects.data()), high_rects.size());
+       }
+
        p.setPen(EdgeColor);
        p.drawLines(edge_lines, edge_count);
        delete[] edge_lines;
index c9230d9d6e350262874bdce9eba8dcd5b3c1c8ac..702fddeb92541eaf0b4c8b00657901c45d73b811 100644 (file)
@@ -22,6 +22,7 @@
 #include <cassert>
 
 #include <QApplication>
+#include <QColorDialog>
 #include <QPainter>
 
 namespace pv {
@@ -29,16 +30,23 @@ namespace widgets {
 
 const int ColorButton::SwatchMargin = 7;
 
+ColorButton::ColorButton(QWidget *parent) :
+       QPushButton("", parent),
+       popup_(nullptr)
+{
+       connect(this, SIGNAL(clicked(bool)), this, SLOT(on_clicked(bool)));
+}
+
 ColorButton::ColorButton(int rows, int cols, QWidget *parent) :
        QPushButton("", parent),
-       popup_(rows, cols, this)
+       popup_(new ColorPopup(rows, cols, this))
 {
        connect(this, SIGNAL(clicked(bool)), this, SLOT(on_clicked(bool)));
-       connect(&popup_, SIGNAL(selected(int, int)),
+       connect(popup_, SIGNAL(selected(int, int)),
                this, SLOT(on_selected(int, int)));
 }
 
-ColorPopup& ColorButton::popup()
+ColorPopup* ColorButton::popup()
 {
        return popup_;
 }
@@ -52,40 +60,60 @@ void ColorButton::set_color(QColor color)
 {
        cur_color_ = color;
 
-       const unsigned int rows = popup_.well_array().numRows();
-       const unsigned int cols = popup_.well_array().numCols();
-
-       for (unsigned int r = 0; r < rows; r++)
-               for (unsigned int c = 0; c < cols; c++)
-                       if (popup_.well_array().cellBrush(r, c).color() == color) {
-                               popup_.well_array().setSelected(r, c);
-                               popup_.well_array().setCurrent(r, c);
-                               return;
-                       }
+       if (popup_) {
+               const unsigned int rows = popup_->well_array().numRows();
+               const unsigned int cols = popup_->well_array().numCols();
+
+               for (unsigned int r = 0; r < rows; r++)
+                       for (unsigned int c = 0; c < cols; c++)
+                               if (popup_->well_array().cellBrush(r, c).color() == color) {
+                                       popup_->well_array().setSelected(r, c);
+                                       popup_->well_array().setCurrent(r, c);
+                                       return;
+                               }
+       }
 }
 
 void ColorButton::set_palette(const QColor *const palette)
 {
        assert(palette);
+       assert(popup_);
 
-       const unsigned int rows = popup_.well_array().numRows();
-       const unsigned int cols = popup_.well_array().numCols();
+       const unsigned int rows = popup_->well_array().numRows();
+       const unsigned int cols = popup_->well_array().numCols();
 
        for (unsigned int r = 0; r < rows; r++)
                for (unsigned int c = 0; c < cols; c++)
-                       popup_.well_array().setCellBrush(r, c,
-                               QBrush(palette[r * cols + c]));
+                       popup_->well_array().setCellBrush(r, c, QBrush(palette[r * cols + c]));
 }
 
 void ColorButton::on_clicked(bool)
 {
-       popup_.set_position(mapToGlobal(rect().center()), Popup::Bottom);
-       popup_.show();
+       if (popup_) {
+               popup_->set_position(mapToGlobal(rect().center()), Popup::Bottom);
+               popup_->show();
+       } else {
+               QColorDialog dlg(this);
+               dlg.setOption(QColorDialog::ShowAlphaChannel);
+               dlg.setOption(QColorDialog::DontUseNativeDialog);
+               connect(&dlg, SIGNAL(colorSelected(const QColor)),
+                       this, SLOT(on_color_selected(const QColor)));
+               dlg.setCurrentColor(cur_color_);
+               dlg.exec();
+       }
 }
 
 void ColorButton::on_selected(int row, int col)
 {
-       cur_color_ = popup_.well_array().cellBrush(row, col).color();
+       assert(popup_);
+
+       cur_color_ = popup_->well_array().cellBrush(row, col).color();
+       selected(cur_color_);
+}
+
+void ColorButton::on_color_selected(const QColor& color)
+{
+       cur_color_ = color;
        selected(cur_color_);
 }
 
index 37cd6e73f0dd9fbdc98bc0c8aa75add8c91dfe85..4726c1bb41bf566384298a3e13af973a2ae5806d 100644 (file)
@@ -35,9 +35,17 @@ private:
        static const int SwatchMargin;
 
 public:
+       /**
+        * Construct a ColorButton instance that uses a QColorDialog
+        */
+       ColorButton(QWidget *parent);
+
+       /**
+        * Construct a ColorButton instance that uses a ColorPopup
+        */
        ColorButton(int rows, int cols, QWidget *parent);
 
-       ColorPopup& popup();
+       ColorPopup* popup();
 
        const QColor& color() const;
 
@@ -50,14 +58,14 @@ private:
 
 private Q_SLOTS:
        void on_clicked(bool);
-
        void on_selected(int row, int col);
+       void on_color_selected(const QColor& color);
 
 Q_SIGNALS:
        void selected(const QColor &color);
 
 private:
-       ColorPopup popup_;
+       ColorPopup* popup_;
        QColor cur_color_;
 };