Moved decoder config into the popup
authorJoel Holdsworth <joel@airwebreathe.org.uk>
Sat, 26 Oct 2013 08:25:22 +0000 (09:25 +0100)
committerJoel Holdsworth <joel@airwebreathe.org.uk>
Tue, 19 Nov 2013 19:32:10 +0000 (19:32 +0000)
17 files changed:
CMakeLists.txt
pv/data/decoder.cpp
pv/data/decoder.h
pv/dialogs/decoder.cpp [deleted file]
pv/dialogs/decoder.h [deleted file]
pv/mainwindow.cpp
pv/prop/binding/binding.h
pv/prop/binding/decoderoptions.cpp
pv/prop/binding/decoderoptions.h
pv/prop/string.cpp
pv/sigsession.cpp
pv/sigsession.h
pv/view/decodesignal.cpp
pv/view/decodesignal.h
pv/view/view.cpp
test/CMakeLists.txt
test/data/decoder.cpp

index 2ea44dba08084bf4d3bcc15f385f3d5ea7c1f873..03d856b7bf923407622b250ca792afef9a5bacd6 100644 (file)
@@ -114,7 +114,6 @@ set(pulseview_SOURCES
        pv/data/snapshot.cpp
        pv/dialogs/about.cpp
        pv/dialogs/connect.cpp
-       pv/dialogs/decoder.cpp
        pv/popups/deviceoptions.cpp
        pv/popups/probes.cpp
        pv/prop/bool.cpp
index 9e7145f34fe4ffd2c715f141d9701dfb4b0b7a38..a9168ae2bdd33f8ec73fc46cfbf08c04e272c512 100644 (file)
@@ -45,17 +45,11 @@ const int64_t Decoder::DecodeChunkLength = 4096;
 
 mutex Decoder::_global_decode_mutex;
 
-Decoder::Decoder(const srd_decoder *const dec,
-       std::map<const srd_probe*,
-               boost::shared_ptr<pv::view::LogicSignal> > probes,
-       GHashTable *options) :
+Decoder::Decoder(const srd_decoder *const dec) :
        _decoder(dec),
-       _probes(probes),
-       _options(options)
+       _options(g_hash_table_new_full(g_str_hash,
+               g_str_equal, g_free, (GDestroyNotify)g_variant_unref))
 {
-       init_decoder();
-
-       begin_decode();
 }
 
 Decoder::~Decoder()
@@ -66,11 +60,36 @@ Decoder::~Decoder()
        g_hash_table_destroy(_options);
 }
 
-const srd_decoder* Decoder::get_decoder() const
+const srd_decoder* Decoder::decoder() const
 {
        return _decoder;
 }
 
