Merge lp:~phcteam/clinica-project/dnd into lp:clinica-project/trunk

Proposed by Leonardo Robol
Status: Merged
Approved by: Leonardo Robol
Approved revision: 322
Merged at revision: 299
Proposed branch: lp:~phcteam/clinica-project/dnd
Merge into: lp:clinica-project/trunk
Diff against target: 2117 lines (+1303/-123) (has conflicts)
24 files modified
clinica/Clinica.vala (+1/-1)
clinica/wscript (+0/-3)
libclinica/Calendar.vala (+45/-9)
libclinica/CalendarEventList.vala (+49/-0)
libclinica/CalendarToolbar.vala (+35/-8)
libclinica/CalendarView.vala (+13/-9)
libclinica/CalendarWindow.vala (+63/-0)
libclinica/DateHandler.vala (+0/-1)
libclinica/Day.vala (+172/-18)
libclinica/DoctorListStore.vala (+1/-1)
libclinica/Event.vala (+172/-0)
libclinica/EventEditor.vala (+224/-0)
libclinica/EventListStore.vala (+123/-0)
libclinica/PatientEditor.vala (+30/-15)
libclinica/PatientEntry.vala (+168/-0)
libclinica/PatientListView.vala (+7/-0)
libclinica/ResourceManager.vala (+110/-10)
libclinica/SqlDataType.vala (+43/-10)
libclinica/UserInterface.vala (+6/-1)
libclinica/Visit.vala (+17/-4)
libclinica/wscript (+2/-2)
ui/patient_editor.glade (+11/-25)
ui/window.glade (+1/-1)
wscript (+10/-5)
Text conflict in wscript
To merge this branch: bzr merge lp:~phcteam/clinica-project/dnd
Reviewer Review Type Date Requested Status
PHC Team Pending
Review via email: mp+78359@code.launchpad.net

Description of the change

