/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2002 CodeFactory AB * Copyright (C) 2002 Richard Hult * Copyright (C) 2002 Mikael Hallendal * Copyright (C) 2002 Alvaro del Castillo * * 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. */ #include #include #include #include #include #include "util/mg-marshal.h" #include "mg-group-model.h" #include "mg-group-dialog.h" /* GtkCellRenderer types */ enum { TREE_VIEW_TEXT, TREE_VIEW_ACTIVE }; typedef struct { MrpProject *project; GtkTreeView *tree_view; GtkWidget *remove_button; } DialogData; static GtkWidget * group_dialog_create (MrpProject *project); static void group_dialog_setup_tree_view (GtkWidget *dialog); static void group_dialog_insert_group_cb (GtkWidget *button, GtkWidget *dialog); static void group_dialog_remove_group_cb (GtkWidget *button, GtkWidget *dialog); static void group_dialog_close_editor_cb (GtkWidget *button, GtkWidget *dialog); static void group_dialog_cell_toggled (GtkCellRendererText *cell, gchar *path_str, GtkWindow *dialog); static void group_dialog_cell_edited (GtkCellRendererText *cell, gchar *path_str, gchar *new_text, GtkWindow *dialog); static void group_dialog_add_column (GtkWidget *dialog, int column, char *title, guint type, gint min_width); static void group_dialog_add_columns (GtkWidget *dialog); static void group_dialog_selection_changed_cb (GtkTreeSelection *selection, GtkWidget *dialog); static GList * group_dialog_selection_get_list (GtkWidget *dialog); static GtkWidget * group_dialog_create (MrpProject *project) { DialogData *data; GladeXML *gui; GtkWidget *dialog; GtkWidget *button; data = g_new0 (DialogData, 1); data->project = g_object_ref (project); gui = glade_xml_new ( DATADIR "/mrproject/glade/mg-group-dialog.glade", NULL , NULL); dialog = glade_xml_get_widget (gui, "dialog_group_editor"); data->tree_view = GTK_TREE_VIEW ( glade_xml_get_widget (gui, "group_edit_treeview")); button = glade_xml_get_widget (gui, "add_group"); g_signal_connect (button, "clicked", G_CALLBACK (group_dialog_insert_group_cb), dialog); data->remove_button = glade_xml_get_widget (gui, "remove_group"); g_signal_connect (data->remove_button, "clicked", G_CALLBACK (group_dialog_remove_group_cb), dialog); button = glade_xml_get_widget (gui, "close_editor"); g_signal_connect (button, "clicked", G_CALLBACK (group_dialog_close_editor_cb), dialog); g_object_set_data (G_OBJECT (dialog), "data", data); group_dialog_setup_tree_view (dialog); return dialog; } static void group_dialog_setup_tree_view (GtkWidget *dialog) { DialogData *data; GtkTreeModel *model; GtkTreeModel *sorted_model; GtkTreeSelection *selection; g_return_if_fail (GTK_IS_DIALOG (dialog)); data = g_object_get_data (G_OBJECT (dialog), "data"); model = GTK_TREE_MODEL (mg_group_model_new (data->project)); sorted_model = gtk_tree_model_sort_new_with_model (model); gtk_tree_view_set_model (data->tree_view, sorted_model); selection = gtk_tree_view_get_selection (data->tree_view); gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); g_signal_connect (selection, "changed", G_CALLBACK (group_dialog_selection_changed_cb), dialog); group_dialog_add_columns (dialog); g_object_unref (model); g_object_unref (sorted_model); } static void group_dialog_insert_group_cb (GtkWidget *button, GtkWidget *dialog) { DialogData *data; MrpGroup *group; g_return_if_fail (GTK_IS_DIALOG (dialog)); data = g_object_get_data (G_OBJECT (dialog), "data"); group = mrp_group_new (); mrp_project_add_group (data->project, group); } static void group_dialog_remove_group_cb (GtkWidget *widget, GtkWidget *dialog) { DialogData *data; GList *list, *node; g_return_if_fail (GTK_IS_DIALOG (dialog)); data = g_object_get_data (G_OBJECT (dialog), "data"); list = group_dialog_selection_get_list (dialog); for (node = list; node; node = node->next) { mrp_project_remove_group (data->project, MRP_GROUP (node->data)); } g_list_free (list); } static void group_dialog_close_editor_cb (GtkWidget *button, GtkWidget *dialog) { DialogData *data; g_return_if_fail (GTK_IS_DIALOG (dialog)); /* We have to destroy the model data */ data = g_object_get_data (G_OBJECT (dialog), "data"); g_object_unref (data->project); g_free (data); gtk_widget_destroy (dialog); } static void group_dialog_cell_toggled (GtkCellRendererText *cell, gchar *path_str, GtkWindow *dialog) { DialogData *data; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; GtkTreeModelSort *sorted_model; GtkTreeIter sorted_iter; gint column; gboolean is_default; MrpGroup *group; data = g_object_get_data (G_OBJECT (dialog), "data"); sorted_model = GTK_TREE_MODEL_SORT (gtk_tree_view_get_model (data->tree_view)); model = gtk_tree_model_sort_get_model (sorted_model); path = gtk_tree_path_new_from_string (path_str); column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column")); gtk_tree_model_get_iter (GTK_TREE_MODEL (sorted_model), &sorted_iter, path); gtk_tree_model_sort_convert_iter_to_child_iter (sorted_model, &iter, &sorted_iter); switch (column) { case GROUP_COL_GROUP_DEFAULT: gtk_tree_model_get (model, &iter, column, &is_default, -1); group = MRP_GROUP (mg_list_model_get_object ( MG_LIST_MODEL (model), &iter)); if (!is_default) { g_object_set (data->project, "default-group", group, NULL); } break; default: g_assert_not_reached (); } gtk_tree_path_free (path); } static void group_dialog_cell_edited (GtkCellRendererText *cell, gchar *path_str, gchar *new_text, GtkWindow *dialog) { DialogData *data; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; GtkTreeModelSort *sorted_model; GtkTreeIter sorted_iter; gint column; MrpGroup *group; data = g_object_get_data (G_OBJECT (dialog), "data"); sorted_model = GTK_TREE_MODEL_SORT (gtk_tree_view_get_model (data->tree_view)); model = gtk_tree_model_sort_get_model (sorted_model); path = gtk_tree_path_new_from_string (path_str); column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column")); gtk_tree_model_get_iter (GTK_TREE_MODEL (sorted_model), &sorted_iter, path); gtk_tree_model_sort_convert_iter_to_child_iter (sorted_model, &iter, &sorted_iter); group = MRP_GROUP (mg_list_model_get_object ( MG_LIST_MODEL (model), &iter)); switch (column) { case GROUP_COL_NAME: mrp_object_set (group, "name", new_text, NULL); break; case GROUP_COL_MANAGER_NAME: mrp_object_set (group, "manager_name", new_text, NULL); break; case GROUP_COL_MANAGER_PHONE: mrp_object_set (group, "manager_phone", new_text, NULL); break; case GROUP_COL_MANAGER_EMAIL: mrp_object_set (group, "manager_email", new_text, NULL); break; default: g_assert_not_reached (); } gtk_tree_path_free (path); } static void group_dialog_add_column (GtkWidget *dialog, int column, char *title, guint type, gint min_width) { DialogData *data; GtkCellRenderer *cell = NULL; GtkTreeModel *model; GtkTreeViewColumn *column_data; gchar *tree_type = NULL; data = g_object_get_data (G_OBJECT (dialog), "data"); model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (gtk_tree_view_get_model (data->tree_view))); switch (type) { case TREE_VIEW_TEXT: cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", TRUE, NULL); g_signal_connect (cell, "edited", G_CALLBACK (group_dialog_cell_edited), dialog); tree_type = "text"; break; case TREE_VIEW_ACTIVE: cell = gtk_cell_renderer_toggle_new (); g_object_set (cell, "activatable", TRUE, "radio", TRUE, NULL); g_signal_connect (cell, "toggled", G_CALLBACK (group_dialog_cell_toggled), dialog); tree_type = "active"; break; default: g_assert_not_reached (); break; } g_object_set_data (G_OBJECT (cell), "column", GINT_TO_POINTER (column)); column_data = gtk_tree_view_column_new_with_attributes (title, cell, tree_type, column, NULL); gtk_tree_view_column_set_min_width (column_data, min_width); if (type == TREE_VIEW_TEXT) { gtk_tree_view_column_set_sort_column_id (column_data, column); } gtk_tree_view_column_set_resizable (column_data, TRUE); gtk_tree_view_append_column (data->tree_view, column_data); } static void group_dialog_add_columns (GtkWidget *dialog) { group_dialog_add_column (dialog, GROUP_COL_NAME, _("Name"), TREE_VIEW_TEXT, 100); group_dialog_add_column (dialog, GROUP_COL_MANAGER_NAME, _("Manager name"), TREE_VIEW_TEXT, 50); group_dialog_add_column (dialog, GROUP_COL_MANAGER_PHONE, _("Manager phone"), TREE_VIEW_TEXT, 50); group_dialog_add_column (dialog, GROUP_COL_MANAGER_EMAIL, _("Manager email"), TREE_VIEW_TEXT, 50); group_dialog_add_column (dialog, GROUP_COL_GROUP_DEFAULT, _("Default"), TREE_VIEW_ACTIVE, -1); } static void group_dialog_selection_changed_cb (GtkTreeSelection *selection, GtkWidget *dialog) { DialogData *data; GList *list; gboolean selected = FALSE; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); g_return_if_fail (GTK_IS_WIDGET (dialog)); data = g_object_get_data (G_OBJECT (dialog), "data"); list = group_dialog_selection_get_list (dialog); if (list) { selected = TRUE; g_list_free (list); } gtk_widget_set_sensitive (data->remove_button, selected); } static void group_dialog_get_selected_func (GtkTreeModel *sorted_model, GtkTreePath *path, GtkTreeIter *sorted_iter, gpointer data) { GList **list = data; MrpObject *object; GtkTreeIter iter; MgListModel *model; model = MG_LIST_MODEL (gtk_tree_model_sort_get_model ( GTK_TREE_MODEL_SORT (sorted_model))); gtk_tree_model_sort_convert_iter_to_child_iter ( GTK_TREE_MODEL_SORT (sorted_model), &iter, sorted_iter); object = mg_list_model_get_object (model, &iter); if (object) { *list = g_list_prepend (*list, object); } } static GList * group_dialog_selection_get_list (GtkWidget *dialog) { DialogData *data; GtkTreeSelection *selection; GList *list; g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL); data = g_object_get_data (G_OBJECT (dialog), "data"); selection = gtk_tree_view_get_selection (data->tree_view); list = NULL; gtk_tree_selection_selected_foreach ( selection, (GtkTreeSelectionForeachFunc) group_dialog_get_selected_func, &list); return list; } GtkWidget * mg_group_dialog_new (MrpProject *project) { GtkWidget *dialog; g_return_val_if_fail (MRP_IS_PROJECT (project), NULL); dialog = group_dialog_create (project); return dialog; }