Commit a7ed5621 authored by Richard Hult's avatar Richard Hult Committed by Richard Hult

Update sensitivity for the context menu items.

2005-02-13  Richard Hult  <richard@imendio.com>

	* src/planner-gantt-row.c (gantt_row_event): Update sensitivity
	for the context menu items.
	(gantt_row_get_selected_tasks): Add.

	* src/planner-task-tree.c (task_tree_tree_view_popup_menu): Update
	sensitivity and position the menu better.

	* src/planner-task-popup.c
	(planner_task_popup_update_sensitivity): Add, use to consistently
	set sensitivity in the task context menu.

	* src/planner-task-dialog.c (task_dialog_update_sensitivity): Make
	it possible to set complete and priority always, but not work or
	duration or fixed duration for milestones.
	(task_dialog_update_title): Simplify.

	* libplanner/mrp-task-manager.c
	(task_manager_get_task_units_intervals): Allow this to be called
	for milestone tasks.
	(task_manager_calculate_milestone_work_start): Add, gets the work
	start for milestones.
	(task_manager_calculate_task_finish): Use the above for milestone
	tasks.

	* libegg/recent-files/egg-recent-view-uimanager.c
	(egg_recent_view_uimanager_set_list): Temporary fix for a crash.

	* libplanner/mrp-task-manager.c
	(task_manager_calculate_task_finish): Add to the comment and
	special-case milestones so they get the correct start time.

	* src/planner-task-tree.c (task_tree_duration_data_func)
	(task_tree_work_data_func): Make duration/work not editable for
	milestones.

	* libplanner/mrp-task-manager.c
	(mrp_task_manager_get_block_scheduling):
	* libplanner/mrp-project.c (mrp_project_get_block_scheduling)
	(mrp_project_set_block_scheduling): Add.

	* libplanner/mrp-object.c (mrp_object_set): Block scheduling
	around the setting to avoid multiple rescheduling.

	* src/planner-window.c (window_confirm_exit_run): Make the label
	not selectable.
