Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-83342

macOS: Native file save dialog crashes if file already exists.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • P1: Critical
    • None
    • 5.9, 5.12, 5.14
    • None
    • macOS 10.15 (Catalina)
    • macOS

    Description

      In macOS 10.15 (Catalina), the native Cocoa file save dialog will crash if all of the following are true:

      • the user confirms the default filename without modifying it
      • an extension is automatically added to the filename based on the selected filter
      • a file with the same name already exists
      • the user chooses to replace the file when prompted by macOS.

      The following program demonstrates the problem:

      #include <QApplication>
      #include <QFileDialog>
      
      int main(int argc, char **argv)
      {
          QApplication app(argc, argv);
          QWidget window;
          QString caption = "Save As";
          QString filter = "Plain text (*.txt);;Markdown (*.md)";
          QString path = "Untitled.txt";
          QString selectedFilter;
          QFileDialog::Options options = QFileDialog::Options();
          path = QFileDialog::getSaveFileName(&window, caption, path, filter,
                                              &selectedFilter, options);
          QFile f(path);
          f.open(QIODevice::WriteOnly);
          f.close();
          path = QFileDialog::getSaveFileName(&window, caption, path, filter, 
                                              &selectedFilter, options);
      }

      The above program will prompt the user for a filename. If the file exists, and the user agrees to replace the file, the program will crash before the first call to QFileDialog::getSaveFileName() returns. Otherwise, the file will be created. Then the program will once again prompt the user for a filename. Assuming the file creation was successful, if the user chooses the same filename and agrees to replace the file, the program will crash.

      I noticed that QNSOpenSavePanelDelegate does not implement the panel:validateURL:error: instance method of the NSOpenSavePanelDelegate protocol. Adding an implementation of this method in

      qtbase/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm

      seems to solve the problem. It can be as simple as this:

      - (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
      {
          Q_UNUSED(sender);
          Q_UNUSED(url);
          Q_UNUSED(outError);
          return YES;
      } 

       At first, my thought was to retain a reference to the NSURL passed to this method, and use that instead of calling [mSavePanel URL], since that seemed to be where the assertion failure was, but I found that simply providing an implementation of this method allowed the calls to [mSavePanel URL] to succeed.

      To be fair, I see this more as a bug in Catalina than in Qt, but I think it would be good to implement this method of the NSOpenSavePanelDelegate protocol, especially since it seems to resolve this issue.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            vestbo Tor Arne Vestbø
            mattmcclinch Matt McClinch
            Votes:
            2 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes