Reputation: 47
I am creating a Save As... function on PyQt5.
The function is supposed to open a file dialog, and let the user specify the directory they want.
Take for example certain applications like Steam. When you save steam, they let you choose a directory to save it in.
User input: D:// But then they will create D://Steam/ for the user. This D://Steam/ folder's name is default and can be changed to anything the user wants For eg: D://asdfgh/ and all content will be downloaded there.
You could think of the function the same as Save As... function in Microsoft Word, but instead of a word document, it is a directory.
This is my current code
saveLocation = QFileDialog.getExistingDirectory(None, "Save As...", os.getenv('HOME'))
if saveLocation:
currentSaveLocation = saveLocation
fromDirectory = Main.tempPath
toDirectory = saveLocation
copy_tree(fromDirectory, toDirectory)
I am unable to save the files into a named directory.
Upvotes: 0
Views: 1954
Reputation: 48489
In order to get a possibly not yet existing path, using the static methods of QFileDialog is not a viable solution. Also, we cannot use the native OS file dialogs, as, like the static methods, they don't give enough control.
We need to do some little "hacking", considering the following aspects:
Directory
fileMode, writing a non existing path disables the Open button;So, these precautions must be taken:
accept()
method of the dialog in order to ignore the warning, and use the base QDialog.accept()
method;class Test(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QHBoxLayout(self)
self.pathEdit = QtWidgets.QLineEdit(placeholderText='Select path...')
self.button = QtWidgets.QToolButton(text='...')
layout.addWidget(self.pathEdit)
layout.addWidget(self.button)
self.button.clicked.connect(self.selectTarget)
def selectTarget(self):
dialog = QtWidgets.QFileDialog(self)
if self.pathEdit.text():
dialog.setDirectory(self.pathEdit.text())
dialog.setFileMode(dialog.Directory)
# we cannot use the native dialog, because we need control over the UI
options = dialog.Options(dialog.DontUseNativeDialog | dialog.ShowDirsOnly)
dialog.setOptions(options)
def checkLineEdit(path):
if not path:
return
if path.endswith(QtCore.QDir.separator()):
return checkLineEdit(path.rstrip(QtCore.QDir.separator()))
path = QtCore.QFileInfo(path)
if path.exists() or QtCore.QFileInfo(path.absolutePath()).exists():
button.setEnabled(True)
return True
# get the "Open" button in the dialog
button = dialog.findChild(QtWidgets.QDialogButtonBox).button(
QtWidgets.QDialogButtonBox.Open)
# get the line edit used for the path
lineEdit = dialog.findChild(QtWidgets.QLineEdit)
lineEdit.textChanged.connect(checkLineEdit)
# override the existing accept() method, otherwise selectedFiles() will
# complain about selecting a non existing path
def accept():
if checkLineEdit(lineEdit.text()):
# if the path is acceptable, call the base accept() implementation
QtWidgets.QDialog.accept(dialog)
dialog.accept = accept
if dialog.exec_() and dialog.selectedFiles():
path = QtCore.QFileInfo(dialog.selectedFiles()[0]).absoluteFilePath()
self.pathEdit.setText(path)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())
Upvotes: 2