Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Sort QSqlRelation in a QSqlTable model



  • Hi all,

    I'm trying to have the values comming from a QSqlRelation sorted alfabetically inside the combo box but I cannot find the way. I was reading the documentation of QSqlRelation but I think that it cannot be done from there. Any hint of how can do the sorting of th combobox given by the QSqlRelation?

    Thanks!


  • Lifetime Qt Champion

    QComboBox has a property to speficy the insertion order: https://doc.qt.io/qt-5/qcombobox.html#InsertPolicy-enum

    If this does not work place a QSortFilterProxyModel between the QSqlRelation and the QComboBox.



  • How are you setting the values in the combobox?
    It should be straightforward using a QSortFilterProxyModel subclass



  • Thanks both for the replies.

    In fact, the combo box is placed automatically by the QSqlRelation. The values are automatically filled by the content of the table specified in the relation, so I have no way to modify the QComboBox...

    model->setRelation(2, QSqlRelation("city", "id", "name"));
    

    In the example (https://doc.qt.io/qt-5/qtsql-relationaltablemodel-example.html) if you click on a cell in Country or City columns you get the values of the Country or the City sorted by id, not by name, and I cannot find the way to have sorted them by name.



  • Yep, as I mentioned it's easy to achieve with a simple QSortFilterProxyModel.

    class SortedRelationalDelegate : public QSqlRelationalDelegate{
        Q_OBJECT
        Q_DISABLE_COPY(SortedRelationalDelegate)
    public:
        explicit SortedRelationalDelegate(QObject* parent = nullptr) :QSqlRelationalDelegate(parent){}
        QWidget *createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const override{
            QWidget* const unsortedWidget = QSqlRelationalDelegate::createEditor(aParent,option,index);
            QComboBox* const combo = qobject_cast<QComboBox*>(unsortedWidget);
            Q_ASSERT(combo);
            QSortFilterProxyModel* const comboSorter = new QSortFilterProxyModel(combo);
            comboSorter->setSourceModel(combo->model());
            comboSorter->sort(combo->modelColumn());
            combo->setModel(comboSorter);
            return combo;
        }
        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override{
            QComboBox* const combo = qobject_cast<QComboBox*>(editor);
            Q_ASSERT(combo);
            QSortFilterProxyModel* const sorter = qobject_cast<QSortFilterProxyModel*>(combo->model());
            Q_ASSERT(sorter);
            const int mappedIndex = sorter->mapToSource(sorter->index(combo->currentIndex(),combo->modelColumn())).row();
            combo->setModel(sorter->sourceModel());
            combo->setCurrentIndex(mappedIndex);
            QSqlRelationalDelegate::setModelData(combo,model,index);
        }
    };
    
        
    

    To use it, call setItemDelegateForColumn on the view for the column that should display the combo



  • @VRonin Thank you! I'm going to do it ASAP.


Log in to reply