GridLayout Arrangement - qml

Following is my main.qml:
Window {
id: window
visible: true
width: 800
height: 480
title: qsTr("Hello World")
ListModel {
id: _listModel
ListElement {
textData: "E1"
isEnabled: false
}
ListElement {
textData: "E2"
isEnabled: false
}
ListElement {
textData: "E3"
isEnabled: false
}
ListElement {
textData: "E4"
isEnabled: false
}
ListElement {
textData: "E5"
isEnabled: false
}
ListElement {
textData: "E6"
isEnabled: false
}
}
ListView {
id: _listview
model: _listModel
width: 100
height: parent.height
anchors.right: parent.right
delegate: Item {
width: parent.width
height: 50
anchors.right: parent.right
Component.onCompleted:
{
if (isEnabled)
visibleRecs++;
}
RowLayout {
Text {
id: itemText
text: qsTr(textData)
}
CheckBox {
height: 30
width: height
checked: isEnabled
onCheckedChanged: {
isEnabled = checked
}
}
}
}
}
ScrollView {
id: _scrollView
width: parent.width / 2
height: parent.height
clip: true
GridLayout {
id: _gridLayout
anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: 10
rowSpacing: 10
columns: 2
Repeater {
model: _listModel
Loader {
id: _loader
sourceComponent: isEnabled ? _recComponent : null
onLoaded: {
item.text = textData
}
}
}
}
}
Component {
id: _recComponent
Rectangle {
property alias text : _txt.text
id: _rec
width: 100
height: 50
radius: 5
color: "yellow"
Text {
id: _txt
anchors.centerIn: parent
}
}
}
}
The above code creates following (when all check boxes are ticked):
When all checkboxes are ticked:
When checkbox E3 is unchecked:
I want the items to be rearranged in the gridlayout if any of the item goes invisible.
E.g. in the above case when E3 is unchecked, I want my view to be something like this:
Please let me know, if it is possible to achieve. Thanks in advance.

The problem is that you still instantiate the Loader, you just set the sourceComponent to null. You have to make the item invisible to not use space in the GridLayout (or put width/height to 0)
ScrollView {
id: _scrollView
width: parent.width / 2
height: parent.height
clip: true
GridLayout {
id: _gridLayout
anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: 10
rowSpacing: 10
columns: 2
Repeater {
model: _listModel
Loader {
id: _loader
visible: isEnabled
sourceComponent: isEnabled ? _recComponent : null
onLoaded: {
item.text = textData
}
}
}
}
}

Related

flickableItem.atYEnd is always false when scrolling QML

I have a ListView which is inside a ScrollView and I want to know or listen when the scroll bar is scrolled to the bottom,
ScrollView {
id: moderatorMessagesScrollViewID
anchors.fill: parent
function update()
{
console.debug("<< moderatorMessagesScrollViewID ScrollView::update ", flickableItem.atYEnd);
}
flickableItem.onAtYBeginningChanged: {
update();
}
flickableItem.onAtYEndChanged: {
update();
}
flickableItem.onContentYChanged: {
update();
}
ListView {
id: moderatorMessagesList
anchors.leftMargin: 15
anchors.rightMargin: 15
anchors.bottomMargin: 5
layoutDirection: Qt.LeftToRight
orientation: ListView.Vertical
verticalLayoutDirection: ListView.BottomToTop
cacheBuffer: (chatPanel.height <= 0) ? 1000 : (chatPanel.height * 1000)
spacing: 0
focus: true
Component.onCompleted: {
updateView();
}
delegate: messageListDelegate
}
style: ScrollViewStyle {
incrementControl: Rectangle {
visible: false
implicitWidth: 0
implicitHeight: 0
}
decrementControl: Rectangle {
visible: false
implicitWidth: 0
implicitHeight: 0
}
corner: Rectangle {
color: "white"
visible: true
rotation: 180
}
handle: Rectangle {
implicitWidth: 5 * MyStyle.props.scrollSizeFactor()
implicitHeight: 7 * MyStyle.props.scrollSizeFactor()
color: Qt.rgba(237/255, 237/255, 237/255, 1)
radius: 2
border.width: 1
border.color: "#C3C3C3"
}
scrollToClickedPosition: true
handleOverlap: 1
scrollBarBackground: Rectangle {
width: 5 * MyStyle.props.scrollSizeFactor()
height: 10 * MyStyle.props.scrollSizeFactor()
color: MyStyle.props.color("chatChatPanelBackground")
}
transientScrollBars: false
}
}
but my issues here are
flickableItem.atYEnd is always false
flickableItem.onAtYEndChanged is not triggered even if I scroll at the bottom
update() is triggered by onContentYChanged() instead when i try to scroll using scrollbar.
What is wrong with this and what areas I need to look into?
Here's a minimum working example depicting the detection of Vertical scroll bar at its bottom:
ListModel {
id: contactModel
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
}
Rectangle {
width: 180; height: 50
Component {
id: contactDelegate
Item {
width: 180; height: 40
Column {
Text { text: '<b>Name:</b> ' + name }
Text { text: '<b>Number:</b> ' + number }
}
}
}
}
ScrollView {
width: 200
height: 60
ListView {
model: contactModel
delegate: contactDelegate
onAtYEndChanged: console.log("Vertical Scroll Bar's bottom reached = ", atYEnd)
}
}

