~cairo-dock-team/cairo-dock-plug-ins/plug-ins

« back to all changes in this revision

Viewing changes to clock/src/applet-calendar.c

  • Committer: Matthieu Baerts
  • Date: 2014-10-19 00:26:10 UTC
  • Revision ID: matttbe@gmail.com-20141019002610-ulf26s9b4c4rw10r
We just switched from BZR to Git.
Follow us on Github: https://github.com/Cairo-Dock

Note: we will only use Github to manage our source code and all pull requests.
Please continue to report your bugs/ideas/messages on our forum or Launchpad! 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
* This file is a part of the Cairo-Dock project
3
 
*
4
 
* Copyright : (C) see the 'copyright' file.
5
 
* E-mail    : see the 'copyright' file.
6
 
*
7
 
* This program is free software; you can redistribute it and/or
8
 
* modify it under the terms of the GNU General Public License
9
 
* as published by the Free Software Foundation; either version 3
10
 
* of the License, or (at your option) any later version.
11
 
*
12
 
* This program is distributed in the hope that it will be useful,
13
 
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
* GNU General Public License for more details.
16
 
* You should have received a copy of the GNU General Public License
17
 
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
*/
19
 
 
20
 
#include <stdlib.h>
21
 
#include <math.h>
22
 
#define __USE_POSIX
23
 
#include <signal.h>
24
 
 
25
 
#include "applet-struct.h"
26
 
#include "applet-task-editor.h"
27
 
#include "applet-calendar.h"
28
 
 
29
 
#define _cd_task_matches_month(pTask, iMonth, iYear) (((pTask)->iMonth == iMonth && ((pTask)->iYear == iYear || (pTask)->iFrequency == CD_TASK_EACH_YEAR)) || (pTask)->iFrequency == CD_TASK_EACH_MONTH)
30
 
#define _cd_task_matches_day(pTask, iDay, iMonth, iYear) ((pTask)->iDay == iDay && _cd_task_matches_month (pTask, iMonth, iYear))
31
 
 
32
 
 
33
 
  /////////////
34
 
 // BACKEND //
35
 
/////////////
36
 
 
37
 
void cd_clock_register_backend (GldiModuleInstance *myApplet, const gchar *cBackendName, CDClockTaskBackend *pBackend)
38
 
{
39
 
        if (myData.pBackends == NULL)
40
 
                myData.pBackends = g_hash_table_new_full (g_str_hash,
41
 
                        g_str_equal,
42
 
                        g_free,
43
 
                        g_free);
44
 
        g_hash_table_insert (myData.pBackends, g_strdup (cBackendName), pBackend);
45
 
}
46
 
 
47
 
CDClockTaskBackend *cd_clock_get_backend (GldiModuleInstance *myApplet, const gchar *cBackendName)
48
 
{
49
 
        CDClockTaskBackend *pBackend = NULL;
50
 
        if (cBackendName != NULL)
51
 
                pBackend = g_hash_table_lookup (myData.pBackends, cBackendName);
52
 
        
53
 
        return pBackend;
54
 
}
55
 
 
56
 
void cd_clock_set_current_backend (GldiModuleInstance *myApplet)
57
 
{
58
 
        if (myData.pBackend && myData.pBackend->stop)
59
 
                myData.pBackend->stop (myApplet);
60
 
        myData.pBackend = cd_clock_get_backend (myApplet, myConfig.cTaskMgrName);
61
 
        if (myData.pBackend == NULL)
62
 
                myData.pBackend = cd_clock_get_backend (myApplet, "Default");
63
 
        if (myData.pBackend->init)
64
 
                myData.pBackend->init (myApplet);
65
 
}
66
 
 
67
 
 
68
 
  ///////////
69
 
 // TASKS //
70
 
///////////
71
 
 
72
 
static int _compare_task (CDClockTask *pTask1, CDClockTask *pTask2, gpointer data)
73
 
