fereria
7/23/2020 - 12:48 PM

カスタムモデルでソートする

#!python3
# -*- coding: utf-8 -*-

import os.path
import sys
from enum import Enum, auto

from PySide2.QtCore import (QAbstractItemModel, QModelIndex, QSize, Qt)
from PySide2.QtGui import QColor, QPixmap
from PySide2.QtWidgets import (QApplication, QDialog, QHeaderView, QTreeView,
                               QVBoxLayout)

CURRENT_PATH = os.path.dirname(os.path.abspath(sys.argv[0]))


class UISample(QDialog):
    def __init__(self, parent=None):
        super(UISample, self).__init__(parent)

        layout = QVBoxLayout()
        self.view = QTreeView()
        self.view.setSortingEnabled(True)
        layout.addWidget(self.view)
        self.setLayout(layout)

        self.model = SampleListModel()
        self.view.setModel(self.model)
        self.view.setItemsExpandable(False)
        self.view.setRootIsDecorated(False)
        header = self.view.header()
        header.setSectionResizeMode(QHeaderView.ResizeToContents)
        # Signal作成
        self.resize(600, 400)

        self.model.listUpdate([Item('hoge', 10, ItemStatus.Waiting),
                               Item('fuga', 20, ItemStatus.Working),
                               Item('foo', 30, ItemStatus.Finish)])

        self.view.doubleClicked.connect(self.doubleClicked)

    def doubleClicked(self, item):
        # ダブルクリックすると、クリックした行のItemを取得できる
        data = item.data(Qt.UserRole)
        print(data)


class ItemStatus(Enum):

    Waiting = auto()
    Working = auto()
    Finish = auto()
    Error = auto()


class Item:

    def __init__(self, name="", value="", status=ItemStatus.Waiting):

        self.__data = {
            'name': name,
            'value': value,
            'status': status
        }

    def data(self, column):

        if column == 0:
            if 'name' in self.__data:
                return self.__data['name']
        if column == 1:
            if 'status' in self.__data:
                return self.__data['status'].name
        if column == 2:
            if 'value' in self.__data:
                return self.__data['value']
        return ""

    def getBackgroundColor(self, column):

        COLORS = {
            'Waiting': QColor(173, 216, 230),
            'Working': QColor(221, 160, 221),
            'Finish': QColor(153, 255, 153),
            'Error': QColor(255, 51, 102)
        }
        if column == 1:
            return COLORS[self.data(column)]

    def getToolTip(self):

        return "テストですよ"


class SampleListModel(QAbstractItemModel):

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

        self.items = []
        self.header = ['Name', 'Status', 'Value']

    def flags(self, index):
        # 各Itemごとにその性質を変更できる
        return Qt.ItemIsSelectable | Qt.ItemIsEnabled

    def headerData(self, column, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.header[column]

    def index(self, row, column, parent=QModelIndex()):
        return self.createIndex(row, column, None)

    def parent(self, index):
        """
        引数のIndexの親ModelIndexを返す
        """
        return QModelIndex()

    def data(self, index, role=Qt.DisplayRole):

        item = self.items[index.row()]

        # 表示する文字
        if role == Qt.DisplayRole:
            return item.data(index.column())

        if role == Qt.UserRole:
            return item

    def sort(self, column, order):

        rev = False
        if order == Qt.SortOrder.DescendingOrder:
            rev = True

        self.items.sort(key=lambda x: x.data(column), reverse=rev)
        self.layoutChanged.emit()

        print(column, order)

    def rowCount(self, parent=None):
        return len(self.items)

    def columnCount(self, parent=None):
        return len(self.header)

    def listUpdate(self, items):

        self.items = items
        self.layoutChanged.emit()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    a = UISample()
    a.show()
    sys.exit(app.exec_())