【问题标题】:Conditional custom rows in pyqt4 QFileSystemModelpyqt4 QFileSystemModel 中的条件自定义行
【发布时间】:2016-02-07 20:09:18
【问题描述】:

我想在 QTreeview 下的 QFileSystemModel 中添加自定义行。仅当目录包含具有特定扩展名的文件时才添加该行。基本上,启动目录列表后,用户将单击文件夹。一旦用户单击的文件夹包含目标文件,我想隐藏这些文件(我知道该怎么做),然后使用自定义行来表示这些文件的摘要。

例如,如果文件夹包含如下文件

A.01.dat
A.02.dat
A.03.dat
...
B.01.dat
B.02.dat
B.03.dat

我想创建自定义行:

A
B

但是,如果单击的文件夹不包含这些 .dat 文件,则不应创建自定义行。

我也尝试将行直接插入 QFileSystemModel

self.treeivew.model = QtGui.QFileSystemModel()

...

for n, s in enumerate(self.sequence):
        self.treeview.model.beginInsertRows(index, 0, 0)
        result = self.treeview.model.insertRow(1, index)
        print(result)
        self.treeview.model.setData(index, QString(s['Name']),role=QtCore.Qt.DisplayRole)
        self.treeview.model.endInsertRows()

但是插入失败了。

如果需要重新实现,正如我看到许多地方所建议的那样,任何人都可以提供一个具体示例,说明应该如何进行重新实现以允许这种有条件的自定义行插入?

提前致谢。

【问题讨论】:

    标签: qt pyqt4


    【解决方案1】:

    我将实现一个带有动态子插入的项目模型。这只是一个标准的QAbstractItemModel,还有一些额外的方法-

    • rowCount - 你通常会为树模型实现这个。如果节点有尚未加载的子节点,请确保它返回 0。
    • hasChildren - 覆盖以返回 True 对于具有尚未加载的子节点的节点,并返回在所有其他情况下基类返回的任何内容。
    • canFetchMore - 如果节点有尚未加载的子节点,则返回 True,否则返回 False
    • fetchMore - 您可以在此处执行所需的任何逻辑来决定创建哪些节点并将它们插入模型中。

    这是基本思想 - 对于您知道有尚未加载的子节点的节点,从 rowCountTruecanFetchMorehasChildren 返回 0。这告诉 Qt 显示一个带有扩展器的节点,即使它当前没有子节点。单击扩展器时,将调用 fetchMore 并从给定的父级填充子级。

    有一点需要注意——你必须在fetchMore方法中调用beginInsertRowsendInsertRows。此外,在调用beginInsertRows 之前或endInsertRows 之后,您不得更改底层数据存储。不幸的是,当您调用beginInsertRows 时,您需要知道插入了多少行——因此您可能想要生成要添加的节点列表,然后调用beginInsertRows。但是,如果您这样做,则无法设置新节点的父节点,因为它会更改底层数据存储。

    您可以在下面的代码中看到,我在Node.insert_child 方法中设置了父节点,该方法在beginInsertRowsendInsertRows 调用之间调用。

    代码并不完全符合您的要求 - 它是一个说明动态加载的基本文件系统模型,您需要插入自定义逻辑以在 fetchMore 调用中生成所需的类别节点。它也只显示文件名并且缺少图标。

    如果您希望显示修改后的日期和大小,您需要将它们存储在相关节点中并设置模型columnCount 方法以返回正确的列数。

    对于图标,扩展模型data 方法以检查Qt.DecorationRole 并返回相关的QIcon

    代码中可能有一些多余的东西,因为它是从其他东西中缩减和重新利用的模型。

    import sys
    import os
    
    import sip
    sip.setapi('QVariant', 2)
    
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    
    class Node(object):
    
        def __init__(self, name, path=None, parent=None):
            super(Node, self).__init__()
    
            self.name = name
            self.children = []
            self.parent = parent
    
            self.is_dir = False
            self.path = path
            self.is_traversed = False
    
            if parent is not None:
                parent.add_child(self)
    
        def add_child(self, child):
            self.children.append(child)
            child.parent = self
    
        def insert_child(self, position, child):
            if position < 0 or position > self.child_count():
                return False
    
            self.children.insert(position, child)
            child.parent = self
    
            return True
    
        def child(self, row):
            return self.children[row]
    
        def child_count(self):
            return len(self.children)
    
        def row(self):
            if self.parent is not None:
                return self.parent.children.index(self)
            return 0
    
    
    class FileSystemTreeModel(QAbstractItemModel):
    
        FLAG_DEFAULT = Qt.ItemIsEnabled | Qt.ItemIsSelectable
    
        def __init__(self, root, path='c:/', parent=None):
            super(FileSystemTreeModel, self).__init__()
    
            self.root = root
            self.parent = parent
            self.path = path
    
            for file in os.listdir(path):
                file_path = os.path.join(path, file)
    
                node = Node(file, file_path, parent=self.root)
                if os.path.isdir(file_path):
                    node.is_dir = True
    
        def getNode(self, index):
            if index.isValid():
                return index.internalPointer()
            else:
                return self.root
    
        ## - dynamic row insertion starts here
        def canFetchMore(self, index):
            node = self.getNode(index)
    
            if node.is_dir and not node.is_traversed:
                return True
    
            return False
    
        ## this is where you put custom logic for handling your special nodes
        def fetchMore(self, index):
            parent = self.getNode(index)
    
            nodes = []
            for file in os.listdir(parent.path):
                file_path = os.path.join(parent.path, file)
    
                node = Node(file, file_path)
                if os.path.isdir(file_path):
                    node.is_dir = True
    
                nodes.append(node)
    
            self.insertNodes(0, nodes, index)
            parent.is_traversed = True
    
        def hasChildren(self, index):
            node = self.getNode(index)
    
            if node.is_dir:
                return True
    
            return super(FileSystemTreeModel, self).hasChildren(index)
    
        def rowCount(self, parent):
            node = self.getNode(parent)
            return node.child_count()
    
        ## dynamic row insert ends here
    
        def columnCount(self, parent):
            return 1
    
        def flags(self, index):
            return FileSystemTreeModel.FLAG_DEFAULT
    
        def parent(self, index):
            node = self.getNode(index)
    
            parent = node.parent
            if parent == self.root:
                return QModelIndex()
    
            return self.createIndex(parent.row(), 0, parent)
    
        def index(self, row, column, parent):
            node = self.getNode(parent)
    
            child = node.child(row)
    
            if not child:
                return QModelIndex()
    
            return self.createIndex(row, column, child)
    
        def headerData(self, section, orientation, role):
            return self.root.name
    
        def data(self, index, role):
            if not index.isValid():
                return None
    
            node = index.internalPointer()
    
            if role == Qt.DisplayRole:
                return node.name
    
            else:
                return None
    
        def insertNodes(self, position, nodes, parent=QModelIndex()):
            node = self.getNode(parent)
    
            self.beginInsertRows(parent, position, position + len(nodes) - 1)
    
            for child in nodes:
                success = node.insert_child(position, child)
    
            self.endInsertRows()
    
            return success
    
    
    
    app = QApplication(sys.argv)
    
    model = FileSystemTreeModel(Node('Filename'), path='c:/')
    
    
    tree = QTreeView()
    tree.setModel(model)
    
    tree.show()
    
    sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢蒂姆。这很有帮助。
    猜你喜欢
    • 2015-02-19
    • 2012-02-11
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    相关资源
    最近更新 更多