How to access nested Repeaters in QML? - qt

I want to fill the colours in the following rectangles created through Repeaters, dynamically.
I am not able to access the bottom Repeater at all.
How should I access "all" the rectangles here?
Row
{
spacing: 20
Repeater
{
id: repeater3
property Repeater repeater2: repeater2
model: head.rows
Column
{
id: columnInBetween
spacing: 20
Repeater
{
id: repeater2
model: head.columns
property Row row1: row1
Row
{
id: row1
property Repeater repeater1: repeater1
Repeater
{
id: repeater1
model: 2
Rectangle
{
width: 20; height: 20
color: "red"
}
}
}
}
}
}
}

Repeater will expand Item they contians.So you can use .children[index] to access those Item expanded.
In your case:
/*0< index < head.rows
you get first Column expanded by repeater3*/
repeater3.itemAt(index).children[0]
/*0< index < head.columns
you get first Row of first Column expanded by repeater3 and repeater2*/
repeater3.itemAt(index).children[0].children[0]
/*0< index < 2
you get first Rectangle of first Row of first Column expanded by repeater3 and repeater2 and repeater1*/
repeater3.itemAt(index).children[0].children[0].children[0]
By the way, I do not know your intention and just remaid that you are getting a head.columns rows and 2 * head.rows columns of tables.

Related

Nested repeaters does not respect z values

I have two repeaters, one is nested inside of the other.
There are two Rectangles;
Repeater {
model: x
Rectangle {
id: alwaysOnBottom
z: -1
..
}
Repeater {
z: 100
model: y
Rectangle {
id: alwaysOnTop
z: 100
}
}
}
I always want the second rectangle two be on top of the first one.
However, other items just does not respect their z value and, say second item's first rectangle overdraws the first item's second rectangle.

Qt QML Notify ListView when items in the model are added or removed

My ListView should always scroll its currently active item to the top between preferredHighlightBegin and preferredHighlightEnd. That works while clicking an item. However when a new item is added to my AbsctractListModel (And its not just added on the end but could be added anywhere in the middle), the ListView shows the new item, but it is not scrolled to the top. This is most likely because list.currentIndex = index is not set for new added items. I want to set it but did not find a way yet to do so. Does anyone have a hint?
I tried different signals such as onCurrentItemChanged but did not find the proper one yet which also gives me the correct index.
ListView {
id: list
anchors.fill: parent
clip: true
spacing: 11
focus: true
highlightMoveDuration: 400
snapMode: ListView.SnapToItem
preferredHighlightBegin: 0
preferredHighlightEnd: 100
highlightRangeMode: ListView.StrictlyEnforceRange
model: myAbstractListModel
delegate: ListItem {
height: 56
width: list.width
color: "red"
onListItemClicked: {
list.currentIndex = index
}
}
}
The expected result would be a ListView which scrolls a programmatically new added item of my AbstractListModel to the top (between preferredHighlightBegin and preferredHighlightEnd).
Adding this to your ListView will change the current index to the last one whenever the number of items in the model changes, you might want to keep track of the previous items count if you want to scroll only on insertion.
onCountChanged: {
if (count > 0) {
currentIndex = count - 1;
}
}
If the new items might be inserted anywhere in the model you could connect directly to it using the Connections item inside your ListView and connect it directly to the rowsInserted signal of QAbstractItemModel.
Connections {
target: model
onRowsInserted: {
currentIndex = first + 1;
}
}
If your model emits only the dataChanged signal you can try this.
Connections {
target: model
onDataChanged: {
currentIndex = topLeft.row() + 1;
}
}

Unique id for each element of a ListView

