|
| 1 | +/** |
| 2 | + * This view is for selecting a location to install alongside an existing operationg system. |
| 3 | + * |
| 4 | + * Possible install options on this view are: |
| 5 | + * |
| 6 | + * - Shrinking the largest existing partition on a disk, if possible. |
| 7 | + * - Installing to the largest unused region on a disk, if possible. |
| 8 | + */ |
| 9 | +public class AlongsideView: OptionsView { |
| 10 | + public signal void next_step (bool use_scale, string? os, uint64 free, uint64 total); |
| 11 | + |
| 12 | + // Whether to use the resize view for choosing a size or not. |
| 13 | + public bool set_scale = false; |
| 14 | + // The number of free sectors that the selected install option has. |
| 15 | + public uint64 selected_free = 0; |
| 16 | + // The number of total sectors that the option has. |
| 17 | + public uint64 selected_total = 0; |
| 18 | + // The OS that is installed to, or may have ownership of, the option. |
| 19 | + public string? selected_os; |
| 20 | + |
| 21 | + // Possible labels that the next button will have, depending on which option is selected. |
| 22 | + private string NEXT_LABEL[5]; |
| 23 | + |
| 24 | + public AlongsideView () { |
| 25 | + Object ( |
| 26 | + cancellable: true, |
| 27 | + artwork: "disks", |
| 28 | + title: _("Install Alongside Another OS") |
| 29 | + ); |
| 30 | + } |
| 31 | + |
| 32 | + construct { |
| 33 | + NEXT_LABEL = new string[5] { |
| 34 | + _("Install"), |
| 35 | + _("Resize Partition"), |
| 36 | + _("Resize OS"), |
| 37 | + _("Install Alongside"), |
| 38 | + _("Erase and Install"), |
| 39 | + }; |
| 40 | + |
| 41 | + next_button.label = NEXT_LABEL[3]; |
| 42 | + next.connect (() => next_step (set_scale, selected_os, selected_free, selected_total)); |
| 43 | + show_all (); |
| 44 | + } |
| 45 | + |
| 46 | + // Clears existing options in the view, and creates new installation options. |
| 47 | + public void update_options () { |
| 48 | + base.clear_options (); |
| 49 | + |
| 50 | + var options = InstallOptions.get_default (); |
| 51 | + |
| 52 | + add_alongside_options (); |
| 53 | + |
| 54 | + if (options.get_options ().has_erase_options ()) { |
| 55 | + add_erase_options (); |
| 56 | + } |
| 57 | + |
| 58 | + base.options.show_all (); |
| 59 | + base.select_first_option (); |
| 60 | + } |
| 61 | + |
| 62 | + private void add_alongside_options () { |
| 63 | + var install_options = InstallOptions.get_default (); |
| 64 | + unowned string? install_device = install_options.get_install_device_path (); |
| 65 | + |
| 66 | + foreach (var option in install_options.get_options ().get_alongside_options ()) { |
| 67 | + var device = Utils.string_from_utf8 (option.get_device ()); |
| 68 | + |
| 69 | + if (install_device != null && install_device == device) { |
| 70 | + debug ("skipping %s because it is on the install device\n", device); |
| 71 | + continue; |
| 72 | + } |
| 73 | + |
| 74 | + string? os = Utils.string_from_utf8 (option.get_os ()); |
| 75 | + os = os == "none" ? null : os; |
| 76 | + |
| 77 | + var free = option.get_sectors_free (); |
| 78 | + var total = option.get_sectors_total (); |
| 79 | + var partition = option.get_partition (); |
| 80 | + var partition_path = Utils.string_from_utf8 (option.get_path ()); |
| 81 | + string logo = Utils.get_distribution_logo_from_alongside (option); |
| 82 | + |
| 83 | + string label; |
| 84 | + string details; |
| 85 | + if (partition == -1) { |
| 86 | + label = _("Unused space on %s").printf (device); |
| 87 | + details = _("%.1f GiB available").printf ((double) free / SECTORS_AS_GIB); |
| 88 | + } else { |
| 89 | + label = _("%s on %s").printf (os == null ? _("Partition") : os, device); |
| 90 | + details = _("Shrink %s (%.1f GiB free)") |
| 91 | + .printf ( |
| 92 | + partition_path, |
| 93 | + (double) free / SECTORS_AS_GIB |
| 94 | + ); |
| 95 | + } |
| 96 | + |
| 97 | + base.add_option (logo, label, details, (button) => { |
| 98 | + unowned string next_label; |
| 99 | + if (partition == -1) { |
| 100 | + next_label = NEXT_LABEL[0]; |
| 101 | + } else if (os == null) { |
| 102 | + next_label = NEXT_LABEL[1]; |
| 103 | + } else { |
| 104 | + next_label = NEXT_LABEL[2]; |
| 105 | + } |
| 106 | + |
| 107 | + button.key_press_event.connect ((event) => handle_key_press (button, event)); |
| 108 | + button.notify["active"].connect (() => { |
| 109 | + if (button.active) { |
| 110 | + base.options.get_children ().foreach ((child) => { |
| 111 | + if (child is Gtk.ToggleButton) { |
| 112 | + ((Gtk.ToggleButton)child).active = child == button; |
| 113 | + } |
| 114 | + }); |
| 115 | + |
| 116 | + install_options.selected_option = new Distinst.InstallOption () { |
| 117 | + tag = Distinst.InstallOptionVariant.ALONGSIDE, |
| 118 | + option = (void*) option, |
| 119 | + encrypt_pass = null, |
| 120 | + sectors = (partition == -1) ? 0 : free - 1 |
| 121 | + }; |
| 122 | + |
| 123 | + set_scale = partition != -1; |
| 124 | + selected_os = os; |
| 125 | + selected_free = free; |
| 126 | + selected_total = total; |
| 127 | + next_button.label = next_label; |
| 128 | + next_button.sensitive = true; |
| 129 | + } else { |
| 130 | + next_button.label = NEXT_LABEL[3]; |
| 131 | + next_button.sensitive = false; |
| 132 | + } |
| 133 | + }); |
| 134 | + }); |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + private void add_erase_options () { |
| 139 | + var install_options = InstallOptions.get_default (); |
| 140 | + unowned Distinst.InstallOptions options = install_options.get_updated_options (); |
| 141 | + unowned string? install_device = install_options.get_install_device_path (); |
| 142 | + |
| 143 | + foreach (unowned Distinst.EraseOption disk in options.get_erase_options ()) { |
| 144 | + string device_path = Utils.string_from_utf8 (disk.get_device_path ()); |
| 145 | + |
| 146 | + if (install_device != null && install_device == device_path && !install_options.has_recovery ()) { |
| 147 | + continue; |
| 148 | + } |
| 149 | + |
| 150 | + string logo = Utils.string_from_utf8 (disk.get_linux_icon ()); |
| 151 | + string label = Utils.string_from_utf8 (disk.get_model ()); |
| 152 | + string details = "Erase %s %.1f GiB".printf ( |
| 153 | + Utils.string_from_utf8 (disk.get_device_path ()), |
| 154 | + (double) disk.get_sectors () / SECTORS_AS_GIB |
| 155 | + ); |
| 156 | + |
| 157 | + base.add_option(logo, label, details, (button) => { |
| 158 | + if (disk.meets_requirements ()) { |
| 159 | + button.key_press_event.connect ((event) => handle_key_press (button, event)); |
| 160 | + button.notify["active"].connect (() => { |
| 161 | + if (button.active) { |
| 162 | + base.options.get_children ().foreach ((child) => { |
| 163 | + if (child is Gtk.ToggleButton) { |
| 164 | + ((Gtk.ToggleButton)child).active = child == button; |
| 165 | + } |
| 166 | + }); |
| 167 | + |
| 168 | + if (install_options.has_recovery ()) { |
| 169 | + var recovery = options.get_recovery_option (); |
| 170 | + |
| 171 | + install_options.selected_option = new Distinst.InstallOption () { |
| 172 | + tag = Distinst.InstallOptionVariant.RECOVERY, |
| 173 | + option = (void*) recovery, |
| 174 | + encrypt_pass = null |
| 175 | + }; |
| 176 | + } else { |
| 177 | + install_options.selected_option = new Distinst.InstallOption () { |
| 178 | + tag = Distinst.InstallOptionVariant.ERASE, |
| 179 | + option = (void*) disk, |
| 180 | + encrypt_pass = null |
| 181 | + }; |
| 182 | + } |
| 183 | + |
| 184 | + set_scale = false; |
| 185 | + next_button.label = NEXT_LABEL[4]; |
| 186 | + next_button.sensitive = true; |
| 187 | + } else { |
| 188 | + next_button.sensitive = false; |
| 189 | + next_button.label = NEXT_LABEL[3]; |
| 190 | + } |
| 191 | + }); |
| 192 | + } else { |
| 193 | + button.sensitive = false; |
| 194 | + } |
| 195 | + }); |
| 196 | + } |
| 197 | + |
| 198 | + base.sort_sensitive (); |
| 199 | + } |
| 200 | + |
| 201 | + private bool handle_key_press (Gtk.Button button, Gdk.EventKey event) { |
| 202 | + if (event.keyval == Gdk.Key.Return) { |
| 203 | + button.clicked (); |
| 204 | + next_button.clicked (); |
| 205 | + return true; |
| 206 | + } |
| 207 | + |
| 208 | + return false; |
| 209 | + } |
| 210 | +} |
0 commit comments