Commit 4c50595f authored by Don Gagne's avatar Don Gagne

Qml Parameter Editor

parent b6b24a16
......@@ -596,14 +596,13 @@ INCLUDEPATH += \
src/VehicleSetup
FORMS += \
src/VehicleSetup/ParameterEditor.ui \
src/VehicleSetup/SetupView.ui \
HEADERS+= \
src/VehicleSetup/SetupView.h \
src/VehicleSetup/ParameterEditor.h \
src/VehicleSetup/VehicleComponent.h \
src/VehicleSetup/FirmwareUpgradeController.h \
src/VehicleSetup/ParameterEditorController.h \
src/VehicleSetup/PX4Bootloader.h \
src/VehicleSetup/PX4FirmwareUpgradeThread.h \
src/AutoPilotPlugins/AutoPilotPluginManager.h \
......@@ -626,9 +625,9 @@ HEADERS+= \
SOURCES += \
src/VehicleSetup/SetupView.cc \
src/VehicleSetup/ParameterEditor.cc \
src/VehicleSetup/VehicleComponent.cc \
src/VehicleSetup/FirmwareUpgradeController.cc \
src/VehicleSetup/ParameterEditorController.cc \
src/VehicleSetup/PX4Bootloader.cc \
src/VehicleSetup/PX4FirmwareUpgradeThread.cc \
src/AutoPilotPlugins/AutoPilotPluginManager.cc \
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 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/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "ParameterEditor.h"
#include "ui_ParameterEditor.h"
ParameterEditor::ParameterEditor(UASInterface* uas, const QStringList& filterList, QWidget* parent) :
QWidget(parent),
_ui(new Ui::ParameterEditor)
{
_ui->setupUi(this);
_ui->paramTreeWidget->setFilterList(filterList);
_ui->paramTreeWidget->setUAS(uas);
_ui->paramTreeWidget->handleOnboardParameterListUpToDate();
_ui->pendingCommitsWidget->setUAS(uas);
_ui->pendingCommitsWidget->update();
}
ParameterEditor::~ParameterEditor()
{
delete _ui;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 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/>.
======================================================================*/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
Rectangle {
QGCPalette { id: qgcPal; colorGroupEnabled: true }
ScreenTools { id: screenTools }
ParameterEditorController { id: controller }
QGCLabel { id: charWidth; text: "X"; visible: false }
readonly property real leftMargin: 10
readonly property real rightMargin: 20
readonly property int maxParamChars: 16
color: qgcPal.window
// We use an ExclusiveGroup to maintain the visibility of a single editing control at a time
ExclusiveGroup {
id: exclusiveEditorGroup
}
Column {
anchors.fill:parent
QGCLabel {
text: "PARAMETER EDITOR"
font.pointSize: screenTools.dpiAdjustedPointSize(20)
}
Item {
height: 20
width: 5
}
Row {
spacing: 10
layoutDirection: Qt.RightToLeft
width: parent.width
QGCButton {
text: "Clear RC to Param"
onClicked: controller.clearRCToParam()
}
QGCButton {
text: "Save to file"
onClicked: controller.saveToFile()
}
QGCButton {
text: "Load from file"
onClicked: controller.loadFromFile()
}
QGCButton {
id: firstButton
text: "Refresh"
onClicked: controller.refresh()
}
QGCLabel {
width: firstButton.x - parent.spacing
wrapMode: Text.WordWrap
text: "Click a parameter value to modify. Right-click to set an RC to Param mapping. Use caution when modifying parameters here since the values are not checked for validity."
}
}
Item {
id: lastSpacer
height: 10
width: 5
}
ScrollView {
id : scrollView
width: parent.width
height: parent.height - (lastSpacer.y + lastSpacer.height)
Column {
Repeater {
model: controller.componentIds
Column {
id: componentColumn
property int componentId: parseInt(modelData)
QGCLabel {
text: "Component #: " + componentId.toString()
font.pointSize: screenTools.dpiAdjustedPointSize(qgcPal.defaultFontPointSize + 4);
}
Item {
height: 10
width: 10
}
Repeater {
model: controller.getGroupsForComponent(componentColumn.componentId)
Column {
Rectangle {
id: groupRect
color: qgcPal.windowShade
height: groupBlock.height
width: scrollView.viewport.width - rightMargin
Column {
id: groupBlock
Rectangle {
color: qgcPal.windowShadeDark
height: groupLabel.height
width: groupRect.width
QGCLabel {
id: groupLabel
height: contentHeight + 5
x: leftMargin
text: modelData
verticalAlignment: Text.AlignVCenter
font.pointSize: screenTools.dpiAdjustedPointSize(qgcPal.defaultFontPointSize + 2);
}
}
Repeater {
model: controller.getFactsForGroup(componentColumn.componentId, modelData)
Row {
spacing: 10
x: leftMargin
Fact { id: modelFact; name: modelData + ":" + componentColumn.componentId }
QGCLabel {
text: modelFact.name
width: charWidth.contentWidth * (maxParamChars + 2)
}
QGCLabel {
text: modelFact.valueString + " " + modelFact.units
width: charWidth.contentWidth * 20
height: contentHeight
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.LeftButton) {
editor.checked = true
editor.focus = true
} else if (mouse.button == Qt.RightButton) {
controller.setRCToParam(modelData)
}
}
}
FactTextField {
id: editor
y: (parent.height - height) / 2
width: parent.width
visible: checked
focus: true
fact: modelFact
showUnits: true
onEditingFinished: checked = false
// We use an ExclusiveGroup to manage visibility
property bool checked: false
property ExclusiveGroup exclusiveGroup: exclusiveEditorGroup
onExclusiveGroupChanged: {
if (exclusiveGroup)
exclusiveGroup.bindCheckable(editor)
}
}
}
QGCLabel {
text: modelFact.shortDescription
}
} // Row - Fact value
} // Repeater - Facts
} // Column - Fact rows
} // Rectangle - Group
Item {
height: 10
width: 10
}
} // Column - Group
} // Repeater - Groups
Item {
height: 10
width: 10
}
} // Column - Component
} // Repeater - Components
} // Column - Component
} // ScrollView
} // Column - Outer
}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ParameterEditor</class>
<widget class="QWidget" name="ParameterEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>750</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>802</width>
<height>471</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QGroupBox" name="advancedConfigurationGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Onboard Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="advancedColumnLayout">
<item>
<widget class="QGCParamWidget" name="paramTreeWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="pendingChangesGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>329</width>
<height>400</height>
</size>
</property>
<property name="title">
<string>Changes Pending</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0">
<property name="spacing">
<number>-1</number>
</property>
<item>
<widget class="QGCPendingParamWidget" name="pendingCommitsWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_13">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="advancedStatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Status</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGCPendingParamWidget</class>
<extends>QWidget</extends>
<header>ui/QGCPendingParamWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QGCParamWidget</class>
<extends>QWidget</extends>
<header>ui/QGCParamWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "ParameterEditorController.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
#include "QGCMapRCToParamDialog.h"
#include "MainWindow.h"
/// @Brief Constructs a new ParameterEditorController Widget. This widget is used within the PX4VehicleConfig set of screens.
ParameterEditorController::ParameterEditorController(void) :
_uas(NULL),
_autopilot(NULL)
{
_uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(_uas);
_autopilot = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uas);
Q_ASSERT(_autopilot);
Q_ASSERT(_autopilot->pluginReady());
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
foreach (int componentId, groupMap.keys()) {
_componentIds += QString("%1").arg(componentId);
}
}
QStringList ParameterEditorController::getGroupsForComponent(int componentId)
{
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
return groupMap[componentId].keys();
}
QStringList ParameterEditorController::getFactsForGroup(int componentId, QString group)
{
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
return groupMap[componentId][group];
}
void ParameterEditorController::clearRCToParam(void)
{
Q_ASSERT(_uas);
_uas->unsetRCToParameterMap();
}
void ParameterEditorController::saveToFile(void)
{
Q_ASSERT(_autopilot);
QString msgTitle("Save Parameters");
QString fileName = QGCFileDialog::getSaveFileName(NULL,
msgTitle,
qgcApp()->savedParameterFilesLocation(),
"Parameter Files (*.params)",
"params",
true);
if (!fileName.isEmpty()) {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QGCMessageBox::critical(msgTitle, "Unable to create file");
return;
}
QTextStream stream(&file);
_autopilot->writeParametersToStream(stream);
file.close();
}
}
void ParameterEditorController::loadFromFile(void)
{
Q_ASSERT(_autopilot);
QString msgTitle("Load Parameters");
QString fileName = QGCFileDialog::getOpenFileName(NULL,
msgTitle,
qgcApp()->savedParameterFilesLocation(),
"Parameter Files (*.params);;All Files (*)");
if (!fileName.isEmpty()) {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QGCMessageBox::critical(msgTitle, "Unable to open file");
return;
}
QTextStream stream(&file);
_autopilot->readParametersFromStream(stream);
file.close();
}
}
void ParameterEditorController::refresh(void)
{
_autopilot->refreshAllParameters();
}
void ParameterEditorController::setRCToParam(const QString& paramName)
{
Q_ASSERT(_uas);
QGCMapRCToParamDialog * d = new QGCMapRCToParamDialog(paramName, _uas, MainWindow::instance());
d->exec();
}
......@@ -2,7 +2,7 @@
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
......@@ -21,31 +21,42 @@
======================================================================*/
#ifndef PARAMETEREDITOR_H
#define PARAMETEREDITOR_H
#include <QWidget>
#include "UASInterface.h"
/// @file
/// @brief This is the Parameter Editor widget which is used in the Parameters tab of Vehicle Setup.
/// @author Don Gagne <don@thegagnes.com>
namespace Ui {
class ParameterEditor;
}
#ifndef PARAMETEREDITORCONTROLLER_H
#define PARAMETEREDITORCONTROLLER_H
#include <QObject>
#include <QList>
class ParameterEditor : public QWidget
#include "AutoPilotPlugin.h"
#include "UASInterface.h"
class ParameterEditorController : public QObject
{
Q_OBJECT
public:
explicit ParameterEditor(UASInterface* uas, const QStringList& filterList, QWidget* parent = 0);
~ParameterEditor();
ParameterEditorController(void);
Q_PROPERTY(QStringList componentIds MEMBER _componentIds CONSTANT)
Q_INVOKABLE QStringList getGroupsForComponent(int componentId);
Q_INVOKABLE QStringList getFactsForGroup(int componentId, QString group);
Q_INVOKABLE void clearRCToParam(void);
Q_INVOKABLE void saveToFile(void);
Q_INVOKABLE void loadFromFile(void);
Q_INVOKABLE void refresh(void);
Q_INVOKABLE void setRCToParam(const QString& paramName);
QList<QObject*> model(void);
private:
Ui::ParameterEditor* _ui;
UASInterface* _uas;
AutoPilotPlugin* _autopilot;
QStringList _componentIds;
};
#endif
......@@ -30,11 +30,11 @@
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "VehicleComponent.h"
#include "ParameterEditor.h"
#include "QGCQmlWidgetHolder.h"
#include "MainWindow.h"
#include "QGCMessageBox.h"
#include "FirmwareUpgradeController.h"
#include "ParameterEditorController.h"
#include <QQmlError>
#include <QQmlContext>
......@@ -54,8 +54,9 @@ SetupView::SetupView(QWidget* parent) :
Q_UNUSED(fSucceeded);
Q_ASSERT(fSucceeded);
qmlRegisterType<FirmwareUpgradeController>("QGroundControl.FirmwareUpgradeController", 1, 0, "FirmwareUpgradeController");
qmlRegisterType<FirmwareUpgradeController>("QGroundControl.Controllers", 1, 0, "FirmwareUpgradeController");
qmlRegisterType<ParameterEditorController>("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
_ui->buttonHolder->rootContext()->setContextProperty("controller", this);
_ui->buttonHolder->setAutoPilot(NULL);
_ui->buttonHolder->setSource(QUrl::fromUserInput("qrc:/qml/SetupViewButtonsDisconnected.qml"));
......@@ -131,8 +132,14 @@ void SetupView::firmwareButtonClicked(void)
void SetupView::parametersButtonClicked(void)
{
ParameterEditor* setup = new ParameterEditor(_uasCurrent, QStringList(), this);
_changeSetupWidget(setup);
QGCQmlWidgetHolder* setup = new QGCQmlWidgetHolder;
Q_CHECK_PTR(setup);
Q_ASSERT(_autoPilotPlugin);
setup->setAutoPilot(_autoPilotPlugin);
setup->setSource(QUrl::fromUserInput("qrc:/qml/ParameterEditor.qml"));
_changeSetupWidget(setup);
}
void SetupView::summaryButtonClicked(void)
......
......@@ -25,7 +25,6 @@
#define SETUPVIEW_H
#include "UASInterface.h"
#include "ParameterEditor.h"
#include "VehicleComponent.h"
#include "AutoPilotPlugin.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