在 C 中测试 GVfs 元数据支持
Testing for GVfs metadata support in C
我正在尝试为 Xfce 桌面的 Thunar 文件浏览器添加对每个目录查看设置的支持。因此,例如,如果用户选择以列表而不是图标网格的形式查看目录的内容,则会记住该目录的此设置,并将在每次查看该目录时使用。
现在 Thunar 是建立在 GLib 之上的,我们选择用来实现它的机制是使用 GFile 属性存储元数据,使用像 g_file_set_attributes_async 这样的方法来存储
名称为“metadata::thunar-view-type”的键。用户可以通过首选项对话框中的复选框打开或关闭每个目录的功能。我对 GIO 和 GLib 的了解非常有限,但我现在已经设法让这一切按预期工作(如果您有兴趣,可以查看我的合并请求 here)。
现在据我了解,我在这里使用的功能依赖于称为“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 元数据可用,DBus 本身也可能不可用)。
因此(终于!)我的问题是:通过 C API 为 GLib、GIO 测试 GVfs 元数据支持的最佳(即最稳健和准确)方法是什么,等等?。正如我上面所说,“GVfs 元数据支持”是指“我可以使用 g_file_set_attributes_async 之类的函数来成功保存元数据,以便将来可用吗?”。
我考虑过的一种方法是查看 运行 个名为“gvfsd-metadata”的进程列表,但这对我来说似乎有点笨拙。
此外,如上所述,我是这些技术的新手,所以我绝对有可能误解了这里的内容,所以如果您发现我在上面所做的断言中有任何错误,请告诉我.
谢谢!
(是的,平常的故事,我很长一段时间 reader SO&co,但第一次提问,所以请随时编辑或让我知道我是否做了什么wrong/bad)
致电g_file_query_settable_attributes()
and g_file_query_writable_namespaces()
on the GFile
, as described in the GFileInfo
documentation:
However, not all attributes can be changed in the file. For instance, the actual size of a file cannot be changed via g_file_info_set_size()
. You may call g_file_query_settable_attributes()
and g_file_query_writable_namespaces()
to discover the settable attributes of a particular file at runtime.
我正在尝试为 Xfce 桌面的 Thunar 文件浏览器添加对每个目录查看设置的支持。因此,例如,如果用户选择以列表而不是图标网格的形式查看目录的内容,则会记住该目录的此设置,并将在每次查看该目录时使用。
现在 Thunar 是建立在 GLib 之上的,我们选择用来实现它的机制是使用 GFile 属性存储元数据,使用像 g_file_set_attributes_async 这样的方法来存储 名称为“metadata::thunar-view-type”的键。用户可以通过首选项对话框中的复选框打开或关闭每个目录的功能。我对 GIO 和 GLib 的了解非常有限,但我现在已经设法让这一切按预期工作(如果您有兴趣,可以查看我的合并请求 here)。
现在据我了解,我在这里使用的功能依赖于称为“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 元数据可用,DBus 本身也可能不可用)。
因此(终于!)我的问题是:通过 C API 为 GLib、GIO 测试 GVfs 元数据支持的最佳(即最稳健和准确)方法是什么,等等?。正如我上面所说,“GVfs 元数据支持”是指“我可以使用 g_file_set_attributes_async 之类的函数来成功保存元数据,以便将来可用吗?”。
我考虑过的一种方法是查看 运行 个名为“gvfsd-metadata”的进程列表,但这对我来说似乎有点笨拙。
此外,如上所述,我是这些技术的新手,所以我绝对有可能误解了这里的内容,所以如果您发现我在上面所做的断言中有任何错误,请告诉我.
谢谢!
(是的,平常的故事,我很长一段时间 reader SO&co,但第一次提问,所以请随时编辑或让我知道我是否做了什么wrong/bad)
致电g_file_query_settable_attributes()
and g_file_query_writable_namespaces()
on the GFile
, as described in the GFileInfo
documentation:
However, not all attributes can be changed in the file. For instance, the actual size of a file cannot be changed via
g_file_info_set_size()
. You may callg_file_query_settable_attributes()
andg_file_query_writable_namespaces()
to discover the settable attributes of a particular file at runtime.