#$Id$
# -*- coding: cp1251 -*-
# (c) svilen.dobrev 2009
# prototype for item/wine -choosing kiosk system
# needs pygtk, pygtkmoz(pygtkmoz-0.1.tar.gz), gtkmoz (as mozilla or xulrununer)

import datetime
import random

import gtk
import pango

#from kiwi.ui.objectlist import ( SequentialColumn, ColoredColumn, )
from kiwi.ui.objectlist import Column as kiwiColumn, ObjectList as kiwiObjectList
from kiwi.ui.widgets.label import ProxyLabel as Label
#from kiwi.ui.widgets.button import ProxyButton
from kiwi.datatypes import currency
currency._format = currency.format
currency.format = lambda me, *a,**k: TXT( me._format(*a,**k))

font_name = "sans 16"
font = pango.FontDescription( font_name)
winsize = 1024,768

MODEL_ENCODING = 'utf-8'
PREFERRED_ENCODING = 'cp1251'
def TXT( txt):  #to unicode.
    if isinstance(txt, unicode): return txt
    #txt = str(txt)
    try: return unicode( txt, MODEL_ENCODING)
    except UnicodeDecodeError:
        return unicode( txt, PREFERRED_ENCODING)


class DictAttr( dict):
    def __init__( me, *a, **k):
        dict.__init__( me, *a, **k)
        me.__dict__ = me

def Button( data, **kargs):
    padding = kargs.pop( 'padding', None)
    b = gtk.Button( data, **kargs)
    l = b.get_children()[0]
    if font: l.modify_font( font)
    if padding: l.set_padding( *padding)
    #b=ProxyButton()
    #b.update(data)
    return b

#imgtype = gtk.gdk.Pixbuf

class Column( kiwiColumn):
    def __init__( me, *args,**kargs):
        me.xpad = kargs.pop( 'xpad', 10)
        me.ypad = kargs.pop( 'ypad', 5)
        autofont = kargs.pop( 'autofont', True)
        if font_name and autofont: kargs.setdefault( 'font_desc', font_name)
        #kargs[ 'format_func'] = TXT
        return kiwiColumn.__init__( me, *args,**kargs)
    def on_attach_renderer( me, renderer):
        if me.xpad: renderer.set_property( 'xpad', me.xpad)
        if me.ypad: renderer.set_property( 'ypad', me.ypad)
        #self._color_normal = renderer.get_property('foreground-gdk')

class ColumnSelf( Column):
    def __init__( me, *args,**kargs):
        me.show_as = kargs.pop( 'show_as')
        me.sort_as = kargs.pop( 'sort_as') or me.show_as
        Column.__init__( me, *args,**kargs)
        me._compare = me.compare
        del me.compare
    def compare( me, x,y):
        return me._compare( getattr( x, me.sort_as), getattr( y, me.sort_as) )
    def as_string( me, x):
        return getattr( x, me.show_as)

def ObjectList( columns, data =(),
        connects ={},
        onchoice =None,
        mode =gtk.SELECTION_SINGLE,
        vscrollbars_always =False,
        **kargs):
    o = kiwiObjectList( columns, mode=mode, **kargs)
    o.extend( data)
    o.set_policy( gtk.POLICY_AUTOMATIC, vscrollbars_always and gtk.POLICY_ALWAYS or gtk.POLICY_AUTOMATIC)
    for k,v in connects.iteritems():
        o.connect( k,v)
    if onchoice:
        for k in [
                'row-activated',    #dblclick/enter
                #'selection-changed',#singleclick
                ]:
            o.connect( k, onchoice, o)
    return o


######################

class choiceq:
    def __init__( me, all):
        me.all = all.split()
    def cmp( me, x, value):
        assert value in me.all
        return x == value

import operator
class choiceN( choiceq):
    ops = dict( (k, getattr( operator,v))
            for k,v in {
            '>' :'gt',
            '<' :'lt',
            '>=':'ge',
            '<=':'le',
            '=' :'eq',
            '==':'eq',
            '!=':'ne',
            }.items()
        )
    type = int
    def __init__( me, all):
        choiceq.__init__( me,all)
        me.split = {}
        for value in me.all:
            op = value.rstrip( '0123456789')
            assert op in me.ops
            val = value[len(op):]
            assert val
            me.split[ value] = me.ops[op], me.type(val)
        #print 11111111, me.split

    def cmp( me, x, value):
        #assert value in me.all
        op,val = me.split[ value]
        return op( x, val)


choiceN.type = currency
choices = DictAttr(
        #XXX '? are these static or dynamic depending on available stock'
        variant = choiceq( 'tall slim fat thin eerie' ),
        color   = choiceq( 'red white pink' ),
        country = choiceq( 'here there anywhere' ),
        price   = choiceN( '<=10 <=20 <=50 >50',  ),  #use lt/le/gt/ge matching
    )

