552 lines
14 KiB
C
552 lines
14 KiB
C
/*
|
|
* Copyright (C) 2012 - Juan Ferrer Toribio
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "vn-handler.h"
|
|
|
|
G_DEFINE_TYPE (VnHandler, vn_handler, GTK_TYPE_HBUTTON_BOX);
|
|
|
|
/**
|
|
* vn_handler_new:
|
|
*
|
|
* Creates a new handler
|
|
*
|
|
* Return value: #GtkWidget created.
|
|
**/
|
|
GtkWidget * vn_handler_new ()
|
|
{
|
|
return g_object_new (VN_TYPE_HANDLER, NULL);
|
|
}
|
|
|
|
/**
|
|
* vn_handler_new_with_form:
|
|
* @form: #DbIterator where the handler will be created
|
|
*
|
|
* Creates a new handler into a iterator gived
|
|
*
|
|
* Return value: #GtkWidget created.
|
|
**/
|
|
GtkWidget * vn_handler_new_with_iterator (DbIterator * iterator)
|
|
{
|
|
return g_object_new (VN_TYPE_HANDLER, "iterator", iterator, NULL);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
|
|
|
|
static void vn_handler_on_add_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
db_iterator_insert (obj->iterator);
|
|
}
|
|
|
|
static void vn_handler_on_remove_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
GtkWidget * toplevel;
|
|
GtkWidget * dialog;
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (obj));
|
|
|
|
dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel)
|
|
,GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
|
|
,GTK_MESSAGE_QUESTION
|
|
,GTK_BUTTONS_OK_CANCEL
|
|
,_("Are you sure you want to delete the selected record?")
|
|
);
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
|
|
db_iterator_delete (obj->iterator);
|
|
|
|
gtk_widget_destroy (dialog);
|
|
}
|
|
|
|
static void vn_handler_on_save_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
db_iterator_perform_operations (obj->iterator);
|
|
}
|
|
|
|
static void vn_handler_on_undo_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
GtkWidget * toplevel;
|
|
GtkWidget * dialog;
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (obj));
|
|
|
|
dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel)
|
|
,GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
|
|
,GTK_MESSAGE_QUESTION
|
|
,GTK_BUTTONS_OK_CANCEL
|
|
,_("Are you sure that you want to undo all changes?")
|
|
);
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
|
|
db_iterator_reverse_operations (obj->iterator);
|
|
|
|
gtk_widget_destroy (dialog);
|
|
}
|
|
|
|
static void vn_handler_on_refresh_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
db_iterator_refresh (obj->iterator);
|
|
}
|
|
|
|
static void vn_handler_on_move_activated (GtkAction * action, VnHandler * obj)
|
|
{
|
|
DbIteratorMove move;
|
|
|
|
if (action == obj->move_previous)
|
|
move = DB_ITERATOR_MOVE_PREVIOUS;
|
|
else if (action == obj->move_next)
|
|
move = DB_ITERATOR_MOVE_NEXT;
|
|
else if (action == obj->move_last)
|
|
move = DB_ITERATOR_MOVE_LAST;
|
|
else
|
|
move = DB_ITERATOR_MOVE_FIRST;
|
|
|
|
db_iterator_move_to (obj->iterator, move);
|
|
}
|
|
|
|
static void vn_handler_refresh_save_undo_status (VnHandler * obj)
|
|
{
|
|
gboolean sensitive = obj->iterator
|
|
&& db_iterator_has_pending_operations (obj->iterator);
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_SAVE)
|
|
gtk_action_set_sensitive (obj->save, sensitive);
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_UNDO)
|
|
gtk_action_set_sensitive (obj->undo, sensitive);
|
|
}
|
|
|
|
static void vn_handler_refresh_scroll_status (VnHandler * obj)
|
|
{
|
|
if (obj->show_flags & VN_HANDLER_SHOW_SCROLL)
|
|
{
|
|
gboolean sensitive;
|
|
gint row = db_iterator_get_row (obj->iterator);
|
|
|
|
sensitive = row > 0;
|
|
gtk_action_set_sensitive (obj->move_first, sensitive);
|
|
gtk_action_set_sensitive (obj->move_previous, sensitive);
|
|
|
|
sensitive = row != -1 && row < db_iterator_get_nrows (obj->iterator) - 1;
|
|
gtk_action_set_sensitive (obj->move_next, sensitive);
|
|
gtk_action_set_sensitive (obj->move_last, sensitive);
|
|
}
|
|
}
|
|
|
|
static void vn_handler_on_data_changed (DbIterator * iterator, VnHandler * obj)
|
|
{
|
|
if (obj->show_flags & VN_HANDLER_SHOW_ADD)
|
|
{
|
|
gboolean sensitive =
|
|
db_iterator_get_update_flags (iterator) & DB_MODEL_INSERT
|
|
&& (db_iterator_get_nrows (iterator) < 1 || !obj->simple_record);
|
|
|
|
gtk_action_set_sensitive (obj->add, sensitive);
|
|
}
|
|
|
|
vn_handler_refresh_save_undo_status (obj);
|
|
vn_handler_refresh_scroll_status (obj);
|
|
}
|
|
|
|
static void vn_handler_on_row_num_changed (DbIterator * iterator, VnHandler * obj)
|
|
{
|
|
if (obj->show_flags & VN_HANDLER_SHOW_REMOVE)
|
|
{
|
|
gboolean sensitive =
|
|
db_iterator_get_update_flags (iterator) & DB_MODEL_DELETE
|
|
&& db_iterator_get_row (iterator) != -1;
|
|
|
|
gtk_action_set_sensitive (obj->remove, sensitive);
|
|
}
|
|
|
|
vn_handler_refresh_scroll_status (obj);
|
|
}
|
|
|
|
static void vn_handler_on_operations_done (DbIterator * iterator, VnHandler * obj)
|
|
{
|
|
vn_handler_refresh_save_undo_status (obj);
|
|
}
|
|
|
|
static void vn_handler_on_status_changed (DbIterator * iterator, gboolean ready, VnHandler * obj)
|
|
{
|
|
gtk_action_group_set_sensitive (obj->group, ready);
|
|
vn_handler_on_row_num_changed (iterator, obj);
|
|
vn_handler_on_data_changed (iterator, obj);
|
|
}
|
|
|
|
static void vn_handler_refresh_status (VnHandler * obj)
|
|
{
|
|
if (!obj->iterator)
|
|
gtk_action_group_set_sensitive (obj->group, FALSE);
|
|
else
|
|
vn_handler_on_status_changed (obj->iterator,
|
|
db_iterator_is_ready (obj->iterator), obj);
|
|
}
|
|
|
|
static VnHandlerShowFlags entries_flags[] =
|
|
{
|
|
VN_HANDLER_SHOW_UNDO
|
|
,VN_HANDLER_SHOW_SAVE
|
|
,VN_HANDLER_SHOW_REFRESH
|
|
,VN_HANDLER_SHOW_REMOVE
|
|
,VN_HANDLER_SHOW_ADD
|
|
,VN_HANDLER_SHOW_SCROLL
|
|
,VN_HANDLER_SHOW_SCROLL
|
|
,VN_HANDLER_SHOW_SCROLL
|
|
,VN_HANDLER_SHOW_SCROLL
|
|
};
|
|
|
|
static GtkActionEntry entries[] =
|
|
{
|
|
{
|
|
"undo"
|
|
,"edit-undo"
|
|
,NULL
|
|
,NULL
|
|
,N_("Undo changes")
|
|
,G_CALLBACK (vn_handler_on_undo_activated)
|
|
},{
|
|
"save"
|
|
,"document-save"
|
|
,NULL
|
|
,NULL
|
|
,N_("Save changes")
|
|
,G_CALLBACK (vn_handler_on_save_activated)
|
|
},{
|
|
"refresh"
|
|
,"view-refresh"
|
|
,NULL
|
|
,NULL
|
|
,N_("Refresh data")
|
|
,G_CALLBACK (vn_handler_on_refresh_activated)
|
|
},{
|
|
"remove"
|
|
,"list-remove"
|
|
,NULL
|
|
,NULL
|
|
,N_("Remove record")
|
|
,G_CALLBACK (vn_handler_on_remove_activated)
|
|
},{
|
|
"add"
|
|
,"list-add"
|
|
,NULL
|
|
,NULL
|
|
,N_("Add record")
|
|
,G_CALLBACK (vn_handler_on_add_activated)
|
|
},{
|
|
"move-first"
|
|
,"go-first"
|
|
,NULL
|
|
,NULL
|
|
,N_("Move to the first row")
|
|
,G_CALLBACK (vn_handler_on_move_activated)
|
|
},{
|
|
"move-previous"
|
|
,"go-previous"
|
|
,NULL
|
|
,NULL
|
|
,N_("Move to the previous row")
|
|
,G_CALLBACK (vn_handler_on_move_activated)
|
|
},{
|
|
"move-next"
|
|
,"go-next"
|
|
,NULL
|
|
,NULL
|
|
,N_("Move to the next row")
|
|
,G_CALLBACK (vn_handler_on_move_activated)
|
|
},{
|
|
"move-last"
|
|
,"go-last"
|
|
,NULL
|
|
,NULL
|
|
,N_("Move to the last row")
|
|
,G_CALLBACK (vn_handler_on_move_activated)
|
|
}
|
|
};
|
|
|
|
static guint n_entries = G_N_ELEMENTS (entries);
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
|
|
|
|
/**
|
|
* vn_handler_get_iterator:
|
|
* @obj: a #VnHandler
|
|
*
|
|
* Gets the iterator handled by #VnHandler
|
|
*
|
|
* Return value: (transfer none) (allow-none): the #DbIterator
|
|
**/
|
|
DbIterator * vn_handler_get_iterator (VnHandler * obj)
|
|
{
|
|
return obj->iterator;
|
|
}
|
|
|
|
/**
|
|
* vn_handler_set_iterator:
|
|
* @obj: a #VnHandler
|
|
* @iterator: the iterator to be handled
|
|
*
|
|
* Sets the iterator handled by #VnHandler
|
|
**/
|
|
void vn_handler_set_iterator (VnHandler * obj, DbIterator * iterator)
|
|
{
|
|
g_return_if_fail (VN_IS_HANDLER (obj));
|
|
g_return_if_fail (DB_IS_ITERATOR (iterator) || !iterator);
|
|
|
|
if (obj->iterator)
|
|
{
|
|
g_object_disconnect (obj->iterator
|
|
,"any-signal", vn_handler_on_status_changed, obj
|
|
,"any-signal", vn_handler_on_data_changed, obj
|
|
,"any-signal", vn_handler_on_row_num_changed, obj
|
|
,"any-signal", vn_handler_on_operations_done, obj
|
|
,NULL
|
|
);
|
|
g_clear_object (&obj->iterator);
|
|
}
|
|
if (iterator)
|
|
{
|
|
obj->iterator = g_object_ref (iterator);
|
|
g_object_connect (iterator
|
|
,"signal::status-changed", vn_handler_on_status_changed, obj
|
|
,"signal::data-changed", vn_handler_on_data_changed, obj
|
|
,"signal::row-num-changed", vn_handler_on_row_num_changed, obj
|
|
,"signal::operations-done", vn_handler_on_operations_done, obj
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
vn_handler_refresh_status (obj);
|
|
}
|
|
|
|
/**
|
|
* vn_handler_set_show_flags:
|
|
* @obj: a #VnHandler
|
|
* @show_flags: the buttons to be shown
|
|
*
|
|
* Sets the buttons that will be shown on the interface.
|
|
**/
|
|
void vn_handler_set_show_flags (VnHandler * obj, VnHandlerShowFlags show_flags)
|
|
{
|
|
gint i;
|
|
gint items;
|
|
GList * j;
|
|
|
|
g_return_if_fail (VN_IS_HANDLER (obj));
|
|
|
|
for (j = gtk_action_group_list_actions (obj->group); j; j = j->next)
|
|
gtk_action_group_remove_action (obj->group, j->data);
|
|
|
|
items = gtk_toolbar_get_n_items (obj->toolbar);
|
|
|
|
for (i = 0; i < items; i++)
|
|
{
|
|
GtkToolItem * tool_item = gtk_toolbar_get_nth_item (obj->toolbar, 0);
|
|
gtk_container_remove (GTK_CONTAINER (obj->toolbar), GTK_WIDGET (tool_item));
|
|
}
|
|
|
|
obj->show_flags = show_flags;
|
|
|
|
for (i = 0; i < n_entries; i++)
|
|
{
|
|
if (obj->show_flags & entries_flags[i])
|
|
{
|
|
gtk_action_group_add_actions (obj->group, &entries[i], 1, obj);
|
|
|
|
GtkAction * action = gtk_action_group_get_action (obj->group, entries[i].name);
|
|
|
|
GtkToolItem * item = GTK_TOOL_ITEM (gtk_action_create_tool_item (action));
|
|
gtk_tool_item_set_homogeneous (item, TRUE);
|
|
gtk_toolbar_insert (obj->toolbar, item, -1);
|
|
}
|
|
}
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_ADD)
|
|
obj->add = gtk_action_group_get_action (obj->group, "add");
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_REMOVE)
|
|
obj->remove = gtk_action_group_get_action (obj->group, "remove");
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_SAVE)
|
|
obj->save = gtk_action_group_get_action (obj->group, "save");
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_UNDO)
|
|
obj->undo = gtk_action_group_get_action (obj->group, "undo");
|
|
|
|
if (obj->show_flags & VN_HANDLER_SHOW_SCROLL)
|
|
{
|
|
obj->move_first = gtk_action_group_get_action (obj->group, "move-first");
|
|
obj->move_previous = gtk_action_group_get_action (obj->group, "move-previous");
|
|
obj->move_next = gtk_action_group_get_action (obj->group, "move-next");
|
|
obj->move_last = gtk_action_group_get_action (obj->group, "move-last");
|
|
}
|
|
|
|
vn_handler_refresh_status (obj);
|
|
}
|
|
|
|
/**
|
|
* vn_handler_set_simple_record:
|
|
* @obj: a #VnHandler
|
|
* @simple: %FALSE if model allows multiple records, %TRUE otherwise
|
|
*
|
|
* Sets if it is used to handle a iterator with a single record.
|
|
**/
|
|
void vn_handler_set_simple_record (VnHandler * obj, gboolean simple)
|
|
{
|
|
g_return_if_fail (VN_IS_HANDLER (obj));
|
|
|
|
obj->simple_record = simple;
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
|
|
|
|
enum
|
|
{
|
|
PROP_FORM = 1
|
|
,PROP_SHOW_FLAGS
|
|
,PROP_SIMPLE_RECORD
|
|
};
|
|
|
|
static void vn_handler_set_property (VnHandler * obj, guint id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
switch (id)
|
|
{
|
|
case PROP_FORM:
|
|
vn_handler_set_iterator (obj, g_value_get_object (value));
|
|
break;
|
|
case PROP_SHOW_FLAGS:
|
|
vn_handler_set_show_flags (obj, g_value_get_flags (value));
|
|
break;
|
|
case PROP_SIMPLE_RECORD:
|
|
vn_handler_set_simple_record (obj, g_value_get_boolean (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
|
|
}
|
|
}
|
|
|
|
static void vn_handler_get_property (VnHandler * obj, guint id,
|
|
GValue * value, GParamSpec * pspec)
|
|
{
|
|
switch (id)
|
|
{
|
|
case PROP_FORM:
|
|
g_value_set_object (value, obj->iterator);
|
|
break;
|
|
case PROP_SHOW_FLAGS:
|
|
g_value_set_flags (value, obj->show_flags);
|
|
break;
|
|
case PROP_SIMPLE_RECORD:
|
|
g_value_set_boolean (value, obj->simple_record);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
|
|
}
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
|
|
|
|
static void vn_handler_init (VnHandler * obj)
|
|
{
|
|
GdkRGBA color = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
obj->add = NULL;
|
|
obj->remove = NULL;
|
|
obj->move_first = NULL;
|
|
obj->move_previous = NULL;
|
|
obj->move_next = NULL;
|
|
obj->move_last = NULL;
|
|
obj->iterator = NULL;
|
|
|
|
gtk_box_set_spacing (GTK_BOX (obj), 6);
|
|
gtk_box_set_homogeneous (GTK_BOX (obj), FALSE);
|
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (obj), GTK_BUTTONBOX_END);
|
|
|
|
obj->group = gtk_action_group_new ("form-handler");
|
|
|
|
obj->toolbar = GTK_TOOLBAR (g_object_new (GTK_TYPE_TOOLBAR
|
|
,"icon-size", GTK_ICON_SIZE_LARGE_TOOLBAR
|
|
,"toolbar-style", GTK_TOOLBAR_BOTH_HORIZ
|
|
,"show-arrow", FALSE
|
|
,NULL
|
|
));
|
|
gtk_widget_override_background_color (GTK_WIDGET (obj->toolbar),
|
|
GTK_STATE_FLAG_NORMAL, &color);
|
|
gtk_box_pack_end (GTK_BOX (obj), GTK_WIDGET (obj->toolbar), FALSE, FALSE, 0);
|
|
}
|
|
|
|
static void vn_handler_finalize (VnHandler * obj)
|
|
{
|
|
vn_handler_set_iterator (obj, NULL);
|
|
G_OBJECT_CLASS (vn_handler_parent_class)->finalize (G_OBJECT (obj));
|
|
}
|
|
|
|
static void vn_handler_class_init (VnHandlerClass * klass)
|
|
{
|
|
GObjectClass * k = G_OBJECT_CLASS (klass);
|
|
k->finalize = (GObjectFinalizeFunc) vn_handler_finalize;
|
|
k->set_property = (GObjectSetPropertyFunc) vn_handler_set_property;
|
|
k->get_property = (GObjectGetPropertyFunc) vn_handler_get_property;
|
|
|
|
g_object_class_install_property (k, PROP_FORM,
|
|
g_param_spec_object ("iterator"
|
|
,"Iterator"
|
|
,"The handled iterator"
|
|
,DB_TYPE_ITERATOR
|
|
,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_SHOW_FLAGS,
|
|
g_param_spec_flags ("show-flags"
|
|
,_("Show flags")
|
|
,_("Sets the buttons that will be shown on the interface")
|
|
,VN_TYPE_HANDLER_SHOW_FLAGS
|
|
,VN_HANDLER_SHOW_UNDO | VN_HANDLER_SHOW_SAVE | VN_HANDLER_SHOW_REMOVE | VN_HANDLER_SHOW_ADD
|
|
,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_SIMPLE_RECORD,
|
|
g_param_spec_boolean ("simple-record"
|
|
,_("Simple record")
|
|
,_("Sets if it is used to handle a iterator with a single record")
|
|
,FALSE
|
|
,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
|
|
));
|
|
}
|
|
|
|
GType vn_handler_show_flags_get_type ()
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (type == 0)
|
|
{
|
|
static const GFlagsValue values[] =
|
|
{
|
|
{VN_HANDLER_SHOW_REFRESH, "VN_HANDLER_SHOW_REFRESH", "refresh"}
|
|
,{VN_HANDLER_SHOW_UNDO, "VN_HANDLER_SHOW_UNDO", "undo"}
|
|
,{VN_HANDLER_SHOW_SAVE, "VN_HANDLER_SHOW_SAVE", "save"}
|
|
,{VN_HANDLER_SHOW_REMOVE, "VN_HANDLER_SHOW_REMOVE", "remove"}
|
|
,{VN_HANDLER_SHOW_ADD, "VN_HANDLER_SHOW_ADD", "add"}
|
|
,{VN_HANDLER_SHOW_SCROLL, "VN_HANDLER_SHOW_SCROLL", "scroll"}
|
|
,{0, NULL, NULL}
|
|
};
|
|
|
|
type = g_flags_register_static
|
|
(g_intern_static_string ("VnHandlerShowFlags"), values);
|
|
}
|
|
|
|
return type;
|
|
}
|