]> sigrok.org Git - pulseview.git/commitdiff
MainBar: Replaced device selector combo-box with a split button
authorJoel Holdsworth <redacted>
Sat, 10 Jan 2015 16:45:55 +0000 (16:45 +0000)
committerJoel Holdsworth <redacted>
Sat, 10 Jan 2015 16:54:01 +0000 (16:54 +0000)
CMakeLists.txt
pv/mainwindow.cpp
pv/mainwindow.hpp
pv/toolbars/mainbar.cpp
pv/toolbars/mainbar.hpp
pv/widgets/devicetoolbutton.cpp [new file with mode: 0644]
pv/widgets/devicetoolbutton.hpp [new file with mode: 0644]

index ddabe2e86de0a1c7226955936946b75f63aacd92..3e621a1f04a08726ce863b86017e862ec841f26b 100644 (file)
@@ -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
index a7dd773666fba9aec90f861dacc2f4935499859b..dc9e7de5be8589ce8f0f23244bbc7fae03c36ae9 100644 (file)
@@ -438,23 +438,7 @@ void MainWindow::session_error(
 
 void MainWindow::update_device_list()
 {
-       assert(main_bar_);
-
-       shared_ptr<Device> selected_device = session_.device();
-       list< shared_ptr<Device> > 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)
index 84245e0ec117c279814faeb7decffdbc03642963..2e6e55c1d1dee53bbb12c796bbd3d6c28a1e7046 100644 (file)
@@ -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();
 
index 82b5fab04dc097cdaebfcb2f62dc19ff34164a1b..50a90643d71f406919172827350318a8517b5056 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the PulseView project.
  *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ * Copyright (C) 2012-2015 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
@@ -20,7 +20,8 @@
 
 #include <extdef.h>
 
-#include <assert.h>
+#include <algorithm>
+#include <cassert>
 
 #include <QAction>
 #include <QDebug>
 
 #include <libsigrok/libsigrok.hpp>
 
+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<sigrok::Device> > &devices,
-       shared_ptr<Device> 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<Device> selected_device = session_.device();
+       list< shared_ptr<Device> > 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<Device> MainBar::get_selected_device() const
-{
-       const int index = device_selector_.currentIndex();
-       if (index < 0)
-               return shared_ptr<Device>();
-
-       return device_selector_.itemData(index).value<shared_ptr<Device>>();
-}
 
 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       const shared_ptr<Device> 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> device = get_selected_device();
+       shared_ptr<Device> device = device_selector_.selected_device();
        if (!device)
                return;
 
index d5d42f5080497840eafc95db258f1ea19e4ca628..27c947007584c10675161a2814210b3f1a4bdaf5 100644 (file)
 
 #include <QComboBox>
 #include <QDoubleSpinBox>
+#include <QMenu>
 #include <QToolBar>
 #include <QToolButton>
 
 #include <pv/session.hpp>
+#include <pv/widgets/devicetoolbutton.hpp>
 #include <pv/widgets/popuptoolbutton.hpp>
 #include <pv/widgets/sweeptimingwidget.hpp>
 
@@ -62,11 +64,7 @@ private:
 public:
        MainBar(Session &session, pv::MainWindow &main_window);
 
-       void set_device_list(
-               const std::list< std::shared_ptr<sigrok::Device> > &devices,
-               std::shared_ptr<sigrok::Device> selected);
-
-       std::shared_ptr<sigrok::Device> 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 (file)
index 0000000..27ba31a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2015 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
+ */
+
+#include <cassert>
+
+#include <libsigrok/libsigrok.hpp>
+
+#include <pv/devicemanager.hpp>
+
+#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<Device> DeviceToolButton::selected_device()
+{
+       return selected_device_;
+}
+
+void DeviceToolButton::set_device_list(
+       const list< shared_ptr<Device> > &devices, shared_ptr<Device> selected)
+{
+       selected_device_ = selected;
+       setText(QString::fromStdString(
+               device_manager_.get_display_name(selected)));
+       devices_ = vector< weak_ptr<Device> >(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<Device> dev_weak_ptr : devices_) {
+               shared_ptr<Device> 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<void*>();
+       for (weak_ptr<Device> dev_weak_ptr : devices_) {
+               shared_ptr<Device> dev_ptr(dev_weak_ptr);
+               if (dev_ptr.get() == dev) {
+                       selected_device_ = shared_ptr<Device>(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 (file)
index 0000000..1fb0a54
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2014 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_WIDGETS_DEVICETOOLBUTTON_H
+#define PULSEVIEW_PV_WIDGETS_DEVICETOOLBUTTON_H
+
+#include <list>
+#include <memory>
+#include <vector>
+
+#include <QAction>
+#include <QMenu>
+#include <QSignalMapper>
+#include <QToolButton>
+
+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<sigrok::Device> 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<sigrok::Device> > &devices,
+               std::shared_ptr<sigrok::Device> 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<sigrok::Device> selected_device_;
+       std::vector< std::weak_ptr<sigrok::Device> > devices_;
+};
+
+} // widgets
+} // pv
+
+#endif // PULSEVIEW_PV_WIDGETS_DEVICETOOLBUTTON_H