【问题标题】:How to "Reveal in Finder" or "Show in Explorer" with Qt如何使用 Qt “在 Finder 中显示”或“在资源管理器中显示”
【发布时间】:2011-03-30 06:05:21
【问题描述】:

是否可以在 Windows Explorer/OS X Finder 中打开一个文件夹,然后选择/突出显示该文件夹中的一个文件,并以跨平台方式进行操作?现在,我正在做类似的事情

QDesktopServices::openUrl( QUrl::fromLocalFile( path ) );

path 是我要打开的文件夹的完整路径。显然,这只会打开文件夹,我必须手动找到我需要的文件。当该文件夹中有数千个文件时,这有点问题。

如果我将其设为该文件夹中特定文件的路径,则该文件将使用该 mime 类型的默认应用程序打开,这不是我需要的。相反,我需要与“在 Finder 中显示”或“在资源管理器中显示”等效的功能。

【问题讨论】:

标签: c++ qt qt4


【解决方案1】:

Qt Creator(source) 有这个功能,复制起来很简单:

void FileUtils::showInGraphicalShell(QWidget *parent, const QString &pathIn)
{
    const QFileInfo fileInfo(pathIn);
    // Mac, Windows support folder or file.
    if (HostOsInfo::isWindowsHost()) {
        const FileName explorer = Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
        if (explorer.isEmpty()) {
            QMessageBox::warning(parent,
                                 QApplication::translate("Core::Internal",
                                                         "Launching Windows Explorer Failed"),
                                 QApplication::translate("Core::Internal",
                                                         "Could not find explorer.exe in path to launch Windows Explorer."));
            return;
        }
        QStringList param;
        if (!fileInfo.isDir())
            param += QLatin1String("/select,");
        param += QDir::toNativeSeparators(fileInfo.canonicalFilePath());
        QProcess::startDetached(explorer.toString(), param);
    } else if (HostOsInfo::isMacHost()) {
        QStringList scriptArgs;
        scriptArgs << QLatin1String("-e")
                   << QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"")
                                         .arg(fileInfo.canonicalFilePath());
        QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
        scriptArgs.clear();
        scriptArgs << QLatin1String("-e")
                   << QLatin1String("tell application \"Finder\" to activate");
        QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
    } else {
        // we cannot select a file here, because no file browser really supports it...
        const QString folder = fileInfo.isDir() ? fileInfo.absoluteFilePath() : fileInfo.filePath();
        const QString app = UnixUtils::fileBrowser(ICore::settings());
        QProcess browserProc;
        const QString browserArgs = UnixUtils::substituteFileBrowserParameters(app, folder);
        bool success = browserProc.startDetached(browserArgs);
        const QString error = QString::fromLocal8Bit(browserProc.readAllStandardError());
        success = success && error.isEmpty();
        if (!success)
            showGraphicalShellError(parent, app, error);
    }
}

另一篇相关的博文(代码更简单,我没试过,所以无法评论),是this

编辑:

当 pathIn 在 Windows 上包含空格时,原始代码中存在错误。 QProcess::startDetached 将自动引用包含空格的参数。但是,Windows 资源管理器将无法识别用引号括起来的参数,而是打开默认位置。在 Windows 命令行中自己尝试一下:

echo. > "C:\a file with space.txt"
:: The following works
C:\Windows\explorer.exe /select,C:\a file with space.txt  
:: The following does not work
C:\Windows\explorer.exe "/select,C:\a file with space.txt"

因此,

QProcess::startDetached(explorer, QStringList(param));

改为

QString command = explorer + " " + param;
QProcess::startDetached(command);

【讨论】:

  • 我测试了您链接的博客文章中的代码。它确实有效(至少在 Mac OS X 上)。
  • @Michael Scheper:我将 DanDennedy 的答案移植到了 PyQt5(参见 here)。我还没有在 Linux 上测试过它,但是看起来很简单。
  • 您的编辑不正确。 Explorer 接受引号包裹的路径就好了(至少在 Windows 10 上)。关键是 explorer args 必须用逗号分隔,所以原始源代码在使用/select,(带逗号)而不是/select 时是正确的。 Qt 会根据需要正确地将路径用引号括起来。来源:geoffchappell.com/studies/windows/shell/explorer/cmdline.htm
  • 发布 GPL 代码并建议复制和粘贴?这是一个陷阱!
  • 它对空格部分非常准确,即使在 Qt 5.15.0 中也是如此。 QProcess::startDetached("explorer.exe", {"/select,c:\\space dir\\some.file"}); 无法工作; QProcess::startDetached("explorer.exe", {"/select,\"c:\\space dir\\some.file\""}); 无法工作;但已弃用 QProcess::startDetached("explorer.exe /select,c:\\space dir\\some.file"}); 有效!请注意,路径周围没有引号。
