62 "en_US",
"ar_SA",
"de_DE",
"es_ES",
"fr_FR",
63 "it_IT",
"ja_JP",
"nl_NL",
"pl_PL",
"pt_PT",
"ru_RU"
66 "English",
"\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
"Deutsch",
"Espa\u00f1ol",
"Fran\u00e7ais",
67 "Italiano",
"\u65e5\u672c\u8a9e",
"Nederlands",
"Polski",
"Portugu\u00eas",
"\u0420\u0443\u0441\u0441\u043a\u0438\u0439"
77 private Gee.ArrayList<Gtk.Image>
themed_img_list =
new Gee.ArrayList<Gtk.Image>();
108 this.title =
"BastionGuard™ Backup";
110 this.set_default_size(980, 520);
111 this.set_resizable(
true);
113 this.set_icon_name(
"bastionguard-backup");
127 hbox_root =
new Gtk.Box(Orientation.HORIZONTAL, 0);
129 hbox_root.hexpand =
true;
130 hbox_root.vexpand =
false;
131 hbox_root.halign = Gtk.Align.FILL;
132 hbox_root.valign = Gtk.Align.FILL;
140 btn_backup.sensitive =
false;
141 btn_nav_settings.sensitive =
false;
142 btn_nav_wizard.sensitive =
false;
146 log_debug(
"MainWindow: MainWindow(): exit");
154 var header =
new Gtk.HeaderBar();
155 header.set_show_title_buttons(
false);
156 header.set_decoration_layout(
"");
157 header.get_style_context().add_class(
"custom-headerbar");
159 var header_left =
new Gtk.Box(Orientation.HORIZONTAL, 0);
160 header_left.set_size_request(180, -1);
161 header_left.get_style_context().add_class(
"header-left");
162 header_left.margin_start = 0;
163 header_left.margin_end = 0;
164 header_left.margin_top = 0;
165 header_left.margin_bottom = 0;
166 header.set_title_widget(
new Gtk.Box(Orientation.HORIZONTAL, 0));
167 var header_root = (Gtk.Box) header.get_title_widget();
168 header_root.hexpand =
true;
169 header_root.append(header_left);
171 var header_mid =
new Gtk.Box(Orientation.HORIZONTAL, 0);
172 header_mid.hexpand =
true;
173 header_mid.get_style_context().add_class(
"header-right");
174 header_root.append(header_mid);
176 var header_right =
new Gtk.Box(Orientation.HORIZONTAL, 0);
177 header_right.get_style_context().add_class(
"header-right");
178 header_right.valign = Gtk.Align.CENTER;
179 header_right.margin_end = 6;
181 var btn_min =
new Gtk.Button();
182 btn_min.set_child(
themed_icon(
"window-minimize-symbolic", 16));
183 btn_min.get_style_context().add_class(
"header-button");
184 btn_min.clicked.connect(() => { this.
minimize(); });
185 header_right.append(btn_min);
187 var btn_close =
new Gtk.Button();
188 btn_close.set_child(
themed_icon(
"window-close-symbolic", 16));
189 btn_close.get_style_context().add_class(
"header-button");
190 btn_close.clicked.connect(() => { this.close(); });
191 header_right.append(btn_close);
193 header_root.append(header_right);
194 this.set_titlebar(header);
209 var parser =
new Json.Parser();
210 parser.load_from_data(content, -1);
212 Json.Node root = parser.get_root();
213 if (root ==
null || root.get_node_type() != Json.NodeType.OBJECT) {
214 log_error(
"Theme config non valido, uso light");
218 Json.Object obj = root.get_object();
219 if (!obj.has_member(
"theme")) {
220 log_debug(
"Chiave 'theme' mancante, uso light");
224 string theme = obj.get_string_member(
"theme");
225 if (theme ==
"dark") {
230 log_debug(
"Tema letto da config: light");
234 log_error(
"Errore lettura theme config: " + e.message);
246 string theme = use_dark ?
"dark" :
"light";
247 string json =
"{\n\t\"theme\": \"%s\"\n}\n".printf(theme);
254 log_error(
"Errore salvataggio theme config: " + e.message);
269 log_debug(
"Language config non trovato, uso English (en_US)");
276 var parser =
new Json.Parser();
277 parser.load_from_data(content, -1);
279 Json.Node root = parser.get_root();
280 if (root ==
null || root.get_node_type() != Json.NodeType.OBJECT) {
281 log_error(
"Language config non valido, uso en_US");
285 Json.Object obj = root.get_object();
286 if (!obj.has_member(
"language")) {
287 log_debug(
"Chiave 'language' mancante, uso en_US");
291 string lang = obj.get_string_member(
"language");
296 log_debug(
"Lingua letta da config: " + lang);
301 log_debug(
"Lingua non supportata '%s', uso en_US".printf(lang));
305 log_error(
"Errore lettura language config: " + e.message);
316 string json =
"{\n\t\"language\": \"%s\"\n}\n".printf(lang_code);
322 log_error(
"Errore salvataggio language config: " + e.message);
334 case "ar_SA": locale_val =
"ar_SA.UTF-8";
break;
335 case "de_DE": locale_val =
"de_DE.UTF-8";
break;
336 case "es_ES": locale_val =
"es_ES.UTF-8";
break;
337 case "fr_FR": locale_val =
"fr_FR.UTF-8";
break;
338 case "it_IT": locale_val =
"it_IT.UTF-8";
break;
339 case "ja_JP": locale_val =
"ja_JP.UTF-8";
break;
340 case "nl_NL": locale_val =
"nl_NL.UTF-8";
break;
341 case "pl_PL": locale_val =
"pl_PL.UTF-8";
break;
342 case "pt_PT": locale_val =
"pt_PT.UTF-8";
break;
343 case "ru_RU": locale_val =
"ru_RU.UTF-8";
break;
344 default: locale_val =
"en_US.UTF-8";
break;
347 GLib.Environment.set_variable(
"LANGUAGE", lang_code,
true);
348 GLib.Environment.set_variable(
"LC_MESSAGES", locale_val,
true);
349 GLib.Environment.set_variable(
"LANG", locale_val,
true);
351 GLib.Intl.setlocale(GLib.LocaleCategory.MESSAGES, locale_val);
352 GLib.Intl.bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
353 GLib.Intl.bind_textdomain_codeset(GETTEXT_PACKAGE,
"UTF-8");
354 GLib.Intl.textdomain(GETTEXT_PACKAGE);
356 if (lang_code ==
"ar_SA") {
357 Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL);
359 Gtk.Widget.set_default_direction(Gtk.TextDirection.LTR);
362 log_debug(
"Locale applicato (processo): " + locale_val);
369 if (idx < 0 || idx >=
LANG_CODES.length)
return;
379 var dlg =
new Gtk.MessageDialog(
381 Gtk.DialogFlags.MODAL,
382 Gtk.MessageType.QUESTION,
383 Gtk.ButtonsType.YES_NO,
384 _(
"Language saved. The application must restart to apply the new language.\n\nRestart now?")
389 if (resp == Gtk.ResponseType.YES) {
400 string exe_path =
"";
402 exe_path = GLib.FileUtils.read_link(
"/proc/self/exe");
404 log_error(
"restart: cannot read /proc/self/exe: " + e.message);
409 string[] argv = { exe_path };
412 GLib.Process.spawn_async(
416 GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
421 log_error(
"restart: spawn failed: " + e.message);
434 string css_name = use_dark ?
"BastionGuard-dark.css" :
"BastionGuard.css";
439 Gtk.StyleContext.remove_provider_for_display(
440 Gdk.Display.get_default(),
450 log_debug(
"CSS caricato da resource: " + css_res);
451 }
else if (path !=
null && FileUtils.test(path, FileTest.EXISTS)) {
453 log_debug(
"CSS caricato da path: " + path);
455 log_debug(css_name +
" non trovato, uso stile di default");
458 Gtk.StyleContext.add_provider_for_display(
459 Gdk.Display.get_default(),
461 Gtk.STYLE_PROVIDER_PRIORITY_USER
464 var gtk_settings = Gtk.Settings.get_default();
465 if (gtk_settings !=
null) {
466 gtk_settings.gtk_application_prefer_dark_theme = use_dark;
496 dark_btn.get_style_context().add_class(
"active-sidebar-button");
497 light_btn.get_style_context().remove_class(
"active-sidebar-button");
500 light_btn.get_style_context().add_class(
"active-sidebar-button");
501 dark_btn.get_style_context().remove_class(
"active-sidebar-button");
513 vbox_sidebar.hexpand =
false;
514 vbox_sidebar.vexpand =
true;
515 vbox_sidebar.halign = Gtk.Align.FILL;
516 vbox_sidebar.valign = Gtk.Align.FILL;
519 var header_box =
new Gtk.Box(Orientation.HORIZONTAL, 8);
520 header_box.get_style_context().add_class(
"sidebar-header");
524 header_box.append(logo);
526 var title_lbl =
new Gtk.Label(
"BastionGuard™\nBackup");
527 title_lbl.xalign = 0;
528 title_lbl.get_style_context().add_class(
"sidebar-title");
529 header_box.append(title_lbl);
531 vbox_sidebar.append(
new Gtk.Box(Orientation.VERTICAL, 0));
537 var spacer =
new Gtk.Box(Orientation.VERTICAL, 0);
538 spacer.vexpand =
true;
542 var theme_sep =
new Gtk.Separator(Orientation.HORIZONTAL);
543 theme_sep.margin_top = 6;
544 theme_sep.margin_bottom = 6;
545 theme_sep.margin_start = 8;
546 theme_sep.margin_end = 8;
549 var theme_title =
new Gtk.Label(
_(
"Theme"));
550 theme_title.xalign = 0;
551 theme_title.margin_start = 18;
552 theme_title.margin_end = 18;
553 theme_title.margin_top = 4;
554 theme_title.margin_bottom = 6;
557 var theme_box =
new Gtk.Box(Orientation.HORIZONTAL, 6);
558 theme_box.margin_start = 10;
559 theme_box.margin_end = 10;
560 theme_box.margin_bottom = 8;
572 var lang_sep =
new Gtk.Separator(Orientation.HORIZONTAL);
573 lang_sep.margin_top = 6;
574 lang_sep.margin_bottom = 6;
575 lang_sep.margin_start = 8;
576 lang_sep.margin_end = 8;
579 var lang_title =
new Gtk.Label(
_(
"Language"));
580 lang_title.xalign = 0;
581 lang_title.margin_start = 18;
582 lang_title.margin_end = 18;
583 lang_title.margin_top = 2;
584 lang_title.margin_bottom = 4;
588 lang_combo.margin_start = 10;
589 lang_combo.margin_end = 10;
590 lang_combo.margin_bottom = 8;
591 lang_combo.get_style_context().add_class(
"sidebar-combo");
603 var sep =
new Gtk.Separator(Orientation.HORIZONTAL);
605 sep.margin_bottom = 6;
606 sep.margin_start = 8;
615 private Gtk.Button
make_nav_btn(
string icon,
string label,
string page) {
616 var btn =
new Gtk.Button();
617 btn.get_style_context().add_class(
"sidebar-button");
620 var box =
new Gtk.Box(Orientation.HORIZONTAL, 12);
621 box.margin_start = 6;
626 var lbl =
new Gtk.Label(label);
633 btn.clicked.connect(() => {
activate_nav(btn, page); });
638 var btn =
new Gtk.Button();
639 btn.get_style_context().add_class(
"sidebar-button");
642 var box =
new Gtk.Box(Orientation.HORIZONTAL, 8);
643 box.margin_start = 6;
649 var lbl =
new Gtk.Label(label);
659 current_nav_btn.get_style_context().remove_class(
"active-sidebar-button");
660 btn.get_style_context().add_class(
"active-sidebar-button");
665 case "settings_page":
685 case "settings_page":
701 int current_width = this.get_width();
702 int current_height = this.get_height();
704 if (current_width > 0)
706 if (current_height > 0)
711 this.set_default_size(width, height);
712 this.set_size_request(width, height);
714 this.set_size_request(-1, -1);
725 case "settings_page":
764 embedded.request_close.connect(() => {
774 embedded.request_close.connect(() => {
784 embedded.request_close.connect(() => {
795 embedded.request_close.connect(() => {
821 var page =
new Gtk.Box(Orientation.VERTICAL, 0);
824 page.halign = Gtk.Align.FILL;
825 page.valign = Gtk.Align.FILL;
827 var title =
new Gtk.Label(
_(
"Informazioni su BastionGuard Backup"));
829 title.get_style_context().add_class(
"page-title");
830 title.margin_start = 20;
831 title.margin_top = 20;
832 title.margin_bottom = 12;
836 card.margin_start = 14;
837 card.margin_end = 14;
838 card.margin_bottom = 16;
841 var body =
new Gtk.Box(Orientation.VERTICAL, 10);
842 body.margin_start = 12;
843 body.margin_end = 12;
844 body.margin_top = 12;
845 body.margin_bottom = 12;
850 var lbl_title =
new Gtk.Label(
"BastionGuard™ Backup");
851 lbl_title.xalign = 0.5f;
852 lbl_title.wrap =
true;
853 lbl_title.get_style_context().add_class(
"title");
854 body.append(lbl_title);
856 var lbl_version =
new Gtk.Label(AppVersion);
857 lbl_version.xalign = 0.5f;
858 body.append(lbl_version);
860 var lbl_desc =
new Gtk.Label(
"Fork di Timeshift con shell UI a pagina singola e sidebar persistente.");
861 lbl_desc.xalign = 0.5f;
862 lbl_desc.wrap =
true;
863 lbl_desc.set_justify(Gtk.Justification.CENTER);
864 body.append(lbl_desc);
866 var link =
new Gtk.LinkButton.with_label(
"https://bastionguard.eu",
"bastionguard.eu");
867 link.set_halign(Gtk.Align.CENTER);
868 link.activate_link.connect(() => {
874 var lbl_copy =
new Gtk.Label(
"© 2025–2026 BastionGuard™. All Rights Reserved.");
875 lbl_copy.xalign = 0.5f;
876 lbl_copy.wrap =
true;
877 lbl_copy.set_justify(Gtk.Justification.CENTER);
878 body.append(lbl_copy);
880 var lbl_tm =
new Gtk.Label(
"BastionGuard was filed by Calogero Scarnà with the Italian Patent and Trademark Office (UIBM) on 16/12/2025 – Application No. 302025000196519.
881The BastionGuard™ name and branding are not licensed under the GPLv3.");
882 lbl_tm.xalign = 0.5f;
884 lbl_tm.set_justify(Gtk.Justification.CENTER);
887 var lbl_license =
new Gtk.Label(
_(
"BastionGuard Backup is a fork of Timeshift by Tony George.
888This program is free software licensed under GNU GPL v2 or later."));
889 lbl_license.xalign = 0.5f;
890 lbl_license.wrap =
true;
891 lbl_license.set_justify(Gtk.Justification.CENTER);
892 body.append(lbl_license);
894 var filler =
new Gtk.Box(Orientation.VERTICAL, 0);
895 filler.vexpand =
true;
907 var vbox_content =
new Gtk.Box(Orientation.VERTICAL, 0);
908 vbox_content.hexpand =
true;
909 vbox_content.vexpand =
false;
910 vbox_content.halign = Gtk.Align.FILL;
911 vbox_content.valign = Gtk.Align.FILL;
915 content_stack.hexpand =
true;
916 content_stack.vexpand =
false;
919 content_stack.halign = Gtk.Align.FILL;
920 content_stack.valign = Gtk.Align.FILL;
921 content_stack.transition_type = Gtk.StackTransitionType.CROSSFADE;
922 content_stack.transition_duration = 160;
933 var vbox =
new Gtk.Box(Orientation.VERTICAL, 0);
936 vbox.vexpand =
false;
937 vbox.halign = Gtk.Align.FILL;
938 vbox.valign = Gtk.Align.FILL;
940 var page_title =
new Gtk.Label(
_(
"Snapshots"));
941 page_title.xalign = 0;
942 page_title.get_style_context().add_class(
"page-title");
943 page_title.margin_start = 14;
944 page_title.margin_top = 8;
945 page_title.margin_bottom = 6;
946 vbox.append(page_title);
948 var cards_box =
new Gtk.Box(Orientation.HORIZONTAL, 0);
949 cards_box.margin_start = 14;
950 cards_box.margin_end = 14;
951 cards_box.margin_bottom = 6;
952 vbox.append(cards_box);
955 cards_box.append(card_status);
957 var status_inner =
new Gtk.Box(Orientation.HORIZONTAL, 12);
958 card_status.append(status_inner);
965 var status_text =
new Gtk.Box(Orientation.VERTICAL, 2);
966 status_inner.append(status_text);
969 lbl_status_title.xalign = 0;
971 lbl_status_title.wrap =
true;
975 lbl_status_detail.xalign = 0;
976 lbl_status_detail.wrap =
true;
980 card_snaps.set_size_request(150, -1);
981 cards_box.append(card_snaps);
983 var snaps_hdr =
new Gtk.Label(
_(
"Snapshots"));
984 snaps_hdr.xalign = 0;
985 card_snaps.append(snaps_hdr);
988 lbl_snap_count.xalign = 0;
993 card_space.set_size_request(170, -1);
994 cards_box.append(card_space);
996 var space_hdr =
new Gtk.Label(
_(
"Free space"));
997 space_hdr.xalign = 0;
998 card_space.append(space_hdr);
1001 lbl_free_space.xalign = 0;
1006 lbl_device_name.xalign = 0;
1009 var action_bar =
new Gtk.Box(Orientation.HORIZONTAL, 4);
1010 action_bar.margin_start = 14;
1011 action_bar.margin_end = 14;
1012 action_bar.margin_bottom = 6;
1013 vbox.append(action_bar);
1031 var sep2 =
new Gtk.Box(Orientation.HORIZONTAL, 0);
1032 sep2.hexpand =
true;
1033 action_bar.append(sep2);
1035 var btn_menu =
make_action_btn(
"open-menu-symbolic",
"",
false,
false);
1036 btn_menu.set_tooltip_text(
_(
"More options"));
1037 action_bar.append(btn_menu);
1040 var list_card =
new Gtk.Box(Orientation.VERTICAL, 0);
1041 list_card.get_style_context().add_class(
"card");
1042 list_card.margin_start = 14;
1043 list_card.margin_end = 14;
1044 list_card.margin_bottom = 6;
1045 list_card.hexpand =
true;
1046 list_card.vexpand =
false;
1047 list_card.halign = Gtk.Align.FILL;
1048 list_card.valign = Gtk.Align.FILL;
1051 snapshot_list_box.vexpand =
false;
1052 snapshot_list_box.hexpand =
true;
1053 snapshot_list_box.halign = Gtk.Align.FILL;
1054 snapshot_list_box.valign = Gtk.Align.FILL;
1056 vbox.append(list_card);
1068 var card =
new Gtk.Box(Orientation.VERTICAL, 4);
1069 card.get_style_context().add_class(
"card");
1070 card.hexpand = hexpand;
1071 card.margin_start = 4;
1072 card.margin_end = 4;
1073 card.margin_top = 4;
1074 card.margin_bottom = 4;
1078 private Gtk.Button
make_action_btn(
string icon,
string label,
bool primary,
bool danger,
string css_class =
"") {
1079 var btn =
new Gtk.Button();
1080 btn.get_style_context().add_class(
"action-btn");
1081 if (css_class.length > 0) {
1082 btn.get_style_context().add_class(css_class);
1084 if (primary) btn.get_style_context().add_class(
"btn-success");
1085 if (danger) btn.get_style_context().add_class(
"btn-danger");
1087 btn.get_style_context().remove_class(
"button");
1089 if (label.length == 0) {
1092 var box =
new Gtk.Box(Orientation.HORIZONTAL, 6);
1094 box.append(
new Gtk.Label(label));
1137 Gtk.MessageType.ERROR,
this, Gtk.ButtonsType.YES_NO);
1140 if (resp == Gtk.ResponseType.YES) {
1169 gtk_messagebox(
_(
"No snapshots on device"),
_(
"Select another device"),
this,
false);
1174 gtk_messagebox(
_(
"Cannot Delete Live Snapshot"),
1175 _(
"Snapshot '%s' is in use").printf(bak.date_formatted),
this,
false);
1179 var dlg =
new Gtk.MessageDialog(
this, Gtk.DialogFlags.MODAL,
1180 Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO,
1181 _(
"Are you sure you want to delete this snapshot?"));
1183 if (resp != Gtk.ResponseType.YES)
return;
1188 if (bak.name == item.name) { dup =
true;
break; }
1199 if (selected.size == 0) {
1200 gtk_messagebox(
_(
"No Snapshots Selected"),
_(
"Select the snapshots to mark"),
this,
false);
1203 bool marked =
false;
1204 foreach (var bak
in selected) {
1205 bak.mark_for_deletion();
1206 marked = marked || bak.marked_for_deletion;
1210 marked ?
_(
"Marked for deletion") :
_(
"Unmarked"),
1211 marked ?
_(
"Snapshots will be removed at next scheduled run")
1212 :
_(
"Snapshots will not be removed"),
1219 if (selected.size == 0) {
1225 var bak = selected[0];
1231 if (selected.size == 0) {
1232 gtk_messagebox(
_(
"Select Snapshot"),
_(
"Please select a snapshot"),
this,
false);
1235 var bak = selected[0];
1236 string log_file = view_restore_log ? bak.rsync_restore_log_file : bak.rsync_log_file;
1244 App.mirror_system =
false;
1251 gtk_messagebox(
_(
"Snapshot deletion in progress..."),
_(
"Please wait."),
this,
true);
1262 if (selected.size == 0) {
1263 gtk_messagebox(
_(
"No snapshots selected"),
_(
"Select the snapshot to restore"),
this,
false);
1266 if (selected.size > 1) {
1267 gtk_messagebox(
_(
"Multiple snapshots selected"),
_(
"Select a single snapshot"),
this,
false);
1272 gtk_messagebox(
_(
"Invalid snapshot"),
1273 _(
"Selected snapshot is marked for deletion"),
this,
false);
1276 App.snapshot_to_restore = snap;
1278 App.snapshot_to_restore =
null;
1315 vbox_sidebar.sensitive = enable;
1316 snapshot_list_box.sensitive = enable;
1326 switch (status_code) {
1345 switch (status_code) {
1396 img.set_from_pixbuf(pix);
1398 img.set_from_icon_name(name);
1417 transient_for: parent
1422 this.resizable =
false;
1423 this.set_icon_name(
"bastionguard-backup");
1426 var root =
new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
1429 var outer =
new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
1430 outer.margin_start = 18;
1431 outer.margin_end = 18;
1432 outer.margin_top = 18;
1433 outer.margin_bottom = 18;
1434 outer.get_style_context().add_class(
"card");
1437 var content =
new Gtk.Box(Gtk.Orientation.VERTICAL, 10);
1438 content.margin_top = 12;
1439 content.margin_bottom = 12;
1440 content.margin_start = 18;
1441 content.margin_end = 18;
1442 outer.append(content);
1444 Gtk.Widget logo_widget;
1447 var img =
new Gtk.Image.from_pixbuf(pix);
1453 content.append(logo_widget);
1455 var lbl_title =
new Gtk.Label(
"BastionGuard™ Backup");
1456 lbl_title.get_style_context().add_class(
"title");
1457 lbl_title.set_justify(Gtk.Justification.CENTER);
1458 lbl_title.set_xalign(0.5f);
1459 content.append(lbl_title);
1461 var lbl_version =
new Gtk.Label(AppVersion);
1462 lbl_version.set_xalign(0.5f);
1463 content.append(lbl_version);
1465 var lbl_desc =
new Gtk.Label(
_(
"System Restore Utility"));
1466 lbl_desc.set_xalign(0.5f);
1467 lbl_desc.set_justify(Gtk.Justification.CENTER);
1468 lbl_desc.wrap =
true;
1469 content.append(lbl_desc);
1471 var link =
new Gtk.LinkButton.with_label(
"https://bastionguard.eu",
"bastionguard.eu");
1472 link.set_halign(Gtk.Align.CENTER);
1473 link.activate_link.connect(() => {
1477 content.append(link);
1479 var lbl_copy =
new Gtk.Label(
1480 "© 2025–2026 BastionGuard™. All Rights Reserved."
1482 lbl_copy.set_xalign(0.5f);
1483 lbl_copy.set_justify(Gtk.Justification.CENTER);
1484 lbl_copy.wrap =
true;
1485 content.append(lbl_copy);
1487 var lbl_trademark =
new Gtk.Label(
1488 "BastionGuard was filed by Calogero Scarnà with the Italian Patent and Trademark Office (UIBM) on 16/12/2025 – Application No. 302025000196519.\n"
1489 +
"The BastionGuard™ name and branding are not licensed under the GPLv3."
1491 lbl_trademark.set_xalign(0.5f);
1492 lbl_trademark.set_justify(Gtk.Justification.CENTER);
1493 lbl_trademark.wrap =
true;
1494 content.append(lbl_trademark);
1496 var lbl_license =
new Gtk.Label(
1497 _(
"BastionGuard Backup is a fork of Timeshift by Tony George.\nThis program is free software licensed under GNU GPL v2 or later.")
1499 lbl_license.set_xalign(0.5f);
1500 lbl_license.set_justify(Gtk.Justification.CENTER);
1501 lbl_license.wrap =
true;
1502 content.append(lbl_license);
1504 var actions =
new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8);
1505 actions.set_halign(Gtk.Align.CENTER);
1506 actions.margin_top = 8;
1507 content.append(actions);
1509 var btn_close =
new Gtk.Button.with_label(
_(
"Close"));
1510 btn_close.set_size_request(120, -1);
1511 btn_close.get_style_context().add_class(
"suggested-action");
1512 btn_close.clicked.connect(() => { this.destroy(); });
1513 actions.append(btn_close);
AboutWindow(Gtk.Window parent)
void stop(AppStatus status_to_update=AppStatus.CANCELLED)
BackupWindow(bool embedded=false)
CustomMessageDialog(string _msg_title, string _msg_body, Gtk.MessageType _msg_type, Window? parent, Gtk.ButtonsType _buttons_type)
DeleteWindow(bool embedded=false)
static Gdk.? Pixbuf lookup(string icon_name, int icon_size, bool symbolic=false, bool use_hardcoded=false, int scale=1)
static Gtk.Image lookup_image(string icon_name, int icon_size, bool symbolic=false, bool use_hardcoded=false)
bool load_theme_preference()
Gtk.Label lbl_device_name
Gtk.Button btn_nav_wizard
void init_snapshots_page()
Gtk.? Button btn_theme_dark
Gee.ArrayList< Gtk.Image > themed_img_list
void btn_restore_clicked()
Gtk.? CssProvider css_provider
Gtk.Button btn_delete_snapshot
void update_theme_buttons()
Gtk.? Widget wizard_page_widget
void resize_main_window(int width, int height)
void show_snapshots_page()
Gtk.Label lbl_status_detail
void activate_nav(Gtk.Button btn, string page)
const string THEME_CONFIG_FILE
bool on_close_request() override
Gtk.? Button btn_theme_light
Gtk.Box make_card(bool hexpand)
const string THEME_CONFIG_DIR
void view_snapshot_log(bool view_restore_log)
Gee.ArrayList< int > themed_img_size
void save_language_preference(string lang_code)
void apply_language_env(string lang_code)
Gtk.Button make_nav_btn(string icon, string label, string page)
Gtk.Button make_action_btn(string icon, string label, bool primary, bool danger, string css_class="")
SettingsWindow? embedded_settings
static string[] LANG_NAMES
void restart_application()
static string[] LANG_CODES
Gtk.Button btn_browse_snapshot
void on_language_changed()
Gee.ArrayList< string > themed_img_name
Gtk.? Widget backup_page_widget
Gtk.Button btn_nav_settings
Gtk.Button make_theme_btn(string icon, string label)
Gtk.? Widget about_page_widget
Gtk.? Widget settings_page_widget
Gtk.Button btn_nav_snapshots
void btn_settings_clicked()
void settings_changed(bool btrfs_mode_prev)
Gtk.Label lbl_status_title
void init_settings_page()
SetupWizardWindow? embedded_wizard
void ui_sensitive(bool enable)
void apply_theme(bool use_dark)
Gtk.? Widget delete_page_widget
int compact_window_height
void remember_compact_window_size()
Gtk.? ComboBoxText lang_combo
Gtk.Image themed_icon(string icon_name, int size)
void apply_window_mode_for_page(string page)
void reload_themed_icons()
void set_dynamic_page(string name, ref Gtk.Widget? slot, Gtk.Widget widget)
void btn_wizard_clicked()
Gtk.? Widget restore_page_widget
string load_language_preference()
bool page_requires_expanded_window(string page)
void save_theme_preference(bool use_dark)
const string LANG_CONFIG_FILE
Gtk.? Widget rsync_log_page_widget
void load_css(bool use_dark=false)
SnapshotListBox snapshot_list_box
Gtk.? Button current_nav_btn
void open_rsync_log_page(string log_file)
bool window_in_expanded_mode
bool check_if_deletion_running()
bool check_btrfs_layout_system(Gtk.Window? win=null)
Gee.ArrayList< Snapshot > delete_list
string backup_parent_uuid
void exit_app(int exit_code=0)
DeleteFileTask delete_file_task
bool thread_delete_running
static bool resource_exists(string rel)
static ? string resolve_css(string name)
static string resource_prefix()
RestoreWindow(bool embedded=false)
RsyncLogWindow(string _rsync_log_file, bool embedded=false)
Gtk.Widget detach_root_widget()
signal void request_close()
SettingsWindow(ClamdConfig &config)
void reload_themed_icons()
void reload_themed_icons()
SetupWizardWindow(bool embedded=false)
Gtk.Widget detach_root_widget()
signal void request_close()
signal void browse_selected()
SnapshotListBox(Gtk.Window _parent_window)
Gee.ArrayList< Snapshot > selected_snapshots()
signal void view_snapshot_log(bool show_restore_log)
signal void mark_selected()
signal void delete_selected()
Gee.ArrayList< Snapshot?> snapshots
bool has_space(uint64 needed=0)
SnapshotRepo. from_null()
SnapshotRepo. from_uuid(string uuid, Gtk.Window? parent_win, bool btrfs_repo)
SnapshotLocationStatus status_code
bool file_exists(string file_path)
string format_file_size(uint64 size, bool binary_units=false, string unit="", bool show_units=true, int decimals=1)
void gtk_set_busy(bool busy, Gtk.Window win)
int gtk_dialog_run(Gtk.Dialog dlg)
void log_debug(string message)
void log_error(string message, bool highlight=false, bool is_warning=false)