parent 61eca493
2005-02-13 Richard Hult <richard@imendio.com>
* src/planner-gantt-row.c (gantt_row_event): Update sensitivity
for the context menu items.
(gantt_row_get_selected_tasks): Add.
* src/planner-task-tree.c (task_tree_tree_view_popup_menu): Update
sensitivity and position the menu better.
* src/planner-task-popup.c
(planner_task_popup_update_sensitivity): Add, use to consistently
set sensitivity in the task context menu.
* src/planner-task-dialog.c (task_dialog_update_sensitivity): Make
it possible to set complete and priority always, but not work or
duration or fixed duration for milestones.
(task_dialog_update_title): Simplify.
* libplanner/mrp-task-manager.c
(task_manager_get_task_units_intervals): Allow this to be called
for milestone tasks.
(task_manager_calculate_milestone_work_start): Add, gets the work
start for milestones.
(task_manager_calculate_task_finish): Use the above for milestone
tasks.
* libegg/recent-files/egg-recent-view-uimanager.c
(egg_recent_view_uimanager_set_list): Temporary fix for a crash.
* libplanner/mrp-task-manager.c
(task_manager_calculate_task_finish): Add to the comment and
special-case milestones so they get the correct start time.
* src/planner-task-tree.c (task_tree_duration_data_func)
(task_tree_work_data_func): Make duration/work not editable for
milestones.
* libplanner/mrp-task-manager.c
(mrp_task_manager_get_block_scheduling):
* libplanner/mrp-project.c (mrp_project_get_block_scheduling)
(mrp_project_set_block_scheduling): Add.
* libplanner/mrp-object.c (mrp_object_set): Block scheduling
around the setting to avoid multiple rescheduling.
* src/planner-window.c (window_confirm_exit_run): Make the label
not selectable.
* libplanner/mrp-xsl.c (html_write): Don't crash if the stylesheet
is invalid.
......
......@@ -200,7 +200,9 @@ egg_recent_view_uimanager_set_list (EggRecentViewUIManager *view, GList *list)
g_free (tooltip);
}
egg_recent_item_ref (item);
g_object_set_data_full (G_OBJECT (action), "egg_recent_uri", item, (GFreeFunc)egg_recent_item_unref);
/* Comment this out, since it crashes when setting a new model. */
/*g_object_set_data_full (G_OBJECT (action), "egg_recent_uri", item, (GFreeFunc)egg_recent_item_unref);*/
if (view->action_callback != NULL) {
GClosure *closure;
......
......@@ -386,12 +386,22 @@ mrp_object_set (gpointer pobject,
{
MrpObject *object = MRP_OBJECT (pobject);
va_list var_args;
gboolean blocked = FALSE;
g_return_if_fail (MRP_IS_OBJECT (object));
if (object->priv->project) {
blocked = mrp_project_get_block_scheduling (object->priv->project);
mrp_project_set_block_scheduling (object->priv->project, TRUE);
}
va_start (var_args, first_property_name);
mrp_object_set_valist (object, first_property_name, var_args);
va_end (var_args);
if (object->priv->project) {
mrp_project_set_block_scheduling (object->priv->project, blocked);
}
}
/**
......
......@@ -2266,3 +2266,28 @@ project_set_calendar (MrpProject *project,
mrp_task_manager_recalc (priv->task_manager, TRUE);
}
void
mrp_project_set_block_scheduling (MrpProject *project, gboolean block)
{
MrpProjectPriv *priv;
g_return_if_fail (MRP_IS_PROJECT (project));
priv = project->priv;
mrp_task_manager_set_block_scheduling (priv->task_manager, block);
}
gboolean
mrp_project_get_block_scheduling (MrpProject *project)
{
MrpProjectPriv *priv;
g_return_val_if_fail (MRP_IS_PROJECT (project), FALSE);
priv = project->priv;
return mrp_task_manager_get_block_scheduling (priv->task_manager);
}
......@@ -142,6 +142,9 @@ MrpCalendar * mrp_project_get_root_calendar (MrpProject *pro
MrpCalendar * mrp_project_get_calendar (MrpProject *project);
MrpDay * mrp_project_get_calendar_day_by_id (MrpProject *project,
gint id);
void mrp_project_set_block_scheduling (MrpProject *project,
gboolean block);
gboolean mrp_project_get_block_scheduling (MrpProject *project);
#endif /* __MRP_PROJECT_H__ */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2004 Imendio AB
* Copyright (C) 2004-2005 Imendio AB
* Copyright (C) 2001-2003 CodeFactory AB
* Copyright (C) 2001-2003 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
......@@ -1304,10 +1304,6 @@ task_manager_get_task_units_intervals (MrpTaskManager *manager,
guint len;
gint i;
if (mrp_task_get_task_type (task) == MRP_TASK_TYPE_MILESTONE) {
return NULL;
}
priv = manager->priv;
assignments = mrp_task_get_assignments (task);
......@@ -1409,9 +1405,85 @@ task_manager_get_task_units_intervals (MrpTaskManager *manager,
return g_list_reverse (unit_ivals);
}
static void
task_manager_calculate_milestone_work_start (MrpTaskManager *manager,
MrpTask *task,
mrptime start)
{
MrpTaskManagerPriv *priv;
mrptime t;
mrptime t1, t2;
mrptime work_start;
GList *unit_ivals, *l;
UnitsInterval *unit_ival;
MrpTaskType type;
priv = manager->priv;
type = mrp_task_get_task_type (task);
g_return_if_fail (type == MRP_TASK_TYPE_MILESTONE);
work_start = -1;
t = mrp_time_align_day (start);
while (1) {
unit_ivals = task_manager_get_task_units_intervals (manager, task, t);
/* If we don't get anywhere in 100 days, then the calendar must
* be broken, so we abort the scheduling of this task. It's not
* the best solution but fixes the issue for now.
*/
if (t - start > (60*60*24*100)) {
break;
}
if (!unit_ivals) {
t += 60*60*24;
continue;
}
for (l = unit_ivals; l; l = l->next) {
unit_ival = l->data;
t1 = t + unit_ival->start;
t2 = t + unit_ival->end;
/* Skip any intervals before the task starts. */
if (t2 < start) {
continue;
}
/* Don't add time before the start of the task. */
t1 = MAX (t1, start);
work_start = t1;
break;
}
if (work_start != -1) {
break;
}
t += 60*60*24;
}
if (work_start == -1) {
work_start = start;
}
imrp_task_set_work_start (task, work_start);
g_list_foreach (unit_ivals, (GFunc) g_free, NULL);
g_list_free (unit_ivals);
}
/* Calculate the finish time from the work needed for the task, and the effort
* that the allocated resources add to the task. Uses the project calendar if no
* resources are allocated.
* resources are allocated. This function also sets the work_start property of
* the task, which is the first time that actually has work scheduled, this can
* differ from the start if start is inside a non-work period.
*/
static mrptime
task_manager_calculate_task_finish (MrpTaskManager *manager,
......@@ -1439,25 +1511,23 @@ task_manager_calculate_task_finish (MrpTaskManager *manager,
return 0;
}
/* Milestone tasks can be special cased, no duration. */
type = mrp_task_get_task_type (task);
/* FIXME: Commented out for now. */
if (0 && type == MRP_TASK_TYPE_MILESTONE) {
if (duration) {
*duration = 0;
}
if (type == MRP_TASK_TYPE_MILESTONE) {
*duration = 0;
task_manager_calculate_milestone_work_start (manager, task, start);
return start;
}
work = mrp_task_get_work (task);
sched = mrp_task_get_sched (task);
if (sched == MRP_TASK_SCHED_FIXED_WORK) {
*duration = 0;
} else {
*duration = mrp_task_get_duration (task);
}
effort = 0;
finish = start;
......@@ -1544,8 +1614,12 @@ task_manager_calculate_task_finish (MrpTaskManager *manager,
}
if (type == MRP_TASK_TYPE_MILESTONE) {
imrp_task_set_work_start (task, start);
//g_print ("milestone, start ");
//mrp_time_debug_print (start);
//imrp_task_set_work_start (task, work_start);
} else {
//g_print ("task, start ");
//mrp_time_debug_print (work_start);
imrp_task_set_work_start (task, work_start);
}
......@@ -1814,6 +1888,14 @@ mrp_task_manager_set_block_scheduling (MrpTaskManager *manager, gboolean block)
}
}
gboolean
mrp_task_manager_get_block_scheduling (MrpTaskManager *manager)
{
g_return_val_if_fail (MRP_IS_TASK_MANAGER (manager), FALSE);
return manager->priv->block_scheduling;
}
void
mrp_task_manager_rebuild (MrpTaskManager *manager)
{
......
......@@ -73,6 +73,7 @@ void mrp_task_manager_traverse (MrpTaskManager *man
gpointer user_data);
void mrp_task_manager_set_block_scheduling (MrpTaskManager *manager,
gboolean block);
gboolean mrp_task_manager_get_block_scheduling (MrpTaskManager *manager);
void mrp_task_manager_rebuild (MrpTaskManager *manager);
void mrp_task_manager_recalc (MrpTaskManager *manager,
gboolean force);
......
......@@ -189,7 +189,7 @@ application_init (PlannerApplication *app)
egg_recent_model_set_filter_uri_schemes (priv->recent_model, "file", NULL);
g_object_set (priv->recent_model, "limit", 5, NULL);
app->priv = priv;
}
......
......@@ -213,6 +213,8 @@ static PlannerCmd *task_cmd_edit_property (PlannerWindow *window,
const gchar *property,
const GValue *value);
static GList * gantt_row_get_selected_tasks (GtkTreeSelection *selection);
static GnomeCanvasItemClass *parent_class;
static guint signals[LAST_SIGNAL];
......@@ -1514,6 +1516,7 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
GtkTreeSelection *selection;
GtkTreeView *tree_view;
GtkTreeIter iter;
GList *tasks;
chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
tree = planner_gantt_chart_get_view (chart);
......@@ -1534,6 +1537,10 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
gtk_tree_selection_select_path (selection, path);
planner_task_tree_set_anchor (tree, path);
}
tasks = gantt_row_get_selected_tasks (selection);
planner_task_popup_update_sensitivity (priv->popup_factory, tasks);
g_list_free (tasks);
gtk_item_factory_popup (priv->popup_factory,
event->button.x_root,
......@@ -1856,8 +1863,6 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
-1,
mrp_task_get_start (priv->task) + duration);
// koko
chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
tree = planner_gantt_chart_get_view (chart);
......@@ -2421,3 +2426,35 @@ task_cmd_edit_property (PlannerWindow *window,
return cmd_base;
}
static void
gantt_row_get_selected_func (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
GList **list = data;
MrpTask *task;
gtk_tree_model_get (model,
iter,
COL_TASK, &task,
-1);
*list = g_list_prepend (*list, task);
}
static GList *
gantt_row_get_selected_tasks (GtkTreeSelection *selection)
{
GList *list;
list = NULL;
gtk_tree_selection_selected_foreach (selection,
gantt_row_get_selected_func,
&list);
list = g_list_reverse (list);
return list;
}
......@@ -2785,43 +2785,38 @@ task_dialog_update_sensitivity (DialogData *data)
{
MrpTaskType type;
MrpTaskSched sched;
gboolean leaf, milestone, fixed, sensitive;
leaf = (mrp_task_get_n_children (data->task) == 0);
gboolean leaf, milestone, fixed;
g_object_get (data->task, "type", &type, NULL);
leaf = (mrp_task_get_n_children (data->task) == 0);
type = mrp_task_get_task_type (data->task);
milestone = (type == MRP_TASK_TYPE_MILESTONE);
g_object_get (data->task, "sched", &sched, NULL);
sched = mrp_task_get_sched (data->task);
fixed = (sched == MRP_TASK_SCHED_FIXED_DURATION);
sensitive = leaf && (type != MRP_TASK_TYPE_MILESTONE);
gtk_widget_set_sensitive (data->milestone_checkbutton, leaf);
gtk_widget_set_sensitive (data->fixed_checkbutton, leaf);
gtk_widget_set_sensitive (data->fixed_checkbutton, leaf && !milestone);
gtk_widget_set_sensitive (data->duration_spinbutton, sensitive && fixed);
gtk_widget_set_sensitive (data->complete_spinbutton, sensitive);
gtk_widget_set_sensitive (data->priority_spinbutton, sensitive);
gtk_widget_set_sensitive (data->duration_spinbutton, leaf && !milestone && fixed);
gtk_widget_set_sensitive (data->work_spinbutton, leaf && !milestone);
}
static void
task_dialog_update_title (DialogData *data)
{
gchar *title;
gchar *name;
const gchar *name;
gchar *title;
g_object_get (data->task, "name", &name, NULL);
name = mrp_task_get_name (data->task);
if (!name || strlen (name) == 0) {
title = g_strdup (_("Edit task properties"));
} else {
title = g_strconcat (name, " - ", _("Edit task properties"), NULL);
}
gtk_window_set_title (GTK_WINDOW (data->dialog), title);
g_free (name);
g_free (title);
}
......
......@@ -193,3 +193,54 @@ planner_task_popup_new (PlannerTaskTree *tree)
return item_factory;
}
static void
task_popup_set_sensitive (GtkItemFactory *factory, gint id, gboolean sensitive)
{
GtkWidget *widget;
widget = gtk_item_factory_get_widget_by_action (factory, id);
gtk_widget_set_sensitive (widget, sensitive);
}
void
planner_task_popup_update_sensitivity (GtkItemFactory *factory,
GList *tasks)
{
gint length;
MrpTask *task;
MrpTaskType type;
gboolean milestone;
length = g_list_length (tasks);
/* Can always insert task. */
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_INSERT, TRUE);
/* Nothing else when nothing is selected. */
if (length == 0) {
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_SUBTASK, FALSE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_REMOVE, FALSE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_UNLINK, FALSE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_EDIT_TASK, FALSE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_EDIT_RESOURCES, FALSE);
return;
}
/* Can only insert subtask when one !milestone is selected. */
if (length == 1) {
task = tasks->data;
type = mrp_task_get_task_type (task);
milestone = (type == MRP_TASK_TYPE_MILESTONE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_SUBTASK, !milestone);
} else {
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_SUBTASK, FALSE);
}
/* The rest are always sensitive when one more more tasks are selected. */
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_REMOVE, TRUE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_UNLINK, TRUE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_EDIT_TASK, TRUE);
task_popup_set_sensitive (factory, PLANNER_TASK_POPUP_EDIT_RESOURCES, TRUE);
}
......@@ -32,6 +32,9 @@ typedef enum {
PLANNER_TASK_POPUP_EDIT_RESOURCES
} PlannerTaskPopupItem;
GtkItemFactory * planner_task_popup_new (PlannerTaskTree *tree);
GtkItemFactory *planner_task_popup_new (PlannerTaskTree *tree);
void planner_task_popup_update_sensitivity (GtkItemFactory *factory,
GList *tasks);
#endif
......@@ -1180,31 +1180,59 @@ task_tree_task_removed_cb (PlannerGanttModel *model,
}
static void
task_tree_tree_view_popup_menu (GtkWidget *widget,
task_tree_tree_view_popup_menu (GtkWidget *widget,
PlannerTaskTree *tree)
{
gint x, y;
GList *tasks;
GtkTreePath *path;
GtkTreeViewColumn *column;
GdkRectangle rect;
gint x, y;
tasks = planner_task_tree_get_selected_tasks (tree);
planner_task_popup_update_sensitivity (tree->priv->popup_factory, tasks);
g_list_free (tasks);
gtk_tree_view_get_cursor (GTK_TREE_VIEW (tree), &path, &column);
gtk_tree_view_get_cell_area (GTK_TREE_VIEW (tree),
path,
column,
&rect);
x = rect.x;
y = rect.y;
gdk_window_get_pointer (widget->window, &x, &y, NULL);
/* Note: this is not perfect, but good enough for now. */
gdk_window_get_root_origin (GTK_WIDGET (tree)->window, &x, &y);
rect.x += x;
rect.y += y;
gtk_widget_translate_coordinates (GTK_WIDGET (tree),
gtk_widget_get_toplevel (GTK_WIDGET (tree)),
rect.x, rect.y,
&x, &y);
/* Offset so it's not overlapping the cell. */
rect.x = x + 20;
rect.y = y + 20;
gtk_item_factory_popup (tree->priv->popup_factory,
x, y,
rect.x, rect.y,
0,
gtk_get_current_event_time ());
}
static gboolean
task_tree_tree_view_button_press_event (GtkTreeView *tree_view,
task_tree_tree_view_button_press_event (GtkTreeView *tv,
GdkEventButton *event,
PlannerTaskTree *tree)
{
GtkTreePath *path;
GtkTreeView *tv;
PlannerTaskTreePriv *priv;
GtkItemFactory *factory;
GtkTreeIter iter;
GList *tasks;
tv = GTK_TREE_VIEW (tree);
priv = tree->priv;
factory = priv->popup_factory;
......@@ -1213,22 +1241,15 @@ task_tree_tree_view_button_press_event (GtkTreeView *tree_view,
/* Select our row. */
if (gtk_tree_view_get_path_at_pos (tv, event->x, event->y, &path, NULL, NULL, NULL)) {
gtk_tree_model_get_iter (gtk_tree_view_get_model (tree_view), &iter, path);
if (!gtk_tree_selection_iter_is_selected (gtk_tree_view_get_selection (tree_view), &iter)) {
gtk_tree_model_get_iter (gtk_tree_view_get_model (tv), &iter, path);
if (!gtk_tree_selection_iter_is_selected (gtk_tree_view_get_selection (tv), &iter)) {
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (tv));
gtk_tree_selection_select_path (gtk_tree_view_get_selection (tv), path);
}
gtk_widget_set_sensitive (
gtk_item_factory_get_widget_by_action (factory, PLANNER_TASK_POPUP_SUBTASK), TRUE);
gtk_widget_set_sensitive (
gtk_item_factory_get_widget_by_action (factory, PLANNER_TASK_POPUP_REMOVE), TRUE);
gtk_widget_set_sensitive (
gtk_item_factory_get_widget_by_action (factory, PLANNER_TASK_POPUP_UNLINK), TRUE);
gtk_widget_set_sensitive (
gtk_item_factory_get_widget_by_action (factory, PLANNER_TASK_POPUP_EDIT_RESOURCES), TRUE);
gtk_widget_set_sensitive (
gtk_item_factory_get_widget_by_action (factory, PLANNER_TASK_POPUP_EDIT_TASK), TRUE);
tasks = planner_task_tree_get_selected_tasks (tree);
planner_task_popup_update_sensitivity (factory, tasks);
g_list_free (tasks);
planner_task_tree_set_anchor (tree, path);
......@@ -1421,6 +1442,7 @@ task_tree_duration_data_func (GtkTreeViewColumn *tree_column,
gchar *str;
gint weight;
gboolean editable;
MrpTask *task;
task_tree = PLANNER_TASK_TREE (data);
priv = task_tree->priv;
......@@ -1430,15 +1452,21 @@ task_tree_duration_data_func (GtkTreeViewColumn *tree_column,
COL_DURATION, &duration,
COL_WEIGHT, &weight,
COL_EDITABLE, &editable,
COL_TASK, &task,
-1);
calendar = mrp_project_get_calendar (priv->project);
hours_per_day = mrp_calendar_day_get_total_work (
calendar, mrp_day_get_work ()) / (60*60);
if (mrp_task_get_task_type (task) == MRP_TASK_TYPE_MILESTONE) {
editable = FALSE;
str = g_strdup ("");
} else {
calendar = mrp_project_get_calendar (priv->project);
hours_per_day = mrp_calendar_day_get_total_work (
calendar, mrp_day_get_work ()) / (60*60);
str = planner_format_duration (duration, hours_per_day);
}
str = planner_format_duration (duration, hours_per_day);
g_object_set (cell,
"text", str,
"weight", weight,
......@@ -1569,16 +1597,21 @@ task_tree_work_data_func (GtkTreeViewColumn *tree_column,
type = mrp_task_get_task_type (task);
g_object_set (cell,
"weight", weight,
"editable", editable,
NULL);
if (type == MRP_TASK_TYPE_MILESTONE) {
g_object_set (cell, "text", "", NULL);
g_object_set (cell,
"weight", weight,
"editable", FALSE,
"text", "",
NULL);
} else {
gchar *str = planner_format_duration (work, hours_per_day);
g_object_set (cell, "text", str, NULL);
g_object_set (cell,
"weight", weight,
"editable", editable,
"text", str,
NULL);
g_free (str);
}
}
......
......@@ -1263,6 +1263,7 @@ window_confirm_exit_run (PlannerWindow *window)
g_object_set (GTK_MESSAGE_DIALOG (dialog)->label,
"use-markup", TRUE,
"wrap", FALSE,
"selectable", FALSE,
NULL);
uri = mrp_project_get_uri (priv->project);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment