Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
5.15.2
-
None
Description
QFileDialogPrivate::typedFiles does not pass full paths into QFileDialogPrivate::addDefaultSuffixToFiles, so when addDefaultSuffixToFiles checks if a typed file is actually a directory, it's actually checking the QFileInfo inside the working directory, not inside the path that the QFileDialog had open.
So, if you open a QFileDialog at an arbitrary path, and your working directory (not the path that QFileDialog is opened to) has a directory with a name that matches what a user types into the text field, then that file is erroneously skipped in addDefaultSuffixToFiles and thus doesn't have the suffix.
Reproduction steps:
- Compile the below project with QT Creator.
- In the build directory, add a folder called "badname" and a folder called "test"
- Run the program. a QFileDialog will appear, opened into the "test" folder. Type the filename "badname" without the quotes. (You could also type "test" instead, or any other name that matches a folder in the working directory)
- The printout reads out the returned file names. Notice how the badname filename is missing the ".txt" suffix
If you type any other filename (except for "badname", "test", or some other name that matches a directory in the working folder), the ".txt" extension will be properly appended.
In practice, my real program has a "temp" folder in the working directory that I utilize. If a user tries to ever save a file with the name "temp" using a save dialog (which we use setDefaultSuffix(".txt")), that file actually doesn't get saved with the extension, no matter where the user tries to save the file. Adding workarounds in my own code is infeasible as I don't have a way to correct such filenames before QFileDialog does things like checking for existing files, etc.
Suggested Fix: QFileDialogPrivate::typedFiles needs to pass actual full file path for the typed file (instead of just the literal user-inputted filename) into addDefaultSuffixToFiles.
main.cpp:
#include <QApplication> #include <QtWidgets/QFileDialog> #include <QDebug> int main(int argc, char *argv[]){ QApplication a(argc, argv); QFileDialog dialog(nullptr, QFileDialog::tr("Save File..."), "test/", QFileDialog::tr("Text File(*.txt)")); dialog.setOption(QFileDialog::DontUseNativeDialog); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setDefaultSuffix(".txt"); dialog.exec(); for (QString file : dialog.selectedFiles()) { QDebug debug(QtMsgType::QtDebugMsg); debug << file; } return 0; }
CMakeLists.txt:
cmake_minimum_required(VERSION 3.14) project(qt_filename_bug LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt5Widgets REQUIRED) add_executable(qt_filename_bug main.cpp ) target_link_libraries(qt_filename_bug Qt${QT_VERSION_MAJOR}::Core Qt5::Widgets)