Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QAbstractListModel as property



  • Hi there,

    I'm pretty new to Qt and since a couple of days I'm trying to wrap my head around Qt abstract model classes and got stuck with the QAbstractListModel.

    I'm trying to create a subclass of the QAbstractListModel called NoteList, which basically houses a QList of a simple class Note with two properties namely a title and a message (Note isn't derived from QObject).

    Now there must be a QObject derived class Notebook, which should offer the NoteList as one of its properties...

    and here it fails!

    /mnt/ramdisk/qt-workspace/test/build-test_model2-Desktop_Qt_5_7_0_GCC_64bit-Debug/moc_Notebook.cpp:113: error: use of deleted function 'NoteList& NoteList::operator=(const NoteList&)'
             case 1: *reinterpret_cast< NoteList*>(_v) = _t->list(); break;
    

    Now when I try to implement NoteList& NoteList::operator=(const NoteList& other) ...

    NoteList& NoteList::operator=(const NoteList& other) {
    	_list = other._list;
    }
    

    ... It still doesnt really want to compile

    /opt/Qt/5.7/gcc_64/include/QtCore/qmetatype.h:766: error: use of deleted function 'NoteList::NoteList(const NoteList&)'
                 return new (where) T(*static_cast<const T*>(t));
    

    I have the feeling to be doing it totally wrong and would be very happy about somebody helping me out on that!
    I've also appended the entire source code of the little app down here:

    NoteList.hpp:

    #ifndef NOTELIST_H
    #define NOTELIST_H
    
    #include "Note.hpp"
    #include <QAbstractListModel>
    #include <QList>
    #include <QHash>
    #include <QByteArray>
    #include <QVariant>
    #include <QModelIndex>
    
    class NoteList : public QAbstractListModel
    {
    	Q_OBJECT
    public:
    	enum Roles {
    		TitleRole = Qt::UserRole,
    		MessageRole
    	};
    
    protected:
    	QList<Note> _list;
    public:
    	NoteList(QObject* parent = 0);
    	QHash<int, QByteArray> roleNames() const;
    	int rowCount(const QModelIndex& parent = QModelIndex()) const;
    	QVariant data(const QModelIndex& index, int role) const;
    };
    
    #endif // NOTELIST_H
    

    NoteList.cpp:

    #include "NoteList.hpp"
    #include "Note.hpp"
    #include <QAbstractListModel>
    #include <QByteArray>
    #include <QHash>
    #include <QModelIndex>
    #include <QVariant>
    
    NoteList::NoteList(QObject* parent) :
    	QAbstractListModel(parent)
    {
    	//append a couple of notes for testing purposes
    	_list.append(Note("tit", "msg"));
    	_list.append(Note("tit2", "msg2"));
    }
    
    QHash<int, QByteArray> NoteList::roleNames() const {
    	QHash<int, QByteArray> roles;
    	roles[TitleRole] = "title";
    	roles[MessageRole] = "message";
    	return roles;
    }
    
    int NoteList::rowCount(const QModelIndex& parent) const {
    	Q_UNUSED(parent);
    	return _list.size();
    }
    
    QVariant NoteList::data(const QModelIndex &index, int role) const {
    	if(!index.isValid()) {
    		return QVariant();
    	}
    	if(index.row() < 0 || (unsigned)index.row() >= _list.size()) {
    		return QVariant();
    	}
    	if(role == TitleRole) {
    		return QVariant(_list.at(index.row()).title());
    	}
    	if(role == MessageRole) {
    		return QVariant(_list.at(index.row()).message());
    	}
    	return QVariant();
    }
    

    Notebook.cpp:

    #include "Notebook.hpp"
    #include <QString>
    #include "NoteList.hpp"
    
    Notebook::Notebook(const QString& name) :
    	QObject(nullptr),
    	_name(name)
    {
    }
    
    QString Notebook::name() const {
    	return _name;
    }
    
    const NoteList& Notebook::list() const {
    	return _list;
    }
    

    Notebook.hpp:

    #ifndef NOTEBOOK_H
    #define NOTEBOOK_H
    
    #include <QObject>
    #include <QString>
    #include "NoteList.hpp"
    
    class Notebook : public QObject
    {
    	Q_OBJECT
    	Q_PROPERTY(QString name READ name NOTIFY nameChanged)
    	Q_PROPERTY(NoteList list READ list NOTIFY listChanged)
    protected:
    	QString _name;
    	NoteList _list;
    public:
    	Notebook(const QString& name);
    	QString name() const;
    	const NoteList& list() const;
    signals:
    	void nameChanged();
    	void listChanged();
    };
    
    #endif // NOTEBOOK_H
    

    Note.hpp:

    #ifndef NOTE_H
    #define NOTE_H
    
    #include <QString>
    
    class Note
    {
    protected:
    	QString _title;
    	QString _message;
    public:
    	Note(QString title = "untitled", QString message = "none");
    	QString title() const;
    	QString message() const;
    };
    
    #endif // NOTE_H
    

    Note.cpp:

    #include "Note.hpp"
    #include <QString>
    
    Note::Note(QString title, QString message) :
    	_title(title),
    	_message(message)
    {
    }
    
    QString Note::title() const {
    	return _title;
    }
    
    QString Note::message() const {
    	return _message;
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "Notebook.hpp"
    #include "NoteList.hpp"
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    	QGuiApplication app(argc, argv);
    
    	QQmlApplicationEngine engine;
    	Notebook notebook("mynotebook");
    	engine.rootContext()->setContextProperty("Notebook", &notebook);
    
    	qRegisterMetaType<NoteList>("NoteList");
    	engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
    	return app.exec();
    }
    

    main.qml

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.0
    
    ApplicationWindow {
    	visible: true
    	width: 800
    	height: 600
    
    	Rectangle {
    		id: menuBar
    		color: Qt.rgba(0,0,0,1)
    		anchors.left: parent.left
    		anchors.right: parent.right
    		anchors.top: parent.top
    		height: 48
    		Text {
    			anchors.centerIn: parent
    			color: Qt.rgba(1,1,1,1)
    			font.pixelSize: 18
    			text: "Notebook: " + Notebook.name
    		}
    	}
    
    	ListView {
    		id: view
    		anchors.top: menuBar.bottom
    		anchors.left: parent.left
    		anchors.right: parent.right
    		anchors.bottom: parent.bottom
    		model: Notebook.list
    		delegate: Item {
    			height: 64
    			Column {
    				Text {
    					text: "Title:" + title
    					font.bold: true
    					font.pixelSize: 16
    				}
    				Text {
    					text: "Message" + message
    					font.pixelSize: 16
    				}
    			}
    		}
    	}
    }
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    QAbstractItemModel is a QObject subclass and thus by definition a non-copyable class.

    You should return a pointer to a NoteList in your property.



  • @SGaist returning a pointer in the getter and defining the Q_PROPERTY as a pointer to the list worked out fine! Thanks for that!