{
74
 
        if (pTask1->iYear < pTask2->iYear)
75
 
                return -1;
76
 
        if (pTask1->iYear > pTask2->iYear)
77
 
                return 1;
78
 
        
79
 
        if (pTask1->iMonth < pTask2->iMonth)
80
 
                return -1;
81
 
        if (pTask1->iMonth > pTask2->iMonth)
82
 
                return 1;
83
 
        
84
 
        if (pTask1->iDay < pTask2->iDay)
85
 
                return -1;
86
 
        if (pTask1->iDay > pTask2->iDay)
87
 
                return 1;
88
 
        
89
 
        if (pTask1->iHour < pTask2->iHour)
90
 
                return -1;
91
 
        if (pTask1->iHour > pTask2->iHour)
92
 
                return 1;
93
 
        
94
 
        if (pTask1->iMinute < pTask2->iMinute)
95
 
                return -1;
96
 
        if (pTask1->iMinute > pTask2->iMinute)
97
 
                return 1;
98
 
        
99
 
        return 0;
100
 
        
101
 
}
102
 
void cd_clock_list_tasks (GldiModuleInstance *myApplet)
103
 
{
104
 
        cd_message ("%s ()", __func__);
105
 
        if (myData.pTasks != NULL)
106
 
                cd_clock_reset_tasks_list (myApplet);
107
 
        
108
 
        myData.pTasks = myData.pBackend->get_tasks (myApplet);
109
 
        CDClockTask *pTask;
110
 
        GList *t;
111
 
        for (t = myData.pTasks; t != NULL; t = t->next)
112
 
        {
113
 
                pTask = t->data;
114
 
                pTask->pApplet = myApplet;
115
 
        }
116
 
        myData.pTasks = g_list_sort_with_data (myData.pTasks,
117
 
                (GCompareDataFunc) _compare_task,
118
 
                NULL);
119
 
        myData.pNextTask = cd_clock_get_next_scheduled_task (myApplet);
120
 
        myData.pNextAnniversary = cd_clock_get_next_anniversary (myApplet);
121
 
}
122
 
 
123
 
void cd_clock_add_task_to_list (CDClockTask *pTask, GldiModuleInstance *myApplet)
124
 
{
125
 
        pTask->pApplet = myApplet;
126
 
        myData.pTasks = g_list_insert_sorted (myData.pTasks, pTask, (GCompareFunc)_compare_task);
127
 
        myData.pNextTask = cd_clock_get_next_scheduled_task (myApplet);
128
 
        myData.pNextAnniversary = cd_clock_get_next_anniversary (myApplet);
129
 
}
130
 
 
131
 
void cd_clock_remove_task_from_list (CDClockTask *pTask, GldiModuleInstance *myApplet)
132
 
{
133
 
        myData.pTasks = g_list_remove (myData.pTasks, pTask);
134
 
        myData.pMissedTasks = g_list_remove (myData.pMissedTasks, pTask);
135
 
        myData.pNextTask = cd_clock_get_next_scheduled_task (myApplet);
136
 
        myData.pNextAnniversary = cd_clock_get_next_anniversary (myApplet);
137
 
}
138
 
 
139
 
void cd_clock_free_task (CDClockTask *pTask)
140
 
{
141
 
        if (pTask == NULL)
142
 
                return;
143
 
        if (pTask->iSidWarning != 0)
144
 
                g_source_remove (pTask->iSidWarning);
145
 
        gldi_object_unref (GLDI_OBJECT(pTask->pWarningDialog));
146
 
        g_free (pTask->cTitle);
147
 
        g_free (pTask->cText);
148
 
        g_free (pTask->cTags);
149
 
        g_free (pTask->cID);
150
 
        g_free (pTask);
151
 
}
152
 
 
153
 
void cd_clock_reset_tasks_list (GldiModuleInstance *myApplet)
154
 
{
155
 
        g_list_foreach (myData.pTasks, (GFunc)cd_clock_free_task, NULL);
156
 
        g_list_free (myData.pTasks);
157
 
        g_list_free (myData.pMissedTasks);
158
 
        myData.pTasks = NULL;
159
 
        myData.pNextTask = NULL;
160
 
        myData.pMissedTasks = NULL;
161
 
}
162
 
 
163
 
CDClockTask *cd_clock_get_task_by_id (const gchar *cID, GldiModuleInstance *myApplet)
164
 
{
165
 
        if (cID == NULL)
166
 
                return NULL;
167
 
        CDClockTask *pTask;
168
 
        GList *t;
169
 
        for (t = myData.pTasks; t != NULL; t = t->next)
170
 
        {
171
 
                pTask = t->data;
172
 
                if (strcmp (pTask->cID, cID) == 0)
173
 
                        return pTask;
174
 
        }
175
 
        return NULL;
176
 
}
177
 
 
178
 
