1 /**
2 * @file subscription_dialog.c property dialog for feed subscriptions
3 *
4 * Copyright (C) 2004-2017 Lars Windolf <lars.windolf@gmx.de>
5 * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@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 "ui/subscription_dialog.h"
23
24 #include <libxml/uri.h>
25 #include <string.h>
26
27 #include "common.h"
28 #include "conf.h"
29 #include "db.h"
30 #include "debug.h"
31 #include "feed.h"
32 #include "feedlist.h"
33 #include "node.h"
34 #include "update.h"
35 #include "ui/liferea_dialog.h"
36 #include "ui/ui_common.h"
37 #include "ui/feed_list_node.h"
38
39 /* Note: these update interval literals should be kept in sync with the
40 ones in ui_prefs.c! */
41
42 static const gchar * default_update_interval_unit_options[] = {
43 N_("minutes"),
44 N_("hours"),
45 N_("days"),
46 NULL
47 };
48
49 /** common private structure for all subscription dialogs */
50 struct SubscriptionDialogPrivate {
51
52 subscriptionPtr subscription; /** used only for "properties" dialog */
53
54 gint selector; /* Desiginates which fileselection dialog box is open.
55 Set to 'u' for source
56 Set to 'f' for filter */
57
58 GtkWidget *dialog;
59 GtkWidget *feedNameEntry;
60 GtkWidget *refreshInterval;
61 GtkWidget *refreshIntervalUnit;
62 GtkWidget *sourceEntry;
63 GtkWidget *selectFile;
64 GtkWidget *fileRadio;
65 GtkWidget *urlRadio;
66 GtkWidget *cmdRadio;
67 GtkWidget *authcheckbox;
68 GtkWidget *credTable;
69 GtkWidget *username;
70 GtkWidget *password;
71 };
72
73 /* properties dialog */
74
75 #define SUBSCRIPTION_PROP_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), SUBSCRIPTION_PROP_DIALOG_TYPE, SubscriptionDialogPrivate))
76
77 static GObjectClass *parent_class = NULL;
78
79 G_DEFINE_TYPE (SubscriptionPropDialog, subscription_prop_dialog, G_TYPE_OBJECT);
80
81 static void
subscription_prop_dialog_finalize(GObject * object)82 subscription_prop_dialog_finalize (GObject *object)
83 {
84 SubscriptionPropDialog *spd = SUBSCRIPTION_PROP_DIALOG (object);
85
86 gtk_widget_destroy (spd->priv->dialog);
87
88 G_OBJECT_CLASS (parent_class)->finalize (object);
89 }
90
91 static void
subscription_prop_dialog_class_init(SubscriptionPropDialogClass * klass)92 subscription_prop_dialog_class_init (SubscriptionPropDialogClass *klass)
93 {
94 GObjectClass *object_class = G_OBJECT_CLASS (klass);
95
96 parent_class = g_type_class_peek_parent (klass);
97
98 object_class->finalize = subscription_prop_dialog_finalize;
99
100 g_type_class_add_private (object_class, sizeof(SubscriptionDialogPrivate));
101 }
102
103 static gchar *
ui_subscription_create_url(gchar * url,gboolean auth,const gchar * username,const gchar * password)104 ui_subscription_create_url (gchar *url,
105 gboolean auth,
106 const gchar *username,
107 const gchar *password)
108 {
109 gchar *source = NULL;
110 gchar *str, *tmp2;
111
112 /* First, strip leading and trailing whitespace */
113 str = g_strstrip(url);
114
115 /* Add http:// if needed */
116 if (strstr(str, "://") == NULL) {
117 tmp2 = g_strdup_printf("http://%s",str);
118 g_free(str);
119 str = tmp2;
120 }
121
122 /* Add trailing / if needed */
123 if (strstr(strstr(str, "://") + 3, "/") == NULL) {
124 tmp2 = g_strdup_printf("%s/", str);
125 g_free(str);
126 str = tmp2;
127 }
128
129 /* Use the values in the textboxes if also specified in the URL! */
130 if(auth) {
131 xmlURIPtr uri = xmlParseURI(str);
132 if (uri != NULL) {
133 xmlChar *sourceUrl;
134 xmlFree(uri->user);
135 uri->user = g_strdup_printf("%s:%s", username, password);
136 sourceUrl = xmlSaveUri(uri);
137 source = g_strdup((gchar *) sourceUrl);
138 g_free(uri->user);
139 uri->user = NULL;
140 xmlFree(sourceUrl);
141 xmlFreeURI(uri);
142 } else
143 source = g_strdup(str);
144 } else {
145 source = g_strdup(str);
146 }
147 g_free(str);
148
149 return source;
150 }
151
152 static gchar *
ui_subscription_dialog_decode_source(SubscriptionDialogPrivate * ui_data)153 ui_subscription_dialog_decode_source (SubscriptionDialogPrivate *ui_data)
154 {
155 gchar *source = NULL;
156
157 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_data->fileRadio)))
158 source = g_strdup (gtk_entry_get_text (GTK_ENTRY (ui_data->sourceEntry)));
159
160 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_data->urlRadio)))
161 source = ui_subscription_create_url (g_strdup (gtk_entry_get_text (GTK_ENTRY (ui_data->sourceEntry))),
162 ui_data->authcheckbox &&
163 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_data->authcheckbox)),
164 ui_data->username?gtk_entry_get_text (GTK_ENTRY (ui_data->username)):NULL,
165 ui_data->password?gtk_entry_get_text (GTK_ENTRY (ui_data->password)):NULL);
166 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_data->cmdRadio)))
167 source = g_strdup_printf ("|%s", gtk_entry_get_text (GTK_ENTRY (ui_data->sourceEntry)));
168
169 return source;
170 }
171
172 static void
on_propdialog_response(GtkDialog * dialog,gint response_id,gpointer user_data)173 on_propdialog_response (GtkDialog *dialog,
174 gint response_id,
175 gpointer user_data)
176 {
177 SubscriptionPropDialog *spd = (SubscriptionPropDialog *)user_data;
178
179 if(response_id == GTK_RESPONSE_OK) {
180 gchar *newSource;
181 const gchar *newFilter;
182 gboolean needsUpdate = FALSE;
183 subscriptionPtr subscription = spd->priv->subscription;
184 nodePtr node = spd->priv->subscription->node;
185 feedPtr feed = (feedPtr)node->data;
186
187 if (SUBSCRIPTION_TYPE(subscription) == feed_get_subscription_type ()) {
188 /* "General" */
189 node_set_title(node, gtk_entry_get_text(GTK_ENTRY(spd->priv->feedNameEntry)));
190
191 /* Source */
192 newSource = ui_subscription_dialog_decode_source(spd->priv);
193
194 /* Filter handling */
195 newFilter = gtk_entry_get_text(GTK_ENTRY(liferea_dialog_lookup(spd->priv->dialog, "filterEntry")));
196 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "filterCheckbox"))) &&
197 strcmp(newFilter,"")) { /* Maybe this should be a test to see if the file exists? */
198 if(subscription_get_filter(subscription) == NULL ||
199 strcmp(newFilter, subscription_get_filter(subscription))) {
200 subscription_set_filter(subscription, newFilter);
201 needsUpdate = TRUE;
202 }
203 } else {
204 if(subscription_get_filter(subscription)) {
205 subscription_set_filter(subscription, NULL);
206 needsUpdate = TRUE;
207 }
208 }
209
210 /* if URL has changed... */
211 if(strcmp(newSource, subscription_get_source(subscription))) {
212 subscription_set_source(subscription, newSource);
213 needsUpdate = TRUE;
214 }
215 g_free(newSource);
216
217 /* Update interval handling */
218 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "updateIntervalNever"))))
219 subscription_set_update_interval (subscription, -2);
220 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "updateIntervalDefault"))))
221 subscription_set_update_interval (subscription, -1);
222 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "updateIntervalSpecific")))) {
223 gint intervalUnit = gtk_combo_box_get_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit));
224 gint updateInterval = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spd->priv->refreshInterval));
225 if (intervalUnit == 1)
226 updateInterval *= 60; /* hours */
227 if (intervalUnit == 2)
228 updateInterval *= 1440; /* days */
229
230 subscription_set_update_interval (subscription, updateInterval);
231 db_subscription_update (subscription);
232 }
233 }
234
235 /* "Archive" handling */
236 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "feedCacheDefault"))))
237 feed->cacheLimit = CACHE_DEFAULT;
238 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "feedCacheDisable"))))
239 feed->cacheLimit = CACHE_DISABLE;
240 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "feedCacheUnlimited"))))
241 feed->cacheLimit = CACHE_UNLIMITED;
242 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "feedCacheLimited"))))
243 feed->cacheLimit = gtk_spin_button_get_value(GTK_SPIN_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "cacheItemLimit")));
244
245 if (SUBSCRIPTION_TYPE(subscription) == feed_get_subscription_type ()) {
246 /* "Download" Options */
247 subscription->updateOptions->dontUseProxy = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(GTK_WIDGET(dialog), "dontUseProxyCheck")));
248 }
249
250 /* "Advanced" options */
251 feed->encAutoDownload = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "enclosureDownloadCheck")));
252 node->loadItemLink = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "loadItemLinkCheck")));
253 feed->ignoreComments = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "ignoreCommentFeeds")));
254 feed->markAsRead = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "markAsReadCheck")));
255 feed->html5Extract = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (GTK_WIDGET (dialog), "html5ExtractCheck")));
256
257 feed_list_node_update (node->id);
258 feedlist_schedule_save ();
259 db_subscription_update (subscription);
260 if (needsUpdate)
261 subscription_update (subscription, FEED_REQ_PRIORITY_HIGH);
262 }
263
264 g_object_unref(spd);
265 }
266
267 static void
on_feed_prop_filtercheck(GtkToggleButton * button,gpointer user_data)268 on_feed_prop_filtercheck (GtkToggleButton *button,
269 gpointer user_data)
270 {
271 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
272
273 gboolean filter = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (ui_data->dialog, "filterCheckbox")));
274 gtk_widget_set_sensitive (liferea_dialog_lookup(ui_data->dialog, "filterbox"), filter);
275 }
276
277 static void
ui_subscription_prop_enable_httpauth(SubscriptionDialogPrivate * ui_data,gboolean enable)278 ui_subscription_prop_enable_httpauth (SubscriptionDialogPrivate *ui_data,
279 gboolean enable)
280 {
281 gboolean on;
282
283 if(ui_data->authcheckbox) {
284 on = enable && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui_data->authcheckbox));
285 gtk_widget_set_sensitive(ui_data->authcheckbox,enable);
286 gtk_widget_set_sensitive(ui_data->credTable,on);
287 }
288 }
289
290 static void
on_feed_prop_authcheck(GtkToggleButton * button,gpointer user_data)291 on_feed_prop_authcheck (GtkToggleButton *button,
292 gpointer user_data)
293 {
294 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
295 gboolean url = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui_data->urlRadio));
296
297 ui_subscription_prop_enable_httpauth(ui_data, url);
298 }
299
300 static void
on_feed_prop_url_radio(GtkToggleButton * button,gpointer user_data)301 on_feed_prop_url_radio (GtkToggleButton *button,
302 gpointer user_data)
303 {
304 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
305 gboolean url = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui_data->urlRadio));
306 gboolean file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui_data->fileRadio));
307 gboolean cmd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui_data->cmdRadio));
308
309 ui_subscription_prop_enable_httpauth(ui_data, url);
310 gtk_widget_set_sensitive(ui_data->selectFile, file || cmd);
311 }
312
313 static void
on_selectfileok_clicked(const gchar * filename,gpointer user_data)314 on_selectfileok_clicked (const gchar *filename,
315 gpointer user_data)
316 {
317 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
318 gchar *utfname;
319
320 if (!filename)
321 return;
322
323 utfname = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
324
325 if (utfname) {
326 if (ui_data->selector == 'u')
327 gtk_entry_set_text (GTK_ENTRY (ui_data->sourceEntry), utfname);
328 else
329 gtk_entry_set_text (GTK_ENTRY (liferea_dialog_lookup (ui_data->dialog, "filterEntry")), utfname);
330 }
331
332 g_free (utfname);
333 }
334
335 static void
on_selectfile_pressed(GtkButton * button,gpointer user_data)336 on_selectfile_pressed (GtkButton *button,
337 gpointer user_data)
338 {
339 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
340 const gchar *utfname;
341 gchar *name;
342
343 if (GTK_WIDGET (button) == ui_data->selectFile) {
344 ui_data->selector = 'u';
345 utfname = gtk_entry_get_text (GTK_ENTRY (ui_data->sourceEntry));
346 } else {
347 ui_data->selector = 'f';
348 utfname = gtk_entry_get_text (GTK_ENTRY (liferea_dialog_lookup (ui_data->dialog, "filterEntry")));
349 }
350
351 name = g_filename_from_utf8 (utfname, -1, NULL, NULL, NULL);
352 ui_choose_file (_("Choose File"), _("_Open"), FALSE, on_selectfileok_clicked, name, NULL, NULL, NULL, ui_data);
353 g_free (name);
354 }
355
356 static void
on_feed_prop_cache_radio(GtkToggleButton * button,gpointer user_data)357 on_feed_prop_cache_radio (GtkToggleButton *button,
358 gpointer user_data)
359 {
360 SubscriptionDialogPrivate *ui_data = (SubscriptionDialogPrivate *)user_data;
361 gboolean limited = gtk_toggle_button_get_active(button);
362
363 gtk_widget_set_sensitive(liferea_dialog_lookup(GTK_WIDGET(ui_data->dialog), "cacheItemLimit"), limited);
364 }
365
366 static void
on_feed_prop_update_radio(GtkToggleButton * button,gpointer user_data)367 on_feed_prop_update_radio (GtkToggleButton *button,
368 gpointer user_data)
369 {
370 SubscriptionDialogPrivate *priv = (SubscriptionDialogPrivate *) user_data;
371 gboolean limited = gtk_toggle_button_get_active (button);
372
373 gtk_widget_set_sensitive (priv->refreshInterval, limited);
374 gtk_widget_set_sensitive (priv->refreshIntervalUnit, limited);
375 }
376
377 static void
subscription_prop_dialog_load(SubscriptionPropDialog * spd,subscriptionPtr subscription)378 subscription_prop_dialog_load (SubscriptionPropDialog *spd,
379 subscriptionPtr subscription)
380 {
381 gint interval;
382 gint default_update_interval;
383 gint defaultInterval, spinSetInterval;
384 gchar *defaultIntervalStr;
385 nodePtr node = subscription->node;
386 feedPtr feed = (feedPtr)node->data;
387
388 spd->priv->subscription = subscription;
389
390 /* General */
391 gtk_entry_set_text(GTK_ENTRY(spd->priv->feedNameEntry), node_get_title(node));
392
393 spd->priv->refreshInterval = liferea_dialog_lookup(spd->priv->dialog,"refreshIntervalSpinButton");
394
395 interval = subscription_get_update_interval(subscription);
396 defaultInterval = subscription_get_default_update_interval(subscription);
397 conf_get_int_value (DEFAULT_UPDATE_INTERVAL, &default_update_interval);
398 spinSetInterval = defaultInterval > 0 ? defaultInterval : default_update_interval;
399
400 if (-2 >= interval) {
401 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalNever")), TRUE);
402 } else if (-1 == interval) {
403 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalDefault")), TRUE);
404 } else {
405 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalSpecific")), TRUE);
406 spinSetInterval = interval;
407 }
408
409 /* Set refresh interval spin button and combo box */
410 if (spinSetInterval % 1440 == 0) { /* days */
411 gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 2);
412 spinSetInterval /= 1440;
413 } else if (spinSetInterval % 60 == 0) { /* hours */
414 gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 1);
415 spinSetInterval /= 60;
416 } else {
417 gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 0);
418 }
419 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spd->priv->refreshInterval), spinSetInterval);
420
421 gtk_widget_set_sensitive (spd->priv->refreshInterval, interval > 0);
422 gtk_widget_set_sensitive (spd->priv->refreshIntervalUnit, interval > 0);
423
424 /* setup info label about default update interval */
425 if(-1 != defaultInterval)
426 defaultIntervalStr = g_strdup_printf(ngettext("The provider of this feed suggests an update interval of %d minute.",
427 "The provider of this feed suggests an update interval of %d minutes.",
428 defaultInterval), defaultInterval);
429 else
430 defaultIntervalStr = g_strdup(_("This feed specifies no default update interval."));
431
432 gtk_label_set_text(GTK_LABEL(liferea_dialog_lookup(spd->priv->dialog, "feedUpdateInfo")), defaultIntervalStr);
433 g_free(defaultIntervalStr);
434
435 /* Source (only for feeds) */
436 if (SUBSCRIPTION_TYPE(subscription) == feed_get_subscription_type ()) {
437 if(subscription_get_source(subscription)[0] == '|') {
438 gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), &(subscription_get_source(subscription)[1]));
439 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->cmdRadio), TRUE);
440 ui_subscription_prop_enable_httpauth(spd->priv, FALSE);
441 gtk_widget_set_sensitive(spd->priv->selectFile, TRUE);
442 } else if(strstr(subscription_get_source(subscription), "://") != NULL) {
443 xmlURIPtr uri = xmlParseURI(subscription_get_source(subscription));
444 xmlChar *parsedUrl;
445 if(uri) {
446 if(uri->user) {
447 gchar *user = uri->user;
448 gchar *pass = strstr(user, ":");
449 if(pass) {
450 pass[0] = '\0';
451 pass++;
452 gtk_entry_set_text(GTK_ENTRY(spd->priv->password), pass);
453 }
454 gtk_entry_set_text(GTK_ENTRY(spd->priv->username), user);
455 xmlFree(uri->user);
456 uri->user = NULL;
457 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->authcheckbox), TRUE);
458 }
459 parsedUrl = xmlSaveUri(uri);
460 gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), (gchar *) parsedUrl);
461 xmlFree(parsedUrl);
462 xmlFreeURI(uri);
463 } else {
464 gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), subscription_get_source(subscription));
465 }
466 ui_subscription_prop_enable_httpauth(spd->priv, TRUE);
467 gtk_widget_set_sensitive(spd->priv->selectFile, FALSE);
468 } else {
469 /* File */
470 gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), subscription_get_source(subscription));
471 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->fileRadio), TRUE);
472 ui_subscription_prop_enable_httpauth(spd->priv, FALSE);
473 gtk_widget_set_sensitive(spd->priv->selectFile, TRUE);
474 }
475
476 if(subscription_get_filter(subscription)) {
477 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "filterCheckbox")), TRUE);
478 gtk_entry_set_text(GTK_ENTRY(liferea_dialog_lookup(spd->priv->dialog, "filterEntry")), subscription_get_filter(subscription));
479 }
480 }
481
482 /* Archive */
483 if(feed->cacheLimit == CACHE_DISABLE) {
484 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheDisable")), TRUE);
485 } else if(feed->cacheLimit == CACHE_DEFAULT) {
486 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheDefault")), TRUE);
487 } else if(feed->cacheLimit == CACHE_UNLIMITED) {
488 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheUnlimited")), TRUE);
489 } else {
490 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheLimited")), TRUE);
491 gtk_spin_button_set_value(GTK_SPIN_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "cacheItemLimit")), feed->cacheLimit);
492 }
493
494 gtk_widget_set_sensitive(liferea_dialog_lookup(spd->priv->dialog, "cacheItemLimit"), feed->cacheLimit > 0);
495
496 on_feed_prop_filtercheck(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "filterCheckbox")), spd->priv);
497
498 /* Download */
499 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "dontUseProxyCheck")), subscription->updateOptions->dontUseProxy);
500
501 /* Advanced */
502 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "enclosureDownloadCheck")), feed->encAutoDownload);
503 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "loadItemLinkCheck")), node->loadItemLink);
504 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "ignoreCommentFeeds")), feed->ignoreComments);
505 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "markAsReadCheck")), feed->markAsRead);
506 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "html5ExtractCheck")), feed->html5Extract);
507
508 /* Remove tabs we do not need... */
509 if (SUBSCRIPTION_TYPE(subscription) != feed_get_subscription_type ()) {
510 /* Remove "General", "Source" and "Download" tab */
511 gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 0);
512 gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 0);
513 gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 1);
514 }
515 }
516
517 static void
subscription_prop_dialog_init(SubscriptionPropDialog * spd)518 subscription_prop_dialog_init (SubscriptionPropDialog *spd)
519 {
520 GtkWidget *propdialog;
521
522 spd->priv = SUBSCRIPTION_PROP_DIALOG_GET_PRIVATE (spd);
523 spd->priv->dialog = propdialog = liferea_dialog_new ("properties");
524
525 /* set default update interval spin button and unit combo box */
526 ui_common_setup_combo_menu (liferea_dialog_lookup (propdialog, "refreshIntervalUnitComboBox"),
527 default_update_interval_unit_options,
528 NULL /* no callback */,
529 -1 /* default value */ );
530
531 spd->priv->feedNameEntry = liferea_dialog_lookup (propdialog, "feedNameEntry");
532 spd->priv->refreshInterval = liferea_dialog_lookup (propdialog, "refreshIntervalSpinButton");
533 spd->priv->refreshIntervalUnit = liferea_dialog_lookup (propdialog, "refreshIntervalUnitComboBox");
534 spd->priv->sourceEntry = liferea_dialog_lookup (propdialog, "sourceEntry");
535 spd->priv->selectFile = liferea_dialog_lookup (propdialog, "selectSourceFileButton");
536 spd->priv->fileRadio = liferea_dialog_lookup (propdialog, "feed_loc_file");
537 spd->priv->urlRadio = liferea_dialog_lookup (propdialog, "feed_loc_url");
538 spd->priv->cmdRadio = liferea_dialog_lookup (propdialog, "feed_loc_command");
539
540 spd->priv->authcheckbox = liferea_dialog_lookup (propdialog, "HTTPauthCheck");
541 spd->priv->username = liferea_dialog_lookup (propdialog, "usernameEntry");
542 spd->priv->password = liferea_dialog_lookup (propdialog, "passwordEntry");
543 spd->priv->credTable = liferea_dialog_lookup (propdialog, "httpAuthBox");
544
545 g_signal_connect (spd->priv->selectFile, "clicked", G_CALLBACK (on_selectfile_pressed), spd->priv);
546 g_signal_connect (spd->priv->urlRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), spd->priv);
547 g_signal_connect (spd->priv->fileRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), spd->priv);
548 g_signal_connect (spd->priv->cmdRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), spd->priv);
549 g_signal_connect (spd->priv->authcheckbox, "toggled", G_CALLBACK (on_feed_prop_authcheck), spd->priv);
550
551 g_signal_connect (liferea_dialog_lookup (propdialog, "filterCheckbox"), "toggled", G_CALLBACK (on_feed_prop_filtercheck), spd->priv);
552 g_signal_connect (liferea_dialog_lookup (propdialog, "filterSelectFile"), "clicked", G_CALLBACK (on_selectfile_pressed), spd->priv);
553 g_signal_connect (liferea_dialog_lookup (propdialog, "feedCacheLimited"), "toggled", G_CALLBACK (on_feed_prop_cache_radio), spd->priv);
554 g_signal_connect (liferea_dialog_lookup (propdialog, "updateIntervalSpecific"), "toggled", G_CALLBACK(on_feed_prop_update_radio), spd->priv);
555
556 g_signal_connect (G_OBJECT (propdialog), "response", G_CALLBACK (on_propdialog_response), spd);
557
558 gtk_widget_show_all (propdialog);
559 }
560
561 SubscriptionPropDialog *
subscription_prop_dialog_new(subscriptionPtr subscription)562 subscription_prop_dialog_new (subscriptionPtr subscription)
563 {
564 SubscriptionPropDialog *spd;
565
566 spd = SUBSCRIPTION_PROP_DIALOG (g_object_new (SUBSCRIPTION_PROP_DIALOG_TYPE, NULL));
567 subscription_prop_dialog_load(spd, subscription);
568 return spd;
569 }
570
571 /* complex "New" dialog */
572
573 #define NEW_SUBSCRIPTION_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), NEW_SUBSCRIPTION_DIALOG_TYPE, SubscriptionDialogPrivate))
574
575 G_DEFINE_TYPE (NewSubscriptionDialog, new_subscription_dialog, G_TYPE_OBJECT);
576
577 static void
new_subscription_dialog_finalize(GObject * object)578 new_subscription_dialog_finalize (GObject *object)
579 {
580 NewSubscriptionDialog *nsd = NEW_SUBSCRIPTION_DIALOG (object);
581
582 gtk_widget_destroy (nsd->priv->dialog);
583
584 G_OBJECT_CLASS (parent_class)->finalize (object);
585 }
586
587 static void
new_subscription_dialog_class_init(NewSubscriptionDialogClass * klass)588 new_subscription_dialog_class_init (NewSubscriptionDialogClass *klass)
589 {
590 GObjectClass *object_class = G_OBJECT_CLASS (klass);
591
592 parent_class = g_type_class_peek_parent (klass);
593
594 object_class->finalize = new_subscription_dialog_finalize;
595
596 g_type_class_add_private (object_class, sizeof(SubscriptionDialogPrivate));
597 }
598
599 static void
on_newdialog_response(GtkDialog * dialog,gint response_id,gpointer user_data)600 on_newdialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
601 {
602 NewSubscriptionDialog *nsd = (NewSubscriptionDialog *)user_data;
603
604 if (response_id == GTK_RESPONSE_OK) {
605 gchar *source = NULL;
606 const gchar *filter = NULL;
607 updateOptionsPtr options;
608 nodePtr duplicateUrlNode = NULL;
609
610 /* Source */
611 source = ui_subscription_dialog_decode_source (nsd->priv);
612
613 /* Filter handling */
614 filter = gtk_entry_get_text (GTK_ENTRY (liferea_dialog_lookup (nsd->priv->dialog, "filterEntry")));
615 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (nsd->priv->dialog, "filterCheckbox"))) ||
616 !strcmp(filter,"")) { /* Maybe this should be a test to see if the file exists? */
617 filter = NULL;
618 }
619
620 options = g_new0 (struct updateOptions, 1);
621 options->dontUseProxy = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(GTK_WIDGET (dialog), "dontUseProxyCheck")));
622
623 duplicateUrlNode = feedlist_find_node (feedlist_get_root (), NODE_BY_URL, source);
624 if (duplicateUrlNode == NULL) {
625 feedlist_add_subscription (source, filter, options, FEED_REQ_PRIORITY_HIGH);
626 g_free (source);
627 } else {
628 feed_list_node_add_duplicate_url_subscription (subscription_new (source, filter, options), duplicateUrlNode);
629 }
630 }
631
632 g_object_unref (nsd);
633 }
634
635 static void
new_subscription_dialog_init(NewSubscriptionDialog * nsd)636 new_subscription_dialog_init (NewSubscriptionDialog *nsd)
637 {
638 GtkWidget *newdialog;
639
640 nsd->priv = NEW_SUBSCRIPTION_DIALOG_GET_PRIVATE (nsd);
641 nsd->priv->dialog = newdialog = liferea_dialog_new ("new_subscription");
642
643 /* Setup source entry */
644 nsd->priv->sourceEntry = liferea_dialog_lookup (newdialog,"sourceEntry");
645 gtk_widget_grab_focus (GTK_WIDGET (nsd->priv->sourceEntry));
646 gtk_entry_set_activates_default (GTK_ENTRY (nsd->priv->sourceEntry), TRUE);
647
648 nsd->priv->selectFile = liferea_dialog_lookup (newdialog,"selectSourceFileButton");
649 g_signal_connect (nsd->priv->selectFile, "clicked", G_CALLBACK (on_selectfile_pressed), nsd->priv);
650
651 /* Feed location radio buttons */
652 nsd->priv->fileRadio = liferea_dialog_lookup (newdialog, "feed_loc_file");
653 nsd->priv->urlRadio = liferea_dialog_lookup (newdialog, "feed_loc_url");
654 nsd->priv->cmdRadio = liferea_dialog_lookup (newdialog, "feed_loc_command");
655
656 g_signal_connect (nsd->priv->urlRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), nsd->priv);
657 g_signal_connect (nsd->priv->fileRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), nsd->priv);
658 g_signal_connect (nsd->priv->cmdRadio, "toggled", G_CALLBACK (on_feed_prop_url_radio), nsd->priv);
659
660 g_signal_connect (liferea_dialog_lookup (newdialog, "filterCheckbox"), "toggled", G_CALLBACK (on_feed_prop_filtercheck), nsd->priv);
661 g_signal_connect (liferea_dialog_lookup (newdialog, "filterSelectFile"), "clicked", G_CALLBACK (on_selectfile_pressed), nsd->priv);
662
663 gtk_widget_grab_default (liferea_dialog_lookup (newdialog, "newfeedbtn"));
664 g_signal_connect (G_OBJECT (newdialog), "response", G_CALLBACK (on_newdialog_response), nsd);
665
666 on_feed_prop_filtercheck (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (newdialog, "filterCheckbox")), nsd->priv);
667 on_feed_prop_url_radio (GTK_TOGGLE_BUTTON (nsd->priv->urlRadio), nsd->priv);
668
669 gtk_widget_show_all (newdialog);
670 }
671
672 static NewSubscriptionDialog *
ui_complex_subscription_dialog_new(void)673 ui_complex_subscription_dialog_new (void)
674 {
675 NewSubscriptionDialog *nsd;
676
677 nsd = NEW_SUBSCRIPTION_DIALOG (g_object_new (NEW_SUBSCRIPTION_DIALOG_TYPE, NULL));
678 return nsd;
679 }
680
681 /* simple "New" dialog */
682
683 #define SIMPLE_SUBSCRIPTION_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), SIMPLE_SUBSCRIPTION_DIALOG_TYPE, SubscriptionDialogPrivate))
684
685 G_DEFINE_TYPE (SimpleSubscriptionDialog, simple_subscription_dialog, G_TYPE_OBJECT);
686
687 static void
simple_subscription_dialog_finalize(GObject * object)688 simple_subscription_dialog_finalize (GObject *object)
689 {
690 SimpleSubscriptionDialog *ssd = SIMPLE_SUBSCRIPTION_DIALOG (object);
691
692 gtk_widget_destroy (ssd->priv->dialog);
693
694 G_OBJECT_CLASS (parent_class)->finalize (object);
695 }
696
697 static void
simple_subscription_dialog_class_init(SimpleSubscriptionDialogClass * klass)698 simple_subscription_dialog_class_init (SimpleSubscriptionDialogClass *klass)
699 {
700 GObjectClass *object_class = G_OBJECT_CLASS (klass);
701
702 parent_class = g_type_class_peek_parent (klass);
703
704 object_class->finalize = simple_subscription_dialog_finalize;
705
706 g_type_class_add_private (object_class, sizeof (SubscriptionDialogPrivate));
707 }
708
709 static void
on_simple_newdialog_response(GtkDialog * dialog,gint response_id,gpointer user_data)710 on_simple_newdialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
711 {
712 SimpleSubscriptionDialog *ssd = (SimpleSubscriptionDialog *) user_data;
713 gchar *source = NULL;
714 nodePtr duplicateUrlNode = NULL;
715
716 if (response_id == GTK_RESPONSE_OK) {
717 source = ui_subscription_create_url (g_strdup (gtk_entry_get_text (GTK_ENTRY(ssd->priv->sourceEntry))),
718 FALSE /* auth */, NULL /* user */, NULL /* passwd */);
719
720 duplicateUrlNode = feedlist_find_node (feedlist_get_root (), NODE_BY_URL, source);
721 if (duplicateUrlNode == NULL) {
722 feedlist_add_subscription (source, NULL, NULL, FEED_REQ_PRIORITY_HIGH);
723 g_free (source);
724 } else {
725 feed_list_node_add_duplicate_url_subscription (subscription_new (source, NULL, NULL), duplicateUrlNode);
726 }
727 }
728
729 if (response_id == GTK_RESPONSE_APPLY) /* misused for "Advanced" */
730 ui_complex_subscription_dialog_new ();
731
732 g_object_unref (ssd);
733 }
734
735 static void
simple_subscription_dialog_init(SimpleSubscriptionDialog * ssd)736 simple_subscription_dialog_init (SimpleSubscriptionDialog *ssd)
737 {
738 GtkWidget *newdialog;
739
740 ssd->priv = SIMPLE_SUBSCRIPTION_DIALOG_GET_PRIVATE (ssd);
741 ssd->priv->dialog = newdialog = liferea_dialog_new ("simple_subscription");
742
743 /* Setup source entry */
744 ssd->priv->sourceEntry = liferea_dialog_lookup (newdialog, "sourceEntry");
745 gtk_widget_grab_focus (GTK_WIDGET (ssd->priv->sourceEntry));
746 gtk_entry_set_activates_default (GTK_ENTRY (ssd->priv->sourceEntry), TRUE);
747
748 g_signal_connect (G_OBJECT (newdialog), "response",
749 G_CALLBACK (on_simple_newdialog_response), ssd);
750
751 gtk_widget_show_all (newdialog);
752 }
753
754 SimpleSubscriptionDialog *
subscription_dialog_new(void)755 subscription_dialog_new (void)
756 {
757 SimpleSubscriptionDialog *ssd;
758
759 ssd = SIMPLE_SUBSCRIPTION_DIALOG (g_object_new (SIMPLE_SUBSCRIPTION_DIALOG_TYPE, NULL));
760 return ssd;
761 }
762