#!/usr/bin/env python

import sys
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import re

class DisplayLines:
    #column_names = ['Contents']
#    column_names = ['Line', 'Contents']

 
    def __init__(self, dname):
        self.Filter=[]
        self.listmodel = self.listToListModel(self.makeBaseList(dname))
        self.modelfilter = self.listmodel.filter_new()
        self.modelfilter.set_visible_func(self.visibleLine,self.Filter)
        # create the TreeView
        self.treeview = gtk.TreeView(self.modelfilter)
        self.treeview.append_column(gtk.TreeViewColumn("Line",    gtk.CellRendererText(), markup=0))
        self.treeview.append_column(gtk.TreeViewColumn("Content", gtk.CellRendererText(), markup=1))

        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.add(self.treeview)
        return


    def getRef(self):
        return self.scrolledwindow

    def listToListModel(self,list):
        listmodel = gtk.ListStore(int,str,str,bool)        
        for (line,number) in list:
            listmodel.append([number,line, line, True])
        return listmodel

    def addFilter(self,name,functor):
        self.Filter+=[(name,functor)]
        if name not in ["delLine","showOnly", "lineModif"]:
            print "Error "+name+ " not yet implemented"
        self.listmodel.foreach(self.filterApplyRow,None)
        self.modelfilter.refilter()

    def setFilter(self,filterList):
        print "FilterList", filterList
        self.Filter=filterList
        self.listmodel.foreach(self.filterApplyRow,None)
        self.modelfilter.refilter()

     
    def visibleLine(self, model, iter, functorList):
        return model.get_value(iter,3)
     

    #def setVisible(self, model, path, iter, user_data):
    #    model.set(iter,3,True)

    def filterApplyRow(self, model, path, iter, user_data):
        #nb=model.get_value(iter,0)
        #line=model.get_value(iter,1)
        lineOrg=model.get_value(iter,2)
        visible=True
        line=lineOrg

        for (name,functor) in self.Filter:   
            if name=="delLine" and functor(line):
                visible=False 
                #print functor, line
                #print "Merde"
            if name=="showOnly" and (not functor(line)):
                visible=False
            if name=="lineModif":
                line=functor(line)
        model.set(iter,1,line)
        model.set(iter,3,visible)
        #print visible


    def hardFilterApplyRow(self, model, path, iter, user_data):
        visible=model.get_value(iter,3)
        if not visible:
            model.remove(iter)


    def hardFilter(self,filter):
        print len(self.listmodel)
        self.listmodel.foreach(self.hardFilterApplyRow,None)
        print len(self.listmodel)
        

    def makeBaseList(self, dname):        
        file=open(dname)
        lineNumber=1
        list=[]
        for f in file.readlines():
            list+=[(f[0:-1].replace("\x00"," "),lineNumber)]
            lineNumber+=1
        return list

    
    

        
class Reg:
    def __init__(self,regExpString):
        self.regexp=re.compile(regExpString)
        self.regExpString=regExpString

    def colorMatch(self,color,type="foreground"):
        def insertColor(matchobj):
            return  "<span "+type+"=\'"+color+"\'>" + matchobj.group(0) + "</span>"
      
        return  lambda line: re.sub(self.regExpString, insertColor, line)


    def colorLineMatch(self,color,type="foreground"):
       def func(line):
           if self.regexp.search(line)==None:
               return line
           else:
               return "<span "+type+"=\'"+color+"\'>" + line + "</span>"
       return func

    def deleteMatch(self):
        def delete(matchobj):
            return  ""
        return  lambda line: re.sub(self.regExpString, delete, line)



