error: Unable to assign [undefined] to QString
-
wrote on 23 Sept 2019, 08:32 last edited by
Hi all,
I have a problem need your help.
I have a PlaylistModel class:playlistmodel.h
#include <QAbstractListModel> #include <QObject> class PlaylistModel : public QAbstractListModel { Q_OBJECT public: enum Roles { TitleRole = Qt::UserRole + 1, SingerRole, SourceRole, AlbumArtRole }; explicit PlaylistModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; void addSong(Song &song); protected: QHash<int, QByteArray> roleNames() const override; private: QList<Song> m_data; QHash<int, QByteArray> m_roleNames; };
playlistmodel.cpp
#include <QMediaPlaylist> #include "playlistmodel.h" PlaylistModel::PlaylistModel(QObject *parent) : QAbstractListModel(parent) { m_data.append(Song("MySong1", "Singer1", "lll", "qrc:/Image/pic1.png")); m_data.append(Song("MySong2", "Singer2", "lll", "qrc:/Image/pic2.png")); m_data.append(Song("MySong3", "Singer3", "lll", "qrc:/Image/pic3.png")); m_roleNames[TitleRole] = "title"; m_roleNames[SingerRole] = "singer"; m_roleNames[SourceRole] = "source"; m_roleNames[AlbumArtRole] = "album_art"; } int PlaylistModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); if (parent.isValid()) return 0; return m_data.size(); } QVariant PlaylistModel::data(const QModelIndex &index, int role) const { if (index.isValid()) { return QVariant(); } Song item = m_data.at(index.row()); switch (role) { case TitleRole: return QVariant(item.title()); case SingerRole: return QVariant(item.singer()); case SourceRole: return QVariant(item.source()); case AlbumArtRole: return QVariant(item.album_art()); } return QVariant(); } void PlaylistModel::addSong(Song &song) { m_data.append(song); } QHash<int, QByteArray> PlaylistModel::roleNames() const { return m_roleNames; }
After registering PlaylistModel in main.cpp. I used it as a model in
main.qml
like this:import Playlist 1.0 ListView { id: mediaPlaylist anchors.fill: playList_bg model: PlaylistModel {} clip: true spacing: 2 currentIndex: 0 delegate: MouseArea { property variant myData: model implicitWidth: playlistItem.width implicitHeight: playlistItem.height Text { // use the defined model role (TitleRole) text: model.title anchors.fill: parent anchors.leftMargin: 35 verticalAlignment: Text.AlignVCenter color: "white" font.pixelSize: 13 } } }
But when I try to assign
model.title
to text, I got anerror: Unable to assign [undefined] to QString
. I want to use TitleRole which defined above, so what I did wrong?
Thanks a lot for your help. -
wrote on 23 Sept 2019, 18:19 last edited by mranger90
You have at least one issue that could be causing this::
in data()
if (index.isValid()) { return QVariant(); }
I think you want to test against !index.isValid()
-
Hi all,
I have a problem need your help.
I have a PlaylistModel class:playlistmodel.h
#include <QAbstractListModel> #include <QObject> class PlaylistModel : public QAbstractListModel { Q_OBJECT public: enum Roles { TitleRole = Qt::UserRole + 1, SingerRole, SourceRole, AlbumArtRole }; explicit PlaylistModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; void addSong(Song &song); protected: QHash<int, QByteArray> roleNames() const override; private: QList<Song> m_data; QHash<int, QByteArray> m_roleNames; };
playlistmodel.cpp
#include <QMediaPlaylist> #include "playlistmodel.h" PlaylistModel::PlaylistModel(QObject *parent) : QAbstractListModel(parent) { m_data.append(Song("MySong1", "Singer1", "lll", "qrc:/Image/pic1.png")); m_data.append(Song("MySong2", "Singer2", "lll", "qrc:/Image/pic2.png")); m_data.append(Song("MySong3", "Singer3", "lll", "qrc:/Image/pic3.png")); m_roleNames[TitleRole] = "title"; m_roleNames[SingerRole] = "singer"; m_roleNames[SourceRole] = "source"; m_roleNames[AlbumArtRole] = "album_art"; } int PlaylistModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); if (parent.isValid()) return 0; return m_data.size(); } QVariant PlaylistModel::data(const QModelIndex &index, int role) const { if (index.isValid()) { return QVariant(); } Song item = m_data.at(index.row()); switch (role) { case TitleRole: return QVariant(item.title()); case SingerRole: return QVariant(item.singer()); case SourceRole: return QVariant(item.source()); case AlbumArtRole: return QVariant(item.album_art()); } return QVariant(); } void PlaylistModel::addSong(Song &song) { m_data.append(song); } QHash<int, QByteArray> PlaylistModel::roleNames() const { return m_roleNames; }
After registering PlaylistModel in main.cpp. I used it as a model in
main.qml
like this:import Playlist 1.0 ListView { id: mediaPlaylist anchors.fill: playList_bg model: PlaylistModel {} clip: true spacing: 2 currentIndex: 0 delegate: MouseArea { property variant myData: model implicitWidth: playlistItem.width implicitHeight: playlistItem.height Text { // use the defined model role (TitleRole) text: model.title anchors.fill: parent anchors.leftMargin: 35 verticalAlignment: Text.AlignVCenter color: "white" font.pixelSize: 13 } } }
But when I try to assign
model.title
to text, I got anerror: Unable to assign [undefined] to QString
. I want to use TitleRole which defined above, so what I did wrong?
Thanks a lot for your help.wrote on 23 Sept 2019, 08:47 last edited by sharathHi @Lucas_1603,
try this,
text:title
For more information, follow this https://wiki.qt.io/How_to_Use_a_Custom_Class_in_C%2B%2B_Model_and_QML_View ,
https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html -
Hi @Lucas_1603,
try this,
text:title
For more information, follow this https://wiki.qt.io/How_to_Use_a_Custom_Class_in_C%2B%2B_Model_and_QML_View ,
https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.htmlwrote on 23 Sept 2019, 16:24 last edited by@sharath
I triedtext: title
as you suggested but it still didn't work (the same error). Do I need to specify them_data
(private QList) in model of ListView? If yes, how can I do that?
Thanks a lot. -
wrote on 23 Sept 2019, 18:19 last edited by mranger90
You have at least one issue that could be causing this::
in data()
if (index.isValid()) { return QVariant(); }
I think you want to test against !index.isValid()
-
You have at least one issue that could be causing this::
in data()
if (index.isValid()) { return QVariant(); }
I think you want to test against !index.isValid()
wrote on 24 Sept 2019, 02:31 last edited by@mranger90 Oh, it worked like a charm! Thank you so much
-
wrote on 24 Sept 2019, 04:35 last edited by
One more question, if I want to use PlaylistModel out side of ListView in QML, such as a Text item (it doesn't have model property to assign PlaylistModel as a model):
PlaylistModel { id: model_ } Text { id: audioTitle anchors.top: headerItem.bottom anchors.topMargin: 3 anchors.left: mediaPlaylist.right anchors.leftMargin: 3 text: model_.title color: "white" font.pixelSize: 15 }
But when I try to set
model_.title
totext
, it didn't understand and raised theerror: Unable to assign [undefined] to QString
How can I use it properly?
Thanks a lot ^^ -
One more question, if I want to use PlaylistModel out side of ListView in QML, such as a Text item (it doesn't have model property to assign PlaylistModel as a model):
PlaylistModel { id: model_ } Text { id: audioTitle anchors.top: headerItem.bottom anchors.topMargin: 3 anchors.left: mediaPlaylist.right anchors.leftMargin: 3 text: model_.title color: "white" font.pixelSize: 15 }
But when I try to set
model_.title
totext
, it didn't understand and raised theerror: Unable to assign [undefined] to QString
How can I use it properly?
Thanks a lot ^^wrote on 24 Sept 2019, 05:25 last edited by sharathHello @Lucas_1603,
You can not use like that. if you want to use it in text then you need to loop over the model like below.
function iterate(){ for(var i = 0; i < yourModel.length; i++){ console.log("model's title::"+yourModel[i].title); audioTitle.text=yourModel[i].title; } }
just try and let me know your result;
Happy coding.
-
Hello @Lucas_1603,
You can not use like that. if you want to use it in text then you need to loop over the model like below.
function iterate(){ for(var i = 0; i < yourModel.length; i++){ console.log("model's title::"+yourModel[i].title); audioTitle.text=yourModel[i].title; } }
just try and let me know your result;
Happy coding.
wrote on 24 Sept 2019, 08:41 last edited by@sharath I tried it out but it didn't work as we expected. I wrote a function like yours and called it in text but it still raised the
error: Unable to assign [undefined] to QString
Don't have any general methods to use PlaylistModel for both in ListView and out of it (wherever in QML)?
Thanks for your help -
@Lucas_1603 said in error: Unable to assign [undefined] to QString:
text: model_.title
What should that mean?
"Give me the title of the song in my playlist"?
Which song are you talking about? the first, the last, one in the middle? -
@Lucas_1603 said in error: Unable to assign [undefined] to QString:
text: model_.title
What should that mean?
"Give me the title of the song in my playlist"?
Which song are you talking about? the first, the last, one in the middle?wrote on 24 Sept 2019, 08:56 last edited by@GrecKo The second song for example. The title is "Mysong2"
-
So you have to somehow tell that you want the second one.
You could add an invokable get method in your model return data from a specific row.
But if you need it to be updated when the model changes, it's going to be hard.I wrote a library for that https://github.com/oKcerG/QmlModelHelper , it works for any standard QAbstractItemModel.
You could use it like that:
text: model_.ModelHelper.map(1).title
-
@GrecKo The second song for example. The title is "Mysong2"
wrote on 24 Sept 2019, 09:30 last edited by sharath@Lucas_1603 for second song,
text:model_[1].title
-
@Lucas_1603 for second song,
text:model_[1].title
wrote on 24 Sept 2019, 09:44 last edited by -
What @sharath proposed won't work. You can't access QAbstractItemModel's data with [].
@Lucas_1603 please better define what you want.
Do you want multiple text items for each of your songs? Or do you want all titles concatenated in one text? Or something else? -
wrote on 24 Sept 2019, 09:56 last edited by
@Lucas_1603 Create get method to get perticular index data from QAbstractListModel class. follow https://stackoverflow.com/questions/22711421/how-to-implement-qml-listmodel-like-get-method-for-an-qabstractlistmodel-derived .
i'm sure that your problem might solve with this link.Happy coding
-
What @sharath proposed won't work. You can't access QAbstractItemModel's data with [].
@Lucas_1603 please better define what you want.
Do you want multiple text items for each of your songs? Or do you want all titles concatenated in one text? Or something else?wrote on 24 Sept 2019, 10:02 last edited by@GrecKo In ListView, I just need to specify the model and then I can assign
model_.title
, it'll display all titles concatenated in one text. I want do the same from the Text outside of ListView.
@sharath I actually created get method and it worked as I expected. Now I want to display all titles concatenated in one text. -
@GrecKo In ListView, I just need to specify the model and then I can assign
model_.title
, it'll display all titles concatenated in one text. I want do the same from the Text outside of ListView.
@sharath I actually created get method and it worked as I expected. Now I want to display all titles concatenated in one text.@Lucas_1603 said in error: Unable to assign [undefined] to QString:
@GrecKo In ListView, I just need to specify the model and then I can assign model_.title, it'll display all titles concatenated in one text.
No that's what it does, it creates a delegate for each row and position them the one after the other
I want do the same from the Text outside of ListView.
If you want the same why don't you want a ListView.
Maybe do a schema of what you actually want?
-
@Lucas_1603 said in error: Unable to assign [undefined] to QString:
@GrecKo In ListView, I just need to specify the model and then I can assign model_.title, it'll display all titles concatenated in one text.
No that's what it does, it creates a delegate for each row and position them the one after the other
I want do the same from the Text outside of ListView.
If you want the same why don't you want a ListView.
Maybe do a schema of what you actually want?
wrote on 24 Sept 2019, 10:20 last edited by@GrecKo Great, I created another ListView and everything was done ^^
Thank you a lot. How about a schema as you said, can you give me some links or docs to learn more about it? Thanks
1/18