Tag Archives: QML

Export QList to QML vol. 2

The most complex and ellegant way to export QList of custom objects to QML is to subclass one of the Qt abstract models ( QAbstractItemModel, or easier QAbstractListModel, QAbstractTableModel ) and build up a whole model with user specified roles. Subclassing QAbstractItemModel allows you to define all the properties and behaviour of your model, however in this case it is enough to subclass QAbstractListModel. In that case we have to provide implementations of only a few pure virtual methods plus some methods to manipulate models content.
Following implementation will show how to subclass QAbstractListModel with a class providing custom roles which will be used for text, its color and image source path. The good point is that they are defined as QVariants so it doesn’t matter if you pass a color, number or text. Expected result is similar to the one in a previous example.

Lets start with defining a list model item. Methods necessary to define fine read/write item are Getter, Setter and a method returning QHash binding role with member name description. Following example should explain this more clearly.
Base class definition:
listitemapi.h

#ifndef LISTITEMAPI_H
#define LISTITEMAPI_H

#include <QObject>
class ListItemAPI : public QObject
{
	Q_OBJECT
public:
	ListItemAPI( QObject* a_pParent = 0 )
		: QObject( a_pParent )
	{}
	virtual ~ListItemAPI() {}

	virtual QVariant GetData( int a_iRole ) const = 0;
	virtual void SetData( int a_iRole, QVariant a_variantData ) = 0;
	virtual QHash<int, QByteArray> RoleNames() const = 0;
};
#endif // LISTITEMAPI_H

Real item class implementation:
mylistitem.h

#ifndef MYLISTITEM_H
#define MYLISTITEM_H

#include <QVariant>
#include <QColor>
#include <QHash>
#include "listitemapi.h"
class MyListItem : public ListItemAPI
{
	Q_OBJECT
public:
	enum ERoles
	{ ROLE_1					= Qt::UserRole + 1
	, ROLE_2					= Qt::UserRole + 2
	, ROLE_3					= Qt::UserRole + 3
	, ROLE_4					= Qt::UserRole + 4
	, ROLE_5					= Qt::UserRole + 5
	};
	explicit MyListItem( QObject* a_pParent = 0 );
	MyListItem( const MyListItem& a_rOther );
	virtual ~MyListItem();

	virtual QVariant GetData( int a_iRole ) const;
	virtual void SetData( int a_iRole, QVariant a_variantData );
	virtual QHash<int, QByteArray> RoleNames() const;

private:
	void SetInitialValues();
	QHash<ERoles, QVariant> m_aDataHash;
};
#endif // MYLISTITEM_H

mylistitem.cpp

#include "mylistitem.h"
MyListItem::MyListItem( QObject* a_pParent )
	: ListItemAPI( a_pParent )
{
	SetInitialValues();
}

MyListItem::MyListItem( const MyListItem& a_rOther )
	: ListItemAPI( a_rOther.parent() )
{
	m_aDataHash = a_rOther.m_aDataHash;
}

MyListItem::~MyListItem()
{
}

QVariant MyListItem::GetData( int a_iRole ) const
{
	return m_aDataHash[static_cast<ERoles>( a_iRole )];
}

void MyListItem::SetData( int a_iRole, QVariant a_variantData )
{
	m_aDataHash[static_cast<ERoles>( a_iRole )] = a_variantData;
}

QHash<int, QByteArray> MyListItem::RoleNames() const
{
	QHash<int, QByteArray> aRoleNames;
	aRoleNames[ROLE_1]			= "m_role1";
	aRoleNames[ROLE_2]			= "m_role2";
	aRoleNames[ROLE_3]			= "m_role3";
	aRoleNames[ROLE_4]			= "m_role4";
	aRoleNames[ROLE_5]			= "m_role5";
	return aRoleNames;
}

void MyListItem::SetInitialValues()
{
	m_aDataHash[ROLE_1] = QVariant( "string" );
	m_aDataHash[ROLE_2] = QVariant( QColor( "#FFFFFF" ) );
	m_aDataHash[ROLE_3] = QVariant( 123 );
	m_aDataHash[ROLE_4] = QVariant( "otherString" );
	m_aDataHash[ROLE_5] = QVariant( 11.34 );
}

