/* * 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 . */ #include "vn-handler.h" G_DEFINE_TYPE (VnHandler, vn_handler, GTK_TYPE_BUTTON_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 current selection?") ); 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_nrows (iterator) > 0; 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); gtk_orientable_set_orientation (GTK_ORIENTABLE (obj), GTK_ORIENTATION_HORIZONTAL); 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; }