Предотвращение действий с файлами в QFileDialog, таких как копирование, просмотр, удаление и т. Д.
Мы смотрим на развертывание приложения PyQt на сервере Azure, и приложение работает достаточно хорошо, хотя и немного медленно, чтобы реагировать на действия пользователя.
Однако у нас есть проблема, заключающаяся в том, что QFileDialog позволяет практически любое действие исследования: скопировать файл с виртуальной машины на локальный диск пользователя, открыть файл в "Program Files (x86)" в Блокноте и т. Д.
Подходы уже рассмотрены:
Поскольку приложение python должно иметь разрешения на чтение и запись для запуска в "Program Files (x86)", мы не можем использовать права доступа к файлам для управления доступом.
Мы можем превратить Python в непостижимый.exe, но его все равно можно скопировать, используя контекстные меню в диалоговом окне файла.
Мы могли бы использовать фильтры файлов, а затем скрыть их, чтобы вы могли видеть (и связываться) только с соответствующими файлами, но пользователь мог копировать целые каталоги.
Единственное, о чем мы можем подумать, - это создать собственный файловый диалог с нуля, но это очень утомительно. Существуют ли какие-либо нестандартные решения?
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++, из которой я получил выше.