display text in tableviewcolumn in treeView QtQuick controls 1.4 - qml

Im trying to create a simple treeView appeared in Qt 5.5 , the problem is that the text in items of the tree doesn't display, despite the model is full.
There is my code :
TreeViewPM.qml
Qt Code:
Switch view
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQml.Models 2.2
import KMTreeModelPM 1.0
Item {
KMTreeModelPM {
id: treeModel
}
ItemSelectionModel {
id: sel
model: treeModel
}
Text {
id:txt
text: " "
}
TreeView {
id: view
anchors.fill: parent
anchors.margins: 12
selection: sel
headerVisible : false
itemDelegate: Rectangle {
color: ( styleData.row % 2 == 0 ) ? "white" : "lightblue"
height: 20
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left // by default x is set to 0 so this had no effect
text: styleData.value
}
}
TableViewColumn {
id : title
title: "Title"
role: "title"
resizable: true
horizontalAlignment : Text.AlignLeft
}
model: treeModel
onDoubleClicked: txt.text = treeModel.data(index,0)
}
}
To copy to clipboard, switch view to plain text mode
main.qml
Qt Code:
Switch view
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQml.Models 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
Rectangle {
width: 785
TabView {
x: 17
y: 8
width: 970
height: 800
currentIndex: 2
visible: true
Tab {
id: tabAddProfile
title: qsTr("Add Profile")
AddProfilePage{}
}
Tab {
id: tabAddTypeSubType
title: qsTr("Add Type/SubType")
AddTypeSubTypePage{}
}
Tab {
id: tabAddDetail
height: 413
visible: true
title: qsTr("Add Detail")
TreeViewPM {}
}
}
}

It's probably your model. It's hard to know when we don't have access to it.
The following works:
#include <QGuiApplication>
#include <QtQml>
#include <QDebug>
#include <QtGui>
static void initStandardTreeModel(QStandardItemModel *model)
{
QStandardItem *item;
item = new QStandardItem(QLatin1String("Row 1 Item"));
model->insertRow(0, item);
item = new QStandardItem(QLatin1String("Row 2 Item"));
item->setCheckable(true);
model->insertRow(1, item);
QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
item->setChild(0, childItem);
item = new QStandardItem(QLatin1String("Row 3 Item"));
item->setIcon(QIcon());
model->insertRow(2, item);
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QStandardItemModel* model = new QStandardItemModel();
initStandardTreeModel(model);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("theModel", model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.qml:
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
width: 800
height: 400
visible: true
TreeView {
id: view
anchors.fill: parent
anchors.margins: 12
TableViewColumn {
id : title
title: "Title"
role: "display"
}
model: theModel
}
}

Related

Storing a user's code in a combo box that calls out for its name when selected

I want to make two input text fields (let's call them X and Y) that are in page A,
X: code of the person, Y: name of the person,
Page A contains two text fields for input, and a combo box for selection (for delete purpose), an adding button, and a delete button,
Once the X and Y are filled in the text fields they are inputed using an 'add' button, I want them to be stored when the button is pressed so I can call them back in the page B, or in the combo box in page A,
Page B contains a combo box and a casual text output next to it, the X goes to the combo box, and the Y goes to the text that both are in page B
When I select in page B one X of the many X that already have been inputed, I want the text to change with what have been selected accordingly,
if I want to delete one of the X, I do so by selecting the combobox that exists in Page A and proceed pressing the delete button,
how to store both the X and Y in variables and insert them in comboboxes and the texts, and make a bond between them, connecting each name with its own code ?
PageA
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.VirtualKeyboard 2.14
Item {
id:pageA
width: 1920
height: 1080
property alias codeIn: code.text
property alias nameIn: name.text
TextField{
id:code
y: 0
width: 200
height: 50
placeholderText: qsTr("Type the code here")
}
TextField{
id:name
x: 0
y: 65
width: 200
height: 50
placeholderText: qsTr("Type the name here")
}
ComboBox{
id:selectionForDelete
x: 320
y: 65
width: 200
height: 50
}
Button{
id:adding
x: 29
y:155
text: "add"
onClicked: {
code.clear()
name.clear()
}
}
Button{
id:deleting
x: 355
y: 155
text: "delete"
}
}
PageB
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.VirtualKeyboard 2.14
Item {
id:pageB
width: 1920
height: 1080
ComboBox{
id:codeList
}
Text {
id: relatedName
y:70
text: qsTr("")
}
}
One very simple solution is to declare a ListModel in your main app and when you instantiate either PageA or PageB they will have read/write access to the ListModel.
//MainApp.qml
Page {
ListModel { id: listModel }
PageA { }
PageB { }
}
//PageA.qml
Page {
}
//PageB.qml
Page {
}
As an example, PageA gives the ability to add new users as well as delete existing users, whereas PageB gives the ability to search for existing users:
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page {
RowLayout {
anchors.fill: parent
PageA {
Layout.fillWidth: true
Layout.preferredWidth: 200
Layout.fillHeight: true
}
PageB {
Layout.fillWidth: true
Layout.preferredWidth: 200
Layout.fillHeight: true
}
}
ListModel {
id: listModel
function appendUser(code, name) { append( { code, name } ); }
}
}
//PageA.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page {
ColumnLayout {
anchors.fill: parent
Frame {
Layout.fillWidth: true
Text { text: qsTr("PageA") }
}
Label { text: qsTr("Users") }
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: listModel
delegate: Frame {
width: ListView.view.width
RowLayout {
width: parent.width
Text {
Layout.fillWidth: true
text: model.code + " " + model.name
}
Button {
text: qsTr("Delete")
onClicked: listModel.remove(model.index)
}
}
}
}
Label { text: qsTr("Create new user") }
TextField {
id: code
Layout.fillWidth: true
placeholderText: qsTr("Code")
}
TextField {
id: name
Layout.fillWidth: true
placeholderText: qsTr("Text")
}
Button {
enabled: code.text && name.text
text: qsTr("Add")
onClicked: listModel.appendUser(code.text, name.text)
}
}
}
//PageB.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page {
ColumnLayout {
anchors.fill: parent
Frame {
Layout.fillWidth: true
Text { text: qsTr("PageB") }
}
Label { text: qsTr("Select Code") }
ComboBox {
id: comboBox
model: listModel
textRole: "code"
valueRole: "name"
}
Label { text: qsTr("Selected Name") }
Text {
text: comboBox.currentValue ?? ""
}
Item {
Layout.fillHeight: true
}
}
}
You can Try it Online!

