QML XML list view not working - c++

I'm new to QML. I cannot get these code working.
Model.qml
import QtQuick 1.1
XmlListModel {
source: "./test.xml"
query: "/tag1/tag2"
onSourceChanged: {
console.log("source changed:" + source)
reload()
}
XmlRole { name: "id"; query: "id/string()" }
XmlRole { name: "name"; query: "name/string()" }
}
View.qml
import QtQuick 1.1
ListView {
width: 200
}
TheDelegate.qml
import QtQuick 1.1
Rectangle {
width: parent.width
height: 20
Text {
text: id + ": " + name
}
}
Main.qml
import QtQuick 1.1
Item {
id: container
Model {
id: resultModel
objectName: "resultModel"
}
View {
id: resultView
model: resultModel
delegate: TheDelegate {}
}
}
And in my main.cpp:
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QDeclarativeView view;
view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
view.setSource(QUrl::fromLocalFile("./TheMain.qml"));
view.show();
int rtnVal = app.exec();
return rtnVal;
}
When i run the project, it just shows nothing, no window displayed.
Thanks in advance.
EDIT:
I use the qmlviewer(4.8.4) to debug my qmls, and i get the warning:
TheDelegate.qml:18: ReferenceError: Can't find variable: name
But I have to name defined in the XmlRole.

You need to set Height as well for listview.
ListView {
width: 200
height: parent.height;
}

Related

How can I customize the child items in a TreeView of QML?

QML:
import QtQuick 2.2
import QtQuick.Controls 1.5
import QtQml.Models 2.2
import filesystem_browser 1.0
ApplicationWindow
{
visible: true
width: 640
height: 480
ItemSelectionModel
{
id: sel
// This model is comming from C++' class DisplayFileSystemModel.
model: treeViewModel
}
TreeView {
id: view
anchors.fill: parent
anchors.margins: 2 * 12
model: treeViewModel
rootIndex: root
selection: sel
TableViewColumn
{
title: "Name"
role: "display"
resizable: true
}
itemDelegate:
Rectangle
{
id: dd
color: "pink"
height: 20
Rectangle
{
height: 20; width: 40; color: "green"; anchors.right: parent.right
border.width: 1
}
border.width: 1
Text
{
anchors.verticalCenter: parent.verticalCenter
text: styleData.value
}
}
}
}
C++
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
QStandardItemModel model;
QStandardItem *item1 = new QStandardItem("File");
item1->appendRows({new QStandardItem("New"),
new QStandardItem("Open"),
new QStandardItem("Open Recent"),
new QStandardItem("Close"),
new QStandardItem("Save..."),
new QStandardItem("Save As..."),
new QStandardItem("Import Audio File..."),
new QStandardItem("Print")
});
QStandardItem *item3 = new QStandardItem("Edit");
item3->appendRows({new QStandardItem("Undo"),
new QStandardItem("Redo"),
new QStandardItem("Cut"),
new QStandardItem("Copy"),
new QStandardItem("Paste"),
new QStandardItem("Delete"),
new QStandardItem("Select All")
});
model.appendRow(item1);
model.appendRow(item3);
qmlRegisterUncreatableType<DisplayFileSystemModel>("filesystem_browser", 1, 0,
"FileSystemModel", "Cannot create");
engine.rootContext()->setContextProperty("treeViewModel", &model);
engine.rootContext()->setContextProperty("root", model.indexFromItem(model.invisibleRootItem()));
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
This results in:
I want to customize the child items and the parent item individually.
For example:
File //Parent item
New.. // Child item
Save.. // Child item
This current code puts the same customisation on the parent as well as the children.
My previous comment about using the row or column value was close, but incorrect. A quick look at the docs shows us that there is another property that gives us the depth of an item. So I think you can achieve what you want by simply doing something like this:
color: styleData.depth ? "blue" : "pink"

QML Treeview: How to get QModelIndex of childs

