From 079d39ea735015597a65390e4c5cacc7d272f78c Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 10 Jan 2015 16:45:55 +0000 Subject: [PATCH] MainBar: Replaced device selector combo-box with a split button --- CMakeLists.txt | 2 + pv/mainwindow.cpp | 18 +---- pv/mainwindow.hpp | 2 +- pv/toolbars/mainbar.cpp | 81 ++++++++------------- pv/toolbars/mainbar.hpp | 11 ++- pv/widgets/devicetoolbutton.cpp | 120 ++++++++++++++++++++++++++++++++ pv/widgets/devicetoolbutton.hpp | 99 ++++++++++++++++++++++++++ 7 files changed, 256 insertions(+), 77 deletions(-) create mode 100644 pv/widgets/devicetoolbutton.cpp create mode 100644 pv/widgets/devicetoolbutton.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ddabe2e..3e621a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,7 @@ set(pulseview_SOURCES pv/view/viewwidget.cpp pv/widgets/colourbutton.cpp pv/widgets/colourpopup.cpp + pv/widgets/devicetoolbutton.cpp pv/widgets/popup.cpp pv/widgets/popuptoolbutton.cpp pv/widgets/sweeptimingwidget.cpp @@ -231,6 +232,7 @@ set(pulseview_HEADERS pv/view/viewwidget.hpp pv/widgets/colourbutton.hpp pv/widgets/colourpopup.hpp + pv/widgets/devicetoolbutton.hpp pv/widgets/popup.hpp pv/widgets/popuptoolbutton.hpp pv/widgets/sweeptimingwidget.hpp diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index a7dd773..dc9e7de 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -438,23 +438,7 @@ void MainWindow::session_error( void MainWindow::update_device_list() { - assert(main_bar_); - - shared_ptr selected_device = session_.device(); - list< shared_ptr > devices; - - if (device_manager_.devices().size() == 0) - return; - - std::copy(device_manager_.devices().begin(), - device_manager_.devices().end(), std::back_inserter(devices)); - - if (std::find(devices.begin(), devices.end(), selected_device) == - devices.end()) - devices.push_back(selected_device); - assert(selected_device); - - main_bar_->set_device_list(devices, selected_device); + main_bar_->update_device_list(); } void MainWindow::closeEvent(QCloseEvent *event) diff --git a/pv/mainwindow.hpp b/pv/mainwindow.hpp index 84245e0..2e6e55c 100644 --- a/pv/mainwindow.hpp +++ b/pv/mainwindow.hpp @@ -102,7 +102,7 @@ private: void session_error(const QString text, const QString info_text); /** - * Updates the device list in the sampling bar + * Updates the device list in the toolbar */ void update_device_list(); diff --git a/pv/toolbars/mainbar.cpp b/pv/toolbars/mainbar.cpp index 82b5fab..50a9064 100644 --- a/pv/toolbars/mainbar.cpp +++ b/pv/toolbars/mainbar.cpp @@ -1,7 +1,7 @@ /* * This file is part of the PulseView project. * - * Copyright (C) 2012 Joel Holdsworth + * Copyright (C) 2012-2015 Joel Holdsworth * * 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 @@ -20,7 +20,8 @@ #include -#include +#include +#include #include #include @@ -38,12 +39,15 @@ #include +using std::back_inserter; +using std::copy; +using std::list; using std::map; -using std::vector; using std::max; using std::min; using std::shared_ptr; using std::string; +using std::vector; using sigrok::Capability; using sigrok::ConfigKey; @@ -61,8 +65,8 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : QToolBar("Sampling Bar", &main_window), session_(session), main_window_(main_window), - device_selector_(this), - updating_device_selector_(false), + device_selector_(this, session.device_manager(), + main_window.action_connect()), configure_button_(this), configure_button_action_(NULL), channels_button_(this), @@ -82,6 +86,10 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : setMovable(false); setFloatable(false); + // Device selector menu + connect(&device_selector_, SIGNAL(device_selected()), + this, SLOT(on_device_selected())); + // Setup the decoder button #ifdef ENABLE_DECODE QToolButton *add_decoder_button = new QToolButton(this); @@ -121,8 +129,6 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : connect(&run_stop_button_, SIGNAL(clicked()), this, SLOT(on_run_stop())); - connect(&device_selector_, SIGNAL(currentIndexChanged (int)), - this, SLOT(on_device_selected())); connect(&sample_count_, SIGNAL(value_changed()), this, SLOT(on_sample_count_changed())); connect(&sample_rate_, SIGNAL(value_changed()), @@ -161,48 +167,22 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : sample_rate_.installEventFilter(this); } -void MainBar::set_device_list( - const std::list< std::shared_ptr > &devices, - shared_ptr selected) +void MainBar::update_device_list() { - int selected_index = -1; - - assert(selected); - - updating_device_selector_ = true; - - device_selector_.clear(); - - for (auto device : devices) { - assert(device); + DeviceManager &mgr = session_.device_manager(); + shared_ptr selected_device = session_.device(); + list< shared_ptr > devs; - string display_name = - session_.device_manager().get_display_name(device); + copy(mgr.devices().begin(), mgr.devices().end(), back_inserter(devs)); - if (selected == device) - selected_index = device_selector_.count(); - - device_selector_.addItem(display_name.c_str(), - qVariantFromValue(device)); - } - - // The selected device should have been in the list - assert(selected_index != -1); - device_selector_.setCurrentIndex(selected_index); + if (std::find(devs.begin(), devs.end(), selected_device) == devs.end()) + devs.push_back(selected_device); + assert(selected_device); + device_selector_.set_device_list(devs, selected_device); update_device_config_widgets(); - - updating_device_selector_ = false; } -shared_ptr MainBar::get_selected_device() const -{ - const int index = device_selector_.currentIndex(); - if (index < 0) - return shared_ptr(); - - return device_selector_.itemData(index).value>(); -} void MainBar::set_capture_state(pv::Session::capture_state state) { @@ -223,7 +203,7 @@ void MainBar::update_sample_rate_selector() if (updating_sample_rate_) return; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -296,7 +276,7 @@ void MainBar::update_sample_rate_selector_value() if (updating_sample_rate_) return; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -319,7 +299,7 @@ void MainBar::update_sample_count_selector() if (updating_sample_count_) return; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -380,7 +360,7 @@ void MainBar::update_device_config_widgets() { using namespace pv::popups; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -438,7 +418,7 @@ void MainBar::commit_sample_count() if (updating_sample_count_) return; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -468,7 +448,7 @@ void MainBar::commit_sample_rate() if (updating_sample_rate_) return; - const shared_ptr device = get_selected_device(); + const shared_ptr device = device_selector_.selected_device(); if (!device) return; @@ -492,10 +472,7 @@ void MainBar::commit_sample_rate() void MainBar::on_device_selected() { - if (updating_device_selector_) - return; - - shared_ptr device = get_selected_device(); + shared_ptr device = device_selector_.selected_device(); if (!device) return; diff --git a/pv/toolbars/mainbar.hpp b/pv/toolbars/mainbar.hpp index d5d42f5..27c9470 100644 --- a/pv/toolbars/mainbar.hpp +++ b/pv/toolbars/mainbar.hpp @@ -28,10 +28,12 @@ #include #include +#include #include #include #include +#include #include #include @@ -62,11 +64,7 @@ private: public: MainBar(Session &session, pv::MainWindow &main_window); - void set_device_list( - const std::list< std::shared_ptr > &devices, - std::shared_ptr selected); - - std::shared_ptr get_selected_device() const; + void update_device_list(); void set_capture_state(pv::Session::capture_state state); @@ -96,8 +94,7 @@ private: Session &session_; MainWindow &main_window_; - QComboBox device_selector_; - bool updating_device_selector_; + pv::widgets::DeviceToolButton device_selector_; pv::widgets::PopupToolButton configure_button_; QAction *configure_button_action_; diff --git a/pv/widgets/devicetoolbutton.cpp b/pv/widgets/devicetoolbutton.cpp new file mode 100644 index 0000000..27ba31a --- /dev/null +++ b/pv/widgets/devicetoolbutton.cpp @@ -0,0 +1,120 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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 + */ + +#include + +#include + +#include + +#include "devicetoolbutton.hpp" + +using std::list; +using std::shared_ptr; +using std::string; +using std::weak_ptr; +using std::vector; + +using sigrok::Device; + +namespace pv { +namespace widgets { + +DeviceToolButton::DeviceToolButton(QWidget *parent, + DeviceManager &device_manager, + QAction *connect_action) : + QToolButton(parent), + device_manager_(device_manager), + connect_action_(connect_action), + menu_(this), + mapper_(this), + devices_() +{ + setPopupMode(QToolButton::MenuButtonPopup); + setMenu(&menu_); + setDefaultAction(connect_action_); + setMinimumWidth(QFontMetrics(font()).averageCharWidth() * 24); + + connect(&mapper_, SIGNAL(mapped(QObject*)), + this, SLOT(on_action(QObject*))); +} + +shared_ptr DeviceToolButton::selected_device() +{ + return selected_device_; +} + +void DeviceToolButton::set_device_list( + const list< shared_ptr > &devices, shared_ptr selected) +{ + selected_device_ = selected; + setText(QString::fromStdString( + device_manager_.get_display_name(selected))); + devices_ = vector< weak_ptr >(devices.begin(), devices.end()); + update_device_list(); +} + +void DeviceToolButton::update_device_list() +{ + menu_.clear(); + menu_.addAction(connect_action_); + menu_.setDefaultAction(connect_action_); + menu_.addSeparator(); + + for (weak_ptr dev_weak_ptr : devices_) { + shared_ptr dev(dev_weak_ptr); + if (!dev) + continue; + + QAction *const a = new QAction(QString::fromStdString( + device_manager_.get_display_name(dev)), this); + a->setCheckable(true); + a->setChecked(selected_device_ == dev); + a->setData(qVariantFromValue((void*)dev.get())); + mapper_.setMapping(a, a); + + connect(a, SIGNAL(triggered()), &mapper_, SLOT(map())); + + menu_.addAction(a); + } +} + +void DeviceToolButton::on_action(QObject *action) +{ + assert(action); + + Device *const dev = (Device*)((QAction*)action)->data().value(); + for (weak_ptr dev_weak_ptr : devices_) { + shared_ptr dev_ptr(dev_weak_ptr); + if (dev_ptr.get() == dev) { + selected_device_ = shared_ptr(dev_ptr); + break; + } + } + + update_device_list(); + setText(QString::fromStdString( + device_manager_.get_display_name(selected_device_))); + + device_selected(); +} + +} // widgets +} // pv diff --git a/pv/widgets/devicetoolbutton.hpp b/pv/widgets/devicetoolbutton.hpp new file mode 100644 index 0000000..1fb0a54 --- /dev/null +++ b/pv/widgets/devicetoolbutton.hpp @@ -0,0 +1,99 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2014 Joel Holdsworth + * + * 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_WIDGETS_DEVICETOOLBUTTON_H +#define PULSEVIEW_PV_WIDGETS_DEVICETOOLBUTTON_H + +#include +#include +#include + +#include +#include +#include +#include + +struct srd_decoder; + +namespace sigrok { +class Device; +} + +namespace pv { + +class DeviceManager; + +namespace widgets { + +class DeviceToolButton : public QToolButton +{ + Q_OBJECT; + +public: + /** + * Constructor + * @param parent the parent widget. + * @param device_manager the device manager. + * @param connect_action the connect-to-device action. + */ + DeviceToolButton(QWidget *parent, DeviceManager &device_manager, + QAction *connect_action); + + /** + * Returns a reference to the selected device. + */ + std::shared_ptr selected_device(); + + /** + * Sets the current list of devices. + * @param device the list of devices. + * @param selected_device the currently active device. + */ + void set_device_list( + const std::list< std::shared_ptr > &devices, + std::shared_ptr selected); + +private: + /** + * Repopulates the menu from the device list. + */ + void update_device_list(); + +private Q_SLOTS: + void on_action(QObject *action); + +Q_SIGNALS: + void device_selected(); + +private: + DeviceManager &device_manager_; + QAction *const connect_action_; + + QMenu menu_; + QSignalMapper mapper_; + + std::shared_ptr selected_device_; + std::vector< std::weak_ptr > devices_; +}; + +} // widgets +} // pv + +#endif // PULSEVIEW_PV_WIDGETS_DEVICETOOLBUTTON_H -- 2.30.2