I'm new to qml and I need to write a simple list with 3 columns and an undefined number of rows showing the output of a log using a tableview. The first column shows the type (error, warning, info). Depending on this keywords I need to change the color of that row. I found code where I was able to change the color of all rows, but not individually depending on the data content. This is my starting point:
import QtQuick 2.13
import QtQuick.Window 2.11
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.4
import QtQuick.Controls 1.4 as QtC1
import QtQuick.Dialogs 1.2
ApplicationWindow {
id: applicationWindow
visible: true
width: 640
height: 480
title: qsTr("Log")
ListModel {
id: listModel
ListElement { category: 'warning'; type: "DEVICE IN USE"; comment: "Device with ID: PS-0002 is in use by Line with ID: L-0001A" }
ListElement { category: 'error'; type: "DEVICE IS OFFLINE"; comment: "Cannot reach device with ID: PS-0006 IP: 192.169.0.112 Port: 788" }
ListElement { category: 'info'; type: "DEVICE STATUS"; comment: "Device PS-00013 is ready for use." }
ListElement { category: 'info'; type: "DEVICE STATUS"; comment: "Device PS-00014 is ready for use." }
ListElement { category: 'info'; type: "DEVICE STATUS"; comment: "Device PS-00015 is ready for use." }
ListElement { category: 'info'; type: "DEVICE STATUS"; comment: "Device PS-00016 is ready for use." }
}
ColumnLayout
{
anchors.fill: parent
transformOrigin: Item.Center
Label {
id: logLabel
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
font.pixelSize: 22
text: qsTr("Summary")
Layout.topMargin: 13
}
QtC1.TableView {
id: tv
Layout.fillHeight: true
Layout.preferredHeight: 18
Layout.preferredWidth: 9
Layout.fillWidth: true
rowDelegate: Rectangle {
color: styleData.value ? "blue":"white"
}
/* Create columns */
QtC1.TableViewColumn
{
id: tv_category
horizontalAlignment: Text.AlignLeft
role: qsTr("category")
title: qsTr("Category")
width: 100
}
QtC1.TableViewColumn
{
id: tv_type
horizontalAlignment: Text.AlignLeft
role: qsTr("type")
title: qsTr("Type")
width: 100
}
QtC1.TableViewColumn
{
id: tv_comment
horizontalAlignment: Text.AlignRight
role: qsTr("comment")
title: qsTr("Comment")
width: contentWidth
}
model: listModel
}
}
}
Any help would be appreciated.
Martin
In the rowDelegate you have access to the row index (using styleData.row). Just use it to get the item from the list model like this:
rowDelegate: Rectangle {
color: {
var item = listModel.get(styleData.row)
if (item.category === "info")
return "skyblue"
else if (item.category === "warning")
return "yellow"
else if (item.category === "error")
return "red"
return "skyblue"
}
}
I am relatively new to QML and Qt Quick and I am looking for recommendations on how to display the UI here:
This UI was made with QGraphicWidgets using Json as a model:
If you notice, the outside "Carriage Strength" container is basically a tree structure. A treeview list seems like the way to go, but I'm unsure if I can customize the view to contain the progress bar and html view (QWebEngineView). I will also need to be able to update specific components like the progress bar at runtime as well.
Any input is helpful. If you have any examples to point to would be great as well. Thanks in advance.
As requested below here is a sample of JSON which would be used to construct the model:
{
"SequenceHistory": [
{
"Definition": {
"ID": "carriage_strength",
"DisplayName": "Carriage Strength",
"TestArray": [
{
"ID": "sequence_one_setup",
"DisplayName": "Sequence 1 Setup",
"TestArray": [
{
"ID": "psm1_carriage_strength",
"DisplayName": "PSM1 Carriage Strength",
"Progress": 100,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Finish Failed",
},
{
"ID": "psm2_carriage_strength",
"DisplayName": "PSM2 Carriage Strength",
"Progress": 43,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "In Progress"
},
{
"ID": "psm3_carriage_strength",
"DisplayName": "PSM3 Carriage Strength",
"Progress": 0,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Not Started"
},
{
"ID": "psm4_carriage_strength",
"DisplayName": "PSM4 Carriage Strength",
"Progress": 0,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Not Started"
}
],
},
],
}
}
]
}
The display name indicates the name, the progress indicates the progress bar percentage, the html indicates the html to be displayed in the WebEngineView, and the status indicates the status label. Disregard any timing info that is in the screenshot, but not in the JSON. The main difference between this JSON and the screenshot is that I added a container "Sequence 1 Setup" inside the Carriage Strength container to show that the containers can contain containers as well as items.
I make extensive use of such GUI elements, and the approach is always to represent the tree as lists of lists, that is, depending on the use case, either a ListView or a plain Repeater with a row or column container inside a Flickable, and then it is just delegate nesting.
The stock TreeView may cut it too, if you don't need access for fine-tuning and customizing the view.
I've personally ran into too much stiffness with many of the stock controls, they just don't work the way I need them to or outright lack the desired functionality, and unless it is something really standard, I prefer to roll out my own implementations, which is actually quite easy in QML.
Update:
Ok, now that you have provided an example data source, I can do a basic mock-up for you. BTW you are missing some commas in the JSON, and even tho in my example it is defined in-line, you can simply use JSON.parse(text) to get the same object from a string. Also note that modelData in each nested model refers to a different data object, basically to the respective array element index. And since only one of your arrays has more than one element, the example skips one level for the sake of brevity:
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property var jsondata: {
"SequenceHistory": [
{
"Definition": {
"ID": "carriage_strength",
"DisplayName": "Carriage Strength",
"TestArray": [
{
"ID": "sequence_one_setup",
"DisplayName": "Sequence 1 Setup",
"TestArray": [
{
"ID": "psm1_carriage_strength",
"DisplayName": "PSM1 Carriage Strength",
"Progress": 100,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Finish Failed"
},
{
"ID": "psm2_carriage_strength",
"DisplayName": "PSM2 Carriage Strength",
"Progress": 43,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "In Progress"
},
{
"ID": "psm3_carriage_strength",
"DisplayName": "PSM3 Carriage Strength",
"Progress": 0,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Not Started"
},
{
"ID": "psm4_carriage_strength",
"DisplayName": "PSM4 Carriage Strength",
"Progress": 0,
"HtmlToDisplay": "<html><body>This is guide instruction</body></html>",
"Status": "Not Started"
}
],
},
],
}
}
]
}
ListView {
id: rv
anchors.fill: parent
model: jsondata.SequenceHistory
delegate: Rectangle {
width: rv.width
height: childrenRect.height // fit the expanding part
color: "grey"
Column {
spacing: 2
Row {
spacing: 10
Button {
id: exp
checkable: true
text: checked ? "+" : "-"
implicitWidth: 20
implicitHeight: 20
}
Text {
text: modelData.Definition.DisplayName
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
x: 20
spacing: 2
Repeater {
// if not expanded model is null else skip one level
model: exp.checked ? 0 : modelData.Definition.TestArray[0].TestArray
delegate: Rectangle {
width: rv.width
height: childrenRect.height
color: "lightgrey"
Column {
Row {
spacing: 10
Button {
id: exp2
checkable: true
text: checked ? "+" : "-"
implicitWidth: 20
implicitHeight: 20
}
ProgressBar {
value: modelData.Progress
from: 1
to: 100
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: modelData.DisplayName
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
visible: exp2.checked // hide if not expanded
TextArea {
width: 300
height: 200
text: modelData.HtmlToDisplay
}
}
}
}
}
}
}
}
}
}
And the result:
Note that you can also compartmentalize things by spreading the delegates across different sources, because as you style them property, they will get bigger. I put it in a single source just for the sake of the example.
I have a ListView ListModel with 10 ListElements, I want the ListView to display the first ListElement from the model.
Is there a way to limit the number of ListElement items that are displayed, or select the ListElement to display from an ID in the data?
Example ListModel:
ListModel {
id: homeMenuModelData
ListElement {
name: "Sam Wise Is A Very Wise Man"
number: "555 0473"
}
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
}
The ListView:
ListView {
anchors.fill: parent
interactive: false
model: HomeMenuModel
delegate: homeMenuDelegate
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
}
I'm thinking something like this would be useful to me:
model.clear();
for( var i=0; i < bookList.length ; ++i ) {
model.append(bookList[i]);
}
****** Updated ******
Props to #folibis (below comments) for the suggestion, good explanation here of using DelegateModel and filterOnGroup: Is it possible to show only certain indexes of a QML listview?
I have a ListModel like the following:
ListModel {
id: liveFeedModel
ListElement {
modelSrc: [
ListElement { src: "../img/pano.jpg" },
ListElement { src: "../img/pano1.jpg" },
ListElement { src: "../img/pano2.jpg" },
ListElement { src: "../img/pano3.jpg" }
]
name: "Cookies"
temp: "456 °C"
time: "--:--"
}
ListElement {
modelSrc: [
ListElement { src: "../img/pano2.jpg" }
]
name: "Sourdough Roll"
temp: "123 °F"
time: "--:--"
}
}
And I would like to set the value of the nested ListElements within modelSrc.
I am looking for something similar to:
liveFeedModel.get(0).modelSrc.get(2).src
except with set, setProperty, or something along those lines, instead of get
Thanks in advance
use:
myListView.model.get(0).modelSrc.setProperty(0, "src", "../img/pano2.jpg");
simple as that!
I have kendo tree-view in my application,I want to apply the styles for kendo tree-view parent node only.How to apply the styles like Font weight-bold for the parent node of tree-view?
My treeview code is
var tree= $("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [{
id: 2, text: "select all", expanded: true,
items: [
{ id: 3, text: "ABH" },
{ id: 4, text: "VFG" },
{ id: 5, text: "VFGT" },
{ id: 6, text: "GTYUJ" },
{ id: 7, text: "GHJ" }
]
}]
}).data("kendoTreeView");
here is the JSfiddle.
Try to configure this in scripts.
.k-top.k-bot {font-weight: bold;}