How to restrict the users not to go above a specified home directory in QFileDialog in PyQt5?
Question:
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.
Answers:
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.')
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.
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.')