#!/usr/bin/python3
import gi, os, re, jwmkit_utils
from shutil import which
import xml.etree.ElementTree as ET
from xml.dom import minidom
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf

# JWM Kit - A set of Graphical Apps to simplify use of JWM (Joe's Window Manager) <https://codeberg.org/JWMKit/JWM_Kit>
# Copyright © 2020-2022 Calvin Kent McNabb <apps.jwmkit@gmail.com>
#
# This file is part of JWM Kit.
#
# JWM Kit is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# JWM Kit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with JWM Kit.  If not, see <https://www.gnu.org/licenses/>.


def set_mode():
    # determine jwm is running with a desktop manager
    tasks = os.popen('ps').read()
    tasks = '{}{}'.format(tasks, os.popen('ps -ax').read()).lower()
    if which('set_bg') and os.popen('whoami').read() == 'root':
        if os.path.isdir('/home/spot') and os.path.isdir('/home/finn'):
            mode = 'set_bg'
    elif re.findall('(spacefm --desktop)', tasks):
        mode = 'spacefm'
    elif re.findall('(zzzfm --desktop)', tasks):
        mode = 'zzzfm'
    elif re.findall('(pcmanfm --desktop)', tasks):
        mode = 'pcmanfm'
    elif re.findall('(rox-?filer -p)', tasks):
        mode = 'rox'
    else:
        mode = 'jwm'
    return mode


def get_button_letter(i):
    letters = ('w', 't', 'i', 'm', 'x')
    if i != -1:
        return letters[i]


def make_svg(values):
    vi = ('w', '', 'i', '', 'm', '', 'x', '')
    ca = (56, 69, 77, 90, 111, 98, 132, 119, 15)
    cb = (3, 16, 24, 37, 58, 45, 79, 66, 50)
    t = (10, 34, 54, 75, 100)
    c = [0, 0, 0, 0, 0, 0, 0, 0]
    ti, i, stop = 0, 0, True
    for v in values:
        if stop:
            if v == 't':
                stop = False
            else:
                ti += 1
                c[vi.index(v)] = cb[i]
                c[vi.index(v)+1] = cb[i+1]
                i += 2
        else:
            if v != 't':
                c[vi.index(v)] = ca[i]
                c[vi.index(v)+1] = ca[i+1]
                i += 2
    c.append(t[ti])

    svg = '<?xml version="1.0" encoding="UTF-8"?>'
    svg = '{}\n<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="22" width="140">'.format(svg)
    svg = '{}\n<rect style="fill:#8D8DA8;stroke:#000;stroke-width:2" width="140" height="22"/>'.format(svg)
    svg = '{}\n<style>.single {{ font: 12px sans; }}</style>'.format(svg)
    svg = '{}\n<path style="fill:none;stroke:#FFFFFF;stroke-width:2" d="M{} '.format(svg, c[0])
    svg = '{}6 {} 6 M{} 9 {} 9 M{} 12 {} 12 M{} 15 {} 15 '.format(svg, c[1], c[0], c[1], c[0], c[1], c[0], c[1])
    svg = '{}M{} 15 {} 15 M{} 7 {} 16 {} 16 {} 7z '.format(svg, c[2], c[3], c[4], c[4], c[5], c[5])
    svg = '{}M {} 8 {} 8 M{} 7 {} 16 M{} 7 {} 16'.format(svg, c[5], c[4], c[6], c[7], c[7], c[6])
    svg = '{}" />\n<text x="{}" y="15" class="single" fill="#F9F9F9">Title</text></svg>'.format(svg, c[8])
    with open('/tmp/jwmkit_button_preview.svg', "w+") as f:
        f.write(svg)


