Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe47a3d86e | |||
| 66ff8f8785 |
+321
-1
@@ -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,
|
||||
|
||||
+53
-3
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user