2002-04-11 jacob berkman <jacob@ximian.com> * (various files): fix improper use of guint as GType
592 lines
16 KiB
C
592 lines
16 KiB
C
/* -*- mode: c; style: linux -*- */
|
|
|
|
/* rollback-capplet-dialog.c
|
|
* Copyright (C) 2000 Helix Code, Inc.
|
|
*
|
|
* Written by Bradford Hovinen <hovinen@helixcode.com>
|
|
*
|
|
* 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, 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.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <glade/glade.h>
|
|
#include <bonobo.h>
|
|
#include <gnome-xml/parser.h>
|
|
|
|
#include <config-archiver/archiver-client.h>
|
|
#include <config-archiver/util.h>
|
|
|
|
#include "rollback-capplet-dialog.h"
|
|
|
|
static const gchar date_mod_units[] = {
|
|
'y', 'M', 'M', 'd', 'd', 'd', 'h', 'm', 'm', 'm', 'm', '\0'
|
|
};
|
|
|
|
static const gint date_mod_values[] = {
|
|
-1, -6, -1, -7, -3, -1, -1, -30, -10, -5, -1, 0
|
|
};
|
|
|
|
static const gchar *labels[] = {
|
|
N_("1 year ago"), N_("6 months ago"), N_("1 month ago"), N_("1 week ago"),
|
|
N_("3 days ago"), N_("1 day ago"), N_("1 hour ago"), N_("30 minutes ago"),
|
|
N_("10 minutes ago"), N_("5 minutes ago"), N_("1 minute ago"), N_("Current time")
|
|
};
|
|
|
|
#define NUM_ROLLBACK_LEVELS (sizeof (labels) / sizeof (const gchar *))
|
|
|
|
enum {
|
|
ARG_0,
|
|
ARG_CAPPLET_NAME
|
|
};
|
|
|
|
struct _RollbackCappletDialogPrivate
|
|
{
|
|
GladeXML *data;
|
|
GtkWidget *contents;
|
|
GtkWidget *control_socket;
|
|
GtkWidget *label;
|
|
gchar *capplet_name;
|
|
gchar *capplet_moniker_name;
|
|
|
|
Bonobo_PropertyControl property_control;
|
|
Bonobo_PropertyBag control_pb;
|
|
|
|
guint rollback_level;
|
|
|
|
struct tm mod_dates[NUM_ROLLBACK_LEVELS - 1];
|
|
};
|
|
|
|
static GnomeDialogClass *parent_class;
|
|
|
|
static void rollback_capplet_dialog_init (RollbackCappletDialog *rollback_capplet_dialog);
|
|
static void rollback_capplet_dialog_class_init (RollbackCappletDialogClass *class);
|
|
|
|
static void rollback_capplet_dialog_set_arg (GtkObject *object,
|
|
GtkArg *arg,
|
|
guint arg_id);
|
|
static void rollback_capplet_dialog_get_arg (GtkObject *object,
|
|
GtkArg *arg,
|
|
guint arg_id);
|
|
|
|
static void rollback_capplet_dialog_destroy (GtkObject *object);
|
|
static void rollback_capplet_dialog_finalize (GtkObject *object);
|
|
|
|
static gchar *get_moniker (gchar *capplet_name,
|
|
struct tm *date);
|
|
static void get_modified_date (guint rollback_level,
|
|
struct tm *date);
|
|
static gboolean do_setup (RollbackCappletDialog *dialog);
|
|
static void apply_settings (RollbackCappletDialog *dialog);
|
|
|
|
static gboolean is_leap_year (guint year);
|
|
static void mod_date_by_str (struct tm *date,
|
|
gint value,
|
|
gchar unit);
|
|
|
|
static void rollback_changed_cb (RollbackCappletDialog *dialog,
|
|
GtkAdjustment *adj);
|
|
static void apply_cb (GtkButton *button,
|
|
RollbackCappletDialog *dialog);
|
|
static void close_cb (GtkButton *button,
|
|
RollbackCappletDialog *dialog);
|
|
|
|
GType
|
|
rollback_capplet_dialog_get_type (void)
|
|
{
|
|
static GType rollback_capplet_dialog_type = 0;
|
|
|
|
if (!rollback_capplet_dialog_type) {
|
|
GtkTypeInfo rollback_capplet_dialog_info = {
|
|
"RollbackCappletDialog",
|
|
sizeof (RollbackCappletDialog),
|
|
sizeof (RollbackCappletDialogClass),
|
|
(GtkClassInitFunc) rollback_capplet_dialog_class_init,
|
|
(GtkObjectInitFunc) rollback_capplet_dialog_init,
|
|
(GtkArgSetFunc) NULL,
|
|
(GtkArgGetFunc) NULL
|
|
};
|
|
|
|
rollback_capplet_dialog_type =
|
|
gtk_type_unique (gnome_dialog_get_type (),
|
|
&rollback_capplet_dialog_info);
|
|
}
|
|
|
|
return rollback_capplet_dialog_type;
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_init (RollbackCappletDialog *dialog)
|
|
{
|
|
GtkAdjustment *adj;
|
|
GtkWidget *range;
|
|
GladeXML *data;
|
|
|
|
static const gchar *buttons[] = {
|
|
GNOME_STOCK_BUTTON_APPLY,
|
|
GNOME_STOCK_BUTTON_CLOSE,
|
|
NULL
|
|
};
|
|
|
|
data = glade_xml_new (GNOMECC_GLADE_DIR "/rollback.glade", "rollback_dialog");
|
|
|
|
if (data == NULL) {
|
|
g_critical ("Your Glade file is either missing or corrupt.");
|
|
dialog->p = (gpointer) 0xdeadbeef;
|
|
return;
|
|
}
|
|
|
|
dialog->p = g_new0 (RollbackCappletDialogPrivate, 1);
|
|
dialog->p->data = data;
|
|
dialog->p->contents = glade_xml_get_widget (dialog->p->data, "rollback_dialog");
|
|
dialog->p->control_socket = glade_xml_get_widget (dialog->p->data, "control_socket");
|
|
dialog->p->label = glade_xml_get_widget (dialog->p->data, "rollback_level_label");
|
|
dialog->p->rollback_level = 12;
|
|
|
|
range = glade_xml_get_widget (dialog->p->data, "rollback_scale");
|
|
adj = GTK_ADJUSTMENT (gtk_adjustment_new (12, 0, 12, 1, 1, 1));
|
|
gtk_range_set_adjustment (GTK_RANGE (range), adj);
|
|
gtk_signal_connect_object (GTK_OBJECT (adj), "value-changed",
|
|
GTK_SIGNAL_FUNC (rollback_changed_cb), GTK_OBJECT (dialog));
|
|
|
|
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), dialog->p->contents, TRUE, TRUE, 0);
|
|
|
|
gnome_dialog_constructv (GNOME_DIALOG (dialog), _("Rollback"), buttons);
|
|
|
|
gnome_dialog_button_connect (GNOME_DIALOG (dialog), 0, GTK_SIGNAL_FUNC (apply_cb), dialog);
|
|
gnome_dialog_button_connect (GNOME_DIALOG (dialog), 1, GTK_SIGNAL_FUNC (close_cb), dialog);
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_class_init (RollbackCappletDialogClass *class)
|
|
{
|
|
GtkObjectClass *object_class;
|
|
|
|
gtk_object_add_arg_type ("RollbackCappletDialog::capplet-name",
|
|
GTK_TYPE_POINTER,
|
|
GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
|
|
ARG_CAPPLET_NAME);
|
|
|
|
object_class = GTK_OBJECT_CLASS (class);
|
|
object_class->destroy = rollback_capplet_dialog_destroy;
|
|
object_class->finalize = rollback_capplet_dialog_finalize;
|
|
object_class->set_arg = rollback_capplet_dialog_set_arg;
|
|
object_class->get_arg = rollback_capplet_dialog_get_arg;
|
|
|
|
parent_class = GNOME_DIALOG_CLASS
|
|
(gtk_type_class (gnome_dialog_get_type ()));
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
|
{
|
|
RollbackCappletDialog *dialog;
|
|
gchar *tmp;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (IS_ROLLBACK_CAPPLET_DIALOG (object));
|
|
|
|
dialog = ROLLBACK_CAPPLET_DIALOG (object);
|
|
|
|
if (dialog->p == (gpointer) 0xdeadbeef)
|
|
return;
|
|
|
|
switch (arg_id) {
|
|
case ARG_CAPPLET_NAME:
|
|
g_return_if_fail (GTK_VALUE_POINTER (*arg) != NULL);
|
|
|
|
dialog->p->capplet_name = GTK_VALUE_POINTER (*arg);
|
|
|
|
dialog->p->capplet_moniker_name = g_strdup (dialog->p->capplet_name);
|
|
if ((tmp = strstr (dialog->p->capplet_moniker_name, "-capplet")) != NULL) *tmp = '\0';
|
|
|
|
break;
|
|
|
|
default:
|
|
g_warning ("Bad argument set");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
|
{
|
|
RollbackCappletDialog *dialog;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (IS_ROLLBACK_CAPPLET_DIALOG (object));
|
|
|
|
dialog = ROLLBACK_CAPPLET_DIALOG (object);
|
|
|
|
switch (arg_id) {
|
|
case ARG_CAPPLET_NAME:
|
|
GTK_VALUE_POINTER (*arg) = dialog->p->capplet_name;
|
|
break;
|
|
|
|
default:
|
|
g_warning ("Bad argument get");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_destroy (GtkObject *object)
|
|
{
|
|
RollbackCappletDialog *dialog;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (IS_ROLLBACK_CAPPLET_DIALOG (object));
|
|
|
|
dialog = ROLLBACK_CAPPLET_DIALOG (object);
|
|
|
|
if (dialog->p != (gpointer) 0xdeadbeef) {
|
|
bonobo_object_release_unref (dialog->p->property_control, NULL);
|
|
bonobo_object_release_unref (dialog->p->control_pb, NULL);
|
|
gtk_object_destroy (GTK_OBJECT (dialog->p->data));
|
|
}
|
|
|
|
if (dialog->p->capplet_name != NULL) {
|
|
g_free (dialog->p->capplet_name);
|
|
dialog->p->capplet_name = NULL;
|
|
}
|
|
|
|
if (dialog->p->capplet_moniker_name != NULL) {
|
|
g_free (dialog->p->capplet_moniker_name);
|
|
dialog->p->capplet_moniker_name = NULL;
|
|
}
|
|
|
|
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
|
}
|
|
|
|
static void
|
|
rollback_capplet_dialog_finalize (GtkObject *object)
|
|
{
|
|
RollbackCappletDialog *dialog;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (IS_ROLLBACK_CAPPLET_DIALOG (object));
|
|
|
|
dialog = ROLLBACK_CAPPLET_DIALOG (object);
|
|
|
|
if (dialog->p != (gpointer) 0xdeadbeef)
|
|
g_free (dialog->p);
|
|
|
|
GTK_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
GtkObject *
|
|
rollback_capplet_dialog_new (gchar *capplet_name)
|
|
{
|
|
GtkObject *object;
|
|
|
|
object = gtk_object_new (rollback_capplet_dialog_get_type (),
|
|
"capplet-name", capplet_name,
|
|
NULL);
|
|
|
|
if (ROLLBACK_CAPPLET_DIALOG (object)->p == (gpointer) 0xdeadbeef) {
|
|
gtk_object_destroy (object);
|
|
return NULL;
|
|
}
|
|
|
|
if (do_setup (ROLLBACK_CAPPLET_DIALOG (object))) {
|
|
return object;
|
|
} else {
|
|
gtk_object_destroy (object);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static gchar *
|
|
get_moniker (gchar *capplet_name, struct tm *date)
|
|
{
|
|
if (date == NULL)
|
|
return g_strconcat ("archive:user-archive#archiverdb:", capplet_name, NULL);
|
|
else
|
|
return g_strdup_printf
|
|
("archive:user-archive#archiverdb:[|%04d%02d%02d%02d%02d%02d]%s",
|
|
date->tm_year + 1900, date->tm_mon + 1, date->tm_mday,
|
|
date->tm_hour, date->tm_min, date->tm_sec, capplet_name);
|
|
}
|
|
|
|
static void
|
|
get_modified_date (guint rollback_level, struct tm *date)
|
|
{
|
|
time_t t;
|
|
|
|
t = time (NULL);
|
|
gmtime_r (&t, date);
|
|
mod_date_by_str (date, date_mod_values[rollback_level], date_mod_units[rollback_level]);
|
|
}
|
|
|
|
/* do_setup
|
|
*
|
|
* Sets up the dialog's controls
|
|
*
|
|
* Returns TRUE on success and FALSE on failure
|
|
*/
|
|
|
|
static gboolean
|
|
do_setup (RollbackCappletDialog *dialog)
|
|
{
|
|
CORBA_Environment ev;
|
|
Bonobo_Control control;
|
|
|
|
BonoboControlFrame *cf;
|
|
|
|
GtkWidget *control_wid;
|
|
GtkWidget *err_dialog;
|
|
|
|
gchar *tmp, *tmp1;
|
|
gchar *oaf_iid;
|
|
gchar *moniker;
|
|
|
|
guint i;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
tmp = g_strdup (dialog->p->capplet_moniker_name);
|
|
while ((tmp1 = strchr (tmp, '-'))) *tmp1 = '_';
|
|
|
|
oaf_iid = g_strconcat ("OAFIID:Bonobo_Control_Capplet_", tmp, NULL);
|
|
dialog->p->property_control = bonobo_get_object (oaf_iid, "IDL:Bonobo/PropertyControl:1.0", &ev);
|
|
g_free (oaf_iid);
|
|
g_free (tmp);
|
|
|
|
if (BONOBO_EX (&ev) || dialog->p->property_control == CORBA_OBJECT_NIL) {
|
|
err_dialog = gnome_error_dialog ("Could not load the capplet.");
|
|
gnome_dialog_run_and_close (GNOME_DIALOG (err_dialog));
|
|
return FALSE;
|
|
}
|
|
|
|
control = Bonobo_PropertyControl_getControl (dialog->p->property_control, 0, &ev);
|
|
|
|
if (BONOBO_EX (&ev) || control == CORBA_OBJECT_NIL) {
|
|
bonobo_object_release_unref (dialog->p->property_control, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
control_wid = bonobo_widget_new_control_from_objref (control, CORBA_OBJECT_NIL);
|
|
|
|
if (control_wid == NULL) {
|
|
bonobo_object_release_unref (dialog->p->property_control, NULL);
|
|
bonobo_object_release_unref (control, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < NUM_ROLLBACK_LEVELS - 1; i++)
|
|
get_modified_date (i, &(dialog->p->mod_dates[i]));
|
|
|
|
moniker = get_moniker (dialog->p->capplet_moniker_name, NULL);
|
|
|
|
cf = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_wid));
|
|
dialog->p->control_pb = bonobo_control_frame_get_control_property_bag (cf, &ev);
|
|
bonobo_property_bag_client_set_value_string (dialog->p->control_pb, "moniker", moniker, &ev);
|
|
g_free (moniker);
|
|
|
|
if (BONOBO_EX (&ev)) {
|
|
err_dialog = gnome_error_dialog ("Could not load your configuration settings.");
|
|
gnome_dialog_run_and_close (GNOME_DIALOG (err_dialog));
|
|
bonobo_object_release_unref (dialog->p->property_control, NULL);
|
|
bonobo_object_release_unref (dialog->p->control_pb, NULL);
|
|
gtk_object_destroy (GTK_OBJECT (control_wid));
|
|
return FALSE;
|
|
}
|
|
|
|
/* gtk_widget_set_sensitive (control_wid, FALSE); */
|
|
gtk_container_add (GTK_CONTAINER (dialog->p->control_socket), control_wid);
|
|
|
|
gtk_widget_show_all (dialog->p->contents);
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
apply_settings (RollbackCappletDialog *dialog)
|
|
{
|
|
ConfigArchiver_Archive archive;
|
|
ConfigArchiver_Location location;
|
|
CORBA_Environment ev;
|
|
xmlDocPtr doc;
|
|
|
|
if (dialog->p->rollback_level == NUM_ROLLBACK_LEVELS - 1)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
archive = bonobo_get_object ("archive:user-archive", "IDL:ConfigArchiver/Archive:1.0", &ev);
|
|
|
|
if (BONOBO_EX (&ev) || archive == CORBA_OBJECT_NIL) {
|
|
g_critical ("Could not retrieve archive (%s)", ev._repo_id);
|
|
CORBA_exception_free (&ev);
|
|
return;
|
|
}
|
|
|
|
location = ConfigArchiver_Archive__get_currentLocation (archive, &ev);
|
|
|
|
if (BONOBO_EX (&ev) || location == CORBA_OBJECT_NIL) {
|
|
g_critical ("Could not retrieve current location (%s)", ev._repo_id);
|
|
bonobo_object_release_unref (archive, NULL);
|
|
CORBA_exception_free (&ev);
|
|
return;
|
|
}
|
|
|
|
doc = location_client_load_rollback_data
|
|
(location, &(dialog->p->mod_dates[dialog->p->rollback_level]), 0, dialog->p->capplet_moniker_name, TRUE, &ev);
|
|
|
|
if (BONOBO_EX (&ev) || doc == NULL) {
|
|
gchar *filename;
|
|
|
|
filename = g_strconcat (GNOMECC_DEFAULTS_DIR "/", dialog->p->capplet_moniker_name, ".xml", NULL);
|
|
doc = xmlParseFile (filename);
|
|
g_free (filename);
|
|
|
|
if (doc == NULL) {
|
|
g_critical ("Could not load rollback data (%s)", ev._repo_id);
|
|
bonobo_object_release_unref (location, NULL);
|
|
bonobo_object_release_unref (archive, NULL);
|
|
CORBA_exception_free (&ev);
|
|
return;
|
|
}
|
|
|
|
CORBA_exception_init (&ev);
|
|
}
|
|
|
|
location_client_store_xml
|
|
(location, dialog->p->capplet_moniker_name, doc, ConfigArchiver_STORE_MASK_PREVIOUS, &ev);
|
|
|
|
if (BONOBO_EX (&ev) || doc == NULL)
|
|
g_critical ("Could not store rollback data (%s)", ev._repo_id);
|
|
|
|
xmlFreeDoc (doc);
|
|
bonobo_object_release_unref (archive, NULL);
|
|
bonobo_object_release_unref (location, NULL);
|
|
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static gboolean
|
|
is_leap_year (guint year)
|
|
{
|
|
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/* mod_date_by_str
|
|
*
|
|
* Modify the given date structure using the given time differential string
|
|
* encoding
|
|
*/
|
|
|
|
static void
|
|
mod_date_by_str (struct tm *date, gint value, gchar unit)
|
|
{
|
|
static const guint month_days[] = {
|
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
|
};
|
|
|
|
switch (unit) {
|
|
case 'm':
|
|
date->tm_min += value;
|
|
break;
|
|
case 'h':
|
|
date->tm_hour += value;
|
|
break;
|
|
case 'd':
|
|
date->tm_mday += value;
|
|
break;
|
|
case 'M':
|
|
date->tm_mon += value;
|
|
break;
|
|
case 'y':
|
|
date->tm_year += value;
|
|
break;
|
|
}
|
|
|
|
if (date->tm_min < 0) {
|
|
date->tm_min = 59;
|
|
date->tm_hour--;
|
|
}
|
|
|
|
if (date->tm_hour < 0) {
|
|
date->tm_hour = 23;
|
|
date->tm_mday--;
|
|
}
|
|
|
|
if (date->tm_mday < 1) {
|
|
if (date->tm_mon == 2 && is_leap_year (date->tm_year))
|
|
date->tm_mday = 29;
|
|
else
|
|
date->tm_mday = month_days[(date->tm_mon + 11) % 12];
|
|
|
|
date->tm_mon--;
|
|
}
|
|
|
|
if (date->tm_mon < 0) {
|
|
date->tm_mon = 11;
|
|
date->tm_year--;
|
|
}
|
|
}
|
|
|
|
static void
|
|
rollback_changed_cb (RollbackCappletDialog *dialog,
|
|
GtkAdjustment *adj)
|
|
{
|
|
gchar *moniker;
|
|
|
|
CORBA_Environment ev;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
dialog->p->rollback_level = adj->value;
|
|
gtk_label_set_text (GTK_LABEL (dialog->p->label), labels[dialog->p->rollback_level]);
|
|
|
|
if (dialog->p->rollback_level == NUM_ROLLBACK_LEVELS - 1)
|
|
moniker = get_moniker (dialog->p->capplet_moniker_name, NULL);
|
|
else
|
|
moniker = get_moniker (dialog->p->capplet_moniker_name, &(dialog->p->mod_dates[dialog->p->rollback_level]));
|
|
|
|
bonobo_property_bag_client_set_value_string (dialog->p->control_pb, "moniker", moniker, &ev);
|
|
g_free (moniker);
|
|
|
|
if (BONOBO_EX (&ev)) {
|
|
g_critical ("Could not load settings for rollback level %.0f (%s)", adj->value, ev._repo_id);
|
|
|
|
if (adj->value != dialog->p->rollback_level)
|
|
gtk_adjustment_set_value (adj, dialog->p->rollback_level);
|
|
} else {
|
|
dialog->p->rollback_level = adj->value;
|
|
}
|
|
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
apply_cb (GtkButton *button, RollbackCappletDialog *dialog)
|
|
{
|
|
apply_settings (dialog);
|
|
}
|
|
|
|
static void
|
|
close_cb (GtkButton *button, RollbackCappletDialog *dialog)
|
|
{
|
|
gnome_dialog_close (GNOME_DIALOG (dialog));
|
|
}
|