gchar *cd_clock_get_tasks_for_today (GldiModuleInstance *myApplet)
179
 
{
180
 
        guint iDay = myData.currentTime.tm_mday, iMonth = myData.currentTime.tm_mon, iYear = myData.currentTime.tm_year + 1900;
181
 
        
182
 
        GString *sTaskString = NULL;
183
 
        CDClockTask *pTask;
184
 
        GList *t;
185
 
        for (t = myData.pTasks; t != NULL; t = t->next)
186
 
        {
187
 
                pTask = t->data;
188
 
                if (_cd_task_matches_day (pTask, iDay, iMonth, iYear))
189
 
                {
190
 
                        if (sTaskString == NULL)
191
 
                                sTaskString = g_string_new ("");
192
 
                        g_string_append_printf (sTaskString, "<b><u>%s</u></b>\n <i>at %d:%02d</i>\n %s\n", pTask->cTitle ? pTask->cTitle : D_("No title"), pTask->iHour, pTask->iMinute, pTask->cText?pTask->cText:"");
193
 
                }
194
 
        }
195
 
        
196
 
        if (sTaskString == NULL)
197
 
                return NULL;
198
 
        
199
 
        gchar *cTasks = sTaskString->str;
200
 
        g_string_free (sTaskString, FALSE);
201
 
        return cTasks;
202
 
}
203
 
 
204
 
gchar *cd_clock_get_tasks_for_this_week (GldiModuleInstance *myApplet)
205
 
{
206
 
        guint iDay = myData.currentTime.tm_mday, iMonth = myData.currentTime.tm_mon, iYear = myData.currentTime.tm_year + 1900;
207
 
        
208
 
        GDate* pCurrentDate = g_date_new_dmy (iDay, iMonth + 1, iYear);
209
 
        GDate* pDate = g_date_new ();
210
 
        guint d, m, y;
211
 
        int iDelta;
212
 
        GString *sTaskString = NULL;
213
 
        CDClockTask *pTask;
214
 
        GList *t;
215
 
        for (t = myData.pTasks; t != NULL; t = t->next)
216
 
        {
217
 
                pTask = t->data;
218
 
                switch (pTask->iFrequency)
219
 
                {
220
 
                        case CD_TASK_DONT_REPEAT:
221
 
                        default:
222
 
                                d = pTask->iDay;
223
 
                                m = pTask->iMonth+1;
224
 
                                y = pTask->iYear;
225
 
                                g_date_set_dmy (pDate, d, m, y);
226
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
227
 
                        break;
228
 
                        
229
 
                        case CD_TASK_EACH_MONTH:
230
 
                                d = pTask->iDay;
231
 
                                m = iMonth+1;
232
 
                                y = iYear;
233
 
                                g_date_set_dmy (pDate, d, m, y);
234
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
235
 
                                if (iDelta < 0)  // pDate est avant pCurrentDate => on teste le mois d'apres.
236
 
                                {
237
 
                                        if (iMonth < 11)
238
 
                                        {
239
 
                                                m = iMonth+2;
240
 
                                                g_date_set_dmy (pDate, d, m, y);
241
 
                                        }
242
 
                                        else
243
 
                                        {
244
 
                                                m = 1;
245
 
                                                y = pTask->iYear + 1;
246
 
                                                g_date_set_dmy (pDate, d, m, y);
247
 
                                        }
248
 
                                        iDelta = g_date_days_between (pCurrentDate, pDate);
249
 
                                }
250
 
                        break;
251
 
                        
252
 
                        case CD_TASK_EACH_YEAR:
253
 
                                d = pTask->iDay;
254
 
                                m = pTask->iMonth+1;
255
 
                                y = iYear;
256
 
                                g_date_set_dmy (pDate, d, m, y);
257
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
258
 
                                //g_print ("iDelta : %d/%d/%d -> %d (%s)\n", d, m, y, iDelta, pTask->cTitle);
259
 
                                if (iDelta < 0)  // pDate est avant pCurrentDate => on teste l'annee d'apres.
260
 
                                {
261
 
                                        y = iYear + 1;
262
 
                                        g_date_set_dmy (pDate, d, m, y);
263
 
                                        iDelta = g_date_days_between (pCurrentDate, pDate);
264
 
                                }
265
 
                        break;
266
 
                }
267
 
                
268
 
                if (iDelta >= 0 && iDelta < 7)
269
 
                {
270
 
                        if (sTaskString == NULL)
271
 
                                sTaskString = g_string_new ("");
272
 
                        g_string_append_printf (sTaskString, "<b><u>%s</u></b>\n <i>%d/%d/%d at %d:%02d</i>\n %s\n",
273
 
                                pTask->cTitle ? pTask->cTitle : D_("No title"),
274
 
                                (myConfig.bNormalDate ? d : y), m, (myConfig.bNormalDate ? y : d),
275
 
                                pTask->iHour, pTask->iMinute,
276
 
                                pTask->cText?pTask->cText:"");
277
 
                }  // on n'arrete pas le parcours si iDelta > 7 pour prendre en compte aussi les anniv.
278
 
        }
279
 
        g_date_free (pCurrentDate);
280
 
        g_date_free (pDate);
281
 
        
282
 
        if (sTaskString == NULL)
283
 
                return NULL;
284
 
        
285
 
        gchar *cTasks = sTaskString->str;
286
 
        g_string_free (sTaskString, FALSE);
287
 
        return cTasks;
288
 
}
289
 
 
290
 
