#!/usr/bin/env python3
#
# by Kendall Weaver <kendall@peppermintos.com>
# for Peppermint OS
# modified by Mark Greaves (PCNetSpec) <mark@peppermintos.com>
# internationalization (i18n)/gettext support by Kiyohito AOKI
#
# Ice is a simple Site Specific Browser (SSB) manager for Chromium and
# Chrome specifically intended to integrate with the LXDE menu system.
# Unlike the built-in functions in the browsers, Ice boasts the ability
# to remove SSBs, validate addresses, and prevent overwriting existing
# SSBs. Special thanks to Matt Phillips <labratmatt@gmail.com> for the
# excellent pyfav library that is integrated into this application.
# ADDENDUM: Added support for Firefox (via "ice-firefox") and Vivaldi.

import os
import sys
import requests
import urllib.request
import urllib.parse
import urllib.error
import os.path
import string
import gi  ## added by MG ##
gi.require_version('Gtk','3.0') ## added by MG ##
from gi.repository import Gtk
from gi.repository.GdkPixbuf import Pixbuf
from urllib.parse import urlparse, urlunparse
from bs4 import BeautifulSoup

import gettext
import locale

_HOME = os.getenv("HOME")
_ICE_DIR = "{0}/.local/share/ice".format(_HOME)
_APPS_DIR = "{0}/.local/share/applications".format(_HOME)
_ICE_ICON = "/usr/share/pixmaps/ice.png"
_CHROME_BIN = "/usr/bin/google-chrome"
_CHROMIUM_BIN = "/usr/bin/chromium-browser"
_VIVALDI_BIN = "/usr/bin/vivaldi"
_FIREFOX_BIN = "/usr/bin/firefox"

gettext.bindtextdomain('messages', os.path.dirname(__file__)+ '/../share/ice/locale/')
gettext.textdomain('messages')
_ = gettext.gettext



# Requisite dirs
if not os.path.exists(_ICE_DIR):
    os.system("mkdir -p {0}".format(_ICE_DIR))

if not os.path.exists(_APPS_DIR):
    os.system("mkdir -p {0}".format(_APPS_DIR))

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) \
        AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 \
        Safari/537.36'
}


def get_details(app):
    a = open(app, 'r')
    nameline = ""
    iconline = ""
    is_ice = False

    for line in a:
        if "Name=" in line:
            array = line.replace("=", " ").split()
            array.pop(0)
            for word in array:
                nameline = nameline + word + " "
        elif "Icon=" in line:
            array = line.replace("=", " ").split()
            array.pop(0)
            for word in array:
                iconline = iconline + word
            try:
                pixbuf = Pixbuf.new_from_file_at_size(iconline, 16, 16)
            except:
                pixbuf = Pixbuf.new_from_file_at_size(_ICE_ICON, 16, 16)
        elif "StartupWMClass=Chromium" in line:
            is_ice = True

    if nameline is not None and iconline is not None and is_ice is True:
        return (nameline, pixbuf)

    return (None, None)


def normalize(url):
    (scheme, netloc, path, _, _, frag) = urlparse(url, "http")
    if not netloc and path:
        return urlunparse((scheme, path, "", "", "", ""))

    return urlunparse((scheme, netloc, path, "", "", ""))


def errortest(url):
    try:
        urllib.request.urlopen(url)
        return True
    except (urllib.request.HTTPError, urllib.request.URLError):
        return False


def download_favicon(url, file_prefix='', target_dir='/tmp'):
    parsed_site_uri = urlparse(url)

    if not parsed_site_uri.scheme:
        url = 'http://{0}'.format(url)
        parsed_site_uri = urlparse(url)

    if not parsed_site_uri.scheme or not parsed_site_uri.netloc:
        raise Exception(_("Unable to parse URL, {0}").format(url))

    favicon_url = get_favicon_url(url)

    if not favicon_url:
        raise Exception(_("Unable to find favicon for, {0}").format(url))
    response = requests.get(favicon_url, headers=headers)
    if response.status_code == requests.codes.ok:
        parsed_uri = urlparse(favicon_url)
        favicon_filepath = parsed_uri.path
        favicon_path, favicon_filename = os.path.split(favicon_filepath)

    valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits)

    sanitized_filename = "".join([x if valid_chars else "" for x in favicon_filename])

    sanitized_filename = os.path.join(target_dir, file_prefix + sanitized_filename)

    with open(sanitized_filename, 'wb') as f:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:  # filter out keep-alive new chunks
                    f.write(chunk)
                    f.flush()

    return sanitized_filename