I have a QML TreeView with a QStandardItemModel and use a ItemSelectionModel to manage the selection. The ItemSelectionModel wants a QModelIndex for its select function. How can I obtain the QModelIndex of children in my view?
The tree looks like this:
file 1
task 1
task 2
file 2
task 1
I want to select task2 when I click on it (I can have a MouseArea in the delegate) (so that the TreeView highlights it), and in order to do this, I must call ItemSelectionModel.select with the QModelIndex of task 2. But I don'
t know how I can get the QModelIndex of task2.
QStandardItemModel is derived from QAbstractItemModel and therefore provides an index function:
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const
but to use this function I need to know the index of the parent. How can I get it from the view?
To obtain the child you must first have the parent, so in the case of your scheme you must obtain "file1" and for this you must obtain his parent, and this parent is the rootIndex of the TreeView, so the sequence is: rootIndex -> file1 -> task1.
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QStandardItemModel>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStandardItemModel model;
QStandardItem *item1 = new QStandardItem("file1");
item1->appendRows({new QStandardItem("task1"), new QStandardItem("task2")});
QStandardItem *item2 = new QStandardItem("file2");
item2->appendRows({new QStandardItem("task1")});
model.appendRow(item1);
model.appendRow(item2);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("tree_model", &model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.Models 2.11
Window {
visible: true
width: 640
height: 480
TreeView {
id: treeView
anchors.fill: parent
model: tree_model
selectionMode: SelectionMode.MultiSelection
selection: ItemSelectionModel {
id: ism
model: tree_model
}
TableViewColumn {
title: "Name"
role: "display"
width: 300
}
Component.onCompleted: {
expandAll()
var ix1 = tree_model.index(0, 0, treeView.rootIndex)
var ix = tree_model.index(0, 0, ix1)
ism.select(ix, ItemSelectionModel.Select)
}
}
// https://forum.qt.io/topic/75395/qml-treeview-expand-method-not-working
function expandAll() {
for(var i=0; i < tree_model.rowCount(); i++) {
var index = tree_model.index(i,0)
if(!treeView.isExpanded(index)) {
treeView.expand(index)
}
}
}
}
Update:
To get the index of the item pressed you must use styleData.index:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.Models 2.11
Window {
visible: true
width: 640
height: 480
TreeView {
id: treeView
anchors.fill: parent
model: tree_model
selectionMode: SelectionMode.MultiSelection
selection: ItemSelectionModel {
id: ism
model: tree_model
}
TableViewColumn {
title: "Name"
role: "display"
width: 300
}
itemDelegate: Item {
Text {
anchors.verticalCenter: parent.verticalCenter
color: styleData.textColor
elide: styleData.elideMode
text: styleData.value
}
MouseArea{
anchors.fill: parent
onClicked: {
var ix = tree_model.index(0, 0, styleData.index)
ism.select(ix, ItemSelectionModel.Select)
}
}
}
}
}

Mapping MapPolyline on the map QML. C++/Qt

On the instructions I should to display map on the screen and draw on it the line. Try to do this:
main.cpp
#include <QGeoPath>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
class PathController: public QObject{
Q_OBJECT
Q_PROPERTY(QGeoPath geopath READ geoPath WRITE setGeoPath NOTIFY geopathChanged)
public:
PathController(QObject *parent = 0) : QObject(parent) {}
QGeoPath geoPath() const {
return mGeoPath;
}
void setGeoPath(const QGeoPath &geoPath) {
if(geoPath != mGeoPath) {
mGeoPath = geoPath;
emit geopathChanged();
}
}
signals:
void geopathChanged();
private:
QGeoPath mGeoPath;
};
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QGeoPath path;
path.addCoordinate(QGeoCoordinate(55.006355, 92.860984));
path.addCoordinate(QGeoCoordinate(55.1, 93));
path.addCoordinate(QGeoCoordinate(56.1, 92.777));
PathController controller;
controller.setGeoPath(path);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("pathController", &controller);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
main.qml
import QtLocation 5.6
import QtPositioning 5.6
Window {
visible: true
width: 640
height: 480
Plugin {
id: osmMapPlugin
name: "osm"
}
Map {
anchors.fill: parent
plugin: osmMapPlugin
center: QtPositioning.coordinate(56.006355, 92.860984)
zoomLevel: 10
MapPolyline {
id: pl
line.width: 3
line.color: 'red'
}
}
Connections{
target: pathController
onGeopathChanged: {
var lines = []
for(var i=0; i < pathController.geopath.size(); i++){
lines[i] = pathController.geopath.coordinateAt(i)
}
pl.path = lines
}
}
}
However, get a blank map. The lines do not appear. Question - how to render lines? They do exist, just like "invisible".
Should be a great triangle
And if you call printf("%s" controller.geoPath().toString().toUtf8().constData()); after assignment - you will see exactly what I entered. But the map is empty for some reason. Help, please.
The error is caused because when a new QGeoPath is established through setGeoPath, it issues the signal to update but at that moment the .qml is not started so the connection is not made so onGeopathChanged is not called in qml since after the first change it never changed back.
A possible solution is to use Component.onCompleted so that it notifies next to onGeopathChanged that there is a change as I show in the following code:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtLocation 5.6
import QtPositioning 5.6
Window {
visible: true
width: 640
height: 480
Plugin {
id: osmMapPlugin
name: "osm"
}
Map {
anchors.fill: parent
plugin: osmMapPlugin
center: QtPositioning.coordinate(56.006355, 92.860984)
zoomLevel: 10
MapPolyline {
id: pl
line.width: 10
line.color: 'red'
}
}
function loadPath(){
var lines = []
for(var i=0; i < pathController.geopath.size(); i++){
lines[i] = pathController.geopath.coordinateAt(i)
}
return lines;
}
Connections{
target: pathController
onGeopathChanged: pl.path = loadPath()
}
Component.onCompleted: pl.path = loadPath()
}

Access to existing QML component from C++

I am a newbie in QML, and cannot resolve a simple issue. I want to get access to the QML components from C++, but I cannot.
The pointer test is always 0. What can be the reason?
The code is the following:
main.cpp
int main(int argc, char *argv[])
{
QGuiApplication &app=reg6::Bonder::BonderGuiApplication::instance();
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject* test=engine.rootObjects().first()->findChild<QObject*> ("cameraArea");
test->setProperty("color","black");
return app.exec();
}
main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 1800
height: 900
SplitView
{
anchors.fill: parent
orientation: Qt.Vertical
SplitView {
Layout.fillHeight: true
SplitView {
orientation: Qt.Vertical
width:400
Layout.minimumWidth: 400
Layout.maximumWidth: 500
Camera {
id: cameraArea
height: 400
Layout.maximumHeight: 400
Layout.minimumHeight: 300
}
List {
id: listArea
}
}
Bonder {
id: mainArea
Layout.fillWidth: true
}
Properties {
id: propertiesArea
Layout.minimumWidth: 300
Layout.maximumWidth: 400
}
}
Error {
id: errorArea
Layout.minimumHeight: 100
height: 200
}
}
}
Camera.qml
import QtQuick 2.5
Rectangle {
color: "lightblue"
}
You have to set the objectName property also of the QML component to get a valid pointer to your QObject because T QObject::findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const needs the objectName not the ID

