/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2001-2002 CodeFactory AB * Copyright (C) 2001-2002 Richard Hult * Copyright (C) 2001-2002 Mikael Hallendal * Copyright (C) 2001-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 #include #include #include #include #include #include "dialogs/calendar-dialog/mg-calendar-selector.h" #include "util/mg-format.h" #include "mg-project-properties.h" typedef struct { MgMainWindow *main_window; MrpProject *project; GtkWidget *dialog; GtkWidget *name_entry; GtkWidget *org_entry; GtkWidget *manager_entry; GtkWidget *start_date; GtkWidget *phase_option_menu; GtkWidget *calendar_label; GtkTreeView *properties_tree; GtkWidget *add_property_button; GtkWidget *remove_property_button; } DialogData; #define DIALOG_GET_DATA(d) g_object_get_data ((GObject*)d, "data") static void mpp_select_calendar_clicked_cb (GtkWidget *button, GtkWidget *dialog); static void mpp_start_changed_cb (GtkWidget *w, GtkWidget *dialog); static void mpp_project_start_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_project_calendar_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_manager_changed_cb (GtkWidget *w, GtkWidget *dialog); static void mpp_project_manager_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_organization_changed_cb (GtkWidget *w, GtkWidget *dialog); static void mpp_project_organization_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_name_changed_cb (GtkWidget *w, GtkWidget *dialog); static void mpp_project_name_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_project_calendar_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_phase_option_menu_changed_cb (GtkOptionMenu *option_menu, GtkWidget *dialog); static void mpp_project_phase_changed_cb (MrpProject *project, MrpProperty *property, GValue *value, GtkWidget *dialog); static void mpp_project_phases_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog); static void mpp_setup_phases (DialogData *data); static void mpp_set_phase (DialogData *data, const gchar *phase); static void mpp_setup_properties_list (GtkWidget *dialog); static void mpp_property_name_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, GtkWidget *dialog); static void mpp_property_value_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, GtkWidget *dialog); static void mpp_property_added (MrpProject *project, GType object_type, MrpProperty *property, GtkWidget *dialog); static void mpp_property_removed (MrpProject *project, MrpProperty *property, GtkWidget *dialog); static void mpp_add_property_button_clicked_cb (GtkButton *button, GtkWidget *dialog); static void mpp_remove_property_button_clicked_cb (GtkButton *button, GtkWidget *dialog); static void mpp_property_value_edited (GtkCellRendererText *cell, gchar *path_string, gchar *new_text, GtkWidget *dialog); enum { COL_PROPERTY, NUM_OF_COLS }; static void mpp_select_calendar_clicked_cb (GtkWidget *button, GtkWidget *dialog) { DialogData *data; GtkWidget *selector; gint response; MrpCalendar *calendar; data = DIALOG_GET_DATA (dialog); selector = mg_calendar_selector_new ( data->main_window, _("Select a calendar to use for this project:")); response = gtk_dialog_run (GTK_DIALOG (selector)); switch (response) { case GTK_RESPONSE_OK: calendar = mg_calendar_selector_get_calendar (selector); g_object_set (data->project, "calendar", calendar, NULL); break; case GTK_RESPONSE_CANCEL: break; case GTK_RESPONSE_DELETE_EVENT: return; default: break; } gtk_widget_destroy (selector); } static void mpp_connect_to_project (MrpProject *project, GtkWidget *dialog) { g_signal_connect_object (project, "notify::name", G_CALLBACK (mpp_project_name_notify_cb), dialog, 0); g_signal_connect_object (project, "notify::project-start", G_CALLBACK (mpp_project_start_notify_cb), dialog, 0); g_signal_connect_object (project, "notify::organization", G_CALLBACK (mpp_project_organization_notify_cb), dialog, 0); g_signal_connect_object (project, "notify::manager", G_CALLBACK (mpp_project_manager_notify_cb), dialog, 0); g_signal_connect_object (project, "notify::calendar", G_CALLBACK (mpp_project_calendar_notify_cb), dialog, 0); g_signal_connect_object (project, "notify::phases", G_CALLBACK (mpp_project_phases_notify_cb), dialog, 0); g_signal_connect_object (project, "prop-changed::phase", G_CALLBACK (mpp_project_phase_changed_cb), dialog, 0); g_signal_connect_object (project, "property_added", G_CALLBACK (mpp_property_added), dialog, 0); g_signal_connect_object (project, "property_removed", G_CALLBACK (mpp_property_removed), dialog, 0); } static void mpp_project_name_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data; gchar *name; g_return_if_fail (MRP_IS_PROJECT (project)); g_return_if_fail (GTK_IS_DIALOG (dialog)); g_object_get (project, "name", &name, NULL); data = DIALOG_GET_DATA (dialog); g_signal_handlers_block_by_func (data->name_entry, mpp_name_changed_cb, project); gtk_entry_set_text (GTK_ENTRY (data->name_entry), name); g_signal_handlers_unblock_by_func (data->name_entry, mpp_name_changed_cb, project); g_free (name); } static void mpp_name_changed_cb (GtkWidget *w, GtkWidget *dialog) { MrpProject *project; const gchar *name; name = gtk_entry_get_text (GTK_ENTRY (w)); project = g_object_get_data (G_OBJECT (dialog), "project"); g_signal_handlers_block_by_func (project, mpp_project_name_notify_cb, dialog); g_object_set (project, "name", name, NULL); g_signal_handlers_unblock_by_func (project, mpp_project_name_notify_cb, dialog); } static void mpp_project_organization_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data; gchar *organization; g_return_if_fail (MRP_IS_PROJECT (project)); g_return_if_fail (GTK_IS_DIALOG (dialog)); g_object_get (project, "organization", &organization, NULL); data = DIALOG_GET_DATA (dialog); g_signal_handlers_block_by_func (data->org_entry, mpp_organization_changed_cb, project); gtk_entry_set_text (GTK_ENTRY (data->org_entry), organization); g_signal_handlers_unblock_by_func (data->org_entry, mpp_organization_changed_cb, project); g_free (organization); } static void mpp_organization_changed_cb (GtkWidget *w, GtkWidget *dialog) { MrpProject *project; const gchar *organization; organization = gtk_entry_get_text (GTK_ENTRY (w)); project = g_object_get_data (G_OBJECT (dialog), "project"); g_signal_handlers_block_by_func (project, mpp_project_organization_notify_cb, dialog); g_object_set (project, "organization", organization, NULL); g_signal_handlers_unblock_by_func (project, mpp_project_organization_notify_cb, dialog); } static void mpp_project_manager_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data; gchar *manager; g_return_if_fail (MRP_IS_PROJECT (project)); g_return_if_fail (GTK_IS_DIALOG (dialog)); g_object_get (project, "manager", &manager, NULL); data = DIALOG_GET_DATA (dialog); g_signal_handlers_block_by_func (data->manager_entry, mpp_manager_changed_cb, project); gtk_entry_set_text (GTK_ENTRY (data->manager_entry), manager); g_signal_handlers_unblock_by_func (data->manager_entry, mpp_manager_changed_cb, project); g_free (manager); } static void mpp_manager_changed_cb (GtkWidget *w, GtkWidget *dialog) { MrpProject *project; const gchar *manager; manager = gtk_entry_get_text (GTK_ENTRY (w)); project = g_object_get_data (G_OBJECT (dialog), "project"); g_signal_handlers_block_by_func (project, mpp_project_manager_notify_cb, dialog); g_object_set (project, "manager", manager, NULL); g_signal_handlers_unblock_by_func (project, mpp_project_manager_notify_cb, dialog); } static void mpp_project_start_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data; mrptime start; g_return_if_fail (MRP_IS_PROJECT (project)); g_return_if_fail (GTK_IS_DIALOG (dialog)); data = DIALOG_GET_DATA (dialog); start = mrp_project_get_project_start (project); g_signal_handlers_block_by_func (data->start_date, mpp_start_changed_cb, project); gnome_date_edit_set_time (GNOME_DATE_EDIT (data->start_date), start); g_signal_handlers_unblock_by_func (data->start_date, mpp_start_changed_cb, project); } static void mpp_start_changed_cb (GtkWidget *w, GtkWidget *dialog) { mrptime start; time_t t; struct tm *tm; MrpProject *project; project = g_object_get_data (G_OBJECT (dialog), "project"); t = gnome_date_edit_get_time (GNOME_DATE_EDIT (w)); /* We need to do this to get the time as UTC. */ tm = localtime (&t); start = mrp_time_from_tm (tm); g_signal_handlers_block_by_func (project, mpp_project_start_notify_cb, dialog); g_object_set (project, "project-start", start, NULL); g_signal_handlers_unblock_by_func (project, mpp_project_start_notify_cb, dialog); } static void mpp_project_calendar_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data; MrpCalendar *calendar; g_return_if_fail (MRP_IS_PROJECT (project)); g_return_if_fail (GTK_IS_DIALOG (dialog)); data = DIALOG_GET_DATA (dialog); calendar = mrp_project_get_calendar (project); gtk_label_set_text (GTK_LABEL (data->calendar_label), mrp_calendar_get_name (calendar)); } static void mpp_phase_option_menu_changed_cb (GtkOptionMenu *option_menu, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); gint active; GtkWidget *menu; GtkMenuItem *item; const gchar *name; menu = gtk_option_menu_get_menu (option_menu); active = gtk_option_menu_get_history (option_menu); item = g_list_nth_data (GTK_MENU_SHELL (menu)->children, active); name = g_object_get_data (G_OBJECT (item), "data"); g_object_set (data->project, "phase", name, NULL); } static void mpp_project_phase_changed_cb (MrpProject *project, MrpProperty *property, GValue *value, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); const gchar *phase; g_return_if_fail (MRP_IS_PROJECT (project)); phase = g_value_get_string (value); mpp_set_phase (data, phase); } static void mpp_project_phases_notify_cb (MrpProject *project, GParamSpec *pspec, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); g_signal_handlers_block_by_func (data->phase_option_menu, mpp_phase_option_menu_changed_cb, dialog); mpp_setup_phases (data); g_signal_handlers_unblock_by_func (data->phase_option_menu, mpp_phase_option_menu_changed_cb, dialog); } static void mpp_setup_phases (DialogData *data) { GtkOptionMenu *option_menu; GList *phases, *l; GtkWidget *menu; GtkWidget *menu_item; gchar *phase; phases = NULL; g_object_get (data->project, "phases", &phases, NULL); option_menu = GTK_OPTION_MENU (data->phase_option_menu); menu = gtk_option_menu_get_menu (option_menu); if (menu) { gtk_widget_destroy (menu); } menu = gtk_menu_new (); menu_item = gtk_menu_item_new_with_label (_("None")); gtk_widget_show (menu_item); gtk_menu_append (GTK_MENU (menu), menu_item); for (l = phases; l; l = l->next) { menu_item = gtk_menu_item_new_with_label (l->data); gtk_widget_show (menu_item); gtk_menu_append (GTK_MENU (menu), menu_item); g_object_set_data_full (G_OBJECT (menu_item), "data", g_strdup (l->data), g_free); } gtk_widget_show (menu); gtk_option_menu_set_menu (option_menu, menu); mrp_string_list_free (phases); g_object_get (data->project, "phase", &phase, NULL); mpp_set_phase (data, phase); g_free (phase); } static void mpp_set_phase (DialogData *data, const gchar *phase) { GtkOptionMenu *option_menu; GtkWidget *menu; GtkWidget *item; GList *children, *l; gint i; gchar *name; option_menu = GTK_OPTION_MENU (data->phase_option_menu); if (phase) { menu = gtk_option_menu_get_menu (option_menu); children = GTK_MENU_SHELL (menu)->children; for (i = 0, l = children; l; i++, l = l->next) { item = l->data; name = g_object_get_data (G_OBJECT (item), "data"); if (name && !strcmp (phase, name)) { gtk_option_menu_set_history (option_menu, i); return; } } } /* If we didn't match, set "None". */ gtk_option_menu_set_history (option_menu, 0); } static void mpp_setup_properties_list (GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); GList *properties, *l; GtkTreeModel *model; GtkTreeViewColumn *col; GtkCellRenderer *cell; model = GTK_TREE_MODEL ( gtk_list_store_new (NUM_OF_COLS, G_TYPE_POINTER)); gtk_tree_view_set_model (data->properties_tree, model); properties = mrp_project_get_properties_from_type (data->project, MRP_TYPE_PROJECT); for (l = properties; l; l = l->next) { MrpProperty *property = MRP_PROPERTY (l->data); GtkTreeIter iter; if (!mrp_property_get_user_defined (property)) { g_print ("foo\n"); continue; } /* FIXME: Don't hard code this, use user_defined instead */ /* if (!strcmp ("phase", mrp_property_get_name (property)) || !strcmp ("phases", mrp_property_get_name (property))) { continue; } */ gtk_list_store_append (GTK_LIST_STORE (model), &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_PROPERTY, mrp_property_ref (property), -1); } cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", FALSE, NULL); col = gtk_tree_view_column_new_with_attributes (_("Property"), cell, NULL); gtk_tree_view_column_set_cell_data_func (col, cell, (GtkTreeCellDataFunc) mpp_property_name_data_func, dialog, NULL); gtk_tree_view_append_column (data->properties_tree, col); cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", TRUE, NULL); col = gtk_tree_view_column_new_with_attributes (_("Value"), cell, NULL); gtk_tree_view_column_set_cell_data_func (col, cell, (GtkTreeCellDataFunc) mpp_property_value_data_func, dialog, NULL); g_signal_connect (cell, "edited", G_CALLBACK (mpp_property_value_edited), dialog); gtk_tree_view_append_column (data->properties_tree, col); } static void mpp_property_name_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, GtkWidget *dialog) { MrpProperty *property; gtk_tree_model_get (tree_model, iter, COL_PROPERTY, &property, -1); g_object_set (cell, "text", mrp_property_get_name (property), NULL); } static void mpp_property_value_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); MrpProperty *property; gchar *svalue; MrpPropertyType type; gint ivalue; gfloat fvalue; /* mrptime tvalue; */ gint work; gtk_tree_model_get (tree_model, iter, COL_PROPERTY, &property, -1); type = mrp_property_get_property_type (property); switch (type) { case MRP_PROPERTY_TYPE_STRING: mrp_object_get (data->project, mrp_property_get_name (property), &svalue, NULL); if (svalue == NULL) { svalue = g_strdup (""); } break; case MRP_PROPERTY_TYPE_INT: mrp_object_get (data->project, mrp_property_get_name (property), &ivalue, NULL); svalue = g_strdup_printf ("%d", ivalue); break; case MRP_PROPERTY_TYPE_FLOAT: mrp_object_get (data->project, mrp_property_get_name (property), &fvalue, NULL); svalue = mg_format_float (fvalue, 4, FALSE); break; case MRP_PROPERTY_TYPE_DATE: svalue = g_strdup (""); /* mrp_object_get (data->project, */ /* mrp_property_get_name (property), &tvalue, */ /* NULL); */ /* svalue = mg_format_date (tvalue); */ break; case MRP_PROPERTY_TYPE_DURATION: mrp_object_get (data->project, mrp_property_get_name (property), &ivalue, NULL); /* work = mrp_calendar_day_get_total_work ( mrp_project_get_calendar (tree->priv->project), mrp_day_get_work ()); */ work = 8*60*60; svalue = mg_format_duration (ivalue, work / (60*60)); break; case MRP_PROPERTY_TYPE_COST: mrp_object_get (data->project, mrp_property_get_name (property), &fvalue, NULL); svalue = mg_format_float (fvalue, 2, FALSE); break; default: g_warning ("Type not implemented."); break; } g_object_set (cell, "text", svalue, NULL); g_free (svalue); } static void mpp_property_added (MrpProject *project, GType object_type, MrpProperty *property, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); GtkTreeModel *model; GtkTreeIter iter; g_return_if_fail (GTK_IS_DIALOG (dialog)); model = gtk_tree_view_get_model (data->properties_tree); if (object_type != MRP_TYPE_PROJECT || !mrp_property_get_user_defined (property)) { return; } if (gtk_tree_view_get_model (data->properties_tree) != model) { g_print ("AARGH\n"); } gtk_list_store_append (GTK_LIST_STORE (model), &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_PROPERTY, mrp_property_ref (property), -1); g_print ("Property added: %s\n", mrp_property_get_name (property)); } typedef struct { MrpProperty *property; GtkTreePath *found_path; GtkTreeIter *found_iter; } PropertyFindData; static gboolean mpp_property_find (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, PropertyFindData *data) { MrpProperty *property; gtk_tree_model_get (model, iter, COL_PROPERTY, &property, -1); if (strcmp (mrp_property_get_name (data->property), mrp_property_get_name (property)) == 0) { data->found_path = gtk_tree_path_copy (path); data->found_iter = gtk_tree_iter_copy (iter); return TRUE; } return FALSE; } static void mpp_property_removed (MrpProject *project, MrpProperty *property, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); GtkTreeModel *model; PropertyFindData *find_data; g_return_if_fail (GTK_IS_DIALOG (dialog)); model = gtk_tree_view_get_model (data->properties_tree); find_data = g_new0 (PropertyFindData, 1); find_data->property = mrp_property_ref (property); find_data->found_path = NULL; find_data->found_iter = NULL; gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) mpp_property_find, find_data); mrp_property_unref (property); if (find_data->found_path) { gtk_list_store_remove (GTK_LIST_STORE (model), find_data->found_iter); mrp_property_unref (property); gtk_tree_iter_free (find_data->found_iter); gtk_tree_path_free (find_data->found_path); } g_free (find_data); } static gboolean mpp_property_dialog_label_changed_cb (GtkWidget *label_entry, GdkEvent *event, GtkWidget *name_entry) { const gchar *name; const gchar *label; name = gtk_entry_get_text (GTK_ENTRY (name_entry)); if (name == NULL || name[0] == 0) { label = gtk_entry_get_text (GTK_ENTRY (label_entry)); gtk_entry_set_text (GTK_ENTRY (name_entry), label); } return FALSE; } static void mpp_property_dialog_setup_option_menu (GtkWidget *option_menu, GCallback func, gpointer user_data, gconstpointer str1, ...) { GtkWidget *menu; GtkWidget *menu_item; gint i; va_list args; gconstpointer str; gint type; menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu)); if (menu) { gtk_widget_destroy (menu); } menu = gtk_menu_new (); va_start (args, str1); for (str = str1, i = 0; str != NULL; str = va_arg (args, gpointer), i++) { menu_item = gtk_menu_item_new_with_label (str); gtk_widget_show (menu_item); gtk_menu_append (GTK_MENU (menu), menu_item); type = va_arg (args, gint); g_object_set_data (G_OBJECT (menu_item), "data", GINT_TO_POINTER (type)); if (func) { g_signal_connect (menu_item, "activate", func, user_data); } } va_end (args); gtk_widget_show (menu); gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu); } static gint mpp_property_dialog_get_selected (GtkWidget *option_menu) { GtkWidget *menu; GtkWidget *item; gint ret; menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu)); item = gtk_menu_get_active (GTK_MENU (menu)); ret = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "data")); return ret; } static void mpp_property_dialog_type_selected_cb (GtkWidget *widget,GtkWidget *dialog) { gint type; type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "data")); g_object_set_data (G_OBJECT (dialog), "type", GINT_TO_POINTER (type)); } static void mpp_add_property_button_clicked_cb (GtkButton *button, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); MrpProperty *property; MrpPropertyType type; const gchar *label; const gchar *name; const gchar *description; GladeXML *glade; GtkWidget *label_entry; GtkWidget *name_entry; GtkWidget *add_dialog; GtkWidget *w; gint response; gboolean finished = FALSE; glade = glade_xml_new (DATADIR "/mrproject/glade/mg-new-property.glade", NULL, NULL); add_dialog = glade_xml_get_widget (glade, "add_dialog"); label_entry = glade_xml_get_widget (glade, "label_entry"); name_entry = glade_xml_get_widget (glade, "name_entry"); g_signal_connect (label_entry, "focus_out_event", G_CALLBACK (mpp_property_dialog_label_changed_cb), name_entry); mpp_property_dialog_setup_option_menu ( glade_xml_get_widget (glade, "type_menu"), G_CALLBACK (mpp_property_dialog_type_selected_cb), add_dialog, mrp_property_type_as_string (MRP_PROPERTY_TYPE_STRING), MRP_PROPERTY_TYPE_STRING, mrp_property_type_as_string (MRP_PROPERTY_TYPE_INT), MRP_PROPERTY_TYPE_INT, mrp_property_type_as_string (MRP_PROPERTY_TYPE_FLOAT), MRP_PROPERTY_TYPE_FLOAT, /* mrp_property_type_as_string (MRP_PROPERTY_TYPE_DATE), */ /* MRP_PROPERTY_TYPE_DATE, */ /* mrp_property_type_as_string (MRP_PROPERTY_TYPE_DURATION), */ /* MRP_PROPERTY_TYPE_DURATION, */ /* mrp_property_type_as_string (MRP_PROPERTY_TYPE_COST), */ /* MRP_PROPERTY_TYPE_COST, */ NULL); while (!finished) { response = gtk_dialog_run (GTK_DIALOG (add_dialog)); switch (response) { case GTK_RESPONSE_OK: label = gtk_entry_get_text (GTK_ENTRY (label_entry)); if (label == NULL || label[0] == 0) { finished = FALSE; break; } name = gtk_entry_get_text (GTK_ENTRY (name_entry)); if (name == NULL || name[0] == 0) { finished = FALSE; break; } if (!isalpha(name[0])) { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (add_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The name of the custom property needs to start with a letter.")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); finished = FALSE; break; } w = glade_xml_get_widget (glade, "description_entry"); description = gtk_entry_get_text (GTK_ENTRY (w)); w = glade_xml_get_widget (glade, "type_menu"); type = mpp_property_dialog_get_selected (w); if (type != MRP_PROPERTY_TYPE_NONE) { property = mrp_property_new (name, type, label, description, TRUE); mrp_project_add_property (data->project, MRP_TYPE_PROJECT, property, TRUE); } finished = TRUE; break; case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_CANCEL: finished = TRUE; break; default: break; } } gtk_widget_destroy (add_dialog); } static void mpp_remove_property_button_clicked_cb (GtkButton *button, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); GtkTreeModel *model; GtkTreeSelection *selection; GtkTreeIter iter; MrpProperty *property; GtkWidget *remove_dialog; gint response; model = gtk_tree_view_get_model (data->properties_tree); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->properties_tree)); if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { return; } gtk_tree_model_get (model, &iter, COL_PROPERTY, &property, -1); remove_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("Do you really want to remove the property '%s' from " "the project?"), mrp_property_get_name (property)); response = gtk_dialog_run (GTK_DIALOG (remove_dialog)); switch (response) { case GTK_RESPONSE_YES: mrp_project_remove_property (data->project, MRP_TYPE_PROJECT, mrp_property_get_name (property)); break; case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_CANCEL: break; default: break; } gtk_widget_destroy (remove_dialog); } static void mpp_property_value_edited (GtkCellRendererText *cell, gchar *path_string, gchar *new_text, GtkWidget *dialog) { DialogData *data = DIALOG_GET_DATA (dialog); GtkTreePath *path; GtkTreeIter iter; GtkTreeModel *model; MrpProperty *property; MrpProject *project; MrpPropertyType type; gfloat fvalue; model = gtk_tree_view_get_model (data->properties_tree); project = data->project; path = gtk_tree_path_new_from_string (path_string); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, COL_PROPERTY, &property, -1); type = mrp_property_get_property_type (property); switch (type) { case MRP_PROPERTY_TYPE_STRING: mrp_object_set (MRP_OBJECT (project), mrp_property_get_name (property), new_text, NULL); break; case MRP_PROPERTY_TYPE_INT: mrp_object_set (MRP_OBJECT (project), mrp_property_get_name (property), atoi (new_text), NULL); break; case MRP_PROPERTY_TYPE_FLOAT: fvalue = g_ascii_strtod (new_text, NULL); mrp_object_set (MRP_OBJECT (project), mrp_property_get_name (property), fvalue, NULL); break; case MRP_PROPERTY_TYPE_DURATION: /* FIXME: support reading units etc... */ mrp_object_set (MRP_OBJECT (project), mrp_property_get_name (property), atoi (new_text) *8*60*60, NULL); break; case MRP_PROPERTY_TYPE_DATE: /* date = MG_CELL_RENDERER_DATE (cell); */ /* mrp_object_set (MRP_OBJECT (project), */ /* mrp_property_get_name (property), */ /* &(date->time), */ /* NULL); */ break; case MRP_PROPERTY_TYPE_COST: fvalue = g_ascii_strtod (new_text, NULL); mrp_object_set (MRP_OBJECT (project), mrp_property_get_name (property), fvalue, NULL); break; case MRP_PROPERTY_TYPE_STRING_LIST: /* FIXME: SHould string-list still be around? */ break; default: g_assert_not_reached (); break; } gtk_tree_path_free (path); } static void mpp_parent_destroy_cb (GtkWidget *parent, GtkWidget *dialog) { gtk_widget_destroy (dialog); } GtkWidget * mg_project_properties_new (MgMainWindow *window) { GladeXML *glade; GtkWidget *dialog; GtkWidget *w; DialogData *data; mrptime start; gchar *name, *org, *manager; MrpCalendar *calendar; g_return_val_if_fail (MG_IS_MAIN_WINDOW (window), NULL); glade = glade_xml_new (DATADIR "/mrproject/glade/mg-project-properties.glade", "project_properties", GETTEXT_PACKAGE); if (!glade) { g_warning (_("Could not create properties dialog.")); return NULL; } dialog = glade_xml_get_widget (glade, "project_properties"); data = g_new0 (DialogData, 1); data->main_window = window; data->project = mg_main_window_get_project (window); data->dialog = dialog; g_signal_connect_object (glade_xml_get_widget (glade, "close_button"), "clicked", G_CALLBACK (mpp_parent_destroy_cb), dialog, 0); g_signal_connect_object (window, "destroy", G_CALLBACK (mpp_parent_destroy_cb), dialog, 0); data->name_entry = glade_xml_get_widget (glade, "entry_name"); data->org_entry = glade_xml_get_widget (glade, "entry_org"); data->manager_entry = glade_xml_get_widget (glade, "entry_manager"); data->start_date = glade_xml_get_widget (glade, "dateedit_start"); data->phase_option_menu = glade_xml_get_widget (glade, "optionmenu_phase"); data->calendar_label = glade_xml_get_widget (glade, "label_calendar"); data->properties_tree = GTK_TREE_VIEW ( glade_xml_get_widget (glade, "properties_tree")); data->add_property_button = glade_xml_get_widget (glade, "add_property_button"); data->remove_property_button = glade_xml_get_widget (glade, "remove_property_button"); w = glade_xml_get_widget (glade, "label_start"); gtk_label_set_mnemonic_widget (GTK_LABEL (w), data->start_date); start = mrp_project_get_project_start (data->project); g_object_set_data_full (G_OBJECT (dialog), "data", data, g_free); g_object_set_data (G_OBJECT (dialog), "project", data->project); g_object_get (data->project, "name", &name, "organization", &org, "manager", &manager, NULL); gnome_date_edit_set_time (GNOME_DATE_EDIT (data->start_date), start); g_signal_connect (data->start_date, "date_changed", G_CALLBACK (mpp_start_changed_cb), dialog); gtk_entry_set_text (GTK_ENTRY (data->name_entry), name); g_signal_connect (data->name_entry, "changed", G_CALLBACK (mpp_name_changed_cb), dialog); gtk_entry_set_text (GTK_ENTRY (data->org_entry), org); g_signal_connect (data->org_entry, "changed", G_CALLBACK (mpp_organization_changed_cb), dialog); gtk_entry_set_text (GTK_ENTRY (data->manager_entry), manager); g_signal_connect (data->manager_entry, "changed", G_CALLBACK (mpp_manager_changed_cb), dialog); /* Project phase. */ mpp_setup_phases (data); g_signal_connect (data->phase_option_menu, "changed", G_CALLBACK (mpp_phase_option_menu_changed_cb), dialog); g_signal_connect (data->add_property_button, "clicked", G_CALLBACK (mpp_add_property_button_clicked_cb), dialog); g_signal_connect (data->remove_property_button, "clicked", G_CALLBACK (mpp_remove_property_button_clicked_cb), dialog); mpp_setup_properties_list (dialog); /* Project calendar. */ calendar = mrp_project_get_calendar (data->project); gtk_label_set_text (GTK_LABEL (data->calendar_label), mrp_calendar_get_name (calendar)); w = glade_xml_get_widget (glade, "button_calendar"); g_signal_connect (w, "clicked", G_CALLBACK (mpp_select_calendar_clicked_cb), dialog); g_free (name); g_free (manager); g_free (org); mpp_connect_to_project (data->project, dialog); g_object_unref (glade); return dialog; }