Compare commits

...

2 Commits

Author SHA1 Message Date
Siegfried-Angel Gevatter Pujals
fe47a3d86e Use const enum ...' instead of const gchar' for the type parameter. 2011-12-29 16:56:47 +01:00
Siegfried-Angel Gevatter Pujals
66ff8f8785 Start working on GtkRecentManagerAndZeitgeist. 2011-12-27 20:54:23 +01:00
2 changed files with 374 additions and 4 deletions

View File

@@ -2,6 +2,8 @@
* gtkrecentmanager.c: a manager for the recently used resources
*
* Copyright (C) 2006 Emmanuele Bassi
* Copyright (C) 2011 Collabora Ltd.
* By Siegfried-Angel Gevatter <sgevatter@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -119,6 +121,19 @@
/* keep in sync with xdgmime */
#define GTK_RECENT_DEFAULT_MIME "application/octet-stream"
/* Zeitgeist D-Bus constants */
#define ZEITGEIST_BUS_NAME "org.gnome.zeitgeist.Engine"
#define ZEITGEIST_INTERFACE_NAME "org.gnome.zeitgeist.Log"
#define ZEITGEIST_OBJECT_PATH "/org/gnome/zeitgeist/log/activity"
#define ZEITGEIST_WAIT_TIMEOUT 1000
/* Other Zeitgeist constants */
#define ZEITGEIST_INTERPRETATION_CREATE_EVENT "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#CreateEvent"
#define ZEITGEIST_INTERPRETATION_ACCESS_EVENT "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#AccessEvent"
#define ZEITGEIST_INTERPRETATION_LEAVE_EVENT "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#LeaveEvent"
#define ZEITGEIST_INTERPRETATION_MODIFY_EVENT "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#ModifyEvent"
#define ZEITGEIST_MANIFESTATION_USER_ACTIVITY "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#UserActivity"
typedef struct
{
gchar *name;
@@ -179,6 +194,9 @@ struct _GtkRecentManagerPrivate
guint changed_timeout;
guint changed_age;
GDBusConnection *connection;
GCancellable *cancellable;
};
enum
@@ -337,6 +355,25 @@ gtk_recent_manager_class_init (GtkRecentManagerClass *klass)
g_type_class_add_private (klass, sizeof (GtkRecentManagerPrivate));
}
static GDBusConnection *
get_connection (void)
{
GDBusConnection *connection;
GError *error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (error)
{
g_debug ("Couldn't connect to D-Bus session bus, %s", error->message);
g_error_free (error);
return NULL;
}
return connection;
}
static void
gtk_recent_manager_init (GtkRecentManager *manager)
{
@@ -349,6 +386,8 @@ gtk_recent_manager_init (GtkRecentManager *manager)
priv->size = 0;
priv->filename = NULL;
priv->cancellable = g_cancellable_new ();
}
static void
@@ -398,6 +437,19 @@ gtk_recent_manager_finalize (GObject *object)
GtkRecentManager *manager = GTK_RECENT_MANAGER (object);
GtkRecentManagerPrivate *priv = manager->priv;
if (priv->cancellable)
{
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->connection)
{
g_object_unref (priv->connection);
priv->connection = NULL;
}
g_free (priv->filename);
if (priv->recent_items != NULL)
@@ -798,6 +850,8 @@ gtk_recent_manager_add_item_query_info (GObject *source_object,
* to the recently used resources list
*
* Since: 2.10
*
* Deprecated: 3.4: Replaced by gtk_recent_manager_add_activity.
*/
gboolean
gtk_recent_manager_add_item (GtkRecentManager *manager,
@@ -853,6 +907,8 @@ gtk_recent_manager_add_item (GtkRecentManager *manager,
* recently used resources list, %FALSE otherwise.
*
* Since: 2.10
*
* Deprecated: 3.4: Replaced by gtk_recent_manager_add_activity.
*/
gboolean
gtk_recent_manager_add_full (GtkRecentManager *manager,
@@ -957,6 +1013,164 @@ gtk_recent_manager_add_full (GtkRecentManager *manager,
return TRUE;
}
/**
* gtk_recent_manager_add_activity:
* @manager: a #GtkRecentManager
* @type: a GtkRecentManagerType
* @recent_data: information to be logged.
*
* Adds an activity to the system's activity log.
*
* Since: FIXME
*/
void
gtk_recent_manager_add_activity (GtkRecentManager *manager,
const enum GtkRecentManagerActivityType type,
const GtkRecentActivityData *data)
{
GtkRecentManagerPrivate *priv;
g_return_if_fail (GTK_IS_RECENT_MANAGER (manager));
g_return_if_fail (data != NULL);
/* sanity checks */
if (!data->uri)
{
g_warning ("Attempting to log an activity but no URI was defined");
return;
}
if ((data->uri) &&
(!g_utf8_validate (data->uri, -1, NULL)))
{
g_warning ("Attempting to log an activity, but the URI (`%s')"
"is not a valid UTF-8 encoded string", data->uri);
return;
}
if ((data->display_name) &&
(!g_utf8_validate (data->display_name, -1, NULL)))
{
g_warning ("Attempting to log an activity concerning `%s', but the "
"display name is not a valid UTF-8 encoded string",
data->uri);
return;
}
if (!data->mime_type)
{
g_warning ("Attempting to log an activity concerning `%s', but "
"no MIME-type was defined", data->uri);
return;
}
if (data->application && (
(!g_str_has_prefix (data->application, "application://")) ||
(!g_str_has_suffix (data->application, ".desktop"))))
{
g_warning ("Attempting to log an activity concerning `%s', but "
" the given application identifier is invalid.", data->uri);
return;
}
priv = manager->priv;
/* get missing info */
// FIXME: uncomment this
/*if (!data->mime_type)
{
GFile* file;
file = g_file_new_for_uri (data->uri);
// FIXME: use g_file_query_info_async
g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
//G_PRIORITY_DEFAULT,
G_FILE_QUERY_INFO_NONE,
priv->cancellable,
NULL);
//gtk_recent_manager_add_activity_query_info,
//g_object_ref (manager));
g_object_unref (file);
}*/
// FIXME: figure out data->application if it's NULL
/* send event to Zeitgeist */
if (!priv->connection)
{
priv->connection = get_connection ();
if (!priv->connection)
return;
}
GError *error = NULL;
GVariantBuilder vb;
GVariant *parameters;
// FIXME: coalesce insertions?
g_variant_builder_init (&vb, G_VARIANT_TYPE ("a(asaasay)"));
g_variant_builder_open (&vb, G_VARIANT_TYPE ("a(asaasay)"));
// Event
g_variant_builder_open (&vb, G_VARIANT_TYPE ("as"));
g_variant_builder_add (&vb, "s", "" /*timestamp_str, sprintf*/); // FIXME
if (type == GTK_RECENT_MANAGER_ACTIVITY_TYPE_CREATED)
g_variant_builder_add (&vb, "s", ZEITGEIST_INTERPRETATION_CREATE_EVENT);
else if (type == GTK_RECENT_MANAGER_ACTIVITY_TYPE_OPENED)
g_variant_builder_add (&vb, "s", ZEITGEIST_INTERPRETATION_ACCESS_EVENT);
else if (type == GTK_RECENT_MANAGER_ACTIVITY_TYPE_CLOSED)
g_variant_builder_add (&vb, "s", ZEITGEIST_INTERPRETATION_LEAVE_EVENT);
else if (type == GTK_RECENT_MANAGER_ACTIVITY_TYPE_MODIFIED)
g_variant_builder_add (&vb, "s", ZEITGEIST_INTERPRETATION_MODIFY_EVENT);
else
{
g_warning ("Attempted to log an activity concerning `%s', but the ",
"given activity type is invalid.", data->uri);
return;
}
g_variant_builder_add(&vb, "s", ZEITGEIST_MANIFESTATION_USER_ACTIVITY);
g_variant_builder_add(&vb, "s", data->application);
g_variant_builder_close (&vb);
// Subject
g_variant_builder_open (&vb, G_VARIANT_TYPE ("aas"));
g_variant_builder_open (&vb, G_VARIANT_TYPE ("as"));
g_variant_builder_add (&vb, "s", data->uri);
g_variant_builder_add (&vb, "s", ""); // empty interpretation, new enough
// ZG will guess it from MIME-type
g_variant_builder_add (&vb, "s", ""); // empty manifestation, new enough ZG
// will guess it from URI
g_variant_builder_add (&vb, "s", ""); // no origin - FIXME: add option for it?
g_variant_builder_add (&vb, "s", data->mime_type);
g_variant_builder_add (&vb, "s", (data->display_name) ? data->display_name : "");
g_variant_builder_add (&vb, "s", ""); // empty storage, ZG will guess it
g_variant_builder_close (&vb);
g_variant_builder_close (&vb);
// Payload
g_variant_builder_open (&vb, G_VARIANT_TYPE ("ay"));
g_variant_builder_close (&vb);
g_variant_builder_close (&vb);
parameters = g_variant_builder_end (&vb);
// FIXME: make async
g_dbus_connection_call_sync (priv->connection,
ZEITGEIST_BUS_NAME,
ZEITGEIST_OBJECT_PATH,
ZEITGEIST_INTERFACE_NAME,
"InsertEvents",
parameters,
NULL, // reply type, we don't care
G_DBUS_CALL_FLAGS_NONE,
ZEITGEIST_WAIT_TIMEOUT,
priv->cancellable,
&error);
}
/**
* gtk_recent_manager_remove_item:
* @manager: a #GtkRecentManager
@@ -1254,6 +1468,112 @@ gtk_recent_manager_move_item (GtkRecentManager *recent_manager,
*/
GList *
gtk_recent_manager_get_items (GtkRecentManager *manager)
{
GtkRecentManagerPrivate *priv;
GList *retval = NULL;
//gchar **uris;
gsize n_events, i;
g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), NULL);
priv = manager->priv;
//if (!priv->recent_items)
// return NULL;
if (!priv->connection)
{
priv->connection = get_connection ();
// FIXME: if (!priv->connection) ????
}
GError *error = NULL;
GVariant *reply;
GVariantBuilder vb;
GVariant *parameters;
g_variant_builder_init (&vb, G_VARIANT_TYPE ("((xx)a(asaasay)uuu)"));
g_variant_builder_add (&vb, "(xx)", 0, 1000000000000000);
g_variant_builder_open (&vb, G_VARIANT_TYPE ("a(asaasay)"));
g_variant_builder_close (&vb);
g_variant_builder_add (&vb, "u", 0); // storage state
g_variant_builder_add (&vb, "u", 100); // num. events
g_variant_builder_add (&vb, "u", 2); // MOST_RECENT_SUBJECTS
parameters = g_variant_builder_end (&vb);
reply = g_dbus_connection_call_sync (priv->connection,
ZEITGEIST_BUS_NAME,
ZEITGEIST_OBJECT_PATH,
ZEITGEIST_INTERFACE_NAME,
"FindEvents",
parameters,
NULL, // a(asaasay)
G_DBUS_CALL_FLAGS_NONE,
ZEITGEIST_WAIT_TIMEOUT,
priv->cancellable,
&error);
if (error)
{
g_warning ("Couldn't request events from Zeitgeist: %s", error->message);
g_error_free (error);
return NULL;
}
GVariant *events;
events = g_variant_get_child_value (reply, 0);
g_variant_unref (reply);
n_events = g_variant_n_children (events);
for (i = 0; i < n_events; ++i)
{
GVariant *event, *event_data, *subjects;
GVariantIter iter, subjects_iter, *subject_data_iter;
event = g_variant_get_child_value (events, i);
g_variant_iter_init (&iter, event);
event_data = g_variant_iter_next_value (&iter);
subjects = g_variant_iter_next_value (&iter);
g_variant_iter_init (&subjects_iter, subjects);
while (g_variant_iter_loop (&subjects_iter, "as", &subject_data_iter))
{
gchar *uri = NULL;
GtkRecentInfo *info;
g_variant_iter_next (subject_data_iter, "s", &uri);
info = gtk_recent_info_new (uri);
retval = g_list_prepend (retval, info);
g_free (uri);
}
g_variant_unref (event);
g_variant_unref (event_data);
g_variant_unref (subjects);
}
retval = g_list_reverse (retval);
g_variant_unref (events);
return retval;
}
/**
* gtk_recent_manager_get_items:
* @manager: a #GtkRecentManager
*
* Gets the list of recently used resources.
*
* Return value: (element-type GtkRecentInfo) (transfer full): a list of
* newly allocated #GtkRecentInfo objects. Use
* gtk_recent_info_unref() on each item inside the list, and then
* free the list itself using g_list_free().
*
* Since: 2.10
*/
/*GList *
gtk_recent_manager_get_items_old (GtkRecentManager *manager)
{
GtkRecentManagerPrivate *priv;
GList *retval = NULL;
@@ -1280,7 +1600,7 @@ gtk_recent_manager_get_items (GtkRecentManager *manager)
g_strfreev (uris);
return retval;
}
}*/
static void
purge_recent_items_list (GtkRecentManager *manager,

View File

@@ -40,8 +40,9 @@ G_BEGIN_DECLS
#define GTK_IS_RECENT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_RECENT_MANAGER))
#define GTK_RECENT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_RECENT_MANAGER, GtkRecentManagerClass))
typedef struct _GtkRecentInfo GtkRecentInfo;
typedef struct _GtkRecentData GtkRecentData;
typedef struct _GtkRecentInfo GtkRecentInfo;
typedef struct _GtkRecentData GtkRecentData;
typedef struct _GtkRecentActivityData GtkRecentActivityData;
typedef struct _GtkRecentManager GtkRecentManager;
typedef struct _GtkRecentManagerClass GtkRecentManagerClass;
typedef struct _GtkRecentManagerPrivate GtkRecentManagerPrivate;
@@ -74,13 +75,59 @@ struct _GtkRecentData
gchar *mime_type;
gchar *app_name;
// FIXME: deprecate
gchar *app_exec;
// FIXME: deprecate
gchar **groups;
// FIXME: deprecate
gboolean is_private;
};
/**
* GtkRecentActivityData:
* @uri: a UTF-8 encoded string, containing the URI of the resource,
* or %NULL,
* @display_name: a UTF-8 encoded string, containing the name of
* the resource to be displayed, or %NULL;
* @mime_type: the MIME type of the resource;
* @application: the identifier of the application that is registering
* this activity (format: "application://<name>.actor"), or %NULL.
*
* Information to be passed to gtk_recent_manager_add() when
* registering an activity.
**/
struct _GtkRecentActivityData
{
gchar *uri;
gchar *display_name;
gchar *mime_type;
gchar *application;
};
/**
* GtkRecentManagerActivityType:
*
* - GTK_RECENT_MANAGER_ACTIVITY_TYPE_CREATED:
* A new resource has been created.
* - GTK_RECENT_MANAGER_ACTIVITY_TYPE_OPENED:
* An existing resource has been opened for viewing/editing/etc.
* - GTK_RECENT_MANAGER_ACTIVITY_TYPE_MODIFIED:
* An existing resource has been modified.
* - GTK_RECENT_MANAGER_ACTIVITY_TYPE_CLOSED:
* A previously opened resource has been closed.
**/
enum GtkRecentManagerActivityType {
GTK_RECENT_MANAGER_ACTIVITY_TYPE_CREATED,
GTK_RECENT_MANAGER_ACTIVITY_TYPE_OPENED,
GTK_RECENT_MANAGER_ACTIVITY_TYPE_CLOSED,
GTK_RECENT_MANAGER_ACTIVITY_TYPE_MODIFIED
};
/**
* GtkRecentManager:
*
@@ -168,7 +215,10 @@ gboolean gtk_recent_manager_add_item (GtkRecentManager *manag
const gchar *uri);
gboolean gtk_recent_manager_add_full (GtkRecentManager *manager,
const gchar *uri,
const GtkRecentData *recent_data);
const GtkRecentData *data);
void gtk_recent_manager_add_activity (GtkRecentManager *manager,
const enum GtkRecentManagerActivityType type,
const GtkRecentActivityData *recent_data);
gboolean gtk_recent_manager_remove_item (GtkRecentManager *manager,
const gchar *uri,
GError **error);