Accesing QML element from C++ code in QT

I am trying to use QML with C++ in QT, but for now unsuccessfully. I cannot access my QML element from the C++ code using rootObjects() function. What am I doing wrong?
qml part:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
ApplicationWindow {
id: window
visible: true
width: 640
height: 520
title: qsTr("My app")
Item {
anchors.fill: parent
Rectangle {
id: rectangle1
x: 0
y: 0
width: 640
height: 370
color: "#ffffff"
}
Button {
id: startButton
x: 325
y: 425
text: qsTr("Start")
}
}
}
C++ Part:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
QObject *rootObject = engine.rootObjects().first();
qDebug() << rootObject->objectName();//prints ""
QObject *qmlObject = rootObject->findChild<QObject*>("window");// or "startButton"
//qDebug() << qmlObject->objectName(); //app fails, because window was not found
QList<QObject *> allQObjects = rootObject->findChildren<QObject *>();
for(int i=0;i< allQObjects.length();++i)
{
qDebug() << allQObjects[i]->objectName(); //prints everytime ""
}
qDebug() << "len: " << allPQObjects.length(); //prints 132
return app.exec();
}
At first: If you do not set a object name there will be no!
QML:
Rectangle { id : frame; objectName : "objFrame" color : "blue" }
Qt:
QObject *pRootObject = m_pQmlView->rootObject();
QObject *pobjFrame = m_pRootObject->findChild<QObject *>("objFrame");
The other way arround:
Qt:
m_pQmlView->rootContext()->setContextProperty( "_view", this );
QML:
Component.onCompleted: {
/********************** Connections ***************************/
// connect signal MyView::retranslate() with slot retranslate
_view.retranslate.connect(retranslate)
}
Need to add objectname to QML
ApplicationWindow {
id: window
objectName: "window"
...
}