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>
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.
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.
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.
29 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
32 /* Claws Mail includes */
33 #include <mainwindow.h>
37 #include "rssyl_feed.h"
38 #include "rssyl_feed_props.h"
39 #include "rssyl_prefs.h"
40 #include "rssyl_update_feed.h"
42 static void rssyl_gtk_prop_store(RFolderItem *ritem)
45 gint x, old_ri, old_fetch_comments;
46 gboolean use_default_ri = FALSE, keep_old = FALSE;
49 g_return_if_fail(ritem != NULL);
50 g_return_if_fail(ritem->feedprop != NULL);
52 url = (gchar *)gtk_entry_get_text(GTK_ENTRY(ritem->feedprop->url));
58 ritem->url = g_strdup(url);
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" ) );
67 /* Use default if checkbutton is set */
69 x = rssyl_prefs_get()->refresh;
71 x = gtk_spin_button_get_value_as_int(
72 GTK_SPIN_BUTTON(ritem->feedprop->refresh_interval) );
74 old_ri = ritem->refresh_interval;
75 ritem->refresh_interval = x;
77 /* Set timer for next automatic refresh, if needed. */
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);
85 ritem->refresh_id = 0;
87 old_fetch_comments = ritem->fetch_comments;
88 ritem->fetch_comments = gtk_toggle_button_get_active(
89 GTK_TOGGLE_BUTTON(ritem->feedprop->fetch_comments));
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;
97 ritem->fetch_comments_max_age = gtk_spin_button_get_value_as_int(
98 GTK_SPIN_BUTTON(ritem->feedprop->fetch_comments_max_age));
100 keep_old = gtk_toggle_button_get_active(
101 GTK_TOGGLE_BUTTON(ritem->feedprop->keep_old));
102 ritem->keep_old = keep_old;
104 ritem->silent_update =
105 gtk_combo_box_get_active(GTK_COMBO_BOX(ritem->feedprop->silent_update));
107 ritem->write_heading = gtk_toggle_button_get_active(
108 GTK_TOGGLE_BUTTON(ritem->feedprop->write_heading));
110 ritem->ignore_title_rename = gtk_toggle_button_get_active(
111 GTK_TOGGLE_BUTTON(ritem->feedprop->ignore_title_rename));
113 ritem->ssl_verify_peer = gtk_toggle_button_get_active(
114 GTK_TOGGLE_BUTTON(ritem->feedprop->ssl_verify_peer));
116 /* Store updated properties */
118 item->folder->klass->item_get_xml(item->folder, item);
122 rssyl_feedprop_togglebutton_toggled_cb(GtkToggleButton *tb,
125 gboolean active = gtk_toggle_button_get_active(tb);
126 RFeedProp *feedprop = (RFeedProp *)data;
127 GtkWidget *sb = NULL;
129 if( (GtkWidget *)tb == feedprop->default_refresh_interval ) {
131 sb = feedprop->refresh_interval;
132 } else if( (GtkWidget *)tb == feedprop->fetch_comments ) {
133 sb = feedprop->fetch_comments_max_age;
136 g_return_val_if_fail(sb != NULL, FALSE);
138 gtk_widget_set_sensitive(sb, active);
145 rssyl_props_cancel_cb(GtkWidget *widget, gpointer data)
147 RFolderItem *ritem = (RFolderItem *)data;
149 debug_print("RSSyl: Cancel pressed\n");
151 gtk_widget_destroy(ritem->feedprop->window);
157 rssyl_props_ok_cb(GtkWidget *widget, gpointer data)
159 RFolderItem *ritem = (RFolderItem *)data;
161 debug_print("RSSyl: OK pressed\n");
162 rssyl_gtk_prop_store(ritem);
164 gtk_widget_destroy(ritem->feedprop->window);
170 rssyl_props_trim_cb(GtkWidget *widget, gpointer data)
172 RFolderItem *ritem = (RFolderItem *)data;
173 gboolean k = ritem->keep_old;
176 ritem->keep_old = FALSE;
178 rssyl_update_feed(ritem, FALSE);
181 ritem->keep_old = TRUE;
187 rssyl_props_key_press_cb(GtkWidget *widget, GdkEventKey *event,
191 switch (event->keyval) {
193 rssyl_props_cancel_cb(widget, data);
197 rssyl_props_ok_cb(widget, data);
208 void rssyl_gtk_prop(RFolderItem *ritem)
210 MainWindow *mainwin = mainwindow_get_mainwindow();
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;
217 #if !(GTK_CHECK_VERSION(2, 12, 0))
218 GtkTooltips *tooltips;
223 g_return_if_fail(ritem != NULL);
225 feedprop = g_new0(RFeedProp, 1);
227 /**** Create required widgets ****/
230 feedprop->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
232 #if !(GTK_CHECK_VERSION(2, 12, 0))
233 tooltips = gtk_tooltips_new();
234 gtk_tooltips_enable(tooltips);
238 feedprop->url = gtk_entry_new();
239 gtk_entry_set_text(GTK_ENTRY(feedprop->url), ritem->url);
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);
248 if( ritem->refresh_interval >= 0 && !ritem->default_refresh_interval )
249 refresh = ritem->refresh_interval;
251 refresh = rssyl_prefs_get()->refresh;
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),
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);
266 gtk_widget_set_tooltip_text(trim_button,
267 _("Update feed, deleting items which are no longer in the source feed"));
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);
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),
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),
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),
293 feedprop->silent_update = gtk_combo_box_text_new();
294 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
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),
300 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
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),
306 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(feedprop->silent_update),
308 _("Never mark as new"));
309 gtk_combo_box_set_active(GTK_COMBO_BOX(feedprop->silent_update),
310 ritem->silent_update);
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);
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);
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."));
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);
338 /* === Now pack all the widgets */
339 vbox = gtk_vbox_new(FALSE, 0);
340 gtk_container_add(GTK_CONTAINER(feedprop->window), vbox);
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);
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);
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);
360 gtk_entry_set_activates_default(GTK_ENTRY(feedprop->url), TRUE);
361 gtk_container_add(GTK_CONTAINER(urlalign), feedprop->url);
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);
367 /* Fetch comments - checkbutton */
368 gtk_table_attach(GTK_TABLE(table), feedprop->fetch_comments,
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),
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);
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,
391 (GtkAttachOptions) (0),
392 (GtkAttachOptions) (0), 10, 5);
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);
403 /* Keep old items - checkbutton */
404 gtk_table_attach(GTK_TABLE(table), feedprop->keep_old,
406 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
407 (GtkAttachOptions) (0), 10, 0);
409 /* 'Trim' - button */
410 gtk_table_attach(GTK_TABLE(table), trim_button,
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);
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);
425 /* Use default refresh interval - checkbutton */
426 gtk_table_attach(GTK_TABLE(table), feedprop->default_refresh_interval,
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),
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)"
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);
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);
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);
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);
469 gtk_table_attach(GTK_TABLE(table), feedprop->silent_update, 1, 2, row, row+1,
470 (GtkAttachOptions) (0),
471 (GtkAttachOptions) (0), 10, 5);
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);
482 /* Write heading - checkbox */
483 gtk_table_attach(GTK_TABLE(table), feedprop->write_heading,
485 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
486 (GtkAttachOptions) (0), 10, 0);
491 /* Ignore title rename - checkbutton */
492 gtk_table_attach(GTK_TABLE(table), feedprop->ignore_title_rename,
494 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
495 (GtkAttachOptions) (0), 10, 0);
499 /* Verify SSL peer certificate - checkbutton */
500 gtk_table_attach(GTK_TABLE(table), feedprop->ssl_verify_peer,
502 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
503 (GtkAttachOptions) (0), 10, 0);
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);
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);
520 cancel_button = gtk_button_new();
521 gtk_container_add(GTK_CONTAINER(bbox), cancel_button);
523 cancel_align = gtk_alignment_new(0.5, 0.5, 0, 0);
524 gtk_container_add(GTK_CONTAINER(cancel_button), cancel_align);
526 cancel_hbox = gtk_hbox_new(FALSE, 2);
527 gtk_container_add(GTK_CONTAINER(cancel_align), cancel_hbox);
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);
533 cancel_label = gtk_label_new_with_mnemonic(_("_Cancel"));
534 gtk_box_pack_end(GTK_BOX(cancel_hbox), cancel_label, FALSE, FALSE, 0);
536 g_signal_connect(G_OBJECT(cancel_button), "clicked",
537 G_CALLBACK(rssyl_props_cancel_cb), ritem);
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 );
544 ok_align = gtk_alignment_new(0.5, 0.5, 0, 0);
545 gtk_container_add(GTK_CONTAINER(ok_button), ok_align);
547 ok_hbox = gtk_hbox_new(FALSE, 2);
548 gtk_container_add(GTK_CONTAINER(ok_align), ok_hbox);
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);
554 ok_label = gtk_label_new_with_mnemonic(_("_OK"));
555 gtk_box_pack_end(GTK_BOX(ok_hbox), ok_label, FALSE, FALSE, 0);
557 g_signal_connect(G_OBJECT(ok_button), "clicked",
558 G_CALLBACK(rssyl_props_ok_cb), ritem);
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) );
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);
572 gtk_widget_show_all(feedprop->window);
573 gtk_widget_grab_default(ok_button);
575 /* Unselect the text in URL entry */
576 gtk_editable_select_region(GTK_EDITABLE(feedprop->url), 0, 0);
578 ritem->feedprop = feedprop;