Предотвращение действий с файлами в QFileDialog, таких как копирование, просмотр, удаление и т. Д.

Мы смотрим на развертывание приложения PyQt на сервере Azure, и приложение работает достаточно хорошо, хотя и немного медленно, чтобы реагировать на действия пользователя.

Однако у нас есть проблема, заключающаяся в том, что QFileDialog позволяет практически любое действие исследования: скопировать файл с виртуальной машины на локальный диск пользователя, открыть файл в "Program Files (x86)" в Блокноте и т. Д.

Подходы уже рассмотрены:

  1. Поскольку приложение python должно иметь разрешения на чтение и запись для запуска в "Program Files (x86)", мы не можем использовать права доступа к файлам для управления доступом.

  2. Мы можем превратить Python в непостижимый.exe, но его все равно можно скопировать, используя контекстные меню в диалоговом окне файла.

  3. Мы могли бы использовать фильтры файлов, а затем скрыть их, чтобы вы могли видеть (и связываться) только с соответствующими файлами, но пользователь мог копировать целые каталоги.

Единственное, о чем мы можем подумать, - это создать собственный файловый диалог с нуля, но это очень утомительно. Существуют ли какие-либо нестандартные решения?

3 ответа

Решение

QFileDialog Класс уже имеет эту функциональность:

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

Однако, похоже, это работает только со встроенным в Qt диалогом файлов. Если вы используете статические функции для открытия собственного файла-диалога, ReadOnly опция, кажется, игнорируется (хотя я только проверял это на Linux).

Глядя на пример qtreeview, они показывают проводник файлов, так что я думаю, что реализовать простой обозреватель файловой системы не так уж и сложно. это особенно легко благодаря QFileSystemModel http://doc.qt.io/qt-5/model-view-programming.html

Вот что я на самом деле сделал, основываясь на совете @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:
      https://stackru.com/questions/2101100/qfiledialog-filtering-folders. """

    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_()

Моя благодарность @serge_gubenko и @Gayan на странице qfiledialog - Фильтрация папок? для обеспечения реализации C++, из которой я получил выше.

Другие вопросы по тегам