阻止QFileDialog中的文件操作,例如复制、查看、删除等

Preventing file actions in QFileDialog, such as copying, viewing, deleting, etc

我们正在考虑在 Azure 服务器上部署 PyQt 应用程序,该应用程序运行良好,尽管对用户操作的响应有点慢。

然而,我们有一个问题,那就是 QFileDialog 几乎允许任何探索操作:将文件从虚拟机复制到用户的本地驱动器,在记事本中打开 'Program Files (x86)' 中的文件,等等

已考虑的方法:

  1. 因为 python 应用程序必须具有读写权限 运行 在 'Program Files (x86)' 下,我们不能使用文件权限来 控制访问。

  2. 我们可以将 Python 变成一个神秘的 .exe,但这可能 仍然可以使用文件对话框中的上下文菜单进行复制。

  3. 我们可以使用文件过滤器然后隐藏它们,所以你只能 查看(并弄乱)相关文件,但用户仍然可以 复制整个目录。

我们唯一能想到的就是从头开始创建我们自己的文件对话框,但这非常繁琐。有没有 'out of the box' 解决方案?

看看 qtreeview 的例子,他们显示了一个文件资源管理器,所以我认为实现一个简单的文件系统资源管理器实际上并不是一项艰巨的任务。多亏了 QFileSystemModel http://doc.qt.io/qt-5/model-view-programming.html#using-models-and-views

,这特别容易

QFileDialog class 已经有这个功能:

    dialog = QtGui.QFileDialog()
    dialog.setOption(QtGui.QFileDialog.ReadOnly, True)
    dialog.exec_()

不过,这似乎只适用于 Qt 的内置文件对话框。如果你使用静态函数打开一个 native 文件对话框,ReadOnly 选项似乎被忽略了(我只在 Linux 上测试过这个,虽然).

根据@ekhumoro 的建议,这是我实际所做的:

from PyQt4 import QtGui
import guidata
import re

class _DirectoryFilterProxyModel(QtGui.QSortFilterProxyModel):
    """ A basic filter to be applied to the file items to be displayed.
     Based on C++ example at:
       """

    def __init__(self, ignore_directories=[], *args, **kw):
        """ Constructor
        :param ignore_directories: A list of directories to exclude.  These
        can be regular expressions or straight names. """
        QtGui.QSortFilterProxyModel.__init__(self, *args, **kw)
        self.ignore_directories = ignore_directories

    def filterAcceptsRow(self, sourceRow, sourceParent):
        fileModel = self.sourceModel()
        index0 = fileModel.index(sourceRow, 0, sourceParent)

        if fileModel:
            if fileModel.isDir(index0):
                for directory in self.ignore_directories:
                    if re.match(directory, fileModel.fileName(index0)):
                        return False
                return True
            else:    # For files
                return True
        else:
            return False

并实例化:

app = guidata.qapplication()
dialog = QtGui.QFileDialog()
proxyModel = _DirectoryFilterProxyModel(ignore_directories=["Program Files", "Program Files (x86)", "Windows"])
dialog.setProxyModel(proxyModel)
dialog.setOption(QtGui.QFileDialog.ReadOnly, True)
dialog.setOption(QtGui.QFileDialog.HideNameFilterDetails, True)
dialog.exec_()

感谢页面 qfiledialog - Filtering Folders? 上的@serge_gubenko 和@Gayan 提供了 C++ 实现,我从中得出了以上内容。