QML ListView delegate with Component Row does't render correctly

And now I have a problem with my qml script. here's the simple code:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: root
anchors.fill: parent
color: "green"
SystemPalette { id: activePalette }
ColumnLayout {
id: rightPanel
Layout.fillHeight: true
Layout.fillWidth: true
Layout.rightMargin: 10
anchors.fill: parent
Component.onCompleted: {
console.log(this, width, parent, parent.width)
}
ListView {
spacing: 2
Layout.fillHeight: true
Layout.fillWidth: true
model: ListModel {
ListElement {
name: "nihao"
value: "1"
}
ListElement {
name: "fds"
value: "2"
}
ListElement {
name: "fdssd"
value: "4"
}
}
delegate: Component {
// Rectangle {
// color: "yellow"
// height: 40
// width: parent.width
Row {
anchors.fill: parent
spacing: 2
height: 40
width: 200
Rectangle {
color: activePalette.window
height: 25
width: 100
border.color: "white"
border.width: 3
Text {
anchors.centerIn: parent
text: name
}
}
Rectangle {
color: activePalette.window
height: 25
width: 100
border.color: "white"
border.width: 3
Text {
anchors.centerIn: parent
text: value
}
}
}
//}
}
}
}
}
}
The code does't display correctly when I use qmlscene to render it, it even render nothing if the ListModel is too long.
But, if I uncomment out the "Rectangle" code in delegate component, it works well. So I'm comfused with the difference between Reactangle and Row for that they are all inherited from Item. And what should be placed into the delegate component as its direct child?

QML: TableView and Columns

I noticed that the column that is on the right always overlaps the data from the column that is on the left. How to change this behavior?
The panel with shadow is defined into TableViewColumn.delegate. I need the panel to overlap the neighbor in the right cell.
// Minimal code example that represent a problem!
Page {
TableView {
anchors.fill: parent
selectionMode: 1
TableViewColumn {
role: "login"
title: "Login"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 40
width: 150
color: "green"
}
}
}
TableViewColumn {
role: "fullName"
title: "FullName"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 30
width: 150
color: "red"
}
}
}
TableViewColumn {
role: "status"
title: "Status"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle{
anchors.verticalCenter: parent.verticalCenter
height: 20
width: 150
color: "blue"
}
}
}
model: ListModel {
ListElement { text: "ghdjbf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
}
property Component headerDelegate: BorderImage {
property bool sortSwitcher: false
height: 40
id: tableHeader
objectName: "TableHeader"
Rectangle {
id: viewableSection
anchors.fill: parent
color: "white" // "#f2f2f2"
Text {
id: textItem
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
anchors.leftMargin: 25
font.pixelSize: 11
font.family: "Roboto"
text: styleData.value
font.bold: true
elide: Text.ElideRight
color: "#646464"
renderType: Text.NativeRendering
}
Rectangle {
id: bottomHeaderBorder
anchors.top: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: "#ebebeb"
}
Rectangle {
id: headerSeparator
z: 1
anchors.left: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
anchors.topMargin: 8
width: 1
color: "lightgrey"
MouseArea {
id: mouseAreaSeparator
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.SizeHorCursor
onEntered: {
mouseAreaSeparator.cursorShape = Qt.SizeVerCursor
}
}
}
}
}
property Component rowDelegate: Rectangle {
id: rowDel
objectName: "RowDelegate"
height: 50
//property color selectedColor: styleData.hasActiveFocus ? primaryColor : secondaryColor
property bool selectionMaskVisible
property bool selected: false
Rectangle {
id: rowSelectionMask
anchors.fill: parent
color: rowDel.selectionMaskVisible ? "#f2f2f2" : "#ffffff"
visible: parent.activeFocus ? false : true
z: parent.activeFocus ? 1 : 2
}
Rectangle {
id: activeFocusMask
anchors.fill: parent
color: parent.activeFocus ? styleData.row !== undefined ? secondaryColor : "White" : "White"
opacity: styleData.row !== undefined ? 0.9 : 0
z: parent.activeFocus ? 2 : 1
}
MouseArea {
id: rowMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
if (styleData.row !== undefined)
{
rowDel.selectionMaskVisible = true
}
}
onExited: {
rowDel.selectionMaskVisible = false
}
}
Rectangle {
id: bottomBorder
objectName: "BottomBorder"
z: 2
anchors.bottom: parent.bottom
height: 1
width: parent.width
color: "#ebebeb"
opacity: styleData.row !== undefined ? 1 : 0
}
Rectangle {
id: separator
z: 1
anchors.left: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 1
anchors.topMargin: 1
width: 1
color: "red"
}
}
}
}
Judging from the code there is no clean solution to it.
But as you can see, the delegate of the TableViewColumn is instantiated by a Loader via a Repeater into a Row.
So to change get the first column on top of the second column, we need to change the z-index - but not of the delegate itself (as this would only affect the children of the same Loader) but of the Loader. This can be achieved e.g in the Component.onCompleted-handler.
TableViewColumn {
role: "login"
title: "Login"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Component.onCompleted: parent.z = 3 // <- Put the loader on top of its siblings
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 40
width: 150
color: "green"
}
}
Component.onCompleted: console.log(Object.keys(this))
}

