code style
[ptask.git] / src / main.c
1 /*
2  * Copyright (C) 2010-2012 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <json/json.h>
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include "note.h"
29 #include "tw.h"
30
31 static struct task **tasks;
32 static GtkTextView *w_note;
33 static GtkEntry *w_description;
34 static GtkEntry *w_project;
35 static GtkTreeView *w_treeview;
36 static GtkWidget *w_tasksave_btn;
37 static GtkWidget *w_taskdone_btn;
38 static GtkComboBox *w_status;
39 static GtkComboBox *w_priority;
40
41 enum {
42         COL_ID,
43         COL_DESCRIPTION,
44         COL_PROJECT,
45         COL_UUID,
46         COL_PRIORITY
47 };
48
49 static struct task *get_selected_task(GtkTreeView *treeview)
50 {
51         GtkTreePath *path;
52         GtkTreeViewColumn *cols;
53         struct task **tasks_cur;
54         GtkTreeIter iter;
55         GtkTreeModel *model;
56         GValue value = {0,};
57         const char *uuid;
58
59         printf("get_selected_task\n");
60
61         gtk_tree_view_get_cursor(treeview, &path, &cols);
62
63         if (path) {
64                 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
65                 gtk_tree_model_get_iter(model, &iter, path);
66                 gtk_tree_model_get_value(model, &iter, COL_UUID, &value);
67
68                 uuid = g_value_get_string(&value);
69
70                 for (tasks_cur = tasks; *tasks_cur; tasks_cur++)
71                         if (!strcmp((*tasks_cur)->uuid, uuid))
72                                 return *tasks_cur;
73
74                 gtk_tree_path_free(path);
75         }
76
77         return NULL;
78 }
79
80 static void clear_task_panel()
81 {
82         GtkTextBuffer *buf;
83
84         gtk_widget_set_sensitive(w_tasksave_btn, 0);
85         gtk_widget_set_sensitive(w_taskdone_btn, 0);
86
87         buf = gtk_text_view_get_buffer(w_note);
88         gtk_text_buffer_set_text(buf, "", 0);
89         gtk_widget_set_sensitive(GTK_WIDGET(w_note), 0);
90
91         gtk_entry_set_text(w_description, "");
92         gtk_widget_set_sensitive(GTK_WIDGET(w_description), 0);
93
94         gtk_entry_set_text(w_project, "");
95         gtk_widget_set_sensitive(GTK_WIDGET(w_project), 0);
96
97         gtk_combo_box_set_active(w_priority, 0);
98         gtk_widget_set_sensitive(GTK_WIDGET(w_priority), 0);
99 }
100
101 static void refresh()
102 {
103         GtkTreeModel *model;
104         struct task **tasks_cur;
105         struct task *task;
106         int i;
107         GtkTreeIter iter;
108         int status;
109         const char *project;
110
111         printf("refresh\n");
112         clear_task_panel();
113
114         status = gtk_combo_box_get_active(w_status);
115         printf("status: %d\n", status);
116
117         if (tasks)
118                 tw_task_list_free(tasks);
119
120         switch (status) {
121         case 0:
122                 tasks = tw_get_all_tasks("pending");
123                 break;
124         case 1:
125                 tasks = tw_get_all_tasks("completed");
126                 break;
127         default:
128                 tasks = tw_get_all_tasks("pending");
129         }
130
131         model = gtk_tree_view_get_model(GTK_TREE_VIEW(w_treeview));
132         gtk_list_store_clear(GTK_LIST_STORE(model));
133         for (tasks_cur = tasks, i = 0; *tasks_cur; tasks_cur++, i++) {
134                 task = (*tasks_cur);
135
136                 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
137
138                 if (task->project)
139                         project = task->project;
140                 else
141                         project = "";
142
143                 gtk_list_store_set(GTK_LIST_STORE(model),
144                                    &iter,
145                                    COL_ID, (*tasks_cur)->id,
146                                    COL_DESCRIPTION, (*tasks_cur)->description,
147                                    COL_PROJECT, project,
148                                    COL_UUID, (*tasks_cur)->uuid,
149                                    COL_PRIORITY, (*tasks_cur)->priority,
150                                    -1);
151         }
152         printf("refresh done\n");
153 }
154
155 int taskdone_clicked_cbk(GtkButton *btn, gpointer data)
156 {
157         struct task *task;
158
159         task = get_selected_task(GTK_TREE_VIEW(w_treeview));
160         tw_done(task->uuid);
161         refresh();
162
163         return FALSE;
164 }
165
166 static int tasksave_clicked_cbk(GtkButton *btn, gpointer data)
167 {
168         struct task *task;
169         GtkTextBuffer *buf;
170         char *txt, *pri;
171         GtkTextIter sIter, eIter;
172         const char *ctxt;
173         int priority;
174
175         task = get_selected_task(GTK_TREE_VIEW(w_treeview));
176
177         printf("tasksave_clicked_cbk %d\n", task->id);
178
179         buf = gtk_text_view_get_buffer(w_note);
180
181         gtk_text_buffer_get_iter_at_offset(buf, &sIter, 0);
182         gtk_text_buffer_get_iter_at_offset(buf, &eIter, -1);
183         txt = gtk_text_buffer_get_text(buf, &sIter, &eIter, TRUE);
184
185         printf("note=%s\n", txt);
186
187         if (!task->note || strcmp(txt, task->note))
188                 note_put(task->uuid, txt);
189
190         ctxt = gtk_entry_get_text(w_description);
191         if (!task->description || strcmp(ctxt, task->description))
192                 tw_modify_description(task->uuid, ctxt);
193
194         ctxt = gtk_entry_get_text(w_project);
195         if (!task->project || strcmp(ctxt, task->project))
196                 tw_modify_project(task->uuid, ctxt);
197
198         priority = gtk_combo_box_get_active(w_priority);
199         printf("priority: %d\n", priority);
200
201         switch (priority) {
202         case 3:
203                 pri = "H";
204                 break;
205         case 2:
206                 pri = "M";
207                 break;
208         case 1:
209                 pri = "L";
210                 break;
211         default:
212                 pri = "";
213         }
214
215         if (strcmp(task->priority, pri))
216                 tw_modify_priority(task->uuid, pri);
217
218         refresh();
219
220         return FALSE;
221 }
222
223 int refresh_clicked_cbk(GtkButton *btn, gpointer data)
224 {
225         printf("refresh_clicked_cbk\n");
226         refresh();
227
228         return FALSE;
229 }
230
231 static gboolean delete_event_cbk(GtkWidget *w, GdkEvent *evt, gpointer data)
232 {
233         gtk_widget_destroy(w);
234         gtk_main_quit();
235
236         return FALSE;
237 }
238
239
240 int newtask_clicked_cbk(GtkButton *btn, gpointer data)
241 {
242         gint result;
243         static GtkDialog *diag;
244         GtkBuilder *builder;
245         GtkEntry *entry;
246         const char *ctxt;
247
248         printf("newtask_clicked_cbk\n");
249
250         builder = gtk_builder_new();
251         gtk_builder_add_from_file
252                 (builder,
253                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "ptask.glade",
254                  NULL);
255         diag = GTK_DIALOG(gtk_builder_get_object(builder, "diag_tasknew"));
256         gtk_builder_connect_signals(builder, NULL);
257
258         result = gtk_dialog_run(diag);
259
260         if (result == GTK_RESPONSE_ACCEPT) {
261                 printf("ok\n");
262                 entry = GTK_ENTRY(gtk_builder_get_object
263                                   (builder, "diag_tasknew_description"));
264                 ctxt = gtk_entry_get_text(entry);
265
266                 printf("%s\n", ctxt);
267
268                 tw_add(ctxt);
269                 refresh();
270         } else {
271                 printf("cancel\n");
272         }
273
274         g_object_unref(G_OBJECT(builder));
275
276         gtk_widget_destroy(GTK_WIDGET(diag));
277
278         return FALSE;
279 }
280
281 static int status_changed_cbk(GtkComboBox *w, gpointer data)
282 {
283         printf("status_changed_cbk\n");
284         refresh();
285
286         return FALSE;
287 }
288
289 static int priority_to_int(const char *str)
290 {
291         switch (*str) {
292         case 'H':
293                 return 3;
294         case 'M':
295                 return 2;
296         case 'L':
297                 return 1;
298         default:
299                 return 0;
300         }
301 }
302
303 static int cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
304 {
305         struct task *task;
306         GtkTextBuffer *buf;
307         int priority;
308
309         printf("cursor_changed_cbk\n");
310
311         task = get_selected_task(treeview);
312
313         if (task) {
314
315                 buf = gtk_text_view_get_buffer(w_note);
316                 if (task->note)
317                         gtk_text_buffer_set_text(buf,
318                                                  task->note,
319                                                  strlen(task->note));
320                 else
321                         gtk_text_buffer_set_text(buf, "", 0);
322                 gtk_widget_set_sensitive(GTK_WIDGET(w_note), 1);
323
324                 gtk_entry_set_text(w_description, task->description);
325                 gtk_widget_set_sensitive(GTK_WIDGET(w_description), 1);
326
327                 if (task->project)
328                         gtk_entry_set_text(w_project, task->project);
329                 else
330                         gtk_entry_set_text(w_project, "");
331                 gtk_widget_set_sensitive(GTK_WIDGET(w_project), 1);
332
333                 gtk_widget_set_sensitive(w_tasksave_btn, 1);
334                 gtk_widget_set_sensitive(w_taskdone_btn, 1);
335
336                 gtk_widget_set_sensitive(GTK_WIDGET(w_priority), 1);
337                 priority = priority_to_int(task->priority);
338                 gtk_combo_box_set_active(w_priority, priority);
339         } else {
340                 printf("clear task widgets\n");
341                 clear_task_panel();
342                 printf("clear task widgets done\n");
343         }
344
345         return FALSE;
346 }
347
348 static gint priority_cmp(GtkTreeModel *model,
349                          GtkTreeIter *a,
350                          GtkTreeIter *b,
351                          gpointer user_data)
352 {
353         GValue v1 = {0,}, v2 = {0,};
354         const char *str1, *str2;
355         int i1, i2;
356
357         gtk_tree_model_get_value(model, a, COL_PRIORITY, &v1);
358         str1 = g_value_get_string(&v1);
359         i1 = priority_to_int(str1);
360
361         gtk_tree_model_get_value(model, b, COL_PRIORITY, &v2);
362         str2 = g_value_get_string(&v2);
363         i2 = priority_to_int(str2);
364
365         if (i1 < i2)
366                 return -1;
367         else if (i1 > i2)
368                 return 1;
369         else
370                 return 0;
371 }
372
373 int main(int argc, char **argv)
374 {
375         GtkWidget *window, *btn;
376         GtkBuilder *builder;
377         GtkTreeModel *model;
378
379         setlocale(LC_ALL, "");
380
381 #if ENABLE_NLS
382         bindtextdomain(PACKAGE, LOCALEDIR);
383         textdomain(PACKAGE);
384 #endif
385
386         gtk_init(NULL, NULL);
387         builder = gtk_builder_new();
388         gtk_builder_add_from_file
389                 (builder,
390                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "ptask.glade",
391                  NULL);
392         window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
393
394         g_signal_connect(window, "delete_event",
395                          G_CALLBACK(delete_event_cbk), NULL);
396
397         w_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
398         model = gtk_tree_view_get_model(GTK_TREE_VIEW(w_treeview));
399         gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model),
400                                         COL_PRIORITY,
401                                         priority_cmp,
402                                         NULL,
403                                         NULL);
404
405         w_note = GTK_TEXT_VIEW(gtk_builder_get_object(builder, "tasknote"));
406
407         w_description = GTK_ENTRY(gtk_builder_get_object(builder,
408                                                          "taskdescription"));
409         w_project = GTK_ENTRY(gtk_builder_get_object(builder, "taskproject"));
410         w_status = GTK_COMBO_BOX(gtk_builder_get_object(builder, "status"));
411         w_priority = GTK_COMBO_BOX(gtk_builder_get_object(builder,
412                                                           "taskpriority"));
413
414         refresh();
415
416         gtk_builder_connect_signals(builder, NULL);
417
418         g_signal_connect(w_treeview,
419                          "cursor-changed", (GCallback)cursor_changed_cbk,
420                          tasks);
421         g_signal_connect(w_status,
422                          "changed", (GCallback)status_changed_cbk,
423                          tasks);
424
425         btn = GTK_WIDGET(gtk_builder_get_object(builder, "tasksave"));
426         g_signal_connect(btn,
427                          "clicked", (GCallback)tasksave_clicked_cbk, tasks);
428         gtk_widget_set_sensitive(btn, 0);
429         w_tasksave_btn = btn;
430
431         w_taskdone_btn = GTK_WIDGET(gtk_builder_get_object(builder,
432                                                            "taskdone"));
433         gtk_widget_set_sensitive(w_taskdone_btn, 0);
434
435         g_object_unref(G_OBJECT(builder));
436
437         gtk_widget_show_all(window);
438
439         gtk_main();
440
441         exit(EXIT_SUCCESS);
442 }