~phcteam/clinica-project/master

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 *   This file is part of Clinica.
 *
 *   Clinica is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Clinica is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with Clinica.  If not, see <http://www.gnu.org/licenses/>.
 *
 *   Authors: Leonardo Robol <leo@robol.it>
 *            Gianmarco Brocchi <brocchi@poisson.phc.unipi.it>
 */
 
 using Gtk;
 
 namespace Clinica {
 
    /**
     * @brief Extension of GtkEntry with autocompletion on patients
     *
     * The selected patient, or null, if there is no selected patient,
     * can be retrieved git the get_patient () method.
     */
    public class PatientEntry : Entry, Clinica.Buildable {
    
        public signal void selection_changed ();
    
        enum PatientCompletionAction {
            CREATE_NEW = 0,
        }
    
        /**
         * @brief The reference to the resource manager
         */
        private ResourceManager resource_manager;
        
        /**
         * @brief The reference to the selected patient
         */
        private Patient? selected_patient = null;        
        
        /**
         * @brief Completion for the patients
         */
        private new EntryCompletion completion;
        
        public PatientEntry (ResourceManager resources) {
            setup (resources);
        }
        
        public void setup (ResourceManager resources) {
            resource_manager = resources;
            
            /* Init the completion */
            completion = new EntryCompletion ();
            completion.set_model (resource_manager.patient_list_store);
            completion.set_text_column (PatientListStore.Field.COMPLETE_NAME);
            completion.set_match_func (completion_match_function);
            completion.insert_action_text (PatientCompletionAction.CREATE_NEW, "Create a new patient");
            
            /* Callback that stores the selected patient */
            completion.match_selected.connect (on_match_selected);
            
            /* Callback for action selected */
            completion.action_activated.connect (on_action_activated);
            
            /* Activate completion */
            set_completion (completion);
            changed.connect (on_changed);
        }
        
        /**
         * Change selection to the given patient
         */
        public void select_patient (Patient patient) {
            selected_patient = patient;
            set_text (patient.get_complete_name ());
        }
        
        public Patient get_patient () {
            return selected_patient;
        }
        
        /** 
         * @brief Return true if this entry has a valid selection.
         */
        public bool is_valid () {
            /* If no patient is selected the entry should be empty */
            if (selected_patient == null) {
                if (get_text () != "")
                    return false;
                else
                    return true;
            }
                
            return (get_text () == selected_patient.get_complete_name ());
        }        
        
        /**
         * @brief Callback function for the patient selection that matches the doctor
         * if the key is a substring of its complete name. 
         */
        private bool completion_match_function (EntryCompletion compl, string key, TreeIter iter) {
        	Value value;
        	resource_manager.patient_list_store.get_value(iter, 0, out value);
        	Patient pat = value as Patient;
        	if (pat == null)
        		return false;
        	return (key.up () in pat.get_complete_name ().up ());
        }
        
        /**
         * @brief Callback called when the user select a patient
         */
        private bool on_match_selected (EntryCompletion compl, TreeModel model, TreeIter iter) {
        	/* Get doctor associated with the selected completion */
        	Value value;
        	model.get_value (iter, PatientListStore.Field.COMPLETE_NAME, out value);
        	set_text (value as string);
        	model.get_value (iter, PatientListStore.Field.PATIENT, out value);
        	
        	/* Set selected doctor in this object to use it later */
        	selected_patient = value as Patient;
        	
        	selection_changed ();
        	
        	return true;
        }
        
        /**
         * @brief Create a new doctor on the fly with the name specifed in the 
         * doctor_entry
         */
        private void on_action_activated (EntryCompletion editable, int action) {
        	if (action != PatientCompletionAction.CREATE_NEW)
            	return;
            	
            /* Create a new dialog precompiled with the user input until now */
            string name = get_text ();
            var dialog = new PatientEditor.with_name (resource_manager, Utils.capitalize (name));
            if (dialog.run () == PatientEditor.Response.CANCEL) {
            	dialog.destroy ();
            	return;
            }
            
            /* Set the newly created doctor as selected doctor */
            selected_patient = dialog.created_patient;
            set_text (selected_patient.get_complete_name ());
            
            /* Destroy the dialog */
            dialog.destroy ();
        }
        
        private void on_changed (Editable editable) {
	        string patient_name = get_text ();
	    	
	    	/* Replace action */
	    	completion.delete_action (PatientCompletionAction.CREATE_NEW);
	    	if (patient_name != "")
	        	completion.insert_action_text (PatientCompletionAction.CREATE_NEW,
	        		@"Create a new patient named $(Utils.capitalize (patient_name))");
	        else 
	        	completion.insert_action_text (PatientCompletionAction.CREATE_NEW,
	        		@"Create a new patient");
	        		
	        selection_changed ();
        }   
    }
 }