/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see
*
*
* Authors:
* Chris Toshok
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include "eab-editor.h"
#include "e-util/e-util.h"
#include "addressbook/gui/widgets/eab-gui-util.h"
struct _EABEditorPrivate {
EShell *shell;
};
enum {
PROP_0,
PROP_SHELL
};
enum {
CONTACT_ADDED,
CONTACT_MODIFIED,
CONTACT_DELETED,
EDITOR_CLOSED,
LAST_SIGNAL
};
static GSList *all_editors;
static gpointer parent_class;
static guint signals[LAST_SIGNAL];
static void
eab_editor_quit_requested_cb (EShell *shell,
EShellQuitReason reason,
EABEditor *editor)
{
GtkWindow *window;
/* Quit immediately if another Evolution process asked us to. */
if (reason == E_SHELL_QUIT_REMOTE_REQUEST)
return;
window = eab_editor_get_window (editor);
eab_editor_raise (editor);
if (!eab_editor_prompt_to_save_changes (editor, window))
e_shell_cancel_quit (shell);
}
static void
eab_editor_set_shell (EABEditor *editor,
EShell *shell)
{
g_return_if_fail (editor->priv->shell == NULL);
g_return_if_fail (E_IS_SHELL (shell));
editor->priv->shell = g_object_ref (shell);
g_signal_connect (
shell, "quit-requested",
G_CALLBACK (eab_editor_quit_requested_cb), editor);
}
static void
eab_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_SHELL:
eab_editor_set_shell (
EAB_EDITOR (object),
g_value_get_object (value));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
eab_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_SHELL:
g_value_set_object (
value, eab_editor_get_shell (
EAB_EDITOR (object)));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
eab_editor_dispose (GObject *object)
{
EABEditorPrivate *priv;
priv = EAB_EDITOR (object)->priv;
if (priv->shell != NULL) {
g_signal_handlers_disconnect_matched (
priv->shell, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, object);
g_object_unref (priv->shell);
priv->shell = NULL;
}
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
eab_editor_finalize (GObject *object)
{
all_editors = g_slist_remove (all_editors, object);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
eab_editor_class_init (EABEditorClass *class)
{
GObjectClass *object_class;
parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (EABEditorPrivate));
object_class = G_OBJECT_CLASS (class);
object_class->set_property = eab_editor_set_property;
object_class->get_property = eab_editor_get_property;
object_class->dispose = eab_editor_dispose;
object_class->finalize = eab_editor_finalize;
g_object_class_install_property (
object_class,
PROP_SHELL,
g_param_spec_object (
"shell",
"Shell",
"The EShell singleton",
E_TYPE_SHELL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[CONTACT_ADDED] =
g_signal_new ("contact_added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EABEditorClass, contact_added),
NULL, NULL,
e_marshal_NONE__POINTER_OBJECT,
G_TYPE_NONE, 2,
G_TYPE_POINTER, G_TYPE_OBJECT);
signals[CONTACT_MODIFIED] =
g_signal_new ("contact_modified",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EABEditorClass, contact_modified),
NULL, NULL,
e_marshal_NONE__POINTER_OBJECT,
G_TYPE_NONE, 2,
G_TYPE_POINTER, G_TYPE_OBJECT);
signals[CONTACT_DELETED] =
g_signal_new ("contact_deleted",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EABEditorClass, contact_deleted),
NULL, NULL,
e_marshal_NONE__POINTER_OBJECT,
G_TYPE_NONE, 2,
G_TYPE_POINTER, G_TYPE_OBJECT);
signals[EDITOR_CLOSED] =
g_signal_new ("editor_closed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EABEditorClass, editor_closed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eab_editor_init (EABEditor *editor)
{
editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (
editor, EAB_TYPE_EDITOR, EABEditorPrivate);
all_editors = g_slist_prepend (all_editors, editor);
}
GType
eab_editor_get_type (void)
{
static GType type = 0;
if (G_UNLIKELY (type == 0)) {
static const GTypeInfo type_info = {
sizeof (EABEditorClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) eab_editor_class_init,
(GClassFinalizeFunc) NULL,
NULL, /* class_data */
sizeof (EABEditor),
0, /* n_preallocs */
(GInstanceInitFunc) eab_editor_init,
NULL /* value_table */
};
type = g_type_register_static (
G_TYPE_OBJECT, "EABEditor", &type_info,
G_TYPE_FLAG_ABSTRACT);
}
return type;
}
EShell *
eab_editor_get_shell (EABEditor *editor)
{
g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL);
return E_SHELL (editor->priv->shell);
}
GSList *
eab_editor_get_all_editors (void)
{
return all_editors;
}
void
eab_editor_show (EABEditor *editor)
{
EABEditorClass *class;
g_return_if_fail (EAB_IS_EDITOR (editor));
class = EAB_EDITOR_GET_CLASS (editor);
g_return_if_fail (class->show != NULL);
class->show (editor);
}
void
eab_editor_close (EABEditor *editor)
{
EABEditorClass *class;
g_return_if_fail (EAB_IS_EDITOR (editor));
class = EAB_EDITOR_GET_CLASS (editor);
g_return_if_fail (class->close != NULL);
class->close (editor);
}
void
eab_editor_raise (EABEditor *editor)
{
EABEditorClass *class;
g_return_if_fail (EAB_IS_EDITOR (editor));
class = EAB_EDITOR_GET_CLASS (editor);
g_return_if_fail (class->raise != NULL);
class->raise (editor);
}
void
eab_editor_save_contact (EABEditor *editor,
gboolean should_close)
{
EABEditorClass *class;
g_return_if_fail (EAB_IS_EDITOR (editor));
class = EAB_EDITOR_GET_CLASS (editor);
g_return_if_fail (class->save_contact != NULL);
class->save_contact (editor, should_close);
}
gboolean
eab_editor_is_changed (EABEditor *editor)
{
EABEditorClass *class;
g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE);
class = EAB_EDITOR_GET_CLASS (editor);
g_return_val_if_fail (class->is_changed != NULL, FALSE);
return class->is_changed (editor);
}
gboolean
eab_editor_is_valid (EABEditor *editor)
{
EABEditorClass *class;
g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE);
class = EAB_EDITOR_GET_CLASS (editor);
g_return_val_if_fail (class->is_valid != NULL, FALSE);
return class->is_valid (editor);
}
GtkWindow *
eab_editor_get_window (EABEditor *editor)
{
EABEditorClass *class;
g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL);
class = EAB_EDITOR_GET_CLASS (editor);
g_return_val_if_fail (class->get_window != NULL, NULL);
return class->get_window (editor);
}
/* This function prompts for saving if editor conents are in changed state and
* save or discards or cancels (just returns with out doing anything) according
* to user input. Editor gets destroyed in case of save and discard case. */
gboolean
eab_editor_prompt_to_save_changes (EABEditor *editor,
GtkWindow *window)
{
if (!eab_editor_is_changed (editor)) {
eab_editor_close (EAB_EDITOR (editor));
return TRUE;
}
switch (eab_prompt_save_dialog (window)) {
case GTK_RESPONSE_YES:
if (!eab_editor_is_valid (editor)) {
return FALSE;
}
eab_editor_save_contact (editor, TRUE);
return TRUE;
case GTK_RESPONSE_NO:
eab_editor_close (EAB_EDITOR (editor));
return TRUE;
case GTK_RESPONSE_CANCEL:
default:
return FALSE;
}
}
void
eab_editor_contact_added (EABEditor *editor,
const GError *error,
EContact *contact)
{
g_return_if_fail (EAB_IS_EDITOR (editor));
g_return_if_fail (E_IS_CONTACT (contact));
g_signal_emit (editor, signals[CONTACT_ADDED], 0, error, contact);
}
void
eab_editor_contact_modified (EABEditor *editor,
const GError *error,
EContact *contact)
{
g_return_if_fail (EAB_IS_EDITOR (editor));
g_return_if_fail (E_IS_CONTACT (contact));
g_signal_emit (editor, signals[CONTACT_MODIFIED], 0, error, contact);
}
void
eab_editor_contact_deleted (EABEditor *editor,
const GError *error,
EContact *contact)
{
g_return_if_fail (EAB_IS_EDITOR (editor));
g_return_if_fail (E_IS_CONTACT (contact));
g_signal_emit (editor, signals[CONTACT_DELETED], 0, error, contact);
}
void
eab_editor_closed (EABEditor *editor)
{
g_return_if_fail (EAB_IS_EDITOR (editor));
g_signal_emit (editor, signals[EDITOR_CLOSED], 0);
}