Как получить значок, тип MIME и приложение, связанное с файлом на рабочем столе Linux?

Используя C++ на рабочем столе Linux, как лучше всего получить значок, описание документа и приложение, "связанное" с произвольным путем к файлу / файлу?

Я хотел бы использовать самый "канонический" способ поиска значков, описаний mime-типов / типов файлов и связанных приложений как в KDE, так и в gnome, и я бы хотел избежать "обстрела" командной строки и "низкого уровня" -уровень ", а также избегая повторного изобретения колеса самостоятельно (без разбора файла mime-types и тому подобного).

Редактирует и отмечает:

Привет, я изначально задал этот вопрос об объекте информации файла QT, и ответ, что "нет четкого ответа", кажется, верен, насколько это возможно. НО это такая испорченная ситуация, что я открываю вопрос в поисках дополнительной информации.

В частности, меня больше не волнует QT, я просто ищу наиболее канонический способ найти mime-тип с помощью вызовов функций C++/c как в KDE, так и в gnome (особенно в Gnome, поскольку именно здесь меня больше всего смущает), Я хочу иметь возможность показывать значки и описания, соответствующие Nautilus в Gnome и Konquerer/ что угодно в KDE, а также открывать файлы соответствующим образом и т. Д.

Я полагаю, это нормально, что я получаю это отдельно для KDE и Gnome. Большой вопрос в том, какой самый распространенный / лучший / канонический способ получить всю эту информацию для рабочего стола Linux? Документация гнома особенно непрозрачна. У gnome-vsf есть подпрограммы mime, но она устарела, и я не могу найти подпрограмму mime для GIO/GFS, заменяющей gnome-vsf. Существует смутное предположение, что следует использовать приложения с открытым рабочим столом, но какое использовать неясно. И где вписываются libmagic и xdg?

Указатели на эссе с кратким изложением проблем с радостью приняты. Опять же, я знаю, что ответ из трех строк - "нет такого животного", но я ищу длинный ответ.

9 ответов

Решение

Вот пример использования GLib/GIO для получения необходимой информации.

#include <gio/gio.h>
#include <stdio.h>

int
main (int argc, char **argv)
{
    g_thread_init (NULL);
    g_type_init ();

    if (argc < 2)
        return -1;

    GError *error;
    GFile *file = g_file_new_for_path (argv[1]);
    GFileInfo *file_info = g_file_query_info (file,
                                              "standard::*",
                                              0,
                                              NULL,
                                              &error);

    const char *content_type = g_file_info_get_content_type (file_info);
    char *desc = g_content_type_get_description (content_type);
    GAppInfo *app_info = g_app_info_get_default_for_type (
                                  content_type,
                                  FALSE);

    /* you'd have to use g_loadable_icon_load to get the actual icon */
    GIcon *icon = g_file_info_get_icon (file_info);

    printf ("File: %s\nDescription: %s\nDefault Application: %s\n",
            argv[1],
            desc,
            g_app_info_get_executable (app_info));

    return 0;
}

Для этого вы можете использовать инструменты, доступные в xdg, в частности xdg-mime query,

Чтобы узнать тип файла, например, файл index.html ты бы

$ xdg-mime query filetype index.html

Это вернет mimetype. Для запроса, какое приложение связано с этим mimetye, используйте, например,

$ xdg-mime query default text/html

Это возвращает epiphany.desktop здесь, т.е. $APPNAME.desktop, так что легко получить имя приложения из него. Если вы просто хотите открыть файл в приложении по умолчанию, вы, конечно, можете просто запустить

$ xdg-open index.html

что бы зажечь Богоявление.

Функции запросов к ресурсам значков, по-видимому, недоступны в xdg-utils, но вы можете написать небольшой скрипт на python, используя pyxdg, который также предлагает множество дополнительных функций.

Для привязки к Си вам, вероятно, нужно взглянуть на код порта, связанный на странице xdg.

РЕДАКТИРОВАТЬ:

Что касается libmagic и друзья, вам нужно будет определиться с вашими предпочтениями: хотя libmagic выглядит более полным (и точным) с точки зрения охвата типов файлов, он не заботится о приложениях или значках по умолчанию. Он также не предоставляет вам инструментов для установки дополнительных типов MIME.

В Qt >= 4.6 есть новая функция для систем X11