#define _compute_index(y,m,d,h,mi) ((((y*12+m)*32+d)*24+h)*60+mi)
291
 
CDClockTask *cd_clock_get_next_scheduled_task (GldiModuleInstance *myApplet)
292
 
{
293
 
        if (myData.pTasks == NULL)
294
 
                return NULL;
295
 
        
296
 
        guint iDay = myData.currentTime.tm_mday;
297
 
        guint iMonth = myData.currentTime.tm_mon;
298
 
        guint iYear = myData.currentTime.tm_year + 1900;
299
 
        guint iHour = myData.currentTime.tm_hour;
300
 
        guint iMinute = myData.currentTime.tm_min;
301
 
        gulong iIndex = _compute_index (iYear, iMonth, iDay, iHour, iMinute);
302
 
        gulong i, iNextIndex=0;
303
 
        //g_print ("%s (%d/%d/%d -> %ld)\n", __func__, iDay, iMonth, iYear, iIndex);
304
 
        
305
 
        CDClockTask *pNextTask = NULL;
306
 
        CDClockTask *pTask;
307
 
        GList *t;
308
 
        for (t = myData.pTasks; t != NULL; t = t->next)
309
 
        {
310
 
                pTask = t->data;
311
 
                //g_print ("test de %s (%d/%d/%d)\n", pTask->cTitle, pTask->iDay, pTask->iMonth, pTask->iYear);
312
 
                switch (pTask->iFrequency)
313
 
                {
314
 
                        case CD_TASK_DONT_REPEAT:
315
 
                        default:
316
 
                                i = _compute_index (pTask->iYear, pTask->iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);
317
 
                                //g_print (" normal : %ld\n", i);
318
 
                        break;
319
 
                        
320
 
                        case CD_TASK_EACH_MONTH:
321
 
                                i = _compute_index (iYear, iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);  // index pour le mois courant.
322
 
                                if (i < iIndex)  // on tombe avant, on calcule l'index pour le mois suivant.
323
 
                                {
324
 
                                        if (iMonth < 11)
325
 
                                                i = _compute_index (iYear, iMonth+1, pTask->iDay, pTask->iHour, pTask->iMinute);
326
 
                                        else
327
 
                                                i = _compute_index (iYear+1, 0, pTask->iDay, pTask->iHour, pTask->iMinute);
328
 
                                }
329
 
                                //g_print (" mensuel : %ld\n", i);
330
 
                        break;
331
 
                        
332
 
                        case CD_TASK_EACH_YEAR:
333
 
                                i = _compute_index (iYear, pTask->iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);
334
 
                                if (i < iIndex)  // on tombe avant, on calcule l'index pour l'annee suivante.
335
 
                                        i = _compute_index (iYear+1, pTask->iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);
336
 
                                //g_print (" annuel : %ld\n", i);
337
 
                        break;
338
 
                }
339
 
                if (i >= iIndex && (iNextIndex == 0 || i < iNextIndex))
340
 
                {
341
 
                        iNextIndex = i;
342
 
                        pNextTask = pTask;
343
 
                        //g_print ("pNextTask <- %s, index <- %ld\n", pNextTask->cTitle, iNextIndex);
344
 
                }
345
 
        }
346
 
        return pNextTask;
347
 
}
348
 
 
349
 
