X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fmainwindow.cpp;h=34938e7364cb5d827670558d903be0f6426fe0c0;hp=f0a4c0714f12075a9d5ff2e6ca317d8392859595;hb=HEAD;hpb=476ca5f48e8a528d529f36b8b0c8471c655415ad diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index f0a4c071..8646175e 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -40,6 +40,7 @@ #include "mainwindow.hpp" +#include "application.hpp" #include "devicemanager.hpp" #include "devices/hardwaredevice.hpp" #include "dialogs/settings.hpp" @@ -51,6 +52,8 @@ #ifdef ENABLE_DECODE #include "subwindows/decoder_selector/subwindow.hpp" +#include "views/decoder_binary/view.hpp" +#include "views/tabular_decoder/view.hpp" #endif #include @@ -62,10 +65,6 @@ using std::string; namespace pv { -namespace view { -class ViewItem; -} - using toolbars::MainBar; const QString MainWindow::WindowTitle = tr("PulseView"); @@ -74,21 +73,18 @@ MainWindow::MainWindow(DeviceManager &device_manager, QWidget *parent) : QMainWindow(parent), device_manager_(device_manager), session_selector_(this), - session_state_mapper_(this), icon_red_(":/icons/status-red.svg"), icon_green_(":/icons/status-green.svg"), icon_grey_(":/icons/status-grey.svg") { - GlobalSettings::add_change_handler(this); - setup_ui(); restore_ui_settings(); + connect(this, SIGNAL(session_error_raised(const QString, const QString)), + this, SLOT(on_session_error_raised(const QString, const QString))); } 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) @@ -101,7 +97,7 @@ MainWindow::~MainWindow() void MainWindow::show_session_error(const QString text, const QString info_text) { // TODO Emulate noquote() - qDebug() << "Notifying user of session error:" << info_text; + qDebug() << "Notifying user of session error: " << text << "; " << info_text; QMessageBox msg; msg.setText(text + "\n\n" + info_text); @@ -135,8 +131,8 @@ shared_ptr MainWindow::get_active_view() const return nullptr; } -shared_ptr MainWindow::add_view(const QString &title, - views::ViewType type, Session &session) +shared_ptr MainWindow::add_view(views::ViewType type, + Session &session) { GlobalSettings settings; shared_ptr v; @@ -150,6 +146,13 @@ shared_ptr MainWindow::add_view(const QString &title, shared_ptr main_bar = session.main_bar(); + // Only use the view type in the name if it's not the main view + QString title; + if (main_bar) + title = QString("%1 (%2)").arg(session.name(), views::ViewTypeNames[type]); + else + title = session.name(); + QDockWidget* dock = new QDockWidget(title, main_window); dock->setObjectName(title); main_window->addDockWidget(Qt::TopDockWidgetArea, dock); @@ -160,8 +163,13 @@ shared_ptr MainWindow::add_view(const QString &title, if (type == views::ViewTypeTrace) // This view will be the main view if there's no main bar yet - v = make_shared(session, - (main_bar ? false : true), dock_main); + v = make_shared(session, (main_bar ? false : true), dock_main); +#ifdef ENABLE_DECODE + if (type == views::ViewTypeDecoderBinary) + v = make_shared(session, false, dock_main); + if (type == views::ViewTypeTabularDecoder) + v = make_shared(session, false, dock_main); +#endif if (!v) return nullptr; @@ -187,22 +195,21 @@ shared_ptr MainWindow::add_view(const QString &title, qobject_cast(v.get()), SLOT(trigger_event(int, util::Timestamp))); + connect(&session, SIGNAL(session_error_raised(const QString, const QString)), + this, SLOT(on_session_error_raised(const QString, const QString))); + if (type == views::ViewTypeTrace) { views::trace::View *tv = qobject_cast(v.get()); - tv->enable_colored_bg(settings.value(GlobalSettings::Key_View_ColoredBG).toBool()); - tv->enable_show_sampling_points(settings.value(GlobalSettings::Key_View_ShowSamplingPoints).toBool()); - tv->enable_show_analog_minor_grid(settings.value(GlobalSettings::Key_View_ShowAnalogMinorGrid).toBool()); - if (!main_bar) { /* Initial view, create the main bar */ main_bar = make_shared(session, this, tv); dock_main->addToolBar(main_bar.get()); session.set_main_bar(main_bar); - connect(main_bar.get(), SIGNAL(new_view(Session*)), - this, SLOT(on_new_view(Session*))); + connect(main_bar.get(), SIGNAL(new_view(Session*, int)), + this, SLOT(on_new_view(Session*, int))); connect(main_bar.get(), SIGNAL(show_decoder_selector(Session*)), this, SLOT(on_show_decoder_selector(Session*))); @@ -223,6 +230,8 @@ shared_ptr MainWindow::add_view(const QString &title, } } + v->setFocus(); + return v; } @@ -258,7 +267,7 @@ shared_ptr MainWindow::add_subwindow( subwindows::SubWindowType type, Session &session) { GlobalSettings settings; - shared_ptr v; + shared_ptr w; QMainWindow *main_window = nullptr; for (auto& entry : session_windows_) @@ -289,14 +298,14 @@ shared_ptr MainWindow::add_subwindow( #ifdef ENABLE_DECODE if (type == subwindows::SubWindowTypeDecoderSelector) - v = make_shared(session, dock_main); + w = make_shared(session, dock_main); #endif - if (!v) + if (!w) return nullptr; - sub_windows_[dock] = v; - dock_main->setCentralWidget(v.get()); + sub_windows_[dock] = w; + dock_main->setCentralWidget(w.get()); dock->setWidget(dock_main); dock->setContextMenuPolicy(Qt::PreventContextMenu); @@ -307,16 +316,19 @@ shared_ptr MainWindow::add_subwindow( dock->findChildren // clazy:exclude=detaching-temporary ("qt_dockwidget_closebutton").front(); + // Allow all subwindows to be closed via ESC. + close_btn->setShortcut(QKeySequence(Qt::Key_Escape)); + 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)); + if (w->has_toolbar()) + dock_main->addToolBar(w->create_toolbar(dock_main)); - if (v->minimum_width() > 0) - dock->setMinimumSize(v->minimum_width(), 0); + if (w->minimum_width() > 0) + dock->setMinimumSize(w->minimum_width(), 0); - return v; + return w; } shared_ptr MainWindow::add_session() @@ -326,13 +338,14 @@ shared_ptr MainWindow::add_session() shared_ptr session = make_shared(device_manager_, name); - connect(session.get(), SIGNAL(add_view(const QString&, views::ViewType, Session*)), - this, SLOT(on_add_view(const QString&, views::ViewType, Session*))); + connect(session.get(), SIGNAL(add_view(ViewType, Session*)), + this, SLOT(on_add_view(ViewType, Session*))); connect(session.get(), SIGNAL(name_changed()), this, SLOT(on_session_name_changed())); - session_state_mapper_.setMapping(session.get(), session.get()); + connect(session.get(), SIGNAL(device_changed()), + this, SLOT(on_session_device_changed())); connect(session.get(), SIGNAL(capture_state_changed(int)), - &session_state_mapper_, SLOT(map())); + this, SLOT(on_session_capture_state_changed(int))); sessions_.push_back(session); @@ -346,8 +359,7 @@ shared_ptr MainWindow::add_session() window->setDockNestingEnabled(true); - shared_ptr main_view = - add_view(name, views::ViewTypeTrace, *session); + add_view(views::ViewTypeTrace, *session); return session; } @@ -476,18 +488,6 @@ void MainWindow::restore_sessions() } } -void MainWindow::on_setting_changed(const QString &key, const QVariant &value) -{ - if (key == GlobalSettings::Key_View_ColoredBG) - on_settingViewColoredBg_changed(value); - - if (key == GlobalSettings::Key_View_ShowSamplingPoints) - on_settingViewShowSamplingPoints_changed(value); - - if (key == GlobalSettings::Key_View_ShowAnalogMinorGrid) - on_settingViewShowAnalogMinorGrid_changed(value); -} - void MainWindow::setup_ui() { setObjectName(QString::fromUtf8("MainWindow")); @@ -552,17 +552,19 @@ void MainWindow::setup_ui() session_selector_.setCornerWidget(static_tab_widget_, Qt::TopLeftCorner); session_selector_.setTabsClosable(true); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + close_application_shortcut_ = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this, SLOT(close())); + close_current_tab_shortcut_ = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_W), this, SLOT(on_close_current_tab())); +#else close_application_shortcut_ = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close())); - close_application_shortcut_->setAutoRepeat(false); - close_current_tab_shortcut_ = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this, SLOT(on_close_current_tab())); +#endif + close_application_shortcut_->setAutoRepeat(false); connect(new_session_button_, SIGNAL(clicked(bool)), this, SLOT(on_new_session_clicked())); connect(run_stop_button_, SIGNAL(clicked(bool)), this, SLOT(on_run_stop_clicked())); - connect(&session_state_mapper_, SIGNAL(mapped(QObject*)), - this, SLOT(on_capture_state_changed(QObject*))); connect(settings_button_, SIGNAL(clicked(bool)), this, SLOT(on_settings_clicked())); @@ -577,6 +579,25 @@ void MainWindow::setup_ui() this, SLOT(on_focus_changed())); } +void MainWindow::update_acq_button(Session *session) +{ + int state; + QString run_caption; + + if (session) { + state = session->get_capture_state(); + run_caption = session->using_file_device() ? tr("Reload") : tr("Run"); + } else { + state = Session::Stopped; + run_caption = tr("Run"); + } + + const QIcon *icons[] = {&icon_grey_, &icon_red_, &icon_green_}; + run_stop_button_->setIcon(*icons[state]); + run_stop_button_->setText((state == pv::Session::Stopped) ? + run_caption : tr("Stop")); +} + void MainWindow::save_ui_settings() { QSettings settings; @@ -602,19 +623,6 @@ void MainWindow::restore_ui_settings() settings.endGroup(); } -void MainWindow::zoom_current_view(double steps) -{ - shared_ptr session = get_tab_session(session_selector_.currentIndex()); - - if (!session) - return; - - shared_ptr v = session.get()->main_view(); - views::trace::View *tv = - qobject_cast(v.get()); - tv->zoom(steps); -} - shared_ptr MainWindow::get_tab_session(int index) const { // Find the session that belongs to the tab's main window @@ -660,13 +668,60 @@ bool MainWindow::restoreState(const QByteArray &state, int version) return false; } -void MainWindow::on_add_view(const QString &title, views::ViewType type, - Session *session) +void MainWindow::on_run_stop_clicked() +{ + GlobalSettings settings; + bool all_sessions = settings.value(GlobalSettings::Key_General_StartAllSessions).toBool(); + + if (all_sessions) + { + vector< shared_ptr > hw_sessions; + + // Make a list of all sessions where a hardware device is used + for (const shared_ptr& s : sessions_) { + shared_ptr hw_device = + dynamic_pointer_cast< devices::HardwareDevice >(s->device()); + if (!hw_device) + continue; + hw_sessions.push_back(s); + } + + // Stop all acquisitions if there are any running ones, start all otherwise + bool any_running = any_of(hw_sessions.begin(), hw_sessions.end(), + [](const shared_ptr &s) + { return (s->get_capture_state() == Session::AwaitingTrigger) || + (s->get_capture_state() == Session::Running); }); + + for (shared_ptr s : hw_sessions) + if (any_running) + s->stop_capture(); + else + s->start_capture([&](QString message) {Q_EMIT session_error_raised("Capture failed", message);}); + } else { + + shared_ptr session = last_focused_session_; + + if (!session) + return; + + switch (session->get_capture_state()) { + case Session::Stopped: + session->start_capture([&](QString message) {Q_EMIT session_error_raised("Capture failed", message);}); + break; + case Session::AwaitingTrigger: + case Session::Running: + session->stop_capture(); + break; + } + } +} + +void MainWindow::on_add_view(views::ViewType type, Session *session) { // We get a pointer and need a reference for (shared_ptr& s : sessions_) if (s.get() == session) - add_view(title, type, *s); + add_view(type, *s); } void MainWindow::on_focus_changed() @@ -703,7 +758,7 @@ void MainWindow::on_focused_session_changed(shared_ptr session) setWindowTitle(session->name() + " - " + WindowTitle); // Update the state of the run/stop button, too - on_capture_state_changed(session.get()); + update_acq_button(session.get()); } void MainWindow::on_new_session_clicked() @@ -711,25 +766,6 @@ void MainWindow::on_new_session_clicked() add_session(); } -void MainWindow::on_run_stop_clicked() -{ - shared_ptr session = last_focused_session_; - - if (!session) - return; - - switch (session->get_capture_state()) { - case Session::Stopped: - session->start_capture([&](QString message) { - show_session_error("Capture failed", message); }); - break; - case Session::AwaitingTrigger: - case Session::Running: - session->stop_capture(); - break; - } -} - void MainWindow::on_settings_clicked() { dialogs::Settings dlg(device_manager_); @@ -764,29 +800,40 @@ void MainWindow::on_session_name_changed() setWindowTitle(session->name() + " - " + WindowTitle); } -void MainWindow::on_capture_state_changed(QObject *obj) +void MainWindow::on_session_device_changed() { - Session *caller = qobject_cast(obj); + Session *session = qobject_cast(QObject::sender()); + assert(session); // Ignore if caller is not the currently focused session // unless there is only one session - if ((sessions_.size() > 1) && (caller != last_focused_session_.get())) + if ((sessions_.size() > 1) && (session != last_focused_session_.get())) return; - int state = caller->get_capture_state(); + update_acq_button(session); +} - const QIcon *icons[] = {&icon_grey_, &icon_red_, &icon_green_}; - run_stop_button_->setIcon(*icons[state]); - run_stop_button_->setText((state == pv::Session::Stopped) ? - tr("Run") : tr("Stop")); +void MainWindow::on_session_capture_state_changed(int state) +{ + (void)state; + + Session *session = qobject_cast(QObject::sender()); + assert(session); + + // Ignore if caller is not the currently focused session + // unless there is only one session + if ((sessions_.size() > 1) && (session != last_focused_session_.get())) + return; + + update_acq_button(session); } -void MainWindow::on_new_view(Session *session) +void MainWindow::on_new_view(Session *session, int view_type) { // We get a pointer and need a reference for (shared_ptr& s : sessions_) if (s.get() == session) - add_view(session->name(), views::ViewTypeTrace, *s); + add_view((views::ViewType)view_type, *s); } void MainWindow::on_view_close_clicked() @@ -847,6 +894,9 @@ void MainWindow::on_tab_close_requested(int index) tr("This session contains unsaved data. Close it anyway?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) remove_session(session); + + if (sessions_.empty()) + update_acq_button(nullptr); } void MainWindow::on_show_decoder_selector(Session *session) @@ -869,6 +919,8 @@ void MainWindow::on_show_decoder_selector(Session *session) for (shared_ptr& s : sessions_) if (s.get() == session) add_subwindow(subwindows::SubWindowTypeDecoderSelector, *s); +#else + (void)session; #endif } @@ -887,6 +939,10 @@ void MainWindow::on_sub_window_close_clicked() sub_windows_.erase(dock); dock->close(); + + // Restore focus to the last used main view + if (last_focused_session_) + last_focused_session_->main_view()->setFocus(); } void MainWindow::on_view_colored_bg_shortcut() @@ -921,51 +977,6 @@ void MainWindow::on_view_show_analog_minor_grid_shortcut() settings.setValue(GlobalSettings::Key_View_ShowAnalogMinorGrid, !state); } -void MainWindow::on_settingViewColoredBg_changed(const QVariant new_value) -{ - bool state = new_value.toBool(); - - for (auto& entry : view_docks_) { - shared_ptr viewbase = entry.second; - - // Only trace views have this setting - views::trace::View* view = - qobject_cast(viewbase.get()); - if (view) - view->enable_colored_bg(state); - } -} - -void MainWindow::on_settingViewShowSamplingPoints_changed(const QVariant new_value) -{ - bool state = new_value.toBool(); - - for (auto& entry : view_docks_) { - shared_ptr viewbase = entry.second; - - // Only trace views have this setting - views::trace::View* view = - qobject_cast(viewbase.get()); - if (view) - view->enable_show_sampling_points(state); - } -} - -void MainWindow::on_settingViewShowAnalogMinorGrid_changed(const QVariant new_value) -{ - bool state = new_value.toBool(); - - for (auto& entry : view_docks_) { - shared_ptr viewbase = entry.second; - - // Only trace views have this setting - views::trace::View* view = - qobject_cast(viewbase.get()); - if (view) - view->enable_show_analog_minor_grid(state); - } -} - void MainWindow::on_close_current_tab() { int tab = session_selector_.currentIndex(); @@ -973,4 +984,8 @@ void MainWindow::on_close_current_tab() on_tab_close_requested(tab); } +void MainWindow::on_session_error_raised(const QString text, const QString info_text) { + MainWindow::show_session_error(text, info_text); +} + } // namespace pv