gnome-control-center/libslab/recent-files.c

294 lines
7.4 KiB
C

/*
* This file is part of the Main Menu.
*
* Copyright (c) 2006 Novell, Inc.
*
* The Main Menu is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* The Main Menu is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* the Main Menu; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "recent-files.h"
#include <gtk/gtk.h>
#include <gio/gio.h>
G_DEFINE_TYPE (MainMenuRecentMonitor, main_menu_recent_monitor, G_TYPE_OBJECT)
G_DEFINE_TYPE (MainMenuRecentFile, main_menu_recent_file, G_TYPE_OBJECT)
#define MAIN_MENU_RECENT_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MAIN_MENU_RECENT_MONITOR_TYPE, MainMenuRecentMonitorPrivate))
#define MAIN_MENU_RECENT_FILE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MAIN_MENU_RECENT_FILE_TYPE, MainMenuRecentFilePrivate))
typedef struct {
GFileMonitor *monitor;
gulong changed_handler_id;
} MainMenuRecentMonitorPrivate;
typedef struct {
GtkRecentInfo *item_obj;
} MainMenuRecentFilePrivate;
enum {
STORE_CHANGED,
LAST_SIGNAL
};
static guint monitor_signals [LAST_SIGNAL] = { 0 };
static void main_menu_recent_monitor_finalize (GObject *);
static void main_menu_recent_file_finalize (GObject *);
static GList *get_files (MainMenuRecentMonitor *, gboolean);
static void
recent_file_store_monitor_cb (GFileMonitor *, GFile *,
GFile *, GFileMonitorEvent, gpointer);
static gint recent_item_mru_comp_func (gconstpointer, gconstpointer);
static void
main_menu_recent_monitor_class_init (MainMenuRecentMonitorClass *this_class)
{
G_OBJECT_CLASS (this_class)->finalize = main_menu_recent_monitor_finalize;
this_class->changed = NULL;
g_type_class_add_private (this_class, sizeof (MainMenuRecentMonitorPrivate));
monitor_signals [STORE_CHANGED] = g_signal_new (
"changed", G_TYPE_FROM_CLASS (this_class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (MainMenuRecentMonitorClass, changed),
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
static void
main_menu_recent_file_class_init (MainMenuRecentFileClass *this_class)
{
G_OBJECT_CLASS (this_class)->finalize = main_menu_recent_file_finalize;
g_type_class_add_private (this_class, sizeof (MainMenuRecentFilePrivate));
}
static void
main_menu_recent_monitor_init (MainMenuRecentMonitor *this)
{
MainMenuRecentMonitorPrivate *priv = MAIN_MENU_RECENT_MONITOR_GET_PRIVATE (this);
priv->model = NULL;
priv->changed_handler_id = 0;
}
static void
main_menu_recent_file_init (MainMenuRecentFile *this)
{
MainMenuRecentFilePrivate *priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (this);
priv->item_obj = NULL;
priv->uri = NULL;
priv->mime_type = NULL;
}
static void
main_menu_recent_monitor_finalize (GObject *g_object)
{
MainMenuRecentMonitorPrivate *priv = MAIN_MENU_RECENT_MONITOR_GET_PRIVATE (g_object);
g_file_monitor_cancel (priv->monitor);
g_object_unref (priv->monitor);
(* G_OBJECT_CLASS (main_menu_recent_monitor_parent_class)->finalize) (g_object);
}
static void
main_menu_recent_file_finalize (GObject *g_object)
{
MainMenuRecentFilePrivate *priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (g_object);
if (priv->item_obj)
gtk_recent_info_unref (priv->item_obj);
(* G_OBJECT_CLASS (main_menu_recent_file_parent_class)->finalize) (g_object);
}
MainMenuRecentMonitor *
main_menu_recent_monitor_new ()
{
MainMenuRecentMonitor *this = g_object_new (MAIN_MENU_RECENT_MONITOR_TYPE, NULL);
MainMenuRecentMonitorPrivate *priv = MAIN_MENU_RECENT_MONITOR_GET_PRIVATE (this);
GtkRecentManager *manager;
gchar *store_path;
GFile *store_file;
manager = gtk_recent_manager_get_default ();
g_object_get (G_OBJECT (manager), "filename", & store_path, NULL);
store_file = g_file_new_for_path (store_path);
priv->monitor = g_file_monitor_file (store_file,
0, NULL, NULL);
if (priv->monitor) {
g_signal_connect (priv->monitor, "changed",
G_CALLBACK (recent_file_store_monitor_cb),
this);
}
g_free (store_path);
g_object_unref (store_file);
return this;
}
static GList *
get_files (MainMenuRecentMonitor *this, gboolean apps)
{
GList *list;
GList *items;
GtkRecentManager *manager = gtk_recent_manager_get_default ();
GtkRecentInfo *info;
gboolean include;
MainMenuRecentFile *item;
MainMenuRecentFilePrivate *item_priv;
GList *node;
list = gtk_recent_manager_get_items (manager);
items = NULL;
for (node = list; node; node = node->next) {
item = g_object_new (MAIN_MENU_RECENT_FILE_TYPE, NULL);
item_priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (item);
info = (GtkRecentInfo *) node->data;
include = (apps && gtk_recent_info_has_group (info, "recently-used-apps")) ||
(! apps && ! gtk_recent_info_get_private_hint (info));
if (include) {
item_priv->item_obj = info;
items = g_list_insert_sorted (items, item, recent_item_mru_comp_func);
}
else
g_object_unref (item);
}
g_list_free (list);
return items;
}
GList *
main_menu_get_recent_files (MainMenuRecentMonitor *this)
{
return get_files (this, FALSE);
}
GList *
main_menu_get_recent_apps (MainMenuRecentMonitor *this)
{
return get_files (this, TRUE);
}
const gchar *
main_menu_recent_file_get_uri (MainMenuRecentFile *this)
{
MainMenuRecentFilePrivate *priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (this);
return gtk_recent_info_get_uri (priv->item_obj);
}
const gchar *
main_menu_recent_file_get_mime_type (MainMenuRecentFile *this)
{
MainMenuRecentFilePrivate *priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (this);
return gtk_recent_info_get_mime_type (priv->item_obj);
}
time_t
main_menu_recent_file_get_modified (MainMenuRecentFile *this)
{
MainMenuRecentFilePrivate *priv = MAIN_MENU_RECENT_FILE_GET_PRIVATE (this);
return gtk_recent_info_get_modified (priv->item_obj);
}
void
main_menu_rename_recent_file (MainMenuRecentMonitor *this, const gchar *uri_0, const gchar *uri_1)
{
GtkRecentManager *manager;
GError *error = NULL;
manager = gtk_recent_manager_get_default ();
gtk_recent_manager_move_item (manager, uri_0, uri_1, & error);
if (error) {
g_warning ("unable to update recent file store with renamed file, [%s] -> [%s]\n", uri_0, uri_1);
g_error_free (error);
}
}
void
main_menu_remove_recent_file (MainMenuRecentMonitor *this, const gchar *uri)
{
GtkRecentManager *manager;
GError *error = NULL;
manager = gtk_recent_manager_get_default ();
gtk_recent_manager_remove_item (manager, uri, & error);
if (error) {
g_warning ("unable to update recent file store with removed file, [%s]\n", uri);
g_error_free (error);
}
}
static void
recent_file_store_monitor_cb (
GFileMonitor *mon, GFile *f1,
GFile *f2, GFileMonitorEvent event_type, gpointer user_data)
{
g_signal_emit ((MainMenuRecentMonitor *) user_data, monitor_signals [STORE_CHANGED], 0);
}
static gint
recent_item_mru_comp_func (gconstpointer a, gconstpointer b)
{
time_t modified_a, modified_b;
modified_a = main_menu_recent_file_get_modified ((MainMenuRecentFile *) a);
modified_b = main_menu_recent_file_get_modified ((MainMenuRecentFile *) b);
return modified_b - modified_a;
}