/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Author :
* Damon Chaplin <damon@helixcode.com>
*
* Copyright 1999, Helix Code, 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
*/
/*
* EShortcutModel keeps track of a number of groups of shortcuts.
* Each shortcut has a URL and a short textual name.
* It is used as the model of the EShortcutBar.
*/
#include <config.h>
#include <gtk/gtksignal.h>
#include <e-util/e-util.h>
#include "e-shortcut-model.h"
/* This contains information on one item. */
typedef struct _EShortcutModelItem EShortcutModelItem;
struct _EShortcutModelItem
{
gchar *name;
gchar *url;
};
/* This contains information on one group. */
typedef struct _EShortcutModelGroup EShortcutModelGroup;
struct _EShortcutModelGroup
{
gchar *name;
/* An array of EShortcutModelItem. */
GArray *items;
};
#define ESM_CLASS(e) ((EShortcutModelClass *)((GtkObject *)e)->klass)
static void e_shortcut_model_class_init (EShortcutModelClass *class);
static void e_shortcut_model_init (EShortcutModel *shortcut_model);
static void e_shortcut_model_destroy (GtkObject *object);
static void e_shortcut_model_free_group (EShortcutModel *shortcut_model,
gint group_num);
static void e_shortcut_model_real_add_group (EShortcutModel *shortcut_model,
gint position,
const gchar *group_name);
static void e_shortcut_model_real_remove_group (EShortcutModel *shortcut_model,
gint group_num);
static void e_shortcut_model_real_add_item (EShortcutModel *shortcut_model,
gint group_num,
gint position,
const gchar *item_url,
const gchar *item_name);
static void e_shortcut_model_real_remove_item (EShortcutModel *shortcut_model,
gint group_num,
gint item_num);
static void e_shortcut_model_marshal1 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
static void e_shortcut_model_marshal2 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
static gint e_shortcut_model_real_get_num_groups(EShortcutModel *shortcut_model);
static gint e_shortcut_model_real_get_num_items (EShortcutModel *shortcut_model,
gint group_num);
static gchar* e_shortcut_model_real_get_group_name (EShortcutModel *shortcut_model,
gint group_num);
static void e_shortcut_model_real_get_item_info (EShortcutModel *shortcut_model,
gint group_num,
gint item_num,
gchar **item_url,
gchar **item_name);
enum
{
GROUP_ADDED,
GROUP_REMOVED,
ITEM_ADDED,
ITEM_REMOVED,
LAST_SIGNAL
};
static guint e_shortcut_model_signals[LAST_SIGNAL] = {0};
static GtkObjectClass *parent_class;
E_MAKE_TYPE(e_shortcut_model, "EShortcutModel", EShortcutModel,
e_shortcut_model_class_init, e_shortcut_model_init,
GTK_TYPE_OBJECT)
static void
e_shortcut_model_class_init (EShortcutModelClass *class)
{
GtkObjectClass *object_class;
parent_class = gtk_type_class (GTK_TYPE_OBJECT);
object_class = (GtkObjectClass *) class;
e_shortcut_model_signals[GROUP_ADDED] =
gtk_signal_new ("group_added",
GTK_RUN_FIRST | GTK_RUN_ACTION,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutModelClass,
group_added),
e_shortcut_model_marshal1,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT, GTK_TYPE_STRING);
e_shortcut_model_signals[GROUP_REMOVED] =
gtk_signal_new ("group_removed",
GTK_RUN_FIRST | GTK_RUN_ACTION,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutModelClass,
group_removed),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
e_shortcut_model_signals[ITEM_ADDED] =
gtk_signal_new ("item_added",
GTK_RUN_FIRST | GTK_RUN_ACTION,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutModelClass,
item_added),
e_shortcut_model_marshal2,
GTK_TYPE_NONE, 4,
GTK_TYPE_INT, GTK_TYPE_INT,
GTK_TYPE_STRING, GTK_TYPE_STRING);
e_shortcut_model_signals[ITEM_REMOVED] =
gtk_signal_new ("item_removed",
GTK_RUN_FIRST | GTK_RUN_ACTION,
object_class->type,
GTK_SIGNAL_OFFSET (EShortcutModelClass,
item_removed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, e_shortcut_model_signals,
LAST_SIGNAL);
/* Method override */
object_class->destroy = e_shortcut_model_destroy;
class->group_added = e_shortcut_model_real_add_group;
class->group_removed = e_shortcut_model_real_remove_group;
class->item_added = e_shortcut_model_real_add_item;
class->item_removed = e_shortcut_model_real_remove_item;
class->get_num_groups = e_shortcut_model_real_get_num_groups;
class->get_num_items = e_shortcut_model_real_get_num_items;
class->get_group_name = e_shortcut_model_real_get_group_name;
class->get_item_info = e_shortcut_model_real_get_item_info;
}
static void
e_shortcut_model_init (EShortcutModel *shortcut_model)
{
shortcut_model->groups = g_array_new (FALSE, FALSE,
sizeof (EShortcutModelGroup));
}
EShortcutModel *
e_shortcut_model_new (void)
{
EShortcutModel *shortcut_model;
shortcut_model = E_SHORTCUT_MODEL (gtk_type_new (e_shortcut_model_get_type ()));
return shortcut_model;
}
static void
e_shortcut_model_destroy (GtkObject *object)
{
EShortcutModel *shortcut_model;
gint num_groups, group_num;
shortcut_model = E_SHORTCUT_MODEL (object);
num_groups = shortcut_model->groups->len;
for (group_num = 0; group_num < num_groups; group_num++)
e_shortcut_model_free_group (shortcut_model, group_num);
g_array_free (shortcut_model->groups, TRUE);
shortcut_model->groups = NULL;
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
e_shortcut_model_free_group (EShortcutModel *shortcut_model,
gint group_num)
{
EShortcutModelGroup *group;
EShortcutModelItem *item;
gint item_num;
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
g_free (group->name);
for (item_num = 0; item_num < group->items->len; item_num++) {
item = &g_array_index (group->items,
EShortcutModelItem, item_num);
g_free (item->name);
g_free (item->url);
}
}
gint
e_shortcut_model_add_group (EShortcutModel *shortcut_model,
gint position,
const gchar *group_name)
{
g_return_val_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model), -1);
g_return_val_if_fail (group_name != NULL, -1);
if (position == -1 || position > shortcut_model->groups->len)
position = shortcut_model->groups->len;
gtk_signal_emit (GTK_OBJECT (shortcut_model),
e_shortcut_model_signals[GROUP_ADDED],
position, group_name);
return position;
}
static void
e_shortcut_model_real_add_group (EShortcutModel *shortcut_model,
gint group_num,
const gchar *group_name)
{
EShortcutModelGroup *group, tmp_group;
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num <= shortcut_model->groups->len);
g_return_if_fail (group_name != NULL);
g_array_insert_val (shortcut_model->groups, group_num, tmp_group);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
group->name = g_strdup (group_name);
group->items = g_array_new (FALSE, FALSE,
sizeof (EShortcutModelItem));
}
void
e_shortcut_model_remove_group (EShortcutModel *shortcut_model,
gint group_num)
{
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num < shortcut_model->groups->len);
gtk_signal_emit (GTK_OBJECT (shortcut_model),
e_shortcut_model_signals[GROUP_REMOVED],
group_num);
}
static void
e_shortcut_model_real_remove_group (EShortcutModel *shortcut_model,
gint group_num)
{
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num < shortcut_model->groups->len);
e_shortcut_model_free_group (shortcut_model, group_num);
g_array_remove_index (shortcut_model->groups, group_num);
}
gint
e_shortcut_model_add_item (EShortcutModel *shortcut_model,
gint group_num,
gint position,
const gchar *item_url,
const gchar *item_name)
{
EShortcutModelGroup *group;
g_return_val_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model), -1);
g_return_val_if_fail (group_num >= 0, -1);
g_return_val_if_fail (group_num < shortcut_model->groups->len, -1);
g_return_val_if_fail (item_url != NULL, -1);
g_return_val_if_fail (item_name != NULL, -1);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
if (position == -1 || position > group->items->len)
position = group->items->len;
gtk_signal_emit (GTK_OBJECT (shortcut_model),
e_shortcut_model_signals[ITEM_ADDED],
group_num, position, item_url, item_name);
return position;
}
static void
e_shortcut_model_real_add_item (EShortcutModel *shortcut_model,
gint group_num,
gint item_num,
const gchar *item_url,
const gchar *item_name)
{
EShortcutModelGroup *group;
EShortcutModelItem *item, tmp_item;
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num < shortcut_model->groups->len);
g_return_if_fail (item_url != NULL);
g_return_if_fail (item_name != NULL);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
g_return_if_fail (item_num >= 0);
g_return_if_fail (item_num <= group->items->len);
g_array_insert_val (group->items, item_num, tmp_item);
item = &g_array_index (group->items,
EShortcutModelItem, item_num);
item->name = g_strdup (item_name);
item->url = g_strdup (item_url);
}
void
e_shortcut_model_remove_item (EShortcutModel *shortcut_model,
gint group_num,
gint item_num)
{
gtk_signal_emit (GTK_OBJECT (shortcut_model),
e_shortcut_model_signals[ITEM_REMOVED],
group_num, item_num);
}
static void
e_shortcut_model_real_remove_item (EShortcutModel *shortcut_model,
gint group_num,
gint item_num)
{
EShortcutModelGroup *group;
EShortcutModelItem *item;
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num < shortcut_model->groups->len);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
g_return_if_fail (item_num >= 0);
g_return_if_fail (item_num < group->items->len);
item = &g_array_index (group->items,
EShortcutModelItem, item_num);
g_free (item->name);
g_free (item->url);
g_array_remove_index (group->items, item_num);
}
static void
e_shortcut_model_marshal1 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
void (*rfunc) (GtkObject*, gint, gpointer, gpointer);
rfunc = (void (*) (GtkObject*, gint, gpointer, gpointer)) func;
(*rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_STRING (args[1]),
func_data);
}
static void
e_shortcut_model_marshal2 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
void (*rfunc) (GtkObject*, gint, gint, gpointer, gpointer, gpointer);
rfunc = (void (*) (GtkObject*, gint, gint, gpointer, gpointer,
gpointer)) func;
(*rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]),
GTK_VALUE_STRING (args[2]), GTK_VALUE_STRING (args[3]),
func_data);
}
gint
e_shortcut_model_get_num_groups (EShortcutModel *shortcut_model)
{
g_return_val_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model), 0);
return ESM_CLASS (shortcut_model)->get_num_groups (shortcut_model);
}
static gint
e_shortcut_model_real_get_num_groups (EShortcutModel *shortcut_model)
{
return shortcut_model->groups->len;
}
gint
e_shortcut_model_get_num_items (EShortcutModel *shortcut_model,
gint group_num)
{
g_return_val_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model), 0);
return ESM_CLASS (shortcut_model)->get_num_items (shortcut_model,
group_num);
}
static gint
e_shortcut_model_real_get_num_items (EShortcutModel *shortcut_model,
gint group_num)
{
EShortcutModelGroup *group;
g_return_val_if_fail (group_num >= 0, 0);
g_return_val_if_fail (group_num < shortcut_model->groups->len, 0);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
return group->items->len;
}
gchar*
e_shortcut_model_get_group_name (EShortcutModel *shortcut_model,
gint group_num)
{
g_return_val_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model), NULL);
return ESM_CLASS (shortcut_model)->get_group_name (shortcut_model,
group_num);
}
static gchar*
e_shortcut_model_real_get_group_name (EShortcutModel *shortcut_model,
gint group_num)
{
EShortcutModelGroup *group;
g_return_val_if_fail (group_num >= 0, NULL);
g_return_val_if_fail (group_num < shortcut_model->groups->len, NULL);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
return g_strdup (group->name);
}
void
e_shortcut_model_get_item_info (EShortcutModel *shortcut_model,
gint group_num,
gint item_num,
gchar **item_url,
gchar **item_name)
{
g_return_if_fail (E_IS_SHORTCUT_MODEL (shortcut_model));
ESM_CLASS (shortcut_model)->get_item_info (shortcut_model,
group_num, item_num,
item_url, item_name);
}
static void
e_shortcut_model_real_get_item_info (EShortcutModel *shortcut_model,
gint group_num,
gint item_num,
gchar **item_url,
gchar **item_name)
{
EShortcutModelGroup *group;
EShortcutModelItem *item;
g_return_if_fail (group_num >= 0);
g_return_if_fail (group_num < shortcut_model->groups->len);
group = &g_array_index (shortcut_model->groups,
EShortcutModelGroup, group_num);
g_return_if_fail (item_num >= 0);
g_return_if_fail (item_num < group->items->len);
item = &g_array_index (group->items,
EShortcutModelItem, item_num);
if (item_url)
*item_url = g_strdup (item->url);
if (item_name)
*item_name = g_strdup (item->name);
}