Merge lp:~leo.robol/clinica-project/data-provider into lp:clinica-project/trunk
- data-provider
- Merge into master
Proposed by
Leonardo Robol
Status: | Merged |
---|---|
Approved by: | Leonardo Robol |
Approved revision: | 425 |
Merged at revision: | 411 |
Proposed branch: | lp:~leo.robol/clinica-project/data-provider |
Merge into: | lp:clinica-project/trunk |
Diff against target: |
5837 lines (+2340/-1670) (has conflicts) 64 files modified
glade/clinica.xml (+1/-3) libclinica/Application.vala (+1/-1) libclinica/Builder.vala (+0/-1) libclinica/Calendar.vala (+16/-16) libclinica/CalendarEventList.vala (+6/-6) libclinica/CalendarToolbar.vala (+1/-2) libclinica/CalendarWindow.vala (+1/-1) libclinica/CoreActivatable.vala (+46/-0) libclinica/CoreActivatableExtensionSet.c (+43/-0) libclinica/DataProvider.vala (+241/-0) libclinica/DateTimePicker.vala (+5/-10) libclinica/Day.vala (+6/-7) libclinica/Doctor.vala (+30/-98) libclinica/DoctorEditor.vala (+6/-11) libclinica/DoctorListStore.vala (+40/-22) libclinica/DoctorListView.vala (+8/-18) libclinica/EmptyVisitIterator.vala (+30/-0) libclinica/Event.vala (+16/-135) libclinica/EventDetail.vala (+3/-5) libclinica/EventEditor.vala (+1/-1) libclinica/EventIterator.vala (+44/-0) libclinica/EventListStore.vala (+40/-20) libclinica/FileObject.vala (+3/-3) libclinica/FileStore.vala (+9/-10) libclinica/FindEntry.vala (+20/-0) libclinica/MedicineDetailDialog.vala (+19/-0) libclinica/MedicineSearchEngine.vala (+19/-0) libclinica/MedicineSearchPage.vala (+19/-0) libclinica/MedicineTreeView.vala (+19/-0) libclinica/Patient.vala (+34/-159) libclinica/PatientEditor.vala (+5/-11) libclinica/PatientEditorActivatable.vala (+19/-0) libclinica/PatientListStore.vala (+20/-52) libclinica/PatientListView.vala (+13/-10) libclinica/PluginEngine.vala (+19/-0) libclinica/ResourceManager.vala (+59/-228) libclinica/Service.vala (+4/-4) libclinica/SettingsManager.vala (+64/-0) libclinica/SqlDataType.vala (+0/-397) libclinica/SqliteDataProvider.vala (+754/-0) libclinica/SqliteDoctorIterator.vala (+45/-0) libclinica/SqlitePatientIterator.vala (+45/-0) libclinica/SqliteVisitIterator.vala (+44/-0) libclinica/UserInterface.vala (+3/-3) libclinica/UserInterfaceActivatable.vala (+19/-0) libclinica/Visit.vala (+31/-182) libclinica/VisitActions.vala (+1/-1) libclinica/VisitBrowser.vala (+7/-8) libclinica/VisitDetail.vala (+1/-2) libclinica/VisitFileManager.vala (+5/-5) libclinica/VisitListStore.vala (+17/-44) libclinica/VisitSchedulerDialog.vala (+4/-4) libclinica/VisitTab.vala (+9/-14) libclinica/VisitWindow.vala (+2/-2) org.phcteam.clinica.gschema.xml (+9/-0) plugins/AgenziaDelFarmaco.plugin (+2/-2) plugins/ClinicaAndroid.plugin (+6/-0) plugins/ClinicaAndroid.py (+130/-0) plugins/wscript (+16/-2) po/es.po (+24/-15) po/it.po (+21/-13) po/pt_BR.po (+203/-128) po/sr.po (+6/-7) po/tr.po (+6/-7) Text conflict in po/es.po Text conflict in po/it.po Text conflict in po/pt_BR.po |
To merge this branch: | bzr merge lp:~leo.robol/clinica-project/data-provider |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PHC Team | Pending | ||
Review via email: mp+94458@code.launchpad.net |
Commit message
Description of the change
Added abstraction of data provider.
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 'glade/clinica.xml' |
2 | --- glade/clinica.xml 2012-02-02 16:52:54 +0000 |
3 | +++ glade/clinica.xml 2012-02-23 21:39:18 +0000 |
4 | @@ -3,9 +3,7 @@ |
5 | |
6 | <glade-widget-classes> |
7 | <glade-widget-class name="ClinicaCalendarView" generic-name="clinica_calendar_view" title="Calendar View" /> |
8 | - <glade-widget-class name="ClinicaDateTimePicker" generic-name="clinica_date_time_picker" title="DateTime picker"> |
9 | - <post-create-function>clinica_date_time_picker_glade_init</post-create-function> |
10 | - </glade-widget-class> |
11 | + <glade-widget-class name="ClinicaDateTimePicker" generic-name="clinica_date_time_picker" title="DateTime picker" /> |
12 | <glade-widget-class name="ClinicaPatientEntry" generic-name="clinica_patient_entry" title="Patient Entry" /> |
13 | </glade-widget-classes> |
14 | |
15 | |
16 | === modified file 'libclinica/Application.vala' |
17 | --- libclinica/Application.vala 2012-01-26 17:41:05 +0000 |
18 | +++ libclinica/Application.vala 2012-02-23 21:39:18 +0000 |
19 | @@ -150,7 +150,7 @@ |
20 | Intl.bindtextdomain("clinica", null); |
21 | |
22 | /* Init resources */ |
23 | - resource_manager.initResources(); |
24 | +// resource_manager.initResources(); |
25 | } |
26 | |
27 | if (daemon_mode) { |
28 | |
29 | === modified file 'libclinica/Builder.vala' |
30 | --- libclinica/Builder.vala 2012-02-02 07:26:45 +0000 |
31 | +++ libclinica/Builder.vala 2012-02-23 21:39:18 +0000 |
32 | @@ -15,7 +15,6 @@ |
33 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
34 | * |
35 | * Authors: Leonardo Robol <leo@robol.it> |
36 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
37 | */ |
38 | |
39 | using Gtk; |
40 | |
41 | === modified file 'libclinica/Calendar.vala' |
42 | --- libclinica/Calendar.vala 2011-11-24 08:14:32 +0000 |
43 | +++ libclinica/Calendar.vala 2012-02-23 21:39:18 +0000 |
44 | @@ -85,10 +85,10 @@ |
45 | return false; |
46 | }); |
47 | |
48 | - resource_manager.event_list_store.event_added.connect (on_event_added); |
49 | - resource_manager.event_list_store.event_removed.connect (on_event_removed); |
50 | - resource_manager.visit_list_store.visit_added.connect (on_visit_added); |
51 | - resource_manager.visit_list_store.visit_removed.connect (on_visit_removed); |
52 | + resource_manager.data_provider.event_added.connect (on_event_added); |
53 | + resource_manager.data_provider.event_removed.connect (on_event_removed); |
54 | + resource_manager.data_provider.visit_added.connect (on_visit_added); |
55 | + resource_manager.data_provider.visit_removed.connect (on_visit_removed); |
56 | realize.connect (() => set_date (today)); |
57 | } |
58 | |
59 | @@ -113,11 +113,11 @@ |
60 | foreach (var day in days) { |
61 | /* Fill events of the day */ |
62 | day.reset_events (); |
63 | - foreach (var visit in Visit.for_day (resource_manager, date, false)) { |
64 | + foreach (var visit in resource_manager.data_provider.visits (null, date, date.add_days (1))) { |
65 | /* Display visits in the day */ |
66 | day.add_visit (visit); |
67 | } |
68 | - foreach (var event in Event.for_day (resource_manager, date, false)) { |
69 | + foreach (var event in resource_manager.data_provider.events (date, date.add_days (1))) { |
70 | day.add_event (event); |
71 | } |
72 | |
73 | @@ -158,15 +158,15 @@ |
74 | * It should find the day of the event, if present in the view, and |
75 | * insert the events in it. |
76 | */ |
77 | - private void on_event_added (int event_id) { |
78 | - update_month (); |
79 | - } |
80 | - |
81 | - private void on_visit_added (int visit_id) { |
82 | - update_month (); |
83 | - } |
84 | - |
85 | - private void on_visit_removed (int visit_id) { |
86 | + private void on_event_added (int64 event_id) { |
87 | + update_month (); |
88 | + } |
89 | + |
90 | + private void on_visit_added (int64 visit_id) { |
91 | + update_month (); |
92 | + } |
93 | + |
94 | + private void on_visit_removed (int64 visit_id) { |
95 | update_month (); |
96 | } |
97 | |
98 | @@ -176,7 +176,7 @@ |
99 | * It should find the day that contained the event and remove it from the |
100 | * view. |
101 | */ |
102 | - private void on_event_removed (int event_id) { |
103 | + private void on_event_removed (int64 event_id) { |
104 | update_month (); |
105 | } |
106 | |
107 | |
108 | === modified file 'libclinica/CalendarEventList.vala' |
109 | --- libclinica/CalendarEventList.vala 2012-02-02 07:26:45 +0000 |
110 | +++ libclinica/CalendarEventList.vala 2012-02-23 21:39:18 +0000 |
111 | @@ -45,10 +45,10 @@ |
112 | set_size_request (280, -1); |
113 | |
114 | /* Connect event added and or removed with the reload of the day */ |
115 | - resource_manager.event_list_store.event_added.connect ((event) => set_day (this.day)); |
116 | - resource_manager.event_list_store.event_removed.connect ((event) => set_day (this.day)); |
117 | - resource_manager.visit_list_store.visit_added.connect ((visit) => set_day (this.day)); |
118 | - resource_manager.visit_list_store.visit_removed.connect ((visit) => set_day (this.day)); |
119 | + resource_manager.data_provider.event_added.connect ((event) => set_day (this.day)); |
120 | + resource_manager.data_provider.event_removed.connect ((event) => set_day (this.day)); |
121 | + resource_manager.data_provider.visit_added.connect ((visit) => set_day (this.day)); |
122 | + resource_manager.data_provider.visit_removed.connect ((visit) => set_day (this.day)); |
123 | } |
124 | |
125 | public void set_day (DateTime date) { |
126 | @@ -75,7 +75,7 @@ |
127 | |
128 | /* Show all the events of the day */ |
129 | bool no_events = true; |
130 | - foreach (Event event in Event.for_day (resource_manager, date)) { |
131 | + foreach (Event event in resource_manager.data_provider.events (date, date.add_days (1))) { |
132 | no_events = false; |
133 | var event_box = new EventDetail (resource_manager, event); |
134 | box.pack_start (event_box, false, true); |
135 | @@ -109,7 +109,7 @@ |
136 | |
137 | /* And now the visits of the day */ |
138 | bool no_visits = true; |
139 | - foreach (Visit visit in Visit.for_day (resource_manager, date)) { |
140 | + foreach (Visit visit in resource_manager.data_provider.visits (null, date, date.add_days(1))) { |
141 | no_visits = false; |
142 | var visit_detail = new VisitDetail (resource_manager, visit); |
143 | box.pack_start (visit_detail, false, true); |
144 | |
145 | === modified file 'libclinica/CalendarToolbar.vala' |
146 | --- libclinica/CalendarToolbar.vala 2011-11-25 15:02:16 +0000 |
147 | +++ libclinica/CalendarToolbar.vala 2012-02-23 21:39:18 +0000 |
148 | @@ -94,8 +94,7 @@ |
149 | |
150 | event_editor.set_transient_for (resource_manager.user_interface.calendar_window); |
151 | if (event_editor.run () == EventEditor.Response.SAVE) { |
152 | - event_editor.selected_event.save (); |
153 | - resource_manager.event_list_store.add_event (event_editor.selected_event); |
154 | + resource_manager.data_provider.save_event (event_editor.selected_event); |
155 | } |
156 | event_editor.destroy (); |
157 | } |
158 | |
159 | === modified file 'libclinica/CalendarWindow.vala' |
160 | --- libclinica/CalendarWindow.vala 2011-11-27 23:17:27 +0000 |
161 | +++ libclinica/CalendarWindow.vala 2012-02-23 21:39:18 +0000 |
162 | @@ -27,7 +27,7 @@ |
163 | internal ResourceManager resource_manager { get; set; } |
164 | internal CalendarView calendar_view { get; set; } |
165 | internal CalendarEventList event_widget { get; set; } |
166 | - internal CalendarToolbar toolbar { get; private set; } |
167 | + internal CalendarToolbar toolbar { get; private set; } |
168 | |
169 | public CalendarWindow (ResourceManager resources) { |
170 | GLib.Object (type: WindowType.TOPLEVEL); |
171 | |
172 | === added file 'libclinica/CoreActivatable.vala' |
173 | --- libclinica/CoreActivatable.vala 1970-01-01 00:00:00 +0000 |
174 | +++ libclinica/CoreActivatable.vala 2012-02-23 21:39:18 +0000 |
175 | @@ -0,0 +1,46 @@ |
176 | +/* |
177 | + * This file is part of Clinica. |
178 | + * |
179 | + * Clinica is free software: you can redistribute it and/or modify |
180 | + * it under the terms of the GNU General Public License as published by |
181 | + * the Free Software Foundation, either version 3 of the License, or |
182 | + * (at your option) any later version. |
183 | + * |
184 | + * Clinica is distributed in the hope that it will be useful, |
185 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
186 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
187 | + * GNU General Public License for more details. |
188 | + * |
189 | + * You should have received a copy of the GNU General Public License |
190 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
191 | + * |
192 | + * Authors: Leonardo Robol <leo@robol.it> |
193 | + */ |
194 | + |
195 | + namespace Clinica { |
196 | + |
197 | + public interface CoreActivatable : Object { |
198 | + |
199 | + /** |
200 | + * @brief The ResourceManager used to interact with clinica. |
201 | + */ |
202 | + public abstract ResourceManager resource_manager { get; set; } |
203 | + |
204 | + /** |
205 | + * @brief Activate method that will be called when the extension |
206 | + * is loaded. Special hooking up to callbacks and similar can be |
207 | + * done here (registering as data_provider, for example). |
208 | + */ |
209 | + public abstract void activate (); |
210 | + |
211 | + /** |
212 | + * @brief Deactivation method. Here the extension should unplug itself |
213 | + * from the Clinica application. |
214 | + */ |
215 | + public abstract void deactivate (); |
216 | + |
217 | + public abstract void update_state (); |
218 | + |
219 | + } |
220 | + |
221 | +} |
222 | |
223 | === added file 'libclinica/CoreActivatableExtensionSet.c' |
224 | --- libclinica/CoreActivatableExtensionSet.c 1970-01-01 00:00:00 +0000 |
225 | +++ libclinica/CoreActivatableExtensionSet.c 2012-02-23 21:39:18 +0000 |
226 | @@ -0,0 +1,43 @@ |
227 | +#include <libpeas/peas.h> |
228 | +#include <clinica.h> |
229 | +#include <stdio.h> |
230 | + |
231 | +static void |
232 | +on_extension_added (PeasExtensionSet *set, |
233 | + PeasPluginInfo *info, |
234 | + ClinicaCoreActivatable *activatable) |
235 | +{ |
236 | + clinica_core_activatable_activate (activatable); |
237 | +} |
238 | + |
239 | +static void |
240 | +on_extension_removed (PeasExtensionSet *set, |
241 | + PeasPluginInfo *info, |
242 | + ClinicaCoreActivatable *activatable) |
243 | +{ |
244 | + clinica_core_activatable_deactivate (activatable); |
245 | +} |
246 | + |
247 | +PeasExtensionSet* |
248 | +clinica_resource_manager_setup_extension_set (ClinicaResourceManager *rm, |
249 | + PeasEngine *engine) |
250 | +{ |
251 | + PeasExtensionSet *set; |
252 | + |
253 | + set = peas_extension_set_new (engine, CLINICA_TYPE_CORE_ACTIVATABLE, |
254 | + "resource_manager", rm, NULL); |
255 | + |
256 | + g_signal_connect (set, "extension-added", |
257 | + G_CALLBACK (on_extension_added), NULL); |
258 | + g_signal_connect (set, "extension-removed", |
259 | + G_CALLBACK (on_extension_removed), NULL); |
260 | +#ifdef HAVE_PEAS_EXTENSION_SET_FOREACH |
261 | + peas_extension_set_foreach (set, |
262 | + (PeasExtensionSetForeachFunc) on_extension_added, |
263 | + NULL); |
264 | +#else |
265 | + peas_extension_set_call (set, "activate"); |
266 | +#endif |
267 | + |
268 | + return set; |
269 | +} |
270 | |
271 | === added file 'libclinica/DataProvider.vala' |
272 | --- libclinica/DataProvider.vala 1970-01-01 00:00:00 +0000 |
273 | +++ libclinica/DataProvider.vala 2012-02-23 21:39:18 +0000 |
274 | @@ -0,0 +1,241 @@ |
275 | +/* |
276 | + * This file is part of Clinica. |
277 | + * |
278 | + * Clinica is free software: you can redistribute it and/or modify |
279 | + * it under the terms of the GNU General Public License as published by |
280 | + * the Free Software Foundation, either version 3 of the License, or |
281 | + * (at your option) any later version. |
282 | + * |
283 | + * Clinica is distributed in the hope that it will be useful, |
284 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
285 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
286 | + * GNU General Public License for more details. |
287 | + * |
288 | + * You should have received a copy of the GNU General Public License |
289 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
290 | + * |
291 | + * Authors: Leonardo Robol <leo@robol.it> |
292 | + */ |
293 | + |
294 | + namespace Clinica { |
295 | + |
296 | + public interface VisitIterator : Object { |
297 | + public abstract Visit get (); |
298 | + public abstract bool next (); |
299 | + public VisitIterator iterator () { return this; } |
300 | + } |
301 | + |
302 | + public interface PatientIterator : Object { |
303 | + public abstract Patient get (); |
304 | + public abstract bool next (); |
305 | + public PatientIterator iterator () { return this; } |
306 | + } |
307 | + |
308 | + public interface DoctorIterator : Object { |
309 | + public abstract Doctor get (); |
310 | + public abstract bool next (); |
311 | + public DoctorIterator iterator () { return this; } |
312 | + } |
313 | + |
314 | + public interface EventIterator : Object { |
315 | + public abstract Event get (); |
316 | + public abstract bool next (); |
317 | + public EventIterator iterator () { return this; } |
318 | + } |
319 | + |
320 | + public interface DataProvider : Object { |
321 | + |
322 | + /** |
323 | + * @brief Get the name of the DataProvider object. This must be a unique |
324 | + * name since it will be used to identify it and to select the right |
325 | + * DataProvider on startup. |
326 | + */ |
327 | + public abstract string get_name (); |
328 | + |
329 | + /** |
330 | + * @brief Get the visit with the given id. |
331 | + */ |
332 | + public abstract Visit get_visit (int64 id); |
333 | + |
334 | + /** |
335 | + * @brief Save a Visit. If the ID associated is 0 |
336 | + * than a new ID will be created and will be returned. |
337 | + */ |
338 | + public abstract int64 save_visit (Visit visit); |
339 | + |
340 | + /** |
341 | + * @brief Remove a Visit from the database. This routine |
342 | + * will return 0 on success. |
343 | + */ |
344 | + public abstract int64 remove_visit (Visit visit); |
345 | + |
346 | + /** |
347 | + * @brief Emitted when a visit changes in the Database; this means |
348 | + * that all Visit object with this ID around must be invalidated and |
349 | + * reloaded. |
350 | + */ |
351 | + public signal void visit_changed (int64 id); |
352 | + |
353 | + /** |
354 | + * @brief Emitted when a visit is removed from the database. This means |
355 | + * that all the Visit with this id must be removed. Please note that you |
356 | + * can't call get_visit () with this ID since the visit has already been |
357 | + * removed. |
358 | + */ |
359 | + public signal void visit_removed (int64 id); |
360 | + |
361 | + /** |
362 | + * @brief Emitted when a new visit is added to the database. |
363 | + */ |
364 | + public signal void visit_added (int64 id); |
365 | + |
366 | + /** |
367 | + * @brief Iterate on all the visits |
368 | + * |
369 | + * @param patient If not null then pick up only the visits of the given patient. |
370 | + * @param start If not null pick up only visits from this starting date. |
371 | + * @param end If not null stop iterating on visits when this date is reached. |
372 | + */ |
373 | + public abstract VisitIterator visits (Patient? patient = null, DateTime? start = null, DateTime? end = null); |
374 | + |
375 | + /** |
376 | + * @brief Get the Patient with the given id. |
377 | + */ |
378 | + public abstract Patient get_patient (int64 id); |
379 | + |
380 | + /** |
381 | + * @brief Save a Patient. If the ID associated is 0 |
382 | + * than a new ID will be created and will be returned. |
383 | + */ |
384 | + public abstract int64 save_patient (Patient patient); |
385 | + |
386 | + /** |
387 | + * @brief Remove a Patient from the database. This routine |
388 | + * will return 0 on success. |
389 | + * |
390 | + * This routine must take care of removing all the patients |
391 | + * visits and deassociate all the events from this patient. |
392 | + */ |
393 | + public abstract int64 remove_patient (Patient patient); |
394 | + |
395 | + /** |
396 | + * @brief Emitted when a patient changes in the database; this means |
397 | + * that all Patient objects with this ID around must be invalidated and |
398 | + * reloaded. |
399 | + */ |
400 | + public signal void patient_changed (int64 id); |
401 | + |
402 | + /** |
403 | + * @brief Emitted when a patient is removed from the database. This means |
404 | + * that all the Patients with this id must be removed. Please note that you |
405 | + * can't call get_patient () with this ID since the patient has already been |
406 | + * removed. |
407 | + */ |
408 | + public signal void patient_removed (int64 id); |
409 | + |
410 | + /** |
411 | + * @brief Emitted when a new patient is added to the database. |
412 | + */ |
413 | + public signal void patient_added (int64 id); |
414 | + |
415 | + /** |
416 | + * @brief Iterate over all the patients in the database. |
417 | + * |
418 | + * @param doctor If doctor is not null iterate only on patients associated |
419 | + * on this doctor. |
420 | + */ |
421 | + public abstract PatientIterator patients (Doctor? doctor = null); |
422 | + |
423 | + /** |
424 | + * @brief Get the doctor associatied with the given id. |
425 | + */ |
426 | + public abstract Doctor get_doctor (int64 id); |
427 | + |
428 | + /** |
429 | + * @brief Save a Doctor. If the ID associated is 0 |
430 | + * than a new ID will be created and will be returned. |
431 | + */ |
432 | + public abstract int64 save_doctor (Doctor doctor); |
433 | + |
434 | + /** |
435 | + * @brief Remove a Doctor from the database. This routine |
436 | + * will return 0 on success. |
437 | + * |
438 | + * This routine must take care of deassociating of the |
439 | + * patients of this doctor from him/her. |
440 | + */ |
441 | + public abstract int64 remove_doctor (Doctor doctor); |
442 | + |
443 | + /** |
444 | + * @brief Emitted when a doctor changes in the database; this means |
445 | + * that all Doctor objects with this ID around must be invalidated and |
446 | + * reloaded. |
447 | + */ |
448 | + public signal void doctor_changed (int64 id); |
449 | + |
450 | + /** |
451 | + * @brief Emitted when a doctor is removed from the database. This means |
452 | + * that all the Doctor with this id must be removed. Please note that you |
453 | + * can't call get_doctor () with this ID since the doctor has already been |
454 | + * removed. |
455 | + */ |
456 | + public signal void doctor_removed (int64 id); |
457 | + |
458 | + /** |
459 | + * @brief Emitted when a new doctor is added to the database. |
460 | + */ |
461 | + public signal void doctor_added (int64 id); |
462 | + |
463 | + /** |
464 | + * @brief Iteratate over all the doctors in the database. |
465 | + */ |
466 | + public abstract DoctorIterator doctors (); |
467 | + |
468 | + /** |
469 | + * @brief Get the event associated to the given ID. |
470 | + */ |
471 | + public abstract Event get_event (int64 id); |
472 | + |
473 | + /** |
474 | + * @brief Save an Event. If the ID associated is 0 |
475 | + * than a new ID will be created and will be returned. |
476 | + */ |
477 | + public abstract int64 save_event (Event event); |
478 | + |
479 | + /** |
480 | + * @brief Remove the event from the database. |
481 | + */ |
482 | + public abstract int64 remove_event (Event event); |
483 | + |
484 | + /** |
485 | + * @brief Emitted when an event changes in the database; this means |
486 | + * that all Event objects with this ID around must be invalidated and |
487 | + * reloaded. |
488 | + */ |
489 | + public signal void event_changed (int64 id); |
490 | + |
491 | + /** |
492 | + * @brief Emitted when an event is removed from the database. This means |
493 | + * that all the Event with this id must be removed. Please note that you |
494 | + * can't call get_event () with this ID since the event has already been |
495 | + * removed. |
496 | + */ |
497 | + public signal void event_removed (int64 id); |
498 | + |
499 | + /** |
500 | + * @brief Emitted when a new event is added to the database. |
501 | + */ |
502 | + public signal void event_added (int64 id); |
503 | + |
504 | + /** |
505 | + * @brief Iterate over all the events in the database. |
506 | + * |
507 | + * @param from If from is not null then iterate only from events starting after |
508 | + * from. |
509 | + * @param to If to is not null then iterate only until events before to. |
510 | + */ |
511 | + public abstract EventIterator events (DateTime? from = null, DateTime? to = null); |
512 | + |
513 | + } |
514 | + |
515 | + } |
516 | |
517 | === modified file 'libclinica/DateTimePicker.vala' |
518 | --- libclinica/DateTimePicker.vala 2012-02-02 17:48:45 +0000 |
519 | +++ libclinica/DateTimePicker.vala 2012-02-23 21:39:18 +0000 |
520 | @@ -20,27 +20,20 @@ |
521 | |
522 | namespace Clinica { |
523 | |
524 | - public class DateTimePicker : Gtk.EventBox, Buildable { |
525 | + public class DateTimePicker : Gtk.EventBox, Buildable, Gtk.Buildable { |
526 | |
527 | private Gtk.Calendar calendar; |
528 | |
529 | private Gtk.SpinButton hour_spinbutton; |
530 | private Gtk.SpinButton minute_spinbutton; |
531 | |
532 | - public static void glade_init (Object adaptor, DateTimePicker picker, int reason) { |
533 | - picker.create_interface (); |
534 | - } |
535 | - |
536 | public void setup (ResourceManager resources) { |
537 | - create_interface (); |
538 | - show_all (); |
539 | } |
540 | |
541 | public DateTimePicker () { |
542 | - create_interface (); |
543 | } |
544 | - |
545 | - public void create_interface () { |
546 | + |
547 | + construct { |
548 | var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 6); |
549 | |
550 | calendar = new Gtk.Calendar (); |
551 | @@ -69,6 +62,8 @@ |
552 | add (vbox); |
553 | |
554 | calendar.set_margin_bottom (6); |
555 | + |
556 | + show_all (); |
557 | } |
558 | |
559 | private void on_hour_spinbutton_changed (Gtk.Editable spin) { |
560 | |
561 | === modified file 'libclinica/Day.vala' |
562 | --- libclinica/Day.vala 2011-12-19 06:28:10 +0000 |
563 | +++ libclinica/Day.vala 2012-02-23 21:39:18 +0000 |
564 | @@ -94,8 +94,7 @@ |
565 | event_editor.set_transient_for (resource_manager.user_interface.calendar_window); |
566 | if (event_editor.run () == EventEditor.Response.SAVE) { |
567 | /* Save the event in the editor */ |
568 | - event_editor.selected_event.save (); |
569 | - resource_manager.event_list_store.add_event (event_editor.selected_event); |
570 | + resource_manager.data_provider.save_event (event_editor.selected_event); |
571 | } |
572 | event_editor.destroy (); |
573 | return true; |
574 | @@ -180,7 +179,7 @@ |
575 | ctx.set_font_size (10.0); |
576 | double line_position = 20; |
577 | double line_height = 13.0; |
578 | - Gee.LinkedList<int> displayed_patients_id = new Gee.LinkedList<int> (); |
579 | + Gee.LinkedList<int64?> displayed_patients_id = new Gee.LinkedList<int64?> (); |
580 | ctx.rectangle (0, 0, width - 4, height - 4); |
581 | ctx.clip (); |
582 | |
583 | @@ -208,9 +207,9 @@ |
584 | |
585 | /* Drawing performed visits */ |
586 | foreach (var visit in visit_list) { |
587 | - if (visit.patient.get_id () in displayed_patients_id) |
588 | + if (visit.patient.id in displayed_patients_id) |
589 | continue; |
590 | - displayed_patients_id.add (visit.patient.get_id ()); |
591 | + displayed_patients_id.add (visit.patient.id); |
592 | string text = "Visit: " + visit.patient.get_complete_name ();; |
593 | ctx.text_extents (text, out extents); |
594 | ctx.move_to (4 - extents.x_bearing, |
595 | @@ -291,7 +290,7 @@ |
596 | */ |
597 | public void remove_visit (Visit visit) { |
598 | foreach (var v in visit_list) { |
599 | - if (v.get_id () == visit.get_id ()) { |
600 | + if (v.id == visit.id) { |
601 | visit_list.remove (v); |
602 | area.queue_draw (); |
603 | return; |
604 | @@ -312,7 +311,7 @@ |
605 | */ |
606 | public void remove_event (Event event) { |
607 | foreach (var e in event_list) { |
608 | - if (e.get_id () == event.get_id ()) { |
609 | + if (e.id == event.id) { |
610 | event_list.remove (e); |
611 | area.queue_draw (); |
612 | return; |
613 | |
614 | === modified file 'libclinica/Doctor.vala' |
615 | --- libclinica/Doctor.vala 2011-09-22 19:27:52 +0000 |
616 | +++ libclinica/Doctor.vala 2012-02-23 21:39:18 +0000 |
617 | @@ -15,104 +15,36 @@ |
618 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
619 | * |
620 | * Authors: Leonardo Robol <leo@robol.it> |
621 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
622 | */ |
623 | - |
624 | - using Gee; |
625 | - using Sqlite; |
626 | - |
627 | - namespace Clinica { |
628 | - |
629 | - |
630 | - public class DoctorIterator : SqlDataIterator { |
631 | - |
632 | - private ResourceManager resource_manager; |
633 | - |
634 | - /** |
635 | - * @brief Iterator over all the Doctors present |
636 | - * in the database. |
637 | - */ |
638 | - public DoctorIterator (ResourceManager resources) { |
639 | - base (resources.db, resources.doctor_table); |
640 | - resource_manager = resources; |
641 | - } |
642 | - |
643 | - public new DoctorIterator iterator () { return this; } |
644 | - |
645 | - public new Doctor get () { |
646 | - return new Doctor.with_id (resource_manager, base.get ()); |
647 | - } |
648 | + |
649 | +namespace Clinica { |
650 | + |
651 | + public class Doctor : Object { |
652 | + |
653 | + public DataProvider? provider = null; |
654 | + |
655 | + public int64 id { get; set; default = 0; } |
656 | + |
657 | + public string given_name { get; set; } |
658 | + |
659 | + public string surname { get; set; } |
660 | + |
661 | + public string phone { get; set; } |
662 | + |
663 | + public string mobile { get; set; } |
664 | + |
665 | + public string get_complete_name () { |
666 | + return string.join (" ", this.given_name, this.surname); |
667 | + } |
668 | + |
669 | + public PatientIterator patients () { |
670 | + return provider.patients (this); |
671 | + } |
672 | + |
673 | + public bool has_patients () { |
674 | + return (patients ().next ()); |
675 | + } |
676 | + |
677 | } |
678 | - |
679 | - /** |
680 | - * @brief A doctor associated with some patients |
681 | - */ |
682 | - public class Doctor : SqlDataType { |
683 | - |
684 | - public new static DoctorIterator all (ResourceManager resources) { |
685 | - return new DoctorIterator (resources); |
686 | - } |
687 | - |
688 | - /* FIELDS */ |
689 | - public string given_name { |
690 | - get { return get_text ("given_name"); } |
691 | - set { set_text ("given_name", value); } |
692 | - } |
693 | - |
694 | - public string surname { |
695 | - get { return get_text ("surname"); } |
696 | - set { set_text ("surname", value); } |
697 | - } |
698 | - |
699 | - public string phone { |
700 | - get { return get_text ("phone"); } |
701 | - set { set_text ("phone", value); } |
702 | - } |
703 | - |
704 | - public string mobile { |
705 | - get { return get_text ("mobile"); } |
706 | - set { set_text ("mobile", value); } |
707 | - } |
708 | - |
709 | - private ResourceManager resource_manager; |
710 | - |
711 | - public Doctor (ResourceManager resources) { |
712 | - base (resources.db); |
713 | - resource_manager = resources; |
714 | - table_name = resources.doctor_table; |
715 | - error.connect ((t,l) => resources.error_callback(t,l)); |
716 | - |
717 | - add_text_field ("given_name"); |
718 | - add_text_field ("surname"); |
719 | - add_text_field ("phone"); |
720 | - add_text_field ("mobile"); |
721 | - |
722 | - /* Finishing connecting the object to the database */ |
723 | - init_resources (); |
724 | - } |
725 | - |
726 | - public Doctor.with_id (ResourceManager resources, int ID) { |
727 | - this (resources); |
728 | - load (ID); |
729 | - } |
730 | - |
731 | - public string get_complete_name () { |
732 | - return string.join(" ", given_name, surname); |
733 | - } |
734 | - |
735 | - public bool has_patients () { |
736 | - GLib.List<int> associated_ids = associated_ids(resource_manager.patient_table, "doctor"); |
737 | - return (associated_ids.length () != 0); |
738 | - } |
739 | - |
740 | - public new void remove () { |
741 | - if (has_patients ()) |
742 | - error (_("You cannot delete a doctor with associated patients. Delete his patients first.")); |
743 | - else |
744 | - base.remove (); |
745 | - } |
746 | - |
747 | - |
748 | |
749 | - } |
750 | - } |
751 | +} |
752 | |
753 | === modified file 'libclinica/DoctorEditor.vala' |
754 | --- libclinica/DoctorEditor.vala 2012-01-31 09:43:09 +0000 |
755 | +++ libclinica/DoctorEditor.vala 2012-02-23 21:39:18 +0000 |
756 | @@ -50,7 +50,7 @@ |
757 | resource_manager = resources; |
758 | error.connect ((me, message) => resource_manager.error_callback (me, message)); |
759 | |
760 | - builder = new Clinica.Builder.with_filename (resources, "doctor-editor.glade"); |
761 | + builder = new Clinica.Builder.with_filename (resources, "doctor_editor.glade"); |
762 | builder.load_into_dialog (this); |
763 | |
764 | /* Pack buttons and content */ |
765 | @@ -85,7 +85,7 @@ |
766 | mobile_entry.set_text (doctor.mobile); |
767 | |
768 | /* Set title of edit doctor dialog, space is important! */ |
769 | - set_title (_("Edit doctor named %s").printf(doctor.get_complete_name ())); |
770 | + set_title (_("Edit doctor named %s").printf (doctor.get_complete_name ())); |
771 | } |
772 | |
773 | /** |
774 | @@ -111,7 +111,7 @@ |
775 | if (base.run () == Response.SAVE) { |
776 | Doctor doc; |
777 | if (existing_doctor == null) |
778 | - doc = new Doctor (resource_manager); |
779 | + doc = new Doctor (); |
780 | else |
781 | doc = existing_doctor; |
782 | |
783 | @@ -120,14 +120,9 @@ |
784 | doc.surname = surname_entry.get_text (); |
785 | doc.phone = phone_entry.get_text (); |
786 | doc.mobile = mobile_entry.get_text (); |
787 | - doc.save (); |
788 | - |
789 | - if (existing_doctor == null) { |
790 | - created_doctor = doc; |
791 | - resource_manager.doctor_list_store.add_doctor (doc); |
792 | - } else { |
793 | - resource_manager.doctor_list_store.reload_doctor (doc); |
794 | - } |
795 | + int64 new_id = resource_manager.data_provider.save_doctor (doc); |
796 | + |
797 | + created_doctor = resource_manager.data_provider.get_doctor (new_id); |
798 | |
799 | return Response.SAVE; |
800 | } |
801 | |
802 | === modified file 'libclinica/DoctorListStore.vala' |
803 | --- libclinica/DoctorListStore.vala 2011-09-28 06:45:15 +0000 |
804 | +++ libclinica/DoctorListStore.vala 2012-02-23 21:39:18 +0000 |
805 | @@ -47,43 +47,61 @@ |
806 | |
807 | /* Asynchronous loading of doctors... */ |
808 | Idle.add (() => { |
809 | - foreach (Doctor doc in Doctor.all (resource_manager)) { |
810 | - add_doctor (doc); |
811 | + foreach (Doctor doc in resource_manager.data_provider.doctors ()) { |
812 | + add_doctor (doc.id); |
813 | } |
814 | |
815 | + /* Setup callbacks to add or remove doctors */ |
816 | + resource_manager.data_provider.doctor_added.connect ( |
817 | + (id) => add_doctor (id)); |
818 | + resource_manager.data_provider.doctor_changed.connect ( |
819 | + (id) => reload_doctor (id)); |
820 | + resource_manager.data_provider.doctor_removed.connect ( |
821 | + (id) => remove_doctor (id)); |
822 | + |
823 | /* We don't need to execute any more */ |
824 | return false; |
825 | }); |
826 | } |
827 | |
828 | - public void add_doctor (Doctor doc) { |
829 | - TreeIter it; |
830 | - append(out it); |
831 | - set_value (it, Field.DOCTOR, doc); |
832 | - set_value (it, Field.GIVEN_NAME, doc.given_name); |
833 | - set_value (it, Field.SURNAME, doc.surname); |
834 | - set_value (it, Field.COMPLETE_NAME, doc.get_complete_name ()); |
835 | - } |
836 | - |
837 | - public void reload_doctor (Doctor doc) { |
838 | - TreeIter it; |
839 | - Value doctor; |
840 | - int this_id = doc.get_id (); |
841 | + private TreeIter id_to_iter (int64 id) { |
842 | + TreeIter it; |
843 | + Value doctor; |
844 | if (!get_iter_first (out it)) { |
845 | error (_("Doctors database seems corrupted.")); |
846 | } |
847 | do { |
848 | get_value (it, Field.DOCTOR, out doctor); |
849 | - if ((doctor as Doctor).get_id () == this_id) { |
850 | - set_value (it, Field.DOCTOR, doc); |
851 | - set_value (it, Field.GIVEN_NAME, doc.given_name); |
852 | - set_value (it, Field.SURNAME, doc.surname); |
853 | - set_value (it, Field.COMPLETE_NAME, doc.get_complete_name ()); |
854 | - return; |
855 | + if ((doctor as Doctor).id == id) { |
856 | + return it; |
857 | } |
858 | } while (iter_next (ref it)); |
859 | |
860 | - assert_not_reached (); |
861 | + return it; |
862 | + } |
863 | + |
864 | + private void add_doctor (int64 id) { |
865 | + Doctor doc = resource_manager.data_provider.get_doctor (id); |
866 | + TreeIter it; |
867 | + append(out it); |
868 | + set_value (it, Field.DOCTOR, doc); |
869 | + set_value (it, Field.GIVEN_NAME, doc.given_name); |
870 | + set_value (it, Field.SURNAME, doc.surname); |
871 | + set_value (it, Field.COMPLETE_NAME, doc.get_complete_name ()); |
872 | + } |
873 | + |
874 | + private void reload_doctor (int64 id) { |
875 | + Doctor doc = resource_manager.data_provider.get_doctor (id); |
876 | + TreeIter it = id_to_iter (id); |
877 | + set_value (it, Field.DOCTOR, doc); |
878 | + set_value (it, Field.GIVEN_NAME, doc.given_name); |
879 | + set_value (it, Field.SURNAME, doc.surname); |
880 | + set_value (it, Field.COMPLETE_NAME, doc.get_complete_name ()); |
881 | + } |
882 | + |
883 | + private void remove_doctor (int64 id) { |
884 | + TreeIter iter = id_to_iter (id); |
885 | + remove (iter); |
886 | } |
887 | } |
888 | } |
889 | |
890 | === modified file 'libclinica/DoctorListView.vala' |
891 | --- libclinica/DoctorListView.vala 2012-01-31 08:10:13 +0000 |
892 | +++ libclinica/DoctorListView.vala 2012-02-23 21:39:18 +0000 |
893 | @@ -126,7 +126,7 @@ |
894 | * @brief Return an iter in the DoctorListStore associated |
895 | * with the current selection, or null |
896 | */ |
897 | - private TreeIter? get_selected_iter () { |
898 | + public TreeIter? get_selected_iter () { |
899 | TreeSelection selection = get_selection (); |
900 | TreeIter iter; |
901 | TreeModel model; |
902 | @@ -184,7 +184,7 @@ |
903 | MessageType.QUESTION, ButtonsType.YES_NO, "%s", ""); |
904 | warning_dialog.set_markup( |
905 | _("The doctor that you have selected for removal has some patients associated. \n") + |
906 | - _("It's not possible to remove it without removing all his patients.\n\n") + |
907 | + _("It's not possible to remove it without disassociating all his patients.\n\n") + |
908 | _("Do you really want to proceed?")); |
909 | warning_dialog.set_title (_("Doctor has associated patients")); |
910 | warning_dialog.set_transient_for (resource_manager.user_interface.window); |
911 | @@ -197,18 +197,14 @@ |
912 | warning_dialog.destroy (); |
913 | |
914 | /* Get List of the patients to remove and delete them */ |
915 | - List<TreeIter?> iters = resource_manager.patient_list_store.get_patients_of (doc); |
916 | - |
917 | - /* This will be used to retrieve data from liststores */ |
918 | - Value value; |
919 | + PatientIterator patients = doc.patients (); |
920 | |
921 | /* Create an array with the names oft he patients |
922 | * that will be deleted */ |
923 | string [] patient_names = {}; |
924 | |
925 | - foreach(TreeIter? it in iters) { |
926 | - resource_manager.patient_list_store.get_value (it, 0, out value); |
927 | - patient_names += " - <b>" + (value as Patient).get_complete_name() + "</b>"; |
928 | + foreach(Patient p in patients) { |
929 | + patient_names += " - <b>" + p.get_complete_name() + "</b>"; |
930 | } |
931 | |
932 | /* Warn another time the user that these patients will be deleted and |
933 | @@ -216,10 +212,10 @@ |
934 | warning_dialog = new MessageDialog(null, DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT, |
935 | MessageType.QUESTION, ButtonsType.YES_NO, "%s", ""); |
936 | warning_dialog.set_markup ( |
937 | - _("The following patients will be deleted by this action:\n") + |
938 | + _("The following patients will be disassociated from this doctor by this action:\n") + |
939 | string.joinv("\n", patient_names) + "\n" + |
940 | _("Do you really want to proceed?")); |
941 | - warning_dialog.set_title (_("Confirm deletion of patients")); |
942 | + warning_dialog.set_title (_("Confirm disassociation of patients")); |
943 | warning_dialog.set_transient_for (resource_manager.user_interface.window); |
944 | |
945 | if (warning_dialog.run () != ResponseType.YES) { |
946 | @@ -229,11 +225,6 @@ |
947 | |
948 | /* If we got here then the user is really sure, so delete the patients */ |
949 | warning_dialog.destroy (); |
950 | - foreach (TreeIter? it in iters) { |
951 | - resource_manager.patient_list_store.get_value (it, 0, out value); |
952 | - (value as Patient).remove (); |
953 | - resource_manager.patient_list_store.remove (it); |
954 | - } |
955 | } |
956 | } |
957 | else { |
958 | @@ -251,8 +242,7 @@ |
959 | } |
960 | |
961 | /* Proceed with the removal of the doctor */ |
962 | - doc.remove (); |
963 | - resource_manager.doctor_list_store.remove(get_selected_iter ()); |
964 | + resource_manager.data_provider.remove_doctor (doc); |
965 | } |
966 | |
967 | } |
968 | |
969 | === added file 'libclinica/EmptyVisitIterator.vala' |
970 | --- libclinica/EmptyVisitIterator.vala 1970-01-01 00:00:00 +0000 |
971 | +++ libclinica/EmptyVisitIterator.vala 2012-02-23 21:39:18 +0000 |
972 | @@ -0,0 +1,30 @@ |
973 | +/* |
974 | + * This file is part of Clinica. |
975 | + * |
976 | + * Clinica is free software: you can redistribute it and/or modify |
977 | + * it under the terms of the GNU General Public License as published by |
978 | + * the Free Software Foundation, either version 3 of the License, or |
979 | + * (at your option) any later version. |
980 | + * |
981 | + * Clinica is distributed in the hope that it will be useful, |
982 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
983 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
984 | + * GNU General Public License for more details. |
985 | + * |
986 | + * You should have received a copy of the GNU General Public License |
987 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
988 | + * |
989 | + * Authors: Leonardo Robol <leo@robol.it> |
990 | + */ |
991 | + |
992 | + namespace Clinica { |
993 | + |
994 | + public class EmptyVisitIterator : GLib.Object, VisitIterator { |
995 | + |
996 | + public VisitIterator iterator () { return this; } |
997 | + public bool next () { return false; } |
998 | + public new Visit get () { return new Visit (); } |
999 | + |
1000 | + } |
1001 | + |
1002 | + } |
1003 | |
1004 | === modified file 'libclinica/Event.vala' |
1005 | --- libclinica/Event.vala 2011-10-10 06:54:39 +0000 |
1006 | +++ libclinica/Event.vala 2012-02-23 21:39:18 +0000 |
1007 | @@ -15,158 +15,39 @@ |
1008 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1009 | * |
1010 | * Authors: Leonardo Robol <leo@robol.it> |
1011 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
1012 | */ |
1013 | - |
1014 | + |
1015 | namespace Clinica { |
1016 | |
1017 | - public class EventIterator : SqlDataIterator { |
1018 | - |
1019 | - private ResourceManager resource_manager { get; set; } |
1020 | - |
1021 | - public EventIterator (ResourceManager resources) { |
1022 | - /* Grab the resource manager and chain the SqlDataIterator constructor, |
1023 | - * ordering by date in decreasing order. */ |
1024 | - base (resources.db, resources.events_table, "date", false); |
1025 | - resource_manager = resources; |
1026 | - } |
1027 | - |
1028 | - public EventIterator.with_day (ResourceManager resources, DateTime date, bool descending = true) { |
1029 | - base.with_like (resources.db, resources.events_table, "date", descending, |
1030 | - "date BETWEEN '%s' AND '%s'".printf (SqlDataType.datetime_to_string (date), |
1031 | - SqlDataType.datetime_to_string (date.add_days (1).add_minutes(-1)))); |
1032 | - resource_manager = resources; |
1033 | - } |
1034 | - |
1035 | - public new EventIterator iterator () { |
1036 | - return this; |
1037 | - } |
1038 | - |
1039 | - public new Event get () { |
1040 | - return new Event.with_id (resource_manager, base.get ()); |
1041 | - } |
1042 | - } |
1043 | - |
1044 | - public class Event : SqlDataType { |
1045 | - |
1046 | - private ResourceManager resource_manager { get; set; } |
1047 | - |
1048 | - /* Properties mapped to the database */ |
1049 | - public string title { |
1050 | - get { return get_text ("title"); } |
1051 | - set { set_text ("title", value); } |
1052 | - } |
1053 | - |
1054 | - public string description { |
1055 | - get { return get_text ("description"); } |
1056 | - set { set_text ("description", value); } |
1057 | - } |
1058 | - |
1059 | - public string venue { |
1060 | - get { return get_text ("venue"); } |
1061 | - set { set_text ("venue", value); } |
1062 | - } |
1063 | + public class Event : Object { |
1064 | + |
1065 | + public DataProvider? provider = null; |
1066 | + |
1067 | + public int64 id { get; set; default = 0; } |
1068 | + |
1069 | + public string title { get; set; } |
1070 | + |
1071 | + public string description { get; set; } |
1072 | + |
1073 | + public string venue { get; set; } |
1074 | |
1075 | /** |
1076 | * @brief Patient associated to this event, if one exists, |
1077 | * or null otherwise |
1078 | */ |
1079 | - private Patient? _patient; |
1080 | - public Patient? patient { |
1081 | - get { |
1082 | - int id = get_integer ("patient"); |
1083 | - if (id == 0) { |
1084 | - return null; |
1085 | - } |
1086 | - else { |
1087 | - _patient = new Patient.with_id (resource_manager, id); |
1088 | - return _patient; |
1089 | - } |
1090 | - } |
1091 | - set { |
1092 | - if (value != null) { |
1093 | - set_integer ("patient", value.get_id ()); |
1094 | - _patient = value; |
1095 | - } |
1096 | - else { |
1097 | - set_integer ("patient", 0); |
1098 | - } |
1099 | - } |
1100 | - } |
1101 | - |
1102 | + public Patient? patient { get; set; } |
1103 | |
1104 | /** |
1105 | * @brief Visit associated to this event, if one exists, |
1106 | * or null otherwise |
1107 | */ |
1108 | - private Visit? _visit; |
1109 | - public Visit? visit { |
1110 | - get { |
1111 | - int id = get_integer ("visit"); |
1112 | - if (id == 0) { |
1113 | - return null; |
1114 | - } |
1115 | - else { |
1116 | - _visit = new Visit.with_id (resource_manager, id); |
1117 | - return _visit; |
1118 | - } |
1119 | - } |
1120 | - set { |
1121 | - if (value != null) { |
1122 | - set_integer ("visit", value.get_id ()); |
1123 | - _visit = value; |
1124 | - } |
1125 | - else { |
1126 | - set_integer ("visit", 0); |
1127 | - } |
1128 | - } |
1129 | - } |
1130 | + public Visit? visit { get; set; } |
1131 | |
1132 | /** |
1133 | * @brief Date associated to this event. |
1134 | */ |
1135 | - private DateTime _date; |
1136 | - public DateTime date { |
1137 | - get { |
1138 | - _date = get_date ("date"); |
1139 | - return _date; |
1140 | - } |
1141 | - set { |
1142 | - _date = value; |
1143 | - set_date ("date", _date); |
1144 | - } |
1145 | - } |
1146 | + public DateTime date { get; set; } |
1147 | |
1148 | - public Event (ResourceManager resources) { |
1149 | - base (resources.db); |
1150 | - resource_manager = resources; |
1151 | - error.connect ((t,l) => resources.error_callback(t,l)); |
1152 | - table_name = resource_manager.events_table; |
1153 | - |
1154 | - add_text_field ("title"); |
1155 | - add_text_field ("description"); |
1156 | - add_text_field ("venue"); |
1157 | - add_integer_field ("patient"); |
1158 | - add_integer_field ("visit"); |
1159 | - add_date_field ("date"); |
1160 | - |
1161 | - init_resources (); |
1162 | - |
1163 | - visit = null; |
1164 | - patient = null; |
1165 | - } |
1166 | - |
1167 | - public Event.with_id (ResourceManager resources, int id) { |
1168 | - this (resources); |
1169 | - load (id); |
1170 | - } |
1171 | - |
1172 | - public static new EventIterator all (ResourceManager resources) { |
1173 | - return new EventIterator (resources); |
1174 | - } |
1175 | - |
1176 | - public static new EventIterator for_day (ResourceManager resources, DateTime date, bool descending = false) { |
1177 | - return new EventIterator.with_day (resources, date, descending); |
1178 | - } |
1179 | } |
1180 | + |
1181 | } |
1182 | |
1183 | === modified file 'libclinica/EventDetail.vala' |
1184 | --- libclinica/EventDetail.vala 2012-02-02 08:38:15 +0000 |
1185 | +++ libclinica/EventDetail.vala 2012-02-23 21:39:18 +0000 |
1186 | @@ -55,6 +55,7 @@ |
1187 | title_label.set_alignment (0.0f, 0.5f); |
1188 | title_label.set_size_request (120, -1); |
1189 | title_label.set_line_wrap (true); |
1190 | + title_label.set_valign (Align.START); |
1191 | box.pack_start (title_label); |
1192 | |
1193 | /* Adding action buttons, such as edit and delete */ |
1194 | @@ -131,9 +132,7 @@ |
1195 | var event_editor = new EventEditor (resource_manager, associated_event); |
1196 | event_editor.set_transient_for (resource_manager.user_interface.calendar_window); |
1197 | if (event_editor.run () == EventEditor.Response.SAVE) { |
1198 | - event_editor.selected_event.save (); |
1199 | - resource_manager.event_list_store.remove_event (event_editor.selected_event); |
1200 | - resource_manager.event_list_store.add_event (event_editor.selected_event); |
1201 | + resource_manager.data_provider.save_event (event_editor.selected_event); |
1202 | } |
1203 | |
1204 | event_editor.destroy (); |
1205 | @@ -151,8 +150,7 @@ |
1206 | } |
1207 | question.destroy (); |
1208 | |
1209 | - associated_event.remove (); |
1210 | - resource_manager.event_list_store.remove_event (associated_event); |
1211 | + resource_manager.data_provider.remove_event (associated_event); |
1212 | } |
1213 | } |
1214 | } |
1215 | |
1216 | === modified file 'libclinica/EventEditor.vala' |
1217 | --- libclinica/EventEditor.vala 2011-11-12 15:14:56 +0000 |
1218 | +++ libclinica/EventEditor.vala 2012-02-23 21:39:18 +0000 |
1219 | @@ -89,7 +89,7 @@ |
1220 | /* If the event is null, let's create a new one, otherwise |
1221 | * store the event passed for editing. */ |
1222 | if (event == null) { |
1223 | - selected_event = new Event (resource_manager); |
1224 | + selected_event = new Event (); |
1225 | set_title (_("Create a new event")); |
1226 | } |
1227 | else { |
1228 | |
1229 | === added file 'libclinica/EventIterator.vala' |
1230 | --- libclinica/EventIterator.vala 1970-01-01 00:00:00 +0000 |
1231 | +++ libclinica/EventIterator.vala 2012-02-23 21:39:18 +0000 |
1232 | @@ -0,0 +1,44 @@ |
1233 | +/* |
1234 | + * This file is part of Clinica. |
1235 | + * |
1236 | + * Clinica is free software: you can redistribute it and/or modify |
1237 | + * it under the terms of the GNU General Public License as published by |
1238 | + * the Free Software Foundation, either version 3 of the License, or |
1239 | + * (at your option) any later version. |
1240 | + * |
1241 | + * Clinica is distributed in the hope that it will be useful, |
1242 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1243 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1244 | + * GNU General Public License for more details. |
1245 | + * |
1246 | + * You should have received a copy of the GNU General Public License |
1247 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1248 | + * |
1249 | + * Authors: Leonardo Robol <leo@robol.it> |
1250 | + */ |
1251 | + |
1252 | +using Sqlite; |
1253 | + |
1254 | +namespace Clinica { |
1255 | + |
1256 | + public class SqliteEventIterator : Object, EventIterator { |
1257 | + |
1258 | + private SqliteDataProvider provider; |
1259 | + private Statement stmt; |
1260 | + |
1261 | + public SqliteEventIterator (SqliteDataProvider provider, string clause = "") { |
1262 | + this.provider = provider; |
1263 | + provider.db.prepare ("SELECT id from %s %s ORDER by date DESC;".printf (provider.event_table, clause), |
1264 | + -1, out stmt); |
1265 | + } |
1266 | + |
1267 | + public bool next () { |
1268 | + return (stmt.step () == ROW); |
1269 | + } |
1270 | + |
1271 | + public new Event get () { |
1272 | + int id = stmt.column_int (0); |
1273 | + return provider.get_event (id); |
1274 | + } |
1275 | + } |
1276 | +} |
1277 | |
1278 | === modified file 'libclinica/EventListStore.vala' |
1279 | --- libclinica/EventListStore.vala 2011-11-26 11:40:13 +0000 |
1280 | +++ libclinica/EventListStore.vala 2012-02-23 21:39:18 +0000 |
1281 | @@ -24,9 +24,6 @@ |
1282 | |
1283 | public class EventListStore : ListStore { |
1284 | |
1285 | - public signal void event_added (int event_id); |
1286 | - public signal void event_removed (int event_id); |
1287 | - |
1288 | /** |
1289 | * @brief Fields present in the store, i.e. header of |
1290 | * the columns. |
1291 | @@ -63,12 +60,38 @@ |
1292 | |
1293 | set_column_types (column_headers); |
1294 | GLib.Idle.add (load_events_from_db); |
1295 | + |
1296 | + /* Setup callbacks to add or remove events */ |
1297 | + resource_manager.data_provider.event_added.connect ( |
1298 | + (id) => add_event (id)); |
1299 | + resource_manager.data_provider.event_changed.connect ( |
1300 | + (id) => reload_event (id)); |
1301 | + resource_manager.data_provider.event_removed.connect ( |
1302 | + (id) => remove_event (id)); |
1303 | + } |
1304 | + |
1305 | + /** |
1306 | + * @brief Reload information about an event |
1307 | + */ |
1308 | + private void reload_event (int64 id) { |
1309 | + var event = resource_manager.data_provider.get_event (id); |
1310 | + TreeIter iter = id_to_iter (id); |
1311 | + |
1312 | + /* Set values in the treeview */ |
1313 | + set_value (iter, Field.EVENT, event); |
1314 | + set_value (iter, Field.DATE, event.date); |
1315 | + set_value (iter, Field.DESCRIPTION, event.description); |
1316 | + set_value (iter, Field.PATIENT, event.patient); |
1317 | + set_value (iter, Field.TITLE, event.title); |
1318 | + set_value (iter, Field.VENUE, event.venue); |
1319 | + set_value (iter, Field.VISIT, event.visit); |
1320 | } |
1321 | |
1322 | /** |
1323 | * @brief Add an event to the liststore. |
1324 | */ |
1325 | - public void add_event (Event event) { |
1326 | + public void add_event (int64 id) { |
1327 | + var event = resource_manager.data_provider.get_event (id); |
1328 | TreeIter iter; |
1329 | append (out iter); |
1330 | |
1331 | @@ -80,31 +103,28 @@ |
1332 | set_value (iter, Field.TITLE, event.title); |
1333 | set_value (iter, Field.VENUE, event.venue); |
1334 | set_value (iter, Field.VISIT, event.visit); |
1335 | - |
1336 | - /* Emit event_added to make calendars and other pieces of interface |
1337 | - * using events know that they must reload their dates */ |
1338 | - event_added (event.get_id ()); |
1339 | - } |
1340 | - |
1341 | - public void remove_event (Event event) { |
1342 | + } |
1343 | + |
1344 | + public void remove_event (int64 id) { |
1345 | + remove (id_to_iter (id)); |
1346 | + } |
1347 | + |
1348 | + private TreeIter id_to_iter (int64 id) { |
1349 | TreeIter iter; |
1350 | Value value; |
1351 | + |
1352 | if (!get_iter_first (out iter)) { |
1353 | error (_("Events database seems corrupted. This is likely to be a bug in the application")); |
1354 | } |
1355 | |
1356 | do { |
1357 | get_value (iter, Field.EVENT, out value); |
1358 | - if ((value as Event).get_id () == event.get_id ()) { |
1359 | - /* Delete this event from the liststore */ |
1360 | - int event_id = event.get_id (); |
1361 | - remove (iter); |
1362 | - event_removed (event_id); |
1363 | - return; |
1364 | + if ((value as Event).id == id) { |
1365 | + return iter; |
1366 | } |
1367 | } while (iter_next (ref iter)); |
1368 | |
1369 | - assert_not_reached (); |
1370 | + return iter; |
1371 | } |
1372 | |
1373 | /** |
1374 | @@ -114,8 +134,8 @@ |
1375 | * This function is now called by default from the constructor. |
1376 | */ |
1377 | private bool load_events_from_db () { |
1378 | - foreach (var event in Event.all (resource_manager)) { |
1379 | - add_event (event); |
1380 | + foreach (var event in resource_manager.data_provider.events ()) { |
1381 | + add_event (event.id); |
1382 | } |
1383 | |
1384 | return false; |
1385 | |
1386 | === modified file 'libclinica/FileObject.vala' |
1387 | --- libclinica/FileObject.vala 2012-01-27 13:36:57 +0000 |
1388 | +++ libclinica/FileObject.vala 2012-02-23 21:39:18 +0000 |
1389 | @@ -38,13 +38,13 @@ |
1390 | /** |
1391 | * @brief The ID of the file store where this file is saved. |
1392 | */ |
1393 | - int id; |
1394 | + int64 id; |
1395 | |
1396 | /** |
1397 | * @brief Generate a FileObject starting from an existing file. |
1398 | * A copy of that filed will be stored in the FileStore specified. |
1399 | */ |
1400 | - public FileObject (FileStore store, int id, string filename, bool in_store = false) { |
1401 | + public FileObject (FileStore store, int64 id, string filename, bool in_store = false) { |
1402 | this.store = store; |
1403 | this.id = id; |
1404 | if (!in_store) |
1405 | @@ -57,7 +57,7 @@ |
1406 | * @brief Obtain the ID in the file store where the file can |
1407 | * be retrieved. |
1408 | */ |
1409 | - public int get_id () { |
1410 | + public int64 get_id () { |
1411 | return id; |
1412 | } |
1413 | |
1414 | |
1415 | === modified file 'libclinica/FileStore.vala' |
1416 | --- libclinica/FileStore.vala 2012-01-29 15:44:14 +0000 |
1417 | +++ libclinica/FileStore.vala 2012-02-23 21:39:18 +0000 |
1418 | @@ -32,7 +32,7 @@ |
1419 | * @brief Signal emitted when the FileStore changes. This invalidates |
1420 | * all the FileObjects around, that must be reloaded. |
1421 | */ |
1422 | - public signal void changed (int id); |
1423 | + public signal void changed (int64 id); |
1424 | |
1425 | /** |
1426 | * @brief Signal emitted when something goes wrong :) |
1427 | @@ -48,13 +48,13 @@ |
1428 | * @brief List of directories that are monitored by the |
1429 | * GioFileMonitor, so we don't monitor the twice. |
1430 | */ |
1431 | - private GLib.List<int> monitored_ids; |
1432 | + private GLib.List<int64?> monitored_ids; |
1433 | |
1434 | public FileStore (ResourceManager resources) { |
1435 | resource_manager = resources; |
1436 | error.connect ((t,l) => resource_manager.error_callback (t,l)); |
1437 | |
1438 | - monitored_ids = new GLib.List<int> (); |
1439 | + monitored_ids = new GLib.List<int64?> (); |
1440 | |
1441 | /* Setup some monitored folders */ |
1442 | try { |
1443 | @@ -63,7 +63,7 @@ |
1444 | |
1445 | FileInfo info; |
1446 | while ((info = enumerator.next_file ()) != null) { |
1447 | - int id = int.parse (info.get_name ()); |
1448 | + int64 id = int64.parse (info.get_name ()); |
1449 | if (id.to_string () == info.get_name ()) { |
1450 | setup_monitor (id); |
1451 | } |
1452 | @@ -78,7 +78,7 @@ |
1453 | * @brief Get the path where the files related to the given ID |
1454 | * are stored. |
1455 | */ |
1456 | - internal string get_id_path (int id) { |
1457 | + internal string get_id_path (int64 id) { |
1458 | string path = Path.build_filename (resource_manager.get_filestore_dir (), |
1459 | id.to_string ()); |
1460 | |
1461 | @@ -100,7 +100,7 @@ |
1462 | * @brief Setup a FileMonitor on the given directory ID, so we |
1463 | * may check for files created in there. |
1464 | */ |
1465 | - private void setup_monitor (int id) { |
1466 | + private void setup_monitor (int64 id) { |
1467 | if (monitored_ids.find (id) != null) { |
1468 | return; |
1469 | } |
1470 | @@ -129,7 +129,7 @@ |
1471 | * @brief Get the list of files associated to an ID. |
1472 | * This may even be an empty List. |
1473 | */ |
1474 | - public GLib.List<FileObject> get_files (int id) { |
1475 | + public GLib.List<FileObject> get_files (int64 id) { |
1476 | // Get the local data directory |
1477 | string this_id_path = get_id_path (id); |
1478 | File d = File.new_for_path (this_id_path); |
1479 | @@ -143,7 +143,6 @@ |
1480 | try { |
1481 | FileEnumerator enumerator = d.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME, FileQueryInfoFlags.NONE); |
1482 | |
1483 | - |
1484 | FileInfo info; |
1485 | while ((info = enumerator.next_file ()) != null) { |
1486 | results.append (new FileObject (this, id, |
1487 | @@ -159,7 +158,7 @@ |
1488 | /** |
1489 | * @brief Store a filed called filename in the FileStore. |
1490 | */ |
1491 | - public string store_file (int id, string filename) { |
1492 | + public string store_file (int64 id, string filename) { |
1493 | // Source file |
1494 | File source_file = File.new_for_path (filename); |
1495 | |
1496 | @@ -193,7 +192,7 @@ |
1497 | /** |
1498 | * @brief Remove a file from the store. |
1499 | */ |
1500 | - public void remove_file (int id, string filename) { |
1501 | + public void remove_file (int64 id, string filename) { |
1502 | FileUtils.remove (Path.build_filename (resource_manager.get_filestore_dir (), |
1503 | id.to_string (), filename)); |
1504 | |
1505 | |
1506 | === modified file 'libclinica/FindEntry.vala' |
1507 | --- libclinica/FindEntry.vala 2011-09-22 19:27:52 +0000 |
1508 | +++ libclinica/FindEntry.vala 2012-02-23 21:39:18 +0000 |
1509 | @@ -1,3 +1,23 @@ |
1510 | +/* |
1511 | + * This file is part of Clinica. |
1512 | + * |
1513 | + * Clinica is free software: you can redistribute it and/or modify |
1514 | + * it under the terms of the GNU General Public License as published by |
1515 | + * the Free Software Foundation, either version 3 of the License, or |
1516 | + * (at your option) any later version. |
1517 | + * |
1518 | + * Clinica is distributed in the hope that it will be useful, |
1519 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1520 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1521 | + * GNU General Public License for more details. |
1522 | + * |
1523 | + * You should have received a copy of the GNU General Public License |
1524 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1525 | + * |
1526 | + * Authors: Leonardo Robol <leo@robol.it> |
1527 | + * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
1528 | + */ |
1529 | + |
1530 | using Gtk; |
1531 | |
1532 | namespace Clinica { |
1533 | |
1534 | === modified file 'libclinica/MedicineDetailDialog.vala' |
1535 | --- libclinica/MedicineDetailDialog.vala 2011-12-19 06:28:10 +0000 |
1536 | +++ libclinica/MedicineDetailDialog.vala 2012-02-23 21:39:18 +0000 |
1537 | @@ -1,3 +1,22 @@ |
1538 | +/* |
1539 | + * This file is part of Clinica. |
1540 | + * |
1541 | + * Clinica is free software: you can redistribute it and/or modify |
1542 | + * it under the terms of the GNU General Public License as published by |
1543 | + * the Free Software Foundation, either version 3 of the License, or |
1544 | + * (at your option) any later version. |
1545 | + * |
1546 | + * Clinica is distributed in the hope that it will be useful, |
1547 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1548 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1549 | + * GNU General Public License for more details. |
1550 | + * |
1551 | + * You should have received a copy of the GNU General Public License |
1552 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1553 | + * |
1554 | + * Authors: Leonardo Robol <leo@robol.it> |
1555 | + */ |
1556 | + |
1557 | using Gtk; |
1558 | |
1559 | namespace Clinica { |
1560 | |
1561 | === modified file 'libclinica/MedicineSearchEngine.vala' |
1562 | --- libclinica/MedicineSearchEngine.vala 2011-12-09 17:28:05 +0000 |
1563 | +++ libclinica/MedicineSearchEngine.vala 2012-02-23 21:39:18 +0000 |
1564 | @@ -1,3 +1,22 @@ |
1565 | +/* |
1566 | + * This file is part of Clinica. |
1567 | + * |
1568 | + * Clinica is free software: you can redistribute it and/or modify |
1569 | + * it under the terms of the GNU General Public License as published by |
1570 | + * the Free Software Foundation, either version 3 of the License, or |
1571 | + * (at your option) any later version. |
1572 | + * |
1573 | + * Clinica is distributed in the hope that it will be useful, |
1574 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1575 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1576 | + * GNU General Public License for more details. |
1577 | + * |
1578 | + * You should have received a copy of the GNU General Public License |
1579 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1580 | + * |
1581 | + * Authors: Leonardo Robol <leo@robol.it> |
1582 | + */ |
1583 | + |
1584 | namespace Clinica { |
1585 | |
1586 | public interface MedicineSearchEngine : UserInterfaceActivatable { |
1587 | |
1588 | === modified file 'libclinica/MedicineSearchPage.vala' |
1589 | --- libclinica/MedicineSearchPage.vala 2012-01-29 10:39:56 +0000 |
1590 | +++ libclinica/MedicineSearchPage.vala 2012-02-23 21:39:18 +0000 |
1591 | @@ -1,3 +1,22 @@ |
1592 | +/* |
1593 | + * This file is part of Clinica. |
1594 | + * |
1595 | + * Clinica is free software: you can redistribute it and/or modify |
1596 | + * it under the terms of the GNU General Public License as published by |
1597 | + * the Free Software Foundation, either version 3 of the License, or |
1598 | + * (at your option) any later version. |
1599 | + * |
1600 | + * Clinica is distributed in the hope that it will be useful, |
1601 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1602 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1603 | + * GNU General Public License for more details. |
1604 | + * |
1605 | + * You should have received a copy of the GNU General Public License |
1606 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1607 | + * |
1608 | + * Authors: Leonardo Robol <leo@robol.it> |
1609 | + */ |
1610 | + |
1611 | using Gtk; |
1612 | |
1613 | namespace Clinica { |
1614 | |
1615 | === modified file 'libclinica/MedicineTreeView.vala' |
1616 | --- libclinica/MedicineTreeView.vala 2011-11-28 15:39:30 +0000 |
1617 | +++ libclinica/MedicineTreeView.vala 2012-02-23 21:39:18 +0000 |
1618 | @@ -1,3 +1,22 @@ |
1619 | +/* |
1620 | + * This file is part of Clinica. |
1621 | + * |
1622 | + * Clinica is free software: you can redistribute it and/or modify |
1623 | + * it under the terms of the GNU General Public License as published by |
1624 | + * the Free Software Foundation, either version 3 of the License, or |
1625 | + * (at your option) any later version. |
1626 | + * |
1627 | + * Clinica is distributed in the hope that it will be useful, |
1628 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1629 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1630 | + * GNU General Public License for more details. |
1631 | + * |
1632 | + * You should have received a copy of the GNU General Public License |
1633 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1634 | + * |
1635 | + * Authors: Leonardo Robol <leo@robol.it> |
1636 | + */ |
1637 | + |
1638 | using Gtk; |
1639 | |
1640 | namespace Clinica { |
1641 | |
1642 | === modified file 'libclinica/Patient.vala' |
1643 | --- libclinica/Patient.vala 2011-11-03 16:41:02 +0000 |
1644 | +++ libclinica/Patient.vala 2012-02-23 21:39:18 +0000 |
1645 | @@ -15,173 +15,48 @@ |
1646 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1647 | * |
1648 | * Authors: Leonardo Robol <leo@robol.it> |
1649 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
1650 | */ |
1651 | - |
1652 | - using Gee; |
1653 | - using Sqlite; |
1654 | - |
1655 | - namespace Clinica { |
1656 | + |
1657 | +namespace Clinica { |
1658 | |
1659 | public enum Gender { |
1660 | MALE, |
1661 | FEMALE, |
1662 | } |
1663 | - |
1664 | - public class PatientIterator : SqlDataIterator { |
1665 | - private ResourceManager resource_manager; |
1666 | - public PatientIterator (ResourceManager resources) { |
1667 | - base (resources.db, resources.patient_table); |
1668 | - resource_manager = resources; |
1669 | - } |
1670 | - |
1671 | - public new PatientIterator iterator () { return this; } |
1672 | - |
1673 | - public new Patient get () { |
1674 | - return new Patient.with_id (resource_manager, base.get ()); |
1675 | - } |
1676 | - } |
1677 | - |
1678 | - /** |
1679 | - * @brief A Patient object represent a person |
1680 | - * whose data are stored in the database (or |
1681 | - * are going to be stored soon). |
1682 | - */ |
1683 | - public class Patient : SqlDataType { |
1684 | - |
1685 | - /** |
1686 | - * @brief Doctor associated to this patient. |
1687 | - */ |
1688 | - private Doctor? _doctor; |
1689 | - public Doctor? doctor { |
1690 | - get { |
1691 | - /* Always reload the doctor to make edits available immediately */ |
1692 | - if (get_integer ("doctor") == -1) |
1693 | - return null; |
1694 | - this._doctor = new Doctor.with_id (resource_manager, get_integer ("doctor")); |
1695 | - return this._doctor; |
1696 | - } |
1697 | - set { |
1698 | - this._doctor = value; |
1699 | - if (_doctor == null) |
1700 | - set_integer ("doctor", -1); |
1701 | - else |
1702 | - set_integer("doctor", value.get_id ()); |
1703 | - } |
1704 | - } |
1705 | - |
1706 | - /* FIELDS */ |
1707 | - public string given_name { |
1708 | - get { return get_text ("given_name"); } |
1709 | - set { set_text ("given_name", value); } |
1710 | - } |
1711 | - |
1712 | - public string surname { |
1713 | - get { return get_text ("surname"); } |
1714 | - set { set_text ("surname", value); } |
1715 | - } |
1716 | - |
1717 | - private DateTime _birth_date; |
1718 | - public DateTime birth_date { |
1719 | - get { |
1720 | - _birth_date = get_date ("birth_date"); |
1721 | - return _birth_date; |
1722 | - } |
1723 | - set { |
1724 | - _birth_date = value; |
1725 | - set_date ("birth_date", _birth_date); |
1726 | - } |
1727 | - } |
1728 | - |
1729 | - public Gender gender { |
1730 | - get { |
1731 | - if (get_text("gender") == "MALE") |
1732 | - return Gender.MALE; |
1733 | - else |
1734 | - return Gender.FEMALE; |
1735 | - } |
1736 | - set { |
1737 | - if (value == Gender.MALE) |
1738 | - set_text("gender", "MALE"); |
1739 | - else |
1740 | - set_text("gender", "FEMALE"); |
1741 | - } |
1742 | - } |
1743 | - |
1744 | - public string phone { |
1745 | - get { return get_text ("phone"); } |
1746 | - set { set_text ("phone", value); } |
1747 | - } |
1748 | - |
1749 | - public string residence_address { |
1750 | - get { return get_text ("residence_address"); } |
1751 | - set { set_text ("residence_address", value); } |
1752 | - } |
1753 | - |
1754 | - public string identification_code { |
1755 | - get { return get_text ("identification_code"); } |
1756 | - set { set_text ("identification_code", value); } |
1757 | - } |
1758 | - |
1759 | - |
1760 | - private ResourceManager resource_manager; |
1761 | - |
1762 | - /** |
1763 | - * @brief Create a new patient |
1764 | - */ |
1765 | - public Patient (ResourceManager resources, Doctor? doctor) { |
1766 | - base (resources.db); |
1767 | - resource_manager = resources; |
1768 | - table_name = resources.patient_table; |
1769 | - error.connect ((t,l) => resources.error_callback(t,l)); |
1770 | - |
1771 | - add_text_field ("given_name"); |
1772 | - add_text_field ("surname"); |
1773 | - add_date_field ("birth_date"); |
1774 | - add_text_field ("gender"); |
1775 | - add_text_field ("phone"); |
1776 | - add_text_field ("residence_address"); |
1777 | - add_text_field ("identification_code"); |
1778 | - add_integer_field ("doctor"); |
1779 | - |
1780 | - this.doctor = doctor; |
1781 | - |
1782 | - init_resources (); |
1783 | - } |
1784 | - |
1785 | - public Patient.with_id (ResourceManager resources, int ID) { |
1786 | - this (resources, null); |
1787 | - load (ID); |
1788 | - if (doctor != null) |
1789 | - { |
1790 | - doctor = new Doctor.with_id (resources, get_integer ("doctor")); |
1791 | - } |
1792 | - } |
1793 | - |
1794 | - public static new PatientIterator all (ResourceManager resources) { |
1795 | - return new PatientIterator (resources); |
1796 | - } |
1797 | + |
1798 | + public class Patient : Object { |
1799 | + |
1800 | + public DataProvider? provider = null; |
1801 | + |
1802 | + public int64 id { get; set; default = 0; } |
1803 | + |
1804 | + public string given_name { get; set; } |
1805 | + |
1806 | + public string surname { get; set; } |
1807 | + |
1808 | + public DateTime birth_date { get; set; } |
1809 | + |
1810 | + public Gender gender { get; set; } |
1811 | + |
1812 | + public string phone { get; set; } |
1813 | + |
1814 | + public string residence_address { get; set; } |
1815 | + |
1816 | + public string identification_code { get; set; } |
1817 | + |
1818 | + public Doctor doctor { get; set; } |
1819 | |
1820 | public string get_complete_name () { |
1821 | return string.join (" ", this.given_name, this.surname); |
1822 | } |
1823 | - |
1824 | - public int64 get_age () { |
1825 | - DateTime today = new DateTime.now_utc (); |
1826 | - var diff = today.difference (this.birth_date); |
1827 | - |
1828 | - /* TimeSpan seems not to work.. :( */ |
1829 | - return (diff / 31557600000000); |
1830 | - } |
1831 | - |
1832 | - /** |
1833 | - * @brief Get the visit IDs for the selected patient. |
1834 | - * Actual visits can then be retrieved with |
1835 | - * var visit = new Visit (ID); |
1836 | - */ |
1837 | - public GLib.List<int> get_visit_ids () { |
1838 | - return associated_ids (resource_manager.visits_table, "patient"); |
1839 | - } |
1840 | + |
1841 | + public VisitIterator visits (DateTime? start = null, DateTime? end = null) { |
1842 | + if (provider == null) |
1843 | + return new EmptyVisitIterator (); |
1844 | + else |
1845 | + return provider.visits (this, start, end); |
1846 | + } |
1847 | + |
1848 | } |
1849 | - |
1850 | - } |
1851 | + |
1852 | +} |
1853 | |
1854 | === modified file 'libclinica/PatientEditor.vala' |
1855 | --- libclinica/PatientEditor.vala 2012-02-02 07:26:45 +0000 |
1856 | +++ libclinica/PatientEditor.vala 2012-02-23 21:39:18 +0000 |
1857 | @@ -405,8 +405,10 @@ |
1858 | |
1859 | /* Save the new patient, creating a new one if this is a new patient, or |
1860 | * reusing the existing one if we are only modifying a patient. */ |
1861 | - if (existing_patient == null) |
1862 | - created_patient = new Patient (resource_manager, selected_doctor); |
1863 | + if (existing_patient == null) { |
1864 | + created_patient = new Patient (); |
1865 | + created_patient.doctor = selected_doctor; |
1866 | + } |
1867 | else |
1868 | created_patient = existing_patient; |
1869 | |
1870 | @@ -443,15 +445,7 @@ |
1871 | else |
1872 | created_patient.gender = Gender.FEMALE; |
1873 | |
1874 | - created_patient.save (); |
1875 | - |
1876 | - // If this was an existing patient we need to reload it in the patient |
1877 | - // list store, otherwise we can just add it |
1878 | - if (existing_patient != null) { |
1879 | - resource_manager.patient_list_store.reload_patient (created_patient); |
1880 | - } else { |
1881 | - resource_manager.patient_list_store.add_patient (created_patient); |
1882 | - } |
1883 | + resource_manager.data_provider.save_patient (created_patient); |
1884 | |
1885 | return Response.SAVE; |
1886 | } |
1887 | |
1888 | === modified file 'libclinica/PatientEditorActivatable.vala' |
1889 | --- libclinica/PatientEditorActivatable.vala 2011-09-22 19:27:52 +0000 |
1890 | +++ libclinica/PatientEditorActivatable.vala 2012-02-23 21:39:18 +0000 |
1891 | @@ -1,3 +1,22 @@ |
1892 | +/* |
1893 | + * This file is part of Clinica. |
1894 | + * |
1895 | + * Clinica is free software: you can redistribute it and/or modify |
1896 | + * it under the terms of the GNU General Public License as published by |
1897 | + * the Free Software Foundation, either version 3 of the License, or |
1898 | + * (at your option) any later version. |
1899 | + * |
1900 | + * Clinica is distributed in the hope that it will be useful, |
1901 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1902 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1903 | + * GNU General Public License for more details. |
1904 | + * |
1905 | + * You should have received a copy of the GNU General Public License |
1906 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
1907 | + * |
1908 | + * Authors: Leonardo Robol <leo@robol.it> |
1909 | + */ |
1910 | + |
1911 | namespace Clinica { |
1912 | |
1913 | /** |
1914 | |
1915 | === modified file 'libclinica/PatientListStore.vala' |
1916 | --- libclinica/PatientListStore.vala 2011-09-22 19:27:52 +0000 |
1917 | +++ libclinica/PatientListStore.vala 2012-02-23 21:39:18 +0000 |
1918 | @@ -53,10 +53,20 @@ |
1919 | |
1920 | /* Asynchronous loading of patients */ |
1921 | Idle.add(() => { |
1922 | - foreach (Patient p in Patient.all (resource_manager)) { |
1923 | - add_patient (p); |
1924 | + foreach (Patient p in resource_manager.data_provider.patients ()) { |
1925 | + add_patient (p.id); |
1926 | } |
1927 | |
1928 | + /* Setup callbacks to add or remove patient */ |
1929 | + resource_manager.data_provider.patient_added.connect ( |
1930 | + (id) => add_patient (id)); |
1931 | + resource_manager.data_provider.patient_changed.connect ( |
1932 | + (id) => reload_patient (id)); |
1933 | + resource_manager.data_provider.patient_removed.connect ((id) => { |
1934 | + TreeIter iter = id_to_iter (id); |
1935 | + remove (iter); |
1936 | + }); |
1937 | + |
1938 | /* We don't need to reiterate this function any more */ |
1939 | return false; |
1940 | }); |
1941 | @@ -65,10 +75,11 @@ |
1942 | /** |
1943 | * @brief Append the given patient to the liststore |
1944 | */ |
1945 | - public void add_patient (Patient p) { |
1946 | + private void add_patient (int64 id) { |
1947 | + Patient p = resource_manager.data_provider.get_patient (id); |
1948 | TreeIter it; |
1949 | append (out it); |
1950 | - set_value (it, Field.PATIENT, p); |
1951 | + set_value (it, Field.PATIENT, p); |
1952 | set_value (it, Field.GIVEN_NAME, p.given_name); |
1953 | set_value (it, Field.SURNAME, p.surname); |
1954 | set_value (it, Field.COMPLETE_NAME, p.get_complete_name ()); |
1955 | @@ -78,7 +89,8 @@ |
1956 | * @brief Reload information about patient p that |
1957 | * should be already present in the database |
1958 | */ |
1959 | - public void reload_patient (Patient p) { |
1960 | + private void reload_patient (int64 id) { |
1961 | + Patient p = resource_manager.data_provider.get_patient (id); |
1962 | TreeIter iter; |
1963 | Value patient; |
1964 | |
1965 | @@ -88,7 +100,7 @@ |
1966 | |
1967 | do { |
1968 | get_value (iter, Field.PATIENT, out patient); |
1969 | - if ((patient as Patient).get_id () == p.get_id ()) { |
1970 | + if ((patient as Patient).id == p.id) { |
1971 | set_value(iter, Field.PATIENT, p); |
1972 | set_value(iter, Field.GIVEN_NAME, p.given_name); |
1973 | set_value(iter, Field.SURNAME, p.surname); |
1974 | @@ -101,63 +113,19 @@ |
1975 | assert_not_reached (); |
1976 | } |
1977 | |
1978 | - /** |
1979 | - * @brief Return a list of treeiters pointing to the patients |
1980 | - * of the given doctor. |
1981 | - */ |
1982 | - public List<TreeIter?> get_patients_of (Doctor doc) { |
1983 | - Value value; |
1984 | - var iters = new List<TreeIter?> (); |
1985 | - TreeIter it; |
1986 | - Patient p; |
1987 | - |
1988 | - if (!get_iter_first (out it)) { |
1989 | - return iters; |
1990 | - } |
1991 | - do { |
1992 | - get_value (it, Field.PATIENT, out value); |
1993 | - p = value as Patient; |
1994 | - if (p.doctor.get_id () == doc.get_id ()) { |
1995 | - iters.append (it); |
1996 | - } |
1997 | - } while (iter_next(ref it)); |
1998 | - |
1999 | - return iters; |
2000 | - } |
2001 | - |
2002 | - public TreeIter patient_to_iter (Patient p) { |
2003 | + private TreeIter id_to_iter (int64 id) { |
2004 | TreeIter it; |
2005 | Value patient; |
2006 | if (!get_iter_first (out it)) |
2007 | error(_("Patients database seems corrupted. This is likely to be a bug in the application")); |
2008 | do { |
2009 | get_value (it, Field.PATIENT, out patient); |
2010 | - if ((patient as Patient).get_id () == p.get_id ()) { |
2011 | + if ((patient as Patient).id == id) { |
2012 | return it; |
2013 | } |
2014 | } while (iter_next (ref it)); |
2015 | |
2016 | assert_not_reached (); |
2017 | } |
2018 | - |
2019 | - public void remove_patient (Patient p) { |
2020 | - TreeIter p_iter = patient_to_iter (p); |
2021 | - remove_patient_from_iter (p_iter); |
2022 | - } |
2023 | - |
2024 | - public void remove_patient_from_iter (TreeIter it) { |
2025 | - Value patient; |
2026 | - get_value (it, Field.PATIENT, out patient); |
2027 | - |
2028 | - var visits = resource_manager.visit_list_store.get_visits_of (patient as Patient); |
2029 | - |
2030 | - foreach (TreeIter v_it in visits) { |
2031 | - resource_manager.visit_list_store.remove_visit_from_iter (v_it); |
2032 | - } |
2033 | - |
2034 | - /* Actually remove the patient */ |
2035 | - (patient as Patient).remove (); |
2036 | - remove (it); |
2037 | - } |
2038 | } |
2039 | } |
2040 | |
2041 | === modified file 'libclinica/PatientListView.vala' |
2042 | --- libclinica/PatientListView.vala 2012-01-31 08:10:13 +0000 |
2043 | +++ libclinica/PatientListView.vala 2012-02-23 21:39:18 +0000 |
2044 | @@ -135,10 +135,7 @@ |
2045 | /* Cast patient and update database data */ |
2046 | patient = value as Patient; |
2047 | patient.given_name = new_text; |
2048 | - patient.save (); |
2049 | - |
2050 | - /* Update UI */ |
2051 | - resource_manager.patient_list_store.reload_patient (patient); |
2052 | + resource_manager.data_provider.save_patient (patient); |
2053 | } |
2054 | |
2055 | private void on_surname_cell_edited (CellRenderer renderer, string path, string new_text) { |
2056 | @@ -155,10 +152,7 @@ |
2057 | /* Set new data in the Patient, save and update treeview */ |
2058 | patient = value as Patient; |
2059 | patient.surname = new_text; |
2060 | - patient.save (); |
2061 | - |
2062 | - /* Update UI */ |
2063 | - resource_manager.patient_list_store.reload_patient (patient); |
2064 | + resource_manager.data_provider.save_patient (patient); |
2065 | } |
2066 | |
2067 | /** |
2068 | @@ -189,8 +183,17 @@ |
2069 | TreeIter it; |
2070 | sortable_model.convert_iter_to_child_iter (out it, iter); |
2071 | filtered_store.convert_iter_to_child_iter (out iter, it); |
2072 | - /* Delete patient from the database and from the store*/ |
2073 | - store.remove_patient_from_iter (iter); |
2074 | + |
2075 | + /* Delete patient from the database */ |
2076 | + Value value; |
2077 | + store.get_value (iter, PatientListStore.Field.PATIENT, out value); |
2078 | + |
2079 | + /* Removing the visits associated with this patient */ |
2080 | + foreach (Visit visit in (value as Patient).visits ()) { |
2081 | + resource_manager.data_provider.remove_visit (visit); |
2082 | + } |
2083 | + |
2084 | + resource_manager.data_provider.remove_patient (value as Patient); |
2085 | } |
2086 | } |
2087 | |
2088 | |
2089 | === modified file 'libclinica/PluginEngine.vala' |
2090 | --- libclinica/PluginEngine.vala 2011-09-22 19:27:52 +0000 |
2091 | +++ libclinica/PluginEngine.vala 2012-02-23 21:39:18 +0000 |
2092 | @@ -1,3 +1,22 @@ |
2093 | +/* |
2094 | + * This file is part of Clinica. |
2095 | + * |
2096 | + * Clinica is free software: you can redistribute it and/or modify |
2097 | + * it under the terms of the GNU General Public License as published by |
2098 | + * the Free Software Foundation, either version 3 of the License, or |
2099 | + * (at your option) any later version. |
2100 | + * |
2101 | + * Clinica is distributed in the hope that it will be useful, |
2102 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2103 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2104 | + * GNU General Public License for more details. |
2105 | + * |
2106 | + * You should have received a copy of the GNU General Public License |
2107 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
2108 | + * |
2109 | + * Authors: Leonardo Robol <leo@robol.it> |
2110 | + */ |
2111 | + |
2112 | namespace Clinica { |
2113 | |
2114 | public class PluginEngine : Peas.Engine { |
2115 | |
2116 | === modified file 'libclinica/ResourceManager.vala' |
2117 | --- libclinica/ResourceManager.vala 2012-02-02 07:26:45 +0000 |
2118 | +++ libclinica/ResourceManager.vala 2012-02-23 21:39:18 +0000 |
2119 | @@ -78,6 +78,14 @@ |
2120 | public EventListStore event_list_store; |
2121 | |
2122 | /** |
2123 | + * @brief This is the object used to retrieve all the data |
2124 | + * about patients and which events should be connected |
2125 | + * to the views to make them react to changes in the database |
2126 | + * or whatever the data source is. |
2127 | + */ |
2128 | + internal DataProvider data_provider; |
2129 | + |
2130 | + /** |
2131 | * @brief Reference to a user interface |
2132 | */ |
2133 | public UserInterface user_interface; |
2134 | @@ -98,24 +106,13 @@ |
2135 | * @brief Local configuration directory |
2136 | * obtained at runtime. |
2137 | */ |
2138 | - private string local_config_directory; |
2139 | + internal string local_config_directory; |
2140 | |
2141 | /** |
2142 | * @brief Local data directory obtained |
2143 | * at runtime. |
2144 | */ |
2145 | - private string local_data_directory; |
2146 | - |
2147 | - /** |
2148 | - * @brief Database path. |
2149 | - */ |
2150 | - private string database_path; |
2151 | - |
2152 | - /** |
2153 | - * @brief SQLite database with data and |
2154 | - * configurations. |
2155 | - */ |
2156 | - public Database db; |
2157 | + internal string local_data_directory; |
2158 | |
2159 | /** |
2160 | * @brief The file store used to retrieve the data associated |
2161 | @@ -135,12 +132,20 @@ |
2162 | */ |
2163 | internal GLib.List<unowned MedicineSearchEngine> medicine_search_engines; |
2164 | |
2165 | + /** |
2166 | + * @brief List containing the available DataProviders that |
2167 | + * can be used to retrieve data in Clinica. |
2168 | + */ |
2169 | + internal List<unowned DataProvider> data_providers; |
2170 | + |
2171 | /** |
2172 | * @brief A pointer to the patient that is been dragged. Should |
2173 | * be set on drag_begin by the treeview and reset to null by the |
2174 | * drag destination handler. |
2175 | */ |
2176 | internal Patient? dragging_patient = null; |
2177 | + |
2178 | + private Peas.ExtensionSet core_set; |
2179 | |
2180 | /** |
2181 | * @brief Path to the UI files directory |
2182 | @@ -160,9 +165,8 @@ |
2183 | /** SIGNALS **/ |
2184 | public signal void medicine_search_engines_added (MedicineSearchEngine engine); |
2185 | public signal void medicine_search_engines_removed (MedicineSearchEngine engine); |
2186 | - |
2187 | - private const string [] supported_db_versions = { "0.1", "0.2" }; |
2188 | - private const string db_version = "0.2"; |
2189 | + public signal void data_provider_added (DataProvider provider); |
2190 | + public signal void data_provider_removed (DataProvider provider); |
2191 | |
2192 | public ResourceManager (Gtk.Application? application, |
2193 | string program_name = "clinica", |
2194 | @@ -198,68 +202,11 @@ |
2195 | DirUtils.create_with_parents (local_data_directory, -1); |
2196 | } |
2197 | |
2198 | - /* Set database path and check if a database exists in the old location, |
2199 | - * if that's the case move it to the new one. */ |
2200 | - check_database_path (); |
2201 | - |
2202 | /* Check if the directory for the FileStore exists */ |
2203 | File fsd = File.new_for_path (get_filestore_dir ()); |
2204 | if (!fsd.query_exists ()) |
2205 | DirUtils.create_with_parents (get_filestore_dir (), -1); |
2206 | file_store = new FileStore (this); |
2207 | - |
2208 | - /* Read database version if existant, saved actual version otherwise. |
2209 | - * This may be used in future to perform one-time upgrade of the database */ |
2210 | - var version_db_file = Path.build_filename (local_config_directory, |
2211 | - ".clinica_db_version"); |
2212 | - |
2213 | - if (!FileUtils.test (version_db_file, FileTest.IS_REGULAR)) { |
2214 | - /* Create the file with the version of the database */ |
2215 | - try { |
2216 | - FileUtils.set_contents(version_db_file, db_version); |
2217 | - } catch (Error e) { |
2218 | - error (_("Error creating some configuration files, check permission on %s".printf(version_db_file))); |
2219 | - } |
2220 | - } |
2221 | - else { |
2222 | - string content; |
2223 | - try { |
2224 | - FileUtils.get_contents(version_db_file, out content); |
2225 | - } catch (Error e) { |
2226 | - error (_("Error reading some configuration files, check permission on %s".printf(version_db_file))); |
2227 | - } |
2228 | - |
2229 | - bool upgraded_correcty = true; |
2230 | - if (db_version != content) { |
2231 | - /* Ask the user if he really wants to upgrade */ |
2232 | - if (!ask_for_upgrade()) { |
2233 | - debug ("The user doesn't want to upgrade, exiting."); |
2234 | - Posix.exit (0); |
2235 | - } |
2236 | - |
2237 | - upgraded_correcty = false; |
2238 | - /* Try to determine if the version of the local database is supported */ |
2239 | - if (content in supported_db_versions) { |
2240 | - if (upgrade_database (content)) { |
2241 | - upgraded_correcty = true; |
2242 | - try { |
2243 | - FileUtils.set_contents (version_db_file, db_version); |
2244 | - } catch (GLib.Error e) { |
2245 | - error (_("Failure while settings new database version to %s").printf (db_version)); |
2246 | - } |
2247 | - } else { |
2248 | - error (_("Failure while upgrading database")); |
2249 | - } |
2250 | - } |
2251 | - else |
2252 | - error (_("Version of the database is not compatible")); |
2253 | - } |
2254 | - |
2255 | - if (!upgraded_correcty) { |
2256 | - debug ("Upgrade failed, exiting."); |
2257 | - Posix.exit (1); |
2258 | - } |
2259 | - } |
2260 | |
2261 | /* Find prefix */ |
2262 | prefix = "/usr/local"; |
2263 | @@ -312,6 +259,11 @@ |
2264 | /* Create configuration */ |
2265 | settings = new Settings (this); |
2266 | |
2267 | + /* SqliteDataProvider must always be the first DataProvider |
2268 | + * in the list */ |
2269 | + data_providers = new List<unowned DataProvider> (); |
2270 | + register_data_provider (new SqliteDataProvider (this)); |
2271 | + |
2272 | /* Load all extensions found... this is quite ugly, but an |
2273 | * interface to select loaded plugins is still needed. |
2274 | * For now, do it in the idle cycle to allow clinica to start |
2275 | @@ -320,64 +272,14 @@ |
2276 | load_plugins.begin (); |
2277 | } |
2278 | |
2279 | - private bool ask_for_upgrade () { |
2280 | - var mb = new MessageDialog (null, |
2281 | - DialogFlags.DESTROY_WITH_PARENT | |
2282 | - DialogFlags.MODAL, |
2283 | - MessageType.QUESTION, |
2284 | - ButtonsType.YES_NO, |
2285 | - "%s", "Database upgrade"); |
2286 | - 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")); |
2287 | - mb.set_title (_("Upgrade database")); |
2288 | - if (mb.run () == ResponseType.YES) { |
2289 | - mb.destroy (); |
2290 | - return true; |
2291 | - } |
2292 | - else { |
2293 | - mb.destroy (); |
2294 | - return false; |
2295 | - } |
2296 | - } |
2297 | - |
2298 | - /** |
2299 | - * @brief Check if the database is in the right path. If it is not there |
2300 | - * move it and the set database_path. |
2301 | - */ |
2302 | - private void check_database_path () { |
2303 | - database_path = Path.build_filename (local_data_directory, |
2304 | - "clinica.db"); |
2305 | - File db_file = File.new_for_path (database_path); |
2306 | - if (!db_file.query_exists ()) { |
2307 | - File old_db_file = File.new_for_path (Path.build_filename (local_config_directory, |
2308 | - "clinica.db")); |
2309 | - if (old_db_file.query_exists ()) { |
2310 | - |
2311 | - var mb = new MessageDialog (null, DialogFlags.DESTROY_WITH_PARENT | DialogFlags.MODAL, |
2312 | - MessageType.QUESTION, ButtonsType.YES_NO, "%s", _("Database needs to be moved")); |
2313 | - mb.format_secondary_markup (_("An older version of clinica has been detected and the old database has to be moved\nto a new location to continue.\n<b>The older version of clinica won't work anymore with this setup</b>.\nDo you still want to continue?")); |
2314 | - if (mb.run () != Gtk.ResponseType.YES) { |
2315 | - mb.destroy (); |
2316 | - Posix.exit (1); |
2317 | - } |
2318 | - |
2319 | - mb.destroy (); |
2320 | - |
2321 | - debug ("Moving old database to its new location (starting from clinica 0.2.9)"); |
2322 | - try { |
2323 | - old_db_file.copy (db_file, FileCopyFlags.ALL_METADATA); |
2324 | - FileUtils.remove (old_db_file.get_path ()); |
2325 | - } catch (GLib.Error e) { |
2326 | - error (_("Error while transferring the database to the new default location for clinica >= 0.2.9")); |
2327 | - } |
2328 | - } |
2329 | - } |
2330 | - } |
2331 | + private extern Peas.ExtensionSet setup_extension_set (PluginEngine engine); |
2332 | |
2333 | /** |
2334 | * @brief Instantiate the plugin engine and load |
2335 | * all the plugins present in the directory |
2336 | */ |
2337 | public async void load_plugins () { |
2338 | + |
2339 | /* Setup plugin engine */ |
2340 | plugin_engine = new PluginEngine (this); |
2341 | plugin_engine.enable_loader ("python"); |
2342 | @@ -396,6 +298,34 @@ |
2343 | debug ("Plugin %s found but disabled".printf (info.get_name ())); |
2344 | } |
2345 | } |
2346 | + |
2347 | + /* Setup the CoreActivatable extension set, so new DataProviders will be available */ |
2348 | + core_set = setup_extension_set (plugin_engine); |
2349 | + |
2350 | + /* Create the store that will be attached to the data provider selected |
2351 | + * above */ |
2352 | + doctor_list_store = new DoctorListStore (this); |
2353 | + patient_list_store = new PatientListStore (this); |
2354 | + visit_list_store = new VisitListStore (this); |
2355 | + event_list_store = new EventListStore (this); |
2356 | + } |
2357 | + |
2358 | + public void register_data_provider (DataProvider provider) { |
2359 | + data_providers.append (provider); |
2360 | + data_provider_added (provider); |
2361 | + |
2362 | + if (data_provider == null) |
2363 | + data_provider = provider; |
2364 | + |
2365 | + if (provider.get_name () == settings.get_string ("data-provider")) |
2366 | + data_provider = provider; |
2367 | + } |
2368 | + |
2369 | + public void unregister_data_provider (DataProvider provider) { |
2370 | + if (provider == data_provider) { |
2371 | + data_provider = data_providers.nth_data (0); |
2372 | + settings.set_string ("data-provider", ""); |
2373 | + } |
2374 | } |
2375 | |
2376 | public void register_medicine_search_engine (MedicineSearchEngine engine) { |
2377 | @@ -440,6 +370,10 @@ |
2378 | } |
2379 | } |
2380 | |
2381 | + public string get_data_path () { |
2382 | + return local_data_directory; |
2383 | + } |
2384 | + |
2385 | /** |
2386 | * @brief Get the directory in which the FileStore can store its files. |
2387 | */ |
2388 | @@ -447,109 +381,6 @@ |
2389 | return Path.build_filename (local_data_directory, "filestore"); |
2390 | } |
2391 | |
2392 | - private bool upgrade_database (string db_version) { |
2393 | - /* Try to open the database first */ |
2394 | - if (!(Database.open (database_path, out db) == OK)) { |
2395 | - error (_("Error upgrading database, please check your installation")); |
2396 | - } |
2397 | - |
2398 | - string sql; |
2399 | - Statement stmt; |
2400 | - int rc; |
2401 | - |
2402 | - /* Performing upgrade from 0.1 */ |
2403 | - if (db_version == "0.1") { |
2404 | - /* We need to create the new table for the events */ |
2405 | - sql = "CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, title TEXT, description TEXT, venue TEXT, patient INTEGER, visit INTEGER, date TEXT);"; |
2406 | - db.prepare (sql, -1, out stmt, null); |
2407 | - rc = stmt.step (); |
2408 | - |
2409 | - if (rc != DONE) { |
2410 | - error (_("Error upgrading the database from version 0.1 to 0.2, sqlite exit code: %d".printf (rc))); |
2411 | - return false; |
2412 | - } else { |
2413 | - db_version = "0.2"; |
2414 | - } |
2415 | - } |
2416 | - |
2417 | - return true; |
2418 | - } |
2419 | - |
2420 | - /** |
2421 | - * @brief Check that all the resources needed by Clinica |
2422 | - * are actually available, and if they are not create them. |
2423 | - */ |
2424 | - public void initResources () { |
2425 | - int rc; |
2426 | - Statement stmt; |
2427 | - string sql; |
2428 | - |
2429 | - /* Open database and, if it does not exists, create it */ |
2430 | - if (!(Database.open (database_path, out db) == OK)) { |
2431 | - error ("Error opening database."); |
2432 | - }; |
2433 | - |
2434 | - /* Check if the required tables exists */ |
2435 | - sql = "SELECT * from sqlite_master WHERE type='table';"; |
2436 | - db.prepare (sql, -1, out stmt, null); |
2437 | - rc = stmt.step (); |
2438 | - |
2439 | - if (rc == DONE) { |
2440 | - /* That means no tables in the database */ |
2441 | - initDatabase (); |
2442 | - } |
2443 | - |
2444 | - /* Load stores */ |
2445 | - doctor_list_store = new DoctorListStore (this); |
2446 | - patient_list_store = new PatientListStore (this); |
2447 | - visit_list_store = new VisitListStore (this); |
2448 | - event_list_store = new EventListStore (this); |
2449 | - } |
2450 | - |
2451 | - |
2452 | - /** |
2453 | - * @brief Init the database with the required tables |
2454 | - */ |
2455 | - private void initDatabase () { |
2456 | - Statement stmt; |
2457 | - string sql; |
2458 | - string err_msg; |
2459 | - |
2460 | - /* Create config table */ |
2461 | - sql = "CREATE TABLE config (id INTEGER PRIMARY KEY, " + |
2462 | - "key TEXT, value TEXT);"; |
2463 | - db.prepare (sql, -1, out stmt, null); |
2464 | - if (!(stmt.step () == DONE)) { |
2465 | - err_msg = db.errmsg (); |
2466 | - error ("Error creating config structure in the Database: " |
2467 | - + err_msg); |
2468 | - } |
2469 | - } |
2470 | - |
2471 | - /** |
2472 | - * @brief Return a Doctor object associated to the given ID |
2473 | - */ |
2474 | - public Doctor getDoctor (int ID) { |
2475 | - Doctor doctor = new Doctor.with_id (this, ID); |
2476 | - return doctor; |
2477 | - } |
2478 | - |
2479 | - /** |
2480 | - * @brief Return a Patient object associated to the given ID |
2481 | - */ |
2482 | - public Patient getPatient (int ID) { |
2483 | - Patient p = new Patient.with_id (this, ID); |
2484 | - return p; |
2485 | - } |
2486 | - |
2487 | - /** |
2488 | - * @brief Return a Visit object associated to the given ID |
2489 | - */ |
2490 | - public Visit getVisit (int ID) { |
2491 | - Visit visit = new Visit.with_id (this, ID); |
2492 | - return visit; |
2493 | - } |
2494 | - |
2495 | |
2496 | } |
2497 | |
2498 | |
2499 | === modified file 'libclinica/Service.vala' |
2500 | --- libclinica/Service.vala 2012-01-26 17:41:05 +0000 |
2501 | +++ libclinica/Service.vala 2012-02-23 21:39:18 +0000 |
2502 | @@ -39,12 +39,12 @@ |
2503 | * @brief Return a lists of patients id whose name |
2504 | * match the given string. |
2505 | */ |
2506 | - public int [] patients_filter (string filter) { |
2507 | + public int64 [] patients_filter (string filter) { |
2508 | string lfilter = filter.down(); |
2509 | - int [] patients = {}; |
2510 | - foreach (var patient in Patient.all (resource_manager)) { |
2511 | + int64 [] patients = {}; |
2512 | + foreach (var patient in resource_manager.data_provider.patients ()) { |
2513 | if (lfilter in patient.get_complete_name ().down ()) { |
2514 | - patients += patient.get_id (); |
2515 | + patients += patient.id; |
2516 | } |
2517 | } |
2518 | |
2519 | |
2520 | === modified file 'libclinica/SettingsManager.vala' |
2521 | --- libclinica/SettingsManager.vala 2012-01-29 10:39:56 +0000 |
2522 | +++ libclinica/SettingsManager.vala 2012-02-23 21:39:18 +0000 |
2523 | @@ -69,6 +69,9 @@ |
2524 | var mse_selector = new MedicineSearchEngineSelector (resource_manager); |
2525 | structure_vbox.pack_start (mse_selector, false); |
2526 | |
2527 | + var dp_selector = new DataProviderSelector (resource_manager); |
2528 | + structure_vbox.pack_start (dp_selector, false); |
2529 | + |
2530 | /* Add structure vbox to the first page of the Notebook */ |
2531 | var sv_alignment = new Alignment (0.5F, 0.5F, 1.0F, 1.0F); |
2532 | sv_alignment.set_padding (6,6,6,6); |
2533 | @@ -166,4 +169,65 @@ |
2534 | } |
2535 | } |
2536 | } |
2537 | + |
2538 | + |
2539 | + public class DataProviderSelector : HBox { |
2540 | + |
2541 | + private ResourceManager resource_manager { get; set; } |
2542 | + private ComboBoxText data_provider_selector; |
2543 | + |
2544 | + public DataProviderSelector (ResourceManager resources) { |
2545 | + GLib.Object (homogeneous: false, spacing: 6); |
2546 | + resource_manager = resources; |
2547 | + var label = new Label (_("Select the data provider\nused to retrieve data")); |
2548 | + label.set_alignment (0.0F, 0.5F); |
2549 | + pack_start (label); |
2550 | + |
2551 | + /* Create the combobox and keep a track of its position in the array. */ |
2552 | + data_provider_selector = new ComboBoxText (); |
2553 | + refresh_provider_list (); |
2554 | + resource_manager.data_provider_added.connect ((provider) => refresh_provider_list ()); |
2555 | + resource_manager.data_provider_removed.connect ((provider) => refresh_provider_list ()); |
2556 | + pack_start (data_provider_selector, false, true); |
2557 | + data_provider_selector.changed.connect (on_data_provider_selector_changed); |
2558 | + } |
2559 | + |
2560 | + private void on_data_provider_selector_changed () { |
2561 | + string? active_id = data_provider_selector.get_active_id (); |
2562 | + if (active_id == null) |
2563 | + return; |
2564 | + var index = int.parse (active_id); |
2565 | + resource_manager.data_provider = |
2566 | + resource_manager.data_providers.nth_data (index); |
2567 | + resource_manager.settings.set_string ("data-provider", |
2568 | + resource_manager.data_provider.get_name ()); |
2569 | + } |
2570 | + |
2571 | + private void refresh_provider_list () { |
2572 | + int i = 0; |
2573 | + data_provider_selector.remove_all (); |
2574 | + |
2575 | + /* If no preference is set set the first engine as selected */ |
2576 | + if (resource_manager.settings.get_string ("data-provider") == "") { |
2577 | + if (resource_manager.data_providers.length () != 0) { |
2578 | + resource_manager.data_provider = |
2579 | + resource_manager.data_providers.nth_data (0); |
2580 | + resource_manager.settings.set_string ("data-provider", |
2581 | + resource_manager.data_provider.get_name ()); |
2582 | + } |
2583 | + } |
2584 | + |
2585 | + /* Load engines in the liststore */ |
2586 | + foreach (var provider in resource_manager.data_providers) { |
2587 | + data_provider_selector.append ("%d".printf (i++), provider.get_name ()); |
2588 | + if (resource_manager.settings.get_string ("data-provider") == provider.get_name ()) { |
2589 | + debug ("Loading data provider: %s", provider.get_name ()); |
2590 | + resource_manager.data_provider = provider; |
2591 | + } |
2592 | + if (provider == resource_manager.data_provider) { |
2593 | + data_provider_selector.set_active (i - 1); |
2594 | + } |
2595 | + } |
2596 | + } |
2597 | + } |
2598 | } |
2599 | |
2600 | === removed file 'libclinica/SqlDataType.vala' |
2601 | --- libclinica/SqlDataType.vala 2011-10-04 12:15:09 +0000 |
2602 | +++ libclinica/SqlDataType.vala 1970-01-01 00:00:00 +0000 |
2603 | @@ -1,397 +0,0 @@ |
2604 | -/* |
2605 | - * This file is part of Clinica. |
2606 | - * |
2607 | - * Clinica is free software: you can redistribute it and/or modify |
2608 | - * it under the terms of the GNU General Public License as published by |
2609 | - * the Free Software Foundation, either version 3 of the License, or |
2610 | - * (at your option) any later version. |
2611 | - * |
2612 | - * Clinica is distributed in the hope that it will be useful, |
2613 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2614 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2615 | - * GNU General Public License for more details. |
2616 | - * |
2617 | - * You should have received a copy of the GNU General Public License |
2618 | - * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
2619 | - * |
2620 | - * Authors: Leonardo Robol <leo@robol.it> |
2621 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
2622 | - */ |
2623 | - |
2624 | -using Sqlite; |
2625 | -using Gee; |
2626 | - |
2627 | -namespace Clinica { |
2628 | - |
2629 | - /** |
2630 | - * @brief Struct representing a column in the database. |
2631 | - */ |
2632 | - public class SqlColumn { |
2633 | - public string type; |
2634 | - public string v; |
2635 | - |
2636 | - public SqlColumn (string type) { |
2637 | - this.type = type; |
2638 | - } |
2639 | - } |
2640 | - |
2641 | - public class SqlDataIterator : GLib.Object { |
2642 | - |
2643 | - protected unowned Database db; |
2644 | - protected Statement stmt; |
2645 | - |
2646 | - public SqlDataIterator (Database db, string table_name, string? order_by = null, bool desc = false) { |
2647 | - this.db = db; |
2648 | - if (order_by == null) |
2649 | - db.prepare (@"SELECT ID FROM $(table_name);", -1, out stmt, null); |
2650 | - else { |
2651 | - if (desc) |
2652 | - db.prepare (@"SELECT ID FROM $(table_name) ORDER by $(order_by) DESC;", -1, out stmt, null); |
2653 | - else |
2654 | - db.prepare (@"SELECT ID FROM $(table_name) ORDER by $(order_by);", -1, out stmt, null); |
2655 | - } |
2656 | - } |
2657 | - |
2658 | - public SqlDataIterator.with_like (Database db, string table_name, string? order_by = null, |
2659 | - bool desc = false, string where_stmt) { |
2660 | - this.db = db; |
2661 | - |
2662 | - if (order_by == null) |
2663 | - db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt);", -1, out stmt, null); |
2664 | - else { |
2665 | - if (desc) |
2666 | - db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt) ORDER by $(order_by) DESC;", -1, out stmt, null); |
2667 | - else |
2668 | - db.prepare (@"SELECT ID FROM $(table_name) WHERE $(where_stmt) ORDER by $(order_by);", -1, out stmt, null); |
2669 | - } |
2670 | - } |
2671 | - |
2672 | - public SqlDataIterator iterator () { |
2673 | - return this; |
2674 | - } |
2675 | - |
2676 | - public bool next () { |
2677 | - return (stmt.step () == ROW); |
2678 | - } |
2679 | - |
2680 | - public new int get () { |
2681 | - return stmt.column_int (0); |
2682 | - } |
2683 | - } |
2684 | - |
2685 | - /** |
2686 | - * @brief Interface representing an abstract data |
2687 | - * type interfaced to a SQLite database. |
2688 | - */ |
2689 | - public class SqlDataType : GLib.Object { |
2690 | - |
2691 | - /** |
2692 | - * @brief Signal emitted when an error eris |
2693 | - * encountered |
2694 | - */ |
2695 | - public signal void error (string message); |
2696 | - |
2697 | - /** |
2698 | - * @brief The table name in the database. Must be set |
2699 | - * by the class implementing this interface. |
2700 | - */ |
2701 | - public string table_name; |
2702 | - |
2703 | - /** |
2704 | - * @brief The database object used to interact with |
2705 | - * the sqlite database. It must be opened by the |
2706 | - * class implementing this interface. |
2707 | - */ |
2708 | - public unowned Database db; |
2709 | - |
2710 | - /** |
2711 | - * @brief Hash mapping column_name -> type, value. |
2712 | - */ |
2713 | - public HashMap<string, SqlColumn?> columns; |
2714 | - |
2715 | - public SqlDataType (Database db) { |
2716 | - this.db = db; |
2717 | - columns = new HashMap<string, SqlColumn> (); |
2718 | - this.columns.set ("ID", new SqlColumn ("INTEGER PRIMARY KEY")); |
2719 | - set_integer ("ID", 0); |
2720 | - } |
2721 | - |
2722 | - public SqlDataType.with_id (Database db, int ID) { |
2723 | - this (db); |
2724 | - load (ID); |
2725 | - } |
2726 | - |
2727 | - protected void add_text_field (string name) { |
2728 | - this.columns.set (name, new SqlColumn ("TEXT")); |
2729 | - } |
2730 | - |
2731 | - protected void add_integer_field (string name) { |
2732 | - this.columns.set (name, new SqlColumn ("INTEGER")); |
2733 | - } |
2734 | - |
2735 | - protected void add_date_field (string name) { |
2736 | - this.columns.set (name, new SqlColumn ("TEXT")); |
2737 | - } |
2738 | - |
2739 | - /** |
2740 | - * @brief Escape a string and surround it with |
2741 | - * double quotes ready to be inserted in the |
2742 | - * database. |
2743 | - */ |
2744 | - protected string quote (string str) { |
2745 | - return "\"" + str.escape ("") + "\""; |
2746 | - } |
2747 | - |
2748 | - /** |
2749 | - * @brief Initialize resource, i.e. open the database |
2750 | - * and check for missing tables. |
2751 | - */ |
2752 | - protected void init_resources () { |
2753 | - lock (db) { |
2754 | - Statement stmt; |
2755 | - |
2756 | - /* Check if the table is present in the database and if it's |
2757 | - * not, create it */ |
2758 | - db.prepare (@"SELECT * from sqlite_master WHERE name='$(table_name)';", |
2759 | - -1, out stmt, null); |
2760 | - |
2761 | - if (stmt.step () == DONE) { |
2762 | - init_database (); |
2763 | - } |
2764 | - } |
2765 | - } |
2766 | - |
2767 | - /** |
2768 | - * @brief Create table structure in the database. |
2769 | - */ |
2770 | - protected void init_database () { |
2771 | - Statement stmt; |
2772 | - string sql = @"CREATE TABLE $(table_name) ("; |
2773 | - foreach (Map.Entry<string, SqlColumn> e in columns.entries) { |
2774 | - sql += @"$(e.key) $(e.value.type), "; |
2775 | - } |
2776 | - |
2777 | - /* Remove last 2 characters ", " and add ); */ |
2778 | - sql = sql[0:-2]; |
2779 | - sql += ");"; |
2780 | - |
2781 | - /* Execute query */ |
2782 | - db.prepare (sql, -1, out stmt, null); |
2783 | - |
2784 | - if (stmt.step () != DONE) { |
2785 | - error (@"Error creating $(table_name) table in the database."); |
2786 | - } |
2787 | - } |
2788 | - |
2789 | - public string get_db_table_name () { |
2790 | - return this.table_name; |
2791 | - } |
2792 | - |
2793 | - public void set_text (string field, string val) { |
2794 | - if (!columns.has_key (field)) { |
2795 | - error (@"Error saving to field $(field) from table $(table_name)\n" + |
2796 | - "Selected field is not present in database"); |
2797 | - return; |
2798 | - } |
2799 | - SqlColumn col = columns.get (field); |
2800 | - col.v = val; |
2801 | - columns.set (field, col); |
2802 | - } |
2803 | - |
2804 | - public unowned string get_text (string field) { |
2805 | - if (!columns.has_key (field)) { |
2806 | - error (@"Error loading from field $(field) from table $(table_name)\n" + |
2807 | - "Selected field is not present in database"); |
2808 | - return ""; |
2809 | - } |
2810 | - SqlColumn col = columns.get (field); |
2811 | - if (col.v != null) |
2812 | - return col.v; |
2813 | - else |
2814 | - return ""; |
2815 | - } |
2816 | - |
2817 | - public unowned int get_integer (string field) { |
2818 | - if (!columns.has_key (field)) { |
2819 | - error (@"Error loading from field $(field) from table $(table_name)\n" + |
2820 | - "Selected field is not present in database"); |
2821 | - return 0; |
2822 | - } |
2823 | - SqlColumn col = columns.get (field); |
2824 | - return int.parse (col.v); |
2825 | - } |
2826 | - |
2827 | - public DateTime get_date (string field) { |
2828 | - if (!columns.has_key (field)) { |
2829 | - error (@"Error loading from field $(field) from table $(table_name)\n" + |
2830 | - "Selected field is not present in database"); |
2831 | - return new DateTime.now_utc (); |
2832 | - } |
2833 | - SqlColumn col = columns.get (field); |
2834 | - string [] fields = col.v.split(" "); |
2835 | - |
2836 | - int year = int.parse (fields[0]); |
2837 | - int month = int.parse (fields[1]); |
2838 | - int day = int.parse (fields[2]); |
2839 | - int hour = int.parse (fields[3]); |
2840 | - int minute = int.parse (fields[4]); |
2841 | - int seconds = int.parse (fields[5]); |
2842 | - |
2843 | - if (year < 1 || year > 9999 || |
2844 | - month < 1 || month > 12 || |
2845 | - day < 1 || day > 31 || |
2846 | - minute < 0 || minute > 59 || |
2847 | - seconds < 0 || seconds > 59) |
2848 | - return new DateTime.now_local (); |
2849 | - |
2850 | - return new DateTime.local (year, month, day, hour, minute, seconds); |
2851 | - } |
2852 | - |
2853 | - public void set_date (string field, DateTime date) { |
2854 | - if (!columns.has_key (field)) { |
2855 | - error (@"Error saving tofield $(field) from table $(table_name)\n" + |
2856 | - "Selected field is not present in database"); |
2857 | - return; |
2858 | - } |
2859 | - SqlColumn col = columns.get (field); |
2860 | - col.v = datetime_to_string (date); |
2861 | - } |
2862 | - |
2863 | - public static string datetime_to_string (DateTime date) { |
2864 | - return string.join(" ", |
2865 | - date.get_year ().to_string (), |
2866 | - "%.2d".printf (date.get_month ()), |
2867 | - "%.2d".printf (date.get_day_of_month()), |
2868 | - "%.2d".printf (date.get_hour ()), |
2869 | - "%.2d".printf (date.get_minute ()), |
2870 | - "%.2d".printf (date.get_second ())); |
2871 | - } |
2872 | - |
2873 | - public int get_id () { |
2874 | - return get_integer ("ID"); |
2875 | - } |
2876 | - |
2877 | - public void set_integer (string field, int64 val) { |
2878 | - if (!columns.has_key (field)) { |
2879 | - error (@"Error saving tofield $(field) from table $(table_name)\n" + |
2880 | - "Selected field is not present in database"); |
2881 | - return; |
2882 | - } |
2883 | - SqlColumn col = columns.get (field); |
2884 | - if (field == "ID" && val == 0) |
2885 | - col.v = "NULL"; |
2886 | - else |
2887 | - col.v = val.to_string (); |
2888 | - columns.set (field, col); |
2889 | - } |
2890 | - |
2891 | - public new string get (string field) { |
2892 | - return get_text (field); |
2893 | - } |
2894 | - |
2895 | - public new void set (string field, string value) { |
2896 | - set_text (field, value); |
2897 | - } |
2898 | - |
2899 | - /** |
2900 | - * @brief Save changes permanently in the database |
2901 | - */ |
2902 | - public void save () { |
2903 | - Statement stmt; |
2904 | - string sql = @"INSERT OR REPLACE INTO $(table_name) ("; |
2905 | - foreach (Map.Entry<string, SqlColumn> e in columns.entries) { |
2906 | - sql += @"$(e.key), "; |
2907 | - } |
2908 | - |
2909 | - sql = sql[0:-2]; |
2910 | - sql += ") VALUES ("; |
2911 | - |
2912 | - foreach (Map.Entry<string, SqlColumn> e in columns.entries) { |
2913 | - if (e.value.v != null) { |
2914 | - if (e.value.type == "TEXT") |
2915 | - sql += @"$(quote(e.value.v)), "; |
2916 | - else |
2917 | - sql += @"$(e.value.v), "; |
2918 | - } |
2919 | - else { |
2920 | - sql += ", "; |
2921 | - } |
2922 | - } |
2923 | - |
2924 | - sql = sql[0:-2]; sql += ");"; |
2925 | - db.prepare (sql, -1, out stmt, null); |
2926 | - if (stmt.step () != DONE) { |
2927 | - error (@"Error inserting values in the database $(table_name)\n Error $(db.errcode()): $(db.errmsg ())"); |
2928 | - } |
2929 | - |
2930 | - /* If we save with ID set to 0 then the ID will be autodetermined |
2931 | - * by sqlite so we should get it back */ |
2932 | - if (get_id () == 0) { |
2933 | - set_integer("ID", db.last_insert_rowid()); |
2934 | - } |
2935 | - } |
2936 | - |
2937 | - /** |
2938 | - * @brief Load data from database, overwriting local |
2939 | - * variables. |
2940 | - */ |
2941 | - public void load (int ID = 0) { |
2942 | - if (ID == 0) |
2943 | - ID = get_integer ("ID"); |
2944 | - |
2945 | - Statement stmt; |
2946 | - string sql = "SELECT "; |
2947 | - foreach (Map.Entry<string, SqlColumn> e in columns.entries) { |
2948 | - sql += @"$(e.key), "; |
2949 | - } |
2950 | - |
2951 | - sql = sql[0:-2]; |
2952 | - sql += @" FROM $(table_name) WHERE ID=$(ID);"; |
2953 | - |
2954 | - db.prepare (sql, -1, out stmt, null); |
2955 | - if (stmt.step () !=ROW) { |
2956 | - error (@"Error loading data from table $(table_name)."); |
2957 | - return; |
2958 | - } |
2959 | - |
2960 | - int i = 0; |
2961 | - foreach (Map.Entry<string, SqlColumn> e in columns.entries) { |
2962 | - if (e.value.type == "TEXT") |
2963 | - e.value.v = stmt.column_text (i).compress (); |
2964 | - else |
2965 | - e.value.v = stmt.column_text (i); |
2966 | - i++; |
2967 | - } |
2968 | - } |
2969 | - |
2970 | - /** |
2971 | - * @brief Delete this item permanently from the database. |
2972 | - */ |
2973 | - public void remove () { |
2974 | - Statement stmt; |
2975 | - string sql = @"DELETE from $(table_name) WHERE ID=$(get_id ());"; |
2976 | - |
2977 | - db.prepare (sql, -1, out stmt, null); |
2978 | - if (stmt.step () != DONE) { |
2979 | - error (@"Error deleting item from the database $(table_name)"); |
2980 | - } |
2981 | - } |
2982 | - |
2983 | - /** |
2984 | - * @brief Find IDs of elements in ex_table (that is assumed to be a table |
2985 | - * associateed to another SqlDataType object and return a vector |
2986 | - * containing their IDs. |
2987 | - */ |
2988 | - public GLib.List<int> associated_ids (string ex_table, string foreign_key) { |
2989 | - var ids = new GLib.List<int> (); |
2990 | - Statement stmt; |
2991 | - string sql = @"SELECT ID from $(ex_table) WHERE $(foreign_key)=$(get_id());"; |
2992 | - |
2993 | - db.prepare (sql, -1, out stmt, null); |
2994 | - while (stmt.step () == ROW) { |
2995 | - ids.append (stmt.column_int (0)); |
2996 | - } |
2997 | - return ids; |
2998 | - } |
2999 | - } |
3000 | -} |
3001 | |
3002 | === added file 'libclinica/SqliteDataProvider.vala' |
3003 | --- libclinica/SqliteDataProvider.vala 1970-01-01 00:00:00 +0000 |
3004 | +++ libclinica/SqliteDataProvider.vala 2012-02-23 21:39:18 +0000 |
3005 | @@ -0,0 +1,754 @@ |
3006 | +/* |
3007 | + * This file is part of Clinica. |
3008 | + * |
3009 | + * Clinica is free software: you can redistribute it and/or modify |
3010 | + * it under the terms of the GNU General Public License as published by |
3011 | + * the Free Software Foundation, either version 3 of the License, or |
3012 | + * (at your option) any later version. |
3013 | + * |
3014 | + * Clinica is distributed in the hope that it will be useful, |
3015 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3016 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3017 | + * GNU General Public License for more details. |
3018 | + * |
3019 | + * You should have received a copy of the GNU General Public License |
3020 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3021 | + * |
3022 | + * Authors: Leonardo Robol <leo@robol.it> |
3023 | + */ |
3024 | + |
3025 | +using Sqlite; |
3026 | +using Gtk; |
3027 | + |
3028 | +namespace Clinica { |
3029 | + |
3030 | + public class SqliteDataProvider : Object, DataProvider { |
3031 | + |
3032 | + public signal void error (string message); |
3033 | + |
3034 | + /** |
3035 | + * @brief Name of the table in the database where the visits |
3036 | + * will be stored. Please note that changing this will require |
3037 | + * a database upgrade, so should be handled correctly. |
3038 | + */ |
3039 | + internal string visit_table = "visits"; |
3040 | + |
3041 | + /** |
3042 | + * @brief Name of the table in the database where the patients |
3043 | + * will be stored. Please note that changing this will require |
3044 | + * a database upgrade, so should be handled correctly. |
3045 | + */ |
3046 | + internal string patient_table = "patients"; |
3047 | + |
3048 | + /** |
3049 | + * @brief Name of the table in the database where the doctors |
3050 | + * will be stored. Please note that changing this will require |
3051 | + * a database upgrade, so should be handled correctly. |
3052 | + */ |
3053 | + internal string doctor_table = "doctors"; |
3054 | + |
3055 | + /** |
3056 | + * @brief Name of the table in the database where the events |
3057 | + * will be stored. Please note that changing this will require |
3058 | + * a database upgrade, so should be handled correctly. |
3059 | + */ |
3060 | + internal string event_table = "events"; |
3061 | + |
3062 | + /** |
3063 | + * @brief The absolute path of the database (typically on Linux systems |
3064 | + * will be ~/.local/share/clinica/clinica.db. |
3065 | + */ |
3066 | + private string database_path; |
3067 | + |
3068 | + /** |
3069 | + * @brief The ResourceManager of this instance of the Clinica Application. |
3070 | + */ |
3071 | + private ResourceManager resource_manager { get; set; } |
3072 | + |
3073 | + /** |
3074 | + * @brief The Sqlite.Database object - this is used to interact with the database |
3075 | + * by the SqliteDataProvider and all the Sqlite*Iterator classes that are generated |
3076 | + * from here. |
3077 | + */ |
3078 | + internal Database db; |
3079 | + |
3080 | + /** |
3081 | + * @brief An array containing the supported versione of the db. This should |
3082 | + * contain the value db_version and means that this SqliteProvider is capable |
3083 | + * of Database migration from any of these old version to the most recent one. |
3084 | + */ |
3085 | + private const string [] supported_db_versions = { "0.1", "0.2" }; |
3086 | + |
3087 | + /** |
3088 | + * @brief The version of the database that is in use now, or that should |
3089 | + * be used to compatbile with this SqliteDataProvider. |
3090 | + * |
3091 | + * Please note that Database version are not the same of Clinica versions. |
3092 | + * Typically the same clinica versions will use the same Database version, |
3093 | + * but the other way is not always true. |
3094 | + */ |
3095 | + private const string db_version = "0.2"; |
3096 | + |
3097 | + |
3098 | + public SqliteDataProvider (ResourceManager resources) { |
3099 | + resource_manager = resources; |
3100 | + error.connect ((t,l) => resource_manager.error_callback (t,l)); |
3101 | + |
3102 | + /* Find the database in all the possible paths for the various |
3103 | + * versions of Clinica, and then possibly do un upgrade, querying |
3104 | + * the user if necessary. */ |
3105 | + check_database_path (); |
3106 | + check_updates (); |
3107 | + |
3108 | + /* This is used to create the tables if they do not exists */ |
3109 | + init_resources (); |
3110 | + } |
3111 | + |
3112 | + /** |
3113 | + * @brief Get the identifier for this DataProvider to be displayed |
3114 | + * to the user. |
3115 | + * |
3116 | + * It has not to be translated since it will be used to detect which |
3117 | + * will be used on startup. |
3118 | + */ |
3119 | + public string get_name () { return "Local database"; } |
3120 | + |
3121 | + /** |
3122 | + * @brief Check if there is the need to upgrade the database from on of |
3123 | + * the supported version to the most recent one. |
3124 | + */ |
3125 | + private void check_updates () { |
3126 | + /* Read database version if existant, saved actual version otherwise. |
3127 | + * This may be used in future to perform one-time upgrade of the database */ |
3128 | + var version_db_file = Path.build_filename (resource_manager.local_config_directory, |
3129 | + ".clinica_db_version"); |
3130 | + |
3131 | + if (!FileUtils.test (version_db_file, FileTest.IS_REGULAR)) { |
3132 | + /* Create the file with the version of the database */ |
3133 | + try { |
3134 | + FileUtils.set_contents(version_db_file, db_version); |
3135 | + } catch (Error e) { |
3136 | + error (_("Error creating some configuration files, check permission on %s").printf (version_db_file)); |
3137 | + } |
3138 | + } |
3139 | + else { |
3140 | + string content; |
3141 | + try { |
3142 | + FileUtils.get_contents(version_db_file, out content); |
3143 | + } catch (Error e) { |
3144 | + error (_("Error reading some configuration files, check permission on %s".printf(version_db_file))); |
3145 | + } |
3146 | + |
3147 | + bool upgraded_correcty = true; |
3148 | + if (db_version != content) { |
3149 | + /* Ask the user if he really wants to upgrade */ |
3150 | + if (!ask_for_upgrade()) { |
3151 | + debug ("The user doesn't want to upgrade, exiting."); |
3152 | + Posix.exit (0); |
3153 | + } |
3154 | + |
3155 | + upgraded_correcty = false; |
3156 | + /* Try to determine if the version of the local database is supported */ |
3157 | + if (content in supported_db_versions) { |
3158 | + if (upgrade_database (content)) { |
3159 | + upgraded_correcty = true; |
3160 | + try { |
3161 | + FileUtils.set_contents (version_db_file, db_version); |
3162 | + } catch (GLib.Error e) { |
3163 | + error (_("Failure while settings new database version to %s").printf (db_version)); |
3164 | + } |
3165 | + } else { |
3166 | + error (_("Failure while upgrading database")); |
3167 | + } |
3168 | + } |
3169 | + else |
3170 | + error (_("Version of the database is not compatible")); |
3171 | + } |
3172 | + |
3173 | + if (!upgraded_correcty) { |
3174 | + debug ("Upgrade failed, exiting."); |
3175 | + Posix.exit (1); |
3176 | + } |
3177 | + } |
3178 | + } |
3179 | + |
3180 | + /** |
3181 | + * @brief This routine is used to ask confirmation to the user for the database |
3182 | + * upgrade. Since the upgrade will make the older version of clinica unusable, we |
3183 | + * should always ask before performing one. |
3184 | + */ |
3185 | + private bool ask_for_upgrade () { |
3186 | + var mb = new MessageDialog (null, |
3187 | + DialogFlags.DESTROY_WITH_PARENT | |
3188 | + DialogFlags.MODAL, |
3189 | + MessageType.QUESTION, |
3190 | + ButtonsType.YES_NO, |
3191 | + "%s", "Database upgrade"); |
3192 | + 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")); |
3193 | + mb.set_title (_("Upgrade database")); |
3194 | + if (mb.run () == ResponseType.YES) { |
3195 | + mb.destroy (); |
3196 | + return true; |
3197 | + } |
3198 | + else { |
3199 | + mb.destroy (); |
3200 | + return false; |
3201 | + } |
3202 | + } |
3203 | + |
3204 | + /** |
3205 | + * @brief Check if the database is in the right path. If it is not there |
3206 | + * move it and the set database_path. |
3207 | + */ |
3208 | + private void check_database_path () { |
3209 | + database_path = Path.build_filename (resource_manager.local_data_directory, |
3210 | + "clinica.db"); |
3211 | + File db_file = File.new_for_path (database_path); |
3212 | + if (!db_file.query_exists ()) { |
3213 | + File old_db_file = File.new_for_path (Path.build_filename (resource_manager.local_config_directory, |
3214 | + "clinica.db")); |
3215 | + if (old_db_file.query_exists ()) { |
3216 | + |
3217 | + var mb = new MessageDialog (null, DialogFlags.DESTROY_WITH_PARENT | DialogFlags.MODAL, |
3218 | + MessageType.QUESTION, ButtonsType.YES_NO, "%s", _("Database needs to be moved")); |
3219 | + mb.format_secondary_markup (_("An older version of clinica has been detected and the old database has to be moved\nto a new location to continue.\n<b>The older version of clinica won't work anymore with this setup</b>.\nDo you still want to continue?")); |
3220 | + if (mb.run () != Gtk.ResponseType.YES) { |
3221 | + mb.destroy (); |
3222 | + Posix.exit (1); |
3223 | + } |
3224 | + |
3225 | + mb.destroy (); |
3226 | + |
3227 | + debug ("Moving old database to its new location (starting from clinica 0.2.9)"); |
3228 | + try { |
3229 | + old_db_file.copy (db_file, FileCopyFlags.ALL_METADATA); |
3230 | + FileUtils.remove (old_db_file.get_path ()); |
3231 | + } catch (GLib.Error e) { |
3232 | + error (_("Error while transferring the database to the new default location for clinica >= 0.2.9")); |
3233 | + } |
3234 | + } |
3235 | + } |
3236 | + } |
3237 | + |
3238 | + /** |
3239 | + * @brief Do upgrade the database starting from db_version. |
3240 | + */ |
3241 | + private bool upgrade_database (string db_version) { |
3242 | + /* Try to open the database first */ |
3243 | + if (!(Database.open (database_path, out db) == OK)) { |
3244 | + error (_("Error upgrading database, please check your installation")); |
3245 | + } |
3246 | + |
3247 | + string sql; |
3248 | + Statement stmt; |
3249 | + int64 rc; |
3250 | + |
3251 | + /* Performing upgrade from 0.1 */ |
3252 | + if (db_version == "0.1") { |
3253 | + /* We need to create the new table for the events */ |
3254 | + sql = "CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, title TEXT, description TEXT, venue TEXT, patient INTEGER, visit INTEGER, date TEXT);"; |
3255 | + db.prepare (sql, -1, out stmt, null); |
3256 | + rc = stmt.step (); |
3257 | + |
3258 | + if (rc != DONE) { |
3259 | + error (_("Error upgrading the database from version 0.1 to 0.2, sqlite exit code: %I64d".printf (rc))); |
3260 | + return false; |
3261 | + } else { |
3262 | + db_version = "0.2"; |
3263 | + } |
3264 | + } |
3265 | + |
3266 | + return true; |
3267 | + } |
3268 | + |
3269 | + /** |
3270 | + * @brief Check that all the resources needed by Clinica |
3271 | + * are actually available, and if they are not create them. |
3272 | + */ |
3273 | + public void init_resources () { |
3274 | + int64 rc; |
3275 | + Statement stmt; |
3276 | + string sql; |
3277 | + |
3278 | + /* Open database and, if it does not exists, create it */ |
3279 | + if (!(Database.open (database_path, out db) == OK)) { |
3280 | + error ("Error opening database."); |
3281 | + }; |
3282 | + |
3283 | + /* Check if the required tables exists */ |
3284 | + sql = "SELECT * from sqlite_master WHERE type='table';"; |
3285 | + db.prepare (sql, -1, out stmt, null); |
3286 | + rc = stmt.step (); |
3287 | + |
3288 | + if (rc == DONE) { |
3289 | + /* That means no tables in the database */ |
3290 | + init_database (); |
3291 | + } |
3292 | + } |
3293 | + |
3294 | + |
3295 | + /** |
3296 | + * @brief Init the database with the required tables |
3297 | + */ |
3298 | + private void init_database () { |
3299 | + |
3300 | + if (db.exec ("CREATE TABLE IF NOT EXISTS doctors (surname TEXT, ID INTEGER PRIMARY KEY, phone TEXT, mobile TEXT, given_name TEXT)") != 0) |
3301 | + error ("Error creating the doctors table"); |
3302 | + if (db.exec ("CREATE TABLE IF NOT EXISTS patients (gender TEXT, doctor INTEGER, surname TEXT, ID INTEGER PRIMARY KEY, identification_code TEXT, phone TEXT, given_name TEXT, birth_date TEXT, residence_address TEXT)") != 0) |
3303 | + error ("Error creating the patients table"); |
3304 | + if (db.exec ("CREATE TABLE IF NOT EXISTS visits (subsequent_checks TEXT, systemic_therapy TEXT, ID INTEGER PRIMARY KEY, laboratory_exam TEXT, diagnosis TEXT, histopathology TEXT, anamnesis TEXT, date TEXT, patient INTEGER, physical_examination TEXT, topical_therapy TEXT)") != 0) |
3305 | + error ("Error creating the visits table"); |
3306 | + if (db.exec ("CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, title TEXT, description TEXT, venue TEXT, patient INTEGER, visit INTEGER, date TEXT)") != 0) |
3307 | + error ("Error creating the events table"); |
3308 | + |
3309 | + } |
3310 | + |
3311 | + /** |
3312 | + * @brief Internal routine used to convert DateTime objects |
3313 | + * to strings that are to be saved in the database. |
3314 | + */ |
3315 | + private static string datetime_to_string (DateTime date) { |
3316 | + return string.join(" ", |
3317 | + date.get_year ().to_string (), |
3318 | + "%.2d".printf (date.get_month ()), |
3319 | + "%.2d".printf (date.get_day_of_month()), |
3320 | + "%.2d".printf (date.get_hour ()), |
3321 | + "%.2d".printf (date.get_minute ()), |
3322 | + "%.2d".printf (date.get_second ())); |
3323 | + } |
3324 | + |
3325 | + /** |
3326 | + * @brief Convert strings encoded with datetime_to_string () back |
3327 | + * to DateTime objects. |
3328 | + */ |
3329 | + private static DateTime string_to_datetime (string input) { |
3330 | + string [] fields = input.split(" "); |
3331 | + |
3332 | + int year = int.parse (fields[0]); |
3333 | + int month = int.parse (fields[1]); |
3334 | + int day = int.parse (fields[2]); |
3335 | + int hour = int.parse (fields[3]); |
3336 | + int minute = int.parse (fields[4]); |
3337 | + int seconds = int.parse (fields[5]); |
3338 | + |
3339 | + if (year < 1 || year > 9999 || |
3340 | + month < 1 || month > 12 || |
3341 | + day < 1 || day > 31 || |
3342 | + minute < 0 || minute > 59 || |
3343 | + seconds < 0 || seconds > 59) |
3344 | + return new DateTime.now_local (); |
3345 | + |
3346 | + return new DateTime.local (year, month, day, hour, minute, seconds); |
3347 | + } |
3348 | + |
3349 | + /* IMPLEMENTATION OF THE ABSTRACT INTERFACES OF DataProvider */ |
3350 | + |
3351 | + public Doctor get_doctor (int64 id) { |
3352 | + var doc = new Doctor (); |
3353 | + Statement stmt; |
3354 | + db.prepare (@"SELECT given_name, surname, phone, mobile FROM $(doctor_table) WHERE id=$(id);", -1, |
3355 | + out stmt, null); |
3356 | + if (!(stmt.step () == ROW)) { |
3357 | + error (_("Error while retrieving the doctor with id = %I64d").printf (id, db.errmsg ())); |
3358 | + } |
3359 | + |
3360 | + /* Load data from the database into the fields */ |
3361 | + doc.id = id; |
3362 | + doc.given_name = stmt.column_text (0).compress (); |
3363 | + doc.surname = stmt.column_text (1).compress (); |
3364 | + doc.phone = stmt.column_text (2).compress (); |
3365 | + doc.mobile = stmt.column_text (3).compress (); |
3366 | + |
3367 | + doc.provider = this; |
3368 | + |
3369 | + return doc; |
3370 | + } |
3371 | + |
3372 | + public int64 save_doctor (Doctor doctor) { |
3373 | + Statement stmt; |
3374 | + |
3375 | + if (doctor.id != 0) |
3376 | + db.prepare ("""INSERT OR REPLACE INTO %s (id, given_name, surname, phone, mobile) |
3377 | + VALUES (:id, :given_name, :surname, :phone, :mobile);""".printf (doctor_table), |
3378 | + -1, out stmt); |
3379 | + else |
3380 | + db.prepare ("""INSERT OR REPLACE INTO %s (given_name, surname, phone, mobile) |
3381 | + VALUES (:given_name, :surname, :phone, :mobile);""".printf (doctor_table), |
3382 | + -1, out stmt); |
3383 | + |
3384 | + |
3385 | + |
3386 | + /* Bind values present in doctor in the SQL statement */ |
3387 | + int i = 1; |
3388 | + if (doctor.id != 0) |
3389 | + stmt.bind_int64 (i++, doctor.id); |
3390 | + stmt.bind_text (i++, doctor.given_name); |
3391 | + stmt.bind_text (i++, doctor.surname); |
3392 | + stmt.bind_text (i++, doctor.phone); |
3393 | + stmt.bind_text (i++, doctor.mobile); |
3394 | + |
3395 | + if (stmt.step () != DONE) { |
3396 | + error (_("An error occurred while saving the doctor with id %d: %s").printf (doctor.id, db.errmsg ())); |
3397 | + return -1; |
3398 | + } |
3399 | + |
3400 | + if (doctor.id == 0) { |
3401 | + doctor.id = db.last_insert_rowid (); |
3402 | + doctor_added (doctor.id); |
3403 | + } |
3404 | + else |
3405 | + doctor_changed (doctor.id); |
3406 | + |
3407 | + return doctor.id; |
3408 | + } |
3409 | + |
3410 | + public int64 remove_doctor (Doctor doctor) { |
3411 | + Statement stmt; |
3412 | + |
3413 | + /* Keep a list of the patient ID we need to notify */ |
3414 | + var patients = new List<int64?> (); |
3415 | + foreach (var patient in doctor.patients ()) { |
3416 | + patients.append (patient.id); |
3417 | + } |
3418 | + |
3419 | + /* Wrap all this in a transaction so the DB doesn't change until |
3420 | + * we commit */ |
3421 | + db.exec ("BEGIN TRANSACTION"); |
3422 | + |
3423 | + string sql = @"DELETE from $(doctor_table) WHERE ID=$(doctor.id);"; |
3424 | + |
3425 | + db.prepare (sql, -1, out stmt, null); |
3426 | + if (stmt.step () != DONE) { |
3427 | + error (@"Error deleting doctor with id $(doctor.id)"); |
3428 | + db.exec ("ROLLBACK TRANSACTION"); |
3429 | + return -1; |
3430 | + } |
3431 | + |
3432 | + /* Now we need to deassociate its patients from him/her */ |
3433 | + if (db.exec (@"UPDATE $(patient_table) SET doctor = 0 WHERE doctor = $(doctor.id);") != 0) { |
3434 | + error (@"Error deassociating the patients from the doctor with ID = $(doctor.id)"); |
3435 | + db.exec ("ROLLBACK TRANSACTION"); |
3436 | + return -1; |
3437 | + } |
3438 | + |
3439 | + db.exec ("COMMIT TRANSACTION"); |
3440 | + |
3441 | + doctor_removed (doctor.id); |
3442 | + |
3443 | + /* Notify changes on the patients */ |
3444 | + foreach (var patient_id in patients) { |
3445 | + patient_changed (patient_id); |
3446 | + } |
3447 | + return 0; |
3448 | + } |
3449 | + |
3450 | + public PatientIterator patients (Doctor? doctor = null) { |
3451 | + return new SqlitePatientIterator (this, (doctor == null) ? "" : @"WHERE doctor = $(doctor.id)"); |
3452 | + } |
3453 | + |
3454 | + public DoctorIterator doctors () { |
3455 | + return new SqliteDoctorIterator (this); |
3456 | + } |
3457 | + |
3458 | + public Patient get_patient (int64 id) { |
3459 | + var patient = new Patient (); |
3460 | + Statement stmt; |
3461 | + db.prepare ("""SELECT given_name, surname, birth_date, gender, phone, residence_address, |
3462 | + identification_code, doctor FROM %s WHERE id=%I64d;""".printf (patient_table, id), |
3463 | + -1, out stmt, null); |
3464 | + if (!(stmt.step () == ROW)) { |
3465 | + error (_("Error while retrieving the patient with id = %I64d").printf (id, db.errmsg ())); |
3466 | + } |
3467 | + |
3468 | + /* Load data from the database into the fields */ |
3469 | + patient.id = id; |
3470 | + patient.given_name = stmt.column_text (0).compress (); |
3471 | + patient.surname = stmt.column_text (1).compress (); |
3472 | + patient.birth_date = string_to_datetime (stmt.column_text (2).compress ()); |
3473 | + patient.gender = (stmt.column_text (3) == "MALE") ? Gender.MALE : Gender.FEMALE; |
3474 | + patient.phone = stmt.column_text (4).compress (); |
3475 | + patient.residence_address = stmt.column_text (5).compress (); |
3476 | + patient.identification_code = stmt.column_text (6).compress (); |
3477 | + patient.doctor = (stmt.column_int64 (7) == 0) ? null : get_doctor (stmt.column_int64 (7)); |
3478 | + |
3479 | + patient.provider = this; |
3480 | + |
3481 | + return patient; |
3482 | + } |
3483 | + |
3484 | + public int64 save_patient (Patient patient) { |
3485 | + Statement stmt; |
3486 | + |
3487 | + if (patient.id != 0) |
3488 | + db.prepare ("""INSERT OR REPLACE INTO %s |
3489 | + (ID, given_name, surname, birth_date, gender, phone, residence_address, identification_code, doctor) |
3490 | + VALUES (:id, :given_name, :surname, :birth_date, :gender, :phone, :residence_address, :identification_code, :doctor);""".printf (patient_table), |
3491 | + -1, out stmt); |
3492 | + else |
3493 | + db.prepare ("""INSERT OR REPLACE INTO %s |
3494 | + (given_name, surname, birth_date, gender, phone, residence_address, identification_code, doctor) |
3495 | + VALUES (:given_name, :surname, :birth_date, :gender, :phone, :residence_address, :identification_code, :doctor);""".printf (patient_table), |
3496 | + -1, out stmt); |
3497 | + |
3498 | + |
3499 | + /* Bind values present in doctor in the SQL statement */ |
3500 | + int i = 1; |
3501 | + if (patient.id != 0) |
3502 | + stmt.bind_int64 (i++, patient.id); |
3503 | + stmt.bind_text (i++, patient.given_name); |
3504 | + stmt.bind_text (i++, patient.surname); |
3505 | + stmt.bind_text (i++, datetime_to_string (patient.birth_date)); |
3506 | + stmt.bind_text (i++, (patient.gender == Gender.MALE) ? "MALE" : "FEMALE"); |
3507 | + stmt.bind_text (i++, patient.phone); |
3508 | + stmt.bind_text (i++, patient.residence_address); |
3509 | + stmt.bind_text (i++, patient.identification_code); |
3510 | + stmt.bind_int64 (i++, (patient.doctor == null) ? 0 : patient.doctor.id); |
3511 | + |
3512 | + if (stmt.step () != DONE) { |
3513 | + error (_("An error occurred while saving the doctor with id %I64d: %s").printf (patient.id, db.errmsg ())); |
3514 | + return -1; |
3515 | + } |
3516 | + |
3517 | + if (patient.id == 0) { |
3518 | + patient.id = db.last_insert_rowid (); |
3519 | + patient_added (patient.id); |
3520 | + } |
3521 | + else |
3522 | + patient_changed (patient.id); |
3523 | + |
3524 | + return patient.id; |
3525 | + } |
3526 | + |
3527 | + public int64 remove_patient (Patient patient) { |
3528 | + |
3529 | + db.exec ("BEGIN TRANSACTION"); |
3530 | + |
3531 | + if (db.exec (@"DELETE from $(patient_table) WHERE ID=$(patient.id)") != 0) { |
3532 | + error (@"Error deleting patient with id $(patient.id)"); |
3533 | + db.exec ("ROLLBACK TRANSACTION"); |
3534 | + return -1; |
3535 | + } |
3536 | + |
3537 | + /* Try to remove all the visits of the patient */ |
3538 | + if (db.exec (@"DELETE FROM $(visit_table) WHERE patient=$(patient.id)") != 0) { |
3539 | + error (@"Error deleting the visits associated to the patient"); |
3540 | + db.exec ("ROLLBACK TRANSACTION"); |
3541 | + return -1; |
3542 | + } |
3543 | + |
3544 | + /* Deassoociate all the events associated with this patient */ |
3545 | + if (db.exec (@"UPDATE $(event_table) SET patient=0 WHERE patient=$(patient.id)") != 0) { |
3546 | + error (@"Error deassociating the events from the deleted patient"); |
3547 | + db.exec ("ROLLBACK TRANSACTION"); |
3548 | + return -1; |
3549 | + } |
3550 | + |
3551 | + db.exec ("COMMIT TRANSACTION"); |
3552 | + |
3553 | + patient_removed (patient.id); |
3554 | + return 0; |
3555 | + } |
3556 | + |
3557 | + public VisitIterator visits (Patient? patient, DateTime? start = null, DateTime? end = null) { |
3558 | + string sql_clause = (patient == null && start == null && end == null) ? "" : "WHERE"; |
3559 | + |
3560 | + if (patient != null) { |
3561 | + sql_clause += @" patient = $(patient.id)"; |
3562 | + if (start != null || end != null) |
3563 | + sql_clause += " AND "; |
3564 | + } |
3565 | + |
3566 | + if (start == null && end == null) |
3567 | + return new SqliteVisitIterator (this, sql_clause); |
3568 | + else if (start != null && end == null) |
3569 | + return new SqliteVisitIterator (this, sql_clause + @" date >= '$(datetime_to_string (start))'"); |
3570 | + else if (start == null && end != null) |
3571 | + return new SqliteVisitIterator (this, sql_clause + @" date < '$(datetime_to_string (end))'"); |
3572 | + else |
3573 | + return new SqliteVisitIterator (this, sql_clause + @" date BETWEEN " + |
3574 | + @"'$(datetime_to_string (start))' AND '$(datetime_to_string (end))'"); |
3575 | + } |
3576 | + |
3577 | + public Visit get_visit (int64 id) { |
3578 | + var visit = new Visit (); |
3579 | + Statement stmt; |
3580 | + db.prepare ("""SELECT anamnesis, physical_examination, laboratory_exam, histopathology, diagnosis, |
3581 | + topical_therapy, systemic_therapy, subsequent_checks, date, patient |
3582 | + FROM %s WHERE id=%I64d;""".printf (visit_table, id), -1, |
3583 | + out stmt, null); |
3584 | + if (!(stmt.step () == ROW)) { |
3585 | + error (_("Error while retrieving the visit with id = %I64d").printf (id, db.errmsg ())); |
3586 | + } |
3587 | + |
3588 | + /* Load data from the database into the fields */ |
3589 | + visit.id = id; |
3590 | + visit.anamnesis = stmt.column_text (0).compress (); |
3591 | + visit.physical_examination = stmt.column_text (1).compress (); |
3592 | + visit.laboratory_exam = stmt.column_text (2).compress (); |
3593 | + visit.histopathology = stmt.column_text (3).compress (); |
3594 | + visit.diagnosis = stmt.column_text (4).compress (); |
3595 | + visit.topical_therapy = stmt.column_text (5).compress (); |
3596 | + visit.systemic_therapy = stmt.column_text (6).compress (); |
3597 | + visit.subsequent_checks = stmt.column_text (7).compress (); |
3598 | + visit.date = string_to_datetime (stmt.column_text (8).compress ()); |
3599 | + visit.patient = get_patient (stmt.column_int64 (9)); |
3600 | + |
3601 | + visit.provider = this; |
3602 | + |
3603 | + return visit; |
3604 | + } |
3605 | + |
3606 | + public int64 save_visit (Visit visit) { |
3607 | + Statement stmt; |
3608 | + if (visit.id != 0) |
3609 | + db.prepare ("""INSERT OR REPLACE INTO %s |
3610 | + (id, anamnesis, physical_examination, laboratory_exam, histopathology, diagnosis, |
3611 | + topical_therapy, systemic_therapy, subsequent_checks, date, patient) |
3612 | + VALUES (:id, :anamnesis, :physical_examination, :laboratory_exam, :histopathology, :diagnosis, |
3613 | + :topical_therapy, :systemic_therapy, :subsequent_checks, :date, :patient);""".printf (visit_table), |
3614 | + -1, out stmt); |
3615 | + else |
3616 | + db.prepare ("""INSERT OR REPLACE INTO %s |
3617 | + (anamnesis, physical_examination, laboratory_exam, histopathology, diagnosis, |
3618 | + topical_therapy, systemic_therapy, subsequent_checks, date, patient) |
3619 | + VALUES (:anamnesis, :physical_examination, :laboratory_exam, :histopathology, :diagnosis, |
3620 | + :topical_therapy, :systemic_therapy, :subsequent_checks, :date, :patient);""".printf (visit_table), |
3621 | + -1, out stmt); |
3622 | + |
3623 | + /* Bind values present in doctor in the SQL statement */ |
3624 | + int i = 1; |
3625 | + if (visit.id != 0) |
3626 | + stmt.bind_int64 (i++, visit.id); |
3627 | + stmt.bind_text (i++, visit.anamnesis); |
3628 | + stmt.bind_text (i++, visit.physical_examination); |
3629 | + stmt.bind_text (i++, visit.laboratory_exam); |
3630 | + stmt.bind_text (i++, visit.histopathology); |
3631 | + stmt.bind_text (i++, visit.diagnosis); |
3632 | + stmt.bind_text (i++, visit.topical_therapy); |
3633 | + stmt.bind_text (i++, visit.systemic_therapy); |
3634 | + stmt.bind_text (i++, visit.subsequent_checks); |
3635 | + stmt.bind_text (i++, datetime_to_string (visit.date)); |
3636 | + stmt.bind_int64 (i++, visit.patient.id); |
3637 | + |
3638 | + if (stmt.step () != DONE) { |
3639 | + error (_("An error occurred while saving the doctor with id %I64d: %s").printf (visit.id, db.errmsg ())); |
3640 | + return -1; |
3641 | + } |
3642 | + |
3643 | + if (visit.id == 0) { |
3644 | + visit.id = db.last_insert_rowid (); |
3645 | + visit_added (visit.id); |
3646 | + } |
3647 | + else |
3648 | + visit_changed (visit.id); |
3649 | + |
3650 | + return visit.id; |
3651 | + } |
3652 | + |
3653 | + public int64 remove_visit (Visit visit) { |
3654 | + Statement stmt; |
3655 | + string sql = @"DELETE from $(visit_table) WHERE ID=$(visit.id);"; |
3656 | + |
3657 | + db.prepare (sql, -1, out stmt, null); |
3658 | + if (stmt.step () != DONE) { |
3659 | + error (@"Error deleting visit with id $(visit.id)"); |
3660 | + return -1; |
3661 | + } |
3662 | + |
3663 | + visit_removed (visit.id); |
3664 | + return 0; |
3665 | + } |
3666 | + |
3667 | + public Event get_event (int64 id) { |
3668 | + var event = new Event (); |
3669 | + Statement stmt; |
3670 | + db.prepare (@"SELECT title, description, venue, patient, visit, date FROM $(event_table) WHERE id=$(id);", -1, |
3671 | + out stmt, null); |
3672 | + if (!(stmt.step () == ROW)) { |
3673 | + error (_("Error while retrieving the event with id = %d").printf (id, db.errmsg ())); |
3674 | + } |
3675 | + |
3676 | + /* Load data from the database into the fields */ |
3677 | + event.id = id; |
3678 | + event.title = stmt.column_text (0).compress (); |
3679 | + event.description = stmt.column_text (1).compress (); |
3680 | + event.venue = stmt.column_text (2).compress (); |
3681 | + event.patient = (stmt.column_int64 (3) != 0) ? get_patient (stmt.column_int64 (3)) : null; |
3682 | + event.visit = (stmt.column_int64 (4) != 0) ? get_visit (stmt.column_int64 (4)) : null; |
3683 | + event.date = string_to_datetime (stmt.column_text (5).compress ()); |
3684 | + |
3685 | + event.provider = this; |
3686 | + |
3687 | + return event; |
3688 | + } |
3689 | + |
3690 | + public int64 save_event (Event event) { |
3691 | + Statement stmt; |
3692 | + |
3693 | + if (event.id != 0) |
3694 | + db.prepare ("""INSERT OR REPLACE INTO %s (id, title, description, venue, patient, visit, date) |
3695 | + VALUES (:id, :title, :description, :venue, :patient, :visit, :date);""".printf (event_table), |
3696 | + -1, out stmt); |
3697 | + else |
3698 | + db.prepare ("""INSERT OR REPLACE INTO %s (title, description, venue, patient, visit, date) |
3699 | + VALUES (:title, :description, :venue, :patient, :visit, :date);""".printf (event_table), |
3700 | + -1, out stmt); |
3701 | + |
3702 | + /* Bind values present in doctor in the SQL statement */ |
3703 | + int i = 1; |
3704 | + if (event.id != 0) |
3705 | + stmt.bind_int64 (i++, event.id); |
3706 | + stmt.bind_text (i++, event.title); |
3707 | + stmt.bind_text (i++, event.description); |
3708 | + stmt.bind_text (i++, event.venue); |
3709 | + stmt.bind_int64 (i++, (event.patient == null) ? 0 : event.patient.id); |
3710 | + stmt.bind_int64 (i++, (event.visit == null) ? 0 : event.visit.id); |
3711 | + stmt.bind_text (i++, datetime_to_string (event.date)); |
3712 | + |
3713 | + if (stmt.step () != DONE) { |
3714 | + error (_("An error occurred while saving the event with id %I64d: %s").printf (event.id, db.errmsg ())); |
3715 | + return -1; |
3716 | + } |
3717 | + |
3718 | + if (event.id == 0) { |
3719 | + event.id = db.last_insert_rowid (); |
3720 | + event_added (event.id); |
3721 | + } |
3722 | + else |
3723 | + event_changed (event.id); |
3724 | + |
3725 | + return event.id; |
3726 | + } |
3727 | + |
3728 | + |
3729 | + public int64 remove_event (Event event) { |
3730 | + Statement stmt; |
3731 | + string sql = @"DELETE from $(event_table) WHERE ID=$(event.id);"; |
3732 | + |
3733 | + db.prepare (sql, -1, out stmt, null); |
3734 | + if (stmt.step () != DONE) { |
3735 | + error (@"Error deleting event with id $(event.id)"); |
3736 | + return -1; |
3737 | + } |
3738 | + |
3739 | + event_removed (event.id); |
3740 | + return 0; |
3741 | + } |
3742 | + |
3743 | + public EventIterator events (DateTime? start = null, DateTime? end = null) { |
3744 | + string sql_clause = ""; |
3745 | + |
3746 | + if (start == null && end == null) |
3747 | + return new SqliteEventIterator (this, sql_clause); |
3748 | + else if (start != null && end == null) |
3749 | + return new SqliteEventIterator (this, sql_clause + @" WHERE date >= '$(datetime_to_string (start))'"); |
3750 | + else if (start == null && end != null) |
3751 | + return new SqliteEventIterator (this, sql_clause + @" WHERE date < '$(datetime_to_string (end))'"); |
3752 | + else |
3753 | + return new SqliteEventIterator (this, sql_clause + @" WHERE date BETWEEN " + |
3754 | + @"'$(datetime_to_string (start))' AND '$(datetime_to_string (end))'"); |
3755 | + } |
3756 | + |
3757 | + } |
3758 | + |
3759 | +} |
3760 | |
3761 | === added file 'libclinica/SqliteDoctorIterator.vala' |
3762 | --- libclinica/SqliteDoctorIterator.vala 1970-01-01 00:00:00 +0000 |
3763 | +++ libclinica/SqliteDoctorIterator.vala 2012-02-23 21:39:18 +0000 |
3764 | @@ -0,0 +1,45 @@ |
3765 | +/* |
3766 | + * This file is part of Clinica. |
3767 | + * |
3768 | + * Clinica is free software: you can redistribute it and/or modify |
3769 | + * it under the terms of the GNU General Public License as published by |
3770 | + * the Free Software Foundation, either version 3 of the License, or |
3771 | + * (at your option) any later version. |
3772 | + * |
3773 | + * Clinica is distributed in the hope that it will be useful, |
3774 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3775 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3776 | + * GNU General Public License for more details. |
3777 | + * |
3778 | + * You should have received a copy of the GNU General Public License |
3779 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3780 | + * |
3781 | + * Authors: Leonardo Robol <leo@robol.it> |
3782 | + */ |
3783 | + |
3784 | +using Sqlite; |
3785 | + |
3786 | +namespace Clinica { |
3787 | + |
3788 | + public class SqliteDoctorIterator : Object, DoctorIterator { |
3789 | + |
3790 | + private SqliteDataProvider provider; |
3791 | + private Statement stmt; |
3792 | + |
3793 | + public SqliteDoctorIterator (SqliteDataProvider provider, string clause = "") { |
3794 | + this.provider = provider; |
3795 | + provider.db.prepare ("SELECT id from %s %s;".printf (provider.doctor_table, clause), |
3796 | + -1, out stmt); |
3797 | + } |
3798 | + |
3799 | + public bool next () { |
3800 | + return (stmt.step () == ROW); |
3801 | + } |
3802 | + |
3803 | + public new Doctor get () { |
3804 | + int id = stmt.column_int (0); |
3805 | + return provider.get_doctor (id); |
3806 | + } |
3807 | + } |
3808 | + |
3809 | +} |
3810 | |
3811 | === added file 'libclinica/SqlitePatientIterator.vala' |
3812 | --- libclinica/SqlitePatientIterator.vala 1970-01-01 00:00:00 +0000 |
3813 | +++ libclinica/SqlitePatientIterator.vala 2012-02-23 21:39:18 +0000 |
3814 | @@ -0,0 +1,45 @@ |
3815 | +/* |
3816 | + * This file is part of Clinica. |
3817 | + * |
3818 | + * Clinica is free software: you can redistribute it and/or modify |
3819 | + * it under the terms of the GNU General Public License as published by |
3820 | + * the Free Software Foundation, either version 3 of the License, or |
3821 | + * (at your option) any later version. |
3822 | + * |
3823 | + * Clinica is distributed in the hope that it will be useful, |
3824 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3825 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3826 | + * GNU General Public License for more details. |
3827 | + * |
3828 | + * You should have received a copy of the GNU General Public License |
3829 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3830 | + * |
3831 | + * Authors: Leonardo Robol <leo@robol.it> |
3832 | + */ |
3833 | + |
3834 | +using Sqlite; |
3835 | + |
3836 | +namespace Clinica { |
3837 | + |
3838 | + public class SqlitePatientIterator : Object, PatientIterator { |
3839 | + |
3840 | + private SqliteDataProvider provider; |
3841 | + private Statement stmt; |
3842 | + |
3843 | + public SqlitePatientIterator (SqliteDataProvider provider, string clause = "") { |
3844 | + this.provider = provider; |
3845 | + provider.db.prepare ("SELECT id from %s %s;".printf (provider.patient_table, clause), |
3846 | + -1, out stmt); |
3847 | + } |
3848 | + |
3849 | + public bool next () { |
3850 | + return (stmt.step () == ROW); |
3851 | + } |
3852 | + |
3853 | + public new Patient get () { |
3854 | + int id = stmt.column_int (0); |
3855 | + return provider.get_patient (id); |
3856 | + } |
3857 | + } |
3858 | + |
3859 | +} |
3860 | |
3861 | === added file 'libclinica/SqliteVisitIterator.vala' |
3862 | --- libclinica/SqliteVisitIterator.vala 1970-01-01 00:00:00 +0000 |
3863 | +++ libclinica/SqliteVisitIterator.vala 2012-02-23 21:39:18 +0000 |
3864 | @@ -0,0 +1,44 @@ |
3865 | +/* |
3866 | + * This file is part of Clinica. |
3867 | + * |
3868 | + * Clinica is free software: you can redistribute it and/or modify |
3869 | + * it under the terms of the GNU General Public License as published by |
3870 | + * the Free Software Foundation, either version 3 of the License, or |
3871 | + * (at your option) any later version. |
3872 | + * |
3873 | + * Clinica is distributed in the hope that it will be useful, |
3874 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3875 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3876 | + * GNU General Public License for more details. |
3877 | + * |
3878 | + * You should have received a copy of the GNU General Public License |
3879 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3880 | + * |
3881 | + * Authors: Leonardo Robol <leo@robol.it> |
3882 | + */ |
3883 | + |
3884 | +using Sqlite; |
3885 | + |
3886 | +namespace Clinica { |
3887 | + |
3888 | + public class SqliteVisitIterator : GLib.Object, VisitIterator { |
3889 | + |
3890 | + private SqliteDataProvider provider; |
3891 | + private Statement stmt; |
3892 | + |
3893 | + public SqliteVisitIterator (SqliteDataProvider provider, string clause = "") { |
3894 | + this.provider = provider; |
3895 | + provider.db.prepare ("SELECT id from %s %s ORDER by date DESC;".printf (provider.visit_table, clause), |
3896 | + -1, out stmt); |
3897 | + } |
3898 | + |
3899 | + public bool next () { |
3900 | + return (stmt.step () == ROW); |
3901 | + } |
3902 | + |
3903 | + public new Visit get () { |
3904 | + int id = stmt.column_int (0); |
3905 | + return provider.get_visit (id); |
3906 | + } |
3907 | + } |
3908 | +} |
3909 | |
3910 | === modified file 'libclinica/UserInterface.vala' |
3911 | --- libclinica/UserInterface.vala 2012-01-31 09:44:59 +0000 |
3912 | +++ libclinica/UserInterface.vala 2012-02-23 21:39:18 +0000 |
3913 | @@ -45,7 +45,7 @@ |
3914 | /* Windows */ |
3915 | internal SettingsManager? settings_manager = null; |
3916 | internal CalendarWindow? calendar_window = null; |
3917 | - internal GLib.HashTable<int, VisitWindow> visit_windows; |
3918 | + internal GLib.HashTable<int64?, VisitWindow> visit_windows; |
3919 | |
3920 | private extern Peas.ExtensionSet setup_extension_set (ResourceManager resources, Peas.Engine engine); |
3921 | internal Peas.ExtensionSet extension_set; |
3922 | @@ -78,7 +78,7 @@ |
3923 | } |
3924 | |
3925 | /* Create an empty HashTable to store the Visit windows */ |
3926 | - visit_windows = new HashTable<int, VisitWindow> (null, null); |
3927 | + visit_windows = new HashTable<int64?, VisitWindow> (null, null); |
3928 | |
3929 | /* Load pages and connect callbacks with errors */ |
3930 | start_page = new StartPage (resource_manager); |
3931 | @@ -181,7 +181,7 @@ |
3932 | * is already open than bring it on top. |
3933 | */ |
3934 | public VisitWindow show_visit_window (Patient p) { |
3935 | - int p_id = p.get_id (); |
3936 | + int64 p_id = p.id; |
3937 | |
3938 | VisitWindow? win = visit_windows.lookup (p_id); |
3939 | if (win == null) { |
3940 | |
3941 | === modified file 'libclinica/UserInterfaceActivatable.vala' |
3942 | --- libclinica/UserInterfaceActivatable.vala 2011-09-22 19:27:52 +0000 |
3943 | +++ libclinica/UserInterfaceActivatable.vala 2012-02-23 21:39:18 +0000 |
3944 | @@ -1,3 +1,22 @@ |
3945 | +/* |
3946 | + * This file is part of Clinica. |
3947 | + * |
3948 | + * Clinica is free software: you can redistribute it and/or modify |
3949 | + * it under the terms of the GNU General Public License as published by |
3950 | + * the Free Software Foundation, either version 3 of the License, or |
3951 | + * (at your option) any later version. |
3952 | + * |
3953 | + * Clinica is distributed in the hope that it will be useful, |
3954 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3955 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3956 | + * GNU General Public License for more details. |
3957 | + * |
3958 | + * You should have received a copy of the GNU General Public License |
3959 | + * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3960 | + * |
3961 | + * Authors: Leonardo Robol <leo@robol.it> |
3962 | + */ |
3963 | + |
3964 | namespace Clinica { |
3965 | |
3966 | /** |
3967 | |
3968 | === modified file 'libclinica/Visit.vala' |
3969 | --- libclinica/Visit.vala 2012-02-02 07:26:45 +0000 |
3970 | +++ libclinica/Visit.vala 2012-02-23 21:39:18 +0000 |
3971 | @@ -15,187 +15,36 @@ |
3972 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
3973 | * |
3974 | * Authors: Leonardo Robol <leo@robol.it> |
3975 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
3976 | */ |
3977 | |
3978 | - using Gee; |
3979 | - using Sqlite; |
3980 | - |
3981 | - namespace Clinica { |
3982 | - |
3983 | - public class VisitIterator : SqlDataIterator { |
3984 | - |
3985 | - |
3986 | - private ResourceManager resource_manager; |
3987 | - |
3988 | - public VisitIterator (ResourceManager resources) { |
3989 | - base (resources.db, resources.visits_table, "date", true); |
3990 | - resource_manager = resources; |
3991 | - } |
3992 | - |
3993 | - public VisitIterator.with_day (ResourceManager resources, DateTime day, bool descending = true) { |
3994 | - DateTime day_after = day.add_days (1).add_minutes (-1); |
3995 | - base.with_like (resources.db, resources.visits_table, "date", descending, |
3996 | - "date BETWEEN '%s' AND '%s'".printf (SqlDataType.datetime_to_string (day), |
3997 | - SqlDataType.datetime_to_string (day_after))); |
3998 | - resource_manager = resources; |
3999 | - } |
4000 | - |
4001 | - public VisitIterator.with_patient (ResourceManager resources, Patient p, bool descending = true, |
4002 | - DateTime? from = null, DateTime? to = null) { |
4003 | - |
4004 | - string base_like; |
4005 | - if (from == null && to == null) { |
4006 | - base_like = "patient = %d".printf (p.get_id ()); |
4007 | - } |
4008 | - else if (from != null && to == null) { |
4009 | - base_like = "patient = %d AND date >= '%s'".printf (p.get_id (), SqlDataType.datetime_to_string (from)); |
4010 | - } |
4011 | - else if (from == null && to != null) { |
4012 | - base_like = "patient = %d AND date < '%s'".printf (p.get_id (), SqlDataType.datetime_to_string (to)); |
4013 | - } |
4014 | - else { |
4015 | - base_like = "patient = %d AND date BETWEEN '%s' AND '%s'".printf (p.get_id (), |
4016 | - SqlDataType.datetime_to_string (from), |
4017 | - SqlDataType.datetime_to_string (to)); |
4018 | - } |
4019 | - |
4020 | - base.with_like (resources.db, resources.visits_table, "date", descending, base_like); |
4021 | - resource_manager = resources; |
4022 | - } |
4023 | - |
4024 | - public new VisitIterator iterator () { return this; } |
4025 | - |
4026 | - public new Visit get () { |
4027 | - return new Visit.with_id (resource_manager, base.get ()); |
4028 | - } |
4029 | - } |
4030 | - |
4031 | - public class Visit : SqlDataType { |
4032 | - |
4033 | - /* FIELDS */ |
4034 | - public string anamnesis { |
4035 | - get { return get_text ("anamnesis"); } |
4036 | - set { set_text ("anamnesis", value); } |
4037 | - } |
4038 | - |
4039 | - public string physical_examination { |
4040 | - get { return get_text ("physical_examination"); } |
4041 | - set { set_text ("physical_examination", value); } |
4042 | - } |
4043 | - |
4044 | - public string laboratory_exam { |
4045 | - get { return get_text ("laboratory_exam"); } |
4046 | - set { set_text ("laboratory_exam", value); } |
4047 | - } |
4048 | - |
4049 | - public string histopathology { |
4050 | - get { return get_text ("histopathology"); } |
4051 | - set { set_text ("histopathology", value); } |
4052 | - } |
4053 | - |
4054 | - public string diagnosis { |
4055 | - get { return get_text ("diagnosis"); } |
4056 | - set { set_text ("diagnosis", value); } |
4057 | - } |
4058 | - |
4059 | - public string topical_therapy { |
4060 | - get { return get_text ("topical_therapy"); } |
4061 | - set { set_text ("topical_therapy", value); } |
4062 | - } |
4063 | - |
4064 | - public string systemic_therapy { |
4065 | - get { return get_text ("systemic_therapy"); } |
4066 | - set { set_text ("systemic_therapy", value); } |
4067 | - } |
4068 | - |
4069 | - public string subsequent_checks { |
4070 | - get { return get_text ("subsequent_checks"); } |
4071 | - set { set_text ("subsequent_checks", value); } |
4072 | - } |
4073 | - |
4074 | - private DateTime _date; |
4075 | - public DateTime date { |
4076 | - get { |
4077 | - _date = get_date ("date"); |
4078 | - return _date; |
4079 | - } |
4080 | - set { |
4081 | - _date = value; |
4082 | - set_date ("date", _date); |
4083 | - } |
4084 | - } |
4085 | - |
4086 | - private Patient _patient; |
4087 | - public Patient patient { |
4088 | - get { |
4089 | - _patient = new Patient.with_id (resource_manager, get_integer ("patient")); |
4090 | - return _patient; |
4091 | - } |
4092 | - set { |
4093 | - this._patient = value; |
4094 | - set_integer("patient", value.get_id ()); |
4095 | - } |
4096 | - } |
4097 | - |
4098 | - private ResourceManager resource_manager; |
4099 | - |
4100 | - /** |
4101 | - * @brief Create a new visit to |
4102 | - * the passed patient. |
4103 | - * @param patient The patient that has been |
4104 | - * visited |
4105 | - */ |
4106 | - public Visit (ResourceManager resources, Patient? patient) { |
4107 | - base (resources.db); |
4108 | - resource_manager = resources; |
4109 | - table_name = resources.visits_table; |
4110 | - error.connect ((t,l) => resources.error_callback(t,l)); |
4111 | - table_name = "visits"; |
4112 | - |
4113 | - add_text_field ("anamnesis"); |
4114 | - add_text_field ("physical_examination"); |
4115 | - add_text_field ("laboratory_exam"); |
4116 | - add_text_field ("histopathology"); |
4117 | - add_text_field ("diagnosis"); |
4118 | - add_text_field ("topical_therapy"); |
4119 | - add_text_field ("systemic_therapy"); |
4120 | - add_text_field ("subsequent_checks"); |
4121 | - add_date_field ("date"); |
4122 | - |
4123 | - add_integer_field ("patient"); |
4124 | - |
4125 | - if (patient != null) { |
4126 | - this.patient = patient; |
4127 | - } |
4128 | - |
4129 | - anamnesis = ""; |
4130 | - physical_examination = ""; |
4131 | - laboratory_exam = ""; |
4132 | - histopathology = ""; |
4133 | - diagnosis = ""; |
4134 | - topical_therapy = ""; |
4135 | - systemic_therapy = ""; |
4136 | - subsequent_checks = ""; |
4137 | - |
4138 | - init_resources (); |
4139 | - } |
4140 | - |
4141 | - public Visit.with_id (ResourceManager resources, int ID) { |
4142 | - this (resources, null); |
4143 | - load (ID); |
4144 | - this.patient = new Patient.with_id (resources, get_integer ("patient")); |
4145 | - } |
4146 | - |
4147 | - public static new VisitIterator all (ResourceManager resources) { |
4148 | - return new VisitIterator (resources); |
4149 | - } |
4150 | - |
4151 | - public static new VisitIterator for_day (ResourceManager resources, DateTime date, bool descending = false) { |
4152 | - return new VisitIterator.with_day (resources, date, descending); |
4153 | - } |
4154 | - |
4155 | - } |
4156 | - |
4157 | - |
4158 | - } |
4159 | +namespace Clinica { |
4160 | + |
4161 | + public class Visit : Object { |
4162 | + |
4163 | + public DataProvider? provider = null; |
4164 | + |
4165 | + public int64 id { get; set; default = 0; } |
4166 | + |
4167 | + public string anamnesis { get; set; default = ""; } |
4168 | + |
4169 | + public string physical_examination { get; set; default = ""; } |
4170 | + |
4171 | + public string laboratory_exam { get; set; default = ""; } |
4172 | + |
4173 | + public string histopathology { get; set; default = ""; } |
4174 | + |
4175 | + public string diagnosis { get; set; default = ""; } |
4176 | + |
4177 | + public string topical_therapy { get; set; default = ""; } |
4178 | + |
4179 | + public string systemic_therapy { get; set; default = ""; } |
4180 | + |
4181 | + public string subsequent_checks { get; set; default = ""; } |
4182 | + |
4183 | + public DateTime date { get; set; } |
4184 | + |
4185 | + public Patient patient { get; set; default = null; } |
4186 | + |
4187 | + } |
4188 | + |
4189 | +} |
4190 | |
4191 | === modified file 'libclinica/VisitActions.vala' |
4192 | --- libclinica/VisitActions.vala 2011-11-23 17:53:36 +0000 |
4193 | +++ libclinica/VisitActions.vala 2012-02-23 21:39:18 +0000 |
4194 | @@ -95,7 +95,7 @@ |
4195 | * visit. */ |
4196 | this.visit_tab = visittab; |
4197 | visit_connection_id = visit_tab.saved.connect ((visit) => delete_button.set_sensitive (true)); |
4198 | - if (visit_tab.visit.get_id () != 0) |
4199 | + if (visit_tab.visit.id != 0) |
4200 | delete_button.set_sensitive (true); |
4201 | else |
4202 | delete_button.set_sensitive (false); |
4203 | |
4204 | === modified file 'libclinica/VisitBrowser.vala' |
4205 | --- libclinica/VisitBrowser.vala 2012-02-02 08:11:46 +0000 |
4206 | +++ libclinica/VisitBrowser.vala 2012-02-23 21:39:18 +0000 |
4207 | @@ -15,7 +15,6 @@ |
4208 | * along with Clinica. If not, see <http://www.gnu.org/licenses/>. |
4209 | * |
4210 | * Authors: Leonardo Robol <leo@robol.it> |
4211 | - * Gianmarco Brocchi <brocchi@poisson.phc.unipi.it> |
4212 | */ |
4213 | |
4214 | using Gtk; |
4215 | @@ -63,7 +62,7 @@ |
4216 | Label l; |
4217 | |
4218 | /* Put in future visits */ |
4219 | - foreach (Visit v in new VisitIterator.with_patient (resource_manager, p, true, new DateTime.now_local ())) { |
4220 | + foreach (Visit v in p.visits (new DateTime.now_local ())) { |
4221 | l = new Label(v.date.format ("%F")); |
4222 | append_page (new VisitTab (resource_manager, visit_window, v, l), l); |
4223 | old_pages++; |
4224 | @@ -78,12 +77,12 @@ |
4225 | new_tab_saved_connection_id = new_page.saved.connect (on_new_page_saved); |
4226 | |
4227 | /* And then load all visits for the patient */ |
4228 | - foreach (Visit v in new VisitIterator.with_patient (resource_manager, p, true, null, new DateTime.now_local ())) { |
4229 | + foreach (Visit v in p.visits (null, new DateTime.now_local ())) { |
4230 | l = new Label(v.date.format ("%F")); |
4231 | append_page (new VisitTab (resource_manager, visit_window, v, l), l); |
4232 | } |
4233 | |
4234 | - store.visit_added.connect (on_visit_list_store_visit_added); |
4235 | + resource_manager.data_provider.visit_added.connect (on_visit_added); |
4236 | } |
4237 | |
4238 | public void save_focused_visit () { |
4239 | @@ -102,9 +101,9 @@ |
4240 | * @brief This callback gets called when a visit is added, probably |
4241 | * in another VisitBrowser. |
4242 | */ |
4243 | - private void on_visit_list_store_visit_added (int visit_id) { |
4244 | + private void on_visit_added (int64 visit_id) { |
4245 | /* Get the new visit */ |
4246 | - Visit new_visit = new Visit.with_id (resource_manager, visit_id); |
4247 | + Visit new_visit = resource_manager.data_provider.get_visit (visit_id); |
4248 | |
4249 | /* We may be the VisitBrowser that added the visit, or not. |
4250 | * Let's find out traversing the tabs */ |
4251 | @@ -113,7 +112,7 @@ |
4252 | |
4253 | for (i = 0; i < n_pages; i++) { |
4254 | VisitTab tab = get_nth_page (i) as VisitTab; |
4255 | - int visit_tab_id = tab.visit.get_id (); |
4256 | + int64 visit_tab_id = tab.visit.id; |
4257 | |
4258 | if (visit_tab_id == visit_id) { |
4259 | return; |
4260 | @@ -147,7 +146,7 @@ |
4261 | |
4262 | /* Check if the visit is already in db. If it is, save it, otherwise |
4263 | * ask the user to do it, since it may not be what he desires */ |
4264 | - if (tab.visit.get_id () <= 0) { |
4265 | + if (tab.visit.id <= 0) { |
4266 | Gtk.MessageDialog dialog = new MessageDialog.with_markup (null, |
4267 | DialogFlags.MODAL, MessageType.QUESTION, ButtonsType.YES_NO, |
4268 | _("A visit need to be saved in order to be exported as PDF.\nDo you want to save the visit now?")); |
4269 | |
4270 | === modified file 'libclinica/VisitDetail.vala' |
4271 | --- libclinica/VisitDetail.vala 2012-02-02 08:38:15 +0000 |
4272 | +++ libclinica/VisitDetail.vala 2012-02-23 21:39:18 +0000 |
4273 | @@ -124,8 +124,7 @@ |
4274 | MessageType.QUESTION, ButtonsType.YES_NO, "%s", |
4275 | _("Deleting a visit will cause all its data to be lost.\nDo you really want to continue?")); |
4276 | if (dialog.run () == ResponseType.YES) { |
4277 | - associated_visit.remove (); |
4278 | - resource_manager.visit_list_store.remove_visit (associated_visit); |
4279 | + resource_manager.data_provider.remove_visit (associated_visit); |
4280 | } |
4281 | |
4282 | dialog.destroy (); |
4283 | |
4284 | === modified file 'libclinica/VisitFileManager.vala' |
4285 | --- libclinica/VisitFileManager.vala 2012-01-29 15:44:14 +0000 |
4286 | +++ libclinica/VisitFileManager.vala 2012-02-23 21:39:18 +0000 |
4287 | @@ -96,7 +96,7 @@ |
4288 | Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT); |
4289 | fd.set_transient_for (visit_window); |
4290 | if (fd.run () == Gtk.ResponseType.ACCEPT) { |
4291 | - resource_manager.file_store.store_file (visit.get_id (), fd.get_filename ()); |
4292 | + resource_manager.file_store.store_file (visit.id, fd.get_filename ()); |
4293 | } |
4294 | |
4295 | fd.destroy (); |
4296 | @@ -108,7 +108,7 @@ |
4297 | */ |
4298 | private void on_browse_button_clicked (Button button) { |
4299 | try { |
4300 | - string path = resource_manager.file_store.get_id_path (visit.get_id ()); |
4301 | + string path = resource_manager.file_store.get_id_path (visit.id); |
4302 | Gtk.show_uri (null, "file://" + path, Gdk.CURRENT_TIME); |
4303 | } catch (GLib.Error e) { |
4304 | warning (_("Unable to open the browser on the filestore position")); |
4305 | @@ -120,8 +120,8 @@ |
4306 | * reload the files if the file changed were the ones that |
4307 | * belong to this visit. |
4308 | */ |
4309 | - private void on_file_store_changed (int id) { |
4310 | - if (visit != null && id == visit.get_id ()) |
4311 | + private void on_file_store_changed (int64 id) { |
4312 | + if (visit != null && id == visit.id) |
4313 | reload_file_list (); |
4314 | } |
4315 | |
4316 | @@ -148,7 +148,7 @@ |
4317 | (attach_button.get_child () as Label).set_text (_("Attach files")); |
4318 | } |
4319 | |
4320 | - foreach (FileObject obj in resource_manager.file_store.get_files (visit.get_id ())) { |
4321 | + foreach (FileObject obj in resource_manager.file_store.get_files (visit.id)) { |
4322 | var file_detail = new FileDetail (resource_manager, visit_window, obj); |
4323 | pack_start (file_detail, false, true); |
4324 | file_detail.show_all (); |
4325 | |
4326 | === modified file 'libclinica/VisitListStore.vala' |
4327 | --- libclinica/VisitListStore.vala 2012-01-26 17:41:05 +0000 |
4328 | +++ libclinica/VisitListStore.vala 2012-02-23 21:39:18 +0000 |
4329 | @@ -24,9 +24,6 @@ |
4330 | |
4331 | public class VisitListStore : ListStore { |
4332 | |
4333 | - public signal void visit_added (int visit_id); |
4334 | - public signal void visit_removed (int visit_id); |
4335 | - |
4336 | enum Field { |
4337 | VISIT, |
4338 | DATE, |
4339 | @@ -48,64 +45,49 @@ |
4340 | |
4341 | /* Fill liststore asynchronously */ |
4342 | Idle.add(() => { |
4343 | - foreach (Visit v in Visit.all (resource_manager)) { |
4344 | - add_visit (v); |
4345 | + foreach (Visit v in resource_manager.data_provider.visits ()) { |
4346 | + add_visit (v.id); |
4347 | } |
4348 | |
4349 | + /* Setup callbacks to add or remove doctors */ |
4350 | + resource_manager.data_provider.visit_added.connect ( |
4351 | + (id) => add_visit (id)); |
4352 | + resource_manager.data_provider.visit_changed.connect ( |
4353 | + (id) => reload_visit (id)); |
4354 | + resource_manager.data_provider.visit_removed.connect ( |
4355 | + (id) => remove_visit (id)); |
4356 | + |
4357 | /* We don't need to execute any more */ |
4358 | return false; |
4359 | }); |
4360 | } |
4361 | |
4362 | - public void add_visit (Visit v) { |
4363 | + private void add_visit (int64 id) { |
4364 | + Visit v = resource_manager.data_provider.get_visit (id); |
4365 | TreeIter iter; |
4366 | append (out iter); |
4367 | set_value (iter, Field.VISIT, v); |
4368 | set_value (iter, Field.DATE, ""); |
4369 | - |
4370 | - visit_added (v.get_id ()); |
4371 | } |
4372 | |
4373 | - public void reload_visit (Visit v) { |
4374 | + private void reload_visit (int64 id) { |
4375 | + Visit v = resource_manager.data_provider.get_visit (id); |
4376 | TreeIter iter = visit_to_iter (v); |
4377 | set_value (iter, Field.VISIT, v); |
4378 | set_value (iter, Field.DATE, ""); |
4379 | } |
4380 | |
4381 | - /** @brief Get visits of the given patient */ |
4382 | - public List<TreeIter?> get_visits_of (Patient p) { |
4383 | - Value value; |
4384 | - var iters = new List<TreeIter?> (); |
4385 | - |
4386 | - TreeIter it; |
4387 | - Visit v; |
4388 | - |
4389 | - if (!get_iter_first (out it)) { |
4390 | - return iters; |
4391 | - } |
4392 | - do { |
4393 | - get_value (it, Field.VISIT, out value); |
4394 | - v = value as Visit; |
4395 | - if (p.get_id () == v.patient.get_id ()) { |
4396 | - iters.append (it); |
4397 | - } |
4398 | - } while (iter_next (ref it)); |
4399 | - return iters; |
4400 | - } |
4401 | - |
4402 | - public void remove_visit (Visit v) { |
4403 | + private void remove_visit (int64 id) { |
4404 | TreeIter it; |
4405 | Value visit; |
4406 | - int this_id = v.get_id (); |
4407 | |
4408 | if (!get_iter_first (out it)) { |
4409 | error(_("Visit database seems corrupted. This is likely to be a bug in the application")); |
4410 | } |
4411 | do { |
4412 | get_value (it, Field.VISIT, out visit); |
4413 | - if ((visit as Visit).get_id () == this_id) { |
4414 | + if ((visit as Visit).id == id) { |
4415 | remove (it); |
4416 | - visit_removed (this_id); |
4417 | return; |
4418 | } |
4419 | } while (iter_next (ref it)); |
4420 | @@ -113,15 +95,6 @@ |
4421 | assert_not_reached (); |
4422 | } |
4423 | |
4424 | - public void remove_visit_from_iter (TreeIter it) { |
4425 | - Value visit; |
4426 | - get_value (it, Field.VISIT, out visit); |
4427 | - int this_id = (visit as Visit).get_id (); |
4428 | - (visit as Visit).remove (); |
4429 | - remove (it); |
4430 | - visit_removed (this_id); |
4431 | - } |
4432 | - |
4433 | public Visit iter_to_visit (TreeIter it) { |
4434 | Value visit; |
4435 | get_value (it, Field.VISIT, out visit); |
4436 | @@ -135,7 +108,7 @@ |
4437 | assert_not_reached (); |
4438 | do { |
4439 | get_value (iter, Field.VISIT, out visit); |
4440 | - if ((visit as Visit).get_id () == v.get_id ()) { |
4441 | + if ((visit as Visit).id == v.id) { |
4442 | return iter; |
4443 | } |
4444 | } while (iter_next (ref iter)); |
4445 | |
4446 | === modified file 'libclinica/VisitSchedulerDialog.vala' |
4447 | --- libclinica/VisitSchedulerDialog.vala 2012-02-02 17:00:18 +0000 |
4448 | +++ libclinica/VisitSchedulerDialog.vala 2012-02-23 21:39:18 +0000 |
4449 | @@ -84,12 +84,12 @@ |
4450 | |
4451 | if (base.run () == Response.SAVE) { |
4452 | /* Saving the new visit in the database */ |
4453 | - Visit visit = new Visit (resource_manager, p_entry.get_patient ()); |
4454 | + Visit visit = new Visit (); |
4455 | + visit.patient = p_entry.get_patient (); |
4456 | visit.date = picker.get_datetime (); |
4457 | |
4458 | - /* And finally save the visit in the database AND the ListStore */ |
4459 | - visit.save (); |
4460 | - resource_manager.visit_list_store.add_visit (visit); |
4461 | + /* And finally save the visit in the database */ |
4462 | + resource_manager.data_provider.save_visit (visit); |
4463 | } |
4464 | |
4465 | return Response.CANCEL; |
4466 | |
4467 | === modified file 'libclinica/VisitTab.vala' |
4468 | --- libclinica/VisitTab.vala 2012-02-02 08:38:15 +0000 |
4469 | +++ libclinica/VisitTab.vala 2012-02-23 21:39:18 +0000 |
4470 | @@ -176,27 +176,28 @@ |
4471 | fill_data (); |
4472 | |
4473 | /* Connect callbacks */ |
4474 | - store.visit_removed.connect (on_visit_list_store_visit_removed); |
4475 | + resource_manager.data_provider.visit_removed.connect (on_visit_removed); |
4476 | } |
4477 | |
4478 | public VisitTab.with_patient (ResourceManager resources, VisitWindow window, Patient p, Label title) { |
4479 | this (resources, window, null, title); |
4480 | - visit = new Visit (resource_manager, p); |
4481 | + visit = new Visit (); |
4482 | + visit.patient = p; |
4483 | } |
4484 | |
4485 | /** |
4486 | * @brief Get the visit id. |
4487 | */ |
4488 | - public int get_visit_id () { |
4489 | - return visit.get_id (); |
4490 | + public int64 get_visit_id () { |
4491 | + return visit.id; |
4492 | } |
4493 | |
4494 | /** |
4495 | * @brief Callback to the visit_removed event in the liststore. |
4496 | */ |
4497 | - private void on_visit_list_store_visit_removed (int visit_id) { |
4498 | + private void on_visit_removed (int64 visit_id) { |
4499 | VisitBrowser parent = this.parent as VisitBrowser; |
4500 | - if (visit_id == visit.get_id ()) |
4501 | + if (visit_id == visit.id) |
4502 | parent.remove_page (parent.page_num (this)); |
4503 | } |
4504 | |
4505 | @@ -241,12 +242,7 @@ |
4506 | /* ..and then actually store that data in the database, changing |
4507 | * the label of the tab to reflect the change... */ |
4508 | label.set_text (visit.date.format ("%F")); |
4509 | - visit.save (); |
4510 | - |
4511 | - if (new_visit) |
4512 | - store.add_visit (visit); |
4513 | - else |
4514 | - store.reload_visit (visit); |
4515 | + resource_manager.data_provider.save_visit (visit); |
4516 | |
4517 | file_manager.update_visit (visit); |
4518 | |
4519 | @@ -264,8 +260,7 @@ |
4520 | MessageType.QUESTION, ButtonsType.YES_NO, "%s", |
4521 | _("Deleting a visit will cause all its data to be lost.\nDo you really want to continue?")); |
4522 | if (dialog.run () == ResponseType.YES) { |
4523 | - store.remove_visit (visit); |
4524 | - visit.remove (); |
4525 | + resource_manager.data_provider.remove_visit (visit); |
4526 | |
4527 | /* Emit deleted() signal */ |
4528 | deleted(); |
4529 | |
4530 | === modified file 'libclinica/VisitWindow.vala' |
4531 | --- libclinica/VisitWindow.vala 2012-01-27 07:27:43 +0000 |
4532 | +++ libclinica/VisitWindow.vala 2012-02-23 21:39:18 +0000 |
4533 | @@ -70,7 +70,7 @@ |
4534 | * to deattach it from the user_interface visit_window hashtable. |
4535 | */ |
4536 | public void on_visit_window_destroy (Widget me) { |
4537 | - resource_manager.user_interface.visit_windows.remove (patient.get_id ()); |
4538 | + resource_manager.user_interface.visit_windows.remove (patient.id); |
4539 | resource_manager.application.remove_window (this); |
4540 | } |
4541 | |
4542 | @@ -81,7 +81,7 @@ |
4543 | int i; |
4544 | for (i = 0; i < visit_browser.get_n_pages (); i++) { |
4545 | VisitTab nth_visit_tab = visit_browser.get_nth_page (i) as VisitTab; |
4546 | - if (nth_visit_tab.get_visit_id () == visit.get_id ()) { |
4547 | + if (nth_visit_tab.get_visit_id () == visit.id) { |
4548 | visit_browser.set_current_page (i); |
4549 | return; |
4550 | } |
4551 | |
4552 | === modified file 'org.phcteam.clinica.gschema.xml' |
4553 | --- org.phcteam.clinica.gschema.xml 2012-01-29 10:39:56 +0000 |
4554 | +++ org.phcteam.clinica.gschema.xml 2012-02-23 21:39:18 +0000 |
4555 | @@ -16,9 +16,18 @@ |
4556 | <summary>Selected medicine search engine</summary> |
4557 | <description>The name of the search engine that the user wants to lookup medicines.</description> |
4558 | </key> |
4559 | + <key name="data-provider" type="s"> |
4560 | + <default>""</default> |
4561 | + <summary>Selected data provider</summary> |
4562 | + <description>The name of the data provider used to retrieve the data in Clinica.</description> |
4563 | + </key> |
4564 | <key name="show-visit-file-manager" type="b"> |
4565 | <default>true</default> |
4566 | <summary>Show "Open file browser" button in the visit window</summary> |
4567 | </key> |
4568 | + <key name="password" type="s"> |
4569 | + <default>"password"</default> |
4570 | + <summary>The password used to sync with the clinica instance via wireless</summary> |
4571 | + </key> |
4572 | </schema> |
4573 | </schemalist> |
4574 | |
4575 | === modified file 'plugins/AgenziaDelFarmaco.plugin' |
4576 | --- plugins/AgenziaDelFarmaco.plugin 2011-09-21 16:46:53 +0000 |
4577 | +++ plugins/AgenziaDelFarmaco.plugin 2012-02-23 21:39:18 +0000 |
4578 | @@ -2,8 +2,8 @@ |
4579 | Loader=python |
4580 | Module=AgenziaDelFarmaco |
4581 | IAge=3 |
4582 | -Name=Search for medicine on agenziadelfarmaco.it |
4583 | -Description=Search for medical products on the italian "Agenzia del Farmaco" |
4584 | +Name=Agenzia del Farmaco |
4585 | +Description=Search for medical products on the italian database of agenziadelfarmaco.it |
4586 | Authors=Leonardo Robol |
4587 | Copyright=2011 Leonardo Robol |
4588 | Website= |
4589 | |
4590 | === added file 'plugins/ClinicaAndroid.plugin' |
4591 | --- plugins/ClinicaAndroid.plugin 1970-01-01 00:00:00 +0000 |
4592 | +++ plugins/ClinicaAndroid.plugin 2012-02-23 21:39:18 +0000 |
4593 | @@ -0,0 +1,6 @@ |
4594 | +[Plugin] |
4595 | +Module = ClinicaAndroid |
4596 | +Loader = python |
4597 | +Name = Clinica for Android |
4598 | +Description = Server to sync Android phones with Clinica |
4599 | +Author = Leonardo Robol |
4600 | |
4601 | === added file 'plugins/ClinicaAndroid.py' |
4602 | --- plugins/ClinicaAndroid.py 1970-01-01 00:00:00 +0000 |
4603 | +++ plugins/ClinicaAndroid.py 2012-02-23 21:39:18 +0000 |
4604 | @@ -0,0 +1,130 @@ |
4605 | +#!/usr/bin/env python |
4606 | +# -*- coding: utf-8 -*- |
4607 | + |
4608 | +import SocketServer, md5, threading, os |
4609 | +from gi.repository import Clinica, GObject, Gtk, PeasGtk, Gio |
4610 | +from socket import gethostname |
4611 | + |
4612 | +authenticated_clients = [] |
4613 | + |
4614 | +class ClinicaAndroid (GObject.GObject, Clinica.UserInterfaceActivatable, PeasGtk.Configurable): |
4615 | + |
4616 | + resource_manager = GObject.property (type = Clinica.ResourceManager) |
4617 | + user_interface = GObject.property (type = Clinica.UserInterface) |
4618 | + |
4619 | + __gtype_name__ = "ClinicaAndroid" |
4620 | + |
4621 | + server = None |
4622 | + |
4623 | + def __init__(self): |
4624 | + GObject.GObject.__init__(self) |
4625 | + |
4626 | + def do_activate (self): |
4627 | + self.clinica_db = os.path.join (self.resource_manager.get_data_path (), |
4628 | + "clinica.db") |
4629 | + |
4630 | + self.server = ClinicaServer (self.clinica_db) |
4631 | + self.server_thread = threading.Thread (target = self.server.serve_forever) |
4632 | + self.server_thread.start () |
4633 | + |
4634 | + self.tcpserver = ClinicaTCPServer (self.clinica_db) |
4635 | + self.tcpserver_thread = threading.Thread (target = self.tcpserver.serve_forever) |
4636 | + self.tcpserver_thread.start () |
4637 | + |
4638 | + def do_deactivate (self): |
4639 | + self.server.shutdown () |
4640 | + self.server_thread.join () |
4641 | + self.tcpserver.shutdown () |
4642 | + self.tcpserver_thread.join () |
4643 | + |
4644 | + def do_create_configure_widget (self): |
4645 | + settings = Gio.Settings.new ("org.phcteam.clinica") |
4646 | + box = Gtk.Box.new (Gtk.Orientation.HORIZONTAL, 6) |
4647 | + |
4648 | + label = Gtk.Label ("Password") |
4649 | + entry = Gtk.Entry () |
4650 | + |
4651 | + box.pack_start (label, 6, False, True) |
4652 | + box.pack_start (entry, 6, True, True) |
4653 | + |
4654 | + settings.bind ("password", entry, "text", Gio.SettingsBindFlags.DEFAULT) |
4655 | + |
4656 | + return box |
4657 | + |
4658 | + def on_name_entry_changed (self, entry): |
4659 | + self.server.set_name (entry.get_text ()) |
4660 | + |
4661 | + def do_update_state (self): |
4662 | + pass |
4663 | + |
4664 | + |
4665 | +class ClinicaRequestHandler (SocketServer.BaseRequestHandler): |
4666 | + |
4667 | + def handle (self): |
4668 | + password = self.server.settings.get_value ("password").get_string () |
4669 | + |
4670 | + data = self.request[0].strip () |
4671 | + socket = self.request[1] |
4672 | + |
4673 | + if data == "GetInfo": |
4674 | + socket.sendto ("ServerName: %s\n" % self.server.name, self.client_address) |
4675 | + |
4676 | + elif data.startswith ("Authenticate:"): |
4677 | + pw = data.split(":")[1].strip () |
4678 | + |
4679 | + if self.client_address[0] in authenticated_clients: |
4680 | + socket.sendto ("Authentication performed\n", self.client_address) |
4681 | + else: |
4682 | + if password == pw: |
4683 | + authenticated_clients.append (self.client_address[0]) |
4684 | + socket.sendto ("Authentication performed\n", self.client_address) |
4685 | + else: |
4686 | + socket.sendto ("Authentication failed\n", self.client_address) |
4687 | + |
4688 | + elif data == "GetDB": |
4689 | + if self.client_address[0] in authenticated_clients: |
4690 | + try: |
4691 | + with open (self.server.db_path) as h : db_content = h.read () |
4692 | + socket.sendto (db_content, self.client_address) |
4693 | + except Exception, e: |
4694 | + socket.sendto ("Sending DB failed : %s" % e, self.client_address) |
4695 | + else: |
4696 | + socket.sendto ("Autenticati, scemo\n", self.client_address) |
4697 | + |
4698 | +class ClinicaTCPRequestHandler (SocketServer.BaseRequestHandler): |
4699 | + |
4700 | + def handle (self): |
4701 | + data = self.request.recv(1024).strip() |
4702 | + if data == "GetDB": |
4703 | + if self.client_address[0] in authenticated_clients: |
4704 | + with open (self.server.db_path) as h : db_content = h.read () |
4705 | + self.request.sendall (db_content) |
4706 | + |
4707 | + |
4708 | +class ClinicaTCPServer (SocketServer.ThreadingTCPServer): |
4709 | + |
4710 | + allow_reuse_address = True |
4711 | + |
4712 | + def __init__(self, db_path, port = 20802): |
4713 | + SocketServer.ThreadingTCPServer.__init__(self, ('', port), ClinicaTCPRequestHandler) |
4714 | + |
4715 | + self.db_path = db_path |
4716 | + self.name = gethostname() |
4717 | + |
4718 | +class ClinicaServer (SocketServer.ThreadingUDPServer): |
4719 | + |
4720 | + allow_reuse_address = True |
4721 | + |
4722 | + def __init__ (self, db_path, port = 20801): |
4723 | + SocketServer.ThreadingUDPServer.__init__ (self, ('', port), ClinicaRequestHandler) |
4724 | + self.db_path = db_path |
4725 | + self.name = gethostname() |
4726 | + self.settings = Gio.Settings.new ("org.phcteam.clinica") |
4727 | + |
4728 | + |
4729 | +if __name__ == "__main__": |
4730 | + |
4731 | + udp_server = ClinicaServer ("Ciao") |
4732 | + tcp_server = ClinicaTCPServer ("Ciao") |
4733 | + |
4734 | + server.serve_forever () |
4735 | |
4736 | === modified file 'plugins/wscript' |
4737 | --- plugins/wscript 2012-01-24 09:36:22 +0000 |
4738 | +++ plugins/wscript 2012-02-23 21:39:18 +0000 |
4739 | @@ -1,8 +1,12 @@ |
4740 | #!/usr/bin/env python |
4741 | # |
4742 | |
4743 | +import os |
4744 | + |
4745 | plugins_install_path = "${PREFIX}/lib/clinica/plugins" |
4746 | |
4747 | +plugins = [] |
4748 | + |
4749 | def build (ctx): |
4750 | ctx.set_group ("clinica") |
4751 | |
4752 | @@ -29,11 +33,21 @@ |
4753 | ctx.install_files (plugins_install_path, [ "AgenziaDelFarmaco.py", |
4754 | "AgenziaDelFarmaco.plugin" ]) |
4755 | |
4756 | + # Add plugins |
4757 | + add_plugin ("AgenziaDelFarmaco") |
4758 | + add_plugin ("DummyDataProvider") |
4759 | + # add_plugin ("GPGEncryption") |
4760 | + add_plugin ("CodiceFiscale") |
4761 | + add_plugin ("ClinicaAndroid") |
4762 | + |
4763 | # Push plugins on the build directory so we can run |
4764 | # clinica in the local dir |
4765 | - for plugin in [ 'AgenziaDelFarmaco.plugin', 'CodiceFiscale.plugin', 'AgenziaDelFarmaco.py', |
4766 | - ]: |
4767 | + for plugin in plugins: |
4768 | push_plugin (ctx, plugin) |
4769 | + |
4770 | +def add_plugin (plugin_name): |
4771 | + plugins_files = filter (lambda x : x.startswith (plugin_name), os.listdir ("plugins")) |
4772 | + plugins.extend (plugins_files) |
4773 | |
4774 | |
4775 | def push_plugin (ctx, plugin_file): |
4776 | |
4777 | === modified file 'po/es.po' |
4778 | --- po/es.po 2012-02-08 08:06:57 +0000 |
4779 | +++ po/es.po 2012-02-23 21:39:18 +0000 |
4780 | @@ -11,12 +11,18 @@ |
4781 | "PO-Revision-Date: 2012-02-07 13:41+0000\n" |
4782 | "Last-Translator: Fitoschido <fitoschido@gmail.com>\n" |
4783 | "Language-Team: Spanish <es@li.org>\n" |
4784 | +"Language: es\n" |
4785 | "MIME-Version: 1.0\n" |
4786 | "Content-Type: text/plain; charset=UTF-8\n" |
4787 | "Content-Transfer-Encoding: 8bit\n" |
4788 | +<<<<<<< TREE |
4789 | "X-Launchpad-Export-Date: 2012-02-08 08:06+0000\n" |
4790 | "X-Generator: Launchpad (build 14747)\n" |
4791 | "Language: es\n" |
4792 | +======= |
4793 | +"X-Launchpad-Export-Date: 2012-01-31 07:02+0000\n" |
4794 | +"X-Generator: Launchpad (build 14734)\n" |
4795 | +>>>>>>> MERGE-SOURCE |
4796 | |
4797 | #: ../libclinica/Doctor.vala:110 |
4798 | msgid "" |
4799 | @@ -259,8 +265,13 @@ |
4800 | msgstr "Visitas realizadas" |
4801 | |
4802 | #: ../libclinica/CalendarEventList.vala:102 |
4803 | +#, fuzzy |
4804 | msgid "Visits scheduled" |
4805 | +<<<<<<< TREE |
4806 | msgstr "Visitas agendadas" |
4807 | +======= |
4808 | +msgstr "Eventos agendados" |
4809 | +>>>>>>> MERGE-SOURCE |
4810 | |
4811 | #: ../libclinica/CalendarEventList.vala:123 |
4812 | msgid "No visits performed on this day" |
4813 | @@ -329,8 +340,8 @@ |
4814 | |
4815 | #: ../libclinica/DoctorListView.vala:186 |
4816 | msgid "" |
4817 | -"The doctor that you have selected for removal has some patients associated. " |
4818 | -"\n" |
4819 | +"The doctor that you have selected for removal has some patients " |
4820 | +"associated. \n" |
4821 | msgstr "" |
4822 | "El doctor que ha elegido para ser eliminado tiene algunos pacientes " |
4823 | "asignados. \n" |
4824 | @@ -360,8 +371,7 @@ |
4825 | msgstr "Confirmar la eliminación de pacientes" |
4826 | |
4827 | #: ../libclinica/DoctorListView.vala:244 |
4828 | -msgid "" |
4829 | -"Really delete this doctor? All information about him/her will be lost." |
4830 | +msgid "Really delete this doctor? All information about him/her will be lost." |
4831 | msgstr "" |
4832 | "¿Seguro de eliminar este médico? Toda la información del médico será perdida." |
4833 | |
4834 | @@ -713,25 +723,24 @@ |
4835 | msgid "Mobile:" |
4836 | msgstr "Móvil:" |
4837 | |
4838 | +#~ msgid "Error loading patient_editor.glade." |
4839 | +#~ msgstr "Error al cargar patient_editor.glade" |
4840 | + |
4841 | +#~ msgid "" |
4842 | +#~ "\n" |
4843 | +#~ "Launchpad contributions: \n" |
4844 | +#~ msgstr "" |
4845 | +#~ "\n" |
4846 | +#~ "Contribuciones de Launchpad: \n" |
4847 | + |
4848 | #~ msgid "Create a new patient" |
4849 | #~ msgstr "Crear un nuevo paciente" |
4850 | |
4851 | #~ msgid "Create a new doctor" |
4852 | #~ msgstr "Crear un nuevo médico" |
4853 | |
4854 | -#, c-format |
4855 | #~ msgid "Clinica %s\n" |
4856 | #~ msgstr "Clínica %s\n" |
4857 | |
4858 | #~ msgid "Back" |
4859 | #~ msgstr "Atrás" |
4860 | - |
4861 | -#~ msgid "Error loading patient_editor.glade." |
4862 | -#~ msgstr "Error al cargar patient_editor.glade" |
4863 | - |
4864 | -#~ msgid "" |
4865 | -#~ "\n" |
4866 | -#~ "Launchpad contributions: \n" |
4867 | -#~ msgstr "" |
4868 | -#~ "\n" |
4869 | -#~ "Contribuciones de Launchpad: \n" |
4870 | |
4871 | === modified file 'po/it.po' |
4872 | --- po/it.po 2012-02-14 06:40:10 +0000 |
4873 | +++ po/it.po 2012-02-23 21:39:18 +0000 |
4874 | @@ -10,12 +10,18 @@ |
4875 | "PO-Revision-Date: 2012-02-13 15:15+0000\n" |
4876 | "Last-Translator: Gianmarco Brocchi <Unknown>\n" |
4877 | "Language-Team: Clinica Development team\n" |
4878 | +"Language: \n" |
4879 | "MIME-Version: 1.0\n" |
4880 | "Content-Type: text/plain; charset=UTF-8\n" |
4881 | "Content-Transfer-Encoding: 8bit\n" |
4882 | +<<<<<<< TREE |
4883 | "X-Launchpad-Export-Date: 2012-02-14 06:40+0000\n" |
4884 | "X-Generator: Launchpad (build 14781)\n" |
4885 | "Language: \n" |
4886 | +======= |
4887 | +"X-Launchpad-Export-Date: 2012-01-31 07:02+0000\n" |
4888 | +"X-Generator: Launchpad (build 14734)\n" |
4889 | +>>>>>>> MERGE-SOURCE |
4890 | |
4891 | #: ../libclinica/Doctor.vala:110 |
4892 | msgid "" |
4893 | @@ -117,8 +123,7 @@ |
4894 | |
4895 | #: ../libclinica/PatientEditor.vala:436 |
4896 | msgid "Date inserted is invalid, aborting patient editing" |
4897 | -msgstr "" |
4898 | -"La data inserita non è valida: non è possibile modificare il paziente" |
4899 | +msgstr "La data inserita non è valida: non è possibile modificare il paziente" |
4900 | |
4901 | #. Set title according to the patient that we have loaded and connect |
4902 | #. * show startup signal to the focusing of the first field in the visit |
4903 | @@ -257,8 +262,13 @@ |
4904 | msgstr "Visite effettuate" |
4905 | |
4906 | #: ../libclinica/CalendarEventList.vala:102 |
4907 | +#, fuzzy |
4908 | msgid "Visits scheduled" |
4909 | +<<<<<<< TREE |
4910 | msgstr "Visita programmata" |
4911 | +======= |
4912 | +msgstr "Eventi in programma" |
4913 | +>>>>>>> MERGE-SOURCE |
4914 | |
4915 | #: ../libclinica/CalendarEventList.vala:123 |
4916 | msgid "No visits performed on this day" |
4917 | @@ -327,8 +337,8 @@ |
4918 | |
4919 | #: ../libclinica/DoctorListView.vala:186 |
4920 | msgid "" |
4921 | -"The doctor that you have selected for removal has some patients associated. " |
4922 | -"\n" |
4923 | +"The doctor that you have selected for removal has some patients " |
4924 | +"associated. \n" |
4925 | msgstr "" |
4926 | "Il dottore che è stato selezionato per la rimozione è associato a dei " |
4927 | "pazienti. \n" |
4928 | @@ -360,8 +370,7 @@ |
4929 | msgstr "Conferma la rimozione dei pazienti" |
4930 | |
4931 | #: ../libclinica/DoctorListView.vala:244 |
4932 | -msgid "" |
4933 | -"Really delete this doctor? All information about him/her will be lost." |
4934 | +msgid "Really delete this doctor? All information about him/her will be lost." |
4935 | msgstr "" |
4936 | "Si è sicuri di voler rimuovere il medico? Tutte le informazioni su di lui o " |
4937 | "lei saranno perse." |
4938 | @@ -714,12 +723,6 @@ |
4939 | msgid "Mobile:" |
4940 | msgstr "Telefono cellulare:" |
4941 | |
4942 | -#~ msgid "Create a new patient" |
4943 | -#~ msgstr "Crea un nuovo paziente" |
4944 | - |
4945 | -#~ msgid "Create a new doctor" |
4946 | -#~ msgstr "Crea un nuovo medico" |
4947 | - |
4948 | #~ msgid "Error loading patient_editor.glade." |
4949 | #~ msgstr "Errore durante il caricamento di patient_editor.glade." |
4950 | |
4951 | @@ -730,7 +733,12 @@ |
4952 | #~ "\n" |
4953 | #~ "Contributi su Launchpad: \n" |
4954 | |
4955 | -#, c-format |
4956 | +#~ msgid "Create a new patient" |
4957 | +#~ msgstr "Crea un nuovo paziente" |
4958 | + |
4959 | +#~ msgid "Create a new doctor" |
4960 | +#~ msgstr "Crea un nuovo medico" |
4961 | + |
4962 | #~ msgid "Clinica %s\n" |
4963 | #~ msgstr "Clinica %s\n" |
4964 | |
4965 | |
4966 | === modified file 'po/pt_BR.po' |
4967 | --- po/pt_BR.po 2012-02-06 05:08:51 +0000 |
4968 | +++ po/pt_BR.po 2012-02-23 21:39:18 +0000 |
4969 | @@ -7,43 +7,52 @@ |
4970 | msgstr "" |
4971 | "Project-Id-Version: clinica-project\n" |
4972 | "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" |
4973 | +<<<<<<< TREE |
4974 | "POT-Creation-Date: 2012-02-02 18:49+0100\n" |
4975 | "PO-Revision-Date: 2012-02-05 15:24+0000\n" |
4976 | "Last-Translator: Marco <marcodefreitas@gmail.com>\n" |
4977 | +======= |
4978 | +"POT-Creation-Date: 2012-01-29 11:43+0100\n" |
4979 | +"PO-Revision-Date: 2012-02-02 05:16+0000\n" |
4980 | +"Last-Translator: Marco <marcodefreitas@gmail.com>\n" |
4981 | +>>>>>>> MERGE-SOURCE |
4982 | "Language-Team: Brazilian Portuguese <pt_BR@li.org>\n" |
4983 | "MIME-Version: 1.0\n" |
4984 | "Content-Type: text/plain; charset=UTF-8\n" |
4985 | "Content-Transfer-Encoding: 8bit\n" |
4986 | +<<<<<<< TREE |
4987 | "X-Launchpad-Export-Date: 2012-02-06 05:08+0000\n" |
4988 | "X-Generator: Launchpad (build 14747)\n" |
4989 | +======= |
4990 | +"X-Launchpad-Export-Date: 2012-02-02 06:29+0000\n" |
4991 | +"X-Generator: Launchpad (build 14738)\n" |
4992 | +>>>>>>> MERGE-SOURCE |
4993 | |
4994 | #: ../libclinica/Doctor.vala:110 |
4995 | msgid "" |
4996 | "You cannot delete a doctor with associated patients. Delete his patients " |
4997 | "first." |
4998 | msgstr "" |
4999 | +<<<<<<< TREE |
5000 | "Você não pode excluir um médico com pacientes associados. Exclua seus " |
The diff has been truncated for viewing.