Sort QTableView by several criteria
-
Hello every one.
I'm at Qt and c++ since 3 months.
I have the following table like this picture.
I'm trying to sort my table on the same way as you can see in the picture.
At first all red rows which are sorted from the highest to the lowest time.
After that the yellow and the green rows which ever are sortet from the lowest to the highest number of "Pts".I have the following database and fill it with an array.
db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName(":memory:"); if (!db.open()) { QMessageBox::critical(nullptr, QObject::tr("Cannot open database"), QObject::tr("Unable to establish a database connection.\n" "This example needs SQLite support. Please read " "the Qt SQL driver documentation for information how " "to build it.\n\n" "Click Cancel to exit."), QMessageBox::Cancel); query = new QSqlQuery; query->exec("Create Table CustomiseToolChange (COLOR varchar(20)," "TOOLNR, TIME int, POCKETSTATUS varchar(20))"); query->prepare("INSERT INTO CustomiseToolChange (COLOR, TOOLNR, TIME, POCKETSTATUS) " "VALUES (:COLOR, :TOOLNR, :TIME, :POCKETSTATUS)"); query->bindValue(":COLOR", ""); return; ... void test_screen::fillDatabaseTableCustomiseToolChange() { for (int i = 0; i < (30 / 3); i++) { query->bindValue(":TOOLNR", arrayCustomiseToolChange[i * 3 + 0]); query->bindValue(":TIME", arrayCustomiseToolChange[i * 3 + 1]); query->bindValue(":POCKETSTATUS", arrayCustomiseToolChange[i * 3 + 2]); query->exec(); } }
The number of rows (for example from the yellow rows) can vary.
Furthermore it is possible that one color not exist for an moment.How can I solve that problem.
I hope you understand what I'm trying to do. (my english is not the best)Thank you very much.
Regards Mogli.
-
Hi
What depends on the color of the cells? -
Did you already take a look at the QSortFilterProxyModel and the examples mentioned there?
-
Hi,
thank you for your answers.@Slawomir_Piernikowski
The color stands in a hidden column from the table, for example like this. (but there is the order not correct)
@Christian-Ehrlicher
Yes, I looked already at the docu but I'm not shure how can I manage that.
I hope someone can give me a tip or a smal example, for better understanding. -
Hi,
thank you for your answers.@Slawomir_Piernikowski
The color stands in a hidden column from the table, for example like this. (but there is the order not correct)
@Christian-Ehrlicher
Yes, I looked already at the docu but I'm not shure how can I manage that.
I hope someone can give me a tip or a smal example, for better understanding.@Mogli123 said in Sort QTableView by several criteria:
but I'm not shure how can I manage that.
I hope someone can give me a tip or a smal example, for better understanding.class ToolSorter : public QSortFilterProxyModel { Q_OBJECT Q_DISABLE_COPY(ToolSorter) public: explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){} protected: // this method is used by the proxy to determine if the index source_left should come before the index source_right*/ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{ const int leftRow = source_left.row(); // get the rows of the indexes const int rightRow= source_right.row(); const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString(); switch(colorCompare(leftColor,rightColor)){ // compare the colours case 1: return true; case -1: return false; default: return // if colours are the same comapre the time sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data() ; } } private: /* Compares the strings with colous: returns 0 if the colours are the same returns 1 if the colour left should go above colour right returns -1 if the colour right should go above colour left */ char colorCompare(const QString& left, const QString& right) const{ if(left==right) return 0; if(left == QLatin1String("yellow")) return 1; if(right== QLatin1String("yellow")) return -1; if(left == QLatin1String("red")) return 1; if(right== QLatin1String("red")) return -1; Q_UNREACHABLE(); return -2; } };
-
@Mogli123 said in Sort QTableView by several criteria:
but I'm not shure how can I manage that.
I hope someone can give me a tip or a smal example, for better understanding.class ToolSorter : public QSortFilterProxyModel { Q_OBJECT Q_DISABLE_COPY(ToolSorter) public: explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){} protected: // this method is used by the proxy to determine if the index source_left should come before the index source_right*/ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{ const int leftRow = source_left.row(); // get the rows of the indexes const int rightRow= source_right.row(); const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString(); switch(colorCompare(leftColor,rightColor)){ // compare the colours case 1: return true; case -1: return false; default: return // if colours are the same comapre the time sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data() ; } } private: /* Compares the strings with colous: returns 0 if the colours are the same returns 1 if the colour left should go above colour right returns -1 if the colour right should go above colour left */ char colorCompare(const QString& left, const QString& right) const{ if(left==right) return 0; if(left == QLatin1String("yellow")) return 1; if(right== QLatin1String("yellow")) return -1; if(left == QLatin1String("red")) return 1; if(right== QLatin1String("red")) return -1; Q_UNREACHABLE(); return -2; } };
-
@Mogli123 said in Sort QTableView by several criteria:
but I'm not shure how can I manage that.
I hope someone can give me a tip or a smal example, for better understanding.class ToolSorter : public QSortFilterProxyModel { Q_OBJECT Q_DISABLE_COPY(ToolSorter) public: explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){} protected: // this method is used by the proxy to determine if the index source_left should come before the index source_right*/ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{ const int leftRow = source_left.row(); // get the rows of the indexes const int rightRow= source_right.row(); const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString(); switch(colorCompare(leftColor,rightColor)){ // compare the colours case 1: return true; case -1: return false; default: return // if colours are the same comapre the time sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data() ; } } private: /* Compares the strings with colous: returns 0 if the colours are the same returns 1 if the colour left should go above colour right returns -1 if the colour right should go above colour left */ char colorCompare(const QString& left, const QString& right) const{ if(left==right) return 0; if(left == QLatin1String("yellow")) return 1; if(right== QLatin1String("yellow")) return -1; if(left == QLatin1String("red")) return 1; if(right== QLatin1String("red")) return -1; Q_UNREACHABLE(); return -2; } };
At first thank you very much for helping :).
I have implement your code but it is not completly correct (If I copied it correctly) and I not understand it realy.
I see you tried to make it understanderbel through inserting coments but I still did not understand it completely.Which value get the right- and leftRow?
The same with the QStrings right- and leftColorthats "my" code and the result:
.h
class sorter : public QSortFilterProxyModel { Q_OBJECT Q_DISABLE_COPY(sorter) public: explicit sorter(QObject* parent = Q_NULLPTR); protected: bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE; private: char colorCompare(const QString& left, const QString& right) const; };
.cpp
sorter::sorter(QObject *parent) : QSortFilterProxyModel(parent) { } //Methoden bool sorter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { // get the rows of the indexes const int leftRow = source_left.row(); const int rightRow= source_right.row(); const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString(); // compare the colours switch(colorCompare(leftColor,rightColor)) { case 1: return true; case -1: return false; default: // if colours are the same comapre the time return sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data(); } } char sorter::colorCompare(const QString& left, const QString& right) const { if(left==right) { return 0; } if(left == QLatin1String("yellow")) { return 1; } if(right== QLatin1String("yellow")) { return -1; } if(left == QLatin1String("red")) { return 1; } if(right== QLatin1String("red")) { return -1; } //wenn keines der Bedingungen eintrift wird -2 zurückgegeben Q_UNREACHABLE(); return -2; }
table.cpp
mySorter = new sorter(this); mySorter->setSourceModel(myTableCustomiseToolChange); myTableview->setModel(mySorter); //Tabelle wird sortiert myTableview->setSortingEnabled(true);
The green rows should be below the yellow rows and the green and yellow rows should sort from the lowest to the highest number.
The sorting from the red rows are correct.If you could explain the methodes more in detail I will try it by my self.
Sorry for the many questions.Regards mogli.
-
Everything seems fine, it's just sorted in descending order, you can call
myTableview->model()->sort(0,Qt::AscendingOrder);
to change the order to ascendingNow it works!!!
thank you very much!!!
I changed it following :
.cppif (leftColor == "red") { return sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data(); } else { return sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data() > sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data(); } ... char sorter::colorCompare(const QString& left, const QString& right) const { if(left==right) { return 0; } if(left == QLatin1String("green")) { return 1; } if(right== QLatin1String("green")) { return -1; } if(left == QLatin1String("yellow")) { return 1; } if(right== QLatin1String("yellow")) { return -1; } //wenn keines der Bedingungen eintrift wird -2 zurückgegeben Q_UNREACHABLE(); return -2; }
table.cpp
mySorter = new sorter(this); mySorter->setSourceModel(myTableCustomiseToolChange); myTableview->setModel(mySorter); //Tabelle wird sortiert myTableview->setSortingEnabled(true); myTableview->model()->sort(0,Qt::DescendingOrder);