Commit 0c9de33c authored by Lorenz Meier's avatar Lorenz Meier

Overhauled activity selection and logfile replay options

parent 55d7b98f
......@@ -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 \
......
......@@ -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*>(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)
......
......@@ -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<QDockWidget> slugsCamControlWidget;
QPointer<QGCToolBar> toolBar;
QPointer<QGCStatusBar> customStatusBar;
QPointer<QDockWidget> mavlinkInspectorWidget;
QPointer<MAVLinkDecoder> mavlinkDecoder;
QPointer<QDockWidget> mavlinkSenderWidget;
QGCMAVLinkLogPlayer* logPlayer;
QMap<int, QDockWidget*> hilDocks;
// Popup widgets
JoystickWidget* joystickWidget;
......
......@@ -323,7 +323,7 @@
<normaloff>:/files/images/status/weather-overcast.svg</normaloff>:/files/images/status/weather-overcast.svg</iconset>
</property>
<property name="text">
<string>Operator</string>
<string>Mission</string>
</property>
<property name="shortcut">
<string>Meta+O</string>
......@@ -338,7 +338,7 @@
<normaloff>:/files/images/apps/utilities-system-monitor.svg</normaloff>:/files/images/apps/utilities-system-monitor.svg</iconset>
</property>
<property name="text">
<string>Engineer</string>
<string>Development</string>
</property>
<property name="shortcut">
<string>Meta+E</string>
......@@ -377,7 +377,7 @@
<normaloff>:/files/images/status/network-wireless-encrypted.svg</normaloff>:/files/images/status/network-wireless-encrypted.svg</iconset>
</property>
<property name="text">
<string>Pilot</string>
<string>Flight</string>
</property>
<property name="shortcut">
<string>Meta+P</string>
......@@ -488,6 +488,21 @@
<string>Update the firmware of one of the connected autopilots</string>
</property>
</action>
<action name="actionSimulation_View">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/files/images/control/launch.svg</normaloff>:/files/images/control/launch.svg</iconset>
</property>
<property name="text">
<string>Simulation View</string>
</property>
<property name="toolTip">
<string>Open the simulation view</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
......
......@@ -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());
}
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>243</width>
<height>261</height>
<width>249</width>
<height>100</height>
</rect>
</property>
<property name="windowTitle">
......@@ -17,13 +17,26 @@
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Airframe</string>
<string>Start</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="airframeComboBox">
<property name="editable">
......@@ -100,20 +113,6 @@
</item>
</widget>
</item>
<item row="5" column="2" colspan="2">
<widget class="QPushButton" name="randomPositionButton">
<property name="text">
<string>Random POS</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPushButton" name="randomAttitudeButton">
<property name="text">
<string>Random ATT</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="hostLabel">
<property name="text">
......@@ -121,26 +120,13 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="startButton">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Start</string>
<string>Airframe</string>
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
......
......@@ -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)));
......
......@@ -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();
......
......@@ -6,76 +6,64 @@
<rect>
<x>0</x>
<y>0</y>
<width>407</width>
<height>152</height>
<width>789</width>
<height>38</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="1,0,0,0,0,0">
<property name="horizontalSpacing">
<number>12</number>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>4</number>
</property>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="logFileNameLabel">
<property name="text">
<string>Please choose logfile</string>
</property>
</widget>
</item>
<item row="0" column="3" colspan="3">
<widget class="QPushButton" name="selectFileButton">
<property name="toolTip">
<string>Select the logfile to replay</string>
<item>
<widget class="QSlider" name="positionSlider">
<property name="maximum">
<number>10000</number>
</property>
<property name="statusTip">
<string>Select the logfile to replay</string>
<property name="pageStep">
<number>100</number>
</property>
<property name="whatsThis">
<string>Select the logfile to replay</string>
<property name="tracking">
<bool>false</bool>
</property>
<property name="text">
<string>Select File</string>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1" colspan="5">
<widget class="QSlider" name="speedSlider">
<item>
<widget class="QToolButton" name="playButton">
<property name="toolTip">
<string>Set the replay speed</string>
<string>Start to replay the logfile</string>
</property>
<property name="statusTip">
<string>Set the replay speed</string>
<string>Start to replay the logfile</string>
</property>
<property name="whatsThis">
<string>Set the replay speed</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
<string>Start to replay the logfile</string>
</property>
<property name="value">
<number>50</number>
<property name="text">
<string>...</string>
</property>
<property name="sliderPosition">
<number>50</number>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/files/images/actions/media-playback-start.svg</normaloff>:/files/images/actions/media-playback-start.svg</iconset>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<item>
<widget class="QLabel" name="logStatsLabel">
<property name="text">
<string>No logfile selected..</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item>
<widget class="QLabel" name="speedLabel">
<property name="toolTip">
<string>Current replay speed</string>
......@@ -91,42 +79,54 @@
</property>
</widget>
</item>
<item row="4" column="0" colspan="6">
<widget class="QSlider" name="positionSlider">
<property name="maximum">
<number>10000</number>
<item>
<widget class="QSlider" name="speedSlider">
<property name="toolTip">
<string>Set the replay speed</string>
</property>
<property name="pageStep">
<property name="statusTip">
<string>Set the replay speed</string>
</property>
<property name="whatsThis">
<string>Set the replay speed</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="tracking">
<bool>false</bool>
<property name="value">
<number>50</number>
</property>
<property name="sliderPosition">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QToolButton" name="playButton">
<item>
<widget class="QLabel" name="logFileNameLabel">
<property name="text">
<string>Please choose logfile</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectFileButton">
<property name="toolTip">
<string>Start to replay the logfile</string>
<string>Select the logfile to replay</string>
</property>
<property name="statusTip">
<string>Start to replay the logfile</string>
<string>Select the logfile to replay</string>
</property>
<property name="whatsThis">
<string>Start to replay the logfile</string>
<string>Select the logfile to replay</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/files/images/actions/media-playback-start.svg</normaloff>:/files/images/actions/media-playback-start.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
<string>Select File</string>
</property>
</widget>
</item>
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2013 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#include <QToolButton>
#include <QLabel>
#include <QSpacerItem>
#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();
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2013 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef QGCSTATUSBAR_H
#define QGCSTATUSBAR_H
#include <QStatusBar>
#include <QAction>
#include <QToolButton>
#include <QPushButton>
#include <QLabel>
#include <QProgressBar>
#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
......@@ -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();
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment