From 488f068c7ecdc101820a3c48be61fb45a7e683dc Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sun, 12 Jan 2014 19:43:02 +0000 Subject: [PATCH] Implemented support for probe groups --- pv/popups/probes.cpp | 194 ++++++++++++++++++++++++++++-------- pv/popups/probes.h | 36 ++++++- pv/toolbars/samplingbar.cpp | 9 +- pv/toolbars/samplingbar.h | 2 - 4 files changed, 191 insertions(+), 50 deletions(-) diff --git a/pv/popups/probes.cpp b/pv/popups/probes.cpp index 60f1e02..3fffec3 100644 --- a/pv/popups/probes.cpp +++ b/pv/popups/probes.cpp @@ -18,15 +18,26 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include +#include + #include "probes.h" +#include #include #include using namespace Qt; + using boost::shared_ptr; +using std::map; +using std::set; using std::vector; +using pv::view::Signal; + namespace pv { namespace popups { @@ -34,94 +45,197 @@ Probes::Probes(SigSession &session, QWidget *parent) : Popup(parent), _session(session), _layout(this), - _probes(this), _updating_probes(false), _probes_bar(this), _enable_all_probes(this), - _disable_all_probes(this) + _disable_all_probes(this), + _check_box_mapper(this) { + // Create the layout setLayout(&_layout); + sr_dev_inst *const sdi = _session.get_device(); + assert(sdi); + + // Collect a set of signals + map > signal_map; + const vector< shared_ptr > sigs = _session.get_signals(); + BOOST_FOREACH(const shared_ptr &sig, sigs) + signal_map[sig->probe()] = sig; + + // Populate probe groups + for (const GSList *g = sdi->probe_groups; g; g = g->next) + { + const sr_probe_group *const group = + (const sr_probe_group*)g->data; + assert(group); + + // Make a set of signals, and removed this signals from the + // signal map. + vector< shared_ptr > group_sigs; + for (const GSList *p = group->probes; p; p = p->next) + { + const sr_probe *const probe = (const sr_probe*)p->data; + assert(probe); + + const map >:: + iterator iter = signal_map.find(probe); + assert(iter != signal_map.end()); + + group_sigs.push_back((*iter).second); + signal_map.erase(iter); + } + + populate_group(group, group_sigs); + } + + // Make a vector of the remaining probes + vector< shared_ptr > global_sigs; + for (const GSList *p = sdi->probes; p; p = p->next) + { + const sr_probe *const probe = (const sr_probe*)p->data; + assert(probe); + + const map >:: + const_iterator iter = signal_map.find(probe); + if (iter != signal_map.end()) + global_sigs.push_back((*iter).second); + } + + // Create a group + populate_group(NULL, global_sigs); + + // Create the enable/disable all buttons connect(&_enable_all_probes, SIGNAL(clicked()), this, SLOT(enable_all_probes())); connect(&_disable_all_probes, SIGNAL(clicked()), this, SLOT(disable_all_probes())); - _layout.addWidget(&_probes); - _enable_all_probes.setText(tr("Enable All")); _probes_bar.addWidget(&_enable_all_probes); _disable_all_probes.setText(tr("Disable All")); _probes_bar.addWidget(&_disable_all_probes); - _layout.addWidget(&_probes_bar); + _layout.addRow(&_probes_bar); - connect(&_probes, SIGNAL(itemChanged(QListWidgetItem*)), - this, SLOT(item_changed(QListWidgetItem*))); + // Connect the check-box signal mapper + connect(&_check_box_mapper, SIGNAL(mapped(QWidget*)), + this, SLOT(on_probe_checked(QWidget*))); } void Probes::set_all_probes(bool set) { - using pv::view::Signal; - _updating_probes = true; - const vector< shared_ptr > sigs = - _session.get_signals(); - for (unsigned int i = 0; i < sigs.size(); i++) + for (map >::const_iterator i = + _check_box_signal_map.begin(); + i != _check_box_signal_map.end(); i++) { - const shared_ptr &s = sigs[i]; - assert(s); - s->enable(set); + const shared_ptr sig = (*i).second; + assert(sig); - QListWidgetItem *const item = _probes.item(i); - assert(item); - item->setCheckState(set ? Qt::Checked : Qt::Unchecked); + sig->enable(set); + (*i).first->setChecked(set); } _updating_probes = false; } +void Probes::populate_group(const sr_probe_group *group, + const vector< shared_ptr > sigs) +{ + using pv::prop::binding::DeviceOptions; + + // Only bind options if this is a group. We don't do it for general + // options, because these properties are shown in the device config + // popup. + shared_ptr binding; + if (group) + binding = shared_ptr(new DeviceOptions( + _session.get_device(), group)); + + // Create a title if the group is going to have any content + if ((!sigs.empty() || (binding && !binding->properties().empty())) && + group && group->name) + _layout.addRow(new QLabel( + QString("

%1

