X-Git-Url: http://git.code-monkey.de/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fmainwindow.cpp;h=d07d3316afb3632a5b9e828c122330851d5f9918;hp=25377024278ca8f7475a572c3d9867d7a64efdb8;hb=97378470ded88af84edaa0f1063d10d834475665;hpb=fe060a4874fc72655cced0596ef610a13f5b0413 diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index 2537702..d07d331 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -44,6 +44,7 @@ #include "devices/hardwaredevice.hpp" #include "dialogs/settings.hpp" #include "globalsettings.hpp" +#include "subwindows/decoder_selector/subwindow.hpp" #include "toolbars/mainbar.hpp" #include "util.hpp" #include "views/trace/view.hpp" @@ -75,9 +76,6 @@ MainWindow::MainWindow(DeviceManager &device_manager, QWidget *parent) : icon_green_(":/icons/status-green.svg"), icon_grey_(":/icons/status-grey.svg") { - qRegisterMetaType("util::Timestamp"); - qRegisterMetaType("uint64_t"); - GlobalSettings::add_change_handler(this); setup_ui(); @@ -88,8 +86,13 @@ MainWindow::~MainWindow() { GlobalSettings::remove_change_handler(this); + // Make sure we no longer hold any shared pointers to widgets after the + // destructor finishes (goes for sessions and sub windows alike) + while (!sessions_.empty()) remove_session(sessions_.front()); + + sub_windows_.clear(); } void MainWindow::show_session_error(const QString text, const QString info_text) @@ -98,8 +101,7 @@ void MainWindow::show_session_error(const QString text, const QString info_text) qDebug() << "Notifying user of session error:" << info_text; QMessageBox msg; - msg.setText(text); - msg.setInformativeText(info_text); + msg.setText(text + "\n\n" + info_text); msg.setStandardButtons(QMessageBox::Ok); msg.setIcon(QMessageBox::Warning); msg.exec(); @@ -123,7 +125,7 @@ shared_ptr MainWindow::get_active_view() const } // Get the view contained in the dock widget - for (auto entry : view_docks_) + for (auto& entry : view_docks_) if (entry.first == dock) return entry.second; @@ -137,7 +139,7 @@ shared_ptr MainWindow::add_view(const QString &title, shared_ptr v; QMainWindow *main_window = nullptr; - for (auto entry : session_windows_) + for (auto& entry : session_windows_) if (entry.first.get() == &session) main_window = entry.second; @@ -172,8 +174,8 @@ shared_ptr MainWindow::add_view(const QString &title, QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); QAbstractButton *close_btn = - dock->findChildren - ("qt_dockwidget_closebutton").front(); + dock->findChildren("qt_dockwidget_closebutton") // clazy:exclude=detaching-temporary + .front(); connect(close_btn, SIGNAL(clicked(bool)), this, SLOT(on_view_close_clicked())); @@ -198,6 +200,8 @@ shared_ptr MainWindow::add_view(const QString &title, connect(main_bar.get(), SIGNAL(new_view(Session*)), this, SLOT(on_new_view(Session*))); + connect(main_bar.get(), SIGNAL(show_decoder_selector(Session*)), + this, SLOT(on_show_decoder_selector(Session*))); main_bar->action_view_show_cursors()->setChecked(tv->cursors_shown()); @@ -226,7 +230,7 @@ void MainWindow::remove_view(shared_ptr view) continue; // Find the dock the view is contained in and remove it - for (auto entry : view_docks_) + for (auto& entry : view_docks_) if (entry.second == view) { // Remove the view from the session session->deregister_view(view); @@ -247,6 +251,61 @@ void MainWindow::remove_view(shared_ptr view) } } +shared_ptr MainWindow::add_subwindow( + subwindows::SubWindowType type, Session &session) +{ + GlobalSettings settings; + shared_ptr v; + + QMainWindow *main_window = nullptr; + for (auto entry : session_windows_) + if (entry.first.get() == &session) + main_window = entry.second; + + assert(main_window); + + QString title = ""; + + switch (type) { + case subwindows::SubWindowTypeDecoderSelector: + title = tr("Decoder Selector"); + } + + QDockWidget* dock = new QDockWidget(title, main_window); + dock->setObjectName(title); + main_window->addDockWidget(Qt::TopDockWidgetArea, dock); + + // Insert a QMainWindow into the dock widget to allow for a tool bar + QMainWindow *dock_main = new QMainWindow(dock); + dock_main->setWindowFlags(Qt::Widget); // Remove Qt::Window flag + + if (type == subwindows::SubWindowTypeDecoderSelector) + v = make_shared(session, dock_main); + + if (!v) + return nullptr; + + sub_windows_[dock] = v; + dock_main->setCentralWidget(v.get()); + dock->setWidget(dock_main); + + dock->setContextMenuPolicy(Qt::PreventContextMenu); + dock->setFeatures(QDockWidget::DockWidgetMovable | + QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); + + QAbstractButton *close_btn = + dock->findChildren + ("qt_dockwidget_closebutton").front(); + + connect(close_btn, SIGNAL(clicked(bool)), + this, SLOT(on_sub_window_close_clicked())); + + if (v->has_toolbar()) + dock_main->addToolBar(v->create_toolbar(dock_main)); + + return v; +} + shared_ptr MainWindow::add_session() { static int last_session_id = 1; @@ -294,7 +353,7 @@ void MainWindow::remove_session(shared_ptr session) session->stop_capture(); QApplication::processEvents(); - for (shared_ptr view : session->views()) + for (const shared_ptr& view : session->views()) remove_view(view); QMainWindow *window = session_windows_.at(session); @@ -313,7 +372,7 @@ void MainWindow::remove_session(shared_ptr session) // When there are no more tabs, the height of the QTabWidget // drops to zero. We must prevent this to keep the static // widgets visible - for (QWidget *w : static_tab_widget_->findChildren()) + for (QWidget *w : static_tab_widget_->findChildren()) // clazy:exclude=range-loop w->setMinimumHeight(h); int margin = static_tab_widget_->layout()->contentsMargins().bottom(); @@ -346,7 +405,7 @@ void MainWindow::add_default_session() // one of the auto detected devices that are not the demo device. // Pick demo in the absence of "genuine" hardware devices. shared_ptr user_device, other_device, demo_device; - for (shared_ptr dev : device_manager_.devices()) { + for (const shared_ptr& dev : device_manager_.devices()) { if (dev == device_manager_.user_spec_device()) { user_device = dev; } else if (dev->hardware_device()->driver()->name() == "demo") { @@ -368,7 +427,7 @@ void MainWindow::save_sessions() QSettings settings; int id = 0; - for (shared_ptr session : sessions_) { + for (shared_ptr& session : sessions_) { // Ignore sessions using the demo device or no device at all if (session->device()) { shared_ptr device = @@ -532,7 +591,7 @@ void MainWindow::restore_ui_settings() shared_ptr MainWindow::get_tab_session(int index) const { // Find the session that belongs to the tab's main window - for (auto entry : session_windows_) + for (auto& entry : session_windows_) if (entry.second == session_selector_.widget(index)) return entry.first; @@ -543,7 +602,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { bool data_saved = true; - for (auto entry : session_windows_) + for (auto& entry : session_windows_) if (!entry.first->data_saved()) data_saved = false; @@ -578,7 +637,7 @@ void MainWindow::on_add_view(const QString &title, views::ViewType type, Session *session) { // We get a pointer and need a reference - for (shared_ptr s : sessions_) + for (shared_ptr& s : sessions_) if (s.get() == session) add_view(title, type, *s); } @@ -656,9 +715,9 @@ void MainWindow::on_session_name_changed() Session *session = qobject_cast(QObject::sender()); assert(session); - for (shared_ptr view : session->views()) { + for (const shared_ptr& view : session->views()) { // Get the dock that contains the view - for (auto entry : view_docks_) + for (auto& entry : view_docks_) if (entry.second == view) { entry.first->setObjectName(session->name()); entry.first->setWindowTitle(session->name()); @@ -666,7 +725,7 @@ void MainWindow::on_session_name_changed() } // Update the tab widget by finding the main window and the tab from that - for (auto entry : session_windows_) + for (auto& entry : session_windows_) if (entry.first.get() == session) { QMainWindow *window = entry.second; const int index = session_selector_.indexOf(window); @@ -698,7 +757,7 @@ void MainWindow::on_capture_state_changed(QObject *obj) void MainWindow::on_new_view(Session *session) { // We get a pointer and need a reference - for (shared_ptr s : sessions_) + for (shared_ptr& s : sessions_) if (s.get() == session) add_view(session->name(), views::ViewTypeTrace, *s); } @@ -719,7 +778,7 @@ void MainWindow::on_view_close_clicked() // Get the view contained in the dock widget shared_ptr view; - for (auto entry : view_docks_) + for (auto& entry : view_docks_) if (entry.first == dock) view = entry.second; @@ -763,6 +822,41 @@ void MainWindow::on_tab_close_requested(int index) remove_session(session); } +void MainWindow::on_show_decoder_selector(Session *session) +{ + // Close dock widget if it's already showing and return + for (auto entry : sub_windows_) { + QDockWidget* dock = entry.first; + if (dynamic_pointer_cast(entry.second)) { + sub_windows_.erase(dock); + dock->close(); + return; + } + } + + // We get a pointer and need a reference + for (shared_ptr s : sessions_) + if (s.get() == session) + add_subwindow(subwindows::SubWindowTypeDecoderSelector, *s); +} + +void MainWindow::on_sub_window_close_clicked() +{ + // Find the dock widget that contains the close button that was clicked + QObject *w = QObject::sender(); + QDockWidget *dock = nullptr; + + while (w) { + dock = qobject_cast(w); + if (dock) + break; + w = w->parent(); + } + + sub_windows_.erase(dock); + dock->close(); +} + void MainWindow::on_view_colored_bg_shortcut() { GlobalSettings settings; @@ -799,7 +893,7 @@ void MainWindow::on_settingViewColoredBg_changed(const QVariant new_value) { bool state = new_value.toBool(); - for (auto entry : view_docks_) { + for (auto& entry : view_docks_) { shared_ptr viewbase = entry.second; // Only trace views have this setting @@ -814,7 +908,7 @@ void MainWindow::on_settingViewShowSamplingPoints_changed(const QVariant new_val { bool state = new_value.toBool(); - for (auto entry : view_docks_) { + for (auto& entry : view_docks_) { shared_ptr viewbase = entry.second; // Only trace views have this setting @@ -829,7 +923,7 @@ void MainWindow::on_settingViewShowAnalogMinorGrid_changed(const QVariant new_va { bool state = new_value.toBool(); - for (auto entry : view_docks_) { + for (auto& entry : view_docks_) { shared_ptr viewbase = entry.second; // Only trace views have this setting