Reputation: 657
It's really a shame that Qt devs skipped this really important part of a table... moving rows (probably the selected ones) with checks for collision and support for selections with gaps - now one has to implement it himself.
Luckily I spent pretty much the whole day creating such, self-contained function that can be easily modified to move anything related to tables/lists (currently it moves selected items - second line). And a more interesting part, I was able to easily (with about 3 lines more) add support for a direction argument instead of a separate function.
I haven't thought about it, but moving by more than 1 item at a time could be possible aswell - though I have no need for that.
Any suggestions and bug-testing is appreciated ~~enjoy.
Upvotes: 1
Views: 3453
Reputation: 11
Suppose your table has 6 columns and > 1 rows
int i = ui->tableWidget->currentRow();
if(i < 1)
return;
for(int col = 0; col < 6; col++)
{
QTableWidgetItem *i0 = ui->tableWidget->takeItem(i,col);
QTableWidgetItem *j0 = ui->tableWidget->takeItem(i-1,col);
ui->tableWidget->setItem(i-1,col,i0);
ui->tableWidget->setItem(i,col,j0);
}
Upvotes: 1
Reputation: 657
The code is (technically simple) quite complex, even without the check for collision, gaps and table endings so I'm not going to explain it right now, but I might later if this sprouts an interest.
Also, this code is c++11, not sure how much would have to be rewritten to compile it without the newer implementations, but just a heads up.
void moveSelected(QTableWidget* _table, MVDIRECTION _dir) {
QList<QTableWidgetItem*> list = _table->selectedItems();
if (list.count() == 0) {
perror("moveSelected(...) - no items supplied (NULL items)!\n");
return;
}
if (_dir == Down)
std::reverse(list.begin(), list.end());
int r_limit = (_dir == Up) ?0 :(_table->rowCount() - 1);
int r_last = list.first()->row() + _dir;
bool block = false;
QTableWidgetItem* buffer = NULL;
if (list.first()->row() != r_limit)
buffer = _table->takeItem(list.first()->row() + _dir, 0);
for (auto &item : list) {
if ( item->row() != (r_last - _dir) ) {
_table->setItem(r_last, 0, buffer);
buffer = _table->takeItem(item->row() + _dir, 0);
block = false;
}
r_last = item->row();
if ( (item->row() != r_limit) & (!block)) {
QTableWidgetItem* _item = _table->takeItem(item->row(), 0);
_table->setItem(r_last + _dir, 0, _item);
}
else if (!block) block = true;
}
if (buffer) _table->setItem(list.last()->row() - _dir, 0, buffer);
}
oh yeah, and just for readability, a MVDIRECTION enum:
enum MVDIRECTION {
Up = -1,
Down = 0
};
Upvotes: 1