def parse_markup_for_favicon(markup, url):
    parsed_site_uri = urlparse(url)

#    soup = BeautifulSoup(markup)
    soup = BeautifulSoup(markup, "lxml") ## edited by MG ##

    icon_link = soup.find('link', rel='icon')
    if icon_link and icon_link.has_attr('href'):

        favicon_url = icon_link['href']

        if favicon_url.startswith('//'):
            parsed_uri = urlparse(url)
            favicon_url = "{0}:{1}".format(parsed_uri.scheme, favicon_url)

        elif favicon_url.startswith('/'):
            favicon_url = "{0}://{1}{2}".format(parsed_site_uri.scheme, parsed_site_uri.netloc, favicon_url)

        elif not favicon_url.startswith('http'):
            path, filename = os.path.split(parsed_site_uri.path)
            favicon_url = "{0}://{1}/{2}".format(parsed_site_uri.scheme, parsed_site_uri.netloc,
                                                 os.path.join(path, favicon_url))

        return favicon_url

    return None


def get_favicon_url(url):
    parsed_site_uri = urlparse(url)

    try:
        response = requests.get(url, headers=headers)
    except:
        raise Exception(_("Unable to find URL. Is it valid? {0}").format(url))

    if response.status_code == requests.codes.ok:
        favicon_url = parse_markup_for_favicon(response.content, url)

        if favicon_url:
            return favicon_url

    favicon_url = '{uri.scheme}://{uri.netloc}/favicon.ico'.format(uri=parsed_site_uri)

    response = requests.get(favicon_url, headers=headers)
    if response.status_code == requests.codes.ok:
        return favicon_url

    return None


def applicate():
    title = name.get_text()
    address = normalize(url.get_text())

    semiformatted = ""
    array = filter(str.isalpha, title)
    for obj in array:
        semiformatted = semiformatted + obj
    formatted = semiformatted.lower()

    loc = where.get_active_text()
    if loc == _("Accessories"):
        location = "Utility;"
    elif loc == _("Games"):
        location = "Game;"
    elif loc == _("Graphics"):
        location = "Graphics;"
    elif loc == _("Internet"):
        location = "Network;"
    elif loc == _("Office"):
        location = "Office;"
    elif loc == _("Programming"):
        location = "Development;"
    elif loc == _("Sound & Video"):
        location = "AudioVideo;"
    elif loc == _("System Tools"):
        location = "System;"

    global iconpath
    iconname = iconpath.replace("/", " ").split()[-1]
    iconext = iconname.replace(".", " ").split()[-1]

    if os.path.exists("{0}/{1}.desktop".format(_APPS_DIR, formatted)):
        DuplicateError(title, formatted, address, iconext, location)
    else:
        writefile(title, formatted, address, iconext, location)


def writefile(title, formatted, address, iconext, location):
    global iconpath
    os.system("cp --force {0} {1}/{2}.{3}".format(iconpath, _ICE_DIR, formatted, iconext))
    appfile = os.path.expanduser("{0}/{1}.desktop".format(_APPS_DIR, formatted))
    os.system("touch {0}".format(appfile))
    if chrome.get_active() == True:
        browser = "google-chrome"
    elif chromium.get_active() == True:
        browser = "chromium-browser"
    elif vivaldi.get_active() == True:
        browser = "vivaldi"
    elif firefox.get_active() == True:
        browser = "ice-firefox"
    else:
        print(_("ERROR: An unknown browser selection error has occurred."))
        sys.exit(1)

    with open(appfile, 'w') as appfile1:
        appfile1.truncate()
        appfile1.write("[Desktop Entry]\n")
        appfile1.write("Version=1.0\n")
        appfile1.write("Name={0}\n".format(title))
        appfile1.write("Comment={0} (Ice SSB)\n".format(title))

        if (browser == "ice-firefox"):
            appfile1.write("Exec={0} {1}\n".format(browser, address))
        else:
            appfile1.write("Exec={0} --app={1}\n".format(browser, address))

        appfile1.write("Terminal=false\n")
        appfile1.write("X-MultipleArgs=false\n")
        appfile1.write("Type=Application\n")
        appfile1.write("Icon={0}/.local/share/ice/{1}.{2}\n".format(_HOME, formatted, iconext))
        appfile1.write("Categories=GTK;{0}\n".format(location))
        appfile1.write("MimeType=text/html;text/xml;application/xhtml_xml;\n")
        appfile1.write("StartupWMClass=Chromium\n")
        appfile1.write("StartupNotify=true\n")

        if (browser == "ice-firefox"):
            address1 = str.replace(address, 'http://', '')
            address2 = str.replace(address1, 'https://', '')
            address3 = str.replace(address2, '/', '_')
            appfile1.write("IceFirefox={0}".format(address3))

    name.set_text("")
    url.set_text("")
    iconpath = _ICE_ICON
    new_icon = Pixbuf.new_from_file_at_size(iconpath, 32, 32)
    icon.set_from_pixbuf(new_icon)
    iconline, pixbuf = get_details(appfile)
    liststore.prepend([pixbuf, iconline])