icons  = [ gtk.STOCK_OK,
           gtk.STOCK_CANCEL,
           gtk.STOCK_HELP,
           gtk.STOCK_DELETE,
           gtk.STOCK_HOME,
        ]

#from decimal import Decimal
class Item:
    """The parameters need to be of the same name of the column headers"""
    def __init__(self, name, year, city, hilite =False):
        self._name  = TXT( name)
        self.year   = year
        self.country = TXT( city)
        self.age = datetime.datetime.today().year - year
        self.price  = random.randint(5,150)
        self.color  = choices.color.all[ random.randint(0, len(choices.color.all)-1) ]
        self.variant= choices.variant.all[ random.randint(0, len(choices.variant.all)-1) ]
        self.recomend = hilite
        #self.image = ... #data_type= gtk.gdk.Pixbuf
        self.icon = icons[ random.randint(0, len(icons)-1) ]
        self.reviews = [ 20*x for x in name ]
        self.location= 'rack %s, level %s' % (random.randint( 0,9), random.randint( 0,17))

    def __repr__(self):
        return '<Item %s>' % self._name

    #these for ColumnSelf to allow showing markuped-name but sorting by plain _name
    @property
    def self( me): return me
    @property
    def name( me):
        r = me._name
        return me.recomend and '<b>%s</b>' % r or r

Item.columns = [
    #SequentialColumn(),
    Column( 'icon',     use_stock=True,
                            justify=gtk.JUSTIFY_CENTER,
                            autofont=False,
                            #icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR
                            ),
    ColumnSelf( 'self',  title= 'Name',
        data_type=str, expand=1*True, use_markup=True,
        show_as  = 'name',
        sort_as  = '_name',
        font_desc=font_name,
        ),

    Column( 'color',    data_type= str),
    Column( 'age',      data_type= int),
    Column( 'year',     data_type= int),
    Column( 'country',  data_type= str, sorted=True, use_markup=True),
    Column( 'price',    data_type= currency, ),
    Column( 'variant',  data_type= str, ),
]
pcols = dict( (c.attribute, c) for c in Item.columns )    #assume once only
Item.columns_extra = [
    Column( 'location', data_type=str ),
]

alldata = [
    Item( 'Evandro roha'    ,1963, 'jamaica', hilite=True, ),
    Item( 'hills bills'     ,2002, 'california'     ),
    Item( 'Henrique D\'oro' ,1981, 'Spain'          ),
    Item( 'old barrel'      ,1993, 'scotland'       ),
    Item( 'Johan bin 341'   ,2003, 'Goteborg'),
    Item( 'Lorenzo'         ,2008, 'Granada',       ),
    Item( 'bon appety'      ,2005, 'provance',       hilite=True),
    Item( 'heaven drops'    ,2009, 'Alalalaååðòú',  ),
    Item( 'maharadja sause' ,2000, 'Bombai',         hilite=True),
    Item( 'overtura didj'   ,2002, 'Ngooroong australia', ),
    Item( 'sarumaia'        ,1992, 'moulinesia',    ),
]
choices.country.all = list( set( p.country for p in alldata ))

def window( size =winsize, delta=0):
    #size = gtk.gdk.screen_width()*2/3, gtk.gdk.screen_height()*2/3
    win = gtk.Window()
    win.set_decorated( False)
        #font.set_family("sans")
        #font.set_size(self.font_size * pango.SCALE)
    win.set_default_size( *[x-delta for x in size] )
    return win

def mainwin():
    win = window( delta=1)
    win.connect('destroy', gtk.main_quit)
    vbox = gtk.VBox( spacing=3)
    win.add(vbox)

    class Data:
        thefilter = {}
        _oldfilter = {}
        listener = None
        def filter( me, attr, value):
            if value is None:
                me.thefilter.pop( attr, None)
            else:
                me.thefilter[ attr] = value

            if me._oldfilter == me.thefilter:   #dont refilter if same
                #print 'same'
                return
            me._oldfilter = me.thefilter.copy()
            if me.listener:
                print 'apply', me.thefilter
                r = []
                for a in me.all():
                    #print a
                    for k,vf in me.thefilter.iteritems():
                        fcmp = choices[k].cmp
                        va = getattr( a, k)
                        #print k, va,vf
                        if not fcmp( va, vf):
                        #    print 'ne'
                            break
                    else:
                        r.append(a)
                print r
                me.listener( r )

        def all( me):
            return alldata

    data = Data()
    if 10:
        class filter_chosen:
            def __init__( me, attr): me.attr = attr
            def __call__( me, colview, item, olist):
                #print 'cal', me.attr, item.val
                data.filter( me.attr, item.val )
            def unset( me, colview,olist):
                #print 'unset', me.attr
                olist.unselect_all()
                data.filter( me.attr, None)

        hbox = gtk.HBox( spacing=9)
        vbox.pack_start(hbox)

        for k,vs in choices.__dict__.items():
            if k.startswith('__'): continue
            cc = Column( 'val', title=k, data_type=str, expand=True, use_markup=pcols[k].use_markup)
            onchoice= filter_chosen( k)
            o = ObjectList( [ cc ],
                    (DictAttr( val=c ) for c in vs.all),
                    onchoice= onchoice.__call__)
            cc.treeview_column.connect( 'clicked', onchoice.unset, o)
            hbox.pack_start(o)


    def row_activated( container, item, olist): itemwin( item)
    o = ObjectList( Item.columns, data.all(), onchoice= row_activated )
    data.listener = lambda x: o.add_list(x) #o.refresh( x,True)
    vbox.pack_start(o)
    win.show_all()
    #win.size_request()
    #win.queue_resize()
    #win.resize( *[x+1 for x in winsize])
    win.resize( *winsize)

