Results 1 to 8 of 8

Thread: QSqlTableModel::SetData on different column

  1. #1
    Join Date
    Jan 2014
    Posts
    8
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default QSqlTableModel::SetData on different column

    I have a QSqlTableModel that works well and all the slots are firing, but I need to update a different column when an check box is clicked.

    The code I have right now is below and I just can't get the model to update a different column in the index

    Qt Code:
    1. #include <QtSql>
    2. #include <QTextCharFormat>
    3. #include <QtDebug>
    4. #include <QCheckBox>
    5.  
    6. #include "includes/selectionsetmodel.h"
    7.  
    8.  
    9. selectionsetSqlModel::selectionsetSqlModel(QObject *parent) : QSqlTableModel(parent)
    10. {
    11. }
    12.  
    13. //! [0]
    14. QVariant selectionsetSqlModel::data(const QModelIndex &index, int role) const
    15. {
    16. QVariant value = QSqlQueryModel::data(index, role);
    17. int col = index.column();
    18.  
    19. switch(role){
    20. case Qt::DisplayRole:
    21. if (col == 6)
    22. {
    23. if (value.toInt()<1024)
    24. {
    25. return QString(QString::number(value.toInt()) + "B");
    26. }
    27. else
    28. {
    29. return QString(QString::number(value.toInt()/1024) + "KB");
    30. }
    31. }
    32. else
    33. {
    34. return QString(value.toString());
    35. }
    36. case Qt::FontRole:
    37.  
    38. // QFont boldFont;
    39. // boldFont.setBold(true);
    40. // return boldFont;
    41.  
    42. case Qt::BackgroundRole:
    43.  
    44. case Qt::TextAlignmentRole:
    45. if (col == 5 or col == 6)
    46. {
    47. return Qt::AlignRight + Qt::AlignVCenter;
    48. }
    49. if (col == 2)
    50. {
    51. return Qt::AlignVCenter;
    52. }
    53. case Qt::CheckStateRole:
    54. int selected = index.model()->data(index.model()->index(index.row(), 1), Qt::DisplayRole).toInt();
    55. if (col == 2 )
    56. {
    57. if(selected==1)
    58. {
    59. return Qt::Checked;
    60. }
    61. else
    62. {
    63. return Qt::Unchecked;
    64. }
    65. }
    66. }
    67. return QVariant();
    68. }
    69.  
    70. Qt::ItemFlags selectionsetSqlModel::flags ( const QModelIndex & index ) const
    71. {
    72. if (index.column() == 2)
    73. return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ;
    74. else
    75. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    76. }
    77.  
    78. bool selectionsetSqlModel::setData(const QModelIndex& index,const QVariant& value,int role)
    79. {
    80.  
    81. bool v;
    82. if(role == Qt::CheckStateRole && index.column() == 2)
    83. {
    84. bool selected = index.model()->data(index.model()->index(index.row(), 1), Qt::DisplayRole).toBool();
    85. v = selected ? false : true;
    86. }
    87. //QModelIndex idx = QModelIndex(index.row(), 1, index);
    88. //bool r = this->setData(idx,v,role);
    89. QModelIndex top = createIndex(index.row(), 0);
    90. QModelIndex bottom = createIndex(index.row(), 3);
    91.  
    92. emit dataChanged(top, bottom); // emit layoutChanged() if headers changed
    93. //qDebug() << "Now Checkable Column: " << r << " = " << v;
    94. return true;
    95. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by silmaril; 30th January 2014 at 20:58.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QSqlTableModel::SetData on different column

    Nothing in your code tries to set the value of any column. As it stands I cannot see how you could update anything at all in the table as you never call the base implementation.

    I think you want column 1 of the model to hold the state of the checkbox displayed against column 2.

    You want something like this (untested code):
    Qt Code:
    1. QVariant selectionsetSqlModel::data(const QModelIndex &index, int role) const
    2. {
    3. ...
    4. case Qt::CheckStateRole:
    5. if (index.column() == 2) {
    6. const QModelIndex sibling = index.sibling(index.row(), 1);
    7. return sibling.data(Qt::EditRole);
    8. }
    9. ...
    10. }
    11.  
    12. bool selectionsetSqlModel::setData(const QModelIndex& index,const QVariant& value,int role)
    13. {
    14. if (role == Qt::CheckStateRole && index.column() == 2) {
    15. const QModelIndex sibling = index.sibling(index.row(), 1);
    16. bool ret = setData(sibling, value, Qt::EditRole);
    17. if (ret) emit dataChanged(index, index);
    18. return ret;
    19. }
    20. else
    21. return QSqlTableModel::setData(index, value, role);
    22. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by ChrisW67; 31st January 2014 at 00:21.

  3. #3
    Join Date
    Jan 2014
    Posts
    8
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: QSqlTableModel::SetData on different column

    Thank you for the reply.

    I tried the code but it still does not update the view:

    Qt Code:
    1. bool selectionsetSqlModel::setData(const QModelIndex& index,const QVariant& value,int role)
    2. {
    3.  
    4. {
    5. if (role == Qt::CheckStateRole && index.column() == 2) {
    6. bool selected = index.model()->data(index.model()->index(index.row(), 1), Qt::DisplayRole).toBool();
    7. QVariant v = selected ? false : true;
    8. qDebug() << v;
    9. const QModelIndex sibling = index.sibling(index.row(), 1);
    10.  
    11. QModelIndex top = createIndex(index.row(), 0);
    12. QModelIndex bottom = createIndex(index.row(), 3);
    13.  
    14. emit dataChanged(top, bottom); // emit layoutChanged() if headers changed
    15. return setData(sibling, v, Qt::EditRole);
    16. }
    17. else
    18. return QSqlTableModel::setData(index, value, role);
    19. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2014
    Posts
    8
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: QSqlTableModel::SetData on different column

    Ok, looking at your code I've tried multiple options but it seems to has the same outcome.

    I first tried the code you provided as is and the following code:
    Qt Code:
    1. bool selectionsetSqlModel::setData(const QModelIndex& index,const QVariant& value,int role)
    2. {
    3.  
    4. {
    5. if (role == Qt::CheckStateRole && index.column() == 2) {
    6. const QModelIndex sibling = index.sibling(index.row(), 1);
    7. bool ret = setData(sibling, value, Qt::EditRole);
    8. if (ret) emit dataChanged(index, index);
    9. qDebug() << "Success: "<<ret << " = " << value;
    10. return ret;
    11. }
    12. else
    13. return QSqlTableModel::setData(index, value, role);
    14. }
    To copy to clipboard, switch view to plain text mode 

    When the checkbox is checked, the value it tries to set the value to is:
    QVariant(int, 0) "Success: false = QVariant(int, 0) "

    When the checkbox is unchecked, the value it tried to set the value to is
    QVariant(int, 2) "Success: false = QVariant(int, 2)"

    In both instances the setData returns a "false".

    If I change the code to the following:
    Qt Code:
    1. bool selectionsetSqlModel::setData(const QModelIndex& index,const QVariant& value,int role)
    2. {
    3.  
    4. {
    5. if (role == Qt::CheckStateRole && index.column() == 2) {
    6. //bool selected = index.model()->data(index.model()->index(index.row(), 1), Qt::DisplayRole).toBool();
    7. const QModelIndex sibling = index.sibling(index.row(), 1);
    8. v = value.toInt() == Qt::Checked ? true : false;
    9. bool ret = setData(sibling, v, Qt::EditRole);
    10. if (ret) emit dataChanged(index, index);
    11. qDebug() << "Success: "<<ret << " = " << value;
    12. return ret;
    13. }
    14. else
    15. return QSqlTableModel::setData(index, value, role);
    16. }
    To copy to clipboard, switch view to plain text mode 

    The set values changes to bool with true and false, but it still fails:
    Success: false = QVariant(bool, false)
    Success: false = QVariant(bool, true)

    Any suggestions around why setData refuses to set the SQL record?

  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QSqlTableModel::SetData on different column

    What data type is the column underlying column 1?

    A complete example:
    Qt Code:
    1. #include <QtGui>
    2. #include <QtSql>
    3. #include <QDebug>
    4.  
    5. class MyModel: public QSqlTableModel {
    6. Q_OBJECT
    7. public:
    8. explicit MyModel(QObject *p = 0): QSqlTableModel(p) {
    9. }
    10.  
    11. Qt::ItemFlags flags ( const QModelIndex & index ) const {
    12. if (index.column() == 2)
    13. return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ;
    14. else
    15. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    16. }
    17.  
    18. QVariant data(const QModelIndex &index, int role) const {
    19. if (role == Qt::CheckStateRole && index.column() == 2) {
    20. const QModelIndex sibling = index.sibling(index.row(), 1);
    21. return sibling.data(Qt::EditRole);
    22. }
    23. else
    24. return QSqlTableModel::data(index, role);
    25. }
    26.  
    27. bool setData(const QModelIndex& index,const QVariant& value,int role) {
    28. if (role == Qt::CheckStateRole && index.column() == 2) {
    29. const QModelIndex sibling = index.sibling(index.row(), 1);
    30. bool ret = setData(sibling, value, Qt::EditRole);
    31. if (ret) emit dataChanged(index, index);
    32. qDebug() << "Success:"<< ret << "Value:" << value;
    33. return ret;
    34. }
    35. else
    36. return QSqlTableModel::setData(index, value, role);
    37. }
    38. };
    39.  
    40. int main(int argc, char *argv[]) {
    41. QApplication app(argc, argv);
    42.  
    43. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    44. db.setDatabaseName(":memory:");
    45. db.open();
    46.  
    47. QSqlQuery query;
    48. query.exec("create table test ( col0 int, col1 int, col2 text )");
    49. query.exec("insert into test values(101, 2, 'Row 0')");
    50. query.exec("insert into test values(102, 2, 'Row 1')");
    51. query.exec("insert into test values(103, 0, 'Row 2')");
    52. query.exec("insert into test values(104, 0, 'Row 3')");
    53. query.exec("insert into test values(105, 2, 'Row 4')");
    54.  
    55. MyModel model;
    56. model.setTable("test");
    57. model.select();
    58.  
    59. QTableView view;
    60. view.setModel(&model);
    61. view.show();
    62. return app.exec();
    63. }
    64. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 
    I am choosing to store that actual Qt::CheckState value, but you could convert to/from Y/N character or 0/1 integer etc.

  6. #6
    Join Date
    Jan 2014
    Posts
    8
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: QSqlTableModel::SetData on different column

    Thanks again for the reply...

    I took your code and it seems to be doing the same as my code. It renders the checkbox, but it does not allow you to change the checkbox:

    Qt Code:
    1. #include <QtGui>
    2. #include <QtSql>
    3. #include <QDebug>
    4. #include <QTableView>
    5. #include <QApplication>
    6.  
    7.  
    8. class MyModel: public QSqlTableModel {
    9. Q_OBJECT
    10. public:
    11. explicit MyModel(QObject *p = 0): QSqlTableModel(p) {
    12. }
    13.  
    14. Qt::ItemFlags flags ( const QModelIndex & index ) const {
    15. if (index.column() == 2)
    16. return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ;
    17. else
    18. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    19. }
    20.  
    21. QVariant data(const QModelIndex &index, int role) const {
    22. if (role == Qt::CheckStateRole && index.column() == 2) {
    23. const QModelIndex sibling = index.sibling(index.row(), 1);
    24. return sibling.data(Qt::EditRole);
    25. }
    26. else
    27. return QSqlTableModel::data(index, role);
    28. }
    29.  
    30. bool setData(const QModelIndex& index,const QVariant& value,int role) {
    31. if (role == Qt::CheckStateRole && index.column() == 2) {
    32. const QModelIndex sibling = index.sibling(index.row(), 1);
    33. bool ret = setData(sibling, value, Qt::EditRole);
    34. if (ret) emit dataChanged(index, index);
    35. qDebug() << "Success:"<< ret << "Value:" << value;
    36. return ret;
    37. }
    38. else
    39. return QSqlTableModel::setData(index, value, role);
    40. }
    41. };
    42.  
    43. int main(int argc, char *argv[]) {
    44. QApplication app(argc, argv);
    45.  
    46. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    47. db.setDatabaseName(":memory:");
    48. db.open();
    49.  
    50. QSqlQuery query;
    51. query.exec("create table test ( col0 int, col1 int, col2 text )");
    52. query.exec("insert into test values(101, 2, 'Row 0')");
    53. query.exec("insert into test values(102, 2, 'Row 1')");
    54. query.exec("insert into test values(103, 0, 'Row 2')");
    55. query.exec("insert into test values(104, 0, 'Row 3')");
    56. query.exec("insert into test values(105, 2, 'Row 4')");
    57.  
    58. MyModel model;
    59. model.setTable("test");
    60. model.select();
    61.  
    62. QTableView view;
    63. view.setModel(&model);
    64. view.show();
    65. return app.exec();
    66. }
    67. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 


    Debugging output is:
    Qt Code:
    1. Success: false Value: QVariant(int, 2)
    2. Success: false Value: QVariant(int, 2)
    3. Success: false Value: QVariant(int, 2)
    4. Success: false Value: QVariant(int, 2)
    5. Success: false Value: QVariant(int, 0)
    6. Success: false Value: QVariant(int, 0)
    7. Success: false Value: QVariant(int, 0)
    8. Success: false Value: QVariant(int, 0)
    9. Success: false Value: QVariant(int, 0)
    10. Success: false Value: QVariant(int, 0)
    11. Success: false Value: QVariant(int, 0)
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Jan 2014
    Posts
    8
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: QSqlTableModel::SetData on different column

    Seems after many hours one will eventually figure stuff out. It seems the "Qt:isplayRole" slot was causing me the problems.

    I changed:

    Qt Code:
    1. case Qt::DisplayRole:
    2. if (col == 6)
    3. {
    4. if (value.toInt()<1024)
    5. {
    6. return QString(QString::number(value.toInt()) + "B");
    7. }
    8. else
    9. {
    10. return QString(QString::number(value.toInt()/1024) + "KB");
    11. }
    12. }
    13. return value;
    To copy to clipboard, switch view to plain text mode 

    to

    Qt Code:
    1. case Qt::DisplayRole:
    2. if (col == 6)
    3. {
    4. if (value.toInt()<1024)
    5. {
    6. return QString(QString::number(value.toInt()) + "B");
    7. }
    8. else
    9. {
    10. return QString(QString::number(value.toInt()/1024) + "KB");
    11. }
    12. }
    13. return QSqlTableModel::data(index, Qt::DisplayRole).toString();
    To copy to clipboard, switch view to plain text mode 

  8. #8
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QSqlTableModel::SetData on different column

    I took your code and it seems to be doing the same as my code. It renders the checkbox, but it does not allow you to change the checkbox:
    My code was built and tested as working on Qt 4.8.5. I just built it with 5.2 to get the same result as you: Qt5 interprets the flags slightly differently and will not let the code update a column that is not editable. This version of flags() works with both Qt versions:
    Qt Code:
    1. Qt::ItemFlags flags ( const QModelIndex & index ) const {
    2. Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
    3. if (index.column() == 2)
    4. f |= Qt::ItemIsUserCheckable;
    5. return f;
    6. }
    To copy to clipboard, switch view to plain text mode 

    Seems after many hours one will eventually figure stuff out. It seems the "Qt::DisplayRole" slot was causing me the problems.
    AFAICT this has nothing to do with the column containing the checkbox state, the one displaying the checkbox, or the topic of the thread.

Similar Threads

  1. QSqlTableModel remove column by name
    By qlands in forum Qt Programming
    Replies: 2
    Last Post: 5th July 2011, 12:48
  2. QSqlTableModel column customization
    By kishore7771 in forum Qt Programming
    Replies: 1
    Last Post: 16th October 2009, 09:07
  3. QSqlTableModel setData not working?
    By jon-ecm in forum Qt Programming
    Replies: 10
    Last Post: 7th May 2009, 06:30
  4. QSqlTableModel and possible bug with setData?
    By sylvainb in forum Qt Programming
    Replies: 2
    Last Post: 25th February 2009, 21:43
  5. Sum of a column in QSqlTableModel
    By giusepped in forum Qt Programming
    Replies: 4
    Last Post: 10th November 2008, 23:38

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.