CDClockTask *cd_clock_get_next_anniversary (GldiModuleInstance *myApplet)
350
 
{
351
 
        if (myData.pTasks == NULL)
352
 
                return NULL;
353
 
        
354
 
        guint iDay = myData.currentTime.tm_mday;
355
 
        guint iMonth = myData.currentTime.tm_mon;
356
 
        guint iYear = myData.currentTime.tm_year + 1900;
357
 
        guint iHour = myData.currentTime.tm_hour;
358
 
        guint iMinute = myData.currentTime.tm_min;
359
 
        gulong iIndex = _compute_index (iYear, iMonth, iDay, iHour, iMinute);
360
 
        gulong i, iNextIndex=0;
361
 
        //g_print ("%s (%d/%d/%d -> %ld)\n", __func__, iDay, iMonth, iYear, iIndex);
362
 
        
363
 
        CDClockTask *pNextAnniversary = NULL;
364
 
        CDClockTask *pTask;
365
 
        GList *t;
366
 
        for (t = myData.pTasks; t != NULL; t = t->next)
367
 
        {
368
 
                pTask = t->data;
369
 
                if (pTask->iFrequency != CD_TASK_EACH_YEAR)
370
 
                        continue;
371
 
                //g_print ("test de %s (%d/%d/%d)\n", pTask->cTitle, pTask->iDay, pTask->iMonth, pTask->iYear);
372
 
                
373
 
                i = _compute_index (iYear, pTask->iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);
374
 
                if (i < iIndex)  // on tombe avant, on calcule l'index pour l'annee suivante.
375
 
                        i = _compute_index (iYear+1, pTask->iMonth, pTask->iDay, pTask->iHour, pTask->iMinute);
376
 
                //g_print (" annuel : %ld\n", i);
377
 
                
378
 
                if (i > iIndex && (iNextIndex == 0 || i < iNextIndex))
379
 
                {
380
 
                        iNextIndex = i;
381
 
                        pNextAnniversary = pTask;
382
 
                        //g_print ("pNextTask <- %s, index <- %ld\n", pNextTask->cTitle, iNextIndex);
383
 
                }
384
 
        }
385
 
        return pNextAnniversary;
386
 
}
387
 
 
388
 
 
389
 
GList *cd_clock_get_missed_tasks (GldiModuleInstance *myApplet)
390
 
{
391
 
        GList *pTaskList = NULL;
392
 
        guint iDay = myData.currentTime.tm_mday;
393
 
        guint iMonth = myData.currentTime.tm_mon;
394
 
        guint iYear = myData.currentTime.tm_year + 1900;
395
 
        guint iHour = myData.currentTime.tm_hour;
396
 
        guint iMinute = myData.currentTime.tm_min;
397
 
        
398
 
        GDate* pCurrentDate = g_date_new_dmy (iDay, iMonth + 1, iYear);
399
 
        GDate* pDate = g_date_new ();
400
 
        guint d, m, y;
401
 
        int iDelta;
402
 
        CDClockTask *pTask;
403
 
        GList *t;
404
 
        for (t = myData.pTasks; t != NULL; t = t->next)
405
 
        {
406
 
                pTask = t->data;
407
 
                if (pTask->bAcknowledged)
408
 
                        continue;
409
 
                
410
 
                switch (pTask->iFrequency)
411
 
                {
412
 
                        case CD_TASK_DONT_REPEAT:
413
 
                        default:
414
 
                                d = pTask->iDay;
415
 
                                m = pTask->iMonth+1;
416
 
                                y = pTask->iYear;
417
 
                                g_date_set_dmy (pDate, d, m, y);
418
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
419
 
                        break;
420
 
                        
421
 
                        case CD_TASK_EACH_MONTH:
422
 
                                d = pTask->iDay;
423
 
                                m = iMonth+1;
424
 
                                y = iYear;
425
 
                                g_date_set_dmy (pDate, d, m, y);
426
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
427
 
                                if (iDelta > 0)  // pDate est apres pCurrentDate => on teste le mois d'avant.
428
 
                                {
429
 
                                        if (iMonth > 0)
430
 
                                        {
431
 
                                                m = iMonth;
432
 
                                                g_date_set_dmy (pDate, d, m, y);
433
 
                                        }
434
 
                                        else
435
 
                                        {
436
 
                                                m = 12;
437
 
                                                y = pTask->iYear - 1;
438
 
                                                g_date_set_dmy (pDate, d, m, y);
439
 
                                        }
440
 
                                        iDelta = g_date_days_between (pCurrentDate, pDate);
441
 
                                }
442
 
                        break;
443
 
                        
444
 
                        case CD_TASK_EACH_YEAR:
445
 
                                d = pTask->iDay;
446
 
                                m = pTask->iMonth+1;
447
 
                                y = iYear;
448
 
                                g_date_set_dmy (pDate, d, m, y);
449
 
                                iDelta = g_date_days_between (pCurrentDate, pDate);
450
 
                                //g_print ("iDelta : %d/%d/%d -> %d (%s)\n", d, m, y, iDelta, pTask->cTitle);
451
 
                                if (iDelta > 0)  // pDate est apres pCurrentDate => on teste l'annee d'avant.
452
 
                                {
453
 
                                        y = iYear - 1;
454
 
                                        g_date_set_dmy (pDate, d, m, y);
455
 
                                        iDelta = g_date_days_between (pCurrentDate, pDate);
456
 
                                }
457
 
                        break;
458
 
                }
459
 
                
460
 
                if (iDelta <= 0 && iDelta > -7)
461
 
                {
462
 
                        if (iDelta == 0)  // today's task, check time
463
 
                        {
464
 
                                if (pTask->iHour > iHour || (pTask->iHour == iHour && pTask->iMinute > iMinute))  // it's in the future, skip it.
465
 
                                        continue;
466
 
                        }
467
 
                        pTaskList = g_list_prepend (pTaskList, pTask);
468
 
                }  // on n'arrete pas le parcours si iDelta > 7 pour prendre en compte aussi les anniv.
469
 
        }
470
 
        g_date_free (pCurrentDate);
471
 
        g_date_free (pDate);
472
 
        
473
 
        return pTaskList;
474
 
}
475
 
 
476
 
 
477
 
  //////////////
