#!/usr/bin/python3
# vim:et:sta:sts=4:sw=4:ts=8:tw=79:

import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import os
import sys

# Internationalization
import locale
import gettext
locale.setlocale(locale.LC_ALL, '')
locale.bindtextdomain("guefi", "/usr/share/locale")
gettext.bindtextdomain("guefi", "/usr/share/locale")
gettext.textdomain("guefi")
_ = gettext.gettext


def efi_name_test(name):
    '''Tests if name is a valid one for an EFI boot entry.'''
    if len(name.replace(' ', '')) == 0:
        return False
    allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.,:;()/ "
    return all(c in allowed for c in name)

class EntryAction:
    DoNothing = 0
    ToggleEnable = 1
    ToggleBootNext = 2

class UEFI:

    def __init__(self):
        efi_partition = self.get_efi_partition()
        if efi_partition:
            self.efi_hd, self.efi_partition, self.efi_partition_number = efi_partition
            self.update()

    def get_efi_partition(self):
        p = subprocess.Popen('lsblk -p -l -t -o name,parttype,maj:min,uuid,pkname,pttype,type'.split(' '), stdout=subprocess.PIPE)
        output = p.communicate()[0].splitlines()
        retval = p.returncode
        if retval == 0:
            for line in output:
                line_str = line.decode()
                line_str = ' '.join(line_str.split())
                try:
                    partition, os_type, maj_min, uuid, disk, partition_type, dev_type = line_str.split(' ')
                    if dev_type.lower() == 'part':
                        if (partition_type.lower() == 'dos' and os_type.lower() == '0xef') or \
                           (partition_type.lower() == 'gpt' and os_type.lower() == 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b'):
                            part_number = maj_min.split(':')[1]
                            return disk, partition, part_number
                except ValueError:
                    # raised when dev_type is "disk" because most columns are
                    # not filled in
                    pass
        return None

    def get_efi_mountpoint(self):
        p = subprocess.Popen(['findmnt', self.efi_partition],
                stdout=subprocess.PIPE)
        output = p.communicate()[0].splitlines()
        retval = p.returncode
        if retval == 0:
            for line in output:
                line_str = line.decode()
                if self.efi_partition in line_str:
                    return line_str.partition(' ')[0]
        else:
            return None

    def add_entry(self, entry):
        self.entries_list.append(entry)

    def create_entry(self, name, loader=None):
        if loader:
            new_loader = loader.replace('/', '\\')
            cmd = ['efibootmgr', '-c', '-d', self.efi_hd, '-l', new_loader,
                    '-p', self.efi_partition_number, '-L', name]
        else:
            cmd = ['efibootmgr', '-c', '-d', self.efi_hd,
                    '-p', self.efi_partition_number, '-L', name]
        return subprocess.call(cmd)

    def delete_entry(self, number):
        for i in self.entries_list:
            if i.number == number:
                self.entries_list.pop(self.entries_list.index(i))
                break

    def set_timeout(self, timeout):
        p = subprocess.call(['efibootmgr', '-t', str(timeout)])
        return p

    def delete_timeout(self):
        p = subprocess.call(['efibootmgr', '-T'])
        return p

    def get_loader(self, number):
        loader = None
        p = subprocess.Popen(['efibootmgr', '-v'], stdout=subprocess.PIPE)
        output = p.communicate()[0].splitlines()
        retval = p.returncode
        if retval == 0:
            for line in output:
                line_str = line.decode()
                if line_str.startswith("Boot%s" % number):
                    if 'File(' in line_str:
                        loader = line_str.partition('File(')[2].partition(')')[0]
                    break
        return loader

    def set_boot_order(self, order):
        return subprocess.call(['efibootmgr', '-o', ','.join(order)])

    def update(self):
        self.entries_list = []
        self.boot_order = []
        self.boot_current = None
        self.boot_next = None
        self.timeout = None
        self.efi_mountpoint = self.get_efi_mountpoint()
        p = subprocess.Popen('efibootmgr', stdout=subprocess.PIPE)
        output = p.communicate()[0].splitlines()
        retval = p.returncode
        if retval == 0:
            for line in output:
                line_str = line.decode()
                part1 = line_str.partition(' ')[0]
                part2 = line_str.partition(' ')[2]
                if part1.startswith('BootCurrent:'):
                    self.boot_current = part2
                elif part1.startswith('BootNext:'):
                    self.boot_next = part2
                elif part1.startswith('BootOrder:'):
                    for i in part2.split(','):
                        self.boot_order.append(i)
                elif part1.startswith('Timeout:'):
                    self.timeout = int(part2.partition(' sec')[0])
                elif part1.startswith('Boot'):
                    if part1.endswith('*'):
                        enabled = True
                        number = part1.partition('*')[0].partition('Boot')[2]
                        name = part2.split('\t')[0]
                    else:
                        enabled = False
                        number = part1.partition('Boot')[2]
                        name = part2.partition(' ')[2]
                    if number == self.boot_next:
                        boot_next = True
                    else:
                        boot_next = False
                    loader = self.get_loader(number)
                    entry = Entry(number, name, enabled=enabled,
                            boot_next = boot_next, loader=loader)
                    self.add_entry(entry)
        return retval

class Entry:

    def __init__(self, number, name, enabled=True, boot_next=False, loader='\elilo.efi'):
        self.number = number
        self.name = name
        self.enabled = enabled
        self.loader = loader
        self.boot_next = boot_next

    def activate(self):
        p = subprocess.call(['efibootmgr', '-a', '-b', self.number])
        if p == 0:
            self.enabled = True
        return p

    def deactivate(self):
        p = subprocess.call(['efibootmgr', '-A', '-b', self.number])
        if p == 0:
            self.enabled = False
        return p

    def enable_boot_next(self):
        p = subprocess.call(['efibootmgr', '-n', self.number])
        if p == 0:
            self.boot_next = True
        return p

    def disable_boot_next(self):
        p = subprocess.call(['efibootmgr', '-N'])
        if p == 0:
            self.boot_next = False
        return p

    def delete(self):
        p = subprocess.call(['efibootmgr', '-B', '-b', self.number])
        return p


class GUEFI:

    #
    # Main window actions
    #
    def gtk_main_quit(self, widget, data=None):
        Gtk.main_quit()

    def on_button_add_clicked(self, widget):
        self.entry_add_name.set_text('')
        self.entry_loader_path.set_text('')
        self.filechooserbutton_loader.set_current_folder(self.uefi.efi_mountpoint)
        filename = self.filechooserbutton_loader.get_filename()
        if filename:
            self.filechooserbutton_loader.unselect_filename(filename)
        self.dialog_add.show()

    def on_button_edit_clicked(self, widget):
        try:
            name, number = self.get_current_selection()
        except TypeError:
            pass
        else:
            loader = None
            loader_efi_path = None
            loader_mounted_path = None
            loader_basename = None
            for i in self.uefi.entries_list:
                if i.number == number and i.loader:
                    loader = i.loader.replace('\\', '/')
                    break
            if loader:
                loader_basename = os.path.basename(loader)
                loader_dir = "%s/" % os.path.dirname(loader)
                loader_efi_path = loader.partition(loader_basename)[0]
                loader_mounted_path = "%s%s" % (self.uefi.efi_mountpoint,
                        loader_efi_path)
                loader_full_path = "%s/%s" % (loader_mounted_path,
                        loader_basename)
                self.entry_edit_loader_path.set_text(loader_dir)
                self.filechooserbutton_edit_loader.select_filename(loader_full_path)
                self.entry_edit_name.set_text(name)
                self.boot_number_to_edit = number
                self.dialog_edit.show()
            else:
                msg = _("This UEFI boot entry cannot be edited")
                self.show_dialog(msg, parent = self.window,
                        dialog_type = Gtk.MessageType.INFO)

    def on_button_remove_clicked(self, widget):
        try:
            name, number = self.get_current_selection()
        except TypeError:
            pass
        else:
            dialog = Gtk.MessageDialog(parent = self.window, flags = 0,
                    message_type = Gtk.MessageType.QUESTION,
                    buttons = Gtk.ButtonsType.YES_NO,
                    text = _("Are you sure you want to remove this EFI boot entry?"))
            dialog.set_modal(self.window)
            dialog.format_secondary_text(name)
            response = dialog.run()
            p = 0
            if response == Gtk.ResponseType.YES:
                p = subprocess.call(['efibootmgr', '-B', '-b', number])
            dialog.destroy()
            self.update_list()
            if p != 0:
                msg = _("Could not delete boot entry")
                self.show_dialog(msg, parent = self.window)

    def on_button_timeout_clicked(self, widget):
        self.update_timeout()
        self.dialog_timeout.show()

    def on_button_about_clicked(self, widget):
        self.aboutdialog.show()

    # the cellrenderertoggles are ran before the cursos-changed signal for the
    # treeview. This creates a problem where if the code to toggle the checkbox
    # was in here, it would change the one for the entry that was previously
    # selected, not the new/current one! By specifying the action here for both
    # boot_next and enabled toggles and having the actual code do the work in
    # on_treeview_entries_cursor_changed further down, we work around this
    # issue.
    def on_cellrenderertoggle_boot_next_toggled(self, widget, data=None):
        self.entry_action = EntryAction.ToggleBootNext

    def on_cellrenderertoggle_enabled_toggled(self, widget, data=None):
        self.entry_action = EntryAction.ToggleEnable

    def on_treeview_entries_drag_end(self, widget, data=None):
        boot_order = []
        for i in self.liststore_entries:
            boot_order.append(i[1])
        p = self.uefi.set_boot_order(boot_order)
        if p != 0:
            msg = _("Could not set boot order")
            self.show_dialog(msg, parent = self.window)
        else:
            # since setting the boot order was successful, also update the
            # internal list that holds it
            self.uefi.boot_order = boot_order

    def get_current_selection(self):
        selectedline = self.treeview_entries.get_selection()
        self.liststore_entries, iter = selectedline.get_selected()
        name = self.liststore_entries.get_value(iter, 0)
        number = self.liststore_entries.get_value(iter, 1)
        return name, number

    def on_treeview_entries_cursor_changed(self, widget, data=None):
        if self.entry_action != EntryAction.DoNothing:
            name, number = self.get_current_selection()
            # self.entry_action is set when running the
            # on_cellrenderertoggle_boot_next_toggled or
            # on_cellrenderertoggle_enabled_toggled functions, which are ran before
            # the cursor-changed signal is emited
            if self.entry_action == EntryAction.ToggleBootNext:
                self.toggle_boot_next(number)
            elif self.entry_action == EntryAction.ToggleEnable:
                self.toggle_enable(number)
            self.entry_action = EntryAction.DoNothing

    def toggle_boot_next(self, number):
            for i in self.uefi.entries_list:
                if i.number == number:
                    selectedline = self.treeview_entries.get_selection()
                    self.liststore_entries, iter = selectedline.get_selected()
                    boot_next = self.liststore_entries.get_value(iter, 3)
                    if boot_next:
                        p = i.disable_boot_next()
                        if p == 0:
                            self.liststore_entries.set_value(iter, 3, False)
                    else:
                        for j in self.uefi.entries_list:
                            j.boot_next = False
                        p = i.enable_boot_next()
                        if p == 0:
                            for j in self.liststore_entries:
                                j[3] = False
                            self.liststore_entries.set_value(iter, 3, True)
                    break

    def toggle_enable(self, number):
            for i in self.uefi.entries_list:
                if i.number == number:
                    selectedline = self.treeview_entries.get_selection()
                    self.liststore_entries, iter = selectedline.get_selected()
                    enabled = self.liststore_entries.get_value(iter, 2)
                    if enabled:
                        p = i.deactivate()
                        if p == 0:
                            self.liststore_entries.set_value(iter, 2, False)
                    else:
                        p = i.activate()
                        if p == 0:
                            self.liststore_entries.set_value(iter, 2, True)
                    if p == 16:
                        msg = _("Cannot set state for this boot entry")
                        self.show_dialog(msg, parent = self.window)
                    break

    #
    # Add dialog actions
    #
    def on_button_add_ok_clicked(self, widget):
        new_name = self.entry_add_name.get_text()
        if not self.new_loader:
            msg = _("No EFI loader has been selected")
            self.show_dialog(msg, parent = self.dialog_add)
        elif not efi_name_test(new_name):
            msg = "%s %s" % (_("Invalid name. Allowed characters are the space character and the following:"),
                    "A-Z a-z 0-9 .,:;-_()/")
            self.show_dialog(msg, parent = self.dialog_add)
        else:
            p = self.uefi.create_entry(new_name, self.new_loader)
            if p != 0:
                msg = "%s %s" % (_("Something went wrong."),
                        _("Could not create new boot entry."))
                self.show_dialog(msg, parent = self.dialog_add)
            else:
                self.update_list()
                self.dialog_add.hide()

    def on_button_add_cancel_clicked(self, widget):
        self.entry_loader_path.set_text('')
        self.new_loader = None
        self.dialog_add.hide()

    # this runs whenever a new file is selected through the "Add" dialog
    def on_filechooserbutton_loader_file_set(self, widget):
        filename = self.filechooserbutton_loader.get_filename()
        self.new_loader = self.get_loader_from_filename(filename)
        if not self.new_loader:
            # show an error message that warns about the EFI loader location
            msg = _("The EFI loader you have selected is not located inside the EFI partition")
            self.show_dialog(msg, parent = self.dialog_add)
            self.entry_loader_path.set_text('**%s**' % _("ERROR"))
            self.new_loader = None

    #
    # Edit dialog actions
    #
    def on_button_edit_ok_clicked(self, widget):
        # efibootmgr does not actually allow for editing an existing entry.
        # One has to create a new entry and delete the old one. This makes
        # "editing" a lot more complicated that it should have been.
        number = self.boot_number_to_edit
        # switch this to True if something happens. Helps avoiding arrowhead
        # code.
        error = False
        done = False
        for i in self.uefi.entries_list:
            if i.number == number:
                old_name = i.name
                old_loader = i.loader.replace('\\', '/')
                enabled = i.enabled
                boot_next = i.boot_next
        new_name = self.entry_edit_name.get_text()
        filename = self.filechooserbutton_edit_loader.get_filename()
        self.new_loader = self.get_loader_from_filename(filename)
        if not self.new_loader:
            # show an error message that warns about the EFI loader location
            error = True
            msg = _("The EFI loader you have selected is not located inside the EFI partition")
            self.show_dialog(msg, parent = self.dialog_edit)
            self.entry_edit_loader_path.set_text('**%s**' % _("ERROR"))
        elif not efi_name_test(new_name):
            error = True
            msg = "%s %s" % (_("Invalid name. Allowed characters are the space character and the following:"),
                    "A-Z a-z 0-9 .,:;-_()/")
            self.show_dialog(msg, parent = self.dialog_edit)
        if not error:
            # store the current position in the boot order, so we can later put
            # the new entry at the same position
            boot_order = self.uefi.boot_order
            if old_name != new_name or old_loader != self.new_loader:
                p = self.uefi.create_entry(new_name, loader = self.new_loader)
                if p != 0:
                    error = True
                    msg = "%s %s" % (_("Something went wrong."),
                        _("Adding new boot entry failed."))
                    self.show_dialog(msg, parent = self.dialog_edit)
            else:
                # Both label and loader have not changed, so nothing else to do
                # here.
                done = True
        if not error and not done:
            # OK, the new boot entry has been succesfully created. Time to
            # delete the old one now
            # Let's update the UEFI info first. The first item in the new
            # boot order is our new entry.
            p = self.uefi.update()
            if p != 0:
                error = True
                msg = "%s %s" % (_("Something went wrong."),
                    _("Could not update UEFI information."))
                self.show_dialog(msg, parent = self.dialog_edit)
        if not error and not done:
            # time to delete the old entry
            p = subprocess.call(['efibootmgr', '-B', '-b', number])
            if p != 0:
                error = True
                msg = "%s %s" % (_("Something went wrong."),
                    _("Deleting old boot entry failed."))
                self.show_dialog(msg, parent = self.dialog_edit)
        if not error and not done:
            # OK, the old boot entry has now been deleted. Now
            # rearrange the boot order to be the same as it was
            # before adding the new entry and deleting the old one
            new_number = self.uefi.boot_order[0]
            boot_order[boot_order.index(number)] = new_number
            p = self.uefi.set_boot_order(boot_order)
            if p != 0:
                error = True
                msg = "%s %s" % (_("Something went wrong."),
                    _("Could not rearrange boot order"))
                self.show_dialog(msg, parent = self.dialog_edit)
        if not error and not done and not enabled:
            # if the previous entry is disabled, so should be the new one.
            # Default for a new entry is to be enabled, so we don't have to
            # explicitly enabled it.
            p = subprocess.call(['efibootmgr', '-A', '-b', new_number])
            if p != 0:
                error = True
                msg = "%s %s" % (_("Something went wrong."),
                    _("Could not disable boot entry."))
                self.show_dialog(msg, parent = self.dialog_edit)
        if not error and not done and boot_next:
            # if the previous entry is set as BootNext, so should be the new
            # one. Default for a new entry is to be disabled.
            p = subprocess.call(['efibootmgr', '-n', new_number])
            if p != 0:
                error = True
                msg = "%s %s" % (_("Something went wrong."),
                    _("Could not set BootNext attribute."))
                self.show_dialog(msg, parent = self.dialog_edit)
        if not error:
            # Done! Finally!
            # Let's update the main window list and clean up
            self.update_list()
            self.boot_number_to_edit = None
            self.new_loader = None
            self.dialog_edit.hide()

    def on_button_edit_cancel_clicked(self, widget):
        self.boot_number_to_edit = None
        self.new_loader = None
        self.dialog_edit.hide()

    # this runs whenever a new file is selected through the "Edit" dialog
    def on_filechooserbutton_edit_loader_file_set(self, widget):
        filename = self.filechooserbutton_edit_loader.get_filename()
        self.new_loader = self.get_loader_from_filename(filename)
        if not self.new_loader:
            # show an error message that warns about the EFI loader location
            msg = _("The EFI loader you have selected is not located inside the EFI partition")
            self.show_dialog(msg, parent = self.dialog_add)
            self.entry_edit_loader_path.set_text('**%s**' % _("ERROR"))
            self.new_loader = None
        else:
            new_path = "%s/" % os.path.dirname(self.new_loader)
            self.entry_edit_loader_path.set_text(new_path)

    # this is used by both the Add and Edit dialogs and returns the new loader
    # from the filename that is chosen using the filechoosers
    def get_loader_from_filename(self, filename):
        basename = os.path.basename(filename)
        if filename.startswith(self.uefi.efi_mountpoint):
            path = filename.partition(self.uefi.efi_mountpoint)[2].partition(basename)[0]
            self.entry_loader_path.set_text(path)
            new_loader = path+basename
            return new_loader
        else:
            return None

    #
    # Timeout dialog actions
    #
    def on_button_timeout_ok_clicked(self, widget):
        enabled = self.checkbutton_timeout.get_active()
        if enabled:
            timeout = self.spinbutton_timeout.get_value()
            if timeout != self.uefi.timeout:
                p = self.uefi.set_timeout(timeout)
                if p == 0:
                    self.uefi.timeout = timeout
        else:
            p = self.uefi.delete_timeout()
            if p == 0:
                self.uefi.timeout = None
        self.update_timeout()
        self.dialog_timeout.hide()

    def on_button_timeout_cancel_clicked(self, widget):
        self.dialog_timeout.hide()

    def update_timeout(self):
        label_t = _("Timeout (s):")
        if not self.uefi.timeout:
            label = "%s %s" % (label_t, _("Disabled"))
            self.checkbutton_timeout.set_active(False)
            self.label_timeout_t.set_sensitive(False)
            self.spinbutton_timeout.set_sensitive(False)
            self.spinbutton_timeout.set_value(0)
        else:
            label = "%s %d" % (label_t, self.uefi.timeout)
            self.checkbutton_timeout.set_active(True)
            self.label_timeout_t.set_sensitive(True)
            self.spinbutton_timeout.set_sensitive(True)
            self.spinbutton_timeout.set_value(self.uefi.timeout)
        self.label_timeout.set_text(label)

    def on_checkbutton_timeout_toggled(self, widget):
        enabled = self.checkbutton_timeout.get_active()
        if enabled:
            self.label_timeout_t.set_sensitive(True)
            self.spinbutton_timeout.set_sensitive(True)
        else:
            self.label_timeout_t.set_sensitive(False)
            self.spinbutton_timeout.set_sensitive(False)

    #
    # About dialog actions
    #
    def on_aboutdialog_response(self, widget, data=None):
        self.aboutdialog.hide()

    def on_aboutdialog_delete_event(self, widget, event):
        self.aboutdialog.hide()
        return True

    # this updates the boot entries list in the main window
    def update_list(self):
        self.liststore_entries.clear()
        self.uefi.update()
        boot_order = self.uefi.boot_order
        # if the boot order does not include all UEFI entries, then append the
        # missing ones at the end of the list
        if len(boot_order) < len(self.uefi.entries_list):
            for i in self.uefi.entries_list:
                if i.number not in boot_order:
                    boot_order.append(i.number)
        # now add everything to the liststore, according to the boot order
        for n in boot_order:
            name = None
            if n == self.uefi.boot_next:
                boot_next = True
            else:
                boot_next = False
            for j in self.uefi.entries_list:
                if j.number == n:
                    name = j.name
                    enabled = j.enabled
                    break
            if name is not None:
                self.liststore_entries.append([name, n, enabled, boot_next])

    def show_dialog(self, message, parent = None,
            dialog_type = Gtk.MessageType.ERROR):
        dialog = Gtk.MessageDialog(parent = parent, flags = 0,
                message_type = dialog_type, buttons = Gtk.ButtonsType.OK,
                text = message)
        dialog.set_modal(parent)
        dialog.run()
        dialog.destroy()

    def __init__(self):
        self.uefi = UEFI()
        self.entry_action = EntryAction()

        # this is going to be used to store the path to the EFI loader when
        # the Add and Edit buttons are pressed
        self.new_loader = None
        # and this for storing the BootNum that is going to be edited
        self.boot_number_to_edit = None

        builder = Gtk.Builder()
        builder.set_translation_domain('guefi')
        if os.path.exists('guefi.ui'):
            builder.add_from_file('guefi.ui')
        elif os.path.exists('/usr/share/guefi/guefi.ui'):
            builder.add_from_file('/usr/share/guefi/guefi.ui')
        
        # Main window
        self.window = builder.get_object('guefi')
        self.treeview_entries = builder.get_object('treeview_entries')
        self.treeviewcolumn_boot_number = builder.get_object('treeviewcolumn_boot_number')
        self.treeviewcolumn_boot_number.set_visible(False)
        self.treeviewcolumn_boot_next = builder.get_object('treeviewcolumn_boot_next')
        self.liststore_entries = builder.get_object('liststore_entries')
        self.label_timeout = builder.get_object('label_timeout')
        self.update_list()

        # Add boot entry dialog
        self.dialog_add = builder.get_object('dialog_add')
        self.entry_add_name = builder.get_object('entry_add_name')
        self.entry_loader_path = builder.get_object('entry_loader_path')
        self.filechooserbutton_loader = builder.get_object('filechooserbutton_loader')

        # Edit boot entry dialog
        self.dialog_edit = builder.get_object('dialog_edit')
        self.entry_edit_name = builder.get_object('entry_edit_name')
        self.label_edit_loader_path = builder.get_object('label_edit_loader_path')
        self.entry_edit_loader_path = builder.get_object('entry_edit_loader_path')
        self.filechooserbutton_edit_loader = builder.get_object('filechooserbutton_edit_loader')

        # This is used for both the Add and Edit dialog filechoosers
        self.filefilter_efi = builder.get_object('filefilter_efi')
        self.filefilter_efi.add_pattern('*.efi')

        # Timeout dialog
        self.dialog_timeout = builder.get_object('dialog_timeout')
        self.checkbutton_timeout = builder.get_object('checkbutton_timeout')
        self.label_timeout_t = builder.get_object('label_timeout_t')
        self.spinbutton_timeout = builder.get_object('spinbutton_timeout')
        self.update_timeout()

        # About dialog
        self.aboutdialog = builder.get_object('aboutdialog')

        if not self.uefi.efi_partition:
            msg = _("No UEFI partition detected. Aborting.")
            self.show_dialog(msg, parent = self.window)
            sys.exit(1)
        if not self.uefi.efi_mountpoint:
            msg = _("UEFI partition is not mounted. Aborting.")
            self.show_dialog(msg, parent = self.window)
            sys.exit(1)

        # it doesn't hurt to reload the efivars module. If it cannot be loaded,
        # then this is not an UEFI system
        p = subprocess.call(['modprobe', 'efivarfs'])
        if p != 0:
            msg = _("This does not look like an UEFI system. Aborting.")
            self.show_dialog(msg, parent = self.window)
            sys.exit(1)

        builder.connect_signals(self)

if __name__ == "__main__":
    app = GUEFI()
    app.window.show_all()
    Gtk.main()