+const map<const srd_probe*, shared_ptr<view::LogicSignal> >&
+Decoder::probes() const
+{
+       return _probes;
+}
+
+void Decoder::set_probes(std::map<const srd_probe*,
+       boost::shared_ptr<view::LogicSignal> > probes)
+{
+       _probes = probes;
+       begin_decode();
+}
+
+const GHashTable* Decoder::options() const
+{
+       return _options;
+}
+
+void Decoder::set_option(const char *id, GVariant *value)
+{
+       g_variant_ref(value);
+       g_hash_table_replace(_options, (void*)g_strdup(id), value);
+       begin_decode();
+}
+
 const vector< shared_ptr<view::decode::Annotation> >
        Decoder::annotations() const
 {
@@ -89,9 +108,26 @@ void Decoder::begin_decode()
        _decode_thread.interrupt();
        _decode_thread.join();
 
+       _annotations.clear();
+
        if (_probes.empty())
                return;
 
+       // Get the samplerate and start time
+       shared_ptr<pv::view::LogicSignal> logic_signal =
+               dynamic_pointer_cast<pv::view::LogicSignal>(
+                       (*_probes.begin()).second);
+       if (logic_signal) {
+               shared_ptr<pv::data::Logic> data(
+                       logic_signal->data());
+               if (data) {
+                       _start_time = data->get_start_time();
+                       _samplerate = data->get_samplerate();
+                       if (_samplerate == 0.0)
+                               _samplerate = 1.0;
+               }
+       }
+
        // We get the logic data of the first probe in the list.
        // This works because we are currently assuming all
        // LogicSignals have the same data/snapshot
@@ -107,26 +143,6 @@ void Decoder::clear_snapshots()
 {
 }
 
-void Decoder::init_decoder()
-{
-       if (!_probes.empty())
-       {
-               shared_ptr<pv::view::LogicSignal> logic_signal =
-                       dynamic_pointer_cast<pv::view::LogicSignal>(
-                               (*_probes.begin()).second);
-               if (logic_signal) {
-                       shared_ptr<pv::data::Logic> data(
-                               logic_signal->data());
-                       if (data) {
-                               _start_time = data->get_start_time();
-                               _samplerate = data->get_samplerate();
-                               if (_samplerate == 0.0)
-                                       _samplerate = 1.0;
-                       }
-               }
-       }
-}
-
 void Decoder::decode_proc(shared_ptr<data::Logic> data)
 {
        srd_session *session;
@@ -134,8 +150,6 @@ void Decoder::decode_proc(shared_ptr<data::Logic> data)
 
        assert(data);
 
-       _annotations.clear();
-
        const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
                data->get_snapshots();
        if (snapshots.empty())
index b8608d2cc4290ed712722ba1e677e6383e96fb03..72ccd2ec58622a9119f6e3f15ddbd2d1fa45e831 100644 (file)
@@ -66,14 +66,20 @@ private:
        static const int64_t DecodeChunkLength;
 
 public:
-       Decoder(const srd_decoder *const decoder,
-               std::map<const srd_probe*,
-                       boost::shared_ptr<pv::view::LogicSignal> > probes,
-               GHashTable *options);
+       Decoder(const srd_decoder *const decoder);
 
        virtual ~Decoder();
 
-       const srd_decoder* get_decoder() const;
+       const srd_decoder* decoder() const;
+
+       const std::map<const srd_probe*, boost::shared_ptr<view::LogicSignal> >&
+               probes() const;
+       void set_probes(std::map<const srd_probe*,
+               boost::shared_ptr<view::LogicSignal> > probes);
+
+       const GHashTable* options() const;
+
+       void set_option(const char *id, GVariant *value);
 
        const std::vector< boost::shared_ptr<pv::view::decode::Annotation> >
                annotations() const;
@@ -85,8 +91,6 @@ public:
 private:
        void begin_decode();
 
-       void init_decoder();
-
        void decode_proc(boost::shared_ptr<data::Logic> data);
 
        static void annotation_callback(srd_proto_data *pdata,
diff --git a/pv/dialogs/decoder.cpp b/pv/dialogs/decoder.cpp
deleted file mode 100644 (file)
index 07375f6..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-extern "C" {
-#include <libsigrokdecode/libsigrokdecode.h>
-}
-
-#include <utility>
-
-#include <boost/foreach.hpp>
-
-#include <QDebug>
-
-#include "decoder.h"
-
-#include <pv/view/logicsignal.h>
-#include <pv/view/signal.h>
-
-using namespace boost;
-using namespace std;
-
-namespace pv {
-namespace dialogs {
-
-Decoder::Decoder(QWidget *parent, const srd_decoder *decoder,
-       const vector< shared_ptr<view::LogicSignal> > &sigs,
-       GHashTable *options) :
-       QDialog(parent),
-       _sigs(sigs),
-       _binding(decoder, options),
-       _layout(this),
-       _form(this),
-       _form_layout(&_form),
-       _heading(this),
-       _button_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
-               Qt::Horizontal, this)
-{
-       const GSList *probe;
-
-       setWindowTitle(tr("Configure %1").arg(decoder->name));
-
-       _heading.setText(tr("<h2>%1</h2>%2")
-               .arg(decoder->longname)
-               .arg(decoder->desc));
-
-       connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
-       connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
-
-       _form.setLayout(&_form_layout);
-
-       setLayout(&_layout);
-       _layout.addWidget(&_heading);
-       _layout.addWidget(&_form);
-       _layout.addWidget(&_button_box);
-
-       _form_layout.addRow(new QLabel(tr("<h3>Probes</h3>"), &_form));
-
-       // Add the mandatory probes
-       for(probe = decoder->probes; probe; probe = probe->next) {
-               const struct srd_probe *const p =
-                       (struct srd_probe *)probe->data;
-               QComboBox *const combo = create_probe_selector(
-                       &_form, p->name);
-               _form_layout.addRow(tr("<b>%1</b> (%2) *")
-                       .arg(p->name).arg(p->desc), combo);
-
-               _probe_selector_map[p] = combo;
-       }
-
-       // Add the optional probes
-       for(probe = decoder->opt_probes; probe; probe = probe->next) {
-               const struct srd_probe *const p =
-                       (struct srd_probe *)probe->data;
-               QComboBox *const combo = create_probe_selector(
-                       &_form, p->name);
-               _form_layout.addRow(tr("<b>%1</b> (%2)")
-                       .arg(p->name).arg(p->desc), combo);
-
-               _probe_selector_map[p] = combo;
-       }
-
-       _form_layout.addRow(new QLabel(
-               tr("<i>* Required Probes</i>"), &_form));
-
-       // Add the options
-       if (!_binding.properties().empty()) {
-               _form_layout.addRow(new QLabel(tr("<h3>Options</h3>"),
-                       &_form));
-               _binding.add_properties_to_form(&_form_layout);
-       }
-}
-
-void Decoder::accept()
-{
-       QDialog::accept();
-       _binding.commit();
-}
-
-QComboBox* Decoder::create_probe_selector(
-       QWidget *parent, const char *name)
-{
-       QComboBox *selector = new QComboBox(parent);
-
-       selector->addItem("-", qVariantFromValue(-1));
-       selector->setCurrentIndex(0);
-
-       for(size_t i = 0; i < _sigs.size(); i++) {
-               const shared_ptr<view::LogicSignal> s(_sigs[i]);
-               assert(s);
-
-               if (s->enabled())
-               {
-                       selector->addItem(s->get_name(), qVariantFromValue(i));
-                       if(s->get_name().toLower().contains(
-                               QString(name).toLower()))
-                               selector->setCurrentIndex(i + 1);
-               }
-       }
-
-       return selector;
-}
-
-map<const srd_probe*, shared_ptr<view::LogicSignal> > Decoder::get_probes()
-{
-       map<const srd_probe*, shared_ptr<view::LogicSignal> > probe_map;
-       for(map<const srd_probe*, QComboBox*>::const_iterator i =
-               _probe_selector_map.begin();
-               i != _probe_selector_map.end(); i++)
-       {
-               const QComboBox *const combo = (*i).second;
-               const int probe_index =
-                       combo->itemData(combo->currentIndex()).value<int>();
-               if(probe_index >= 0) {
-                       shared_ptr<view::LogicSignal> sig = _sigs[probe_index];
-                       probe_map[(*i).first] = sig;
-               }
-       }
-
-       return probe_map;
-}
-
-} // namespace dialogs
-} // namespace pv
diff --git a/pv/dialogs/decoder.h b/pv/dialogs/decoder.h
deleted file mode 100644 (file)
index 926d015..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_DECODER_H
-#define PULSEVIEW_PV_DECODER_H
-
-#include <vector>
-#include <map>
-
-#include <boost/shared_ptr.hpp>
-
-#include <QComboBox>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFormLayout>
-#include <QLabel>
-#include <QVBoxLayout>
-
-#include <pv/prop/binding/decoderoptions.h>
-
-struct srd_decoder;
-
-namespace pv {
-
-namespace view {
-class LogicSignal;
-}
-
-namespace dialogs {
-
-class Decoder : public QDialog
-{
-public:
-       Decoder(QWidget *parent, const srd_decoder *decoder,
-               const std::vector< boost::shared_ptr<view::LogicSignal> > &sigs,
-               GHashTable *options);
-
-       void accept();
-
-       std::map<const srd_probe*, boost::shared_ptr<view::LogicSignal> >
-               get_probes();
-
-private:
-       QComboBox* create_probe_selector(
-               QWidget *parent, const char *name);
-
-private:
-       const std::vector< boost::shared_ptr<view::LogicSignal> > &_sigs;
-
-       std::map<const srd_probe*, QComboBox*> _probe_selector_map;
-
-       pv::prop::binding::DecoderOptions _binding;
-
-       QVBoxLayout _layout;
-
-       QWidget _form;
-       QFormLayout _form_layout;
-
-       QLabel _heading;
-       QDialogButtonBox _button_box;
-};
-
-} // namespace dialogs
-} // namespace pv
-
-#endif // PULSEVIEW_PV_DECODER_H
index 183e841e804c3c6f48d37949268ec3227a0c70be..e1f831408a54385d7b12da34999e92a6f6956e2d 100644 (file)
@@ -39,7 +39,6 @@
 #include "devicemanager.h"
 #include "dialogs/about.h"
 #include "dialogs/connect.h"
-#include "dialogs/decoder.h"
 #include "toolbars/samplingbar.h"
 #include "view/logicsignal.h"
 #include "view/view.h"
@@ -376,27 +375,7 @@ void MainWindow::add_decoder(QObject *action)
                (srd_decoder*)((QAction*)action)->data().value<void*>();
        assert(dec);
 
-       vector< shared_ptr<view::LogicSignal> > logic_sigs;
-       const vector< shared_ptr<view::Signal> > &sigs =
-               _session.get_signals();
-       BOOST_FOREACH(shared_ptr<view::Signal> s, sigs) {
-               assert(s);
-               shared_ptr<view::LogicSignal> l =
-                       dynamic_pointer_cast<view::LogicSignal>(s);
-               if (l)
-                       logic_sigs.push_back(l);
-       }
-
-       GHashTable *const options = g_hash_table_new_full(g_str_hash,
-               g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
-
-       dialogs::Decoder dlg(this, dec, logic_sigs, options);
-       if(dlg.exec() != QDialog::Accepted) {
-               g_hash_table_destroy(options);
-               return;
-       }
-
-       _session.add_decoder(dec, dlg.get_probes(), options);
+       _session.add_decoder(dec);
 }
 
 void MainWindow::run_stop()
index 4de4af33ba3044f150b88c5fc4fc8698e5a21ab5..9b63c16214f1fffc9e83bd27245b1600d0a2dedd 100644 (file)
@@ -24,6 +24,7 @@
 #include <vector>
 #include <boost/shared_ptr.hpp>
 
+class QFormLayout;
 class QWidget;
 
 namespace pv {
index dc3a8e974355c515322d3fb30e1920f4148afaab..5ad7e3562e6150e057c9299964069af1e931feba 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <libsigrokdecode/libsigrokdecode.h>
+
 #include "decoderoptions.h"
 
 #include <boost/foreach.hpp>
 #include <boost/none_t.hpp>
 
+#include <pv/data/decoder.h>
 #include <pv/prop/int.h>
 #include <pv/prop/string.h>
 
@@ -33,15 +36,15 @@ namespace pv {
 namespace prop {
 namespace binding {
 
-DecoderOptions::DecoderOptions(const srd_decoder *decoder,
-       GHashTable *options) :
-       _decoder(decoder),
-       _options(options)
+DecoderOptions::DecoderOptions(shared_ptr<pv::data::Decoder> decoder) :
+       _decoder(decoder)
 {
-       assert(decoder);
+       assert(_decoder);
 
+       const srd_decoder *const dec = _decoder->decoder();
+       assert(dec);
 
-       for (GSList *l = decoder->options; l; l = l->next)
+       for (GSList *l = dec->options; l; l = l->next)
        {
                const srd_decoder_option *const opt =
                        (srd_decoder_option*)l->data;
@@ -70,13 +73,18 @@ DecoderOptions::DecoderOptions(const srd_decoder *decoder,
 
 GVariant* DecoderOptions::getter(const char *id)
 {
+       assert(_decoder);
+
        // Get the value from the hash table if it is already present
-       GVariant *val = (GVariant*)g_hash_table_lookup(_options, id);
+       GVariant *val = (GVariant*)g_hash_table_lookup(
+               (GHashTable*)_decoder->options(), id);
 
        if (!val)
        {
+               assert(_decoder->decoder());
+
                // Get the default value if not
-               for (GSList *l = _decoder->options; l; l = l->next)
+               for (GSList *l = _decoder->decoder()->options; l; l = l->next)
                {
                        const srd_decoder_option *const opt =
                                (srd_decoder_option*)l->data;
@@ -95,8 +103,8 @@ GVariant* DecoderOptions::getter(const char *id)
 
 void DecoderOptions::setter(const char *id, GVariant *value)
 {
-       g_variant_ref(value);
-       g_hash_table_insert(_options, (void*)g_strdup(id), value);
+       assert(_decoder);
+       _decoder->set_option(id, value);
 }
 
 } // binding
index 8217b4791e19c6f9a3b98b4f71df8f5118634f5a..11b0be724afd9d738da6de3105640a72f401a8b5 100644 (file)
 #ifndef PULSEVIEW_PV_PROP_BINDING_DECODEROPTIONS_H
 #define PULSEVIEW_PV_PROP_BINDING_DECODEROPTIONS_H
 
-#include <libsigrokdecode/libsigrokdecode.h>
+#include <glib.h>
 
 #include "binding.h"
 
 namespace pv {
+
+namespace data {
+class Decoder;
+}
+
 namespace prop {
 namespace binding {
 
 class DecoderOptions : public Binding
 {
 public:
-       DecoderOptions(const srd_decoder *decoder, GHashTable *options);
+       DecoderOptions(boost::shared_ptr<pv::data::Decoder> decoder);
 
 private:
        GVariant* getter(const char *id);
@@ -40,8 +45,7 @@ private:
        void setter(const char *id, GVariant *value);
 
 private:
-       const srd_decoder *const _decoder;
-       GHashTable *const _options;
+       boost::shared_ptr<pv::data::Decoder> _decoder;
 };
 
 } // binding
index b8f3351cf8fb2acbc160a7bcd41bfb529443ddd3..c2b2c67c26a5c97377dff2b853759206ef65ffe7 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <assert.h>
 
+#include <QLineEdit>
 #include <QSpinBox>
 
 #include "string.h"
index b27fd6ec7f80e8d77635e4219a2fed65c4cfde63..aeb6d22072f55f6bc49c04dd389295fd852b5c6a 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <libsigrokdecode/libsigrokdecode.h>
+
 #include "sigsession.h"
 
 #include "devicemanager.h"
@@ -36,6 +38,8 @@
 
 #include <stdexcept>
 
+#include <boost/foreach.hpp>
+
 #include <sys/stat.h>
 
 #include <QDebug>
@@ -195,17 +199,34 @@ boost::shared_ptr<data::Logic> SigSession::get_data()
        return _logic_data;
 }
 
-bool SigSession::add_decoder(srd_decoder *const dec,
-       std::map<const srd_probe*,
-               boost::shared_ptr<view::LogicSignal> > probes,
-       GHashTable *options)
+bool SigSession::add_decoder(srd_decoder *const dec)
 {
+       map<const srd_probe*, shared_ptr<view::LogicSignal> > probes;
+
        try
        {
                lock_guard<mutex> lock(_signals_mutex);
 
-               shared_ptr<data::Decoder> decoder(
-                       new data::Decoder(dec, probes, options));
+               // Create the decoder
+               shared_ptr<data::Decoder> decoder(new data::Decoder(dec));
+
+               // Auto select the initial probes
+               for(const GSList *i = dec->probes; i; i = i->next)
+               {
+                       const srd_probe *const probe = (const srd_probe*)i->data;
+                       BOOST_FOREACH(shared_ptr<view::Signal> s, _signals)
+                       {
+                               shared_ptr<view::LogicSignal> l =
+                                       dynamic_pointer_cast<view::LogicSignal>(s);
+                               if (l && QString(probe->name).toLower().contains(
+                                       l->get_name().toLower()))
+                                       probes[probe] = l;
+                       }
+               }
+
+               decoder->set_probes(probes);
+
+               // Create the decode signal
                shared_ptr<view::DecodeSignal> d(
                        new view::DecodeSignal(*this, decoder,
                                _decode_traces.size()));
index 5c69a9bc3a1aa428982ce64b15bf240bda08d322..801c0a57c60c67066ef04d3d61a9b6a6eb5889d8 100644 (file)
@@ -94,10 +94,7 @@ public:
 
        boost::shared_ptr<data::Logic> get_data();
 
-       bool add_decoder(srd_decoder *const dec,
-               std::map<const srd_probe*,
-                       boost::shared_ptr<view::LogicSignal> > probes,
-               GHashTable *options);
+       bool add_decoder(srd_decoder *const dec);
 
        std::vector< boost::shared_ptr<view::DecodeSignal> >
                get_decode_signals() const;
index 1cbce00d6be4843802132e961006603d89836061..9f81ab42567dd5e58f2cc59a741bb565e58044bd 100644 (file)
@@ -27,12 +27,16 @@ extern "C" {
 #include <boost/foreach.hpp>
 
 #include <QAction>
+#include <QComboBox>
+#include <QFormLayout>
+#include <QLabel>
 #include <QMenu>
 
 #include "decodesignal.h"
 
 #include <pv/sigsession.h>
 #include <pv/data/decoder.h>
+#include <pv/view/logicsignal.h>
 #include <pv/view/view.h>
 #include <pv/view/decode/annotation.h>
 
@@ -53,8 +57,9 @@ const QColor DecodeSignal::ErrorBgColour = QColor(0xEF, 0x29, 0x29);
 
 DecodeSignal::DecodeSignal(pv::SigSession &session,
        boost::shared_ptr<pv::data::Decoder> decoder, int index) :
-       Trace(session, QString(decoder->get_decoder()->name)),
-       _decoder(decoder)
+       Trace(session, QString(decoder->decoder()->name)),
+       _decoder(decoder),
+       _binding(decoder)
 {
        assert(_decoder);
 
@@ -121,6 +126,61 @@ void DecodeSignal::paint_mid(QPainter &p, int left, int right)
        }
 }
 
+void DecodeSignal::populate_popup_form(QWidget *parent, QFormLayout *form)
+{
+       const GSList *probe;
+
+       assert(form);
+       assert(parent);
+       assert(_decoder);
+
+       const srd_decoder *const decoder = _decoder->decoder();
+
+       assert(decoder);
+
+       Trace::populate_popup_form(parent, form);
+
+       form->addRow(new QLabel(tr("<h3>Probes</h3>"), parent));
+
+       _probe_selector_map.clear();
+
+       // Add the mandatory probes
+       for(probe = decoder->probes; probe; probe = probe->next) {
+               const struct srd_probe *const p =
+                       (struct srd_probe *)probe->data;
+               QComboBox *const combo = create_probe_selector(parent, p);
+               connect(combo, SIGNAL(currentIndexChanged(int)),
+                       this, SLOT(on_probe_selected(int)));
+               form->addRow(tr("<b>%1</b> (%2) *")
+                       .arg(p->name).arg(p->desc), combo);
+
+               _probe_selector_map[p] = combo;
+       }
+
+       // Add the optional probes
+       for(probe = decoder->opt_probes; probe; probe = probe->next) {
+               const struct srd_probe *const p =
+                       (struct srd_probe *)probe->data;
+               QComboBox *const combo = create_probe_selector(parent, p);
+               connect(combo, SIGNAL(currentIndexChanged(int)),
+                       this, SLOT(on_probe_selected(int)));
+               form->addRow(tr("<b>%1</b> (%2)")
+                       .arg(p->name).arg(p->desc), combo);
+
+               _probe_selector_map[p] = combo;
+       }
+
+       form->addRow(new QLabel(
+               tr("<i>* Required Probes</i>"), parent));
+
+       // Add the options
+       if (!_binding.properties().empty()) {
+               form->addRow(new QLabel(tr("<h3>Options</h3>"),
+                       parent));
+               _binding.add_properties_to_form(form, true);
+       }
+}
+
 QMenu* DecodeSignal::create_context_menu(QWidget *parent)
 {
        QMenu *const menu = Trace::create_context_menu(parent);
@@ -156,6 +216,66 @@ void DecodeSignal::draw_error(QPainter &p, const QString &message,
        p.drawText(text_rect, message);
 }
 
+QComboBox* DecodeSignal::create_probe_selector(
+       QWidget *parent, const srd_probe *const probe)
+{
+       const vector< shared_ptr<Signal> > sigs = _session.get_signals();
+
+       assert(_decoder);
+       const map<const srd_probe*,
+               shared_ptr<LogicSignal> >::const_iterator probe_iter =
+               _decoder->probes().find(probe);
+
+       QComboBox *selector = new QComboBox(parent);
+
+       selector->addItem("-", qVariantFromValue((void*)NULL));
+
+       if (probe_iter == _decoder->probes().end())
+               selector->setCurrentIndex(0);
+
+       for(size_t i = 0; i < sigs.size(); i++) {
+               const shared_ptr<view::Signal> s(sigs[i]);
+               assert(s);
+
+               if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
+               {
+                       selector->addItem(s->get_name(),
+                               qVariantFromValue((void*)s.get()));
+                       if ((*probe_iter).second == s)
+                               selector->setCurrentIndex(i + 1);
+               }
+       }
+
+       return selector;
+}
+
+void DecodeSignal::commit_probes()
+{
+       assert(_decoder);
+
+       map<const srd_probe*, shared_ptr<LogicSignal> > probe_map;
+       const vector< shared_ptr<Signal> > sigs = _session.get_signals();
+
+       for(map<const srd_probe*, QComboBox*>::const_iterator i =
+               _probe_selector_map.begin();
+               i != _probe_selector_map.end(); i++)
+       {
+               const QComboBox *const combo = (*i).second;
+               const LogicSignal *const selection =
+                       (LogicSignal*)combo->itemData(combo->currentIndex()).
+                       value<void*>();
+
+               BOOST_FOREACH(shared_ptr<Signal> s, sigs)
+                       if(s.get() == selection) {
+                               probe_map[(*i).first] =
+                                       dynamic_pointer_cast<LogicSignal>(s);
+                               break;
+                       }
+       }
+
+       _decoder->set_probes(probe_map);
+}
+
 void DecodeSignal::on_new_decode_data()
 {
        if (_view)
@@ -172,5 +292,10 @@ void DecodeSignal::on_delete()
        _session.remove_decode_signal(this);
 }
 
+void DecodeSignal::on_probe_selected(int)
+{
+       commit_probes();
+}
+
 } // namespace view
 } // namespace pv
index efa3449575942e1a4b69170276c3094b770c8256..7977c1c3ab40cd25497a548888d8958bc1b80de5 100644 (file)
 
 #include "trace.h"
 
+#include <map>
+
 #include <boost/shared_ptr.hpp>
 
+#include <pv/prop/binding/decoderoptions.h>
+
+struct srd_probe;
+
+class QComboBox;
+
 namespace pv {
 
 namespace data {
@@ -67,6 +75,8 @@ public:
         **/
        void paint_mid(QPainter &p, int left, int right);
 
+       void populate_popup_form(QWidget *parent, QFormLayout *form);
+
        QMenu* create_context_menu(QWidget *parent);
 
        void delete_pressed();
@@ -75,15 +85,26 @@ private:
        void draw_error(QPainter &p, const QString &message,
                int left, int right);
 
+       QComboBox* create_probe_selector(
+               QWidget *parent, const srd_probe *const probe);
+
+       void commit_probes();
+
 private slots:
        void on_new_decode_data();
 
        void on_delete();
 
+       void on_probe_selected(int);
+
 private:
        boost::shared_ptr<pv::data::Decoder> _decoder;
 
        uint64_t _decode_start, _decode_end;
+
+       pv::prop::binding::DecoderOptions _binding;
+
+       std::map<const srd_probe*, QComboBox*> _probe_selector_map;
 };
 
 } // namespace view
index 6af03c9c0f7a78fec96a341c57c7e38b1d951bae..42a2f79f0b22e96b45340c67aef0eabaa0c8957d 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <libsigrokdecode/libsigrokdecode.h>
+
 #include <assert.h>
 #include <limits.h>
 #include <math.h>
index 0a58cde8e747d41dbd5f22308449d0ef23336e0d..e55e20dea9cfc53dcc909d72657dd13e06fc001b 100644 (file)
@@ -46,6 +46,11 @@ set(pulseview_TEST_SOURCES
        ${PROJECT_SOURCE_DIR}/pv/data/logicsnapshot.cpp
        ${PROJECT_SOURCE_DIR}/pv/data/snapshot.cpp
        ${PROJECT_SOURCE_DIR}/pv/data/signaldata.cpp
+       ${PROJECT_SOURCE_DIR}/pv/prop/int.cpp
+       ${PROJECT_SOURCE_DIR}/pv/prop/property.cpp
+       ${PROJECT_SOURCE_DIR}/pv/prop/string.cpp
+       ${PROJECT_SOURCE_DIR}/pv/prop/binding/binding.cpp
+       ${PROJECT_SOURCE_DIR}/pv/prop/binding/decoderoptions.cpp
        ${PROJECT_SOURCE_DIR}/pv/view/analogsignal.cpp
        ${PROJECT_SOURCE_DIR}/pv/view/cursor.cpp
        ${PROJECT_SOURCE_DIR}/pv/view/cursorpair.cpp
@@ -76,6 +81,9 @@ set(pulseview_TEST_SOURCES
 set(pulseview_TEST_HEADERS
        ${PROJECT_SOURCE_DIR}/pv/sigsession.h
        ${PROJECT_SOURCE_DIR}/pv/data/decoder.h
+       ${PROJECT_SOURCE_DIR}/pv/prop/int.h
+       ${PROJECT_SOURCE_DIR}/pv/prop/property.h
+       ${PROJECT_SOURCE_DIR}/pv/prop/string.h
        ${PROJECT_SOURCE_DIR}/pv/view/cursor.h
        ${PROJECT_SOURCE_DIR}/pv/view/decodesignal.h
        ${PROJECT_SOURCE_DIR}/pv/view/header.h
index 4ea4b10ff50f6231313c9aa8f9f341c13f2d7dd7..0a54a8669dae376e28c51a391a972768cd230832 100644 (file)
@@ -55,14 +55,8 @@ BOOST_AUTO_TEST_CASE(TwoDecoder)
                srd_decoder *const dec = (struct srd_decoder*)l->data;
                BOOST_REQUIRE(dec);
 
-               map<const srd_probe*, shared_ptr<view::LogicSignal> > probes;
-               ss.add_decoder(dec, probes,
-                       g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-                               (GDestroyNotify)g_variant_unref));
-               
-               ss.add_decoder(dec, probes,
-                       g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-                               (GDestroyNotify)g_variant_unref));
+               ss.add_decoder(dec);
+               ss.add_decoder(dec);
 
                // Check the signals were created
                const vector< shared_ptr<view::DecodeSignal> > sigs =