PDA

View Full Version : Sort QTableView Columns with drag and drop



aguayro
5th January 2013, 12:49
I'm trying to set Drag and Drog columns to my QTabeView, but it's a bit frustrating.
I've been googling about 2 days, and tryng a lot of things:
-Setted the table to DragDrop enabled + internal move via Qt Designer, via code, enabled QHeaderView::setSectionsMovable(), etc.. but nothing works.
I think that the problem is that i reimplemented data an HeaderData in my custom QAbstractTableModel:


QVariant rs_GameModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role != Qt::DisplayRole)
return QVariant();
if (role == Qt::DisplayRole) {
if (section == cols.at(0)) {
return tr("Juego");
} else if (section == cols.at(1)) {
return tr("Tipo");
} else if (section == cols.at(2)) {
return tr("Valoracion");
} else if (section == cols.at(3)) {
return tr("Emulador");
} else if (section == cols.at(4)) {
return tr("Usos");
} else if (section == cols.at(5)) {
return tr("Genero");
} else if (section == cols.at(6)) {
return tr("Idioma");
} else if (section == cols.at(7)) {
return tr("Año");
} else if (section == cols.at(8)) {
return tr("Compañia");
} else if (section == cols.at(9)) {
return tr("Jugadores");
} else if (section == cols.at(10)) {
return tr("Ruta");
}
}
return QVariant();
}


QVariant rs_GameModel::data(const QModelIndex &index, int role) const {
if (!index.isValid()) {
return QVariant();
}
if (index.row() >= romCount || index.row() < 0 ) {
return QVariant();
}

if (role == Qt::TextAlignmentRole) {
if (index.column() > 0 && index.column() < 10) {
return Qt::AlignHCenter;
}

}
if (role == Qt::UserRole) {
if (index.column() == cols.at(0)) {
return ROMs.at(index.row()).section(";", 11, 11);
}
}
if (role == Qt::DecorationRole) {
if (index.column() == cols.at(0)) {
return QIcon(QString("Skin/%1/icons/sys/rom16.png").arg(CurrSkin));
}
if (index.column() == cols.at(1)) {
QString tmpExt = ROMs.at(index.row()).section(";", 1, 1);

if (tmpExt.compare("zip", Qt::CaseInsensitive) == 0 || tmpExt.compare("7Z", Qt::CaseInsensitive) == 0 || tmpExt.compare("r", Qt::CaseInsensitive) == 0 ) {
return QIcon(QString("Skin/%1/icons/sys/compressed16.png").arg(CurrSkin));
} else if (tmpExt.compare("iso", Qt::CaseInsensitive) == 0 || tmpExt.compare("cue", Qt::CaseInsensitive) == 0 || tmpExt.compare("bin", Qt::CaseInsensitive) == 0 ||
tmpExt.compare("nrg", Qt::CaseInsensitive) == 0 || tmpExt.compare("mdf", Qt::CaseInsensitive) == 0 || tmpExt.compare("mds", Qt::CaseInsensitive) == 0 ) {
return QIcon(QString("Skin/%1/icons/sys/cddvd16.png").arg(CurrSkin));
} else {
return QIcon(QString("Skin/%1/icons/sys/cartridge16.png").arg(CurrSkin));;
}
}
}
if (role == Qt::DisplayRole) {
if (index.column() == cols.at(0)) {
return ROMs.at(index.row()).section(";", 0, 0);
}

if (index.column() == cols.at(3)) {
if (ROMs.at(index.row()).section(";", 3,3) == "0") {
return cEmulator;
} else { return ROMs.at(index.row()).section(";", 3,3); }
}
if (index.column() == cols.at(4)) {
return ROMs.at(index.row()).section(";", 4, 4);
}
if (index.column() == cols.at(6)) {
return ROMs.at(index.row()).section(";", 6, 6);
}
if (index.column() == cols.at(10)) {
return ROMs.at(index.row()).section(";", 10, 10);
}

}

return QVariant();
}

Probably the problem is that i must change de content of "cols" members, that should change the column for each section, i'm right?
So i need a signal, or something to know when and what "cols" members have to change. Tryed QHeaderView::sectionMoved(int,int,int) signal, but seems that the signal is not emitted.
Really need some clue to know how could approach this.
Maybe need i reimplement any move related function on my custom QAbstractTableModel? Any help will be appreciated, i'm stucked with this, and i think this is an standard feature for any app, so i must find a way to implement it.
thanks in advance.

Santosh Reddy
5th January 2013, 14:14
The problem you are facing is with Sort/Filter model, which you have not posted.

Did you look at Basic Sort/Filter Model Example (http://doc.qt.digia.com/qt/itemviews-basicsortfiltermodel.html), it does the same thing you are looking for

aguayro
5th January 2013, 14:20
I've readed the example, but it seems to be a sorting cells example, i'm right?
I want move columns withouth sort the column's cells, only move the cells with the header moved, just swap columns.

Santosh Reddy
5th January 2013, 15:00
You can drag drop the columns in the example. Try running it.

aguayro
5th January 2013, 15:45
i've runned the example, the last two columns are swapable as you said, but in my QTableView, i can't see any drop indicator, it seems like a "picture of a table", i click and drag, but nothing changes, there is no a header shadow indicating where to move the column.

I've tryed:



ui->gameView->setDragEnabled(true);
ui->gameView->setDragDropMode(QTableView::InternalMove);
ui->gameView->horizontalHeader()->setSectionsMovable(true);
ui->gameView->horizontalHeader()->setDropIndicatorShown(true);
ui->gameView->horizontalHeader()->setDragEnabled(true);
ui->gameView->horizontalHeader()->setDragDropMode(QTableView::InternalMove);


I'm very confused with this, nothing seems to work. The headers are static, only can resize them and click to sort cells, but no way to drag.

EDIT: Ok, I solved it, was a own mistake in app structure, some header routines seems to work before the table is fill, some others not. Thanks for the help!!

baloo
21st November 2013, 13:14
i've the same problem, someone can explain me the solution?

Thanks