How can I make a custom delegate for my ListView?

I'm trying to make a custom ListView (AppDataListView) that can be used for data manipulation (essentially having a bunch of inputs). The problem I'm having is finding a way to tell AppDataListView what input types to use in the delegate of the ListView.
I currently try and do this by creating a loader in the ListView delegate, setting its source to a property of type Component, and then when I create an instance of AppDataListView, I specify the Component... However, I don't have any access to the model data, so it's kind of pointless.
Does anyone know how I can accomplish this?
Main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick .Controls 2.12
import QtQuick.Layouts 1.12
Window {
width: 640
height: 480
visible: true
ListModel {
id: sampleData
ListElement {
itemId: 1
name: "Name1"
}
ListElement {
itemId: 2
name: "Name2"
}
ListElement {
itemId: 3
name: "Name3"
}
ListElement {
itemId: 4
name: "Name4"
}
}
AppDataListView {
anchors.fill: parent
headers: ["ID", "Name"]
model: sampleData
delegate: Component {
RowLayout {
anchors.fill: parent
TextArea {
// I can't access itemId from here even though this is loaded into the delegate.
text: itemId
}
TextArea {
// I can't access name from here even though this is loaded into the delegate.
text: name
}
}
}
}
}
AppDataListView.qml
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Rectangle {
property var headers: []
property alias model: listView.model
property alias listView: listView
required property Component delegate;
id: root
color: "#bdbdbd"
ColumnLayout {
anchors.fill: parent
anchors.margins: 1
spacing:0
RowLayout {
spacing: 1
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Item {
Layout.minimumWidth: 30
Layout.maximumWidth: 30
}
Repeater {
id: headerRepeater
model: headers
delegate: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
gradient: Gradient {
GradientStop { position: 0.0; color: "#FFFFFF" }
GradientStop { position: 0.5; color: "#F1F1F1" }
GradientStop { position: 1.0; color: "#FFFFFF" }
}
Label {
text: modelData
padding: 5
anchors.centerIn: parent
}
}
}
}
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
interactive: true
clip: true
boundsBehavior: Flickable.StopAtBounds
spacing: 1
ScrollBar.vertical: ScrollBar {
active: true
policy: ScrollBar.AlwaysOn
}
delegate: RowLayout {
width: parent.width
spacing: 1
Button {
id: rowBtn
Layout.minimumWidth: 30
Layout.maximumWidth: 30
background: Rectangle {
gradient: Gradient {
GradientStop { position: 0.0; color: (rowBtn.down ? "#56aff5" : rowBtn.hovered ? "#d9ebf9" : "#FFFFFF") }
GradientStop { position: 0.5; color: (rowBtn.down ? "#1b93f1" : rowBtn.hovered ? "#a4b2bd" : "#F1F1F1") }
GradientStop { position: 1.0; color: (rowBtn.down ? "#56aff5" : rowBtn.hovered ? "#d9ebf9" : "#FFFFFF") }
}
}
}
Loader {
sourceComponent: root.delegate
}
}
}
}
}
Capturing #Amfasis excellent comments to the question and adding some more detail....
Change your Loader reference to this:
Loader {
sourceComponent: root.delegate
property int itemId: model.itemId
property string name: model.name
}
fixes it. Here's why....
A Component declaration is put into the QML namespace hierarchy where it is declared not where it is instantiated at runtime. In other words, by declaring the delegate within main.qml, it can only see that namespace regardless of where it is instantiated at (in this case in AppDataListView).
More info here:
https://doc.qt.io/qt-5/qml-qtqml-component.html#creation-context
As #Amfasis pointed out, the workaround in this case is to declare properties on the Loader to pass in the model references you need. In this case the Loader acts as a bridge of sorts from the ListView namespace over to the delegate Component's namespace in main.qml.
More info on that here:
https://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within-a-view-delegate

