1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 #include <linux/limits.h>
31 #include <ventoy_define.h>
32 #include <ventoy_json.h>
33 #include <ventoy_util.h>
34 #include <ventoy_disk.h>
35 #include <ventoy_http.h>
38 #include "ventoy_gtk.h"
40 int g_secure_boot_support
= 0;
41 GtkWidget
*g_topWindow
= NULL
;
42 GtkWidget
*g_partCfgWindow
= NULL
;
43 GtkBuilder
*g_pXmlBuilder
= NULL
;
44 GtkComboBoxText
*g_dev_combobox
= NULL
;
45 GtkButton
*g_refresh_button
= NULL
;
46 GtkButton
*g_install_button
= NULL
;
47 GtkButton
*g_update_button
= NULL
;
48 GtkMenu
*g_lang_menu
= NULL
;;
49 GtkCheckMenuItem
*g_menu_item_secure_boot
= NULL
;
50 GtkCheckMenuItem
*g_menu_item_mbr
= NULL
;
51 GtkCheckMenuItem
*g_menu_item_gpt
= NULL
;
52 GtkCheckMenuItem
*g_menu_item_show_all
= NULL
;
53 GtkLabel
*g_device_title
= NULL
;
54 GtkLabel
*g_label_local_part_style
= NULL
;
55 GtkLabel
*g_label_dev_part_style
= NULL
;
56 GtkLabel
*g_label_local_ver
= NULL
;
57 GtkLabel
*g_label_disk_ver
= NULL
;
58 GtkLabel
*g_label_status
= NULL
;
59 GtkImage
*g_image_secure_local
= NULL
;
60 GtkImage
*g_image_secure_device
= NULL
;
61 GtkToggleButton
*g_part_align_checkbox
= NULL
;
62 GtkToggleButton
*g_part_preserve_checkbox
= NULL
;
63 GtkEntry
*g_part_reserve_space_value
= NULL
;
64 GtkComboBoxText
*g_part_space_unit_combox
= NULL
;
65 GtkProgressBar
*g_progress_bar
= NULL
;
66 VTOY_JSON
*g_languages_json
= NULL
;
67 int g_languages_toggled_proc
= 0;
68 int g_dev_changed_proc
= 0;
69 gboolean g_align_part_with_4k
= TRUE
;
70 gboolean g_preserve_space_check
= FALSE
;
71 int g_preserve_space_unit
= 1;
72 int g_preserve_space_number
= 0;
73 gboolean g_thread_run
= FALSE
;
75 const char *language_string(const char *id
)
77 const char *pName
= NULL
;
78 VTOY_JSON
*node
= NULL
;
79 const char *pCurLang
= ventoy_code_get_cur_language();
81 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
83 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
84 if (0 == g_strcmp0(pName
, pCurLang
))
95 return vtoy_json_get_string_ex(node
->pstChild
, id
);
98 int msgbox(GtkMessageType type
, GtkButtonsType buttons
, const char *strid
)
101 GtkWidget
*pMsgBox
= NULL
;
103 pMsgBox
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, type
, buttons
, "%s", language_string(strid
));
105 ret
= gtk_dialog_run(GTK_DIALOG(pMsgBox
));
106 gtk_widget_destroy(pMsgBox
);
112 static void set_item_visible(const char *id
, int visible
)
114 GtkWidget
*pWidget
= NULL
;
116 pWidget
= GTK_WIDGET(gtk_builder_get_object(g_pXmlBuilder
, id
));
119 gtk_widget_show(pWidget
);
123 gtk_widget_hide(pWidget
);
127 static void init_part_style_menu(void)
131 style
= ventoy_code_get_cur_part_style();
132 gtk_check_menu_item_set_active(g_menu_item_mbr
, (0 == style
));
133 gtk_check_menu_item_set_active(g_menu_item_gpt
, (1 == style
));
134 gtk_label_set_text(g_label_local_part_style
, style
? "GPT" : "MBR");
137 static void select_language(const char *lang
)
139 const char *pName
= NULL
;
140 const char *pPos
= NULL
;
141 const char *pDevice
= NULL
;
142 VTOY_JSON
*node
= NULL
;
145 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
147 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
148 if (0 == g_strcmp0(pName
, lang
))
159 pDevice
= gtk_label_get_text(g_device_title
);
160 if (pDevice
&& (pPos
= strchr(pDevice
, '[')) != NULL
)
162 g_snprintf(device
, sizeof(device
), "%s %s", vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"), pPos
);
163 gtk_label_set_text(g_device_title
, device
);
167 gtk_label_set_text(g_device_title
, vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"));
170 LANG_LABEL_TEXT("label_local_ver", "STR_LOCAL_VER");
171 LANG_LABEL_TEXT("label_device_ver", "STR_DISK_VER");
173 LANG_LABEL_TEXT("label_status", "STR_STATUS");
175 LANG_BUTTON_TEXT("button_install", "STR_INSTALL");
176 LANG_BUTTON_TEXT("button_update", "STR_UPDATE");
178 LANG_MENU_ITEM_TEXT("menu_option", "STR_MENU_OPTION");
179 LANG_MENU_ITEM_TEXT("menu_item_secure", "STR_MENU_SECURE_BOOT");
180 LANG_MENU_ITEM_TEXT("menu_part_style", "STR_MENU_PART_STYLE");
181 LANG_MENU_ITEM_TEXT("menu_item_part_cfg", "STR_MENU_PART_CFG");
182 LANG_MENU_ITEM_TEXT("menu_item_clear", "STR_MENU_CLEAR");
183 LANG_MENU_ITEM_TEXT("menu_item_show_all", "STR_SHOW_ALL_DEV");
185 LANG_BUTTON_TEXT("space_check_btn", "STR_PRESERVE_SPACE");
186 LANG_BUTTON_TEXT("space_align_btn", "STR_PART_ALIGN_4KB");
187 LANG_BUTTON_TEXT("button_partcfg_ok", "STR_BTN_OK");
188 LANG_BUTTON_TEXT("button_partcfg_cancel", "STR_BTN_CANCEL");
190 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), vtoy_json_get_string_ex(node
->pstChild
, "STR_MENU_PART_CFG"));
196 gtk_widget_hide(g_topWindow
);
197 gtk_widget_show(g_topWindow
);
201 void on_secure_boot_toggled(GtkMenuItem
*menuItem
, gpointer data
)
203 g_secure_boot_support
= 1 - g_secure_boot_support
;
205 if (g_secure_boot_support
)
207 gtk_widget_show((GtkWidget
*)g_image_secure_local
);
211 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
215 void on_devlist_changed(GtkWidget
*widget
, gpointer data
)
218 ventoy_disk
*cur
= NULL
;
221 if (g_dev_changed_proc
== 0)
226 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
228 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
229 gtk_label_set_markup(g_label_disk_ver
, "");
230 gtk_label_set_text(g_label_dev_part_style
, "");
232 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
233 if (active
< 0 || active
>= g_disk_num
)
235 vlog("invalid active combox id %d\n", active
);
239 cur
= g_disk_list
+ active
;
240 if (cur
->vtoydata
.ventoy_valid
)
242 if (cur
->vtoydata
.secure_boot_flag
)
244 gtk_widget_show((GtkWidget
*)g_image_secure_device
);
248 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
251 if (g_secure_boot_support
!= cur
->vtoydata
.secure_boot_flag
)
253 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
256 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, cur
->vtoydata
.ventoy_ver
);
257 gtk_label_set_markup(g_label_disk_ver
, version
);
258 gtk_label_set_text(g_label_dev_part_style
, cur
->vtoydata
.partition_style
? "GPT" : "MBR");
260 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
264 if (g_secure_boot_support
)
266 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
272 void on_language_toggled(GtkMenuItem
*menuItem
, gpointer data
)
274 const char *cur_lang
= NULL
;
276 if (g_languages_toggled_proc
== 0)
281 cur_lang
= ventoy_code_get_cur_language();
282 if (g_strcmp0(cur_lang
, (char *)data
) != 0)
284 ventoy_code_set_cur_language((char *)data
);
285 select_language((char *)data
);
289 void on_part_style_toggled(GtkMenuItem
*menuItem
, gpointer data
)
293 style
= ventoy_code_get_cur_part_style();
294 ventoy_code_set_cur_part_style(1 - style
);
296 gtk_label_set_text(g_label_local_part_style
, style
? "MBR" : "GPT");
299 static ventoy_disk
*select_active_dev(const char *select
, int *activeid
)
303 ventoy_disk
*cur
= NULL
;
305 alldev
= ventoy_code_get_cur_show_all();
307 /* find the match one */
310 for (i
= 0; i
< g_disk_num
; i
++)
312 cur
= g_disk_list
+ i
;
313 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
318 if (strcmp(cur
->disk_name
, select
) == 0)
326 /* find the first one that installed with Ventoy */
327 for (i
= 0; i
< g_disk_num
; i
++)
329 cur
= g_disk_list
+ i
;
330 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
335 if (cur
->vtoydata
.ventoy_valid
)
342 /* find the first USB interface device */
343 for (i
= 0; i
< g_disk_num
; i
++)
345 cur
= g_disk_list
+ i
;
346 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
351 if (cur
->type
== VTOY_DEVICE_USB
)
358 /* use the first one */
359 for (i
= 0; i
< g_disk_num
; i
++)
361 cur
= g_disk_list
+ i
;
362 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
374 static void fill_dev_list(const char *select
)
381 ventoy_disk
*cur
= NULL
;
382 ventoy_disk
*active
= NULL
;
383 GtkListStore
*store
= NULL
;
385 g_dev_changed_proc
= 0;
387 alldev
= ventoy_code_get_cur_show_all();
389 vlog("fill_dev_list total disk: %d showall:%d\n", g_disk_num
, alldev
);
391 /* gtk_combo_box_text_remove_all */
392 store
= GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(g_dev_combobox
)));
393 gtk_list_store_clear(store
);
395 for (i
= 0; i
< g_disk_num
; i
++)
397 cur
= g_disk_list
+ i
;
399 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
404 g_snprintf(line
, sizeof(line
), "%s [%s] %s", cur
->disk_name
, cur
->human_readable_size
, cur
->disk_model
);
405 gtk_combo_box_text_append_text(g_dev_combobox
, line
);
409 active
= select_active_dev(select
, &activeid
);
412 vlog("combox count:%d, active:%s id:%d\n", count
, active
->disk_name
, activeid
);
413 gtk_combo_box_set_active((GtkComboBox
*)g_dev_combobox
, activeid
);
414 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
415 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), active
->vtoydata
.ventoy_valid
);
419 vlog("combox count:%d, no active id\n", count
);
420 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), FALSE
);
421 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
424 g_dev_changed_proc
= 1;
425 on_devlist_changed(NULL
, NULL
);
429 void on_show_all_toggled(GtkMenuItem
*menuItem
, gpointer data
)
431 int show_all
= ventoy_code_get_cur_show_all();
433 ventoy_code_set_cur_show_all(1 - show_all
);
437 void on_button_refresh_clicked(GtkWidget
*widget
, gpointer data
)
439 if (g_thread_run
|| ventoy_code_is_busy())
441 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
445 ventoy_code_refresh_device();
449 static void set_progress_bar_percent(int percent
)
452 const char *text
= NULL
;
455 gtk_progress_bar_set_fraction(g_progress_bar
, percent
* 1.0 / 100);
456 vlog("set percent %d\n", percent
);
458 text
= language_string("STR_STATUS");
461 gtk_label_set_text(g_label_status
, text
);
465 g_snprintf(tmp
, sizeof(tmp
), "%s", text
);
466 pos
= strchr(tmp
, '-');
469 g_snprintf(pos
+ 2, sizeof(tmp
), "%d%%", percent
);
470 gtk_label_set_text(g_label_status
, tmp
);
475 void on_clear_ventoy(GtkMenuItem
*menuItem
, gpointer data
)
482 ventoy_disk
*cur
= NULL
;
484 if (g_thread_run
|| ventoy_code_is_busy())
486 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
490 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
491 if (active
< 0 || active
>= g_disk_num
)
493 vlog("invalid active combox id %d\n", active
);
497 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
502 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
507 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
508 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
509 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
513 cur
= g_disk_list
+ active
;
514 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
515 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"clean\",\"disk\":\"%s\"}", disk_name
);
518 ventoy_func_handler(buf
, out
, sizeof(out
));
519 vlog("func handler clean <%s>\n", out
);
521 if (strstr(out
, "success"))
523 ret
= ventoy_code_get_result();
524 ventoy_code_refresh_device();
534 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_CLEAR_SUCCESS");
538 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_CLEAR_FAILED");
541 set_progress_bar_percent(0);
542 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
543 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
544 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
546 fill_dev_list(disk_name
);
547 g_thread_run
= FALSE
;
550 static int install_proc(ventoy_disk
*cur
)
562 vlog("install_thread ...\n");
564 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
566 buflen
= sizeof(buf
);
567 VTOY_JSON_FMT_BEGIN(pos
, buf
, buflen
);
568 VTOY_JSON_FMT_OBJ_BEGIN();
569 VTOY_JSON_FMT_STRN("method", "install");
570 VTOY_JSON_FMT_STRN("disk", disk_name
);
572 if (g_preserve_space_check
)
574 space
= g_preserve_space_number
;
575 if (g_preserve_space_unit
== 1)
577 space
= space
* 1024 * 1024 * 1024LL;
581 space
= space
* 1024 * 1024LL;
584 snprintf(dec
, sizeof(dec
), "%lld", space
);
585 VTOY_JSON_FMT_STRN("reserve_space", dec
);
589 VTOY_JSON_FMT_STRN("reserve_space", "0");
592 VTOY_JSON_FMT_UINT("partstyle", ventoy_code_get_cur_part_style());
593 VTOY_JSON_FMT_UINT("secure_boot", g_secure_boot_support
);
594 VTOY_JSON_FMT_UINT("align_4kb", g_align_part_with_4k
);
595 VTOY_JSON_FMT_OBJ_END();
596 VTOY_JSON_FMT_END(pos
);
599 ventoy_func_handler(buf
, out
, sizeof(out
));
600 vlog("func handler install <%s>\n", out
);
602 if (strstr(out
, "success"))
604 while (percent
!= 100)
606 percent
= ventoy_code_get_percent();
607 set_progress_bar_percent(percent
);
612 ret
= ventoy_code_get_result();
613 ventoy_code_refresh_device();
623 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_INSTALL_FAILED");
627 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_INSTALL_SUCCESS");
630 set_progress_bar_percent(0);
631 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
632 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
633 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
635 fill_dev_list(disk_name
);
636 g_thread_run
= FALSE
;
641 void on_button_install_clicked(GtkWidget
*widget
, gpointer data
)
646 ventoy_disk
*cur
= NULL
;
648 if (g_thread_run
|| ventoy_code_is_busy())
650 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
654 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
655 if (active
< 0 || active
>= g_disk_num
)
657 vlog("invalid active combox id %d\n", active
);
661 cur
= g_disk_list
+ active
;
663 if (ventoy_code_get_cur_part_style() == 0 && cur
->size_in_byte
> 2199023255552ULL)
665 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_DISK_2TB_MBR_ERROR");
669 if (g_preserve_space_check
)
671 space
= g_preserve_space_number
;
672 if (g_preserve_space_unit
== 1)
674 space
= space
* 1024;
681 size
= cur
->size_in_byte
/ SIZE_1MB
;
682 if (size
<= space
|| (size
- space
) <= (VTOYEFI_PART_BYTES
/ SIZE_1MB
))
684 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
685 vlog("reserved space value too big ...\n");
690 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
695 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
700 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
701 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
702 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
710 static int update_proc(ventoy_disk
*cur
)
718 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
719 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"update\",\"disk\":\"%s\",\"secure_boot\":%d}",
720 disk_name
, g_secure_boot_support
);
723 ventoy_func_handler(buf
, out
, sizeof(out
));
724 vlog("func handler update <%s>\n", out
);
726 if (strstr(out
, "success"))
728 while (percent
!= 100)
730 percent
= ventoy_code_get_percent();
731 set_progress_bar_percent(percent
);
736 ret
= ventoy_code_get_result();
737 ventoy_code_refresh_device();
747 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_UPDATE_FAILED");
751 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_UPDATE_SUCCESS");
754 set_progress_bar_percent(0);
755 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
756 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
757 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
759 fill_dev_list(disk_name
);
760 g_thread_run
= FALSE
;
766 void on_button_update_clicked(GtkWidget
*widget
, gpointer data
)
769 ventoy_disk
*cur
= NULL
;
771 if (g_thread_run
|| ventoy_code_is_busy())
773 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
777 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
778 if (active
< 0 || active
>= g_disk_num
)
780 vlog("invalid active combox id %d\n", active
);
783 cur
= g_disk_list
+ active
;
785 if (cur
->vtoydata
.ventoy_valid
== 0)
787 vlog("invalid ventoy version.\n");
791 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK_CANCEL
, "STR_UPDATE_TIP"))
796 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
797 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
798 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
805 static gint
lang_compare(gconstpointer a
, gconstpointer b
)
807 const char *name1
= (const char *)a
;
808 const char *name2
= (const char *)b
;
810 if (strncmp(name1
, "Chinese Simplified", 18) == 0)
814 else if (strncmp(name2
, "Chinese Simplified", 18) == 0)
820 return g_strcmp0(name1
, name2
);
824 static int load_languages(void)
829 const char *pCurLang
= NULL
;
830 const char *pName
= NULL
;
831 VTOY_JSON
*json
= NULL
;
832 VTOY_JSON
*node
= NULL
;
833 VTOY_JSON
*lang
= NULL
;
834 GSList
*pGroup
= NULL
;
835 GList
*pNameNode
= NULL
;
836 GList
*pNameList
= NULL
;
837 GtkRadioMenuItem
*pItem
= NULL
;
839 vlog("load_languages ...\n");
841 pCurLang
= ventoy_code_get_cur_language();
842 if (pCurLang
[0] == 0)
844 pName
= getenv("LANG");
845 if (pName
&& strncmp(pName
, "zh_CN", 5) == 0)
847 ventoy_code_set_cur_language("Chinese Simplified (ç®€ä½“ä¸æ–‡)");
851 ventoy_code_set_cur_language("English (English)");
853 pCurLang
= ventoy_code_get_cur_language();
856 vlog("current language <%s>\n", pCurLang
);
858 ventoy_read_file_to_buf("./tool/languages.json", 1, (void **)&pBuf
, &size
);
860 json
= vtoy_json_create();
861 vtoy_json_parse(json
, pBuf
);
862 g_languages_json
= json
;
864 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
866 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
869 pNameList
= g_list_append(pNameList
, (gpointer
)pName
);
872 for (lang
= node
->pstChild
; lang
; lang
= lang
->pstNext
)
874 if (lang
->enDataType
== JSON_TYPE_STRING
)
876 pCur
= lang
->unData
.pcStrVal
;
883 else if (*pCur
== '@')
893 pNameList
= g_list_sort(pNameList
, lang_compare
);
895 for (pNameNode
= g_list_first(pNameList
); pNameNode
; pNameNode
= g_list_next(pNameNode
))
897 pName
= (char *)(pNameNode
->data
);
898 pItem
= (GtkRadioMenuItem
*)gtk_radio_menu_item_new_with_label(pGroup
, pName
);
899 pGroup
= gtk_radio_menu_item_get_group(pItem
);
901 if (strcmp(pCurLang
, pName
) == 0)
903 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pItem
), TRUE
);
906 g_signal_connect(pItem
, "toggled", G_CALLBACK(on_language_toggled
), (gpointer
)pName
);
907 gtk_widget_show((GtkWidget
*)pItem
);
908 gtk_menu_shell_append(GTK_MENU_SHELL(g_lang_menu
), (GtkWidget
*)pItem
);
911 g_list_free(pNameList
);
914 select_language(pCurLang
);
915 g_languages_toggled_proc
= 1;
920 void on_part_cfg_ok(GtkWidget
*widget
, gpointer data
)
922 const char *pos
= NULL
;
923 const char *input
= NULL
;
925 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
929 input
= gtk_entry_get_text(g_part_reserve_space_value
);
930 if (input
== NULL
|| input
[0] == 0)
932 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
936 for (pos
= input
; *pos
; pos
++)
938 if (*pos
< '0' || *pos
>= '9')
940 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
945 g_preserve_space_unit
= gtk_combo_box_get_active((GtkComboBox
*)g_part_space_unit_combox
);
946 g_preserve_space_number
= (int)strtol(input
, NULL
, 10);
948 g_snprintf(device
, sizeof(device
), "%s [ -%d%s ]",
949 language_string("STR_DEVICE"), g_preserve_space_number
,
950 g_preserve_space_unit
? "GB" : "MB");
951 gtk_label_set_text(g_device_title
, device
);
955 gtk_label_set_text(g_device_title
, language_string("STR_DEVICE"));
958 g_preserve_space_check
= checked
;
959 g_align_part_with_4k
= gtk_toggle_button_get_active(g_part_align_checkbox
);
960 gtk_widget_hide(g_partCfgWindow
);
963 void on_part_cfg_cancel(GtkWidget
*widget
, gpointer data
)
965 gtk_widget_hide(g_partCfgWindow
);
968 int on_part_cfg_close(GtkWidget
*widget
, gpointer data
)
970 gtk_widget_hide(g_partCfgWindow
);
974 void on_part_config(GtkMenuItem
*menuItem
, gpointer data
)
978 gtk_toggle_button_set_active(g_part_align_checkbox
, g_align_part_with_4k
);
979 gtk_toggle_button_set_active(g_part_preserve_checkbox
, g_preserve_space_check
);
980 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), g_preserve_space_check
);
981 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), g_preserve_space_check
);
983 if (g_preserve_space_check
)
985 g_snprintf(value
, sizeof(value
), "%d", g_preserve_space_number
);
986 gtk_entry_set_text(g_part_reserve_space_value
, value
);
987 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
990 gtk_widget_show_all(g_partCfgWindow
);
993 void on_reserve_space_toggled(GtkMenuItem
*menuItem
, gpointer data
)
995 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
997 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), checked
);
998 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), checked
);
1001 static void init_part_cfg_window(GtkBuilder
*pBuilder
)
1003 #if GTK_CHECK_VERSION(3, 0, 0)
1004 GtkWidget
*pHeader
= NULL
;
1006 pHeader
= gtk_header_bar_new();
1007 gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(pHeader
), FALSE
);
1008 gtk_window_set_titlebar (GTK_WINDOW(g_partCfgWindow
), pHeader
);
1009 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), "Partition Configuration");
1012 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
1013 gtk_widget_set_sensitive (GTK_WIDGET(g_part_reserve_space_value
), FALSE
);
1014 gtk_widget_set_sensitive (GTK_WIDGET(g_part_space_unit_combox
), FALSE
);
1016 SIGNAL("space_check_btn", "toggled", on_reserve_space_toggled
);
1018 SIGNAL("button_partcfg_ok", "clicked", on_part_cfg_ok
);
1019 SIGNAL("button_partcfg_cancel", "clicked", on_part_cfg_cancel
);
1020 SIGNAL("part_cfg_dlg", "delete_event", on_part_cfg_close
);
1023 void on_init_window(GtkBuilder
*pBuilder
)
1025 GSList
*pGroup
= NULL
;
1028 vlog("on_init_window ...\n");
1030 g_pXmlBuilder
= pBuilder
;
1031 g_topWindow
= BUILDER_ITEM(GtkWidget
, "window");
1032 g_partCfgWindow
= BUILDER_ITEM(GtkWidget
, "part_cfg_dlg");
1034 g_dev_combobox
= BUILDER_ITEM(GtkComboBoxText
, "combobox_devlist");
1035 g_refresh_button
= BUILDER_ITEM(GtkButton
, "button_refresh");
1036 g_install_button
= BUILDER_ITEM(GtkButton
, "button_install");
1037 g_update_button
= BUILDER_ITEM(GtkButton
, "button_update");
1039 g_lang_menu
= BUILDER_ITEM(GtkMenu
, "submenu_language");
1040 g_menu_item_secure_boot
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_secure");
1041 g_menu_item_mbr
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_mbr");
1042 g_menu_item_gpt
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_gpt");
1043 g_menu_item_show_all
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_show_all");
1045 g_device_title
= BUILDER_ITEM(GtkLabel
, "label_device");
1046 g_label_local_part_style
= BUILDER_ITEM(GtkLabel
, "label_local_part_style");
1047 g_label_dev_part_style
= BUILDER_ITEM(GtkLabel
, "label_dev_part_style");
1049 g_label_local_ver
= BUILDER_ITEM(GtkLabel
, "label_local_ver_value");
1050 g_label_disk_ver
= BUILDER_ITEM(GtkLabel
, "label_dev_ver_value");
1052 g_label_status
= BUILDER_ITEM(GtkLabel
, "label_status");
1054 g_image_secure_local
= BUILDER_ITEM(GtkImage
, "image_secure_local");
1055 g_image_secure_device
= BUILDER_ITEM(GtkImage
, "image_secure_dev");
1057 g_part_preserve_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_check_btn");
1058 g_part_align_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_align_btn");
1060 g_part_reserve_space_value
= BUILDER_ITEM(GtkEntry
, "entry_reserve_space");
1061 g_part_space_unit_combox
= BUILDER_ITEM(GtkComboBoxText
, "comboboxtext_unit");
1063 g_progress_bar
= BUILDER_ITEM(GtkProgressBar
, "progressbar1");
1065 init_part_cfg_window(pBuilder
);
1068 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy1"), GTK_SHADOW_NONE
);
1069 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy2"), GTK_SHADOW_NONE
);
1072 pGroup
= gtk_radio_menu_item_get_group((GtkRadioMenuItem
*)g_menu_item_mbr
);
1073 gtk_radio_menu_item_set_group((GtkRadioMenuItem
*)g_menu_item_gpt
, pGroup
);
1075 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
1076 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
1078 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, ventoy_get_local_version());
1079 gtk_label_set_markup(g_label_local_ver
, version
);
1081 init_part_style_menu();
1082 gtk_check_menu_item_set_active(g_menu_item_show_all
, ventoy_code_get_cur_show_all());
1086 SIGNAL("combobox_devlist", "changed", on_devlist_changed
);
1088 SIGNAL("button_refresh", "clicked", on_button_refresh_clicked
);
1089 SIGNAL("button_install", "clicked", on_button_install_clicked
);
1090 SIGNAL("button_update", "clicked", on_button_update_clicked
);
1092 SIGNAL("menu_item_secure", "toggled", on_secure_boot_toggled
);
1093 SIGNAL("menu_item_mbr", "toggled", on_part_style_toggled
);
1094 SIGNAL("menu_item_show_all", "toggled", on_show_all_toggled
);
1096 SIGNAL("menu_item_part_cfg", "activate", on_part_config
);
1097 SIGNAL("menu_item_clear", "activate", on_clear_ventoy
);
1099 fill_dev_list(NULL
);
1104 int on_exit_window(GtkWidget
*widget
, gpointer data
)
1106 vlog("on_exit_window ...\n");
1108 if (g_thread_run
|| ventoy_code_is_busy())
1110 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
1114 ventoy_code_save_cfg();