Re: [Planner Dev] Prop. for new feat. - second patch released
- From: Matteo Nastasi aka mop <nastasi alternativeoutput it>
- To: Planner Project Manager - Development List <planner-dev lists imendio com>
- Subject: Re: [Planner Dev] Prop. for new feat. - second patch released
- Date: Wed, 22 Feb 2006 20:56:39 +0100
Hi, sorry for the lag,
On Mon, Feb 06, 2006 at 08:47:37PM +0100, Richard Hult wrote:
> Hi,
>
---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
> Using macros is fine by me. I haven't really thought about what they do
> though. We probably need some comments in the code for that.
I have added some comment, I hope that it explains the code better.
---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
> >
> >How about --enable-priority-scheduling ??
>
> Or --enable-simple-priority-scheduling to emphasize that it's not the
> "real" thing.
"in media stat virtus" - I have used this option name.
Attached my second patch that replaces my first.
Regards, Matteo.
--
Matteo Nastasi - Milano - Italy | HomePage: www.alternativeoutput.it
Sostenere e supportare GNU/Linux ! | IRC: #linux-mi irc freenode net
Milano Linux | E-Mail: matteo nastasi milug org
Users Group www.milug.org | nastasi alternativeoutput it
* looking for nastasi alternativeoutput it--projects/planner--mop--0--base-0 to compare with
* comparing to nastasi alternativeoutput it--projects/planner--mop--0--base-0
A {arch}/planner/planner--mop/planner--mop--0/nastasi alternativeoutput it--projects/patch-log/patch-1
M libplanner/mrp-task.h
M libplanner/mrp-task.c
M src/planner-task-tree.c
M configure.in
M src/planner-gantt-chart.c
M autogen.sh
M data/ui/gantt-view.ui
M libplanner/mrp-task-manager.c
M src/planner-gantt-chart.h
M libplanner/mrp-calendar.c
M libplanner/mrp-calendar.h
M src/planner-gantt-view.c
M src/planner-task-view.c
M src/planner-gantt-row.c
M data/planner.schemas.in
* modified files
--- orig/autogen.sh
+++ mod/autogen.sh
@@ -163,7 +163,7 @@
fi
done
-conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
+conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c #--enable-simple-priority-scheduling
cd "$ORIGDIR"
--- orig/configure.in
+++ mod/configure.in
@@ -249,6 +249,18 @@
AM_CONDITIONAL(HAVE_EDS_PLUGIN, test x$use_eds = xyes)
dnl -----------------------------------------------------------
+dnl -----------------------------------
+dnl | Simple Priority Scheduling check |-----------------------------------------
+dnl -----------------------------------
+AC_ARG_ENABLE(simple_priority_scheduling, [ --enable-simple-priority-scheduling enable a simple priority scheduling in tasks management[default=no]], enable_simple_priority_scheduling="$enableval", enable_simple_priority_scheduling=no)
+if test "x$enable_simple_priority_scheduling" = "xyes" ; then
+ use_simple_priority_scheduling=yes
+ AC_DEFINE(WITH_SIMPLE_PRIORITY_SCHEDULING, 1, [Define to 1 to enable enable a simple priority scheduling in tasks management feature])
+else
+ use_simple_priority_scheduling=no
+fi
+AM_CONDITIONAL(HAVE_SIMPLE_PRIORITY_SCHEDULING, test x$use_simple_priority_scheduling = xyes)
+dnl -----------------------------------------------------------
dnl -------------------------------------
dnl | Evolution Data Server Backend check |--------------------------------------
@@ -326,11 +338,16 @@
echo "Python bindings : $have_python"
echo "Python plugin : $enable_python_plugin"
#echo "Dotnet bindings : $have_dotnet"
+echo "Simple priority scheduling : $use_simple_priority_scheduling"
echo "Database/GDA support : $use_gda"
echo "Evolution Data Server import : $use_eds"
echo "Evolution Data Server backend: $use_eds_backend"
echo
+if test "x$use_simple_priority_scheduling" = "xyes" ; then
+ echo "*** Note: The use simple priority tasks scheduling is experimental. Don't use it in production systems ***"
+fi
+
if test "x$enable_eds_backend" = "xyes" ; then
echo "*** Note: The Evolution backend is experimental. Don't use it in production systems ***"
fi
--- orig/data/planner.schemas.in
+++ mod/data/planner.schemas.in
@@ -14,6 +14,18 @@
</schema>
<schema>
+ <key>/schemas/apps/planner/views/gantt_view/not_standard_days</key>
+ <applyto>/apps/planner/views/gantt_view/not_standard_days</applyto>
+ <owner>planner</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Display not standard days in Gantt view</short>
+ <long>Whether to display not standard days in the Gantt view.</long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/planner/views/task_view/highlight_critical_path</key>
<applyto>/apps/planner/views/task_view/highlight_critical_path</applyto>
<owner>planner</owner>
--- orig/data/ui/gantt-view.ui
+++ mod/data/ui/gantt-view.ui
@@ -14,6 +14,7 @@
<placeholder name="View specific placeholder bottom">
<menuitem action="EditColumns"/>
<menuitem action="HighlightCriticalTasks"/>
+ <menuitem action="NotStandardDays"/>
</placeholder>
</menu>
--- orig/libplanner/mrp-calendar.c
+++ mod/libplanner/mrp-calendar.c
@@ -1063,6 +1063,29 @@
}
}
+/**
+ * mrp_interval_set_absolute:
+ * @interval: an #MrpInterval
+ * @offset: the offset to subtract to start and end
+ * @start: value of start time
+ * @end: value of end time
+ *
+ * Set the start and end time of #interval, with an optional @offset.
+ *
+ **/
+void
+mrp_interval_set_absolute (MrpInterval *interval,
+ mrptime offset,
+ mrptime start,
+ mrptime end)
+{
+ g_return_if_fail (interval != NULL);
+
+ interval->start = start - offset;
+
+ interval->end = end - offset;
+}
+
static void
foreach_day_interval_add_to_list (MrpDay *day,
GList *intervals,
--- orig/libplanner/mrp-calendar.h
+++ mod/libplanner/mrp-calendar.h
@@ -127,6 +127,10 @@
mrptime offset,
mrptime *start,
mrptime *end);
+void mrp_interval_set_absolute (MrpInterval *interval,
+ mrptime offset,
+ mrptime start,
+ mrptime end);
#endif /* __MRP_CALENDAR_H__ */
--- orig/libplanner/mrp-task-manager.c
+++ mod/libplanner/mrp-task-manager.c
@@ -76,6 +76,12 @@
task_manager_task_duration_notify_cb (MrpTask *task,
GParamSpec *spec,
MrpTaskManager *manager);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager);
+#endif
static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
@@ -261,6 +267,13 @@
"notify::duration",
G_CALLBACK (task_manager_task_duration_notify_cb),
manager);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ /* Added to manage the transaction from normal to vampire. */
+ g_signal_connect (task,
+ "notify::priority",
+ G_CALLBACK (task_manager_task_priority_notify_cb),
+ manager);
+#endif
g_signal_connect (task,
"notify::constraint",
G_CALLBACK (task_manager_task_constraint_notify_cb),
@@ -1222,20 +1235,13 @@
return start;
}
-typedef struct {
- gboolean is_start;
- mrptime start;
- mrptime end;
- gint units;
-} UnitsInterval;
-
-#define UNIT_IVAL_GET_TIME(R) ((R->is_start?R->start:R->end))
-
+/* NOTE: MrpUnitsInterval moved in mrp-task.h to enable
+ other objects to use it. */
static gint
units_interval_sort_func (gconstpointer a, gconstpointer b)
{
- UnitsInterval *ai = *(UnitsInterval **) a;
- UnitsInterval *bi = *(UnitsInterval **) b;
+ MrpUnitsInterval *ai = *(MrpUnitsInterval **) a;
+ MrpUnitsInterval *bi = *(MrpUnitsInterval **) b;
mrptime at, bt;
if (ai->is_start) {
@@ -1260,12 +1266,12 @@
}
}
-static UnitsInterval *
+static MrpUnitsInterval *
units_interval_new (MrpInterval *ival, gint units, gboolean is_start)
{
- UnitsInterval *unit_ival;
+ MrpUnitsInterval *unit_ival;
- unit_ival = g_new (UnitsInterval, 1);
+ unit_ival = g_new (MrpUnitsInterval, 1);
unit_ival->is_start = is_start;
unit_ival->units = units;
@@ -1292,50 +1298,180 @@
MrpDay *day;
GList *ivals, *l;
MrpInterval *ival;
- UnitsInterval *unit_ival, *new_unit_ival;
+
+ MrpUnitsInterval *unit_ival, *new_unit_ival;
+ MrpUnitsInterval *unit_ival_start, *unit_ival_end;
GList *unit_ivals = NULL;
MrpAssignment *assignment;
MrpResource *resource;
GList *assignments, *a;
- gint units;
+ gint units, units_full, units_orig, priority;
+ mrptime i_start, i_end;
+
mrptime t;
mrptime poc;
GPtrArray *array;
guint len;
gint i;
+ mrptime diffe;
+
+ gint res_n;
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ MrpInterval *ival_split;
+ MrpUnitsInterval *unit_ival_start_cmp;
+ MrpUnitsInterval *split_unit_ival;
+ MrpAssignment *v_assignment;
+ MrpResource *v_resource;
+ GList *v_assignments, *v_a;
+ gint v_units;
+ GList *v_tasks, *v_l;
+ GPtrArray *array_split;
+ gint e, lastct;
+ mrptime v_start, v_end;
+ mrptime i_start_post, i_end_post, i_start_cmp, i_end_cmp;
+#endif
+
priv = manager->priv;
assignments = mrp_task_get_assignments (task);
array = g_ptr_array_new ();
+ priority = mrp_task_get_priority (task);
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ v_tasks = mrp_task_manager_get_all_tasks (manager);
+#endif
for (a = assignments; a; a = a->next) {
assignment = a->data;
resource = mrp_assignment_get_resource (assignment);
- units = mrp_assignment_get_units (assignment);
+ units_orig = mrp_assignment_get_units (assignment);
calendar = mrp_resource_get_calendar (resource);
if (!calendar) {
calendar = mrp_project_get_calendar (priv->project);
}
-
day = mrp_calendar_get_day (calendar, date, TRUE);
ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
for (l = ivals; l; l = l->next) {
ival = l->data;
+ mrp_interval_get_absolute(ival, date, &i_start, &i_end);
+ units = units_orig;
+ diffe = i_end - i_start;
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (v_l = v_tasks; v_l; v_l = v_l->next) {
+ MrpTask *v_task;
+
+ v_task = v_l->data;
+
+ if (v_task == task)
+ continue;
+ if (mrp_task_is_vampire (v_task) == FALSE)
+ continue;
+
+ /* If intervals not overlapped -> contine. */
+ v_start = mrp_task_get_work_start (v_task);
+ v_end = mrp_task_get_finish (v_task);
+
+ if (i_start > v_end ||
+ i_end < v_start)
+ continue;
+
+ /* Compare resources task with resources of vampire task. */
+ v_assignments = mrp_task_get_assignments (v_task);
+
+ for (v_a = v_assignments; v_a; v_a = v_a->next) {
+ v_assignment = v_a->data;
+
+ v_resource = mrp_assignment_get_resource (v_assignment);
+ if (v_resource == resource) {
+ v_units = mrp_assignment_get_units (v_assignment);
+ /*
+ If the vampire cost is compatible with the task
+ request -> break.
+
+ FIXME - tasks that share the vampirised resource not work!
+ */
+ if (100 - v_units > units)
+ break;
+
+ /* Trim the interval of the vampire task. */
+ v_start = (v_start < i_start ?
+ i_start : v_start);
+ v_end = (v_end > i_end ?
+ i_end : v_end);
+
+ if (i_start < v_start) {
+ /*
+ ----...
+ ------...
+ ival len from start to vampire
+ */
+ ival = mrp_interval_new (i_start-date, v_start-date);
+
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+ }
+
+ ival = mrp_interval_new (v_start-date, v_end-date);
+
+ unit_ival_start = units_interval_new (ival, (100 - v_units), TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, (100 - v_units), FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+
+ if (v_end < i_end) {
+ /*
+ ---- ...
+ ------...
+ ival len from end to vampire
+ */
+ ival = mrp_interval_new (v_end-date, i_end-date);
+
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+ }
+ break;
+ }
+ } // for (v_a = v_assignments; v_a; ...
+ if (v_a != NULL)
+ break;
+ } // for (v_l = v_tasks; v_l; ...
+
+
+ if (v_l == NULL) {
+#endif // ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
/* Start of the interval. */
- unit_ival = units_interval_new (ival, units, TRUE);
- g_ptr_array_add (array, unit_ival);
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
/* End of the interval. */
- unit_ival = units_interval_new (ival, units, FALSE);
- g_ptr_array_add (array, unit_ival);
- }
- }
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ }
+#endif
+ } // for (l = ivals; l; ...
+ } // for (a = assignments; a; ...
/* If the task is not allocated, we handle it as if we have one resource
* assigned to it, 100%, using the project calendar.
@@ -1351,20 +1487,81 @@
/* Start of the interval. */
unit_ival = units_interval_new (ival, 100, TRUE);
+ unit_ival->units_full = 100;
g_ptr_array_add (array, unit_ival);
/* End of the interval. */
unit_ival = units_interval_new (ival, 100, FALSE);
+ unit_ival->units_full = 100;
g_ptr_array_add (array, unit_ival);
}
}
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ /* Requantize the time intervals. */
+ array_split = g_ptr_array_new ();
+ len = array->len;
+ poc = -1;
+ units = 0;
+ /* += 2 because start and end are strictly joined. */
+ for (i = 0; i < len; i+= 2) {
+ unit_ival_start = g_ptr_array_index (array, i);
+
+ i_start = unit_ival_start->start;
+ i_end = unit_ival_start->end;
+
+ lastct = 1;
+ i_end_post = i_end;
+ for (i_start_post = i_start; i_start_post < i_end && lastct > 0;) {
+ lastct = 0;
+ i_end_post = i_end;
+ for (e = 0 ; e < len ; e+= 2) {
+ unit_ival_start_cmp = g_ptr_array_index (array, e);
+
+ i_start_cmp = unit_ival_start_cmp->start;
+ i_end_cmp = unit_ival_start_cmp->end;
+
+ /* If not overlapped intervals. */
+ if (i_start_post >= i_end_cmp || i_end_post <= i_start_cmp)
+ continue;
+ if (i_start_post < i_start_cmp && i_start_cmp < i_end_post) {
+ i_end_post = i_start_cmp;
+ lastct++;
+ continue;
+ }
+ if (i_start_post < i_end_cmp && i_end_cmp < i_end_post) {
+ i_end_post = i_end_cmp;
+ lastct++;
+ continue;
+ }
+ }
+ ival_split = mrp_interval_new (i_start_post, i_end_post);
+ split_unit_ival = units_interval_new(ival_split, unit_ival_start->units, TRUE);
+ split_unit_ival->units_full = unit_ival_start->units_full;
+ g_ptr_array_add(array_split, split_unit_ival);
+ split_unit_ival = units_interval_new(ival_split, unit_ival_start->units, FALSE);
+ split_unit_ival->units_full = unit_ival_start->units_full;
+ g_ptr_array_add(array_split, split_unit_ival);
+ i_start_post = i_end_post;
+ }
+ }
+ for (i = 0; i < array->len; i++) {
+ g_free (array->pdata[i]);
+ }
+
+ g_ptr_array_free (array, TRUE);
+ array = array_split;
+#endif // ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ /* Clean and reassign the split_array ptr to the array */
g_ptr_array_sort (array, units_interval_sort_func);
len = array->len;
+
poc = -1;
units = 0;
+ units_full = 0;
+ res_n = 0;
for (i = 0; i < len; i++) {
unit_ival = g_ptr_array_index (array, i);
@@ -1376,23 +1573,27 @@
* determined by now.
*/
if (poc != -1) {
- if (units > 0) {
- new_unit_ival = g_new (UnitsInterval, 1);
- new_unit_ival->units = units;
- new_unit_ival->start = poc;
- new_unit_ival->end = t;
-
- unit_ivals = g_list_prepend (unit_ivals, new_unit_ival);
- }
+ new_unit_ival = g_new (MrpUnitsInterval, 1);
+ new_unit_ival->units = units;
+ new_unit_ival->units_full = units_full;
+ new_unit_ival->start = poc;
+ new_unit_ival->end = t;
+ new_unit_ival->res_n = res_n;
+ res_n = 0;
+ unit_ivals = g_list_prepend (unit_ivals, new_unit_ival);
}
-
+
poc = t;
}
-
+
if (unit_ival->is_start) {
units += unit_ival->units;
+ units_full += unit_ival->units_full;
+ if (assignments)
+ res_n++;
} else {
units -= unit_ival->units;
+ units_full -= unit_ival->units_full;
}
}
@@ -1416,7 +1617,7 @@
mrptime t1, t2;
mrptime work_start;
GList *unit_ivals, *l;
- UnitsInterval *unit_ival;
+ MrpUnitsInterval *unit_ival;
MrpTaskType type;
priv = manager->priv;
@@ -1499,11 +1700,12 @@
gint work;
gint effort;
gint delta;
- GList *unit_ivals, *l;
- UnitsInterval *unit_ival;
+ GList *unit_ivals, *unit_ivals_tot = NULL, *l = NULL;
+ MrpUnitsInterval *unit_ival;
MrpTaskType type;
MrpTaskSched sched;
+
priv = manager->priv;
if (task == priv->root) {
@@ -1547,6 +1749,7 @@
}
if (!unit_ivals) {
+ /* Holidays for all. */
t += 60*60*24;
continue;
}
@@ -1556,7 +1759,6 @@
t1 = t + unit_ival->start;
t2 = t + unit_ival->end;
-
/* Skip any intervals before the task starts. */
if (t2 < start) {
continue;
@@ -1577,6 +1779,7 @@
if (sched == MRP_TASK_SCHED_FIXED_WORK) {
delta = floor (0.5 + (double) unit_ival->units * (t2 - t1) / 100.0);
+ if (unit_ival->units_full > 0)
*duration += (t2 - t1);
if (effort + delta >= work) {
@@ -1584,8 +1787,14 @@
/* Subtract the spill. */
*duration -= floor (0.5 + (effort + delta - work) / unit_ival->units * 100.0);
+ unit_ival->start = t1;
+ unit_ival->end = finish;
+ unit_ivals_tot = g_list_prepend (unit_ivals_tot, unit_ival);
goto done;
}
+ unit_ival->start = t1;
+ unit_ival->end = t2;
+ unit_ivals_tot = g_list_prepend (unit_ivals_tot, unit_ival);
}
else if (sched == MRP_TASK_SCHED_FIXED_DURATION) {
delta = t2 - t1;
@@ -1602,7 +1811,6 @@
effort += delta;
}
-
t += 60*60*24;
}
@@ -1613,9 +1821,18 @@
}
imrp_task_set_work_start (task, work_start);
- g_list_foreach (unit_ivals, (GFunc) g_free, NULL);
+ /* clean the tail of the list before exit of function. */
+ if (l) {
+ for (l = l->next ; l; l = l->next) {
+ unit_ival = l->data;
+ g_free(unit_ival);
+ }
+ }
g_list_free (unit_ivals);
+ unit_ivals_tot = g_list_reverse (unit_ivals_tot);
+ mrp_task_set_unit_ivals (task, unit_ivals_tot);
+
return finish;
}
@@ -1976,6 +2193,15 @@
mrp_task_manager_recalc (manager, TRUE);
}
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager)
+{
+ mrp_task_manager_recalc (manager, TRUE);
+}
+#endif
static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
@@ -2254,6 +2480,80 @@
return work;
}
+static gint
+task_manager_get_work_for_task_with_assignments (MrpTaskManager *manager,
+ MrpTask *task,
+ mrptime start,
+ mrptime finish)
+{
+ MrpTaskManagerPriv *priv;
+ mrptime t;
+ mrptime t1, t2;
+ gint work, delta;
+ GList *ivals, *l;
+ MrpUnitsInterval *ival;
+
+ priv = manager->priv;
+
+ work = 0;
+
+ /* Loop through the intervals of the calendar and add up the work, until
+ * the finish time is hit.
+ */
+ t = mrp_time_align_day (start);
+
+
+ while (t < finish) {
+ 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 (work == 0 && t - start > (60*60*24*100)) {
+ break;
+ }
+
+ if (!ivals) {
+ /* Holidays for all. */
+ t += 60*60*24;
+ continue;
+ }
+
+ for (l = ivals; l; l = l->next) {
+ ival = l->data;
+
+ t1 = t + ival->start;
+ t2 = t + 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);
+ if (t1 == t2) {
+ continue;
+ }
+
+ /* Resize the too long interval */
+ t2 = MIN (t2, finish);
+ if (t1 >= t2) {
+ break;
+ }
+
+ delta = floor (0.5 + (double) ival->units * (t2 - t1) / 100.0);
+
+ work += delta;
+ }
+
+
+ t += 24*60*60;
+ }
+
+ return (work);
+}
+
/* Calculate the work needed to achieve the specified start and finish, with the
* allocated resources' calendars in consideration.
*/
@@ -2265,9 +2565,7 @@
{
MrpTaskManagerPriv *priv;
gint work = 0;
- MrpAssignment *assignment;
- MrpResource *resource;
- GList *assignments, *a;
+ GList *assignments;
MrpCalendar *calendar;
priv = manager->priv;
@@ -2293,24 +2591,13 @@
*/
assignments = mrp_task_get_assignments (task);
- for (a = assignments; a; a = a->next) {
- assignment = a->data;
-
- resource = mrp_assignment_get_resource (assignment);
-
- calendar = mrp_resource_get_calendar (resource);
- if (!calendar) {
- calendar = mrp_project_get_calendar (priv->project);
- }
-
- work += task_manager_get_work_for_calendar (manager,
- calendar,
- start,
- finish) *
- mrp_assignment_get_units (assignment) / 100;
+ if (assignments) {
+ work = task_manager_get_work_for_task_with_assignments (manager,
+ task,
+ start,
+ finish);
}
-
- if (!assignments) {
+ else {
calendar = mrp_project_get_calendar (priv->project);
work = task_manager_get_work_for_calendar (manager,
--- orig/libplanner/mrp-task.c
+++ mod/libplanner/mrp-task.c
@@ -125,6 +125,9 @@
/* List of assignments. */
GList *assignments;
+ /* Intervals to build graphical view of the task */
+ GList *unit_ivals;
+
gfloat cost;
gboolean cost_cached;
};
@@ -195,6 +198,7 @@
priv->cost = 0.0;
priv->cost_cached = FALSE;
+ priv->unit_ivals = NULL;
}
static void
@@ -1499,6 +1503,87 @@
}
/**
+ * mrp_task_get_priority:
+ * @task: an #MrpTask
+ *
+ * Retrieves the priority of @task.
+ *
+ * Return value: The priority of @task.
+ **/
+gint
+mrp_task_get_priority (MrpTask *task)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ return task->priv->priority;
+}
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+/**
+ * mrp_task_is_vampire:
+ * @task: an #MrpTask
+ *
+ * Retrieves if @task is a vampire task.
+ *
+ * Return value: if @task is a vampire task.
+ **/
+gboolean
+mrp_task_is_vampire (MrpTask *task)
+{
+ MrpConstraint constraint;
+
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ constraint = impr_task_get_constraint (task);
+ if (constraint.type != MRP_CONSTRAINT_MSO)
+ return (FALSE);
+
+ if (task->priv->priority != MRP_VAMPIRE_PRIORITY)
+ return (FALSE);
+
+ return (TRUE);
+}
+#endif
+/**
+ * mrp_task_get_unit_ivals:
+ * @task: an #MrpTask
+ *
+ * Retrieves the list of intervals of @task.
+ *
+ * Return value: Intervals of @task.
+ **/
+GList *
+mrp_task_get_unit_ivals (MrpTask *task)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ return task->priv->unit_ivals;
+}
+
+/**
+ * mrp_task_set_unit_ivals:
+ * @task: an #MrpTask
+ *
+ * Set the list of intervals of @task.
+ *
+ * Return value: Intervals of @task.
+ **/
+GList *
+mrp_task_set_unit_ivals (MrpTask *task, GList *ivals)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ if (task->priv->unit_ivals) {
+ g_list_foreach (task->priv->unit_ivals, (GFunc) g_free, NULL);
+ g_list_free (task->priv->unit_ivals);
+ task->priv->unit_ivals = NULL;
+ }
+ task->priv->unit_ivals = ivals;
+
+ return task->priv->unit_ivals;
+}
+
+/**
* mrp_task_get_assignments:
* @task: an #MrpTask
*
@@ -1515,6 +1600,27 @@
}
/**
+ * mrp_task_get_nres:
+ * @task: an #MrpTask
+ *
+ * Calculate the number of resources assigned to task.
+ *
+ * Return value: the number of resources.
+ **/
+gint mrp_task_get_nres (MrpTask *task)
+{
+ GList *assignments, *a;
+ gint nres = 0;
+
+ assignments = mrp_task_get_assignments (task);
+
+ for (a = assignments; a; a = a->next)
+ nres++;
+
+ return (nres);
+}
+
+/**
* mrp_task_get_assignment:
* @task: an #MrpTask
* @resource: an #MrpResource
--- orig/libplanner/mrp-task.h
+++ mod/libplanner/mrp-task.h
@@ -42,6 +42,31 @@
typedef struct _MrpTaskClass MrpTaskClass;
typedef struct _MrpTaskPriv MrpTaskPriv;
+// NOTE: moved from libplanner/mrp-task-manager.c to use
+// the structure in the src/planner-gantt-row.c
+// new fields are:
+// units . worked units in the interval
+// units_full . expected worked units in the interval
+// all resources that are working in the
+// interval in the right percentage
+// res_n . number of expected resources working
+// at the task in the interval
+typedef struct {
+ gboolean is_start;
+ mrptime start;
+ mrptime end;
+ gint units;
+ gint units_full;
+ gint res_n;
+} MrpUnitsInterval;
+
+#define UNIT_IVAL_GET_TIME(R) ((R->is_start?R->start:R->end))
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+// value of the magic priority of a vampire task
+#define MRP_VAMPIRE_PRIORITY 9999
+#endif
+
#include <libplanner/mrp-relation.h>
struct _MrpTask
@@ -95,7 +120,17 @@
mrptime mrp_task_get_latest_finish (MrpTask *task);
gint mrp_task_get_duration (MrpTask *task);
gint mrp_task_get_work (MrpTask *task);
+gint mrp_task_get_priority (MrpTask *task);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+gboolean mrp_task_is_vampire (MrpTask *task);
+#endif
+GList * mrp_task_get_unit_ivals (MrpTask *task);
+GList * mrp_task_set_unit_ivals (MrpTask *task,
+ GList *ivals);
GList *mrp_task_get_assignments (MrpTask *task);
+gint mrp_task_get_nres (MrpTask *task);
+
+gint mrp_task_get_fullwork (MrpTask *task);
MrpAssignment *mrp_task_get_assignment (MrpTask *task,
MrpResource *resource);
void mrp_task_reset_constraint (MrpTask *task);
--- orig/src/planner-gantt-chart.c
+++ mod/src/planner-gantt-chart.c
@@ -54,6 +54,7 @@
static gdouble f = 1.0;
#define CRITICAL_PATH_KEY "/views/gantt_view/highlight_critical_path"
+#define NOSTDDAYS_PATH_KEY "/views/gantt_view/not_standard_days"
typedef struct _TreeNode TreeNode;
@@ -103,6 +104,9 @@
/* Critical path. */
gboolean highlight_critical;
+
+ /* Not standard days visualization */
+ gboolean not_standard_days;
/* Keep a list of signal connection ids, so we can remove them
* easily.
@@ -384,6 +388,8 @@
priv->highlight_critical = planner_conf_get_bool (CRITICAL_PATH_KEY,
NULL);
+ priv->not_standard_days = planner_conf_get_bool (NOSTDDAYS_PATH_KEY,
+ NULL);
}
static void
@@ -1917,3 +1923,32 @@
return chart->priv->highlight_critical;
}
+
+void
+planner_gantt_chart_set_not_standard_days (PlannerGanttChart *chart,
+ gboolean state)
+{
+ PlannerGanttChartPriv *priv;
+
+ g_return_if_fail (PLANNER_IS_GANTT_CHART (chart));
+
+ priv = chart->priv;
+
+ if (priv->not_standard_days == state) {
+ return;
+ }
+
+ priv->not_standard_days = state;
+
+ gtk_widget_queue_draw (GTK_WIDGET (priv->canvas));
+
+ planner_conf_set_bool (NOSTDDAYS_PATH_KEY, state, NULL);
+}
+
+gboolean
+planner_gantt_chart_get_not_standard_days (PlannerGanttChart *chart)
+{
+ g_return_val_if_fail (PLANNER_IS_GANTT_CHART (chart), FALSE);
+
+ return chart->priv->not_standard_days;
+}
--- orig/src/planner-gantt-chart.h
+++ mod/src/planner-gantt-chart.h
@@ -90,5 +90,11 @@
gboolean
planner_gantt_chart_get_highlight_critical_tasks (PlannerGanttChart *chart);
+void
+planner_gantt_chart_set_not_standard_days (PlannerGanttChart *chart,
+ gboolean state);
+gboolean
+planner_gantt_chart_get_not_standard_days (PlannerGanttChart *chart);
+
#endif /* __PLANNER_GANTT_CHART_H__ */
--- orig/src/planner-gantt-row.c
+++ mod/src/planner-gantt-row.c
@@ -28,6 +28,7 @@
#include <libplanner/mrp-project.h>
#include <libplanner/mrp-resource.h>
#include <libplanner/mrp-task.h>
+#include <libplanner/mrp-calendar.h>
#include <glib/gi18n.h>
#include <libgnomecanvas/gnome-canvas.h>
#include "planner-marshal.h"
@@ -57,6 +58,21 @@
/* Minimum width for a task to keep it visible. */
#define MIN_WIDTH 2
+// Trim the value to short int work space. */
+#define TRSH(a) ((int)((a) < SHRT_MIN ? (short int)SHRT_MIN : ((a) > SHRT_MAX ? (short int)SHRT_MAX : (a))))
+
+// Same gdk_draw_rectangle but with trimmed x,y,w,h args.
+#define draw_cut_rectangle ((a),(b),(c),(d),(e),(f),(g)) \
+ gdk_draw_rectangle ((a),(b),(c),TRSH(d),TRSH(e),TRSH(f),TRSH(g))
+
+// Same gdk_draw_rectangle but with trimmed x1,y1,x2,y2 args.
+#define draw_cut_line ((a),(b),(c),(d),(e),(f)) \
+ gdk_draw_line ((a),(b),TRSH(c),TRSH(d),TRSH(e),TRSH(f))
+
+// Same gdk_draw_layout but with trimmed x,y args.
+#define draw_cut_layout ((a),(b),(c),(d),(e)) \
+ gdk_draw_layout ((a),(b),TRSH(c),TRSH(d),(e))
+
enum {
PROP_0,
PROP_X,
@@ -91,6 +107,8 @@
GdkGC *break_gc;
GdkGC *fill_gc;
GdkGC *frame_gc;
+ GdkGC *ttask_gc;
+
/* FIXME: Don't need those per gantt row. */
GdkColor color_normal;
@@ -219,6 +237,16 @@
static GList * gantt_row_get_selected_tasks (GtkTreeSelection *selection);
+static MrpUnitsInterval *mop_get_next_ival(GList **cur, gint *is_a_gap, GList *start, MrpUnitsInterval *buf);
+static MrpInterval *mop_get_next_mrp_ival(GList **cur, gint *is_a_gap, GList *start, MrpInterval *buf);
+static gboolean gantt_draw_tasktime(GdkDrawable *drawable,
+ GdkGC *gc,
+ GnomeCanvas *canvas,
+ gdouble start_wx, gdouble start_wy,
+ gdouble end_wx, gdouble end_wy,
+ gint cy1, gint cy2, gint x, gint y,
+ gboolean is_up, gchar *colorname);
+
static GnomeCanvasItemClass *parent_class;
static guint signals[LAST_SIGNAL];
@@ -807,6 +835,8 @@
priv->frame_gc = gdk_gc_new (item->canvas->layout.bin_window);
+ priv->ttask_gc = gdk_gc_new (item->canvas->layout.bin_window);
+
gnome_canvas_get_color (item->canvas,
"LightSkyBlue3",
&priv->color_normal);
@@ -847,6 +877,9 @@
gdk_gc_unref (row->priv->frame_gc);
row->priv->frame_gc = NULL;
+ gdk_gc_unref (row->priv->ttask_gc);
+ row->priv->ttask_gc = NULL;
+
if (break_stipple) {
g_object_unref (break_stipple);
}
@@ -868,6 +901,219 @@
GDK_JOIN_MITER);
}
+
+static MrpUnitsInterval *mop_get_next_ival(GList **cur, gint *is_a_gap, GList *start, MrpUnitsInterval *buf)
+{
+ MrpUnitsInterval *cur_ival;
+ gint last_end, md;
+
+ if (start) {
+ *cur = start;
+ cur_ival = start->data;
+ md = cur_ival->start % (24*60*60);
+ if (md > 0) {
+ buf->start = cur_ival->start - md;
+ buf->end = cur_ival->start;
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ if ((*cur) == NULL)
+ return (NULL);
+
+ cur_ival = (*cur)->data;
+
+ if (*is_a_gap == 1) { /* last was a gap */
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ else {
+ if ((*cur)->next != NULL) {
+ last_end = cur_ival->end;
+ *cur = (*cur)->next;
+ cur_ival = (*cur)->data;
+
+ if (last_end < cur_ival->start) { /* another gap */
+ buf->start = last_end;
+ buf->end = cur_ival->start;
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ else {
+ md = cur_ival->end % (24*60*60);
+ if (md > 0) {
+ buf->start = cur_ival->end;
+ buf->end = cur_ival->end - md + (24*60*60);
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+ *cur = NULL;
+ return (buf);
+ }
+ else
+ return (NULL);
+ }
+ }
+
+ return (NULL);
+}
+
+
+
+static MrpInterval *mop_get_next_mrp_ival(GList **cur, gint *is_a_gap, GList *start, MrpInterval *buf)
+{
+ MrpInterval *cur_ival;
+ gint last_end, md;
+ mrptime cur_start, cur_end;
+
+ if (start) {
+ *cur = start;
+ cur_ival = start->data;
+
+ mrp_interval_get_absolute(cur_ival, 0, &cur_start, &cur_end);
+ md = cur_start % (24*60*60);
+ if (md > 0) {
+ mrp_interval_set_absolute(buf, 0, 0, cur_start);
+ *is_a_gap = 1;
+
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ if ((*cur) == NULL)
+ return (NULL);
+
+ cur_ival = (*cur)->data;
+ mrp_interval_get_absolute(cur_ival, 0, &cur_start, &cur_end);
+
+ if (*is_a_gap == 1) { /* last was a gap */
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ else {
+ if ((*cur)->next != NULL) {
+ last_end = cur_end;
+ *cur = (*cur)->next;
+ cur_ival = (*cur)->data;
+ mrp_interval_get_absolute(cur_ival, 0, &cur_start, &cur_end);
+
+ if (last_end < cur_start) { /* another gap */
+ mrp_interval_set_absolute(buf, 0, last_end, cur_start);
+
+ *is_a_gap = 1;
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ else {
+ md = cur_end % (24*60*60);
+ if (md > 0) {
+ mrp_interval_set_absolute(buf, 0, cur_end, cur_end - md + (24*60*60));
+
+ *is_a_gap = 1;
+ *cur = NULL;
+ return (buf);
+ }
+ else
+ return (NULL);
+ }
+ }
+
+ return (NULL);
+}
+
+
+static gboolean gantt_draw_tasktime(GdkDrawable *drawable,
+ GdkGC *gc,
+ GnomeCanvas *canvas,
+ gdouble start_wx, gdouble start_wy,
+ gdouble end_wx, gdouble end_wy,
+ gint cy1, gint cy2,
+ gint x, gint y,
+ gboolean is_up,
+ gchar *colorname)
+{
+ GdkColor color;
+ gint ttime_x1, ttime_y1, ttime_x2, ttime_y2;
+
+ gnome_canvas_w2c (canvas, start_wx, start_wy, &ttime_x1, &ttime_y1);
+ gnome_canvas_w2c (canvas, end_wx, end_wy, &ttime_x2, &ttime_y2);
+ ttime_x1 -= x; ttime_y1 -= y;
+ ttime_x2 -= x; ttime_y2 -= y;
+
+ if (ttime_x2 > ttime_x1) {
+ gnome_canvas_get_color (canvas, colorname, &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ if (is_up) {
+ gdk_draw_rectangle (drawable,
+ gc,
+ TRUE,
+ ttime_x1,
+ ttime_y1,
+ ttime_x2 - ttime_x1,
+ cy1 - ttime_y1);
+
+ gnome_canvas_get_color (canvas, "gray40", &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x2-1, ttime_y1);
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x1, cy1-1);
+ }
+ else {
+ gdk_draw_rectangle (drawable,
+ gc,
+ TRUE,
+ ttime_x1, cy2+1,
+ ttime_x2 - ttime_x1,
+ ttime_y2 - cy2 - 1);
+
+ gnome_canvas_get_color (canvas, "gray40", &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y2,
+ ttime_x2-1, ttime_y2);
+ gdk_draw_line (drawable, gc, ttime_x1, cy2+1,
+ ttime_x1, ttime_y2);
+ }
+
+ return (TRUE);
+ }
+ else
+ return (FALSE);
+}
+
+
+/* x,y w,h sono relate al rettangolo visibile rispetto al canvas del widget
+ in oggetto */
static void
gantt_row_draw (GnomeCanvasItem *item,
GdkDrawable *drawable,
@@ -881,7 +1127,7 @@
PlannerGanttChart *chart;
gdouble i2w_dx;
gdouble i2w_dy;
- gdouble dx1, dy1, dx2, dy2;
+ gdouble dx1, dy1, dx2, dy2, dshay1, dshay2;
gint level;
MrpTaskType type;
gboolean summary;
@@ -890,32 +1136,82 @@
gint percent_complete;
gint complete_x2, complete_width;
gboolean highlight_critical;
+ gboolean not_standard_days;
gboolean critical;
-
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ gboolean is_vampire;
+#endif
gint rx1, ry1;
gint rx2, ry2;
gint cx1, cy1, cx2, cy2;
-
+
+ GList *unit_ivals, *cal_ivals, *cur_unit, *cur_cal;
+ GdkColor color;
+ gint x_start, x_end, y_dumb, is_a_gap, is_a_subgap;
+ MrpUnitsInterval *unit_ival, ival_buf;
+ MrpInterval *ival_subbuf = NULL, *cal_ival;
+ gint i, day_cur, cur_start, cur_end;
+
+ MrpProject *project;
+ MrpDay *day;
+ MrpCalendar *calendar;
+ mrptime cal_start, cal_end;
+ gboolean is_before_work;
+ gboolean shadup_is_cached, shadup_draw_it;
+ gboolean shaddo_is_cached, shaddo_draw_it;
+ gint shadup_start = -1, shadup_end = -1;
+ gint shaddo_start = -1, shaddo_end = -1;
+
+ gboolean workup_is_cached, workup_draw_it;
+ gboolean workdo_is_cached, workdo_draw_it;
+ gint workup_start = -1, workup_end = -1;
+ gint workdo_start = -1, workdo_end = -1;
+
+ gboolean wunits_is_first = FALSE, wunits_is_cached = FALSE, wunits_draw_it;
+ gint wunits_x_start = -1;
+
+ gint last_end = 0;
+
+ gint topy, nres, finish;
+ gdouble delta = -1.0;
+ GList *assignments;
+
row = PLANNER_GANTT_ROW (item);
priv = row->priv;
+ project = mrp_object_get_project (MRP_OBJECT (priv->task));
+ calendar = mrp_project_get_calendar (project);
+
chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
highlight_critical = planner_gantt_chart_get_highlight_critical_tasks (chart);
-
+ not_standard_days = planner_gantt_chart_get_not_standard_days (chart);
level = planner_scale_clamp_zoom (priv->zoom);
+
+ /*
+ MOP NOTES
+
+ w -> world
+ i -> item
+ c -> canvas
+
+ priv->x = t * scale
+ */
+
/* Get item area in canvas coordinates. */
i2w_dx = 0.0;
i2w_dy = 0.0;
gnome_canvas_item_i2w (item, &i2w_dx, &i2w_dy);
dx1 = priv->x;
- dy1 = priv->y + 0.15 * priv->height;
+ dy1 = priv->y + 0.25 * priv->height;
dx2 = priv->x + priv->width;
- dy2 = priv->y + 0.70 * priv->height;
+ dy2 = priv->y + 0.75 * priv->height;
dx2 = MAX (dx2, dx1 + MIN_WIDTH);
+ dshay1 = priv->y + 0.08 * priv->height;
+ dshay2 = priv->y + 0.92 * priv->height;
gnome_canvas_w2c (item->canvas,
dx1 + i2w_dx,
dy1 + i2w_dy,
@@ -932,12 +1228,12 @@
cy1 -= y;
cx2 -= x;
cy2 -= y;
-
+
if (cy1 >= cy2 || cx1 >= cx2) {
return;
}
- summary_y = floor (priv->y + 2 * 0.15 * priv->height + 0.5) - y;
+ summary_y = floor (priv->y + 2 * 0.25 * priv->height + 0.5) - y;
/* "Clip" the expose area. */
rx1 = MAX (cx1, 0);
@@ -953,7 +1249,12 @@
percent_complete = mrp_task_get_percent_complete (priv->task);
critical = mrp_task_get_critical (priv->task);
type = mrp_task_get_task_type (priv->task);
-
+ finish = mrp_task_get_finish (priv->task);
+ nres = mrp_task_get_nres (priv->task);
+ assignments = mrp_task_get_assignments (priv->task);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ is_vampire = mrp_task_is_vampire(priv->task);
+#endif
if (!summary) {
complete_width = floor ((cx2 - cx1) * (percent_complete / 100.0) + 0.5);
complete_x2 = MIN (cx1 + complete_width, rx2);
@@ -967,20 +1268,426 @@
priv->complete_gc);
}
+ if (assignments) {
+ /* #define DRAW_BACKGROUND_CHECK 1 */
+#ifdef DRAW_BACKGROUND_CHECK
+ gnome_canvas_get_color (item->canvas, "indian red", &color);
+ gdk_gc_set_foreground (priv->fill_gc, &color);
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ rx1,
+ cy1,
+ rx2 - rx1,
+ cy2 - cy1);
+#endif
+
+ /* Start slices drawer */
+ unit_ivals = mrp_task_get_unit_ivals (priv->task);
+ ival_subbuf = mrp_interval_new(0,0);
+
+ is_before_work = TRUE;
+ shadup_is_cached = FALSE;
+ shaddo_is_cached = FALSE;
+ workup_is_cached = FALSE;
+ workdo_is_cached = FALSE;
+ for (i = 0, unit_ival = mop_get_next_ival(&cur_unit, &is_a_gap,
+ unit_ivals, &ival_buf)
+ ; unit_ival && (i == 0 || cur_start < finish) ; i++) {
+ if (i == 0) {
+ /* first iteration: read the day when start the task */
+ day_cur = mrp_time_align_day (unit_ival->start);
+
+ /* extract the intervals of the day */
+ day = mrp_calendar_get_day (calendar, day_cur, TRUE);
+ cal_ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
+
+ if (cal_ivals == NULL) {
+ mrp_interval_set_absolute(ival_subbuf, 0, 0, (24*60*60));
+ is_a_subgap = 1;
+ cal_ival = ival_subbuf;
+ }
+ else {
+ for (cal_ival = mop_get_next_mrp_ival(&cur_cal, &is_a_subgap,
+ cal_ivals, ival_subbuf)
+ ; cal_ival
+ ; cal_ival = mop_get_next_mrp_ival(&cur_cal, &is_a_subgap,
+ NULL, ival_subbuf)) {
+ mrp_interval_get_absolute(cal_ival, day_cur, &cal_start, &cal_end);
+
+ if (cal_end > unit_ival->start)
+ break;
+ }
+ }
+ cur_start = MAX(unit_ival->start, cal_start);
+ cur_end = MIN(unit_ival->end , cal_end );
+ wunits_is_first = TRUE;
+ }
+ g_assert(cal_ival != NULL);
+
+ gnome_canvas_w2c (item->canvas, (cur_start * priv->scale)
+ + i2w_dx, i2w_dy, &x_start, &y_dumb);
+ gnome_canvas_w2c (item->canvas, (cur_end * priv->scale)
+ + i2w_dx, i2w_dy, &x_end, &y_dumb);
+ x_start -= x;
+ x_end -= x;
+
+ if (is_before_work) {
+ if (unit_ival->units_full == 0)
+ goto cont_shadowloop;
+ else
+ is_before_work = FALSE;
+ }
+ if (not_standard_days) {
+ shadup_draw_it = FALSE;
+ shaddo_draw_it = FALSE;
+ workup_draw_it = FALSE;
+ workdo_draw_it = FALSE;
+
+ if (unit_ival->res_n == 0 && (!is_a_subgap ||
+ (is_a_subgap && planner_scale_conf[level].nonworking_limit
+ > cal_end - cal_start))) {
+ if (shadup_is_cached == FALSE) {
+ shadup_start = cur_start;
+ shadup_is_cached = TRUE;
+ }
+ }
+ else {
+ if (shadup_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - shadup_start) {
+ shadup_end = cur_start;
+ shadup_draw_it = TRUE;
+ }
+ shadup_is_cached = FALSE;
+ }
+ }
+
+ if (unit_ival->res_n < nres && (!is_a_subgap ||
+ (is_a_subgap && planner_scale_conf[level].nonworking_limit
+ > cal_end - cal_start))) {
+
+ if (shaddo_is_cached == FALSE) {
+ shaddo_start = cur_start;
+ shaddo_is_cached = TRUE;
+ }
+ }
+ else {
+ if (shaddo_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - shaddo_start) {
+ shaddo_end = cur_start;
+ shaddo_draw_it = TRUE;
+ }
+ shaddo_is_cached = FALSE;
+ }
+ }
+
+ if ((unit_ival->res_n == nres && is_a_subgap) ||
+ (unit_ival->res_n == 0 &&
+ (cal_start % (24*60*60) == 0) && (cal_end % (24*60*60) == 0) &&
+ planner_scale_conf[level].nonworking_limit > cur_end - cur_start)) {
+ if (workup_is_cached == FALSE) {
+ workup_start = cur_start;
+ workup_is_cached = TRUE;
+ }
+ }
+ else {
+ if (workup_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - workup_start) {
+ workup_end = cur_start;
+ workup_draw_it = TRUE;
+ }
+ workup_is_cached = FALSE;
+ }
+ }
+
+ if ((unit_ival->res_n > 0 && is_a_subgap) ||
+ (unit_ival->res_n == 0 &&
+ (cal_start % (24*60*60) == 0) && (cal_end % (24*60*60) == 0) &&
+ planner_scale_conf[level].nonworking_limit > cur_end - cur_start)) {
+
+ if (workdo_is_cached == FALSE) {
+ workdo_start = cur_start;
+ workdo_is_cached = TRUE;
+ }
+ }
+ else {
+ if (workdo_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - workdo_start) {
+ workdo_end = cur_start;
+ workdo_draw_it = TRUE;
+ }
+ workdo_is_cached = FALSE;
+ }
+ }
+
+ /* Show shadow up. */
+ if (shadup_draw_it ||
+ (shadup_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!shadup_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ shadup_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ shadup_end - shadup_start) {
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (shadup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shadup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "grey96");
+ }
+ shadup_draw_it = FALSE;
+ shadup_is_cached = FALSE;
+ }
+
+ /* Show shadow down. */
+ if (shaddo_draw_it ||
+ (shaddo_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!shaddo_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ shaddo_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ shaddo_end - shaddo_start) {
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (shaddo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shaddo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "grey96");
+ }
+ shaddo_draw_it = FALSE;
+ shaddo_is_cached = FALSE;
+ }
+
+ /* Show work up. */
+ if (workup_draw_it ||
+ (workup_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!workup_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ workup_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ workup_end - workup_start) {
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (workup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "white");
+ }
+ workup_draw_it = FALSE;
+ workup_is_cached = FALSE;
+ }
+
+ /* Show work down. */
+ if (workdo_draw_it ||
+ (workdo_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!workdo_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ workdo_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ workdo_end - workdo_start) {
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (workdo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workdo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "white");
+
+ workdo_draw_it = FALSE;
+ workdo_is_cached = FALSE;
+ }
+ }
+ }
+ /* Draw area. */
+ wunits_draw_it = TRUE;
+ if (unit_ival->res_n > 0 && unit_ival->units_full > 0) {
+ delta = (double)unit_ival->units / (double)unit_ival->units_full;
+ }
+ else {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_end - cur_start) {
+ delta = 1.0;
+ }
+ else {
+ if (wunits_is_first == TRUE) {
+ wunits_is_cached = TRUE;
+ wunits_x_start = x_start;
+ wunits_draw_it = FALSE;
+ }
+ }
+ }
+
+ topy = floor ((cy1 + ((1.0 - (double)delta) * (double)(cy2 - cy1 - 3))) + 0.5);
+ if (!highlight_critical || !critical) {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
+ } else {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
+ }
+
+ if (wunits_draw_it) {
+ if (wunits_is_cached) {
+ wunits_is_cached = FALSE;
+ }
+ else {
+ wunits_x_start = x_start;
+ }
+
+ if ((cy2 - topy - 3) > 0) {
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ wunits_x_start,
+ topy + 2,
+ x_end - wunits_x_start,
+ cy2 - topy - 3);
+ }
+ if (topy - cy1 > 0) {
+ gnome_canvas_get_color (item->canvas, "white", &color);
+ gdk_gc_set_foreground (priv->fill_gc, &color);
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ wunits_x_start,
+ cy1+2,
+ x_end - wunits_x_start,
+ topy - cy1);
+ }
+ }
+
+ cont_shadowloop:
+ if (not_standard_days)
+ last_end = cur_end;
+ wunits_is_first = FALSE;
+
+ if (cur_end == unit_ival->end) {
+ if ((unit_ival = mop_get_next_ival(&cur_unit, &is_a_gap,
+ NULL, &ival_buf)) == NULL)
+ break;
+ }
+ if (cur_end == cal_end) {
+ if ((cal_ival = mop_get_next_mrp_ival(&cur_cal, &is_a_subgap,
+ NULL, ival_subbuf)) == NULL) {
+ /* End of the day intervals, read next. */
+ day_cur += (24*60*60);
+ day = mrp_calendar_get_day (calendar, day_cur, TRUE);
+ cal_ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
+ if (cal_ivals) {
+ /* Not empty day. */
+ cal_ival = mop_get_next_mrp_ival(&cur_cal, &is_a_subgap,
+ cal_ivals, ival_subbuf);
+ }
+ else {
+ /* Empty day. */
+ mrp_interval_set_absolute(ival_subbuf, 0, 0, (24*60*60));
+ is_a_subgap = 1;
+ cal_ival = ival_subbuf;
+ }
+ wunits_is_first = TRUE;
+ }
+ mrp_interval_get_absolute(cal_ival, day_cur, &cal_start, &cal_end);
+ }
+
+ cur_start = MAX(unit_ival->start, cal_start);
+ cur_end = MIN(unit_ival->end , cal_end );
+ }
+
+ if (not_standard_days) {
+ /*
+ H O L Y D A Y S
+ */
+
+ /* Show shad up. */
+ if (shadup_is_cached) {
+ shadup_end = last_end;
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (shadup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shadup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "grey96");
+ }
+
+ /* Show shad down. */
+ if (shaddo_is_cached) {
+ shaddo_end = last_end;
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (shaddo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shaddo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "grey96");
+ }
+
+ /*
+ W O R K
+ */
+
+ /* Show work up. */
+ if (workup_is_cached) {
+ workup_end = last_end;
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (workup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "white");
+ }
+
+ /* Show work down. */
+ if (workdo_is_cached) {
+ workdo_end = last_end;
+
+ gantt_draw_tasktime(drawable, priv->ttask_gc, item->canvas,
+ (workdo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workdo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "white");
+ }
+ }
+ }
+ else { /* if (assignments) ... */
+ if (!highlight_critical || !critical) {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
+ } else {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
+ }
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ rx1,
+ cy1,
+ rx2 - rx1,
+ cy2 - cy1);
+ }
+
+
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ if (ival_subbuf)
+ mrp_interval_unref(ival_subbuf);
+
if (!highlight_critical || !critical) {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
} else {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
}
-
- gdk_draw_rectangle (drawable,
- priv->fill_gc,
- TRUE,
- rx1,
- cy1 + 1,
- rx2 - rx1,
- cy2 - cy1 - 1);
-
+
if (rx1 <= complete_x2) {
gdk_draw_rectangle (drawable,
priv->complete_gc,
@@ -991,8 +1698,31 @@
cy2 - cy1 - 7);
}
- gdk_draw_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
- gdk_draw_line (drawable, priv->frame_gc, rx1, cy2, rx2, cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (i = 0 ; i < (is_vampire && !(!summary && priv->highlight) ? 2 : 1) ; ++i) {
+ if (i == 1) {
+ gnome_canvas_get_color (item->canvas, "indian red", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ gdk_gc_set_line_attributes (priv->frame_gc,
+ 0,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ gdk_draw_line (drawable, priv->frame_gc, cx1, cy1, cx2, cy1);
+ gdk_draw_line (drawable, priv->frame_gc, cx1, cy2, cx2, cy2);
+ gantt_row_setup_frame_gc (row, !summary && priv->highlight);
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+ }
+ else {
+#endif
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy2, rx2, cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ }
+ }
+#endif
if (!highlight_critical || !critical) {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal_light);
@@ -1037,26 +1767,34 @@
rx2 - 1,
cy2 - 1);
}
-
- /* FIXME: Drawing of shadows on non-working time should go here. */
-
- if (cx1 == rx1) {
- gdk_draw_line (drawable,
- priv->frame_gc,
- rx1,
- cy1,
- rx1,
- cy2);
- }
-
- if (cx2 == rx2) {
- gdk_draw_line (drawable,
- priv->frame_gc,
- rx2,
- cy1,
- rx2,
- cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (i = 0 ; i < (is_vampire && !(!summary && priv->highlight) ? 2 : 1) ; ++i) {
+ if (i == 1) {
+ gnome_canvas_get_color (item->canvas, "red", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ gdk_gc_set_line_attributes (priv->frame_gc,
+ 0,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ }
+#endif
+ if (cx1 == rx1)
+ gdk_draw_line (drawable, priv->frame_gc,
+ cx1, cy1, cx1, cy2);
+ if (cx2 == rx2)
+ gdk_draw_line (drawable, priv->frame_gc,
+ cx2, cy1, cx2, cy2);
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ if (i == 1) {
+ gantt_row_setup_frame_gc (row, !summary && priv->highlight);
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+ }
}
+#endif
}
else if (type == MRP_TASK_TYPE_MILESTONE && !summary && rx1 <= rx2) {
points[0].x = cx1;
@@ -1250,7 +1988,8 @@
* it since it's a good optimization.
*/
else if (strcmp (pspec->name, "critical") != 0 &&
- strcmp (pspec->name, "percent-complete")) {
+ strcmp (pspec->name, "priority") != 0 &&
+ strcmp (pspec->name, "percent-complete")) {
return;
}
@@ -1361,10 +2100,12 @@
*x2 = priv->x + priv->width;
}
if (y1) {
- *y1 = priv->y + 0.15 * priv->height;
+ /* preMOP *y1 = priv->y + 0.15 * priv->height; */
+ *y1 = priv->y;
}
if (y2) {
- *y2 = priv->y + 0.70 * priv->height;
+ /* preMOP *y2 = priv->y + 0.70 * priv->height; */
+ *y2 = priv->y + priv->height;
}
}
@@ -1494,11 +2235,11 @@
#define IN_DRAG_DURATION_SPOT(x,y,right,top,height) \
((abs(x - (right)) <= 3) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+ (y > top + 0.25 * height) && (y < top + 0.75 * height))
#define IN_DRAG_RELATION_SPOT(x,y,right,top,height) \
((x <= right) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+ (y > top + 0.25 * height) && (y < top + 0.75 * height))
static gboolean
gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
@@ -1592,9 +2333,9 @@
priv->state = STATE_DRAG_DURATION;
wx1 = priv->x;
- wy1 = priv->y + 0.15 * priv->height;
+ wy1 = priv->y + 0.25 * priv->height;
wx2 = event->button.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + 0.75 * priv->height;
gnome_canvas_item_i2w (item, &wx1, &wy1);
gnome_canvas_item_i2w (item, &wx2, &wy2);
@@ -1621,7 +2362,6 @@
priv->y,
priv->height)) {
priv->state = STATE_DRAG_LINK;
-
if (drag_points == NULL) {
drag_points = gnome_canvas_points_new (2);
}
@@ -1817,7 +2557,7 @@
project = mrp_object_get_project (MRP_OBJECT (priv->task));
wx2 = event->motion.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + 0.75 * priv->height;
gnome_canvas_item_i2w (item, &wx2, &wy2);
--- orig/src/planner-gantt-view.c
+++ mod/src/planner-gantt-view.c
@@ -84,6 +84,8 @@
gpointer data);
static void gantt_view_highlight_critical_cb (GtkAction *action,
gpointer data);
+static void gantt_view_not_standard_days_cb (GtkAction *action,
+ gpointer data);
static void gantt_view_edit_columns_cb (GtkAction *action,
gpointer data);
static void gantt_view_update_row_height (PlannerGanttView *view);
@@ -175,10 +177,14 @@
static const GtkToggleActionEntry toggle_entries[] = {
{ "HighlightCriticalTasks", NULL, N_("_Highlight Critical Tasks"),
NULL, NULL,
- G_CALLBACK (gantt_view_highlight_critical_cb), FALSE }
+ G_CALLBACK (gantt_view_highlight_critical_cb), FALSE },
+ { "NotStandardDays", NULL, N_("_Not Standard Days"),
+ NULL, NULL,
+ G_CALLBACK (gantt_view_not_standard_days_cb), FALSE }
};
+
G_DEFINE_TYPE (PlannerGanttView, planner_gantt_view, PLANNER_TYPE_VIEW);
@@ -213,7 +219,7 @@
gantt_view_activate (PlannerView *view)
{
PlannerGanttViewPriv *priv;
- gboolean show_critical;
+ gboolean show_critical, show_nostd_days;
gchar *filename;
priv = PLANNER_GANTT_VIEW (view)->priv;
@@ -242,6 +248,9 @@
show_critical = planner_gantt_chart_get_highlight_critical_tasks (
PLANNER_GANTT_CHART (priv->gantt));
+ show_nostd_days = planner_gantt_chart_get_not_standard_days (
+ PLANNER_GANTT_CHART (priv->gantt));
+
planner_task_tree_set_highlight_critical (PLANNER_TASK_TREE (priv->tree),
show_critical);
@@ -249,6 +258,10 @@
GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "HighlightCriticalTasks")),
show_critical);
+ gtk_toggle_action_set_active (
+ GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "NotStandardDays")),
+ show_nostd_days);
+
gantt_view_selection_changed_cb (PLANNER_TASK_TREE (priv->tree),
PLANNER_GANTT_VIEW (view));
gantt_view_update_zoom_sensitivity (PLANNER_GANTT_VIEW (view));
@@ -828,6 +841,24 @@
}
static void
+gantt_view_not_standard_days_cb (GtkAction *action,
+ gpointer data)
+{
+ PlannerGanttView *view;
+ PlannerGanttViewPriv *priv;
+ gboolean state;
+
+ view = PLANNER_GANTT_VIEW (data);
+ priv = view->priv;
+
+ state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
+
+ planner_gantt_chart_set_not_standard_days (
+ PLANNER_GANTT_CHART (priv->gantt),
+ state);
+}
+
+static void
gantt_view_edit_columns_cb (GtkAction *action,
gpointer data)
{
--- orig/src/planner-task-tree.c
+++ mod/src/planner-task-tree.c
@@ -60,7 +60,7 @@
PlannerWindow *main_window;
gboolean highlight_critical;
-
+
/* Keep the dialogs here so that we can just raise the dialog if it's
* opened twice for the same task.
*/
@@ -2276,6 +2276,12 @@
switch (column) {
case COL_WBS:
cell = gtk_cell_renderer_text_new ();
+
+ /* NOTE: with ypad and yalign add space
+ to insert not working bands */
+ g_object_set (cell, "ypad", 6, NULL);
+ g_object_set (cell, "yalign", 0.5, NULL);
+
col = gtk_tree_view_column_new_with_attributes (title,
cell,
NULL);
@@ -3587,6 +3593,7 @@
return tree->priv->highlight_critical;
}
+
void
planner_task_tree_set_anchor (PlannerTaskTree *tree, GtkTreePath *anchor)
{
--- orig/src/planner-task-view.c
+++ mod/src/planner-task-view.c
@@ -96,6 +96,8 @@
gpointer data);
static void task_view_highlight_critical_cb (GtkAction *action,
gpointer data);
+static void task_view_not_standard_days_cb (GtkAction *action,
+ gpointer data);
static void task_view_edit_columns_cb (GtkAction *action,
gpointer data);
static void task_view_selection_changed_cb (PlannerTaskTree *tree,
@@ -156,10 +158,13 @@
static const GtkToggleActionEntry toggle_entries[] = {
{ "HighlightCriticalTasks", NULL, N_("_Highlight Critical Tasks"), NULL, NULL,
- G_CALLBACK (task_view_highlight_critical_cb), FALSE }
+ G_CALLBACK (task_view_highlight_critical_cb), FALSE },
+ { "NotStandardDays", NULL, N_("_Not Standard Days"), NULL, NULL,
+ G_CALLBACK (task_view_not_standard_days_cb), FALSE }
};
-#define CRITICAL_PATH_KEY "/views/task_view/highlight_critical_path"
+#define CRITICAL_PATH_KEY "/views/task_view/highlight_critical_path"
+#define NOSTDDAYS_PATH_KEY "/views/task_view/not_standard_days"
G_DEFINE_TYPE (PlannerTaskView, planner_task_view, PLANNER_TYPE_VIEW);
@@ -582,6 +587,20 @@
}
static void
+task_view_not_standard_days_cb (GtkAction *action,
+ gpointer data)
+{
+ PlannerTaskViewPriv *priv;
+ gboolean state;
+
+ priv = PLANNER_TASK_VIEW (data)->priv;
+
+ state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ planner_conf_set_bool (NOSTDDAYS_PATH_KEY, state, NULL);
+}
+
+static void
task_view_edit_columns_cb (GtkAction *action,
gpointer data)
{
* added files
--- /dev/null
+++ mod/{arch}/planner/planner--mop/planner--mop--0/nastasi alternativeoutput it--projects/patch-log/patch-1
@@ -0,0 +1,19 @@
+Revision: planner--mop--0--patch-1
+Archive: nastasi alternativeoutput it--projects
+Creator: Matteo Nastasi <nastasi alternativeoutput it>
+Date: sab feb 18 16:21:45 CET 2006
+Standard-date: 2006-02-18 15:21:45 GMT
+Modified-files: autogen.sh configure.in
+ data/planner.schemas.in data/ui/gantt-view.ui
+ libplanner/mrp-calendar.c libplanner/mrp-calendar.h
+ libplanner/mrp-task-manager.c libplanner/mrp-task.c
+ libplanner/mrp-task.h src/planner-gantt-chart.c
+ src/planner-gantt-chart.h src/planner-gantt-row.c
+ src/planner-gantt-view.c src/planner-task-tree.c
+ src/planner-task-view.c
+New-patches: nastasi alternativeoutput it--projects/planner--mop--0--patch-1
+Summary: not standard days and simple priority scheduling added
+Keywords:
+
+not standard days and simple priority scheduling added
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]