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
;
666 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_4KN_UNSUPPORTED");
670 if (ventoy_code_get_cur_part_style() == 0 && cur
->size_in_byte
> 2199023255552ULL)
672 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_DISK_2TB_MBR_ERROR");
676 if (g_preserve_space_check
)
678 space
= g_preserve_space_number
;
679 if (g_preserve_space_unit
== 1)
681 space
= space
* 1024;
688 size
= cur
->size_in_byte
/ SIZE_1MB
;
689 if (size
<= space
|| (size
- space
) <= (VTOYEFI_PART_BYTES
/ SIZE_1MB
))
691 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
692 vlog("reserved space value too big ...\n");
697 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
702 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
707 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
708 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
709 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
717 static int update_proc(ventoy_disk
*cur
)
725 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
726 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"update\",\"disk\":\"%s\",\"secure_boot\":%d}",
727 disk_name
, g_secure_boot_support
);
730 ventoy_func_handler(buf
, out
, sizeof(out
));
731 vlog("func handler update <%s>\n", out
);
733 if (strstr(out
, "success"))
735 while (percent
!= 100)
737 percent
= ventoy_code_get_percent();
738 set_progress_bar_percent(percent
);
743 ret
= ventoy_code_get_result();
744 ventoy_code_refresh_device();
754 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_UPDATE_FAILED");
758 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_UPDATE_SUCCESS");
761 set_progress_bar_percent(0);
762 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
763 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
764 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
766 fill_dev_list(disk_name
);
767 g_thread_run
= FALSE
;
773 void on_button_update_clicked(GtkWidget
*widget
, gpointer data
)
776 ventoy_disk
*cur
= NULL
;
778 if (g_thread_run
|| ventoy_code_is_busy())
780 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
784 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
785 if (active
< 0 || active
>= g_disk_num
)
787 vlog("invalid active combox id %d\n", active
);
790 cur
= g_disk_list
+ active
;
792 if (cur
->vtoydata
.ventoy_valid
== 0)
794 vlog("invalid ventoy version.\n");
798 if (GTK_RESPONSE_OK
!= msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK_CANCEL
, "STR_UPDATE_TIP"))
803 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
804 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
805 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
812 static gint
lang_compare(gconstpointer a
, gconstpointer b
)
814 const char *name1
= (const char *)a
;
815 const char *name2
= (const char *)b
;
817 if (strncmp(name1
, "Chinese Simplified", 18) == 0)
821 else if (strncmp(name2
, "Chinese Simplified", 18) == 0)
827 return g_strcmp0(name1
, name2
);
831 static int load_languages(void)
836 const char *pCurLang
= NULL
;
837 const char *pName
= NULL
;
838 VTOY_JSON
*json
= NULL
;
839 VTOY_JSON
*node
= NULL
;
840 VTOY_JSON
*lang
= NULL
;
841 GSList
*pGroup
= NULL
;
842 GList
*pNameNode
= NULL
;
843 GList
*pNameList
= NULL
;
844 GtkRadioMenuItem
*pItem
= NULL
;
846 vlog("load_languages ...\n");
848 pCurLang
= ventoy_code_get_cur_language();
849 if (pCurLang
[0] == 0)
851 pName
= getenv("LANG");
852 if (pName
&& strncmp(pName
, "zh_CN", 5) == 0)
854 ventoy_code_set_cur_language("Chinese Simplified (ç®€ä½“ä¸æ–‡)");
858 ventoy_code_set_cur_language("English (English)");
860 pCurLang
= ventoy_code_get_cur_language();
863 vlog("current language <%s>\n", pCurLang
);
865 ventoy_read_file_to_buf("./tool/languages.json", 1, (void **)&pBuf
, &size
);
867 json
= vtoy_json_create();
868 vtoy_json_parse(json
, pBuf
);
869 g_languages_json
= json
;
871 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
873 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
876 pNameList
= g_list_append(pNameList
, (gpointer
)pName
);
879 for (lang
= node
->pstChild
; lang
; lang
= lang
->pstNext
)
881 if (lang
->enDataType
== JSON_TYPE_STRING
)
883 pCur
= lang
->unData
.pcStrVal
;
890 else if (*pCur
== '@')
900 pNameList
= g_list_sort(pNameList
, lang_compare
);
902 for (pNameNode
= g_list_first(pNameList
); pNameNode
; pNameNode
= g_list_next(pNameNode
))
904 pName
= (char *)(pNameNode
->data
);
905 pItem
= (GtkRadioMenuItem
*)gtk_radio_menu_item_new_with_label(pGroup
, pName
);
906 pGroup
= gtk_radio_menu_item_get_group(pItem
);
908 if (strcmp(pCurLang
, pName
) == 0)
910 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pItem
), TRUE
);
913 g_signal_connect(pItem
, "toggled", G_CALLBACK(on_language_toggled
), (gpointer
)pName
);
914 gtk_widget_show((GtkWidget
*)pItem
);
915 gtk_menu_shell_append(GTK_MENU_SHELL(g_lang_menu
), (GtkWidget
*)pItem
);
918 g_list_free(pNameList
);
921 select_language(pCurLang
);
922 g_languages_toggled_proc
= 1;
927 void on_part_cfg_ok(GtkWidget
*widget
, gpointer data
)
929 const char *pos
= NULL
;
930 const char *input
= NULL
;
932 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
936 input
= gtk_entry_get_text(g_part_reserve_space_value
);
937 if (input
== NULL
|| input
[0] == 0)
939 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
943 for (pos
= input
; *pos
; pos
++)
945 if (*pos
< '0' || *pos
> '9')
947 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
952 g_preserve_space_unit
= gtk_combo_box_get_active((GtkComboBox
*)g_part_space_unit_combox
);
953 g_preserve_space_number
= (int)strtol(input
, NULL
, 10);
955 g_snprintf(device
, sizeof(device
), "%s [ -%d%s ]",
956 language_string("STR_DEVICE"), g_preserve_space_number
,
957 g_preserve_space_unit
? "GB" : "MB");
958 gtk_label_set_text(g_device_title
, device
);
962 gtk_label_set_text(g_device_title
, language_string("STR_DEVICE"));
965 g_preserve_space_check
= checked
;
966 g_align_part_with_4k
= gtk_toggle_button_get_active(g_part_align_checkbox
);
967 gtk_widget_hide(g_partCfgWindow
);
970 void on_part_cfg_cancel(GtkWidget
*widget
, gpointer data
)
972 gtk_widget_hide(g_partCfgWindow
);
975 int on_part_cfg_close(GtkWidget
*widget
, gpointer data
)
977 gtk_widget_hide(g_partCfgWindow
);
981 void on_part_config(GtkMenuItem
*menuItem
, gpointer data
)
985 gtk_toggle_button_set_active(g_part_align_checkbox
, g_align_part_with_4k
);
986 gtk_toggle_button_set_active(g_part_preserve_checkbox
, g_preserve_space_check
);
987 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), g_preserve_space_check
);
988 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), g_preserve_space_check
);
990 if (g_preserve_space_check
)
992 g_snprintf(value
, sizeof(value
), "%d", g_preserve_space_number
);
993 gtk_entry_set_text(g_part_reserve_space_value
, value
);
994 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
997 gtk_widget_show_all(g_partCfgWindow
);
1000 void on_reserve_space_toggled(GtkMenuItem
*menuItem
, gpointer data
)
1002 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
1004 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), checked
);
1005 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), checked
);
1008 static void init_part_cfg_window(GtkBuilder
*pBuilder
)
1010 #if GTK_CHECK_VERSION(3, 0, 0)
1011 GtkWidget
*pHeader
= NULL
;
1013 pHeader
= gtk_header_bar_new();
1014 gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(pHeader
), FALSE
);
1015 gtk_window_set_titlebar (GTK_WINDOW(g_partCfgWindow
), pHeader
);
1016 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), "Partition Configuration");
1019 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
1020 gtk_widget_set_sensitive (GTK_WIDGET(g_part_reserve_space_value
), FALSE
);
1021 gtk_widget_set_sensitive (GTK_WIDGET(g_part_space_unit_combox
), FALSE
);
1023 SIGNAL("space_check_btn", "toggled", on_reserve_space_toggled
);
1025 SIGNAL("button_partcfg_ok", "clicked", on_part_cfg_ok
);
1026 SIGNAL("button_partcfg_cancel", "clicked", on_part_cfg_cancel
);
1027 SIGNAL("part_cfg_dlg", "delete_event", on_part_cfg_close
);
1030 static void add_accelerator(GtkAccelGroup
*agMain
, void *widget
, const char *signal
, guint accel_key
)
1032 gtk_widget_add_accelerator(GTK_WIDGET(widget
), signal
, agMain
, accel_key
, GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
1033 gtk_widget_add_accelerator(GTK_WIDGET(widget
), signal
, agMain
, accel_key
, GDK_SHIFT_MASK
| GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
1036 void on_init_window(GtkBuilder
*pBuilder
)
1038 GSList
*pGroup
= NULL
;
1039 GtkAccelGroup
*agMain
= NULL
;
1042 vlog("on_init_window ...\n");
1044 g_pXmlBuilder
= pBuilder
;
1045 g_topWindow
= BUILDER_ITEM(GtkWidget
, "window");
1046 g_partCfgWindow
= BUILDER_ITEM(GtkWidget
, "part_cfg_dlg");
1048 g_dev_combobox
= BUILDER_ITEM(GtkComboBoxText
, "combobox_devlist");
1049 g_refresh_button
= BUILDER_ITEM(GtkButton
, "button_refresh");
1050 g_install_button
= BUILDER_ITEM(GtkButton
, "button_install");
1051 g_update_button
= BUILDER_ITEM(GtkButton
, "button_update");
1053 g_lang_menu
= BUILDER_ITEM(GtkMenu
, "submenu_language");
1054 g_menu_item_secure_boot
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_secure");
1055 g_menu_item_mbr
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_mbr");
1056 g_menu_item_gpt
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_gpt");
1057 g_menu_item_show_all
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_show_all");
1059 g_device_title
= BUILDER_ITEM(GtkLabel
, "label_device");
1060 g_label_local_part_style
= BUILDER_ITEM(GtkLabel
, "label_local_part_style");
1061 g_label_dev_part_style
= BUILDER_ITEM(GtkLabel
, "label_dev_part_style");
1063 g_label_local_ver
= BUILDER_ITEM(GtkLabel
, "label_local_ver_value");
1064 g_label_disk_ver
= BUILDER_ITEM(GtkLabel
, "label_dev_ver_value");
1066 g_label_status
= BUILDER_ITEM(GtkLabel
, "label_status");
1068 g_image_secure_local
= BUILDER_ITEM(GtkImage
, "image_secure_local");
1069 g_image_secure_device
= BUILDER_ITEM(GtkImage
, "image_secure_dev");
1071 g_part_preserve_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_check_btn");
1072 g_part_align_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_align_btn");
1074 g_part_reserve_space_value
= BUILDER_ITEM(GtkEntry
, "entry_reserve_space");
1075 g_part_space_unit_combox
= BUILDER_ITEM(GtkComboBoxText
, "comboboxtext_unit");
1077 g_progress_bar
= BUILDER_ITEM(GtkProgressBar
, "progressbar1");
1079 init_part_cfg_window(pBuilder
);
1082 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy1"), GTK_SHADOW_NONE
);
1083 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy2"), GTK_SHADOW_NONE
);
1086 pGroup
= gtk_radio_menu_item_get_group((GtkRadioMenuItem
*)g_menu_item_mbr
);
1087 gtk_radio_menu_item_set_group((GtkRadioMenuItem
*)g_menu_item_gpt
, pGroup
);
1089 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
1090 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
1092 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, ventoy_get_local_version());
1093 gtk_label_set_markup(g_label_local_ver
, version
);
1095 init_part_style_menu();
1096 gtk_check_menu_item_set_active(g_menu_item_show_all
, ventoy_code_get_cur_show_all());
1100 SIGNAL("combobox_devlist", "changed", on_devlist_changed
);
1102 SIGNAL("button_refresh", "clicked", on_button_refresh_clicked
);
1103 SIGNAL("button_install", "clicked", on_button_install_clicked
);
1104 SIGNAL("button_update", "clicked", on_button_update_clicked
);
1106 SIGNAL("menu_item_secure", "toggled", on_secure_boot_toggled
);
1107 SIGNAL("menu_item_mbr", "toggled", on_part_style_toggled
);
1108 SIGNAL("menu_item_show_all", "toggled", on_show_all_toggled
);
1110 SIGNAL("menu_item_part_cfg", "activate", on_part_config
);
1111 SIGNAL("menu_item_clear", "activate", on_clear_ventoy
);
1113 agMain
= gtk_accel_group_new();
1114 gtk_window_add_accel_group(GTK_WINDOW(g_topWindow
), agMain
);
1115 add_accelerator(agMain
, g_dev_combobox
, "popup", GDK_KEY_d
);
1116 add_accelerator(agMain
, g_install_button
, "clicked", GDK_KEY_i
);
1117 add_accelerator(agMain
, g_update_button
, "clicked", GDK_KEY_u
);
1118 add_accelerator(agMain
, g_refresh_button
, "clicked", GDK_KEY_r
);
1120 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
1122 fill_dev_list(NULL
);
1127 int on_exit_window(GtkWidget
*widget
, gpointer data
)
1129 vlog("on_exit_window ...\n");
1131 if (g_thread_run
|| ventoy_code_is_busy())
1133 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
1137 ventoy_code_save_cfg();