def delete(button):
    a = iconview.get_selected_items()
    b = liststore.get_iter(a[0])
    c = liststore.get_value(b, 1)
    liststore.remove(b)

    semiformatted = ""
    array = filter(str.isalpha, c)

    for obj in array:
        semiformatted = semiformatted + obj

    formatted = semiformatted.lower()
    appfile = "{0}/{1}.desktop".format(_APPS_DIR, formatted)

    appfileopen = open(appfile, 'r')
    appfilelines = appfileopen.readlines()
    appfileopen.close()

    for line in appfilelines:
        if "IceFirefox=" in line:
            profile = str.replace(line, 'IceFirefox=', '')
            directory = os.path.expanduser('{0}/firefox'.format(_ICE_DIR))

            for profiles in os.listdir(directory):
#                if profile in profiles:## edited by MG ##
                    os.system("rm -rf {0}/{1}".format(directory, profile))

    os.system("rm {0}".format(appfile))


class IconSel(Gtk.FileChooserDialog):

    def __init__(self):

        def update_image(dialog):
            filename = dialog.get_preview_filename()

            try:
                pixbuf = Pixbuf.new_from_file(filename)
                preview.set_from_pixbuf(pixbuf)
                valid_preview = True
            except:
                valid_preview = False

            dialog.set_preview_widget_active(valid_preview)

        filew = Gtk.FileChooserDialog(
            _("Please choose an icon."),
            None,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        filew.set_filename(_ICE_ICON)

        filter1 = Gtk.FileFilter()
        filter1.set_name("Icons")
        filter1.add_mime_type("image/png")
        filter1.add_mime_type("image/jpeg")
        filter1.add_mime_type("image/gif")
        filter1.add_pattern("*.png")
        filter1.add_pattern("*.jpg")
        filter1.add_pattern("*.gif")
        filter1.add_pattern("*.xpm")
        filter1.add_pattern("*.svg")
        filew.add_filter(filter1)

        preview = Gtk.Image()
        filew.set_preview_widget(preview)
        filew.connect("update-preview", update_image)

        response = filew.run()
        if response == Gtk.ResponseType.OK:
            global iconpath
            iconpath = filew.get_filename()
            new_icon = Pixbuf.new_from_file_at_size(iconpath, 32, 32)
            icon.set_from_pixbuf(new_icon)
            filew.destroy()
        elif response == Gtk.ResponseType.CANCEL:
            filew.destroy()


class NoBrowserError(Gtk.Window):

    def destroy(self, button):
        self.close()

    def __init__(self):
        Gtk.Window.__init__(self, title=_("Browser Error"))
        self.set_size_request(250, 130)
        self.set_icon_from_file(_ICE_ICON)

        print(_("test"))

        main_lab = Gtk.Label()
        main_lab.set_markup(_("<b>Warning: No Suitable Browser Detected</b>"))
        text_lab = Gtk.Label(_("The name of the SSB will cause an existing SSB to\nbe overwritten. To prevent this, change a letter in\nthe name. Continue anyway?"))
        text_lab = Gtk.Label(_("Ice requires a system installation of either Google\nChrome or Chromium in order to function. Please\ninstall at least one in order to create SSBs."))

        close = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
        close.connect("clicked", self.destroy)
        void = Gtk.Label()
        box = Gtk.HBox()
        box.pack_start(void, True, True, 0)
        box.pack_start(close, False, False, 0)

        main_vbox = Gtk.VBox()
        main_vbox.pack_start(main_lab, False, False, 10)
        main_vbox.pack_start(text_lab, False, False, 0)
        main_vbox.pack_start(box, False, False, 10)

        main_hbox = Gtk.HBox()
        main_hbox.pack_start(main_vbox, True, True, 10)
        self.add(main_hbox)
        self.show_all()


class DuplicateError(Gtk.Window):

    def destroy(self, button):
        self.close()

    def okay_clicked(self, button, title, formatted, address, iconext, location):

        for item in liststore:
            itemiter = item.iter
            semiformatted = ""
            array = filter(str.isalpha, item[1])

            for obj in array:
                semiformatted = semiformatted + obj

            forma = semiformatted.lower()

            if forma == formatted:
                liststore.remove(itemiter)

        writefile(title, formatted, address, iconext, location)
        self.close()

    def __init__(self, title, formatted, address, iconext, location):
        Gtk.Window.__init__(self, title=_("Duplication Error"))
        self.set_size_request(250, 130)
        self.set_icon_from_file(_ICE_ICON)

        main_lab = Gtk.Label()
        main_lab.set_markup(_("<b>Warning: File Duplication Error</b>"))
        text_lab = Gtk.Label(_("The name of the SSB will cause an existing SSB to\nbe overwritten. To prevent this, change a letter in\nthe name. Continue anyway?"))

        okay = Gtk.Button.new_from_stock(Gtk.STOCK_OK)
        okay.connect("clicked", self.okay_clicked, title, formatted, address, iconext, location)
        cancel = Gtk.Button.new_from_stock(Gtk.STOCK_CANCEL)
        cancel.connect("clicked", self.destroy)
        void = Gtk.Label()
        box = Gtk.HBox()
        box.pack_start(void, True, True, 0)
        box.pack_start(okay, False, False, 10)
        box.pack_start(cancel, False, False, 0)

        main_vbox = Gtk.VBox()
        main_vbox.pack_start(main_lab, False, False, 10)
        main_vbox.pack_start(text_lab, False, False, 0)
        main_vbox.pack_start(box, False, False, 10)

        main_hbox = Gtk.HBox()
        main_hbox.pack_start(main_vbox, True, True, 10)
        self.add(main_hbox)
        self.show_all()


class AddressError(Gtk.Window):

    def destroy(self, button):
        self.close()

    def okay_clicked(self, button):
        applicate()
        self.close()

    def __init__(self):
        Gtk.Window.__init__(self, title=_("Address Error"))
        self.set_size_request(250, 130)
        self.set_icon_from_file(_ICE_ICON)

        main_lab = Gtk.Label()
        main_lab.set_markup(_("<b>Warning: HTTP or URL Error</b>"))
        text_lab = Gtk.Label(_("An error with the web address has been detected.\nThis is possibly the site being down or unavailable\nright now. Continue anyway?"))

        okay = Gtk.Button.new_from_stock(Gtk.STOCK_OK)
        okay.connect("clicked", self.okay_clicked)
        cancel = Gtk.Button.new_from_stock(Gtk.STOCK_CANCEL)
        cancel.connect("clicked", self.destroy)
        void = Gtk.Label()
        box = Gtk.HBox()
        box.pack_start(void, True, True, 0)
        box.pack_start(okay, False, False, 10)
        box.pack_start(cancel, False, False, 0)

        main_vbox = Gtk.VBox()
        main_vbox.pack_start(main_lab, False, False, 10)
        main_vbox.pack_start(text_lab, False, False, 0)
        main_vbox.pack_start(box, False, False, 10)

        main_hbox = Gtk.HBox()
        main_hbox.pack_start(main_vbox, True, True, 10)
        self.add(main_hbox)
        self.show_all()


class Ice(Gtk.Window):

    def destroy(self, button):
        Gtk.main_quit()

    def icon_select(self, button):
        IconSel()

    def apply_clicked(self, button):
        if errortest(normalize(url.get_text())) is True:
            applicate()
        elif errortest(normalize(url.get_text())) is False:
            AddressError()
        elif errortest(normalize(url.get_text())) is None:
            print(_("ERROR: An address error has occurred."))
            sys.exit(1)
        else:
            print(_("ERROR: An unknown error has occurred."))
            sys.exit(1)

    def icon_download(self, button):
        appurl = normalize(url.get_text())
        global iconpath
        try:
            download_favicon(appurl)
            addr0 = get_favicon_url(appurl)
            addr1 = addr0.replace('/', ' ')
            addr2 = addr1.split()[-1]
            iconpath = "/tmp/{0}".format(addr2)
            new_icon = Pixbuf.new_from_file_at_size(iconpath, 32, 32)
            icon.set_from_pixbuf(new_icon)
        except:
            iconpath = _ICE_ICON
            new_icon = Pixbuf.new_from_file_at_size(iconpath, 32, 32)
            icon.set_from_pixbuf(new_icon)

    def __init__(self):
        Gtk.Window.__init__(self, title="Ice")
        self.current_directory = os.path.realpath(_APPS_DIR)
        self.set_size_request(460, 350)
        self.set_icon_from_file(_ICE_ICON)

        ######################
        #   'Create' page.   #
        ######################

        welcome = Gtk.Label()
        welcome.set_markup(_("<b>Welcome to Ice, a simple SSB manager.</b>"))
        global name
        name = Gtk.Entry()
        name.set_placeholder_text(_("Name the application"))
        global url
        url = Gtk.Entry()
        url.set_placeholder_text(_("Enter web address"))

        where_store = [_("Accessories"), _("Games"), _("Graphics"), _("Internet"),
                       _("Office"), _("Programming"), _("Sound & Video"), _("System Tools")]
        where_lab = Gtk.Label(_("Where in the menu?"))
        global where
        where = Gtk.ComboBoxText()
        where.set_entry_text_column(0)
        for entry in where_store:
            where.append_text(entry)
        where.set_active(3)

        where_box = Gtk.HBox()
        where_void = Gtk.Label()
        where_box.pack_start(where_lab, False, False, 0)
        where_box.pack_start(where_void, False, False, 10)
        where_box.pack_start(where, True, True, 0)

        global iconpath
        iconpath = _ICE_ICON
        icon_pixbuf = Pixbuf.new_from_file_at_size(iconpath, 32, 32)
        global icon
        icon = Gtk.Image()
        icon.set_from_pixbuf(icon_pixbuf)

        icon_void = Gtk.Label()
        icon_box = Gtk.HBox()
        icon_box.pack_start(icon, False, False, 10)
        icon_box.pack_start(icon_void, False, False, 10)

        choose_icon = Gtk.Button(_("Select an icon"))
        choose_icon.connect("clicked", self.icon_select)
        download_icon = Gtk.Button(_("Use site favicon"))
        download_icon.connect("clicked", self.icon_download)

        icon_vbox = Gtk.VBox()
        icon_vbox.pack_start(choose_icon, True, True, 5)
        icon_vbox.pack_start(download_icon, True, True, 5)
        icon_hbox = Gtk.HBox()
        icon_hbox.pack_start(icon_box, False, False, 10)
        icon_hbox.pack_start(icon_vbox, True, True, 0)

        global firefox
        firefox = Gtk.RadioButton.new_with_label_from_widget(None, "Firefox")

        if not os.path.exists(_FIREFOX_BIN):
            firefox.set_sensitive(False)

        if not os.path.exists(_CHROMIUM_BIN) and not \
                os.path.exists(_CHROME_BIN) and not \
                os.path.exists(_VIVALDI_BIN) and \
                os.path.exists(_FIREFOX_BIN):
            firefox.set_active(True)

        global chrome
        chrome = Gtk.RadioButton.new_from_widget(firefox)
        chrome.set_label("Chrome")

        if not os.path.exists(_CHROME_BIN):
            chrome.set_sensitive(False)

        if not os.path.exists(_CHROMIUM_BIN) and not \
                os.path.exists(_FIREFOX_BIN) and not \
                os.path.exists(_VIVALDI_BIN) and \
                os.path.exists(_CHROME_BIN):
            chrome.set_active(True)

        global vivaldi
        vivaldi = Gtk.RadioButton.new_from_widget(chrome)
        vivaldi.set_label("Vivaldi")

        if not os.path.exists(_VIVALDI_BIN):
            vivaldi.set_sensitive(False)

        if not os.path.exists(_CHROMIUM_BIN) and not \
                os.path.exists(_FIREFOX_BIN) and not \
                os.path.exists(_CHROME_BIN) and \
                os.path.exists(_VIVALDI_BIN):
            vivaldi.set_active(True)

        global chromium
        chromium = Gtk.RadioButton.new_from_widget(chrome)
        chromium.set_label("Chromium")

        if not os.path.exists(_CHROMIUM_BIN):
            chromium.set_sensitive(False)

        if not os.path.exists(_CHROME_BIN) and not \
                os.path.exists(_FIREFOX_BIN) and not \
                os.path.exists(_VIVALDI_BIN) and \
                os.path.exists(_CHROMIUM_BIN):
            chromium.set_active(True)

        apply_button = Gtk.Button.new_from_stock(Gtk.STOCK_APPLY)
        apply_button.connect("clicked", self.apply_clicked)
        close_button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
        close_button.connect("clicked", self.destroy)
        button_void = Gtk.Label()
        button_box = Gtk.HBox()
        button_box.pack_start(chrome, False, False, 10)
        button_box.pack_start(chromium, False, False, 0)
        button_box.pack_start(vivaldi, False, False, 10)
        button_box.pack_start(firefox, False, False, 0)
        button_box.pack_start(button_void, True, True, 0)
        button_box.pack_start(close_button, False, False, 20)
        button_box.pack_start(apply_button, False, False, 0)

        create_vbox = Gtk.VBox()
        create_vbox.pack_start(welcome, False, False, 15)
        create_vbox.pack_start(name, False, False, 0)
        create_vbox.pack_start(url, False, False, 10)
        create_vbox.pack_start(where_box, False, False, 10)
        create_vbox.pack_start(icon_hbox, False, False, 10)
        create_vbox.pack_start(button_box, False, False, 0)

        create_hbox = Gtk.HBox()
        create_hbox.pack_start(create_vbox, True, True, 20)
        create_lab = Gtk.Label(_("Create"))

        ######################
        #   'Remove' page.   #
        ######################

        global liststore
        liststore = Gtk.ListStore(Pixbuf, str)

        for fl in os.listdir(_APPS_DIR):
            a = "{0}/{1}".format(_APPS_DIR, fl)
            if not os.path.isdir(a):
                nameline, pixbuf = get_details(a)
                if nameline is not None and pixbuf is not None:
                    liststore.append([pixbuf, nameline])

        global iconview
        iconview = Gtk.IconView()
        iconview.set_model(liststore)
        iconview.set_pixbuf_column(0)
        iconview.set_text_column(1)
        iconview.set_selection_mode(1)

        scroll = Gtk.ScrolledWindow()
        scroll.add(iconview)

        remove = Gtk.Button.new_from_stock(Gtk.STOCK_REMOVE)
        remove.connect("clicked", delete)
        close = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
        close.connect("clicked", self.destroy)
        void = Gtk.Label()
        buttons = Gtk.HBox()
        buttons.pack_start(void, True, True, 0)
        buttons.pack_start(close, False, False, 20)
        buttons.pack_start(remove, False, False, 0)

        remove_vbox = Gtk.VBox()
        remove_vbox.pack_start(scroll, True, True, 10)
        remove_vbox.pack_start(buttons, False, False, 0)

        remove_hbox = Gtk.HBox()
        remove_hbox.pack_start(remove_vbox, True, True, 20)
        remove_lab = Gtk.Label(_("Remove"))

        ##########################
        #   Main window stuff.   #
        ##########################

        notebook = Gtk.Notebook()
        notebook.append_page(create_hbox, create_lab)
        notebook.append_page(remove_hbox, remove_lab)

        main_vbox = Gtk.VBox()
        main_vbox.pack_start(notebook, True, True, 10)
        main_hbox = Gtk.HBox()
        main_hbox.pack_start(main_vbox, True, True, 10)
        self.add(main_hbox)
        self.show_all()

        if not os.path.exists(_CHROME_BIN) and not \
                os.path.exists(_CHROMIUM_BIN) and not \
                os.path.exists(_VIVALDI_BIN) and not \
                os.path.exists(_FIREFOX_BIN):
            apply_button.set_sensitive(False)
            NoBrowserError()


if __name__ == '__main__':
    window = Ice()
    window.connect("delete-event", Gtk.main_quit)
    Gtk.main()
