ComboBox.qml 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2016 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and The Qt Company. For licensing terms
  14. ** and conditions see https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 3 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL3 included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 3 requirements
  23. ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  24. **
  25. ** GNU General Public License Usage
  26. ** Alternatively, this file may be used under the terms of the GNU
  27. ** General Public License version 2.0 or (at your option) the GNU General
  28. ** Public license version 3 or any later version approved by the KDE Free
  29. ** Qt Foundation. The licenses are as published by the Free Software
  30. ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  31. ** included in the packaging of this file. Please review the following
  32. ** information to ensure the GNU General Public License requirements will
  33. ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  34. ** https://www.gnu.org/licenses/gpl-3.0.html.
  35. **
  36. ** $QT_END_LICENSE$
  37. **
  38. ****************************************************************************/
  39. import QtQml 2.14 as Qml
  40. import QtQuick 2.2
  41. import QtQuick.Controls 1.2
  42. import QtQuick.Controls.Private 1.0
  43. /*!
  44. \qmltype ComboBox
  45. \inqmlmodule QtQuick.Controls
  46. \since 5.1
  47. \ingroup controls
  48. \brief Provides a drop-down list functionality.
  49. \image combobox.png
  50. Add items to the ComboBox by assigning it a ListModel, or a list of strings
  51. to the \l model property.
  52. \qml
  53. ComboBox {
  54. width: 200
  55. model: [ "Banana", "Apple", "Coconut" ]
  56. }
  57. \endqml
  58. In this example we are demonstrating how to use a ListModel with a combo box.
  59. \qml
  60. ComboBox {
  61. currentIndex: 2
  62. model: ListModel {
  63. id: cbItems
  64. ListElement { text: "Banana"; color: "Yellow" }
  65. ListElement { text: "Apple"; color: "Green" }
  66. ListElement { text: "Coconut"; color: "Brown" }
  67. }
  68. width: 200
  69. onCurrentIndexChanged: console.debug(cbItems.get(currentIndex).text + ", " + cbItems.get(currentIndex).color)
  70. }
  71. \endqml
  72. You can make a combo box editable by setting the \l editable property. An editable combo box will
  73. autocomplete its text based on what is available in the model.
  74. In the next example we demonstrate how you can append content to an editable combo box by
  75. reacting to the \l accepted signal. Note that you have to explicitly prevent duplicates.
  76. \qml
  77. ComboBox {
  78. editable: true
  79. model: ListModel {
  80. id: model
  81. ListElement { text: "Banana"; color: "Yellow" }
  82. ListElement { text: "Apple"; color: "Green" }
  83. ListElement { text: "Coconut"; color: "Brown" }
  84. }
  85. onAccepted: {
  86. if (find(currentText) === -1) {
  87. model.append({text: editText})
  88. currentIndex = find(editText)
  89. }
  90. }
  91. }
  92. \endqml
  93. You can create a custom appearance for a ComboBox by
  94. assigning a \l {ComboBoxStyle}.
  95. */
  96. Control {
  97. id: comboBox
  98. /*! \qmlproperty model ComboBox::model
  99. The model to populate the ComboBox from.
  100. Changing the model after initialization will reset \l currentIndex to \c 0.
  101. */
  102. property alias model: popupItems.model
  103. /*! The model role used for populating the ComboBox. */
  104. property string textRole: ""
  105. /*! \qmlproperty int ComboBox::currentIndex
  106. The index of the currently selected item in the ComboBox.
  107. Setting currentIndex to \c -1 will reset the selection and clear the text
  108. label. If \l editable is \c true, you may also need to manually clear \l editText.
  109. \sa model
  110. */
  111. property alias currentIndex: popup.__selectedIndex
  112. /*! \qmlproperty string ComboBox::currentText
  113. The text of the currently selected item in the ComboBox.
  114. \note Since \c currentText depends on \c currentIndex, there's no way to ensure \c currentText
  115. will be up to date whenever a \c onCurrentIndexChanged handler is called.
  116. */
  117. readonly property alias currentText: popup.currentText
  118. /*! This property holds whether the combo box can be edited by the user.
  119. The default value is \c false.
  120. \since QtQuick.Controls 1.1
  121. */
  122. property bool editable: false
  123. /*! \qmlproperty string ComboBox::editText
  124. \since QtQuick.Controls 1.1
  125. This property specifies text being manipulated by the user for an editable combo box.
  126. */
  127. property alias editText: input.text
  128. /*! \qmlproperty enumeration ComboBox::inputMethodHints
  129. \since QtQuick.Controls 1.5
  130. Provides hints to the input method about the expected content of the combo box and how it
  131. should operate.
  132. The value is a bit-wise combination of flags or \c Qt.ImhNone if no hints are set.
  133. Flags that alter behavior are:
  134. \list
  135. \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
  136. \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
  137. in any persistent storage like predictive user dictionary.
  138. \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
  139. when a sentence ends.
  140. \li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
  141. \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
  142. \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
  143. \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
  144. \li Qt.ImhDate - The text editor functions as a date field.
  145. \li Qt.ImhTime - The text editor functions as a time field.
  146. \endlist
  147. Flags that restrict input (exclusive flags) are:
  148. \list
  149. \li Qt.ImhDigitsOnly - Only digits are allowed.
  150. \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
  151. \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
  152. \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
  153. \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
  154. \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
  155. \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
  156. \endlist
  157. Masks:
  158. \list
  159. \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
  160. \endlist
  161. */
  162. property alias inputMethodHints: input.inputMethodHints
  163. /*! This property specifies whether the combobox should gain active focus when pressed.
  164. The default value is \c false. */
  165. property bool activeFocusOnPress: false
  166. /*! \qmlproperty bool ComboBox::pressed
  167. This property holds whether the button is being pressed. */
  168. readonly property bool pressed: mouseArea.effectivePressed || popup.__popupVisible
  169. /*! \qmlproperty bool ComboBox::hovered
  170. This property indicates whether the control is being hovered.
  171. */
  172. readonly property bool hovered: mouseArea.containsMouse || input.containsMouse
  173. /*! \qmlproperty int ComboBox::count
  174. \since QtQuick.Controls 1.1
  175. This property holds the number of items in the combo box.
  176. */
  177. readonly property alias count: popupItems.count
  178. /*! \qmlmethod string ComboBox::textAt(int index)
  179. Returns the text for a given \a index.
  180. If an invalid index is provided, \c null is returned
  181. \since QtQuick.Controls 1.1
  182. */
  183. function textAt (index) {
  184. if (index >= count || index < 0)
  185. return null;
  186. return popupItems.objectAt(index).text;
  187. }
  188. /*! \qmlmethod int ComboBox::find(string text)
  189. Finds and returns the index of a given \a text
  190. If no match is found, \c -1 is returned. The search is case sensitive.
  191. \since QtQuick.Controls 1.1
  192. */
  193. function find (text) {
  194. return input.find(text, Qt.MatchExactly)
  195. }
  196. /*!
  197. \qmlproperty Validator ComboBox::validator
  198. \since QtQuick.Controls 1.1
  199. Allows you to set a text validator for an editable ComboBox.
  200. When a validator is set,
  201. the text field will only accept input which leaves the text property in
  202. an intermediate state. The accepted signal will only be sent
  203. if the text is in an acceptable state when enter is pressed.
  204. Currently supported validators are \l[QtQuick]{IntValidator},
  205. \l[QtQuick]{DoubleValidator}, and \l[QtQuick]{RegExpValidator}. An
  206. example of using validators is shown below, which allows input of
  207. integers between 11 and 31 into the text field:
  208. \note This property is only applied when \l editable is \c true
  209. \qml
  210. import QtQuick 2.2
  211. import QtQuick.Controls 1.2
  212. ComboBox {
  213. editable: true
  214. model: 10
  215. validator: IntValidator {bottom: 0; top: 10;}
  216. focus: true
  217. }
  218. \endqml
  219. \sa acceptableInput, accepted, editable
  220. */
  221. property alias validator: input.validator
  222. /*!
  223. \since QtQuick.Controls 1.3
  224. This property contains the edit \l Menu for working
  225. with text selection. Set it to \c null if no menu
  226. is wanted.
  227. \note The menu is only in use when \l editable is \c true
  228. */
  229. property Component menu: input.editMenu.defaultMenu
  230. /*!
  231. \qmlproperty bool ComboBox::acceptableInput
  232. \since QtQuick.Controls 1.1
  233. Returns \c true if the combo box contains acceptable
  234. text in the editable text field.
  235. If a validator was set, this property will return \c
  236. true if the current text satisfies the validator or mask as
  237. a final string (not as an intermediate string).
  238. \sa validator, accepted
  239. */
  240. readonly property alias acceptableInput: input.acceptableInput
  241. /*!
  242. \qmlproperty bool ComboBox::selectByMouse
  243. \since QtQuick.Controls 1.3
  244. This property determines if the user can select the text in
  245. the editable text field with the mouse.
  246. The default value is \c true.
  247. */
  248. property bool selectByMouse: true
  249. /*!
  250. \qmlproperty bool ComboBox::inputMethodComposing
  251. \since QtQuick.Controls 1.3
  252. This property holds whether an editable ComboBox has partial text input from an input method.
  253. While it is composing an input method may rely on mouse or key events from the ComboBox
  254. to edit or commit the partial text. This property can be used to determine when to disable
  255. events handlers that may interfere with the correct operation of an input method.
  256. */
  257. readonly property bool inputMethodComposing: !!input.inputMethodComposing
  258. /*!
  259. \qmlsignal ComboBox::accepted()
  260. \since QtQuick.Controls 1.1
  261. This signal is emitted when the Return or Enter key is pressed on an
  262. \l editable combo box. If the confirmed string is not currently in the model,
  263. the currentIndex will be set to -1 and the \l currentText will be updated
  264. accordingly.
  265. \note If there is a \l validator set on the combobox,
  266. the signal will only be emitted if the input is in an acceptable state.
  267. The corresponding handler is \c onAccepted.
  268. */
  269. signal accepted
  270. /*!
  271. \qmlsignal ComboBox::activated(int index)
  272. \since QtQuick.Controls 1.1
  273. This signal is similar to currentIndex changed, but will only
  274. be emitted if the combo box index was changed by the user, not
  275. when set programmatically.
  276. \e index is the activated model index, or \c -1 if a new string is
  277. accepted.
  278. The corresponding handler is \c onActivated.
  279. */
  280. signal activated(int index)
  281. /*!
  282. \qmlmethod void ComboBox::selectAll()
  283. \since QtQuick.Controls 1.1
  284. Causes all \l editText to be selected.
  285. */
  286. function selectAll() {
  287. input.selectAll()
  288. }
  289. /*! \internal */
  290. function __selectPrevItem() {
  291. input.blockUpdate = true
  292. if (currentIndex > 0) {
  293. currentIndex--;
  294. input.text = popup.currentText;
  295. activated(currentIndex);
  296. }
  297. input.blockUpdate = false;
  298. }
  299. /*! \internal */
  300. function __selectNextItem() {
  301. input.blockUpdate = true;
  302. if (currentIndex < popupItems.count - 1) {
  303. currentIndex++;
  304. input.text = popup.currentText;
  305. activated(currentIndex);
  306. }
  307. input.blockUpdate = false;
  308. }
  309. /*! \internal */
  310. property var __popup: popup
  311. style: Settings.styleComponent(Settings.style, "ComboBoxStyle.qml", comboBox)
  312. activeFocusOnTab: true
  313. Accessible.name: editable ? editText : currentText
  314. Accessible.role: Accessible.ComboBox
  315. Accessible.editable: editable
  316. MouseArea {
  317. id: mouseArea
  318. property bool overridePressed: false
  319. readonly property bool effectivePressed: (pressed || overridePressed) && containsMouse
  320. anchors.fill: parent
  321. hoverEnabled: Settings.hoverEnabled
  322. onPressed: {
  323. if (comboBox.activeFocusOnPress)
  324. forceActiveFocus()
  325. if (!Settings.hasTouchScreen)
  326. popup.toggleShow()
  327. else
  328. overridePressed = true
  329. }
  330. onCanceled: overridePressed = false
  331. onClicked: {
  332. if (Settings.hasTouchScreen)
  333. popup.toggleShow()
  334. overridePressed = false
  335. }
  336. onWheel: {
  337. if (wheel.angleDelta.y > 0) {
  338. __selectPrevItem();
  339. } else if (wheel.angleDelta.y < 0){
  340. __selectNextItem();
  341. }
  342. }
  343. }
  344. Component.onCompleted: {
  345. if (currentIndex === -1)
  346. currentIndex = 0
  347. popup.ready = true
  348. popup.resolveTextValue(textRole)
  349. }
  350. Keys.onPressed: {
  351. // Perform one-character based lookup for non-editable combo box
  352. if (!editable && event.text.length > 0) {
  353. var index = input.find(event.text, Qt.MatchStartsWith);
  354. if (index >= 0 && index !== currentIndex) {
  355. currentIndex = index;
  356. activated(currentIndex);
  357. }
  358. }
  359. }
  360. TextInputWithHandles {
  361. id: input
  362. visible: editable
  363. enabled: editable
  364. focus: true
  365. clip: contentWidth > width
  366. control: comboBox
  367. cursorHandle: __style ? __style.__cursorHandle : undefined
  368. selectionHandle: __style ? __style.__selectionHandle : undefined
  369. anchors.fill: parent
  370. anchors.leftMargin: __style ? __style.padding.left : 0
  371. anchors.topMargin: __style ? __style.padding.top : 0
  372. anchors.rightMargin: __style ? __panel.dropDownButtonWidth + __style.padding.right : 0
  373. anchors.bottomMargin: __style ? __style.padding.bottom: 0
  374. verticalAlignment: Text.AlignVCenter
  375. font: __panel && __panel.font !== undefined ? __panel.font : TextSingleton.font
  376. renderType: __style ? __style.renderType : Text.NativeRendering
  377. color: __panel ? __panel.textColor : "black"
  378. selectionColor: __panel ? __panel.selectionColor : "blue"
  379. selectedTextColor: __panel ? __panel.selectedTextColor : "white"
  380. onAccepted: {
  381. var idx = input.find(editText, Qt.MatchFixedString)
  382. if (idx > -1) {
  383. editTextMatches = true;
  384. currentIndex = idx;
  385. editText = textAt(idx);
  386. } else {
  387. editTextMatches = false;
  388. currentIndex = -1;
  389. popup.currentText = editText;
  390. }
  391. comboBox.accepted();
  392. }
  393. property bool blockUpdate: false
  394. property string prevText
  395. property bool editTextMatches: true
  396. function find (text, searchType) {
  397. for (var i = 0 ; i < popupItems.count ; ++i) {
  398. var currentString = popupItems.objectAt(i).text
  399. if (searchType === Qt.MatchExactly) {
  400. if (text === currentString)
  401. return i;
  402. } else if (searchType === Qt.CaseSensitive) {
  403. if (currentString.indexOf(text) === 0)
  404. return i;
  405. } else if (searchType === Qt.MatchFixedString) {
  406. if (currentString.toLowerCase().indexOf(text.toLowerCase()) === 0
  407. && currentString.length === text.length)
  408. return i;
  409. } else if (currentString.toLowerCase().indexOf(text.toLowerCase()) === 0) {
  410. return i
  411. }
  412. }
  413. return -1;
  414. }
  415. // Finds first entry and shortest entry. Used by editable combo
  416. function tryComplete (inputText) {
  417. var candidate = "";
  418. var shortestString = "";
  419. for (var i = 0 ; i < popupItems.count ; ++i) {
  420. var currentString = popupItems.objectAt(i).text;
  421. if (currentString.toLowerCase().indexOf(inputText.toLowerCase()) === 0) {
  422. if (candidate.length) { // Find smallest possible match
  423. var cmp = 0;
  424. // We try to complete the shortest string that matches our search
  425. if (currentString.length < candidate.length)
  426. candidate = currentString
  427. while (cmp < Math.min(currentString.length, shortestString.length)
  428. && shortestString[cmp].toLowerCase() === currentString[cmp].toLowerCase())
  429. cmp++;
  430. shortestString = shortestString.substring(0, cmp);
  431. } else { // First match, select as current index and find other matches
  432. candidate = currentString;
  433. shortestString = currentString;
  434. }
  435. }
  436. }
  437. if (candidate.length)
  438. return inputText + candidate.substring(inputText.length, candidate.length);
  439. return inputText;
  440. }
  441. property bool allowComplete: false
  442. Keys.forwardTo: comboBox
  443. Keys.onPressed: allowComplete = (event.key !== Qt.Key_Backspace && event.key !== Qt.Key_Delete);
  444. onTextChanged: {
  445. if (editable && !blockUpdate && allowComplete && text.length > 0) {
  446. var completed = input.tryComplete(text)
  447. if (completed.length > text.length) {
  448. var oldtext = input.text;
  449. input.text = completed;
  450. input.select(text.length, oldtext.length);
  451. }
  452. }
  453. prevText = text
  454. }
  455. }
  456. Qml.Binding {
  457. target: input
  458. property: "text"
  459. value: popup.currentText
  460. when: input.editTextMatches
  461. restoreMode: Binding.RestoreBinding
  462. }
  463. onTextRoleChanged: popup.resolveTextValue(textRole)
  464. ExclusiveGroup { id: eg }
  465. Menu {
  466. id: popup
  467. objectName: "popup"
  468. style: isPopup ? __style.__popupStyle : __style.__dropDownStyle
  469. property string currentText: selectedText
  470. onSelectedTextChanged: popup.currentText = selectedText
  471. property string selectedText
  472. property int triggeredIndex: -1
  473. on__SelectedIndexChanged: {
  474. if (__selectedIndex === -1)
  475. popup.currentText = ""
  476. else
  477. updateSelectedText()
  478. if (triggeredIndex >= 0 && triggeredIndex == __selectedIndex) {
  479. activated(currentIndex)
  480. triggeredIndex = -1
  481. }
  482. }
  483. property string textRole: ""
  484. property bool ready: false
  485. property bool isPopup: !editable && !!__panel && __panel.popup
  486. property int y: isPopup ? (comboBox.__panel.height - comboBox.__panel.implicitHeight) / 2.0 : comboBox.__panel.height
  487. __minimumWidth: comboBox.width
  488. __visualItem: comboBox
  489. property bool modelIsArray: false
  490. Instantiator {
  491. id: popupItems
  492. active: false
  493. property bool updatingModel: false
  494. onModelChanged: {
  495. popup.modelIsArray = !!model ? model.constructor === Array : false
  496. if (active) {
  497. if (updatingModel && popup.__selectedIndex === 0) {
  498. // We still want to update the currentText
  499. popup.updateSelectedText()
  500. } else {
  501. updatingModel = true
  502. popup.__selectedIndex = 0
  503. }
  504. }
  505. popup.resolveTextValue(comboBox.textRole)
  506. }
  507. MenuItem {
  508. text: popup.textRole === '' ?
  509. modelData :
  510. ((popup.modelIsArray ? modelData[popup.textRole] : model[popup.textRole]) || '')
  511. onTriggered: {
  512. popup.triggeredIndex = index
  513. comboBox.editText = text
  514. }
  515. onTextChanged: if (index === currentIndex) popup.updateSelectedText();
  516. checkable: true
  517. exclusiveGroup: eg
  518. }
  519. onObjectAdded: {
  520. popup.insertItem(index, object)
  521. if (!updatingModel && index === popup.__selectedIndex)
  522. popup.selectedText = object["text"]
  523. }
  524. onObjectRemoved: popup.removeItem(object)
  525. }
  526. function resolveTextValue(initialTextRole) {
  527. if (!ready || !model) {
  528. popupItems.active = false
  529. return;
  530. }
  531. var get = model['get'];
  532. if (!get && popup.modelIsArray && !!model[0]) {
  533. if (model[0].constructor !== String && model[0].constructor !== Number)
  534. get = function(i) { return model[i]; }
  535. }
  536. var modelMayHaveRoles = get !== undefined
  537. textRole = initialTextRole
  538. if (textRole === "" && modelMayHaveRoles && get(0)) {
  539. // No text role set, check whether model has a suitable role
  540. // If 'text' is found, or there's only one role, pick that.
  541. var listElement = get(0)
  542. var roleName = ""
  543. var roleCount = 0
  544. for (var role in listElement) {
  545. if (listElement[role].constructor === Function)
  546. continue;
  547. if (role === "text") {
  548. roleName = role
  549. break
  550. } else if (!roleName) {
  551. roleName = role
  552. }
  553. ++roleCount
  554. }
  555. if (roleCount > 1 && roleName !== "text") {
  556. console.warn("No suitable 'textRole' found for ComboBox.")
  557. } else {
  558. textRole = roleName
  559. }
  560. }
  561. if (!popupItems.active)
  562. popupItems.active = true
  563. else
  564. updateSelectedText()
  565. }
  566. function toggleShow() {
  567. if (popup.__popupVisible) {
  568. popup.__dismissAndDestroy()
  569. } else {
  570. if (items[__selectedIndex])
  571. items[__selectedIndex].checked = true
  572. __currentIndex = comboBox.currentIndex
  573. if (Qt.application.layoutDirection === Qt.RightToLeft)
  574. __popup(Qt.rect(comboBox.width, y, 0, 0), isPopup ? __selectedIndex : 0)
  575. else
  576. __popup(Qt.rect(0, y, 0, 0), isPopup ? __selectedIndex : 0)
  577. }
  578. }
  579. function updateSelectedText() {
  580. var selectedItem;
  581. if (__selectedIndex !== -1 && (selectedItem = items[__selectedIndex])) {
  582. input.editTextMatches = true
  583. selectedText = Qt.binding(function () { return selectedItem.text })
  584. if (currentText !== selectedText) // __selectedIndex went form -1 to 0
  585. selectedTextChanged()
  586. }
  587. }
  588. }
  589. // The key bindings below will only be in use when popup is
  590. // not visible. Otherwise, native popup key handling will take place:
  591. Keys.onSpacePressed: {
  592. if (!editable)
  593. popup.toggleShow()
  594. else
  595. event.accepted = false
  596. }
  597. Keys.onUpPressed: __selectPrevItem()
  598. Keys.onDownPressed: __selectNextItem()
  599. }