Results 1 to 5 of 5

Thread: QTableWidget row swapping and insertion

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Nov 2006
    Location
    Almaty, Kazakhstan
    Posts
    8
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QTableWidget row swapping and insertion

    Hi all,

    I have placed a QTableWidget with 3 columns in Designer and promoted it to DataTableWidget. In implementation I have provided item delegates to have the first and the third column acting like QLineEdit and the second column acting like QComboBox. When cellChanged(int row, int) signal is emitted and if (row == rowCount() - 1) then a new row is added else if there is no data in the currently edited row (deleted just now) then the row is removed. I have also reimplemented insertRow() like this:

    Qt Code:
    1. void DataTableWidget::insertRow(int row)
    2. {
    3. QTableWidget::insertRow(row); // call the parent function
    4. // now make sure that all the cells exist
    5. setItem(row, 0, new QTableWidgetItem());
    6. setItem(row, 1, new QTableWidgetItem());
    7. setItem(row, 2, new QTableWidgetItem());
    8. }
    To copy to clipboard, switch view to plain text mode 

    Everything works like a charm, but now I have to implement an ability of moving rows up or down. I have provided a context menu with these actions, so when the user right-clicks on the cell:

    Qt Code:
    1. void DataTableWidget::contextMenuEvent(QContextMenuEvent* event)
    2. {
    3. // disable these actions by default
    4. rowDownAction->setEnabled(false);
    5. rowUpAction->setEnabled(false);
    6.  
    7. int row = rowAt(event->y());
    8.  
    9. if (row != -1) // if there is a row under cursor
    10. {
    11. selectRow(row);
    12. // if it is not the last row which is designed for entering new data only
    13. // and not the first row which cannot be moved up
    14. if (row != rowCount() - 1 && row > 0)
    15. rowUpAction->setEnabled(true);
    16.  
    17. // if it is not the last row with data
    18. // then we can move it down
    19. if (row < rowCount() - 2)
    20. rowDownAction->setEnabled(true);
    21. }
    22.  
    23. contextMenu->popup(QPoint(event->globalX(), event->globalY()));
    24. event->accept();
    25. }
    To copy to clipboard, switch view to plain text mode 

    The problem is that I don't know how to swap the rows. I mean

    Qt Code:
    1. void DataTableWidget::onRowDown()
    2. {
    3. // what is here?
    4. }
    To copy to clipboard, switch view to plain text mode 

    I have tried simple
    Qt Code:
    1. for (int c = 0; c < columnCount(); c++)
    2. {
    3. QTableWidgetItem* src = item(currentCell()->row(), c);
    4. QTableWidgetItem* dest = item(currentCell()->row() + 1, c);
    5. QTableWidgetItem* buf = src;
    6. src = dest;
    7. dest = buf;
    8. }
    To copy to clipboard, switch view to plain text mode 

    as well as

    Qt Code:
    1. for (int c = 0; c < columnCount(); c++)
    2. {
    3. QTableWidgetItem* src = item(currentCell()->row(), c);
    4. QTableWidgetItem* dest = item(currentCell()->row() + 1, c);
    5. setItem(currentCell()->row(), c, dest);
    6. setItem(currentCell()->row() + 1, c, src);
    7. }
    To copy to clipboard, switch view to plain text mode 

    but neither worked for me. Then I have decided to insertRow(currentCell()->row() + 1) and copy all the elements of the current row to the new row, then remove the current row. But I have discovered that it doesn't insertRow(int row) with row set to anything other than rowCount(). I mean the function is called and executed but nothing happens.

    How can I swap rows and insert a new row in random position of the table?

    thanks

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget row swapping and insertion

    This would be easier if you were using a model-view approach... There you would simply call insertRow, move the data and delete the old row. Here you could also try this - call insertRow(), then move data from items using setItem (the item will be removed from its origin) and finally call removeRow() on the old row. I doubt that insertRow() doesn't work for you, but if you're sure about it, maybe you should report it to Trolltech.

  3. #3
    Join Date
    Nov 2006
    Location
    Almaty, Kazakhstan
    Posts
    8
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTableWidget row swapping and insertion

    thanks for the response.

    as I understand, I actually use model-view, the cells of the table are the descendants of QItemDelegate, they are viewed as text and edited with QLineEdit and QComboBox. You might want to have a look at this, I'm attaching the widget class.
    Attached Files Attached Files

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget row swapping and insertion

    Yes, you are using model-view, but the actual model and view is hidden from you, you use convenience classes which keep their own internal model so for example you can't just reorder the internal structures of the model, because you don't have access to them - you have to do that manually by moving each item. If you had a real model, you could do something like this:

    Qt Code:
    1. void myModel::swapRows(QModelIndex i1, QModelIndex i2){
    2. Q_ASSERT(i1.isValid() && i2.isValid());
    3. int r1 = i1.row();
    4. int r2 = i2.row();
    5. if(r1==r2) return;
    6. MyStruct temp = _internaldata.at(r1);
    7. _internaldata[r1] = _internaldata[r2];
    8. _internaldata[r2] = temp;
    9. int cc = columnCount();
    10. emit dataChanged(i1.sibling(r1, 0), i1.sibling(r1, cc-1);
    11. emit dataChanged(i2.sibling(r2, 0), i2.sibling(r2, cc-1);
    12. }
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Nov 2006
    Location
    Almaty, Kazakhstan
    Posts
    8
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTableWidget row swapping and insertion

    Thanks, but looking like I feel myself not that experienced in Qt to use such a deep way.

    Okay, I have modified the code and now it inserts rows perfectly (you were right, that was my fault). It copies the values from the old row to the new one with setItem() as you told. So I have

    Qt Code:
    1. void DataTableWidget::onRowDown()
    2. {
    3. int crow = currentItem()->row();
    4.  
    5. insertRow(crow + 2);
    6.  
    7. setItem(crow + 2, 0, item(crow, 0));
    8. setItem(crow + 2, 1, item(crow, 1));
    9. setItem(crow + 2, 2, item(crow, 2));
    10.  
    11. removeRow(crow);
    12. }
    To copy to clipboard, switch view to plain text mode 

    I got SIGSEGV when I tried to removeRow(). I have commented it out and this code worked but the new row was somehow linked to the old one. I mean when I was changing data in the new row, the old one was changed in the same way and vice versa. Moreover when I had some changes in the widget and closed the dialogs, I had SIGSEGV too.

    Then I tried to find a way how to remove the old cells and decided to get them by takeItem(), not by item(). So the final code looks like

    Qt Code:
    1. void DataTableWidget::onRowDown()
    2. {
    3. int crow = currentItem()->row();
    4.  
    5. insertRow(crow + 2);
    6.  
    7. setItem(crow + 2, 0, takeItem(crow, 0));
    8. setItem(crow + 2, 1, takeItem(crow, 1));
    9. setItem(crow + 2, 2, takeItem(crow, 2));
    10.  
    11. removeRow(crow);
    12. }
    To copy to clipboard, switch view to plain text mode 
    And this thing works, and removeRow() works too. At least when moving rows down

    Thank you so much, wysota!

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
  •  
Qt is a trademark of The Qt Company.