I was caught by this yesterday with an amd64 16.04.1 DVD install to a
BIOS+GPT custom ("Something Else") configuration where I had forgotten
to create the GPT BIOS Boot Partition for GRUB's core.

The Bootloader Error dialog is modal with only a GtkButton "gtk-ok".
Reading the ubiquity Python code and XML user interface description
files it looks as if the OK button is disabled if *any* changes are made
to the device GtkComboBox where the user-selected device is invalid
(which is checked by the grub_verify_loop() handler.

In my case there was no alternative valid option so once I'd interacted
with the GtkComboBox the OK button was disabled and I couldn't close the
modal dialog.

So the issue seems to be that once the OK button has been disabled it is
never re-enabled when selecting other valid options.

I spent quite some time trying to understand and track the execution
flow but didn't get to the point of testing my bug-fix hypothesis due to
lack of time but it is detailed at the end of this comment if anyone
cares to test it.

/use/lib/ubiquity/ubiquity/frontend/gtk_ui.py::Wizard.run(): (line ~718)

        # Auto-connecting signals with additional parameters does not work.
        self.grub_new_device_entry.connect(
            'changed', self.grub_verify_loop, self.grub_fail_okbutton)

This connects a signal from the device GtkComboBox to the
grub_verify_loop() function.

/usr/lib/ubiquity/ubiquity/frontend/gtk_ui.py::Wizard.grub_verify_loop()
(line ~1706)

    def grub_verify_loop(self, widget, okbutton):
        if widget is not None:
            if validation.check_grub_device(widget.get_child().get_text()):
                okbutton.set_sensitive(True)
            else:
                okbutton.set_sensitive(False)

Which will disable the OK button if the device is not valid.

/usr/lib/ubiquity/ubiquity/frontend/gtk_ui.py::bootloader_dialog(): (line ~1775)
...
        response = self.bootloader_fail_dialog.run()
        self.bootloader_fail_dialog.hide()
        if response == Gtk.ResponseType.OK:
            if self.grub_new_device.get_active():
                return self.grub_new_device_entry.get_child().get_text()
            elif self.grub_no_new_device.get_active():
                return 'skip'
            else:
                return ''
        else:
            return ''

because bootloader_fail_dialog.run() blocks and never returns the
subsequent .hide() and response handling never occurs.

In /usr/share/ubiquity/gtk/ubiquity.ui the OK button id is
"grub_fail_okbutton" and it is attached to:

 <action-widget response="-5">grub_fail_okbutton</action-widget>

The XML also defines a "toggled" signal attached to each of the radio
buttons that calls the toggle_grub_fail() handler.

/usr/lib/ubiquity/ubiquity/frontend/gtk_ui.py::Wizard.toggle_grub_fail()
(line ~1761)

    def toggle_grub_fail(self, unused_widget):
        if self.grub_no_new_device.get_active():
            self.no_grub_warn.show()
            self.grub_new_device_entry.set_sensitive(False)
            self.abort_warn.hide()
        elif self.grub_fail_option.get_active():
            self.abort_warn.show()
            self.no_grub_warn.hide()
            self.grub_new_device_entry.set_sensitive(False)
        else:
            self.abort_warn.hide()
            self.no_grub_warn.hide()
            self.grub_new_device_entry.set_sensitive(True)

This changes the visibility of the option-specific warnings that appear
when those options are selected and alters the enabled status of the
GtkComboBox.

So I guess the solution is to add two identical lines here to ensure the
OK button is enabled for the 'proceed without GRUB' or 'Cancel
installtion' options:

    def toggle_grub_fail(self, unused_widget):
        if self.grub_no_new_device.get_active():
            self.no_grub_warn.show()
            self.grub_new_device_entry.set_sensitive(False)

            self.okbutton.set_sensitive(True)

            self.abort_warn.hide()
        elif self.grub_fail_option.get_active():
            self.abort_warn.show()
            self.no_grub_warn.hide()
            self.grub_new_device_entry.set_sensitive(False)

            self.okbutton.set_sensitive(True)

        else:
            self.abort_warn.hide()
            self.no_grub_warn.hide()
            self.grub_new_device_entry.set_sensitive(True)

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/686859

Title:
  "Bootloader install failed" cannot be closed

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/686859/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to