class FilterEdit:
    
    def __init__(self, applyFunction, hardFilter):
  
        self.externFunction=applyFunction
        self.externHard=hardFilter
        
        self.listFilter=gtk.ListStore(str)
        for item in  ["delLine","showOnly","deleteMatch", "DELETE FILTER"]:
            self.listFilter.append([item])
    
        self.listColor=gtk.ListStore(str)
        for item in  ["colorMatch","colorMatchLine", "DELETE FILTER"]:
            self.listColor.append([item])
            
        self.listOfColor=gtk.ListStore(str)
        for item in  ["red","blue", "purple", "green", "yellow"]:
            self.listOfColor.append([item])


        self.listmodel = gtk.ListStore(str, gobject.TYPE_OBJECT,str )
        self.addFunction()
        
        self.listmodelcolor = gtk.ListStore(str, gobject.TYPE_OBJECT,str, str, gobject.TYPE_OBJECT )
        self.addFunctionColor()


        self.treeview = gtk.TreeView(self.listmodel)
        self.treeviewColor = gtk.TreeView(self.listmodelcolor)



        self.comboBox= self.createMenu()
        column0=gtk.TreeViewColumn("Filter",self.comboBox)
        column0.set_attributes(self.comboBox,text=0)
        self.treeview.append_column(column0)
        self.cellRender= self.createMenuRegExp(self.listmodel)
        column1=gtk.TreeViewColumn("Regular Expression",self.cellRender,text=2)
        self.treeview.append_column(column1)

        
        self.comboBoxColor= self.createMenuColor()
        column0=gtk.TreeViewColumn("Filter",self.comboBoxColor)
        column0.set_attributes(self.comboBoxColor,text=0)
        self.treeviewColor.append_column(column0)
        self.cellRenderColor= self.createMenuRegExp(self.listmodelcolor)
        column1=gtk.TreeViewColumn("Regular Expression",self.cellRenderColor,text=2)
        self.treeviewColor.append_column(column1)

        self.cellRenderListColor= self.createComboColor()
        column2=gtk.TreeViewColumn("Color",self.cellRenderListColor,text=3)
        self.treeviewColor.append_column(column2)


        #self.treeview.append_column(gtk.TreeViewColumn("Param 1", gtk.CellRendererText()))
        #self.treeview.append_column(gtk.TreeViewColumn("Param 2", gtk.CellRendererText()))

        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
        self.scrolledwindow.add(self.treeview)

        self.scrolledwindowColor = gtk.ScrolledWindow()
        self.scrolledwindowColor.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
        self.scrolledwindowColor.add(self.treeviewColor)



        self.vbox = gtk.VBox()
        self.hbox = gtk.HButtonBox()
        self.vbox.pack_start(self.scrolledwindow, True)
        self.vbox.pack_start(self.scrolledwindowColor, True)
        self.vbox.pack_start(self.hbox, False)
        #self.bUp    = gtk.Button('Up')
        #self.bDown  = gtk.Button('Down')
        #self.bAdd   = gtk.Button('Add')
        #self.bDel   = gtk.Button('Delete')
        self.bApply = gtk.Button('Apply')
        self.bApplyH = gtk.Button('Hard Filter')
        #self.hbox.pack_start(self.bUp)
        #self.hbox.pack_start(self.bDown)
        #self.hbox.pack_start(self.bAdd)
        #self.hbox.pack_start(self.bDel)
        self.hbox.pack_start(self.bApply)
        self.hbox.pack_start(self.bApplyH)
        #self.hbox.pack_start(self.createMenu())        

        #self.bAdd.connect('clicked', self.addFunction)
        #self.bDel.connect('clicked', self.delFunction)
        self.bApply.connect('clicked', self.applyFunction)
        self.bApplyH.connect('clicked', self.externHard)

        return

    
    def addFunction(self,button=None):
        self.listmodel.append(["Choose Filter",self.listFilter, "" ])


    def addFunctionColor(self,button=None):
        self.listmodelcolor.append(["Choose Filter",self.listColor, "", "",self.listOfColor ])



    def delFunction(self,button):
        selection = self.treeview.get_selection()
        model, iter = selection.get_selected()
        if iter:
            model.remove(iter)
        return

    
    def delFunctionColor(self,button):
        selection = self.treeviewcolor.get_selection()
        model, iter = selection.get_selected()
        if iter:
            model.remove(iter)
        return


    def applyFunction(self,button):
        filter=[]
        for row in self.listmodel:            
            name = row[0]
            text=  row[2]

            print name, text
            if name == "delLine":
                filter+=[("delLine",lambda line : (text in line))]
            elif name=="showOnly":
                filter+=[("showOnly",lambda line : (text in line))]
            elif name == "deleteMatch":
                filter+=[("lineModif",Reg(text).deleteMatch())]
            elif name != "Choose Filter":
                print "No Yet Implemented"

        for row in self.listmodelcolor:            
            name = row[0]
            text = row[2]
            color= row[3]
            if color!="":
                if name == "colorMatch":
                    filter+=[("lineModif",Reg(text).colorMatch(color))]
                if name == "colorMatchLine":
                    filter+=[("lineModif",Reg(text).colorLineMatch(color))]
        print filter
        self.externFunction(filter)




    def getRef(self):
        return self.vbox

    
    def createMenu(self):
        def EditingCellEnd(cell, row, newText):
            if newText=="DELETE FILTER":
                if int(row)!=(len(self.listmodel)-1) :
                    self.delFunction(row)                 
                else:
                    self.listmodel[row][0]="Choose Filter"
            
            elif int(row) !=(len(self.listmodel)-1) :
                self.listmodel[row][0]=newText

            else:
                self.listmodel[row][0]=newText
                self.addFunction()
            
            
        cellcombo = gtk.CellRendererCombo()
        cellcombo.set_property("text-column", 0)
        cellcombo.set_property("editable", True)
        cellcombo.set_property("has-entry", True)
        cellcombo.set_property("model", self.listFilter)        
        cellcombo.connect("edited", EditingCellEnd)

        return cellcombo


    
    
    def createMenuColor(self):
        def EditingCellEnd(cell, row, newText):
            if newText=="DELETE FILTER":
                if int(row)!=(len(self.listmodelcolor)-1) :
                    self.delFunctionColor(row)                 
                else:
                    self.listmodelcolor[row][0]="Choose Filter"
            
            elif int(row) !=(len(self.listmodelcolor)-1) :
                self.listmodelcolor[row][0]=newText

            else:
                self.listmodelcolor[row][0]=newText
                self.addFunctionColor()
            
            
        cellcombo = gtk.CellRendererCombo()
        cellcombo.set_property("text-column", 0)
        cellcombo.set_property("editable", True)
        cellcombo.set_property("has-entry", True)
        cellcombo.set_property("model", self.listColor)        
        cellcombo.connect("edited", EditingCellEnd)

        return cellcombo



    
    def createComboColor(self):
        def EditingCellEnd(cell, row, newText):
            self.listmodelcolor[row][3]=newText  
            
        cellcombo = gtk.CellRendererCombo()
        cellcombo.set_property("text-column", 0)
        cellcombo.set_property("editable", True)
        cellcombo.set_property("has-entry", True)
        cellcombo.set_property("model", self.listOfColor)        
        cellcombo.connect("edited", EditingCellEnd)

        return cellcombo



    def createMenuRegExp(self,model):
        def EditingCellEnd(cell, row, newText):
           
            model[row][2]=newText


        cellText = gtk.CellRendererText()
