Тестирование поддержки метаданных GVfs на C

Я пытаюсь добавить поддержку настроек просмотра для отдельных каталогов в файловый браузер Thunar на рабочем столе Xfce. Так, например, если пользователь предпочитает просматривать содержимое каталога в виде списка, а не в виде сетки значков, этот параметр запоминается для этого каталога и будет использоваться при каждом просмотре этого каталога.

Теперь Thunar построен на GLib, и механизм, который мы выбрали для его реализации, заключается в хранении метаданных с использованием атрибутов GFile с использованием таких методов, как g_file_set_attributes_async для хранения ключей с такими именами, как metadata :: thunar-view-type. Функция для каждого каталога может быть включена или отключена пользователем с помощью флажка в диалоговом окне настроек. Мои знания о GIO и GLib довольно ограничены, но теперь мне удалось заставить все это работать должным образом (вы можете увидеть мой запрос на слияние здесь, если вам интересно).

Насколько я понимаю, функциональность, которую я здесь использую, зависит от чего-то, что называется метаданными GVfs, и, насколько я понимаю, это может быть доступно не во всех системах. В системах, где метаданные GVfs недоступны, я хочу отключить эту функцию и, в частности, сделать флажок в диалоговом окне настроек нечувствительным (т. Е. Выделенным серым цветом). Таким образом, мне нужно написать функцию для определения, доступна ли поддержка метаданных gvfs, под этим я подразумеваю, могу ли я использовать такие функции, как g_file_set_attributes_async, для успешного сохранения метаданных, чтобы они были доступны в будущем.

Thunar написан на C, поэтому эта функция должна быть написана на C с использованием C API для GLib, GIO и т. Д. Функция, которую я придумал (из большого чтения документации API, изменения найденных фрагментов кода и экспериментов ) как следует.

gboolean
thunar_g_vfs_metadata_is_supported  (void)
{
  GDBusMessage     *send, *reply;
  GDBusConnection  *conn;
  GVariant         *v1, *v2;
  GError           *error = NULL;
  const gchar     **service_names;
  gboolean          metadata_found;

  /* connect to the session bus */
  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);

  /* check that the connection was opened sucessfully */
  if (error != NULL)
    {
      g_error_free (error);
      return FALSE;
    }

  /* create the message to send to list the available services */
  send = g_dbus_message_new_method_call ("org.freedesktop.DBus",
                                         "/org/freedesktop/DBus",
                                         "org.freedesktop.DBus",
                                         "ListNames");

  /* send the message and wait for the reply */
  reply = g_dbus_connection_send_message_with_reply_sync (conn, send, G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                          -1, NULL, NULL, &error);

  /* release the connection and the sent message */
  g_object_unref (send);
  g_object_unref (conn);

  /* check if we got a sucessful reply */
  if (error != NULL)
    {
      g_error_free (error);
      return FALSE;
    }

  /* extract the GVariant with the array of strings describing the available services */
  v1 = g_dbus_message_get_body (reply); /* v1 belongs to reply and must not be freed */
  if (v1 == NULL || !g_variant_is_container (v1) || g_variant_n_children (v1) < 1)
    {
      g_object_unref (reply);
      return FALSE;
    }
  v2 = g_variant_get_child_value (v1, 0);
  g_object_unref (reply);

  /* check that the GVariant we have been given does contain an array of strings */
  if (!g_variant_is_of_type (v2, G_VARIANT_TYPE_STRING_ARRAY))
    {
      g_variant_unref (v2);
      return FALSE;
    }

  /* search through the list of service names to see if gvfs metadata is present */
  metadata_found = FALSE;
  service_names = g_variant_get_strv (v2, NULL);
  for (int i=0; service_names[i] != NULL; i++)
    if (g_strcmp0 (service_names[i], "org.gtk.vfs.Metadata") == 0)
      metadata_found = TRUE;

  g_free (service_names);
  g_variant_unref (v2);

  return metadata_found;
}

Как видите, эта функция использует DBus для запроса имен служб, чтобы узнать, доступна ли необходимая служба. Насколько я могу проверить, эта функция работает так, как я хочу. Однако во время обзора кода возник вопрос, можно ли это сделать, не полагаясь на DBus (который сам по себе может быть недоступен, даже если есть метаданные GVfs).

Итак (наконец!) Мой вопрос: каков наилучший (т.е. самый надежный и точный) способ проверить поддержку метаданных GVfs через C API для GLib, GIO и т. Д.?. Как я сказал выше, под поддержкой метаданных GVfs я имею в виду, могу ли я использовать такие функции, как g_file_set_attributes_async, для успешного сохранения метаданных, чтобы они были доступны в будущем ?.

Один из рассмотренных мной методов - это просмотр списка запущенных процессов с именем gvfsd-metadata, но мне это кажется немного запутанным.

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

Спасибо!

(И да, обычная история, я давно читаю SO & co, но впервые задаю вопрос, поэтому, пожалуйста, не стесняйтесь редактировать или дайте мне знать, если я сделал что-то не так / плохо)


person reubengreen73    schedule 03.07.2020    source источник


Ответы (1)


Вызовите g_file_query_settable_attributes() и _ 2_ на GFile, как описано в < a href = "https://developer.gnome.org/gio/stable/GFileInfo.html#GFileInfo.description" rel = "nofollow noreferrer"> GFileInfo документация:

Однако не все атрибуты можно изменить в файле. Например, фактический размер файла нельзя изменить с помощью _ 5_. Вы можете вызвать g_file_query_settable_attributes() и _ 7_, чтобы обнаружить настраиваемые атрибуты конкретный файл во время выполнения.

person Philip Withnall    schedule 15.07.2020
comment
Спасибо за ответ! Так что я действительно надеюсь на метод проверки наличия поддержки метаданных для всей файловой системы, а не на проверку доступности отдельных файлов (если между ними действительно есть разница). Однако g_file_query_writable_namespaces () может быть способом сделать это, поскольку я мог бы просто вызвать это в GFile для корневого каталога и искать метаданные среди возвращенных имен. Я думаю, это будет довольно надежным индикатором того, будут ли метаданные работать для всей файловой системы (?), Так что спасибо, что показали мне это! - person reubengreen73; 15.07.2020
comment
Продолжение моего предыдущего комментария: подход, который я упомянул, с использованием корневого каталога, кажется, работает хорошо. - person reubengreen73; 17.07.2020