X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fmainwindow.cpp;h=f64345cc532f9d33af4684ad1d7da43046aee7ce;hp=f8463257b5b882531692abc3c0ab4803efdcfa64;hb=f4e57597347e47a4ea58fbdc7b0a22e07f1c0ede;hpb=0f8f8c180b32413177f3940ea6f216d1cbadf09b diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index f8463257..f64345cc 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -38,6 +38,7 @@ #include "devicemanager.hpp" #include "util.hpp" +#include "devices/hardwaredevice.hpp" #include "dialogs/about.hpp" #include "toolbars/mainbar.hpp" #include "view/view.hpp" @@ -46,6 +47,7 @@ #include #include +using std::dynamic_pointer_cast; using std::list; using std::make_shared; using std::map; @@ -60,14 +62,13 @@ class ViewItem; using toolbars::MainBar; +const QString MainWindow::WindowTitle = tr("PulseView"); + MainWindow::MainWindow(DeviceManager &device_manager, string open_file_name, string open_file_format, QWidget *parent) : QMainWindow(parent), device_manager_(device_manager), - session_(device_manager), - open_file_name_(open_file_name), - open_file_format_(open_file_format), action_view_sticky_scrolling_(new QAction(this)), action_view_coloured_bg_(new QAction(this)), action_about_(new QAction(this)) @@ -76,6 +77,32 @@ MainWindow::MainWindow(DeviceManager &device_manager, setup_ui(); restore_ui_settings(); + + if (!open_file_name.empty()) { + shared_ptr session = add_session(); + session->main_bar()->load_init_file(open_file_name, open_file_format); + } + + // Add empty default session if there aren't any sessions + if (sessions_.size() == 0) { + shared_ptr session = add_session(); + + map dev_info; + shared_ptr other_device, demo_device; + + // Use any available device that's not demo + for (shared_ptr dev : device_manager_.devices()) { + if (dev->hardware_device()->driver()->name() == "demo") { + demo_device = dev; + } else { + other_device = dev; + } + } + + // ...and if there isn't any, just use demo then + session->main_bar()->select_device(other_device ? + other_device : demo_device); + } } MainWindow::~MainWindow() @@ -91,8 +118,11 @@ MainWindow::~MainWindow() // Remove the QMainWindow dock->setWidget(0); - const std::shared_ptr view = entry.second; - session_.deregister_view(view); + const std::shared_ptr view = entry.second; + + for (shared_ptr session : sessions_) + if (session->has_view(view)) + session->deregister_view(view); } } @@ -111,7 +141,7 @@ QAction* MainWindow::action_about() const return action_about_; } -shared_ptr MainWindow::get_active_view() const +shared_ptr MainWindow::get_active_view() const { // If there's only one view, use it... if (view_docks_.size() == 1) @@ -133,15 +163,13 @@ shared_ptr MainWindow::get_active_view() const if (entry.first.get() == dock) return entry.second; - return shared_ptr(); + return nullptr; } -shared_ptr MainWindow::add_view(const QString &title, - view::ViewType type, Session &session) +shared_ptr MainWindow::add_view(const QString &title, + views::ViewType type, Session &session) { - shared_ptr v; - - if (type == pv::view::TraceView) { + if (type == views::ViewTypeTrace) { shared_ptr dock = make_shared(title, this); dock->setObjectName(title); addDockWidget(Qt::TopDockWidgetArea, dock.get()); @@ -150,7 +178,8 @@ shared_ptr MainWindow::add_view(const QString &title, QMainWindow *dock_main = new QMainWindow(dock.get()); dock_main->setWindowFlags(Qt::Widget); // Remove Qt::Window flag - v = make_shared(session, dock_main); + shared_ptr v = + make_shared(session, dock_main); view_docks_[dock] = v; session.register_view(v); @@ -158,34 +187,82 @@ shared_ptr MainWindow::add_view(const QString &title, dock->setWidget(dock_main); dock->setFeatures(QDockWidget::DockWidgetMovable | - QDockWidget::DockWidgetFloatable); + QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); + + QAbstractButton *close_btn = + dock->findChildren + ("qt_dockwidget_closebutton").front(); + + connect(close_btn, SIGNAL(clicked(bool)), + this, SLOT(on_view_close_clicked())); - if (type == view::TraceView) { - connect(&session, SIGNAL(trigger_event(util::Timestamp)), v.get(), + if (type == views::ViewTypeTrace) { + connect(&session, SIGNAL(trigger_event(util::Timestamp)), + qobject_cast(v.get()), SLOT(trigger_event(util::Timestamp))); - connect(v.get(), SIGNAL(sticky_scrolling_changed(bool)), this, - SLOT(sticky_scrolling_changed(bool))); - connect(v.get(), SIGNAL(always_zoom_to_fit_changed(bool)), this, - SLOT(always_zoom_to_fit_changed(bool))); v->enable_sticky_scrolling(action_view_sticky_scrolling_->isChecked()); v->enable_coloured_bg(action_view_coloured_bg_->isChecked()); shared_ptr main_bar = session.main_bar(); if (!main_bar) { - main_bar = make_shared(session_, *this, - open_file_name_, open_file_format_); + main_bar = make_shared(session, *this); dock_main->addToolBar(main_bar.get()); session.set_main_bar(main_bar); - open_file_name_.clear(); - open_file_format_.clear(); + connect(main_bar.get(), SIGNAL(new_session()), + this, SLOT(on_new_session())); + connect(main_bar.get(), SIGNAL(new_view(Session*)), + this, SLOT(on_new_view(Session*))); } main_bar->action_view_show_cursors()->setChecked(v->cursors_shown()); + + connect(v.get(), SIGNAL(always_zoom_to_fit_changed(bool)), + main_bar.get(), SLOT(on_always_zoom_to_fit_changed(bool))); } + + return v; + } + + return nullptr; +} + +shared_ptr MainWindow::add_session() +{ + static int last_session_id = 1; + QString name = tr("Untitled-%1").arg(last_session_id++); + + 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(name_changed()), + this, SLOT(on_session_name_changed())); + + sessions_.push_back(session); + + shared_ptr main_view = + add_view(name, views::ViewTypeTrace, *session); + + return session; +} + +void MainWindow::remove_session(shared_ptr session) +{ + for (shared_ptr view : session->views()) { + // Find the dock the view is contained in and close it + for (auto entry : view_docks_) + if (entry.second == view) + entry.first->close(); } - return v; + sessions_.remove_if([&](shared_ptr s) { + return s == session; }); + + // Update the window title if there is no view left to + // generate focus change events + if (sessions_.empty()) + setWindowTitle(WindowTitle); } void MainWindow::setup_ui() @@ -214,52 +291,48 @@ void MainWindow::setup_ui() action_about_->setObjectName(QString::fromUtf8("actionAbout")); action_about_->setText(tr("&About...")); - // Set up the initial view - shared_ptr main_view = - add_view(tr("Untitled"), pv::view::TraceView, session_); + setDockNestingEnabled(true); - // Set the title - setWindowTitle(tr("PulseView")); + connect(static_cast(QCoreApplication::instance()), + SIGNAL(focusChanged(QWidget*, QWidget*)), + this, SLOT(on_focus_changed())); } void MainWindow::save_ui_settings() { QSettings settings; - - map dev_info; - list key_list; + int id = 0; settings.beginGroup("MainWindow"); settings.setValue("state", saveState()); settings.setValue("geometry", saveGeometry()); settings.endGroup(); - if (session_.device()) { - settings.beginGroup("Device"); - key_list.push_back("vendor"); - key_list.push_back("model"); - key_list.push_back("version"); - key_list.push_back("serial_num"); - key_list.push_back("connection_id"); - - dev_info = device_manager_.get_device_info( - session_.device()); - - for (string key : key_list) { - if (dev_info.count(key)) - settings.setValue(QString::fromUtf8(key.c_str()), - QString::fromUtf8(dev_info.at(key).c_str())); - else - settings.remove(QString::fromUtf8(key.c_str())); + for (shared_ptr session : sessions_) { + // Ignore sessions using the demo device or no device at all + if (session->device()) { + shared_ptr device = + dynamic_pointer_cast< devices::HardwareDevice > + (session->device()); + + if (device && + device->hardware_device()->driver()->name() == "demo") + continue; + + settings.beginGroup("Session" + QString::number(id++)); + settings.remove(""); // Remove all keys in this group + session->save_settings(settings); + settings.endGroup(); } - - settings.endGroup(); } + + settings.setValue("sessions", id); } void MainWindow::restore_ui_settings() { QSettings settings; + int i, session_count; settings.beginGroup("MainWindow"); @@ -270,6 +343,15 @@ void MainWindow::restore_ui_settings() resize(1000, 720); settings.endGroup(); + + session_count = settings.value("sessions", 0).toInt(); + + for (i = 0; i < session_count; i++) { + settings.beginGroup("Session" + QString::number(i)); + shared_ptr session = add_session(); + session->restore_settings(settings); + settings.endGroup(); + } } void MainWindow::closeEvent(QCloseEvent *event) @@ -294,16 +376,114 @@ bool MainWindow::restoreState(const QByteArray &state, int version) return false; } +void MainWindow::on_add_view(const QString &title, views::ViewType type, + Session *session) +{ + // We get a pointer and need a reference + for (std::shared_ptr s : sessions_) + if (s.get() == session) + add_view(title, type, *s); +} + +void MainWindow::on_focus_changed() +{ + shared_ptr view; + bool title_set = false; + + view = get_active_view(); + + for (shared_ptr session : sessions_) { + if (!session->has_view(view)) + continue; + + setWindowTitle(session->name() + " - " + WindowTitle); + title_set = true; + } + + if (!title_set) + setWindowTitle(WindowTitle); +} + +void MainWindow::on_new_session() +{ + add_session(); +} + +void MainWindow::on_session_name_changed() +{ + // Update the corresponding dock widget's name(s) + Session *session = qobject_cast(QObject::sender()); + assert(session); + + for (shared_ptr view : session->views()) { + // Get the dock that contains the view + for (auto entry : view_docks_) + if (entry.second == view) { + entry.first->setObjectName(session->name()); + entry.first->setWindowTitle(session->name()); + } + } + + // Refresh window title if the affected session has focus + on_focus_changed(); +} + +void MainWindow::on_new_view(Session *session) +{ + // We get a pointer and need a reference + for (std::shared_ptr s : sessions_) + if (s.get() == session) + add_view(session->name(), views::ViewTypeTrace, *s); +} + +void MainWindow::on_view_close_clicked() +{ + // Find the dock widget that contains the close button that was clicked + QObject *w = QObject::sender(); + QDockWidget *dock = 0; + + while (w) { + dock = qobject_cast(w); + if (dock) + break; + w = w->parent(); + } + + // Get the view contained in the dock widget + shared_ptr view; + + for (auto entry : view_docks_) + if (entry.first.get() == dock) + view = entry.second; + + // Deregister the view + for (shared_ptr session : sessions_) { + if (!session->has_view(view)) + continue; + + // Also destroy the entire session if its main view is closing + if (view == session->main_view()) { + remove_session(session); + break; + } else + session->deregister_view(view); + } +} + void MainWindow::on_actionViewStickyScrolling_triggered() { - shared_ptr view = get_active_view(); + shared_ptr viewbase = get_active_view(); + views::TraceView::View* view = + qobject_cast(viewbase.get()); if (view) view->enable_sticky_scrolling(action_view_sticky_scrolling_->isChecked()); } void MainWindow::on_actionViewColouredBg_triggered() { - shared_ptr view = get_active_view(); + shared_ptr viewbase = get_active_view(); + views::TraceView::View* view = + qobject_cast(viewbase.get()); if (view) view->enable_coloured_bg(action_view_coloured_bg_->isChecked()); }