Unsolved How to set currentIndex in ComboBox
-
Hi,
I have a hard time understanding the concept of the ComboBox. I can set the model to a custom QQmListProperty and setting the textRole. And I also can set the currentIndex to e.g. a number to select the right element. But what I really want is the ComboBox to automatically calculate it's index through a short Javascript function. This function e.g. searches through the model until it finds a match.
This works as long as the model does not change. After I append a new item to the model, the new list is loaded but the currentIndex is reset to 0. How would I also make it reload the new index? Thanks for any help I really appreciate it!Appended is my implementation with PyQt but I doubt this matters from a pure C++ implementation.
main.qml
import QtQuick 2.2 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 import MyModel 1.0 import MyItem 1.0 ApplicationWindow { function getCurrentIndex(list, element) { if (list && element) { for (var i = 0; i < list.length; i++) { if (list[i].name === element.name) { console.log('Found item at pos: ' + i) return i } } } return -1 } id: mainWindow width: 800; height: 600 color: "gray" MyModel { id: mymodel } ComboBox { id: combo width: parent.width currentIndex: getCurrentIndex(mymodel.items, mymodel.item) model: mymodel.items textRole: 'name' } Button { anchors.top: combo.bottom text: 'Add item' onClicked: mymodel.new_item() } }
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from PyQt5.QtQml import QQmlListProperty class MyItem(QObject): nameChanged = pyqtSignal() def __init__(self, name, parent=None): QObject.__init__(self, parent) self._name = name @pyqtProperty('QString', notify=nameChanged) def name(self): return self._name class MyModel(QObject): itemChanged = pyqtSignal() itemsChanged = pyqtSignal() def __init__(self, parent=None): QObject.__init__(self, parent) self._items = [MyItem('one'), MyItem('two'), MyItem('three')] self._item = self._items[1] @pyqtProperty(MyItem, notify=itemChanged) def item(self): return self._item @pyqtProperty(QQmlListProperty, notify=itemsChanged) def items(self): print('Query for items') return QQmlListProperty(MyItem, self, self._items) @pyqtSlot() def new_item(self): print('Append new item') self._items.append(MyItem('new')) self.itemsChanged.emit()
import os import sys from PyQt5 import QtCore, QtQml, QtWidgets from mymodel import MyModel, MyItem osname = os.name.lower() sysplatform = sys.platform.lower() windows = os.name.lower() == "nt" and sysplatform.startswith("win") # PyQt class name, QML URI, major version, minor version, QML type name QtQml.qmlRegisterType(MyModel, 'MyModel', 1, 0, 'MyModel') QtQml.qmlRegisterType(MyItem, 'MyItem', 1, 0, 'MyItem') app = QtWidgets.QApplication(sys.argv) # Create the QML engine engine = QtQml.QQmlEngine(app) engine.quit.connect(app.quit) # Load the main.qml file and create the toplevel component component = QtQml.QQmlComponent(engine) currentFilePath = os.path.dirname(os.path.abspath(__file__)) mainFilepath = os.path.join(currentFilePath, "main.qml") if windows: mainFilepath = mainFilepath.replace('\\', '/') qmlFile = QtCore.QUrl("file:///" + mainFilepath) component.loadUrl(qmlFile) if component.status() != QtQml.QQmlComponent.Ready: for error in component.errors(): print(error.toString()) sys.exit(-1) topLevelItem = component.create() if not topLevelItem: for error in component.errors(): print(error.toString()) sys.exit(-1) # Now run the main loop until the user closes the application topLevelItem.show() sys.exit(app.exec_())