2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2022 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 if (IS_SYSTEM_THEME(theme_str
)) {
504 alert_title
= g_strdup_printf(_("Remove system theme '%s'"), tmp
);
506 alert_title
= g_strdup_printf(_("Remove theme '%s'"), tmp
);
510 val
= alertpanel(alert_title
,
511 _("Are you sure you want to remove this theme?"),
512 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_FIRST
);
515 if (G_ALERTALTERNATE
== val
) {
516 gchar
*status
= NULL
;
518 prefs_themes_foreach_file(theme_str
, prefs_themes_file_remove
, &status
);
519 if (0 != rmdir(theme_str
)) {
520 if (status
!= NULL
) {
521 alertpanel_error(_("File %s failed\nwhile removing theme."), status
);
525 alertpanel_error(_("Removing theme directory failed."));
528 alertpanel_notice(_("Theme removed successfully"));
529 /* update interface back to first theme */
530 prefs_themes_get_themes_and_names(tdata
);
531 prefs_themes_set_themes_menu(GTK_COMBO_BOX(tdata
->page
->op_menu
), tdata
);
532 prefs_themes_display_global_stats(tdata
);
533 tdata
->displayed
= (gchar
*)((g_list_first(tdata
->themes
))->data
);
534 prefs_themes_get_theme_info(tdata
);
539 static void prefs_themes_btn_install_clicked_cb(GtkWidget
*widget
, gpointer data
)
541 gchar
*filename
, *source
;
542 gchar
*themeinfo
, *themename
;
543 gchar
*alert_title
= NULL
;
546 ThemesData
*tdata
= prefs_themes_data
;
548 filename
= filesel_select_file_open_folder(_("Select theme folder"), NULL
);
549 if (filename
== NULL
)
552 if (filename
[strlen(filename
) - 1] != G_DIR_SEPARATOR
)
553 filename
= g_strconcat(filename
, G_DIR_SEPARATOR_S
, NULL
);
555 filename
= g_strdup(filename
);
557 cinfo
= g_new0(CopyInfo
, 1);
558 source
= g_path_get_dirname(filename
);
559 themename
= g_path_get_basename(source
);
560 debug_print("Installing '%s' theme from %s\n", themename
, filename
);
562 themeinfo
= g_strconcat(source
, G_DIR_SEPARATOR_S
, THEMEINFO_FILE
, NULL
);
563 alert_title
= g_strdup_printf(_("Install theme '%s'"), themename
);
564 if (file_exist(themeinfo
, FALSE
) == FALSE
) {
565 val
= alertpanel(alert_title
,
566 _("This folder doesn't seem to be a theme"
567 "folder.\nInstall anyway?"),
568 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_FIRST
);
569 if (G_ALERTALTERNATE
!= val
) {
575 val
= alertpanel(alert_title
,
576 _("Do you want to install theme for all users?"),
577 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_FIRST
);
580 case G_ALERTALTERNATE
:
581 cinfo
->dest
= stock_pixmap_get_system_theme_dir_for_theme(
590 if (cinfo
->dest
== NULL
) {
591 cinfo
->dest
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
592 PIXMAP_THEME_DIR
, G_DIR_SEPARATOR_S
,
595 if (TRUE
== is_dir_exist(cinfo
->dest
)) {
596 AlertValue val
= alertpanel_full(_("Theme exists"),
597 _("A theme with the same name is\n"
598 "already installed in this location.\n\n"
599 "Do you want to replace it?"),
600 NULL
, _("_Cancel"), NULL
, _("Overwrite"), NULL
, NULL
,
601 ALERTFOCUS_FIRST
, FALSE
, NULL
, ALERT_WARNING
);
602 if (val
== G_ALERTALTERNATE
) {
603 if (remove_dir_recursive(cinfo
->dest
) < 0) {
604 alertpanel_error(_("Couldn't delete the old theme in %s."),
612 if (0 != make_dir_hier(cinfo
->dest
)) {
613 alertpanel_error(_("Couldn't create destination directory %s."),
617 prefs_themes_foreach_file(source
, prefs_themes_file_install
, cinfo
);
618 if (cinfo
->status
== NULL
) {
621 /* update interface to show newly installed theme */
622 prefs_themes_get_themes_and_names(tdata
);
623 insted
= g_list_find_custom(tdata
->themes
,
624 (gpointer
)(cinfo
->dest
),
625 (GCompareFunc
)g_strcmp0
);
626 if (NULL
!= insted
) {
627 alertpanel_notice(_("Theme installed successfully."));
628 tdata
->displayed
= (gchar
*)(insted
->data
);
629 prefs_themes_set_themes_menu(GTK_COMBO_BOX(tdata
->page
->op_menu
), tdata
);
630 prefs_themes_display_global_stats(tdata
);
631 prefs_themes_get_theme_info(tdata
);
634 alertpanel_error(_("Failed installing theme"));
637 alertpanel_error(_("File %s failed\nwhile installing theme."), cinfo
->status
);
647 static gboolean
prefs_themes_viewall_key_pressed(GtkWidget
*keywidget
, GdkEventKey
*event
, GtkWidget
**widget
)
649 if (event
&& event
->keyval
== GDK_KEY_Escape
) {
650 prefs_themes_viewall_close_btn_clicked(NULL
, widget
);
656 static void prefs_themes_viewall_close_btn_clicked(GtkWidget
*widget
, gpointer data
)
658 GtkWidget
**window
= (GtkWidget
**) data
;
660 cm_return_if_fail(window
!= NULL
);
661 cm_return_if_fail(*window
!= NULL
);
663 gtk_widget_destroy(*window
);
667 #define ICONS_PER_ROW 19
669 static void prefs_themes_btn_viewall_clicked_cb(GtkWidget
*widget
, gpointer data
)
671 static GtkWidget
*viewall_win
= NULL
;
673 ThemesData
*tdata
= prefs_themes_data
;
676 GtkWidget
*icons
[N_STOCK_PIXMAPS
];
677 GdkPixbuf
*pixbufs
[N_STOCK_PIXMAPS
];
678 GtkWidget
*separator
;
679 GtkWidget
*confirm_area
;
680 GtkWidget
*close_btn
;
681 gchar
*save_prefs_path
;
684 viewall_win
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_themes_view_all");
685 gtk_container_set_border_width(GTK_CONTAINER(viewall_win
), 5);
686 gtk_window_set_title(GTK_WINDOW(viewall_win
), _("View all theme icons"));
687 gtk_window_set_position(GTK_WINDOW(viewall_win
), GTK_WIN_POS_CENTER
);
689 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 5);
690 gtk_widget_show(vbox
);
691 gtk_container_add(GTK_CONTAINER(viewall_win
), vbox
);
693 save_prefs_path
= prefs_common
.pixmap_theme_path
;
694 prefs_common
.pixmap_theme_path
= tdata
->displayed
;
695 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
696 gtk_widget_show(hbox
);
697 for (i
= 0; i
< N_STOCK_PIXMAPS
; ++i
) {
698 icons
[i
] = gtk_image_new();
699 gtk_widget_show (icons
[i
]);
700 stock_pixbuf_gdk(i
, &(pixbufs
[i
]));
701 gtk_image_set_from_pixbuf(GTK_IMAGE(icons
[i
]), pixbufs
[i
]);
702 gtk_box_pack_start(GTK_BOX(hbox
), icons
[i
], TRUE
, TRUE
, 5);
703 if ((i
+ 1) % ICONS_PER_ROW
== 0) {
704 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, TRUE
, TRUE
, 5);
705 if (i
+ 1 < N_STOCK_PIXMAPS
) {
706 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
707 gtk_widget_show(hbox
);
711 prefs_common
.pixmap_theme_path
= save_prefs_path
;
713 separator
= gtk_separator_new(GTK_ORIENTATION_HORIZONTAL
);
714 gtk_widget_show(separator
);
715 gtk_box_pack_start(GTK_BOX(vbox
), separator
, FALSE
, FALSE
, 0);
717 gtkut_stock_button_set_create(&confirm_area
,
718 &close_btn
, "window-close", _("_Close"),
719 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
720 gtk_box_pack_start(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 5);
721 gtk_widget_show(confirm_area
);
722 gtk_widget_grab_default(close_btn
);
723 gtk_widget_grab_focus(close_btn
);
725 g_signal_connect(G_OBJECT(close_btn
), "clicked",
726 G_CALLBACK(prefs_themes_viewall_close_btn_clicked
),
728 g_signal_connect(G_OBJECT(viewall_win
), "key_press_event",
729 G_CALLBACK(prefs_themes_viewall_key_pressed
),
732 manage_window_set_transient(GTK_WINDOW(viewall_win
));
733 gtk_window_set_modal(GTK_WINDOW(viewall_win
), TRUE
);
734 gtk_widget_show(viewall_win
);
737 static void prefs_themes_menu_item_activated_cb(GtkWidget
*widget
, gpointer data
)
739 ThemesData
*tdata
= prefs_themes_data
;
744 cm_return_if_fail(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget
), &iter
));
746 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(widget
));
747 gtk_tree_model_get(model
, &iter
, 1, &path
, -1);
749 tdata
->displayed
= path
;
750 prefs_themes_get_theme_info(tdata
);
754 #define MM_INCH 0.0393700787402
755 static gdouble
prefs_themes_compute_ppi(GdkScreen
*screen
)
757 GdkRectangle workarea
= {0};
758 GdkMonitor
*monitor
= gdk_display_get_primary_monitor(gdk_display_get_default());
760 gdk_monitor_get_workarea(monitor
, &workarea
);
761 gdouble wp
= workarea
.width
;
762 gdouble hp
= workarea
.height
;
763 gdouble wi
= gdk_monitor_get_width_mm(monitor
);
764 gdouble hi
= gdk_monitor_get_height_mm(monitor
);
767 debug_print("screen is %f x %f pixels, %f x %f mm\n", wp
, hp
, wi
, hi
);
769 /* https://en.wikipedia.org/wiki/Pixel_density */
772 dp
= sqrt(wp
* wp
+ hp
* hp
);
773 di
= sqrt(wi
* wi
+ hi
* hi
);
775 return (di
!= 0.0)? dp
/ di
: 0.0;
778 static gdouble
prefs_themes_get_adjusted_ppi(void)
781 GdkScreen
* screen
= gdk_screen_get_default();
783 if (screen
== NULL
) { /* oops! */
784 g_warning("unable to get default GDK screen");
788 ppi
= gdk_screen_get_resolution(screen
);
789 cppi
= prefs_themes_compute_ppi(screen
);
790 debug_print("returned PPI: %f / computed PPI: %f\n", ppi
, cppi
);
792 gdk_screen_get_resolution doesn't seem to work well when running
793 on a remote display and returns the value of the local display.
794 height/width functions do this better, so we can compute a PPI
795 from them and take the highest value.
797 return MAX(ppi
, cppi
);
800 static void prefs_themes_checkbtn_enable_scaling_toggled_cb (GtkWidget
*widget
, gpointer data
)
802 ThemesPage
*page
= (ThemesPage
*) data
;
803 gboolean enabled
= gtk_toggle_button_get_active(
804 GTK_TOGGLE_BUTTON (widget
));
805 gboolean automatic
= gtk_toggle_button_get_active(
806 GTK_TOGGLE_BUTTON (page
->checkbtn_scaling_auto
));
808 gtk_widget_set_sensitive(page
->checkbtn_scaling_auto
, enabled
);
809 gtk_widget_set_sensitive(page
->spinbtn_scaling_ppi
, enabled
&& !automatic
);
810 gtk_widget_set_sensitive(page
->label_scaling_ppi
, enabled
&& !automatic
);
813 static void prefs_themes_checkbtn_scaling_auto_toggled_cb(GtkWidget
*widget
, gpointer data
)
815 ThemesPage
*page
= (ThemesPage
*) data
;
816 gboolean automatic
= gtk_toggle_button_get_active(
817 GTK_TOGGLE_BUTTON (widget
));
819 gtk_widget_set_sensitive(page
->spinbtn_scaling_ppi
, !automatic
);
820 gtk_widget_set_sensitive(page
->label_scaling_ppi
, !automatic
);
822 if (automatic
) /* update PPI value */
823 gtk_spin_button_set_value(
824 GTK_SPIN_BUTTON (page
->spinbtn_scaling_ppi
),
825 prefs_themes_get_adjusted_ppi());
829 static void prefs_themes_update_buttons(const ThemesData
*tdata
)
831 ThemesPage
*theme
= tdata
->page
;
832 gboolean can_rem
, can_use
;
834 can_use
= !IS_CURRENT_THEME(tdata
->displayed
);
835 can_rem
= can_use
&& !IS_INTERNAL_THEME(tdata
->displayed
);
837 if (theme
->btn_remove
!= NULL
)
838 gtk_widget_set_sensitive(theme
->btn_remove
, can_rem
);
841 /* placeholders may already be utf8 (i18n) */
842 #define SET_LABEL_TEXT_UTF8(label, text) \
846 if (!g_utf8_validate(text, -1, NULL)) \
847 tmpstr = conv_codeset_strdup(text, \
848 conv_get_locale_charset_str(), CS_UTF_8); \
850 tmpstr = g_strdup(text); \
852 gtk_label_set_text(GTK_LABEL(label), tmpstr); \
853 gtk_label_set_selectable(GTK_LABEL(label), TRUE); \
856 static void prefs_themes_display_theme_info(ThemesData
*tdata
, const ThemeInfo
*info
)
858 ThemesPage
*theme
= tdata
->page
;
859 gchar
*save_prefs_path
;
862 SET_LABEL_TEXT_UTF8(theme
->name
, info
->name
);
863 SET_LABEL_TEXT_UTF8(theme
->author
, info
->author
);
864 SET_LABEL_TEXT_UTF8(theme
->url
, info
->url
);
865 SET_LABEL_TEXT_UTF8(theme
->status
, info
->status
);
867 save_prefs_path
= prefs_common
.pixmap_theme_path
;
868 prefs_common
.pixmap_theme_path
= tdata
->displayed
;
869 for (i
= 0; i
< PREVIEW_ICONS
; ++i
) {
870 stock_pixbuf_gdk(prefs_themes_icons
[i
], &(theme
->pixbufs
[i
]));
871 gtk_image_set_from_pixbuf(GTK_IMAGE(theme
->icons
[i
]),
874 prefs_common
.pixmap_theme_path
= save_prefs_path
;
876 prefs_themes_update_buttons(tdata
);
878 #undef SET_LABEL_TEXT_UTF8
880 static void prefs_themes_display_global_stats(const ThemesData
*tdata
)
882 ThemesPage
*theme
= tdata
->page
;
883 GList
*tnames
= tdata
->names
;
889 while (tnames
!= NULL
) {
890 ThemeName
*tname
= (ThemeName
*)(tnames
->data
);
891 gchar
*tpath
= (gchar
*)(tname
->item
->data
);
893 if (IS_SYSTEM_THEME(tpath
))
895 else if (!IS_INTERNAL_THEME(tpath
))
898 tnames
= g_list_next(tnames
);
901 gstats
= g_strdup_printf(_("%d themes available (%d user, %d system, 1 internal)"),
903 gtk_label_set_text(GTK_LABEL(theme
->global
), gstats
);
904 gtk_label_set_justify (GTK_LABEL (theme
->global
), GTK_JUSTIFY_LEFT
);
905 gtkut_widget_set_small_font_size (theme
->global
);
909 #define INFOFILE_LINE_LEN 80
911 #define FGETS_INFOFILE_LINE() \
913 if (claws_fgets(line, INFOFILE_LINE_LEN, finfo) != NULL && (len = strlen(line)) > 0) { \
914 if (line[len - 1] == '\n') line[len - 1] = '\0'; \
917 g_strlcpy(line, _("Unknown"),sizeof(line)); \
920 static void prefs_themes_get_theme_info(ThemesData
*tdata
)
925 gchar line
[INFOFILE_LINE_LEN
];
928 ThemesPage
*theme
= tdata
->page
;
930 cm_return_if_fail(theme
!= NULL
);
931 path
= tdata
->displayed
;
932 cm_return_if_fail(path
!= NULL
);
934 debug_print("Getting theme info for %s\n", path
);
936 info
= g_new0(ThemeInfo
, 1);
938 if (IS_INTERNAL_THEME(path
)) {
939 info
->name
= g_strdup(_("Default internal theme"));
940 info
->author
= g_strdup(_("The Claws Mail Team"));
941 info
->url
= g_strdup(HOMEPAGE_URI
);
942 info
->status
= g_strdup_printf(_("Internal theme has %d icons"), N_STOCK_PIXMAPS
);
945 sinfo
= g_strconcat(path
, G_DIR_SEPARATOR_S
, THEMEINFO_FILE
, NULL
);
946 finfo
= claws_fopen(sinfo
, "r");
948 info
->name
= g_strdup(_("No info file available for this theme"));
949 info
->author
= g_strdup(_("Unknown"));
950 info
->url
= g_strdup(_("Unknown"));
953 FGETS_INFOFILE_LINE()
954 info
->name
= g_strdup(line
);
955 FGETS_INFOFILE_LINE()
956 info
->author
= g_strdup(line
);
957 FGETS_INFOFILE_LINE()
958 info
->url
= g_strdup(line
);
964 info
->status
= prefs_themes_get_theme_stats(path
);
965 if (info
->status
== NULL
) {
966 info
->status
= g_strdup(_("Error: couldn't get theme status"));
970 prefs_themes_display_theme_info(tdata
, info
);
973 g_free(info
->author
);
975 g_free(info
->status
);
980 #undef FGETS_INFOFILE_LINE
982 static gchar
*prefs_themes_get_theme_stats(const gchar
*dirname
)
988 dinfo
= g_new0(DirInfo
, 1);
989 dinfo
->supported
= stock_pixmap_theme_extensions();
990 for (i
= 0; (dinfo
->supported
)[i
] != NULL
; ++i
);
991 dinfo
->length
= g_malloc(i
* sizeof(gint
));
992 for (i
= 0; (dinfo
->supported
)[i
] != NULL
; ++i
) {
993 (dinfo
->length
)[i
] = strlen((dinfo
->supported
)[i
]);
995 prefs_themes_foreach_file(dirname
, prefs_themes_file_stats
, dinfo
);
996 stats
= g_strdup_printf(_("%d files (%d icons), size: %s"),
997 dinfo
->files
, dinfo
->pixms
,
998 to_human_readable((goffset
)dinfo
->bytes
));
999 g_free(dinfo
->length
);
1004 static void prefs_themes_create_widget(PrefsPage
*page
, GtkWindow
*window
, gpointer data
)
1006 ThemesPage
*prefs_themes
= (ThemesPage
*)page
;
1007 ThemesData
*tdata
= prefs_themes_data
;
1013 GtkWidget
*menu_themes
;
1014 GtkWidget
*btn_install
;
1015 GtkWidget
*btn_more
;
1016 GtkWidget
*label_global_status
;
1017 GtkWidget
*frame_info
;
1022 GtkWidget
*label_name
;
1023 GtkWidget
*label_author
;
1024 GtkWidget
*label_url
;
1026 GtkWidget
*label_status
;
1027 GtkWidget
*frame_preview
;
1036 GtkWidget
*btn_viewall
;
1037 GtkWidget
*frame_buttons
;
1038 GtkWidget
*hbuttonbox1
;
1039 GtkWidget
*btn_remove
;
1040 GtkCellRenderer
*renderer
;
1042 GtkWidget
*frame_scaling
;
1043 GtkWidget
*checkbtn_enable_alpha
;
1044 GtkWidget
*checkbtn_enable_scaling
;
1045 GtkWidget
*checkbtn_scaling_auto
;
1046 GtkWidget
*label_scaling_ppi
;
1047 GtkWidget
*spinbtn_scaling_ppi
;
1048 GtkAdjustment
*spinbtn_scaling_ppi_adj
;
1051 vbox1
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, VSPACING
);
1052 gtk_container_set_border_width (GTK_CONTAINER (vbox1
), 5);
1053 gtk_widget_show (vbox1
);
1055 vbox2
= gtkut_get_options_frame(vbox1
, &frame1
, _("Selector"));
1057 hbox3
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
1058 gtk_widget_show (hbox3
);
1059 gtk_box_pack_start (GTK_BOX (vbox2
), hbox3
, FALSE
, FALSE
, 0);
1060 // gtk_container_set_border_width (GTK_CONTAINER (hbox3), 5);
1062 menu_themes
= gtk_combo_box_new();
1063 gtk_widget_show (menu_themes
);
1064 gtk_box_pack_start (GTK_BOX (hbox3
), menu_themes
, FALSE
, FALSE
, 0);
1066 btn_install
= gtk_button_new_with_label (_("Install new..."));
1067 gtk_widget_show (btn_install
);
1068 gtk_box_pack_start (GTK_BOX (hbox3
), btn_install
, FALSE
, FALSE
, 0);
1069 gtk_widget_set_can_default (btn_install
, TRUE
);
1071 btn_more
= gtk_link_button_new_with_label(THEMES_URI
, _("Get more..."));
1072 gtk_widget_show (btn_more
);
1073 gtk_box_pack_start (GTK_BOX (hbox3
), btn_more
, FALSE
, FALSE
, 0);
1075 label_global_status
= gtk_label_new ("");
1076 gtk_widget_show (label_global_status
);
1077 gtk_box_pack_start (GTK_BOX (vbox2
), label_global_status
, FALSE
, FALSE
, 0);
1078 gtk_label_set_justify (GTK_LABEL (label_global_status
), GTK_JUSTIFY_LEFT
);
1079 gtk_label_set_xalign (GTK_LABEL (label_global_status
), 0.0);
1080 gtk_widget_set_margin_start(GTK_WIDGET(label_global_status
), 1);
1081 gtk_widget_set_margin_end(GTK_WIDGET(label_global_status
), 0);
1083 PACK_FRAME(vbox1
, frame_info
, _("Information"));
1085 table1
= gtk_grid_new();
1086 gtk_widget_show (table1
);
1087 gtk_container_add (GTK_CONTAINER (frame_info
), table1
);
1088 gtk_container_set_border_width (GTK_CONTAINER (table1
), 5);
1089 gtk_grid_set_row_spacing(GTK_GRID(table1
), 4);
1090 gtk_grid_set_column_spacing(GTK_GRID(table1
), 8);
1092 label1
= gtk_label_new (_("Name"));
1093 gtk_widget_show (label1
);
1094 gtk_label_set_justify (GTK_LABEL (label1
), GTK_JUSTIFY_LEFT
);
1095 gtk_label_set_xalign (GTK_LABEL (label1
), 1.0);
1096 gtk_grid_attach(GTK_GRID(table1
), label1
, 0, 0, 1, 1);
1098 label2
= gtk_label_new (_("Author"));
1099 gtk_widget_show (label2
);
1100 gtk_label_set_justify (GTK_LABEL (label2
), GTK_JUSTIFY_LEFT
);
1101 gtk_label_set_xalign (GTK_LABEL (label2
), 1.0);
1102 gtk_grid_attach(GTK_GRID(table1
), label2
, 0, 1, 1, 1);
1104 label3
= gtk_label_new (_("URL"));
1105 gtk_widget_show (label3
);
1106 gtk_label_set_xalign (GTK_LABEL (label3
), 1.0);
1107 gtk_grid_attach(GTK_GRID(table1
), label3
, 0, 2, 1, 1);
1109 label_name
= gtk_label_new ("");
1110 gtk_widget_show (label_name
);
1111 gtk_label_set_xalign (GTK_LABEL (label_name
), 0.0);
1112 gtk_grid_attach(GTK_GRID(table1
), label_name
, 1, 0, 1, 1);
1113 gtk_widget_set_hexpand(label_name
, TRUE
);
1114 gtk_widget_set_halign(label_name
, GTK_ALIGN_FILL
);
1116 label_author
= gtk_label_new ("");
1117 gtk_widget_show (label_author
);
1118 gtk_label_set_xalign (GTK_LABEL (label_author
), 0.0);
1119 gtk_grid_attach(GTK_GRID(table1
), label_author
, 1, 1, 1, 1);
1120 gtk_widget_set_hexpand(label_author
, TRUE
);
1121 gtk_widget_set_halign(label_author
, GTK_ALIGN_FILL
);
1123 label_url
= gtk_label_new ("");
1124 gtk_widget_show (label_url
);
1125 gtk_label_set_xalign (GTK_LABEL (label_url
), 0.0);
1126 gtk_grid_attach(GTK_GRID(table1
), label_url
, 1, 2, 1, 1);
1127 gtk_widget_set_hexpand(label_url
, TRUE
);
1128 gtk_widget_set_halign(label_url
, GTK_ALIGN_FILL
);
1130 label4
= gtk_label_new (_("Status"));
1131 gtk_widget_show (label4
);
1132 gtk_label_set_xalign (GTK_LABEL (label4
), 1.0);
1133 gtk_grid_attach(GTK_GRID(table1
), label4
, 0, 3, 1, 1);
1135 label_status
= gtk_label_new ("");
1136 gtk_widget_show (label_status
);
1137 gtk_label_set_xalign (GTK_LABEL (label_status
), 0.0);
1138 gtk_grid_attach(GTK_GRID(table1
), label_status
, 1, 3, 1, 1);
1139 gtk_widget_set_hexpand(label_status
, TRUE
);
1140 gtk_widget_set_halign(label_status
, GTK_ALIGN_FILL
);
1142 PACK_FRAME(vbox1
, frame_preview
, _("Preview"));
1144 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
1145 gtk_widget_show (hbox1
);
1146 gtk_container_add (GTK_CONTAINER (frame_preview
), hbox1
);
1147 gtk_container_set_border_width (GTK_CONTAINER (hbox1
), 5);
1149 icon_1
= gtk_image_new();
1150 gtk_widget_show (icon_1
);
1151 gtk_box_pack_start (GTK_BOX (hbox1
), icon_1
, TRUE
, TRUE
, 2);
1152 gtk_widget_set_margin_start(GTK_WIDGET(icon_1
), 0);
1153 gtk_widget_set_margin_end(GTK_WIDGET(icon_1
), 5);
1155 icon_2
= gtk_image_new();
1156 gtk_widget_show (icon_2
);
1157 gtk_box_pack_start (GTK_BOX (hbox1
), icon_2
, TRUE
, TRUE
, 2);
1158 gtk_widget_set_margin_start(GTK_WIDGET(icon_2
), 0);
1159 gtk_widget_set_margin_end(GTK_WIDGET(icon_2
), 5);
1161 icon_3
= gtk_image_new();
1162 gtk_widget_show (icon_3
);
1163 gtk_box_pack_start (GTK_BOX (hbox1
), icon_3
, TRUE
, TRUE
, 2);
1164 gtk_widget_set_margin_start(GTK_WIDGET(icon_3
), 0);
1165 gtk_widget_set_margin_end(GTK_WIDGET(icon_3
), 5);
1167 icon_4
= gtk_image_new();
1168 gtk_widget_show (icon_4
);
1169 gtk_box_pack_start (GTK_BOX (hbox1
), icon_4
, TRUE
, TRUE
, 2);
1170 gtk_widget_set_margin_start(GTK_WIDGET(icon_4
), 0);
1171 gtk_widget_set_margin_end(GTK_WIDGET(icon_4
), 5);
1173 icon_5
= gtk_image_new();
1174 gtk_widget_show (icon_5
);
1175 gtk_box_pack_start (GTK_BOX (hbox1
), icon_5
, TRUE
, TRUE
, 2);
1176 gtk_widget_set_margin_start(GTK_WIDGET(icon_5
), 0);
1177 gtk_widget_set_margin_end(GTK_WIDGET(icon_5
), 5);
1179 icon_6
= gtk_image_new();
1180 gtk_widget_show (icon_6
);
1181 gtk_box_pack_start (GTK_BOX (hbox1
), icon_6
, TRUE
, TRUE
, 2);
1182 gtk_widget_set_margin_start(GTK_WIDGET(icon_6
), 0);
1183 gtk_widget_set_margin_end(GTK_WIDGET(icon_6
), 5);
1185 icon_7
= gtk_image_new();
1186 gtk_widget_show (icon_7
);
1187 gtk_box_pack_start (GTK_BOX (hbox1
), icon_7
, TRUE
, TRUE
, 2);
1188 gtk_widget_set_margin_start(GTK_WIDGET(icon_7
), 0);
1189 gtk_widget_set_margin_end(GTK_WIDGET(icon_7
), 5);
1191 PACK_FRAME(vbox1
, frame_buttons
, _("Actions"));
1193 hbuttonbox1
= gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL
);
1194 gtk_widget_show (hbuttonbox1
);
1195 gtk_container_add (GTK_CONTAINER (frame_buttons
), hbuttonbox1
);
1196 gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1
), 8);
1197 gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1
), GTK_BUTTONBOX_START
);
1198 gtk_box_set_spacing (GTK_BOX (hbuttonbox1
), 5);
1200 btn_remove
= gtkut_stock_button("list-remove", _("_Remove"));
1201 gtk_widget_show (btn_remove
);
1202 gtk_container_add (GTK_CONTAINER (hbuttonbox1
), btn_remove
);
1203 gtk_widget_set_can_default (btn_remove
, TRUE
);
1205 btn_viewall
= gtk_button_new_with_label(_("View all"));
1206 gtk_widget_show (btn_viewall
);
1207 gtk_box_pack_start (GTK_BOX (hbuttonbox1
), btn_viewall
, FALSE
, FALSE
, 5);
1210 PACK_FRAME(vbox1
, frame_scaling
, _("SVG rendering"));
1212 vbox2
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, VSPACING
);
1213 gtk_widget_show (vbox2
);
1214 gtk_container_set_border_width (GTK_CONTAINER (vbox2
), 5);
1215 gtk_container_add (GTK_CONTAINER (frame_scaling
), vbox2
);
1217 PACK_CHECK_BUTTON(vbox2
, checkbtn_enable_alpha
, _("Enable alpha channel"));
1218 PACK_CHECK_BUTTON(vbox2
, checkbtn_enable_scaling
, _("Force scaling"));
1219 PACK_CHECK_BUTTON(vbox2
, checkbtn_scaling_auto
, _("Automatic"));
1221 hbox3
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5);
1222 gtk_widget_show (hbox3
);
1224 label_scaling_ppi
= gtk_label_new (_("Pixels per inch (PPI)"));
1225 gtk_widget_show (label_scaling_ppi
);
1226 gtk_box_pack_start (GTK_BOX (hbox3
), label_scaling_ppi
,
1229 spinbtn_scaling_ppi_adj
= GTK_ADJUSTMENT(
1230 gtk_adjustment_new (MIN_PPI
, MIN_PPI
, MAX_PPI
, 1, 10, 0));
1231 spinbtn_scaling_ppi
= gtk_spin_button_new(
1232 spinbtn_scaling_ppi_adj
, 1.0, 0);
1233 gtk_widget_show (spinbtn_scaling_ppi
);
1234 gtk_box_pack_start (GTK_BOX (hbox3
), spinbtn_scaling_ppi
,
1237 gtk_box_pack_start (GTK_BOX (vbox2
), hbox3
, FALSE
, FALSE
, 0);
1239 /* initialize widget values */
1240 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_enable_alpha
),
1241 prefs_common
.enable_alpha_svg
);
1242 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_enable_scaling
),
1243 prefs_common
.enable_pixmap_scaling
);
1244 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (checkbtn_scaling_auto
),
1245 prefs_common
.pixmap_scaling_auto
);
1246 gtk_spin_button_set_value(GTK_SPIN_BUTTON (spinbtn_scaling_ppi
),
1247 prefs_common
.pixmap_scaling_ppi
);
1250 gtk_widget_set_sensitive(checkbtn_scaling_auto
,
1251 prefs_common
.enable_pixmap_scaling
);
1252 gtk_widget_set_sensitive(spinbtn_scaling_ppi
,
1253 prefs_common
.enable_pixmap_scaling
1254 && !prefs_common
.pixmap_scaling_auto
);
1255 gtk_widget_set_sensitive(label_scaling_ppi
,
1256 prefs_common
.enable_pixmap_scaling
1257 && !prefs_common
.pixmap_scaling_auto
);
1260 g_signal_connect(G_OBJECT(checkbtn_enable_scaling
), "toggled",
1261 G_CALLBACK(prefs_themes_checkbtn_enable_scaling_toggled_cb
),
1263 g_signal_connect(G_OBJECT(checkbtn_scaling_auto
), "toggled",
1264 G_CALLBACK(prefs_themes_checkbtn_scaling_auto_toggled_cb
),
1268 g_signal_connect(G_OBJECT(btn_remove
), "clicked",
1269 G_CALLBACK(prefs_themes_btn_remove_clicked_cb
),
1271 g_signal_connect(G_OBJECT(btn_install
), "clicked",
1272 G_CALLBACK(prefs_themes_btn_install_clicked_cb
),
1274 g_signal_connect(G_OBJECT(btn_viewall
), "clicked",
1275 G_CALLBACK(prefs_themes_btn_viewall_clicked_cb
),
1278 prefs_themes
->window
= GTK_WIDGET(window
);
1280 prefs_themes
->name
= label_name
;
1281 prefs_themes
->author
= label_author
;
1282 prefs_themes
->url
= label_url
;
1283 prefs_themes
->status
= label_status
;
1284 prefs_themes
->global
= label_global_status
;
1286 prefs_themes
->icons
[0] = icon_1
;
1287 prefs_themes
->icons
[1] = icon_2
;
1288 prefs_themes
->icons
[2] = icon_3
;
1289 prefs_themes
->icons
[3] = icon_4
;
1290 prefs_themes
->icons
[4] = icon_5
;
1291 prefs_themes
->icons
[5] = icon_6
;
1292 prefs_themes
->icons
[6] = icon_7
;
1294 prefs_themes
->btn_remove
= btn_remove
;
1295 prefs_themes
->btn_install
= btn_install
;
1296 prefs_themes
->btn_more
= btn_more
;
1298 prefs_themes
->op_menu
= menu_themes
;
1301 prefs_themes
->checkbtn_enable_alpha
= checkbtn_enable_alpha
;
1302 prefs_themes
->checkbtn_enable_scaling
= checkbtn_enable_scaling
;
1303 prefs_themes
->checkbtn_scaling_auto
= checkbtn_scaling_auto
;
1304 prefs_themes
->label_scaling_ppi
= label_scaling_ppi
;
1305 prefs_themes
->spinbtn_scaling_ppi
= spinbtn_scaling_ppi
;
1308 prefs_themes
->page
.widget
= vbox1
;
1310 prefs_themes_set_themes_menu(GTK_COMBO_BOX(menu_themes
), tdata
);
1311 renderer
= gtk_cell_renderer_text_new();
1312 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(menu_themes
), renderer
, TRUE
);
1313 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(menu_themes
), renderer
,
1316 prefs_themes_get_theme_info(tdata
);
1317 prefs_themes_display_global_stats(tdata
);
1320 static void prefs_themes_destroy_widget(PrefsPage
*page
)
1322 /* ThemesPage *theme = (ThemesPage *)page; */
1325 static void prefs_themes_save(PrefsPage
*page
)
1327 ThemesData
*tdata
= prefs_themes_data
;
1328 gchar
*theme_str
= tdata
->displayed
;
1330 ThemesPage
*tpage
= (ThemesPage
*) page
;
1331 gboolean alpha
= prefs_common
.enable_alpha_svg
;
1332 gboolean scaling
= prefs_common
.enable_pixmap_scaling
;
1333 gboolean scaling_auto
= prefs_common
.pixmap_scaling_auto
;
1334 gint scaling_ppi
= prefs_common
.pixmap_scaling_ppi
;
1336 prefs_common
.enable_alpha_svg
= gtk_toggle_button_get_active(
1337 GTK_TOGGLE_BUTTON (tpage
->checkbtn_enable_alpha
));
1338 prefs_common
.enable_pixmap_scaling
= gtk_toggle_button_get_active(
1339 GTK_TOGGLE_BUTTON (tpage
->checkbtn_enable_scaling
));
1340 prefs_common
.pixmap_scaling_auto
= gtk_toggle_button_get_active(
1341 GTK_TOGGLE_BUTTON (tpage
->checkbtn_scaling_auto
));
1342 prefs_common
.pixmap_scaling_ppi
= gtk_spin_button_get_value_as_int (
1343 GTK_SPIN_BUTTON (tpage
->spinbtn_scaling_ppi
));
1346 if (!IS_CURRENT_THEME(theme_str
)) {
1347 debug_print("Changing theme to %s\n", theme_str
);
1348 g_free(prefs_common
.pixmap_theme_path
);
1350 prefs_common
.pixmap_theme_path
= g_strdup(theme_str
);
1352 main_window_reflect_prefs_all_real(TRUE
);
1353 compose_reflect_prefs_pixmap_theme();
1354 addrcompl_reflect_prefs_pixmap_theme();
1356 prefs_themes_update_buttons(tdata
);
1359 else if (scaling
!= prefs_common
.enable_pixmap_scaling
1360 || alpha
!= prefs_common
.enable_alpha_svg
1361 || (scaling_auto
!= prefs_common
.pixmap_scaling_auto
1362 && scaling_ppi
!= prefs_common
.pixmap_scaling_ppi
)) {
1363 /* same theme, different scaling options */
1364 debug_print("Updating theme scaling\n");
1365 stock_pixmap_invalidate_all_icons();
1366 main_window_reflect_prefs_all_real(TRUE
);
1367 compose_reflect_prefs_pixmap_theme();
1368 addrcompl_reflect_prefs_pixmap_theme();