In header i define few general purpose roles. Depending on use it is up to single list instance to interpret which role relates to which property. Using QVariant allows to set many various property types to one variable (of QVariant type). (NOTE: remember that if you bind a single item role from c++ string to qml color then it will result in property binding error).
In this class i also define copy constructor so i can set some common default properties for all list objects in one object and then just copy it to other items.

Having an item defined we can move further to QAbstractListModel reimplementation:
mylistmodel.h

#ifndef MYLISTMODEL_H
#define MYLISTMODEL_H

#include <QAbstractListModel>
#include "listitemapi.h"

class MyListModel : public QAbstractListModel
{
	Q_OBJECT
	Q_PROPERTY( int count READ rowCount NOTIFY signalCountChanged )
public:
	explicit MyListModel( QObject* a_pParent = 0 );
	explicit MyListModel( ListItemAPI* a_pPrototype, QObject* a_pParent = 0 );
	virtual ~MyListModel();

	// QAbstractListModel reimplemented methods
	int rowCount( const QModelIndex& a_rParent = QModelIndex() ) const;
	QVariant data( const QModelIndex& a_rIndex, int a_iRole = Qt::DisplayRole ) const;
	QHash<int, QByteArray> roleNames() const;
	bool removeRows( int a_iRow, int a_iCount, const QModelIndex& a_rParent = QModelIndex() );

	// Methods created to match QML Model style of data manipulation
	Q_INVOKABLE void append( ListItemAPI* a_pItem );
	Q_INVOKABLE QVariant get( int a_iIndex );
	Q_INVOKABLE void clear();

	inline ListItemAPI* GetItem( int a_iIndex );
signals:
	void signalCountChanged( int a_iNewCount );
protected:
	ListItemAPI* m_pPrototype;
	QList<ListItemAPI*> m_aItems;
};
/////////////////////////////////////////////////////////
ListItemAPI* MyListModel::GetItem( int a_iIndex )
{
	if ( m_aItems.size() > a_iIndex )
	{
		return m_aItems[a_iIndex];
	}
	return 0;
}
#endif // MYLISTMODEL_H

and its following implementation:
mylistmodel.cpp

#include "mylistmodel.h"

MyListModel::MyListModel( QObject* a_pParent )
	: QAbstractListModel( a_pParent )
	, m_pPrototype( 0 )
	, m_aItems ( QList<ListItemAPI*>() )
{
}

MyListModel::MyListModel( ListItemAPI* a_pPrototype, QObject* a_pParent )
	: QAbstractListModel( a_pParent )
	, m_pPrototype( a_pPrototype )
	, m_aItems ( QList<ListItemAPI*>() )
{
}

MyListModel::~MyListModel()
{
	clear();
}

int MyListModel::rowCount( const QModelIndex& a_rParent ) const
{
	Q_UNUSED( a_rParent );
	return m_aItems.size();
}

QVariant MyListModel::data( const QModelIndex& a_rIndex, int a_iRole ) const
{
	if ( a_rIndex.row() < 0 )
	{
		return QVariant();
	}
	if ( a_rIndex.row() > m_aItems.size() )
	{
		return QVariant();
	}
	ListItemAPI* pValidate = m_aItems.at( a_rIndex.row() );
	if ( pValidate )
	{
		return pValidate->GetData( a_iRole );
	}
	return QVariant();
}

QHash<int, QByteArray> MyListModel::roleNames() const
{
	if ( m_pPrototype )
	{
		return m_pPrototype->RoleNames();
	}
	return ( QHash<int, QByteArray>() );
}

bool MyListModel::removeRows( int a_iRow, int a_iCount, const QModelIndex& a_rParent )
{
	if ( a_iRow < 0 )
	{
		return false;
	}
	if ( a_iCount <= 0 )
	{
		return false;
	}
	if ( ( a_iRow + a_iCount ) > m_aItems.size() )
	{
		return false;
	}
	beginRemoveRows( a_rParent, a_iRow, a_iRow + a_iCount - 1 );
	for ( int i = 0; i < a_iCount; i++ )
	{
		ListItemAPI* pItem = m_aItems.takeAt( a_iRow );
		pItem->deleteLater();
		pItem = 0;
	}
	endRemoveRows();
	emit signalCountChanged( rowCount() );
	return true;
}

void MyListModel::append( ListItemAPI* a_pItem )
{
	if ( a_pItem != 0 )
	{
		beginInsertRows( QModelIndex(), rowCount(), rowCount() );
		m_aItems.append( a_pItem );
		endInsertRows();
		emit signalCountChanged( rowCount() );
	}
}

