X-Git-Url: http://git.code-monkey.de/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fmainwindow.cpp;h=f8463257b5b882531692abc3c0ab4803efdcfa64;hp=b3377f7ab9154208bad84f8fbbc6750c6c1df046;hb=0f8f8c180b32413177f3940ea6f216d1cbadf09b;hpb=238b21f366aa9ac71e2801cfa7ef7e16ba8b390d diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index b3377f7..f846325 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -27,66 +27,30 @@ #include #include -#include - #include #include -#include #include -#include -#include -#include -#include +#include #include -#include -#include #include -#include - #include "mainwindow.hpp" #include "devicemanager.hpp" #include "util.hpp" -#include "data/segment.hpp" -#include "devices/hardwaredevice.hpp" -#include "devices/inputfile.hpp" -#include "devices/sessionfile.hpp" #include "dialogs/about.hpp" -#include "dialogs/connect.hpp" -#include "dialogs/inputoutputoptions.hpp" -#include "dialogs/storeprogress.hpp" #include "toolbars/mainbar.hpp" -#include "view/logicsignal.hpp" #include "view/view.hpp" -#include "widgets/exportmenu.hpp" -#include "widgets/importmenu.hpp" -#ifdef ENABLE_DECODE -#include "widgets/decodermenu.hpp" -#endif -#include #include #include -#include #include -using std::cerr; -using std::endl; using std::list; using std::make_shared; using std::map; -using std::max; -using std::pair; using std::shared_ptr; using std::string; -using std::vector; - -using boost::algorithm::join; - -using sigrok::Error; -using sigrok::OutputFormat; -using sigrok::InputFormat; namespace pv { @@ -94,8 +58,7 @@ namespace view { class ViewItem; } -const char *MainWindow::SettingOpenDirectory = "MainWindow/OpenDirectory"; -const char *MainWindow::SettingSaveDirectory = "MainWindow/SaveDirectory"; +using toolbars::MainBar; MainWindow::MainWindow(DeviceManager &device_manager, string open_file_name, string open_file_format, @@ -103,88 +66,36 @@ MainWindow::MainWindow(DeviceManager &device_manager, QMainWindow(parent), device_manager_(device_manager), session_(device_manager), - action_open_(new QAction(this)), - action_save_as_(new QAction(this)), - action_save_selection_as_(new QAction(this)), - action_connect_(new QAction(this)), - action_quit_(new QAction(this)), - action_view_zoom_in_(new QAction(this)), - action_view_zoom_out_(new QAction(this)), - action_view_zoom_fit_(new QAction(this)), - action_view_zoom_one_to_one_(new QAction(this)), + 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_view_show_cursors_(new QAction(this)), action_about_(new QAction(this)) -#ifdef ENABLE_DECODE - , menu_decoders_add_(new pv::widgets::DecoderMenu(this, true)) -#endif { qRegisterMetaType("util::Timestamp"); setup_ui(); restore_ui_settings(); - if (open_file_name.empty()) - select_init_device(); - else - load_init_file(open_file_name, open_file_format); } MainWindow::~MainWindow() { for (auto entry : view_docks_) { + const std::shared_ptr dock = entry.first; + + // Remove view from the dock widget's QMainWindow + QMainWindow *dock_main = dynamic_cast(dock->widget()); + dock_main->setCentralWidget(0); + + // Remove the QMainWindow dock->setWidget(0); + const std::shared_ptr view = entry.second; session_.deregister_view(view); } } -QAction* MainWindow::action_open() const -{ - return action_open_; -} - -QAction* MainWindow::action_save_as() const -{ - return action_save_as_; -} - -QAction* MainWindow::action_save_selection_as() const -{ - return action_save_selection_as_; -} - -QAction* MainWindow::action_connect() const -{ - return action_connect_; -} - -QAction* MainWindow::action_quit() const -{ - return action_quit_; -} - -QAction* MainWindow::action_view_zoom_in() const -{ - return action_view_zoom_in_; -} - -QAction* MainWindow::action_view_zoom_out() const -{ - return action_view_zoom_out_; -} - -QAction* MainWindow::action_view_zoom_fit() const -{ - return action_view_zoom_fit_; -} - -QAction* MainWindow::action_view_zoom_one_to_one() const -{ - return action_view_zoom_one_to_one_; -} - QAction* MainWindow::action_view_sticky_scrolling() const { return action_view_sticky_scrolling_; @@ -195,23 +106,11 @@ QAction* MainWindow::action_view_coloured_bg() const return action_view_coloured_bg_; } -QAction* MainWindow::action_view_show_cursors() const -{ - return action_view_show_cursors_; -} - QAction* MainWindow::action_about() const { return action_about_; } -#ifdef ENABLE_DECODE -QMenu* MainWindow::menu_decoder_add() const -{ - return menu_decoders_add_; -} -#endif - shared_ptr MainWindow::get_active_view() const { // If there's only one view, use it... @@ -242,15 +141,21 @@ shared_ptr MainWindow::add_view(const QString &title, { shared_ptr v; - if (type == pv::view::TraceView) - v = make_shared(session, this); - - if (v) { + if (type == pv::view::TraceView) { shared_ptr dock = make_shared(title, this); - dock->setWidget(v.get()); dock->setObjectName(title); addDockWidget(Qt::TopDockWidgetArea, dock.get()); + + // Insert a QMainWindow into the dock widget to allow for a tool bar + QMainWindow *dock_main = new QMainWindow(dock.get()); + dock_main->setWindowFlags(Qt::Widget); // Remove Qt::Window flag + + v = make_shared(session, dock_main); view_docks_[dock] = v; + session.register_view(v); + + dock_main->setCentralWidget(v.get()); + dock->setWidget(dock_main); dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); @@ -265,168 +170,22 @@ shared_ptr MainWindow::add_view(const QString &title, v->enable_sticky_scrolling(action_view_sticky_scrolling_->isChecked()); v->enable_coloured_bg(action_view_coloured_bg_->isChecked()); - action_view_show_cursors_->setChecked(v->cursors_shown()); - } - - session.register_view(v); - } - - return v; -} -void MainWindow::run_stop() -{ - switch (session_.get_capture_state()) { - case Session::Stopped: - session_.start_capture([&](QString message) { - session_error("Capture failed", message); }); - break; - case Session::AwaitingTrigger: - case Session::Running: - session_.stop_capture(); - break; - } -} - -void MainWindow::select_device(shared_ptr device) -{ - try { - if (device) - session_.set_device(device); - else - session_.set_default_device(); - } catch (const QString &e) { - QMessageBox msg(this); - msg.setText(e); - msg.setInformativeText(tr("Failed to Select Device")); - msg.setStandardButtons(QMessageBox::Ok); - msg.setIcon(QMessageBox::Warning); - msg.exec(); - } -} - -void MainWindow::export_file(shared_ptr format, - bool selection_only) -{ - using pv::dialogs::StoreProgress; - - // Make sure there's a view selected to pull the data from - shared_ptr view = get_active_view(); - if (!view) { - show_session_error(tr("No View Selected"), tr("Please click on the " \ - "view whose data you want to save and try again.")); - return; - } - - // Stop any currently running capture session - session_.stop_capture(); - - QSettings settings; - const QString dir = settings.value(SettingSaveDirectory).toString(); - - std::pair sample_range; - - // Selection only? Verify that the cursors are active and fetch their values - if (selection_only) { - if (!view->cursors()->enabled()) { - show_session_error(tr("Missing Cursors"), tr("You need to set the " \ - "cursors before you can save the data enclosed by them " \ - "to a session file (e.g. using ALT-V - Show Cursors).")); - return; + shared_ptr main_bar = session.main_bar(); + if (!main_bar) { + main_bar = make_shared(session_, *this, + open_file_name_, open_file_format_); + dock_main->addToolBar(main_bar.get()); + session.set_main_bar(main_bar); + + open_file_name_.clear(); + open_file_format_.clear(); + } + main_bar->action_view_show_cursors()->setChecked(v->cursors_shown()); } - - const double samplerate = session_.get_samplerate(); - - const pv::util::Timestamp& start_time = view->cursors()->first()->time(); - const pv::util::Timestamp& end_time = view->cursors()->second()->time(); - - const uint64_t start_sample = - std::max((double)0, start_time.convert_to() * samplerate); - const uint64_t end_sample = end_time.convert_to() * samplerate; - - sample_range = std::make_pair(start_sample, end_sample); - } else { - sample_range = std::make_pair(0, 0); - } - - // Construct the filter - const vector exts = format->extensions(); - QString filter = tr("%1 files ").arg( - QString::fromStdString(format->description())); - - if (exts.empty()) - filter += "(*.*)"; - else - filter += QString("(*.%1);;%2 (*.*)").arg( - QString::fromStdString(join(exts, ", *.")), - tr("All Files")); - - // Show the file dialog - const QString file_name = QFileDialog::getSaveFileName( - this, tr("Save File"), dir, filter); - - if (file_name.isEmpty()) - return; - - const QString abs_path = QFileInfo(file_name).absolutePath(); - settings.setValue(SettingSaveDirectory, abs_path); - - // Show the options dialog - map options; - if (!format->options().empty()) { - dialogs::InputOutputOptions dlg( - tr("Export %1").arg(QString::fromStdString( - format->description())), - format->options(), this); - if (!dlg.exec()) - return; - options = dlg.options(); } - StoreProgress *dlg = new StoreProgress(file_name, format, options, - sample_range, session_, this); - dlg->run(); -} - -void MainWindow::import_file(shared_ptr format) -{ - assert(format); - - QSettings settings; - const QString dir = settings.value(SettingOpenDirectory).toString(); - - // Construct the filter - const vector exts = format->extensions(); - const QString filter = exts.empty() ? "" : - tr("%1 files (*.%2)").arg( - QString::fromStdString(format->description()), - QString::fromStdString(join(exts, ", *."))); - - // Show the file dialog - const QString file_name = QFileDialog::getOpenFileName( - this, tr("Import File"), dir, tr( - "%1 files (*.*);;All Files (*.*)").arg( - QString::fromStdString(format->description()))); - - if (file_name.isEmpty()) - return; - - // Show the options dialog - map options; - if (!format->options().empty()) { - dialogs::InputOutputOptions dlg( - tr("Import %1").arg(QString::fromStdString( - format->description())), - format->options(), this); - if (!dlg.exec()) - return; - options = dlg.options(); - } - - load_file(file_name, format, options); - - const QString abs_path = QFileInfo(file_name).absolutePath(); - settings.setValue(SettingOpenDirectory, abs_path); + return v; } void MainWindow::setup_ui() @@ -438,77 +197,6 @@ void MainWindow::setup_ui() icon.addFile(QString(":/icons/sigrok-logo-notext.png")); setWindowIcon(icon); - action_open_->setText(tr("&Open...")); - action_open_->setIcon(QIcon::fromTheme("document-open", - QIcon(":/icons/document-open.png"))); - action_open_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); - action_open_->setObjectName(QString::fromUtf8("actionOpen")); - - action_save_as_->setText(tr("&Save As...")); - action_save_as_->setIcon(QIcon::fromTheme("document-save-as", - QIcon(":/icons/document-save-as.png"))); - action_save_as_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); - action_save_as_->setObjectName(QString::fromUtf8("actionSaveAs")); - - action_save_selection_as_->setText(tr("Save Selected &Range As...")); - action_save_selection_as_->setIcon(QIcon::fromTheme("document-save-as", - QIcon(":/icons/document-save-as.png"))); - action_save_selection_as_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); - action_save_selection_as_->setObjectName(QString::fromUtf8("actionSaveSelectionAs")); - - widgets::ExportMenu *menu_file_export = new widgets::ExportMenu(this, - device_manager_.context()); - menu_file_export->setTitle(tr("&Export")); - connect(menu_file_export, - SIGNAL(format_selected(std::shared_ptr)), - this, SLOT(export_file(std::shared_ptr))); - - widgets::ImportMenu *menu_file_import = new widgets::ImportMenu(this, - device_manager_.context()); - menu_file_import->setTitle(tr("&Import")); - connect(menu_file_import, - SIGNAL(format_selected(std::shared_ptr)), - this, SLOT(import_file(std::shared_ptr))); - - action_connect_->setText(tr("&Connect to Device...")); - action_connect_->setObjectName(QString::fromUtf8("actionConnect")); - - action_quit_->setText(tr("&Quit")); - action_quit_->setIcon(QIcon::fromTheme("application-exit", - QIcon(":/icons/application-exit.png"))); - action_quit_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); - action_quit_->setObjectName(QString::fromUtf8("actionQuit")); - - action_view_zoom_in_->setText(tr("Zoom &In")); - action_view_zoom_in_->setIcon(QIcon::fromTheme("zoom-in", - QIcon(":/icons/zoom-in.png"))); - // simply using Qt::Key_Plus shows no + in the menu - action_view_zoom_in_->setShortcut(QKeySequence::ZoomIn); - action_view_zoom_in_->setObjectName( - QString::fromUtf8("actionViewZoomIn")); - - action_view_zoom_out_->setText(tr("Zoom &Out")); - action_view_zoom_out_->setIcon(QIcon::fromTheme("zoom-out", - QIcon(":/icons/zoom-out.png"))); - action_view_zoom_out_->setShortcut(QKeySequence::ZoomOut); - action_view_zoom_out_->setObjectName( - QString::fromUtf8("actionViewZoomOut")); - - action_view_zoom_fit_->setCheckable(true); - action_view_zoom_fit_->setText(tr("Zoom to &Fit")); - action_view_zoom_fit_->setIcon(QIcon::fromTheme("zoom-fit", - QIcon(":/icons/zoom-fit.png"))); - action_view_zoom_fit_->setShortcut(QKeySequence(Qt::Key_F)); - action_view_zoom_fit_->setObjectName( - QString::fromUtf8("actionViewZoomFit")); - - action_view_zoom_one_to_one_->setText(tr("Zoom to O&ne-to-One")); - action_view_zoom_one_to_one_->setIcon(QIcon::fromTheme("zoom-original", - QIcon(":/icons/zoom-original.png"))); - action_view_zoom_one_to_one_->setShortcut(QKeySequence(Qt::Key_O)); - action_view_zoom_one_to_one_->setObjectName( - QString::fromUtf8("actionViewZoomOneToOne")); - action_view_sticky_scrolling_->setCheckable(true); action_view_sticky_scrolling_->setChecked(true); action_view_sticky_scrolling_->setShortcut(QKeySequence(Qt::Key_S)); @@ -523,118 +211,17 @@ void MainWindow::setup_ui() QString::fromUtf8("actionViewColouredBg")); action_view_coloured_bg_->setText(tr("Use &coloured backgrounds")); - action_view_show_cursors_->setCheckable(true); - action_view_show_cursors_->setIcon(QIcon::fromTheme("show-cursors", - QIcon(":/icons/show-cursors.svg"))); - action_view_show_cursors_->setShortcut(QKeySequence(Qt::Key_C)); - action_view_show_cursors_->setObjectName( - QString::fromUtf8("actionViewShowCursors")); - action_view_show_cursors_->setText(tr("Show &Cursors")); - -#ifdef ENABLE_DECODE - menu_decoders_add_->setTitle(tr("&Add")); - connect(menu_decoders_add_, SIGNAL(decoder_selected(srd_decoder*)), - this, SLOT(add_decoder(srd_decoder*))); -#endif - action_about_->setObjectName(QString::fromUtf8("actionAbout")); action_about_->setText(tr("&About...")); - QMetaObject::connectSlotsByName(this); - - // Setup the toolbar - main_bar_ = new toolbars::MainBar(session_, *this); - // Set up the initial view - add_view(tr("Untitled"), pv::view::TraceView, session_); - - // Populate the device list and select the initially selected device - update_device_list(); - - addToolBar(main_bar_); + shared_ptr main_view = + add_view(tr("Untitled"), pv::view::TraceView, session_); // Set the title setWindowTitle(tr("PulseView")); - - // Setup session_ events - connect(&session_, SIGNAL(capture_state_changed(int)), this, - SLOT(capture_state_changed(int))); - connect(&session_, SIGNAL(device_selected()), this, - SLOT(device_selected())); -} - -void MainWindow::select_init_device() -{ - QSettings settings; - map dev_info; - list key_list; - shared_ptr device; - - // Re-select last used device if possible but only if it's not demo - 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"); - - for (string key : key_list) { - const QString k = QString::fromStdString(key); - if (!settings.contains(k)) - continue; - - const string value = settings.value(k).toString().toStdString(); - if (!value.empty()) - dev_info.insert(std::make_pair(key, value)); - } - - if (dev_info.count("model") > 0) - if (dev_info.at("model").find("Demo device") == std::string::npos) - device = device_manager_.find_device_from_info(dev_info); - - // When we can't find a device similar to the one we used last - // time and there is at least one device aside from demo, use it - if (!device) { - for (shared_ptr dev : device_manager_.devices()) { - dev_info = device_manager_.get_device_info(dev); - - if (dev_info.count("model") > 0) - if (dev_info.at("model").find("Demo device") == std::string::npos) { - device = dev; - break; - } - } - } - - select_device(device); - update_device_list(); - - settings.endGroup(); } -void MainWindow::load_init_file(const std::string &file_name, - const std::string &format) -{ - shared_ptr input_format; - - if (!format.empty()) { - const map > formats = - device_manager_.context()->input_formats(); - const auto iter = find_if(formats.begin(), formats.end(), - [&](const pair > f) { - return f.first == format; }); - if (iter == formats.end()) { - cerr << "Unexpected input format: " << format << endl; - return; - } - - input_format = (*iter).second; - } - - load_file(QString::fromStdString(file_name), input_format); -} - - void MainWindow::save_ui_settings() { QSettings settings; @@ -685,66 +272,12 @@ void MainWindow::restore_ui_settings() settings.endGroup(); } -void MainWindow::session_error( - const QString text, const QString info_text) -{ - QMetaObject::invokeMethod(this, "show_session_error", - Qt::QueuedConnection, Q_ARG(QString, text), - Q_ARG(QString, info_text)); -} - -void MainWindow::update_device_list() -{ - main_bar_->update_device_list(); -} - -void MainWindow::load_file(QString file_name, - std::shared_ptr format, - const std::map &options) -{ - const QString errorMessage( - QString("Failed to load file %1").arg(file_name)); - - try { - if (format) - session_.set_device(shared_ptr( - new devices::InputFile( - device_manager_.context(), - file_name.toStdString(), - format, options))); - else - session_.set_device(shared_ptr( - new devices::SessionFile( - device_manager_.context(), - file_name.toStdString()))); - } catch (Error e) { - show_session_error(tr("Failed to load ") + file_name, e.what()); - session_.set_default_device(); - update_device_list(); - return; - } - - update_device_list(); - - session_.start_capture([&, errorMessage](QString infoMessage) { - session_error(errorMessage, infoMessage); }); -} - void MainWindow::closeEvent(QCloseEvent *event) { save_ui_settings(); event->accept(); } -void MainWindow::keyReleaseEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Alt) { - menuBar()->setHidden(!menuBar()->isHidden()); - menuBar()->setFocus(); - } - QMainWindow::keyReleaseEvent(event); -} - QMenu* MainWindow::createPopupMenu() { return nullptr; @@ -761,94 +294,6 @@ bool MainWindow::restoreState(const QByteArray &state, int version) return false; } -void MainWindow::show_session_error( - const QString text, const QString info_text) -{ - QMessageBox msg(this); - msg.setText(text); - msg.setInformativeText(info_text); - msg.setStandardButtons(QMessageBox::Ok); - msg.setIcon(QMessageBox::Warning); - msg.exec(); -} - -void MainWindow::on_actionOpen_triggered() -{ - QSettings settings; - const QString dir = settings.value(SettingOpenDirectory).toString(); - - // Show the dialog - const QString file_name = QFileDialog::getOpenFileName( - this, tr("Open File"), dir, tr( - "Sigrok Sessions (*.sr);;" - "All Files (*.*)")); - - if (!file_name.isEmpty()) { - load_file(file_name); - - const QString abs_path = QFileInfo(file_name).absolutePath(); - settings.setValue(SettingOpenDirectory, abs_path); - } -} - -void MainWindow::on_actionSaveAs_triggered() -{ - export_file(device_manager_.context()->output_formats()["srzip"]); -} - -void MainWindow::on_actionSaveSelectionAs_triggered() -{ - export_file(device_manager_.context()->output_formats()["srzip"], true); -} - -void MainWindow::on_actionConnect_triggered() -{ - // Stop any currently running capture session - session_.stop_capture(); - - dialogs::Connect dlg(this, device_manager_); - - // If the user selected a device, select it in the device list. Select the - // current device otherwise. - if (dlg.exec()) - select_device(dlg.get_selected_device()); - - update_device_list(); -} - -void MainWindow::on_actionQuit_triggered() -{ - close(); -} - -void MainWindow::on_actionViewZoomIn_triggered() -{ - shared_ptr view = get_active_view(); - if (view) - view->zoom(1); -} - -void MainWindow::on_actionViewZoomOut_triggered() -{ - shared_ptr view = get_active_view(); - if (view) - view->zoom(-1); -} - -void MainWindow::on_actionViewZoomFit_triggered() -{ - shared_ptr view = get_active_view(); - if (view) - view->zoom_fit(action_view_zoom_fit_->isChecked()); -} - -void MainWindow::on_actionViewZoomOneToOne_triggered() -{ - shared_ptr view = get_active_view(); - if (view) - view->zoom_one_to_one(); -} - void MainWindow::on_actionViewStickyScrolling_triggered() { shared_ptr view = get_active_view(); @@ -863,62 +308,10 @@ void MainWindow::on_actionViewColouredBg_triggered() view->enable_coloured_bg(action_view_coloured_bg_->isChecked()); } -void MainWindow::on_actionViewShowCursors_triggered() -{ - shared_ptr view = get_active_view(); - if (!view) - return; - - const bool show = !view->cursors_shown(); - if (show) - view->centre_cursors(); - - view->show_cursors(show); -} - void MainWindow::on_actionAbout_triggered() { dialogs::About dlg(device_manager_.context(), this); dlg.exec(); } -void MainWindow::sticky_scrolling_changed(bool state) -{ - action_view_sticky_scrolling_->setChecked(state); -} - -void MainWindow::always_zoom_to_fit_changed(bool state) -{ - action_view_zoom_fit_->setChecked(state); -} - -void MainWindow::add_decoder(srd_decoder *decoder) -{ -#ifdef ENABLE_DECODE - assert(decoder); - session_.add_decoder(decoder); -#else - (void)decoder; -#endif -} - -void MainWindow::capture_state_changed(int state) -{ - main_bar_->set_capture_state((pv::Session::capture_state)state); -} - -void MainWindow::device_selected() -{ - // Set the title to include the device/file name - const shared_ptr device = session_.device(); - - if (!device) { - main_bar_->reset_device_selector(); - return; - } - - const string display_name = device->display_name(device_manager_); - setWindowTitle(tr("%1 - PulseView").arg(display_name.c_str())); -} - } // namespace pv