Question

I want the user to be able to enter a name for a file that will be saved as an xml file. Currently on Windows and Mac if you enter "test" as the file name it will automatically add ".xml" which is what I want. Unfortunately when testing a Linux build I found that entering a file name without an extension would save as an ordinary file. The user has to specify the extension in the file string (i.e "test.xml") in order for it to save in the correct format.

The code I'm using is below. Is this a Qt bug or is there a way to specify in Qt that it should add an extension if one wasn't found?

// Get value for "dir". If the setting doesn't exist then use
// the the path in "defaultsave.directory"
QString prevPath = prevValues.value("dir", QString::fromStdString(
  ConfigService::Instance().getString("defaultsave.directory"))).toString();

QString filter;
filter.append("Files (*.xml)");
filter += ";;AllFiles (*.*)";
QString groupingFile = QFileDialog::getSaveFileName(this, "Save Grouping file as", prevPath, filter);
Was it helpful?

Solution

Since you get the string from the dialog with getSaveFileName, you can just do something like:

if (!groupingFile.endsWith(".xml"))
    groupingFile += ".xml";

It's probably different on Linux because of this little snippet buried in the documentation for getSaveFileName:

On Windows, Mac OS X and Symbian^3, this static function will use the native file dialog and not a QFileDialog.

In other words, it's the adding of the prefix (done by the native dialogs) that is aberrant, at least in terms of Qt.


As pointed out in the comments, you may find an issue with this solution in that the dialog box itself won't notify you if you type in xyzzy manually and the file xyzzy.xml already exists (assuming the native dialogs do this - I haven't actually checked). If you want that behaviour, you'll need to implement it as well.

OTHER TIPS

We created our own save dialog method to get around this. The solution is essentially the same as @paxdiablo's answer (just add the extension), but this is more general:

QString ShowSaveFileDialog(QWidget *parent,
                           const QString &title,
                           const QString &directory,
                           const QString &filter) {
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
  return QFileDialog::getSaveFileName(parent,
                                      title,
                                      directory,
                                      filter);
#else
  QFileDialog dialog(parent, title, directory, filter);
  if (parent) {
    dialog.setWindowModality(Qt::WindowModal);
  }
  QRegExp filter_regex(QLatin1String("(?:^\\*\\.(?!.*\\()|\\(\\*\\.)(\\w+)"));
  QStringList filters = filter.split(QLatin1String(";;"));
  if (!filters.isEmpty()) {
    dialog.setNameFilter(filters.first());
    if (filter_regex.indexIn(filters.first()) != -1) {
      dialog.setDefaultSuffix(filter_regex.cap(1));
    }
  }
  dialog.setAcceptMode(QFileDialog::AcceptSave);
  if (dialog.exec() == QDialog::Accepted) {
    QString file_name = dialog.selectedFiles().first();
    QFileInfo info(file_name);
    if (info.suffix().isEmpty() && !dialog.selectedNameFilter().isEmpty()) {
      if (filter_regex.indexIn(dialog.selectedNameFilter()) != -1) {
        QString extension = filter_regex.cap(1);
        file_name += QLatin1String(".") + extension;
      }
    }
    return file_name;
  } else {
    return QString();
  }
#endif  // Q_WS_MAC || Q_WS_WIN
}

Did you look at QFileDialog::setDefaultSuffix?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top