QVariant MyListModel::get( int a_iIndex )
{
	if ( a_iIndex < 0 )
	{
		return QVariant();
	}
	if ( a_iIndex >= m_aItems.size() )
	{
		return QVariant();
	}
	QMap<QString, QVariant> aItemData;
	ListItemAPI* pItem = m_aItems.at( a_iIndex );
	if ( pItem )
	{
		QHashIterator<int, QByteArray> aRolesItr( pItem->RoleNames() );
		while ( aRolesItr.hasNext() )
		{
			aRolesItr.next();
			aItemData.insert( aRolesItr.value(), QVariant( pItem->GetData( aRolesItr.key() ) ) );
		}
		return QVariant( aItemData );
	}
	return QVariant();
}

void MyListModel::clear()
{
	if ( m_aItems.size() > 0 )
	{
		removeRows( 0, m_aItems.size() );
	}
}

In general reimplementation is done according to Qt docs with one exception. This is a ‘prototype item’. When creating an instance of listmodel class we have to pass prototype item to tell the class what types of items will be filled with. Here roleNames() class implementation is redirected to prototypes RoleNames() definition. Doing it this way i can have one common MyListModel class for all lists exported to QML and only to create new MyListModelItems (well, in fact i don’t even subclass MyListModelItem, i just add more item Roles with numbering and manage their meanings separately for every use).

The last class presented in this tutorial is actual QML listView reflection in C++. It provides a few methods to manipulate data in both ways (QmlC++).
customlistview.h

#ifndef CUSTOMLISTVIEW_H
#define CUSTOMLISTVIEW_H

#include <QQuickItem>
#include "mylistmodel.h"
#include "mylistitem.h"
class CustomListView : public QQuickItem
{
	Q_OBJECT
	Q_PROPERTY( int m_iCurrentIndex READ GetCurrentIndex WRITE SetCurrentIndex NOTIFY signalCurrentIndexChanged )
	Q_PROPERTY( MyListModel* m_pListModel READ GetListModel NOTIFY signalListModelChanged )
public:
	explicit CustomListView( QQuickItem* a_pParent = 0 );
	explicit CustomListView( MyListModel* a_pListModel, QQuickItem* a_pParent = 0 );
	virtual ~CustomListView();

	inline int GetCurrentIndex() const { return m_iCurrentIndex; }
	Q_INVOKABLE void SetCurrentIndex( int a_iNewCurrentIndex );

	void ClearElements();
	void AppendElement( MyListItem* a_pNewElement );

	inline MyListModel* GetListModel() const { return m_pListModel; }
signals:
	void signalCurrentIndexChanged( int a_iNewCurrentIndex );
	void signalListModelChanged();

protected:
	MyListModel* m_pListModel;
	int m_iCurrentIndex;
};
#endif // CUSTOMLISTVIEW_H

customlistview.cpp

#include "customlistview.h"

CustomListView::CustomListView( MyListModel* a_pListModel, QQuickItem* a_pParent )
	: QQuickItem( a_pParent )
	, m_pListModel( a_pListModel )
	, m_iCurrentIndex( -1 )
{
}

CustomListView::CustomListView( QQuickItem* a_pParent )
	: QQuickItem( a_pParent )
	, m_pListModel( new MyListModel( new MyListItem() ) )
	, m_iCurrentIndex( -1 )
{
}

CustomListView::~CustomListView()
{
	if ( m_pListModel )
	{
		delete m_pListModel;
		m_pListModel = 0;
	}
}

void CustomListView::SetCurrentIndex( int a_iNewCurrentIndex )
{
	if ( a_iNewCurrentIndex != m_iCurrentIndex )
	{
		m_iCurrentIndex = a_iNewCurrentIndex;
		emit signalCurrentIndexChanged( m_iCurrentIndex );
	}
}

void CustomListView::ClearElements()
{
	if ( m_pListModel )
	{
		m_pListModel->clear();
		m_iCurrentIndex = -1;
		emit signalListModelChanged();
	}
}

void CustomListView::AppendElement( MyListItem* a_pNewElement )
{
	if ( a_pNewElement && m_pListModel )
	{
		m_pListModel->append( a_pNewElement );
		emit signalListModelChanged();
	}
}