Is it possible to set a Pathview element in QML to stop when it reaches last element in the model?

Pathview rotate to the first element when it reaches end, how to stop it when it reaches the end?
Thanks
import QtQuick 1.0
Rectangle {
id: rectangle1
width: 360
height: 360
color: "grey"
opacity: 1
ListModel {
id: listModel
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
}
Component {
id: delegate
Text {
id: nameText
width: 64; height: 20
wrapMode: Text.Wrap
text: name
}
}
Rectangle {
y:parent.height/2
width: parent.width
height: parent.height/2
ListView {
width: parent.width
height: parent.height
model: listModel
focus: true
delegate: Text {
id: item
text: name + ": " + number
}
preferredHighlightBegin: 20
preferredHighlightEnd: 40
highlightRangeMode: ListView.StrictlyEnforceRange
highlight: Rectangle { color: "lightblue"; radius: 5 }
}
}
}
This effect can be achieved by ListView, with the properties setting.

how to use one model in two views

i have one model for pictures and want to show them in grid view or list view (fullscreen) synchronously. if user clicks on one image in grid view i want this image to be shown in fullscreen mode (in listview).
i have one solution but my list view scrolls till "the current index".
THanx.
PhotoView.qml
Rectangle {
width: settings.pageWidth
height: settings.pageHeight
anchors.fill: parent
VisualDataModel {
id: visualModel
delegate: PhotoDelegate {}
model: photosModel
}
ListView {
id:fullscreen
anchors.fill: parent;
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem;
flickDeceleration: 500
//highlightFollowsCurrentItem: true
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: 0; preferredHighlightEnd: 0
cacheBuffer: width;
spacing: settings.largeMargin
model: visualModel.parts.grid
}
GridView{
id:grid
width: settings.pageWidth
height: settings.pageHeight
anchors.fill: parent
cellWidth: settings.gridCellWidth
cellHeight: settings.gridCellHeight
snapMode: GridView.SnapToRow
cacheBuffer: settings.pageHeight
clip: true
model: visualModel.parts.grid
}
// // Menu/Back Button
// IconButton{
// id: backButton
// iconSource: "qrc:///gfx/back_arrow.png"
// anchors.right: parent.right
// anchors.bottom: parent.bottom
// onClicked: mainWindow.close();
// }
// Fade Top
Image{
id:bottom_fade
source: "qrc:///gfx/bottom-page-fade.png"
height: 33
width: settings.pageWidth
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
}
// Fade Bottom
Image{
id:top_fade
source: "qrc:///gfx/top-page-fade.png"
height: 33
width: settings.pageWidth
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
}
}
PhotoDelegate.qml
import QtQuick 1.0
import Qt 4.7
import "../views"
import "../model"
import "../views/components"
Package {
Item { id: listDelegate; Package.name: 'list'; width: settings.pageWidth; height: settings.pageHeight }
Item { id: gridDelegate; Package.name: 'grid'; width: settings.pageWidth; height: settings.pageHeight }
Item {
id: wrapper
width: settings.pageWidth; height: settings.pageHeight
Image {
id: thumbnail; smooth: true; source: thumbnail_url
}
MouseArea {
anchors.fill: parent
onClicked: {
if (wrapper.state == 'inGrid') {
listDelegate.fullscreen.view.currentIndex = index;
wrapper.state = 'fullscreen'
} else {
gridDelegate.grid.view.currentIndex = index;
wrapper.state = 'inGrid'
}
}
}
state: 'inGrid'
states: [
State {
name: 'fullscreen'
ParentChange { target: wrapper; parent: listDelegate; x: 0; y: 0;
width: listDelegate.width; height: listDelegate.height
}
},
State {
name: 'inGrid'
ParentChange {
target: wrapper; parent: gridDelegate
x: 0; y: 0; width: gridDelegate.width; height: gridDelegate.height
}
}
]
transitions: [
Transition {
from: 'inGrid'; to: 'fullscreen'
SequentialAnimation {
PauseAnimation { duration: gridItem.GridView.isCurrentItem ? 0 : 600 }
ParentAnimation {
target: wrapper; via: foreground
NumberAnimation {
targets: [ wrapper]
properties: 'x,y,width,height,opacity'
duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
}
}
}
},
Transition {
from: 'fullscreen'; to: 'inGrid'
ParentAnimation {
target: wrapper; via: foreground
NumberAnimation {
targets: [ wrapper ]
properties: 'x,y,width,height,opacity'
duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
}
}
}
]
}
}
To showing selected item without scrolling until index of selected item is to synchronize the view elements current index:
onCurrentIndexChanged: {
your_component.positionViewAtIndex(currentIndex, YourViewElement.Contain)
}