Exemple #1
0
        def _load(filePath):
            # type: (pathlib.Path) -> NoReturn
            with itemsLock:
                icon = self.__iconsCache.get(filePath)

            if icon is None:
                iconProvider = QFileIconProvider()

                posixPath = filePath.as_posix()
                file = QFileInfo(posixPath)
                icon = iconProvider.icon(file)

                if icon.isNull():
                    mimeDb = QMimeDatabase()
                    for mime in mimeDb.mimeTypesForFileName(posixPath):
                        icon = QIcon.fromTheme(mime.iconName())
                        if not icon.isNull():
                            break

            result = QFileIconLoader.LoadResult(filePath, icon)
            with itemsLock:
                loadedItems[filePath] = result
                self.__iconsCache.set(filePath, icon)

            self.loaded.emit(result)

            if len(loadedItems) == len(targetPaths):
                self.completed.emit(loadedItems)
    def setupModelData(self, parent):
        parents = [parent]
        numAssets = rt.AssetManager.getNumAssets()

        # For each asset (row)
        for i in range(1, numAssets + 1):

            # Get the asset object
            asset = rt.AssetManager.getAssetByIndex(i)

            # Get the asset properties
            assetFilename = asset.GetFilename()
            assetBasename = os.path.basename(assetFilename)
            assetName = os.path.splitext(assetBasename)[0]
            assetPath = os.path.dirname(assetFilename)
            assetExt = os.path.splitext(assetBasename)[1]
            if assetExt == "":
                continue
            assetType = str(asset.GetType())
            assetStatus = os.path.exists(assetFilename)
            if (assetStatus):
                assetSize = os.path.getsize(assetFilename)
            else:
                assetSize = 0

            # We'll use QFileIconProvider to grab the icon that the OS
            # is currently using to grab the icon to display in the view
            fileInfo = QtCore.QFileInfo(assetFilename)
            iconProvider = QFileIconProvider()
            assetIcon = iconProvider.icon(fileInfo)

            # Read the column data from the rest of the line.
            columnData = [
                assetName, assetExt, assetPath, assetType,
                os.path.exists(assetFilename), assetSize
            ]

            # Append a new node to the root
            parent = parents[-1]
            parent.insertChildren(parent.childCount(), 1,
                                  self._rootItem.columnCount())
            node = parent.child(parent.childCount() - 1)

            # Fill each column in the current row
            for column in range(len(columnData)):
                node.setData(column, columnData[column])
                node.setIcon(assetIcon)
Exemple #3
0
 def __init__(self, parent):
     super().__init__(parent)
     iconProvider = QFileIconProvider()
     self.__defaultIcon = iconProvider.icon(QFileIconProvider.Folder)
     self.__driveIcon = iconProvider.icon(QFileIconProvider.Drive)