478
 
 // CALENDAR //
479
 
//////////////
480
 
 
481
 
static void _mark_days (GtkCalendar *pCalendar, GldiModuleInstance *myApplet)
482
 
{
483
 
        guint iYear, iMonth, iDay;
484
 
        gtk_calendar_get_date (GTK_CALENDAR (pCalendar),
485
 
                &iYear,
486
 
                &iMonth,
487
 
                &iDay);
488
 
        
489
 
        CDClockTask *pTask;
490
 
        GList *t;
491
 
        for (t = myData.pTasks; t != NULL; t = t->next)
492
 
        {
493
 
                pTask = t->data;
494
 
                if (_cd_task_matches_month (pTask, iMonth, iYear))
495
 
                {
496
 
                        gtk_calendar_mark_day (GTK_CALENDAR (pCalendar), pTask->iDay);
497
 
                }
498
 
        }
499
 
}
500
 
void cd_clock_update_calendar_marks (GldiModuleInstance *myApplet)
501
 
{
502
 
        if (myData.pCalendarDialog != NULL)
503
 
        {
504
 
                gtk_calendar_clear_marks (GTK_CALENDAR (myData.pCalendarDialog->pInteractiveWidget));
505
 
                _mark_days (GTK_CALENDAR (myData.pCalendarDialog->pInteractiveWidget), myApplet);
506
 
        }
507
 
}
508
 
 
509
 
static gchar * _on_display_task_detail (GtkCalendar *calendar, guint iYear, guint iMonth, guint iDay, GldiModuleInstance *myApplet)
510
 
{
511
 
        if (myData.pTasks == NULL)
512
 
                return NULL;
513
 
        
514
 
        //g_print ("%s (%d/%d/%d)\n", __func__, iDay, iMonth, iYear);
515
 
        GString *sDetail = NULL;
516
 
        CDClockTask *pTask;
517
 
        GList *t;
518
 
        for (t = myData.pTasks; t != NULL; t = t->next)
519
 
        {
520
 
                pTask = t->data;
521
 
                if (_cd_task_matches_day (pTask, iDay, iMonth, iYear))
522
 
                {
523
 
                        if (sDetail == NULL)
524
 
                                sDetail = g_string_new ("");
525
 
                        if (pTask->iFrequency == CD_TASK_EACH_YEAR && iYear > pTask->iYear)
526
 
                                g_string_append_printf (sDetail, "<b><u>%s</u> (%d %s)</b>\n <i>at %d:%02d</i>\n %s\n",
527
 
                                        pTask->cTitle ? pTask->cTitle : D_("No title"),
528
 
                                        iYear - pTask->iYear, D_("years"),
529
 
                                        pTask->iHour, pTask->iMinute,
530
 
                                        pTask->cText?pTask->cText:"");
531
 
                        else
532
 
                                g_string_append_printf (sDetail, "<b><u>%s</u></b>\n <i>at %d:%02d</i>\n %s\n", pTask->cTitle ? pTask->cTitle : D_("No title"),
533
 
                                pTask->iHour, pTask->iMinute,
534
 
                                pTask->cText?pTask->cText:"");
535
 
                }
536
 
        }
537
 
        
538
 
        if (sDetail == NULL)
539
 
                return NULL;
540
 
        gchar *cDetail= sDetail->str;
541
 
        g_string_free (sDetail, FALSE);
542
 
        //g_print ("* detail : %s\n", cDetail);
543
 
        return cDetail;
544
 
}
545
 
 
546
 
static void _on_day_selected_double_click (GtkCalendar *pCalendar, GldiModuleInstance *myApplet)
547
 
{
548
 
        guint iDay, iMonth, iYear;
549
 
        gtk_calendar_get_date (pCalendar,
550
 
                &iYear,
551
 
                &iMonth,
552
 
                &iDay);
553
 
        cd_clock_build_task_editor (iDay, iMonth, iYear, myApplet);
554
 
}
555
 
 
556
 
static void _on_date_changed (GtkCalendar *pCalendar, GldiModuleInstance *myApplet)
557
 
{
558
 
        gtk_calendar_clear_marks (pCalendar);
559
 
        _mark_days (pCalendar, myApplet);
560
 
}
561
 
 
562
 
static void _on_add_task (GtkWidget *pMenuItem, GldiModuleInstance *myApplet)
563
 
{
564
 
        guint iDay, iMonth, iYear;
565
 
        gtk_calendar_get_date (GTK_CALENDAR (myData.pCalendarDialog->pInteractiveWidget),
566
 
                &iYear,
567
 
                &iMonth,
568
 
                &iDay);
569
 
        
570
 
        CDClockTask *pTask = g_new0 (CDClockTask, 1);
571
 
        pTask->iDay = iDay;
572
 
        pTask->iMonth = iMonth;
573
 
        pTask->iYear = iYear;
574
 
        pTask->cTitle = g_strdup (D_("No title"));
575
 
        pTask->iHour = 12;
576
 
        gboolean bCreated = myData.pBackend->create_task (pTask, myApplet);
577
 
        if (bCreated)
578
 
        {
579
 
                cd_clock_add_task_to_list (pTask, myApplet);
580
 
                
581
 
                cd_clock_update_calendar_marks (myApplet);
582
 
        }
583
 
        
584
 
        cd_clock_build_task_editor (iDay, iMonth, iYear, myApplet);
585
 
}
586
 
static void _on_edit_tasks (GtkWidget *pMenuItem, GldiModuleInstance *myApplet)
587
 
{
588
 
        guint iDay, iMonth, iYear;
589
 
        gtk_calendar_get_date (GTK_CALENDAR (myData.pCalendarDialog->pInteractiveWidget),
590
 
                &iYear,
591
 
                &iMonth,
592
 
                &iDay);
593
 
        cd_clock_build_task_editor (iDay, iMonth, iYear, myApplet);
594
 
}
595
 
static gboolean on_button_released_calendar (GtkWidget *widget,
596
 
        GdkEventButton *pButton,
597
 
        GldiModuleInstance *myApplet)
598
 
{
599
 
        if (pButton->button == 3)  // right-click
600
 
        {
601
 
                GtkWidget *pMenu = gldi_menu_new (NULL);
602
 
                
603
 
                // add a task
604
 
                cairo_dock_add_in_menu_with_stock_and_data (D_("Add a new task"), GLDI_ICON_NAME_ADD, G_CALLBACK (_on_add_task), pMenu, myApplet);
605
 
                
606
 
                // edit tasks
607
 
                gchar *cLabel = g_strdup_printf ("%s (%s)", D_("Edit tasks"), D_("double-click"));
608
 
                cairo_dock_add_in_menu_with_stock_and_data (cLabel, GLDI_ICON_NAME_EDIT, G_CALLBACK (_on_edit_tasks), pMenu, myApplet);
609
 
                g_free (cLabel);
610
 
                
611
 
                gtk_widget_show_all (GTK_WIDGET (pMenu));
612
 
                gtk_menu_popup (GTK_MENU (pMenu),
613
 
                        NULL,
614
 
                        NULL,
615
 
                        NULL,
616
 
                        NULL,  // data
617
 
                        1,
618
 
                        gtk_get_current_event_time ());
619
 
        }
620
 
        return FALSE;
621
 
}
622
 
 
623
 
