Commit 3ef3f654 authored by Mariano Lizarraga's avatar Mariano Lizarraga

Merge branch 'experimental' of git@github.com:pixhawk/qgroundcontrol into mergeRemote

parents 3656dc6d 7d609bc3
......@@ -39,6 +39,8 @@ This file is part of the QGROUNDCONTROL project
#include <QStyleFactory>
#include <QAction>
#include <QDebug>
#include "configuration.h"
#include "QGC.h"
#include "Core.h"
......@@ -65,29 +67,43 @@ This file is part of the QGROUNDCONTROL project
Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
{
// Set application name
this->setApplicationName(QGC_APPLICATION_NAME);
this->setApplicationVersion(QGC_APPLICATION_VERSION);
this->setOrganizationName(QLatin1String("OPENMAV"));
this->setOrganizationDomain("http://qgroundcontrol.org");
this->setOrganizationDomain("org.qgroundcontrol");
// Set settings format
QSettings::setDefaultFormat(QSettings::IniFormat);
// Check application settings
// clear them if they mismatch
// QGC then falls back to default
QSettings settings;
settings.sync();
if (settings.contains("QGC_APPLICATION_VERSION_INT"))
// Show user an upgrade message if QGC got upgraded (see code below, after splash screen)
bool upgraded = false;
QString lastApplicationVersion("");
if (settings.contains("QGC_APPLICATION_VERSION"))
{
QString qgcVersion = settings.value("QGC_APPLICATION_VERSION").toString();
if (qgcVersion != QGC_APPLICATION_VERSION)
{
lastApplicationVersion = qgcVersion;
settings.clear();
// Write current application version
settings.setValue("QGC_APPLICATION_VERSION", QGC_APPLICATION_VERSION);
upgraded = true;
}
}
else
{
// If application version is not set, clear settings anyway
settings.clear();
// Write current application version
settings.setValue("QGC_APPLICATION_VERSION", QGC_APPLICATION_VERSION);
}
settings.sync();
// Show splash screen
......@@ -98,7 +114,6 @@ Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
splashScreen->show();
splashScreen->showMessage(tr("Loading application fonts"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
QSettings::setDefaultFormat(QSettings::IniFormat);
// Exit main application when last window is closed
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
......@@ -147,9 +162,12 @@ Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
//mainWindow->addLink(simulationLink);
mainWindow = MainWindow::instance();
// Remove splash screen
// Remove splash screen
splashScreen->finish(mainWindow);
if (upgraded) mainWindow->showInfoMessage(tr("Default Settings Loaded"), tr("QGroundControl has been upgraded from version %1 to version %2. Some of your user preferences have been reset to defaults for safety reasons. Please adjust them where needed.").arg(lastApplicationVersion).arg(QGC_APPLICATION_VERSION));
// Check if link could be connected
if (!udpLink->connect())
{
......
......@@ -66,12 +66,8 @@ MainWindow::MainWindow(QWidget *parent):
toolsMenuActions(),
currentView(VIEW_ENGINEER),
aboutToCloseFlag(false),
changingViewsFlag(false),
settings()
changingViewsFlag(false)
{
// Get current settings
settings.sync();
if (!settings.contains("CURRENT_VIEW"))
{
// Set this view as default view
......@@ -132,6 +128,7 @@ MainWindow::MainWindow(QWidget *parent):
// Setup user interface
ui.setupUi(this);
ui.actionNewCustomWidget->setEnabled(false);
setVisible(false);
......@@ -224,6 +221,43 @@ QString MainWindow::getWindowGeometryKey()
return QString::number(currentView)+"/geometry";
}
void MainWindow::buildCustomWidget()
{
// Show custom widgets only if UAS is connected
if (UASManager::instance()->getActiveUAS() != NULL)
{
// Enable custom widgets
ui.actionNewCustomWidget->setEnabled(true);
// Create custom widgets
QList<QGCToolWidget*> widgets = QGCToolWidget::createWidgetsFromSettings(this);
if (widgets.size() > 0)
{
ui.menuTools->addSeparator();
}
for(int i = 0; i < widgets.size(); ++i)
{
qDebug() << "ADDING WIDGET #" << i << widgets.at(i);
// Check if this widget already has a parent, do not create it in this case
QDockWidget* dock = dynamic_cast<QDockWidget*>(widgets.at(i)->parentWidget());
if (!dock)
{
QDockWidget* dock = new QDockWidget(widgets.at(i)->windowTitle(), this);
dock->setWidget(widgets.at(i));
connect(widgets.at(i), SIGNAL(destroyed()), dock, SLOT(deleteLater()));
QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
connect(showAction, SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool)));
connect(dock, SIGNAL(visibilityChanged(bool)), showAction, SLOT(setChecked(bool)));
widgets.at(i)->setMainMenuAction(showAction);
ui.menuTools->addAction(showAction);
addDockWidget(Qt::BottomDockWidgetArea, dock);
}
}
}
}
void MainWindow::buildCommonWidgets()
{
//TODO: move protocol outside UI
......@@ -824,10 +858,23 @@ void MainWindow::connectCommonWidgets()
void MainWindow::createCustomWidget()
{
//qDebug() << "ADDING CUSTOM WIDGET";
QGCToolWidget* tool = new QGCToolWidget(this);
QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", this);
if (QGCToolWidget::instances()->size() < 2)
{
// This is the first widget
ui.menuTools->addSeparator();
}
QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
dock->setWidget(tool);
this->addDockWidget(Qt::LeftDockWidgetArea, dock);
QAction* showAction = new QAction("Show Unnamed Tool", this);
connect(dock, SIGNAL(visibilityChanged(bool)), showAction, SLOT(setChecked(bool)));
connect(showAction, SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool)));
tool->setMainMenuAction(showAction);
ui.menuTools->addAction(showAction);
this->addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setVisible(true);
}
......@@ -1346,6 +1393,9 @@ void MainWindow::UASCreated(UASInterface* uas)
}
if (!ui.menuConnected_Systems->isEnabled()) ui.menuConnected_Systems->setEnabled(true);
// Custom widgets, added last to all menus and layouts
buildCustomWidget();
}
/**
......
......@@ -305,6 +305,7 @@ protected:
void clearView();
void buildCustomWidget();
void buildCommonWidgets();
void buildPxWidgets();
void buildSlugsWidgets();
......
......@@ -119,6 +119,13 @@ void QGCMAVLinkLogPlayer::setAccelerationFactorInt(int factor)
void QGCMAVLinkLogPlayer::loadLogFile(const QString& file)
{
// Check if logging is still enabled
if (mavlink->loggingEnabled())
{
mavlink->enableLogging(false);
MainWindow::instance()->showInfoMessage(tr("MAVLink Logging Stopped during Replay"), tr("MAVLink logging has been stopped during the log replay. To re-enable logging, use the link properties in the communication menu."));
}
// Ensure that the playback process is stopped
if (logFile.isOpen())
{
......
......@@ -52,7 +52,13 @@ QGCActionButton::QGCActionButton(QWidget *parent) :
connect(ui->editFinishButton, SIGNAL(clicked()), this, SLOT(endEditMode()));
connect(ui->editButtonName, SIGNAL(textChanged(QString)), this, SLOT(setActionButtonName(QString)));
connect(ui->editActionComboBox, SIGNAL(currentIndexChanged(QString)), ui->nameLabel, SLOT(setText(QString)));
endEditMode();
// Hide all edit items
ui->editActionComboBox->hide();
ui->editActionsRefreshButton->hide();
ui->editFinishButton->hide();
ui->editNameLabel->hide();
ui->editButtonName->hide();
// add action labels to combobox
for (int i = 0; i < MAV_ACTION_NB; i++)
......@@ -105,7 +111,28 @@ void QGCActionButton::endEditMode()
ui->editButtonName->hide();
// Write to settings
emit editingFinished();
isInEditMode = false;
}
void QGCActionButton::writeSettings(QSettings& settings)
{
settings.setValue("TYPE", "BUTTON");
settings.setValue("QGC_ACTION_BUTTON_DESCRIPTION", ui->nameLabel->text());
settings.setValue("QGC_ACTION_BUTTON_BUTTONTEXT", ui->actionButton->text());
settings.setValue("QGC_ACTION_BUTTON_ACTIONID", ui->editActionComboBox->currentIndex());
settings.sync();
}
void QGCActionButton::readSettings(const QSettings& settings)
{
ui->editNameLabel->setText(settings.value("QGC_ACTION_BUTTON_DESCRIPTION", "ERROR LOADING BUTTON").toString());
ui->editButtonName->setText(settings.value("QGC_ACTION_BUTTON_BUTTONTEXT", "UNKNOWN").toString());
ui->editActionComboBox->setCurrentIndex(settings.value("QGC_ACTION_BUTTON_ACTIONID", 0).toInt());
ui->nameLabel->setText(settings.value("QGC_ACTION_BUTTON_DESCRIPTION", "ERROR LOADING BUTTON").toString());
ui->actionButton->setText(settings.value("QGC_ACTION_BUTTON_BUTTONTEXT", "UNKNOWN").toString());
ui->editActionComboBox->setCurrentIndex(settings.value("QGC_ACTION_BUTTON_ACTIONID", 0).toInt());
qDebug() << "DONE READING SETTINGS";
}
......@@ -22,6 +22,8 @@ public slots:
void setActionButtonName(QString text);
void startEditMode();
void endEditMode();
void writeSettings(QSettings& settings);
void readSettings(const QSettings& settings);
private:
Ui::QGCActionButton *ui;
......
......@@ -53,6 +53,7 @@ void QGCParamSlider::endEditMode()
ui->maxSpinBox->hide();
ui->typeComboBox->hide();
isInEditMode = false;
emit editingFinished();
}
void QGCParamSlider::sendParameter()
......@@ -78,3 +79,13 @@ void QGCParamSlider::changeEvent(QEvent *e)
break;
}
}
void QGCParamSlider::writeSettings(QSettings& settings)
{
}
void QGCParamSlider::readSettings(const QSettings& settings)
{
}
......@@ -24,6 +24,8 @@ public slots:
void endEditMode();
/** @brief Send the parameter to the MAV */
void sendParameter();
void writeSettings(QSettings& settings);
void readSettings(const QSettings& settings);
protected:
QString parameterName; ///< Key/Name of the parameter
......
......@@ -6,20 +6,31 @@
#include <QInputDialog>
#include <QDockWidget>
#include <QContextMenuEvent>
#include <QSettings>
#include "QGCParamSlider.h"
#include "QGCActionButton.h"
#include "UASManager.h"
QGCToolWidget::QGCToolWidget(QWidget *parent) :
QGCToolWidget::QGCToolWidget(const QString& title, QWidget *parent) :
QWidget(parent),
toolLayout(new QVBoxLayout(this)),
mav(NULL),
mainMenuAction(NULL),
ui(new Ui::QGCToolWidget)
{
ui->setupUi(this);
setObjectName(title);
createActions();
toolLayout = ui->toolLayout;
toolLayout->setAlignment(Qt::AlignTop);
QDockWidget* dock = dynamic_cast<QDockWidget*>(this->parentWidget());
if (dock)
{
dock->setWindowTitle(title);
}
this->setWindowTitle(title);
QList<UASInterface*> systems = UASManager::instance()->getUASList();
foreach (UASInterface* uas, systems)
{
......@@ -30,6 +41,7 @@ QGCToolWidget::QGCToolWidget(QWidget *parent) :
}
}
connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*)));
if (!instances()->contains(title)) instances()->insert(title, this);
}
QGCToolWidget::~QGCToolWidget()
......@@ -37,6 +49,109 @@ QGCToolWidget::~QGCToolWidget()
delete ui;
}
/**
* @param parent Object later holding these widgets, usually the main window
* @return List of all widgets
*/
QList<QGCToolWidget*> QGCToolWidget::createWidgetsFromSettings(QWidget* parent)
{
// Store list of widgets
QSettings settings;
QList<QGCToolWidget*> newWidgets;
int size = settings.beginReadArray("QGC_TOOL_WIDGET_NAMES");
for (int i = 0; i < size; i++)
{
settings.setArrayIndex(i);
QString name = settings.value("TITLE", tr("UNKNOWN WIDGET %1").arg(i)).toString();
if (!instances()->contains(name))
{
QGCToolWidget* tool = new QGCToolWidget(name, parent);
instances()->insert(name, tool);
newWidgets.append(tool);
}
}
settings.endArray();
qDebug() << "NEW WIDGETS: " << newWidgets.size();
// Load individual widget items
for (int i = 0; i < newWidgets.size(); i++)
{
QString widgetName = newWidgets.at(i)->getTitle();
qDebug() << "READING: " << widgetName;
settings.beginGroup(widgetName);
int size = settings.beginReadArray("QGC_TOOL_WIDGET_ITEMS");
qDebug() << "CHILDREN SIZE:" << size;
for (int j = 0; j < size; j++)
{
settings.setArrayIndex(j);
QString type = settings.value("TYPE", "UNKNOWN").toString();
if (type != "UNKNOWN")
{
QGCToolWidgetItem* item = NULL;
if (type == "BUTTON")
{
item = new QGCActionButton(newWidgets.at(i));
qDebug() << "CREATED BUTTON";
}
if (item)
{
// Configure and add to layout
newWidgets.at(i)->addToolWidget(item);
item->readSettings(settings);
qDebug() << "Created tool widget";
}
}
else
{
qDebug() << "UNKNOWN TOOL WIDGET TYPE";
}
}
settings.endArray();
settings.endGroup();
}
return instances()->values();
}
void QGCToolWidget::storeWidgetsToSettings()
{
// Store list of widgets
QSettings settings;
settings.beginWriteArray("QGC_TOOL_WIDGET_NAMES");
for (int i = 0; i < instances()->size(); ++i)
{
settings.setArrayIndex(i);
settings.setValue("TITLE", instances()->values().at(i)->getTitle());
}
settings.endArray();
// Store individual widget items
for (int i = 0; i < instances()->size(); ++i)
{
QString widgetName = instances()->values().at(i)->getTitle();
settings.beginGroup(widgetName);
settings.beginWriteArray("QGC_TOOL_WIDGET_ITEMS");
int k = 0; // QGCToolItem counter
for (int j = 0; j < instances()->values().at(i)->children().size(); ++j)
{
// Store only QGCToolWidgetItems
QGCToolWidgetItem* item = dynamic_cast<QGCToolWidgetItem*>(instances()->values().at(i)->children().at(j));
if (item)
{
settings.setArrayIndex(k++);
// Store the ToolWidgetItem
item->writeSettings(settings);
}
}
settings.endArray();
settings.endGroup();
}
}
void QGCToolWidget::addUAS(UASInterface* uas)
{
UAS* newMav = dynamic_cast<UAS*>(uas);
......@@ -53,6 +168,7 @@ void QGCToolWidget::contextMenuEvent (QContextMenuEvent* event)
//menu.addAction(addParamAction);
menu.addAction(addButtonAction);
menu.addAction(setTitleAction);
menu.addAction(deleteAction);
menu.exec(event->globalPos());
}
......@@ -69,11 +185,33 @@ void QGCToolWidget::createActions()
setTitleAction = new QAction(tr("Set Widget Title"), this);
setTitleAction->setStatusTip(tr("Set the title caption of this tool widget"));
connect(setTitleAction, SIGNAL(triggered()), this, SLOT(setTitle()));
deleteAction = new QAction(tr("Delete this widget"), this);
deleteAction->setStatusTip(tr("Delete this widget permanently"));
connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteWidget()));
}
QMap<QString, QGCToolWidget*>* QGCToolWidget::instances()
{
static QMap<QString, QGCToolWidget*>* instances;
if (!instances) instances = new QMap<QString, QGCToolWidget*>();
return instances;
}
QList<QGCToolWidgetItem*>* QGCToolWidget::itemList()
{
static QList<QGCToolWidgetItem*>* instances;
if (!instances) instances = new QList<QGCToolWidgetItem*>();
return instances;
}
void QGCToolWidget::addParam()
{
QGCParamSlider* slider = new QGCParamSlider(this);
if (ui->hintLabel)
{
ui->hintLabel->deleteLater();
}
toolLayout->addWidget(slider);
slider->startEditMode();
}
......@@ -81,20 +219,80 @@ void QGCToolWidget::addParam()
void QGCToolWidget::addAction()
{
QGCActionButton* button = new QGCActionButton(this);
if (ui->hintLabel)
{
ui->hintLabel->deleteLater();
}
toolLayout->addWidget(button);
button->startEditMode();
}
void QGCToolWidget::addToolWidget(QGCToolWidgetItem* widget)
{
if (ui->hintLabel)
{
ui->hintLabel->deleteLater();
}
toolLayout->addWidget(widget);
}
const QString QGCToolWidget::getTitle()
{
QDockWidget* parent = dynamic_cast<QDockWidget*>(this->parentWidget());
if (parent)
{
return parent->windowTitle();
}
else
{
return this->windowTitle();
}
}
void QGCToolWidget::setTitle()
{
QDockWidget* parent = dynamic_cast<QDockWidget*>(this->parentWidget());
if (parent)
{
bool ok;
bool ok;
QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"),
tr("Widget title:"), QLineEdit::Normal,
parent->windowTitle(), &ok);
if (ok && !text.isEmpty())
parent->setWindowTitle(text);
{
QSettings settings;
settings.beginGroup(parent->windowTitle());
settings.remove("");
settings.endGroup();
parent->setWindowTitle(text);
storeWidgetsToSettings();
emit titleChanged(text);
if (mainMenuAction) mainMenuAction->setText(text);
}
}
}
void QGCToolWidget::setMainMenuAction(QAction* action)
{
this->mainMenuAction = action;
}
void QGCToolWidget::deleteWidget()
{
// Remove from settings
// Hide
this->hide();
instances()->remove(getTitle());
QSettings settings;
settings.beginGroup(getTitle());
settings.remove("");
settings.endGroup();
storeWidgetsToSettings();
// Delete
mainMenuAction->deleteLater();
this->deleteLater();
}
......@@ -3,7 +3,9 @@
#include <QWidget>
#include <QAction>
#include <QMap>
#include <QVBoxLayout>
#include "QGCToolWidgetItem.h"
#include "UAS.h"
......@@ -16,21 +18,41 @@ class QGCToolWidget : public QWidget
Q_OBJECT
public:
explicit QGCToolWidget(QWidget *parent = 0);
explicit QGCToolWidget(const QString& title, QWidget *parent = 0);
~QGCToolWidget();
/** @brief Factory method to instantiate all tool widgets */
static QList<QGCToolWidget*> createWidgetsFromSettings(QWidget* parent);
/** @Give the tool widget a reference to its action in the main menu */
void setMainMenuAction(QAction* action);
/** @brief All instances of this class */
static QMap<QString, QGCToolWidget*>* instances();
public slots:
void addUAS(UASInterface* uas);
/** @brief Delete this widget */
void deleteWidget();
/** @brief Store all widgets of this type to QSettings */
static void storeWidgetsToSettings();
signals:
void titleChanged(QString);
protected:
QAction* addParamAction;
QAction* addButtonAction;
QAction* setTitleAction;
QAction* deleteAction;
QVBoxLayout* toolLayout;
UAS* mav;
QAction* mainMenuAction;
void contextMenuEvent(QContextMenuEvent* event);
void createActions();
QList<QGCToolWidgetItem* >* itemList();
const QString getTitle();
/** @brief Add an existing tool widget */
void addToolWidget(QGCToolWidgetItem* widget);
protected slots:
void addParam();
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>QGCToolWidget</class>
<widget class="QWidget" name="QGCToolWidget">
<property name="geometry">
......@@ -15,7 +13,16 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="toolLayout">
<item>
<widget class="QLabel" name="hintLabel">
<property name="text">
<string>Right-click into the widget to customize</string>
</property>
</widget>
</item>
</layout>
</widget>
<pixmapfunction/>
<resources/>
<connections/>
</ui>
......@@ -3,6 +3,7 @@
#include <QMenu>
#include <QContextMenuEvent>
#include "QGCToolWidget.h"
#include "UASManager.h"
QGCToolWidgetItem::QGCToolWidgetItem(const QString& name, QWidget *parent) :
......@@ -12,23 +13,30 @@ QGCToolWidgetItem::QGCToolWidgetItem(const QString& name, QWidget *parent) :
uas(NULL),
_component(-1)
{
startEditAction = new QAction("Edit "+qgcToolWidgetItemName, this);
startEditAction = new QAction(tr("Edit %1").arg(qgcToolWidgetItemName), this);
connect(startEditAction, SIGNAL(triggered()), this, SLOT(startEditMode()));
stopEditAction = new QAction("Finish Editing Slider", this);
stopEditAction = new QAction(tr("Finish Editing %1").arg(qgcToolWidgetItemName), this);
connect(stopEditAction, SIGNAL(triggered()), this, SLOT(endEditMode()));
deleteAction = new QAction(tr("Delete %1").arg(qgcToolWidgetItemName), this);
connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
QGCToolWidget* tool = dynamic_cast<QGCToolWidget*>(parent);
if (tool)
{
connect(this, SIGNAL(editingFinished()), tool, SLOT(storeWidgetsToSettings()));
}
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
// Set first UAS if it exists
setActiveUAS(UASManager::instance()->getActiveUAS());
endEditMode();
}
QGCToolWidgetItem::~QGCToolWidgetItem()
{
delete startEditAction;
delete stopEditAction;
delete deleteAction;
}
void QGCToolWidgetItem::contextMenuEvent (QContextMenuEvent* event)
......@@ -37,6 +45,7 @@ void QGCToolWidgetItem::contextMenuEvent (QContextMenuEvent* event)
if (!isInEditMode)
{
menu.addAction(startEditAction);
menu.addAction(deleteAction);
}
else
{
......
......@@ -3,6 +3,7 @@
#include <QWidget>
#include <QAction>
#include <QSettings>
#include "UASInterface.h"
......@@ -19,11 +20,17 @@ public slots:
virtual void startEditMode() {}
virtual void endEditMode() {}
virtual void setComponent(int comp) {_component = comp;}
virtual void writeSettings(QSettings& settings) = 0;
virtual void readSettings(const QSettings& settings) = 0;
void setActiveUAS(UASInterface *uas);
signals:
void editingFinished();
protected:
QAction* startEditAction;
QAction* stopEditAction;
QAction* deleteAction;
bool isInEditMode;
QString qgcToolWidgetItemName;
UASInterface* uas;
......
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