Exemple #4
0
class FolderListModel(QAbstractTableModel):
    """
    This class provides a model for browsing a folder.
    """
    folderChanged = Signal(str)  # emitted when the folder changes

    def __init__(self, parent):
        super().__init__(parent=parent)
        self._folder = None
        self._filter = "*"
        self._children = []
        self._iconProvider = QFileIconProvider()
        self._reset(self._folder, self._filter)

    def setFolder(self, folder):
        """
        set the folder of this browser

        :param folder: a Path or string instance
        :return:
        """
        if Path(folder) != self._folder:
            self._reset(folder, self._filter)

    def setFilter(self, flt):
        """
        Set the filter of this browser

        :param flt: string or a list of strings containing glob-style patterns
        :return:
        """
        if isinstance(flt, str):
            flt = [flt]
        self._reset(self._folder, flt)

    def fileToIndex(self, filename):
        """
        return the given file name to a model index.

        :param filename: a string or Path instance
        :return: a QModelIndex instance
        """
        filename = Path(filename)
        try:
            idx = self._children.index(filename)
            return self.createIndex(idx, 0)
        except ValueError:
            return QModelIndex()

    def _match(self, path):
        if path.is_dir():
            return True
        res = QDir.match(self._filter, path.name)
        return res

    def _reset(self, folder, flt):
        self.beginRemoveRows(QModelIndex(), 0, self.rowCount() - 1)
        self._folder = None
        self.endRemoveRows()
        if folder is not None:
            listDrives = False
            f = Path(folder).resolve()
            if platform.system() == "Windows":
                folder = Path(folder)
                if folder.name == ".." and folder.parent == Path(folder.drive +
                                                                 "/"):
                    listDrives = True
                    f = Path("<Drives>")
            self._folder = f
            self._filter = flt
            if platform.system() == "Windows":
                if listDrives:
                    self._children = [
                        Path("%s:/" % dl) for dl in string.ascii_uppercase
                        if Path("%s:/" % dl).exists()
                    ]
                else:
                    self._children = [f / ".."]
            else:
                self._children = ([] if f.root == f else [f / ".."])
            if not listDrives:
                self._children += [x for x in f.glob("*") if self._match(x)]
                self._children.sort(key=lambda c: (c.is_file(
                ), c.drive, int(c.name != ".."), c.name))
            self.beginInsertRows(QModelIndex(), 0, len(self._children) - 1)
            self.endInsertRows()
            if listDrives:
                self.folderChanged.emit("<Drives>")
            else:
                self.folderChanged.emit(
                    str(self._folder) +
                    (os.path.sep if self._folder.is_dir() else ""))

    def folder(self):
        """
        Return the current folder.

        :return: a Path instance
        """
        return self._folder

    def filter(self):
        """
        Return the current filter

        :return: a list of strings
        """
        return self._filter

    def columnCount(self, index=QModelIndex()):  # pylint: disable=unused-argument
        """
        overwritten from base class

        :param index:
        :return:
        """
        return 4

    def rowCount(self, index=QModelIndex()):  # pylint: disable=unused-argument
        """
        overwritten from base class

        :param index:
        :return:
        """
        return len(self._children)

    def data(self, index, role):
        """
        overwritten from base class

        :param index:
        :param role:
        :return:
        """
        c = self._children[index.row()]
        if role == Qt.DisplayRole:
            if index.column() == 0:
                return c.name if c.name != "" else str(c)
            if index.column() == 1:
                if c.is_dir():
                    return ""
                try:
                    s = c.stat().st_size
                except Exception:  # pylint: disable=broad-except
                    return ""
                if s >= 1024 * 1024 * 1024:
                    return "%.0f GB" % (s / (1024 * 1024 * 1024))
                if s >= 1024 * 1024:
                    return "%.0f MB" % (s / (1024 * 1024))
                if s >= 1024:
                    return "%.0f kB" % (s / 1024)
                return s
            if index.column() == 2:
                try:
                    return QDateTime.fromMSecsSinceEpoch(c.stat().st_mtime *
                                                         1000)
                except Exception:  # pylint: disable=broad-except
                    return ""
        if role == Qt.DecorationRole:
            if index.column() == 0:
                if c.is_dir():
                    return self._iconProvider.icon(QFileIconProvider.Drive)
                return self._iconProvider.icon(QFileInfo(str(c.absolute())))
        if role == Qt.UserRole:
            if index.column() == 0:
                return c
        if role in [Qt.DisplayRole, Qt.EditRole]:
            if index.column() == 3:
                if index.row() > 0:
                    return str(c) + (os.path.sep if c.is_dir() else "")
                return str(c.parent) + os.path.sep
        return None

    def headerData(self, section, orientation, role):
        """
        overwritten from base class

        :param section:
        :param orientation:
        :param role:
        :return:
        """
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return ["Name", "Size", "Time", ""][section]
        return super().headerData(section, orientation, role)