QIcon QIcon::fromTheme ( const QString & name, const QIcon & fallback = QIcon() ) [static]

Вы можете использовать эту функцию. Документация здесь / (Qt 5)

Ни QFileIconProvider, ни QFileInfo ничего не будут делать с базой данных Mime ОС. Чтобы получить доступ к значкам, связанным с различными типами пантомимы, вам придется использовать функции базовой среды рабочего стола. В Qt нет (пока) канонического пути.

Представьте, что у вас может быть другой значок в Gnome, в KDE и в Windows. Так, например, в KDE вы бы использовали KMimeType.

Я только что нашел KFileItem. Этот класс дает вам все, что вам нужно для значков, типов пантомимы и связанных с ними вещей в KDE. Я уверен, что в gnome есть эквивалент, но это дает доступ на том же уровне, что и приложение QT.

Копирование / вставка приведенного выше хорошего примера (с использованием GLib / Gio) просто добавили надлежащее освобождение выделенной памяти в соответствии с документацией. Я пытался просто отредактировать существующий ответ, но он продолжал говорить, что очередь редактирования заполнена :(

      #include <gio/gio.h>
#include <stdio.h>

int
main (int argc, char **argv)
{
    g_thread_init (NULL);
    g_type_init ();

    if (argc < 2)
        return -1;

    g_autoptr(GError) error;
    GFile* file = g_file_new_for_path (argv[1]);
    GFileInfo* file_info = g_file_query_info (file,
                                              "standard::*",
                                              G_FILE_QUERY_INFO_NONE,
                                              NULL,
                                              &error);

    const char* content_type = g_file_info_get_content_type (file_info);
    g_autofree gchar* desc = g_content_type_get_description (content_type);
    GAppInfo* app_info = g_app_info_get_default_for_type (
                                  content_type,
                                  FALSE);

    /* you'd have to use g_loadable_icon_load to get the actual icon */
    GIcon* icon = g_file_info_get_icon (file_info);

    printf ("File: %s\nDescription: %s\nDefault Application: %s\n",
            argv[1],
            desc,
            g_app_info_get_executable (app_info));

    g_object_unref(file_info);
    g_object_unref(file);
    return 0;
}

Может быть, посмотрите на этот код: http://ftp.devil-linux.org/pub/devel/sources/1.2/file-4.23.tar.gz

Это стандартная утилита, используемая в большинстве дистрибутивов Linux/Unix. Вы получите MIME-тип и дополнительную информацию.

Я думаю, что и у Gnome, и у KDE есть свои способы определить это, а также установить значок и стандартное приложение для него.

В любом случае, этот файл-инструмент, вероятно, лучший способ получить тип mime и описание документа. А в некоторых случаях даже некоторые подробности о содержании.

Это даст вам MIME-тип. Это то, что вам нужно, чтобы узнать, как открыть файл. Это отдельные шаги. Файл не говорит вам ни о значке, ни о приложении, с которым можно открыть файл.

Вы можете использовать системный файл "/etc/mime.types". Это также хорошая идея, чтобы сохранить копию вашей программы файла типа MIME. Таким образом, вы не зависите от системы, но в то же время вы должны держать ее достаточно исчерпывающей. Не уверен насчет икон.

Около 8 лет поздно, но все же полезно.

Чтобы получить связанные приложения в KDE, вы можете сделать то, что предложил Джо (используя KFileItem). Однако это требует включения большого количества библиотек. Код ниже требует меньше.

#include <QCoreApplication>
#include <QMimeDatabase>
#include <QDebug>

#include <KMimeTypeTrader>

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);

  if (argc < 2)
  {
    qDebug() << "missing argument <filename>";
    return 1;
  }
  QMimeDatabase mimeDb;
  QMimeType     mimeType = mimeDb.mimeTypeForFile(QString::fromLocal8Bit(argv[1]));

  KService::List services = KMimeTypeTrader::self()->query(
      mimeType.name(),QStringLiteral("Application"));

  foreach(const QExplicitlySharedDataPointer<KService>& svc, services)
  {
    qDebug() << "service: " << svc->name();
    qDebug() << "exec: " << svc->exec();
  }
}

Для компиляции кода добавьте QT += KService KCoreAddons к вашему qmake .pro файл.

Ссылки на документацию KMimeTypeTrader & KService:

Другие вопросы по тегам