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"
Related
I am creating a Table using the new qml tableview (Qt 5.12).
I am able to create a model in C++ and able to populate the model in tabular format along with scrollbar.How do I add column headers to this table?
Code:
import QtQuick 2.12
import QtQuick.Controls 2.5
import Qt.labs.qmlmodels 1.0
//import QtQuick.Controls.Styles 1.4
import TableModel 0.1
Rectangle {
id:table
border.width: 3
border.color: 'dark blue'
QtObject{
id:internals
property int rows:0
property int col:0
property int colwidth:0
property var columnName:[]
}
function setRows(num){ internals.rows = num}
function setCols(num){ internals.col = num}
function setColWidth(num){internals.colwidth = num}
function setColNames(stringlist){
if(stringlist.length > 1)
internals.col = stringlist.length
dataModel.setColumnName(stringlist);
}
function addRowData(stringlist){
var len = stringlist.length
if(len >0)
{
dataModel.addData(stringlist)
}
}
TableModel {
id:dataModel
}
TableView{
id:tbl
anchors.top: headerCell
anchors.fill: parent
//columnSpacing: 1
//rowSpacing: 1
clip: true
ScrollBar.horizontal: ScrollBar{}
ScrollBar.vertical: ScrollBar{}
model:dataModel
Component{
id:datacell
Rectangle {
implicitWidth: 100
implicitHeight: 20
color: 'white'
border.width: 1
border.color: 'dark grey'
Text {
id:txtbox
anchors.fill: parent
wrapMode: Text.NoWrap
clip: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: display
}
}
}
}
function init(){
console.log("Calling init")
tbl.delegate= datacell
}
}
Currently TableView does not have headers so you should create it, in this case use Row, Column and Repeater.
On the other hand you must implement the headerData method and you must do it Q_INVOKABLE.
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
// ...
Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// ...
TableView {
id: tableView
model: table_model
// ...
Row {
id: columnsHeader
y: tableView.contentY
z: 2
Repeater {
model: tableView.columns > 0 ? tableView.columns : 1
Label {
width: tableView.columnWidthProvider(modelData)
height: 35
text: table_model.headerData(modelData, Qt.Horizontal)
color: '#aaaaaa'
font.pixelSize: 15
padding: 10
verticalAlignment: Text.AlignVCenter
background: Rectangle { color: "#333333" }
}
}
}
Column {
id: rowsHeader
x: tableView.contentX
z: 2
Repeater {
model: tableView.rows > 0 ? tableView.rows : 1
Label {
width: 60
height: tableView.rowHeightProvider(modelData)
text: table_model.headerData(modelData, Qt.Vertical)
color: '#aaaaaa'
font.pixelSize: 15
padding: 10
verticalAlignment: Text.AlignVCenter
background: Rectangle { color: "#333333" }
}
}
}
The complete example you find here.
If you're using Qt 5.15, you can use a HorizontalHeaderView for column labels.
https://doc.qt.io/qt-5/qml-qtquick-controls2-horizontalheaderview.html
There's also VerticalHeaderView for row labeling.
https://doc.qt.io/qt-5/qml-qtquick-controls2-verticalheaderview.html
I'm new to the QML. I came to the answer of eyllanesc so many times through my struggle with the new TableView (qt 5.12+), so I wanna thank you and share what helped me even more.
It's this video:
Shawn Rutledge - TableView and DelegateChooser: new in Qt 5.12
part of Qt Virtual Tech Summit 2019
The discussed code
It's a bit long but he covers
the differences between old and new TableView
how to create universal model for the views
resizable headers
different representation per column type - DelegateChooser
sortable columns
column reorder
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)
}
}
}
}
}
I am trying to populate a QML ListView using a class that inherits QAbstractListModel. So far, I managed to create this using the QT Documentation here, under the "QAbstractItemModel subclass" section:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "gamemodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
GameModel model; //A class similar to AnimalModel in Qt Documentation.
//It contains a QList of Objects, each having 2 QString
//members (title and genre).
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
model.readFile("c:/somePath/XML_G.xml"); //Initializing GameModel QList member
//using an XML file
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("myModel", &model);
return app.exec();
}
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
Window
{
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ListView
{
id: myList
width: parent.width
height: 50
clip: true
spacing: 5
orientation: ListView.Horizontal
model: myModel
delegate:
Rectangle
{
width: 150
height: 20
color: "#2255ff"
Text
{
text: gameTitle + " " + genre
}
}
}
}
Up to this point, my code works. However, if I try to change my main.qml file like this:
import QtQuick 2.5
import QtQuick.Window 2.2
Window
{
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item //ListView is now nested in this Item
{
ListView
{
id: myList
width: parent.width
height: 50
clip: true
spacing: 5
orientation: ListView.Horizontal
model: myModel
delegate:
Rectangle
{
width: 150
height: 20
color: "#2255ff"
Text
{
text: gameTitle + " " + genre
}
}
}
}
}
I end up being unable to set my model using ctxt->setContextProperty("myModel", &model);. From what little I can gather from the Qt Documentation (although I am most likely wrong), QQmlContext acts like a scope for the QML file. Thinking that, I tried changing this:
QQmlContext *ctxt = engine.rootContext();
to this:
QQmlContext *ctxt = engine.rootContext()->findChild<QQmlContext*>("list");
As well as setting my Item's objectName property to "list". Obviously, that failed, and it also caused a crash. Since my experience with QML is limited to the Qt Docs, I have been unsuccessful at finding a workaround. Is a solution using QQmlContext possible, or do I have to use QObject? If so, what would the QObject equivalent of ctxt->setContextProperty("myModel", &model) be?
The first argument of the setContextProperty() call is basically the "identifier" of the object, like the id property on the QML side.
You need to set that before accessing it in QML, otherwise it is unknown at the time of usage.
So you don't need any other call, but you need to do it before you load QML that needs it.
Just move it before the engine.load(...) line in your main.cpp
OK, apparently my problem was in my QML file. In my code, I setup my ListView like this:
width: parent.width
However, when I added an Item as the parent of my ListView, I forgot to set an initial width for my Item, thus turning ListView's width to 0. After I set an initial width for my Item, everything works as expected again.
I want to create tab with ListView from C++. Part of adding tab is done :D I want to have one model per ListView and be able to control model from C++ side.
So far I have done this:
C++ part:
SmsModel *model = new SmsModel();
model->createDummyData(phoneNumber);
QObject* tab = findTab(phoneNumber);
if (tab == nullptr)
{
QObject* pRoot = mAppEngine->rootObjects()[0];
QObject* m_pTabView= pRoot->findChildren<QObject*>("conversationTabView").first();
if (m_pTabView)
{
QVariant returnedValue;
QVariant title = phoneNumber;
QQmlContext *context = new QQmlContext(mAppEngine, mAppEngine);
context->setContextProperty(QString("myModel"), model);
QQmlComponent *component = new QQmlComponent(mAppEngine, QUrl("qrc:/ChatView.qml"), this);
QObject *object = component->create(context);
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
QObject *p = object->findChild<QObject*>("chatView");
p->setProperty("model", context->contextProperty("myModel"));
qDebug() << p->property("model");
object->setProperty("active", QVariant(true));
component->setParent(m_pTabView);
QMetaObject::invokeMethod(m_pTabView, "addTab",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, title),
Q_ARG(QVariant, QVariant::fromValue(component)));
object->setProperty("anchors.fill", "parent");
}
QML part:
import QtQuick 2.5
import QtQml.Models 2.2
import QtQuick.Window 2.2
import org.example 1.0
Rectangle {
color: "#E0E0E0"
ListView {
objectName: "chatView"
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
clip: true
model: myModel
delegate: bubbleDelegate
Component {
id: bubbleDelegate
Rectangle {
implicitWidth: messageText.implicitWidth + 2*messageText.anchors.margins
implicitHeight: messageText.implicitHeight + 2*messageText.anchors.margins
anchors.left: model.received ? parent.left : undefined
anchors.right: model.received ? undefined : parent.right
anchors.margins: 5
id: bubble
smooth: true
radius: 10
color: model.received ? "#673AB7" : "#E040FB"
Text {
id: messageText
anchors.fill: parent
anchors.margins: 5
text: model.message
wrapMode: Text.WordWrap;
horizontalAlignment: model.received ? Text.AlignLeft : Text.AlignRight
color: "white"
}
}
}
}
}
When I run my application, there is no data in GUI and I have following error
ReferenceError: myModel is not defined.
Thank you for every response.
In order to use a C++ object as a list model you must have a class that inherits from QAbstractListModel. Take a look at the example here.
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;
}