简体   繁体   中英

How to move rows in Qt (in QTableWidget)

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 .

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
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM