#!/usr/bin/env python3
#
# by Kendall Weaver <kendall@peppermintos.com>
# for Peppermint OS
# modified by Mark Greaves (PCNetSpec) <mark@peppermintos.com>
# with much appreciated code contributions by rhein
# internationalization (i18n)/gettext support by Kiyohito AOKI
# 
# Modified by Scott Vandergrift <scottvandergrift@gmail.com>
# for Pearl Linux
#
# 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)
_PROFILES_DIR = "{0}/profiles".format(_ICE_DIR)
_FF_PROFILES_DIR = "{0}/firefox".format(_ICE_DIR)
_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
for directory in [ _ICE_DIR, _APPS_DIR, _PROFILES_DIR, _FF_PROFILES_DIR ]: 
    if not os.path.exists(directory):
        os.system("mkdir -p {0}".format(directory))

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0',
    #'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', errors='ignore')
    nameline = ""
    iconline = ""
    profile = ""
    is_ice	= False
    is_firefox = False
    is_isolated = 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:
            # for legacy apps
            is_ice = True
        elif "StartupWMClass=ICE-SSB" in line:
            is_ice = True
        elif "IceFirefox=" in line:
            is_firefox = True
            profile = str.replace(line, 'IceFirefox=', '').strip()
        elif "X-ICE-SSB-Profile=" in line:
            is_isolated = True
            profile = str.replace(line, 'X-ICE-SSB-Profile=', '').strip()

    if nameline != "" and iconline != "" and is_ice is True:
        details = {
          'nameline' : nameline,
          'profile' : profile,
          'is_firefox' : is_firefox,
          'is_isolated' : is_isolated,
          'pixbuf': pixbuf
          }
        return details

    return 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, parsed_site_uri):

    soup = BeautifulSoup(markup, "lxml")

    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, parsed_site_uri)

        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 == _("Multimedia"):
        location = "AudioVideo;"
    elif loc == _("System"):
        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)
    elif len(title) == 0:
        EmptyNameError()
    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 = "firefox"
    else:
        print(_("ERROR: An unknown browser selection error has occurred."))
        sys.exit(1)

    with open(appfile, 'w') as appfile1:
        global isolate_profile
        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 == "firefox"):
            firefox_profile_path  = "{0}/{1}".format(_FF_PROFILES_DIR, formatted)
            appfile1.write("Exec={0} --class ICE-SSB-{2} --profile {3} --no-remote {1}\n".format(browser, address, formatted, firefox_profile_path))
            appfile1.write("IceFirefox={0}\n".format(formatted))
            init_firefox_profile(firefox_profile_path)
        else:
            if isolate_profile == True:
                profile_path = "{0}/{1}".format(_PROFILES_DIR, formatted)
                appfile1.write("Exec={0} --app={1} --class=ICE-SSB-{2} --user-data-dir={3}\n".format(browser, address, formatted, profile_path))
                appfile1.write("X-ICE-SSB-Profile={0}\n".format(formatted))
            else:
              appfile1.write("Exec={0} --app={1} --class=ICE-SSB-{2}\n".format(browser, address, formatted))

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

    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)
    details = get_details(appfile)
    if details is not None:
        liststore.prepend([ details['pixbuf'], details['nameline'] ])

