Commit 10e1b31e authored by Don Gagne's avatar Don Gagne

Parameter search is now typedown style

Rewrote editor to be performant enough to support typedown
parent 478b0edd
...@@ -32,9 +32,8 @@ QGCView { ...@@ -32,9 +32,8 @@ QGCView {
property Fact _editorDialogFact: Fact { } property Fact _editorDialogFact: Fact { }
property int _rowHeight: ScreenTools.defaultFontPixelHeight * 2 property int _rowHeight: ScreenTools.defaultFontPixelHeight * 2
property int _rowWidth: 10 // Dynamic adjusted at runtime property int _rowWidth: 10 // Dynamic adjusted at runtime
property bool _searchFilter: false ///< true: showing results of search property bool _searchFilter: searchText.text != "" ///< true: showing results of search
property var _searchResults ///< List of parameter names from search results property var _searchResults ///< List of parameter names from search results
property string _currentGroup: ""
property bool _showRCToParam: !ScreenTools.isMobile && QGroundControl.multiVehicleManager.activeVehicle.px4Firmware property bool _showRCToParam: !ScreenTools.isMobile && QGroundControl.multiVehicleManager.activeVehicle.px4Firmware
ParameterEditorController { ParameterEditorController {
...@@ -55,34 +54,24 @@ QGCView { ...@@ -55,34 +54,24 @@ QGCView {
id: header id: header
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: searchText.height + ScreenTools.defaultFontPixelHeight / 3
spacing: ScreenTools.defaultFontPixelWidth spacing: ScreenTools.defaultFontPixelWidth
QGCTextField { QGCLabel {
id: searchText anchors.baseline: clearButton.baseline
text: qsTr("Search:")
} }
QGCButton { QGCTextField {
anchors.top: searchText.top id: searchText
anchors.bottom: searchText.bottom anchors.baseline: clearButton.baseline
text: qsTr("Search") text: controller.searchText
onClicked: { onDisplayTextChanged: controller.searchText = displayText
_searchResults = controller.searchParametersForComponent(-1, searchText.text)
_searchFilter = true
}
} }
QGCButton { QGCButton {
anchors.top: searchText.top id: clearButton
anchors.bottom: searchText.bottom
text: qsTr("Clear") text: qsTr("Clear")
visible: _searchFilter onClicked: searchText.text = ""
onClicked: {
searchText.text = ""
_searchFilter = false
hideDialog()
}
} }
} // Row - Header } // Row - Header
...@@ -132,65 +121,56 @@ QGCView { ...@@ -132,65 +121,56 @@ QGCView {
} }
} }
//--------------------------------------------- /// Group buttons
//-- Contents
Loader {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: header.bottom
anchors.bottom: parent.bottom
sourceComponent: _searchFilter ? searchResultsViewComponent: groupedViewComponent
}
}
//-- Parameter Groups
Component {
id: groupedViewComponent
Row {
spacing: ScreenTools.defaultFontPixelWidth * 0.5
//-- Parameter Groups
QGCFlickable { QGCFlickable {
id : groupScroll id : groupScroll
width: ScreenTools.defaultFontPixelWidth * 25 width: ScreenTools.defaultFontPixelWidth * 25
height: parent.height anchors.top: header.bottom
anchors.bottom: parent.bottom
clip: true clip: true
pixelAligned: true pixelAligned: true
contentHeight: groupedViewComponentColumn.height contentHeight: groupedViewComponentColumn.height
contentWidth: groupedViewComponentColumn.width contentWidth: groupedViewComponentColumn.width
flickableDirection: Flickable.VerticalFlick flickableDirection: Flickable.VerticalFlick
visible: !_searchFilter
Column { Column {
id: groupedViewComponentColumn id: groupedViewComponentColumn
spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25) spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
Repeater { Repeater {
model: controller.componentIds model: controller.componentIds
Column { Column {
id: componentColumn id: componentColumn
readonly property int componentId: parseInt(modelData)
spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25) spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
readonly property int componentId: modelData
QGCLabel { QGCLabel {
text: qsTr("Component #: %1").arg(componentId.toString()) text: qsTr("Component #: %1").arg(componentId.toString())
font.family: ScreenTools.demiboldFontFamily font.family: ScreenTools.demiboldFontFamily
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
ExclusiveGroup { id: groupGroup } ExclusiveGroup { id: groupGroup }
Repeater { Repeater {
model: controller.getGroupsForComponent(componentId) model: controller.getGroupsForComponent(componentId)
QGCButton { QGCButton {
width: ScreenTools.defaultFontPixelWidth * 25 width: ScreenTools.defaultFontPixelWidth * 25
text: modelData text: groupName
height: _rowHeight height: _rowHeight
exclusiveGroup: setupButtonGroup exclusiveGroup: setupButtonGroup
readonly property string groupName: modelData
onClicked: { onClicked: {
checked = true checked = true
// Clear the rows from the component first. This allows us to change the componentId without
// breaking any bindings.
factRowsLoader.parameterNames = [ ]
_rowWidth = 10 _rowWidth = 10
factRowsLoader.componentId = componentId controller.currentComponentId = componentId
factRowsLoader.parameterNames = controller.getParametersForGroup(componentId, modelData) controller.currentGroup = groupName
_currentGroup = modelData
factScrollView.contentX = 0
factScrollView.contentY = 0
} }
} }
} }
...@@ -198,82 +178,39 @@ QGCView { ...@@ -198,82 +178,39 @@ QGCView {
} }
} }
} }
Rectangle {
color: __qgcPal.text
width: 1
height: parent.height
opacity: 0.1
}
//-- Parameters
QGCFlickable {
id: factScrollView
width: parent.width - groupScroll.width
height: parent.height
contentHeight: factRowsLoader.height
contentWidth: _rowWidth
boundsBehavior: Flickable.OvershootBounds
pixelAligned: true
clip: true
Loader {
id: factRowsLoader
sourceComponent: factRowsComponent
property int componentId: controller.componentIds[0]
property var parameterNames: controller.getParametersForGroup(componentId, controller.getGroupsForComponent(componentId)[0])
onLoaded: {
_currentGroup = controller.getGroupsForComponent(controller.componentIds[0])[0]
}
}
}
}
}
//--------------------------------------------- /// Parameter list
// Search result view ListView {
Component { id: editorListView
id: searchResultsViewComponent anchors.leftMargin: ScreenTools.defaultFontPixelWidth
Item { anchors.left: _searchFilter ? parent.left : groupScroll.right
QGCFlickable { anchors.right: parent.right
id: factScrollView anchors.top: header.bottom
width: parent.width anchors.bottom: parent.bottom
height: parent.height orientation: ListView.Vertical
contentHeight: factRowsLoader.height model: controller.parameters
contentWidth: _rowWidth cacheBuffer: height > 0 ? height * 2 : 0
boundsBehavior: Flickable.OvershootBounds
pixelAligned: true
clip: true clip: true
Loader {
id: factRowsLoader
sourceComponent: factRowsComponent
property int componentId: -1
property var parameterNames: _searchResults
}
}
}
}
//--------------------------------------------- delegate: Rectangle {
// Paremeters view
Component {
id: factRowsComponent
Column {
spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
Repeater {
model: parameterNames
Rectangle {
height: _rowHeight height: _rowHeight
width: _rowWidth width: _rowWidth
color: Qt.rgba(0,0,0,0) color: Qt.rgba(0,0,0,0)
Row { Row {
id: factRow id: factRow
property Fact modelFact: controller.getParameterFact(componentId, modelData)
spacing: Math.ceil(ScreenTools.defaultFontPixelWidth * 0.5) spacing: Math.ceil(ScreenTools.defaultFontPixelWidth * 0.5)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
property Fact modelFact: object
QGCLabel { QGCLabel {
id: nameLabel id: nameLabel
width: ScreenTools.defaultFontPixelWidth * 20 width: ScreenTools.defaultFontPixelWidth * 20
text: factRow.modelFact.name text: factRow.modelFact.name
clip: true clip: true
} }
QGCLabel { QGCLabel {
id: valueLabel id: valueLabel
width: ScreenTools.defaultFontPixelWidth * 20 width: ScreenTools.defaultFontPixelWidth * 20
...@@ -281,15 +218,18 @@ QGCView { ...@@ -281,15 +218,18 @@ QGCView {
text: factRow.modelFact.enumStrings.length == 0 ? factRow.modelFact.valueString + " " + factRow.modelFact.units : factRow.modelFact.enumStringValue text: factRow.modelFact.enumStrings.length == 0 ? factRow.modelFact.valueString + " " + factRow.modelFact.units : factRow.modelFact.enumStringValue
clip: true clip: true
} }
QGCLabel { QGCLabel {
text: factRow.modelFact.shortDescription text: factRow.modelFact.shortDescription
} }
Component.onCompleted: { Component.onCompleted: {
if(_rowWidth < factRow.width + ScreenTools.defaultFontPixelWidth) { if(_rowWidth < factRow.width + ScreenTools.defaultFontPixelWidth) {
_rowWidth = factRow.width + ScreenTools.defaultFontPixelWidth _rowWidth = factRow.width + ScreenTools.defaultFontPixelWidth
} }
} }
} }
Rectangle { Rectangle {
width: _rowWidth width: _rowWidth
height: 1 height: 1
...@@ -298,6 +238,7 @@ QGCView { ...@@ -298,6 +238,7 @@ QGCView {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
...@@ -308,8 +249,7 @@ QGCView { ...@@ -308,8 +249,7 @@ QGCView {
} }
} }
} }
} } // QGCViewPanel
}
Component { Component {
id: editorDialogComponent id: editorDialogComponent
...@@ -320,44 +260,6 @@ QGCView { ...@@ -320,44 +260,6 @@ QGCView {
} }
} }
Component {
id: searchDialogComponent
QGCViewDialog {
function accept() {
_searchResults = controller.searchParametersForComponent(-1, searchFor.text, true /*searchInName.checked*/, true /*searchInDescriptions.checked*/)
_searchFilter = true
hideDialog()
}
function reject() {
_searchFilter = false
hideDialog()
}
QGCLabel {
id: searchForLabel
text: qsTr("Search for:")
}
QGCTextField {
id: searchFor
anchors.topMargin: defaultTextHeight / 3
anchors.top: searchForLabel.bottom
width: ScreenTools.defaultFontPixelWidth * 20
}
QGCLabel {
anchors.topMargin: defaultTextHeight
anchors.top: searchFor.bottom
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Hint: Leave 'Search For' blank and click Apply to list all parameters sorted by name.")
}
}
}
Component { Component {
id: mobileFilePicker id: mobileFilePicker
......
...@@ -25,14 +25,20 @@ ...@@ -25,14 +25,20 @@
/// @Brief Constructs a new ParameterEditorController Widget. This widget is used within the PX4VehicleConfig set of screens. /// @Brief Constructs a new ParameterEditorController Widget. This widget is used within the PX4VehicleConfig set of screens.
ParameterEditorController::ParameterEditorController(void) ParameterEditorController::ParameterEditorController(void)
: _currentComponentId(_vehicle->defaultComponentId())
, _parameters(new QmlObjectListModel(this))
{ {
if (_autopilot) {
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap(); const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
foreach (int componentId, groupMap.keys()) { foreach (int componentId, groupMap.keys()) {
_componentIds += QString("%1").arg(componentId); _componentIds += QString("%1").arg(componentId);
} }
}
_currentGroup = groupMap[_currentComponentId].keys()[0];
_updateParameters();
connect(this, &ParameterEditorController::searchTextChanged, this, &ParameterEditorController::_updateParameters);
connect(this, &ParameterEditorController::currentComponentIdChanged, this, &ParameterEditorController::_updateParameters);
connect(this, &ParameterEditorController::currentGroupChanged, this, &ParameterEditorController::_updateParameters);
} }
ParameterEditorController::~ParameterEditorController() ParameterEditorController::~ParameterEditorController()
...@@ -175,3 +181,26 @@ void ParameterEditorController::setRCToParam(const QString& paramName) ...@@ -175,3 +181,26 @@ void ParameterEditorController::setRCToParam(const QString& paramName)
d->exec(); d->exec();
#endif #endif
} }
void ParameterEditorController::_updateParameters(void)
{
QObjectList newParameterList;
if (_searchText.isEmpty()) {
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
foreach (const QString& parameter, groupMap[_currentComponentId][_currentGroup]) {
newParameterList.append(_autopilot->getParameterFact(_currentComponentId, parameter));
}
} else {
foreach(const QString &parameter, _autopilot->parameterNames(_vehicle->defaultComponentId())) {
Fact* fact = _autopilot->getParameterFact(_vehicle->defaultComponentId(), parameter);
if (fact->name().contains(_searchText, Qt::CaseInsensitive) ||
fact->shortDescription().contains(_searchText, Qt::CaseInsensitive) ||
fact->longDescription().contains(_searchText, Qt::CaseInsensitive)) {
newParameterList.append(fact);
}
}
}
_parameters->swapObjectList(newParameterList);
}
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "AutoPilotPlugin.h" #include "AutoPilotPlugin.h"
#include "UASInterface.h" #include "UASInterface.h"
#include "FactPanelController.h" #include "FactPanelController.h"
#include "QmlObjectListModel.h"
class ParameterEditorController : public FactPanelController class ParameterEditorController : public FactPanelController
{ {
...@@ -29,7 +30,11 @@ public: ...@@ -29,7 +30,11 @@ public:
ParameterEditorController(void); ParameterEditorController(void);
~ParameterEditorController(); ~ParameterEditorController();
Q_PROPERTY(QStringList componentIds MEMBER _componentIds CONSTANT) Q_PROPERTY(QString searchText MEMBER _searchText NOTIFY searchTextChanged)
Q_PROPERTY(int currentComponentId MEMBER _currentComponentId NOTIFY currentComponentIdChanged)
Q_PROPERTY(QString currentGroup MEMBER _currentGroup NOTIFY currentGroupChanged)
Q_PROPERTY(QmlObjectListModel* parameters MEMBER _parameters CONSTANT)
Q_PROPERTY(QVariantList componentIds MEMBER _componentIds CONSTANT)
Q_INVOKABLE QStringList getGroupsForComponent(int componentId); Q_INVOKABLE QStringList getGroupsForComponent(int componentId);
Q_INVOKABLE QStringList getParametersForGroup(int componentId, QString group); Q_INVOKABLE QStringList getParametersForGroup(int componentId, QString group);
...@@ -47,10 +52,20 @@ public: ...@@ -47,10 +52,20 @@ public:
QList<QObject*> model(void); QList<QObject*> model(void);
signals: signals:
void searchTextChanged(QString searchText);
void currentComponentIdChanged(int componentId);
void currentGroupChanged(QString group);
void showErrorMessage(const QString& errorMsg); void showErrorMessage(const QString& errorMsg);
private slots:
void _updateParameters(void);
private: private:
QStringList _componentIds; QVariantList _componentIds;
QString _searchText;
int _currentComponentId;
QString _currentGroup;
QmlObjectListModel* _parameters;
}; };
#endif #endif
...@@ -179,7 +179,7 @@ void QmlObjectListModel::append(QObject* object) ...@@ -179,7 +179,7 @@ void QmlObjectListModel::append(QObject* object)
insert(_objectList.count(), object); insert(_objectList.count(), object);
} }
QObjectList QmlObjectListModel::swapObjectList(QObjectList newlist) QObjectList QmlObjectListModel::swapObjectList(const QObjectList& newlist)
{ {
QObjectList oldlist(_objectList); QObjectList oldlist(_objectList);
beginResetModel(); beginResetModel();
......
...@@ -37,7 +37,7 @@ public: ...@@ -37,7 +37,7 @@ public:
void setDirty(bool dirty); void setDirty(bool dirty);
void append(QObject* object); void append(QObject* object);
QObjectList swapObjectList(QObjectList newlist); QObjectList swapObjectList(const QObjectList& newlist);
void clear(void); void clear(void);
QObject* removeAt(int i); QObject* removeAt(int i);
QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); } QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); }
......
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