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.

Asked By: Tamas

||

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.')
Answered By: Tamas
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.