How to open directory in file manager and highlight specific item in it ?



  • Hi everyone,
    I want to implement "Open Containing Folder" kinda thing. If someone doesn't know, it's like I want to open a directory in filemanager in which specific file/folder would be highlighted.
    In linux, freedesktop dbus specification[0] has "ShowItems" method to attain such behaviour but I don't have any idea about other operating systems.

    Does anyone has any idea about it ? I tried to find but wasn't able to find any Qt API which performs such action.

    [0] http://www.freedesktop.org/wiki/Specifications/file-manager-interface/
    Regards,
    Ashish Bansal



  • @ashishbansal Apparently QtCreator does such a thing, so have a look around its code to find how it does that and just copy it to your project.

    http://code.qt.io/cgit/qt-creator/qt-creator.git/



  • @raf924 said:

    @ashishbansal Apparently QtCreator does such a thing, so have a look around its code to find how it does that and just copy it to your project.

    http://code.qt.io/cgit/qt-creator/qt-creator.git/

    But it only opens up directory doesn't highlight that item on which I pressed "Show Containing folder".



  • @ashishbansal I just tried it on Qt Creator 3.4.2 on Windows and it does highlight the item.



  • @raf924 said:

    @ashishbansal I just tried it on Qt Creator 3.4.2 on Windows and it does highlight the item.

    But not on linux :|



  • @ashishbansal Oh but you already have a solution for Linux don't you?



  • @raf924 said:

    @ashishbansal Oh but you already have a solution for Linux don't you?

    Yeah I have that but I was looking for better alternative if possible like something in-built API in Qt.
    BTW what about Mac OS.



  • @ashishbansal FOund this in the source of qBittorent:

    void Utils::Misc::openFolderSelect(const QString& absolutePath)
    {
        const QString path = Utils::Fs::fromNativePath(absolutePath);
    #ifdef Q_OS_WIN
        if (QFileInfo(path).exists()) {
            // Syntax is: explorer /select, "C:\Folder1\Folder2\file_to_select"
            // Dir separators MUST be win-style slashes
    
            // QProcess::startDetached() has an obscure bug. If the path has
            // no spaces and a comma(and maybe other special characters) it doesn't
            // get wrapped in quotes. So explorer.exe can't find the correct path and
            // displays the default one. If we wrap the path in quotes and pass it to
            // QProcess::startDetached() explorer.exe still shows the default path. In
            // this case QProcess::startDetached() probably puts its own quotes around ours.
    
            STARTUPINFO startupInfo;
            ::ZeroMemory(&startupInfo, sizeof(startupInfo));
            startupInfo.cb = sizeof(startupInfo);
    
            PROCESS_INFORMATION processInfo;
            ::ZeroMemory(&processInfo, sizeof(processInfo));
    
            QString cmd = QString("explorer.exe /select,\"%1\"").arg(Utils::Fs::toNativePath(absolutePath));
            LPWSTR lpCmd = new WCHAR[cmd.size() + 1];
            cmd.toWCharArray(lpCmd);
            lpCmd[cmd.size()] = 0;
    
            bool ret = ::CreateProcessW(NULL, lpCmd, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);
            delete [] lpCmd;
    
            if (ret) {
                ::CloseHandle(processInfo.hProcess);
                ::CloseHandle(processInfo.hThread);
            }
        }
        else {
            // If the item to select doesn't exist, try to open its parent
            openPath(path.left(path.lastIndexOf("/")));
        }
    #elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
        if (QFileInfo(path).exists()) {
            QProcess proc;
            QString output;
            proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
            proc.waitForFinished();
            output = proc.readLine().simplified();
            if (output == "dolphin.desktop" || output == "org.kde.dolphin.desktop")
                proc.startDetached("dolphin", QStringList() << "--select" << Utils::Fs::toNativePath(path));
            else if (output == "nautilus.desktop" || output == "org.gnome.Nautilus.desktop"
                     || output == "nautilus-folder-handler.desktop")
                proc.startDetached("nautilus", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "caja-folder-handler.desktop")
                proc.startDetached("caja", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "nemo.desktop")
                proc.startDetached("nemo", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "kfmclient_dir.desktop")
                proc.startDetached("konqueror", QStringList() << "--select" << Utils::Fs::toNativePath(path));
            else
                openPath(path.left(path.lastIndexOf("/")));
        }
        else {
            // If the item to select doesn't exist, try to open its parent
            openPath(path.left(path.lastIndexOf("/")));
        }
    #else
        openPath(path.left(path.lastIndexOf("/")));
    #endif
    }
    


  • @raf924 said:

    @ashishbansal FOund this in the source of qBittorent:

    void Utils::Misc::openFolderSelect(const QString& absolutePath)
    {
        const QString path = Utils::Fs::fromNativePath(absolutePath);
    #ifdef Q_OS_WIN
        if (QFileInfo(path).exists()) {
            // Syntax is: explorer /select, "C:\Folder1\Folder2\file_to_select"
            // Dir separators MUST be win-style slashes
    
            // QProcess::startDetached() has an obscure bug. If the path has
            // no spaces and a comma(and maybe other special characters) it doesn't
            // get wrapped in quotes. So explorer.exe can't find the correct path and
            // displays the default one. If we wrap the path in quotes and pass it to
            // QProcess::startDetached() explorer.exe still shows the default path. In
            // this case QProcess::startDetached() probably puts its own quotes around ours.
    
            STARTUPINFO startupInfo;
            ::ZeroMemory(&startupInfo, sizeof(startupInfo));
            startupInfo.cb = sizeof(startupInfo);
    
            PROCESS_INFORMATION processInfo;
            ::ZeroMemory(&processInfo, sizeof(processInfo));
    
            QString cmd = QString("explorer.exe /select,\"%1\"").arg(Utils::Fs::toNativePath(absolutePath));
            LPWSTR lpCmd = new WCHAR[cmd.size() + 1];
            cmd.toWCharArray(lpCmd);
            lpCmd[cmd.size()] = 0;
    
            bool ret = ::CreateProcessW(NULL, lpCmd, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);
            delete [] lpCmd;
    
            if (ret) {
                ::CloseHandle(processInfo.hProcess);
                ::CloseHandle(processInfo.hThread);
            }
        }
        else {
            // If the item to select doesn't exist, try to open its parent
            openPath(path.left(path.lastIndexOf("/")));
        }
    #elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
        if (QFileInfo(path).exists()) {
            QProcess proc;
            QString output;
            proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
            proc.waitForFinished();
            output = proc.readLine().simplified();
            if (output == "dolphin.desktop" || output == "org.kde.dolphin.desktop")
                proc.startDetached("dolphin", QStringList() << "--select" << Utils::Fs::toNativePath(path));
            else if (output == "nautilus.desktop" || output == "org.gnome.Nautilus.desktop"
                     || output == "nautilus-folder-handler.desktop")
                proc.startDetached("nautilus", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "caja-folder-handler.desktop")
                proc.startDetached("caja", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "nemo.desktop")
                proc.startDetached("nemo", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path));
            else if (output == "kfmclient_dir.desktop")
                proc.startDetached("konqueror", QStringList() << "--select" << Utils::Fs::toNativePath(path));
            else
                openPath(path.left(path.lastIndexOf("/")));
        }
        else {
            // If the item to select doesn't exist, try to open its parent
            openPath(path.left(path.lastIndexOf("/")));
        }
    #else
        openPath(path.left(path.lastIndexOf("/")));
    #endif
    }
    

    Thanks. It seems that it would solve the problem :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.