####################

def align( l, xalign=0, yalign=0.5, xscale=0, yscale=0):
    align = gtk.Alignment( xalign, yalign, xscale, yscale)
    align.add(l)
    return align


def label( name):
    l = Label( name)
    if font: l.modify_font( font)
    return l

# 'www.svilendobrev.com'
urls = '''
    file://localhost/home/az/azcom/index.html
    file://localhost/home/az/azcom/mysoft.html
    file://localhost/home/az/azcom/efficiency.html
'''.split()


class Moz:
    inited = None
    def __init__( me):
        me.moz = me.widget = None
        try:
            import gtkmoz
            # pygtkmoz-0.1/ : makefile/setup.py: pkgname is xulrunner-gtkmozembed
            #       needs xulrunner-dev + python-gtk2-dev
            if 0:
                import os
                try: homedir = os.environ["HOME"]
                except KeyError:
                    print "no home directory"
                    homedir = '.'
                profiledir = os.path.join( homedir, ".gtkmozembedexample/")
                gtkmoz.gtk_moz_embed_set_profile_path( profiledir, "helpsys")

            me.moz = me.widget = gtkmoz.MozEmbed()
            if not me.inited:
                gtkmoz.gtk_moz_embed_push_startup()     #keep xpcom from shutdown
                me.inited = 1
        except:
            print 'aaaaaaa'
            import traceback
            traceback.print_exc()
            me.widget = Label( 'browser here')

        #data = '<html><head><title>Hello</title></head><body>pygtk dev</body></html>'
        #moz.render_data(data, long(len(data)), 'file:///', 'text/html')
        #moz.load_url( urls[-1])
        #vbox.set_size_request( 200,200)
        #vbox.queue_resize( )

    def bbox( me):
        return me.widget

    def kill( me, abox):
        if me.moz is not None:
            abox.remove( me.moz)
            del me.moz

    def set_url( me, url):
        if me.moz is not None:
            me.moz.load_url( url)
        else: me.fake.set_text( url)

ypadding=5
def label2cell( tbl, name, x,y, w=1, ypadding=ypadding, kargs4align ={}, **kargs):
    l = label( name)
    tbl.attach( align(l, **kargs4align), x,x+w,  y,y+1, ypadding=ypadding, **kargs)

def itemwin( item):
    moz = Moz()

    win = window()
    win.move(0,0)

    vbox = gtk.VBox( homogeneous=False, spacing=5)
    win.add(vbox)

    #vbox.pack_start(
    #    align( label( 'this item features:'), xalign=0.20), expand=False )

    ok = Button( '_Ok, close', padding= (10,10) )
    if font: ok.modify_font( font)
    def kill( x):
        moz.kill( vbox)
        win.destroy()
    ok.connect( 'clicked', kill)
    #ok.set_border_width(10)
    vbox.pack_end( align( ok, xalign=0.5, xscale=0.3 ), expand=False, padding=5 )

    vbox.pack_end( moz.bbox() )

    attrs = Item.columns + Item.columns_extra
    hitem = len( attrs)
    t = gtk.Table( columns=2, rows= 1+hitem, homogeneous=False)
    label2cell( t,
        'this item features:', kargs4align= dict( xalign= 0.20),
        x=0,w=2, y=0, )
    y=1
    for c in attrs:
        name = c.title
        label2cell( t, name, 0,y, xpadding=20, xoptions=gtk.FILL)

        attr = getattr( c, 'show_as', c.attribute)
        label2cell( t, str(getattr( item, attr)),
                    1,y, xpadding=10, )
        y+=1

    hbox = gtk.HBox()
    hbox.pack_start(t)

    cols = [ Column( 'url', title='reviews', data_type=str, expand=True ), ]
    def row_activated( container, item, olist):
        ii = id(item)/64
        u = urls[ ii%len(urls) ]+'?'+item.url
        print u
        moz.set_url( u )
    l = ObjectList( cols,
            (DictAttr( url=u) for u in item.reviews),
            onchoice= row_activated
        )
    hbox.pack_start(l)

    vbox.pack_start( hbox, expand=False)

    win.show_all()

#itemwin( alldata[0])
mainwin()

gtk.main()
# vim:ts=4:sw=4:expandtab