How to show/hide KDE plasmoid's tooltip programatically?

Is there a way to make a plasmoid tooltip to show/hide programatically?
I tried by setting a ToolTipArea over the compact representation, and trying to trigger it with a Timer - it does not work (the regular tooltip keeps showing but only when hovering the plasmoid icon (aka compactRepresentation):
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
Layout.preferredWidth: 200
Layout.preferredHeight: 300
Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
Plasmoid.compactRepresentation: Item
{
anchors.fill: parent
MouseArea
{
onClicked:
{
plasmoid.expanded = !plasmoid.expanded
}
}
PlasmaCore.ToolTipArea
{
id: toolTip
width: parent.width
height: parent.height
anchors.fill: parent
mainItem: tooltipContentItem
active: false
interactive: true
}
Timer
{
interval: 3000
running: true
repeat: true
onTriggered:
{
if (tooltipContentItem.active == false)
{
toolTip.showToolTip()
toolTip.active == true
}
else
{
toolTip.hideToolTip()
toolTip.active == false
}
}
}
}
Item
{
id: tooltipContentItem
implicitWidth: 300
implicitHeight: 200
ColumnLayout
{
id: mainLayout
anchors
{
left: parent.left
top: parent.top
margins: PlasmaCore.Units.gridUnit / 2
}
PlasmaExtras.Heading
{
id: tooltipMaintext
level: 3
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
elide: Text.ElideRight
text: "Test"
}
PlasmaComponents.Label
{
id: tooltipSubtext
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
text: "Testing text"
opacity: 0.6
}
}
}
}
There's the toolTipItem QQuickItem too, but I cannot figure out if it is possible to make it show or hide on command (this bit was borrowed from KDE's digitalclock plasmoid:
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
Layout.preferredWidth: 200
Layout.preferredHeight: 300
Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
Plasmoid.compactRepresentation: Item
{
anchors.fill: parent
MouseArea
{
onClicked:
{
plasmoid.expanded = !plasmoid.expanded
}
}
}
plasmoid.toolTipItem: Loader
{
id: toolTipLoader
source: "Tooltip.qml" // Just holds the tooltip contents
}
}

Unable to assign [undefined] to QString

I am new to QML so kindly help me out as why QML throws error when trying to build this one
import QtQuick
import QtQuick.Window
import QtQuick.Controls 2.4
Window {
width: 640
height: 480
visible: true
title: qsTr("App title")
ListModel {
id: modelName
ListElement { name: "alpha" }
ListElement { name: "beeta" }
ListElement { name: "gamma" }
}
Component {
id: delegateName
Text {
text: modelName.name // QML throw error here
font.pixelSize: 32
}
}
ListView {
anchors.fill: parent
model: modelName
delegate: delegateName
clip: true
}
}
I'm building this using QT-Creator. Any help would be appreciated
In a delegate, try this one: text: model.name. Every delegate has its own model property with accordingly model's data

Changing model doesn't affect ComboBox

Suppose, we have the following code:
import QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Window {
id: win
width: 800
height: 600
ListModel {
id: listModel
ListElement { name: "element1" }
ListElement { name: "element2" }
ListElement { name: "element3" }
}
ColumnLayout {
anchors.centerIn: parent
width: 200
height: 200
ComboBox {
model: listModel
currentIndex: 1
Layout.fillWidth: true
}
ListView {
model: listModel
delegate: Text {
text: name
}
Layout.fillHeight: true
Layout.fillWidth: true
}
Button {
text: "Change model"
onClicked: {
listModel.get(1).name = "changed text";
//listModel.setProperty(1,"name","changed text"); this line not works too
}
}
}
}
So clicking the button have to change model's element with index 1. But changing the model affects only ListView. The ComboBox remains unchanged.
Why that happens? Is it bug or feature? Is there a way to update ComboBox after changing its model?
I had a similar problem, I used a workaround. In onClicked function of button, create copy of model, change it as you want and then assign it again to ListViews model:
ListView {
id: listView
...
}
Button {
onClicked: {
var copy = listView.model;
copy.get(1).name = "changed text";
listView.model = copy; }
}
}