class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="JWM Kit Desktops")
        self.home = os.path.expanduser('~')
        self.desk_mode = set_mode()
        self.set_border_width(15)
        self.jwmrc = self.get_path()
        if self.jwmrc == 'warning_settings':
            jwmkit_utils.warning_settings(self)
            return
        self.Image_dir = self.get_last_dir()
        self.Folder_list = os.listdir(self.Image_dir)
        self.Image_folder = []
        self.make_imagelist(self.Folder_list)
        self.display_mode = "stretch"
        self.selected_img, self.image, self.pixs, self.color1, self.color2 = None, None, None, None, None
        self.set_icon_from_file("/usr/share/pixmaps/jwmkit/wallpaper.svg")
        mainbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        self.add(mainbox)
        self.notebook = Gtk.Notebook()
        v_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=20)
        wall_box = Gtk.Box(spacing=5)
        wall_box.set_border_width(10)
        v_box.pack_start(wall_box, True, True, 15)
        self.notebook.append_page(v_box, Gtk.Label(label='Wallpaper'))
        v_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=20)
        p_box = Gtk.Box(spacing=5)
        v_box.add(p_box)
        self.notebook.append_page(v_box, Gtk.Label(label='Preferences'))
        header_box = Gtk.Box(spacing=10)
        mainbox.pack_start(header_box, False, False, 0)
        scroll_window = Gtk.ScrolledWindow()
        scroll_window.set_min_content_width(640)

        self.header_label = Gtk.Label()
        self.header_label.set_markup('\n  <big><b>Wallpaper</b></big>'
                                '\n  &amp; background color\n')
        image = jwmkit_utils.create_image('/usr/share/pixmaps/jwmkit/wallpaper.svg', 48, 48, True)
        header_box.pack_start(image, False, False, 10)
        header_box.add(self.header_label)

        mainbox.pack_start(self.notebook, True, True, 0)
        i_grid = Gtk.Grid()
        wall_box.pack_start(i_grid, False, True, 0)
        wall_box.pack_start(scroll_window, False, True, 0)

        self.image_box = Gtk.Grid()
        scroll_window.add(self.image_box)

        self.status_image = Gtk.Image()
        self.color_button1 = Gtk.ColorButton()
        self.color_button1.connect('color-set', self.on_color_set)
        self.color_button2 = Gtk.ColorButton()
        self.color_button2.connect('color-set', self.on_color_set)
        self.color_button1.set_sensitive(False)
        self.color_button2.set_sensitive(False)

        i_grid.attach(self.color_button1, 1, 6, 1, 1)
        i_grid.attach(self.color_button2, 1, 7, 1, 1)

        status_button = Gtk.Button(image=self.status_image)
        status_button.set_property("height-request", 100)
        status_button.set_property("width-request", 125)
        i_grid.attach(status_button, 1, 0, 1, 1)
        i_grid.attach(Gtk.Label(), 1, 1, 1, 1)
        i_grid.attach(Gtk.Label(), 1, 5, 1, 1)
        i_grid.attach(Gtk.Label(), 1, 8, 1, 1)
        i_grid.attach(Gtk.Label(), 1, 11, 1, 1)

        browse_button = Gtk.Button(label="Browse", image=Gtk.Image(stock=Gtk.STOCK_DIRECTORY))
        browse_button.set_property("width-request", 120)
        browse_button.connect("clicked", self.pick_folder)
        browse_button.set_border_width(2)
        i_grid.attach(browse_button, 1, 12, 1, 1)

        self.stretch = Gtk.RadioButton.new_with_label_from_widget(None, "Stretch")
        self.stretch.set_border_width(1)
        self.stretch.connect("toggled", self.on_button_toggled, "stretch")
        i_grid.attach(self.stretch, 1, 2, 1, 1)

        self.scale = Gtk.RadioButton.new_with_label_from_widget(self.stretch, "Scale")
        self.scale.set_border_width(1)
        self.scale.connect("toggled", self.on_button_toggled, "scale")
        i_grid.attach(self.scale, 1, 3, 1, 1)

        self.tiled = Gtk.RadioButton.new_with_label_from_widget(self.stretch, "Tiled")
        self.tiled.set_border_width(1)
        self.tiled.connect("toggled", self.on_button_toggled, "tiled")
        i_grid.attach(self.tiled, 1, 4, 1, 1)

        self.solid = Gtk.RadioButton.new_with_mnemonic_from_widget(self.stretch, "solid")
        self.solid.set_border_width(1)
        self.solid.set_label("solid color")
        self.solid.connect("toggled", self.on_button_toggled, "solid")
        i_grid.attach(self.solid, 1, 9, 1, 1)

        self.gradient = Gtk.RadioButton.new_with_mnemonic_from_widget(self.stretch, "gradient")
        self.gradient.set_border_width(1)
        self.gradient.set_label("gradient")
        self.gradient.connect("toggled", self.on_button_toggled, "gradient")
        i_grid.attach(self.gradient, 1, 10, 1, 1)

        apply_button = Gtk.Button(label="apply", image=Gtk.Image(stock=Gtk.STOCK_APPLY))
        apply_button.connect("clicked", self.apply_clicked)
        apply_button.set_property("width-request", 120)

        self.clear_button = Gtk.Button(image=Gtk.Image(stock=Gtk.STOCK_DELETE))
        self.clear_button.set_tooltip_text("Remove the selected Desktop's background")
        self.clear_button.set_always_show_image(True)
        self.clear_button.set_property("width-request", 40)
        self.clear_button.connect('clicked', self.clear_background)

        self.about_button = Gtk.Button(image=Gtk.Image(stock=Gtk.STOCK_ABOUT))
        self.about_button.set_always_show_image(True)
        self.about_button.set_property("width-request", 40)
        self.about_button.connect('clicked', jwmkit_utils.get_about, self)

        self.about_button2 = Gtk.Button(label="About", image=Gtk.Image(stock=Gtk.STOCK_ABOUT))
        self.about_button2.set_always_show_image(True)
        self.about_button2.set_property("width-request", 120)
        self.about_button2.connect('clicked', jwmkit_utils.get_about, self)
        self.about_button2.set_no_show_all(True)

        self.workspace_combo = Gtk.ComboBoxText()
        self.workspace_combo.set_property("width-request", 120)
        self.workspace_combo.append_text('All')
        self.workspace_combo.append_text('Default')
        self.workspace_combo.set_active(0)
        self.workspace_label = Gtk.Label(label='Desktop')

        v_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
        box = Gtk.Box(spacing=5)
        header_box.pack_end(v_box, False, False, 0)
        box.pack_end(self.about_button, False, False, 0)
        box.pack_end(apply_button, False, False, 0)

        v_box.add(box)
        box = Gtk.Box(spacing=5)
        v_box.add(box)

        box.pack_end(self.clear_button, False, False, 0)
        box.pack_end(self.workspace_combo, False, False, 0)
        box.pack_end(self.workspace_label, False, False, 0)
        box.pack_end(self.about_button2, False, False, 0)

        self.display_image_butt()

        if self.desk_mode in ('rox', 'spacefm', 'zzzfm'):
            self.solid.set_no_show_all(True)
            self.gradient.set_no_show_all(True)
            self.color_button1.set_no_show_all(True)
            self.color_button2.set_no_show_all(True)
            self.color_button1.set_visible(False)
            self.color_button2.set_visible(False)
            self.solid.set_visible(False)
            self.gradient.set_visible(False)
            if self.desk_mode in ('spacefm', 'zzzfm'):
                self.stretch.set_sensitive(False)
                self.scale.set_sensitive(False)
                self.tiled.set_sensitive(False)

        self.notebook.connect("switch-page", self.page_switch)

        p_grid = Gtk.Grid()
        p_grid.set_row_spacing(10)
        p_grid.set_column_spacing(10)
        p_grid.set_border_width(30)
        p_box.pack_start(p_grid, False, True, 0)
        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Virtual Desktops</b></big>')

        self.d_wide_spin, self.d_high_spin, self.delta_spin = Gtk.SpinButton(), Gtk.SpinButton(), Gtk.SpinButton()
        self.speed_spin, self.delay_spin, self.distance_spin = Gtk.SpinButton(), Gtk.SpinButton(), Gtk.SpinButton()
        self.focus_combo, self.move_coord, self.move_keys = Gtk.ComboBoxText(), Gtk.ComboBoxText(), Gtk.ComboBoxText()
        self.resize_coord, self.snap_combo = Gtk.ComboBoxText(), Gtk.ComboBoxText()
        self.b1_combo, self.b2_combo, self.b3_combo = Gtk.ComboBoxText(), Gtk.ComboBoxText(), Gtk.ComboBoxText()
        self.b4_combo, self.b5_combo = Gtk.ComboBoxText(), Gtk.ComboBoxText()
        self.move_outline, self.resize_outline = Gtk.CheckButton(label='outline'), Gtk.CheckButton(label='outline')
        self.b_defaults = Gtk.CheckButton(label='default')
        self.b_defaults.set_tooltip_text('Use default button order. Uncheck to configure a custom button order')
        self.b_defaults.connect('clicked', self.b_default_on)

        for v in ('click', 'clicktitle', 'sloppy', 'sloppytitle'):
            self.focus_combo.append_text(v)

        for k in ('ALT', 'Control', 'Shift', 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5'):
            self.move_keys.append_text(k)

        self.snap_combo.append_text('none')
        self.snap_combo.append_text('screen')
        self.snap_combo.append_text('border')

        values = ('menu', 'title', 'minimize', 'maximize', 'close')
        for i, combo in enumerate ((self.b1_combo, self.b2_combo, self.b3_combo, self.b4_combo, self.b5_combo)):
            for v in values:
                combo.append_text(v)
                combo.connect('changed', self.combo_setter)
                combo.set_tooltip_text('The button order will not be saved if all values are not set.')

        for combo in (self.move_coord, self.resize_coord):
            combo.append_text('off')
            combo.append_text('corner')
            combo.append_text('window')
            combo.append_text('screen')

        adjustment = Gtk.Adjustment(value=4, lower=1, upper=20, step_increment=1)
        self.d_wide_spin.set_tooltip_text('Number of virtual desktops in the horizontal direction\nDefault is 4')
        self.d_wide_spin.set_adjustment(adjustment)

        adjustment = Gtk.Adjustment(value=1, lower=1, upper=20, step_increment=1)
        self.d_high_spin.set_tooltip_text('Number of virtual desktops in the vertical direction\nDefault is 1')
        self.d_high_spin.set_adjustment(adjustment)

        adjustment = Gtk.Adjustment(value=2, lower=0, upper=32, step_increment=1)
        self.delta_spin.set_tooltip_text('number of pixels the mouse can move during a double click\nDefault is 2')
        self.delta_spin.set_adjustment(adjustment)

        adjustment = Gtk.Adjustment(value=400, lower=1, upper=2000, step_increment=1)
        self.speed_spin.set_tooltip_text('number of milliseconds between clicks for a double click\nDefault is 400')
        self.speed_spin.set_adjustment(adjustment)

        adjustment = Gtk.Adjustment(value=1000, lower=0, upper=10000, step_increment=1)
        self.delay_spin.set_tooltip_text('Milliseconds before moving a window to a different desktop\nDefault is 1000')
        self.delay_spin.set_adjustment(adjustment)

        adjustment = Gtk.Adjustment(value=5, lower=1, upper=32, step_increment=1)
        self.distance_spin.set_tooltip_text('The distance at which snapping occurs\nDefault is 5')
        self.distance_spin.set_adjustment(adjustment)

        p_grid.attach(label, 0, 0, 2, 1)
        p_grid.attach(Gtk.Label(label='Width', xalign=1), 0, 1, 1, 1)
        p_grid.attach(self.d_wide_spin, 1, 1, 1, 1)
        p_grid.attach(Gtk.Label(label='height', xalign=1), 0, 2, 1, 1)
        p_grid.attach(self.d_high_spin, 1, 2, 1, 1)
        p_grid.attach(Gtk.Label(), 0, 3, 1, 1)

        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Double Click</b></big>')
        p_grid.attach(label, 0, 4, 2, 1)
        p_grid.attach(Gtk.Label(label='Delta', xalign=1), 0, 5, 1, 1)
        p_grid.attach(self.delta_spin, 1, 5, 1, 1)
        p_grid.attach(Gtk.Label(label='Speed', xalign=1), 0, 6, 1, 3)
        p_grid.attach(self.speed_spin, 1, 6, 1, 3)
        p_grid.attach(Gtk.Label(), 0, 9, 4, 1)

        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Focus</b></big>')
        p_grid.attach(label, 0, 10, 2, 1)
        p_grid.attach(self.focus_combo, 1, 11, 1, 1)

        p_grid.attach(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), 5, 0, 1, 10)
        p_grid.attach(Gtk.Label(), 6, 0, 1, 1)

        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Move</b></big>')
        p_grid.attach(label, 7, 0, 1, 1)

        p_grid.attach(Gtk.Label(label='coordinates', xalign=.3), 8, 0, 1, 1)
        p_grid.attach(Gtk.Label(), 9, 0, 1, 1)
        p_grid.attach(Gtk.Label(label='delay', xalign=.3), 10, 0, 1, 1)
        p_grid.attach(Gtk.Label(), 11, 0, 1, 1)
        p_grid.attach(Gtk.Label(label='mod key'), 12, 0, 1, 1)
        p_grid.attach(self.move_outline, 7, 1, 1, 1)
        p_grid.attach(self.move_coord, 8, 1, 1, 1)
        p_grid.attach(self.delay_spin, 10, 1, 1, 1)
        p_grid.attach(self.move_keys, 12, 1, 1, 1)

        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Resize</b></big>')
        p_grid.attach(label, 7, 2, 1, 1)
        p_grid.attach(Gtk.Label(label='coordinates', xalign=.3), 8, 2, 1, 1)
        p_grid.attach(self.resize_outline, 7, 3, 1, 1)
        p_grid.attach(self.resize_coord, 8, 3, 1, 1)

        label = Gtk.Label(xalign=0)
        label.set_markup('<big><b>Snap</b></big>')
        p_grid.attach(label, 7, 4, 1, 1)
        p_grid.attach(Gtk.Label(label='mode', xalign=.3), 8, 4, 1, 1)
        p_grid.attach(Gtk.Label(label='distance', xalign=.3), 10, 4, 1, 1)
        p_grid.attach(self.snap_combo, 8, 5, 1, 1)
        p_grid.attach(self.distance_spin, 10, 5, 1, 1)
        p_grid.attach(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), 7, 6, 10, 1)

        label = Gtk.Label()
        label.set_markup('<big><b>Button Order</b></big>\t* requires JWM Version 2.4 or higher')
        label.set_tooltip_text('Older versions of JWM will ignore this option.')
        box = Gtk.Box(spacing=5)
        box.pack_start(label, False, False, 0)
        box.pack_end(self.b_defaults, False, False, 0)
        p_grid.attach(box, 7, 7, 12, 1)

        box = Gtk.Box(spacing=5)
        p_grid.attach(box, 7, 9, 12, 1)
        box.add(self.b1_combo)
        box.add(self.b2_combo)
        box.add(self.b3_combo)
        box.add(self.b4_combo)
        box.add(self.b5_combo)
        box = Gtk.Box(spacing=0)
        p_grid.attach(box, 7, 10, 12, 4)

        self.preview = Gtk.Image()
        self.preview.set_tooltip_text('Preview will update when all values are set.')
        box.pack_end(self.preview, True, False, 0)

        try:
            self.backgrounds = self.read_preferences()
        except (AttributeError, FileNotFoundError):
            self.backgrounds = ['', '']

        if self.desk_mode != 'jwm':
            self.clear_button.set_no_show_all(True)
            self.about_button.set_no_show_all(True)
            self.workspace_combo.set_no_show_all(True)
            self.workspace_label.set_no_show_all(True)
            self.about_button2.set_visible(True)
            self.header_label.set_markup('\n  <big><b>Preferences</b></big>'
                                         '\n  Workspaces &amp; window behavior\n')

    def b_default_on(self, button):
        status = not button.get_active()
        self.b1_combo.set_sensitive(status)
        self.b2_combo.set_sensitive(status)
        self.b3_combo.set_sensitive(status)
        self.b4_combo.set_sensitive(status)
        self.b5_combo.set_sensitive(status)

    def combo_setter(self, combo):
        combos = [self.b1_combo, self.b2_combo, self.b3_combo, self.b4_combo, self.b5_combo]
        active = combo.get_active()
        svg_values = []
        for c in combos:
            a = c.get_active()
            if a != -1:
                svg_values.append(get_button_letter(a))
            if c != combo:
                if a == active:
                    c.set_active(-1)

        if len(set(svg_values)) == 5:
            make_svg(svg_values)
            pb = GdkPixbuf.Pixbuf.new_from_file_at_scale('/tmp/jwmkit_button_preview.svg',
                                                         480, -1, preserve_aspect_ratio=True)
            self.preview.set_from_pixbuf(pb)

    def clear_background(self, button):
        i = self.workspace_combo.get_active()
        if i == 0:
            for i in range(len(self.backgrounds)):
                self.backgrounds[i] = ['', '']
        else:
            self.backgrounds[i-1] = ['', '']
        self.save_preferences()

    def read_preferences(self):

        def get_elm_text(value, default, num, check):
            elm = root.find(value)
            try:
                v = elm.text
                if not v:
                    v = default
                if num:
                    if not v.isdigit():
                        v = default
                if check != '':
                    if v not in check:
                        v = default
            except AttributeError:
                v = default
            return v

        def get_elm_attrib(value, default, num, check):
            try:
                v = elm.get(value)
                if not v:
                    v = default
                if num:
                    if not v.isdigit():
                        v = default
                if check != '':
                    if v not in check:
                        v = default
            except AttributeError:
                v = default
            return v

        def bg_type_check(type):
            if type in (None, ''):
                if tmp1[-4:].lower() in ('.jpg', '.png', '.gif', 'jpeg', '.xpm', '.svg'):
                    type = 'image'
                elif tmp1[1:].isdigit():
                    type = 'solid'
                elif tmp1.replace('#', '').replace(':', '').isdigit():
                    type = 'gradient'
            return type

        tree = ET.parse(self.jwmrc)
        root = tree.getroot()
        elm = root.find('Desktops')
        bk = elm.find('Background')
        desktops = elm.findall('Desktop')

        v = elm.get('width')
        if not v or not v.isdigit():
            v = '4'
        self.d_wide_spin.set_value(int(v))
        v1 = elm.get('height')
        if not v1 or not v1.isdigit():
            v1 = '1'
        self.d_high_spin.set_value(int(v1))
        total = int(v)*int(v1)
        for i in range(total):
            self.workspace_combo.append_text(str(i+1))

        self.delta_spin.set_value(int(get_elm_text('DoubleClickDelta', '2', True, '')))
        self.speed_spin.set_value(int(get_elm_text('DoubleClickSpeed', '400', True, '')))

        cv = ('click', 'clicktitle', 'sloppy', 'sloppytitle')
        v = get_elm_text('FocusModel', 'sloppy', False, cv)
        self.focus_combo.set_active(cv.index(v))

        v = get_elm_text('MoveMode', 'opaque', False, '')
        self.move_outline.set_active(True) if v == 'outline' else self.move_outline.set_active(False)
        v = get_elm_text('ResizeMode', 'opaque', False, '')
        self.resize_outline.set_active(True) if v == 'outline' else self.resize_outline.set_active(False)

        cv = ('none', 'screen', 'border')
        v = get_elm_text('SnapMode', 'border', False, cv)
        self.snap_combo.set_active(cv.index(v))

        elm = root.find('MoveMode')
        cv = ('A', 'C', 'S', '1', '2', '3', '4', '5')
        v = get_elm_attrib('mask', 'A', False, cv)
        self.move_keys.set_active(cv.index(v))

        cv = ('off', 'corner', 'window', 'screen')
        v = get_elm_attrib('coordinates', 'screen', False, cv)
        self.move_coord.set_active(cv.index(v))

        self.delay_spin.set_value(int(get_elm_attrib('delay', '1000', True, '')))

        elm = root.find('ResizeMode')
        v = get_elm_attrib('coordinates', 'screen', False, cv)
        self.resize_coord.set_active(cv.index(v))

        elm = root.find('SnapMode')
        self.distance_spin.set_value(int(get_elm_attrib('distance', '5', True, '')))

        elm = root.find('TitleButtonOrder')
        v = get_elm_text('TitleButtonOrder', 'wtimx', False, '')
        if v == 'wtimx':
            self.b_defaults.set_active(True)
        bv = ('w', 't', 'i', 'm', 'x')
        ok = True
        for va, combo in zip(list(v), [self.b1_combo, self.b2_combo, self.b3_combo, self.b4_combo, self.b5_combo]):
            try:
                combo.set_active(bv.index(va))
            except (ValueError, IndexError):
                ok = False
        if len(set(v)) == 5 and ok:
            make_svg(list(v))
            pb = GdkPixbuf.Pixbuf.new_from_file_at_scale('/tmp/jwmkit_button_preview.svg',
                                                         480, -1, preserve_aspect_ratio=True)
            self.preview.set_from_pixbuf(pb)

        backgrounds = []
        try:
            tmp1, tmp2 = bk.get('type'), bk.text
            if not tmp1:
                tmp1 = ''
            if not tmp2:
                tmp2 = ''
            tmp2 = bg_type_check(tmp2)
            backgrounds.append([tmp1, tmp2])
        except AttributeError:
            backgrounds.append(['', ''])
        if not backgrounds[0]:
            backgrounds[0] = ['', '']

        if len(desktops) > 1:
            for d in desktops:
                try:
                    tmp = d.find('Background')
                    tmp1 = tmp.text
                    tmp2 = tmp.get('type')
                    tmp2 = bg_type_check(tmp2)
                    tmp = [tmp2, tmp1]
                except AttributeError:
                    tmp = ['', '']
                backgrounds.append(tmp)
        while total+1 > len(backgrounds):
            backgrounds.append(['', ''])
        return backgrounds

    def page_switch(self, notebook, p_label, page):
        if self.desk_mode != 'jwm':
            return
        if page == 0:
            self.workspace_combo.set_visible(True)
            self.workspace_label.set_visible(True)
            self.clear_button.set_visible(True)
            self.about_button.set_visible(True)
            self.about_button2.set_visible(False)
            self.header_label.set_markup('\n  <big><b>Wallpaper</b></big>'
                                         '\n  &amp; background color\n')
        else:
            self.clear_button.set_visible(False)
            self.about_button.set_visible(False)
            self.about_button2.set_visible(True)
            self.workspace_combo.set_visible(False)
            self.workspace_label.set_visible(False)
            self.header_label.set_markup('\n  <big><b>Preferences</b></big>'
                                         '\n  Workspaces &amp; window behavior\n')

    def display_image_butt(self, imagey=0, imagex=0):
        for imag in self.Image_folder:
            self.image = Gtk.Image()
            try:
                pix = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.Image_dir + "/" + imag, 200, -1,
                                                          preserve_aspect_ratio=True)
                self.image.set_from_pixbuf(pix)
                img_button = Gtk.Button(image=self.image)
                img_button.connect("clicked", self.img_clicked, imag)
                self.image_box.attach(img_button, imagey, int(imagex / 3), 1, 1)
                self.image_box.show_all()
                imagey += 1
                imagex += 1
                if imagey == 3:
                    imagey = 0
            except gi.repository.GLib.Error:
                print(imag + ' is corrupt or unsupported file.')

    def on_color_set(self, button, data=None):
        color1 = self.color_button1.get_rgba()
        color2 = self.color_button2.get_rgba()

        def convert_color(colors):
            red = int(colors.red * 255)
            green = int(colors.green * 255)
            blue = int(colors.blue * 255)
            return "%02x%02x%02x" % (red, green, blue)

        self.color1 = convert_color(color1)
        self.color2 = convert_color(color2)

    def img_clicked(self, widget, imag):
        if self.display_mode not in ("gradient", "solid"):
            self.selected_img = imag
            self.pixs = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.Image_dir + "/" + self.selected_img, 110, 85,
                                                                preserve_aspect_ratio=True)
            self.status_image.set_from_pixbuf(self.pixs)

    def apply_clicked(self, widget):

        def set_background(select_type, selectbg):
            if self.desk_mode == 'rox':
                cmd = 'roxfiler --RPC << EOF\n<?xml version="1.0"?>\n<env:Envelope xmlns:env="http://www.w3.org/' \
                      '2001/12/soap-envelope">\n <env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">\n  ' \
                      '<SetBackdrop>\n   <Filename>{}</Filename>\n   <Style>{}</Style>\n  ' \
                      '</SetBackdrop>\n </env:Body>\n</env:Envelope>\nEOF\n'.format(selectbg, select_type)
                os.system(cmd)
            elif self.desk_mode == 'spacefm':
                print('Spacefm does not support setting the wallpaper-mode, or colors from the commandline')
                print("Use Spacefm's built in Desktop preferences to set the mode")
                os.system('spacefm --set-wallpaper "{}"'.format(selectbg))
            elif self.desk_mode == 'zzzfm':
                print('zzzfm does not support setting the wallpaper-mode, or colors from the commandline')
                print("Use zzzfm's built in Desktop preferences to set the mode")
                os.system('zzzfm --set-wallpaper "{}"'.format(selectbg))
            elif self.desk_mode == 'pcmanfm':
                print('Pcmanfm does not support setting the background color from the command line')
                print("Use pcmanfm's built in Desktop Preferences to set a background color")
                cmd = 'pcmanfm --wallpaper-mode={}'.format(select_type.replace('scale', 'fit'))
                os.system(cmd)
                cmd = 'pcmanfm --set-wallpaper="{}"'.format(selectbg)
                os.system(cmd)
            elif self.desk_mode == 'set_bg':
                with open('/root/.config/wallpaper/backgroundmode', "w") as f:
                    f.write(select_type.replace('image', 'stretch'))
                with open('/root/.config/wallpaper/bg_img', "w") as f:
                    f.write(selectbg)
                cmd = 'set_bg "{}"'.format(selectbg)
                os.system(cmd)
            elif self.desk_mode == 'jwm':
                desktop = self.workspace_combo.get_active()
                tree = ET.parse(self.jwmrc)
                root = tree.getroot()
                dk = root.find('Desktops')
                width = dk.get('width')
                height = dk.get('height')
                if not width:
                    width = 2
                if not height:
                    height = 1
                if desktop == 1:
                    bk = dk.find('Background')
                    self.backgrounds[0] = [select_type.replace('stretch', 'image'), selectbg]
                    try:
                        bk.set('type', select_type.replace('stretch', 'image'))
                        bk.text = selectbg
                    except AttributeError:
                        bk = ET.SubElement(dk, "Background")
                        bk.set('type', select_type.replace('stretch', 'image'))
                        bk.text = selectbg
                elif desktop == 0:
                    for i, b in enumerate(self.backgrounds):
                        self.backgrounds[i] = ['', '']
                    self.backgrounds[0] = [select_type.replace('stretch', 'image'), selectbg]
                    dk.clear()
                    dk.set('width', width)
                    dk.set('height', height)
                    bk = ET.SubElement(dk, "Background")
                    bk.set('type', select_type.replace('stretch', 'image'))
                    bk.text = selectbg
                else:
                    dk.clear()
                    dk.set('width', width)
                    dk.set('height', height)
                    self.backgrounds[desktop-1] = [select_type.replace('stretch', 'image'), selectbg]
                    if self.backgrounds[0][1] != '':
                        bk = ET.SubElement(dk, "Background")
                        bk.set('type', self.backgrounds[0][0].replace('stretch', 'image'))
                        bk.text = self.backgrounds[0][1]
                    for b in self.backgrounds[1:]:
                        d = ET.SubElement(dk, "Desktop")
                        if b[1] != '':
                            bk = ET.SubElement(d, "Background")
                            bk.set('type', b[0])
                            bk.text = b[1]
                xml = b''.join([s.strip() for s in ET.tostring(root).splitlines() if s.strip()])
                xml = minidom.parseString(xml).toprettyxml(newl='\n', indent='   ')
                xml = ET.ElementTree(ET.fromstring(xml))
                xml.write(self.jwmrc, encoding="utf-8", xml_declaration=True)
                os.system('jwm -restart')

        page = self.notebook.get_current_page()
        if page == 0:
            mode = self.display_mode.replace('tiled', 'tile')
            if self.display_mode not in ("gradient", "solid"):
                set_background(mode, self.Image_dir + "/" + self.selected_img)
            elif self.display_mode == "solid":
                set_background(mode, '#' + self.color1)
            else:
                set_background(mode, '#' + self.color1 + ":#" + self.color2)
        if page == 1:
            self.save_preferences()

    def save_preferences(self):
        coordinates = ('off', 'corner', 'window', 'screen')
        root = ET.Element('JWM')
        # Desktops
        width, height = str(int(self.d_wide_spin.get_value())), str(int(self.d_high_spin.get_value()))
        element = ET.SubElement(root, 'Desktops', {'width': width, 'height': height})
        if self.backgrounds[0][1] != '':
            sub = ET.SubElement(element, 'Background', {'type': self.backgrounds[0][0]})
            sub.text = self.backgrounds[0][1]
        test = False
        for b in self.backgrounds[1:]:
            if b[1] != '':
                test = True
                break
        if test:
            for b in self.backgrounds[1:]:
                d = ET.SubElement(element, "Desktop")
                if b[1] != '':
                    bk = ET.SubElement(d, "Background")
                    bk.set('type', b[0])
                    bk.text = b[1]
        # Double click
        v = str(int(self.delta_spin.get_value()))
        if v != '2':
            element = ET.SubElement(root, 'DoubleClickDelta')
            element.text = v

        v = str(int(self.speed_spin.get_value()))
        if v != '400':
            element = ET.SubElement(root, 'DoubleClickSpeed')
            element.text = v
        # FocusModel
        v = self.focus_combo.get_active()
        if v != 2:
            values = ('click', 'clicktitle', 'sloppy', 'sloppytitle')
            element = ET.SubElement(root, 'FocusModel')
            element.text = values[v]
        # MoveMode
        v = self.move_outline.get_active()
        v1 = self.move_coord.get_active()
        v2 = str(int(self.delay_spin.get_value()))
        v3 = self.move_keys.get_active()
        if (v, v1, v2, v3) != (False,  3, '1000', 0):
            element = ET.SubElement(root, 'MoveMode')
            if v:
                element.text = 'outline'
            else:
                element.text = 'opaque'
            v = coordinates[v1]
            if v != 'screen':
                element.set('coordinates', v)
            if v2 != '1000':
                element.set('delay', v2)
            if v3 != 0:
                values = ('A', 'C', 'S', '1', '2', '3', '4', '5')
                element.set('mask', values[v3])
        # ResizeMode
        v = self.resize_outline.get_active()
        v1 = self.resize_coord.get_active()
        if (v, v1) != (False, 3):
            element = ET.SubElement(root, 'ResizeMode')
            if v:
                element.text = 'outline'
            else:
                element.text = 'opaque'
            v = coordinates[v1]
            if v != 'screen':
                element.set('coordinates', v)
        # SnapMode
        v = self.snap_combo.get_active()
        v1 = str(int(self.distance_spin.get_value()))
        if (v, v1) != (2, '5'):
            values = ('none', 'screen', 'border')
            element = ET.SubElement(root, 'SnapMode')
            element.text = values[v]
            if v1 != '5':
                element.set('distance', v1)
        # button order
        if not self.b_defaults.get_active():
            v1 = get_button_letter(self.b1_combo.get_active())
            v2 = get_button_letter(self.b2_combo.get_active())
            v3 = get_button_letter(self.b3_combo.get_active())
            v4 = get_button_letter(self.b4_combo.get_active())
            v5 = get_button_letter(self.b5_combo.get_active())
            v = '{}{}{}{}{}'.format(v1, v2, v3, v4, v5)
            if len(v) == 5 and v != 'wtimx':
                element = ET.SubElement(root, 'TitleButtonOrder')
                element.text = v

        xml = b'\n'.join([s.strip() for s in ET.tostring(root).splitlines() if s.strip()])
        xml = minidom.parseString(xml).toprettyxml(newl='\n', indent='   ')
        xml = ET.ElementTree(ET.fromstring(xml))
        xml.write(self.jwmrc, encoding="utf-8", xml_declaration=True)
        os.system('jwm -restart')

    def on_button_toggled(self, button, name):
        self.display_mode = name
        if name == "solid":
            self.color_button1.set_sensitive(True)
            self.color_button2.set_sensitive(False)
            self.status_image.set_from_pixbuf()
        elif name == "gradient":
            self.color_button1.set_sensitive(True)
            self.color_button2.set_sensitive(True)
            self.status_image.set_from_pixbuf()
        else:
            self.color_button1.set_sensitive(False)
            self.color_button2.set_sensitive(False)
            self.status_image.set_from_pixbuf(self.pixs)

    def pick_folder(self, widget):
        dialog = Gtk.FileChooserDialog(title="Folder Selection", parent=self, action=Gtk.FileChooserAction.SELECT_FOLDER)
        dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)
        dialog.set_current_folder(self.home)
        dialog.set_show_hidden(False)
        dialog.set_default_size(650, 400)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.image_box.remove_column(0)
            self.image_box.remove_column(0)
            self.image_box.remove_column(0)
            self.Image_dir = dialog.get_filename()
            self.Folder_list = os.listdir(self.Image_dir)
            self.make_imagelist(self.Folder_list)
            self.status_image.set_from_pixbuf()
            self.display_image_butt()
            last_dir = self.home + '/.config/jwmkit/LastWallDir'
            with open(last_dir, "w") as f:
                f.write(self.Image_dir)
        dialog.destroy()

    def make_imagelist(self, image_dir):
        self.Image_folder = []
        for image in image_dir:
            image_types = ('jpg', 'png', 'gif', 'jpeg', 'xpm', 'svg')
            for im_type in image_types:
                if image.lower().endswith(im_type):
                    self.Image_folder.append(image)

    def get_last_dir(self):
        last_dir = '{}/.config/jwmkit/LastWallDir'.format(self.home)
        if os.path.isfile(last_dir):
            with open(last_dir) as f:
                f = f.read()
            last_dir = re.findall('.*', f)[0]
            if not os.path.isdir(last_dir):
                last_dir = self.home
        else:
            last_dir = self.home
        return last_dir

    def get_path(self):
        # search JWM Kit setting file for path to groups xml then
        # make a list of the groups found in the JWM groups xml
        settings = self.home + '/.config/jwmkit/settings'
        path_ok = False
        if os.path.isfile(settings):
            with open(settings) as f:
                f = f.read()
            f = '\n{}'.format(f)
            try:
                path = re.findall('\npreferences.*=(.+)', f)[0]
                if path.startswith('$HOME'):
                    path = self.home + path[5:]
                path_ok = True
            except IndexError:
                path_ok = False
        if not path_ok:
            return 'warning_settings'
        return path


window = MainWindow()
window.connect("delete-event", Gtk.main_quit)
window.set_position(Gtk.WindowPosition.CENTER)
window.set_resizable(False)
window.show_all()
Gtk.main()
