/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-shortcuts.c
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*
* This program 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.
*
* This program 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 this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli
*/
/* The shortcut list goes like this:
- evolution:/local/Inbox
- evolution:/local/Trash
- evolution:/local/Calendar
- evolution:/local/Personal
FIXME: Do we want to use a namespace for this?
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include "e-shortcuts.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "e-shortcuts-view.h"
#include "e-shell-constants.h"
#define PARENT_TYPE GTK_TYPE_OBJECT
static GtkObjectClass *parent_class = NULL;
struct _ShortcutGroup {
/* Title of the group. */
char *title;
/* A list of shortcuts. */
GSList *shortcuts;
};
typedef struct _ShortcutGroup ShortcutGroup;
struct _EShortcutsPrivate {
/* Name of the file associated with these shortcuts. Changes in the shortcuts
will update this file automatically. */
char *file_name;
/* ID of the idle function that will be called to save the shortcuts when they are
changed. */
int save_idle_id;
/* Whether these shortcuts need to be saved to disk. */
gboolean dirty;
/* The storage set to which these shortcuts are associated. */
EStorageSet *storage_set;
/* The folder type registry. */
EFolderTypeRegistry *folder_type_registry;
/* A list of ShortcutGroups. */
GSList *groups;
/* A list of ShortcutViews. */
GSList *views;
/* A hash table to get a group given its name. */
GHashTable *title_to_group;
};
enum {
NEW_GROUP,
REMOVE_GROUP,
NEW_SHORTCUT,
REMOVE_SHORTCUT,
UPDATE_SHORTCUT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static EShortcutItem *
shortcut_item_new (const char *uri,
const char *name,
const char *type)
{
EShortcutItem *new;
if (name == NULL)
name = g_basename (uri);
new = g_new (EShortcutItem, 1);
new->uri = g_strdup (uri);
new->name = g_strdup (name);
new->type = g_strdup (type);
return new;
}
static void
shortcut_item_update (EShortcutItem *shortcut_item,
const char *uri,
const char *name,
const char *type)
{
if (name == NULL)
name = g_basename (uri);
if (shortcut_item->uri != uri) {
g_free (shortcut_item->uri);
shortcut_item->uri = g_strdup (uri);
}
if (shortcut_item->name != name) {
g_free (shortcut_item->name);
shortcut_item->name = g_strdup (name);
}
if (shortcut_item->type != type) {
g_free (shortcut_item->type);
shortcut_item->type = g_strdup (type);
}
}
static void
shortcut_item_free (EShortcutItem *shortcut_item)
{
g_free (shortcut_item->uri);
g_free (shortcut_item->name);
g_free (shortcut_item->type);
g_free (shortcut_item);
}
static ShortcutGroup *
shortcut_group_new (const char *title)
{
ShortcutGroup *new;
new = g_new (ShortcutGroup, 1);
new->title = g_strdup (title);
new->shortcuts = NULL;
return new;
}
static void
shortcut_group_free (ShortcutGroup *group)
{
GSList *p;
g_free (group->title);
for (p = group->shortcuts; p != NULL; p = p->next)
shortcut_item_free ((EShortcutItem *) p->data);
g_slist_free (group->shortcuts);
g_free (group);
}
/* Utility functions. */
static void
update_shortcut_and_emit_signal (EShortcuts *shortcuts,
EShortcutItem *shortcut_item,
int group_num,
int num,
const char *uri,
const char *name,
const char *type)
{
shortcut_item_update (shortcut_item, uri, name, type);
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[UPDATE_SHORTCUT], group_num, num);
}
static void
override_shortcut_name_and_type_from_storage_set (EShortcuts *shortcuts,
EShortcutItem *shortcut_item)
{
EShortcutsPrivate *priv;
EFolder *folder;
priv = shortcuts->priv;
/* If it is not an evolution: link, there is not much we can do. */
if (strncmp (shortcut_item->uri, E_SHELL_URI_PREFIX, E_SHELL_URI_PREFIX_LEN) != 0)
return;
folder = e_storage_set_get_folder (priv->storage_set,
shortcut_item->uri + E_SHELL_URI_PREFIX_LEN);
if (folder == NULL)
return;
shortcut_item_update (shortcut_item,
shortcut_item->uri,
NULL,
e_folder_get_type_string (folder));
}
static void
unload_shortcuts (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
GSList *orig_groups;
GSList *p;
priv = shortcuts->priv;
orig_groups = priv->groups;
for (p = priv->groups; p != NULL; p = p->next) {
ShortcutGroup *group;
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_GROUP], 0);
group = (ShortcutGroup *) p->data;
g_hash_table_remove (priv->title_to_group, group->title);
shortcut_group_free (group);
priv->groups = priv->groups->next;
}
if (orig_groups != NULL)
g_slist_free (orig_groups);
priv->groups = NULL;
g_hash_table_destroy (priv->title_to_group);
priv->title_to_group = g_hash_table_new (g_str_hash, g_str_equal);
}
static gboolean
load_shortcuts (EShortcuts *shortcuts,
const char *file_name)
{
EShortcutsPrivate *priv;
xmlDoc *doc;
xmlNode *root;
xmlNode *p, *q;
/* FIXME: Update the views by emitting the appropriate signals. */
priv = shortcuts->priv;
doc = xmlParseFile (file_name);
if (doc == NULL)
return FALSE;
root = xmlDocGetRootElement (doc);
if (root == NULL || strcmp (root->name, "shortcuts") != 0) {
xmlFreeDoc (doc);
return FALSE;
}
unload_shortcuts (shortcuts);
for (p = root->childs; p != NULL; p = p->next) {
ShortcutGroup *shortcut_group;
xmlChar *shortcut_group_title;
if (strcmp ((char *) p->name, "group") != 0)
continue;
shortcut_group_title = xmlGetProp (p, "title");
if (shortcut_group_title == NULL)
continue;
shortcut_group = g_hash_table_lookup (priv->title_to_group, shortcut_group_title);
if (shortcut_group != NULL) {
g_warning ("Duplicate shortcut group title -- %s",
shortcut_group_title);
xmlFree (shortcut_group_title);
continue;
}
shortcut_group = shortcut_group_new (shortcut_group_title);
xmlFree (shortcut_group_title);
for (q = p->childs; q != NULL; q = q->next) {
EShortcutItem *shortcut_item;
xmlChar *uri;
xmlChar *name;
xmlChar *type;
if (strcmp ((char *) q->name, "item") != 0)
continue;
uri = xmlNodeListGetString (doc, q->childs, 1);
name = xmlGetProp (q, "name");
type = xmlGetProp (q, "type");
shortcut_item = shortcut_item_new (uri, name, type);
/* The name and type are the ones we saved from the
last session. If the folder is in the storage, we
have to get the type and name from this storage. */
override_shortcut_name_and_type_from_storage_set (shortcuts, shortcut_item);
shortcut_group->shortcuts = g_slist_prepend (shortcut_group->shortcuts,
shortcut_item);
if (uri != NULL)
xmlFree (uri);
if (name != NULL)
xmlFree (name);
if (type != NULL)
xmlFree (type);
}
shortcut_group->shortcuts = g_slist_reverse (shortcut_group->shortcuts);
priv->groups = g_slist_prepend (priv->groups, shortcut_group);
g_hash_table_insert (priv->title_to_group, shortcut_group->title, shortcut_group);
}
priv->groups = g_slist_reverse (priv->groups);
xmlFreeDoc (doc);
/* After loading, we always have to re-save ourselves as we have merged
the information we have with the information we got from the
StorageSet. */
make_dirty (shortcuts);
return TRUE;
}
static gboolean
save_shortcuts (EShortcuts *shortcuts,
const char *file_name)
{
EShortcutsPrivate *priv;
xmlDoc *doc;
xmlNode *root;
GSList *p, *q;
priv = shortcuts->priv;
doc = xmlNewDoc ((xmlChar *) "1.0");
root = xmlNewDocNode (doc, NULL, (xmlChar *) "shortcuts", NULL);
xmlDocSetRootElement (doc, root);
for (p = priv->groups; p != NULL; p = p->next) {
ShortcutGroup *group;
xmlNode *group_node;
group = (ShortcutGroup *) p->data;
group_node = xmlNewChild (root, NULL, (xmlChar *) "group", NULL);
xmlSetProp (group_node, (xmlChar *) "title", group->title);
for (q = group->shortcuts; q != NULL; q = q->next) {
EShortcutItem *shortcut;
xmlNode *shortcut_node;
shortcut = (EShortcutItem *) q->data;
shortcut_node = xmlNewChild (group_node, NULL, (xmlChar *) "item", (xmlChar *) shortcut->uri);
if (shortcut->name != NULL)
xmlSetProp (shortcut_node, (xmlChar *) "name", shortcut->name);
if (shortcut->type != NULL)
xmlSetProp (shortcut_node, (xmlChar *) "type", shortcut->type);
}
}
if (xmlSaveFile (file_name, doc) < 0) {
xmlFreeDoc (doc);
return FALSE;
}
xmlFreeDoc (doc);
return TRUE;
}
static EShortcutItem *
get_item (EShortcuts *shortcuts,
int group_num,
int num)
{
EShortcutsPrivate *priv;
ShortcutGroup *group;
GSList *group_element;
GSList *shortcut_element;
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
priv = shortcuts->priv;
group_element = g_slist_nth (priv->groups, group_num);
if (group_element == NULL)
return NULL;
group = (ShortcutGroup *) group_element->data;
shortcut_element = g_slist_nth (group->shortcuts, num);
if (shortcut_element == NULL)
return NULL;
return (EShortcutItem *) shortcut_element->data;
}
/* Idle function to update the file on disk. */
static int
idle_cb (void *data)
{
EShortcuts *shortcuts;
EShortcutsPrivate *priv;
shortcuts = E_SHORTCUTS (data);
priv = shortcuts->priv;
if (priv->dirty) {
g_print ("Saving shortcuts -- %s\n", priv->file_name);
if (! e_shortcuts_save (shortcuts, NULL))
g_warning ("Saving of shortcuts failed -- %s", priv->file_name);
else
priv->dirty = FALSE;
}
priv->save_idle_id = 0;
return FALSE;
}
static void
schedule_idle (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
priv = shortcuts->priv;
if (priv->save_idle_id != 0)
return;
priv->save_idle_id = gtk_idle_add (idle_cb, shortcuts);
}
static void
make_dirty (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
priv = shortcuts->priv;
priv->dirty = TRUE;
schedule_idle (shortcuts);
}
static void
update_shortcuts_by_path (EShortcuts *shortcuts,
const char *path)
{
EShortcutsPrivate *priv;
EFolder *folder;
const GSList *p, *q;
char *evolution_uri;
int group_num, num;
priv = shortcuts->priv;
folder = e_storage_set_get_folder (priv->storage_set, path);
evolution_uri = g_strconcat (E_SHELL_URI_PREFIX, path, NULL);
group_num = 0;
for (p = priv->groups; p != NULL; p = p->next, group_num++) {
ShortcutGroup *group;
group = (ShortcutGroup *) p->data;
num = 0;
for (q = group->shortcuts; q != NULL; q = q->next, num++) {
EShortcutItem *shortcut_item;
shortcut_item = (EShortcutItem *) q->data;
if (strcmp (shortcut_item->uri, evolution_uri) == 0)
update_shortcut_and_emit_signal (shortcuts,
shortcut_item,
group_num,
num,
evolution_uri,
NULL,
e_folder_get_type_string (folder));
}
}
g_free (evolution_uri);
make_dirty (shortcuts);
}
/* Signal handlers for the views. */
static void
view_destroyed_cb (GtkObject *object,
gpointer data)
{
EShortcuts *shortcuts;
EShortcutsPrivate *priv;
shortcuts = E_SHORTCUTS (data);
priv = shortcuts->priv;
priv->views = g_slist_remove (priv->views, object);
}
/* Signal handlers for the EStorageSet. */
static void
storage_set_new_folder_callback (EStorageSet *storage_set,
const char *path,
void *data)
{
EShortcuts *shortcuts;
shortcuts = E_SHORTCUTS (data);
update_shortcuts_by_path (shortcuts, path);
make_dirty (shortcuts);
}
static void
storage_set_updated_folder_callback (EStorageSet *storage_set,
const char *path,
void *data)
{
EShortcuts *shortcuts;
shortcuts = E_SHORTCUTS (data);
update_shortcuts_by_path (shortcuts, path);
make_dirty (shortcuts);
}
/* GtkObject methods. */
static void
destroy (GtkObject *object)
{
EShortcuts *shortcuts;
EShortcutsPrivate *priv;
shortcuts = E_SHORTCUTS (object);
priv = shortcuts->priv;
g_free (priv->file_name);
if (priv->storage_set != NULL)
gtk_object_unref (GTK_OBJECT (priv->storage_set));
if (priv->folder_type_registry != NULL)
gtk_object_unref (GTK_OBJECT (priv->folder_type_registry));
unload_shortcuts (shortcuts);
if (priv->save_idle_id != 0)
gtk_idle_remove (priv->save_idle_id);
if (priv->dirty) {
if (! e_shortcuts_save (shortcuts, NULL))
g_warning (_("Error saving shortcuts.")); /* FIXME */
}
g_hash_table_destroy (priv->title_to_group);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void
class_init (EShortcutsClass *klass)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) klass;
object_class->destroy = destroy;
parent_class = gtk_type_class (gtk_object_get_type ());
signals[NEW_GROUP]
= gtk_signal_new ("new_group",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutsClass, new_group),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
signals[REMOVE_GROUP]
= gtk_signal_new ("remove_group",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutsClass, remove_group),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
signals[NEW_SHORTCUT]
= gtk_signal_new ("new_shortcut",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutsClass, new_shortcut),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
signals[REMOVE_SHORTCUT]
= gtk_signal_new ("remove_shortcut",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutsClass, remove_shortcut),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
signals[UPDATE_SHORTCUT]
= gtk_signal_new ("update_shortcut",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutsClass, update_shortcut),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
static void
init (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
priv = g_new (EShortcutsPrivate, 1);
priv->file_name = NULL;
priv->storage_set = NULL;
priv->groups = NULL;
priv->views = NULL;
priv->title_to_group = g_hash_table_new (g_str_hash, g_str_equal);
priv->dirty = 0;
priv->save_idle_id = 0;
shortcuts->priv = priv;
}
void
e_shortcuts_construct (EShortcuts *shortcuts,
EStorageSet *storage_set,
EFolderTypeRegistry *folder_type_registry)
{
EShortcutsPrivate *priv;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
g_return_if_fail (storage_set != NULL);
g_return_if_fail (E_IS_STORAGE_SET (storage_set));
GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (shortcuts), GTK_FLOATING);
priv = shortcuts->priv;
gtk_object_ref (GTK_OBJECT (storage_set));
priv->storage_set = storage_set;
gtk_signal_connect (GTK_OBJECT (storage_set), "new_folder",
GTK_SIGNAL_FUNC (storage_set_new_folder_callback), shortcuts);
gtk_signal_connect (GTK_OBJECT (storage_set), "updated_folder",
GTK_SIGNAL_FUNC (storage_set_updated_folder_callback), shortcuts);
gtk_object_ref (GTK_OBJECT (folder_type_registry));
priv->folder_type_registry = folder_type_registry;
}
EShortcuts *
e_shortcuts_new (EStorageSet *storage_set,
EFolderTypeRegistry *folder_type_registry,
const char *file_name)
{
EShortcuts *new;
g_return_val_if_fail (storage_set != NULL, NULL);
g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL);
new = gtk_type_new (e_shortcuts_get_type ());
e_shortcuts_construct (new, storage_set, folder_type_registry);
if (! e_shortcuts_load (new, file_name)) {
gtk_object_unref (GTK_OBJECT (new));
return NULL;
}
return new;
}
GSList *
e_shortcuts_get_group_titles (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
ShortcutGroup *group;
GSList *list;
GSList *p;
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
priv = shortcuts->priv;
list = NULL;
for (p = priv->groups; p != NULL; p = p->next) {
group = (ShortcutGroup *) p->data;
list = g_slist_prepend (list, g_strdup (group->title));
}
return g_slist_reverse (list);
}
const GSList *
e_shortcuts_get_shortcuts_in_group (EShortcuts *shortcuts,
const char *group_title)
{
EShortcutsPrivate *priv;
ShortcutGroup *shortcut_group;
priv = shortcuts->priv;
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
g_return_val_if_fail (group_title != NULL, NULL);
shortcut_group = g_hash_table_lookup (priv->title_to_group, group_title);
if (shortcut_group == NULL)
return NULL;
return shortcut_group->shortcuts;
}
EStorageSet *
e_shortcuts_get_storage_set (EShortcuts *shortcuts)
{
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
return shortcuts->priv->storage_set;
}
GtkWidget *
e_shortcuts_new_view (EShortcuts *shortcuts)
{
EShortcutsPrivate *priv;
GtkWidget *new;
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
priv = shortcuts->priv;
new = e_shortcuts_view_new (shortcuts);
priv->views = g_slist_prepend (priv->views, new);
gtk_signal_connect (GTK_OBJECT (new), "destroy", view_destroyed_cb, shortcuts);
return new;
}
gboolean
e_shortcuts_load (EShortcuts *shortcuts,
const char *file_name)
{
EShortcutsPrivate *priv;
char *tmp;
g_return_val_if_fail (shortcuts != NULL, FALSE);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE);
g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE);
priv = shortcuts->priv;
if (file_name == NULL) {
if (priv->file_name == NULL)
return FALSE;
file_name = priv->file_name;
}
if (! load_shortcuts (shortcuts, file_name))
return FALSE;
tmp = g_strdup (file_name);
g_free (priv->file_name);
priv->file_name = tmp;
return TRUE;
}
gboolean
e_shortcuts_save (EShortcuts *shortcuts,
const char *file_name)
{
EShortcutsPrivate *priv;
char *tmp;
g_return_val_if_fail (shortcuts != NULL, FALSE);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE);
g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE);
priv = shortcuts->priv;
if (file_name == NULL) {
if (priv->file_name == NULL)
return FALSE;
file_name = priv->file_name;
}
if (! save_shortcuts (shortcuts, file_name))
return FALSE;
tmp = g_strdup (file_name);
g_free (priv->file_name);
priv->file_name = tmp;
return TRUE;
}
const EShortcutItem *
e_shortcuts_get_shortcut (EShortcuts *shortcuts,
int group_num,
int num)
{
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
return (const EShortcutItem *) get_item (shortcuts, group_num, num);
}
void
e_shortcuts_remove_shortcut (EShortcuts *shortcuts,
int group_num,
int num)
{
EShortcutsPrivate *priv;
ShortcutGroup *group;
GSList *p;
EShortcutItem *item;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
priv = shortcuts->priv;
p = g_slist_nth (priv->groups, group_num);
g_return_if_fail (p != NULL);
group = (ShortcutGroup *) p->data;
p = g_slist_nth (group->shortcuts, num);
g_return_if_fail (p != NULL);
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_SHORTCUT], group_num, num);
item = (EShortcutItem *) p->data;
shortcut_item_free (item);
group->shortcuts = g_slist_remove_link (group->shortcuts, p);
make_dirty (shortcuts);
}
void
e_shortcuts_add_shortcut (EShortcuts *shortcuts,
int group_num,
int num,
const char *uri,
const char *name,
const char *type)
{
EShortcutsPrivate *priv;
ShortcutGroup *group;
EShortcutItem *item;
GSList *p;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
priv = shortcuts->priv;
p = g_slist_nth (priv->groups, group_num);
g_return_if_fail (p != NULL);
group = (ShortcutGroup *) p->data;
if (num == -1)
num = g_slist_length (group->shortcuts);
item = shortcut_item_new (uri, name, type);
group->shortcuts = g_slist_insert (group->shortcuts, item, num);
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[NEW_SHORTCUT], group_num, num);
make_dirty (shortcuts);
}
void
e_shortcuts_update_shortcut (EShortcuts *shortcuts,
int group_num,
int num,
const char *uri,
const char *name,
const char *type)
{
EShortcutItem *shortcut_item;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
shortcut_item = get_item (shortcuts, group_num, num);
update_shortcut_and_emit_signal (shortcuts, shortcut_item, group_num, num, uri, name, type);
}
void
e_shortcuts_remove_group (EShortcuts *shortcuts,
int group_num)
{
EShortcutsPrivate *priv;
GSList *p;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
priv = shortcuts->priv;
p = g_slist_nth (priv->groups, group_num);
g_return_if_fail (p != NULL);
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_GROUP], group_num);
shortcut_group_free ((ShortcutGroup *) p->data);
priv->groups = g_slist_remove_link (priv->groups, p);
make_dirty (shortcuts);
}
void
e_shortcuts_add_group (EShortcuts *shortcuts,
int group_num,
const char *group_name)
{
EShortcutsPrivate *priv;
ShortcutGroup *group;
g_return_if_fail (shortcuts != NULL);
g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
priv = shortcuts->priv;
group = shortcut_group_new (group_name);
if (group_num == -1)
group_num = g_slist_length (priv->groups);
priv->groups = g_slist_insert (priv->groups, group, group_num);
gtk_signal_emit (GTK_OBJECT (shortcuts), signals[NEW_GROUP], group_num);
make_dirty (shortcuts);
}
const char *
e_shortcuts_get_group_title (EShortcuts *shortcuts,
int group_num)
{
EShortcutsPrivate *priv;
GSList *group_element;
const ShortcutGroup *group;
g_return_val_if_fail (shortcuts != NULL, NULL);
g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
priv = shortcuts->priv;
group_element = g_slist_nth (priv->groups, group_num);
if (group_element == NULL)
return NULL;
group = (ShortcutGroup *) group_element->data;
return group->title;
}
E_MAKE_TYPE (e_shortcuts, "EShortcuts", EShortcuts, class_init, init, PARENT_TYPE)