Results 1 to 13 of 13

Thread: Custom Model Class

  1. #1
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Custom Model Class

    Hi,

    I'm trying to figure out how best to make my own model class but I'm going round in circles figuring out what to inherit from and what to reimplement.

    Currently I have it inheriting from QStandardItemModel like so:

    Qt Code:
    1. class PlayersModel : public QStandardItemModel
    2. {
    3. Q_OBJECT
    4. public:
    5. PlayersModel(QObject* parent = 0);
    6. };
    To copy to clipboard, switch view to plain text mode 

    And then the constructor is set up like so:

    Qt Code:
    1. PlayersModel::PlayersModel(QObject* parent) : QStandardItemModel(0, 2, parent)
    2. {
    3. this->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));
    4. this->setHeaderData(1, Qt::Horizontal, QObject::tr("Email"));
    5. }
    To copy to clipboard, switch view to plain text mode 

    But then I am aware that the user of PlayersModel could use the add column functions which I don't want them to be able to do. I simple want to define a list of name and email address (and maybe other things later).

    Can anyone point me in the right direction of a tutorial (or just simply help by giving me a bit of code to help) which I can use to learn this? I've tried the model view tutorial in the Qt docs but it doesn't really explain what I need.

    I would also like to be able to perform drag and drop between table view classes using the same model, which I have no idea how to implement at the moment but am keeping that in mind for now incase it has a bearing on how to implement my model class.

    Thanks so much guys!

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Custom Model Class

    Here' what you need to make your own model:
    Subclassing
    Note: Some general guidelines for subclassing models are available in the Model Subclassing Reference.
    When subclassing QAbstractItemModel, at the very least you must implement index(), parent(), rowCount(), columnCount(), and data(). These functions are used in all read-only models, and form the basis of editable models.
    You can also reimplement hasChildren() to provide special behavior for models where the implementation of rowCount() is expensive. This makes it possible for models to restrict the amount of data requested by views, and can be used as a way to implement lazy population of model data.
    To enable editing in your model, you must also implement setData(), and reimplement flags() to ensure that ItemIsEditable is returned. You can also reimplement headerData() and setHeaderData() to control the way the headers for your model are presented.
    Note that the dataChanged() and headerDataChanged() signals must be emitted explicitly when reimplementing the setData() and setHeaderData() functions, respectively.
    Custom models need to create model indexes for other components to use. To do this, call createIndex() with suitable row and column numbers for the item, and supply a unique identifier for the item, either as a pointer or as an integer value. Custom models typically use these unique identifiers in other reimplemented functions to retrieve item data and access information about the item's parents and children. See the Simple Tree Model example for more information about unique identifiers.
    It is not necessary to support every role defined in Qt::ItemDataRole. Depending on the type of data contained within a model, it may only be useful to implement the data() function to return valid information for some of the more common roles. Most models provide at least a textual representation of item data for the Qt:isplayRole, and well-behaved models should also provide valid information for the Qt::ToolTipRole and Qt::WhatsThisRole. Supporting these roles enables models to be used with standard Qt views. However, for some models that handle highly-specialized data, it may be appropriate to provide data only for user-defined roles.
    Models that provide interfaces to resizable data structures can provide implementations of insertRows(), removeRows(), insertColumns(), and removeColumns(). When implementing these functions, it is important to notify any connected views about changes to the model's dimensions both before and after they occur:
    ·An insertRows() implementation must call beginInsertRows() before inserting new rows into the data structure, and it must call endInsertRows() immediately afterwards.
    ·An insertColumns() implementation must call beginInsertColumns() before inserting new columns into the data structure, and it must call endInsertColumns() immediately afterwards.
    ·A removeRows() implementation must call beginRemoveRows() before the rows are removed from the data structure, and it must call endRemoveRows() immediately afterwards.
    ·A removeColumns() implementation must call beginRemoveColumns() before the columns are removed from the data structure, and it must call endRemoveColumns() immediately afterwards.
    The private signals that these functions emit give attached components the chance to take action before any data becomes unavailable. The encapsulation of the insert and remove operations with these begin and end functions also enables the model to manage persistent model indexes correctly. If you want selections to be handled properly, you must ensure that you call these functions.
    As for examples, have you checked the Interview example? Or the Item views example( they are all in the demos ).

    Regards

  3. #3
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    Hey, many thanks for the help there - I shall look into that.

    I'm just going round in circles at the moment because I want to be able to add and remove to this model using a button underneath a qtableview which is displaying it. But I can't work out how on earth to do this properly. Do I have slots in the model for this? Or in the tableview? Because the model needs to know where to insert / delete the item... which needs access to the view displaying it...

    ARGH!

  4. #4
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Custom Model Class

    Quote Originally Posted by mattjgalloway View Post
    I'm just going round in circles at the moment because I want to be able to add and remove to this model using a button underneath a qtableview which is displaying it. But I can't work out how on earth to do this properly. Do I have slots in the model for this? Or in the tableview? Because the model needs to know where to insert / delete the item... which needs access to the view displaying it...
    Could you make yourself a little clearer? If you want to modify the content of your model you MUST specify where you want to add (or remove) rows (or columns). I've not used QStandardItemModel myself because I thought having full control over node types would better fit my needs. It does not mean however that you can't use this class, although it is rumored to be buggy...

    What is particularly puzzling in what you are saying is that you seem to be looking for a way to make the model magically guess what should be added/removed just by pressing a button... Would be a neat feature but I'm afraid, even Trolltech is unable to craft such a thing...
    Current Qt projects : QCodeEdit, RotiDeCode

  5. #5
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    Hehe, I know that it won't be able to magically know what wants deleting, but what I am trying to do is have a QTableView with two buttons beneath it, Add and Remove. These should add rows to my derived model class. So what slot should these buttons be connected to? Slots of the model, or of the table view? And I assume I have to implement the slot myself? I can't seem to find any slots in QTableView which automatically do this anyway.

    I'm getting there with implementing the model, I'm now deriving from QAbstractItemModel where each item is a "Player" which contains a QString for name and a QString for email, etc.

  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: Custom Model Class

    Quote Originally Posted by mattjgalloway View Post
    So what slot should these buttons be connected to? Slots of the model, or of the table view?
    Custom slot of the widget which holds the model or the view variable.

    And I assume I have to implement the slot myself?
    You assume correct. Any by this assumptions you should have already answered your previous question - if we're talking about a custom slot, it has to be in a class you're just creating...

    I can't seem to find any slots in QTableView which automatically do this anyway.
    The button doesn't emit any parameters when clicked, so how would you want the view that only displays the model to know what you want to add to the model?

  7. #7
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    Well exactly... if the button doesn't emit any parameters, that's why I was confused as to how to implement the adding.

    So... I think I've worked it out... in that I have to add a slot into the mainWindow class (which holds the model, view and button) and have a slot there for addPlayer, removePlayer which looks at the current index of the view and then adds to the model at the correct place. I'm guessing that looks reasonable?

  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: Custom Model Class

    Yes, it's fine.

  9. #9
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    Argh I'm now coming across another problem...

    My QTableView which I am using to view the model can't see to edit the model! I've implemented a flags() function which is like so:
    Qt Code:
    1. if (!index.isValid())
    2. return Qt::ItemIsEnabled;
    3.  
    4. return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
    To copy to clipboard, switch view to plain text mode 

    So that should return that it's editable, selectable, etc. But when I try to click on a cell, nothing happens, it doesn't turn blue or allow me to edit, nothing!

    Any ideas?

  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: Custom Model Class

    Did you implement the model to return some data when asked for EditRole? Did you set the edit triggers for the view that fit your needs?

  11. #11
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    I think I figured out why it wasn't working - can't remember what it was now, but it seems to be fine.

    Now I have yet another problem... I have switched to using a QTreeView because that seems actually to be more what I want. I don't actually have a tree structure, but the view looks better than a QTableView for my functionality.

    But my custom model I have created doesn't work properly. Basically whenever I add an item, it gets put into the list, but also as a child of itself, and thus a child of that, and so on and so on. Adding another new entry makes that a child of the first, and etc, etc. It's really odd.

    I'm fairly sure this is something to do with the way my index() and parent() functions are defined. Currently they are thus:

    Qt Code:
    1. QModelIndex PlayersModel::index(int row, int column, const QModelIndex &parent) const
    2. {
    3. return createIndex(row, column);
    4. }
    5.  
    6. QModelIndex PlayersModel::parent(const QModelIndex &index) const
    7. {
    8. return QModelIndex();
    9. }
    To copy to clipboard, switch view to plain text mode 

    Any ideas what I am doing wrong?

  12. #12
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Custom Model Class

    The index() function shouldn't return a "blank" index like this... Index created by it are used by the view to iterate over your data and display it properly. The great big thing here is to clearly define how you associate model indexes with your underlying data. QModelIndex provides a way of associating either a void* or an integer which can be retrieved later on (mainly in functions like
    data(), flags(), setData(), ... but not only). What's wrong with your code is that you discard the parent passed to createIndex()...

    If this parent is not valid it means that the (row, col) are relative to the root of the tree. Otherwise they are children of the parent index passed. and QTreeView keeps adding children. To fix this just use this code (I'mm assuming that you really don't use any tree structure here...)
    Qt Code:
    1. QModelIndex PlayersModel::index(int row, int column, const QModelIndex& parent)
    2. {
    3. if ( parent.isValid() )
    4. return QModelIdex();
    5. return createIndex(row, column);
    6. }
    To copy to clipboard, switch view to plain text mode 
    Current Qt projects : QCodeEdit, RotiDeCode

  13. #13
    Join Date
    Jun 2007
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Custom Model Class

    Thanks! I had literally just figured it out as well, but went with:

    Qt Code:
    1. if(parent == QModelIndex())
    2. return createIndex(row, column);
    3. else
    4. return QModelIndex();
    To copy to clipboard, switch view to plain text mode 

    Is your code more valid? It looks like it'll do pretty much the same thing. I'm just trying to see if the code I came up with has any obvious design flaw you see, as I'm trying to learn good programming technique at the same time as coding.

    Many thanks!

Similar Threads

  1. hierarchical model in a flat view
    By gniking in forum Qt Programming
    Replies: 4
    Last Post: 10th November 2009, 20:17
  2. Coin3d + Qt: SIGLNALs and SLOTs
    By vonCZ in forum Newbie
    Replies: 26
    Last Post: 15th May 2009, 07:34
  3. Treeview and custom model
    By steg90 in forum Qt Programming
    Replies: 8
    Last Post: 15th May 2007, 13:54
  4. TreeView custom model
    By steg90 in forum Newbie
    Replies: 1
    Last Post: 9th May 2007, 10:06
  5. Replies: 16
    Last Post: 7th March 2006, 15:57

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.