").arg(group->name))); + + // Create the probe group grid + QGridLayout *const probe_grid = + create_probe_group_grid(sigs); + _layout.addRow(probe_grid); + + // Create the probe group options + if (binding) + { + binding->add_properties_to_form(&_layout, true); + _group_bindings.push_back(binding); + } +} + +QGridLayout* Probes::create_probe_group_grid( + const vector< shared_ptr > sigs) +{ + int row = 0, col = 0; + QGridLayout *const grid = new QGridLayout(); + + BOOST_FOREACH(const shared_ptr& sig, sigs) + { + assert(sig); + + QCheckBox *const checkbox = new QCheckBox(sig->get_name()); + _check_box_mapper.setMapping(checkbox, checkbox); + connect(checkbox, SIGNAL(toggled(bool)), + &_check_box_mapper, SLOT(map())); + + grid->addWidget(checkbox, row, col); + + _check_box_signal_map[checkbox] = sig; + + if(++col >= 8) + col = 0, row++; + } + + return grid; +} + void Probes::showEvent(QShowEvent *e) { pv::widgets::Popup::showEvent(e); _updating_probes = true; - _probes.clear(); - - const vector< shared_ptr > sigs = - _session.get_signals(); - for (unsigned int i = 0; i < sigs.size(); i++) + for (map >::const_iterator i = + _check_box_signal_map.begin(); + i != _check_box_signal_map.end(); i++) { - const shared_ptr &s = sigs[i]; - assert(s); - QListWidgetItem *const item = new QListWidgetItem( - s->get_name(), &_probes); - assert(item); - item->setCheckState(s->enabled() ? Checked : Unchecked); - item->setData(UserRole, qVariantFromValue(i)); - _probes.addItem(item); + const shared_ptr sig = (*i).second; + assert(sig); + + (*i).first->setChecked(sig->enabled()); } _updating_probes = false; } -void Probes::item_changed(QListWidgetItem *item) +void Probes::on_probe_checked(QWidget *widget) { - using pv::view::Signal; - if (_updating_probes) return; - assert(item); - const vector< shared_ptr > sigs = - _session.get_signals(); - const shared_ptr s = sigs[ - item->data(UserRole).value()]; + QCheckBox *const check_box = (QCheckBox*)widget; + assert(check_box); + + // Look up the signal of this check-box + map< QCheckBox*, shared_ptr >::const_iterator iter = + _check_box_signal_map.find((QCheckBox*)check_box); + assert(iter != _check_box_signal_map.end()); + + const shared_ptr s = (*iter).second; assert(s); - s->enable(item->checkState() == Checked); + + s->enable(check_box->isChecked()); } void Probes::enable_all_probes() diff --git a/pv/popups/probes.h b/pv/popups/probes.h index b5eda58..dc7324d 100644 --- a/pv/popups/probes.h +++ b/pv/popups/probes.h @@ -21,17 +21,31 @@ #ifndef PULSEVIEW_PV_POPUPS_PROBES_H #define PULSEVIEW_PV_POPUPS_PROBES_H -#include +#include + +#include #include #include -#include #include +class QCheckBox; +class QGridLayout; + namespace pv { class SigSession; +namespace prop { +namespace binding { +class DeviceOptions; +} +} + +namespace view { +class Signal; +} + namespace popups { class Probes : public pv::widgets::Popup @@ -44,11 +58,17 @@ public: private: void set_all_probes(bool set); + void populate_group(const sr_probe_group *group, + const std::vector< boost::shared_ptr > sigs); + + QGridLayout* create_probe_group_grid( + const std::vector< boost::shared_ptr > sigs); + private: void showEvent(QShowEvent *e); private slots: - void item_changed(QListWidgetItem *item); + void on_probe_checked(QWidget *widget); void enable_all_probes(); void disable_all_probes(); @@ -56,14 +76,20 @@ private slots: private: pv::SigSession &_session; - QVBoxLayout _layout; + QFormLayout _layout; - QListWidget _probes; bool _updating_probes; + std::vector< boost::shared_ptr > + _group_bindings; + std::map< QCheckBox*, boost::shared_ptr > + _check_box_signal_map; + QToolBar _probes_bar; QToolButton _enable_all_probes; QToolButton _disable_all_probes; + + QSignalMapper _check_box_mapper; }; } // popups diff --git a/pv/toolbars/samplingbar.cpp b/pv/toolbars/samplingbar.cpp index 0e3ce62..778f7aa 100644 --- a/pv/toolbars/samplingbar.cpp +++ b/pv/toolbars/samplingbar.cpp @@ -33,6 +33,7 @@ #include #include +#include using std::string; @@ -72,7 +73,6 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) : _configure_button(this), _configure_button_action(NULL), _probes_button(this), - _probes_popup(_session, this), _record_length_selector(this), _sample_rate_action(NULL), _sample_rate_list(this), @@ -108,7 +108,6 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) : _probes_button.setIcon(QIcon::fromTheme("probes", QIcon(":/icons/probes.svg"))); - _probes_button.set_popup(&_probes_popup); _run_stop_button.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -304,7 +303,7 @@ void SamplingBar::commit_sample_rate() void SamplingBar::on_device_selected() { - using pv::popups::DeviceOptions; + using namespace pv::popups; if (_updating_device_selector) return; @@ -319,6 +318,10 @@ void SamplingBar::on_device_selected() _configure_button_action->setVisible( !opts->binding().properties().empty()); _configure_button.set_popup(opts); + + // Update the probes popup + Probes *const probes = new Probes(_session, this); + _probes_button.set_popup(probes); } void SamplingBar::on_sample_rate_changed() diff --git a/pv/toolbars/samplingbar.h b/pv/toolbars/samplingbar.h index 9f6ceb2..5821a01 100644 --- a/pv/toolbars/samplingbar.h +++ b/pv/toolbars/samplingbar.h @@ -31,7 +31,6 @@ #include #include -#include #include struct st_dev_inst; @@ -86,7 +85,6 @@ private: QAction *_configure_button_action; pv::widgets::PopupToolButton _probes_button; - pv::popups::Probes _probes_popup; QComboBox _record_length_selector; -- 2.30.2