#        cellText.set_property("text-column", 0)
        cellText.set_property("editable", True)
 #       cellText.set_property("has-entry", True)
        #cellText.set_property("model", self.listFilter)        
        cellText.connect("edited", EditingCellEnd)

        return cellText






class App:

    def __init__(self):
        # Create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(400, 300) 
        self.window.connect("delete_event", self.delete_event)

        if len(sys.argv)!=2:
            self.fileName="DDErr.0"
        else:
            self.fileName=sys.argv[1]
        self.dpLine=DisplayLines(self.fileName)

        self.window.set_title("FilterTxt : "+self.fileName )
        self.window.add(self.dpLine.getRef())
        self.window.show_all()
        

        self.fe = FilterEdit(self.dpLine.setFilter,self.dpLine.hardFilter)
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)        
        win.connect("delete_event", self.delete_event)
        win.add(self.fe.getRef())
        win.show_all()
        win.set_size_request(400, 300) 
        


    def run(self):
        #self.dpLine.addFilter("delLine",lambda line : ("***"in line))
        #self.dpLine.addFilter("delLine",lambda line : ("include/Legolas"in line))
        #self.dpLine.addFilter("delLine",lambda line : ("Numerics/Legolas"in line))
        #self.dpLine.addFilter("replace", None)
        #self.dpLine.addFilter("lineModif",Reg("DEBUG").colorLine("red"))
        #self.dpLine.addFilter("lineModif",Reg("[^>:]* Ctor").colorLineMatch("blue"))        
        #self.dpLine.addFilter("lineModif",Reg("[^>:]* Dtor").colorLineMatch("red"))

        gtk.main()


    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False




    

if __name__ == "__main__":

    app=App()
    app.run()

