Commit 7bf0dc2d authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #4923 from DonLakeFlyer/QGCComboBox

Fix the stupid )(&*@#$)*(& android combox box problem
parents ec248836 786cc265
...@@ -5,58 +5,246 @@ import QtQuick.Controls.Styles 1.4 ...@@ -5,58 +5,246 @@ import QtQuick.Controls.Styles 1.4
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
ComboBox { Button {
id: combo
property real pointSize: ScreenTools.defaultFontPointSize ///< Point size for button text
property alias model: popupItems.model
property alias textRole: popup.textRole
property alias currentIndex: popup.__selectedIndex
readonly property alias count: popupItems.count
readonly property alias currentText: popup.currentText
property var _qgcPal: QGCPalette { colorGroupEnabled: enabled } property var _qgcPal: QGCPalette { colorGroupEnabled: enabled }
property bool _showHighlight: pressed | hovered property int _horizontalPadding: ScreenTools.defaultFontPixelWidth
property bool _showBorder: _qgcPal.globalTheme === QGCPalette.Light property int _verticalPadding: Math.round(ScreenTools.defaultFontPixelHeight / 2)
property var __popup: popup
style: ComboBoxStyle { signal activated(int index)
font.pointSize: ScreenTools.defaultFontPointSize
textColor: _showHighlight ? style: ButtonStyle {
control._qgcPal.buttonHighlightText : /*! The padding between the background and the label components. */
control._qgcPal.buttonText padding {
top: _verticalPadding
bottom: _verticalPadding
left: _horizontalPadding
right: _horizontalPadding
}
background: Item { /*! This defines the background of the button. */
background: Rectangle {
implicitWidth: ScreenTools.implicitComboBoxWidth implicitWidth: ScreenTools.implicitComboBoxWidth
implicitHeight: ScreenTools.implicitComboBoxHeight implicitHeight: ScreenTools.implicitComboBoxHeight
color: control._qgcPal.button
Rectangle {
anchors.fill: parent
color: _showHighlight ? control._qgcPal.buttonHighlight : control._qgcPal.button
border.width: _showBorder ? 1: 0
border.color: control._qgcPal.buttonText
}
QGCColoredImage { QGCColoredImage {
id: image id: image
width: ScreenTools.defaultFontPixelHeight / 2 width: ScreenTools.defaultFontPixelHeight / 2
height: width height: width
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: width / 2
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: dropDownButtonWidth / 2
source: "/qmlimages/arrow-down.png" source: "/qmlimages/arrow-down.png"
color: qgcPal.text color: control._qgcPal.buttonText
}
}
/*! This defines the label of the button. */
label: Item {
implicitWidth: text.implicitWidth
implicitHeight: text.implicitHeight
baselineOffset: text.y + text.baselineOffset
Text {
id: text
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
text: control.currentText
font.pointSize: pointSize
font.family: ScreenTools.normalFontFamily
color: control._qgcPal.buttonText
}
}
}
onClicked: popup.toggleShow()
Component.onCompleted: {
if (currentIndex === -1) {
currentIndex = 0
}
popup.resolveTextValue(textRole)
} }
function textAt (index) {
if (index >= count || index < 0)
return null;
return popupItems.objectAt(index).text;
}
function find (text) {
for (var i = 0 ; i < popupItems.count ; ++i) {
var currentString = popupItems.objectAt(i).text
if (text === currentString) {
return i
}
}
return -1
}
Menu {
id: popup
__minimumWidth: combo.width
__visualItem: combo
style: MenuStyle {
font: combo.font
__menuItemType: "comboboxitem"
__scrollerStyle: ScrollViewStyle { }
}
property string textRole: ""
property bool showing: false
property string currentText: selectedText
property string selectedText
onSelectedTextChanged: popup.currentText = selectedText
on__SelectedIndexChanged: {
if (__selectedIndex === -1)
popup.currentText = ""
else
updateSelectedText()
}
property int _y: combo.height
property bool _modelIsArray: false
onAboutToShow: showing = true
onAboutToHide: showing = false
function toggleShow() {
if (popup._popupVisible) {
popup.__dismissAndDestroy()
} else {
__popup(Qt.rect(0, _y, 0, 0), 0)
} }
} }
// Capture Wheel events to disable scrolling options in ComboBox. function resolveTextValue(initialTextRole) {
// As a side effect, this also prevents scrolling the page when if (!model) {
// mouse is over a ComboBox, but this would also the case when return
// scrolling items in the ComboBox is enabled. }
MouseArea {
anchors.fill: parent var get = model['get'];
onWheel: { if (!get && popup._modelIsArray && !!model[0]) {
// do nothing if (model[0].constructor !== String && model[0].constructor !== Number)
wheel.accepted = true; get = function(i) { return model[i]; }
}
var modelMayHaveRoles = get !== undefined
textRole = initialTextRole
if (textRole === "" && modelMayHaveRoles && get(0)) {
// No text role set, check whether model has a suitable role
// If 'text' is found, or there's only one role, pick that.
var listElement = get(0)
var roleName = ""
var roleCount = 0
for (var role in listElement) {
if (listElement[role].constructor === Function)
continue;
if (role === "text") {
roleName = role
break
} else if (!roleName) {
roleName = role
}
++roleCount
}
if (roleCount > 1 && roleName !== "text") {
console.warn("No suitable 'textRole' found for ComboBox.")
} else {
textRole = roleName
}
}
updateSelectedText()
}
function updateSelectedText() {
var selectedItem
if (__selectedIndex !== -1 && (selectedItem = items[__selectedIndex])) {
selectedText = Qt.binding(function () { return selectedItem.text })
if (currentText !== selectedText) // __selectedIndex went form -1 to 0
selectedTextChanged()
}
}
Component {
id: menuItemComponent
MenuItem {
property int index
onTriggered: {
//console.log("onTriggered", index, currentIndex)
if (index !== currentIndex) {
//console.log("activated", index)
activated(index)
}
}
}
}
Instantiator {
id: popupItems
onModelChanged: {
popup._modelIsArray = !!model ? model.constructor === Array : false
popup.resolveTextValue(popup.textRole)
}
onObjectAdded: {
// There is a bug in Instantiator which can cause objects to be added out of order from an index standpoint.
// If not handled correcty this will cause menu items to be added incorrectly due to the way Menu.insertItem works.
//console.log("menu add", index, object.text)
if (index === popup.__selectedIndex) {
popup.selectedText = object["text"]
}
// Find the correct place for menu item. We can't just add at index, due to possible bad ordering
var insertIndex = -1
for (var i=0; i<popup.items.length; i++) {
//console.log("position search", i, popup.items[i].itemIndex)
if (popup.items[i].itemIndex > index) {
insertIndex = i
break
}
}
if (insertIndex === -1) {
popup.insertItem(popup.items.length, object)
} else {
//console.log("out of order menu add", index, insertIndex)
popup.insertItem(insertIndex, object)
}
}
onObjectRemoved: popup.removeItem(object)
MenuItem {
text: popup.textRole === '' ? modelData : ((popup._modelIsArray ? modelData[popup.textRole] : model[popup.textRole]) || '')
property int itemIndex: index
onTriggered: {
//console.log("onTriggered", index, currentIndex)
if (index !== currentIndex) {
//console.log("activated", index)
activated(index)
}
} }
onPressed: {
// propogate to ComboBox
mouse.accepted = false;
} }
onReleased: {
// propogate to ComboBox
mouse.accepted = false;
} }
} }
} }
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