Как добавить «Выбрать элемент…» в QComboBox при использовании отсортированной модели QAbstractTableModel?

Я хочу установить отсортированное QAbstractListModel в QComboBox и всегда отображать "Выбрать элемент..." как самое первое значение в поле со списком.

Всякий раз, когда я использую сортировку, элемент "Выбрать элемент..." нежелательно сортируется вместе со всеми другими элементами:

import sys

from PySide2 import QtCore  # or PyQt5
from PySide2 import QtWidgets  # or PyQt5

import natsort  # pip install natsort


class NatSort(QtCore.QSortFilterProxyModel):

    def __init__(self, parent=None):
        super(NatSort, self).__init__(parent)

    def lessThan(self, left, right):
        left_data = self.sourceModel().data(left, role=QtCore.Qt.DisplayRole)
        right_data = self.sourceModel().data(right, role=QtCore.Qt.DisplayRole)

        sorted_data = natsort.natsorted([left_data, right_data])

        if left_data == sorted_data[0]:
            return True
        return False


class ListModel(QtCore.QAbstractListModel):

    def __init__(self, items=[], parent=None):
        QtCore.QAbstractListModel.__init__(self, parent)
        self._items = items

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self._items) + 1  # adjust row count

    def data(self, index, role):

        row = index.row() - 1  # adjust row count

        if role == QtCore.Qt.DisplayRole:
            if row >= 0:
                obj = self._items[row]
                return obj
            else:
                return 'Select item...'


if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    button = QtWidgets.QComboBox()

    data = ['m', '?', 'A', 'X', '1', 'b']

    model = ListModel(items=data)
    proxy_model = NatSort()
    # proxy_model = QtCore.QSortFilterProxyModel()  # same results
    proxy_model.setSourceModel(model)
    proxy_model.sort(0, QtCore.Qt.AscendingOrder)
    button.setModel(proxy_model)

    button.show()
    app.exec_()

введите здесь описание изображения

Поскольку модель не знает о прокси-сервере, как я могу надежно вставить «Выбрать элемент ...», чтобы он всегда отображался первым элементом в поле со списком?


person fredrik    schedule 25.06.2018    source источник
comment
Вы не совсем разместили достаточно кода, чтобы этот пример можно было запустить. Сбросьте его, чтобы он работал с некоторыми примерами данных, чтобы мы могли увидеть поведение, которое вы видите.   -  person shao.lo    schedule 25.06.2018
comment
Я добавил полностью рабочий пример вместе со скриншотом.   -  person fredrik    schedule 25.06.2018


Ответы (1)


Это должно делать то, что вы хотите...

class NatSort(QtCore.QSortFilterProxyModel):
    SPECIAL_ITEM = 'Select item...'

    def lessThan(self, left, right):
        """Custom natural sorting"""
        left_data = self.sourceModel().data(left, role=QtCore.Qt.DisplayRole)
        right_data = self.sourceModel().data(right, role=QtCore.Qt.DisplayRole)

        sorted_data = natsort.natsorted([left_data, right_data])

        if left_data == NatSort.SPECIAL_ITEM:
            return True
        if right_data == NatSort.SPECIAL_ITEM:
            return False
        if left_data == sorted_data[0]:
            return True
        return False
person shao.lo    schedule 25.06.2018
comment
Имеет смысл включить эту логику в алгоритм сортировки. Спасибо! - person fredrik; 26.06.2018