refactoring
[ptask.git] / src / main.c
1 /*
2  * Copyright (C) 2012-2013 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 #include <getopt.h>
23 #include <sys/stat.h>
24
25 #include <json/json.h>
26
27 #include <glib/gi18n.h>
28
29 #include <config.h>
30
31 #include <log.h>
32 #include <note.h>
33 #include <tw.h>
34 #include <ui.h>
35 #include <ui_projecttree.h>
36 #include <ui_taskpanel.h>
37 #include <ui_tasktree.h>
38
39 static const char *program_name;
40 static struct task **tasks;
41 static GtkTextView *w_note;
42 static GtkEntry *w_description;
43 static GtkEntry *w_project;
44 static GtkTreeView *w_treeview;
45 static GtkWidget *w_taskdone_btn;
46 static GtkComboBox *w_status;
47 static GtkComboBox *w_priority;
48 static GSettings *settings;
49
50 enum {
51         COL_ID,
52         COL_DESCRIPTION,
53         COL_PROJECT,
54         COL_UUID,
55         COL_PRIORITY
56 };
57
58 static struct option long_options[] = {
59         {"version", no_argument, 0, 'v'},
60         {"help", no_argument, 0, 'h'},
61         {"debug", required_argument, 0, 'd'},
62         {0, 0, 0, 0}
63 };
64
65 static void print_version()
66 {
67         printf("ptask %s\n", VERSION);
68         printf(_("Copyright (C) %s jeanfi@gmail.com\n"
69                  "License GPLv2: GNU GPL version 2 or later "
70                  "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
71                  "This is free software: you are free to change and "
72                  " redistribute it.\n"
73                  "There is NO WARRANTY, to the extent permitted by law.\n"),
74                "2012-2013");
75 }
76
77 static void print_help()
78 {
79         printf(_("Usage: %s [OPTION]...\n"), program_name);
80
81         puts(_("ptask is a task management user interface based"
82                " on taskwarrior."));
83
84         puts("");
85         puts(_("Options:"));
86         puts(_("  -h, --help          display this help and exit\n"
87                "  -v, --version       display version information and exit"));
88
89         puts("");
90
91         puts(_("  -d, --debug=LEVEL   "
92                "set the debug level, integer between 0 and 3"));
93
94         puts("");
95
96         printf(_("Report bugs to: %s\n"), PACKAGE_BUGREPORT);
97         puts("");
98         printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
99 }
100
101 static struct task *get_selected_task(GtkTreeView *treeview)
102 {
103         GtkTreePath *path;
104         GtkTreeViewColumn *cols;
105         struct task **tasks_cur;
106         GtkTreeIter iter;
107         GtkTreeModel *model;
108         GValue value = {0,};
109         const char *uuid;
110
111         log_debug("get_selected_task");
112
113         gtk_tree_view_get_cursor(treeview, &path, &cols);
114
115         if (path) {
116                 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
117                 gtk_tree_model_get_iter(model, &iter, path);
118                 gtk_tree_model_get_value(model, &iter, COL_UUID, &value);
119
120                 uuid = g_value_get_string(&value);
121
122                 for (tasks_cur = tasks; *tasks_cur; tasks_cur++)
123                         if (!strcmp((*tasks_cur)->uuid, uuid))
124                                 return *tasks_cur;
125
126                 gtk_tree_path_free(path);
127         }
128
129         return NULL;
130 }
131
132 void refresh()
133 {
134         GtkWidget *dialog;
135         GtkTreeModel *model;
136         struct task **tasks_cur;
137         struct task *task;
138         int i;
139         GtkTreeIter iter;
140         int status;
141         const char *project;
142
143         log_fct_enter();
144         ui_taskpanel_update(NULL);
145
146         status = gtk_combo_box_get_active(w_status);
147         log_debug("status: %d", status);
148
149         if (tasks)
150                 tw_task_list_free(tasks);
151
152         switch (status) {
153         case 0:
154                 tasks = tw_get_all_tasks("pending");
155                 break;
156         case 1:
157                 tasks = tw_get_all_tasks("completed");
158                 break;
159         default:
160                 tasks = tw_get_all_tasks("pending");
161         }
162
163         model = gtk_tree_view_get_model(GTK_TREE_VIEW(w_treeview));
164         gtk_list_store_clear(GTK_LIST_STORE(model));
165
166         if (tasks) {
167                 for (tasks_cur = tasks, i = 0; *tasks_cur; tasks_cur++, i++) {
168                         task = (*tasks_cur);
169
170                         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
171
172                         if (task->project)
173                                 project = task->project;
174                         else
175                                 project = "";
176
177                         gtk_list_store_set(GTK_LIST_STORE(model),
178                                            &iter,
179                                            COL_ID, (*tasks_cur)->id,
180                                            COL_DESCRIPTION,
181                                            (*tasks_cur)->description,
182                                            COL_PROJECT, project,
183                                            COL_UUID, (*tasks_cur)->uuid,
184                                            COL_PRIORITY, (*tasks_cur)->priority,
185                                            -1);
186                 }
187                 ui_projecttree_update(tasks);
188         } else {
189                 dialog = gtk_message_dialog_new(NULL,
190                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
191                                                 GTK_MESSAGE_ERROR,
192                                                 GTK_BUTTONS_CLOSE,
193                                                 _("Error loading tasks, verify "
194                                                   "that a supported version of "
195                                                   "taskwarrior is installed "));
196                 gtk_dialog_run(GTK_DIALOG(dialog));
197                 gtk_widget_destroy(dialog);
198         }
199         log_fct(__func__, "EXIT");
200 }
201
202 int taskdone_clicked_cbk(GtkButton *btn, gpointer data)
203 {
204         struct task *task;
205
206         task = get_selected_task(GTK_TREE_VIEW(w_treeview));
207         tw_done(task->uuid);
208         refresh();
209
210         return FALSE;
211 }
212
213 int refresh_clicked_cbk(GtkButton *btn, gpointer data)
214 {
215         log_debug("refresh_clicked_cbk");
216         refresh();
217
218         return FALSE;
219 }
220
221 static int status_changed_cbk(GtkComboBox *w, gpointer data)
222 {
223         log_debug("status_changed_cbk");
224         refresh();
225
226         return FALSE;
227 }
228
229 static int cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
230 {
231         log_fct_enter();
232
233         ui_taskpanel_update(get_selected_task(treeview));
234
235         log_fct_exit();
236
237         return FALSE;
238 }
239
240 static void log_init()
241 {
242         char *home, *path, *dir;
243
244         home = getenv("HOME");
245
246         if (!home)
247                 return ;
248
249         dir = malloc(strlen(home)+1+strlen(".ptask")+1);
250         sprintf(dir, "%s/%s", home, ".ptask");
251         mkdir(dir, 0777);
252
253         path = malloc(strlen(dir)+1+strlen("log")+1);
254         sprintf(path, "%s/%s", dir, "log");
255
256         log_open(path);
257
258         free(dir);
259         free(path);
260 }
261
262 int main(int argc, char **argv)
263 {
264         GtkWindow *window;
265         GtkBuilder *builder;
266         int optc, cmdok, opti;
267
268         program_name = argv[0];
269
270         setlocale(LC_ALL, "");
271
272 #if ENABLE_NLS
273         bindtextdomain(PACKAGE, LOCALEDIR);
274         textdomain(PACKAGE);
275 #endif
276
277         cmdok = 1;
278         while ((optc = getopt_long(argc, argv, "vhd:", long_options,
279                                    &opti)) != -1) {
280                 switch (optc) {
281                 case 'h':
282                         print_help();
283                         exit(EXIT_SUCCESS);
284                 case 'v':
285                         print_version();
286                         exit(EXIT_SUCCESS);
287                 case 'd':
288                         log_level = atoi(optarg);
289                         log_info(_("Enables debug mode."));
290                         break;
291                 default:
292                         cmdok = 0;
293                         break;
294                 }
295         }
296
297         if (!cmdok || optind != argc) {
298                 fprintf(stderr, _("Try `%s --help' for more information.\n"),
299                         program_name);
300                 exit(EXIT_FAILURE);
301         }
302
303         log_init();
304
305         gtk_init(NULL, NULL);
306
307         settings = g_settings_new("ptask");
308
309         builder = gtk_builder_new();
310         gtk_builder_add_from_file
311                 (builder,
312                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "ptask.glade",
313                  NULL);
314         window = create_window(builder, settings);
315
316         ui_taskpanel_init(builder);
317         ui_tasktree_init(builder);
318         ui_projecttree_init(builder);
319
320         w_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "tasktree"));
321
322         w_note = GTK_TEXT_VIEW(gtk_builder_get_object(builder, "tasknote"));
323
324         w_description = GTK_ENTRY(gtk_builder_get_object(builder,
325                                                          "taskdescription"));
326         w_project = GTK_ENTRY(gtk_builder_get_object(builder, "taskproject"));
327         w_status = GTK_COMBO_BOX(gtk_builder_get_object(builder, "status"));
328         w_priority = GTK_COMBO_BOX(gtk_builder_get_object(builder,
329                                                           "taskpriority"));
330
331         gtk_builder_connect_signals(builder, NULL);
332
333         g_signal_connect(w_treeview,
334                          "cursor-changed", (GCallback)cursor_changed_cbk,
335                          tasks);
336         g_signal_connect(w_status,
337                          "changed", (GCallback)status_changed_cbk,
338                          tasks);
339
340         w_taskdone_btn = GTK_WIDGET(gtk_builder_get_object(builder,
341                                                            "taskdone"));
342         gtk_widget_set_sensitive(w_taskdone_btn, 0);
343
344         g_object_unref(G_OBJECT(builder));
345
346         refresh();
347
348         gtk_widget_show_all(GTK_WIDGET(window));
349
350         gtk_main();
351
352         exit(EXIT_SUCCESS);
353 }