diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 2721a9331a8432c8bce816c4fc3ea39f9344ae37..d5755fff2a48ee931d58278ecccd27af196bb5db 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -340,6 +340,7 @@ HEADERS += src/MG.h \ libs/qextserialport/qextserialenumerator.h \ src/QGCGeo.h \ src/ui/QGCToolBar.h \ + src/ui/QGCStatusBar.h \ src/ui/QGCMAVLinkInspector.h \ src/ui/MAVLinkDecoder.h \ src/ui/WaypointViewOnlyView.h \ @@ -503,6 +504,7 @@ SOURCES += src/main.cc \ src/ui/map/QGCMapTool.cc \ src/ui/map/QGCMapToolBar.cc \ src/ui/QGCToolBar.cc \ + src/ui/QGCStatusBar.cc \ src/ui/QGCMAVLinkInspector.cc \ src/ui/MAVLinkDecoder.cc \ src/ui/WaypointViewOnlyView.cc \ diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index c324483063c77acdf38de75aa67e8cc117d0260e..e07c459267a74499abce5f15925765e1c72605a0 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -57,6 +57,7 @@ This file is part of the QGROUNDCONTROL project #include "QGCMAVLinkMessageSender.h" #include "QGCRGBDView.h" #include "QGCFirmwareUpdate.h" +#include "QGCStatusBar.h" #ifdef QGC_OSG_ENABLED #include "Q3DWidgetFactory.h" @@ -141,7 +142,7 @@ MainWindow::MainWindow(QWidget *parent): configureWindowName(); // Setup corners - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea); // Setup UI state machines centerStackActionGroup->setExclusive(true); @@ -152,10 +153,14 @@ MainWindow::MainWindow(QWidget *parent): // Load Toolbar toolBar = new QGCToolBar(this); this->addToolBar(toolBar); - // Add actions - toolBar->addPerspectiveChangeAction(ui.actionOperatorsView); + // Add actions (inverted order due to insert) + toolBar->addPerspectiveChangeAction(ui.actionSimulation_View); toolBar->addPerspectiveChangeAction(ui.actionEngineersView); toolBar->addPerspectiveChangeAction(ui.actionPilotsView); + toolBar->addPerspectiveChangeAction(ui.actionOperatorsView); + + customStatusBar = new QGCStatusBar(this); + this->setStatusBar(customStatusBar); emit initStatusChanged("Building common widgets."); @@ -373,6 +378,10 @@ void MainWindow::buildCommonWidgets() // Add generic MAVLink decoder mavlinkDecoder = new MAVLinkDecoder(mavlink, this); + // Log player + logPlayer = new QGCMAVLinkLogPlayer(mavlink, customStatusBar); + customStatusBar->setLogPlayer(logPlayer); + // Dock widgets if (!controlDockWidget) { @@ -418,15 +427,15 @@ void MainWindow::buildCommonWidgets() addTool(debugConsoleDockWidget, tr("Communication Console"), Qt::BottomDockWidgetArea); } - if (!logPlayerDockWidget) - { - logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this); - logPlayer = new QGCMAVLinkLogPlayer(mavlink, this); - toolBar->setLogPlayer(logPlayer); - logPlayerDockWidget->setWidget(logPlayer); - logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET"); - addTool(logPlayerDockWidget, tr("MAVLink Log Replay"), Qt::RightDockWidgetArea); - } +// if (!logPlayerDockWidget) +// { +// logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this); +// logPlayer = new QGCMAVLinkLogPlayer(mavlink, this); +// customStatusBar->setLogPlayer(logPlayer); +// logPlayerDockWidget->setWidget(logPlayer); +// logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET"); +// addTool(logPlayerDockWidget, tr("MAVLink Log Replay"), Qt::RightDockWidgetArea); +// } if (!mavlinkInspectorWidget) { @@ -664,7 +673,7 @@ void MainWindow::showHILConfigurationWidget(UASInterface* uas) // Add simulation configuration widget UAS* mav = dynamic_cast(uas); - if (mav) + if (mav && !hilDocks.contains(mav->getUASID())) { QGCHilConfiguration* hconf = new QGCHilConfiguration(mav, this); QString hilDockName = tr("HIL Config (%1)").arg(uas->getUASName()); @@ -672,11 +681,13 @@ void MainWindow::showHILConfigurationWidget(UASInterface* uas) hilDock->setWidget(hconf); hilDock->setObjectName(QString("HIL_CONFIG_%1").arg(uas->getUASID())); addTool(hilDock, hilDockName, Qt::RightDockWidgetArea); + hilDocks.insert(mav->getUASID(), hilDock); + if (currentView != VIEW_SIMULATION) + hilDock->hide(); + else + hilDock->show(); } - - // Reload view state in case new widgets were added - loadViewState(); } void MainWindow::closeEvent(QCloseEvent *event) @@ -1035,6 +1046,7 @@ void MainWindow::connectCommonActions() perspectives->addAction(ui.actionEngineersView); perspectives->addAction(ui.actionMavlinkView); perspectives->addAction(ui.actionPilotsView); + perspectives->addAction(ui.actionSimulation_View); perspectives->addAction(ui.actionOperatorsView); perspectives->addAction(ui.actionFirmwareUpdateView); perspectives->addAction(ui.actionUnconnectedView); @@ -1044,6 +1056,7 @@ void MainWindow::connectCommonActions() if (currentView == VIEW_ENGINEER) ui.actionEngineersView->setChecked(true); if (currentView == VIEW_MAVLINK) ui.actionMavlinkView->setChecked(true); if (currentView == VIEW_PILOT) ui.actionPilotsView->setChecked(true); + if (currentView == VIEW_SIMULATION) ui.actionSimulation_View->setChecked(true); if (currentView == VIEW_OPERATOR) ui.actionOperatorsView->setChecked(true); if (currentView == VIEW_FIRMWAREUPDATE) ui.actionFirmwareUpdateView->setChecked(true); if (currentView == VIEW_UNCONNECTED) ui.actionUnconnectedView->setChecked(true); @@ -1072,6 +1085,7 @@ void MainWindow::connectCommonActions() // Views actions connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView())); + connect(ui.actionSimulation_View, SIGNAL(triggered()), this, SLOT(loadSimulationView())); connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView())); connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView())); connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView())); @@ -1383,6 +1397,9 @@ void MainWindow::UASCreated(UASInterface* uas) } } + // HIL + showHILConfigurationWidget(uas); + // Line chart if (!linechartWidget) { @@ -1440,6 +1457,9 @@ void MainWindow::UASCreated(UASInterface* uas) case VIEW_PILOT: loadPilotView(); break; + case VIEW_SIMULATION: + loadSimulationView(); + break; case VIEW_UNCONNECTED: loadUnconnectedView(); break; @@ -1532,8 +1552,7 @@ void MainWindow::loadViewState() waypointsDockWidget->hide(); infoDockWidget->hide(); debugConsoleDockWidget->show(); - logPlayerDockWidget->show(); - mavlinkInspectorWidget->show(); + //mavlinkInspectorWidget->show(); //mavlinkSenderWidget->show(); parametersDockWidget->show(); hsiDockWidget->hide(); @@ -1551,7 +1570,7 @@ void MainWindow::loadViewState() waypointsDockWidget->hide(); infoDockWidget->hide(); debugConsoleDockWidget->hide(); - logPlayerDockWidget->hide(); +// logPlayerDockWidget->hide(); mavlinkInspectorWidget->hide(); parametersDockWidget->hide(); hsiDockWidget->show(); @@ -1569,7 +1588,7 @@ void MainWindow::loadViewState() waypointsDockWidget->hide(); infoDockWidget->hide(); debugConsoleDockWidget->hide(); - logPlayerDockWidget->hide(); +// logPlayerDockWidget->hide(); mavlinkInspectorWidget->show(); //mavlinkSenderWidget->show(); parametersDockWidget->hide(); @@ -1588,7 +1607,7 @@ void MainWindow::loadViewState() waypointsDockWidget->hide(); infoDockWidget->hide(); debugConsoleDockWidget->hide(); - logPlayerDockWidget->hide(); +// logPlayerDockWidget->hide(); mavlinkInspectorWidget->hide(); //mavlinkSenderWidget->hide(); parametersDockWidget->hide(); @@ -1607,7 +1626,7 @@ void MainWindow::loadViewState() waypointsDockWidget->show(); infoDockWidget->hide(); debugConsoleDockWidget->show(); - logPlayerDockWidget->show(); +// logPlayerDockWidget->show(); parametersDockWidget->hide(); hsiDockWidget->hide(); headDown1DockWidget->hide(); @@ -1618,6 +1637,18 @@ void MainWindow::loadViewState() video2DockWidget->hide(); mavlinkInspectorWidget->hide(); break; + + case VIEW_SIMULATION: + centerStack->setCurrentWidget(mapWidget); + controlDockWidget->show(); + waypointsDockWidget->show(); + parametersDockWidget->show(); + mavlinkInspectorWidget->hide(); + foreach (int key, hilDocks.keys()) { + hilDocks.value(key)->show(); + } + break; + case VIEW_UNCONNECTED: case VIEW_FULL: default: @@ -1627,7 +1658,7 @@ void MainWindow::loadViewState() waypointsDockWidget->hide(); infoDockWidget->hide(); debugConsoleDockWidget->show(); - logPlayerDockWidget->show(); +// logPlayerDockWidget->show(); parametersDockWidget->hide(); hsiDockWidget->hide(); headDown1DockWidget->hide(); @@ -1692,6 +1723,17 @@ void MainWindow::loadPilotView() } } +void MainWindow::loadSimulationView() +{ + if (currentView != VIEW_SIMULATION) + { + storeViewState(); + currentView = VIEW_SIMULATION; + ui.actionSimulation_View->setChecked(true); + loadViewState(); + } +} + void MainWindow::loadMAVLinkView() { if (currentView != VIEW_MAVLINK) diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 8b71dbf8413c5c11d78255fbe614e47fa201099c..c66cad8da26b6550b5995b9e27cf14f6dd90cc9b 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -86,6 +86,7 @@ class QGCMapTool; class QGCMAVLinkMessageSender; class QGCFirmwareUpdate; class QSplashScreen; +class QGCStatusBar; /** * @brief Main Application Window @@ -159,6 +160,8 @@ public slots: void loadUnconnectedView(); /** @brief Load view for pilot */ void loadPilotView(); + /** @brief Load view for simulation */ + void loadSimulationView(); /** @brief Load view for engineer */ void loadEngineerView(); /** @brief Load view for operator */ @@ -260,6 +263,7 @@ protected: VIEW_ENGINEER, VIEW_OPERATOR, VIEW_PILOT, + VIEW_SIMULATION, VIEW_MAVLINK, VIEW_FIRMWAREUPDATE, VIEW_UNCONNECTED, ///< View in unconnected mode, when no UAS is available @@ -367,11 +371,13 @@ protected: QPointer slugsCamControlWidget; QPointer toolBar; + QPointer customStatusBar; QPointer mavlinkInspectorWidget; QPointer mavlinkDecoder; QPointer mavlinkSenderWidget; QGCMAVLinkLogPlayer* logPlayer; + QMap hilDocks; // Popup widgets JoystickWidget* joystickWidget; diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index dcc1b142a0596e5e2c633252d4545b43572a83ee..ab688cb4af894262b004a72c977fb79835f25f24 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -323,7 +323,7 @@ :/files/images/status/weather-overcast.svg:/files/images/status/weather-overcast.svg - Operator + Mission Meta+O @@ -338,7 +338,7 @@ :/files/images/apps/utilities-system-monitor.svg:/files/images/apps/utilities-system-monitor.svg - Engineer + Development Meta+E @@ -377,7 +377,7 @@ :/files/images/status/network-wireless-encrypted.svg:/files/images/status/network-wireless-encrypted.svg - Pilot + Flight Meta+P @@ -488,6 +488,21 @@ Update the firmware of one of the connected autopilots + + + true + + + + :/files/images/control/launch.svg:/files/images/control/launch.svg + + + Simulation View + + + Open the simulation view + + diff --git a/src/ui/QGCHilXPlaneConfiguration.cc b/src/ui/QGCHilXPlaneConfiguration.cc index 4914317e5b78bf12e7c932a63d7cd82803bd40ad..1eaf7632c934a58b041a0f186d611cca2fe61bc0 100644 --- a/src/ui/QGCHilXPlaneConfiguration.cc +++ b/src/ui/QGCHilXPlaneConfiguration.cc @@ -23,8 +23,8 @@ QGCHilXPlaneConfiguration::QGCHilXPlaneConfiguration(QGCHilLink* link, QWidget * if (xplane) { - connect(ui->randomAttitudeButton, SIGNAL(clicked()), link, SLOT(setRandomAttitude())); - connect(ui->randomPositionButton, SIGNAL(clicked()), link, SLOT(setRandomPosition())); +// connect(ui->randomAttitudeButton, SIGNAL(clicked()), link, SLOT(setRandomAttitude())); +// connect(ui->randomPositionButton, SIGNAL(clicked()), link, SLOT(setRandomPosition())); connect(ui->airframeComboBox, SIGNAL(activated(QString)), link, SLOT(selectAirframe(QString))); ui->airframeComboBox->setCurrentIndex(link->getAirFrameIndex()); } diff --git a/src/ui/QGCHilXPlaneConfiguration.ui b/src/ui/QGCHilXPlaneConfiguration.ui index eaf6b2661ed2cac41d92d846c0d73bc8449f6fb4..dbcc93a97110b2ede278717d8eb1c1300a877252 100644 --- a/src/ui/QGCHilXPlaneConfiguration.ui +++ b/src/ui/QGCHilXPlaneConfiguration.ui @@ -6,8 +6,8 @@ 0 0 - 243 - 261 + 249 + 100 @@ -17,13 +17,26 @@ 0 - - + + - Airframe + Start + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -100,20 +113,6 @@ - - - - Random POS - - - - - - - Random ATT - - - @@ -121,26 +120,13 @@ - - + + - Start + Airframe - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/ui/QGCMAVLinkLogPlayer.cc b/src/ui/QGCMAVLinkLogPlayer.cc index e989fc25049f013b5aa5032f8a7ac457567bbff1..1c7a9a4b922127298b312552b8631947f09bff7e 100644 --- a/src/ui/QGCMAVLinkLogPlayer.cc +++ b/src/ui/QGCMAVLinkLogPlayer.cc @@ -26,7 +26,7 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(MAVLinkProtocol* mavlink, QWidget *pare ui(new Ui::QGCMAVLinkLogPlayer) { ui->setupUi(this); - ui->gridLayout->setAlignment(Qt::AlignTop); + ui->horizontalLayout->setAlignment(Qt::AlignTop); // Connect protocol connect(this, SIGNAL(bytesReady(LinkInterface*,QByteArray)), mavlink, SLOT(receiveBytes(LinkInterface*,QByteArray))); diff --git a/src/ui/QGCMAVLinkLogPlayer.h b/src/ui/QGCMAVLinkLogPlayer.h index e4c0e4fd64627e2232b85d1b1b1020dd97f3543d..df20d7361c38fc0d4c53c98019f28f4de7794eb1 100644 --- a/src/ui/QGCMAVLinkLogPlayer.h +++ b/src/ui/QGCMAVLinkLogPlayer.h @@ -37,6 +37,14 @@ public: return logFile.isOpen(); } + /** + * @brief Set the last log file name + * @param filename + */ + void setLastLogFile(const QString& filename) { + lastLogDirectory = filename; + } + public slots: /** @brief Toggle between play and pause */ void playPauseToggle(); diff --git a/src/ui/QGCMAVLinkLogPlayer.ui b/src/ui/QGCMAVLinkLogPlayer.ui index ac207f79b698a13f40078036509c6d0e38e0141e..282eb75dd3bb87b95413ad2ee43ef425d206fbed 100644 --- a/src/ui/QGCMAVLinkLogPlayer.ui +++ b/src/ui/QGCMAVLinkLogPlayer.ui @@ -6,76 +6,64 @@ 0 0 - 407 - 152 + 789 + 38 Form - - - 12 + + + 4 - - - - Please choose logfile - - - - - - - Select the logfile to replay + + + + 10000 - - Select the logfile to replay + + 100 - - Select the logfile to replay + + false - - Select File + + Qt::Horizontal - - + + - Set the replay speed + Start to replay the logfile - Set the replay speed + Start to replay the logfile - Set the replay speed - - - 1 - - - 100 + Start to replay the logfile - - 50 + + ... - - 50 + + + :/files/images/actions/media-playback-start.svg:/files/images/actions/media-playback-start.svg - - Qt::Horizontal + + true - + No logfile selected.. - + Current replay speed @@ -91,42 +79,54 @@ - - - - 10000 + + + + Set the replay speed - + + Set the replay speed + + + Set the replay speed + + + 1 + + 100 - - false + + 50 + + + 50 Qt::Horizontal - - + + + + Please choose logfile + + + + + - Start to replay the logfile + Select the logfile to replay - Start to replay the logfile + Select the logfile to replay - Start to replay the logfile + Select the logfile to replay - ... - - - - :/files/images/actions/media-playback-start.svg:/files/images/actions/media-playback-start.svg - - - true + Select File diff --git a/src/ui/QGCStatusBar.cc b/src/ui/QGCStatusBar.cc new file mode 100644 index 0000000000000000000000000000000000000000..7e771903ae21e45fb3b9f5de73c1bf7efe6a45b4 --- /dev/null +++ b/src/ui/QGCStatusBar.cc @@ -0,0 +1,132 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009 - 2013 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL 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 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#include +#include +#include +#include "QGCStatusBar.h" +#include "UASManager.h" +#include "MainWindow.h" + +QGCStatusBar::QGCStatusBar(QWidget *parent) : + QStatusBar(parent), + toggleLoggingButton(NULL), + player(NULL), + changed(true), + lastLogDirectory(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)) +{ + setObjectName("QGC_STATUSBAR"); + + toggleLoggingButton = new QPushButton("Logging", this); + toggleLoggingButton->setCheckable(true); + + addWidget(toggleLoggingButton); + + loadSettings(); +} + +void QGCStatusBar::setLogPlayer(QGCMAVLinkLogPlayer* player) +{ + this->player = player; + addPermanentWidget(player); + connect(toggleLoggingButton, SIGNAL(clicked(bool)), this, SLOT(logging(bool))); + + // XXX Mutex issue if called like this +// toggleLoggingButton->blockSignals(true); +// toggleLoggingButton->setChecked(MainWindow::instance()->getMAVLink()->loggingEnabled()); +// toggleLoggingButton->blockSignals(false); +} + +void QGCStatusBar::logging(bool checked) +{ + // Stop logging in any case + MainWindow::instance()->getMAVLink()->enableLogging(false); + + if (!checked && player) + { + player->setLastLogFile(lastLogDirectory); + } + + // If the user is enabling logging + if (checked) + { + // Prompt the user for a filename/location to save to + QString fileName = QFileDialog::getSaveFileName(this, tr("Specify MAVLink log file to save to"), lastLogDirectory, tr("MAVLink Logfile (*.mavlink *.log *.bin);;")); + + // Check that they didn't cancel out + if (fileName.isNull()) + { + toggleLoggingButton->setChecked(false); + return; + } + + // Make sure the file's named properly + if (!fileName.endsWith(".mavlink")) + { + fileName.append(".mavlink"); + } + + // Check that we can save the logfile + QFileInfo file(fileName); + if ((file.exists() && !file.isWritable())) + { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + msgBox.setText(tr("The selected logfile is not writable")); + msgBox.setInformativeText(tr("Please make sure that the file %1 is writable or select a different file").arg(fileName)); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.exec(); + } + // Otherwise we're off and logging + else + { + MainWindow::instance()->getMAVLink()->setLogfileName(fileName); + MainWindow::instance()->getMAVLink()->enableLogging(true); + lastLogDirectory = file.absoluteDir().absolutePath(); //save last log directory + } + } +} + +void QGCStatusBar::loadSettings() +{ + QSettings settings; + settings.beginGroup("QGC_MAVLINKLOGPLAYER"); + lastLogDirectory = settings.value("LAST_LOG_DIRECTORY", lastLogDirectory).toString(); + settings.endGroup(); +} + +void QGCStatusBar::storeSettings() +{ + QSettings settings; + settings.beginGroup("QGC_MAVLINKLOGPLAYER"); + settings.setValue("LAST_LOG_DIRECTORY", lastLogDirectory); + settings.endGroup(); + settings.sync(); +} + +QGCStatusBar::~QGCStatusBar() +{ + storeSettings(); + if (toggleLoggingButton) toggleLoggingButton->deleteLater(); +} diff --git a/src/ui/QGCStatusBar.h b/src/ui/QGCStatusBar.h new file mode 100644 index 0000000000000000000000000000000000000000..ca60b5a83547ffd5fcfcf51858d6e5a699f2f736 --- /dev/null +++ b/src/ui/QGCStatusBar.h @@ -0,0 +1,61 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009 - 2013 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL 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 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#ifndef QGCSTATUSBAR_H +#define QGCSTATUSBAR_H + +#include +#include +#include +#include +#include +#include +#include "UASInterface.h" +#include "QGCMAVLinkLogPlayer.h" + +class QGCStatusBar : public QStatusBar +{ + Q_OBJECT + +public: + explicit QGCStatusBar(QWidget* parent = 0); + void addPerspectiveChangeAction(QAction* action); + ~QGCStatusBar(); + +public slots: + /** @brief Start / stop logging */ + void logging(bool checked); + /** @brief Set log playing component */ + void setLogPlayer(QGCMAVLinkLogPlayer* player); + +protected: + void storeSettings(); + void loadSettings(); + + QPushButton* toggleLoggingButton; + QGCMAVLinkLogPlayer* player; + bool changed; + QString lastLogDirectory; +}; + +#endif // QGCSTATUSBAR_H diff --git a/src/ui/QGCToolBar.cc b/src/ui/QGCToolBar.cc index 74acfc0e4be15fcbd4a694cfe16fdb98510d1420..86136039827b1681d562545d4a3660599571b8e5 100644 --- a/src/ui/QGCToolBar.cc +++ b/src/ui/QGCToolBar.cc @@ -30,8 +30,6 @@ This file is part of the QGROUNDCONTROL project QGCToolBar::QGCToolBar(QWidget *parent) : QToolBar(parent), - toggleLoggingAction(NULL), - logReplayAction(NULL), mav(NULL), player(NULL), changed(true), @@ -40,28 +38,52 @@ QGCToolBar::QGCToolBar(QWidget *parent) : wpId(0), wpDistance(0), systemArmed(false), - lastLogDirectory(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)), - currentLink(NULL) + currentLink(NULL), + firstAction(NULL) { setObjectName("QGC_TOOLBAR"); - toggleLoggingAction = new QAction(QIcon(":"), "Logging", this); - toggleLoggingAction->setCheckable(true); - logReplayAction = new QAction(QIcon(":"), "Replay", this); - logReplayAction->setCheckable(false); + // Do not load UI, wait for actions +} - addAction(toggleLoggingAction); - addAction(logReplayAction); +void QGCToolBar::heartbeatTimeout(bool timeout, unsigned int ms) +{ + // set timeout label visible + if (timeout) + { + // Alternate colors to increase visibility + if ((ms / 1000) % 2 == 0) + { + toolBarTimeoutLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.name())); + } + else + { + toolBarTimeoutLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.dark(250).name())); + } + toolBarTimeoutLabel->setText(tr("CONNECTION LOST: %1 s").arg((ms / 1000.0f), 2, 'f', 1, ' ')); + } + else + { + // Check if loss text is present, reset once + if (toolBarTimeoutLabel->text() != "") + { + toolBarTimeoutLabel->setText(""); + toolBarTimeoutLabel->setStyleSheet(QString("")); + } + } +} +void QGCToolBar::createUI() +{ // CREATE TOOLBAR ITEMS // Add internal actions // Add MAV widget symbolButton = new QToolButton(this); symbolButton->setStyleSheet("QWidget { background-color: #050508; color: #DDDDDF; background-clip: border; }"); - addWidget(symbolButton); + addWidget(symbolButton); toolBarNameLabel = new QLabel("------", this); - toolBarNameLabel->setToolTip(tr("Currently controlled vehicle")); + toolBarNameLabel->setToolTip(tr("Currently controlled vehicle")); addWidget(toolBarNameLabel); toolBarTimeoutLabel = new QLabel("UNCONNECTED", this); @@ -71,17 +93,17 @@ QGCToolBar::QGCToolBar(QWidget *parent) : toolBarSafetyLabel = new QLabel("SAFE", this); toolBarSafetyLabel->setStyleSheet("QLabel { margin: 0px 2px; font: 14px; color: #14C814; }"); - toolBarSafetyLabel->setToolTip(tr("Vehicle safety state")); + toolBarSafetyLabel->setToolTip(tr("Vehicle safety state")); addWidget(toolBarSafetyLabel); toolBarModeLabel = new QLabel("------", this); toolBarModeLabel->setStyleSheet("QLabel { margin: 0px 2px; font: 14px; color: #3C7B9E; }"); - toolBarModeLabel->setToolTip(tr("Vehicle mode")); + toolBarModeLabel->setToolTip(tr("Vehicle mode")); addWidget(toolBarModeLabel); toolBarStateLabel = new QLabel("------", this); toolBarStateLabel->setStyleSheet("QLabel { margin: 0px 2px; font: 14px; color: #FEC654; }"); - toolBarStateLabel->setToolTip(tr("Vehicle state")); + toolBarStateLabel->setToolTip(tr("Vehicle state")); addWidget(toolBarStateLabel); toolBarBatteryBar = new QProgressBar(this); @@ -95,7 +117,7 @@ QGCToolBar::QGCToolBar(QWidget *parent) : toolBarBatteryVoltageLabel = new QLabel("xx.x V"); toolBarBatteryVoltageLabel->setStyleSheet(QString("QLabel { margin: 0px 0px 0px 4px; font: 14px; color: %1; }").arg(QColor(Qt::green).name())); - toolBarBatteryVoltageLabel->setToolTip(tr("Battery voltage")); + toolBarBatteryVoltageLabel->setToolTip(tr("Battery voltage")); addWidget(toolBarBatteryVoltageLabel); toolBarWpLabel = new QLabel("WP--", this); @@ -109,7 +131,7 @@ QGCToolBar::QGCToolBar(QWidget *parent) : toolBarMessageLabel = new QLabel("No system messages.", this); toolBarMessageLabel->setStyleSheet("QLabel { margin: 0px 4px; font: 12px; font-style: italic; color: #3C7B9E; }"); - toolBarMessageLabel->setToolTip(tr("Most recent system message")); + toolBarMessageLabel->setToolTip(tr("Most recent system message")); addWidget(toolBarMessageLabel); QWidget* spacer = new QWidget(); @@ -124,7 +146,7 @@ QGCToolBar::QGCToolBar(QWidget *parent) : // DONE INITIALIZING BUTTONS - // Configure the toolbar for the current default UAS + // Configure the toolbar for the current default UAS setActiveUAS(UASManager::instance()->getActiveUAS()); connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); @@ -145,113 +167,15 @@ QGCToolBar::QGCToolBar(QWidget *parent) : loadSettings(); } -void QGCToolBar::heartbeatTimeout(bool timeout, unsigned int ms) -{ - // set timeout label visible - if (timeout) - { - // Alternate colors to increase visibility - if ((ms / 1000) % 2 == 0) - { - toolBarTimeoutLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.name())); - } - else - { - toolBarTimeoutLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.dark(250).name())); - } - toolBarTimeoutLabel->setText(tr("CONNECTION LOST: %1 s").arg((ms / 1000.0f), 2, 'f', 1, ' ')); - } - else - { - // Check if loss text is present, reset once - if (toolBarTimeoutLabel->text() != "") - { - toolBarTimeoutLabel->setText(""); - toolBarTimeoutLabel->setStyleSheet(QString("")); - } - } -} - -void QGCToolBar::setLogPlayer(QGCMAVLinkLogPlayer* player) -{ - this->player = player; - connect(toggleLoggingAction, SIGNAL(triggered(bool)), this, SLOT(logging(bool))); - connect(logReplayAction, SIGNAL(triggered(bool)), this, SLOT(playLogFile(bool))); -} - -void QGCToolBar::playLogFile(bool checked) -{ - // Check if player exists - if (player) - { - // If a logfile is already replayed, stop the replay - // and select a new logfile - if (player->isPlayingLogFile()) - { - player->playPause(false); - if (checked) - { - if (!player->selectLogFile(lastLogDirectory)) return; - } - } - // If no replaying happens already, start it - else - { - if (!player->selectLogFile(lastLogDirectory)) return; - } - player->playPause(checked); - } -} - -void QGCToolBar::logging(bool checked) -{ - // Stop logging in any case - MainWindow::instance()->getMAVLink()->enableLogging(false); - - // If the user is enabling logging - if (checked) - { - // Prompt the user for a filename/location to save to - QString fileName = QFileDialog::getSaveFileName(this, tr("Specify MAVLink log file to save to"), lastLogDirectory, tr("MAVLink Logfile (*.mavlink *.log *.bin);;")); - - // Check that they didn't cancel out - if (fileName.isNull()) - { - toggleLoggingAction->setChecked(false); - return; - } - - // Make sure the file's named properly - if (!fileName.endsWith(".mavlink")) - { - fileName.append(".mavlink"); - } - - // Check that we can save the logfile - QFileInfo file(fileName); - if ((file.exists() && !file.isWritable())) - { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText(tr("The selected logfile is not writable")); - msgBox.setInformativeText(tr("Please make sure that the file %1 is writable or select a different file").arg(fileName)); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); - } - // Otherwise we're off and logging - else - { - MainWindow::instance()->getMAVLink()->setLogfileName(fileName); - MainWindow::instance()->getMAVLink()->enableLogging(true); - lastLogDirectory = file.absoluteDir().absolutePath(); //save last log directory - } - } -} - void QGCToolBar::addPerspectiveChangeAction(QAction* action) { - insertAction(toggleLoggingAction, action); + if (firstAction) { + insertAction(firstAction, action); + } else { + addAction(action); + firstAction = action; + createUI(); + } } void QGCToolBar::setActiveUAS(UASInterface* active) @@ -508,6 +432,7 @@ void QGCToolBar::removeLink(LinkInterface* link) void QGCToolBar::updateLinkState(bool connected) { + Q_UNUSED(connected); if (currentLink && currentLink->isConnected()) { connectButton->setText(tr("Disconnect")); @@ -543,7 +468,6 @@ void QGCToolBar::loadSettings() { QSettings settings; settings.beginGroup("QGC_TOOLBAR"); - lastLogDirectory = settings.value("LAST_LOG_DIRECTORY", lastLogDirectory).toString(); settings.endGroup(); } @@ -551,7 +475,6 @@ void QGCToolBar::storeSettings() { QSettings settings; settings.beginGroup("QGC_TOOLBAR"); - settings.setValue("LAST_LOG_DIRECTORY", lastLogDirectory); settings.endGroup(); settings.sync(); } @@ -565,6 +488,4 @@ void QGCToolBar::clearStatusString() QGCToolBar::~QGCToolBar() { storeSettings(); - if (toggleLoggingAction) toggleLoggingAction->deleteLater(); - if (logReplayAction) logReplayAction->deleteLater(); } diff --git a/src/ui/QGCToolBar.h b/src/ui/QGCToolBar.h index 2fcdc3f9a2015c69e790d366c73010e8d2f064eb..270e56ac21be59f481997d52f622442fe0631f9c 100644 --- a/src/ui/QGCToolBar.h +++ b/src/ui/QGCToolBar.h @@ -61,12 +61,6 @@ public slots: void setSystemType(UASInterface* uas, unsigned int systemType); /** @brief Received system text message */ void receiveTextMessage(int uasid, int componentid, int severity, QString text); - /** @brief Start / stop logging */ - void logging(bool checked); - /** @brief Start playing logfile */ - void playLogFile(bool checked); - /** @brief Set log playing component */ - void setLogPlayer(QGCMAVLinkLogPlayer* player); /** @brief Update battery charge state */ void updateBatteryRemaining(UASInterface* uas, double voltage, double percent, int seconds); /** @brief Update current waypoint */ @@ -88,9 +82,8 @@ protected: void createCustomWidgets(); void storeSettings(); void loadSettings(); + void createUI(); - QAction* toggleLoggingAction; - QAction* logReplayAction; UASInterface* mav; QToolButton* symbolButton; QLabel* toolBarNameLabel; @@ -117,8 +110,8 @@ protected: quint64 lastSystemMessageTimeMs; QTimer updateViewTimer; bool systemArmed; - QString lastLogDirectory; LinkInterface* currentLink; + QAction* firstAction; }; #endif // QGCTOOLBAR_H