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
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
ComboBox {
property var _qgcPal: QGCPalette { colorGroupEnabled: enabled }
property bool _showHighlight: pressed | hovered
property bool _showBorder: _qgcPal.globalTheme === QGCPalette.Light
style: ComboBoxStyle {
font.pointSize: ScreenTools.defaultFontPointSize
textColor: _showHighlight ?
control._qgcPal.buttonHighlightText :
control._qgcPal.buttonText
background: Item {
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 int _horizontalPadding: ScreenTools.defaultFontPixelWidth
property int _verticalPadding: Math.round(ScreenTools.defaultFontPixelHeight / 2)
property var __popup: popup
signal activated(int index)
style: ButtonStyle {
/*! The padding between the background and the label components. */
padding {
top: _verticalPadding
bottom: _verticalPadding
left: _horizontalPadding
right: _horizontalPadding
}
/*! This defines the background of the button. */
background: Rectangle {
implicitWidth: ScreenTools.implicitComboBoxWidth
implicitHeight: ScreenTools.implicitComboBoxHeight
Rectangle {
anchors.fill: parent
color: _showHighlight ? control._qgcPal.buttonHighlight : control._qgcPal.button
border.width: _showBorder ? 1: 0
border.color: control._qgcPal.buttonText
}
color: control._qgcPal.button
QGCColoredImage {
id: image
width: ScreenTools.defaultFontPixelHeight / 2
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: width / 2
anchors.right: parent.right
anchors.rightMargin: dropDownButtonWidth / 2
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
}
}
}
// Capture Wheel events to disable scrolling options in ComboBox.
// As a side effect, this also prevents scrolling the page when
// mouse is over a ComboBox, but this would also the case when
// scrolling items in the ComboBox is enabled.
MouseArea {
anchors.fill: parent
onWheel: {
// do nothing
wheel.accepted = true;
}
onPressed: {
// propogate to ComboBox
mouse.accepted = false;
}
onReleased: {
// propogate to ComboBox
mouse.accepted = false;
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)
}
}
function resolveTextValue(initialTextRole) {
if (!model) {
return
}
var get = model['get'];
if (!get && popup._modelIsArray && !!model[0]) {
if (model[0].constructor !== String && model[0].constructor !== Number)
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)
}
}
}
}
}
}
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