Results 1 to 12 of 12

Thread: Tabview update after the model data changes

  1. #1
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Tabview update after the model data changes

    I have searched and not found an answer that works. That may be because I still don't get the tableview --> model connection...

    I have a QTableView and it's associated model and the model data starts out empty.

    At some point the data is changed (in this case the data starts out empty and is added to) (I can see the data in the model has changed in the debugger)

    But, the table view doesn't update.

    The code that does the update:
    Qt Code:
    1. self.tablemodel.setData(self.tablemodel.rowCount(None), newitemindex,0)
    2. self.tableView_ControlsInStrip.resizeColumnsToContents()
    3. self.tableView_ControlsInStrip.selectRow(0)
    To copy to clipboard, switch view to plain text mode 

    The table model looks like this:
    Qt Code:
    1. class MyTableModel(QtCore.QAbstractTableModel):
    2. def __init__(self, datain, headerdata, parent=None):
    3. """
    4. Args:
    5. datain: a list of lists\n
    6. headerdata: a list of strings
    7. """
    8. QtCore.QAbstractTableModel.__init__(self, parent)
    9. self.arraydata = datain
    10. self.headerdata = headerdata
    11.  
    12. def rowCount(self, parent):
    13. return len(self.arraydata)
    14.  
    15. def columnCount(self, parent):
    16. if len(self.arraydata) > 0:
    17. return len(self.arraydata[0])
    18. return 0
    19.  
    20. def data(self, index, role):
    21. if not index.isValid():
    22. return QVariant()
    23. # elif role == Qt.BackgroundColorRole:
    24. # #print (self.arraydata[index.row()][7])
    25. # if self.arraydata[index.row()][7] == 'Stage':
    26. # return QBrush(Qt.blue)
    27. # elif self.arraydata[index.row()][7] == 'Sound':
    28. # return QBrush(Qt.yellow)
    29. # elif self.arraydata[index.row()][7] == 'Light':
    30. # return QBrush(Qt.darkGreen)
    31. # elif self.arraydata[index.row()][7] == 'Mixer':
    32. # return QBrush(Qt.darkYellow)
    33. # else:
    34. # return QBrush(Qt.darkMagenta)
    35. #
    36. elif role != QtCore.Qt.DisplayRole:
    37. return QtCore.QVariant()
    38. return QtCore.QVariant(self.arraydata[index.row()][index.column()])
    39.  
    40. def setData(self, index, value, role):
    41. self.arraydata.extend([supportedcontroltypes[index]])
    42. self.dataChanged.emit(self.createIndex(0,0),
    43. self.createIndex(self.rowCount(None),self.columnCount(None)))
    44.  
    45. def headerData(self, col, orientation, role):
    46. if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
    47. return QtCore.QVariant(self.headerdata[col])
    48. return QtCore.QVariant()
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    Why are you ignoring the "role" in the setData() call? Who is calling setData(), and with what value(s)? Is it always your code, and is it always with a Qt.DisplayRole value for the role? If not, then you need to check that the role == Qt.DisplayRole and if not, do nothing.

    Likewise, you do not check that "index" is valid; indeed, you ignore index entirely - what is index is invalid or pointing to an already existing element of arrayData? Your code seems to assume that it's always going to point beyond the end of the array, so you have to extend it.

    And you ignore the "value" argument as well. Which begs the question - if your code is calling setData() and then ignoring everything that is passed as argument except self, why is your code bothering to call it at all? If what you want to do is to extend the array, then write yourself a custom method for your model that does that, don't override and misuse a standard model method. With the code as you've written it, you have no way to change existing elements in the model.

    In C++, the setData() method is supposed to return "true" if the update was successful, "false" if not. Your implementation doesn't return anything. The default implementation returns false, so perhaps that is why the view update isn't occurring.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Tabview update after the model data changes

    Quote Originally Posted by d_stranz View Post
    Why are you ignoring the "role" in the setData() call? Who is calling setData(), and with what value(s)? Is it always your code, and is it always with a Qt.DisplayRole value for the role? If not, then you need to check that the role == Qt.DisplayRole and if not, do nothing.

    Likewise, you do not check that "index" is valid; indeed, you ignore index entirely - what is index is invalid or pointing to an already existing element of arrayData? Your code seems to assume that it's always going to point beyond the end of the array, so you have to extend it.

    And you ignore the "value" argument as well. Which begs the question - if your code is calling setData() and then ignoring everything that is passed as argument except self, why is your code bothering to call it at all? If what you want to do is to extend the array, then write yourself a custom method for your model that does that, don't override and misuse a standard model method. With the code as you've written it, you have no way to change existing elements in the model.

    In C++, the setData() method is supposed to return "true" if the update was successful, "false" if not. Your implementation doesn't return anything. The default implementation returns false, so perhaps that is why the view update isn't occurring.
    Well, I'll reply, not necessarily in order.

    "why is your code bothering to call it at all?"
    Because I'm trying to figure out how to call it correctly and have had little success after reading docs, trying examples, and searching the web until my eyes are dry and blurry. Hence a blundering attempt at something.

    "Who is calling setData()"
    I'm calling it in this case. The doc ( https://doc.qt.io/qt-5/qabstractitemmodel.html#setData ) doesn't, at least to me, indicate that it gets called by native code.

    "is it always with a Qt.DisplayRole value for the role"
    in this case, I didn't bother checking it because I'm calling and it is set to 0. (Obviously not what I'd set it to for REAL use, though, here again, I'm not sure what other role I might want.)

    "With the code as you've written it, you have no way to change existing elements in the model."
    So, self.arraydata is not the model data that is displayed in the table?

    "Your implementation doesn't return anything."
    I changed it to return true. The table is still blank.
    Last edited by drmacro; 3rd April 2017 at 20:24.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    I'm calling it in this case. The doc ( https://doc.qt.io/qt-5/qabstractitemmodel.html#setData ) doesn't, at least to me, indicate that it gets called by native code.
    Views that are editable call it. The Qt Model / View architecture works roughly like this when the view is some sort of table view:

    - the user clicks in the cell. This causes three things to happen: the table instantiates a widget for editing the value and places it in the space occupied by the cell, calls data() on the model using the EditRole to get the cell's value in editable form, then sets that value into the editor widget and sets input focus to it.

    - the user edits the value in the editor.

    - when editing concludes (user hits "Return", focus leaves the cell, whatever), the view copies the new value from the editor, destroys the edit widget, and then calls setData() on the model with the cell's index, new value, and EditRole role.

    - the model replaces the current value at "index" with the new value and emits dataChanged().

    - the view asks the model for the new formatted values to display in the range that has changed, using their indexes and DisplayRole.

    "With the code as you've written it, you have no way to change existing elements in the model."
    So, self.arraydata is not the model data that is displayed in the table?
    If your table allows editing, then what your setData() method does (no matter what cell is edited), is extend the array and emit dataChanged() with the coordinates of the entire data array as what has changed. Your arrayData -is- what's being displayed in the table, because that is what the data() method uses when asked to return something for Qt.DisplayRole.

    Your call to self.tablemodel.setData() also has an incorrect form for "index". It should be of the type "QModelIndex", not "int". This is an unfortunate side-effect of Python's lack of strict typing that it will allow any argument of any type in a method call, correct or not. A QModelIndex specifies both a row and a column for the model element. Your code assumes (I guess) a row only. Your code works because you allow the wrong type of argument, and because Python doesn't call you out for not following the rules. We C++ programmers can't get away with that.

    You haven't posted the code that shows how you create the model in the first place or how you tell the view about it, so the failure to update the view when changes are made could be due to something wrong there.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Tabview update after the model data changes

    The code that creates the tableview in this case:

    Qt Code:
    1. self.self.tabledata = []
    2. self.tablemodel = MyTableModel(self.tabledata, ['Controls'], self)
    3. self.tableView_ControlsInStrip.setModel(self.tablemodel)
    4. self.tableView_ControlsInStrip.resizeColumnsToContents()
    5. self.control_index = 0
    6. self.tableView_ControlsInStrip.selectRow(self.control_index)
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    Dunno. Looks OK to me, except that lines 4 - 6 won't really have any effect if the table has not yet been "shown" (eg. this code is executed in an __init__ method prior to a showEvent() on the table view). Until the table is actually visible on screen, its size is indeterminate, so calling a method like resizeColumnsToContent() has no effect. That particular method is not setting a flag, it is dynamically resizing the table view. If you call it once, then change the table values such that the width of the column(s) is different no resizing takes place until you call it again.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #7
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Tabview update after the model data changes

    The short answer is it turns out to be that I was not getting arraydata to be a list of lists.
    (If I understand correctly, the list should look like: [[col1, col2, col3],[col1, col2, col3],...]
    so each list is the columns of the row.)

    As I often do when I'm confused, I make a minimum version of the code and figure out how to get that working.
    This often helps enlighten me...
    I did and it is shown below.

    I was not able to grok a few things but this does work.

    The docs for rowCount() and columnCount() say they should return 0 if it is a table. (it's not clear to me from the
    docs whether, for a table it should ever return the actual count of rows/columns...) It shows the parent argument
    to be a QModelIndex. What I gleaned is that a parent for trees would have children, where a table cell does not.
    And, my experiments have always resulted in a non-valid parent when the selected cell of the table is sent as this argument.

    I was also never able to get insertRow() to insert a row.
    (Hence this example modifies the arraydata, then emits layoutChanged. Is this a valid or proper approach?)
    The docs indicate that insertRow() calls insertRows() which is virtual. But it is not clear to me from the docs whether
    my implementation of insertRows() MUST do all the actual inserting (is insertRow/s actually inserting a row in the
    model's modelindex and not the model data?)

    The docs also say:
    "If row is 0, the rows are prepended to any existing rows in the parent.

    If row is rowCount(), the rows are appended to any existing rows in the parent."

    So, but what if the current model data is empty? i.e. arraydata = []
    And, this appears to imply that rowCount() could return the actual number of rows...not 0 as noted above.

    It also says: "If parent has no children, a single column with count rows is inserted."
    But the parent ( a QModelIndex) for a table never has children.

    And what does the view actually do when beginInsertRows/endInsertRows are called? Does this allow the view to manage if the
    view needs to scroll or resize? Wouldn't this happen when layoutChanged is emitted anyway?

    Sorry for the long post.

    Qt Code:
    1. import sys
    2.  
    3. from PyQt5 import Qt, QtCore, QtGui, QtWidgets
    4. from PyQt5.QtCore import *
    5. from PyQt5.QtWidgets import *
    6.  
    7. import TableUpdate_ui
    8.  
    9. class TblUpd(QtWidgets.QDialog, TableUpdate_ui.Ui_Dialog):
    10. def __init__(self, parent=None):
    11. QDialog.__init__(self, parent)
    12. self.setupUi(self)
    13. self.pushButton_update.clicked.connect(self.on_update_btn_click)
    14. self.pushButton_add.clicked.connect(self.on_add_btn_click)
    15. self.pushButton_insert.clicked.connect(self.on_insert_btn_click)
    16. self.tabledata = []
    17. # set the table model
    18. self.tablemodel = MyTableModel(self.tabledata, ['Controls'], self)
    19. self.tableView.horizontalHeader().setVisible(True)
    20. self.tableView.setModel(self.tablemodel)
    21. self.tableView.resizeColumnsToContents()
    22. self.tableView.selectRow(0)
    23.  
    24. def on_update_btn_click(self):
    25. print('Update button clicked.')
    26. print('lineEdit.text = {0}'.format(self.lineEdit.text()))
    27. if self.lineEdit.text() == '':
    28. value = 'blank'
    29. else:
    30. value = self.lineEdit.text()
    31. print('value = {0}'.format(value))
    32. selectedindex = self.tableView.currentIndex()
    33. print(self.tablemodel.setData(selectedindex, value,
    34. QtCore.Qt.EditRole))
    35. self.tableView.resizeColumnsToContents()
    36. pass
    37.  
    38. def on_add_btn_click(self):
    39. print('Insert button clicked.')
    40. print('lineEdit.text = {0}'.format(self.lineEdit.text()))
    41. if self.lineEdit.text() == '':
    42. value = 'blank'
    43. else:
    44. value = self.lineEdit.text()
    45. print('value = {0}'.format(value))
    46. self.tablemodel.arraydata.extend([[value]])
    47. self.tablemodel.layoutChanged.emit()
    48. self.tableView.resizeColumnsToContents()
    49.  
    50. def on_insert_btn_click(self):
    51. print('Insert clicked.')
    52. if self.lineEdit.text() == '':
    53. value = 'blank'
    54. else:
    55. value = self.lineEdit.text()
    56. print('value = {0}'.format(value))
    57. selectedindex = self.tableView.currentIndex()
    58. self.tablemodel.arraydata.insert(selectedindex.row(), [value])
    59. self.tablemodel.layoutChanged.emit()
    60. self.tableView.resizeColumnsToContents()
    61. pass
    62.  
    63. class MyTableModel(QtCore.QAbstractTableModel):
    64. def __init__(self, datain, headerdata, parent=None):
    65. """
    66. Args:
    67. datain: a list of lists\n
    68. headerdata: a list of strings
    69. """
    70. QtCore.QAbstractTableModel.__init__(self, parent)
    71. self.arraydata = datain
    72. self.headerdata = headerdata
    73.  
    74. def rowCount(self, parent):
    75. if parent.isValid():
    76. return 0
    77. return len(self.arraydata)
    78.  
    79. def columnCount(self, parent):
    80. if parent.isValid():
    81. return 0
    82. else:
    83. return 1
    84.  
    85. def data(self, index, role):
    86. print('In data()')
    87. if not index.isValid():
    88. print('Invalid index in MyModel>data')
    89. retval = QtCore.QVariant()
    90. elif role != QtCore.Qt.DisplayRole:
    91. retval = QtCore.QVariant()
    92. else:
    93. retval = QtCore.QVariant(self.arraydata[index.row()][index.column()])
    94. print(self.arraydata[index.row()][index.column()])
    95. print(retval)
    96. return retval
    97.  
    98. def setData(self, index, value, role):
    99. if role == QtCore.Qt.EditRole and index.isValid():
    100. print(index.row())
    101. self.arraydata[index.row()] = [value]
    102. print('Return from rowCount: {0}'.format(self.rowCount(index)))
    103. self.dataChanged.emit(index, index, [QtCore.Qt.DisplayRole])
    104. return True
    105. return False
    106.  
    107. def headerData(self, col, orientation, role):
    108. if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
    109. return QtCore.QVariant(self.headerdata[col])
    110. return QtCore.QVariant()
    111.  
    112. def main():
    113. app = QtWidgets.QApplication(sys.argv)
    114. tblupd = TblUpd()
    115. tblupd.show()
    116. sys.exit(app.exec_())
    117.  
    118. if __name__ == '__main__':
    119. main()
    To copy to clipboard, switch view to plain text mode 

  8. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    The docs for rowCount() and columnCount() say they should return 0 if it is a table.
    Where did you get that idea? Are you maybe misinterpreting the C++ syntax in the documentation of QAbstractItemModel::columnCount()?

    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
    This means that columnCount() is a pure virtual method that has no implementation in this base class ("= 0") and must be overridden and implemented in a derived class.

    A table model is basically a flat (row, column) matrix. For this type of model, if you are asked for the row or column count of an invalid QModelIndex (i.e. the "root" of the model), then you return the actual number of rows or columns in the matrix. For any other valid QModelIndex, you return zero because that implies that you are being asked for the number of child rows or columns of a given cell, which a flat matrix doesn't have. Only tree-structured models can have children within children.

    But it is not clear to me from the docs whether my implementation of insertRows() MUST do all the actual inserting (is insertRow/s actually inserting a row in the model's modelindex and not the model data?)
    For any method that modifies the table model, -you- must implement the code to modify the data array (list of lists) that underlies the model. You need to look at it this way: your list of lists is -your- representation of the data you want to display and modify. MyTableModel is the "glue" that connects your internal model to Qt's world of table views. So everything that the table view does to request data from or modify data in your list of lists goes through the MyTableModel glue. QAbstractTableModel, the base class, stores absolutely nothing. It is merely the definition of the interface that specifies the rules by which views interact with your model and how the model informs the views that its content is or has changed.

    The docs also say:
    "If row is 0, the rows are prepended to any existing rows in the parent.

    If row is rowCount(), the rows are appended to any existing rows in the parent."
    So your implementation has to do that. In the first case, you create a new row with the right number of empty column cells (i.e. a one element list containing a list of columns), append your existing list of lists to it, then assign the result back to your list of lists variable. In the second case, you need to create the same one element list of lists, then stick it on the end of the existing list. For a row in between you need to copy the existing list up to just before the indicated row, stick the new list onto that, then copy the rest of your existing list after that. The "insert" semantics imply "insert before" except when the insertion point is greater or equal to the number of rows.

    And what does the view actually do when beginInsertRows/endInsertRows are called?
    beginInsertRows() (or any of the "begin...() methods) emits a signal that the view listens for. When it gets that signal, it suspends any operations on the model, because the model has just told it it is changing and any model indexes the view has could become invalid or point to something else. endInsertRows() (or any end...() method) emits another signal that says, OK, I'm done making changes, you can now update that part of the view that was affected. modelAboutToBeReset() and modelReset() are the "nuclear option" - they tell the view that everything you know is wrong and that when it is all over you'll have to retrieve everything. These are useful when some external calculation updates the whole data set that the model wraps and there isn't really a way to do a partial update.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  9. The following user says thank you to d_stranz for this useful post:

    drmacro (6th April 2017)

  10. #9
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Tabview update after the model data changes

    d_stranz, as usual, your explanations are thorough and make it clear how things work!

    Where did you get that idea?
    Your explaination makes it very clear:
    A table model is basically a flat (row, column) matrix. For this type of model,
    if you are asked for the row or column count of an invalid QModelIndex (i.e. the "root" of the model),
    then you return the actual number of rows or columns in the matrix. For any other valid QModelIndex,
    you return zero because that implies that you are being asked for the number of child rows or columns
    of a given cell, which a flat matrix doesn't have. Only tree-structured models can have children within children.
    This from the doc page: http://doc.qt.io/qt-4.8/https://doc.qt.io/qt-5/qabstractitemmodel.html#rowCount does not:
    Note: When implementing a table based model, rowCount() should return 0 when the parent is valid.

    In fact, the rest of that doc on rowCount() never mentions tree. After your explanation, it's clear what to do with a tree and why (it's the why that I find missing
    often when reading doc...but, might be my issue.)

    I'm slowly learning how to extrapolate what the QT docs say and what they imply.
    For me, in many cases, it's sort of:
    Me:"How do you make bread?"
    Docs: "You use yeast and flower."
    Me: "And?..."

  11. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    For me, in many cases, it's sort of:
    Me:"How do you make bread?"
    Docs: "You use yeast and flower."
    Me: "And?..."
    Funny language, English... most bakers would use "flour" when making bread, but I am always interested in hearing new recipes.

    Note: When implementing a table based model, rowCount() should return 0 when the parent is valid.
    As I said in my last post.

    I agree, sometimes the only thing that makes sense in the Qt documentation are the tutorials and examples. The class documentation often leaves out important details that you don't understand until you look at an example. If you haven't looked at the Qt tutorials and examples, you should. Even if you aren't a C++ programmer, the language is similar enough to Python that I think you can follow them.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  12. #11
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Tabview update after the model data changes

    Quote Originally Posted by d_stranz View Post
    Funny language, English... most bakers would use "flour" when making bread, but I am always interested in hearing new recipes.



    As I said in my last post.

    I agree, sometimes the only thing that makes sense in the Qt documentation are the tutorials and examples. The class documentation often leaves out important details that you don't understand until you look at an example. If you haven't looked at the Qt tutorials and examples, you should. Even if you aren't a C++ programmer, the language is similar enough to Python that I think you can follow them.
    Yeah, that should have been flour...but, I'll bet you could dry flowers and make a flour.

    In a past life I did plenty of C/C++ so the examples aren't foreign to me. That said, sometimes I still seem to be left wanting details. And, sometimes there don't seem to be examples that cover what I'm attempting (but, that could be I just don't know where to look.)

    In any case, I appreciate you taking the time to explain!

    Quote Originally Posted by d_stranz View Post
    Funny language, English... most bakers would use "flour" when making bread, but I am always interested in hearing new recipes.



    As I said in my last post.

    I agree, sometimes the only thing that makes sense in the Qt documentation are the tutorials and examples. The class documentation often leaves out important details that you don't understand until you look at an example. If you haven't looked at the Qt tutorials and examples, you should. Even if you aren't a C++ programmer, the language is similar enough to Python that I think you can follow them.
    Yeah, that should have been flour...but, I'll bet you could dry flowers and make a flour.

    In a past life I did plenty of C/C++ so the examples aren't foreign to me. That said, sometimes I still seem to be left wanting details. And, sometimes there don't seem to be examples that cover what I'm attempting (but, that could be I just don't know where to look.)

    In any case, I appreciate you taking the time to explain!


    Added after 1 25 minutes:


    Ok, so if I want to use insertRow(), I need to implement insertRows().

    InsertRows() should start with beginInsertRow(), insert the row/s, then endInsertRow().

    InsertRow() and insertRows() don't have the new data for the row, thus insert empty rows in the model data.

    So, I'm missing how the new data gets into the the newly created row.

    If the insertRow() caller puts the data in, doesn't that potentially mess with the view, since the data will actually update after the endinsert has been called?

    I'm confused again...
    Last edited by drmacro; 6th April 2017 at 21:53.

  13. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Tabview update after the model data changes

    So, I'm missing how the new data gets into the the newly created row.
    That's what setData() is for. Your UI calls insertRow() / insertRows(), which do indeed insert a row / rows of empty lists of lists into your data array (and call beginInsertRows() before and endInsertRows() after inserting). Your UI can then optionally call setData() on each cell in each row to add actual data to the elements of the data array. For efficiency, you might want to implement custom model method(s), setRow() or setRows(), which take a row index and list of lists or list of row indexes and lists of lists, respectively, and update entire row(s) of your data array in one go. In such a case, instead of emitting dataChanged() for each cell (and causing a table view refresh for each cell), you change everything first, then emit dataChanged() for the entire set of cells. This results in one view refresh versus many.

    A really good book for understanding the model / view architecture is "Advanced Qt Programming" by Mark Summerfield. It is based on Qt4 and C++, but the M/V architecture hasn't changed all that much in Qt5 so almost everything still applies. Covers custom models, custom views, proxies, and more, with non-trivial examples.

    Edit: I say "empty list of lists", but actually this would be more like a list of empty strings: [ "", "", "", "", ... ] (size equal to the column count) if that's what your data array contains.

    Yeah, that should have been flour...but, I'll bet you could dry flowers and make a flour.
    Heh. I saw an episode of the TV show "Shark Tank" a week or so ago where someone was trying to raise money for making energy bars from flour made from dried crickets.
    Last edited by d_stranz; 6th April 2017 at 23:50.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 3
    Last Post: 28th January 2015, 01:09
  2. Replies: 4
    Last Post: 21st October 2013, 22:24
  3. Replies: 9
    Last Post: 14th February 2013, 20:39
  4. Replies: 0
    Last Post: 2nd November 2011, 12:13
  5. Replies: 1
    Last Post: 24th February 2011, 06:54

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.