Here i have defined MyListModel as Q_PROPERTY (this is possible as QAbstractListModel is a QObject derived class, unlike the QList class) to be able to refer to its items through it. There is also currentIndex property to notify Qml/C++ about listview index changes. You can also define here other properties used to specify PathView behaviour and bind them in qml such as:
pathItemCount: id_listView.m_iPathItemCount
highlightMoveDuration: id_listView.m_iAnimationDuration
..and a few others.

QmlListView.qml

import MyCustoms 1.0
import QtQuick 2.0

CustomListView
{
	id: id_listView

	onSignalCurrentIndexChanged:
	{
		id_listViewPath.currentIndex = m_iCurrentIndex
	}
	Component
	{
		id: id_delegate
		Item
		{
			id: id_delegate_item
			scale: PathView.iconScale
			opacity: PathView.iconOpacity
			Image
			{
				id: id_img
				anchors.horizontalCenter: id_delegate_item.horizontalCenter
				width: 60
				height: 60
				source: m_role1
			}
		}
	}
	PathView
	{
		id: id_listViewPath
		anchors.fill: id_listView

		model: id_listView.m_pListModel
		delegate: id_delegate
		pathItemCount: 3

		snapMode: PathView.NoSnap
		highlightMoveDuration: 300
		interactive: true

		preferredHighlightBegin: 0.5
		preferredHighlightEnd: 0.5
		highlightRangeMode: PathView.StrictlyEnforceRange
		dragMargin: 20
		path: Path
		{
			id: id_path
			startX: id_listViewPath.width / 2
			startY: id_listViewPath.y
			PathAttribute { name: "iconScale"; value: 0.5 }
			PathAttribute { name: "iconOpacity"; value: 0.5 }
			PathLine { x: id_listViewPath.width / 2; relativeY: id_listViewPath.height / 2 }
			PathAttribute { name: "iconScale"; value: 1 }
			PathAttribute { name: "iconOpacity"; value: 1 }
			PathLine { x: id_listViewPath.width / 2; relativeY: id_listViewPath.height / 2 }
		}
		onCurrentIndexChanged:
		{
			id_listView.m_iCurrentIndex = currentIndex
		}
	}
	Text
	{
		id: id_text
		anchors.left: id_listView.left
		anchors.verticalCenter: id_listView.verticalCenter
		text: id_listView.m_pListModel.get(id_listView.m_iCurrentIndex) ? id_listView.m_pListModel.get(id_listView.m_iCurrentIndex).m_role2 : ""
		color: id_listView.m_pListModel.get(id_listView.m_iCurrentIndex) ? id_listView.m_pListModel.get(id_listView.m_iCurrentIndex).m_role3 : "red"
	}
}

main.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import MyCustoms 1.0
import "res/qml"
Window
{
	id: id_root
    visible: true
	width: 400
	height: width
	Rectangle
	{
		id: id_rect
		width: id_root.width
		height: id_root.height
		QmlListView
		{
			id: id_listView
			anchors.fill: id_rect
			objectName: "ListView_Instance"
		}
	}
}

My main.qml file looks like this, and to get a pointer to my id_listView item after creation of main.qml with Window object i use ‘findChild’ method. A good idea is to set listView’s objectName so we never get mislead when more instances of objects of the same type have the same parent().

The whole setup is done in main and is self explaining and consists of a few main parts:
Create application window
Retrieve pointer to my listview class
Set listview model items

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>

#include "mylistitem.h"
#include "customlistview.h"

void registerCustomQMLTypes();
void fillModel(CustomListView* a_pView);
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
	registerCustomQMLTypes();
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
	
	CustomListView* pQmlListView = 0;
	QList<QObject*> aRoots = engine.rootObjects();
	for( int i=0; i<aRoots.size(); i++ )
	{
		pQmlListView = aRoots[i]->findChild<CustomListView*>("ListView_Instance");
		if (pQmlListView != 0)
			break;
	}
	
	fillModel(pQmlListView);

    return app.exec();
}

void registerCustomQMLTypes()
{
	qmlRegisterType<MyListItem>("MyCustoms", 1, 0, "MyListItem");
	qmlRegisterType<MyListModel>("MyCustoms", 1, 0, "MyListModel");
	qmlRegisterType<CustomListView>("MyCustoms", 1, 0, "CustomListView");
}

