在Linux上,是否有一种使用QFileDialog自动为文件添加扩展名的方法?

9
我希望用户能够输入一个文件名,该文件将保存为XML文件。在Windows和Mac上,如果您输入"test"作为文件名,它会自动添加".xml",这正是我想要的。但遗憾的是,在测试Linux版本时,我发现输入没有扩展名的文件名会保存为普通文件。用户必须在文件字符串中指定扩展名(即"test.xml"),才能以正确的格式保存。
下面是我使用的代码。这是Qt的一个bug吗?还是有办法在Qt中指定如果未找到扩展名,应该添加扩展名呢?
// 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);

你是否已考虑过有关平台规范的文档? - Sebastian Mach
我已经在最初请求此功能的错误报告中添加了评论(并声称已修复):https://bugreports.qt-project.org/browse/QTBUG-27186#comment-248985 - Bernhard Reiter
@vsz,你检查过这个提议的解决方案是否适用于此处使用的静态调用“getSaveFileName”吗?我知道它适用于实际的“QFileDialog”对象,但我不确定静态函数是否总是使用“QFileDialog”。 - paxdiablo
3个回答

12

由于您使用getSaveFileName从对话框获取字符串,因此可以像这样操作:

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

由于在getSaveFileName文档中有下面这段被埋藏的小片段,所以在Linux上可能会不同:

在Windows、Mac OS X和Symbian^3上,该静态函数将使用本地文件对话框而非QFileDialog。

换句话说,至少从Qt的角度来看,是由本地对话框添加前缀(而非QFileDialog)导致了这种异常。


正如评论中指出的那样,你可能会发现这种解决方案存在一个问题,即如果你手动输入xyzzy,并且文件xyzzy.xml已经存在(假设本地对话框确实会这样做-我实际上没有检查),那么对话框本身不会通知你。如果你需要这种行为,你也需要自己实现它。


1
@RobertWhitley,请看我的更新,有一些文档说明这些静态函数实际上并没有使用QFileDialog - paxdiablo
2
这种方法存在一个缺陷:如果您使用QFileDialog :: confirmOverwrite(默认值),QFileDialog会测试与实际写入的文件名不同的文件名。 解决方案是要么传递QFileDialog:: DontConfirmOverwrite并执行自己的确认对话框,要么使用QFileDialog :: defaultSuffix,但此选项不能通过QFileDialog :: getSaveFileName获得。 无论哪种方式,您都需要更多代码而不仅仅是静态函数调用。 :-( - hans_meine
-1:这个重复问题的原始版本提供了正确的答案。但是这个回答存在一个问题,就是没有检查正确的文件以进行覆盖。 - vsz
@vsz,我在问题中没有看到检查覆盖的要求,只有一个添加扩展名的请求(而且我必须假设这是令人满意的,因为OP接受了答案)。无论如何,我不认为这一定是重复的。链接的问题实际上直接使用了QFileDialog对象,而这个问题则调用了静态函数getSaveFileName,该函数并不在所有平台上都使用QFileDialog对象。 - paxdiablo
1
@vsz,我会怎么想呢?我认为内存泄漏是长时间运行程序中的一个错误,但在短时间运行的程序中则不相关。如同“情境很重要”。不过,我在答案中做了一些注释指出这也是人们可能需要考虑的问题。如果你认为还有改进的余地,我很乐意(而且也没有自我)接受任何建议 :-) 至今为止,感谢你的贡献,我非常感激。 - paxdiablo
显示剩余3条评论

4
我们创建了自己的保存对话框方法来解决这个问题。解决方案本质上与@paxdiablo的答案相同(只需添加扩展名),但这更加通用:
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
}

这个不支持多个可能的过滤器,对吗? - Ruslan

0
你看过QFileDialog::setDefaultSuffix吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接