Reputation: 53
In QFileDialog in PyQt5 I wish to restrict the user access to a specified home directory and its subdirectories. I have found a solution for c++ here, but I could not successfully implement it in PyQt5 :
import sys
from PyQt5.QtWidgets import QApplication, QFileDialog, QMessageBox
class restrictedFileDialog(QFileDialog):
def __init__(self, homedir):
super().__init__()
self.directoryEntered.connect(self.ontDirectoryChanged)
self.homedir = homedir
self.filtertxt = "Data files (*.dat);;All Files (*)"
self.options = QFileDialog.Options()
self.options |= QFileDialog.DontUseNativeDialog
self.filePath, _ = self.getOpenFileName(None, "Load data file", self.homedir,
self.filtertxt, options=self.options)
def ontDirectoryChanged(self, dirName):
QMessageBox.information(self, 'Restricted directory', 'Directory haschanged.')
if dirName.startswith(self.homedir):
pass
else:
self.setDirectory(self.homedir)
QMessageBox.warning(self, 'Restricted directory', 'Cannot walk up in the path.')
if __name__ == '__main__':
app = QApplication(sys.argv)
homedir = 'C:\\Users'
rd = restrictedFileDialog(homedir)
if rd.filePath:
print(rd.filePath)
app.exec_()
The problem is that the slot 'ontDirectoryChanged' is never triggered. I know that the signal 'directoryEntered' gives a python string containing the current directory name, and I am not sure whether my slot 'ontDirectoryChanged' is bound correctly.
Upvotes: 0
Views: 339
Reputation: 53
Following @musicamante's hints I could solve the problem. Here is a minimal solution:
import sys, os
from PyQt5.QtWidgets import QApplication, QFileDialog, QMessageBox
class restrictedFileDialog(QFileDialog):
def __init__(self, homedir):
super().__init__()
self.homeDir = os.path.normpath(homedir)
self.setDirectory(self.homeDir)
self.directoryEntered.connect(self.onDirectoryChanged)
def onDirectoryChanged(self, dirName):
dn = os.path.normpath(dirName)
if not dn.startswith(self.homeDir):
self.setDirectory(self.homeDir)
QMessageBox.warning(self, 'Restricted path', 'Cannot walk above the home directory:\n%s' % self.homeDir)
if __name__ == '__main__':
app = QApplication(sys.argv)
rfd = restrictedFileDialog('C:\\Users')
rfd.setFileMode(QFileDialog.ExistingFile)
rfd.setWindowTitle('Load data file')
rfd.setNameFilter("Data files (*.dat);;All Files (*)")
rfd.selectNameFilter("Data files (*.dat)")
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
rfd.setOptions(options)
if rfd.exec():
print(rfd.selectedFiles())
else:
print('Dialog is cancelled.')
Upvotes: 1