def init_firefox_profile(path):
    chromepath = "{0}/chrome".format(path)
    settingsfile = "{0}/user.js".format(path)
    cssfile = "{0}/userChrome.css".format(chromepath)

    os.system('mkdir -p ' + chromepath)
    os.system('cp -n /usr/lib/pearllinux/ice/search.json.mozlz4 ' + path + '/search.json.mozlz4')
    os.system('cp -n /usr/lib/pearllinux/ice/places.sqlite ' + path + '/places.sqlite')
    os.system("touch {0}".format(cssfile))
    with open(cssfile, 'w') as cfile:
        cfile.write("#nav-bar { max-height: 0 !important; margin-bottom: -20px !important; opacity: 0; } #identity-box, #navigator-toolbox::after, #tabbrowser-tabs {  --tab-min-height: 0px !important;  margin-left: 0px !important;  height: 0px !important; }")

    os.system("touch {0}".format(settingsfile))
    with open(settingsfile, 'w') as sfile:
        sfile.write('user_pref("browser.cache.disk.enable", false);')
        sfile.write('user_pref("browser.cache.disk.capacity", 0);')
        sfile.write('user_pref("browser.cache.disk.filesystem_reported", 1);')
        sfile.write('user_pref("browser.cache.disk.smart_size.enabled", false);')
        sfile.write('user_pref("browser.cache.disk.smart_size.first_run", false);')
        sfile.write('user_pref("browser.cache.disk.smart_size.use_old_max", false);')
        sfile.write('user_pref("browser.ctrlTab.previews", true);')
        sfile.write('user_pref("browser.tabs.warnOnClose", false);')
        sfile.write('user_pref("plugin.state.flash", 2);')
        sfile.write('user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);')

    # rhein: do we really need this? 
    #os.system('rm -rf ' + chromepath + '/cache2')


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=', '')
            os.system("rm -rf {0}/{1}".format(_FF_PROFILES_DIR, profile))

        if "X-ICE-SSB-Profile=" in line:
            profile = str.replace(line, 'X-ICE-SSB-Profile=', '')
            os.system("rm -rf {0}/{1}".format(_PROFILES_DIR, profile))

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


def clean_orphaned_profiles(known_apps):
    known_profiles = []
    for app in known_apps:
        a = "{0}/{1}".format(_FF_PROFILES_DIR, app['profile'])
        if app['profile'] != "":
            # make sure firefox apps have profiles available
            if app['is_firefox'] is True and not os.path.isdir(a):
                init_firefox_profile(a)
            known_profiles.append(app['profile'])

    for p_type in ['profiles','firefox']:
        for fl in os.listdir("{0}/{1}/".format(_ICE_DIR, p_type)):
            a = "{0}/{1}/{2}".format(_ICE_DIR, p_type, fl)
            if not os.path.isdir(a) or fl not in known_profiles:
                os.system("rm -rf {0}".format(a))


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(label=_("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(label=_("OK"))
        okay.connect("clicked", self.okay_clicked, title, formatted, address, iconext, location)
        cancel = Gtk.Button(label=_("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(label=_("OK"))
        okay.connect("clicked", self.okay_clicked)
        cancel = Gtk.Button(label=_("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 EmptyNameError(Gtk.Window):

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

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

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

        main_lab = Gtk.Label()
        main_lab.set_markup(_("<b>Error: No Application Name Entered.</b>"))
        text_lab = Gtk.Label(_("Please enter an application name to continue."))

        close = Gtk.Button(label=_("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 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 isolate_clicked(self, button):
        global isolate_profile
        isolate_profile=False
        if button.get_active() == True:
          isolate_profile = True

    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"), _("Multimedia"), _("System")]
        where_lab = Gtk.Label(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(label=_("Select an icon"))
        choose_icon.connect("clicked", self.icon_select)
        download_icon = Gtk.Button(label=_("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)

        global isolate_profile
        isolate_profile=False
        isolate_box = Gtk.VBox()
        isolate_button = Gtk.CheckButton(label=_(" Create the SSB with an isolated browser profile (Note: Firefox SSB's are always isolated)"))
        isolate_button.connect("toggled", self.isolate_clicked)
        isolate_box.add(isolate_button)

        apply_button = Gtk.Button(label=_("Apply"))
        apply_button.connect("clicked", self.apply_clicked)
        close_button = Gtk.Button(label=_("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(isolate_box, 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(label=_("Create"))

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

        global liststore
        known_profiles = []
        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):
                details = get_details(a)
                if details is not None:
                    liststore.append([ details['pixbuf'], details['nameline'] ])
                    known_profiles.append(details)

        clean_orphaned_profiles(known_profiles)

        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(label=_("Remove"))
        remove.connect("clicked", delete)
        close = Gtk.Button(label=_("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(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()
