1 /*
2 * Osmo - a handy personal organizer
3 *
4 * Copyright (C) 2007-2009 Tomasz Maka <pasp@users.sourceforge.net>
5 * 2007-2009 Piotr Maka <silloz@users.sourceforge.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (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 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "calendar.h"
23 #include "i18n.h"
24 #include "options_prefs.h"
25 #include "stock_icons.h"
26 #include "tasks.h"
27 #include "tasks_preferences_gui.h"
28 #include "utils_gui.h"
29
30 #ifdef TASKS_ENABLED
31
32 /* ========================================================================== */
33
34 static void
checkbutton_clicked_cb(GtkToggleButton * togglebutton,gint * option)35 checkbutton_clicked_cb (GtkToggleButton *togglebutton, gint *option)
36 {
37 *option = gtk_toggle_button_get_active (togglebutton);
38 }
39
40 /* ========================================================================== */
41
42 static void
due_today_color_changed_cb(GtkColorChooser * color_button,GUI * appGUI)43 due_today_color_changed_cb (GtkColorChooser *color_button, GUI *appGUI)
44 {
45 GdkRGBA color;
46
47 gtk_color_chooser_get_rgba (color_button, &color);
48 utl_gui_convert_color_to_string (&color, config.due_today_color);
49 refresh_tasks (appGUI);
50 }
51
52 /* ========================================================================== */
53
54 static void
due_7days_color_changed_cb(GtkColorChooser * color_button,GUI * appGUI)55 due_7days_color_changed_cb (GtkColorChooser *color_button, GUI *appGUI)
56 {
57 GdkRGBA color;
58
59 gtk_color_chooser_get_rgba (color_button, &color);
60 utl_gui_convert_color_to_string(&color, config.due_7days_color);
61 refresh_tasks (appGUI);
62 }
63
64 /* ========================================================================== */
65
66 static void
past_due_color_changed_cb(GtkColorChooser * color_button,GUI * appGUI)67 past_due_color_changed_cb (GtkColorChooser *color_button, GUI *appGUI)
68 {
69 GdkRGBA color;
70
71 gtk_color_chooser_get_rgba (color_button, &color);
72 utl_gui_convert_color_to_string (&color, config.past_due_color);
73 refresh_tasks (appGUI);
74 }
75
76 /* ========================================================================== */
77
78 static void
bold_items_cb(GtkToggleButton * widget,GUI * appGUI)79 bold_items_cb (GtkToggleButton *widget, GUI *appGUI)
80 {
81 config.tasks_high_in_bold = gtk_toggle_button_get_active (widget);
82 refresh_tasks (appGUI);
83 }
84
85 /* ========================================================================== */
86
87 static void
ti_font_select_cb(GtkWidget * widget,GUI * appGUI)88 ti_font_select_cb (GtkWidget *widget, GUI *appGUI)
89 {
90 GtkWidget *font_selector;
91 gchar *font_name;
92 gint response;
93
94 font_selector = gtk_font_chooser_dialog_new (_("Select a font..."), GTK_WINDOW (appGUI->main_window));
95 gtk_window_set_modal (GTK_WINDOW (font_selector), TRUE);
96 gtk_window_set_position (GTK_WINDOW (font_selector), GTK_WIN_POS_MOUSE);
97 gtk_window_set_transient_for (GTK_WINDOW (font_selector), GTK_WINDOW (appGUI->main_window));
98 gtk_font_chooser_set_font (GTK_FONT_CHOOSER (font_selector), config.task_info_font);
99 gtk_widget_show (font_selector);
100 response = gtk_dialog_run (GTK_DIALOG (font_selector));
101
102 if (response == GTK_RESPONSE_OK) {
103 font_name = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font_selector));
104 g_strlcpy (config.task_info_font, font_name, MAXFONTNAME);
105 gtk_entry_set_text (GTK_ENTRY (appGUI->opt->ti_font_entry), font_name);
106 g_free (font_name);
107 g_object_set (G_OBJECT (appGUI->tsk->font_tag_object), "font", (gchar *) config.task_info_font, NULL);
108 }
109
110 gtk_widget_destroy (font_selector);
111 }
112
113 /* ========================================================================== */
114
115 static void
create_appearance_section(GtkWidget * appearance_vbox,GUI * appGUI)116 create_appearance_section (GtkWidget *appearance_vbox, GUI *appGUI)
117 {
118 GtkWidget *table, *colors_hbox;
119 GtkWidget *checkbutton, *label, *color_button, *font_button;
120 GdkRGBA color;
121
122 table = gtk_grid_new ();
123 gtk_box_pack_start (GTK_BOX (appearance_vbox), table, FALSE, FALSE, 0);
124 gtk_grid_set_column_spacing (GTK_GRID (table), 4);
125 gtk_grid_set_row_spacing (GTK_GRID (table), 8);
126
127 colors_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
128 gtk_grid_attach (GTK_GRID (table), colors_hbox, 1, 0, 1, 1);
129
130 color_button = gtk_color_button_new ();
131 if (config.enable_tooltips)
132 gtk_widget_set_tooltip_text (color_button, _("Color of items that are due today"));
133 gdk_rgba_parse (&color, config.due_today_color);
134 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &color);
135 gtk_box_pack_start (GTK_BOX (colors_hbox), color_button, FALSE, FALSE, 0);
136 g_signal_connect (G_OBJECT (color_button), "color-set", G_CALLBACK (due_today_color_changed_cb), appGUI);
137 appGUI->opt->due_today_color_picker = color_button;
138
139 color_button = gtk_color_button_new ();
140 g_signal_connect (G_OBJECT (color_button), "color-set", G_CALLBACK (due_7days_color_changed_cb), appGUI);
141 if (config.enable_tooltips)
142 gtk_widget_set_tooltip_text (color_button, _("Color of items that are due in the next 7 days"));
143 gdk_rgba_parse (&color, config.due_7days_color);
144 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &color);
145 gtk_box_pack_start (GTK_BOX (colors_hbox), color_button, FALSE, FALSE, 0);
146 appGUI->opt->due_7days_color_picker = color_button;
147
148 color_button = gtk_color_button_new ();
149 if (config.enable_tooltips)
150 gtk_widget_set_tooltip_text (color_button, _("Color of items that are past due"));
151 gdk_rgba_parse(&color, config.past_due_color);
152 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &color);
153 gtk_box_pack_start (GTK_BOX (colors_hbox), color_button, FALSE, FALSE, 0);
154 g_signal_connect (G_OBJECT (color_button), "color-set", G_CALLBACK (past_due_color_changed_cb), appGUI);
155 appGUI->opt->past_due_color_picker = color_button;
156
157 appGUI->opt->ti_font_entry = gtk_entry_new ();
158 gtk_entry_set_text (GTK_ENTRY (appGUI->opt->ti_font_entry), config.task_info_font);
159 gtk_widget_set_can_focus (appGUI->opt->ti_font_entry, FALSE);
160 gtk_widget_set_hexpand(appGUI->opt->ti_font_entry, TRUE);
161 gtk_grid_attach (GTK_GRID (table), appGUI->opt->ti_font_entry, 1, 1, 1, 1);
162
163 font_button = gtk_button_new_from_icon_name ("gtk-select-font", GTK_ICON_SIZE_BUTTON);
164 gtk_grid_attach (GTK_GRID (table), font_button, 2, 1, 1, 1);
165 g_signal_connect (G_OBJECT (font_button), "clicked", G_CALLBACK (ti_font_select_cb), appGUI);
166
167 label = utl_gui_create_label ("%s:", _("Task info font"));
168 gtk_grid_attach (GTK_GRID (table), label, 0, 1, 1, 1);
169
170 label = utl_gui_create_label ("%s:", _("Colors"));
171 gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
172
173 checkbutton = gtk_check_button_new_with_mnemonic (_("Show in bold tasks with high priority"));
174 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.tasks_high_in_bold);
175 gtk_grid_attach (GTK_GRID (table), checkbutton, 0, 3, 3, 1);
176 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (bold_items_cb), appGUI);
177 appGUI->opt->ct_bold_items_checkbutton = checkbutton;
178 }
179
180 /* ========================================================================== */
181
182 static void
visible_columns_changed_cb(GtkToggleButton * widget,GUI * appGUI)183 visible_columns_changed_cb (GtkToggleButton *widget, GUI *appGUI)
184 {
185 config.tsk_visible_due_date_column = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->vc_due_date_checkbutton));
186 gtk_tree_view_column_set_visible (appGUI->tsk->tasks_columns[TA_COLUMN_DUE_DATE], config.tsk_visible_due_date_column);
187 config.tsk_visible_type_column = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->vc_type_checkbutton));
188 gtk_tree_view_column_set_visible (appGUI->tsk->tasks_columns[TA_COLUMN_TYPE], config.tsk_visible_type_column);
189 config.tsk_visible_category_column = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->vc_category_checkbutton));
190 gtk_tree_view_column_set_visible (appGUI->tsk->tasks_columns[TA_COLUMN_CATEGORY], config.tsk_visible_category_column);
191 config.tsk_visible_priority_column = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->vc_priority_checkbutton));
192 gtk_tree_view_column_set_visible (appGUI->tsk->tasks_columns[TA_COLUMN_PRIORITY], config.tsk_visible_priority_column);
193
194 set_tasks_columns_width (appGUI);
195 }
196
197 /* ========================================================================== */
198
199 static void
create_visible_columns_section(GtkWidget * visible_columns_vbox,GUI * appGUI)200 create_visible_columns_section (GtkWidget *visible_columns_vbox, GUI *appGUI)
201 {
202 GtkWidget *table, *checkbutton;
203
204 table = gtk_grid_new ();
205 gtk_box_pack_start (GTK_BOX (visible_columns_vbox), table, FALSE, FALSE, 0);
206 gtk_grid_set_row_spacing (GTK_GRID (table), 4);
207 gtk_grid_set_column_spacing (GTK_GRID (table), 8);
208
209 checkbutton = gtk_check_button_new_with_mnemonic (_("Due date"));
210 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.tsk_visible_due_date_column);
211 gtk_widget_set_hexpand(checkbutton, TRUE);
212 gtk_grid_attach (GTK_GRID (table), checkbutton, 0, 0, 1, 1);
213 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (visible_columns_changed_cb), appGUI);
214 appGUI->opt->vc_due_date_checkbutton = checkbutton;
215
216 checkbutton = gtk_check_button_new_with_mnemonic (_("Type"));
217 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.tsk_visible_type_column);
218 gtk_widget_set_hexpand(checkbutton, TRUE);
219 gtk_grid_attach (GTK_GRID (table), checkbutton, 1, 0, 1, 1);
220 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (visible_columns_changed_cb), appGUI);
221 appGUI->opt->vc_type_checkbutton = checkbutton;
222
223 checkbutton = gtk_check_button_new_with_mnemonic (_("Priority"));
224 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.tsk_visible_priority_column);
225 gtk_widget_set_hexpand(checkbutton, TRUE);
226 gtk_grid_attach (GTK_GRID (table), checkbutton, 2, 0, 1, 1);
227 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (visible_columns_changed_cb), appGUI);
228 appGUI->opt->vc_priority_checkbutton = checkbutton;
229
230 checkbutton = gtk_check_button_new_with_mnemonic (_("Category"));
231 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.tsk_visible_category_column);
232 gtk_widget_set_hexpand(checkbutton, TRUE);
233 gtk_grid_attach (GTK_GRID (table), checkbutton, 3, 0, 1, 1);
234 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (visible_columns_changed_cb), appGUI);
235 appGUI->opt->vc_category_checkbutton = checkbutton;
236 }
237
238 /* ========================================================================== */
239
240 static void
tasks_category_remove_cb(GtkWidget * widget,GUI * appGUI)241 tasks_category_remove_cb (GtkWidget *widget, GUI *appGUI)
242 {
243 GtkTreePath *path;
244 GtkTreeIter iter;
245
246 gtk_tree_view_get_cursor (GTK_TREE_VIEW (appGUI->opt->tasks_category_treeview), &path, NULL);
247
248 if (path != NULL) {
249 gtk_tree_model_get_iter (GTK_TREE_MODEL (appGUI->opt->tasks_category_store), &iter, path);
250 gtk_list_store_remove (appGUI->opt->tasks_category_store, &iter);
251 gtk_tree_path_free (path);
252 refresh_tasks (appGUI);
253 set_categories (appGUI);
254 }
255 }
256
257 /* ========================================================================== */
258
259 static void
tasks_category_add_cb(GtkWidget * widget,GUI * appGUI)260 tasks_category_add_cb (GtkWidget *widget, GUI *appGUI)
261 {
262 GtkTreeIter iter;
263 const gchar *category_name;
264 gchar *item;
265 gboolean has_next;
266
267 category_name = gtk_entry_get_text (GTK_ENTRY (appGUI->opt->tasks_category_entry));
268 if (!strlen (category_name)) return;
269
270 has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (appGUI->opt->tasks_category_store), &iter);
271 while (has_next) {
272 gtk_tree_model_get (GTK_TREE_MODEL (appGUI->opt->tasks_category_store), &iter, TC_COLUMN_NAME, &item, -1);
273 if (!strcmp (category_name, item)) {
274 g_free (item);
275 return;
276 }
277 g_free (item);
278 has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (appGUI->opt->tasks_category_store), &iter);
279 }
280
281 gtk_list_store_append (appGUI->opt->tasks_category_store, &iter);
282 gtk_list_store_set (appGUI->opt->tasks_category_store, &iter,
283 TC_COLUMN_NAME, category_name,
284 TC_COLUMN_CALENDAR, TRUE,
285 TC_COLUMN_TASKS, TRUE, -1);
286
287 gtk_entry_set_text (GTK_ENTRY (appGUI->opt->tasks_category_entry), "");
288 gtk_widget_set_sensitive (appGUI->opt->tasks_category_add_button, FALSE);
289
290 utl_gui_create_category_combobox (GTK_COMBO_BOX (appGUI->tsk->cf_combobox), appGUI->opt->tasks_category_store, FALSE);
291 gtk_combo_box_set_active (GTK_COMBO_BOX (appGUI->tsk->cf_combobox), 0);
292
293 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (appGUI->tsk->tasks_filter));
294 set_categories (appGUI);
295 refresh_tasks (appGUI);
296 }
297
298 /* ========================================================================== */
299
300 static void
tsk_show_in_tasks_list_toggled(GtkCellRendererToggle * cell,gchar * path_str,GUI * appGUI)301 tsk_show_in_tasks_list_toggled (GtkCellRendererToggle *cell, gchar *path_str, GUI *appGUI)
302 {
303 GtkTreeModel *model;
304 GtkTreePath *path;
305 GtkTreeIter iter;
306 gboolean done_status;
307
308 model = GTK_TREE_MODEL (appGUI->opt->tasks_category_store);
309 path = gtk_tree_path_new_from_string (path_str);
310
311 if (path != NULL) {
312 gtk_tree_model_get_iter (model, &iter, path); /* get toggled iter */
313 gtk_tree_model_get (model, &iter, TC_COLUMN_TASKS, &done_status, -1);
314 gtk_list_store_set (GTK_LIST_STORE (model), &iter, TC_COLUMN_TASKS, !done_status, -1);
315 refresh_tasks (appGUI);
316 gtk_tree_path_free (path);
317 }
318 }
319
320 /* ========================================================================== */
321
322 static void
tsk_show_in_calendar_toggled(GtkCellRendererToggle * cell,gchar * path_str,GUI * appGUI)323 tsk_show_in_calendar_toggled (GtkCellRendererToggle *cell, gchar *path_str, GUI *appGUI)
324 {
325 GtkTreeModel *model;
326 GtkTreePath *path;
327 GtkTreeIter iter;
328 gboolean done_status;
329
330 model = GTK_TREE_MODEL (appGUI->opt->tasks_category_store);
331 path = gtk_tree_path_new_from_string (path_str);
332
333 if (path != NULL) {
334 gtk_tree_model_get_iter (model, &iter, path); /* get toggled iter */
335 gtk_tree_model_get (model, &iter, TC_COLUMN_CALENDAR, &done_status, -1);
336 gtk_list_store_set (GTK_LIST_STORE(model), &iter, TC_COLUMN_CALENDAR, !done_status, -1);
337 cal_set_day_info (appGUI);
338 cal_refresh_marks (appGUI);
339 gtk_tree_path_free (path);
340 }
341 }
342
343 /* ========================================================================== */
344
345 static void
tasks_category_cell_edited_cb(GtkCellRendererText * renderer,gchar * path,gchar * new_text,GUI * appGUI)346 tasks_category_cell_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, GUI *appGUI)
347 {
348 GtkTreeModel *model;
349 GtkTreeIter iter;
350
351 if (g_ascii_strcasecmp (new_text, "") != 0) {
352 model = gtk_tree_view_get_model (GTK_TREE_VIEW (appGUI->opt->tasks_category_treeview));
353 if (gtk_tree_model_get_iter_from_string (model, &iter, path)) {
354 gtk_list_store_set (appGUI->opt->tasks_category_store, &iter, TC_COLUMN_NAME, new_text, -1);
355 }
356 }
357 }
358
359 /* ========================================================================== */
360
361 static void
tasks_category_selected_cb(GtkTreeSelection * selection,GUI * appGUI)362 tasks_category_selected_cb (GtkTreeSelection *selection, GUI *appGUI)
363 {
364 GtkTreeModel *model;
365 GtkTreeIter iter;
366
367 if (gtk_tree_selection_get_selected (selection, &model, &iter))
368 gtk_widget_set_sensitive (appGUI->opt->tasks_category_remove_button, TRUE);
369 else
370 gtk_widget_set_sensitive (appGUI->opt->tasks_category_remove_button, FALSE);
371 }
372
373 /* ========================================================================== */
374
375 static gint
tasks_category_entry_key_release_cb(GtkEntry * widget,GdkEventKey * event,GUI * appGUI)376 tasks_category_entry_key_release_cb (GtkEntry *widget, GdkEventKey *event, GUI *appGUI)
377 {
378 gboolean state = FALSE;
379
380 if (strlen (gtk_entry_get_text (widget)))
381 state = TRUE;
382
383 gtk_widget_set_sensitive (appGUI->opt->tasks_category_add_button, state);
384
385 if (event->keyval == GDK_KEY_Return) {
386 if (state) tasks_category_add_cb (NULL, appGUI);
387 return TRUE;
388 }
389
390 return FALSE;
391 }
392
393 /* ========================================================================== */
394
395 static void
create_categories_section(GtkWidget * categories_vbox,GUI * appGUI)396 create_categories_section (GtkWidget *categories_vbox, GUI *appGUI)
397 {
398 GtkTreeViewColumn *column;
399 GtkCellRenderer *renderer;
400 GtkWidget *table, *scrolledwindow, *treeview;
401
402 table = gtk_grid_new ();
403 gtk_box_pack_start (GTK_BOX (categories_vbox), table, TRUE, TRUE, 0);
404 gtk_container_set_border_width (GTK_CONTAINER (table), 8);
405 gtk_grid_set_row_spacing (GTK_GRID (table), 8);
406 gtk_grid_set_column_spacing (GTK_GRID (table), 4);
407
408 appGUI->opt->tasks_category_entry = gtk_entry_new ();
409 gtk_widget_set_hexpand(appGUI->opt->tasks_category_entry, TRUE);
410 gtk_grid_attach (GTK_GRID (table), appGUI->opt->tasks_category_entry, 0, 3, 1, 1);
411 g_signal_connect (G_OBJECT (appGUI->opt->tasks_category_entry), "key_release_event",
412 G_CALLBACK (tasks_category_entry_key_release_cb), appGUI);
413
414 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
415 gtk_widget_set_hexpand(scrolledwindow, TRUE);
416 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW (scrolledwindow), 120);
417 gtk_grid_attach (GTK_GRID (table), scrolledwindow, 0, 0, 3, 3);
418 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
419 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN);
420
421 treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (appGUI->opt->tasks_category_store));
422 gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview);
423 gtk_container_set_border_width (GTK_CONTAINER (treeview), 4);
424 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), TRUE);
425 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
426 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
427 appGUI->opt->tasks_category_treeview = treeview;
428
429 appGUI->opt->tasks_category_select = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
430 g_signal_connect (G_OBJECT (appGUI->opt->tasks_category_select), "changed", G_CALLBACK (tasks_category_selected_cb), appGUI);
431
432 renderer = gtk_cell_renderer_text_new ();
433 g_object_set (renderer, "editable", TRUE, "editable-set", TRUE, NULL);
434 g_signal_connect (G_OBJECT (renderer), "edited", G_CALLBACK (tasks_category_cell_edited_cb), appGUI);
435
436 column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", TC_COLUMN_NAME, NULL);
437 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
438 gtk_tree_view_column_set_expand (column, TRUE);
439
440 renderer = gtk_cell_renderer_toggle_new (); /* Show in calendar */
441 column = gtk_tree_view_column_new_with_attributes(_("Calendar"), renderer, "active", TC_COLUMN_CALENDAR, NULL);
442 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
443 g_signal_connect (renderer, "toggled", G_CALLBACK (tsk_show_in_calendar_toggled), appGUI);
444
445 renderer = gtk_cell_renderer_toggle_new (); /* Show in tasks list */
446 column = gtk_tree_view_column_new_with_attributes (_("Tasks"), renderer, "active", TC_COLUMN_TASKS, NULL);
447 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
448 g_signal_connect (renderer, "toggled", G_CALLBACK (tsk_show_in_tasks_list_toggled), appGUI);
449
450 appGUI->opt->tasks_category_add_button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_BUTTON);
451 gtk_widget_set_sensitive (appGUI->opt->tasks_category_add_button, FALSE);
452 gtk_grid_attach (GTK_GRID (table), appGUI->opt->tasks_category_add_button, 1, 3, 1, 1);
453 g_signal_connect (appGUI->opt->tasks_category_add_button, "clicked", G_CALLBACK (tasks_category_add_cb), appGUI);
454
455 appGUI->opt->tasks_category_remove_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_BUTTON);
456 gtk_widget_set_sensitive (appGUI->opt->tasks_category_remove_button, FALSE);
457 gtk_grid_attach (GTK_GRID (table), appGUI->opt->tasks_category_remove_button, 2, 3, 1, 1);
458 g_signal_connect (appGUI->opt->tasks_category_remove_button, "clicked", G_CALLBACK (tasks_category_remove_cb), appGUI);
459 }
460
461 /* ========================================================================== */
462
463 static void
delete_items_cb(GtkToggleButton * togglebutton,GUI * appGUI)464 delete_items_cb (GtkToggleButton *togglebutton, GUI *appGUI)
465 {
466 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_delete_items_checkbutton)))
467 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_hide_items_checkbutton), FALSE);
468 }
469
470 /* ========================================================================== */
471
472 static void
hide_items_cb(GtkToggleButton * togglebutton,GUI * appGUI)473 hide_items_cb (GtkToggleButton *togglebutton, GUI *appGUI)
474 {
475 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_hide_items_checkbutton)))
476 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_delete_items_checkbutton), FALSE);
477 }
478
479 /* ========================================================================== */
480
481 static void
hide_delete_changed_cb(GtkToggleButton * widget,GUI * appGUI)482 hide_delete_changed_cb (GtkToggleButton *widget, GUI *appGUI)
483 {
484 config.hide_completed = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_hide_items_checkbutton));
485 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (appGUI->tsk->tasks_filter));
486 config.delete_completed = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->opt->ct_delete_items_checkbutton));
487 }
488
489 /* ========================================================================== */
490
491 static void
create_tasks_options_section(GtkWidget * tasks_opt_vbox,GUI * appGUI)492 create_tasks_options_section (GtkWidget *tasks_opt_vbox, GUI *appGUI)
493 {
494 GtkWidget *checkbutton;
495
496 checkbutton = gtk_check_button_new_with_mnemonic (_("Hide completed tasks"));
497 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.hide_completed);
498 gtk_box_pack_start (GTK_BOX (tasks_opt_vbox), checkbutton, FALSE, FALSE, 4);
499 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (hide_delete_changed_cb), appGUI);
500 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (hide_items_cb), appGUI);
501 appGUI->opt->ct_hide_items_checkbutton = checkbutton;
502
503 checkbutton = gtk_check_button_new_with_mnemonic (_("Delete completed tasks without confirmation"));
504 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.delete_completed);
505 gtk_box_pack_start (GTK_BOX (tasks_opt_vbox), checkbutton, FALSE, FALSE, 4);
506 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (hide_delete_changed_cb), appGUI);
507 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (delete_items_cb), appGUI);
508 appGUI->opt->ct_delete_items_checkbutton = checkbutton;
509
510 checkbutton = gtk_check_button_new_with_mnemonic (_("Add new task when double clicked on tasks list"));
511 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.add_edit);
512 gtk_box_pack_start (GTK_BOX (tasks_opt_vbox), checkbutton, FALSE, FALSE, 4);
513 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (checkbutton_clicked_cb), &(config.add_edit));
514 appGUI->opt->ct_add_item_checkbutton = checkbutton;
515
516 checkbutton = gtk_check_button_new_with_mnemonic (_("Remember the last selected category"));
517 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), config.remember_category_in_tasks);
518 gtk_box_pack_start (GTK_BOX (tasks_opt_vbox), checkbutton, FALSE, FALSE, 4);
519 g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (checkbutton_clicked_cb),
520 &(config.remember_category_in_tasks));
521 appGUI->opt->ct_remember_category_checkbutton = checkbutton;
522 }
523 /* ========================================================================== */
524
525 static gint
global_notification_entry_changed_cb(GtkEditable * editable,GUI * appGUI)526 global_notification_entry_changed_cb(GtkEditable *editable, GUI *appGUI) {
527 gchar *text = gtk_editable_get_chars(editable, 0, -1);
528 utl_gui_update_command_status(editable, appGUI->opt->global_notification_valid_image, appGUI);
529 g_strlcpy(config.global_notification_command, text, MAXHELPERCMD);
530 g_free(text);
531 return FALSE;
532 }
533
534 /* ========================================================================== */
535
536 static void
sound_alarm_repeat_changed_cb(GtkSpinButton * spinbutton,GUI * appGUI)537 sound_alarm_repeat_changed_cb (GtkSpinButton *spinbutton, GUI *appGUI)
538 {
539 config.sound_alarm_repeat = (gint) gtk_spin_button_get_value (spinbutton);
540 }
541
542 /* ========================================================================== */
543
544 static void
postpone_time_changed_cb(GtkSpinButton * spinbutton,GUI * appGUI)545 postpone_time_changed_cb (GtkSpinButton *spinbutton, GUI *appGUI)
546 {
547 config.postpone_time = (gint) gtk_spin_button_get_value (spinbutton);
548 }
549
550 /* ========================================================================== */
551
552 static void
create_reminder_options_section(GtkWidget * reminder_opt_vbox,GUI * appGUI)553 create_reminder_options_section (GtkWidget *reminder_opt_vbox, GUI *appGUI)
554 {
555 GtkWidget *table, *label, *spinbutton, *entry, *valid_hbox;
556 GtkAdjustment *adjustment;
557 gchar *str;
558 gint i = 0;
559
560 table = gtk_grid_new ();
561 gtk_box_pack_start (GTK_BOX (reminder_opt_vbox), table, FALSE, FALSE, 0);
562 gtk_grid_set_column_spacing (GTK_GRID (table), 4);
563 gtk_grid_set_row_spacing (GTK_GRID (table), 8);
564
565 label = utl_gui_create_label ("%s:", _("Postpone time"));
566 gtk_grid_attach (GTK_GRID (table), label, 0, i, 1, 1);
567
568 adjustment = gtk_adjustment_new (0, 0, 1440, 1, 10, 0);
569 spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
570 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
571 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), config.postpone_time);
572 gtk_grid_attach (GTK_GRID (table), spinbutton, 1, i, 1, 1);
573 g_signal_connect (G_OBJECT (spinbutton), "value-changed", G_CALLBACK (postpone_time_changed_cb), appGUI);
574 appGUI->opt->postpone_time_spinbutton = spinbutton;
575
576 str = g_strdup_printf ("%s (%s)", _("minutes"), _("0 for disable"));
577 label = gtk_label_new (str);
578 g_free (str);
579 gtk_widget_set_valign(label, GTK_ALIGN_START);
580 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
581 gtk_grid_attach (GTK_GRID (table), label, 2, i, 1, 1);
582
583 i++;
584 label = utl_gui_create_label ("%s:", _("Repeat sound alarm"));
585 gtk_grid_attach (GTK_GRID (table), label, 0, i, 1, 1);
586
587 adjustment = gtk_adjustment_new (0, 0, 100, 1, 10, 0);
588 spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
589 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
590 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), config.sound_alarm_repeat);
591 gtk_grid_attach (GTK_GRID (table), spinbutton, 1, i, 1, 1);
592 g_signal_connect (G_OBJECT (spinbutton), "value-changed", G_CALLBACK (sound_alarm_repeat_changed_cb), appGUI);
593 appGUI->opt->sound_alarm_repeat_spinbutton = spinbutton;
594
595 str = g_strdup_printf ("%s (%s)", _("times"), _("0 for disable"));
596 label = gtk_label_new (str);
597 g_free (str);
598 gtk_widget_set_valign(label, GTK_ALIGN_START);
599 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
600 gtk_grid_attach (GTK_GRID (table), label, 2, i, 1, 1);
601
602 i++;
603 label = utl_gui_create_label ("%s:", _("Global notification command"));
604 gtk_grid_attach (GTK_GRID (table), label, 0, i, 1, 1);
605
606 valid_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
607 gtk_grid_attach (GTK_GRID (table), valid_hbox, 1, i, 2, 1);
608
609 entry = gtk_entry_new ();
610 gtk_entry_set_text (GTK_ENTRY (entry), config.global_notification_command);
611 gtk_box_pack_start (GTK_BOX (valid_hbox), entry, TRUE, TRUE, 0);
612 g_signal_connect (G_OBJECT (entry), "changed",
613 G_CALLBACK (global_notification_entry_changed_cb), appGUI);
614 appGUI->opt->global_notification_cmd_entry = entry;
615
616 appGUI->opt->global_notification_valid_image = gtk_image_new ();
617 gtk_box_pack_start (GTK_BOX (valid_hbox), appGUI->opt->global_notification_valid_image, FALSE, FALSE, 0);
618
619 utl_gui_update_command_status (GTK_EDITABLE(entry), appGUI->opt->global_notification_valid_image, appGUI);
620 }
621
622 /* ========================================================================== */
623
624 GtkWidget *
tsk_create_preferences_page(GtkWidget * notebook,GUI * appGUI)625 tsk_create_preferences_page (GtkWidget *notebook, GUI *appGUI)
626 {
627 GtkWidget *vbox_top, *vbox_icon, *vbox, *scrolledwindow;
628
629 vbox_top = gtk_box_new (GTK_ORIENTATION_VERTICAL, VBOX_SPACING);
630 gtk_container_set_border_width (GTK_CONTAINER (vbox_top), BORDER_WIDTH);
631 scrolledwindow = utl_gui_insert_in_scrolled_window (vbox_top, GTK_SHADOW_ETCHED_IN);
632 gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow), 2);
633 vbox_icon = utl_gui_create_icon_with_label (OSMO_STOCK_TASKS, _("Tasks"));
634
635 vbox = utl_gui_create_vbox_in_frame (vbox_top, _("Appearance"));
636 create_appearance_section (vbox, appGUI);
637
638 vbox = utl_gui_create_vbox_in_frame (vbox_top, _("Visible columns"));
639 create_visible_columns_section (vbox, appGUI);
640
641 vbox = utl_gui_create_vbox_in_frame (vbox_top, _("Categories"));
642 create_categories_section (vbox, appGUI);
643
644 vbox = utl_gui_create_vbox_in_frame (vbox_top, _("Tasks options"));
645 create_tasks_options_section (vbox, appGUI);
646
647 vbox = utl_gui_create_vbox_in_frame (vbox_top, _("Reminder options"));
648 create_reminder_options_section (vbox, appGUI);
649
650 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolledwindow, vbox_icon);
651 gtk_widget_show_all (scrolledwindow);
652
653 return scrolledwindow;
654 }
655
656 /* ========================================================================== */
657
658 #endif /* TASKS_ENABLED */
659
660