/* * Copyright (C) 2004-2006 Jimmy Do * * 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 */ #ifdef HAVE_CONFIG_H #include #endif #include "presets-manager.h" /* for _() macro */ #include #include #include "add-preset-dialog.h" #include "gloo/gloo-presets.h" #include "layout-utils.h" typedef struct { GtkWidget *add_preset_dialog; GtkTreeModel *presets_list; GtkWidget *presets_tree_view; GtkWidget *add_button; GtkWidget *edit_button; GtkWidget *delete_button; ViewEmptyCallback view_empty_cb; ViewNotEmptyCallback view_not_empty_cb; SelectionEmptyCallback selection_empty_cb; SelectionNotEmptyCallback selection_not_empty_cb; RowSelectedCallback row_selected_cb; gpointer row_selected_cb_data; PresetsManagerAddedCallback preset_added_cb; gpointer preset_added_cb_data; PresetsManagerEditedCallback preset_edited_cb; gpointer preset_edited_cb_data; PresetsManagerDeletedCallback preset_deleted_cb; gpointer preset_deleted_cb_data; } PresetsManagerPrivate; static gboolean preset_name_exists (GtkTreeModel *tree_model, const gchar *input_name) { gboolean exists; GtkTreeIter iter; gboolean valid; exists = FALSE; valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree_model), &iter); while (valid && !exists) { gchar *preset_name; gtk_tree_model_get (GTK_TREE_MODEL (tree_model), &iter, GLOO_PRESETS_NAME_COL, &preset_name, -1); g_assert (input_name); g_assert (preset_name); if (g_ascii_strncasecmp (input_name, preset_name, MAX_PRESET_NAME_LENGTH) == 0) { exists = TRUE; } g_free (preset_name); preset_name = NULL; valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (tree_model), &iter); } return exists; } static gboolean name_is_valid_func (const gchar *preset_name, const gchar *ignore_name, gpointer user_data) { GtkTreeModel *preset_list; preset_list = (GtkTreeModel *)user_data; g_assert (preset_list); if (ignore_name && (g_strncasecmp (ignore_name, preset_name, MAX_PRESET_NAME_LENGTH) == 0)) { return TRUE; } else { return (strlen (preset_name) > 0) && !preset_name_exists (preset_list, preset_name); } } static PresetsManagerPrivate * get_private_data (GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; priv_data = g_object_get_data (G_OBJECT (presets_manager), "private-data"); g_assert (priv_data); return priv_data; } static void on_add_clicked (GtkWidget *button, GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; priv_data = get_private_data (presets_manager); add_preset_dialog_open (priv_data->add_preset_dialog, _("Add Preset"), _("Untitled Preset"), 0, NULL); } static void on_edit_clicked (GtkWidget *button, GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; GtkTreeRowReference *selected_row_ref; gchar *selected_name; guint selected_duration; priv_data = get_private_data (presets_manager); selected_row_ref = presets_manager_get_selected_preset (presets_manager); g_assert (selected_row_ref); gloo_presets_get_name_and_duration (GLOO_PRESETS (priv_data->presets_list), selected_row_ref, &selected_name, &selected_duration); add_preset_dialog_open (priv_data->add_preset_dialog, _("Edit Preset"), selected_name, selected_duration, selected_row_ref); g_assert (selected_name); g_free (selected_name); selected_name = NULL; } static void on_delete_clicked (GtkWidget *button, gpointer user_data) { GtkWidget *presets_manager; PresetsManagerPrivate *priv_data; GtkTreeRowReference *row_ref_to_delete; presets_manager = (GtkWidget *)user_data; priv_data = get_private_data (presets_manager); if ((row_ref_to_delete = presets_manager_delete_selection (presets_manager, NULL)) != NULL) { g_assert (row_ref_to_delete); if (priv_data->preset_deleted_cb) { priv_data->preset_deleted_cb (presets_manager, row_ref_to_delete, priv_data->preset_deleted_cb_data); } } } static void on_preset_added (GtkWidget *add_preset_dialog, gchar *preset_name, guint preset_duration, gpointer user_data) { GtkWidget *presets_manager; PresetsManagerPrivate *priv_data; presets_manager = (GtkWidget *)user_data; priv_data = get_private_data (presets_manager); if (priv_data->preset_added_cb) { priv_data->preset_added_cb (presets_manager, preset_name, preset_duration, priv_data->preset_added_cb_data); } } static void on_preset_edited (GtkWidget *add_preset_dialog, GtkTreeRowReference *row_ref, gchar *preset_name, guint preset_duration, gpointer user_data) { GtkWidget *presets_manager; PresetsManagerPrivate *priv_data; presets_manager = (GtkWidget *)user_data; priv_data = get_private_data (presets_manager); if (priv_data->preset_edited_cb) { priv_data->preset_edited_cb (presets_manager, row_ref, preset_name, preset_duration, priv_data->preset_edited_cb_data); } } static void on_row_deleted (GtkTreeModel *tree_model, GtkTreePath *tree_path, GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; ViewEmptyCallback empty_cb; priv_data = get_private_data (presets_manager); empty_cb = priv_data->view_empty_cb; if (gtk_tree_model_iter_n_children (tree_model, NULL) == 0) { if (empty_cb) { g_assert (empty_cb); empty_cb (presets_manager); } } } static void on_row_inserted (GtkTreeModel *tree_model, GtkTreePath *tree_path1, GtkTreePath *tree_path2, GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; ViewNotEmptyCallback not_empty_cb; priv_data = get_private_data (presets_manager); not_empty_cb = priv_data->view_not_empty_cb; if (gtk_tree_model_iter_n_children (tree_model, NULL) == 1) { if (not_empty_cb) { g_assert (not_empty_cb); not_empty_cb (presets_manager); } } } static void on_selection_changed (GtkTreeSelection *tree_selection, GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; GtkWidget *delete_button; GtkWidget *edit_button; SelectionEmptyCallback empty_cb; SelectionNotEmptyCallback not_empty_cb; priv_data = get_private_data (presets_manager); delete_button = priv_data->delete_button; edit_button = priv_data->edit_button; g_assert (delete_button); g_assert (edit_button); empty_cb = priv_data->selection_empty_cb; not_empty_cb = priv_data->selection_not_empty_cb; if (gtk_tree_selection_count_selected_rows (tree_selection) == 0) { g_object_set (G_OBJECT (delete_button), "sensitive", FALSE, NULL); g_object_set (G_OBJECT (edit_button), "sensitive", FALSE, NULL); if (empty_cb) { empty_cb (presets_manager); } } else { g_object_set (G_OBJECT (delete_button), "sensitive", TRUE, NULL); g_object_set (G_OBJECT (edit_button), "sensitive", TRUE, NULL); if (not_empty_cb) { not_empty_cb (presets_manager); } { RowSelectedCallback selected_cb; gpointer user_data; selected_cb = priv_data->row_selected_cb; user_data = priv_data->row_selected_cb_data; if (selected_cb) { selected_cb (presets_manager, user_data); } } } } void set_display_name_cell_data (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { gchar *name; guint duration; gchar *display_name; gtk_tree_model_get (tree_model, iter, GLOO_PRESETS_NAME_COL, &name, GLOO_PRESETS_DURATION_COL, &duration, -1); display_name = construct_display_name (name, duration); g_free (name); name = NULL; g_object_set (G_OBJECT (cell), "text", display_name, NULL); g_free (display_name); display_name = NULL; } GtkWidget * presets_manager_new (GtkTreeModel *tree_model) { PresetsManagerPrivate *priv_data; GtkWidget *main_vbox; GtkWidget *button_hbox; GtkWidget *preset_tree_view; GtkTreeViewColumn *tree_col; GtkWidget *button; GtkCellRenderer *cell_renderer; GtkWidget *scrolled_window; GtkWidget *add_preset_dialog; g_assert (tree_model != NULL); main_vbox = gtk_vbox_new (FALSE, 6); add_preset_dialog = add_preset_dialog_new (name_is_valid_func, tree_model); add_preset_dialog_set_handlers (add_preset_dialog, on_preset_added, main_vbox, on_preset_edited, main_vbox); priv_data = g_new0 (PresetsManagerPrivate, 1); priv_data->add_preset_dialog = add_preset_dialog; priv_data->presets_list = tree_model; g_object_set_data (G_OBJECT (main_vbox), "private-data", priv_data); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (main_vbox), scrolled_window, TRUE, TRUE, 0); gtk_widget_show (scrolled_window); preset_tree_view = gtk_tree_view_new (); g_object_set (G_OBJECT (preset_tree_view), "headers-visible", FALSE, NULL); gtk_container_add (GTK_CONTAINER (scrolled_window), preset_tree_view); gtk_widget_show (preset_tree_view); priv_data->presets_tree_view = preset_tree_view; tree_col = gtk_tree_view_column_new (); cell_renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (tree_col, cell_renderer, TRUE); gtk_tree_view_column_set_cell_data_func (tree_col, cell_renderer, (GtkTreeCellDataFunc)set_display_name_cell_data, NULL, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (preset_tree_view), tree_col); button_hbox = gtk_hbox_new (TRUE, 6); gtk_box_pack_start (GTK_BOX (main_vbox), button_hbox, FALSE, FALSE, 0); gtk_widget_show (button_hbox); button = gtk_button_new_with_mnemonic (_("_Add...")); gtk_box_pack_end (GTK_BOX (button_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); priv_data->add_button = button; g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_add_clicked), main_vbox); button = gtk_button_new_with_mnemonic (_("_Edit...")); gtk_box_pack_end (GTK_BOX (button_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); g_object_set (G_OBJECT (button), "sensitive", FALSE, NULL); priv_data->edit_button = button; g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_edit_clicked), main_vbox); button = gtk_button_new_with_mnemonic (_("_Delete")); gtk_box_pack_end (GTK_BOX (button_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); g_object_set (G_OBJECT (button), "sensitive", FALSE, NULL); priv_data->delete_button = button; g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_delete_clicked), main_vbox); g_signal_connect (G_OBJECT (tree_model), "row-deleted", G_CALLBACK (on_row_deleted), main_vbox); g_signal_connect (G_OBJECT (tree_model), "row-inserted", G_CALLBACK (on_row_inserted), main_vbox); { GtkTreeSelection *tree_selection; tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (preset_tree_view)); gtk_tree_selection_set_mode (GTK_TREE_SELECTION (tree_selection), GTK_SELECTION_BROWSE); g_signal_connect (G_OBJECT (tree_selection), "changed", G_CALLBACK (on_selection_changed), main_vbox); } gtk_tree_view_set_model (GTK_TREE_VIEW (preset_tree_view), tree_model); return main_vbox; } void presets_manager_connect_row_selected (GtkWidget *presets_manager, RowSelectedCallback row_activated_cb, gpointer user_data) { PresetsManagerPrivate *priv_data; priv_data = get_private_data (presets_manager); priv_data->row_selected_cb = row_activated_cb; priv_data->row_selected_cb_data = user_data; } GtkTreeRowReference * presets_manager_get_selected_preset (GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; GtkWidget *presets_tree_view; GtkTreeRowReference *row_ref; priv_data = get_private_data (presets_manager); g_assert (presets_manager); presets_tree_view = priv_data->presets_tree_view; g_assert (presets_tree_view); { GtkTreeSelection *selection; gboolean node_selected; GtkTreeIter iter; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (presets_tree_view)); node_selected = gtk_tree_selection_get_selected (selection, NULL, &iter); row_ref = NULL; if (node_selected) { GtkTreeModel *tree_model; GtkTreePath *path; tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (presets_tree_view)); g_assert (tree_model); path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model), &iter); g_assert (path); row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (tree_model), path); g_assert (row_ref); g_free (path); path = NULL; } } return row_ref; } GtkTreeRowReference * presets_manager_delete_selection (GtkWidget *presets_manager, GtkWidget *parent_window) { PresetsManagerPrivate *priv_data; GtkWidget *presets_tree_view; GtkTreeSelection *selection; GtkTreeIter selected_iter; gboolean has_selection; GtkTreeRowReference *selected_ref; GtkTreeRowReference *row_ref_to_delete; priv_data = get_private_data (presets_manager); row_ref_to_delete = NULL; g_assert (presets_manager); presets_tree_view = priv_data->presets_tree_view; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (presets_tree_view)); has_selection = gtk_tree_selection_get_selected (selection, NULL, &selected_iter); { GtkTreeModel *tree_model; GtkTreePath *path; tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (presets_tree_view)); path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model), &selected_iter); selected_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (tree_model), path); g_free (path); path = NULL; } { GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, _("Delete the selected timer preset?")); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); dialog = NULL; switch (response) { case GTK_RESPONSE_OK: row_ref_to_delete = selected_ref; break; case GTK_RESPONSE_CANCEL: break; default: g_assert_not_reached (); } } return row_ref_to_delete; } void presets_manager_set_view_change_handlers (GtkWidget *presets_manager, ViewEmptyCallback empty_cb, ViewNotEmptyCallback not_empty_cb) { PresetsManagerPrivate *priv_data; priv_data = get_private_data (presets_manager); priv_data->view_empty_cb = empty_cb; priv_data->view_not_empty_cb = not_empty_cb; } void presets_manager_set_selection_change_handlers (GtkWidget *presets_manager, SelectionEmptyCallback empty_cb, SelectionNotEmptyCallback not_empty_cb) { PresetsManagerPrivate *priv_data; priv_data = get_private_data (presets_manager); priv_data->selection_empty_cb = empty_cb; priv_data->selection_not_empty_cb = not_empty_cb; } void presets_manager_select_first_row (GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; GtkTreeModel *tree_model; GtkTreeView *preset_tree_view; priv_data = get_private_data (presets_manager); preset_tree_view = GTK_TREE_VIEW (priv_data->presets_tree_view); tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (preset_tree_view)); /* Select first row, if possible */ { GtkTreeIter first_row; gboolean iter_set; iter_set = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree_model), &first_row); if (iter_set) { GtkTreePath *tree_path; tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model), &first_row); g_assert (tree_path); gtk_tree_view_set_cursor (GTK_TREE_VIEW (preset_tree_view), tree_path, NULL, FALSE); } } } void presets_manager_select_row (GtkWidget *presets_manager, GtkTreeRowReference *row_ref) { PresetsManagerPrivate *priv_data; GtkTreeView *preset_tree_view; priv_data = get_private_data (presets_manager); preset_tree_view = GTK_TREE_VIEW (priv_data->presets_tree_view); { GtkTreePath *tree_path; tree_path = gtk_tree_row_reference_get_path (row_ref); g_assert (tree_path); gtk_tree_view_set_cursor (GTK_TREE_VIEW (preset_tree_view), tree_path, NULL, FALSE); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (preset_tree_view), tree_path, NULL, FALSE, 0.0, 0.0); g_free(tree_path); tree_path = NULL; } } void presets_manager_set_preset_handlers (GtkWidget *presets_manager, PresetsManagerAddedCallback added_cb, gpointer user_data1, PresetsManagerEditedCallback edited_cb, gpointer user_data2, PresetsManagerDeletedCallback deleted_cb, gpointer user_data3) { PresetsManagerPrivate *priv_data; priv_data = get_private_data (presets_manager); priv_data->preset_added_cb = added_cb; priv_data->preset_added_cb_data = user_data1; priv_data->preset_edited_cb = edited_cb; priv_data->preset_edited_cb_data = user_data2; priv_data->preset_deleted_cb = deleted_cb; priv_data->preset_deleted_cb_data = user_data3; } GtkWidget * presets_manager_get_tree_view (GtkWidget *presets_manager) { PresetsManagerPrivate *priv_data; priv_data = g_object_get_data (G_OBJECT (presets_manager), "private-data"); return priv_data->presets_tree_view; }