fereria
8/12/2020 - 12:18 PM

ColumnView Sample

# -*- coding: utf-8 -*-

import os.path
import sys

from PySide2.QtCore import QModelIndex, Qt, QAbstractItemModel
from PySide2.QtWidgets import QApplication, QDialog, QTreeView, QVBoxLayout, QColumnView, QPushButton


class BaseItem(object):
    def __init__(self, data=None, parent=None):

        self.parentItem = parent
        self.__data = data
        self.childItems = []

    def appendChild(self, item):

        self.childItems.append(item)

    def removeChild(self, row):
        self.childItems.pop(row)

    def child(self, row):
        if len(self.childItems) > row:
            return self.childItems[row]
        else:
            return None

    def childCount(self):
        return len(self.childItems)

    def columnCount(self):
        return 1

    def data(self, column):
        if self.__data is None:
            return ""
        return self.__data

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0

    def clear(self):
        self.childItems = []

    def dataExists(self, data):

        if data in [x.data(0) for x in self.childItems]:
            return True
        else:
            return False

    def getFullPath(self):

        current = self
        retVal = []
        while current.data(0) != "":
            retVal.insert(0,current.data(0))
            current = current.parent()

        return "/".join(retVal)


class ColumnModel(QAbstractItemModel):
    def __init__(self, items=[], parent=None):
        super().__init__(parent)

        self.__items = items
        self.rootItem = BaseItem()
        # 現在のページ
        self.setItems(items)

    def setItems(self, items):

        self.__items = items
        self.setupModelData()

    def setupModelData(self):
        """
        表示用のItemを再構築する
        """
        self.rootItem.clear()
        parents = {}
        self.beginResetModel()
        for item in self.__items:
            buff = item.split("/")
            for num, i in  enumerate(buff):
                key = "/".join(buff[:num])
                if key in parents:
                    parent = parents[key]
                else:
                    parent = self.rootItem
                if not parent.dataExists(i):
                    p = BaseItem(i, parent)
                    parent.appendChild(p)
                    parents["/".join(buff[:num + 1])] = p

        self.endResetModel()

    def columnCount(self, parent):

        if parent.isValid():
            return parent.internalPointer().columnCount()
        else:
            return self.rootItem.columnCount()

    def data(self, index, role):

        if not index.isValid():
            return None
        item = index.internalPointer()
        if role == Qt.DisplayRole:
            return item.data(index.column())
        if role == Qt.UserRole:
            return item

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.rootItem.data(section)
        return None

    def index(self, row, column, parent):

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        childItem = parentItem.child(row)
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QModelIndex()

    def parent(self, index):

        if not index.isValid():
            return QModelIndex()
        childItem = index.internalPointer()
        parentItem = childItem.parent()
        if parentItem == self.rootItem:
            return QModelIndex()
        return self.createIndex(parentItem.row(), 0, parentItem)

    def rowCount(self, parent):

        if parent.column() > 0:
            return 0
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        return parentItem.childCount()


class UISample(QDialog):

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

        layout = QVBoxLayout()
        self.setLayout(layout)

        data = ["a/b/c",
                "a/b/d",
                "a/e/f",
                "b/d/c",
                "てすと/はろー/ワールド"]

        # カスタムUIを作成
        self.view = QColumnView()
        self.model = ColumnModel(data)
        self.view.setModel(self.model)
        layout.addWidget(self.view)

        btn = QPushButton()
        layout.addWidget(btn)
        btn.clicked.connect(self.showSelection)

        self.resize(900, 400)

    def showSelection(self):
        a = self.view.selectedIndexes()
        if len(a) > 0:
            data = a[0].data(Qt.UserRole)
            print(data.getFullPath())


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