Added basilare event support, with drag and dropping from patients.
Small cleanup even in the database upgrade.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'clinica/Clinica.vala'
2--- clinica/Clinica.vala 2011-09-22 19:27:52 +0000
3+++ clinica/Clinica.vala 2011-10-06 07:06:24 +0000
4@@ -60,6 +60,7 @@
5
6 /* Init resource manager and connect error function
7 * to a message display for the user */
8+ Gdk.threads_enter ();
9 var resources = new ResourceManager (args[0], Utils.show_error_message);
10
11 /* Init gettext translation system */
12@@ -83,7 +84,6 @@
13 var user_interface = new UserInterface (resources);
14
15 /* Actually start the application */
16- Gdk.threads_enter ();
17 user_interface.start ();
18 Gdk.threads_leave ();
19
20
21=== modified file 'clinica/wscript'
22--- clinica/wscript 2011-09-22 23:25:12 +0000
23+++ clinica/wscript 2011-10-06 07:06:24 +0000
24@@ -24,6 +24,3 @@
25
26 # Extra includes
27 prog.includes = [ '.', '../libclinica' ]
28-
29- # Enable threading
30- prog.threading = True
31
32=== modified file 'libclinica/Calendar.vala'
33--- libclinica/Calendar.vala 2011-09-22 19:27:52 +0000
34+++ libclinica/Calendar.vala 2011-10-06 07:06:24 +0000
35@@ -25,6 +25,7 @@
36
37 public DateHandler handler { get; private set; }
38 private CalendarView calendar_view;
39+ private ResourceManager resource_manager { get; set; }
40
41 internal Day[] days;
42
43@@ -35,12 +36,13 @@
44 }
45 }
46
47- public Calendar (CalendarView view) {
48+ public Calendar (ResourceManager resources, CalendarView view) {
49+ this.resource_manager = resources;
50 this.calendar_view = view;
51
52 handler = new DateHandler ();
53
54- // Gtk.Table properties
55+ /* Gtk.Table properties */
56 n_rows = 6;
57 n_columns = 7;
58 column_spacing = 0;
59@@ -57,10 +59,10 @@
60 }
61 update_month ();
62
63- // Signals and handlers
64+ /* Signals and handlers */
65 handler.changed.connect (update_month);
66
67- // Change today when it changes
68+ /* Change today when it changes */
69 var today = new DateTime.now_local ();
70 var tomorrow = today.add_full (0, 0, 1, -today.get_hour (), -today.get_minute (), -today.get_second ());
71 var difference = tomorrow.to_unix() - today.to_unix();
72@@ -83,6 +85,8 @@
73 return false;
74 });
75
76+ resource_manager.event_list_store.event_added.connect (on_event_added);
77+ resource_manager.event_list_store.event_removed.connect (on_event_removed);
78 realize.connect (() => set_date (today));
79 }
80
81@@ -91,15 +95,13 @@
82 }
83
84 public void set_date (DateTime date) {
85-
86 if (handler.current_month != date.get_month () || handler.current_year != date.get_year ())
87 handler.add_full_offset (date.get_month () - handler.current_month, date.get_year () - handler.current_year);
88
89 days[date_to_index (date.get_day_of_month ())].grab_focus ();
90 }
91
92- private void update_month () {
93-
94+ internal void update_month () {
95 var today = new DateTime.now_local ();
96 int month = handler.current_month;
97 int year = handler.current_year;
98@@ -107,6 +109,16 @@
99 var date = new DateTime.local (year, month, 1, 0, 0, 0).add_days (-days_to_prepend);
100
101 foreach (var day in days) {
102+ /* Fill events of the day */
103+ day.reset_events ();
104+ foreach (var visit in Visit.for_day (resource_manager, date)) {
105+ /* Display visits in the day */
106+ day.add_visit (visit);
107+ }
108+ foreach (var event in Event.for_day (resource_manager, date)) {
109+ day.add_event (event);
110+ }
111+
112 if (date.get_day_of_year () == today.get_day_of_year () && date.get_year () == today.get_year ()) {
113 day.name = "today";
114 day.can_focus = true;
115@@ -126,12 +138,36 @@
116 }
117 }
118
119-
120-
121 private int date_to_index (int day_of_month) {
122 return days_to_prepend + day_of_month - 1;
123 }
124
125+ /**
126+ * @brief Callback called when an event is pushed to the EventListStore
127+ *
128+ * It should find the day of the event, if present in the view, and
129+ * insert the events in it.
130+ */
131+ private void on_event_added (Event event) {
132+ DateTime event_date = event.date;
133+ if (event_date.get_month () != handler.current_month)
134+ return;
135+ if (event_date.get_year () != handler.current_year)
136+ return;
137+
138+ /* Otherwise add the event to the right */
139+ days[date_to_index (event_date.get_day_of_month ())].add_event (event);
140+ }
141+
142+ /**
143+ * @brief Callback called when an event is removed from the EventListStore
144+ *
145+ * It should find the day that contained the event and remove it from the
146+ * view.
147+ */
148+ private void on_event_removed (Event event) {
149+ }
150+
151 }
152
153 }
154
155=== added file 'libclinica/CalendarEventList.vala'
156--- libclinica/CalendarEventList.vala 1970-01-01 00:00:00 +0000
157+++ libclinica/CalendarEventList.vala 2011-10-06 07:06:24 +0000
158@@ -0,0 +1,49 @@
159+/*
160+ * This file is part of Clinica.
161+ *
162+ * Clinica is free software: you can redistribute it and/or modify
163+ * it under the terms of the GNU General Public License as published by
164+ * the Free Software Foundation, either version 3 of the License, or
165+ * (at your option) any later version.
166+ *
167+ * Clinica is distributed in the hope that it will be useful,
168+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
169+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
170+ * GNU General Public License for more details.
171+ *
172+ * You should have received a copy of the GNU General Public License
173+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
174+ *
175+ * Authors: Leonardo Robol <leo@robol.it>
176+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
177+ */
178+
179+ using Gtk;
180+
181+ namespace Clinica {
182+
183+ public class CalendarEventList : Alignment {
184+
185+ private ResourceManager resource_manager { get; private set; }
186+
187+ public CalendarEventList (ResourceManager resources) {
188+ resource_manager = resources;
189+
190+ /* Set the right padding, according to what is set in
191+ * the resource_manager */
192+ set_padding (resource_manager.PADDING, resource_manager.PADDING,
193+ resource_manager.PADDING, resource_manager.PADDING);
194+
195+ /* Create a header for the event list */
196+ var title = new Label ("");
197+ title.set_markup (_("<b>What's next:</b>"));
198+
199+ /* Pack all the widgets together */
200+ var box = new VBox (false, 0);
201+ box.pack_start (title, false);
202+ add (box);
203+
204+ set_size_request (250, -1);
205+ }
206+ }
207+ }
208
209=== modified file 'libclinica/CalendarToolbar.vala'
210--- libclinica/CalendarToolbar.vala 2011-09-22 19:27:52 +0000
211+++ libclinica/CalendarToolbar.vala 2011-10-06 07:06:24 +0000
212@@ -25,15 +25,30 @@
213
214 public class CalendarToolbar : Gtk.Toolbar {
215
216+ /**
217+ * @brief Switcher for the months
218+ */
219 internal DateSwitcher month_switcher;
220+
221+ /**
222+ * @brief Switcher for the years.
223+ */
224 internal DateSwitcher year_switcher;
225- private CalendarView calendar_view;
226-
227- public CalendarToolbar (CalendarView view) {
228- this.calendar_view = view;
229+
230+ internal Button add_event_button;
231+
232+ private ResourceManager resource_manager;
233+
234+ public CalendarToolbar (ResourceManager resources) {
235+ resource_manager = resources;
236
237 /* Get the look of Ubuntu and elementaries toolbars */
238 get_style_context ().add_class ("primary-toolbar");
239+
240+ add_event_button = new Button.from_stock (Stock.ADD);
241+ var add_item = new ToolItem ();
242+ add_item.add (add_event_button);
243+ add_event_button.clicked.connect (on_add_button_clicked);
244
245 /* Request a decent width for the month switcher so it's likely
246 * not to resize on month name change */
247@@ -45,22 +60,34 @@
248 var year_toolitem = new ToolItem ();
249 year_toolitem.add (year_switcher);
250
251+ /* The add button first */
252+ insert (add_item, 0);
253+
254 /* Insert a spacer before and after the month and
255 * year switcher so they don't end in a corner */
256 var left_spacer = new ToolItem ();
257 left_spacer.set_expand (true);
258- insert (left_spacer, 0);
259+ insert (left_spacer, 1);
260+ insert (month_toolitem, 2);
261
262- insert (month_toolitem, 1);
263 /* Even some margin between the two selectors */
264 month_toolitem.set_margin_right (10);
265- insert (year_toolitem, 2);
266+ insert (year_toolitem, 3);
267
268 /* The right spacer that keep our control buttons
269 * centered in the toolbar */
270 var right_spacer = new ToolItem ();
271 right_spacer.set_expand (true);
272- insert (right_spacer, 3);
273+ insert (right_spacer, 4);
274+ }
275+
276+ public void on_add_button_clicked (Button button) {
277+ var event_editor = new EventEditor (resource_manager);
278+ if (event_editor.run () == EventEditor.Response.SAVE) {
279+ event_editor.selected_event.save ();
280+ resource_manager.event_list_store.add_event (event_editor.selected_event);
281+ }
282+ event_editor.destroy ();
283 }
284 }
285 }
286
287=== modified file 'libclinica/CalendarView.vala'
288--- libclinica/CalendarView.vala 2011-09-22 19:27:52 +0000
289+++ libclinica/CalendarView.vala 2011-10-06 07:06:24 +0000
290@@ -61,11 +61,14 @@
291
292 public CalendarHeader header { get; private set; }
293 public Calendar calendar { get; private set; }
294- public CalendarToolbar toolbar { get; private set; }
295 public CssProvider style_context { get; private set; }
296+ public CalendarToolbar toolbar { get; set; }
297+ internal ResourceManager resource_manager { get; private set; }
298
299- public CalendarView () {
300+ public CalendarView (ResourceManager resources, CalendarToolbar toolbar) {
301 GLib.Object (spacing: 0, homogeneous: false);
302+ resource_manager = resources;
303+ this.toolbar = toolbar;
304
305 /* Create CssProvider */
306 style_context = new CssProvider ();
307@@ -76,11 +79,9 @@
308 }
309
310 /* Create elements of the calendar view */
311- toolbar = new CalendarToolbar (this);
312 header = new CalendarHeader (this);
313- calendar = new Calendar (this);
314+ calendar = new Calendar (resource_manager, this);
315
316- pack_start (toolbar, false, false, 0);
317 pack_start (header, false, false, 0);
318 pack_end (calendar, true, true, 0);
319
320@@ -103,10 +104,6 @@
321
322 var date = new DateTime.local (year, month, 1, 0, 0, 0).add_days (-calendar.days_to_prepend);
323
324- // Update switcher text
325- toolbar.month_switcher.text = calendar.handler.format ("%B");
326- toolbar.year_switcher.text = calendar.handler.format ("%Y");
327-
328 foreach (var day in calendar.days) {
329 if (date.get_day_of_year () == today.get_day_of_year () && date.get_year () == today.get_year ()) {
330 day.name = "today";
331@@ -125,6 +122,13 @@
332 day.date = date;
333 date = date.add_days (1);
334 }
335+
336+ /* Update events displayed in the calendar */
337+ calendar.update_month ();
338+
339+ /* Update switcher text */
340+ toolbar.month_switcher.text = calendar.handler.format ("%B");
341+ toolbar.year_switcher.text = calendar.handler.format ("%Y");
342 }
343
344 }
345
346=== added file 'libclinica/CalendarWindow.vala'
347--- libclinica/CalendarWindow.vala 1970-01-01 00:00:00 +0000
348+++ libclinica/CalendarWindow.vala 2011-10-06 07:06:24 +0000
349@@ -0,0 +1,63 @@
350+/*
351+ * This file is part of Clinica.
352+ *
353+ * Clinica is free software: you can redistribute it and/or modify
354+ * it under the terms of the GNU General Public License as published by
355+ * the Free Software Foundation, either version 3 of the License, or
356+ * (at your option) any later version.
357+ *
358+ * Clinica is distributed in the hope that it will be useful,
359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
361+ * GNU General Public License for more details.
362+ *
363+ * You should have received a copy of the GNU General Public License
364+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
365+ *
366+ * Authors: Leonardo Robol <leo@robol.it>
367+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
368+ */
369+
370+ using Gtk;
371+
372+ namespace Clinica {
373+
374+ public class CalendarWindow : Gtk.Window {
375+
376+ private ResourceManager resource_manager { get; set; }
377+ private CalendarView calendar_view { get; set; }
378+ private CalendarEventList event_widget { get; set; }
379+ public CalendarToolbar toolbar { get; private set; }
380+
381+ public CalendarWindow (ResourceManager resources) {
382+ GLib.Object (type: WindowType.TOPLEVEL);
383+ resource_manager = resources;
384+
385+ set_title (_("Clinica calendar"));
386+
387+ /* The Toolbar used to switch */
388+ toolbar = new CalendarToolbar (resource_manager);
389+
390+ /* Create the calendar view */
391+ calendar_view = new CalendarView (resource_manager, toolbar);
392+
393+ /* And the widget that display the events present in the calendar.
394+ * This is a label that does nothing for the moment being. */
395+ event_widget = new CalendarEventList (resource_manager);
396+
397+ /* Pack widgets in the box */
398+ var main_table = new Table (2, 2, false);
399+ main_table.attach (toolbar, 0, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND,
400+ AttachOptions.FILL, 0, 0);
401+ main_table.attach (calendar_view, 0, 1, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND,
402+ AttachOptions.EXPAND | AttachOptions.FILL, 0, 0);
403+ main_table.attach (event_widget, 1, 2, 1, 2, AttachOptions.FILL,
404+ AttachOptions.EXPAND | AttachOptions.FILL, 0, 0);
405+
406+ /* Create an alignment to set the right padding of the window */
407+ var alignment = new Alignment (0.5F, 0.5F, 1.0F, 1.0F);
408+ alignment.add (main_table);
409+ add (alignment);
410+ }
411+ }
412+ }
413
414=== modified file 'libclinica/DateHandler.vala'
415--- libclinica/DateHandler.vala 2011-09-22 19:27:52 +0000
416+++ libclinica/DateHandler.vala 2011-10-06 07:06:24 +0000
417@@ -54,7 +54,6 @@
418 }
419
420 public DateHandler () {
421-
422 date = new DateTime.now_local ();
423 }
424
425
426=== modified file 'libclinica/Day.vala'
427--- libclinica/Day.vala 2011-09-22 19:27:52 +0000
428+++ libclinica/Day.vala 2011-10-06 07:06:24 +0000
429@@ -32,48 +32,92 @@
430 private DrawingArea area;
431
432 public DateTime date { get; set; }
433- private CalendarView calendar_view;
434+ private CalendarView calendar_view { get; set; }
435+ private ResourceManager resource_manager { get; set; }
436+
437+ private double highlight_level = 0;
438+
439+ private GLib.List<Visit> visit_list;
440+ private GLib.List<Event> event_list;
441
442 public Day (CalendarView view) {
443 this.calendar_view = view;
444+ this.resource_manager = view.resource_manager;
445
446 /* vbox = new VBox (false, 0);
447 label = new Label (""); */
448 area = new DrawingArea ();
449
450- // EventBox Properties
451+ /* EventBox Properties */
452 can_focus = true;
453 set_visible_window (true);
454 events |= EventMask.BUTTON_PRESS_MASK;
455
456 get_style_context ().add_provider (calendar_view.style_context, 600);
457 get_style_context ().add_class ("cell");
458- set_size_request (70,70);
459-
460- /* label.halign = Align.END;
461- label.get_style_context ().add_provider (calendar_view.style_context, 600);
462- label.name = "date";
463- vbox.pack_start (label, false, false, 0); */
464-
465- /* vbox.margin_bottom = vbox.margin_top = vbox.margin_left = vbox.margin_right = 3; */
466+ set_size_request (90, 90);
467+
468 area.draw.connect (on_area_draw);
469 add (area);
470
471- // Signals and handlers
472+ /* Signals and handlers */
473 button_press_event.connect (on_button_press);
474 focus_in_event.connect (on_focus_in);
475 focus_out_event.connect (on_focus_out);
476 draw.connect (on_draw);
477
478- // notify["date"].connect (() => label.label = date.get_day_of_month ().to_string ());
479 notify["date"].connect (on_date_changed);
480+
481+ /* Drag and drop support */
482+ TargetEntry patient_target = { "PATIENT", 0, 1 };
483+ drag_dest_set (this, DestDefaults.ALL | DestDefaults.HIGHLIGHT ,
484+ { patient_target }, DragAction.COPY);
485+ drag_drop.connect (on_drag_drop);
486+ drag_motion.connect (on_drag_motion);
487+ drag_leave.connect ((context, time) => { highlight_level = 0.0; queue_draw (); });
488+ }
489+
490+ private bool on_drag_drop (Widget widget, Gdk.DragContext context, int x, int y, uint time)
491+ {
492+ var patient = resource_manager.dragging_patient;
493+ if (patient == null) {
494+ debug ("Not doing drag and drop since resource_manager.dragging_patient is null");
495+ return false;
496+ }
497+ debug ("You dropped patient: %s on day %s", patient.get_complete_name (),
498+ date.format ("%F"));
499+ drag_finish (context, true, false, time);
500+ resource_manager.dragging_patient = null;
501+
502+ var event_editor = new EventEditor.with_date (resource_manager, date);
503+ event_editor.select_patient (patient);
504+ if (event_editor.run () == EventEditor.Response.SAVE) {
505+ /* Save the event in the editor */
506+ event_editor.selected_event.save ();
507+ resource_manager.event_list_store.add_event (event_editor.selected_event);
508+ }
509+ event_editor.destroy ();
510+ return true;
511+ }
512+
513+ private bool on_drag_motion (Widget widget, Gdk.DragContext context, int x, int y, uint time) {
514+ int height = widget.get_allocated_height();
515+ int width = widget.get_allocated_width ();
516+ highlight_level = 16.0 * (1.0 * width - x) * x * y * (height - y) / (width*width) / (height * height);
517+ queue_draw ();
518+ return false;
519 }
520
521 private void on_date_changed () {
522-
523+ if (calendar_view.calendar == null)
524+ return;
525+ if (date.get_month () != calendar_view.calendar.handler.current_month)
526+ can_focus = false;
527 }
528
529 private bool on_area_draw (Widget w, Context ctx) {
530+ TextExtents extents;
531+
532 /* Get allocation */
533 var height = w.get_allocated_height ();
534 var width = w.get_allocated_width ();
535@@ -89,19 +133,83 @@
536 ctx.set_source_rgba (0.1, 0.1, 0.1, 0.2);
537 ctx.rectangle (0, 0, width, height);
538 ctx.fill ();
539+ } else {
540+ ctx.set_source_rgba (0.1, 0.1, 0.1, 0.07);
541+ ctx.rectangle (0, 0, width, height);
542+ ctx.fill ();
543 }
544
545+ /* Draw the background if dragging over this, red if it is
546+ * saturday or sunday, blue otherwise! */
547+ if (highlight_level != 0 && can_focus) {
548+ if (date.get_day_of_week () > 5) {
549+ ctx.set_source_rgba (0.5 + 0.5 * highlight_level, 0, 0, 0.2 + 0.5 * highlight_level);
550+ }
551+ else {
552+ ctx.set_source_rgba (0, 0, 0.5 * (1 + highlight_level), 0.2 + 0.5 * highlight_level);
553+ }
554+ ctx.rectangle (0, 0, width, height);
555+ ctx.fill ();
556+ }
557+
558 /* If we have the focus draw the light :) */
559 if (has_focus) {
560- ctx.set_source_rgba (0.1, 0.1, 1, 0.2);
561+ ctx.set_source_rgba (0.1 + 0.9 * highlight_level, 0.1, 1, 0.2);
562 ctx.rectangle (0, 0, width, height);
563 ctx.fill ();
564 }
565
566+ /* Draw another green layer if there are events on this day, we should
567+ * also render events in the calendar */
568+ var event_number = visit_list.length () + event_list.length ();
569+ if (can_focus && event_number > 0) {
570+
571+ /* Set the color of the day according to how much is busy */
572+ if (event_number < 2)
573+ ctx.set_source_rgba (0.2, 1.0, 0.2, 0.3);
574+ else if (event_number < 4)
575+ ctx.set_source_rgba (1.0, 0.55, 0.0, 0.3);
576+ else
577+ ctx.set_source_rgba (1.0, 0.2 , 0.2, 0.3);
578+
579+ ctx.rectangle (0, 0, width, height);
580+ ctx.fill ();
581+
582+ ctx.set_source_rgba (0.1, 0.1, 0.1, 0.7);
583+ ctx.set_font_size (12.0);
584+ double line_position = 12;
585+ double line_height = 15.0;
586+ Gee.LinkedList<int> displayed_patients_id = new Gee.LinkedList<int> ();
587+ ctx.rectangle (0, 0, width - 8, height - 8);
588+ ctx.clip ();
589+ foreach (var visit in visit_list) {
590+ if (visit.patient.get_id () in displayed_patients_id)
591+ continue;
592+ displayed_patients_id.add (visit.patient.get_id ());
593+ string text = visit.patient.get_complete_name ();;
594+ ctx.text_extents (text, out extents);
595+ ctx.move_to (8 - extents.x_bearing,
596+ line_position + line_height / 2 - extents.y_bearing);
597+ line_position += line_height;
598+ ctx.show_text (text);
599+ }
600+
601+ foreach (var event in event_list) {
602+ string text = event.title;
603+ ctx.text_extents (text, out extents);
604+ ctx.move_to (8 - extents.x_bearing,
605+ line_position + line_height / 2 - extents.y_bearing);
606+ line_position += line_height;
607+ ctx.show_text (text);
608+ }
609+
610+ /* Undo the clipping to make the whole day drawable */
611+ ctx.restore ();
612+ }
613+
614 /* Draw number with the date with the usual switch on can_focus
615- * to render properly hiddent date (of the past and future month). */
616+ * to render properly hidden date (of the past and future month). */
617 string date = date.get_day_of_month ().to_string ();
618- TextExtents extents;
619 ctx.set_font_size (12.0);
620 if (can_focus)
621 ctx.set_source_rgba (0.1, 0.1, 0.1, 0.7);
622@@ -143,14 +251,60 @@
623 cr.set_antialias (Antialias.NONE);
624 cr.stroke ();
625
626- // Draw inner highlight stroke
627+ cr.set_source_rgba (1.0, 1.0, 1.0, 0.2);
628 cr.rectangle (1.5, 1.5, size.width - 1.5, size.height - 1.5);
629- cr.set_source_rgba (1.0, 1.0, 1.0, 0.2);
630 cr.stroke ();
631
632 return false;
633 }
634
635+ /**
636+ * @brief Add a new visit for this day
637+ */
638+ public void add_visit (Visit visit) {
639+ visit_list.append (visit);
640+ area.queue_draw ();
641+ }
642+
643+ /**
644+ * @brief Remove a visit from the list
645+ */
646+ public void remove_visit (Visit visit) {
647+ foreach (var v in visit_list) {
648+ if (v.get_id () == visit.get_id ()) {
649+ visit_list.remove (v);
650+ area.queue_draw ();
651+ return;
652+ }
653+ }
654+ }
655+
656+ /**
657+ * @brief Add a new event for this day
658+ */
659+ public void add_event (Event event) {
660+ event_list.append (event);
661+ area.queue_draw ();
662+ }
663+
664+ /**
665+ * @brief Remove an event in the list.
666+ */
667+ public void remove_event (Event event) {
668+ foreach (var e in event_list) {
669+ if (e.get_id () == event.get_id ()) {
670+ event_list.remove (e);
671+ area.queue_draw ();
672+ return;
673+ }
674+ }
675+ }
676+
677+ public void reset_events () {
678+ event_list = new List<Event> ();
679+ visit_list = new List<Visit> ();
680+ }
681+
682 }
683
684 }
685
686=== modified file 'libclinica/DoctorListStore.vala'
687--- libclinica/DoctorListStore.vala 2011-09-22 19:27:52 +0000
688+++ libclinica/DoctorListStore.vala 2011-10-06 07:06:24 +0000
689@@ -33,7 +33,7 @@
690
691 public signal void error (string message);
692
693- private ResourceManager resource_manager;
694+ private ResourceManager resource_manager { get; set; }
695
696 public class DoctorListStore (ResourceManager resources) {
697 resource_manager = resources;
698
699=== added file 'libclinica/Event.vala'
700--- libclinica/Event.vala 1970-01-01 00:00:00 +0000
701+++ libclinica/Event.vala 2011-10-06 07:06:24 +0000
702@@ -0,0 +1,172 @@
703+/*
704+ * This file is part of Clinica.
705+ *
706+ * Clinica is free software: you can redistribute it and/or modify
707+ * it under the terms of the GNU General Public License as published by
708+ * the Free Software Foundation, either version 3 of the License, or
709+ * (at your option) any later version.
710+ *
711+ * Clinica is distributed in the hope that it will be useful,
712+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
713+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
714+ * GNU General Public License for more details.
715+ *
716+ * You should have received a copy of the GNU General Public License
717+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
718+ *
719+ * Authors: Leonardo Robol <leo@robol.it>
720+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
721+ */
722+
723+namespace Clinica {
724+
725+ public class EventIterator : SqlDataIterator {
726+
727+ private ResourceManager resource_manager { get; set; }
728+
729+ public EventIterator (ResourceManager resources) {
730+ /* Grab the resource manager and chain the SqlDataIterator constructor,
731+ * ordering by date in decreasing order. */
732+ base (resources.db, resources.events_table, "date", true);
733+ resource_manager = resources;
734+ }
735+
736+ public EventIterator.with_day (ResourceManager resources, DateTime date) {
737+ base.with_like (resources.db, resources.events_table, "date", true,
738+ "date BETWEEN '%s' AND '%s'".printf (SqlDataType.datetime_to_string (date),
739+ SqlDataType.datetime_to_string (date.add_days (1).add_minutes(-1))));
740+ resource_manager = resources;
741+ }
742+
743+ public new EventIterator iterator () {
744+ return this;
745+ }
746+
747+ public new Event get () {
748+ return new Event.with_id (resource_manager, base.get ());
749+ }
750+ }
751+
752+ public class Event : SqlDataType {
753+
754+ private ResourceManager resource_manager { get; set; }
755+
756+ /* Properties mapped to the database */
757+ public string title {
758+ get { return get_text ("title"); }
759+ set { set_text ("title", value); }
760+ }
761+
762+ public string description {
763+ get { return get_text ("description"); }
764+ set { set_text ("description", value); }
765+ }
766+
767+ public string venue {
768+ get { return get_text ("venue"); }
769+ set { set_text ("venue", value); }
770+ }
771+
772+ /**
773+ * @brief Patient associated to this event, if one exists,
774+ * or null otherwise
775+ */
776+ private Patient? _patient;
777+ public Patient? patient {
778+ get {
779+ int id = get_integer ("patient");
780+ if (id == 0) {
781+ return null;
782+ }
783+ else {
784+ _patient = new Patient.with_id (resource_manager, id);
785+ return _patient;
786+ }
787+ }
788+ set {
789+ if (value != null) {
790+ set_integer ("patient", value.get_id ());
791+ _patient = value;
792+ }
793+ else {
794+ set_integer ("patient", 0);
795+ }
796+ }
797+ }
798+
799+
800+ /**
801+ * @brief Visit associated to this event, if one exists,
802+ * or null otherwise
803+ */
804+ private Visit? _visit;
805+ public Visit? visit {
806+ get {
807+ int id = get_integer ("visit");
808+ if (id == 0) {
809+ return null;
810+ }
811+ else {
812+ _visit = new Visit.with_id (resource_manager, id);
813+ return _visit;
814+ }
815+ }
816+ set {
817+ if (value != null) {
818+ set_integer ("visit", value.get_id ());
819+ _visit = value;
820+ }
821+ else {
822+ set_integer ("visit", 0);
823+ }
824+ }
825+ }
826+
827+ /**
828+ * @brief Date associated to this event.
829+ */
830+ private DateTime _date;
831+ public DateTime date {
832+ get {
833+ _date = get_date ("date");
834+ return _date;
835+ }
836+ set {
837+ _date = value;
838+ set_date ("date", _date);
839+ }
840+ }
841+
842+ public Event (ResourceManager resources) {
843+ base (resources.db);
844+ resource_manager = resources;
845+ error.connect ((t,l) => resources.error_callback(t,l));
846+ table_name = resource_manager.events_table;
847+
848+ add_text_field ("title");
849+ add_text_field ("description");
850+ add_text_field ("venue");
851+ add_integer_field ("patient");
852+ add_integer_field ("visit");
853+ add_date_field ("date");
854+
855+ init_resources ();
856+
857+ visit = null;
858+ patient = null;
859+ }
860+
861+ public Event.with_id (ResourceManager resources, int id) {
862+ this (resources);
863+ load (id);
864+ }
865+
866+ public static new EventIterator all (ResourceManager resources) {
867+ return new EventIterator (resources);
868+ }
869+
870+ public static new EventIterator for_day (ResourceManager resources, DateTime date) {
871+ return new EventIterator.with_day (resources, date);
872+ }
873+ }
874+}
875
876=== added file 'libclinica/EventEditor.vala'
877--- libclinica/EventEditor.vala 1970-01-01 00:00:00 +0000
878+++ libclinica/EventEditor.vala 2011-10-06 07:06:24 +0000
879@@ -0,0 +1,224 @@
880+/*
881+ * This file is part of Clinica.
882+ *
883+ * Clinica is free software: you can redistribute it and/or modify
884+ * it under the terms of the GNU General Public License as published by
885+ * the Free Software Foundation, either version 3 of the License, or
886+ * (at your option) any later version.
887+ *
888+ * Clinica is distributed in the hope that it will be useful,
889+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
890+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
891+ * GNU General Public License for more details.
892+ *
893+ * You should have received a copy of the GNU General Public License
894+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
895+ *
896+ * Authors: Leonardo Robol <leo@robol.it>
897+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
898+ */
899+
900+ using Gtk;
901+
902+ namespace Clinica {
903+
904+ public class EventEditor : Dialog {
905+
906+ enum Response {
907+ CANCEL,
908+ SAVE,
909+ }
910+
911+ /**
912+ * @brief Resource Manager used to access clinica
913+ * resources.
914+ */
915+ private ResourceManager resource_manager { get; set; }
916+
917+ /**
918+ * @brief event that is being edited by the EventEditor
919+ */
920+ internal Event selected_event { get; private set; }
921+
922+ /**
923+ * @brief Entry for the title of the event.
924+ */
925+ private Entry title_entry;
926+
927+ /**
928+ * @brief Entry for the venue.
929+ */
930+ private Entry venue_entry;
931+
932+ /**
933+ * @brief Calendar used in the dialog to select the data of the event
934+ */
935+ private Gtk.Calendar calendar;
936+
937+ /**
938+ * @brief Multiline editor for the desription of the event
939+ */
940+ private TextView description_textview;
941+
942+ /**
943+ * @brief Boolean value that tells if the user has filled the buffer
944+ * of the description, or if it is left with its default hint.
945+ *
946+ * In the first case the description should be saved, in the latter ignored.
947+ */
948+ private bool description_inserted = false;
949+
950+ /**
951+ * @brief Entry used by the user to select the patient
952+ */
953+ private PatientEntry patient_entry;
954+
955+ public EventEditor (ResourceManager resources, Event? event = null) {
956+ resource_manager = resources;
957+
958+ /* If the event is null, let's create a new one, otherwise
959+ * store the event passed for editing. */
960+ if (event == null) {
961+ selected_event = new Event (resource_manager);
962+ set_title (_("Create a new event"));
963+ }
964+ else {
965+ selected_event = event;
966+ set_title (_("Editing event: %s").printf (event.title));
967+ }
968+
969+ /* Add Save and Cancel buttons */
970+ add_buttons (Stock.CANCEL, Response.CANCEL,
971+ Stock.SAVE, Response.SAVE);
972+
973+ /* A vertical box to contain all the widgets */
974+ var structure_box = new VBox (false, resource_manager.PADDING);
975+
976+ /* The header, with a picture representing an event and title
977+ * and venue. */
978+ var event_picture = new Image.from_file (resource_manager.get_image_file ("calendar.svg"));
979+ var header_box = new HBox (false, resource_manager.PADDING);
980+ header_box.pack_start (event_picture, false);
981+
982+ /* Create the entry for title of the event and venue */
983+ var title_label = new Label (_("Title"));
984+ var venue_label = new Label (_("Venue"));
985+
986+ title_entry = new Entry ();
987+ venue_entry = new Entry ();
988+
989+ /* Packing them near the image */
990+ var table = new Table (2, 2, false);
991+ table.attach (title_label, 0, 1, 0, 1, AttachOptions.FILL, AttachOptions.FILL,
992+ resource_manager.PADDING / 2, resource_manager.PADDING / 2);
993+ table.attach (venue_label, 0, 1, 1, 2, AttachOptions.FILL, AttachOptions.FILL,
994+ resource_manager.PADDING / 2, resource_manager.PADDING / 2);
995+ table.attach (title_entry, 1, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND,
996+ AttachOptions.FILL, resource_manager.PADDING / 2, resource_manager.PADDING / 2);
997+ table.attach (venue_entry, 1, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND,
998+ AttachOptions.FILL, resource_manager.PADDING / 2, resource_manager.PADDING / 2);
999+
1000+ header_box.pack_start (table);
1001+ structure_box.pack_start (header_box, false);
1002+
1003+ /* Box for calendar and description */
1004+ var cal_desc_box = new HBox (false, resource_manager.PADDING);
1005+
1006+ /* Create the calendar used to select the date */
1007+ calendar = new Gtk.Calendar ();
1008+ cal_desc_box.pack_start (calendar, false);
1009+
1010+ /* Create the field for the description */
1011+ description_textview = new TextView ();
1012+ var scroll_w = new ScrolledWindow (null, null);
1013+ scroll_w.add_with_viewport (description_textview);
1014+ scroll_w.set_shadow_type (ShadowType.ETCHED_OUT);
1015+ cal_desc_box.pack_start (scroll_w);
1016+ description_textview.get_buffer ().set_text (_("Insert the description here..."));
1017+
1018+ /* Make the description view gray until the user select it, then reset
1019+ * the text in the textview and let the user fill the description.
1020+ *
1021+ * FIXME: We are assuming here that the default backgroun color is black, and
1022+ * that's not always the case. I don't get why vala doesn't allow reset_color
1023+ * to be null that, following Gtk documentation, should reset the color to
1024+ * its default value.
1025+ */
1026+ Gdk.RGBA hint_color = Gdk.RGBA ();
1027+ hint_color.parse ("#bcbcbc");
1028+ description_textview.override_color (StateFlags.NORMAL, hint_color);
1029+ description_textview.focus_in_event.connect ((widget, event) => {
1030+ Gdk.RGBA reset_color = Gdk.RGBA ();
1031+ reset_color.parse ("#000000");
1032+ description_textview.override_color (StateFlags.NORMAL, reset_color);
1033+ description_textview.get_buffer ().set_text ("");
1034+ description_inserted = true;
1035+ return false;
1036+ });
1037+
1038+ structure_box.pack_start (cal_desc_box);
1039+
1040+ /* Adding entries to select the patient and the visit */
1041+ var patient_visit_box = new Table (2, 2, false);
1042+
1043+ var patient_label = new Label(_("Patient"));
1044+ patient_entry = new PatientEntry (resource_manager);
1045+ patient_visit_box.attach (patient_label, 0, 1, 0, 1, AttachOptions.FILL,
1046+ AttachOptions.FILL | AttachOptions.EXPAND, 0, 0);
1047+ patient_visit_box.attach (patient_entry, 1, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND,
1048+ AttachOptions.FILL | AttachOptions.EXPAND, 0, 0);
1049+ patient_entry.margin_left = resource_manager.PADDING;;
1050+ structure_box.pack_start (patient_visit_box);
1051+
1052+ /* Pack the table in the dialog, with some alignment */
1053+ var alignment = new Alignment (0.5F, 0.5F, 1.0F, 1.0F);
1054+ alignment.set_padding (resource_manager.PADDING, resource_manager.PADDING,
1055+ resource_manager.PADDING, resource_manager.PADDING);
1056+ alignment.add (structure_box);
1057+ (get_content_area () as Container).add (alignment);
1058+ alignment.show_all ();
1059+
1060+ set_size_request (520, -1);
1061+
1062+ response.connect (on_response);
1063+ }
1064+
1065+ /**
1066+ * @brief Create a new event editor with a preselected date in the calendar.
1067+ */
1068+ public EventEditor.with_date (ResourceManager resources, DateTime date) {
1069+ this (resources);
1070+ calendar.select_month (date.get_month () - 1, date.get_year ());
1071+ calendar.select_day (date.get_day_of_month ());
1072+ }
1073+
1074+ /**
1075+ * @brief Change selection to the given patient
1076+ */
1077+ public void select_patient (Patient patient) {
1078+ patient_entry.select_patient (patient);
1079+ }
1080+
1081+ private void on_response () {
1082+ selected_event.title = title_entry.get_text ();
1083+ selected_event.venue = venue_entry.get_text ();
1084+
1085+ TextIter start, end;
1086+ TextBuffer buffer = description_textview.get_buffer ();
1087+ buffer.get_start_iter (out start);
1088+ buffer.get_end_iter (out end);
1089+ if (description_inserted)
1090+ selected_event.description = buffer.get_text (start, end, false);
1091+ else
1092+ selected_event.description = "";
1093+
1094+ /* Select patient if is valid */
1095+ if (patient_entry.is_valid () && patient_entry.get_patient () != null) {
1096+ selected_event.patient = patient_entry.get_patient ();
1097+ }
1098+
1099+ selected_event.date = new DateTime.local (calendar.year, calendar.month + 1,
1100+ calendar.day, 0, 0, 0);
1101+ }
1102+ }
1103+ }
1104
1105=== added file 'libclinica/EventListStore.vala'
1106--- libclinica/EventListStore.vala 1970-01-01 00:00:00 +0000
1107+++ libclinica/EventListStore.vala 2011-10-06 07:06:24 +0000
1108@@ -0,0 +1,123 @@
1109+/*
1110+ * This file is part of Clinica.
1111+ *
1112+ * Clinica is free software: you can redistribute it and/or modify
1113+ * it under the terms of the GNU General Public License as published by
1114+ * the Free Software Foundation, either version 3 of the License, or
1115+ * (at your option) any later version.
1116+ *
1117+ * Clinica is distributed in the hope that it will be useful,
1118+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1119+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1120+ * GNU General Public License for more details.
1121+ *
1122+ * You should have received a copy of the GNU General Public License
1123+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
1124+ *
1125+ * Authors: Leonardo Robol <leo@robol.it>
1126+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
1127+ */
1128+
1129+ using Gtk;
1130+
1131+ namespace Clinica {
1132+
1133+ public class EventListStore : ListStore {
1134+
1135+ public signal void event_added (Event event);
1136+ public signal void event_removed (Event event);
1137+
1138+ /**
1139+ * @brief Fields present in the store, i.e. header of
1140+ * the columns.
1141+ */
1142+ enum Field {
1143+ EVENT,
1144+ TITLE,
1145+ DESCRIPTION,
1146+ VENUE,
1147+ PATIENT,
1148+ VISIT,
1149+ DATE,
1150+ }
1151+
1152+ /**
1153+ * @brief This signal is emitted if an error occur in the
1154+ * list_store
1155+ */
1156+ public signal void error (string message);
1157+
1158+ /**
1159+ * @brief ResourceManager associated to this clinica application
1160+ * that will be used to retrieve various informationa about the
1161+ * other components running
1162+ */
1163+ private ResourceManager resource_manager { get; set; }
1164+
1165+ public EventListStore (ResourceManager resources) {
1166+ resource_manager = resources;
1167+ error.connect ((widget, message) => resource_manager.error_callback (widget, message));
1168+
1169+ Type [] column_headers = { typeof (Event), typeof (string), typeof (string),
1170+ typeof (string), typeof (Patient?), typeof (Visit?), typeof (DateTime) };
1171+
1172+ set_column_types (column_headers);
1173+ GLib.Idle.add (load_events_from_db);
1174+ }
1175+
1176+ /**
1177+ * @brief Add an event to the liststore.
1178+ */
1179+ public void add_event (Event event) {
1180+ TreeIter iter;
1181+ append (out iter);
1182+
1183+ /* Set values in the treeview */
1184+ set_value (iter, Field.EVENT, event);
1185+ set_value (iter, Field.DATE, event.date);
1186+ set_value (iter, Field.DESCRIPTION, event.description);
1187+ set_value (iter, Field.PATIENT, event.patient);
1188+ set_value (iter, Field.TITLE, event.title);
1189+ set_value (iter, Field.VENUE, event.venue);
1190+ set_value (iter, Field.VISIT, event.visit);
1191+
1192+ /* Emit event_added to make calendars and other pieces of interface
1193+ * using events know that they must reload their dates */
1194+ event_added (event);
1195+ }
1196+
1197+ public void remove_event (Event event) {
1198+ TreeIter iter;
1199+ Value value;
1200+ if (!get_iter_first (out iter)) {
1201+ error (_("Events database seems corrupted. This is likely to be a bug in the application"));
1202+ }
1203+
1204+ do {
1205+ get_value (iter, Field.EVENT, out value);
1206+ if ((value as Event).get_id () == event.get_id ()) {
1207+ /* Delete this event from the liststore */
1208+ remove (iter);
1209+ event_removed (event);
1210+ return;
1211+ }
1212+ } while (iter_next (ref iter));
1213+
1214+ assert_not_reached ();
1215+ }
1216+
1217+ /**
1218+ * @brief Function to be schedule with GLib.Idle_add () when loading of
1219+ * the events from the db is needed at the start of the application.
1220+ *
1221+ * This function is now called by default from the constructor.
1222+ */
1223+ private bool load_events_from_db () {
1224+ foreach (var event in Event.all (resource_manager)) {
1225+ add_event (event);
1226+ }
1227+
1228+ return false;
1229+ }
1230+ }
1231+ }
1232
1233=== modified file 'libclinica/PatientEditor.vala'
1234--- libclinica/PatientEditor.vala 2011-09-22 19:27:52 +0000
1235+++ libclinica/PatientEditor.vala 2011-10-06 07:06:24 +0000
1236@@ -60,7 +60,7 @@
1237
1238 /* Set to a patient that is the existing object for the
1239 * one represented here. */
1240- private Patient? existing_patient = null;
1241+ private Patient? existing_patient { get; set; default = null; }
1242
1243 /* Dialog opened to select data of the new patient */
1244 public Dialog dialog;
1245@@ -88,6 +88,8 @@
1246 public Gdk.Color alert_color;
1247
1248 private ResourceManager resource_manager;
1249+
1250+ internal Patient created_patient;
1251
1252 public PatientEditor (ResourceManager resources) {
1253 resource_manager = resources;
1254@@ -102,6 +104,9 @@
1255
1256 /* Fill the dialog with the pieces from the gtk builder file */
1257 dialog = builder.get_object("patient_editor") as Dialog;
1258+
1259+ /* Prepare for drag and drop if the patient is changed */
1260+ notify["existing_patient"].connect (update_draggable_patient_status);
1261
1262 /* Load entries into local object */
1263 doctor_entry = builder.get_object ("doctor_entry") as Entry;
1264@@ -150,6 +155,16 @@
1265 extensions = setup_extension_set (resource_manager.plugin_engine);
1266 }
1267
1268+ private void update_draggable_patient_status () {
1269+ /* Enable drag and drop on the patient icon */
1270+ if (existing_patient == null)
1271+ return;
1272+ var patient_eventbox = builder.get_object ("patient_eventbox") as EventBox;
1273+ TargetEntry patient_target = { "PATIENT", 0, 1 };
1274+ Gtk.drag_source_set (patient_eventbox, Gdk.ModifierType.BUTTON1_MASK, { patient_target }, Gdk.DragAction.COPY);
1275+ patient_eventbox.drag_begin.connect ((widget, context) => resource_manager.dragging_patient = existing_patient);
1276+ }
1277+
1278 private void on_doctor_entry_changed (Editable editable) {
1279 Entry entry = (editable as Entry);
1280 string doc_name = entry.get_text ();
1281@@ -252,6 +267,7 @@
1282 // Load doctors and existing patient
1283 selected_doctor = p.doctor;
1284 existing_patient = p;
1285+ update_draggable_patient_status ();
1286 doctor_entry.set_text (p.doctor.get_complete_name ());
1287
1288 // Pre fill the fields in the interface
1289@@ -383,17 +399,16 @@
1290
1291 /* Save the new patient, creating a new one if this is a new patient, or
1292 * reusing the existing one if we are only modifying a patient. */
1293- Patient patient;
1294 if (existing_patient == null)
1295- patient = new Patient (resource_manager, selected_doctor);
1296+ created_patient = new Patient (resource_manager, selected_doctor);
1297 else
1298- patient = existing_patient;
1299+ created_patient = existing_patient;
1300
1301- patient.given_name = given_name_entry.get_text ();
1302- patient.surname = surname_entry.get_text ();
1303- patient.phone = phone_entry.get_text ();
1304- patient.identification_code = identification_code_entry.get_text ();
1305- patient.residence_address = residence_address_entry.get_text ();
1306+ created_patient.given_name = given_name_entry.get_text ();
1307+ created_patient.surname = surname_entry.get_text ();
1308+ created_patient.phone = phone_entry.get_text ();
1309+ created_patient.identification_code = identification_code_entry.get_text ();
1310+ created_patient.residence_address = residence_address_entry.get_text ();
1311
1312 /* Create new DateTime */
1313 int year = int.parse (year_entry.get_text ());
1314@@ -406,7 +421,7 @@
1315 (1 <= day) && (day <= 31))
1316 {
1317 t = new DateTime (new TimeZone.utc (), year, month, day, 0, 0, 0);
1318- patient.birth_date = t;
1319+ created_patient.birth_date = t;
1320 }
1321 else
1322 {
1323@@ -417,18 +432,18 @@
1324
1325 /* Set gender here */
1326 if (gender_combobox.get_active () == 0)
1327- patient.gender = Gender.MALE;
1328+ created_patient.gender = Gender.MALE;
1329 else
1330- patient.gender = Gender.FEMALE;
1331+ created_patient.gender = Gender.FEMALE;
1332
1333- patient.save ();
1334+ created_patient.save ();
1335
1336 // If this was an existing patient we need to reload it in the patient
1337 // list store, otherwise we can just add it
1338 if (existing_patient != null) {
1339- resource_manager.patient_list_store.reload_patient (patient);
1340+ resource_manager.patient_list_store.reload_patient (created_patient);
1341 } else {
1342- resource_manager.patient_list_store.add_patient (patient);
1343+ resource_manager.patient_list_store.add_patient (created_patient);
1344 }
1345
1346 return Response.SAVE;
1347
1348=== added file 'libclinica/PatientEntry.vala'
1349--- libclinica/PatientEntry.vala 1970-01-01 00:00:00 +0000
1350+++ libclinica/PatientEntry.vala 2011-10-06 07:06:24 +0000
1351@@ -0,0 +1,168 @@
1352+/*
1353+ * This file is part of Clinica.
1354+ *
1355+ * Clinica is free software: you can redistribute it and/or modify
1356+ * it under the terms of the GNU General Public License as published by
1357+ * the Free Software Foundation, either version 3 of the License, or
1358+ * (at your option) any later version.
1359+ *
1360+ * Clinica is distributed in the hope that it will be useful,
1361+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1362+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1363+ * GNU General Public License for more details.
1364+ *
1365+ * You should have received a copy of the GNU General Public License
1366+ * along with Clinica. If not, see <http://www.gnu.org/licenses/>.
1367+ *
1368+ * Authors: Leonardo Robol <leo@robol.it>
1369+ * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
1370+ */
1371+
1372+ using Gtk;
1373+
1374+ namespace Clinica {
1375+
1376+ /**
1377+ * @brief Extension of GtkEntry with autocompletion on patients
1378+ *
1379+ * The selected patient, or null, if there is no selected patient,
1380+ * can be retrieved git the get_patient () method.
1381+ */
1382+ public class PatientEntry : Entry {
1383+
1384+ public signal void selection_changed ();
1385+
1386+ enum PatientCompletionAction {
1387+ CREATE_NEW = 0,
1388+ }
1389+
1390+ /**
1391+ * @brief The reference to the resource manager
1392+ */
1393+ private ResourceManager resource_manager { get; set; }
1394+
1395+ /**
1396+ * @brief The reference to the selected patient
1397+ */
1398+ private Patient? selected_patient = null;
1399+
1400+ /**
1401+ * @brief Completion for the patients
1402+ */
1403+ private new EntryCompletion completion;
1404+
1405+ public PatientEntry (ResourceManager resources) {
1406+ resource_manager = resources;
1407+
1408+ /* Init the completion */
1409+ completion = new EntryCompletion ();
1410+ completion.set_model (resource_manager.patient_list_store);
1411+ completion.set_text_column (PatientListStore.Field.COMPLETE_NAME);
1412+ completion.set_match_func (completion_match_function);
1413+ completion.insert_action_text (PatientCompletionAction.CREATE_NEW, "Create a new patient");
1414+
1415+ /* Callback that stores the selected patient */
1416+ completion.match_selected.connect (on_match_selected);
1417+
1418+ /* Callback for action selected */
1419+ completion.action_activated.connect (on_action_activated);
1420+
1421+ /* Activate completion */
1422+ set_completion (completion);
1423+ changed.connect (on_changed);
1424+ }
1425+
1426+ /**
1427+ * Change selection to the given patient
1428+ */
1429+ public void select_patient (Patient patient) {
1430+ selected_patient = patient;
1431+ set_text (patient.get_complete_name ());
1432+ }
1433+
1434+ public Patient get_patient () {
1435+ return selected_patient;
1436+ }
1437+
1438+ /**
1439+ * @brief Return true if this entry has a valid selection.
1440+ */
1441+ public bool is_valid () {
1442+ /* If no patient is selected the entry should be empty */
1443+ if (selected_patient == null) {
1444+ if (get_text () != "")
1445+ return false;
1446+ else
1447+ return true;
1448+ }
1449+
1450+ return (get_text () == selected_patient.get_complete_name ());
1451+ }
1452+
1453+ /**
1454+ * @brief Callback function for the patient selection that matches the doctor
1455+ * if the key is a substring of its complete name.
1456+ */
1457+ private bool completion_match_function (EntryCompletion compl, string key, TreeIter iter) {
1458+ Value value;
1459+ resource_manager.patient_list_store.get_value(iter, 0, out value);
1460+ Patient pat = value as Patient;
1461+ if (pat == null)
1462+ return false;
1463+ return (key.up () in pat.get_complete_name ().up ());
1464+ }
1465+
1466+ /**
1467+ * @brief Callback called when the user select a patient
1468+ */
1469+ private bool on_match_selected (EntryCompletion compl, TreeModel model, TreeIter iter) {
1470+ /* Get doctor associated with the selected completion */
1471+ Value value;
1472+ model.get_value (iter, PatientListStore.Field.COMPLETE_NAME, out value);
1473+ set_text (value as string);
1474+ model.get_value (iter, PatientListStore.Field.PATIENT, out value);
1475+
1476+ /* Set selected doctor in this object to use it later */
1477+ selected_patient = value as Patient;
1478+
1479+ return true;
1480+ }
1481+
1482+ /**
1483+ * @brief Create a new doctor on the fly with the name specifed in the
1484+ * doctor_entry
1485+ */
1486+ private void on_action_activated (EntryCompletion editable, int action) {
1487+ if (action != PatientCompletionAction.CREATE_NEW)
1488+ return;
1489+
1490+ /* Create a new dialog precompiled with the user input until now */
1491+ string name = get_text ();
1492+ var dialog = new PatientEditor.with_name (resource_manager, Utils.capitalize (name));
1493+ if (dialog.run () == PatientEditor.Response.CANCEL) {
1494+ dialog.destroy ();
1495+ return;
1496+ }
1497+
1498+ /* Set the newly created doctor as selected doctor */
1499+ selected_patient = dialog.created_patient;
1500+ set_text (selected_patient.get_complete_name ());
1501+
1502+ /* Destroy the dialog */
1503+ dialog.destroy ();
1504+ }
1505+
1506+ private void on_changed (Editable editable) {
1507+ string patient_name = get_text ();
1508+
1509+ /* Replace action */
1510+ completion.delete_action (PatientCompletionAction.CREATE_NEW);
1511+ if (patient_name != "")
1512+ completion.insert_action_text (PatientCompletionAction.CREATE_NEW,
1513+ @"Create a new patient named $(Utils.capitalize (patient_name))");
1514+ else
1515+ completion.insert_action_text (PatientCompletionAction.CREATE_NEW,
1516+ @"Create a new patient");
1517+ }
1518+ }
1519+ }
1520
1521=== modified file 'libclinica/PatientListView.vala'
1522--- libclinica/PatientListView.vala 2011-09-22 19:27:52 +0000
1523+++ libclinica/PatientListView.vala 2011-10-06 07:06:24 +0000
1524@@ -87,6 +87,13 @@
1525
1526 /* Some styling, row in alternating colors */
1527 set_rules_hint (true);
1528+
1529+ /* Drag and drop support */
1530+ TargetEntry patient_target = { "PATIENT", 0, 1 };
1531+ enable_model_drag_source (Gdk.ModifierType.BUTTON1_MASK, { patient_target }, Gdk.DragAction.COPY);
1532+ drag_begin.connect ((context) => {
1533+ resource_manager.dragging_patient = get_selected_patient ();
1534+ });
1535 }
1536
1537 private void on_name_cell_edited (CellRenderer renderer, string path, string new_text) {
1538
1539=== modified file 'libclinica/ResourceManager.vala'
1540--- libclinica/ResourceManager.vala 2011-09-23 13:24:03 +0000
1541+++ libclinica/ResourceManager.vala 2011-10-06 07:06:24 +0000
1542@@ -23,7 +23,6 @@
1543 using Gtk;
1544
1545 namespace Clinica {
1546-
1547
1548 /**
1549 * @brief Type representing the callback for the error
1550@@ -38,6 +37,12 @@
1551 public class ResourceManager : GLib.Object {
1552
1553 /**
1554+ * @brief The padding the should be used in windows
1555+ * in Clinica.
1556+ */
1557+ public const int PADDING = 6;
1558+
1559+ /**
1560 * @brief Callback that manages errors
1561 * notification to the end user.
1562 */
1563@@ -61,6 +66,15 @@
1564 */
1565 public VisitListStore visit_list_store;
1566
1567+ /**
1568+ * @brief EventListStore that holds the list of
1569+ * the events scheduled in clinica.
1570+ */
1571+ public EventListStore event_list_store;
1572+
1573+ /**
1574+ * @brief Reference to a user interface
1575+ */
1576 public UserInterface user_interface;
1577
1578 /**
1579@@ -105,6 +119,13 @@
1580 internal GLib.List<unowned MedicineSearchEngine> medicine_search_engines;
1581
1582 /**
1583+ * @brief A pointer to the patient that is been dragged. Should
1584+ * be set on drag_begin by the treeview and reset to null by the
1585+ * drag destination handler.
1586+ */
1587+ internal Patient? dragging_patient = null;
1588+
1589+ /**
1590 * @brief Path to the UI files directory
1591 */
1592 private string ui_files_path;
1593@@ -114,13 +135,17 @@
1594
1595 private bool is_local = false;
1596
1597- public string doctor_table = "doctors";
1598- public string patient_table = "patients";
1599- public string visits_table = "visits";
1600+ public const string doctor_table = "doctors";
1601+ public const string patient_table = "patients";
1602+ public const string visits_table = "visits";
1603+ public const string events_table = "events";
1604
1605 /** SIGNALS **/
1606 public signal void medicine_search_engines_added (MedicineSearchEngine engine);
1607 public signal void medicine_search_engines_removed (MedicineSearchEngine engine);
1608+
1609+ private const string [] supported_db_versions = { "0.1", "0.2" };
1610+ private const string db_version = "0.2";
1611
1612 public ResourceManager (string program_name = "clinica", ErrorCallback? callback = null) {
1613 if (callback != null)
1614@@ -150,11 +175,11 @@
1615 * This may be used in future to perform one-time upgrade of the database */
1616 var version_db_file = Path.build_filename (local_config_directory,
1617 ".clinica_db_version");
1618-
1619+
1620 if (!FileUtils.test (version_db_file, FileTest.IS_REGULAR)) {
1621 /* Create the file with the version of the database */
1622 try {
1623- FileUtils.set_contents(version_db_file, "0.1");
1624+ FileUtils.set_contents(version_db_file, db_version);
1625 } catch (Error e) {
1626 error (_("Error creating some configuration files, check permission on %s".printf(version_db_file)));
1627 }
1628@@ -166,8 +191,36 @@
1629 } catch (Error e) {
1630 error (_("Error reading some configuration files, check permission on %s".printf(version_db_file)));
1631 }
1632- if ("0.1" != content) {
1633- error (_("Version of the database is not compatible"));
1634+
1635+ bool upgraded_correcty = true;
1636+ if (db_version != content) {
1637+ /* Ask the user if he really wants to upgrade */
1638+ if (!ask_for_upgrade()) {
1639+ debug ("The user doesn't want to upgrade, exiting.");
1640+ Posix.exit (0);
1641+ }
1642+
1643+ upgraded_correcty = false;
1644+ /* Try to determine if the version of the local database is supported */
1645+ if (content in supported_db_versions) {
1646+ if (upgrade_database (content)) {
1647+ upgraded_correcty = true;
1648+ try {
1649+ FileUtils.set_contents (version_db_file, db_version);
1650+ } catch (GLib.Error e) {
1651+ error (_("Failure while settings new database version to %s").printf (db_version));
1652+ }
1653+ } else {
1654+ error (_("Failure while upgrading database"));
1655+ }
1656+ }
1657+ else
1658+ error (_("Version of the database is not compatible"));
1659+ }
1660+
1661+ if (!upgraded_correcty) {
1662+ debug ("Upgrade failed, exiting.");
1663+ Posix.exit (1);
1664 }
1665 }
1666
1667@@ -207,7 +260,7 @@
1668 * use local schema file */
1669 if (is_local) {
1670 debug ("Trying to compile my own gsettings schema");
1671- try {
1672+ try {
1673 Process.spawn_sync (null, {Environment.find_program_in_path ("glib-compile-schemas"),
1674 src_base},
1675 null, GLib.SpawnFlags.STDERR_TO_DEV_NULL, null);
1676@@ -217,7 +270,6 @@
1677 Environment.set_variable ("GSETTINGS_SCHEMA_DIR", src_base, true);
1678 Environment.set_variable ("GI_TYPELIB_PATH",
1679 Path.build_filename (src_base, "_build_", "libclinica"), true);
1680- debug (Environment.get_variable ("GI_TYPELIB_PATH"));
1681 }
1682
1683 /* Create configuration */
1684@@ -231,6 +283,25 @@
1685 load_plugins.begin ();
1686 }
1687
1688+ private bool ask_for_upgrade () {
1689+ var mb = new MessageDialog (null,
1690+ DialogFlags.DESTROY_WITH_PARENT |
1691+ DialogFlags.MODAL,
1692+ MessageType.QUESTION,
1693+ ButtonsType.YES_NO,
1694+ "%s", "Database upgrade");
1695+ mb.format_secondary_markup (_("This is a version of Clinica newer than the one that created the\npatients database installed on the system.\nUsing this version requires upgrading the database, and\n<b>the old version will not be able to use it anymore</b>.\nDo you wish to perform this one-time upgrade?\n"));
1696+ mb.set_title (_("Upgrade database"));
1697+ if (mb.run () == ResponseType.YES) {
1698+ mb.destroy ();
1699+ return true;
1700+ }
1701+ else {
1702+ mb.destroy ();
1703+ return false;
1704+ }
1705+ }
1706+
1707 /**
1708 * @brief Instantiate the plugin engine and load
1709 * all the plugins present in the directory
1710@@ -298,6 +369,34 @@
1711 }
1712 }
1713
1714+ private bool upgrade_database (string db_version) {
1715+ /* Try to open the database first */
1716+ if (!(Database.open (database_path, out db) == OK)) {
1717+ error (_("Error upgrading database, please check your installation"));
1718+ }
1719+
1720+ string sql;
1721+ Statement stmt;
1722+ int rc;
1723+
1724+ /* Performing upgrade from 0.1 */
1725+ if (db_version == "0.1") {
1726+ /* We need to create the new table for the events */
1727+ sql = "CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, title TEXT, description TEXT, venue TEXT, patient INTEGER, visit INTEGER, date TEXT);";
1728+ db.prepare (sql, -1, out stmt, null);
1729+ rc = stmt.step ();
1730+
1731+ if (rc != DONE) {
1732+ error (_("Error upgrading the database from version 0.1 to 0.2, sqlite exit code: %d".printf (rc)));
1733+ return false;
1734+ } else {
1735+ db_version = "0.2";
1736+ }
1737+ }
1738+
1739+ return true;
1740+ }
1741+
1742 /**
1743 * @brief Check that all the resources needed by Clinica
1744 * are actually available, and if they are not create them.
1745@@ -326,6 +425,7 @@
1746 doctor_list_store = new DoctorListStore (this);
1747 patient_list_store = new PatientListStore (this);
1748 visit_list_store = new VisitListStore (this);
1749+ event_list_store = new EventListStore (this);
1750 }
1751
1752
1753
1754=== modified file 'libclinica/SqlDataType.vala'
1755--- libclinica/SqlDataType.vala 2011-09-22 19:27:52 +0000
1756+++ libclinica/SqlDataType.vala 2011-10-06 07:06:24 +0000
1757@@ -40,9 +40,30 @@
1758 protected unowned Database db;
1759 protected Statement stmt;
1760
1761- public SqlDataIterator (Database db, string table_name) {
1762- this.db = db;
1763- db.prepare (@"SELECT ID FROM $(table_name);", -1, out stmt, null);
1764+ public SqlDataIterator (Database db, string table_name, string? order_by = null, bool desc = false) {
1765+ this.db = db;
1766+ if (order_by == null)
1767+ db.prepare (@"SELECT ID FROM $(table_name);", -1, out stmt, null);
1768+ else {
1769+ if (desc)
1770+ db.prepare (@"SELECT ID FROM $(table_name) ORDER by $(order_by) DESC;", -1, out stmt, null);
1771+ else
1772+ db.prepare (@"SELECT ID FROM $(table_name) ORDER by $(order_by);", -1, out stmt, null);
1773+ }
1774+ }
1775+
1776+ public SqlDataIterator.with_like (Database db, string table_name, string? order_by = null,
1777+ bool desc = false, string where_stmt) {
1778+ this.db = db;
1779+
1780+ if (order_by == null)
1781+ db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt);", -1, out stmt, null);
1782+ else {
1783+ if (desc)
1784+ db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt) ORDER by $(order_by) DESC;", -1, out stmt, null);
1785+ else
1786+ db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt) ORDER by $(order_by);", -1, out stmt, null);
1787+ }
1788 }
1789
1790 public SqlDataIterator iterator () {
1791@@ -184,7 +205,10 @@
1792 return "";
1793 }
1794 SqlColumn col = columns.get (field);
1795- return col.v;
1796+ if (col.v != null)
1797+ return col.v;
1798+ else
1799+ return "";
1800 }
1801
1802 public unowned int get_integer (string field) {
1803@@ -230,7 +254,11 @@
1804 return;
1805 }
1806 SqlColumn col = columns.get (field);
1807- col.v = string.join(" ",
1808+ col.v = datetime_to_string (date);
1809+ }
1810+
1811+ public static string datetime_to_string (DateTime date) {
1812+ return string.join(" ",
1813 date.get_year ().to_string (),
1814 "%.2d".printf (date.get_month ()),
1815 "%.2d".printf (date.get_day_of_month()),
1816@@ -279,16 +307,21 @@
1817 sql += ") VALUES (";
1818
1819 foreach (Map.Entry<string, SqlColumn> e in columns.entries) {
1820- if (e.value.type == "TEXT")
1821- sql += @"$(quote(e.value.v)), ";
1822- else
1823- sql += @"$(e.value.v), ";
1824+ if (e.value.v != null) {
1825+ if (e.value.type == "TEXT")
1826+ sql += @"$(quote(e.value.v)), ";
1827+ else
1828+ sql += @"$(e.value.v), ";
1829+ }
1830+ else {
1831+ sql += ", ";
1832+ }
1833 }
1834
1835 sql = sql[0:-2]; sql += ");";
1836 db.prepare (sql, -1, out stmt, null);
1837 if (stmt.step () != DONE) {
1838- error (@"Error inserting values in the database $(table_name)");
1839+ error (@"Error inserting values in the database $(table_name)\n Error $(db.errcode()): $(db.errmsg ())");
1840 }
1841
1842 /* If we save with ID set to 0 then the ID will be autodetermined
1843
1844=== modified file 'libclinica/UserInterface.vala'
1845--- libclinica/UserInterface.vala 2011-09-22 19:27:52 +0000
1846+++ libclinica/UserInterface.vala 2011-10-06 07:06:24 +0000
1847@@ -45,6 +45,7 @@
1848
1849 /* Windows */
1850 private SettingsManager? settings_manager = null;
1851+ private CalendarWindow? calendar_window = null;
1852
1853 private extern Peas.ExtensionSet setup_extension_set (ResourceManager resources, Peas.Engine engine);
1854 internal Peas.ExtensionSet extension_set;
1855@@ -160,7 +161,11 @@
1856 */
1857 [CCode (instance_pos = -1)]
1858 public void show_calendar_window (GLib.Object? source = null) {
1859- debug ("Calendar is not available yet");
1860+ if (calendar_window == null) {
1861+ calendar_window = new CalendarWindow (resource_manager);
1862+ calendar_window.destroy.connect ((cw) => calendar_window = null);
1863+ }
1864+ calendar_window.show_all ();
1865 }
1866
1867 /* CALLBACKS */
1868
1869=== modified file 'libclinica/Visit.vala'
1870--- libclinica/Visit.vala 2011-09-22 19:27:52 +0000
1871+++ libclinica/Visit.vala 2011-10-06 07:06:24 +0000
1872@@ -29,11 +29,20 @@
1873 private ResourceManager resource_manager;
1874
1875 public VisitIterator (ResourceManager resources) {
1876- base (resources.db, resources.visits_table);
1877- resource_manager = resources;
1878- db.prepare (@"SELECT ID FROM $(resources.visits_table) ORDER by date DESC;", -1, out stmt, null);
1879- }
1880+ base (resources.db, resources.visits_table, "date", true);
1881+ resource_manager = resources;
1882+ }
1883+
1884+ public VisitIterator.with_day (ResourceManager resources, DateTime day) {
1885+ DateTime day_after = day.add_days (1).add_minutes (-1);
1886+ base.with_like (resources.db, resources.visits_table, "date", true,
1887+ "date BETWEEN '%s' AND '%s'".printf (SqlDataType.datetime_to_string (day),
1888+ SqlDataType.datetime_to_string (day_after)));
1889+ resource_manager = resources;
1890+ }
1891+
1892 public new VisitIterator iterator () { return this; }
1893+
1894 public new Visit get () {
1895 return new Visit.with_id (resource_manager, base.get ());
1896 }
1897@@ -149,6 +158,10 @@
1898 public static new VisitIterator all (ResourceManager resources) {
1899 return new VisitIterator (resources);
1900 }
1901+
1902+ public static new VisitIterator for_day (ResourceManager resources, DateTime date) {
1903+ return new VisitIterator.with_day (resources, date);
1904+ }
1905
1906 }
1907
1908
1909=== modified file 'libclinica/wscript'
1910--- libclinica/wscript 2011-09-25 09:49:30 +0000
1911+++ libclinica/wscript 2011-10-06 07:06:24 +0000
1912@@ -5,7 +5,7 @@
1913
1914 def build(bld):
1915 bld.add_group ("libclinica")
1916- prog = bld(features = 'c cshlib glib2')
1917+ prog = bld(features = 'c cshlib glib2', valaflags=[ "-g" ])
1918 bld.set_group ("libclinica")
1919
1920 # Symbolic name used to reference this object
1921@@ -26,7 +26,7 @@
1922 prog.uselib = 'GOBJECT PEAS GTK+ GEE SQLITE PEASGTK'
1923
1924 # Vala packages to use
1925- prog.packages = 'gtk+-3.0 Peas-1.0 PeasGtk-1.0 sqlite3 gee-1.0 config'
1926+ prog.packages = 'gtk+-3.0 Peas-1.0 PeasGtk-1.0 sqlite3 gee-1.0 config posix'
1927 prog.vapi = 'clinica-0.2'
1928
1929 # Extra vapi dirs
1930
1931=== modified file 'ui/patient_editor.glade'
1932--- ui/patient_editor.glade 2011-07-24 17:22:39 +0000
1933+++ ui/patient_editor.glade 2011-10-06 07:06:24 +0000
1934@@ -1,7 +1,6 @@
1935 <?xml version="1.0" encoding="UTF-8"?>
1936 <interface>
1937 <requires lib="gtk+" version="2.24"/>
1938- <!-- interface-naming-policy project-wide -->
1939 <object class="GtkListStore" id="gender_store">
1940 <columns>
1941 <!-- column-name gender -->
1942@@ -22,12 +21,12 @@
1943 <property name="title" translatable="yes">Create a new patient</property>
1944 <property name="type_hint">dialog</property>
1945 <child internal-child="vbox">
1946- <object class="GtkVBox" id="dialog-vbox1">
1947+ <object class="GtkBox" id="dialog-vbox1">
1948 <property name="visible">True</property>
1949 <property name="can_focus">False</property>
1950 <property name="spacing">2</property>
1951 <child internal-child="action_area">
1952- <object class="GtkHButtonBox" id="dialog-action_area1">
1953+ <object class="GtkButtonBox" id="dialog-action_area1">
1954 <property name="visible">True</property>
1955 <property name="can_focus">False</property>
1956 <property name="layout_style">end</property>
1957@@ -75,15 +74,20 @@
1958 <property name="can_focus">False</property>
1959 <property name="spacing">5</property>
1960 <child>
1961- <object class="GtkImage" id="image1">
1962+ <object class="GtkEventBox" id="patient_eventbox">
1963 <property name="visible">True</property>
1964 <property name="can_focus">False</property>
1965- <property name="pixbuf">icons/patient.svg</property>
1966+ <child>
1967+ <object class="GtkImage" id="patient_image">
1968+ <property name="visible">True</property>
1969+ <property name="can_focus">False</property>
1970+ <property name="pixbuf">icons/patient.svg</property>
1971+ </object>
1972+ </child>
1973 </object>
1974 <packing>
1975- <property name="expand">False</property>
1976+ <property name="expand">True</property>
1977 <property name="fill">True</property>
1978- <property name="padding">10</property>
1979 <property name="position">0</property>
1980 </packing>
1981 </child>
1982@@ -109,8 +113,6 @@
1983 <property name="invisible_char_set">True</property>
1984 <property name="primary_icon_activatable">False</property>
1985 <property name="secondary_icon_activatable">False</property>
1986- <property name="primary_icon_sensitive">True</property>
1987- <property name="secondary_icon_sensitive">True</property>
1988 <signal name="focus-out-event" handler="clinica_patient_editor_on_name_focus_out_event" swapped="no"/>
1989 </object>
1990 <packing>
1991@@ -128,8 +130,6 @@
1992 <property name="invisible_char_set">True</property>
1993 <property name="primary_icon_activatable">False</property>
1994 <property name="secondary_icon_activatable">False</property>
1995- <property name="primary_icon_sensitive">True</property>
1996- <property name="secondary_icon_sensitive">True</property>
1997 <signal name="focus-out-event" handler="clinica_patient_editor_on_surname_focus_out_event" swapped="no"/>
1998 </object>
1999 <packing>
2000@@ -221,8 +221,6 @@
2001 <property name="invisible_char_set">True</property>
2002 <property name="primary_icon_activatable">False</property>
2003 <property name="secondary_icon_activatable">False</property>
2004- <property name="primary_icon_sensitive">True</property>
2005- <property name="secondary_icon_sensitive">True</property>
2006 </object>
2007 <packing>
2008 <property name="expand">True</property>
2009@@ -253,8 +251,6 @@
2010 <property name="invisible_char_set">True</property>
2011 <property name="primary_icon_activatable">False</property>
2012 <property name="secondary_icon_activatable">False</property>
2013- <property name="primary_icon_sensitive">True</property>
2014- <property name="secondary_icon_sensitive">True</property>
2015 </object>
2016 <packing>
2017 <property name="expand">True</property>
2018@@ -285,8 +281,6 @@
2019 <property name="invisible_char_set">True</property>
2020 <property name="primary_icon_activatable">False</property>
2021 <property name="secondary_icon_activatable">False</property>
2022- <property name="primary_icon_sensitive">True</property>
2023- <property name="secondary_icon_sensitive">True</property>
2024 </object>
2025 <packing>
2026 <property name="expand">True</property>
2027@@ -308,8 +302,6 @@
2028 <property name="invisible_char_set">True</property>
2029 <property name="primary_icon_activatable">False</property>
2030 <property name="secondary_icon_activatable">False</property>
2031- <property name="primary_icon_sensitive">True</property>
2032- <property name="secondary_icon_sensitive">True</property>
2033 </object>
2034 <packing>
2035 <property name="left_attach">1</property>
2036@@ -354,8 +346,6 @@
2037 <property name="invisible_char_set">True</property>
2038 <property name="primary_icon_activatable">False</property>
2039 <property name="secondary_icon_activatable">False</property>
2040- <property name="primary_icon_sensitive">True</property>
2041- <property name="secondary_icon_sensitive">True</property>
2042 </object>
2043 <packing>
2044 <property name="left_attach">3</property>
2045@@ -385,8 +375,6 @@
2046 <property name="invisible_char_set">True</property>
2047 <property name="primary_icon_activatable">False</property>
2048 <property name="secondary_icon_activatable">False</property>
2049- <property name="primary_icon_sensitive">True</property>
2050- <property name="secondary_icon_sensitive">True</property>
2051 </object>
2052 <packing>
2053 <property name="left_attach">1</property>
2054@@ -403,8 +391,6 @@
2055 <property name="invisible_char_set">True</property>
2056 <property name="primary_icon_activatable">False</property>
2057 <property name="secondary_icon_activatable">False</property>
2058- <property name="primary_icon_sensitive">True</property>
2059- <property name="secondary_icon_sensitive">True</property>
2060 </object>
2061 <packing>
2062 <property name="left_attach">1</property>
2063
2064=== modified file 'ui/window.glade'
2065--- ui/window.glade 2011-09-27 21:50:27 +0000
2066+++ ui/window.glade 2011-10-06 07:06:24 +0000
2067@@ -26,7 +26,7 @@
2068 <property name="title" translatable="yes">Clinica</property>
2069 <property name="window_position">center</property>
2070 <property name="default_width">700</property>
2071- <property name="default_height">500</property>
2072+ <property name="default_height">400</property>
2073 <signal name="destroy" handler="clinica_user_interface_on_window_destroy" swapped="no"/>
2074 <child>
2075 <object class="GtkVBox" id="vbox1">
2076
2077=== modified file 'wscript'
2078--- wscript 2011-10-03 16:31:06 +0000
2079+++ wscript 2011-10-06 07:06:24 +0000
2080@@ -13,10 +13,6 @@
2081
2082 def options (opt):
2083 opt.load ('compiler_cc glib2 gnu_dirs')
2084- # opt.add_option ('--destdir', action='store', default='',
2085- # help = 'Install project in a different root',
2086- # 1;2802;0c dest = 'destdir')
2087-
2088
2089 def put_config_h_in (ctx, destination):
2090
2091@@ -56,11 +52,13 @@
2092 ctx.find_program ('glib-compile-schemas', var='GLIB_COMPILE_SCHEMAS')
2093 ctx.find_program ('g-ir-compiler', var = 'G_IR_COMPILER')
2094
2095+ ctx.env.append_value ('VALAFLAGS', '-g')
2096+
2097 put_config_h_in (ctx, "libclinica")
2098 put_config_h_in (ctx, "clinica")
2099 put_config_h_in (ctx, "plugins")
2100
2101- ctx.env.append_value ('CFLAGS', '-DHAVE_CONFIG_H -include config.h'.split ())
2102+ ctx.env.append_value ('CFLAGS', '-g -DHAVE_CONFIG_H -include config.h'.split ())
2103
2104 def build(bld):
2105 bld.add_subdirs('libclinica')
2106@@ -100,4 +98,11 @@
2107
2108
2109 def run(ctx):
2110+<<<<<<< TREE
2111 ctx.exec_command ("LD_LIBRARY_PATH=./_build_/libclinica GI_TYPELIB_PATH=./_build_/libclinica ./_build_/clinica/clinica")
2112+=======
2113+ ctx.exec_command ("LD_LIBRARY_PATH=./_build_/libclinica ./_build_/clinica/clinica")
2114+
2115+def debug (ctx):
2116+ ctx.exec_command ("LD_LIBRARY_PATH=./_build_/libclinica gdb --args ./_build_/clinica/clinica")
2117+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches

to all changes: