2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
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.
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/>.
25
#include "applet-struct.h"
26
#include "applet-calendar.h"
27
#include "applet-task-editor.h"
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))
32
typedef enum _CDClockTaskColumns
45
static gboolean on_delete_task_window (GtkWidget *pWidget, GdkEvent *event, CairoDockModuleInstance *myApplet)
47
//g_print ("%s ()\n", __func__);
56
myData.pTaskWindow = NULL;
58
return FALSE; // detruit la fenetre.
61
static GtkListStore *_cd_clock_create_model_for_current_day (guint iDay, guint iMonth, guint iYear, CairoDockModuleInstance *myApplet)
63
//g_print ("%s (%d/%d/%d)\n", __func__, iDay, iMonth, iYear);
64
//\______________ On cree le modele.
66
if (myData.pModel != NULL)
68
gtk_list_store_clear (myData.pModel);
69
pModel = myData.pModel;
73
pModel = gtk_list_store_new (CD_TASKS_NB_COLUMNS,
74
G_TYPE_STRING, // CD_TASK_ID
75
G_TYPE_BOOLEAN, // CD_TASK_ACTIVE
76
G_TYPE_STRING, // CD_TASK_TITLE
77
G_TYPE_STRING, // CD_TASK_TAGS
78
G_TYPE_STRING, // CD_TASK_TEXT
79
G_TYPE_INT, // CD_TASK_TIME
80
G_TYPE_INT); // CD_TASK_FREQ
81
myData.pModel = pModel;
83
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (pModel), CD_TASK_TIME, GTK_SORT_ASCENDING);
85
//\______________ On remplit le modele.
88
for (t = myData.pTasks; t != NULL; t = t->next)
91
if (_cd_task_matches_day (pTask, iDay, iMonth, iYear))
93
//g_print (" + %s\n", pTask->cTitle);
95
memset (&iter, 0, sizeof (GtkTreeIter));
96
gtk_list_store_append (GTK_LIST_STORE (pModel), &iter);
97
gtk_list_store_set (GTK_LIST_STORE (pModel), &iter,
98
CD_TASK_ID, pTask->cID,
100
CD_TASK_TITLE, pTask->cTitle,
101
CD_TASK_TEXT, pTask->cText,
102
CD_TASK_TAGS, pTask->cTags,
103
CD_TASK_TIME, pTask->iHour*60 + pTask->iMinute,
104
CD_TASK_FREQ, pTask->iFrequency, -1);
110
static void _cd_clock_add_new_task (GtkMenuItem *pMenuItem, CairoDockModuleInstance *myApplet)
112
//g_print ("%s ()\n", __func__);
113
CDClockTask *pTask = g_new0 (CDClockTask, 1);
114
int iDay, iMonth, iYear;
116
pTask->iDay = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (myData.pTaskWindow), "day"));
117
pTask->iMonth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (myData.pTaskWindow), "month"));
118
pTask->iYear = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (myData.pTaskWindow), "year"));
119
pTask->cTitle = g_strdup (D_("No title"));
121
gboolean bCreated = myData.pBackend->create_task (pTask, myApplet);
124
cd_clock_add_task_to_list (pTask, myApplet);
126
_cd_clock_create_model_for_current_day (pTask->iDay, pTask->iMonth, pTask->iYear, myApplet); // on pourrait n'ajouter que la ligne concernee mais inutile de compliquer pour si peu.
127
gtk_widget_show_all (myData.pTaskWindow);
129
cd_clock_update_calendar_marks (myApplet);
132
static void _cd_clock_delete_task (GtkMenuItem *pMenuItem, gpointer *data)
134
cd_debug ("%s ()", __func__);
135
CairoDockModuleInstance *myApplet = data[0];
136
CDClockTask *pTask = data[1];
137
gboolean bDeleted = myData.pBackend->delete_task (pTask, myApplet);
141
cd_clock_remove_task_from_list (pTask, myApplet);
143
_cd_clock_create_model_for_current_day (pTask->iDay, pTask->iMonth, pTask->iYear, myApplet); // on pourrait n'effacer que la ligne concernee mais inutile de compliquer pour si peu.
144
cd_clock_free_task (pTask);
145
gtk_widget_show_all (myData.pTaskWindow);
147
cd_clock_update_calendar_marks (myApplet);
150
static gboolean _on_click_tree_view (GtkTreeView *pTreeView, GdkEventButton* pButton, CairoDockModuleInstance *myApplet)
152
static gpointer *data = NULL;
153
if (pButton->button == 3 && pButton->type == GDK_BUTTON_RELEASE)
155
GtkWidget *pMenu = gtk_menu_new ();
156
cairo_dock_add_in_menu_with_stock_and_data (D_("Add a new task"), GTK_STOCK_ADD, (GFunc)_cd_clock_add_new_task, pMenu, myApplet);
158
GtkTreeSelection *pSelection = gtk_tree_view_get_selection (pTreeView);
159
GtkTreeModel *pModel;
161
if (gtk_tree_selection_get_selected (pSelection, &pModel, &iter))
163
gchar *cTaskID = NULL;
164
gtk_tree_model_get (pModel, &iter,
165
CD_TASK_ID, &cTaskID, -1);
166
CDClockTask *pTask = cd_clock_get_task_by_id (cTaskID, myApplet);
172
data = g_new (gpointer, 3);
177
cairo_dock_add_in_menu_with_stock_and_data (D_("Delete this task"), GTK_STOCK_REMOVE, (GFunc)_cd_clock_delete_task, pMenu, data);
180
gtk_widget_show_all (pMenu);
181
gtk_menu_popup (GTK_MENU (pMenu),
187
gtk_get_current_event_time ());
192
static gboolean _cd_clock_select_one_item_in_tree (GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, CairoDockModuleInstance *myApplet)
194
if (path_currently_selected)
197
if (! gtk_tree_model_get_iter (model, &iter, path))
200
//g_print ("%s ()\n", __func__);
206
static GtkListStore *_make_frequency_list_store (void)
208
GtkListStore *freq_list = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
211
memset (&iter, 0, sizeof (GtkTreeIter));
212
gtk_list_store_append (GTK_LIST_STORE (freq_list), &iter);
213
gtk_list_store_set (GTK_LIST_STORE (freq_list), &iter,
214
0, CD_TASK_DONT_REPEAT,
215
1, D_("Don't repeat"), -1);
217
memset (&iter, 0, sizeof (GtkTreeIter));
218
gtk_list_store_append (GTK_LIST_STORE (freq_list), &iter);
219
gtk_list_store_set (GTK_LIST_STORE (freq_list), &iter,
220
0, CD_TASK_EACH_MONTH,
221
1, D_("Each month"), -1);
223
memset (&iter, 0, sizeof (GtkTreeIter));
224
gtk_list_store_append (GTK_LIST_STORE (freq_list), &iter);
225
gtk_list_store_set (GTK_LIST_STORE (freq_list), &iter,
226
0, CD_TASK_EACH_YEAR,
227
1, D_("Each year"), -1);
232
#define _get_task_from_path(new_text, path_string)\
233
GtkListStore *model = myData.pModel;\
235
if (! gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &it, path_string))\
238
gtk_tree_model_get (GTK_TREE_MODEL (model), &it, CD_TASK_ID, &cID, -1);\
239
CDClockTask *pTask = cd_clock_get_task_by_id (cID, myApplet);\
241
g_return_if_fail (pTask != NULL);
243
static void _on_change_title (GtkCellRendererText * cell, gchar * path_string, gchar * new_text, CairoDockModuleInstance *myApplet)
245
if (new_text == NULL || *new_text == '\0')\
247
_get_task_from_path (new_text, path_string);
249
g_free (pTask->cTitle);
250
pTask->cTitle = g_strdup (new_text);
251
gboolean bUpdated = myData.pBackend->update_task (pTask, myApplet);
254
gtk_list_store_set (GTK_LIST_STORE (model), &it, CD_TASK_TITLE, pTask->cTitle, -1);
258
static void _on_change_text (GtkCellRendererText * cell, gchar * path_string, gchar * new_text, CairoDockModuleInstance *myApplet)
260
_get_task_from_path (new_text, path_string);
262
g_free (pTask->cText);
263
pTask->cText = g_strdup (new_text);
264
gboolean bUpdated = myData.pBackend->update_task (pTask, myApplet);
267
gtk_list_store_set (GTK_LIST_STORE (model), &it, CD_TASK_TEXT, pTask->cText, -1);
271
static void _on_change_tags (GtkCellRendererText * cell, gchar * path_string, gchar * new_text, CairoDockModuleInstance *myApplet)
273
_get_task_from_path (new_text, path_string);
275
g_free (pTask->cTags);
276
pTask->cTags = g_strdup (new_text);
277
gboolean bUpdated = myData.pBackend->update_task (pTask, myApplet);
280
gtk_list_store_set (GTK_LIST_STORE (model), &it, CD_TASK_TAGS, pTask->cTags, -1);
284
static void _on_change_time (GtkCellRendererText * cell, gchar * path_string, gchar * new_text, CairoDockModuleInstance *myApplet)
286
_get_task_from_path(new_text, path_string);
289
sscanf (new_text, "%d:%d", &h, &m);
290
pTask->iHour = MAX (0, MIN (23, h));
291
pTask->iMinute = MAX (0, MIN (59, m));
292
gboolean bUpdated = myData.pBackend->update_task (pTask, myApplet);
295
pTask->bFirstWarning = FALSE;
296
pTask->b15mnWarning = FALSE;
297
gtk_list_store_set (GTK_LIST_STORE (model), &it, CD_TASK_TIME, pTask->iHour*60+pTask->iMinute, -1);
298
myData.pNextTask = cd_clock_get_next_scheduled_task (myApplet);
302
static gboolean _search_frequency (GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer *data)
306
gtk_tree_model_get (model, iter,
309
if (cName && strcmp (cName, data[0]) == 0)
311
data[1] = GINT_TO_POINTER (iFrequency);
316
static void _on_change_frequency (GtkCellRendererText * cell, gchar * path_string, gchar * new_text, CairoDockModuleInstance *myApplet)
318
_get_task_from_path(new_text, path_string);
320
GtkListStore *pModel = NULL;
321
g_object_get (cell, "model", &pModel, NULL);
322
gpointer data[2] = {new_text, GINT_TO_POINTER (CD_TASK_NB_FREQUENCIES)};
323
gtk_tree_model_foreach (GTK_TREE_MODEL (pModel), (GtkTreeModelForeachFunc) _search_frequency, data);
324
g_object_unref (pModel);
326
pTask->iFrequency = GPOINTER_TO_INT (data[1]);
327
gboolean bUpdated = myData.pBackend->update_task (pTask, myApplet);
331
pTask->bFirstWarning = FALSE;
332
pTask->b15mnWarning = FALSE;
333
gtk_list_store_set (GTK_LIST_STORE (model), &it, CD_TASK_FREQ, pTask->iFrequency, -1);
334
myData.pNextTask = cd_clock_get_next_scheduled_task (myApplet);
338
static void _cd_clock_render_frequency (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model,GtkTreeIter *iter, CairoDockModuleInstance *myApplet)
341
gtk_tree_model_get (model, iter, CD_TASK_FREQ, &iFrequency, -1);
345
case CD_TASK_DONT_REPEAT :
347
g_object_set (cell, "text", "-", NULL);
349
case CD_TASK_EACH_MONTH :
350
g_object_set (cell, "text", D_("each month"), NULL);
352
case CD_TASK_EACH_YEAR :
353
g_object_set (cell, "text", D_("each year"), NULL);
358
static void _cd_clock_render_time (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model,GtkTreeIter *iter, CairoDockModuleInstance *myApplet)
361
gtk_tree_model_get (model, iter, CD_TASK_TIME, &iTime, -1);
364
int m = iTime - h * 60;
365
gchar *cTime = g_strdup_printf ("%02d:%02d", h, m);
366
g_object_set (cell, "text", cTime, NULL);
371
void cd_clock_build_task_editor (guint iDay, guint iMonth, guint iYear, CairoDockModuleInstance *myApplet)
373
//\______________ On remplit le modele avec la date courante.
374
GtkListStore *pModel = _cd_clock_create_model_for_current_day (iDay, iMonth, iYear, myApplet);
376
//\______________ On construit/met a jour la fenetre.
377
if (myData.pTaskWindow == NULL)
379
myData.pTaskWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
381
//\______________ On construit le treeview.
382
GtkWidget *pTreeView = gtk_tree_view_new ();
383
gtk_tree_view_set_model (GTK_TREE_VIEW (pTreeView), GTK_TREE_MODEL (pModel));
384
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pTreeView), TRUE);
385
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pTreeView), TRUE);
386
g_signal_connect (G_OBJECT (pTreeView), "button-release-event", G_CALLBACK (_on_click_tree_view), myApplet);
387
GtkTreeViewColumn* col;
388
GtkCellRenderer *rend;
389
if (myData.pTasks == NULL) // on ajoute un message pour l'utilisateur debutant.
391
gtk_widget_set_tooltip_text (pTreeView, D_("Right-click to add a new task."));
394
rend = gtk_cell_renderer_text_new ();
395
g_object_set (G_OBJECT (rend), "editable", TRUE, NULL);
396
g_signal_connect (G_OBJECT (rend), "edited", (GCallback) _on_change_title, myApplet);
397
col = gtk_tree_view_column_new_with_attributes (D_("Title"), rend, "text", CD_TASK_TITLE, NULL);
398
gtk_tree_view_column_set_sort_column_id (col, CD_TASK_TITLE);
399
gtk_tree_view_append_column (GTK_TREE_VIEW (pTreeView), col);
401
rend = gtk_cell_renderer_text_new ();
402
g_object_set (G_OBJECT (rend), "editable", TRUE, NULL);
403
g_signal_connect (G_OBJECT (rend), "edited", (GCallback) _on_change_text, myApplet);
404
col = gtk_tree_view_column_new_with_attributes (D_("Text"), rend, "text", CD_TASK_TEXT, NULL);
405
gtk_tree_view_column_set_sort_column_id (col, CD_TASK_TEXT);
406
gtk_tree_view_append_column (GTK_TREE_VIEW (pTreeView), col);
408
rend = gtk_cell_renderer_text_new ();
409
g_object_set (G_OBJECT (rend), "editable", TRUE, NULL);
410
g_signal_connect (G_OBJECT (rend), "edited", (GCallback) _on_change_time, myApplet);
411
col = gtk_tree_view_column_new_with_attributes (D_("Time"), rend, "text", CD_TASK_TIME, NULL);
412
gtk_tree_view_column_set_cell_data_func (col, rend, (GtkTreeCellDataFunc)_cd_clock_render_time, NULL, NULL);
413
gtk_tree_view_column_set_sort_column_id (col, CD_TASK_TIME);
414
gtk_tree_view_append_column (GTK_TREE_VIEW (pTreeView), col);
416
rend = gtk_cell_renderer_combo_new ();
417
GtkListStore *freq_list = _make_frequency_list_store ();
418
g_object_set (G_OBJECT (rend),
424
g_signal_connect (G_OBJECT (rend), "edited", (GCallback) _on_change_frequency, myApplet);
425
col = gtk_tree_view_column_new_with_attributes (D_("Freq."), rend, "text", CD_TASK_FREQ, NULL);
426
gtk_tree_view_column_set_cell_data_func (col, rend, (GtkTreeCellDataFunc)_cd_clock_render_frequency, myApplet, NULL);
427
gtk_tree_view_append_column (GTK_TREE_VIEW (pTreeView), col);
429
rend = gtk_cell_renderer_text_new ();
430
g_object_set (G_OBJECT (rend), "editable", TRUE, NULL);
431
g_signal_connect (G_OBJECT (rend), "edited", (GCallback) _on_change_tags, myApplet);
432
col = gtk_tree_view_column_new_with_attributes (D_("Tags"), rend, "text", CD_TASK_TAGS, NULL);
433
gtk_tree_view_column_set_sort_column_id (col, CD_TASK_TAGS);
434
gtk_tree_view_append_column (GTK_TREE_VIEW (pTreeView), col);
436
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pTreeView));
437
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
438
gtk_tree_selection_set_select_function (selection,
439
(GtkTreeSelectionFunc) _cd_clock_select_one_item_in_tree,
443
//\______________ On l'ajoute a la fenetre.
444
GtkWidget *pScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
445
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
446
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pScrolledWindow), pTreeView);
447
gtk_container_add (GTK_CONTAINER (myData.pTaskWindow), pScrolledWindow);
448
//gtk_box_pack_start (GTK_BOX (pVBox), pScrolledWindow, FALSE, FALSE, 0);
450
g_signal_connect (myData.pTaskWindow, "delete-event", G_CALLBACK (on_delete_task_window), myApplet);
451
gtk_window_set_keep_above (GTK_WINDOW (myData.pTaskWindow), TRUE);
452
///gtk_window_set_modal (GTK_WINDOW (myData.pTaskWindow), TRUE);
453
gtk_window_resize (GTK_WINDOW (myData.pTaskWindow), 640, 300);
456
gchar *cTitle = g_strdup_printf ("%d/%d/%d", (myConfig.bNormalDate ? iDay : iYear), iMonth+1 /*et oui, ca commence a 1 dans la vraie vie :)*/, (myConfig.bNormalDate ? iYear : iDay));
457
gtk_window_set_title (GTK_WINDOW (myData.pTaskWindow), cTitle);
459
g_object_set_data (G_OBJECT (myData.pTaskWindow), "day", GINT_TO_POINTER (iDay));
460
g_object_set_data (G_OBJECT (myData.pTaskWindow), "month", GINT_TO_POINTER (iMonth));
461
g_object_set_data (G_OBJECT (myData.pTaskWindow), "year", GINT_TO_POINTER (iYear));
462
gtk_widget_show_all (myData.pTaskWindow);