2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2023 the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 #include <glib/gi18n.h>
39 #include "prefs_common.h"
40 #include "prefs_gtk.h"
42 #include "gtk/gtkutils.h"
43 #include "gtk/prefswindow.h"
44 #include "gtk/filesel.h"
45 #include "gtk/manage_window.h"
47 #include "stock_pixmap.h"
48 #include "mainwindow.h"
50 #include "alertpanel.h"
51 #include "addr_compl.h"
52 #include "file-utils.h"
54 #define IS_CURRENT_THEME(path) (strcmp(prefs_common.pixmap_theme_path, path) == 0)
55 #define IS_INTERNAL_THEME(path) (strcmp(DEFAULT_PIXMAP_THEME, path) == 0)
56 #define IS_SYSTEM_THEME(path) (prefs_themes_is_system_theme(path))
58 #define PREVIEW_ICONS 7
60 typedef struct _ThemesPage
64 GtkWidget
*window
; /* do not modify */
67 GtkWidget
*btn_install
;
76 GtkWidget
*icons
[PREVIEW_ICONS
];
78 GtkWidget
*btn_remove
;
80 GdkPixbuf
*pixbufs
[PREVIEW_ICONS
];
83 GtkWidget
*checkbtn_enable_alpha
;
84 GtkWidget
*checkbtn_enable_scaling
;
85 GtkWidget
*checkbtn_scaling_auto
;
86 GtkWidget
*label_scaling_ppi
;
87 GtkWidget
*spinbtn_scaling_ppi
;
91 typedef struct _ThemeInfo
99 typedef struct _ThemeName
105 typedef struct _ThemesData
113 typedef void (*FileFunc
) (const gchar
*filename
, gpointer data
);
115 typedef struct _DirInfo
{
119 /* extensions info */
120 const char **supported
;
124 typedef struct _CopyInfo
{
129 static ThemesData
*prefs_themes_data
;
131 StockPixmap prefs_themes_icons
[PREVIEW_ICONS
] = {
132 STOCK_PIXMAP_DIR_CLOSE
,
133 STOCK_PIXMAP_MAIL_SEND
,
134 STOCK_PIXMAP_MAIL_RECEIVE
,
135 STOCK_PIXMAP_MAIL_ATTACH
,
137 STOCK_PIXMAP_MIME_TEXT_PLAIN
,
143 static void prefs_themes_btn_remove_clicked_cb (GtkWidget
*widget
, gpointer data
);
144 static void prefs_themes_btn_install_clicked_cb (GtkWidget
*widget
, gpointer data
);
145 static void prefs_themes_btn_viewall_clicked_cb (GtkWidget
*widget
, gpointer data
);
146 static void prefs_themes_viewall_close_btn_clicked (GtkWidget
*widget
, gpointer data
);
147 static gboolean
prefs_themes_viewall_key_pressed (GtkWidget
*keywidget
, GdkEventKey
*event
, GtkWidget
**widget
);
148 static void prefs_themes_menu_item_activated_cb (GtkWidget
*widget
, gpointer data
);
150 static gdouble
prefs_themes_compute_ppi(GdkScreen
*screen
);
151 static gdouble
prefs_themes_get_adjusted_ppi(void);
152 static void prefs_themes_checkbtn_enable_scaling_toggled_cb (GtkWidget
*widget
, gpointer data
);
153 static void prefs_themes_checkbtn_scaling_auto_toggled_cb (GtkWidget
*widget
, gpointer data
);
156 static void prefs_themes_update_buttons (const ThemesData
*tdata
);
157 static void prefs_themes_display_global_stats (const ThemesData
*tdata
);
158 static void prefs_themes_get_theme_info (ThemesData
*tdata
);
159 static void prefs_themes_display_theme_info (ThemesData
*tdata
, const ThemeInfo
*info
);
160 static void prefs_themes_get_themes_and_names (ThemesData
*tdata
);
161 static int prefs_themes_cmp_name(gconstpointer a
, gconstpointer b
);
162 static void prefs_themes_free_names (ThemesData
*tdata
);
164 static void prefs_themes_set_themes_menu (GtkComboBox
*combo
, const ThemesData
*tdata
);
166 static gchar
*prefs_themes_get_theme_stats (const gchar
*dirname
);
167 static gboolean
prefs_themes_is_system_theme (const gchar
*dirname
);
169 static void prefs_themes_create_widget (PrefsPage
*page
, GtkWindow
*window
, gpointer data
);
170 static void prefs_themes_destroy_widget (PrefsPage
*page
);
171 static void prefs_themes_save (PrefsPage
*page
);
173 static void prefs_themes_foreach_file (const gchar
*dirname
, const FileFunc func
, gpointer data
);
174 static void prefs_themes_file_stats (const gchar
*filename
, gpointer data
);
175 static void prefs_themes_file_remove (const gchar
*filename
, gpointer data
);
176 static void prefs_themes_file_install (const gchar
*filename
, gpointer data
);
180 static void prefs_themes_file_stats(const gchar
*filename
, gpointer data
)
185 GError
*error
= NULL
;
190 DirInfo
*di
= (DirInfo
*)data
;
195 f
= g_file_new_for_path(filename
);
196 fi
= g_file_query_info(f
, "standard::size,standard::type",
197 G_FILE_QUERY_INFO_NONE
, NULL
, &error
);
199 g_warning(error
->message
);
204 if (g_file_info_get_file_type(fi
) != G_FILE_TYPE_REGULAR
) {
209 size
= g_file_info_get_size(fi
);
213 if ((i
= g_stat(filename
, &s
)) != 0) {
214 debug_print("g_stat on '%s' failed: %d\n", filename
, i
);
217 if (!S_ISREG(s
.st_mode
)) {
225 len
= strlen(filename
);
226 for (i
= 0; (di
->supported
)[i
] != NULL
; ++i
) {
227 gint curlen
= (di
->length
)[i
];
230 const gchar
*extension
= filename
+ (len
- curlen
);
231 if (!strcmp(extension
, (di
->supported
)[i
])) {
238 static void prefs_themes_file_remove(const gchar
*filename
, gpointer data
)
240 gchar
**status
= (gchar
**)data
;
243 if ((*status
) != NULL
)
246 base
= g_path_get_basename(filename
);
247 if (TRUE
== is_dir_exist(filename
)) {
248 if (strcmp(base
, ".") != 0 && strcmp(base
, "..") != 0)
249 g_warning("prefs_themes_file_remove(): subdir in theme dir skipped: '%s'",
252 else if (0 != claws_unlink(filename
)) {
253 (*status
) = g_strdup(filename
);
258 static void prefs_themes_file_install(const gchar
*filename
, gpointer data
)
260 CopyInfo
*ci
= (CopyInfo
*)data
;
263 if (ci
->status
!= NULL
)
266 base
= g_path_get_basename(filename
);
267 if (TRUE
== is_dir_exist(filename
)) {
268 if (strcmp(base
, ".") != 0 && strcmp(base
, "..") !=0 )
269 g_warning("prefs_themes_file_install(): subdir in theme dir skipped: '%s'",
275 fulldest
= g_strconcat(ci
->dest
, G_DIR_SEPARATOR_S
, base
, NULL
);
277 if (0 != copy_file(filename
, fulldest
, FALSE
)) {
278 ci
->status
= g_strdup(filename
);
285 static void prefs_themes_foreach_file(const gchar
*dirname
, const FileFunc func
, gpointer data
)
290 GError
*error
= NULL
;
292 cm_return_if_fail(dirname
!= NULL
);
293 cm_return_if_fail(func
!= NULL
);
295 if ((dp
= g_dir_open(dirname
, 0, &error
)) == NULL
) {
296 debug_print("couldn't open dir '%s': %s (%d)\n", dirname
,
297 error
->message
, error
->code
);
302 while ((entry
= g_dir_read_name(dp
)) != NULL
) {
304 fullentry
= g_strconcat(dirname
, G_DIR_SEPARATOR_S
, entry
, NULL
);
306 (*func
)(fullentry
, data
);
313 static gboolean
prefs_themes_is_system_theme(const gchar
*dirname
)
316 gchar
*system_theme_dir
;
317 gboolean is_sys
= FALSE
;
319 cm_return_val_if_fail(dirname
!= NULL
, FALSE
);
321 system_theme_dir
= stock_pixmap_get_system_theme_dir_for_theme(NULL
);
322 len
= strlen(system_theme_dir
);
323 if (strlen(dirname
) > len
&& 0 == strncmp(dirname
, system_theme_dir
, len
))
326 g_free(system_theme_dir
);
331 static void prefs_themes_set_themes_menu(GtkComboBox
*combo
, const ThemesData
*tdata
)
335 GList
*themes
= tdata
->names
;
336 gint i
= 0, active
= 0;
337 GList
*sorted_list
= NULL
;
339 cm_return_if_fail(combo
!= NULL
);
341 /* sort theme data list by data name */
342 while (themes
!= NULL
) {
343 ThemeName
*tname
= (ThemeName
*)(themes
->data
);
345 sorted_list
= g_list_insert_sorted(sorted_list
, (gpointer
)(tname
),
346 (GCompareFunc
)prefs_themes_cmp_name
);
348 themes
= g_list_next(themes
);
351 store
= gtk_list_store_new(2, G_TYPE_STRING
, G_TYPE_POINTER
);
353 /* feed gtk_menu w/ sorted themes names */
354 themes
= sorted_list
;
355 while (themes
!= NULL
) {
356 ThemeName
*tname
= (ThemeName
*)(themes
->data
);
357 gchar
*tpath
= (gchar
*)(tname
->item
->data
);
359 gtk_list_store_append(store
, &iter
);
360 gtk_list_store_set(store
, &iter
,
362 1, tname
->item
->data
, -1);
364 if (tdata
->displayed
!= NULL
&& !g_strcmp0(tdata
->displayed
,tpath
))
368 themes
= g_list_next(themes
);
371 g_list_free(sorted_list
);
373 g_signal_connect(G_OBJECT(combo
), "changed",
374 G_CALLBACK(prefs_themes_menu_item_activated_cb
),
377 gtk_combo_box_set_model(combo
, GTK_TREE_MODEL(store
));
378 gtk_combo_box_set_active(combo
, active
);
381 static int prefs_themes_cmp_name(gconstpointer a_p
, gconstpointer b_p
)
383 /* compare two ThemeData structures by their name attribute */
384 return g_strcmp0((gchar
*)(((ThemeName
*)a_p
)->name
),
385 (gchar
*)(((ThemeName
*)b_p
)->name
));
388 static void prefs_themes_get_themes_and_names(ThemesData
*tdata
)
392 cm_return_if_fail(tdata
!= NULL
);
394 stock_pixmap_themes_list_free(tdata
->themes
);
395 prefs_themes_free_names(tdata
);
397 tdata
->themes
= stock_pixmap_themes_list_new();
399 tpaths
= tdata
->themes
;
400 while (tpaths
!= NULL
) {
401 ThemeName
*name
= g_new0(ThemeName
, 1);
402 gchar
*sname
= g_path_get_basename((const gchar
*)(tpaths
->data
));
404 if (IS_INTERNAL_THEME(sname
))
405 name
->name
= g_strdup(_("Default internal theme"));
407 name
->name
= g_strdup(sname
);
410 tdata
->names
= g_list_append(tdata
->names
, name
);
411 if (!g_strcmp0(tpaths
->data
, prefs_common
.pixmap_theme_path
)) {
412 tdata
->displayed
= (gchar
*)tpaths
->data
;
414 tpaths
= g_list_next(tpaths
);
419 void prefs_themes_init(void)
424 static gchar
*path
[3];
426 path
[0] = _("Display");
427 path
[1] = _("Themes");
430 debug_print("Creating preferences for themes...\n");
432 tdata
= g_new0(ThemesData
, 1);
433 prefs_themes_data
= tdata
;
435 prefs_themes_get_themes_and_names(tdata
);
437 page
= g_new0(ThemesPage
, 1);
439 page
->page
.path
= path
;
440 page
->page
.create_widget
= prefs_themes_create_widget
;
441 page
->page
.destroy_widget
= prefs_themes_destroy_widget
;
442 page
->page
.save_page
= prefs_themes_save
;
443 page
->page
.weight
= 130.0;
444 prefs_gtk_register_page((PrefsPage
*) page
);
448 tpaths
= g_list_first(tdata
->themes
);
449 if (tdata
->displayed
== NULL
)
450 tdata
->displayed
= (gchar
*)(tpaths
->data
);
452 if (prefs_common
.pixmap_scaling_auto
)
453 prefs_common
.pixmap_scaling_ppi
= prefs_themes_get_adjusted_ppi();
457 static void prefs_themes_free_names(ThemesData
*tdata
)
461 cm_return_if_fail(tdata
!= NULL
);
463 if (tdata
->names
== NULL
)
466 names
= tdata
->names
;
467 while (names
!= NULL
) {
468 ThemeName
*tn
= (ThemeName
*)(names
->data
);
474 names
= g_list_next(names
);
476 g_list_free(tdata
->names
);
480 void prefs_themes_done(void)
482 ThemesData
*tdata
= prefs_themes_data
;
484 debug_print("Finished preferences for themes.\n");
486 stock_pixmap_themes_list_free(tdata
->themes
);
487 prefs_themes_free_names(tdata
);
492 static void prefs_themes_btn_remove_clicked_cb(GtkWidget
*widget
, gpointer data
)
494 ThemesData
*tdata
= prefs_themes_data
;
496 gchar
*alert_title
= NULL
;
500 theme_str
= tdata
->displayed
;
502 tmp
= g_path_get_basename(theme_str
);
503 alert_title
= g_strdup_printf(_("Remove theme '%s'"), tmp
);
506 val
= alertpanel(alert_title
,
507 _("Are you sure you want to remove this theme?"),
508 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_FIRST
);
511 if (G_ALERTALTERNATE
== val
) {
512 gchar
*status
= NULL
;
514 prefs_themes_foreach_file(theme_str
, prefs_themes_file_remove
, &status
);
515 if (0 != rmdir(theme_str
)) {
516 if (status
!= NULL
) {
517 alertpanel_error(_("File %s failed\nwhile removing theme."), status
);
521 alertpanel_error(_("Removing theme directory failed."));
524 alertpanel_notice(_("Theme removed successfully"));
525 /* update interface back to first theme */
526 prefs_themes_get_themes_and_names(tdata
);
527 prefs_themes_set_themes_menu(GTK_COMBO_BOX(tdata
->page
->op_menu
), tdata
);
528 prefs_themes_display_global_stats(tdata
);
529 tdata
->displayed
= (gchar
*)((g_list_first(tdata
->themes
))->data
);
530 prefs_themes_get_theme_info(tdata
);
535 static void prefs_themes_btn_install_clicked_cb(GtkWidget
*widget
, gpointer data
)
537 gchar
*filename
, *source
;
538 gchar
*themeinfo
, *themename
;
539 gchar
*alert_title
= NULL
;
542 ThemesData
*tdata
= prefs_themes_data
;
544 filename
= filesel_select_file_open_folder(_("Select theme folder"), NULL
);
545 if (filename
== NULL
)
548 if (filename
[strlen(filename
) - 1] != G_DIR_SEPARATOR
)
549 filename
= g_strconcat(filename
, G_DIR_SEPARATOR_S
, NULL
);
551 filename
= g_strdup(filename
);
553 cinfo
= g_new0(CopyInfo
, 1);
554 source
= g_path_get_dirname(filename
);
555 themename
= g_path_get_basename(source
);
556 debug_print("Installing '%s' theme from %s\n", themename
, filename
);
558 themeinfo
= g_strconcat(source
, G_DIR_SEPARATOR_S
, THEMEINFO_FILE
, NULL
);
559 alert_title
= g_strdup_printf(_("Install theme '%s'"), themename
);
560 if (file_exist(themeinfo
, FALSE
) == FALSE
) {
561 val
= alertpanel(alert_title
,
562 _("This folder doesn't seem to be a theme"
563 "folder.\nInstall anyway?"),
564 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_FIRST
);
565 if (G_ALERTALTERNATE
!= val
)
569 cinfo
->dest
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
570 PIXMAP_THEME_DIR
, G_DIR_SEPARATOR_S
,
572 if (TRUE
== is_dir_exist(cinfo
->dest
)) {
573 AlertValue val
= alertpanel_full(_("Theme exists"),
574 _("A theme with the same name is\n"
575 "already installed in this location.\n\n"
576 "Do you want to replace it?"),
577 NULL
, _("_Cancel"), NULL
, _("Overwrite"), NULL
, NULL
,
578 ALERTFOCUS_FIRST
, FALSE
, NULL
, ALERT_WARNING
);
579 if (val
== G_ALERTALTERNATE
) {
580 if (remove_dir_recursive(cinfo
->dest
) < 0) {
581 alertpanel_error(_("Couldn't delete the old theme in %s."),
589 if (0 != make_dir_hier(cinfo
->dest
)) {
590 alertpanel_error(_("Couldn't create destination directory %s."),
594 prefs_themes_foreach_file(source
, prefs_themes_file_install
, cinfo
);
595 if (cinfo
->status
== NULL
) {
598 /* update interface to show newly installed theme */
599 prefs_themes_get_themes_and_names(tdata
);
600 insted
= g_list_find_custom(tdata
->themes
,
601 (gpointer
)(cinfo
->dest
),
602 (GCompareFunc
)g_strcmp0
);
603 if (NULL
!= insted
) {
604 alertpanel_notice(_("Theme installed successfully."));
605 tdata
->displayed
= (gchar
*)(insted
->data
);
606 prefs_themes_set_themes_menu(GTK_COMBO_BOX(tdata
->page
->op_menu
), tdata
);
607 prefs_themes_display_global_stats(tdata
);
608 prefs_themes_get_theme_info(tdata
);
611 alertpanel_error(_("Failed installing theme"));
614 alertpanel_error(_("File %s failed\nwhile installing theme."), cinfo
->status
);
625 static gboolean
prefs_themes_viewall_key_pressed(GtkWidget
*keywidget
, GdkEventKey
*event
, GtkWidget
**widget
)
627 if (event
&& event
->keyval
== GDK_KEY_Escape
) {
628 prefs_themes_viewall_close_btn_clicked(NULL
, widget
);
634 static void prefs_themes_viewall_close_btn_clicked(GtkWidget
*widget
, gpointer data
)
636 GtkWidget
**window
= (GtkWidget
**) data
;
638 cm_return_if_fail(window
!= NULL
);
639 cm_return_if_fail(*window
!= NULL
);
641 gtk_widget_destroy(*window
);
645 #define ICONS_PER_ROW 19
647 static void prefs_themes_btn_viewall_clicked_cb(GtkWidget
*widget
, gpointer data
)
649 static GtkWidget
*viewall_win
= NULL
;
651 ThemesData
*tdata
= prefs_themes_data
;
654 GtkWidget
*icons
[N_STOCK_PIXMAPS
];
655 GdkPixbuf
*pixbufs
[N_STOCK_PIXMAPS
];
656 GtkWidget
*separator
;
657 GtkWidget
*confirm_area
;
658 GtkWidget
*close_btn
;
659 gchar
*save_prefs_path
;
662 viewall_win
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_themes_view_all");
663 gtk_container_set_border_width(GTK_CONTAINER(viewall_win
), 5);
664 gtk_window_set_title(GTK_WINDOW(viewall_win
), _("View all theme icons"));
665 gtk_window_set_position(GTK_WINDOW(viewall_win
), GTK_WIN_POS_CENTER
);
667 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 5);
668 gtk_widget_show(vbox
);
669 gtk_container_add(GTK_CONTAINER(viewall_win
), vbox
);
671 save_prefs_path
= prefs_common
.pixmap_theme_path
;
672 prefs_common
.pixmap_theme_path
= tdata
->displayed
;
673 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
674 gtk_widget_show(hbox
);
675 for (i
= 0; i
< N_STOCK_PIXMAPS
; ++i
) {
676 icons
[i
] = gtk_image_new();
677 gtk_widget_show (icons
[i
]);
678 stock_pixbuf_gdk(i
, &(pixbufs
[i
]));
679 gtk_image_set_from_pixbuf(GTK_IMAGE(icons
[i
]), pixbufs
[i
]);
680 gtk_box_pack_start(GTK_BOX(hbox
), icons
[i
], TRUE
, TRUE
, 5);
681 if ((i
+ 1) % ICONS_PER_ROW
== 0) {
682 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, TRUE
, TRUE
, 5);
683 if (i
+ 1 < N_STOCK_PIXMAPS
) {
684 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
685 gtk_widget_show(hbox
);
689 prefs_common
.pixmap_theme_path
= save_prefs_path
;
691 separator
= gtk_separator_new(GTK_ORIENTATION_HORIZONTAL
);
692 gtk_widget_show(separator
);
693 gtk_box_pack_start(GTK_BOX(vbox
), separator
, FALSE
, FALSE
, 0);
695 gtkut_stock_button_set_create(&confirm_area
,
696 &close_btn
, "window-close", _("_Close"),
697 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
698 gtk_box_pack_start(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 5);
699 gtk_widget_show(confirm_area
);
700 gtk_widget_grab_default(close_btn
);
701 gtk_widget_grab_focus(close_btn
);
703 g_signal_connect(G_OBJECT(close_btn
), "clicked",
704 G_CALLBACK(prefs_themes_viewall_close_btn_clicked
),
706 g_signal_connect(G_OBJECT(viewall_win
), "key_press_event",
707 G_CALLBACK(prefs_themes_viewall_key_pressed
),
710 manage_window_set_transient(GTK_WINDOW(viewall_win
));
711 gtk_window_set_modal(GTK_WINDOW(viewall_win
), TRUE
);
712 gtk_widget_show(viewall_win
);
715 static void prefs_themes_menu_item_activated_cb(GtkWidget
*widget
, gpointer data
)
717 ThemesData
*tdata
= prefs_themes_data
;
722 cm_return_if_fail(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget
), &iter
));
724 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(widget
));
725 gtk_tree_model_get(model
, &iter
, 1, &path
, -1);
727 tdata
->displayed
= path
;
728 prefs_themes_get_theme_info(tdata
);
732 #define MM_INCH 0.0393700787402
733 static gdouble
prefs_themes_compute_ppi(GdkScreen
*screen
)
735 GdkRectangle workarea
= {0};
736 GdkMonitor
*monitor
= gdk_display_get_primary_monitor(gdk_display_get_default());
738 gdk_monitor_get_workarea(monitor
, &workarea
);
739 gdouble wp
= workarea
.width
;
740 gdouble hp
= workarea
.height
;
741 gdouble wi
= gdk_monitor_get_width_mm(monitor
);
742 gdouble hi
= gdk_monitor_get_height_mm(monitor
);
745 debug_print("screen is %f x %f pixels, %f x %f mm\n", wp
, hp
, wi
, hi
);
747 /* https://en.wikipedia.org/wiki/Pixel_density */
750 dp
= sqrt(wp
* wp
+ hp
* hp
);
751 di
= sqrt(wi
* wi
+ hi
* hi
);
753 return (di
!= 0.0)? dp
/ di
: 0.0;
756 static gdouble
prefs_themes_get_adjusted_ppi(void)
759 GdkScreen
* screen
= gdk_screen_get_default();
761 if (screen
== NULL
) { /* oops! */
762 g_warning("unable to get default GDK screen");
766 ppi
= gdk_screen_get_resolution(screen
);
767 cppi
= prefs_themes_compute_ppi(screen
);
768 debug_print("returned PPI: %f / computed PPI: %f\n", ppi
, cppi
);
770 gdk_screen_get_resolution doesn't seem to work well when running
771 on a remote display and returns the value of the local display.
772 height/width functions do this better, so we can compute a PPI
773 from them and take the highest value.
775 return MAX(ppi
, cppi
);
778 static void prefs_themes_checkbtn_enable_scaling_toggled_cb (GtkWidget
*widget
, gpointer data
)
780 ThemesPage
*page
= (ThemesPage
*) data
;
781 gboolean enabled
= gtk_toggle_button_get_active(
782 GTK_TOGGLE_BUTTON (widget
));
783 gboolean automatic
= gtk_toggle_button_get_active(
784 GTK_TOGGLE_BUTTON (page
->checkbtn_scaling_auto
));
786 gtk_widget_set_sensitive(page
->checkbtn_scaling_auto
, enabled
);
787 gtk_widget_set_sensitive(page
->spinbtn_scaling_ppi
, enabled
&& !automatic
);
788 gtk_widget_set_sensitive(page
->label_scaling_ppi
, enabled
&& !automatic
);
791 static void prefs_themes_checkbtn_scaling_auto_toggled_cb(GtkWidget
*widget
, gpointer data
)
793 ThemesPage
*page
= (ThemesPage
*) data
;
794 gboolean automatic
= gtk_toggle_button_get_active(
795 GTK_TOGGLE_BUTTON (widget
));
797 gtk_widget_set_sensitive(page
->spinbtn_scaling_ppi
, !automatic
);
798 gtk_widget_set_sensitive(page
->label_scaling_ppi
, !automatic
);
800 if (automatic
) /* update PPI value */
801 gtk_spin_button_set_value(
802 GTK_SPIN_BUTTON (page
->spinbtn_scaling_ppi
),
803 prefs_themes_get_adjusted_ppi());
807 static void prefs_themes_update_buttons(const ThemesData
*tdata
)
809 ThemesPage
*theme
= tdata
->page
;
812 can_rem
= !IS_CURRENT_THEME(tdata
->displayed
) &&
813 !IS_INTERNAL_THEME(tdata
->displayed
) &&
814 !IS_SYSTEM_THEME(tdata
->displayed
);
816 if (theme
->btn_remove
!= NULL
)
817 gtk_widget_set_sensitive(theme
->btn_remove
, can_rem
);
820 /* placeholders may already be utf8 (i18n) */
821 #define SET_LABEL_TEXT_UTF8(label, text) \
825 if (!g_utf8_validate(text, -1, NULL)) \
826 tmpstr = conv_codeset_strdup(text, \
827 conv_get_locale_charset_str(), CS_UTF_8); \
829 tmpstr = g_strdup(text); \
831 gtk_label_set_text(GTK_LABEL(label), tmpstr); \
832 gtk_label_set_selectable(GTK_LABEL(label), TRUE); \
835 static void prefs_themes_display_theme_info(ThemesData
*tdata
, const ThemeInfo
*info
)
837 ThemesPage
*theme
= tdata
->page
;
838 gchar
*save_prefs_path
;
841 SET_LABEL_TEXT_UTF8(theme
->name
, info
->name
);
842 SET_LABEL_TEXT_UTF8(theme
->author
, info
->author
);
843 SET_LABEL_TEXT_UTF8(theme
->url
, info
->url
);
844 SET_LABEL_TEXT_UTF8(theme
->status
, info
->status
);
846 save_prefs_path
= prefs_common
.pixmap_theme_path
;
847 prefs_common
.pixmap_theme_path
= tdata
->displayed
;
848 for (i
= 0; i
< PREVIEW_ICONS
; ++i
) {
849 stock_pixbuf_gdk(prefs_themes_icons
[i
], &(theme
->pixbufs
[i
]));
850 gtk_image_set_from_pixbuf(GTK_IMAGE(theme
->icons
[i
]),
853 prefs_common
.pixmap_theme_path
= save_prefs_path
;
855 prefs_themes_update_buttons(tdata
);
857 #undef SET_LABEL_TEXT_UTF8
859 static void prefs_themes_display_global_stats(const ThemesData
*tdata
)
861 ThemesPage
*theme
= tdata
->page
;
862 GList
*tnames
= tdata
->names
;
868 while (tnames
!= NULL
) {
869 ThemeName
*tname
= (ThemeName
*)(tnames
->data
);
870 gchar
*tpath
= (gchar
*)(tname
->item
->data
);
872 if (IS_SYSTEM_THEME(tpath
))
874 else if (!IS_INTERNAL_THEME(tpath
))
877 tnames
= g_list_next(tnames
);
880 gstats
= g_strdup_printf(_("%d themes available (%d user, %d system, 1 internal)"),
882 gtk_label_set_text(GTK_LABEL(theme
->global
), gstats
);
883 gtk_label_set_justify (GTK_LABEL (theme
->global
), GTK_JUSTIFY_LEFT
);
884 gtkut_widget_set_small_font_size (theme
->global
);
888 #define INFOFILE_LINE_LEN 80
890 #define FGETS_INFOFILE_LINE() \
892 if (claws_fgets(line, INFOFILE_LINE_LEN, finfo) != NULL && (len = strlen(line)) > 0) { \
893 if (line[len - 1] == '\n') line[len - 1] = '\0'; \
896 g_strlcpy(line, _("Unknown"),sizeof(line)); \
899 static void prefs_themes_get_theme_info(ThemesData
*tdata
)
904 gchar line
[INFOFILE_LINE_LEN
];
907 ThemesPage
*theme
= tdata
->page
;
909 cm_return_if_fail(theme
!= NULL
);
910 path
= tdata
->displayed
;
911 cm_return_if_fail(path
!= NULL
);
913 debug_print("Getting theme info for %s\n", path
);
915 info
= g_new0(ThemeInfo
, 1);
917 if (IS_INTERNAL_THEME(path
)) {
918 info
->name
= g_strdup(_("Default internal theme"));
919 info
->author
= g_strdup(_("The Claws Mail Team"));
920 info
->url
= g_strdup(HOMEPAGE_URI
);
921 info
->status
= g_strdup_printf(_("Internal theme has %d icons"), N_STOCK_PIXMAPS
);
924 sinfo
= g_strconcat(path
, G_DIR_SEPARATOR_S
, THEMEINFO_FILE
, NULL
);
925 finfo
= claws_fopen(sinfo
, "r");
927 info
->name
= g_strdup(_("No info file available for this theme"));
928 info
->author
= g_strdup(_("Unknown"));
929 info
->url
= g_strdup(_("Unknown"));
932 FGETS_INFOFILE_LINE()
933 info
->name
= g_strdup(line
);
934 FGETS_INFOFILE_LINE()
935 info
->author
= g_strdup(line
);
936 FGETS_INFOFILE_LINE()
937 info
->url
= g_strdup(line
);
943 info
->status
= prefs_themes_get_theme_stats(path
);
944 if (info
->status
== NULL
) {
945 info
->status
= g_strdup(_("Error: couldn't get theme status"));
949 prefs_themes_display_theme_info(tdata
, info
);
952 g_free(info
->author
);
954 g_free(info
->status
);
959 #undef FGETS_INFOFILE_LINE
961 static gchar
*prefs_themes_get_theme_stats(const gchar
*dirname
)
967 dinfo
= g_new0(DirInfo
, 1);
968 dinfo
->supported
= stock_pixmap_theme_extensions();
969 for (i
= 0; (dinfo
->supported
)[i
] != NULL
; ++i
);
970 dinfo
->length
= g_malloc(i
* sizeof(gint
));
971 for (i
= 0; (dinfo
->supported
)[i
] != NULL
; ++i
) {
972 (dinfo
->length
)[i
] = strlen((dinfo
->supported
)[i
]);
974 prefs_themes_foreach_file(dirname
, prefs_themes_file_stats
, dinfo
);
975 stats
= g_strdup_printf(_("%d files (%d icons), size: %s"),
976 dinfo
->files
, dinfo
->pixms
,
977 to_human_readable((goffset
)dinfo
->bytes
));
978 g_free(dinfo
->length
);
983 static void prefs_themes_create_widget(PrefsPage
*page
, GtkWindow
*window
, gpointer data
)
985 ThemesPage
*prefs_themes
= (ThemesPage
*)page
;
986 ThemesData
*tdata
= prefs_themes_data
;
992 GtkWidget
*menu_themes
;
993 GtkWidget
*btn_install
;
995 GtkWidget
*label_global_status
;
996 GtkWidget
*frame_info
;
1001 GtkWidget
*label_name
;
1002 GtkWidget
*label_author
;
1003 GtkWidget
*label_url
;
1005 GtkWidget
*label_status
;
1006 GtkWidget
*frame_preview
;
1015 GtkWidget
*btn_viewall
;
1016 GtkWidget
*frame_buttons
;
1017 GtkWidget
*hbuttonbox1
;
1018 GtkWidget
*btn_remove
;
1019 GtkCellRenderer
*renderer
;
1021 GtkWidget
*frame_scaling
;
1022 GtkWidget
*checkbtn_enable_alpha
;
1023 GtkWidget
*checkbtn_enable_scaling
;
1024 GtkWidget
*checkbtn_scaling_auto
;
1025 GtkWidget
*label_scaling_ppi
;
1026 GtkWidget
*spinbtn_scaling_ppi
;
1027 GtkAdjustment
*spinbtn_scaling_ppi_adj
;
1030 vbox1
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, VSPACING
);
1031 gtk_container_set_border_width (GTK_CONTAINER (vbox1
), 5);
1032 gtk_widget_show (vbox1
);
1034 vbox2
= gtkut_get_options_frame(vbox1
, &frame1
, _("Selector"));
1036 hbox3
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
1037 gtk_widget_show (hbox3
);
1038 gtk_box_pack_start (GTK_BOX (vbox2
), hbox3
, FALSE
, FALSE
, 0);
1039 // gtk_container_set_border_width (GTK_CONTAINER (hbox3), 5);
1041 menu_themes
= gtk_combo_box_new();
1042 gtk_widget_show (menu_themes
);
1043 gtk_box_pack_start (GTK_BOX (hbox3
), menu_themes
, FALSE
, FALSE
, 0);
1045 btn_install
= gtk_button_new_with_label (_("Install new..."));
1046 gtk_widget_show (btn_install
);
1047 gtk_box_pack_start (GTK_BOX (hbox3
), btn_install
, FALSE
, FALSE
, 0);
1048 gtk_widget_set_can_default (btn_install
, TRUE
);
1050 btn_more
= gtk_link_button_new_with_label(THEMES_URI
, _("Get more..."));
1051 gtk_widget_show (btn_more
);
1052 gtk_box_pack_start (GTK_BOX (hbox3
), btn_more
, FALSE
, FALSE
, 0);
1054 label_global_status
= gtk_label_new ("");
1055 gtk_widget_show (label_global_status
);
1056 gtk_box_pack_start (GTK_BOX (vbox2
), label_global_status
, FALSE
, FALSE
, 0);
1057 gtk_label_set_justify (GTK_LABEL (label_global_status
), GTK_JUSTIFY_LEFT
);
1058 gtk_label_set_xalign (GTK_LABEL (label_global_status
), 0.0);
1059 gtk_widget_set_margin_start(GTK_WIDGET(label_global_status
), 1);
1060 gtk_widget_set_margin_end(GTK_WIDGET(label_global_status
), 0);
1062 PACK_FRAME(vbox1
, frame_info
, _("Information"));
1064 table1
= gtk_grid_new();
1065 gtk_widget_show (table1
);
1066 gtk_container_add (GTK_CONTAINER (frame_info
), table1
);
1067 gtk_container_set_border_width (GTK_CONTAINER (table1
), 5);
1068 gtk_grid_set_row_spacing(GTK_GRID(table1
), 4);
1069 gtk_grid_set_column_spacing(GTK_GRID(table1
), 8);
1071 label1
= gtk_label_new (_("Name"));
1072 gtk_widget_show (label1
);
1073 gtk_label_set_justify (GTK_LABEL (label1
), GTK_JUSTIFY_LEFT
);
1074 gtk_label_set_xalign (GTK_LABEL (label1
), 1.0);
1075 gtk_grid_attach(GTK_GRID(table1
), label1
, 0, 0, 1, 1);
1077 label2
= gtk_label_new (_("Author"));
1078 gtk_widget_show (label2
);
1079 gtk_label_set_justify (GTK_LABEL (label2
), GTK_JUSTIFY_LEFT
);
1080 gtk_label_set_xalign (GTK_LABEL (label2
), 1.0);
1081 gtk_grid_attach(GTK_GRID(table1
), label2
, 0, 1, 1, 1);
1083 label3
= gtk_label_new (_("URL"));
1084 gtk_widget_show (label3
);
1085 gtk_label_set_xalign (GTK_LABEL (label3
), 1.0);
1086 gtk_grid_attach(GTK_GRID(table1
), label3
, 0, 2, 1, 1);
1088 label_name
= gtk_label_new ("");
1089 gtk_widget_show (label_name
);
1090 gtk_label_set_xalign (GTK_LABEL (label_name
), 0.0);
1091 gtk_grid_attach(GTK_GRID(table1
), label_name
, 1, 0, 1, 1);
1092 gtk_widget_set_hexpand(label_name
, TRUE
);
1093 gtk_widget_set_halign(label_name
, GTK_ALIGN_FILL
);
1095 label_author
= gtk_label_new ("");
1096 gtk_widget_show (label_author
);
1097 gtk_label_set_xalign (GTK_LABEL (label_author
), 0.0);
1098 gtk_grid_attach(GTK_GRID(table1
), label_author
, 1, 1, 1, 1);
1099 gtk_widget_set_hexpand(label_author
, TRUE
);
1100 gtk_widget_set_halign(label_author
, GTK_ALIGN_FILL
);
1102 label_url
= gtk_label_new ("");
1103 gtk_widget_show (label_url
);
1104 gtk_label_set_xalign (GTK_LABEL (label_url
), 0.0);
1105 gtk_grid_attach(GTK_GRID(table1
), label_url
, 1, 2, 1, 1);
1106 gtk_widget_set_hexpand(label_url
, TRUE
);
1107 gtk_widget_set_halign(label_url
, GTK_ALIGN_FILL
);
1109 label4
= gtk_label_new (_("Status"));
1110 gtk_widget_show (label4
);
1111 gtk_label_set_xalign (GTK_LABEL (label4
), 1.0);
1112 gtk_grid_attach(GTK_GRID(table1
), label4
, 0, 3, 1, 1);
1114 label_status
= gtk_label_new ("");
1115 gtk_widget_show (label_status
);
1116 gtk_label_set_xalign (GTK_LABEL (label_status
), 0.0);
1117 gtk_grid_attach(GTK_GRID(table1
), label_status
, 1, 3, 1, 1);
1118 gtk_widget_set_hexpand(label_status
, TRUE
);
1119 gtk_widget_set_halign(label_status
, GTK_ALIGN_FILL
);
1121 PACK_FRAME(vbox1
, frame_preview
, _("Preview"));
1123 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
1124 gtk_widget_show (hbox1
);
1125 gtk_container_add (GTK_CONTAINER (frame_preview
), hbox1
);
1126 gtk_container_set_border_width (GTK_CONTAINER (hbox1
), 5);
1128 icon_1
= gtk_image_new();
1129 gtk_widget_show (icon_1
);
1130 gtk_box_pack_start (GTK_BOX (hbox1
), icon_1
, TRUE
, TRUE
, 2);
1131 gtk_widget_set_margin_start(GTK_WIDGET(icon_1
), 0);
1132 gtk_widget_set_margin_end(GTK_WIDGET(icon_1
), 5);
1134 icon_2
= gtk_image_new();
1135 gtk_widget_show (icon_2
);
1136 gtk_box_pack_start (GTK_BOX (hbox1
), icon_2
, TRUE
, TRUE
, 2);
1137 gtk_widget_set_margin_start(GTK_WIDGET(icon_2
), 0);
1138 gtk_widget_set_margin_end(GTK_WIDGET(icon_2
), 5);
1140 icon_3
= gtk_image_new();
1141 gtk_widget_show (icon_3
);
1142 gtk_box_pack_start (GTK_BOX (hbox1
), icon_3
, TRUE
, TRUE
, 2);
1143 gtk_widget_set_margin_start(GTK_WIDGET(icon_3
), 0);
1144 gtk_widget_set_margin_end(GTK_WIDGET(icon_3
), 5);
1146 icon_4
= gtk_image_new();
1147 gtk_widget_show (icon_4
);
1148 gtk_box_pack_start (GTK_BOX (hbox1
), icon_4
, TRUE
, TRUE
, 2);
1149 gtk_widget_set_margin_start(GTK_WIDGET(icon_4
), 0);
1150 gtk_widget_set_margin_end(GTK_WIDGET(icon_4
), 5);
1152 icon_5
= gtk_image_new();
1153 gtk_widget_show (icon_5
);
1154 gtk_box_pack_start (GTK_BOX (hbox1
), icon_5
, TRUE
, TRUE
, 2);
1155 gtk_widget_set_margin_start(GTK_WIDGET(icon_5
), 0);
1156 gtk_widget_set_margin_end(GTK_WIDGET(icon_5
), 5);
1158 icon_6
= gtk_image_new();
1159 gtk_widget_show (icon_6
);
1160 gtk_box_pack_start (GTK_BOX (hbox1
), icon_6
, TRUE
, TRUE
, 2);
1161 gtk_widget_set_margin_start(GTK_WIDGET(icon_6
), 0);
1162 gtk_widget_set_margin_end(GTK_WIDGET(icon_6
), 5);
1164 icon_7
= gtk_image_new();
1165 gtk_widget_show (icon_7
);
1166 gtk_box_pack_start (GTK_BOX (hbox1
), icon_7
, TRUE
, TRUE
, 2);
1167 gtk_widget_set_margin_start(GTK_WIDGET(icon_7
), 0);
1168 gtk_widget_set_margin_end(GTK_WIDGET(icon_7
), 5);
1170 PACK_FRAME(vbox1
, frame_buttons
, _("Actions"));
1172 hbuttonbox1
= gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL
);
1173 gtk_widget_show (hbuttonbox1
);
1174 gtk_container_add (GTK_CONTAINER (frame_buttons
), hbuttonbox1
);
1175 gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1
), 8);
1176 gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1
), GTK_BUTTONBOX_START
);
1177 gtk_box_set_spacing (GTK_BOX (hbuttonbox1
), 5);
1179 btn_remove
= gtkut_stock_button("list-remove", _("_Remove"));
1180 gtk_widget_show (btn_remove
);
1181 gtk_container_add (GTK_CONTAINER (hbuttonbox1
), btn_remove
);
1182 gtk_widget_set_can_default (btn_remove
, TRUE
);
1184 btn_viewall
= gtk_button_new_with_label(_("View all"));
1185 gtk_widget_show (btn_viewall
);
1186 gtk_box_pack_start (GTK_BOX (hbuttonbox1
), btn_viewall
, FALSE
, FALSE
, 5);
1189 PACK_FRAME(vbox1
, frame_scaling
, _("SVG rendering"));
1191 vbox2
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, VSPACING
);
1192 gtk_widget_show (vbox2
);
1193 gtk_container_set_border_width (GTK_CONTAINER (vbox2
), 5);
1194 gtk_container_add (GTK_CONTAINER (frame_scaling
), vbox2
);
1196 PACK_CHECK_BUTTON(vbox2
, checkbtn_enable_alpha
, _("Enable alpha channel"));
1197 PACK_CHECK_BUTTON(vbox2
, checkbtn_enable_scaling
, _("Force scaling"));
1198 PACK_CHECK_BUTTON(vbox2
, checkbtn_scaling_auto
, _("Automatic"));
1200 hbox3
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
1201 gtk_widget_show (hbox3
);
1203 label_scaling_ppi
= gtk_label_new (_("Pixels per inch (PPI)"));
1204 gtk_widget_show (label_scaling_ppi
);
1205 gtk_box_pack_start (GTK_BOX (hbox3
), label_scaling_ppi
,
1208 spinbtn_scaling_ppi_adj
= GTK_ADJUSTMENT(
1209 gtk_adjustment_new (MIN_PPI
, MIN_PPI
, MAX_PPI
, 1, 10, 0));
1210 spinbtn_scaling_ppi
= gtk_spin_button_new(
1211 spinbtn_scaling_ppi_adj
, 1.0, 0);
1212 gtk_widget_show (spinbtn_scaling_ppi
);
1213 gtk_box_pack_start (GTK_BOX (hbox3
), spinbtn_scaling_ppi
,
1216 gtk_box_pack_start (GTK_BOX (vbox2
), hbox3
, FALSE
, FALSE
, 0);
1218 /* initialize widget values */
1219 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_enable_alpha
),
1220 prefs_common
.enable_alpha_svg
);
1221 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_enable_scaling
),
1222 prefs_common
.enable_pixmap_scaling
);
1223 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_scaling_auto
),
1224 prefs_common
.pixmap_scaling_auto
);
1225 gtk_spin_button_set_value(GTK_SPIN_BUTTON (spinbtn_scaling_ppi
),
1226 prefs_common
.pixmap_scaling_ppi
);
1229 gtk_widget_set_sensitive(checkbtn_scaling_auto
,
1230 prefs_common
.enable_pixmap_scaling
);
1231 gtk_widget_set_sensitive(spinbtn_scaling_ppi
,
1232 prefs_common
.enable_pixmap_scaling
1233 && !prefs_common
.pixmap_scaling_auto
);
1234 gtk_widget_set_sensitive(label_scaling_ppi
,
1235 prefs_common
.enable_pixmap_scaling
1236 && !prefs_common
.pixmap_scaling_auto
);
1239 g_signal_connect(G_OBJECT(checkbtn_enable_scaling
), "toggled",
1240 G_CALLBACK(prefs_themes_checkbtn_enable_scaling_toggled_cb
),
1242 g_signal_connect(G_OBJECT(checkbtn_scaling_auto
), "toggled",
1243 G_CALLBACK(prefs_themes_checkbtn_scaling_auto_toggled_cb
),
1247 g_signal_connect(G_OBJECT(btn_remove
), "clicked",
1248 G_CALLBACK(prefs_themes_btn_remove_clicked_cb
),
1250 g_signal_connect(G_OBJECT(btn_install
), "clicked",
1251 G_CALLBACK(prefs_themes_btn_install_clicked_cb
),
1253 g_signal_connect(G_OBJECT(btn_viewall
), "clicked",
1254 G_CALLBACK(prefs_themes_btn_viewall_clicked_cb
),
1257 prefs_themes
->window
= GTK_WIDGET(window
);
1259 prefs_themes
->name
= label_name
;
1260 prefs_themes
->author
= label_author
;
1261 prefs_themes
->url
= label_url
;
1262 prefs_themes
->status
= label_status
;
1263 prefs_themes
->global
= label_global_status
;
1265 prefs_themes
->icons
[0] = icon_1
;
1266 prefs_themes
->icons
[1] = icon_2
;
1267 prefs_themes
->icons
[2] = icon_3
;
1268 prefs_themes
->icons
[3] = icon_4
;
1269 prefs_themes
->icons
[4] = icon_5
;
1270 prefs_themes
->icons
[5] = icon_6
;
1271 prefs_themes
->icons
[6] = icon_7
;
1273 prefs_themes
->btn_remove
= btn_remove
;
1274 prefs_themes
->btn_install
= btn_install
;
1275 prefs_themes
->btn_more
= btn_more
;
1277 prefs_themes
->op_menu
= menu_themes
;
1280 prefs_themes
->checkbtn_enable_alpha
= checkbtn_enable_alpha
;
1281 prefs_themes
->checkbtn_enable_scaling
= checkbtn_enable_scaling
;
1282 prefs_themes
->checkbtn_scaling_auto
= checkbtn_scaling_auto
;
1283 prefs_themes
->label_scaling_ppi
= label_scaling_ppi
;
1284 prefs_themes
->spinbtn_scaling_ppi
= spinbtn_scaling_ppi
;
1287 prefs_themes
->page
.widget
= vbox1
;
1289 prefs_themes_set_themes_menu(GTK_COMBO_BOX(menu_themes
), tdata
);
1290 renderer
= gtk_cell_renderer_text_new();
1291 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(menu_themes
), renderer
, TRUE
);
1292 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(menu_themes
), renderer
,
1295 prefs_themes_get_theme_info(tdata
);
1296 prefs_themes_display_global_stats(tdata
);
1299 static void prefs_themes_destroy_widget(PrefsPage
*page
)
1301 /* ThemesPage *theme = (ThemesPage *)page; */
1304 static void prefs_themes_save(PrefsPage
*page
)
1306 ThemesData
*tdata
= prefs_themes_data
;
1307 gchar
*theme_str
= tdata
->displayed
;
1309 ThemesPage
*tpage
= (ThemesPage
*) page
;
1310 gboolean alpha
= prefs_common
.enable_alpha_svg
;
1311 gboolean scaling
= prefs_common
.enable_pixmap_scaling
;
1312 gboolean scaling_auto
= prefs_common
.pixmap_scaling_auto
;
1313 gint scaling_ppi
= prefs_common
.pixmap_scaling_ppi
;
1315 prefs_common
.enable_alpha_svg
= gtk_toggle_button_get_active(
1316 GTK_TOGGLE_BUTTON (tpage
->checkbtn_enable_alpha
));
1317 prefs_common
.enable_pixmap_scaling
= gtk_toggle_button_get_active(
1318 GTK_TOGGLE_BUTTON (tpage
->checkbtn_enable_scaling
));
1319 prefs_common
.pixmap_scaling_auto
= gtk_toggle_button_get_active(
1320 GTK_TOGGLE_BUTTON (tpage
->checkbtn_scaling_auto
));
1321 prefs_common
.pixmap_scaling_ppi
= gtk_spin_button_get_value_as_int (
1322 GTK_SPIN_BUTTON (tpage
->spinbtn_scaling_ppi
));
1325 if (!IS_CURRENT_THEME(theme_str
)) {
1326 debug_print("Changing theme to %s\n", theme_str
);
1327 g_free(prefs_common
.pixmap_theme_path
);
1329 prefs_common
.pixmap_theme_path
= g_strdup(theme_str
);
1331 main_window_reflect_prefs_all_real(TRUE
);
1332 compose_reflect_prefs_pixmap_theme();
1333 addrcompl_reflect_prefs_pixmap_theme();
1335 prefs_themes_update_buttons(tdata
);
1338 else if (scaling
!= prefs_common
.enable_pixmap_scaling
1339 || alpha
!= prefs_common
.enable_alpha_svg
1340 || (scaling_auto
!= prefs_common
.pixmap_scaling_auto
1341 && scaling_ppi
!= prefs_common
.pixmap_scaling_ppi
)) {
1342 /* same theme, different scaling options */
1343 debug_print("Updating theme scaling\n");
1344 main_window_reflect_prefs_all_real(FALSE
);
1345 compose_reflect_prefs_pixmap_theme();
1346 addrcompl_reflect_prefs_pixmap_theme();