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/>.
30 #include <ventoy_define.h>
31 #include <ventoy_json.h>
32 #include <ventoy_util.h>
33 #include <ventoy_disk.h>
34 #include <ventoy_http.h>
37 #include "ventoy_gtk.h"
39 int g_secure_boot_support
= 0;
40 GtkWidget
*g_topWindow
= NULL
;
41 GtkWidget
*g_partCfgWindow
= NULL
;
42 GtkBuilder
*g_pXmlBuilder
= NULL
;
43 GtkComboBoxText
*g_dev_combobox
= NULL
;
44 GtkButton
*g_refresh_button
= NULL
;
45 GtkButton
*g_install_button
= NULL
;
46 GtkButton
*g_update_button
= NULL
;
47 GtkMenu
*g_lang_menu
= NULL
;;
48 GtkCheckMenuItem
*g_menu_item_secure_boot
= NULL
;
49 GtkCheckMenuItem
*g_menu_item_mbr
= NULL
;
50 GtkCheckMenuItem
*g_menu_item_gpt
= NULL
;
51 GtkCheckMenuItem
*g_menu_item_show_all
= NULL
;
52 GtkLabel
*g_device_title
= NULL
;
53 GtkLabel
*g_label_local_part_style
= NULL
;
54 GtkLabel
*g_label_dev_part_style
= NULL
;
55 GtkLabel
*g_label_local_ver
= NULL
;
56 GtkLabel
*g_label_disk_ver
= NULL
;
57 GtkLabel
*g_label_status
= NULL
;
58 GtkImage
*g_image_secure_local
= NULL
;
59 GtkImage
*g_image_secure_device
= NULL
;
60 GtkToggleButton
*g_part_align_checkbox
= NULL
;
61 GtkToggleButton
*g_part_preserve_checkbox
= NULL
;
62 GtkEntry
*g_part_reserve_space_value
= NULL
;
63 GtkComboBoxText
*g_part_space_unit_combox
= NULL
;
64 GtkProgressBar
*g_progress_bar
= NULL
;
65 VTOY_JSON
*g_languages_json
= NULL
;
66 int g_languages_toggled_proc
= 0;
67 int g_dev_changed_proc
= 0;
68 gboolean g_align_part_with_4k
= TRUE
;
69 gboolean g_preserve_space_check
= FALSE
;
70 int g_preserve_space_unit
= 1;
71 int g_preserve_space_number
= 0;
72 gboolean g_thread_run
= FALSE
;
74 const char *language_string(const char *id
)
76 const char *pName
= NULL
;
77 VTOY_JSON
*node
= NULL
;
78 const char *pCurLang
= ventoy_code_get_cur_language();
80 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
82 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
83 if (0 == g_strcmp0(pName
, pCurLang
))
94 return vtoy_json_get_string_ex(node
->pstChild
, id
);
97 int msgbox(GtkMessageType type
, GtkButtonsType buttons
, const char *strid
)
100 GtkWidget
*pMsgBox
= NULL
;
102 pMsgBox
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, type
, buttons
, "%s", language_string(strid
));
104 ret
= gtk_dialog_run(GTK_DIALOG(pMsgBox
));
105 gtk_widget_destroy(pMsgBox
);
111 static void set_item_visible(const char *id
, int visible
)
113 GtkWidget
*pWidget
= NULL
;
115 pWidget
= GTK_WIDGET(gtk_builder_get_object(g_pXmlBuilder
, id
));
118 gtk_widget_show(pWidget
);
122 gtk_widget_hide(pWidget
);
126 static void init_part_style_menu(void)
130 style
= ventoy_code_get_cur_part_style();
131 gtk_check_menu_item_set_active(g_menu_item_mbr
, (0 == style
));
132 gtk_check_menu_item_set_active(g_menu_item_gpt
, (1 == style
));
133 gtk_label_set_text(g_label_local_part_style
, style
? "GPT" : "MBR");
136 static void select_language(const char *lang
)
138 const char *pName
= NULL
;
139 const char *pPos
= NULL
;
140 const char *pDevice
= NULL
;
141 VTOY_JSON
*node
= NULL
;
144 for (node
= g_languages_json
->pstChild
; node
; node
= node
->pstNext
)
146 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
147 if (0 == g_strcmp0(pName
, lang
))
158 pDevice
= gtk_label_get_text(g_device_title
);
159 if (pDevice
&& (pPos
= strchr(pDevice
, '[')) != NULL
)
161 g_snprintf(device
, sizeof(device
), "%s %s", vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"), pPos
);
162 gtk_label_set_text(g_device_title
, device
);
166 gtk_label_set_text(g_device_title
, vtoy_json_get_string_ex(node
->pstChild
, "STR_DEVICE"));
169 LANG_LABEL_TEXT("label_local_ver", "STR_LOCAL_VER");
170 LANG_LABEL_TEXT("label_device_ver", "STR_DISK_VER");
172 LANG_LABEL_TEXT("label_status", "STR_STATUS");
174 LANG_BUTTON_TEXT("button_install", "STR_INSTALL");
175 LANG_BUTTON_TEXT("button_update", "STR_UPDATE");
177 LANG_MENU_ITEM_TEXT("menu_option", "STR_MENU_OPTION");
178 LANG_MENU_ITEM_TEXT("menu_item_secure", "STR_MENU_SECURE_BOOT");
179 LANG_MENU_ITEM_TEXT("menu_part_style", "STR_MENU_PART_STYLE");
180 LANG_MENU_ITEM_TEXT("menu_item_part_cfg", "STR_MENU_PART_CFG");
181 LANG_MENU_ITEM_TEXT("menu_item_clear", "STR_MENU_CLEAR");
182 LANG_MENU_ITEM_TEXT("menu_item_show_all", "STR_SHOW_ALL_DEV");
184 LANG_BUTTON_TEXT("space_check_btn", "STR_PRESERVE_SPACE");
185 LANG_BUTTON_TEXT("space_align_btn", "STR_PART_ALIGN_4KB");
186 LANG_BUTTON_TEXT("button_partcfg_ok", "STR_BTN_OK");
187 LANG_BUTTON_TEXT("button_partcfg_cancel", "STR_BTN_CANCEL");
189 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), vtoy_json_get_string_ex(node
->pstChild
, "STR_MENU_PART_CFG"));
195 gtk_widget_hide(g_topWindow
);
196 gtk_widget_show(g_topWindow
);
200 void on_secure_boot_toggled(GtkMenuItem
*menuItem
, gpointer data
)
202 g_secure_boot_support
= 1 - g_secure_boot_support
;
204 vlog("on_secure_boot_toggled %d\n",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
)
303 ventoy_disk
*cur
= NULL
;
305 /* find the match one */
308 for (i
= 0; i
< g_disk_num
; i
++)
310 cur
= g_disk_list
+ i
;
311 if (strcmp(cur
->disk_name
, select
) == 0)
319 /* find the first one that installed with Ventoy */
320 for (i
= 0; i
< g_disk_num
; i
++)
322 cur
= g_disk_list
+ i
;
323 if (cur
->vtoydata
.ventoy_valid
)
330 /* find the first USB interface device */
331 for (i
= 0; i
< g_disk_num
; i
++)
333 cur
= g_disk_list
+ i
;
334 if (cur
->type
== VTOY_DEVICE_USB
)
341 /* use the first one */
346 static void fill_dev_list(const char *select
)
353 ventoy_disk
*cur
= NULL
;
354 ventoy_disk
*active
= NULL
;
355 GtkListStore
*store
= NULL
;
357 g_dev_changed_proc
= 0;
359 alldev
= ventoy_code_get_cur_show_all();
361 vlog("fill_dev_list total disk: %d showall:%d\n", g_disk_num
, alldev
);
363 /* gtk_combo_box_text_remove_all */
364 store
= GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(g_dev_combobox
)));
365 gtk_list_store_clear(store
);
367 for (i
= 0; i
< g_disk_num
; i
++)
369 cur
= g_disk_list
+ i
;
371 if (alldev
== 0 && cur
->type
!= VTOY_DEVICE_USB
)
376 g_snprintf(line
, sizeof(line
), "%s [%s] %s", cur
->disk_name
, cur
->human_readable_size
, cur
->disk_model
);
377 gtk_combo_box_text_append_text(g_dev_combobox
, line
);
381 active
= select_active_dev(select
, &activeid
);
384 vlog("combox count:%d, active:%s id:%d\n", count
, active
->disk_name
, activeid
);
385 gtk_combo_box_set_active((GtkComboBox
*)g_dev_combobox
, activeid
);
386 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
387 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), active
->vtoydata
.ventoy_valid
);
391 vlog("combox count:%d, no active id\n", count
);
392 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), FALSE
);
393 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), FALSE
);
396 g_dev_changed_proc
= 1;
397 on_devlist_changed(NULL
, NULL
);
401 void on_show_all_toggled(GtkMenuItem
*menuItem
, gpointer data
)
403 int show_all
= ventoy_code_get_cur_show_all();
405 ventoy_code_set_cur_show_all(1 - show_all
);
409 void on_button_refresh_clicked(GtkWidget
*widget
, gpointer data
)
411 if (g_thread_run
|| ventoy_code_is_busy())
413 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
417 ventoy_code_refresh_device();
421 static void set_progress_bar_percent(int percent
)
424 const char *text
= NULL
;
427 gtk_progress_bar_set_fraction(g_progress_bar
, percent
* 1.0 / 100);
428 vlog("set percent %d\n", percent
);
430 text
= language_string("STR_STATUS");
433 gtk_label_set_text(g_label_status
, text
);
437 g_snprintf(tmp
, sizeof(tmp
), "%s", text
);
438 pos
= strchr(tmp
, '-');
441 g_snprintf(pos
+ 2, sizeof(tmp
), "%d%%", percent
);
442 gtk_label_set_text(g_label_status
, tmp
);
447 void on_clear_ventoy(GtkMenuItem
*menuItem
, gpointer data
)
454 ventoy_disk
*cur
= NULL
;
456 if (g_thread_run
|| ventoy_code_is_busy())
458 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
462 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
463 if (active
< 0 || active
>= g_disk_num
)
465 vlog("invalid active combox id %d\n", active
);
469 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
474 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
479 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
480 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
481 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
485 cur
= g_disk_list
+ active
;
486 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
487 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"clean\",\"disk\":\"%s\"}", disk_name
);
490 ventoy_func_handler(buf
, out
, sizeof(out
));
491 vlog("func handler clean <%s>\n", out
);
493 if (strstr(out
, "success"))
495 ret
= ventoy_code_get_result();
496 ventoy_code_refresh_device();
506 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_CLEAR_SUCCESS");
510 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_CLEAR_FAILED");
513 set_progress_bar_percent(0);
514 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
515 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
516 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
518 fill_dev_list(disk_name
);
519 g_thread_run
= FALSE
;
522 static int install_proc(ventoy_disk
*cur
)
534 vlog("install_thread ...\n");
536 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
538 buflen
= sizeof(buf
);
539 VTOY_JSON_FMT_BEGIN(pos
, buf
, buflen
);
540 VTOY_JSON_FMT_OBJ_BEGIN();
541 VTOY_JSON_FMT_STRN("method", "install");
542 VTOY_JSON_FMT_STRN("disk", disk_name
);
544 if (g_preserve_space_check
)
546 space
= g_preserve_space_number
;
547 if (g_preserve_space_unit
== 1)
549 space
= space
* 1024 * 1024 * 1024LL;
553 space
= space
* 1024 * 1024LL;
556 snprintf(dec
, sizeof(dec
), "%lld", space
);
557 VTOY_JSON_FMT_STRN("reserve_space", dec
);
561 VTOY_JSON_FMT_STRN("reserve_space", "0");
564 VTOY_JSON_FMT_UINT("partstyle", ventoy_code_get_cur_part_style());
565 VTOY_JSON_FMT_UINT("secure_boot", g_secure_boot_support
);
566 VTOY_JSON_FMT_UINT("align_4kb", g_align_part_with_4k
);
567 VTOY_JSON_FMT_OBJ_END();
568 VTOY_JSON_FMT_END(pos
);
571 ventoy_func_handler(buf
, out
, sizeof(out
));
572 vlog("func handler install <%s>\n", out
);
574 if (strstr(out
, "success"))
576 while (percent
!= 100)
578 percent
= ventoy_code_get_percent();
579 set_progress_bar_percent(percent
);
584 ret
= ventoy_code_get_result();
585 ventoy_code_refresh_device();
595 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_INSTALL_FAILED");
599 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_INSTALL_SUCCESS");
602 set_progress_bar_percent(0);
603 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
604 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
605 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
607 fill_dev_list(disk_name
);
608 g_thread_run
= FALSE
;
613 void on_button_install_clicked(GtkWidget
*widget
, gpointer data
)
616 ventoy_disk
*cur
= NULL
;
618 if (g_thread_run
|| ventoy_code_is_busy())
620 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
624 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
625 if (active
< 0 || active
>= g_disk_num
)
627 vlog("invalid active combox id %d\n", active
);
631 cur
= g_disk_list
+ active
;
633 if (ventoy_code_get_cur_part_style() == 0 && cur
->size_in_byte
> 2199023255552ULL)
635 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_DISK_2TB_MBR_ERROR");
639 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP"))
644 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK_CANCEL
, "STR_INSTALL_TIP2"))
649 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
650 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
651 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
659 static int update_proc(ventoy_disk
*cur
)
667 g_snprintf(disk_name
, sizeof(disk_name
), "%s", cur
->disk_name
);
668 g_snprintf(buf
, sizeof(buf
), "{\"method\":\"update\",\"disk\":\"%s\",\"secure_boot\":%d}",
669 disk_name
, g_secure_boot_support
);
672 ventoy_func_handler(buf
, out
, sizeof(out
));
673 vlog("func handler update <%s>\n", out
);
675 if (strstr(out
, "success"))
677 while (percent
!= 100)
679 percent
= ventoy_code_get_percent();
680 set_progress_bar_percent(percent
);
685 ret
= ventoy_code_get_result();
686 ventoy_code_refresh_device();
696 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_UPDATE_FAILED");
700 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_UPDATE_SUCCESS");
703 set_progress_bar_percent(0);
704 gtk_widget_set_sensitive(GTK_WIDGET(g_refresh_button
), TRUE
);
705 gtk_widget_set_sensitive(GTK_WIDGET(g_install_button
), TRUE
);
706 gtk_widget_set_sensitive(GTK_WIDGET(g_update_button
), TRUE
);
708 fill_dev_list(disk_name
);
709 g_thread_run
= FALSE
;
715 void on_button_update_clicked(GtkWidget
*widget
, gpointer data
)
718 ventoy_disk
*cur
= NULL
;
720 if (g_thread_run
|| ventoy_code_is_busy())
722 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
726 active
= gtk_combo_box_get_active((GtkComboBox
*)g_dev_combobox
);
727 if (active
< 0 || active
>= g_disk_num
)
729 vlog("invalid active combox id %d\n", active
);
732 cur
= g_disk_list
+ active
;
734 if (cur
->vtoydata
.ventoy_valid
== 0)
736 vlog("invalid ventoy version.\n");
740 if (GTK_RESPONSE_CANCEL
== msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK_CANCEL
, "STR_UPDATE_TIP"))
745 gtk_widget_set_sensitive (GTK_WIDGET(g_refresh_button
), FALSE
);
746 gtk_widget_set_sensitive (GTK_WIDGET(g_install_button
), FALSE
);
747 gtk_widget_set_sensitive (GTK_WIDGET(g_update_button
), FALSE
);
754 static gint
lang_compare(gconstpointer a
, gconstpointer b
)
756 const char *name1
= (const char *)a
;
757 const char *name2
= (const char *)b
;
759 if (strncmp(name1
, "Chinese Simplified", 18) == 0)
763 else if (strncmp(name2
, "Chinese Simplified", 18) == 0)
769 return g_strcmp0(name1
, name2
);
773 static int load_languages(void)
778 const char *pCurLang
= NULL
;
779 const char *pName
= NULL
;
780 VTOY_JSON
*json
= NULL
;
781 VTOY_JSON
*node
= NULL
;
782 VTOY_JSON
*lang
= NULL
;
783 GSList
*pGroup
= NULL
;
784 GList
*pNameNode
= NULL
;
785 GList
*pNameList
= NULL
;
786 GtkRadioMenuItem
*pItem
= NULL
;
788 vlog("load_languages ...\n");
790 pCurLang
= ventoy_code_get_cur_language();
791 if (pCurLang
[0] == 0)
793 pName
= getenv("LANG");
794 if (pName
&& strncmp(pName
, "zh_CN", 5) == 0)
796 ventoy_code_set_cur_language("Chinese Simplified (ç®€ä½“ä¸æ–‡)");
800 ventoy_code_set_cur_language("English (English)");
802 pCurLang
= ventoy_code_get_cur_language();
805 vlog("current language <%s>\n", pCurLang
);
807 ventoy_read_file_to_buf("./tool/languages.json", 1, (void **)&pBuf
, &size
);
809 json
= vtoy_json_create();
810 vtoy_json_parse(json
, pBuf
);
811 g_languages_json
= json
;
813 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
815 pName
= vtoy_json_get_string_ex(node
->pstChild
, "name");
818 pNameList
= g_list_append(pNameList
, (gpointer
)pName
);
821 for (lang
= node
->pstChild
; lang
; lang
= lang
->pstNext
)
823 if (lang
->enDataType
== JSON_TYPE_STRING
)
825 pCur
= lang
->unData
.pcStrVal
;
832 else if (*pCur
== '@')
842 pNameList
= g_list_sort(pNameList
, lang_compare
);
844 for (pNameNode
= g_list_first(pNameList
); pNameNode
; pNameNode
= g_list_next(pNameNode
))
846 pName
= (char *)(pNameNode
->data
);
847 pItem
= (GtkRadioMenuItem
*)gtk_radio_menu_item_new_with_label(pGroup
, pName
);
848 pGroup
= gtk_radio_menu_item_get_group(pItem
);
850 if (strcmp(pCurLang
, pName
) == 0)
852 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pItem
), TRUE
);
855 g_signal_connect(pItem
, "toggled", G_CALLBACK(on_language_toggled
), (gpointer
)pName
);
856 gtk_widget_show((GtkWidget
*)pItem
);
857 gtk_menu_shell_append(GTK_MENU_SHELL(g_lang_menu
), (GtkWidget
*)pItem
);
860 g_list_free(pNameList
);
863 select_language(pCurLang
);
864 g_languages_toggled_proc
= 1;
869 void on_part_cfg_ok(GtkWidget
*widget
, gpointer data
)
871 const char *pos
= NULL
;
872 const char *input
= NULL
;
874 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
878 input
= gtk_entry_get_text(g_part_reserve_space_value
);
879 if (input
== NULL
|| input
[0] == 0)
881 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
885 for (pos
= input
; *pos
; pos
++)
887 if (*pos
< '0' || *pos
>= '9')
889 msgbox(GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "STR_SPACE_VAL_INVALID");
894 g_preserve_space_unit
= gtk_combo_box_get_active((GtkComboBox
*)g_part_space_unit_combox
);
895 g_preserve_space_number
= (int)strtol(input
, NULL
, 10);
897 g_snprintf(device
, sizeof(device
), "%s [ -%d%s ]",
898 language_string("STR_DEVICE"), g_preserve_space_number
,
899 g_preserve_space_unit
? "GB" : "MB");
900 gtk_label_set_text(g_device_title
, device
);
904 gtk_label_set_text(g_device_title
, language_string("STR_DEVICE"));
907 g_preserve_space_check
= checked
;
908 g_align_part_with_4k
= gtk_toggle_button_get_active(g_part_align_checkbox
);
909 gtk_widget_hide(g_partCfgWindow
);
912 void on_part_cfg_cancel(GtkWidget
*widget
, gpointer data
)
914 gtk_widget_hide(g_partCfgWindow
);
917 int on_part_cfg_close(GtkWidget
*widget
, gpointer data
)
919 gtk_widget_hide(g_partCfgWindow
);
923 void on_part_config(GtkMenuItem
*menuItem
, gpointer data
)
927 gtk_toggle_button_set_active(g_part_align_checkbox
, g_align_part_with_4k
);
928 gtk_toggle_button_set_active(g_part_preserve_checkbox
, g_preserve_space_check
);
929 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), g_preserve_space_check
);
930 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), g_preserve_space_check
);
932 if (g_preserve_space_check
)
934 g_snprintf(value
, sizeof(value
), "%d", g_preserve_space_number
);
935 gtk_entry_set_text(g_part_reserve_space_value
, value
);
936 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
939 gtk_widget_show_all(g_partCfgWindow
);
942 void on_reserve_space_toggled(GtkMenuItem
*menuItem
, gpointer data
)
944 gboolean checked
= gtk_toggle_button_get_active(g_part_preserve_checkbox
);
946 gtk_widget_set_sensitive(GTK_WIDGET(g_part_reserve_space_value
), checked
);
947 gtk_widget_set_sensitive(GTK_WIDGET(g_part_space_unit_combox
), checked
);
950 static void init_part_cfg_window(GtkBuilder
*pBuilder
)
952 #if GTK_CHECK_VERSION(3, 0, 0)
953 GtkWidget
*pHeader
= NULL
;
955 pHeader
= gtk_header_bar_new();
956 gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(pHeader
), FALSE
);
957 gtk_window_set_titlebar (GTK_WINDOW(g_partCfgWindow
), pHeader
);
958 gtk_window_set_title(GTK_WINDOW(g_partCfgWindow
), "Partition Configuration");
961 gtk_combo_box_set_active((GtkComboBox
*)g_part_space_unit_combox
, g_preserve_space_unit
);
962 gtk_widget_set_sensitive (GTK_WIDGET(g_part_reserve_space_value
), FALSE
);
963 gtk_widget_set_sensitive (GTK_WIDGET(g_part_space_unit_combox
), FALSE
);
965 SIGNAL("space_check_btn", "toggled", on_reserve_space_toggled
);
967 SIGNAL("button_partcfg_ok", "clicked", on_part_cfg_ok
);
968 SIGNAL("button_partcfg_cancel", "clicked", on_part_cfg_cancel
);
969 SIGNAL("part_cfg_dlg", "delete_event", on_part_cfg_close
);
972 void on_init_window(GtkBuilder
*pBuilder
)
974 GSList
*pGroup
= NULL
;
977 vlog("on_init_window ...\n");
979 g_pXmlBuilder
= pBuilder
;
980 g_topWindow
= BUILDER_ITEM(GtkWidget
, "window");
981 g_partCfgWindow
= BUILDER_ITEM(GtkWidget
, "part_cfg_dlg");
983 g_dev_combobox
= BUILDER_ITEM(GtkComboBoxText
, "combobox_devlist");
984 g_refresh_button
= BUILDER_ITEM(GtkButton
, "button_refresh");
985 g_install_button
= BUILDER_ITEM(GtkButton
, "button_install");
986 g_update_button
= BUILDER_ITEM(GtkButton
, "button_update");
988 g_lang_menu
= BUILDER_ITEM(GtkMenu
, "submenu_language");
989 g_menu_item_secure_boot
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_secure");
990 g_menu_item_mbr
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_mbr");
991 g_menu_item_gpt
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_gpt");
992 g_menu_item_show_all
= BUILDER_ITEM(GtkCheckMenuItem
, "menu_item_show_all");
994 g_device_title
= BUILDER_ITEM(GtkLabel
, "label_device");
995 g_label_local_part_style
= BUILDER_ITEM(GtkLabel
, "label_local_part_style");
996 g_label_dev_part_style
= BUILDER_ITEM(GtkLabel
, "label_dev_part_style");
998 g_label_local_ver
= BUILDER_ITEM(GtkLabel
, "label_local_ver_value");
999 g_label_disk_ver
= BUILDER_ITEM(GtkLabel
, "label_dev_ver_value");
1001 g_label_status
= BUILDER_ITEM(GtkLabel
, "label_status");
1003 g_image_secure_local
= BUILDER_ITEM(GtkImage
, "image_secure_local");
1004 g_image_secure_device
= BUILDER_ITEM(GtkImage
, "image_secure_dev");
1006 g_part_preserve_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_check_btn");
1007 g_part_align_checkbox
= BUILDER_ITEM(GtkToggleButton
, "space_align_btn");
1009 g_part_reserve_space_value
= BUILDER_ITEM(GtkEntry
, "entry_reserve_space");
1010 g_part_space_unit_combox
= BUILDER_ITEM(GtkComboBoxText
, "comboboxtext_unit");
1012 g_progress_bar
= BUILDER_ITEM(GtkProgressBar
, "progressbar1");
1014 init_part_cfg_window(pBuilder
);
1017 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy1"), GTK_SHADOW_NONE
);
1018 gtk_frame_set_shadow_type(BUILDER_ITEM(GtkFrame
, "frame_dummy2"), GTK_SHADOW_NONE
);
1021 pGroup
= gtk_radio_menu_item_get_group((GtkRadioMenuItem
*)g_menu_item_mbr
);
1022 gtk_radio_menu_item_set_group((GtkRadioMenuItem
*)g_menu_item_gpt
, pGroup
);
1024 gtk_widget_hide((GtkWidget
*)g_image_secure_local
);
1025 gtk_widget_hide((GtkWidget
*)g_image_secure_device
);
1027 g_snprintf(version
, sizeof(version
), VTOY_VER_FMT
, ventoy_get_local_version());
1028 gtk_label_set_markup(g_label_local_ver
, version
);
1030 init_part_style_menu();
1031 gtk_check_menu_item_set_active(g_menu_item_show_all
, ventoy_code_get_cur_show_all());
1035 SIGNAL("combobox_devlist", "changed", on_devlist_changed
);
1037 SIGNAL("button_refresh", "clicked", on_button_refresh_clicked
);
1038 SIGNAL("button_install", "clicked", on_button_install_clicked
);
1039 SIGNAL("button_update", "clicked", on_button_update_clicked
);
1041 SIGNAL("menu_item_secure", "toggled", on_secure_boot_toggled
);
1042 SIGNAL("menu_item_mbr", "toggled", on_part_style_toggled
);
1043 SIGNAL("menu_item_show_all", "toggled", on_show_all_toggled
);
1045 SIGNAL("menu_item_part_cfg", "activate", on_part_config
);
1046 SIGNAL("menu_item_clear", "activate", on_clear_ventoy
);
1048 fill_dev_list(NULL
);
1053 int on_exit_window(GtkWidget
*widget
, gpointer data
)
1055 vlog("on_exit_window ...\n");
1057 if (g_thread_run
|| ventoy_code_is_busy())
1059 msgbox(GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, "STR_WAIT_PROCESS");
1063 ventoy_code_save_cfg();