【解决方案2】:

也许你可以使用QFileDialog::getOpenFileName 来获取文件名。文档在here.. 上面的函数将返回完整的路径,包括文件名和它的扩展名 如果有的话..

那你可以给

QDesktopServices::openUrl(path);

在其默认应用程序中打开文件,其中path 将是QFileDialog::getOpenFileName 返回的QString

希望对你有帮助..

【讨论】:

  • 感谢您的回答,但这不是我需要的。我更新了问题以试图澄清这一点。我需要的是“在 Finder 中显示”或“在资源管理器中显示”功能。
  • QDesktopServices 的 openUrl()-Method 实际上在资源管理器中显示了一个文件/目录。您是否在路径字符串中添加了“file:///”?
  • @liaK:OP 只想在资源管理器中 show 文件,而不是 打开 它。您的方法将尝试打开文件本身。
  • 澄清一下(5 年后)...如果“path”是一个目录,openUrl(path) 在默认文件资源管理器中打开该目录(它不会在常识,意思是打开父目录)。如果“路径”是一个文件,它将使用默认应用程序打开。您可以检测路径是否为文件,然后删除文件名(仅保留目录),但它不会在文件资源管理器中选择文件。
  • 您不必在路径字符串前面加上“file://”;有QUrl::fromLocalFile();如果您使用相对路径,则可能必须将其与QFile#absoluteFilePath() 等一起使用。抄送@斯特拉迪瓦里
【解决方案3】:

在 Windows 资源管理器(不是浏览器)中打开文件

void OpenFileInExplorer()
{
   QString path = "C:/exampleDir/example.txt";

   QStringList args;

   args << "/select," << QDir::toNativeSeparators(path);

   QProcess *process = new QProcess(this);
   process->start("explorer.exe", args); 

}

【讨论】:

  • 如果您使用的是 Windows Explorer 附带的操作系统,那很好,但我的大多数用户更愿意避免使用这些操作系统。 ☺
  • Windows 特有的小技巧,但效果很好,谢谢!
  • 不跨平台。
  • 您没有提供启动函数所需的第三个参数,这也不是跨平台解决方案
【解决方案4】:

这是我根据先前答案的输入使用的代码。该版本不依赖Qt Creator中的其他方法,接受文件或目录,并具有错误处理和其他平台的回退模式:

void Util::showInFolder(const QString& path)
{
    QFileInfo info(path);
#if defined(Q_OS_WIN)
    QStringList args;
    if (!info.isDir())
        args << "/select,";
    args << QDir::toNativeSeparators(path);
    if (QProcess::startDetached("explorer", args))
        return;
#elif defined(Q_OS_MAC)
    QStringList args;
    args << "-e";
    args << "tell application \"Finder\"";
    args << "-e";
    args << "activate";
    args << "-e";
    args << "select POSIX file \"" + path + "\"";
    args << "-e";
    args << "end tell";
    args << "-e";
    args << "return";
    if (!QProcess::execute("/usr/bin/osascript", args))
        return;
#endif
    QDesktopServices::openUrl(QUrl::fromLocalFile(info.isDir()? path : info.path()));
}

【讨论】:

  • 我喜欢这种方法,因为它很简单。我将它移植到 python/PyQt5,看看here
  • 对于 MacOS:请注意 path 必须是绝对的。只需添加一条return 指令即可抑制来自osascript 的输出消息。
  • 还有一件事:在 MacOS 上只执行 open dirPath 会更加直接,但如果 path 实际上是一个文件,它不会突出显示该文件。
  • 这应该是公认的答案。非常感谢。
【解决方案5】:

此解决方案适用于 Windows 和 Mac:

void showFileInFolder(const QString &path){
    #ifdef _WIN32    //Code for Windows
        QProcess::startDetached("explorer.exe", {"/select,", QDir::toNativeSeparators(path)});
    #elif defined(__APPLE__)    //Code for Mac
        QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to reveal POSIX file \"" + path + "\""});
        QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"});
    #endif
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多