static GtkWidget *cd_clock_build_calendar (GldiModuleInstance *myApplet)
624
 
{
625
 
        cd_message ("%s ()", __func__);
626
 
        GtkWidget *pCalendar = gtk_calendar_new ();
627
 
        g_object_set (G_OBJECT (pCalendar), "show-details", FALSE, NULL);
628
 
        
629
 
        _mark_days (GTK_CALENDAR (pCalendar), myApplet);
630
 
        
631
 
        // reload the marks when the month/year changes
632
 
        g_signal_connect (G_OBJECT (pCalendar), "prev-month" , G_CALLBACK (_on_date_changed), myApplet);
633
 
        g_signal_connect (G_OBJECT (pCalendar), "next-month" , G_CALLBACK (_on_date_changed), myApplet);
634
 
        g_signal_connect (G_OBJECT (pCalendar), "prev-year" , G_CALLBACK (_on_date_changed), myApplet);
635
 
        g_signal_connect (G_OBJECT (pCalendar), "next-year" , G_CALLBACK (_on_date_changed), myApplet);
636
 
        // edit tasks on double-click or right-click
637
 
        g_signal_connect (G_OBJECT (pCalendar), "day-selected-double-click" , G_CALLBACK (_on_day_selected_double_click), myApplet);  // it's not a good idea to show the task-editor on left-click, because we can receve the 'click' event when clicking on the month/year buttons, and the 'day-selected' event when we change the month/year.
638
 
        g_signal_connect (G_OBJECT (pCalendar),
639
 
                "button-release-event",
640
 
                G_CALLBACK (on_button_released_calendar),
641
 
                myApplet);
642
 
 
643
 
        gtk_calendar_set_detail_func (GTK_CALENDAR (pCalendar),
644
 
                (GtkCalendarDetailFunc) _on_display_task_detail,
645
 
                myApplet,
646
 
                (GDestroyNotify) NULL);
647
 
        return pCalendar;
648
 
}
649
 
 
650
 
void cd_clock_hide_dialogs (GldiModuleInstance *myApplet)
651
 
{
652
 
        gldi_dialogs_remove_on_icon (myIcon);
653
 
        myData.pCalendarDialog = NULL;
654
 
}
655
 
 
656
 
 
657
 
static void _on_dialog_destroyed (GldiModuleInstance *myApplet)
658
 
{
659
 
        myData.pCalendarDialog = NULL;
660
 
}
661
 
void cd_clock_show_hide_calendar (GldiModuleInstance *myApplet)
662
 
{
663
 
        cd_debug ("%s (%x)", __func__, myData.pCalendarDialog);
664
 
        if (myData.pCalendarDialog != NULL)
665
 
        {
666
 
                gldi_object_unref (GLDI_OBJECT(myData.pCalendarDialog));
667
 
                myData.pCalendarDialog = NULL;
668
 
                if (myData.pTaskWindow != NULL)
669
 
                {
670
 
                        gtk_widget_destroy (myData.pTaskWindow);
671
 
                        myData.pTaskWindow = NULL;
672
 
                        myData.pModel = NULL;
673
 
                }
674
 
        }
675
 
        else
676
 
        {
677
 
                gldi_dialogs_remove_on_icon (myIcon);
678
 
                GtkWidget *pCalendar = cd_clock_build_calendar (myApplet);
679
 
                myData.pCalendarDialog = gldi_dialog_show (D_("Calendar and tasks"),
680
 
                        myIcon, myContainer,
681
 
                        0,
682
 
                        MY_APPLET_SHARE_DATA_DIR"/dates.svg",
683
 
                        pCalendar,
684
 
                        NULL,
685
 
                        myApplet,
686
 
                        (GFreeFunc)_on_dialog_destroyed);
687
 
        }
688
 
}