#!/usr/bin/env python

#ToDo add terminal open command if bool = true

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject, GLib, Gio, GdkPixbuf
from xdg.DesktopEntry import DesktopEntry
from xdg.BaseDirectory import xdg_config_home
from xdg.BaseDirectory import xdg_data_home
import xdg.IconTheme
import os
import re
import subprocess

icon_size = 32
term_app = 'desktop-defaults-run -t '
apps = Gio.app_info_get_all()

class mainWindow(Gtk.Window):
    
    def refresh_filter(self,widget):
        self.filter.refilter()
        search_query = self.searchentry.get_text()
        if search_query != "":
            self.treeview.set_cursor(0)
            self.filtermessage.show()
        else:
            self.filtermessage.hide()

    def visible_cb(self, model, iter, data=None):
        search_query = self.searchentry.get_text().lower()
        active_category = self.searchcombo.get_active()
        search_in_all_columns = active_category == 0

        if search_query == "":
            return True

        if search_in_all_columns:
            for col in range(1,self.treeview.get_n_columns()):
                value = model.get_value(iter, col).lower()
                #if value.startswith(search_query):
                #    return True
                if search_query in value:
                    return True

            return False

        value = model.get_value(iter, active_category).lower()
        return True if search_query in value else False
    
    def run_button(self, test):
        self.run(self,"","")
            
    def run(self, test, fill, fill2):
        tree_selection = self.treeview.get_selection()
        (model, pathlist) = tree_selection.get_selected_rows()
        for i, path in enumerate(pathlist) :
            tree_iter = model.get_iter(path)
            appname = model.get_value(tree_iter,1)
            appexec = model.get_value(tree_iter,3)
            appexec = re.sub(r'%.*', '', appexec)
            appterm = model.get_value(tree_iter,4)
            
            if appterm:
                os.system(term_app+" "+appexec+" > /dev/null 2>&1 &")
            else:
                os.system(appexec+" > /dev/null 2>&1 &")
    
    def add_item(self, store, filename, iftype):
        appexec = DesktopEntry(filename).getExec()
        appname = iftype+DesktopEntry(filename).getName()
        appicon = DesktopEntry(filename).getIcon()
        appdesc = DesktopEntry(filename).getComment()
        appterm = DesktopEntry(filename).getTerminal()
        missing_icon = "gtk-missing-image"
        
        if appicon == "":
            appicon = missing_icon
        
        if os.path.isfile(appicon):
            icon = appicon
        else:
            icon_theme = Gtk.IconTheme.get_default()
            icon_check = icon_theme.lookup_icon(appicon, icon_size, 0)
            if icon_check:
                icon_info = icon_theme.lookup_icon(appicon, icon_size, 0)
                icon = icon_info.get_filename()
            else:
                if os.path.exists("/usr/share/pixmaps/%s" % appicon):
                    icon = "/usr/share/pixmaps/"+appicon
                else:
                    #p =  subprocess.Popen(["locate "+appicon],stdout=subprocess.PIPE, shell=True)
                    #(output, err) = p.communicate()
                    #last_attempt = output.partition('\n')[0]
                    #if os.path.isfile(last_attempt):
                    #    icon = last_attempt
                    #else:
                        icon = missing_icon
        
        icon = re.sub(r' ','\ ', icon)
        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(icon)
        except:
            icon_info = icon_theme.lookup_icon(missing_icon, icon_size, 0)
            icon = icon_info.get_filename()
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(icon)
            
        pixbuf = GdkPixbuf.Pixbuf.scale_simple(pixbuf, icon_size, icon_size,0)
        store.append([pixbuf, appname, appdesc, appexec, appterm])
        store.set_sort_column_id(1,0)
    
    def make_list(self):
        count = 0
        store = Gtk.ListStore(GdkPixbuf.Pixbuf,str,str,str,bool)
        
        #Disabled for now:
        #Can test / preview by uncommenting the below lines / for statements
              
        #for item in os.walk(xdg_config_home+"/autostart/"):
        #    if item[2]:
        #        filename = item[0]+"/"+"".join(item[2])
        #        self.add_item(store, filename, 'Autostart: ')
        
        #for item in os.walk(xdg_data_home+"/applications/"):
        #    if item[2]:
        #        filename = item[0]+"/"+"".join(item[2])
        #        self.add_item(store, filename, 'Personal: ')
        
        
        for name in apps:
            filename = name.get_filename()
            self.add_item(store, filename, '')

        
        self.filter = store.filter_new()
        self.filter.set_visible_func(self.visible_cb)
        self.searchentry.connect("changed", self.refresh_filter)
        self.searchentry.connect("activate", self.run_button)
        self.searchcombo.connect("changed", self.refresh_filter)
        
        self.treeview = Gtk.TreeView.new_with_model(self.filter)
        self.treeview.connect("row-activated", self.run)
        self.treeview.set_enable_search(False)
        renderer = Gtk.CellRendererPixbuf()
        column = Gtk.TreeViewColumn("", renderer, pixbuf=0)
        column.set_resizable(True)
        self.treeview.append_column(column)
        for i, column_title in enumerate(["Name", "Description", "Exec"]):
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn(column_title, renderer, text=i+1)
            column.set_resizable(True)
            column.set_fixed_width(250)
            self.treeview.append_column(column)

        self.sw.add(self.treeview)
        self.treeview.show()


    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_size_request(640,480)
        self.set_border_width(10)
        self.set_title(" App Select ")
        self.show()
    
        vbox = Gtk.VBox()
        self.add(vbox)
        vbox.show()
                
        hbox = Gtk.HBox()
        vbox.pack_start(hbox, 0,0,0)
        hbox.show()
        
        label = Gtk.Label("Search / Filter: ")
        hbox.pack_start(label,0,0,0)
        label.show()
        
        # Search EntryEntry
        self.searchentry = Gtk.Entry()
        self.searchentry.set_placeholder_text("Type to filter...")
        hbox.pack_start(self.searchentry, True, True, 0)
        self.searchentry.grab_focus()
        self.searchentry.show()

        # Search Combo
        categories = ["All", "Name", "Description", "Exec"]
        self.searchcombo = Gtk.ComboBoxText()
        self.searchcombo.set_entry_text_column(0)
        hbox.pack_start(self.searchcombo, False, False, 0)
        for category in categories:
            self.searchcombo.append_text(category)
        self.searchcombo.set_active(0)
        self.searchcombo.show()
        
        self.filtermessage = Gtk.Label("\nDisplaying filtered results\n")
        vbox.pack_start(self.filtermessage,0,0,0)
        self.filtermessage.hide()
        
        self. sw= Gtk.ScrolledWindow()
        vbox.pack_start(self.sw,1,1,1)
        self.sw.show()
        
        self.make_list()
        
        buttonbox = Gtk.HButtonBox()
        vbox.pack_start(buttonbox,0,0,1)
        buttonbox.show()
        
        run = Gtk.Button(stock=Gtk.STOCK_EXECUTE)
        run.connect("clicked", self.run_button)
        buttonbox.pack_start(run,0,0,0)
        run.set_can_default(True)
        run.grab_default()
        run.show()
        
        close = Gtk.Button(stock=Gtk.STOCK_CLOSE)
        close.connect("clicked", lambda w: Gtk.main_quit())
        buttonbox.add(close)
        close.show()
        
    
        

win = mainWindow()
win.connect("delete-event", Gtk.main_quit)
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL) # without this, Ctrl+C from parent term is ineffectual
Gtk.main()
