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 <gdk/gdkkeysyms.h>
39 #include "ventoy_gtk.h"
41 int g_secure_boot_support
= 0;
42 GtkWidget
*g_topWindow
= NULL
;
43 GtkWidget
*g_partCfgWindow
= NULL
;
44 GtkBuilder
*g_pXmlBuilder
= NULL
;
45 GtkComboBoxText
*g_dev_combobox
= NULL
;
46 GtkButton
*g_refresh_button
= NULL
;
47 GtkButton
*g_install_button
= NULL
;
48 GtkButton
*g_update_button
= NULL
;
49 GtkMenu
*g_lang_menu
= NULL
;;
50 GtkCheckMenuItem
*g_menu_item_secure_boot
= NULL
;
51 GtkCheckMenuItem
*g_menu_item_mbr
= NULL
;
52 GtkCheckMenuItem
*g_menu_item_gpt
= NULL
;
53 GtkCheckMenuItem
*g_menu_item_show_all
= NULL
;
54 GtkLabel
*g_device_title
= NULL
;
55 GtkLabel
*g_label_local_part_style
= NULL
;
56 GtkLabel
*g_label_dev_part_style
= NULL
;
57 GtkLabel
*g_label_local_ver
= NULL
;
58 GtkLabel
*g_label_disk_ver
= NULL
;
59 GtkLabel
*g_label_status
= NULL
;
60 GtkImage
*g_image_secure_local
= NULL
;
61 GtkImage
*g_image_secure_device
= NULL
;
62 GtkToggleButton
*g_part_align_checkbox
= NULL
;
63 GtkToggleButton
*g_part_preserve_checkbox
= NULL
;
64 GtkEntry
*g_part_reserve_space_value
= NULL
;
65 GtkComboBoxText
*g_part_space_unit_combox
= NULL
;
66 GtkProgressBar
*g_progress_bar
= NULL
;
67 VTOY_JSON
*g_languages_json
= NULL
;
68 int g_languages_toggled_proc
= 0;
69 int g_dev_changed_proc
= 0;
70 gboolean g_align_part_with_4k
= TRUE
;
71 gboolean g_preserve_space_check
= FALSE
;
72 int g_preserve_space_unit
= 1;
73 int g_preserve_space_number
= 0;
74 gboolean g_thread_run
= FALSE
;
76 const char *language_string(const char *id
)
78 const char *pName
= NULL
;
79 VTOY_JSON
*node
= NULL
;
80 const char *pCurLang
= ventoy_code_get_cur_language();
82 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
84 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
85 if (0 == g_strcmp0(pName
, pCurLang
))
96 return vtoy_json_get_string_ex(node
->pstChild
, id
);
99 int msgbox(GtkMessageType type
, GtkButtonsType buttons
, const char *strid
)
102 GtkWidget
*pMsgBox
= NULL
;
104 pMsgBox
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, type
, buttons
, "%s", language_string(strid
));
106 ret
= gtk_dialog_run(GTK_DIALOG(pMsgBox
));
107 gtk_widget_destroy(pMsgBox
);
113 static void set_item_visible(const char *id
, int visible
)
115 GtkWidget
*pWidget
= NULL
;
117 pWidget
= GTK_WIDGET(gtk_builder_get_object(g_pXmlBuilder
, id
));
120 gtk_widget_show(pWidget
);
124 gtk_widget_hide(pWidget
);
128 static void init_part_style_menu(void)
132 style
= ventoy_code_get_cur_part_style();
133 gtk_check_menu_item_set_active(g_menu_item_mbr
, (0 == style
));
134 gtk_check_menu_item_set_active(g_menu_item_gpt
, (1 == style
));
135 gtk_label_set_text(g_label_local_part_style
, style
? "GPT" : "MBR");
138 static void select_language(const char *lang
)
140 const char *pName
= NULL
;
141 const char *pPos
= NULL
;
142 const char *pDevice
= NULL
;
143 VTOY_JSON
*node
= NULL
;
146 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
148 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
149 if (0 == g_strcmp0(pName
, lang
))
160 pDevice
= gtk_label_get_text(g_device_title
);
161 if (pDevice
&& (pPos
= strchr(pDevice
, '[')) != NULL
)
163 g_snprintf(device
, sizeof(device
), "%s %s", vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"), pPos
);
164 gtk_label_set_text(g_device_title
, device
);
168 gtk_label_set_text(g_device_title
, vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"));
171 LANG_LABEL_TEXT("label_local_ver", "STR_LOCAL_VER");
172 LANG_LABEL_TEXT("label_device_ver", "STR_DISK_VER");
174 LANG_LABEL_TEXT("label_status", "STR_STATUS");
176 LANG_BUTTON_TEXT("button_install", "STR_INSTALL");
177 LANG_BUTTON_TEXT("button_update", "STR_UPDATE");
179 LANG_MENU_ITEM_TEXT("menu_option", "STR_MENU_OPTION");
180 LANG_MENU_ITEM_TEXT("menu_item_secure", "STR_MENU_SECURE_BOOT");
181 LANG_MENU_ITEM_TEXT("menu_part_style", "STR_MENU_PART_STYLE");
182 LANG_MENU_ITEM_TEXT("menu_item_part_cfg", "STR_MENU_PART_CFG");
183 LANG_MENU_ITEM_TEXT("menu_item_clear", "STR_MENU_CLEAR");
184 LANG_MENU_ITEM_TEXT("menu_item_show_all", "STR_SHOW_ALL_DEV");
186 LANG_BUTTON_TEXT("space_check_btn", "STR_PRESERVE_SPACE");
187 LANG_BUTTON_TEXT("space_align_btn", "STR_PART_ALIGN_4KB");
188 LANG_BUTTON_TEXT("button_partcfg_ok", "STR_BTN_OK");
189 LANG_BUTTON_TEXT("button_partcfg_cancel", "STR_BTN_CANCEL");
191 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), vtoy_json_get_string_ex(node
->pstChild
, "STR_MENU_PART_CFG"));
197 gtk_widget_hide(g_topWindow
);
198 gtk_widget_show(g_topWindow
);
202 void on_secure_boot_toggled(GtkMenuItem
*menuItem
, gpointer data
)
204 g_secure_boot_support
= 1 - g_secure_boot_support
;
206 if (g_secure_boot_support
)
208 gtk_widget_show((GtkWidget
*)g_image_secure_local
);
212 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
216 void on_devlist_changed(GtkWidget
*widget
, gpointer data
)
219 ventoy_disk
*cur
= NULL
;
222 if (g_dev_changed_proc
== 0)
227 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
229 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
230 gtk_label_set_markup(g_label_disk_ver
, "");
231 gtk_label_set_text(g_label_dev_part_style
, "");
233 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
234 if (active
< 0 || active
>= g_disk_num
)
236 vlog("invalid active combox id %d\n", active
);
240 cur
= g_disk_list
+ active
;
241 if (cur
->vtoydata
.ventoy_valid
)
243 if (cur
->vtoydata
.secure_boot_flag
)
245 gtk_widget_show((GtkWidget
*)g_image_secure_device
);
249 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
252 if (g_secure_boot_support
!= cur
->vtoydata
.secure_boot_flag
)
254 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
257 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, cur
->vtoydata
.ventoy_ver
);
258 gtk_label_set_markup(g_label_disk_ver
, version
);
259 gtk_label_set_text(g_label_dev_part_style
, cur
->vtoydata
.partition_style
? "GPT" : "MBR");
261 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
265 if (g_secure_boot_support
)
267 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
273 void on_language_toggled(GtkMenuItem
*menuItem
, gpointer data
)
275 const char *cur_lang
= NULL
;
277 if (g_languages_toggled_proc
== 0)
282 cur_lang
= ventoy_code_get_cur_language();
283 if (g_strcmp0(cur_lang
, (char *)data
) != 0)
285 ventoy_code_set_cur_language((char *)data
);
286 select_language((char *)data
);
290 void on_part_style_toggled(GtkMenuItem
*menuItem
, gpointer data
)
294 style
= ventoy_code_get_cur_part_style();
295 ventoy_code_set_cur_part_style(1 - style
);
297 gtk_label_set_text(g_label_local_part_style
, style
? "MBR" : "GPT");
300 static ventoy_disk
*select_active_dev(const char *select
, int *activeid
)
304 ventoy_disk
*cur
= NULL
;
306 alldev
= ventoy_code_get_cur_show_all();
308 /* find the match one */
311 for (i
= 0; i
< g_disk_num
; i
++)
313 cur
= g_disk_list
+ i
;
314 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
319 if (strcmp(cur
->disk_name
, select
) == 0)
327 /* find the first one that installed with Ventoy */
328 for (i
= 0; i
< g_disk_num
; i
++)
330 cur
= g_disk_list
+ i
;
331 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
336 if (cur
->vtoydata
.ventoy_valid
)
343 /* find the first USB interface device */
344 for (i
= 0; i
< g_disk_num
; i
++)
346 cur
= g_disk_list
+ i
;
347 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
352 if (cur
->type
== VTOY_DEVICE_USB
)
359 /* use the first one */
360 for (i
= 0; i
< g_disk_num
; i
++)
362 cur
= g_disk_list
+ i
;
363 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
375 static void fill_dev_list(const char *select
)
382 ventoy_disk
*cur
= NULL
;
383 ventoy_disk
*active
= NULL
;
384 GtkListStore
*store
= NULL
;
386 g_dev_changed_proc
= 0;
388 alldev
= ventoy_code_get_cur_show_all();
390 vlog("fill_dev_list total disk: %d showall:%d\n", g_disk_num
, alldev
);
392 /* gtk_combo_box_text_remove_all */
393 store
= GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(g_dev_combobox
)));
394 gtk_list_store_clear(store
);
396 for (i
= 0; i
< g_disk_num
; i
++)
398 cur
= g_disk_list
+ i
;
400 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
405 g_snprintf(line
, sizeof(line
), "%s [%s] %s", cur
->disk_name
, cur
->human_readable_size
, cur
->disk_model
);
406 gtk_combo_box_text_append_text(g_dev_combobox
, line
);
410 active
= select_active_dev(select
, &activeid
);
413 vlog("combox count:%d, active:%s id:%d\n", count
, active
->disk_name
, activeid
);
414 gtk_combo_box_set_active((GtkComboBox
*)g_dev_combobox
, activeid
);
415 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
416 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), active
->vtoydata
.ventoy_valid
);
420 vlog("combox count:%d, no active id\n", count
);
421 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), FALSE
);
422 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
425 g_dev_changed_proc
= 1;
426 on_devlist_changed(NULL
, NULL
);
430 void on_show_all_toggled(GtkMenuItem
*menuItem
, gpointer data
)
432 int show_all
= ventoy_code_get_cur_show_all();
434 ventoy_code_set_cur_show_all(1 - show_all
);
438 void on_button_refresh_clicked(GtkWidget
*widget
, gpointer data
)
440 if (g_thread_run
|| ventoy_code_is_busy())
442 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
446 ventoy_code_refresh_device();
450 static void set_progress_bar_percent(int percent
)
453 const char *text
= NULL
;
456 gtk_progress_bar_set_fraction(g_progress_bar
, percent
* 1.0 / 100);
457 vlog("set percent %d\n", percent
);
459 text
= language_string("STR_STATUS");
462 gtk_label_set_text(g_label_status
, text
);
466 g_snprintf(tmp
, sizeof(tmp
), "%s", text
);
467 pos
= strchr(tmp
, '-');
470 g_snprintf(pos
+ 2, sizeof(tmp
), "%d%%", percent
);
471 gtk_label_set_text(g_label_status
, tmp
);
476 void on_clear_ventoy(GtkMenuItem
*menuItem
, gpointer data
)
483 ventoy_disk
*cur
= NULL
;
485 if (g_thread_run
|| ventoy_code_is_busy())
487 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
491 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
492 if (active
< 0 || active
>= g_disk_num
)
494 vlog("invalid active combox id %d\n", active
);
498 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
503 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
508 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
509 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
510 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
514 cur
= g_disk_list
+ active
;
515 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
516 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"clean\",\"disk\":\"%s\"}", disk_name
);
519 ventoy_func_handler(buf
, out
, sizeof(out
));
520 vlog("func handler clean <%s>\n", out
);
522 if (strstr(out
, "success"))
524 ret
= ventoy_code_get_result();
525 ventoy_code_refresh_device();
535 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_CLEAR_SUCCESS");
539 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_CLEAR_FAILED");
542 set_progress_bar_percent(0);
543 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
544 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
545 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
547 fill_dev_list(disk_name
);
548 g_thread_run
= FALSE
;
551 static int install_proc(ventoy_disk
*cur
)
563 vlog("install_thread ...\n");
565 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
567 buflen
= sizeof(buf
);
568 VTOY_JSON_FMT_BEGIN(pos
, buf
, buflen
);
569 VTOY_JSON_FMT_OBJ_BEGIN();
570 VTOY_JSON_FMT_STRN("method", "install");
571 VTOY_JSON_FMT_STRN("disk", disk_name
);
573 if (g_preserve_space_check
)
575 space
= g_preserve_space_number
;
576 if (g_preserve_space_unit
== 1)
578 space
= space
* 1024 * 1024 * 1024LL;
582 space
= space
* 1024 * 1024LL;
585 snprintf(dec
, sizeof(dec
), "%lld", space
);
586 VTOY_JSON_FMT_STRN("reserve_space", dec
);
590 VTOY_JSON_FMT_STRN("reserve_space", "0");
593 VTOY_JSON_FMT_UINT("partstyle", ventoy_code_get_cur_part_style());
594 VTOY_JSON_FMT_UINT("secure_boot", g_secure_boot_support
);
595 VTOY_JSON_FMT_UINT("align_4kb", g_align_part_with_4k
);
596 VTOY_JSON_FMT_OBJ_END();
597 VTOY_JSON_FMT_END(pos
);
600 ventoy_func_handler(buf
, out
, sizeof(out
));
601 vlog("func handler install <%s>\n", out
);
603 if (strstr(out
, "success"))
605 while (percent
!= 100)
607 percent
= ventoy_code_get_percent();
608 set_progress_bar_percent(percent
);
613 ret
= ventoy_code_get_result();
614 ventoy_code_refresh_device();
624 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_INSTALL_FAILED");
628 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_INSTALL_SUCCESS");
631 set_progress_bar_percent(0);
632 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
633 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
634 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
636 fill_dev_list(disk_name
);
637 g_thread_run
= FALSE
;
642 void on_button_install_clicked(GtkWidget
*widget
, gpointer data
)
647 ventoy_disk
*cur
= NULL
;
649 if (g_thread_run
|| ventoy_code_is_busy())
651 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
655 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
656 if (active
< 0 || active
>= g_disk_num
)
658 vlog("invalid active combox id %d\n", active
);
662 cur
= g_disk_list
+ active
;
664 if (ventoy_code_get_cur_part_style() == 0 && cur
->size_in_byte
> 2199023255552ULL)
666 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_DISK_2TB_MBR_ERROR");
670 if (g_preserve_space_check
)
672 space
= g_preserve_space_number
;
673 if (g_preserve_space_unit
== 1)
675 space
= space
* 1024;
682 size
= cur
->size_in_byte
/ SIZE_1MB
;
683 if (size
<= space
|| (size
- space
) <= (VTOYEFI_PART_BYTES
/ SIZE_1MB
))
685 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
686 vlog("reserved space value too big ...\n");
691 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
696 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
701 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
702 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
703 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
711 static int update_proc(ventoy_disk
*cur
)
719 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
720 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"update\",\"disk\":\"%s\",\"secure_boot\":%d}",
721 disk_name
, g_secure_boot_support
);
724 ventoy_func_handler(buf
, out
, sizeof(out
));
725 vlog("func handler update <%s>\n", out
);
727 if (strstr(out
, "success"))
729 while (percent
!= 100)
731 percent
= ventoy_code_get_percent();
732 set_progress_bar_percent(percent
);
737 ret
= ventoy_code_get_result();
738 ventoy_code_refresh_device();
748 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_UPDATE_FAILED");
752 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_UPDATE_SUCCESS");
755 set_progress_bar_percent(0);
756 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
757 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
758 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
760 fill_dev_list(disk_name
);
761 g_thread_run
= FALSE
;
767 void on_button_update_clicked(GtkWidget
*widget
, gpointer data
)
770 ventoy_disk
*cur
= NULL
;
772 if (g_thread_run
|| ventoy_code_is_busy())
774 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
778 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
779 if (active
< 0 || active
>= g_disk_num
)
781 vlog("invalid active combox id %d\n", active
);
784 cur
= g_disk_list
+ active
;
786 if (cur
->vtoydata
.ventoy_valid
== 0)
788 vlog("invalid ventoy version.\n");
792 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK_CANCEL
, "STR_UPDATE_TIP"))
797 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
798 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
799 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
806 static gint
lang_compare(gconstpointer a
, gconstpointer b
)
808 const char *name1
= (const char *)a
;
809 const char *name2
= (const char *)b
;
811 if (strncmp(name1
, "Chinese Simplified", 18) == 0)
815 else if (strncmp(name2
, "Chinese Simplified", 18) == 0)
821 return g_strcmp0(name1
, name2
);
825 static int load_languages(void)
830 const char *pCurLang
= NULL
;
831 const char *pName
= NULL
;
832 VTOY_JSON
*json
= NULL
;
833 VTOY_JSON
*node
= NULL
;
834 VTOY_JSON
*lang
= NULL
;
835 GSList
*pGroup
= NULL
;
836 GList
*pNameNode
= NULL
;
837 GList
*pNameList
= NULL
;
838 GtkRadioMenuItem
*pItem
= NULL
;
840 vlog("load_languages ...\n");
842 pCurLang
= ventoy_code_get_cur_language();
843 if (pCurLang
[0] == 0)
845 pName
= getenv("LANG");
846 if (pName
&& strncmp(pName
, "zh_CN", 5) == 0)
848 ventoy_code_set_cur_language("Chinese Simplified (ç®€ä½“ä¸æ–‡)");
852 ventoy_code_set_cur_language("English (English)");
854 pCurLang
= ventoy_code_get_cur_language();
857 vlog("current language <%s>\n", pCurLang
);
859 ventoy_read_file_to_buf("./tool/languages.json", 1, (void **)&pBuf
, &size
);
861 json
= vtoy_json_create();
862 vtoy_json_parse(json
, pBuf
);
863 g_languages_json
= json
;
865 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
867 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
870 pNameList
= g_list_append(pNameList
, (gpointer
)pName
);
873 for (lang
= node
->pstChild
; lang
; lang
= lang
->pstNext
)
875 if (lang
->enDataType
== JSON_TYPE_STRING
)
877 pCur
= lang
->unData
.pcStrVal
;
884 else if (*pCur
== '@')
894 pNameList
= g_list_sort(pNameList
, lang_compare
);
896 for (pNameNode
= g_list_first(pNameList
); pNameNode
; pNameNode
= g_list_next(pNameNode
))
898 pName
= (char *)(pNameNode
->data
);
899 pItem
= (GtkRadioMenuItem
*)gtk_radio_menu_item_new_with_label(pGroup
, pName
);
900 pGroup
= gtk_radio_menu_item_get_group(pItem
);
902 if (strcmp(pCurLang
, pName
) == 0)
904 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pItem
), TRUE
);
907 g_signal_connect(pItem
, "toggled", G_CALLBACK(on_language_toggled
), (gpointer
)pName
);
908 gtk_widget_show((GtkWidget
*)pItem
);
909 gtk_menu_shell_append(GTK_MENU_SHELL(g_lang_menu
), (GtkWidget
*)pItem
);
912 g_list_free(pNameList
);
915 select_language(pCurLang
);
916 g_languages_toggled_proc
= 1;
921 void on_part_cfg_ok(GtkWidget
*widget
, gpointer data
)
923 const char *pos
= NULL
;
924 const char *input
= NULL
;
926 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
930 input
= gtk_entry_get_text(g_part_reserve_space_value
);
931 if (input
== NULL
|| input
[0] == 0)
933 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
937 for (pos
= input
; *pos
; pos
++)
939 if (*pos
< '0' || *pos
>= '9')
941 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
946 g_preserve_space_unit
= gtk_combo_box_get_active((GtkComboBox
*)g_part_space_unit_combox
);
947 g_preserve_space_number
= (int)strtol(input
, NULL
, 10);
949 g_snprintf(device
, sizeof(device
), "%s [ -%d%s ]",
950 language_string("STR_DEVICE"), g_preserve_space_number
,
951 g_preserve_space_unit
? "GB" : "MB");
952 gtk_label_set_text(g_device_title
, device
);
956 gtk_label_set_text(g_device_title
, language_string("STR_DEVICE"));
959 g_preserve_space_check
= checked
;
960 g_align_part_with_4k
= gtk_toggle_button_get_active(g_part_align_checkbox
);
961 gtk_widget_hide(g_partCfgWindow
);
964 void on_part_cfg_cancel(GtkWidget
*widget
, gpointer data
)
966 gtk_widget_hide(g_partCfgWindow
);
969 int on_part_cfg_close(GtkWidget
*widget
, gpointer data
)
971 gtk_widget_hide(g_partCfgWindow
);
975 void on_part_config(GtkMenuItem
*menuItem
, gpointer data
)
979 gtk_toggle_button_set_active(g_part_align_checkbox
, g_align_part_with_4k
);
980 gtk_toggle_button_set_active(g_part_preserve_checkbox
, g_preserve_space_check
);
981 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), g_preserve_space_check
);
982 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), g_preserve_space_check
);
984 if (g_preserve_space_check
)
986 g_snprintf(value
, sizeof(value
), "%d", g_preserve_space_number
);
987 gtk_entry_set_text(g_part_reserve_space_value
, value
);
988 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
991 gtk_widget_show_all(g_partCfgWindow
);
994 void on_reserve_space_toggled(GtkMenuItem
*menuItem
, gpointer data
)
996 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
998 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), checked
);
999 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), checked
);
1002 static void init_part_cfg_window(GtkBuilder
*pBuilder
)
1004 #if GTK_CHECK_VERSION(3, 0, 0)
1005 GtkWidget
*pHeader
= NULL
;
1007 pHeader
= gtk_header_bar_new();
1008 gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(pHeader
), FALSE
);
1009 gtk_window_set_titlebar (GTK_WINDOW(g_partCfgWindow
), pHeader
);
1010 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), "Partition Configuration");
1013 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
1014 gtk_widget_set_sensitive (GTK_WIDGET(g_part_reserve_space_value
), FALSE
);
1015 gtk_widget_set_sensitive (GTK_WIDGET(g_part_space_unit_combox
), FALSE
);
1017 SIGNAL("space_check_btn", "toggled", on_reserve_space_toggled
);
1019 SIGNAL("button_partcfg_ok", "clicked", on_part_cfg_ok
);
1020 SIGNAL("button_partcfg_cancel", "clicked", on_part_cfg_cancel
);
1021 SIGNAL("part_cfg_dlg", "delete_event", on_part_cfg_close
);
1024 static void add_accelerator(GtkAccelGroup
*agMain
, void *widget
, const char *signal
, guint accel_key
)
1026 gtk_widget_add_accelerator(GTK_WIDGET(widget
), signal
, agMain
, accel_key
, GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
1027 gtk_widget_add_accelerator(GTK_WIDGET(widget
), signal
, agMain
, accel_key
, GDK_SHIFT_MASK
| GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
1030 void on_init_window(GtkBuilder
*pBuilder
)
1032 GSList
*pGroup
= NULL
;
1033 GtkAccelGroup
*agMain
= NULL
;
1036 vlog("on_init_window ...\n");
1038 g_pXmlBuilder
= pBuilder
;
1039 g_topWindow
= BUILDER_ITEM(GtkWidget
, "window");
1040 g_partCfgWindow
= BUILDER_ITEM(GtkWidget
, "part_cfg_dlg");
1042 g_dev_combobox
= BUILDER_ITEM(GtkComboBoxText
, "combobox_devlist");
1043 g_refresh_button
= BUILDER_ITEM(GtkButton
, "button_refresh");
1044 g_install_button
= BUILDER_ITEM(GtkButton
, "button_install");
1045 g_update_button
= BUILDER_ITEM(GtkButton
, "button_update");
1047 g_lang_menu
= BUILDER_ITEM(GtkMenu
, "submenu_language");
1048 g_menu_item_secure_boot
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_secure");
1049 g_menu_item_mbr
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_mbr");
1050 g_menu_item_gpt
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_gpt");
1051 g_menu_item_show_all
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_show_all");
1053 g_device_title
= BUILDER_ITEM(GtkLabel
, "label_device");
1054 g_label_local_part_style
= BUILDER_ITEM(GtkLabel
, "label_local_part_style");
1055 g_label_dev_part_style
= BUILDER_ITEM(GtkLabel
, "label_dev_part_style");
1057 g_label_local_ver
= BUILDER_ITEM(GtkLabel
, "label_local_ver_value");
1058 g_label_disk_ver
= BUILDER_ITEM(GtkLabel
, "label_dev_ver_value");
1060 g_label_status
= BUILDER_ITEM(GtkLabel
, "label_status");
1062 g_image_secure_local
= BUILDER_ITEM(GtkImage
, "image_secure_local");
1063 g_image_secure_device
= BUILDER_ITEM(GtkImage
, "image_secure_dev");
1065 g_part_preserve_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_check_btn");
1066 g_part_align_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_align_btn");
1068 g_part_reserve_space_value
= BUILDER_ITEM(GtkEntry
, "entry_reserve_space");
1069 g_part_space_unit_combox
= BUILDER_ITEM(GtkComboBoxText
, "comboboxtext_unit");
1071 g_progress_bar
= BUILDER_ITEM(GtkProgressBar
, "progressbar1");
1073 init_part_cfg_window(pBuilder
);
1076 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy1"), GTK_SHADOW_NONE
);
1077 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy2"), GTK_SHADOW_NONE
);
1080 pGroup
= gtk_radio_menu_item_get_group((GtkRadioMenuItem
*)g_menu_item_mbr
);
1081 gtk_radio_menu_item_set_group((GtkRadioMenuItem
*)g_menu_item_gpt
, pGroup
);
1083 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
1084 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
1086 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, ventoy_get_local_version());
1087 gtk_label_set_markup(g_label_local_ver
, version
);
1089 init_part_style_menu();
1090 gtk_check_menu_item_set_active(g_menu_item_show_all
, ventoy_code_get_cur_show_all());
1094 SIGNAL("combobox_devlist", "changed", on_devlist_changed
);
1096 SIGNAL("button_refresh", "clicked", on_button_refresh_clicked
);
1097 SIGNAL("button_install", "clicked", on_button_install_clicked
);
1098 SIGNAL("button_update", "clicked", on_button_update_clicked
);
1100 SIGNAL("menu_item_secure", "toggled", on_secure_boot_toggled
);
1101 SIGNAL("menu_item_mbr", "toggled", on_part_style_toggled
);
1102 SIGNAL("menu_item_show_all", "toggled", on_show_all_toggled
);
1104 SIGNAL("menu_item_part_cfg", "activate", on_part_config
);
1105 SIGNAL("menu_item_clear", "activate", on_clear_ventoy
);
1107 agMain
= gtk_accel_group_new();
1108 gtk_window_add_accel_group(GTK_WINDOW(g_topWindow
), agMain
);
1109 add_accelerator(agMain
, g_dev_combobox
, "popup", GDK_KEY_d
);
1110 add_accelerator(agMain
, g_install_button
, "clicked", GDK_KEY_i
);
1111 add_accelerator(agMain
, g_update_button
, "clicked", GDK_KEY_u
);
1112 add_accelerator(agMain
, g_refresh_button
, "clicked", GDK_KEY_r
);
1114 fill_dev_list(NULL
);
1119 int on_exit_window(GtkWidget
*widget
, gpointer data
)
1121 vlog("on_exit_window ...\n");
1123 if (g_thread_run
|| ventoy_code_is_busy())
1125 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
1129 ventoy_code_save_cfg();