void fillModel(CustomListView* a_pView)
{
	if (a_pView)
	{
		MyListModel* pModel = a_pView->GetListModel();
		if (pModel)
		{
			MyListItem* pItem = new MyListItem();
			if (pItem)
			{
				pItem->SetData(MyListItem::ROLE_1, QVariant("qrc:/res/img/cat0.png"));
				pItem->SetData(MyListItem::ROLE_2, QVariant("Text_0"));
				pItem->SetData(MyListItem::ROLE_3, QVariant( QColor(0x00, 0xFF, 0xFF)));
				pModel->append(pItem);
			}
			pItem = new MyListItem();
			if (pItem)
			{
				pItem->SetData(MyListItem::ROLE_1, QVariant("qrc:/res/img/cat1.png"));
				pItem->SetData(MyListItem::ROLE_2, QVariant("Second cat"));
				pItem->SetData(MyListItem::ROLE_3, QVariant( QColor(0x00, 0x00, 0x00)));
				pModel->append(pItem);
			}
			.
			.
			.
		}
		a_pView->SetCurrentIndex(0);
	}
}

When creating new items for a model i use 3 roles. I decided that ROLE_1 will describe list delegate Image.source property (and it is a string), ROLE_2 describes an item text (also string) and item text color (QColor). This properties are binded to QML names from MyListItem file:

QHash<int, QByteArray> MyListItem::RoleNames() const
{
	QHash<int, QByteArray> aRoleNames;
	aRoleNames[ROLE_1]			= "m_role1";
	aRoleNames[ROLE_2]			= "m_role2";
	aRoleNames[ROLE_3]			= "m_role3";
	aRoleNames[ROLE_4]			= "m_role4";
	aRoleNames[ROLE_5]			= "m_role5";
	return aRoleNames;
}

so in QML names are recognised as m_roleX:

			Image
			{
				id: id_img
				anchors.horizontalCenter: id_delegate_item.horizontalCenter
				width: 60
				height: 60
				source: m_role1
			}

If you have any questions feel free to write to me and i will try to explain things in more clear way.
Whole project compiled under Ubuntu 14.04 using Qt 5.2 is available here. (Should work with previous Qt versions as well)
In the next post I will write about creating truly flexible ListViews with proper-user defined scalling and with automated ListView delegates creation.

Export QList to QML

Problem:

How to expose QList<QObject*> into QML so I can dynamically change its content?

Comment:

Sometimes when developing Qt application we want to show some content in a fancy QML UI controls but we still want to stick to C++ in terms of object manipulating. By QML controls i mean stuff like ListView, PathView and similar model-based controls. So why is exposing QList to QML such a big deal? The thing is, QList is not a QObject-derived, so it cannot be easily exposed to QML. There are a few ways to accomplish this which are going to be covered in this post:

  • Create a list property in QML file and access it using functions declared in QML ( modifying already existing content requires redeclaring all items at list )
  • Use a class provided by Qt ( QQmlListProperty ) to make a QList<QObject*> created in C++ visible at QML side
  • Subclass QAbstractListModel to create a complete model which can be used in QML

Each of this ways obviously have its pros and cons. They are listed from least time-consuming ( and though least elegant ) to the most time-consuming order. So, lets make our hands dirty…

The easiest way is to create a property list in QML, functions to modify its content and QMetaObject::InvokeMethod them from C++.

… will be added later…

The other way is to use provided by Qt special class QQmlListProperty<MyQObject>. All we have to do is to declare a Q_PROPERTY of this class type with a proper accessors. The most simple example would be a ReadOnly list. This means it can be modified from C++ and notify signal will be sent to QML so it updates, but no changes from QML can be made. Here it is:
cqmllist.h

#include &lt;QQuickItem&gt;
class CQmlList : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty&lt;QObject&gt; m_aItems READ getQmlItemList NOTIFY signalQmlItemListChanged)
    // there is no need to call Q_PROPERTIES the same as in c++. i just use it to know who is who.
public:
    inline QQmlListProperty&lt;QObject&gt; getQmlItemList()
    {
        return QQmlListProperty&lt;QObject&gt;( this, m_aItems );
    }
signals:
    void signalQmlItemListChanged(QQmlListProperty&lt;QObject&gt; a_aItems );
private:
    QList&lt;QObject*&gt; m_aItems;
};

Now, to make its content dynamical we need to declare a few more methods. ( Note the need of copying pointers to objects before deleting it to notify QML about this )

