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 vlog("on_secure_boot_toggled %d\n",g_secure_boot_support
);
207 if (g_secure_boot_support
)
209 gtk_widget_show((GtkWidget
*)g_image_secure_local
);
213 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
217 void on_devlist_changed(GtkWidget
*widget
, gpointer data
)
220 ventoy_disk
*cur
= NULL
;
223 if (g_dev_changed_proc
== 0)
228 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
230 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
231 gtk_label_set_markup(g_label_disk_ver
, "");
232 gtk_label_set_text(g_label_dev_part_style
, "");
234 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
235 if (active
< 0 || active
>= g_disk_num
)
237 vlog("invalid active combox id %d\n", active
);
241 cur
= g_disk_list
+ active
;
242 if (cur
->vtoydata
.ventoy_valid
)
244 if (cur
->vtoydata
.secure_boot_flag
)
246 gtk_widget_show((GtkWidget
*)g_image_secure_device
);
250 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
253 if (g_secure_boot_support
!= cur
->vtoydata
.secure_boot_flag
)
255 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
258 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, cur
->vtoydata
.ventoy_ver
);
259 gtk_label_set_markup(g_label_disk_ver
, version
);
260 gtk_label_set_text(g_label_dev_part_style
, cur
->vtoydata
.partition_style
? "GPT" : "MBR");
262 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
266 if (g_secure_boot_support
)
268 gtk_check_menu_item_set_active(g_menu_item_secure_boot
, 1 - g_secure_boot_support
);
274 void on_language_toggled(GtkMenuItem
*menuItem
, gpointer data
)
276 const char *cur_lang
= NULL
;
278 if (g_languages_toggled_proc
== 0)
283 cur_lang
= ventoy_code_get_cur_language();
284 if (g_strcmp0(cur_lang
, (char *)data
) != 0)
286 ventoy_code_set_cur_language((char *)data
);
287 select_language((char *)data
);
291 void on_part_style_toggled(GtkMenuItem
*menuItem
, gpointer data
)
295 style
= ventoy_code_get_cur_part_style();
296 ventoy_code_set_cur_part_style(1 - style
);
298 gtk_label_set_text(g_label_local_part_style
, style
? "MBR" : "GPT");
301 static ventoy_disk
*select_active_dev(const char *select
, int *activeid
)
305 ventoy_disk
*cur
= NULL
;
307 alldev
= ventoy_code_get_cur_show_all();
309 /* find the match one */
312 for (i
= 0; i
< g_disk_num
; i
++)
314 cur
= g_disk_list
+ i
;
315 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
320 if (strcmp(cur
->disk_name
, select
) == 0)
328 /* find the first one that installed with Ventoy */
329 for (i
= 0; i
< g_disk_num
; i
++)
331 cur
= g_disk_list
+ i
;
332 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
337 if (cur
->vtoydata
.ventoy_valid
)
344 /* find the first USB interface device */
345 for (i
= 0; i
< g_disk_num
; i
++)
347 cur
= g_disk_list
+ i
;
348 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
353 if (cur
->type
== VTOY_DEVICE_USB
)
360 /* use the first one */
361 for (i
= 0; i
< g_disk_num
; i
++)
363 cur
= g_disk_list
+ i
;
364 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
376 static void fill_dev_list(const char *select
)
383 ventoy_disk
*cur
= NULL
;
384 ventoy_disk
*active
= NULL
;
385 GtkListStore
*store
= NULL
;
387 g_dev_changed_proc
= 0;
389 alldev
= ventoy_code_get_cur_show_all();
391 vlog("fill_dev_list total disk: %d showall:%d\n", g_disk_num
, alldev
);
393 /* gtk_combo_box_text_remove_all */
394 store
= GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(g_dev_combobox
)));
395 gtk_list_store_clear(store
);
397 for (i
= 0; i
< g_disk_num
; i
++)
399 cur
= g_disk_list
+ i
;
401 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
406 g_snprintf(line
, sizeof(line
), "%s [%s] %s", cur
->disk_name
, cur
->human_readable_size
, cur
->disk_model
);
407 gtk_combo_box_text_append_text(g_dev_combobox
, line
);
411 active
= select_active_dev(select
, &activeid
);
414 vlog("combox count:%d, active:%s id:%d\n", count
, active
->disk_name
, activeid
);
415 gtk_combo_box_set_active((GtkComboBox
*)g_dev_combobox
, activeid
);
416 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
417 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), active
->vtoydata
.ventoy_valid
);
421 vlog("combox count:%d, no active id\n", count
);
422 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), FALSE
);
423 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
426 g_dev_changed_proc
= 1;
427 on_devlist_changed(NULL
, NULL
);
431 void on_show_all_toggled(GtkMenuItem
*menuItem
, gpointer data
)
433 int show_all
= ventoy_code_get_cur_show_all();
435 ventoy_code_set_cur_show_all(1 - show_all
);
439 void on_button_refresh_clicked(GtkWidget
*widget
, gpointer data
)
441 if (g_thread_run
|| ventoy_code_is_busy())
443 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
447 ventoy_code_refresh_device();
451 static void set_progress_bar_percent(int percent
)
454 const char *text
= NULL
;
457 gtk_progress_bar_set_fraction(g_progress_bar
, percent
* 1.0 / 100);
458 vlog("set percent %d\n", percent
);
460 text
= language_string("STR_STATUS");
463 gtk_label_set_text(g_label_status
, text
);
467 g_snprintf(tmp
, sizeof(tmp
), "%s", text
);
468 pos
= strchr(tmp
, '-');
471 g_snprintf(pos
+ 2, sizeof(tmp
), "%d%%", percent
);
472 gtk_label_set_text(g_label_status
, tmp
);
477 void on_clear_ventoy(GtkMenuItem
*menuItem
, gpointer data
)
484 ventoy_disk
*cur
= NULL
;
486 if (g_thread_run
|| ventoy_code_is_busy())
488 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
492 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
493 if (active
< 0 || active
>= g_disk_num
)
495 vlog("invalid active combox id %d\n", active
);
499 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
504 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
509 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
510 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
511 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
515 cur
= g_disk_list
+ active
;
516 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
517 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"clean\",\"disk\":\"%s\"}", disk_name
);
520 ventoy_func_handler(buf
, out
, sizeof(out
));
521 vlog("func handler clean <%s>\n", out
);
523 if (strstr(out
, "success"))
525 ret
= ventoy_code_get_result();
526 ventoy_code_refresh_device();
536 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_CLEAR_SUCCESS");
540 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_CLEAR_FAILED");
543 set_progress_bar_percent(0);
544 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
545 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
546 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
548 fill_dev_list(disk_name
);
549 g_thread_run
= FALSE
;
552 static int install_proc(ventoy_disk
*cur
)
564 vlog("install_thread ...\n");
566 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
568 buflen
= sizeof(buf
);
569 VTOY_JSON_FMT_BEGIN(pos
, buf
, buflen
);
570 VTOY_JSON_FMT_OBJ_BEGIN();
571 VTOY_JSON_FMT_STRN("method", "install");
572 VTOY_JSON_FMT_STRN("disk", disk_name
);
574 if (g_preserve_space_check
)
576 space
= g_preserve_space_number
;
577 if (g_preserve_space_unit
== 1)
579 space
= space
* 1024 * 1024 * 1024LL;
583 space
= space
* 1024 * 1024LL;
586 snprintf(dec
, sizeof(dec
), "%lld", space
);
587 VTOY_JSON_FMT_STRN("reserve_space", dec
);
591 VTOY_JSON_FMT_STRN("reserve_space", "0");
594 VTOY_JSON_FMT_UINT("partstyle", ventoy_code_get_cur_part_style());
595 VTOY_JSON_FMT_UINT("secure_boot", g_secure_boot_support
);
596 VTOY_JSON_FMT_UINT("align_4kb", g_align_part_with_4k
);
597 VTOY_JSON_FMT_OBJ_END();
598 VTOY_JSON_FMT_END(pos
);
601 ventoy_func_handler(buf
, out
, sizeof(out
));
602 vlog("func handler install <%s>\n", out
);
604 if (strstr(out
, "success"))
606 while (percent
!= 100)
608 percent
= ventoy_code_get_percent();
609 set_progress_bar_percent(percent
);
614 ret
= ventoy_code_get_result();
615 ventoy_code_refresh_device();
625 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_INSTALL_FAILED");
629 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_INSTALL_SUCCESS");
632 set_progress_bar_percent(0);
633 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
634 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
635 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
637 fill_dev_list(disk_name
);
638 g_thread_run
= FALSE
;
643 void on_button_install_clicked(GtkWidget
*widget
, gpointer data
)
648 ventoy_disk
*cur
= NULL
;
650 if (g_thread_run
|| ventoy_code_is_busy())
652 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
656 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
657 if (active
< 0 || active
>= g_disk_num
)
659 vlog("invalid active combox id %d\n", active
);
663 cur
= g_disk_list
+ active
;
665 if (ventoy_code_get_cur_part_style() == 0 && cur
->size_in_byte
> 2199023255552ULL)
667 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_DISK_2TB_MBR_ERROR");
671 if (g_preserve_space_check
)
673 space
= g_preserve_space_number
;
674 if (g_preserve_space_unit
== 1)
676 space
= space
* 1024;
683 size
= cur
->size_in_byte
/ SIZE_1MB
;
684 if (size
<= space
|| (size
- space
) <= (VTOYEFI_PART_BYTES
/ SIZE_1MB
))
686 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
687 vlog("reserved space value too big ...\n");
692 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
697 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
702 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
703 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
704 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
712 static int update_proc(ventoy_disk
*cur
)
720 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
721 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"update\",\"disk\":\"%s\",\"secure_boot\":%d}",
722 disk_name
, g_secure_boot_support
);
725 ventoy_func_handler(buf
, out
, sizeof(out
));
726 vlog("func handler update <%s>\n", out
);
728 if (strstr(out
, "success"))
730 while (percent
!= 100)
732 percent
= ventoy_code_get_percent();
733 set_progress_bar_percent(percent
);
738 ret
= ventoy_code_get_result();
739 ventoy_code_refresh_device();
749 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_UPDATE_FAILED");
753 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_UPDATE_SUCCESS");
756 set_progress_bar_percent(0);
757 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
758 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
759 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
761 fill_dev_list(disk_name
);
762 g_thread_run
= FALSE
;
768 void on_button_update_clicked(GtkWidget
*widget
, gpointer data
)
771 ventoy_disk
*cur
= NULL
;
773 if (g_thread_run
|| ventoy_code_is_busy())
775 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
779 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
780 if (active
< 0 || active
>= g_disk_num
)
782 vlog("invalid active combox id %d\n", active
);
785 cur
= g_disk_list
+ active
;
787 if (cur
->vtoydata
.ventoy_valid
== 0)
789 vlog("invalid ventoy version.\n");
793 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK_CANCEL
, "STR_UPDATE_TIP"))
798 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
799 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
800 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
807 static gint
lang_compare(gconstpointer a
, gconstpointer b
)
809 const char *name1
= (const char *)a
;
810 const char *name2
= (const char *)b
;
812 if (strncmp(name1
, "Chinese Simplified", 18) == 0)
816 else if (strncmp(name2
, "Chinese Simplified", 18) == 0)
822 return g_strcmp0(name1
, name2
);
826 static int load_languages(void)
831 const char *pCurLang
= NULL
;
832 const char *pName
= NULL
;
833 VTOY_JSON
*json
= NULL
;
834 VTOY_JSON
*node
= NULL
;
835 VTOY_JSON
*lang
= NULL
;
836 GSList
*pGroup
= NULL
;
837 GList
*pNameNode
= NULL
;
838 GList
*pNameList
= NULL
;
839 GtkRadioMenuItem
*pItem
= NULL
;
841 vlog("load_languages ...\n");
843 pCurLang
= ventoy_code_get_cur_language();
844 if (pCurLang
[0] == 0)
846 pName
= getenv("LANG");
847 if (pName
&& strncmp(pName
, "zh_CN", 5) == 0)
849 ventoy_code_set_cur_language("Chinese Simplified (ç®€ä½“ä¸æ–‡)");
853 ventoy_code_set_cur_language("English (English)");
855 pCurLang
= ventoy_code_get_cur_language();
858 vlog("current language <%s>\n", pCurLang
);
860 ventoy_read_file_to_buf("./tool/languages.json", 1, (void **)&pBuf
, &size
);
862 json
= vtoy_json_create();
863 vtoy_json_parse(json
, pBuf
);
864 g_languages_json
= json
;
866 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
868 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
871 pNameList
= g_list_append(pNameList
, (gpointer
)pName
);
874 for (lang
= node
->pstChild
; lang
; lang
= lang
->pstNext
)
876 if (lang
->enDataType
== JSON_TYPE_STRING
)
878 pCur
= lang
->unData
.pcStrVal
;
885 else if (*pCur
== '@')
895 pNameList
= g_list_sort(pNameList
, lang_compare
);
897 for (pNameNode
= g_list_first(pNameList
); pNameNode
; pNameNode
= g_list_next(pNameNode
))
899 pName
= (char *)(pNameNode
->data
);
900 pItem
= (GtkRadioMenuItem
*)gtk_radio_menu_item_new_with_label(pGroup
, pName
);
901 pGroup
= gtk_radio_menu_item_get_group(pItem
);
903 if (strcmp(pCurLang
, pName
) == 0)
905 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pItem
), TRUE
);
908 g_signal_connect(pItem
, "toggled", G_CALLBACK(on_language_toggled
), (gpointer
)pName
);
909 gtk_widget_show((GtkWidget
*)pItem
);
910 gtk_menu_shell_append(GTK_MENU_SHELL(g_lang_menu
), (GtkWidget
*)pItem
);
913 g_list_free(pNameList
);
916 select_language(pCurLang
);
917 g_languages_toggled_proc
= 1;
922 void on_part_cfg_ok(GtkWidget
*widget
, gpointer data
)
924 const char *pos
= NULL
;
925 const char *input
= NULL
;
927 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
931 input
= gtk_entry_get_text(g_part_reserve_space_value
);
932 if (input
== NULL
|| input
[0] == 0)
934 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
938 for (pos
= input
; *pos
; pos
++)
940 if (*pos
< '0' || *pos
>= '9')
942 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
947 g_preserve_space_unit
= gtk_combo_box_get_active((GtkComboBox
*)g_part_space_unit_combox
);
948 g_preserve_space_number
= (int)strtol(input
, NULL
, 10);
950 g_snprintf(device
, sizeof(device
), "%s [ -%d%s ]",
951 language_string("STR_DEVICE"), g_preserve_space_number
,
952 g_preserve_space_unit
? "GB" : "MB");
953 gtk_label_set_text(g_device_title
, device
);
957 gtk_label_set_text(g_device_title
, language_string("STR_DEVICE"));
960 g_preserve_space_check
= checked
;
961 g_align_part_with_4k
= gtk_toggle_button_get_active(g_part_align_checkbox
);
962 gtk_widget_hide(g_partCfgWindow
);
965 void on_part_cfg_cancel(GtkWidget
*widget
, gpointer data
)
967 gtk_widget_hide(g_partCfgWindow
);
970 int on_part_cfg_close(GtkWidget
*widget
, gpointer data
)
972 gtk_widget_hide(g_partCfgWindow
);
976 void on_part_config(GtkMenuItem
*menuItem
, gpointer data
)
980 gtk_toggle_button_set_active(g_part_align_checkbox
, g_align_part_with_4k
);
981 gtk_toggle_button_set_active(g_part_preserve_checkbox
, g_preserve_space_check
);
982 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), g_preserve_space_check
);
983 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), g_preserve_space_check
);
985 if (g_preserve_space_check
)
987 g_snprintf(value
, sizeof(value
), "%d", g_preserve_space_number
);
988 gtk_entry_set_text(g_part_reserve_space_value
, value
);
989 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
992 gtk_widget_show_all(g_partCfgWindow
);
995 void on_reserve_space_toggled(GtkMenuItem
*menuItem
, gpointer data
)
997 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
999 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), checked
);
1000 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), checked
);
1003 static void init_part_cfg_window(GtkBuilder
*pBuilder
)
1005 #if GTK_CHECK_VERSION(3, 0, 0)
1006 GtkWidget
*pHeader
= NULL
;
1008 pHeader
= gtk_header_bar_new();
1009 gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(pHeader
), FALSE
);
1010 gtk_window_set_titlebar (GTK_WINDOW(g_partCfgWindow
), pHeader
);
1011 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), "Partition Configuration");
1014 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
1015 gtk_widget_set_sensitive (GTK_WIDGET(g_part_reserve_space_value
), FALSE
);
1016 gtk_widget_set_sensitive (GTK_WIDGET(g_part_space_unit_combox
), FALSE
);
1018 SIGNAL("space_check_btn", "toggled", on_reserve_space_toggled
);
1020 SIGNAL("button_partcfg_ok", "clicked", on_part_cfg_ok
);
1021 SIGNAL("button_partcfg_cancel", "clicked", on_part_cfg_cancel
);
1022 SIGNAL("part_cfg_dlg", "delete_event", on_part_cfg_close
);
1025 void on_init_window(GtkBuilder
*pBuilder
)
1027 GSList
*pGroup
= NULL
;
1030 vlog("on_init_window ...\n");
1032 g_pXmlBuilder
= pBuilder
;
1033 g_topWindow
= BUILDER_ITEM(GtkWidget
, "window");
1034 g_partCfgWindow
= BUILDER_ITEM(GtkWidget
, "part_cfg_dlg");
1036 g_dev_combobox
= BUILDER_ITEM(GtkComboBoxText
, "combobox_devlist");
1037 g_refresh_button
= BUILDER_ITEM(GtkButton
, "button_refresh");
1038 g_install_button
= BUILDER_ITEM(GtkButton
, "button_install");
1039 g_update_button
= BUILDER_ITEM(GtkButton
, "button_update");
1041 g_lang_menu
= BUILDER_ITEM(GtkMenu
, "submenu_language");
1042 g_menu_item_secure_boot
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_secure");
1043 g_menu_item_mbr
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_mbr");
1044 g_menu_item_gpt
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_gpt");
1045 g_menu_item_show_all
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_show_all");
1047 g_device_title
= BUILDER_ITEM(GtkLabel
, "label_device");
1048 g_label_local_part_style
= BUILDER_ITEM(GtkLabel
, "label_local_part_style");
1049 g_label_dev_part_style
= BUILDER_ITEM(GtkLabel
, "label_dev_part_style");
1051 g_label_local_ver
= BUILDER_ITEM(GtkLabel
, "label_local_ver_value");
1052 g_label_disk_ver
= BUILDER_ITEM(GtkLabel
, "label_dev_ver_value");
1054 g_label_status
= BUILDER_ITEM(GtkLabel
, "label_status");
1056 g_image_secure_local
= BUILDER_ITEM(GtkImage
, "image_secure_local");
1057 g_image_secure_device
= BUILDER_ITEM(GtkImage
, "image_secure_dev");
1059 g_part_preserve_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_check_btn");
1060 g_part_align_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_align_btn");
1062 g_part_reserve_space_value
= BUILDER_ITEM(GtkEntry
, "entry_reserve_space");
1063 g_part_space_unit_combox
= BUILDER_ITEM(GtkComboBoxText
, "comboboxtext_unit");
1065 g_progress_bar
= BUILDER_ITEM(GtkProgressBar
, "progressbar1");
1067 init_part_cfg_window(pBuilder
);
1070 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy1"), GTK_SHADOW_NONE
);
1071 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy2"), GTK_SHADOW_NONE
);
1074 pGroup
= gtk_radio_menu_item_get_group((GtkRadioMenuItem
*)g_menu_item_mbr
);
1075 gtk_radio_menu_item_set_group((GtkRadioMenuItem
*)g_menu_item_gpt
, pGroup
);
1077 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
1078 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
1080 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, ventoy_get_local_version());
1081 gtk_label_set_markup(g_label_local_ver
, version
);
1083 init_part_style_menu();
1084 gtk_check_menu_item_set_active(g_menu_item_show_all
, ventoy_code_get_cur_show_all());
1088 SIGNAL("combobox_devlist", "changed", on_devlist_changed
);
1090 SIGNAL("button_refresh", "clicked", on_button_refresh_clicked
);
1091 SIGNAL("button_install", "clicked", on_button_install_clicked
);
1092 SIGNAL("button_update", "clicked", on_button_update_clicked
);
1094 SIGNAL("menu_item_secure", "toggled", on_secure_boot_toggled
);
1095 SIGNAL("menu_item_mbr", "toggled", on_part_style_toggled
);
1096 SIGNAL("menu_item_show_all", "toggled", on_show_all_toggled
);
1098 SIGNAL("menu_item_part_cfg", "activate", on_part_config
);
1099 SIGNAL("menu_item_clear", "activate", on_clear_ventoy
);
1101 fill_dev_list(NULL
);
1106 int on_exit_window(GtkWidget
*widget
, gpointer data
)
1108 vlog("on_exit_window ...\n");
1110 if (g_thread_run
|| ventoy_code_is_busy())
1112 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
1116 ventoy_code_save_cfg();