class SD_FS_Model(QAbstractItemModel):
    def __init__(self, parent=None, *args):
        super().__init__(parent, *args)
        self.root = FS_Item("/")
        self.header_labels = ['Name', 'Children']
        self.icon_provider = QFileIconProvider()

    # return an index for the given row/column pair and the parent element
    # this index is then used by views to access data
    def index(self,
              row: int,
              column: int,
              parent: QModelIndex = None) -> QModelIndex:
        if not parent or not parent.isValid():
            parent_item = self.root
        else:
            parent_item = parent.internalPointer()

        # check if row is valid
        if row >= parent_item.child_count():
            return QModelIndex()

        child_item = parent_item.child(row)

        # check if column is valid for child
        if column >= child_item.column_count():
            return QModelIndex()

        # return the valid index for the childs column
        return self.createIndex(row, column, child_item)

    def parent(self, index: QModelIndex = None) -> QModelIndex:
        if not index.isValid():
            return QModelIndex()

        child_item = index.internalPointer()
        parent_item = child_item.parent()

        # return invalid index if we hit root
        if parent_item == self.root:
            return QModelIndex()

        return self.createIndex(parent_item.row(), 0, parent_item)

    # returns the amount of nested rows aka children for the parent item the index identifies
    def rowCount(self, parent: QModelIndex = None) -> int:
        # if the column count is nonzero we return
        # indices that identify a node/row and not a value/field have column=0 by convention
        if parent is not None and parent.column() > 0:
            return 0

        if not parent or not parent.isValid():
            parent_item = self.root
        else:
            parent_item = parent.internalPointer()

        return parent_item.child_count()

    # returns the number of columns available for an index
    def columnCount(self, index: QModelIndex = None) -> int:
        # for now, we accept indices with column>0, as there is no drawback
        if index is not None and index.isValid():
            return index.internalPointer().column_count()
        return self.root.column_count()

    # returns the value of the data attribute mapped to the column
    # column mapping is done in the respective class the CanItem holds
    # via the column_representation classmethod
    def data(self, index: QModelIndex, role: int = None):
        # we return None for root data or roles we dont serve
        if not index.isValid():
            return None
        if role == Qt.DecorationRole and index.column() == 0:
            if index.internalPointer().dir:
                return self.icon_provider.icon(QFileIconProvider.Folder)
            else:
                return self.icon_provider.icon(QFileIconProvider.File)
        elif role == Qt.DisplayRole:
            # we get the desired data by calling the CanItems data() function
            # that then calls the held objects get_data function
            return index.internalPointer().data(index.column())

        return None

    def flags(self, index: QModelIndex) -> Qt.ItemFlags:
        if not index.isValid():
            return Qt.NoItemFlags
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable

    # returns header labeling, atm just copied from the table model
    def headerData(self, section, orientation, role: Qt.DisplayRole = None):
        if role == Qt.DisplayRole and orientation == Qt.Orientation.Horizontal:
            return self.header_labels[section]
        return QAbstractTableModel.headerData(self, section, orientation, role)

    def add_item(self, index: QModelIndex, name: str, is_dir: bool):
        # find the parent
        if index is None or not index.isValid():
            parent_item = self.root
        else:
            parent_item = index.internalPointer()

        item = FS_Item(name, is_dir=is_dir, parent=parent_item)

        # send insert signals and append child
        if index is not None:

            self.beginInsertRows(index, parent_item.child_count(),
                                 parent_item.child_count())
            parent_item.append_child(item)
            self.endInsertRows()
        else:
            print(f"heres the bug: \n {item.name} \n {item.get_filepath()}")

    def remove_item(self, index: QModelIndex):
        # cant remove root
        if index is None or not index.isValid():
            return

        # retrieve parameters fo signal call
        parent_item = index.internalPointer().parent()
        parent_index = self.parent(index)
        row = index.row()

        # remove child from parent
        self.beginRemoveRows(parent_index, row, row)
        parent_item.remove_child(row)
        self.endRemoveRows()

    def child_index_by_name(self, parent_index: QModelIndex,
                            name: str) -> QModelIndex:
        if not parent_index.isValid():
            parent = self.root
        else:
            parent = parent_index.internalPointer()

        for child in parent.children:
            if child.name == name:
                return self.createIndex(child.row(), 0, child)
        # no child has the name -> return invalid Index
        return QModelIndex()

    # search through the items according to the given directory path and return index to end of path
    def index_for_path(self, path: str) -> QModelIndex:
        # return an invalid index for the root
        if path == "/":
            return QModelIndex()

        slash1 = 0
        slash2 = path.find("/", slash1 + 1)

        if slash2 == -1:
            directory = path[slash1 + 1:]
        else:
            directory = path[slash1 + 1:slash2]

        path_end_index = self.child_index_by_name(QModelIndex(), directory)

        while True:
            if not path_end_index.isValid():
                # subdirectory not found, return None
                return None

            # go deeper if we have a longer path
            if slash2 != -1:
                slash1 = slash2
                slash2 = path.find("/", slash1 + 1)
            else:
                return path_end_index

            if slash2 == -1:
                directory = path[slash1 + 1:]
            else:
                directory = path[slash1 + 1:slash2]

            path_end_index = self.child_index_by_name(path_end_index,
                                                      directory)

    def is_filled(self) -> bool:
        return self.root.child_count() > 0