I have a ListView of Items and I need that each element has an unique id.
But I have two conditions on my Items:
I can't use index because my Itemscan be moved (drag&drop), so their index will change.
Each Item can be displayed many times, so there is no property of these elements that can help me to distinguish them.
My idea was to do something like that:
ListView {
id: list
property int uniqueId: 0
width: 180; height: 200
model: myModel
delegate: Text {
property int uniqueid: list.uniqueId
text: uniqueid
}
Component.onCompleted: list.uniqueId++
}
But it doesn't work because when list.uniqueId is updated, it will update my Items id and they will all have the same id ( id = list.uniqueId)
How could I proceed?
Well, if you severe (or don't create) the binding, it will not auto update:
delegate: Text {
Component.onCompleted: text = uniqueId++
}
However, I don't think avoiding this will really fix your design. What you should do is have the the unique id part implemented all the way back into the model data.

Open QML ComboBox drop down menu from the current item position

I have choose an item in combobox. Item's position is 300 for example. If I want to choose new element from combobox . Popup shows from beginning. I want to popup opened from current item position.
ComboBox {
id: control
model: ["First", "Second", "Third","MERHABA","NASILSIN","SELAM","IYIMISIN","DOSTUM","SUAN","BIR","DENEME YAPILIYOR"]
//width: 350
//font.pixelSize: 20
delegate: ItemDelegate {
width: 350
text: modelData
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
font.pixelSize: 30
highlighted: control.highlightedIndex == index
}
For QtQuick.Controls 2, There is a 'popup' property, so we can set the popup position with it's own property 'y', like this:
ComboBox {
model: ["First", "Second", "Third"]
delegate: ItemDelegate {
text: modelData
}
popup.y: y + height // popup just below ComboBox
}
The ComboBox will work the way you want it if the conditions allow for it, that is, if you have enough elements to fill the entire drop down list after the current index item it will show from that item rather than the beginning.
The stock ComboBox however doesn't seem to allow you to specify the drop down list height, so it will take significantly more elements than you have in your example. Or significantly taller elements.
Furthermore, if the current index is the last element, how do you imagine this will show? The list would show only the last element plus a whole bunch of nothing, which is not even possible, the last item cannot move up from the end of the list.
If you really want that behavior, you will have to implement your own combo box element from scratch.
I was facing the same issue and found out that if you place the popup onOpened, it works perfectly:
ComboBox {
id: yearDropdown
model: yearModel
onActivated: updateVisibleDate()
popup: Popup {
id: comboPopup
clip: true
contentItem: ListView {
id: listView
implicitHeight: contentHeight
model: yearDropdown.popup.visible ? yearDropdown.delegateModel : null
onModelChanged: if(model) positionViewAtIndex(yearDropdown.currentIndex, ListView.Center);
ScrollIndicator.vertical: ScrollIndicator { }
}
onOpened: {
x = yearDropdown.x //Set the position you want
y = yearDropdown.y + yearDropdown.implicitHeight //Set the position you want
}
}
}

QML Gridview with InputText

I need a Listview with InputText on each row. Use case is a cart of items wherein qty can be changed for each row.
With the below code, Listview is rendering with a label and a text box alongside.
Issue is, all textboxes are going to have the same id, because of which, all textbox values are changing based on the last textbox value changed. Ex: If I enter 10 for the first item and 12 for the second item, even first item's qty changes to 12.
The onEnter is only for demonstration. It could be onFocusChanged going forward:
ListView {
id:list
model: fruitModel
x:10
y:10
width: parent.width-20
height: parent.height-20
clip:true
anchors.fill: parent
delegate: Row {
width: parent.width
height:30
Item
{
property variant myData: model
property alias value: text.text
Text {
id:text
width: parent.width
height: 30
text:name
}
InputText {
id: inp_box
text:qty
width:100
height:22
anchors.verticalCenterOffset: 15
anchors.horizontalCenterOffset:250
focus: true
onEnter: {
editQty(inp_box.text);
}
}
}
}
focus: true
snapMode: ListView.SnapOneItem
ScrollBar {
flickable: list
vertical: true
hideScrollBarsWhenStopped:false
}
}
You should extend your editQty function to take the index of edited entry in fruitModel as an additional parameter. The index of the current entry is available within the list view's delegate as index. The way you did it, editQty has no chance to know which entry to change.

Resources