Results 1 to 20 of 25

Thread: Updating a view's proxy model when the source model changes

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Updating a view's proxy model when the source model changes

    Hello,

    I have a model that manages a list of files. It's viewed by two widgets (a combobox and a tableview). Each widget has it's own QSortFilterProxy to pick which files it's supposed to display.

    The problem I'm encountering is related to drag and drop operations. After I perform a drag and drop (reordering list items), I've had trouble updating the views. For some reason, neither proxy model responds to the source model's dataChanged() signal (which I emit in the source model's setData() function, as well as the removeRows() function which is called last in the drag-drop operation). Anyway, I can solve the tableview refresh problem easily enough by adding a call to reset() in a slot in it's proxymodel, but the combo box is proving more difficult.

    I can't use the reset() trick with the combobox's proxy model because it will reset the current index to -1, losing whatever item has been selected.

    This leaves me with two possible solutions. Either I need to make a connection which ensures a proxy model is always synced with changes in it's source, or I need to save the current index of the combo box before the model is changed, then restore that index after the change is made. On the latter technique, I'm not sure how I can do that, nor am I certain that the view would update if I updated it's proxy model programmatically...

    Any help would be much appreciated...

  2. #2
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Updating a view's proxy model when the source model changes

    The problem I'm encountering is related to drag and drop operations. After I perform a drag and drop (reordering list items), I've had trouble updating the views.
    What do you mean by reordering?
    If it is just inserting row(s), are you using beginInsertRows() and endInsertRows()?
    If it is complete reordering, are you using beginModelReset() and endResetModel()?
    When you know how to do it then you may do it wrong.
    When you don't know how to do it then it is not that you may do it wrong but you may not do it right.

  3. #3
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Updating a view's proxy model when the source model changes

    I'm only inserting a row at a time. I still have to call reset() on each proxy (or in the source model alone) to get the view to refresh properly. That's fine for the table view, but not good for the combo box view...

  4. #4
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Updating a view's proxy model when the source model changes

    are you using beginInsertRows() and endInsertRows()?

  5. #5
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Updating a view's proxy model when the source model changes

    Yes - sorry - I forgot to mention that. Here's some code...

    Source model drag/drop and other relevant code...

    Qt Code:
    1. Qt::ItemFlags EsxModel::ContentModel::flags(const QModelIndex &index) const
    2. {
    3. if (!index.isValid())
    4. return Qt::NoItemFlags;
    5.  
    6. EsmFile *file = item(index.row());
    7.  
    8. if (!file)
    9. return Qt::NoItemFlags;
    10.  
    11. Qt::ItemFlags dragDropFlags = Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
    12. Qt::ItemFlags checkFlags = Qt::ItemIsUserCheckable;
    13. Qt::ItemFlags defaultFlags = Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
    14.  
    15. if (canBeChecked(file))
    16. return Qt::ItemIsEnabled | dragDropFlags | checkFlags | defaultFlags;
    17. else
    18. return defaultFlags;
    19. }
    20.  
    21. bool EsxModel::ContentModel::setData(const QModelIndex &index, const QVariant &value, int role)
    22. {
    23. if (index.isValid() && role == Qt::EditRole)
    24. {
    25. QString fname = value.value<QString>();
    26. mFiles.replace(index.row(), findItem(fname));
    27. emit dataChanged(index, index);
    28. return true;
    29. }
    30.  
    31. return false;
    32. }
    33.  
    34. bool EsxModel::ContentModel::insertRows(int position, int rows, const QModelIndex &parent)
    35. {
    36. beginInsertRows(QModelIndex(), position, position+rows-1);
    37.  
    38. for (int row = 0; row < rows; ++row)
    39. mFiles.insert(position, new EsmFile);
    40.  
    41. endInsertRows();
    42. return true;
    43. }
    44.  
    45. bool EsxModel::ContentModel::removeRows(int position, int rows, const QModelIndex &parent)
    46. {
    47. beginRemoveRows(QModelIndex(), position, position+rows-1);
    48.  
    49. for (int row = 0; row < rows; ++row)
    50. mFiles.removeAt(position);
    51.  
    52. endRemoveRows();
    53. emit dataChanged(index(0,0,parent), index(rowCount()-1, 0, parent));
    54. return true;
    55. }
    56.  
    57. Qt::DropActions EsxModel::ContentModel::supportedDropActions() const
    58. {
    59. return Qt::CopyAction | Qt::MoveAction;
    60. }
    61.  
    62. QStringList EsxModel::ContentModel::mimeTypes() const
    63. {
    64. QStringList types;
    65. types << "application/omwcontent";
    66. return types;
    67. }
    68.  
    69. QMimeData *EsxModel::ContentModel::mimeData(const QModelIndexList &indexes) const
    70. {
    71. QMimeData *mimeData = new QMimeData();
    72. QByteArray encodedData;
    73.  
    74. QDataStream stream(&encodedData, QIODevice::WriteOnly);
    75.  
    76. foreach (const QModelIndex &index, indexes)
    77. {
    78. if (index.isValid())
    79. {
    80. QString text = data(index, Qt::DisplayRole).toString();
    81. stream << text;
    82. }
    83. }
    84.  
    85. mimeData->setData("application/omwcontent", encodedData);
    86. return mimeData;
    87. }
    88.  
    89. bool EsxModel::ContentModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
    90. {
    91. if (action == Qt::IgnoreAction)
    92. return true;
    93.  
    94. if (!data->hasFormat("application/omwcontent"))
    95. return false;
    96.  
    97. if (column > 0)
    98. return false;
    99.  
    100. int beginRow;
    101.  
    102. if (row != -1)
    103. beginRow = row;
    104. else if (parent.isValid())
    105. beginRow = parent.row();
    106. else
    107. beginRow = rowCount(QModelIndex());
    108.  
    109. QByteArray encodedData = data->data("application/omwcontent");
    110. QDataStream stream(&encodedData, QIODevice::ReadOnly);
    111. QStringList newItems;
    112. int rows = 0;
    113.  
    114. while (!stream.atEnd())
    115. {
    116. QString text;
    117. stream >> text;
    118. newItems << text;
    119. ++rows;
    120. }
    121.  
    122. insertRows(beginRow, rows, QModelIndex());
    123.  
    124. foreach (const QString &text, newItems)
    125. {
    126. QModelIndex idx = index(beginRow, 0, QModelIndex());
    127. setData(idx, text);
    128. beginRow++;
    129. }
    130.  
    131. return true;
    132. }
    To copy to clipboard, switch view to plain text mode 

    And the proxy model:

    Qt Code:
    1. EsxModel::MasterProxyModel::MasterProxyModel(QObject *parent, QAbstractTableModel* model) :
    2. {
    3. setFilterRegExp(QString("game"));
    4. setFilterRole (Qt::UserRole);
    5.  
    6. if (model)
    7. setSourceModel (model);
    8. }
    9.  
    10. QVariant EsxModel::MasterProxyModel::data(const QModelIndex &index, int role) const
    11. {
    12. return QSortFilterProxyModel::data (index, role);
    13. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Updating a view's proxy model when the source model changes

    Can you show the rowCount()? Is it based on anything other than mFiles.size()?
    When you know how to do it then you may do it wrong.
    When you don't know how to do it then it is not that you may do it wrong but you may not do it right.

  7. #7
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Updating a view's proxy model when the source model changes

    Nope.

    Qt Code:
    1. int EsxModel::ContentModel::rowCount(const QModelIndex &parent) const
    2. {
    3. return mFiles.size();
    4. }
    To copy to clipboard, switch view to plain text mode 

  8. #8
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Updating a view's proxy model when the source model changes

    Add this
    Qt Code:
    1. int EsxModel::ContentModel::rowCount(const QModelIndex &parent) const
    2. {
    3. if(parent.isValid())
    4. return 0;
    5.  
    6. return mFiles.size();
    7. }
    To copy to clipboard, switch view to plain text mode 

    also do the corresponding changes in parent() and index()
    When you know how to do it then you may do it wrong.
    When you don't know how to do it then it is not that you may do it wrong but you may not do it right.

  9. #9
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Updating a view's proxy model when the source model changes

    Being new to Qt in general, I'm a bit lost... The parent() and index() functions have not been implemented in the source model. I presume that's something that needs to be done? Any examples you could point to that might fill in the gaps in my understanding on this?

  10. #10
    Join Date
    May 2013
    Posts
    35
    Thanks
    1
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Updating a view's proxy model when the source model changes

    I may not have a clear enough understanding of Qt, but could it be that the proxied view gets messed up because the item is being manipulated w.r.t the source model parent index and not the proxy model? That is, I presume each proxy has a local parent for it's filtered version of the source model (since it will have it's own unique index values)... So, if the drag/drop and related operations reference the items according to the source model's parent, then it would make sense that they would get screwed up when rendered in a view that is filtered by a proxy...

    Which would suggest implementing the source model methods that take a parent() parameter in the proxy and calling the source model method with mapToSource() ... ?

  11. #11
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Updating a view's proxy model when the source model changes

    What is you model based on QAbstractItemModel/QAbstractTableModel/QStandardItemModel?
    When you know how to do it then you may do it wrong.
    When you don't know how to do it then it is not that you may do it wrong but you may not do it right.

Similar Threads

  1. Replies: 1
    Last Post: 29th August 2013, 05:41
  2. Source Model Ad Proxy Model
    By sajis997 in forum Qt Programming
    Replies: 1
    Last Post: 19th July 2011, 05:13
  3. Replies: 0
    Last Post: 16th November 2010, 09:55
  4. Model, View and Proxy
    By No-Nonsense in forum Qt Programming
    Replies: 2
    Last Post: 21st November 2006, 08:50
  5. Filter Proxy Model to Autoupdate View
    By Big Duck in forum Qt Programming
    Replies: 1
    Last Post: 1st June 2006, 20:32

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.