web-dev-qa-db-fra.com

Comment "révéler dans le Finder" ou "Afficher dans l'explorateur" avec Qt

Est-il possible d'ouvrir un dossier dans Windows Explorer/OS X Finder, puis de sélectionner/mettre en surbrillance un fichier de ce dossier et de le faire de manière multiplateforme? En ce moment, je fais quelque chose comme

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

path est un chemin complet du dossier que je veux ouvrir. Évidemment, cela ne fera qu'ouvrir le dossier et je devrai rechercher manuellement le fichier dont j'ai besoin. C'est un peu un problème quand il y a des milliers de fichiers dans ce dossier.

Si je fais un chemin vers un fichier spécifique dans ce dossier, alors ce fichier est ouvert avec l'application par défaut pour ce type MIME, et ce n'est pas ce dont j'ai besoin. Au lieu de cela, j'ai besoin de la fonctionnalité équivalente à "Révéler dans le Finder" ou "Afficher dans l'explorateur".

45
nnc

Qt Creator ( /source ) a cette fonctionnalité, il est facile de la copier:

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);
    }
}

Un autre article de blog connexe (avec un code plus simple, je ne l’ai pas essayé et je ne peux donc pas commenter), est this .

Modifier:

Il y a un bogue dans le code d'origine lorsque pathIn contient des espaces sous Windows. QProcess :: startDetached citera automatiquement un paramètre s'il contient des espaces. Toutefois, l'Explorateur Windows ne reconnaîtra pas un paramètre entouré de guillemets et ouvrira l'emplacement par défaut. Essayez vous-même dans la ligne de commande 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"

Ainsi,

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

est changé en 

QString command = Explorer + " " + param;
QProcess::startDetached(command);
38
Ivo

Vous pouvez probablement utiliser QFileDialog::getOpenFileName pour obtenir le nom du fichier. La documentation est disponible ici .. La fonction ci-dessus va renvoyer le chemin complet, y compris le nom du fichier et son extensionle cas échéant ..

Ensuite, vous pouvez donner 

QDesktopServices::openUrl(path);

pour ouvrir le fichier dans son application par défaut, où path sera la QString renvoyée par QFileDialog::getOpenFileName.

J'espère que ça aide..

8
liaK

Ouvrir le fichier dans Windows Explorer (pas le navigateur)

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); 

}
5
Elias

Voici le code que je suis allé avec basé sur les entrées d'une réponse précédente. Cette version ne dépend pas d'autres méthodes de Qt Creator, accepte un fichier ou un répertoire et dispose d'un mode de secours pour la gestion des erreurs et d'autres plates-formes:

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()));
}
2
Dan Dennedy

Cette solution fonctionne à la fois sous Windows et 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
}
0
Donald Duck