fix building RSSyl
[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;
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         use_default_ri = gtk_toggle_button_get_active(
62                         GTK_TOGGLE_BUTTON(ritem->feedprop->default_refresh_interval));
63         ritem->default_refresh_interval = use_default_ri;
64         debug_print("store: default refresh interval is %s\n",
65                         ( use_default_ri ? "ON" : "OFF" ) );
66
67         /* Use default if checkbutton is set */
68         if( use_default_ri )
69                 x = rssyl_prefs_get()->refresh;
70         else
71                 x = gtk_spin_button_get_value_as_int(
72                                 GTK_SPIN_BUTTON(ritem->feedprop->refresh_interval) );
73
74         old_ri = ritem->refresh_interval;
75         ritem->refresh_interval = x;
76
77         /* Set timer for next automatic refresh, if needed. */
78         if( x > 0 ) {
79                 if( old_ri != x || ritem->refresh_id == 0 ) {
80                         debug_print("RSSyl: GTK - refresh interval changed to %d , updating "
81                                         "timeout\n", ritem->refresh_interval);
82                         rssyl_feed_start_refresh_timeout(ritem);
83                 }
84         } else
85                 ritem->refresh_id = 0;
86
87         old_fetch_comments = ritem->fetch_comments;
88         ritem->fetch_comments = gtk_toggle_button_get_active(
89                         GTK_TOGGLE_BUTTON(ritem->feedprop->fetch_comments));
90
91         if (!old_fetch_comments && ritem->fetch_comments) {
92                 /* reset the RFolderItem's mtime to be sure we get all 
93                  * available comments */
94                  ritem->item.mtime = 0;
95         }
96         
97         ritem->fetch_comments_max_age = gtk_spin_button_get_value_as_int(
98                         GTK_SPIN_BUTTON(ritem->feedprop->fetch_comments_max_age));
99
100         keep_old = gtk_toggle_button_get_active(
101                         GTK_TOGGLE_BUTTON(ritem->feedprop->keep_old));
102         ritem->keep_old = keep_old;
103
104         ritem->silent_update =
105                 gtk_combo_box_get_active(GTK_COMBO_BOX(ritem->feedprop->silent_update));
106
107         ritem->write_heading = gtk_toggle_button_get_active(
108                         GTK_TOGGLE_BUTTON(ritem->feedprop->write_heading));
109
110         ritem->ignore_title_rename = gtk_toggle_button_get_active(
111                         GTK_TOGGLE_BUTTON(ritem->feedprop->ignore_title_rename));
112
113         ritem->ssl_verify_peer = gtk_toggle_button_get_active(
114                         GTK_TOGGLE_BUTTON(ritem->feedprop->ssl_verify_peer));
115
116         /* Store updated properties */
117         item = &ritem->item;
118         item->folder->klass->item_get_xml(item->folder, item);
119 }
120
121 static gboolean
122 rssyl_feedprop_togglebutton_toggled_cb(GtkToggleButton *tb,
123                 gpointer data)
124 {
125         gboolean active = gtk_toggle_button_get_active(tb);
126         RFeedProp *feedprop = (RFeedProp *)data;
127         GtkWidget *sb = NULL;
128
129         if( (GtkWidget *)tb == feedprop->default_refresh_interval ) {
130                 active = !active;
131                 sb = feedprop->refresh_interval;
132         } else if( (GtkWidget *)tb == feedprop->fetch_comments ) {
133                 sb = feedprop->fetch_comments_max_age;
134         }
135
136         g_return_val_if_fail(sb != NULL, FALSE);
137
138         gtk_widget_set_sensitive(sb, active);
139
140         return FALSE;
141 }
142
143
144 static gboolean
145 rssyl_props_cancel_cb(GtkWidget *widget, gpointer data)
146 {
147         RFolderItem *ritem = (RFolderItem *)data;
148
149         debug_print("RSSyl: Cancel pressed\n");
150
151         gtk_widget_destroy(ritem->feedprop->window);
152
153         return FALSE;
154 }
155
156 static gboolean
157 rssyl_props_ok_cb(GtkWidget *widget, gpointer data)
158 {
159         RFolderItem *ritem = (RFolderItem *)data;
160
161         debug_print("RSSyl: OK pressed\n");
162         rssyl_gtk_prop_store(ritem);
163
164         gtk_widget_destroy(ritem->feedprop->window);
165
166         return FALSE;
167 }
168
169 static gboolean
170 rssyl_props_trim_cb(GtkWidget *widget, gpointer data)
171 {
172         RFolderItem *ritem = (RFolderItem *)data;
173         gboolean k = ritem->keep_old;
174
175         if( k )
176                 ritem->keep_old = FALSE;
177
178         rssyl_update_feed(ritem, FALSE);
179
180         if( k )
181                 ritem->keep_old = TRUE;
182
183         return FALSE;
184 }
185
186 static gboolean
187 rssyl_props_key_press_cb(GtkWidget *widget, GdkEventKey *event,
188                 gpointer data)
189 {
190         if (event) {
191                 switch (event->keyval) {
192                         case GDK_Escape:
193                                 rssyl_props_cancel_cb(widget, data);
194                                 return TRUE;
195                         case GDK_Return:
196                         case GDK_KP_Enter:
197                                 rssyl_props_ok_cb(widget, data);
198                                 return TRUE;
199                         default:
200                                 break;
201                 }
202         }
203
204         return FALSE;
205 }
206
207
208 void rssyl_gtk_prop(RFolderItem *ritem)
209 {
210         MainWindow *mainwin = mainwindow_get_mainwindow();
211         RFeedProp *feedprop;
212         GtkWidget *vbox, *urllabel, *urlframe, *urlalign, *table, *label,
213                                                 *hsep, *sep, *bbox, *cancel_button, *cancel_align,
214                                                 *cancel_hbox, *cancel_image, *cancel_label, *ok_button, *ok_align,
215                                                 *ok_hbox, *ok_image, *ok_label, *trim_button, *silent_update_label;
216         GtkObject *adj;
217 #if !(GTK_CHECK_VERSION(2, 12, 0))
218         GtkTooltips *tooltips;
219 #endif
220         gint refresh;
221         gint row = 0;
222
223         g_return_if_fail(ritem != NULL);
224
225         feedprop = g_new0(RFeedProp, 1);
226
227         /**** Create required widgets ****/
228
229         /* Window */
230         feedprop->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
231
232 #if !(GTK_CHECK_VERSION(2, 12, 0))
233         tooltips = gtk_tooltips_new();
234         gtk_tooltips_enable(tooltips);
235 #endif
236
237         /* URL entry */
238         feedprop->url = gtk_entry_new();
239         gtk_entry_set_text(GTK_ENTRY(feedprop->url), ritem->url);
240
241         /* "Use default refresh interval" checkbutton */
242         feedprop->default_refresh_interval = gtk_check_button_new_with_mnemonic(
243                         _("Use default refresh interval"));
244         gtk_toggle_button_set_active(
245                         GTK_TOGGLE_BUTTON(feedprop->default_refresh_interval),
246                         ritem->default_refresh_interval);
247
248         if( ritem->refresh_interval >= 0 && !ritem->default_refresh_interval )
249                 refresh = ritem->refresh_interval;
250         else
251                 refresh = rssyl_prefs_get()->refresh;
252
253         /* "Keep old items" checkbutton */
254         feedprop->keep_old = gtk_check_button_new_with_mnemonic(
255                         _("Keep old items"));
256         gtk_toggle_button_set_active(
257                         GTK_TOGGLE_BUTTON(feedprop->keep_old),
258                         ritem->keep_old);
259
260         /* "Trim" button */
261         trim_button = gtk_button_new_with_mnemonic(_("_Trim"));
262 #if !(GTK_CHECK_VERSION(2, 12, 0))
263         gtk_tooltips_set_tip(tooltips, trim_button,
264                         _("Update feed, deleting items which are no longer in the source feed"), NULL);
265 #else
266         gtk_widget_set_tooltip_text(trim_button,
267                         _("Update feed, deleting items which are no longer in the source feed"));
268 #endif
269
270         feedprop->fetch_comments = gtk_check_button_new_with_mnemonic(
271                         _("Fetch comments if possible"));
272         gtk_toggle_button_set_active(
273                         GTK_TOGGLE_BUTTON(feedprop->fetch_comments),
274                         ritem->fetch_comments);
275
276         /* Fetch comments max age spinbutton */
277         adj = gtk_adjustment_new(ritem->fetch_comments_max_age,
278                         -1, 100000, 1, 10, 0);
279         feedprop->fetch_comments_max_age = gtk_spin_button_new(GTK_ADJUSTMENT(adj),
280                         1, 0);
281
282         /* Refresh interval spinbutton */
283         adj = gtk_adjustment_new(refresh,
284                         0, 100000, 10, 100, 0);
285         feedprop->refresh_interval = gtk_spin_button_new(GTK_ADJUSTMENT(adj),
286                         1, 0);
287
288         /* Silent update - combobox */
289 #if !GTK_CHECK_VERSION(2, 24, 0)
290         feedprop->silent_update = gtk_combo_box_new_text();
291         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
292 #else
293         feedprop->silent_update = gtk_combo_box_text_new();
294         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
295 #endif
296                         _("Always mark as new"));
297 #if !GTK_CHECK_VERSION(2, 24, 0)
298         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
299 #else
300         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
301 #endif
302                         _("If only its text changed"));
303 #if !GTK_CHECK_VERSION(2, 24, 0)
304         gtk_combo_box_append_text(GTK_COMBO_BOX(feedprop->silent_update),
305 #else
306         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
307 #endif
308                         _("Never mark as new"));
309         gtk_combo_box_set_active(GTK_COMBO_BOX(feedprop->silent_update),
310                         ritem->silent_update);
311
312         feedprop->write_heading = gtk_check_button_new_with_mnemonic(
313                         _("Add item title to top of message"));
314         gtk_toggle_button_set_active(
315                         GTK_TOGGLE_BUTTON(feedprop->write_heading),
316                         ritem->write_heading);
317
318         /* Ignore title rename - checkbox */
319         feedprop->ignore_title_rename = gtk_check_button_new_with_mnemonic(
320                         _("Ignore title rename"));
321         gtk_toggle_button_set_active(
322                         GTK_TOGGLE_BUTTON(feedprop->ignore_title_rename),
323                         ritem->ignore_title_rename);
324 #if !(GTK_CHECK_VERSION(2, 12, 0))
325         gtk_tooltips_set_tip(tooltips, feedprop->ignore_title_rename,
326                         _("Enable this to keep current folder name, even if feed author changes title of the feed."), NULL);
327 #else
328         gtk_widget_set_tooltip_text(feedprop->ignore_title_rename,
329                         _("Enable this to keep current folder name, even if feed author changes title of the feed."));
330 #endif
331
332         /* Verify SSL peer certificate */
333         feedprop->ssl_verify_peer = gtk_check_button_new_with_label(
334                         _("Verify SSL certificate validity"));
335         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(feedprop->ssl_verify_peer),
336                         ritem->ssl_verify_peer);
337
338         /* === Now pack all the widgets */
339         vbox = gtk_vbox_new(FALSE, 0);
340         gtk_container_add(GTK_CONTAINER(feedprop->window), vbox);
341
342         /* URL frame */
343         urlframe = gtk_frame_new(NULL);
344         gtk_container_set_border_width(GTK_CONTAINER(urlframe), 5);
345         gtk_frame_set_label_align(GTK_FRAME(urlframe), 0.05, 0.5);
346         gtk_frame_set_shadow_type(GTK_FRAME(urlframe), GTK_SHADOW_ETCHED_OUT);
347         gtk_box_pack_start(GTK_BOX(vbox), urlframe, FALSE, FALSE, 0);
348
349         /* Label for URL frame */
350         urllabel = gtk_label_new(_("<b>Source URL:</b>"));
351         gtk_label_set_use_markup(GTK_LABEL(urllabel), TRUE);
352         gtk_misc_set_padding(GTK_MISC(urllabel), 5, 0);
353         gtk_frame_set_label_widget(GTK_FRAME(urlframe), urllabel);
354
355         /* URL entry (+ alignment in frame) */
356         urlalign = gtk_alignment_new(0, 0.5, 1, 1);
357         gtk_alignment_set_padding(GTK_ALIGNMENT(urlalign), 5, 5, 5, 5);
358         gtk_container_add(GTK_CONTAINER(urlframe), urlalign);
359
360         gtk_entry_set_activates_default(GTK_ENTRY(feedprop->url), TRUE);
361         gtk_container_add(GTK_CONTAINER(urlalign), feedprop->url);
362
363         /* Table for remaining properties */
364         table = gtk_table_new(11, 2, FALSE);
365         gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
366
367         /* Fetch comments - checkbutton */
368         gtk_table_attach(GTK_TABLE(table), feedprop->fetch_comments,
369                         0, 2, row, row+1,
370                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
371                         (GtkAttachOptions) (0), 10, 0);
372         g_signal_connect(G_OBJECT(feedprop->fetch_comments), "toggled",
373                         G_CALLBACK(rssyl_feedprop_togglebutton_toggled_cb),
374                         (gpointer)feedprop);
375
376         row++;
377         /* Fetch comments max age - label */
378         label = gtk_label_new(_("<b>Fetch comments on posts aged less than:</b>\n"
379                                 "<small>(In days; set to -1 to fetch all comments)</small>"));
380         gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
381         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
382         gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1,
383                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
384                         (GtkAttachOptions) (0), 10, 5);
385
386         /* Fetch comments max age - spinbutton */
387         gtk_widget_set_sensitive(feedprop->fetch_comments_max_age,
388                         ritem->fetch_comments);
389         gtk_table_attach(GTK_TABLE(table), feedprop->fetch_comments_max_age,
390                         1, 2, row, row+1,
391                         (GtkAttachOptions) (0),
392                         (GtkAttachOptions) (0), 10, 5);
393
394         row++;
395         /* Separator below comments max age */
396         hsep = gtk_hseparator_new();
397         gtk_widget_set_size_request(hsep, -1, 10);
398         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
399                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
400                         (GtkAttachOptions) (0), 10, 5);
401
402         row++;
403         /* Keep old items - checkbutton */
404         gtk_table_attach(GTK_TABLE(table), feedprop->keep_old,
405                         0, 1, row, row+1,
406                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
407                         (GtkAttachOptions) (0), 10, 0);
408
409         /* 'Trim' - button */
410         gtk_table_attach(GTK_TABLE(table), trim_button,
411                         1, 2, row, row+1,
412                         (GtkAttachOptions) (0),
413                         (GtkAttachOptions) (0), 10, 0);
414         g_signal_connect(G_OBJECT(trim_button), "clicked",
415                         G_CALLBACK(rssyl_props_trim_cb), ritem);
416
417         row++;
418         hsep = gtk_hseparator_new();
419         gtk_widget_set_size_request(hsep, -1, 10);
420         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
421                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
422                         (GtkAttachOptions) (0), 10, 5);
423
424         row++;
425         /* Use default refresh interval - checkbutton */
426         gtk_table_attach(GTK_TABLE(table), feedprop->default_refresh_interval,
427                         0, 2, row, row+1,
428                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
429                         (GtkAttachOptions) (0), 10, 0);
430         g_signal_connect(G_OBJECT(feedprop->default_refresh_interval), "toggled",
431                         G_CALLBACK(rssyl_feedprop_togglebutton_toggled_cb),
432                         (gpointer)feedprop);
433
434         row++;
435         /* Refresh interval - label */
436         label = gtk_label_new(_("<b>Refresh interval in minutes:</b>\n"
437                         "<small>(Set to 0 to disable automatic refreshing for this feed)"
438                         "</small>"));
439         gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
440         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
441         gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1,
442                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
443                         (GtkAttachOptions) (0), 10, 5);
444
445         /* Refresh interval - spinbutton */
446         gtk_widget_set_sensitive(feedprop->refresh_interval,
447                         !ritem->default_refresh_interval);
448         gtk_table_attach(GTK_TABLE(table), feedprop->refresh_interval, 1, 2, row, row+1,
449                         (GtkAttachOptions) (0),
450                         (GtkAttachOptions) (0), 10, 5);
451
452         row++;
453         hsep = gtk_hseparator_new();
454         gtk_widget_set_size_request(hsep, -1, 10);
455         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
456                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
457                         (GtkAttachOptions) (0), 10, 5);
458
459         row++;
460         /* Silent update - label */
461         silent_update_label =
462                 gtk_label_new(_("<b>If an item changes, do not mark it as new:</b>"));
463         gtk_label_set_use_markup(GTK_LABEL(silent_update_label), TRUE);
464         gtk_misc_set_alignment(GTK_MISC(silent_update_label), 0, 0.5);
465         gtk_table_attach(GTK_TABLE(table), silent_update_label, 0, 1, row, row+1,
466                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
467                         (GtkAttachOptions) (0), 10, 5);
468
469         gtk_table_attach(GTK_TABLE(table), feedprop->silent_update, 1, 2, row, row+1,
470                         (GtkAttachOptions) (0),
471                         (GtkAttachOptions) (0), 10, 5);
472
473         row++;
474         hsep = gtk_hseparator_new();
475         gtk_widget_set_size_request(hsep, -1, 10);
476         gtk_table_attach(GTK_TABLE(table), hsep, 0, 2, row, row+1,
477                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
478                         (GtkAttachOptions) (0), 10, 5);
479
480         row++;
481
482         /* Write heading - checkbox */
483         gtk_table_attach(GTK_TABLE(table), feedprop->write_heading,
484                         0, 2, row, row+1,
485                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
486                         (GtkAttachOptions) (0), 10, 0);
487
488
489         row++;
490
491         /* Ignore title rename - checkbutton */
492         gtk_table_attach(GTK_TABLE(table), feedprop->ignore_title_rename,
493                         0, 1, row, row+1,
494                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
495                         (GtkAttachOptions) (0), 10, 0);
496
497         row++;
498
499         /* Verify SSL peer certificate - checkbutton */
500         gtk_table_attach(GTK_TABLE(table), feedprop->ssl_verify_peer,
501                         0, 1, row, row+1,
502                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
503                         (GtkAttachOptions) (0), 10, 0);
504
505         row++;
506
507         /* Separator above the button box */
508         sep = gtk_hseparator_new();
509         gtk_widget_set_size_request(sep, -1, 10);
510         gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
511
512         /* Buttonbox */
513         bbox = gtk_hbutton_box_new();
514         gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
515         gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
516         gtk_box_set_spacing(GTK_BOX(bbox), 5);
517         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
518
519         /* Cancel button */
520         cancel_button = gtk_button_new();
521         gtk_container_add(GTK_CONTAINER(bbox), cancel_button);
522
523         cancel_align = gtk_alignment_new(0.5, 0.5, 0, 0);
524         gtk_container_add(GTK_CONTAINER(cancel_button), cancel_align);
525
526         cancel_hbox = gtk_hbox_new(FALSE, 2);
527         gtk_container_add(GTK_CONTAINER(cancel_align), cancel_hbox);
528
529         cancel_image = gtk_image_new_from_stock(GTK_STOCK_CANCEL,
530                         GTK_ICON_SIZE_BUTTON);
531         gtk_box_pack_start(GTK_BOX(cancel_hbox), cancel_image, FALSE, FALSE, 0);
532
533         cancel_label = gtk_label_new_with_mnemonic(_("_Cancel"));
534         gtk_box_pack_end(GTK_BOX(cancel_hbox), cancel_label, FALSE, FALSE, 0);
535
536         g_signal_connect(G_OBJECT(cancel_button), "clicked",
537                         G_CALLBACK(rssyl_props_cancel_cb), ritem);
538
539         /* OK button */
540         ok_button = gtk_button_new();
541         gtk_container_add(GTK_CONTAINER(bbox), ok_button);
542         GTK_WIDGET_SET_FLAGS(ok_button, GTK_CAN_DEFAULT );
543
544         ok_align = gtk_alignment_new(0.5, 0.5, 0, 0);
545         gtk_container_add(GTK_CONTAINER(ok_button), ok_align);
546
547         ok_hbox = gtk_hbox_new(FALSE, 2);
548         gtk_container_add(GTK_CONTAINER(ok_align), ok_hbox);
549
550         ok_image = gtk_image_new_from_stock(GTK_STOCK_OK,
551                         GTK_ICON_SIZE_BUTTON);
552         gtk_box_pack_start(GTK_BOX(ok_hbox), ok_image, FALSE, FALSE, 0);
553
554         ok_label = gtk_label_new_with_mnemonic(_("_OK"));
555         gtk_box_pack_end(GTK_BOX(ok_hbox), ok_label, FALSE, FALSE, 0);
556
557         g_signal_connect(G_OBJECT(ok_button), "clicked",
558                         G_CALLBACK(rssyl_props_ok_cb), ritem);
559
560         /* Set some misc. stuff */
561         gtk_window_set_title(GTK_WINDOW(feedprop->window),
562                         g_strdup(_("Set feed properties")) );
563         gtk_window_set_modal(GTK_WINDOW(feedprop->window), TRUE);
564         gtk_window_set_transient_for(GTK_WINDOW(feedprop->window),
565                         GTK_WINDOW(mainwin->window) );
566
567         /* Attach callbacks to handle Enter and Escape keys */
568         g_signal_connect(G_OBJECT(feedprop->window), "key_press_event",
569                         G_CALLBACK(rssyl_props_key_press_cb), ritem);
570
571         /* ...and voila! */
572         gtk_widget_show_all(feedprop->window);
573         gtk_widget_grab_default(ok_button);
574
575         /* Unselect the text in URL entry */
576         gtk_editable_select_region(GTK_EDITABLE(feedprop->url), 0, 0);
577
578         ritem->feedprop = feedprop;
579 }