(no commit message)
[prss.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
24 #include <json/json.h>
25 #include <webkit/webkit.h>
26 #include <glib/gi18n.h>
27 #include <gtk/gtk.h>
28
29 #include "http.h"
30 #include "ttrss.h"
31 #include "webbrowser.h"
32
33 static const char *program_name;
34 static GSettings *settings;
35
36 static int model_state;
37
38 enum {
39         COL_FEED_TITLE,
40         COL_FEED_ID
41 };
42
43 static struct option long_options[] = {
44         {"version", no_argument, 0, 'v'},
45         {"help", no_argument, 0, 'h'},
46         {0, 0, 0, 0}
47 };
48
49 static void print_version()
50 {
51         printf("prss %s\n", VERSION);
52         printf(_("Copyright (C) %s jeanfi@gmail.com\n"
53                  "License GPLv2: GNU GPL version 2 or later "
54                  "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
55                  "This is free software: you are free to change and "
56                  " redistribute it.\n"
57                  "There is NO WARRANTY, to the extent permitted by law.\n"),
58                "2012-2013");
59 }
60
61 static void print_help()
62 {
63         printf(_("Usage: %s [OPTION]...\n"), program_name);
64
65         puts(_("Prss is a GTK+ news reader for tt-rss."));
66
67         puts("");
68         puts(_("Options:"));
69         puts(_("  -h, --help          display this help and exit\n"
70                "  -v, --version       display version information and exit"));
71
72         puts("");
73
74         printf(_("Report bugs to: %s\n"), PACKAGE_BUGREPORT);
75         puts("");
76         printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
77 }
78
79 GtkTreeView *w_treeview;
80 GtkTreeView *w_headlineview;
81
82 void update()
83 {
84         struct feed **feeds;
85         GtkTreeModel *model;
86         GtkTreeIter iter;
87         char *title;
88
89         model = gtk_tree_view_get_model(GTK_TREE_VIEW(w_treeview));
90
91         printf("update(): clear feed tree\n");
92         model_state = 1;
93         gtk_list_store_clear(GTK_LIST_STORE(model));
94         gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(w_headlineview)));
95         printf("update(): clear feed tree done\n");
96         feeds = ttrss_get_feeds();
97         while (feeds && *feeds) {
98                 if ((*feeds)->unread)
99                         title = g_strdup_printf("<b>%s (%d)</b>",
100                                                 (*feeds)->title,
101                                                 (*feeds)->unread);
102                 else
103                         title = strdup((*feeds)->title);
104
105
106                 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
107
108                 gtk_list_store_set(GTK_LIST_STORE(model),
109                                    &iter,
110                                    0, title,
111                                    1, (*feeds)->id,
112                                    -1);
113                 free(title);
114                 feeds++;
115         }
116         model_state = 0;
117
118         printf("refresh done\n");
119 }
120
121 void refresh_clicked_cbk(GtkWidget *btn, gpointer data)
122 {
123         printf("refresh_clicked_cbk\n");
124         update();
125 }
126
127 void settings_activate_cbk(GtkWidget *menu_item, gpointer data)
128 {
129         GtkDialog *diag;
130         GtkBuilder *builder;
131         GtkEntry *login, *url, *pwd;
132
133         printf("settings_activate_cbk\n");
134
135         builder = gtk_builder_new();
136
137         gtk_builder_add_from_file
138                 (builder,
139                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "prss.glade",
140                  NULL);
141
142         diag = GTK_DIALOG(gtk_builder_get_object(builder, "settings_dialog"));
143
144         url = GTK_ENTRY(gtk_builder_get_object(builder, "url_entry"));
145         gtk_entry_set_text(url, g_settings_get_string(settings, "url"));
146
147         login = GTK_ENTRY(gtk_builder_get_object(builder, "login_entry"));
148         gtk_entry_set_text(login, g_settings_get_string(settings, "user"));
149
150         pwd = GTK_ENTRY(gtk_builder_get_object(builder, "password_entry"));
151         gtk_entry_set_text(pwd, g_settings_get_string(settings, "password"));
152
153         if (gtk_dialog_run(diag)) {
154                 g_settings_set_string(settings,
155                                       "password",
156                                       gtk_entry_get_text(pwd));
157                 g_settings_set_string(settings,
158                                       "url",
159                                       gtk_entry_get_text(url));
160                 g_settings_set_string(settings,
161                                       "user",
162                                       gtk_entry_get_text(login));
163
164                 update();
165         }
166
167         gtk_widget_destroy(GTK_WIDGET(diag));
168
169         g_object_unref(G_OBJECT(builder));
170 }
171
172 static struct feed *get_selected_feed()
173 {
174         GtkTreePath *path;
175         GtkTreeViewColumn *cols;
176         GtkTreeIter iter;
177         GtkTreeModel *model;
178         int id;
179
180         gtk_tree_view_get_cursor(w_treeview, &path, &cols);
181
182         if (path) {
183                 model = gtk_tree_view_get_model(w_treeview);
184                 gtk_tree_model_get_iter(model, &iter, path);
185                 gtk_tree_model_get(model, &iter, 1, &id, -1);
186
187                 gtk_tree_path_free(path);
188
189                 return ttrss_get_feed(id);
190         }
191
192         return NULL;
193 }
194
195 static struct headline *get_selected_headline(GtkTreeIter *iter)
196 {
197         GtkTreePath *path;
198         GtkTreeViewColumn *cols;
199         GtkTreeModel *model;
200         int id;
201
202         gtk_tree_view_get_cursor(w_headlineview, &path, &cols);
203
204         if (path) {
205                 model = gtk_tree_view_get_model(w_headlineview);
206                 gtk_tree_model_get_iter(model, iter, path);
207                 gtk_tree_model_get(model, iter, 1, &id, -1);
208
209                 gtk_tree_path_free(path);
210
211                 return ttrss_get_headline(id);
212         }
213
214         return NULL;
215 }
216
217 int feed_cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
218 {
219         GtkTreeIter iter;
220         GtkTreeModel *headline_model;
221         GtkListStore *headline_store;
222         struct feed *feed;
223         struct headline **headlines;
224         char *title;
225
226         if (model_state)
227                 return TRUE;
228
229         printf("feed_cursor_changed_cbk\n");
230
231         feed = get_selected_feed();
232
233         if (feed) {
234                 headline_model = gtk_tree_view_get_model(w_headlineview);
235                 headline_store = GTK_LIST_STORE(headline_model);
236                 model_state = 1;
237                 gtk_list_store_clear(headline_store);
238
239                 if (feed) {
240                         headlines = ttrss_feed_get_headlines(feed);
241                         while (headlines && *headlines) {
242                                 gtk_list_store_append(headline_store, &iter);
243                                 
244                                 if ((*headlines)->unread)
245                                         title = g_strdup_printf
246                                                 ("<b>%s</b>",
247                                                  (*headlines)->title);
248                                 else
249                                         title = strdup((*headlines)->title);
250                                 
251                                 gtk_list_store_set(headline_store,
252                                                    &iter,
253                                                    0, title,
254                                                    1, (*headlines)->id,
255                                                    -1);
256                                 
257                                 free(title);
258                                 
259                                 headlines++;
260                         }
261                 }
262
263                 model_state = 0;
264         }
265
266         return 1;
267 }
268
269 int headline_cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
270 {
271         GtkTreeIter iter;
272         GtkTreeModel *model;
273         struct headline *headline;
274         const char *str;
275
276         printf("headline_cursor_changed_cbk\n");
277
278         if (model_state)
279                 return TRUE;
280
281         headline = get_selected_headline(&iter);
282
283         if (headline) {
284                 str = ttrss_get_headline_content(headline);
285
286                 if (str)
287                         web_load(str);
288                 else
289                         web_load("");
290
291                 if (headline->unread) {
292                         ttrss_set_article_unread(headline->id, 0);
293                         headline->unread = 0;
294                 }
295
296                 model = gtk_tree_view_get_model(w_headlineview);
297                 gtk_list_store_set(GTK_LIST_STORE(model),
298                                    &iter,
299                                    0, headline->title,
300                                    -1);
301         } else {
302                 printf("headline not found\n");
303         }               
304
305
306         return TRUE;
307 }
308
309 void headline_row_activated_cbk(GtkWidget *widget, gpointer data)
310 {
311         GdkScreen *screen;
312         GError *error;
313         GtkTreeSelection *selection;
314         GtkTreeModel *model;
315         GtkTreeIter iter;
316         struct feed *feed;
317         const char *url;
318
319         printf("headline_row_activated_cbk\n");
320
321         selection = gtk_tree_view_get_selection(w_headlineview);
322         model = gtk_tree_view_get_model(w_headlineview);
323
324         if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
325                 gtk_tree_model_get(model, &iter, 1, &feed, -1);
326                 url = feed->url;
327
328                 if (gtk_widget_has_screen(widget))
329                         screen = gtk_widget_get_screen(widget);
330                 else
331                         screen = gdk_screen_get_default();
332
333                 error = NULL;
334                 gtk_show_uri(screen, url, gtk_get_current_event_time(), &error);
335         }
336 }
337
338 gboolean
339 window_delete_event_cbk(GtkWidget *widget, GdkEvent *event, gpointer data)
340 {
341         printf("window_delete_event_cbk\n");
342
343         gtk_main_quit();
344
345         return TRUE;
346 }
347
348 int main(int argc, char **argv)
349 {
350         GtkWidget *window, *panh;
351         GtkBuilder *builder;
352         int optc, cmdok, opti;
353
354         program_name = argv[0];
355
356         setlocale(LC_ALL, "");
357
358 #if ENABLE_NLS
359         bindtextdomain(PACKAGE, LOCALEDIR);
360         textdomain(PACKAGE);
361 #endif
362
363         cmdok = 1;
364         while ((optc = getopt_long(argc, argv, "vh", long_options,
365                                    &opti)) != -1) {
366                 switch (optc) {
367                 case 'h':
368                         print_help();
369                         exit(EXIT_SUCCESS);
370                 case 'v':
371                         print_version();
372                         exit(EXIT_SUCCESS);
373                 default:
374                         cmdok = 0;
375                         break;
376                 }
377         }
378
379         if (!cmdok || optind != argc) {
380                 fprintf(stderr, _("Try `%s --help' for more information.\n"),
381                         program_name);
382                 exit(EXIT_FAILURE);
383         }
384
385         http_init();
386
387         gtk_init(NULL, NULL);
388         settings = g_settings_new("prss");
389
390         ttrss_set_config(g_settings_get_string(settings, "url"),
391                          g_settings_get_string(settings, "user"),
392                          g_settings_get_string(settings, "password"));
393         ws_open_session();
394
395         builder = gtk_builder_new();
396         gtk_builder_add_from_file
397                 (builder,
398                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "prss.glade",
399                  NULL);
400         window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
401         w_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder,
402                                                           "feed_tree"));
403         w_headlineview = GTK_TREE_VIEW(gtk_builder_get_object(builder,
404                                                               "headline_tree"));
405
406         gtk_builder_connect_signals(builder, NULL);
407
408         panh = GTK_WIDGET(gtk_builder_get_object(builder, "webkit_window"));
409
410         gtk_container_add(GTK_CONTAINER(panh), web_get_widget());
411
412         g_object_unref(G_OBJECT(builder));
413
414         gtk_widget_show_all(window);
415
416         gtk_main();
417
418         exit(EXIT_SUCCESS);
419 }