Q_INVOKABLE void clearItems()
{
	QList&lt;QObject*&gt; tmpList = m_aItems;
	// we have to notify QML that content changed before actually deleting objects
	m_aItems.clear();
	emit signalQmlItemListChanged(getQmlItemList());
	qDeleteAll(tmpList);
	tmpList.clear();
	emit signalQmlItemListChanged(getQmlItemList());
}
void appendItem(QObject *a_pItem)
{
	m_aItems.append(a_pItem);
	emit signalQmlItemListChanged(getQmlItemList());
}

This is it! Now when you pass to the list an item of your MyQObject* type you will be able to access its content just like in C++ as it will be autocasted to your type. Lets see how it works. Declare a class with your own Q_PROPERTIES and proper accessors.
clistitem.h

#include &lt;QObject&gt;
class CListItem : public QObject
{
	Q_OBJECT
	Q_PROPERTY(QString m_strName READ getName WRITE setName NOTIFY nameChanged)
	Q_PROPERTY(QString m_strImgSource READ getImgSource WRITE setImgSource NOTIFY imgSourceChanged)
public:
	explicit CListItem(QObject *pParent = 0)
		: QObject(pParent)
		, m_strImgSource(&quot;dummy&quot;)
		, m_strName(&quot;dummy&quot;)
	{}
	virtual ~CListItem(){}

	inline QString getName() const { return m_strName; }
	inline void setName(QString a_strNewName) { m_strName = a_strNewName; }

	inline QString getImgSource() const { return m_strImgSource; }
	inline void setImgSource(QString a_strNewImgSource) { m_strImgSource = a_strNewImgSource; }
signals:
	void nameChanged(QString a_strNewName);
	void imgSourceChanged(QString a_strNewImgSource);
private:
	QString m_strName;
	QString m_strImgSource;
};

…And now use it in QML! This example may look a bit complicated but i highlighted the most important lanes. I use PathView which delegate is previously declared Component id_component is an image with source stored in class Q_PROPERTY ‘m_strImgSource’. There is also a textbox at the bottom. I could not add this textbox to a Component as i want it to be visible only for currently selected item. I accomplish this by checking PathView currentIndex property. I just display a name ( stored under ‘m_strName’ property ) of an item on a list with a currentIndex, otherwise i set an empty string.
QmlList.qml

import QtQuick 2.0
import MyCustoms 1.0

CQmlList
{
	id: id_myList
	Component
	{
		id: id_component
		Item
		{
			id: id_rect
			scale: PathView.iconScale
			opacity:  PathView.iconOpacity
			Image
			{
				anchors.horizontalCenter: id_rect.horizontalCenter
				width: 60
				height: 60
				// m_strImgSource property registered in C++
				source: m_strImgSource
			}
		}
	}
	//real view starts here
	PathView
	{
		id: id_view
		anchors.fill: id_myList
		model: m_aItems
		delegate: id_component
		preferredHighlightBegin: 0.5
		preferredHighlightEnd: 0.5
		pathItemCount: 3
		dragMargin: 100
		interactive: true
		snapMode: PathView.SnapOneItem
		path: Path
		{
			startX: id_myList.x
			startY: id_myList.height/2
			PathAttribute { name: &quot;iconScale&quot;; value: 0.5 }
			PathAttribute { name: &quot;iconOpacity&quot;; value: 0.5 }
			PathLine { relativeX: id_myList.width/2; y: id_myList.height/2 }
			PathAttribute { name: &quot;iconScale&quot;; value: 1 }
			PathAttribute { name: &quot;iconOpacity&quot;; value: 1 }
			PathLine { relativeX: id_myList.width/2; y: id_myList.height/2 }
		}
	}
	Text
	{
		anchors.bottom: id_myList.bottom
		anchors.horizontalCenter: id_myList.horizontalCenter
		// make sure to set text only if ItemList index is valid
		// m_strName property registered in C++
		text: id_myList.m_aItems[id_view.currentIndex] ? id_myList.m_aItems[id_view.currentIndex].m_strName : &quot;&quot;

		MouseArea
		{
			anchors.fill: parent
			onClicked:
			{
				// just provoke some action in qml from c++ function
				// it was declared as Q_INVOKABLE so i can do this
				id_myList.clearItems()
			}
		}
	}
}

the final effect looks like this:
qml_list qml_list1
For a full qt project with this issue you can go to my gitorious and download it here

In the next post I describe more complex approach to flexible QObject list exporting to QML.