Unverified Commit 6a0f7679 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #8641 from mavlink/ValuesPageEditor

New grid based values page editor support
parents edf69f88 60d75808
......@@ -25,6 +25,8 @@
<file alias="JoystickBezel.png">resources/JoystickBezel.png</file>
<file alias="JoystickBezelLight.png">resources/JoystickBezelLight.png</file>
<file alias="land.svg">resources/land.svg</file>
<file alias="LockClosed.svg">resources/LockClosed.svg</file>
<file alias="LockOpen.svg">resources/LockOpen.svg</file>
<file alias="notile.png">resources/notile.png</file>
<file alias="Pause.svg">resources/Pause.svg</file>
<file alias="pause-mission.svg">resources/pause-mission.svg</file>
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://web.resource.org/cc/"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:ns1="http://sozi.baierouge.fr"
id="svg2064"
viewBox="0 0 150 150"
version="1.0"
y="0"
x="0"
>
<g
id="layer1"
>
<g
id="g2061"
transform="translate(10.641 12.191)"
>
<path
id="rect2723"
style="fill-rule:evenodd;fill:#282828"
d="m64.359 2c-20.072 0-36.231 16.159-36.231 36.231v40.256h10.064v-40.256c0-14.497 11.671-26.167 26.167-26.167s26.167 11.67 26.167 26.167v40.256h10.064v-40.256c0-20.072-16.159-36.231-36.231-36.231z"
/>
<rect
id="rect1941"
style="fill-rule:evenodd;fill:#000000"
rx="0.5"
ry=".5"
height="66.259"
width="85.603"
y="57.359"
x="21.558"
/>
</g
>
</g
>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>padlock silhouette a.j. 01</dc:title
>
<dc:date
>2011-01-20T20:53:10</dc:date
>
<dc:description
>Originally uploaded by AJ Ashton for OCAL 0.18</dc:description
>
<dc:source
>https://openclipart.org/detail/105751/padlock-silhouette-a.j.--01-by-anonymous</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>Anonymous</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>fix</rdf:li
>
<rdf:li
>keyword</rdf:li
>
<rdf:li
>librarians</rdf:li
>
<rdf:li
>tag</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://web.resource.org/cc/"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:ns1="http://sozi.baierouge.fr"
id="svg2064"
viewBox="0 0 150 150"
version="1.0"
y="0"
x="0"
>
<g
id="layer1"
>
<g
id="g2096"
transform="translate(-2.9648 2.5)"
>
<path
id="rect2723"
style="fill-rule:evenodd;fill:#282828"
d="m112.5 4.1909c-20.072 0-36.231 16.159-36.231 36.231v40.256h10.064v-40.256c0-14.497 11.671-26.167 26.167-26.167 14.5 0 26.17 11.67 26.17 26.167v27.756h10.06v-27.756c0-20.072-16.16-36.231-36.23-36.231z"
/>
<rect
id="rect1941"
style="fill-rule:evenodd;fill:#000000"
rx="0.5"
ry=".5"
height="66.259"
width="85.603"
y="74.55"
x="7.1987"
/>
</g
>
</g
>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>padlock unlocked silhou 01</dc:title
>
<dc:date
>2011-01-20T20:53:10</dc:date
>
<dc:description
>Originally uploaded by AJ Ashton for OCAL 0.18</dc:description
>
<dc:source
>https://openclipart.org/detail/105745/padlock-unlocked-silhou-01-by-anonymous</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>Anonymous</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>fix</rdf:li
>
<rdf:li
>keyword</rdf:li
>
<rdf:li
>librarians</rdf:li
>
<rdf:li
>tag</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>
......@@ -10,6 +10,8 @@
import QtQuick 2.3
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.5
import QtQml 2.12
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
......@@ -21,23 +23,32 @@ import QGroundControl 1.0
/// Value page for InstrumentPanel PageView
Column {
id: _largeColumn
id: _root
width: pageWidth
spacing: _margins
spacing: ScreenTools.defaultFontPixelHeight / 2
property bool showSettingsIcon: true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property real _margins: ScreenTools.defaultFontPixelWidth / 2
property bool showLockIcon: true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property real _margins: ScreenTools.defaultFontPixelWidth / 2
property int _colMax: 4
property bool _settingsUnlocked: false
property var _valuePickerInstrumentValue: null
property int _valuePickerRowIndex: 0
property var _rgFontSizes: [ ScreenTools.defaultFontPointSize, ScreenTools.smallFontPointSize, ScreenTools.mediumFontPointSize, ScreenTools.largeFontPointSize ]
property real _blankEntryHeight: ScreenTools.defaultFontPixelHeight * 2
property real _columnButtonWidth: ScreenTools.minTouchPixels / 2
property real _columnButtonHeight: ScreenTools.minTouchPixels
property real _columnButtonSpacing: 2
property real _columnButtonsTotalHeight: (_columnButtonHeight * 2) + _columnButtonSpacing
QGCPalette { id:qgcPal; colorGroupEnabled: true }
ValuesWidgetController {
id: controller
}
ValuesWidgetController { id: controller }
function showSettings() {
mainWindow.showComponentDialog(propertyPicker, qsTr("Value Widget Setup"), mainWindow.showDialogDefaultWidth, StandardButton.Ok)
function showSettings(settingsUnlocked) {
_settingsUnlocked = settingsUnlocked
}
function listContains(list, value) {
......@@ -49,88 +60,166 @@ Column {
return false
}
Repeater {
model: _activeVehicle ? controller.largeValues : 0
Loader {
sourceComponent: fact ? largeValue : undefined
property Fact fact: _activeVehicle.getFact(modelData.replace("Vehicle.", ""))
}
} // Repeater - Large
Flow {
id: _smallFlow
width: parent.width
layoutDirection: Qt.LeftToRight
spacing: _margins
Repeater {
model: _activeVehicle ? controller.smallValues : 0
Loader {
sourceComponent: fact ? smallValue : undefined
property Fact fact: _activeVehicle.getFact(modelData.replace("Vehicle.", ""))
}
} // Repeater - Small
} // Flow
ButtonGroup { id: factRadioGroup }
Component {
id: largeValue
id: valueItemMouseAreaComponent
Column {
width: _largeColumn.width
property bool largeValue: listContains(controller.altitudeProperties, fact.name)
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
text: fact.shortDescription + (fact.units ? " (" + fact.units + ")" : "")
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
font.pointSize: ScreenTools.mediumFontPointSize * (largeValue ? 1.3 : 1.0)
font.family: largeValue ? ScreenTools.demiboldFontFamily : ScreenTools.normalFontFamily
fontSizeMode: Text.HorizontalFit
text: fact.enumOrValueString
MouseArea {
anchors.centerIn: parent
width: parent.width
height: _columnButtonsTotalHeight
visible: _settingsUnlocked
property var instrumentValue
property int rowIndex
onClicked: {
_valuePickerInstrumentValue = instrumentValue
_valuePickerRowIndex = rowIndex
mainWindow.showComponentDialog(valuePickerDialog, qsTr("Select Value"), mainWindow.showDialogDefaultWidth, StandardButton.Ok)
}
}
}
Component {
id: smallValue
Repeater {
id: rowRepeater
model: controller.valuesModel
Column {
width: (pageWidth / 2) - (_margins / 2) - 0.1
clip: true
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
font.pointSize: ScreenTools.isTinyScreen ? ScreenTools.smallFontPointSize * 0.75 : ScreenTools.smallFontPointSize
text: fact.shortDescription
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
fontSizeMode: Text.HorizontalFit
text: fact.enumOrValueString
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
font.pointSize: ScreenTools.isTinyScreen ? ScreenTools.smallFontPointSize * 0.75 : ScreenTools.smallFontPointSize
fontSizeMode: Text.HorizontalFit
text: fact.units
id: rowRepeaterLayout
spacing: 1
property int rowIndex: index
Row {
id: columnRow
spacing: 1
Repeater {
id: columnRepeater
model: object
property real _interColumnSpacing: (columnRepeater.count - (_settingsUnlocked ? 0 : 1)) * columnRow.spacing
property real columnWidth: (pageWidth - (_settingsUnlocked ? _columnButtonWidth : 0) - _interColumnSpacing) / columnRepeater.count
onItemAdded: valueItemMouseAreaComponent.createObject(item, { "instrumentValue": object.get(index), "rowIndex": index })
Item {
width: columnRepeater.columnWidth
height: value.y + value.height
anchors.verticalCenter: _settingsUnlocked ? parent.verticalCenter : undefined
anchors.bottom: _settingsUnlocked ? undefined : parent.bottom
QGCLabel {
width: columnRepeater.columnWidth
height: _columnButtonsTotalHeight
font.pointSize: ScreenTools.smallFontPointSize
text: _settingsUnlocked ? qsTr("BLANK") : ""
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: !object.fact
}
QGCLabel {
id: label
width: columnRepeater.columnWidth
font.pointSize: ScreenTools.smallFontPointSize
text: object.label.toUpperCase()
horizontalAlignment: Text.AlignHCenter
visible: object.fact && object.label
}
QGCLabel {
id: value
anchors.topMargin: label.visible ? 2 : 0
anchors.top: label.visible ? label.bottom : parent.top
width: columnRepeater.columnWidth
font.pointSize: _rgFontSizes[object.fontSize]
text: visible ? (object.fact.enumOrValueString + (object.showUnits ? object.fact.units : "")) : ""
horizontalAlignment: Text.AlignHCenter
visible: object.fact
}
}
} // Repeater - columns
ColumnLayout {
id: columnsButtonsLayout
width: _columnButtonWidth
spacing: _columnButtonSpacing
visible: _settingsUnlocked
QGCButton {
Layout.fillHeight: true
Layout.minimumHeight: ScreenTools.minTouchPixels
Layout.preferredWidth: parent.width
text: qsTr("+")
onClicked: controller.appendColumn(rowRepeaterLayout.rowIndex)
}
QGCButton {
Layout.fillHeight: true
Layout.minimumHeight: ScreenTools.minTouchPixels
Layout.preferredWidth: parent.width
text: qsTr("-")
enabled: index !== 0 || columnRepeater.count !== 1
onClicked: controller.deleteLastColumn(rowRepeaterLayout.rowIndex)
}
}
} // RowLayout
RowLayout {
width: parent.width
height: ScreenTools.defaultFontPixelWidth * 2
spacing: 1
visible: _settingsUnlocked
QGCButton {
Layout.fillWidth: true
Layout.preferredHeight: ScreenTools.defaultFontPixelWidth * 2
text: qsTr("+")
onClicked: controller.insertRow(index)
}
QGCButton {
Layout.fillWidth: true
Layout.preferredHeight: ScreenTools.defaultFontPixelWidth * 2
text: qsTr("-")
enabled: index !== 0
onClicked: controller.deleteRow(index)
}
}
}
} // Repeater - rows
QGCButton {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Reset To Defaults")
visible: _settingsUnlocked
onClicked: controller.resetToDefaults()
}
Component {
id: propertyPicker
id: valuePickerDialog
QGCViewDialog {
id: _propertyPickerDialog
function accept() {
if (factRadioGroup.checkedButton) {
_valuePickerInstrumentValue.setFact(factRadioGroup.checkedButton.radioFactGroupName, factRadioGroup.checkedButton.radioFact.name, labelTextField.text, fontSizeCombo.currentIndex)
} else {
_valuePickerInstrumentValue.clearFact()
}
hideDialog()
}
Connections {
target: factRadioGroup
onCheckedButtonChanged: labelTextField.text = factRadioGroup.checkedButton.radioFact.shortDescription
}
ButtonGroup { id: fontRadioGroup }
QGCFlickable {
anchors.fill: parent
......@@ -138,39 +227,50 @@ Column {
flickableDirection: Flickable.VerticalFlick
clip: true
Column {
ColumnLayout {
id: column
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
/*
Leaving this here for now just in case
FactCheckBox {
text: qsTr("Show large compass")
fact: _showLargeCompass
visible: _showLargeCompass.visible
RowLayout {
Layout.fillWidth: true
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel { text: qsTr("Label") }
QGCTextField {
id: labelTextField
Layout.fillWidth: true
text: _valuePickerInstrumentValue.label
}
}
property Fact _showLargeCompass: QGroundControl.settingsManager.appSettings.showLargeCompass
RowLayout {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel { text: qsTr("Font Size (for whole row)") }
QGCComboBox {
id: fontSizeCombo
model: [ qsTr("Default"), qsTr("Small"), qsTr("Medium"), qsTr("Large") ]
currentIndex: _valuePickerInstrumentValue.fontSize
sizeToContents: true
onActivated: _valuePickerInstrumentValue.fontSize = index
}
}
*/
Item {
width: 1
height: _margins
QGCCheckBox {
text: qsTr("Show Units")
checked: _valuePickerInstrumentValue.showUnits
onClicked: _valuePickerInstrumentValue.showUnits = checked
}
QGCLabel {
id: _label
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("Select the values you want to display:")
QGCButton {
text: qsTr("Blank Entry")
onClicked: { _valuePickerInstrumentValue.clearFact(); hideDialog() }
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
sourceComponent: factGroupList
property var factGroup: _activeVehicle
......@@ -181,14 +281,12 @@ Column {
model: _activeVehicle.factGroupNames
Loader {
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
sourceComponent: factGroupList
property var factGroup: _activeVehicle.getFactGroup(modelData)
property string factGroupName: modelData
}
}
}
}
......@@ -203,8 +301,6 @@ Column {
// property string factGroupName
Column {
spacing: _margins
SectionHeader {
id: header
anchors.left: parent.left
......@@ -214,78 +310,23 @@ Column {
}
Column {
spacing: _margins
visible: header.checked
visible: header.checked
Repeater {
model: factGroup ? factGroup.factNames : 0
RowLayout {
spacing: _margins
visible: factGroup.getFact(modelData).shortDescription !== ""
property string propertyName: factGroupName + "." + modelData
QGCRadioButton {
text: radioFact.shortDescription
ButtonGroup.group: factRadioGroup
checked: radioFactGroupName == _valuePickerInstrumentValue.factGroupName && radioFact == _valuePickerInstrumentValue.fact
function removeFromList(list, value) {
var newList = []
for (var i=0; i<list.length; i++) {
if (list[i] !== value) {
newList.push(list[i])
}
}
return newList
}
property string radioFactGroupName: factGroupName
property var radioFact: factGroup.getFact(modelData)
function addToList(list, value) {
var found = false
for (var i=0; i<list.length; i++) {
if (list[i] === value) {
found = true
break
}
Component.onCompleted: {
if (checked) {
header.checked = true
}
if (!found) {
list.push(value)
}
return list
}
function updateValues() {
if (_addCheckBox.checked) {
if (_largeCheckBox.checked) {
controller.largeValues = addToList(controller.largeValues, propertyName)
controller.smallValues = removeFromList(controller.smallValues, propertyName)
} else {
controller.smallValues = addToList(controller.smallValues, propertyName)
controller.largeValues = removeFromList(controller.largeValues, propertyName)
}
} else {
controller.largeValues = removeFromList(controller.largeValues, propertyName)
controller.smallValues = removeFromList(controller.smallValues, propertyName)
}
}
QGCCheckBox {
id: _addCheckBox
text: factGroup.getFact(modelData).shortDescription
checked: listContains(controller.smallValues, propertyName) || _largeCheckBox.checked
onClicked: updateValues()
Layout.fillWidth: true
Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 20
Component.onCompleted: {
if (checked) {
header.checked = true
}
}
}
QGCCheckBox {
id: _largeCheckBox
text: qsTr("Large")
checked: listContains(controller.largeValues, propertyName)
enabled: _addCheckBox.checked
onClicked: updateValues()
}
}
}
......
......@@ -14,51 +14,429 @@
#include <QSettings>
const char* ValuesWidgetController::_groupKey = "ValuesWidget";
const char* ValuesWidgetController::_largeValuesKey = "large";
const char* ValuesWidgetController::_smallValuesKey = "small";
const char* ValuesWidgetController::_groupKey = "ValuesWidget2";
const char* ValuesWidgetController::_rowsKey = "rows";
const char* ValuesWidgetController::_columnsKey = "columns";
ValuesWidgetController::ValuesWidgetController(void)
const char* ValuesWidgetController::_deprecatedGroupKey = "ValuesWidget";
const char* ValuesWidgetController::_deprecatedLargeValuesKey = "large";
const char* ValuesWidgetController::_deprecatedSmallValuesKey = "small";
const char* InstrumentValue::_factGroupNameKey = "groupName";
const char* InstrumentValue::_factNameKey = "factName";
const char* InstrumentValue::_labelKey = "label";
const char* InstrumentValue::_fontSizeKey = "fontSize";
const char* InstrumentValue::_showUnitsKey = "showUnits";
ValuesWidgetController::ValuesWidgetController(bool forDefaultSettingsCreation)
: _valuesModel(new QmlObjectListModel(this))
{
QSettings settings;
settings.beginGroup(_groupKey);
QStringList largeDefaults, smallDefaults;
qgcApp()->toolbox()->corePlugin()->valuesWidgetDefaultSettings(largeDefaults, smallDefaults);
_multiVehicleMgr = qgcApp()->toolbox()->multiVehicleManager();
connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &ValuesWidgetController::_activeVehicleChanged);
if (!forDefaultSettingsCreation) {
_loadSettings();
}
}
InstrumentValue* ValuesWidgetController::_createNewInstrumentValueWorker(Vehicle* activeVehicle, int fontSize, QmlObjectListModel* rowModel)
{
InstrumentValue* newValue = new InstrumentValue(activeVehicle, fontSize, rowModel);
connect(newValue, &InstrumentValue::factChanged, this, &ValuesWidgetController::_saveSettings);
connect(newValue, &InstrumentValue::factGroupNameChanged, this, &ValuesWidgetController::_saveSettings);
connect(newValue, &InstrumentValue::labelChanged, this, &ValuesWidgetController::_saveSettings);
connect(newValue, &InstrumentValue::fontSizeChanged, this, &ValuesWidgetController::_saveSettings);
connect(newValue, &InstrumentValue::showUnitsChanged, this, &ValuesWidgetController::_saveSettings);
return newValue;
}
_largeValues = settings.value(_largeValuesKey, largeDefaults).toStringList();
_smallValues = settings.value(_smallValuesKey, smallDefaults).toStringList();
_altitudeProperties << "altitudeRelative" << "altitudeAMSL";
InstrumentValue* ValuesWidgetController::appendColumn(int rowIndex)
{
InstrumentValue* newValue = nullptr;
// Keep back compat for removed WGS84 value
if (_largeValues.contains ("Vehicle.altitudeWGS84")) {
setLargeValues(_largeValues.replaceInStrings("Vehicle.altitudeWGS84", "Vehicle.altitudeRelative"));
if (rowIndex >= 0 && rowIndex < _valuesModel->count()) {
QmlObjectListModel* row = _valuesModel->value<QmlObjectListModel*>(rowIndex);
int fontSize = InstrumentValue::DefaultFontSize;
if (row->count()) {
fontSize = row->value<InstrumentValue*>(0)->fontSize();
}
newValue = _createNewInstrumentValueWorker(_currentActiveVehicle(), fontSize, row);
row->append(newValue);
}
if (_smallValues.contains ("Vehicle.altitudeWGS84")) {
setSmallValues(_largeValues.replaceInStrings("Vehicle.altitudeWGS84", "Vehicle.altitudeRelative"));
_saveSettings();
return newValue;
}
void ValuesWidgetController::deleteLastColumn(int rowIndex)
{
if (rowIndex >= 0 && rowIndex < _valuesModel->count()) {
QmlObjectListModel* row = _valuesModel->value<QmlObjectListModel*>(rowIndex);
if (rowIndex != 0 || row->count() > 1) {
row->removeAt(row->count() - 1);
}
if (row->count() == 0) {
// Last column was deleted, delete the row as well
_valuesModel->removeAt(rowIndex);
}
}
_saveSettings();
}
void ValuesWidgetController::setLargeValues(const QStringList& values)
QmlObjectListModel* ValuesWidgetController::appendRow(bool addBlanksColumn)
{
QmlObjectListModel* newRow = new QmlObjectListModel(_valuesModel);
_valuesModel->append(newRow);
int rowIndex = _valuesModel->count() - 1;
if (addBlanksColumn) {
appendColumn(rowIndex);
}
_saveSettings();
return newRow;
}
QmlObjectListModel* ValuesWidgetController::insertRow(int atIndex, bool addBlanksColumn)
{
QmlObjectListModel* newRow = nullptr;
if (atIndex >= 0 && atIndex < _valuesModel->count() + 1) {
QmlObjectListModel* newRow = new QmlObjectListModel(_valuesModel);
_valuesModel->insert(atIndex, newRow);
if (addBlanksColumn) {
appendColumn(atIndex);
}
_saveSettings();
}
return newRow;
}
void ValuesWidgetController::deleteRow(int rowIndex)
{
if (rowIndex >= 0 && rowIndex < _valuesModel->count()) {
if (_valuesModel->count() > 1) {
_valuesModel->removeAt(rowIndex);
}
_saveSettings();
}
}
Vehicle* ValuesWidgetController::_currentActiveVehicle(void)
{
Vehicle* activeVehicle = _multiVehicleMgr->activeVehicle();
if (!activeVehicle) {
activeVehicle = _multiVehicleMgr->offlineEditingVehicle();
}
return activeVehicle;
}
void ValuesWidgetController::_activeVehicleChanged(Vehicle* activeVehicle)
{
if (!activeVehicle) {
activeVehicle = _currentActiveVehicle();
}
for (int rowIndex=0; rowIndex<_valuesModel->count(); rowIndex++) {
QmlObjectListModel* rowModel = _valuesModel->value<QmlObjectListModel*>(rowIndex);
for (int colIndex=0; colIndex<rowModel->count(); colIndex++) {
rowModel->value<InstrumentValue*>(colIndex)->activeVehicleChanged(activeVehicle);
}
}
}
bool ValuesWidgetController::_validRowIndex(int rowIndex)
{
return rowIndex >= 0 && rowIndex < _valuesModel->count();
}
int ValuesWidgetController::fontSizeForRow(int rowIndex)
{
return _validRowIndex(rowIndex) ? _rgFontSizeByRow[rowIndex].toInt() : _rgFontSizeByRow[0].toInt();
}
void ValuesWidgetController::setFontSizeForRow(int rowIndex, int fontSize)
{
if (_validRowIndex(rowIndex)) {
_rgFontSizeByRow[rowIndex] = fontSize;
}
}
void ValuesWidgetController::_saveSettings(void)
{
if (_preventSaveSettings) {
return;
}
QSettings settings;
settings.beginGroup(_groupKey);
settings.setValue(_largeValuesKey, values);
settings.remove(QStringLiteral(""));
settings.beginWriteArray(_rowsKey);
for (int rowIndex=0; rowIndex<_valuesModel->count(); rowIndex++) {
QmlObjectListModel* colValuesModel = _valuesModel->value<QmlObjectListModel*>(rowIndex);
settings.setArrayIndex(rowIndex);
settings.beginWriteArray(_columnsKey);
for (int colIndex=0; colIndex<colValuesModel->count(); colIndex++) {
settings.setArrayIndex(colIndex);
colValuesModel->value<InstrumentValue*>(colIndex)->saveToSettings(settings);
}
settings.endArray();
}
settings.endArray();
}
void ValuesWidgetController::_loadSettings(void)
{
QSettings settings;
_valuesModel->deleteLater();
_valuesModel = new QmlObjectListModel(this);
emit valuesModelChanged(_valuesModel);
if (settings.childGroups().contains(_deprecatedGroupKey)) {
settings.beginGroup(_deprecatedGroupKey);
QStringList largeValues = settings.value(_deprecatedLargeValuesKey).toStringList();
QStringList smallValues = settings.value(_deprecatedSmallValuesKey).toStringList();
QStringList altitudeProperties = { "altitudeRelative" , "altitudeAMSL" };
int rowIndex = -1;
int valueCount = 0;
QmlObjectListModel* rowModel = nullptr;
for (const QString& largeValue: largeValues) {
QStringList parts = largeValue.split(".");
rowModel = appendRow(false /* addBlankColumn */);
rowIndex++;
InstrumentValue* colValue = appendColumn(rowIndex);
colValue->setFact(parts[0], parts[1], QString());
colValue->setLabel(colValue->fact()->shortDescription());
colValue->setShowUnits(true);
colValue->setFontSize(altitudeProperties.contains(parts[1]) ? InstrumentValue::LargeFontSize : InstrumentValue::DefaultFontSize);
}
_largeValues = values;
emit largeValuesChanged(values);
valueCount = 0;
rowModel = nullptr;
for (const QString& smallValue: smallValues) {
QStringList parts = smallValue.split(".");
if (!(valueCount++ & 1)) {
rowModel = appendRow(false /* addBlankColumn */);
rowIndex++;
}
InstrumentValue* colValue = appendColumn(rowIndex);
colValue->setFact(parts[0], parts[1], QString());
colValue->setLabel(colValue->fact()->shortDescription());
colValue->setShowUnits(true);
colValue->setFontSize(InstrumentValue::SmallFontSize);
}
settings.endGroup();
settings.remove(_deprecatedGroupKey);
} else {
_preventSaveSettings = true;
settings.beginGroup(_groupKey);
int cRows = settings.beginReadArray(_rowsKey);
for (int rowIndex=0; rowIndex<cRows; rowIndex++) {
appendRow(false /* addBlankColumns */);
settings.setArrayIndex(rowIndex);
int cCols = settings.beginReadArray(_columnsKey);
for (int colIndex=0; colIndex<cCols; colIndex++) {
settings.setArrayIndex(colIndex);
appendColumn(rowIndex)->readFromSettings(settings);
}
settings.endArray();
}
settings.endArray();
_preventSaveSettings = false;
}
// Use defaults if nothing there
if (_valuesModel->count() == 0) {
_valuesModel->deleteLater();
_valuesModel = qgcApp()->toolbox()->corePlugin()->valuesWidgetDefaultSettings(this);
emit valuesModelChanged(_valuesModel);
}
}
void ValuesWidgetController::setSmallValues(const QStringList& values)
void ValuesWidgetController::resetToDefaults(void)
{
QSettings settings;
settings.beginGroup(_groupKey);
settings.setValue(_smallValuesKey, values);
settings.remove("");
_loadSettings();
}
void ValuesWidgetController::setPreventSaveSettings(bool preventSaveSettings)
{
_preventSaveSettings = preventSaveSettings;
}
InstrumentValue::InstrumentValue(Vehicle* activeVehicle, int fontSize, QmlObjectListModel* rowModel)
: QObject (rowModel)
, _activeVehicle(activeVehicle)
, _rowModel (rowModel)
, _fontSize (fontSize)
{
}
void InstrumentValue::activeVehicleChanged(Vehicle* activeVehicle)
{
_activeVehicle = activeVehicle;
if (_fact) {
_fact = nullptr;
FactGroup* factGroup = nullptr;
QString factName;
if (_factGroupName == QStringLiteral("Vehicle")) {
factGroup = _activeVehicle;
} else {
factGroup = _activeVehicle->getFactGroup(_factGroupName);
}
if (factGroup) {
_fact = factGroup->getFact(factName);
}
emit factChanged(_fact);
}
}
void InstrumentValue::setFact(QString factGroupName, QString factName, QString label)
{
if (_fact) {
_fact = nullptr;
}
FactGroup* factGroup = nullptr;
if (factGroupName == QStringLiteral("Vehicle")) {
factGroup = _activeVehicle;
} else {
factGroup = _activeVehicle->getFactGroup(factGroupName);
}
if (factGroup) {
_fact = factGroup->getFact(factName);
}
if (_fact) {
_factGroupName = factGroupName;
_label = label;
} else {
_factGroupName.clear();
_label.clear();
}
emit labelChanged(_label);
emit factChanged(_fact);
emit factGroupNameChanged(_factGroupName);
}
void InstrumentValue::_setFontSize(int fontSize)
{
if (fontSize != _fontSize) {
_fontSize = fontSize;
emit fontSizeChanged(fontSize);
}
}
void InstrumentValue::setFontSize(int fontSize)
{
_setFontSize(fontSize);
// All other items in row must change to match
for (int i=0; i<_rowModel->count(); i++) {
InstrumentValue* instrumentValue = _rowModel->value<InstrumentValue*>(i);
if (instrumentValue != this) {
instrumentValue->_setFontSize(fontSize);
}
}
}
void InstrumentValue::saveToSettings(QSettings& settings) const
{
if (_fact) {
settings.setValue(_factGroupNameKey, _factGroupName);
settings.setValue(_factNameKey, _fact->name());
} else {
settings.setValue(_factGroupNameKey, "");
settings.setValue(_factNameKey, "");
}
settings.setValue(_labelKey, _label);
settings.setValue(_fontSizeKey, _fontSize);
settings.setValue(_showUnitsKey, _showUnits);
}
void InstrumentValue::readFromSettings(const QSettings& settings)
{
_factGroupName = settings.value(_factGroupNameKey).toString();
_label = settings.value(_labelKey).toString();
_fontSize = settings.value(_fontSizeKey).toInt();
_showUnits = settings.value(_showUnitsKey).toBool();
QString factName = settings.value(_factNameKey).toString();
if (!factName.isEmpty()) {
setFact(_factGroupName, factName, _label);
}
emit factChanged (_fact);
emit factGroupNameChanged (_factGroupName);
emit labelChanged (_label);
emit fontSizeChanged (_fontSize);
emit showUnitsChanged (_showUnits);
}
void InstrumentValue::setLabel(const QString& label)
{
if (label != _label) {
_label = label;
emit labelChanged(label);
}
}
void InstrumentValue::setShowUnits(bool showUnits)
{
if (showUnits != _showUnits) {
_showUnits = showUnits;
emit showUnitsChanged(showUnits);
}
}
void InstrumentValue::clearFact(void)
{
_fact = nullptr;
_factGroupName.clear();
_label.clear();
_showUnits = true;
_smallValues = values;
emit smallValuesChanged(values);
emit factChanged (_fact);
emit factGroupNameChanged (_factGroupName);
emit labelChanged (_label);
emit showUnitsChanged (_showUnits);
}
......@@ -7,42 +7,124 @@
*
****************************************************************************/
#pragma once
#ifndef ValuesWidgetController_H
#define ValuesWidgetController_H
#include "FactSystem.h"
#include "QmlObjectListModel.h"
#include "QGCApplication.h"
#include <QObject>
class ValuesWidgetController;
class InstrumentValue : public QObject
{
Q_OBJECT
public:
enum FontSize {
DefaultFontSize=0,
SmallFontSize,
MediumFontSize,
LargeFontSize
};
InstrumentValue(Vehicle* activeVehicle, int fontSize, QmlObjectListModel* rowModel);
Q_PROPERTY(QString factGroupName MEMBER _factGroupName NOTIFY factGroupNameChanged)
Q_PROPERTY(Fact* fact READ fact NOTIFY factChanged)
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
Q_PROPERTY(bool showUnits READ showUnits WRITE setShowUnits NOTIFY showUnitsChanged)
Q_INVOKABLE void setFact(QString factGroupName, QString factName, QString label);
Q_INVOKABLE void clearFact(void);
Fact* fact (void) { return _fact; }
int fontSize (void) const { return _fontSize; }
QString label (void) const { return _label; }
bool showUnits (void) const { return _showUnits; }
void setFontSize (int fontSize);
void setLabel (const QString& label);
void setShowUnits (bool showUnits);
void activeVehicleChanged (Vehicle* activeVehicle);
void saveToSettings (QSettings& settings) const;
void readFromSettings (const QSettings& settings);
signals:
void factChanged (Fact* fact);
void factGroupNameChanged (QString factGroup);
void labelChanged (QString label);
void fontSizeChanged (int fontSize);
void showUnitsChanged (bool showUnits);
private slots:
private:
void _setFontSize(int fontSize);
Vehicle* _activeVehicle = nullptr;
QmlObjectListModel* _rowModel = nullptr;
Fact* _fact = nullptr;
QString _factGroupName;
QString _label;
bool _showUnits = true;
int _fontSize = DefaultFontSize;
static const char* _factGroupNameKey;
static const char* _factNameKey;
static const char* _labelKey;
static const char* _fontSizeKey;
static const char* _showUnitsKey;
};
class ValuesWidgetController : public QObject
{
Q_OBJECT
public:
ValuesWidgetController(void);
ValuesWidgetController(bool forDefaultSettingsCreation = false);
Q_PROPERTY(QStringList largeValues READ largeValues WRITE setLargeValues NOTIFY largeValuesChanged)
Q_PROPERTY(QStringList smallValues READ smallValues WRITE setSmallValues NOTIFY smallValuesChanged)
Q_PROPERTY(QmlObjectListModel* valuesModel READ valuesModel NOTIFY valuesModelChanged)
Q_PROPERTY(QStringList altitudeProperties READ altitudeProperties CONSTANT)
Q_INVOKABLE InstrumentValue* appendColumn (int rowIndex);
Q_INVOKABLE void deleteLastColumn (int rowIndex);
Q_INVOKABLE QmlObjectListModel* appendRow (bool addBlanksColumn = true);
Q_INVOKABLE QmlObjectListModel* insertRow (int atIndex, bool addBlanksColumn = true);
Q_INVOKABLE void deleteRow (int rowIndex);
Q_INVOKABLE int fontSizeForRow (int rowIndex);
Q_INVOKABLE void setFontSizeForRow (int rowIndex, int fontSize);
Q_INVOKABLE void resetToDefaults (void);
QStringList largeValues(void) const { return _largeValues; }
QStringList smallValues(void) const { return _smallValues; }
void setLargeValues(const QStringList& values);
void setSmallValues(const QStringList& values);
QStringList altitudeProperties(void) const { return _altitudeProperties; }
QmlObjectListModel* valuesModel(void) { return _valuesModel; }
/// Turn on/off saving changes to QSettings
void setPreventSaveSettings(bool preventSaveSettings);
signals:
void largeValuesChanged(QStringList values);
void smallValuesChanged(QStringList values);
void valuesModelChanged(QmlObjectListModel* valuesModel);
private slots:
void _activeVehicleChanged(Vehicle* activeVehicle);
Vehicle* _currentActiveVehicle(void);
void _saveSettings (void);
private:
QStringList _largeValues;
QStringList _smallValues;
QStringList _altitudeProperties;
bool _validRowIndex (int rowIndex);
InstrumentValue* _createNewInstrumentValueWorker (Vehicle* activeVehicle, int fontSize, QmlObjectListModel* rowModel);
void _loadSettings (void);
MultiVehicleManager* _multiVehicleMgr = nullptr;
QmlObjectListModel* _valuesModel = nullptr;
QVariantList _rgFontSizeByRow;
bool _preventSaveSettings = false;
static const char* _groupKey;
static const char* _largeValuesKey;
static const char* _smallValuesKey;
};
static const char* _rowsKey;
static const char* _columnsKey;
static const char* _deprecatedGroupKey;
static const char* _deprecatedLargeValuesKey;
static const char* _deprecatedSmallValuesKey;
#endif
};
......@@ -100,6 +100,7 @@
#include "LogReplayLink.h"
#include "VehicleObjectAvoidance.h"
#include "TrajectoryPoints.h"
#include "ValuesWidgetController.h"
#if defined(QGC_ENABLE_PAIRING)
#include "PairingManager.h"
......@@ -523,6 +524,7 @@ void QGCApplication::_initCommon()
qmlRegisterUncreatableType<QGCMapPolygon> ("QGroundControl.FlightMap", 1, 0, "QGCMapPolygon", kRefOnly);
qmlRegisterUncreatableType<QGCGeoBoundingCube> ("QGroundControl.FlightMap", 1, 0, "QGCGeoBoundingCube", kRefOnly);
qmlRegisterUncreatableType<TrajectoryPoints> ("QGroundControl.FlightMap", 1, 0, "TrajectoryPoints", kRefOnly);
qmlRegisterUncreatableType<InstrumentValue> (kQGCControllers, 1, 0, "InstrumentValue", kRefOnly);
qmlRegisterType<QGCMapCircle> ("QGroundControl.FlightMap", 1, 0, "QGCMapCircle");
......
......@@ -17,6 +17,7 @@ Rectangle {
property real _margins: ScreenTools.defaultFontPixelWidth / 2
property real _pageWidth: _root.width
property var _instrumentPages: QGroundControl.corePlugin.instrumentPages
property bool _settingsUnlocked: false
QGCPalette { id:qgcPal; colorGroupEnabled: parent.enabled }
......@@ -29,11 +30,13 @@ Rectangle {
centeredLabel: true
font.pointSize: ScreenTools.smallFontPointSize
onCurrentIndexChanged: _settingsUnlocked = false
QGCColoredImage {
anchors.leftMargin: _margins
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
source: "/res/gear-black.svg"
source: pageWidgetLoader.item.showLockIcon ? (_settingsUnlocked ? "/res/LockOpen.svg" : "/res/LockClosed.svg") : "/res/gear-black.svg"
mipmap: true
height: parent.height * 0.7
width: height
......@@ -44,7 +47,14 @@ Rectangle {
QGCMouseArea {
fillItem: parent
onClicked: pageWidgetLoader.item.showSettings()
onClicked: {
if (pageWidgetLoader.item.showLockIcon) {
_settingsUnlocked = !_settingsUnlocked
pageWidgetLoader.item.showSettings(_settingsUnlocked)
} else {
pageWidgetLoader.item.showSettings()
}
}
}
}
}
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick 2.12
import QtQuick.Controls 2.12
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Text {
font.pointSize: ScreenTools.defaultFontPointSize
......
......@@ -22,6 +22,7 @@
#endif
#include "QGCLoggingCategory.h"
#include "QGCCameraManager.h"
#include "ValuesWidgetController.h"
#include <QtQml>
#include <QQmlEngine>
......@@ -406,10 +407,40 @@ QString QGCCorePlugin::showAdvancedUIMessage() const
"Are you sure you want to enable Advanced Mode?");
}
void QGCCorePlugin::valuesWidgetDefaultSettings(QStringList& largeValues, QStringList& smallValues)
QmlObjectListModel* QGCCorePlugin::valuesWidgetDefaultSettings(QObject* valuesModelParent)
{
Q_UNUSED(smallValues);
largeValues << "Vehicle.altitudeRelative" << "Vehicle.groundSpeed" << "Vehicle.flightTime";
ValuesWidgetController controller(true /* forDefaultSettingsCreation */);
// We don't want these to get written out to settings. This way if the user doesn't modify them
// they will get new changes to default settings from newer builds automatically on next run.
controller.setPreventSaveSettings(true);
QmlObjectListModel* columnModel = controller.appendRow();
InstrumentValue* colValue = columnModel->value<InstrumentValue*>(0);
colValue->setFact("Vehicle", "altitudeRelative", QString());
colValue->setLabel(colValue->fact()->shortDescription());
colValue->setShowUnits(true);
colValue->setFontSize(InstrumentValue::LargeFontSize);
columnModel = controller.appendRow();
colValue = columnModel->value<InstrumentValue*>(0);
colValue->setFact("Vehicle", "groundSpeed", QString());
colValue->setLabel(colValue->fact()->shortDescription());
colValue->setShowUnits(true);
colValue->setFontSize(InstrumentValue::DefaultFontSize);
columnModel = controller.appendRow();
colValue = columnModel->value<InstrumentValue*>(0);
colValue->setFact("Vehicle", "flightTime", QString());
colValue->setLabel(colValue->fact()->shortDescription());
colValue->setShowUnits(false);
colValue->setFontSize(InstrumentValue::DefaultFontSize);
controller.setPreventSaveSettings(false);
controller.valuesModel()->setParent(valuesModelParent);
return controller.valuesModel();
}
QQmlApplicationEngine* QGCCorePlugin::createRootWindow(QObject *parent)
......
......@@ -105,8 +105,9 @@ public:
/// Allows a plugin to override the specified color name from the palette
virtual void paletteOverride(QString colorName, QGCPalette::PaletteColorInfo_t& colorInfo);
/// Allows the plugin to override the default settings for the Values Widget large and small values
virtual void valuesWidgetDefaultSettings(QStringList& largeValues, QStringList& smallValues);
/// Return the default Intrument Value model for the Values Widget. The returned model will be
/// re-parented to valuesModelParent for ownership.
virtual QmlObjectListModel* valuesWidgetDefaultSettings(QObject* valuesModelParent);
/// Allows the plugin to override the creation of the root (native) window.
virtual QQmlApplicationEngine* createRootWindow(QObject* parent);
......
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