f5d81e790a2e942f39f7577a33bc540e930f4b67
[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 <string.h>
35 #include "modest-ui-dimming-rules.h"
36 #include "modest-tny-folder.h"
37 #include <modest-runtime.h>
38
39
40 static gboolean _folder_is_any_of_type (TnyFolder *folder, TnyFolderType types[], guint ntypes);
41 static gboolean _invalid_msg_selected (ModestMainWindow *win, gboolean unique);
42 static gboolean _already_opened_msg (ModestWindow *win);
43 static gboolean _selected_msg_marked_as (ModestWindow *win, TnyHeaderFlags mask, gboolean opposite);
44 static gboolean _selected_folder_not_writeable (ModestMainWindow *win);
45 static gboolean _selected_folder_is_any_of_type (ModestMainWindow *win, TnyFolderType types[], guint ntypes);
46 static gboolean _selected_folder_is_root (ModestMainWindow *win);
47 static gboolean _msg_download_in_progress (ModestMsgViewWindow *win);
48
49
50 gboolean 
51 modest_ui_dimming_rules_on_new_msg (ModestWindow *win, gpointer user_data)
52 {
53         gboolean dimmed = FALSE;
54
55         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW(win), FALSE);
56                 
57         /* Check dimmed rule */ 
58         if (!dimmed)
59                 dimmed = _msg_download_in_progress (MODEST_MSG_VIEW_WINDOW(win));
60
61         return dimmed;
62 }
63
64 gboolean 
65 modest_ui_dimming_rules_on_new_folder (ModestWindow *win, gpointer user_data)
66 {
67         gboolean dimmed = FALSE;
68         GtkWidget *folder_view = NULL;
69         TnyFolderStore *parent_folder = NULL;
70
71         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
72
73
74         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
75                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
76         /* Get selected folder as parent of new folder to create */
77         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
78         if (!parent_folder)
79                 return TRUE;
80         
81         /* If it's the local account do not dim */
82         if (modest_tny_folder_store_is_virtual_local_folders (parent_folder)) {
83                 return FALSE;
84         } else if (TNY_IS_ACCOUNT (parent_folder)) {
85                 /* If it's the MMC root folder then dim it */
86                 if (!strcmp (tny_account_get_id (TNY_ACCOUNT (parent_folder)), MODEST_MMC_ACCOUNT_ID)) {
87                         dimmed = TRUE;
88                 } else {
89                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (parent_folder));
90                         /* If it's POP then dim */
91                         dimmed = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
92                                   MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
93                 }
94         } else {
95                 /* TODO: the specs say that only one level of subfolder is allowed, is this true ? */
96
97                 /* Apply folder rules */        
98                 dimmed = _selected_folder_not_writeable (MODEST_MAIN_WINDOW(win));
99         }
100
101         return dimmed;
102 }
103
104 gboolean 
105 modest_ui_dimming_rules_on_rename_folder (ModestWindow *win, gpointer user_data)
106 {
107         gboolean dimmed = FALSE;
108
109         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
110                 
111         /* Check dimmed rule */ 
112         if (!dimmed)
113                 dimmed = _selected_folder_not_writeable (MODEST_MAIN_WINDOW(win));
114         if (!dimmed)
115                 dimmed = _selected_folder_is_root (MODEST_MAIN_WINDOW(win));
116
117         return dimmed;
118 }
119
120 gboolean 
121 modest_ui_dimming_rules_on_open_msg (ModestWindow *win, gpointer user_data)
122 {
123         gboolean dimmed = FALSE;
124
125         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
126                 
127         /* Check dimmed rule */ 
128         if (!dimmed)
129                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), TRUE);
130
131         return dimmed;
132 }
133
134 gboolean 
135 modest_ui_dimming_rules_on_reply_msg (ModestWindow *win, gpointer user_data)
136 {
137         gboolean dimmed = FALSE;
138         TnyFolderType types[3];
139
140         /* main window dimming rules */
141         if (MODEST_IS_MAIN_WINDOW(win)) {
142                 
143                 types[0] = TNY_FOLDER_TYPE_DRAFTS; 
144                 types[1] = TNY_FOLDER_TYPE_OUTBOX;
145                 types[2] = TNY_FOLDER_TYPE_ROOT;
146                 
147                 /* Check dimmed rule */ 
148                 if (!dimmed)
149                         dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 3);
150                 
151                 if (!dimmed)
152                         dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
153
154         /* msg view window dimming rules */
155         } else if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
156                 
157                 /* Check dimmed rule */ 
158                 if (!dimmed)
159                         dimmed = _msg_download_in_progress (MODEST_MSG_VIEW_WINDOW(win));
160         }
161         
162         return dimmed;
163 }
164
165
166 gboolean 
167 modest_ui_dimming_rules_on_contents_msg (ModestWindow *win, gpointer user_data)
168 {
169         gboolean dimmed = FALSE;
170
171         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
172                 
173         /* Check dimmed rule */ 
174         dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
175
176         return dimmed;
177 }
178
179 gboolean 
180 modest_ui_dimming_rules_always_dimmed (ModestWindow *win, gpointer user_data)
181 {
182         gboolean dimmed = FALSE;
183
184         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
185                 
186         /* Check dimmed rule */ 
187         if (!dimmed)
188                 dimmed = TRUE;
189
190         return dimmed;
191 }
192
193 gboolean 
194 modest_ui_dimming_rules_on_delete_msg (ModestWindow *win, gpointer user_data)
195 {
196         gboolean dimmed = FALSE;
197         
198         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
199         
200         /* Check dimmed rule */ 
201         if (!dimmed)
202                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
203         if (!dimmed)
204                 dimmed = _already_opened_msg (win);
205         
206         return dimmed;
207 }
208
209 gboolean 
210 modest_ui_dimming_rules_on_details (ModestWindow *win, gpointer user_data)
211 {
212         gboolean dimmed = FALSE;
213         
214         /* main window dimming rules */
215         if (MODEST_IS_MAIN_WINDOW(win)) {
216                 GtkWidget *header_view;
217
218                 /* Check dimmed rule */
219                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
220                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
221
222                 /* If the header view does not have the focus then do
223                    not apply msg dimming rules because the action will
224                    show the folder details that have no dimming
225                    rule */
226                 if (gtk_widget_is_focus (header_view)) {
227                         if (!dimmed)
228                                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), TRUE);
229                 }
230
231         /* msg view window dimming rules */
232         } else {
233
234                 /* Check dimmed rule */ 
235                 if (!dimmed)
236                         dimmed = _msg_download_in_progress (MODEST_MSG_VIEW_WINDOW(win));
237         }
238
239         return dimmed;
240 }
241
242 gboolean 
243 modest_ui_dimming_rules_on_mark_as_read_msg (ModestWindow *win, gpointer user_data)
244 {
245         gboolean dimmed = FALSE;
246         TnyHeaderFlags flags;
247
248         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
249         
250         flags = TNY_HEADER_FLAG_SEEN; 
251
252         /* Check dimmed rule */ 
253         if (!dimmed)
254                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
255         if (!dimmed) 
256                 dimmed = _selected_msg_marked_as (win, flags, FALSE);
257         
258         return dimmed;
259 }
260
261 gboolean 
262 modest_ui_dimming_rules_on_mark_as_unread_msg (ModestWindow *win, gpointer user_data)
263 {
264         gboolean dimmed = FALSE;
265         TnyHeaderFlags flags;
266
267         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
268         
269         flags = TNY_HEADER_FLAG_SEEN; 
270
271         /* Check dimmed rule */ 
272         if (!dimmed)
273                 dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
274         if (!dimmed) 
275                 dimmed = _selected_msg_marked_as (win, flags, TRUE);
276
277         return dimmed;
278 }
279
280 gboolean 
281 modest_ui_dimming_rules_on_move_to (ModestWindow *win, gpointer user_data)
282 {
283         gboolean dimmed = FALSE;
284
285         if (MODEST_IS_MAIN_WINDOW (win)) 
286                 dimmed = modest_ui_dimming_rules_on_main_window_move_to (win, user_data);
287         else 
288                 dimmed = modest_ui_dimming_rules_on_view_window_move_to (win, user_data);
289
290         return dimmed;
291 }
292
293
294 gboolean 
295 modest_ui_dimming_rules_on_main_window_move_to (ModestWindow *win, gpointer user_data)
296 {
297         GtkWidget *folder_view = NULL;
298         GtkWidget *header_view = NULL;
299         gboolean dimmed = FALSE;
300         
301         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), TRUE);
302         
303         /* Get the folder view */
304         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
305                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
306
307         /* Get header view */
308         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
309                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
310
311         /* Check common diming rules */
312
313         /* Check diming rules for folder transfer  */
314         if (gtk_widget_is_focus (folder_view)) {
315                 if (!dimmed) 
316                         dimmed = _selected_folder_not_writeable(MODEST_MAIN_WINDOW(win));
317         }
318         /* Check diming rules for msg transfer  */
319         else if (gtk_widget_is_focus (header_view)) {
320                 if (!dimmed)
321                         dimmed = _invalid_msg_selected (MODEST_MAIN_WINDOW(win), FALSE);
322                 
323         }
324
325         return dimmed;
326 }
327
328 gboolean 
329 modest_ui_dimming_rules_on_view_window_move_to (ModestWindow *win, gpointer user_data)
330 {
331         gboolean dimmed = FALSE;
332
333         return dimmed;
334 }
335
336 gboolean 
337 modest_ui_dimming_rules_on_paste_msgs (ModestWindow *win, gpointer user_data)
338 {
339         TnyFolderType types[3];
340         gboolean dimmed = FALSE;
341
342         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
343
344         types[0] = TNY_FOLDER_TYPE_DRAFTS; 
345         types[1] = TNY_FOLDER_TYPE_OUTBOX;
346         types[2] = TNY_FOLDER_TYPE_SENT;
347         
348         /* Check dimmed rule */ 
349         if (!dimmed)
350                 dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 3);
351
352         return dimmed;
353 }
354
355 gboolean 
356 modest_ui_dimming_rules_on_delete_msgs (ModestWindow *win, gpointer user_data)
357 {
358         TnyFolderType types[5];
359         gboolean dimmed = FALSE;
360
361         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
362
363         types[0] = TNY_FOLDER_TYPE_DRAFTS; 
364         types[1] = TNY_FOLDER_TYPE_OUTBOX;
365         types[2] = TNY_FOLDER_TYPE_SENT;
366         types[3] = TNY_FOLDER_TYPE_INBOX;
367         types[4] = TNY_FOLDER_TYPE_ROOT;
368         
369         /* Check dimmed rule */ 
370         if (!dimmed)
371                 dimmed = _selected_folder_is_any_of_type (MODEST_MAIN_WINDOW(win), types, 5);
372
373         return dimmed;
374 }
375
376
377 /* *********************** static utility functions ******************** */
378
379 static gboolean
380 _selected_folder_not_writeable (ModestMainWindow *win)
381 {
382         GtkWidget *folder_view = NULL;
383         TnyFolderStore *parent_folder = NULL;
384         ModestTnyFolderRules rules;
385         gboolean result = FALSE;
386
387         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
388
389         /* Get folder view */
390         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
391                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
392         /* If no folder view, always dimmed */
393         if (!folder_view)
394                 return TRUE;
395         
396         /* Get selected folder as parent of new folder to create */
397         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
398         if (!(parent_folder || TNY_IS_FOLDER(parent_folder)))
399                 return TRUE;
400         
401         /* Check dimmed rule */ 
402         rules = modest_tny_folder_get_rules (TNY_FOLDER (parent_folder));
403         result = rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE;
404
405         /* free */
406         g_object_unref (parent_folder);
407
408         return result;
409 }
410
411 static gboolean
412 _selected_folder_is_root (ModestMainWindow *win)
413 {
414         TnyFolderType types[2];
415         gboolean result = FALSE;
416
417         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
418
419         types[0] = TNY_FOLDER_TYPE_ROOT; 
420         types[1] = TNY_FOLDER_TYPE_INBOX; 
421
422         /* Check folder type */
423         result = _selected_folder_is_any_of_type (win, types, 2);
424
425         return result;
426 }
427
428 static gboolean
429 _selected_folder_is_any_of_type (ModestMainWindow *win,
430                                  TnyFolderType types[], 
431                                  guint ntypes)
432 {
433         GtkWidget *folder_view = NULL;
434         TnyFolderStore *folder = NULL;
435         gboolean result = FALSE;
436
437         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
438
439         /* Get folder view */
440         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
441                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
442         /* If no folder view, always dimmed */
443         if (!folder_view)
444                 return TRUE;
445         
446         /* Get selected folder as parent of new folder to create */
447         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
448         if (!(folder || TNY_IS_FOLDER(folder)))
449                 return TRUE;
450         
451         /* Check folder type */
452         result = _folder_is_any_of_type (TNY_FOLDER(folder), types, ntypes);
453
454         /* free */
455         g_object_unref (folder);
456
457         return result;  
458 }
459
460 static gboolean
461 _folder_is_any_of_type (TnyFolder *folder,
462                         TnyFolderType types[], 
463                         guint ntypes)
464 {
465         TnyFolderType folder_type;
466         gboolean result = FALSE;
467         guint i;
468
469         g_return_val_if_fail (TNY_IS_FOLDER(folder), FALSE);
470
471         /* Get folder type */
472         if (modest_tny_folder_is_local_folder (folder))
473                 folder_type = modest_tny_folder_get_local_folder_type (folder);         
474         else 
475                 folder_type = modest_tny_folder_guess_folder_type (folder);             
476         
477         /* Check foler type */
478         for (i=0; i < ntypes; i++) {
479                 result = result || folder_type == types[i];
480         }
481
482         return result;
483 }
484
485
486
487 static gboolean
488 _invalid_msg_selected (ModestMainWindow *win,
489                        gboolean unique) 
490 {
491         GtkWidget *header_view = NULL;          
492         GtkWidget *folder_view = NULL;
493         TnyList *selected_headers = NULL;
494         gboolean result = FALSE;
495
496         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
497                 
498         /* Get header view to check selected messages */
499         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
500                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
501         
502         /* Get folder view to check focus */
503         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
504                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
505
506         /* Get selected headers */
507         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
508
509         /* Check dimmed rule (TODO: check focus on widgets */   
510         result = ((selected_headers == NULL) || 
511                   (GTK_WIDGET_HAS_FOCUS (folder_view)));
512         if (!result)
513                 result = tny_list_get_length (selected_headers) > 1;
514         
515         /* free */
516         if (selected_headers != NULL) 
517                 g_object_unref (selected_headers);
518
519         return result;
520 }
521
522 static gboolean
523 _already_opened_msg (ModestWindow *win)
524 {
525         ModestWindow *window = NULL;
526         ModestWindowMgr *mgr = NULL;
527         GtkWidget *header_view = NULL;          
528         TnyList *selected_headers = NULL;
529         TnyIterator *iter = NULL;
530         TnyHeader *header = NULL;
531         gboolean result = TRUE;
532
533         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(win), FALSE);
534                 
535         /* Get header view to check selected messages */
536         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
537                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
538
539         /* Get selected headers */
540         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
541         if (selected_headers == NULL) 
542                 return FALSE;
543
544         /* Check dimmed rule (TODO: check focus on widgets */   
545         mgr = modest_runtime_get_window_mgr ();
546         iter = tny_list_create_iterator (selected_headers);
547         while (!tny_iterator_is_done (iter) && result) {        
548                 header = TNY_HEADER (tny_iterator_get_current (iter));
549                 window = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
550                 result = result && (window != NULL);
551                         
552                 g_object_unref (header);
553                 tny_iterator_next (iter);
554         }
555         
556         /* free */
557         if (selected_headers != NULL) 
558                 g_object_unref (selected_headers);
559         if (iter != NULL)
560                 g_object_unref (iter);
561                 
562         return result;
563 }
564
565 static gboolean
566 _selected_msg_marked_as (ModestWindow *win, 
567                          TnyHeaderFlags mask, 
568                          gboolean opposite)
569 {
570         GtkWidget *header_view = NULL;
571         TnyList *selected_headers = NULL;
572         TnyIterator *iter = NULL;
573         TnyHeader *header = NULL;
574         TnyHeaderFlags flags;
575         gboolean result = FALSE;
576
577         /* Get header view to check selected messages */
578         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
579                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
580
581         /* Get selected headers */
582         selected_headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
583         if (selected_headers == NULL) 
584                 return TRUE;
585         
586         /* Call the function for each header */
587         iter = tny_list_create_iterator (selected_headers);
588         while (!tny_iterator_is_done (iter) && !result) {
589                 header = TNY_HEADER (tny_iterator_get_current (iter));
590
591                 flags = tny_header_get_flags (header);
592                 if (opposite)
593                         result = (flags & mask) == 0; 
594                 else
595                         result = (flags & mask) != 0; 
596
597                 g_object_unref (header);
598                 tny_iterator_next (iter);
599         }
600
601         /* free */
602         if (selected_headers != NULL) 
603                 g_object_unref (selected_headers);
604         if (iter != NULL)
605                 g_object_unref (iter);
606
607         return result;
608 }
609
610 static gboolean
611 _msg_download_in_progress (ModestMsgViewWindow *win)
612 {
613         gboolean result = FALSE;
614
615         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), FALSE);
616
617         return result;
618 }