Results 1 to 12 of 12

Thread: How to remove items of c++ model from within qml delegate?

  1. #1
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default How to remove items of c++ model from within qml delegate?

    My model is subclass of QAbstractListModel
    What methods should I implement? I guess it's deleteRows but how do I "call" them inside of qml code? Especially if I don't have access to my model (or it's methods because of some strange qt magic which turns my model to QQmlDMAbstractItemModelData which has all the rolls but no methods, and I don't want to store my model as property in all qml delegates)
    I mean then I do something like role = data it implicitly calls setData, when I just use role it uses data(). But how to make it remove current item (at index)?

    The only sort of broken solution I found is to have "somemethod" var property in all of my delegates and to set it to my model desired methods while I still have direct access to y model.

    (btw, simply trying to iterate over all "model after binding" properties with for in leads to a crash via assert)
    Last edited by flashmozzg; 24th April 2015 at 20:25.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    Can you prepare a minimal compilable example demonstrating that you don't have access to methods defined in the C++ model?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by wysota View Post
    Can you prepare a minimal compilable example demonstrating that you don't have access to methods defined in the C++ model?
    Well, that's probably not exactly the case. I CAN access them while I have DIRECT access to my model. But I can't or don't know how I can access them inside of a delegate.
    For example I do something like
    Qt Code:
    1. engine.rootContext()->setContextProperty("testModel", &model);
    To copy to clipboard, switch view to plain text mode 
    And then in qml I can call my "testMethod()" via "testModel.testMethod()" (if it's marked as Q_INVOKABLE of course).
    But if I have something like
    Qt Code:
    1. MyCustomDelegate {
    2. model: testModel
    3. }
    To copy to clipboard, switch view to plain text mode 
    and in MyCustomDelegate.qml I write model.testMethod(), testMethod or something I get that this property is not a function.
    So right now I have something like this:
    Qt Code:
    1. MyCustomDelegate {
    2. model: testModel
    3. testMethod: testModel.testMethod
    4. }
    To copy to clipboard, switch view to plain text mode 
    where testMethod is var property of my delegate.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    This is a matter of proper encapsulation. The delegate should not directly invoke methods on the model. Instead it should signal its actions to its environment where it can be intercepted by something which has direct access to the model.

    javascript Code:
    1. ListView {
    2. model: someModel
    3.  
    4. delegate: MyItemDelegate {
    5. onDeleteRequested: someModel.deleteRow(index)
    6. }
    7. }
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by wysota View Post
    This is a matter of proper encapsulation. The delegate should not directly invoke methods on the model. Instead it should signal its actions to its environment where it can be intercepted by something which has direct access to the model.

    javascript Code:
    1. ListView {
    2. model: someModel
    3.  
    4. delegate: MyItemDelegate {
    5. onDeleteRequested: someModel.deleteRow(index)
    6. }
    7. }
    To copy to clipboard, switch view to plain text mode 
    Alright but is there some standard/built in way to remove (maybe add) elements to model from within the delegate? Just how there is way to read and change items.
    (I mean since there already removeRows in the interface, isn't there a more convenient way to call/use it?)

    The inconvenience with above method that my view is in separate qml. So I'd have to bind signal from delegate to signal from view.
    Last edited by flashmozzg; 24th April 2015 at 23:02.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by flashmozzg View Post
    Alright but is there some standard/built in way to remove (maybe add) elements to model from within the delegate?
    No, there are different kinds of model. How would you delete a row from a model defined by an integer (e.g. "10")?

    Just how there is way to read and change items.
    There is no standard way to modify items if the model doesn't allow it.

    (I mean since there already removeRows in the interface, isn't there a more convenient way to call/use it?)
    No, there is no built-in method calling removeRows. You should equip your model with one but then you have to call the model directly and not through the data proxy which only gives you access to particular record in the model.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by wysota View Post
    There is no standard way to modify items if the model doesn't allow it.
    But if you allow (via flag) - there is. You can simply do this:
    Qt Code:
    1. roleName = newValue
    To copy to clipboard, switch view to plain text mode 
    And it will call setData and such.
    Also, standard qml ListModel has append and remove methods.
    So if removeRows is already virtual and in interface why isn't it "translated" into remove method of the model?

    Btw, I have another question related to removing and c++ <-> qml interop.
    I've written removeRows like this:
    Qt Code:
    1. bool MyModel::removeRows(int row, int count, const QModelIndex &parent)
    2. {
    3. if (count == 0 || mItems.isEmpty())
    4. return true;
    5. beginRemoveRows(parent, row, row + count - 1);
    6. for (int i = row; i < row + count; ++i)
    7. {
    8. AbstractItem *item = mItems.takeAt(row);
    9. delete item;
    10. }
    11. endRemoveRows();
    12. return true;
    13. }
    To copy to clipboard, switch view to plain text mode 

    But when I delete item it doesn't update view of my model! How to do this? I thought begin/endRemoveRows should be enough.
    Last edited by flashmozzg; 25th April 2015 at 01:14.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by flashmozzg View Post
    But if you allow (via flag) - there is. You can simply do this:
    Qt Code:
    1. roleName = newValue
    To copy to clipboard, switch view to plain text mode 
    And it will call setData and such.
    If there is a "setData" behind the model

    Also, standard qml ListModel has append and remove methods.
    Exactly. The methods are defined in a particular model, they are not some general functions that work on every model, just this one.

    So if removeRows is already virtual and in interface why isn't it "translated" into remove method of the model?
    It is not a slot so it is not visible from within the script. Besides the API would not make sense then (e.g. QtQuick doesn't use QModelIndex).

    I thought begin/endRemoveRows should be enough.
    It is enough. If it doesn't work then you probably didn't call it correctly. For instance your for loop completely ignores the "parent" but beginRemoveRows() doesn't.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by wysota View Post
    If there is a "setData" behind the model
    Exactly. The methods are defined in a particular model, they are not some general functions that work on every model, just this one.
    It is not a slot so it is not visible from within the script. Besides the API would not make sense then (e.g. QtQuick doesn't use QModelIndex).
    But setData isn't a slot/visible either =)
    And it uses QModelIndex too just fine. In ListView case it contains index of the row.
    It is enough. If it doesn't work then you probably didn't call it correctly. For instance your for loop completely ignores the "parent" but beginRemoveRows() doesn't.
    But parent is empty anyway. It is subclass of listmodel - there are only rows. There shouldn't be any parents (it's by default QModelIndex()).

    I even found almost the same implementation in qt docs http://doc.qt.io/qt-5/model-view-programming.html:
    Qt Code:
    1. bool StringListModel::removeRows(int position, int rows, const QModelIndex &parent)
    2. {
    3. beginRemoveRows(QModelIndex(), position, position+rows-1);
    4.  
    5. for (int row = 0; row < rows; ++row) {
    6. stringList.removeAt(position);
    7. }
    8.  
    9. endRemoveRows();
    10. return true;
    11. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by flashmozzg; 25th April 2015 at 01:11.

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by flashmozzg View Post
    But setData isn't a slot/visible either =)
    And it uses QModelIndex too just fine. In ListView case it contains index of the row.
    setData() is not exposed directly in QML anywhere so I don't see your point. QAbstractItemModel subclass instance is exposed to QML using a regular mechanism which allows you to modify properties of a QObject or call its slots. The object is not "translated" in any way so there is no (general) way to add artificial methods to the model class unless you implement them as scriptable methods in C++.

    But parent is empty anyway. It is subclass of listmodel - there are only rows. There shouldn't be any parents (it's by default QModelIndex()).
    As I said, if it doesn't work then you either didn't implement something correctly or you didn't call it correctly. Does it update if you use it with QListView? Does your method even get called?

    I even found almost the same implementation in qt docs
    It's the "almost" part that worries me
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Feb 2015
    Posts
    23
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by wysota View Post
    setData() is not exposed directly in QML anywhere so I don't see your point. QAbstractItemModel subclass instance is exposed to QML using a regular mechanism which allows you to modify properties of a QObject or call its slots. The object is not "translated" in any way so there is no (general) way to add artificial methods to the model class unless you implement them as scriptable methods in C++.
    My point is: why not have the same mechanism for deleting/adding items as there is for setting items?
    Currently if the right flag is passed and setData is implemented you can modify item properties corresponding to roles.
    I don't see why you can't in the same they if removeRows/Columns implemented remove items.
    As I said, if it doesn't work then you either didn't implement something correctly or you didn't call it correctly. Does it update if you use it with QListView? Does your method even get called?
    It's the "almost" part that worries me
    My app is in QtQuick so I'm obviously using qml ListView.

    Anyway, it seems to be working now for no apparent reason. It was probably some another weird bug with desync of mocs/precompiled files and etc. whic miraculously cures itself after rebuilding/running qmake again.

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to remove items of c++ model from within qml delegate?

    Quote Originally Posted by flashmozzg View Post
    My point is: why not have the same mechanism for deleting/adding items as there is for setting items?
    Because there is no standard way to do this.

    Currently if the right flag is passed and setData is implemented you can modify item properties corresponding to roles.
    You have fixated yourself on using editable QAbstractItemModel subclasses. This is a miniscule of models used in QML.

    I don't see why you can't in the same they if removeRows/Columns implemented remove items.
    Because in case of editing you are not accessing the model but rather a special object which internally has C++ access to the model. This special proxy represents a single record in the model. It would be counter-intuitive to equip the record with abilities to add other records to a model or remove other records from the model.

    My app is in QtQuick so I'm obviously using qml ListView.
    I don't see how that matters. Check the model with a QListView to see if it is updated when you call the method which you say doesn't work if you call it from QtQuick.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 3
    Last Post: 5th February 2014, 15:39
  2. How to remove a delegate from particular column
    By psarangi in forum Qt Programming
    Replies: 1
    Last Post: 4th February 2014, 06:02
  3. Model/Delegate/Proxy
    By skyline2000 in forum Qt Programming
    Replies: 1
    Last Post: 9th March 2011, 16:13
  4. set combobox delegate on some view items
    By GrahamLabdon in forum Newbie
    Replies: 0
    Last Post: 8th March 2011, 14:36
  5. Use delegate to draw different type of items
    By nifei in forum Qt Programming
    Replies: 1
    Last Post: 19th January 2009, 13:16

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.