I'm actually developing a software with Python and QML. I've manage to learn it by myself and thanks to some good videos but I've come across a problem lately that I can't manage to deal with.
So here is my ListView Element :
ListView {
id: listView
anchors.fill:parent
anchors.bottom: start_button.top
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.topMargin: 20
delegate: informationDelegate
model: ListModel { id:informationModel }
}
Well, as you can see I have a delegate to "pre-format" my list :
Component{
id:informationDelegate
Column {
spacing: 5
height: 60
Text { text: name ; font.bold: true ; color: "#ffffff" }
Text { text: path ; color: "#ffffff" ; ToolTip.delay: 1000 ; ToolTip.visible: ma.containsMouse ; ToolTip.text: qsTr("Tooltip empty")
MouseArea { id: ma ; anchors.fill: parent ; hoverEnabled: true}
}
}
}
And then, I'd like to modify the Tooltip.text value in a JS function but I can't find a way to do it. I've tried many things but don't really find a way to do it.
informationModel.clear()
informationModel.append ({"name" : "Ansible Playbook :" , "path.ToolTip.text" : obj.ansiblePath , "path" : obj.ansiblePath.split('/').pop() })
informationModel.append ({"name" : "Configuration File :" , "path.ToolTip.text" : qsTr(obj.ansiblePath) , "path" : displayConf.split('/').pop() })
informationModel.append ({"name" : "Firmware File :" , "path.ToolTip.text" : qsTr(obj.ansiblePath) , "path" : displayFirmware.split('/').pop() })
Let me know if you have a hint about this issue ;)
Your approach is wrong, the model does not directly modify the view but the view uses the model to modify itself, so in your case you must create a property and make a binding with the ToolTip.text:
Component{
id:informationDelegate
Column{
required property string name
required property string path
required property string message
spacing: 5
height: 60
Text {
text: name
font.bold: true
color: "#ffffff"
}
Text {
text: path
ToolTip.delay: 1000
ToolTip.visible: ma.containsMouse
ToolTip.text: message
MouseArea {
id: ma
anchors.fill: parent
hoverEnabled: true
}
}
}
}
informationModel.clear()
informationModel.append({"name" : "Ansible Playbook :" , "message" :"message1" , "path" : "path1" })
informationModel.append({"name" : "Configuration File :" , "message" : "message2" , "path" : "path2" })
informationModel.append({"name" : "Firmware File :" , "message" : "message3" , "path" : "path3" })
Related
Since my last issue with my code, I've come across a new one. Unfortunately, it's not really an implementation issue but much more an "conceptual" issue.
Well so let met introduce the case. I have a grid full of button and then to deal with their onClicked events I have a ButtonGroup
GridLayout {
id: gl
anchors.fill: parent
...
CustomButton{
id: btnMILA1
text: "PlayBook 1"
... //Layout stuff
}
CustomButton{
id: btnMILA2
text: "PlayBook 1"
... //Layout stuff
}
CustomButton{
id: btnMILAN
text: "PlayBook 1"
... //Layout stuff
}
}
Those are generated in a loop so no worries, I didn't wrote all 40 buttons ^^ So here is my ButtonGroup
ButtonGroup {
id: btnGroup
buttons: gl.children
onClicked: {
... //Do some stuff
}
}
As you may have seen, I have a CustomButton element which is used for two reasons :
Esthetics (custom design, round corners, etc...)
Add a MouseArea to each button and onRightclick, show a Menu element
So here is a simplified version of my code for CustomButton element:
import QtQuick 2.15
Button {
id: button
property string optionalConf //SEE LATER BELOW, THIS ITEM WILL BE USEFUL
text: qsTr("Button")
contentItem: Item{
Text {
id: name
text: button.text
font: button.font
color: "#ffffff"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
}
background: Rectangle{
color: internal.dynamicColor //Used to deal with Hovered/Pressed/Default states
radius: 10
}
MouseArea {
id:mouseHovered
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked:{
rightClickMenu.open()
}
hoverEnabled: true
}
Menu {
id: rightClickMenu
MenuItem {
text: qsTr("Choix du fichier de configuration...")
shortcut: StandardKey.Open
onTriggered: confOpen.open()
}
MenuItem {
text: qsTr("Choix du firmware...")
shortcut: "Ctrl+Shift+O"
onTriggered: firmwareOpen.open()
}
MenuSeparator{}
MenuItem {
text: qsTr("Console")
shortcut: StandardKey.AddTab
//onTriggered: zoomOut()
enabled: false
}
}
}
I don't really know the efficiency in generating a mouseArea for each element so let me know if you have a better way to have an independent onRightclick option for something like 20 or 30 elements.
My issue is the following. On the page, let's say main.qml where the CustomButton is implemented, I have two fileDialog items : one called confOpen and the other called firmwareOpen as you could expect given the code above. When the user uses the rightclick, the MenuItem shows at the exact place of the mouse, he can choose wherever option he wants. Then a called is made to either confOpen or firmwareOpen and the user is able to select one file.
FileDialog{
id: confOpen
title: "Please choose a conf file"
folder: shortcuts.desktop
selectMultiple: false
nameFilters: ["Conf file (*.conf)"]
onAccepted: {
console.log(fileUrl)
//I'd like to do something like this :
//ButtonUsedToOpenFileDialog.optionalConf : fileUrl
}
}
So here is the real issue, I'd like to store the file path into a property of my CustomButton. I have a property string optionalConf in order to do so. But I can't manage to which button made the call to the FileDialog, so I don't know which button should have his optionalConf property updated.
I hope I've been clear and it doesn't take to long to read but I wanted to be clear and precise. Let me know if you have better ways to do what I'm doing, I'm always listening to advice :)
Add a function to your FileDialog called openDialog and pass to it the button like this:
[...]
MenuItem {
text: qsTr("Choix du fichier de configuration...")
shortcut: StandardKey.Open
onTriggered: confOpen.openDialog(button)
}
[...]
FileDialog {
id: confOpen
property var button
function openDialog(button_) {
button = button_;
open();
}
onAccepted: {
button.optionalConf = "UPDATED";
}
}
I'm trying to adapt the row height of a TreeView to automatically fit the content in its itemDelegate, but I have no clue how to do so.
So far, I tried to create a property "lines" in my itemDelegate object, but everytime I try to access it QML says my treeDeleg item is undefined.
Is there a way to get the result I want ?
EDIT : following what JarMan said, it's not possible to reference a delegateComponent by ID. So instead, is there's a way to automatically adapt the row height to its content ? Something along the lines of "height: auto" in CSS. This is really important because long values make my interface hard to read.
If all else fails, would there be a better component to create a tree styled view able to contain long, editable values ?
main.qml :
TreeView
{
id:treeView
anchors.top: rowInfo.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
itemDelegate: TreeDelegate
{
id: treeDeleg
}
style: TreeViewStyle
{
id: styleTree
rowDelegate:Rectangle
{
id : rowDeleg
height: styleData.selected ? 75 : 25 * treeDeleg.lines
color:
{
var baseColor = styleData.alternate ? "white" : "#d9edf7"
return styleData.selected ? "yellow" : baseColor
}
}
}
Component.onCompleted:
{
treeView.model = Qt.binding(function()
{
if (typeof theModel !== "undefined")
{
return theModel;
}
else
{
return null;
}
});
}
TableViewColumn
{
id:column1
role: "Name"
title: "Name"
width: 450
}
TableViewColumn
{
id:column3
role: "Value"
title: "Value"
width: 400
}
TableViewColumn
{
id:column4
role: "Desc"
title: "Description"
width: 750
}
}
TreeDelegate.qml
Item
{
id: item
width : parent.width
height : 25
property var lines: null
TextEdit
{
id: text1
font.pixelSize: 14
readOnly: true
focus: false
width : parent.width
height: 25 * lineCount
anchors.left: parent.left
wrapMode: TextEdit.Wrap
text: (styleData.value !== null) ? (styleData.value.text + styleData.value.id) : "";
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
Component.onCompleted:
{
lines = text1.lineCount == 0 ? 1 : text1.lineCount;
console.log("Lines : " + lines);
}
}
}
```
I want to put a condition if the condition is true then show the images. But when i run this code i'm getting an error. It shows image is undefined
here is my code sample
Row{
spacing:5
Component.onCompleted:{
if( my condition is true ==true)
{
image.source="image_path"
}
}
Repeater{
model: 4
Image {
id: image
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
}
}
}
Referencing an id inside Repeater does not work, since the Repeater breaks the scope a bit.
But if you turn around the logic it works: you can bind the source property inside the delegate to a new property on the main control (which I named control here):
Row {
id: control
spacing:5
property bool show : false
Repeater{
model: 4
Image {
id: image
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
source: control.show ? "image_path" : ""
}
}
}
TreeView {
anchors.fill: parent
model: theModel
onCurrentIndexChanged: console.log("current index: " + currentIndex+ " current row: " + currentIndex.row)
itemDelegate: Rectangle {
color: ( styleData.row % 2 == 0 ) ? "white" : "lightblue"
height: 40
Text {
anchors.verticalCenter: parent.verticalCenter
text: styleData.value === undefined ? "" : styleData.value // The branches don't have a description_role so styleData.value will be undefined
}
}
TableViewColumn {
role: "name_role"
title: "Database name"
}
onClicked: {
console.log("clicked", index)
}
this is my treeview code.it will show database names as parent and table names as the child. I need to get the child name when I click on the child area.
that's all I need.
for eg:
database_name
|____table_one
|____table_two
when i click on 'table_one' i need to get the table_one as a text/string
this is my application I need to get the child items names as a text from this treeview
After some search, I have got the solution for the above question myself
syntax: model_class_name.data(index,"Role_name");
*the above code will return the current item that in focus in a tree view
In the qml file, you must set the class name as model_class_name.data(index,INT); where INT - it is a number of role.
I have the following TreeView:
TreeView {
id: view
anchors.fill: parent
sortIndicatorVisible: true
model: fileSystemModel
rootIndex: rootPathIndex
selection: sel
selectionMode: 2
TableViewColumn {
id: namecolumn
title: "Name"
role: "fileName"
resizable: true
width: parent.width-sizeWidth-dateWidth-scrollBarWidth
delegate: ItemDelegate {
id: fileCheckDelegate
Row{CheckBox{
id: cbox
y: -4
}
Text{text: model.fileName
width: namecolumn.width-x-cbox.width
elide: Text.ElideRight
}
}
ToolTip {
parent: fileCheckDelegate
visible: hovered
delay: 1000
text: qsTr(model.fileName)
}
}
}
}
Everything is displayed correctly, but in the terminal I get many of the following messages:
qrc:/FileSystem.qml:49: TypeError: Cannot read property 'fileName' of null
qrc:/FileSystem.qml:57: TypeError: Cannot read property 'fileName' of null
The locations are in my delegate, once in Text text: model.fileName and once in ToolTip text: qsTr(model.fileName). As I said, everything is displayed correctly but I am worried that this error might still give me problems. What am I doing wrong?
Edit: A workaround seems to be if I use styleData.value instead of model.fileName. Still, I do not understand why I cannot write model.fileName