* Implementation of 'email menu' dimming rules of main window.
[modest] / src / modest-ui-dimming-rules.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include "modest-ui-dimming-rules.h"
35 #include "modest-tny-folder.h"
36 #include <modest-runtime.h>
37
38
39 static gboolean _folder_is_any_of_type (TnyFolder *folder, TnyFolderType types[], guint ntypes);
40 static gboolean _invalid_msg_selected (ModestMainWindow *win, gboolean unique);
41 static gboolean _already_opened_msg (ModestWindow *win);
42 static gboolean _selected_msg_marked_as (ModestWindow *win, TnyHeaderFlags mask, gboolean opposite);
43 static gboolean _selected_folder_not_writeable (ModestMainWindow *win);
44 static gboolean _selected_folder_is_any_of_type (ModestMainWindow *win, TnyFolderType types[], guint ntypes);
45 static gboolean _selected_folder_is_root (ModestMainWindow *win);
46
47 gboolean 
48 modest_ui_dimming_rules_on_new_folder (ModestWindow *win, gpointer user_data)
49 {
50         gboolean dimmed = FALSE;
51
52         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
53                 
54         /* Check dimmed rule */ 
55         if (!dimmed)
56                 dimmed = _selected_folder_not_writeable (MODEST_MAIN_WINDOW(win));
57
58         return dimmed;
59 }
60
61 gboolean 
62 modest_ui_dimming_rules_on_rename_folder (ModestWindow *win, gpointer user_data)
63 {
64         gboolean dimmed = FALSE;
65
66         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
67                 
68         /* Check dimmed rule */ 
69         if (!dimmed)
70                 dimmed = _selected_folder_not_writeable (MODEST_MAIN_WINDOW(win));
71         if (!dimmed)
72                 dimmed = _selected_folder_is_root (MODEST_MAIN_WINDOW(win));
73
74         return dimmed;
75 }
76
77 gboolean 
78 modest_ui_dimming_rules_on_open_msg (ModestWindow *win, gpointer user_data)
79 {
80         gboolean dimmed = FALSE;
81
82         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
83                 
84         /* Check dimmed rule */ 
85         if (!dimmed)
86                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), TRUE);
87
88         return dimmed;
89 }
90
91 gboolean 
92 modest_ui_dimming_rules_on_reply_msg (ModestWindow *win, gpointer user_data)
93 {
94         gboolean dimmed = FALSE;
95         TnyFolderType types[3];
96
97         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
98
99         types[0] = TNY_FOLDER_TYPE_DRAFTS; 
100         types[1] = TNY_FOLDER_TYPE_OUTBOX;
101         types[2] = TNY_FOLDER_TYPE_ROOT;
102
103         /* Check dimmed rule */ 
104         if (!dimmed)
105                 dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 3);
106         
107         if (!dimmed)
108                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
109
110         return dimmed;
111 }
112
113
114 gboolean 
115 modest_ui_dimming_rules_on_contents_msg (ModestWindow *win, gpointer user_data)
116 {
117         gboolean dimmed = FALSE;
118
119         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
120                 
121         /* Check dimmed rule */ 
122         dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
123
124         return dimmed;
125 }
126
127 gboolean 
128 modest_ui_dimming_rules_always_dimmed (ModestWindow *win, gpointer user_data)
129 {
130         gboolean dimmed = FALSE;
131
132         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
133                 
134         /* Check dimmed rule */ 
135         if (!dimmed)
136                 dimmed = TRUE;
137
138         return dimmed;
139 }
140
141 gboolean 
142 modest_ui_dimming_rules_on_delete_msg (ModestWindow *win, gpointer user_data)
143 {
144         gboolean dimmed = FALSE;
145         
146         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
147         
148         /* Check dimmed rule */ 
149         if (!dimmed)
150                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
151         if (!dimmed)
152                 dimmed = _already_opened_msg (win);
153         
154         return dimmed;
155 }
156
157 gboolean 
158 modest_ui_dimming_rules_on_details_msg (ModestWindow *win, gpointer user_data)
159 {
160         gboolean dimmed = FALSE;
161         
162         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
163         
164         /* Check dimmed rule */ 
165         if (!dimmed)
166                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), TRUE);
167         
168         return dimmed;
169 }
170
171 gboolean 
172 modest_ui_dimming_rules_on_mark_as_read_msg (ModestWindow *win, gpointer user_data)
173 {
174         gboolean dimmed = FALSE;
175         TnyHeaderFlags flags;
176
177         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
178         
179         flags = TNY_HEADER_FLAG_SEEN; 
180
181         /* Check dimmed rule */ 
182         if (!dimmed)
183                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
184         if (!dimmed) 
185                 dimmed = _selected_msg_marked_as (win, flags, FALSE);
186         
187         return dimmed;
188 }
189
190 gboolean 
191 modest_ui_dimming_rules_on_mark_as_unread_msg (ModestWindow *win, gpointer user_data)
192 {
193         gboolean dimmed = FALSE;
194         TnyHeaderFlags flags;
195
196         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
197         
198         flags = TNY_HEADER_FLAG_SEEN; 
199
200         /* Check dimmed rule */ 
201         if (!dimmed)
202                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
203         if (!dimmed) 
204                 dimmed = _selected_msg_marked_as (win, flags, TRUE);
205
206         return dimmed;
207 }
208
209 gboolean 
210 modest_ui_dimming_rules_on_move_to (ModestWindow *win, gpointer user_data)
211 {
212         gboolean dimmed = FALSE;
213
214         if (MODEST_IS_MAIN_WINDOW (win)) 
215                 dimmed = modest_ui_dimming_rules_on_main_window_move_to (win, user_data);
216         else 
217                 dimmed = modest_ui_dimming_rules_on_view_window_move_to (win, user_data);
218
219         return dimmed;
220 }
221
222
223 gboolean 
224 modest_ui_dimming_rules_on_main_window_move_to (ModestWindow *win, gpointer user_data)
225 {
226         GtkWidget *folder_view = NULL;
227         GtkWidget *header_view = NULL;
228         gboolean dimmed = FALSE;
229         
230         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), TRUE);
231         
232         /* Get the folder view */
233         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
234                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
235
236         /* Get header view */
237         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
238                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
239
240         /* Check common diming rules */
241
242         /* Check diming rules for folder transfer  */
243         if (gtk_widget_is_focus (folder_view)) {
244                 if (!dimmed) 
245                         dimmed = _selected_folder_not_writeable(MODEST_MAIN_WINDOW(win));
246         }
247         /* Check diming rules for msg transfer  */
248         else if (gtk_widget_is_focus (header_view)) {
249                 if (!dimmed)
250                         dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
251                 
252         }
253
254         return dimmed;
255 }
256
257 gboolean 
258 modest_ui_dimming_rules_on_view_window_move_to (ModestWindow *win, gpointer user_data)
259 {
260         gboolean dimmed = FALSE;
261
262         return dimmed;
263 }
264
265 gboolean 
266 modest_ui_dimming_rules_on_paste_msgs (ModestWindow *win, gpointer user_data)
267 {
268         TnyFolderType types[3];
269         gboolean dimmed = FALSE;
270
271         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
272
273         types[0] = TNY_FOLDER_TYPE_DRAFTS; 
274         types[1] = TNY_FOLDER_TYPE_OUTBOX;
275         types[2] = TNY_FOLDER_TYPE_SENT;
276         
277         /* Check dimmed rule */ 
278         if (!dimmed)
279                 dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 3);
280
281         return dimmed;
282 }
283
284 gboolean 
285 modest_ui_dimming_rules_on_delete_msgs (ModestWindow *win, gpointer user_data)
286 {
287         TnyFolderType types[5];
288         gboolean dimmed = FALSE;
289
290         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
291
292         types[0] = TNY_FOLDER_TYPE_DRAFTS; 
293         types[1] = TNY_FOLDER_TYPE_OUTBOX;
294         types[2] = TNY_FOLDER_TYPE_SENT;
295         types[3] = TNY_FOLDER_TYPE_INBOX;
296         types[4] = TNY_FOLDER_TYPE_ROOT;
297         
298         /* Check dimmed rule */ 
299         if (!dimmed)
300                 dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 5);
301
302         return dimmed;
303 }
304
305
306 /* *********************** static utility functions ******************** */
307
308 static gboolean
309 _selected_folder_not_writeable (ModestMainWindow *win)
310 {
311         GtkWidget *folder_view = NULL;
312         TnyFolderStore *parent_folder = NULL;
313         ModestTnyFolderRules rules;
314         gboolean result = FALSE;
315
316         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
317
318         /* Get folder view */
319         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
320                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
321         /* If no folder view, always dimmed */
322         if (!folder_view)
323                 return TRUE;
324         
325         /* Get selected folder as parent of new folder to create */
326         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
327         if (!(parent_folder || TNY_IS_FOLDER(parent_folder)))
328                 return TRUE;
329         
330         /* Check dimmed rule */ 
331         rules = modest_tny_folder_get_rules (TNY_FOLDER (parent_folder));
332         result = rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE;
333
334         /* free */
335         g_object_unref (parent_folder);
336
337         return result;
338 }
339
340 static gboolean
341 _selected_folder_is_root (ModestMainWindow *win)
342 {
343         TnyFolderType types[2];
344         gboolean result = FALSE;
345
346         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
347
348         types[0] = TNY_FOLDER_TYPE_ROOT; 
349         types[1] = TNY_FOLDER_TYPE_INBOX; 
350
351         /* Check folder type */
352         result = _selected_folder_is_any_of_type (win, types, 2);
353
354         return result;
355 }
356
357 static gboolean
358 _selected_folder_is_any_of_type (ModestMainWindow *win,
359                                  TnyFolderType types[], 
360                                  guint ntypes)
361 {
362         GtkWidget *folder_view = NULL;
363         TnyFolderStore *folder = NULL;
364         gboolean result = FALSE;
365
366         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
367
368         /* Get folder view */
369         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
370                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
371         /* If no folder view, always dimmed */
372         if (!folder_view)
373                 return TRUE;
374         
375         /* Get selected folder as parent of new folder to create */
376         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
377         if (!(folder || TNY_IS_FOLDER(folder)))
378                 return TRUE;
379         
380         /* Check folder type */
381         result = _folder_is_any_of_type (TNY_FOLDER(folder), types, ntypes);
382
383         /* free */
384         g_object_unref (folder);
385
386         return result;  
387 }
388
389 static gboolean
390 _folder_is_any_of_type (TnyFolder *folder,
391                         TnyFolderType types[], 
392                         guint ntypes)
393 {
394         TnyFolderType folder_type;
395         gboolean result = FALSE;
396         guint i;
397
398         g_return_val_if_fail (TNY_IS_FOLDER(folder), FALSE);
399
400         /* Get folder type */
401         if (modest_tny_folder_is_local_folder (folder))
402                 folder_type = modest_tny_folder_get_local_folder_type (folder);         
403         else 
404                 folder_type = modest_tny_folder_guess_folder_type (folder);             
405         
406         /* Check foler type */
407         for (i=0; i < ntypes; i++) {
408                 result = result || folder_type == types[i];
409         }
410
411         return result;
412 }
413
414
415
416 static gboolean
417 _invalid_msg_selected (ModestMainWindow *win,
418                        gboolean unique) 
419 {
420         GtkWidget *header_view = NULL;          
421         GtkWidget *folder_view = NULL;
422         TnyList *selected_headers = NULL;
423         gboolean result = FALSE;
424
425         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
426                 
427         /* Get header view to check selected messages */
428         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
429                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
430         
431         /* Get folder view to check focus */
432         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
433                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
434
435         /* Get selected headers */
436         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
437
438         /* Check dimmed rule (TODO: check focus on widgets */   
439         result = ((selected_headers == NULL) || 
440                   (GTK_WIDGET_HAS_FOCUS (folder_view)));
441         if (!result)
442                 result = tny_list_get_length (selected_headers) > 1;
443         
444         /* free */
445         if (selected_headers != NULL) 
446                 g_object_unref (selected_headers);
447
448         return result;
449 }
450
451 static gboolean
452 _already_opened_msg (ModestWindow *win)
453 {
454         ModestWindow *window = NULL;
455         ModestWindowMgr *mgr = NULL;
456         GtkWidget *header_view = NULL;          
457         TnyList *selected_headers = NULL;
458         TnyIterator *iter = NULL;
459         TnyHeader *header = NULL;
460         gboolean result = TRUE;
461
462         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
463                 
464         /* Get header view to check selected messages */
465         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
466                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
467
468         /* Get selected headers */
469         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
470         if (selected_headers == NULL) 
471                 return FALSE;
472
473         /* Check dimmed rule (TODO: check focus on widgets */   
474         mgr = modest_runtime_get_window_mgr ();
475         iter = tny_list_create_iterator (selected_headers);
476         while (!tny_iterator_is_done (iter) && result) {        
477                 header = TNY_HEADER (tny_iterator_get_current (iter));
478                 window = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
479                 result = result && (window != NULL);
480                         
481                 g_object_unref (header);
482                 tny_iterator_next (iter);
483         }
484         
485         /* free */
486         if (selected_headers != NULL) 
487                 g_object_unref (selected_headers);
488         if (iter != NULL)
489                 g_object_unref (iter);
490                 
491         return result;
492 }
493
494 static gboolean
495 _selected_msg_marked_as (ModestWindow *win, 
496                          TnyHeaderFlags mask, 
497                          gboolean opposite)
498 {
499         GtkWidget *header_view = NULL;
500         TnyList *selected_headers = NULL;
501         TnyIterator *iter = NULL;
502         TnyHeader *header = NULL;
503         TnyHeaderFlags flags;
504         gboolean result = FALSE;
505
506         /* Get header view to check selected messages */
507         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
508                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
509
510         /* Get selected headers */
511         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
512         if (selected_headers == NULL) 
513                 return TRUE;
514         
515         /* Call the function for each header */
516         iter = tny_list_create_iterator (selected_headers);
517         while (!tny_iterator_is_done (iter) && !result) {
518                 header = TNY_HEADER (tny_iterator_get_current (iter));
519
520                 flags = tny_header_get_flags (header);
521                 if (opposite)
522                         result = (flags & mask) == 0; 
523                 else
524                         result = (flags & mask) != 0; 
525
526                 g_object_unref (header);
527                 tny_iterator_next (iter);
528         }
529
530         /* free */
531         if (selected_headers != NULL) 
532                 g_object_unref (selected_headers);
533         if (iter != NULL)
534                 g_object_unref (iter);
535
536         return result;
537 }