model/view



  • i need to have a table like widget. i'm confused how i should do it? use QTableWidget or QTableVIew? what about models? i need read only widget

    my data is in this form:

    QHash<QString, QHash<QString, QStringList>> data;
    

    should i use QHash<QString, QHash<QString, QStringList>> as internal data structure for model?


  • Moderators

    @user4592357
    when you already have your data in such a defined data-structure reuse it and subclass QAbstractTableModel and implement the missing methods.
    See the addressbook example as a guide.

    You will need to map your keys of the hash (QString) to a specific column index.



  • I would disagree with raven this time. QHash does not structure the data stably enough to be manageable inside QAbstractTableModel (basically, when it rehashes you will have a bad time remapping rows/cols)

    Just store your data in a QStandardItemModel and make your life easy


  • Moderators

    @VRonin said in model/view:

    I would disagree with raven this time. QHash does not structure the data stably enough to be manageable inside QAbstractTableModel (basically, when it rehashes you will have a bad time remapping rows/cols)

    I don't quite understand your argument.
    At least i assumed that the keys are known and a simple mapping from e.g. column 3 to "Key3" is possible. I don't see where you get "a bad time"?!

    Just store your data in a QStandardItemModel and make your life easy

    QStandardItems is easy to use yes, but depending on the number of items, it comes straight from hell.



  • I don't quite understand your argument.

    Let's make it easy: 2 columns, name and address, stored in QHash<QString,QString> as a member of QAbstractTableModel.
    You call insertRow the data is re-hashed.
    you now call data(index(0,0)) how do you map the index 0 to the same place as before the rehashing? You'd have the model resetting (actually dataCahnging for the whole table) for every time you do something other than changing the hash value (the address).
    Hell then breaks loose if you change a key to make it a duplicate of something already present



  • sorry but i'm new to model/view programming in qt, and i understand basic examples but not this one.

    should i reimplement setData() and flags()? the widget is read-only.

    if not, how should i insert data in the model?


  • Moderators

    @VRonin said in model/view:

    You call insertRow the data is re-hashed.

    now is see....sorry. How could i not think about the "outer hash" .... i dont know.

    @user4592357 said in model/view:

    should i reimplement setData() and flags()? the widget is read-only.

    actually you need to reimplement all pure virtual methods.
    These are at least (in case of QAbstractTableModel):

    • columnCount()
    • data()
    • rowCount()
    • parent()


  • @raven-worx
    okay
    this thing I'm doing would suit tree view more than table, but as you can guess, i'm going have done duplicate columns in table.

    how should i map indices to my hash of hashes?

    EDIT: should i use hash of hashes as model internal data storage or array??? like this:

    for example if my hash of hashes is this

    r1 -> c1 -> x1, x2
          c2 -> x1, x2
          c3 -> x1, x2
    r2 -> c4 -> x1, x2
          c5 -> x1, x2
    r3 -> c6 -> x1, x2
          c7 -> x1, x2
          c8 -> x1, x2
    

    i'd have this array of arrays as model internal data structure:

    [r1, c1, x1, x2]
    [r1, c2, x1, x2]
    [r1, c3, x1, x2]
    [r2, c4, x1, x2]
    [r2, c5, x1, x2]
    [r3, c6, x1, x2]
    [r3, c7, x1, x2]
    [r3, c8, x1, x2]
    

    is this okay???


  • Moderators

    @user4592357
    as @VRonin said, a hash of hashes would only make sense if the hash doesn't change and all Keys are known and fixed.

    But shouldn't your hash definition actually look something like QHash<QString,QHash<QString, QStringList>>?!



  • @raven-worx
    yeah you're right, i got lost in the flow of template arguments :D will correct now

    and yes, the hash doesn't change, i have some data loaded from which is need to just show in the table.

    so, is saving it like that matrix okay?

    and also, what should i do if i want to display this data in tree view too? should i use another model? currently my model receives the hash of hashes and in constructor saves it as the matrix above


  • Moderators

    @user4592357 said in model/view:

    and also, what should i do if i want to display this data in tree view too? should i use another model?

    Yes, you need another model. Tree and table models are different by their rowCount() and parent() functions.
    Tree models are more complex than table/list models. See this example.

    currently my model receives the hash of hashes and in constructor saves it as the matrix above

    When it is fixed as you say, you can use it as it is. Just use the mapping from rows/cols to the corresponding QString indexes. Then you do not need to copy it again into another matrix-structure.



  • @raven-worx
    i can't clearly picture how that mapping should be done.
    for example, for the structure i wrote above?


  • Moderators

    @user4592357
    as i've already explained above, for example:

    QVariant MyModel::data( const QModelIndex &index, int role) const 
    {
        if( role != Qt::DisplayRole )
             return QVariant();
    
        const int r = index.r();
        const int c = index.c();
        QString rowKey;
        switch( r )
        {
              case 0:   rowKey = "Key1"; break;
              case 1:   rowKey = "Key2"; break;
              case 2:   rowKey = "Key3"; break;
              ...
       }
    
        QHash<QString, QStringList> rowData = mHash.value( rowKey ); // mHash is 'QHash<QString,QHash<QString, QStringList>>'
        QString columnKey;
        switch( r )
        {
              case 0:   columnKey = "Key1"; break;
              case 1:   columnKey = "Key2"; break;
              case 2:   columnKey = "Key3"; break;
              ...
       }
    
       QStringList colData = rowData.value( columnData );
       return QVariant::fromValue<QString>(  colData .join(", ") );
    }
    


  • @raven-worx
    thanks. but what if i don't beforehand know the values of rows/columns?

    and what base model should i use for implementing model tree view?


  • Moderators

    @user4592357
    For tables: QAbstractTableModel
    For trees: QAbstractItemModel

    But i suggest you first implement a table model, before jumping onto the tree model implementation, for the sake of simplicity.

    About how many cells in the end are we talking actually?
    If we are not talking about hundreds to thousands you can also use QStandartItems (with QTreeWidget/QTableWidget) as @VRonin suggested.



  • @raven-worx
    the cells are a lot actually

    and about your code snippet, what if the row/column values aren't known beforehand?



  • @raven-worx said in model/view:

    If we are not talking about hundreds to thousands you can also use QStandartItems

    I actually use tens of thousands tree elements with QStandartItemModel and works for me


  • Moderators

    @VRonin said in model/view:

    I actually use tens of thousands tree elements with QStandartItemModel and works for me

    i never said it's not working, but it's a waste of memory.
    And thus discouraged to do so (from my side).



  • @raven-worx
    about your code snippet, what if the row/column values aren't known beforehand?


  • Moderators

    @user4592357
    then reusing the QHash structure is not ideal, you could use your matrix approach then



  • @raven-worx
    can't i use QTableWidget and QTreeWidget since my models aren't reused?



  • @user4592357 That's basically the same as using QStandartItemModel that we suggested at the beginning



  • @VRonin
    how is it the same?

    should i use the same QStandartItemModel for both views?



  • I mean QStandartItemModel + QTreeView = QTreeWidget and QStandartItemModel + QTableView = QTableWidget



  • @VRonin @raven-worx
    i have another question.

    so my table widget consists of 2 widgets: QTableView and a QTextEdit under it to display info about a particular cell.

    the data container i use to set model data consists of two maps:

    1. data storage for table view
    2. data storage for text edit

    how should i handle this in data()?



  • should i user two different containers???


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.