b702a03d76d2d0cb13b392788ffd1b28f818a423
[claws.git] / src / plugins / rssyl / rssyl_feed_props.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2004 Hiroyuki Yamamoto
4  * This file (C) 2005 Andrej Kacian <andrej@kacian.sk>
5  *
6  * - Plugin preferences
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 /* Global includes */
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
31
32 /* Claws Mail includes */
33 #include <mainwindow.h>
34
35 /* Local includes */
36 #include "rssyl.h"
37 #include "rssyl_feed.h"
38 #include "rssyl_feed_props.h"
39 #include "rssyl_prefs.h"
40 #include "rssyl_update_feed.h"
41
42 static void rssyl_gtk_prop_store(RFolderItem *ritem)
43 {
44         gchar *url, *auth_user, *auth_pass;
45         gint x, old_ri, old_fetch_comments;
46         gboolean use_default_ri = FALSE, keep_old = FALSE;
47         FolderItem *item;
48
49         g_return_if_fail(ritem != NULL);
50         g_return_if_fail(ritem->feedprop != NULL);
51
52         url = (gchar *)gtk_entry_get_text(GTK_ENTRY(ritem->feedprop->url));
53
54         if( strlen(url) ) {
55                 if( ritem->url ) {
56                         g_free(ritem->url);
57                 }
58                 ritem->url = g_strdup(url);
59         }
60
61         ritem->auth->type = gtk_combo_box_get_active(GTK_COMBO_BOX(ritem->feedprop->auth_type));
62
63         auth_user = (gchar *)gtk_entry_get_text(GTK_ENTRY(ritem->feedprop->auth_username));
64         if (auth_user != NULL) {
65                 if (ritem->auth->username) {
66                         g_free(ritem->auth->username);
67                 }
68                 ritem->auth->username = g_strdup(auth_user);
69         }
70
71         auth_pass = (gchar *)gtk_entry_get_text(GTK_ENTRY(ritem->feedprop->auth_password));
72         if (auth_pass != NULL) {
73                 if (ritem->auth->password) {
74                         g_free(ritem->auth->password);
75                 }
76                 ritem->auth->password = g_strdup(auth_pass);
77         }
78
79         use_default_ri = gtk_toggle_button_get_active(
80                         GTK_TOGGLE_BUTTON(ritem->feedprop->default_refresh_interval));
81         ritem->default_refresh_interval = use_default_ri;
82         debug_print("store: default refresh interval is %s\n",
83                         ( use_default_ri ? "ON" : "OFF" ) );
84
85         /* Use default if checkbutton is set */
86         if( use_default_ri )
87                 x = rssyl_prefs_get()->refresh;
88         else
89                 x = gtk_spin_button_get_value_as_int(
90                                 GTK_SPIN_BUTTON(ritem->feedprop->refresh_interval) );
91
92         old_ri = ritem->refresh_interval;
93         ritem->refresh_interval = x;
94
95         /* Set timer for next automatic refresh, if needed. */
96         if( x > 0 ) {
97                 if( old_ri != x || ritem->refresh_id == 0 ) {
98                         debug_print("RSSyl: GTK - refresh interval changed to %d , updating "
99                                         "timeout\n", ritem->refresh_interval);
100                         rssyl_feed_start_refresh_timeout(ritem);
101                 }
102         } else
103                 ritem->refresh_id = 0;
104
105         old_fetch_comments = ritem->fetch_comments;
106         ritem->fetch_comments = gtk_toggle_button_get_active(
107                         GTK_TOGGLE_BUTTON(ritem->feedprop->fetch_comments));
108
109         if (!old_fetch_comments && ritem->fetch_comments) {
110                 /* reset the RFolderItem's mtime to be sure we get all 
111                  * available comments */
112                  ritem->item.mtime = 0;
113         }
114         
115         ritem->fetch_comments_max_age = gtk_spin_button_get_value_as_int(
116                         GTK_SPIN_BUTTON(ritem->feedprop->fetch_comments_max_age));
117
118         keep_old = gtk_toggle_button_get_active(
119                         GTK_TOGGLE_BUTTON(ritem->feedprop->keep_old));
120         ritem->keep_old = keep_old;
121
122         ritem->silent_update =
123                 gtk_combo_box_get_active(GTK_COMBO_BOX(ritem->feedprop->silent_update));
124
125         ritem->write_heading = gtk_toggle_button_get_active(
126                         GTK_TOGGLE_BUTTON(ritem->feedprop->write_heading));
127
128         ritem->ignore_title_rename = gtk_toggle_button_get_active(
129                         GTK_TOGGLE_BUTTON(ritem->feedprop->ignore_title_rename));
130
131         ritem->ssl_verify_peer = gtk_toggle_button_get_active(
132                         GTK_TOGGLE_BUTTON(ritem->feedprop->ssl_verify_peer));
133
134         /* Store updated properties */
135         item = &ritem->item;
136         item->folder->klass->item_get_xml(item->folder, item);
137 }
138
139 static gboolean
140 rssyl_feedprop_togglebutton_toggled_cb(GtkToggleButton *tb,
141                 gpointer data)
142 {
143         gboolean active = gtk_toggle_button_get_active(tb);
144         RFeedProp *feedprop = (RFeedProp *)data;
145         GtkWidget *sb = NULL;
146
147         if( (GtkWidget *)tb == feedprop->default_refresh_interval ) {
148                 active = !active;
149                 sb = feedprop->refresh_interval;
150         } else if( (GtkWidget *)tb == feedprop->fetch_comments ) {
151                 sb = feedprop->fetch_comments_max_age;
152         }
153
154         g_return_val_if_fail(sb != NULL, FALSE);
155
156         gtk_widget_set_sensitive(sb, active);
157
158         return FALSE;
159 }
160
161 static void
162 rssyl_feedprop_auth_type_changed_cb(GtkComboBox *cb, gpointer data)
163 {
164         RFeedProp *feedprop = (RFeedProp *)data;
165         gboolean enable = (FEED_AUTH_NONE != gtk_combo_box_get_active(cb));
166         gtk_widget_set_sensitive(GTK_WIDGET(feedprop->auth_username), enable);
167         gtk_widget_set_sensitive(GTK_WIDGET(feedprop->auth_password), enable);
168 }
169
170 static gboolean
171 rssyl_props_cancel_cb(GtkWidget *widget, gpointer data)
172 {
173         RFolderItem *ritem = (RFolderItem *)data;
174
175         debug_print("RSSyl: Cancel pressed\n");
176
177         gtk_widget_destroy(ritem->feedprop->window);
178
179         return FALSE;
180 }
181
182 static gboolean
183 rssyl_props_ok_cb(GtkWidget *widget, gpointer data)
184 {
185         RFolderItem *ritem = (RFolderItem *)data;
186
187         debug_print("RSSyl: OK pressed\n");
188         rssyl_gtk_prop_store(ritem);
189
190         gtk_widget_destroy(ritem->feedprop->window);
191
192         return FALSE;
193 }
194
195 static gboolean
196 rssyl_props_trim_cb(GtkWidget *widget, gpointer data)
197 {
198         RFolderItem *ritem = (RFolderItem *)data;
199         gboolean k = ritem->keep_old;
200
201         if( k )
202                 ritem->keep_old = FALSE;
203
204         rssyl_update_feed(ritem, FALSE);
205
206         if( k )
207                 ritem->keep_old = TRUE;
208
209         return FALSE;
210 }
211
212 static gboolean
213 rssyl_props_key_press_cb(GtkWidget *widget, GdkEventKey *event,
214                 gpointer data)
215 {
216         if (event) {
217                 switch (event->keyval) {
218                         case GDK_Escape:
219                                 rssyl_props_cancel_cb(widget, data);
220                                 return TRUE;
221                         case GDK_Return:
222                         case GDK_KP_Enter:
223                                 rssyl_props_ok_cb(widget, data);
224                                 return TRUE;
225                         default:
226                                 break;
227                 }
228         }
229
230         return FALSE;
231 }
232
233
234 void rssyl_gtk_prop(RFolderItem *ritem)
235 {
236         MainWindow *mainwin = mainwindow_get_mainwindow();
237         RFeedProp *feedprop;
238         GtkWidget *vbox, *urllabel, *urlframe, *urlalign, *table, *label,
239                 *inner_vbox, *auth_hbox, *auth_user_label, *auth_pass_label,
240                                                 *hsep, *sep, *bbox, *cancel_button, *cancel_align,
241                                                 *cancel_hbox, *cancel_image, *cancel_label, *ok_button, *ok_align,
242                                                 *ok_hbox, *ok_image, *ok_label, *trim_button, *silent_update_label;
243         GtkObject *adj;
244 #if !(GTK_CHECK_VERSION(2, 12, 0))
245         GtkTooltips *tooltips;
246 #endif
247         gint refresh;
248         gint row = 0;
249
250         g_return_if_fail(ritem != NULL);
251
252         feedprop = g_new0(RFeedProp, 1);
253
254         /**** Create required widgets ****/
255
256         /* Window */
257         feedprop->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
258
259 #if !(GTK_CHECK_VERSION(2, 12, 0))
260         tooltips = gtk_tooltips_new();
261         gtk_tooltips_enable(tooltips);
262 #endif
263
264         /* URL entry */
265         feedprop->url = gtk_entry_new();
266         gtk_entry_set_text(GTK_ENTRY(feedprop->url), ritem->url);
267
268         /* URL auth type combo */
269 #if !GTK_CHECK_VERSION(2, 24, 0)
270         feedprop->auth_type = gtk_combo_box_new_text();
271         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->auth_type),
272 #else
273         feedprop->auth_type = gtk_combo_box_text_new();
274         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->auth_type),
275 #endif
276                         _("No authentication"));
277 #if !GTK_CHECK_VERSION(2, 24, 0)
278         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->auth_type),
279 #else
280         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->auth_type),
281 #endif
282                         _("HTTP Basic authentication"));
283         gtk_combo_box_set_active(GTK_COMBO_BOX(feedprop->auth_type),
284                         ritem->auth->type);
285
286         /* Auth username */
287         feedprop->auth_username = gtk_entry_new();
288         gtk_entry_set_text(GTK_ENTRY(feedprop->auth_username),
289                         ritem->auth->username);
290
291         /* Auth password */
292         feedprop->auth_password = gtk_entry_new();
293         gtk_entry_set_visibility(GTK_ENTRY(feedprop->auth_password), FALSE);
294         gtk_entry_set_text(GTK_ENTRY(feedprop->auth_password),
295                         ritem->auth->password);
296
297         /* "Use default refresh interval" checkbutton */
298         feedprop->default_refresh_interval = gtk_check_button_new_with_mnemonic(
299                         _("Use default refresh interval"));
300         gtk_toggle_button_set_active(
301                         GTK_TOGGLE_BUTTON(feedprop->default_refresh_interval),
302                         ritem->default_refresh_interval);
303
304         if( ritem->refresh_interval >= 0 && !ritem->default_refresh_interval )
305                 refresh = ritem->refresh_interval;
306         else
307                 refresh = rssyl_prefs_get()->refresh;
308
309         /* "Keep old items" checkbutton */
310         feedprop->keep_old = gtk_check_button_new_with_mnemonic(
311                         _("Keep old items"));
312         gtk_toggle_button_set_active(
313                         GTK_TOGGLE_BUTTON(feedprop->keep_old),
314                         ritem->keep_old);
315
316         /* "Trim" button */
317         trim_button = gtk_button_new_with_mnemonic(_("_Trim"));
318 #if !(GTK_CHECK_VERSION(2, 12, 0))
319         gtk_tooltips_set_tip(tooltips, trim_button,
320                         _("Update feed, deleting items which are no longer in the source feed"), NULL);
321 #else
322         gtk_widget_set_tooltip_text(trim_button,
323                         _("Update feed, deleting items which are no longer in the source feed"));
324 #endif
325
326         feedprop->fetch_comments = gtk_check_button_new_with_mnemonic(
327                         _("Fetch comments if possible"));
328         gtk_toggle_button_set_active(
329                         GTK_TOGGLE_BUTTON(feedprop->fetch_comments),
330                         ritem->fetch_comments);
331
332         /* Fetch comments max age spinbutton */
333         adj = gtk_adjustment_new(ritem->fetch_comments_max_age,
334                         -1, 100000, 1, 10, 0);
335         feedprop->fetch_comments_max_age = gtk_spin_button_new(GTK_ADJUSTMENT(adj),
336                         1, 0);
337
338         /* Refresh interval spinbutton */
339         adj = gtk_adjustment_new(refresh,
340                         0, 100000, 10, 100, 0);
341         feedprop->refresh_interval = gtk_spin_button_new(GTK_ADJUSTMENT(adj),
342                         1, 0);
343
344         /* Silent update - combobox */
345 #if !GTK_CHECK_VERSION(2, 24, 0)
346         feedprop->silent_update = gtk_combo_box_new_text();
347         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
348 #else
349         feedprop->silent_update = gtk_combo_box_text_new();
350         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
351 #endif
352                         _("Always mark as new"));
353 #if !GTK_CHECK_VERSION(2, 24, 0)
354         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
355 #else
356         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
357 #endif
358                         _("If only its text changed"));
359 #if !GTK_CHECK_VERSION(2, 24, 0)
360         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
361 #else
362         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
363 #endif
364                         _("Never mark as new"));
365         gtk_combo_box_set_active(GTK_COMBO_BOX(feedprop->silent_update),
366                         ritem->silent_update);
367
368         feedprop->write_heading = gtk_check_button_new_with_mnemonic(
369                         _("Add item title to top of message"));
370         gtk_toggle_button_set_active(
371                         GTK_TOGGLE_BUTTON(feedprop->write_heading),
372                         ritem->write_heading);
373
374         /* Ignore title rename - checkbox */
375         feedprop->ignore_title_rename = gtk_check_button_new_with_mnemonic(
376                         _("Ignore title rename"));
377         gtk_toggle_button_set_active(
378                         GTK_TOGGLE_BUTTON(feedprop->ignore_title_rename),
379                         ritem->ignore_title_rename);
380 #if !(GTK_CHECK_VERSION(2, 12, 0))
381         gtk_tooltips_set_tip(tooltips, feedprop->ignore_title_rename,
382                         _("Enable this to keep current folder name, even if feed author changes title of the feed."), NULL);
383 #else
384         gtk_widget_set_tooltip_text(feedprop->ignore_title_rename,
385                         _("Enable this to keep current folder name, even if feed author changes title of the feed."));
386 #endif
387
388         /* Verify SSL peer certificate */
389         feedprop->ssl_verify_peer = gtk_check_button_new_with_label(
390                         _("Verify SSL certificate validity"));
391         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(feedprop->ssl_verify_peer),
392                         ritem->ssl_verify_peer);
393
394         /* === Now pack all the widgets */
395         vbox = gtk_vbox_new(FALSE, 0);
396         gtk_container_add(GTK_CONTAINER(feedprop->window), vbox);
397
398         /* URL frame */
399         urlframe = gtk_frame_new(NULL);
400         gtk_container_set_border_width(GTK_CONTAINER(urlframe), 5);
401         gtk_frame_set_label_align(GTK_FRAME(urlframe), 0.05, 0.5);
402         gtk_frame_set_shadow_type(GTK_FRAME(urlframe), GTK_SHADOW_ETCHED_OUT);
403         gtk_box_pack_start(GTK_BOX(vbox), urlframe, FALSE, FALSE, 0);
404
405         /* Label for URL frame */
406         urllabel = gtk_label_new(_("<b>Source URL:</b>"));
407         gtk_label_set_use_markup(GTK_LABEL(urllabel), TRUE);
408         gtk_misc_set_padding(GTK_MISC(urllabel), 5, 0);
409         gtk_frame_set_label_widget(GTK_FRAME(urlframe), urllabel);
410
411         /* URL entry (+ alignment in frame) */
412         urlalign = gtk_alignment_new(0, 0.5, 1, 1);
413         gtk_alignment_set_padding(GTK_ALIGNMENT(urlalign), 5, 5, 5, 5);
414         gtk_container_add(GTK_CONTAINER(urlframe), urlalign);
415
416         inner_vbox = gtk_vbox_new(FALSE, 5);
417         gtk_box_pack_start(GTK_BOX(inner_vbox), feedprop->url, FALSE, FALSE, 0);
418         gtk_entry_set_activates_default(GTK_ENTRY(feedprop->url), TRUE);
419         gtk_container_add(GTK_CONTAINER(urlalign), inner_vbox);
420
421         /* Auth combo + user (label + entry) + pass (label + entry) */
422         auth_hbox = gtk_hbox_new(FALSE, 5);
423         gtk_box_pack_start(GTK_BOX(auth_hbox), feedprop->auth_type, FALSE, FALSE, 0);
424         g_signal_connect(G_OBJECT(feedprop->auth_type), "changed",
425                         G_CALLBACK(rssyl_feedprop_auth_type_changed_cb),
426                         (gpointer) feedprop);
427         g_signal_emit_by_name(G_OBJECT(feedprop->auth_type), "changed");
428         auth_user_label = gtk_label_new(_("User name"));
429         gtk_box_pack_start(GTK_BOX(auth_hbox), auth_user_label, FALSE, FALSE, 0);
430         gtk_box_pack_start(GTK_BOX(auth_hbox), feedprop->auth_username, FALSE, FALSE, 0);
431         auth_pass_label = gtk_label_new(_("Password"));
432         gtk_box_pack_start(GTK_BOX(auth_hbox), auth_pass_label, FALSE, FALSE, 0);
433         gtk_box_pack_start(GTK_BOX(auth_hbox), feedprop->auth_password, FALSE, FALSE, 0);
434         gtk_box_pack_start(GTK_BOX(inner_vbox), auth_hbox, FALSE, FALSE, 0);
435
436         /* Table for remaining properties */
437         table = gtk_table_new(11, 2, FALSE);
438         gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
439
440         /* Fetch comments - checkbutton */
441         gtk_table_attach(GTK_TABLE(table), feedprop->fetch_comments,
442                         0, 2, row, row+1,
443                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
444                         (GtkAttachOptions) (0), 10, 0);
445         g_signal_connect(G_OBJECT(feedprop->fetch_comments), "toggled",
446                         G_CALLBACK(rssyl_feedprop_togglebutton_toggled_cb),
447                         (gpointer)feedprop);
448
449         row++;
450         /* Fetch comments max age - label */
451         label = gtk_label_new(_("<b>Fetch comments on posts aged less than:</b>\n"
452                                 "<small>(In days; set to -1 to fetch all comments)</small>"));
453         gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
454         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
455         gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1,
456                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
457                         (GtkAttachOptions) (0), 10, 5);
458
459         /* Fetch comments max age - spinbutton */
460         gtk_widget_set_sensitive(feedprop->fetch_comments_max_age,
461                         ritem->fetch_comments);
462         gtk_table_attach(GTK_TABLE(table), feedprop->fetch_comments_max_age,
463                         1, 2, row, row+1,
464                         (GtkAttachOptions) (0),
465                         (GtkAttachOptions) (0), 10, 5);
466
467         row++;
468         /* Separator below comments max age */
469         hsep = gtk_hseparator_new();
470         gtk_widget_set_size_request(hsep, -1, 10);
471         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
472                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
473                         (GtkAttachOptions) (0), 10, 5);
474
475         row++;
476         /* Keep old items - checkbutton */
477         gtk_table_attach(GTK_TABLE(table), feedprop->keep_old,
478                         0, 1, row, row+1,
479                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
480                         (GtkAttachOptions) (0), 10, 0);
481
482         /* 'Trim' - button */
483         gtk_table_attach(GTK_TABLE(table), trim_button,
484                         1, 2, row, row+1,
485                         (GtkAttachOptions) (0),
486                         (GtkAttachOptions) (0), 10, 0);
487         g_signal_connect(G_OBJECT(trim_button), "clicked",
488                         G_CALLBACK(rssyl_props_trim_cb), ritem);
489
490         row++;
491         hsep = gtk_hseparator_new();
492         gtk_widget_set_size_request(hsep, -1, 10);
493         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
494                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
495                         (GtkAttachOptions) (0), 10, 5);
496
497         row++;
498         /* Use default refresh interval - checkbutton */
499         gtk_table_attach(GTK_TABLE(table), feedprop->default_refresh_interval,
500                         0, 2, row, row+1,
501                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
502                         (GtkAttachOptions) (0), 10, 0);
503         g_signal_connect(G_OBJECT(feedprop->default_refresh_interval), "toggled",
504                         G_CALLBACK(rssyl_feedprop_togglebutton_toggled_cb),
505                         (gpointer)feedprop);
506
507         row++;
508         /* Refresh interval - label */
509         label = gtk_label_new(_("<b>Refresh interval in minutes:</b>\n"
510                         "<small>(Set to 0 to disable automatic refreshing for this feed)"
511                         "</small>"));
512         gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
513         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
514         gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1,
515                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
516                         (GtkAttachOptions) (0), 10, 5);
517
518         /* Refresh interval - spinbutton */
519         gtk_widget_set_sensitive(feedprop->refresh_interval,
520                         !ritem->default_refresh_interval);
521         gtk_table_attach(GTK_TABLE(table), feedprop->refresh_interval, 1, 2, row, row+1,
522                         (GtkAttachOptions) (0),
523                         (GtkAttachOptions) (0), 10, 5);
524
525         row++;
526         hsep = gtk_hseparator_new();
527         gtk_widget_set_size_request(hsep, -1, 10);
528         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
529                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
530                         (GtkAttachOptions) (0), 10, 5);
531
532         row++;
533         /* Silent update - label */
534         silent_update_label =
535                 gtk_label_new(_("<b>If an item changes, do not mark it as new:</b>"));
536         gtk_label_set_use_markup(GTK_LABEL(silent_update_label), TRUE);
537         gtk_misc_set_alignment(GTK_MISC(silent_update_label), 0, 0.5);
538         gtk_table_attach(GTK_TABLE(table), silent_update_label, 0, 1, row, row+1,
539                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
540                         (GtkAttachOptions) (0), 10, 5);
541
542         gtk_table_attach(GTK_TABLE(table), feedprop->silent_update, 1, 2, row, row+1,
543                         (GtkAttachOptions) (0),
544                         (GtkAttachOptions) (0), 10, 5);
545
546         row++;
547         hsep = gtk_hseparator_new();
548         gtk_widget_set_size_request(hsep, -1, 10);
549         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
550                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
551                         (GtkAttachOptions) (0), 10, 5);
552
553         row++;
554
555         /* Write heading - checkbox */
556         gtk_table_attach(GTK_TABLE(table), feedprop->write_heading,
557                         0, 2, row, row+1,
558                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
559                         (GtkAttachOptions) (0), 10, 0);
560
561
562         row++;
563
564         /* Ignore title rename - checkbutton */
565         gtk_table_attach(GTK_TABLE(table), feedprop->ignore_title_rename,
566                         0, 1, row, row+1,
567                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
568                         (GtkAttachOptions) (0), 10, 0);
569
570         row++;
571
572         /* Verify SSL peer certificate - checkbutton */
573         gtk_table_attach(GTK_TABLE(table), feedprop->ssl_verify_peer,
574                         0, 1, row, row+1,
575                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
576                         (GtkAttachOptions) (0), 10, 0);
577
578         row++;
579
580         /* Separator above the button box */
581         sep = gtk_hseparator_new();
582         gtk_widget_set_size_request(sep, -1, 10);
583         gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
584
585         /* Buttonbox */
586         bbox = gtk_hbutton_box_new();
587         gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
588         gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
589         gtk_box_set_spacing(GTK_BOX(bbox), 5);
590         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
591
592         /* Cancel button */
593         cancel_button = gtk_button_new();
594         gtk_container_add(GTK_CONTAINER(bbox), cancel_button);
595
596         cancel_align = gtk_alignment_new(0.5, 0.5, 0, 0);
597         gtk_container_add(GTK_CONTAINER(cancel_button), cancel_align);
598
599         cancel_hbox = gtk_hbox_new(FALSE, 2);
600         gtk_container_add(GTK_CONTAINER(cancel_align), cancel_hbox);
601
602         cancel_image = gtk_image_new_from_stock(GTK_STOCK_CANCEL,
603                         GTK_ICON_SIZE_BUTTON);
604         gtk_box_pack_start(GTK_BOX(cancel_hbox), cancel_image, FALSE, FALSE, 0);
605
606         cancel_label = gtk_label_new_with_mnemonic(_("_Cancel"));
607         gtk_box_pack_end(GTK_BOX(cancel_hbox), cancel_label, FALSE, FALSE, 0);
608
609         g_signal_connect(G_OBJECT(cancel_button), "clicked",
610                         G_CALLBACK(rssyl_props_cancel_cb), ritem);
611
612         /* OK button */
613         ok_button = gtk_button_new();
614         gtk_container_add(GTK_CONTAINER(bbox), ok_button);
615         GTK_WIDGET_SET_FLAGS(ok_button, GTK_CAN_DEFAULT );
616
617         ok_align = gtk_alignment_new(0.5, 0.5, 0, 0);
618         gtk_container_add(GTK_CONTAINER(ok_button), ok_align);
619
620         ok_hbox = gtk_hbox_new(FALSE, 2);
621         gtk_container_add(GTK_CONTAINER(ok_align), ok_hbox);
622
623         ok_image = gtk_image_new_from_stock(GTK_STOCK_OK,
624                         GTK_ICON_SIZE_BUTTON);
625         gtk_box_pack_start(GTK_BOX(ok_hbox), ok_image, FALSE, FALSE, 0);
626
627         ok_label = gtk_label_new_with_mnemonic(_("_OK"));
628         gtk_box_pack_end(GTK_BOX(ok_hbox), ok_label, FALSE, FALSE, 0);
629
630         g_signal_connect(G_OBJECT(ok_button), "clicked",
631                         G_CALLBACK(rssyl_props_ok_cb), ritem);
632
633         /* Set some misc. stuff */
634         gtk_window_set_title(GTK_WINDOW(feedprop->window),
635                         g_strdup(_("Set feed properties")) );
636         gtk_window_set_modal(GTK_WINDOW(feedprop->window), TRUE);
637         gtk_window_set_transient_for(GTK_WINDOW(feedprop->window),
638                         GTK_WINDOW(mainwin->window) );
639
640         /* Attach callbacks to handle Enter and Escape keys */
641         g_signal_connect(G_OBJECT(feedprop->window), "key_press_event",
642                         G_CALLBACK(rssyl_props_key_press_cb), ritem);
643
644         /* ...and voila! */
645         gtk_widget_show_all(feedprop->window);
646         gtk_widget_grab_default(ok_button);
647
648         /* Unselect the text in URL entry */
649         gtk_editable_select_region(GTK_EDITABLE(feedprop->url), 0, 0);
650
651         ritem->feedprop = feedprop;
652 }