#!/usr/bin/env python

"""
v 5.4

gAnyRemote
GTK-based GUI for anyRemote - a bluetooth remote for your PC.

Copyright (C) 2007,2008 Mikhail Fedotov <anyremote@mail.ru>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
"""

import locale
import gettext
import getopt
import gobject
import os
import re
import pygtk
import signal
import socket
import sys
import threading
import thread
import time
from sets import Set

signal.signal(signal.SIGINT, signal.SIG_DFL)
pygtk.require('2.0')

#Translation stuff

#Get the local directory since we are not installing anything
dirpath = os.path.dirname(sys.argv[0])
local_path = os.path.realpath(os.path.join(dirpath,'mo'))

# try ../share/locale/ (Linux)
if not os.path.exists(local_path):
    local_path = os.path.realpath(os.path.join(dirpath,'../share/locale/'))

# try ../lib/locale/ (Sun)
if not os.path.exists(local_path):
    local_path = os.path.realpath(os.path.join(dirpath,'../lib/locale/'))

# last resort ... try /usr/share/locale
if not os.path.exists(local_path):
    local_path = os.path.realpath('/usr/share/locale/')

langs = []

lc = ''
encoding = ''
try:
    lc, encoding = locale.getdefaultlocale()
except ValueError, cmd:
   print 'Error: ',cmd,'\nCorrect $LANG or $LANGUAGE first !!!'
   quit()

if lc:
    #If we have a default, it's the first in the list
    langs = [lc]

# Now lets get all of the supported languages on the system
language = os.environ.get('LANGUAGE', None)
if language:
    langs += language.split(":")

#langs += ["ru_RU"]
#print 'langs',langs

APP_NAME = "ganyremote"

gettext.bindtextdomain(APP_NAME, local_path)
gettext.textdomain(APP_NAME)

# Get the language to use
lang = gettext.translation(APP_NAME, local_path, languages=langs, fallback = True)

_ = lang.gettext

#
# String constants (not all!)
#
AR_NOTINSTALLED = _('Not installed')

AR_NOINFO   = _('No information')
AR_AVAIL    = _('Available')
AR_NOTAVAIL = _('Not available')
AR_MANAGED  = _('Managed')
AR_RUNNING  = _('Running')

AR_CONN_DEV = _('Connecting to device')
AR_WAIT_OPS = _('Wait other operations to finish')
AR_SEL_DIR  = _('Directory selection')

AR_OK       = _('OK')
AR_CANCEL   = _('Cancel')
AR_ADD      = _('Add')
AR_DELETE   = _('Delete')
AR_CHOOSE   = _('Choose')
AR_ALL      = _('All')
AR_FILE     = _('File')
AR_CLOSE    = _('Close')

AR_MODE     = _('Mode')
AR_STATUS   = _('Status')
AR_APP      = _('Application')
AR_CUSTOM   = _('Custom')
AR_EXAMPLE  = _('Example')

AR_STOPPED  = _('anyRemote stopped')
AR_DISCONN  = _('Disconnected from phone')
AR_CONNECT  = _('Connected to phone')

try:
   import gtk
except ImportError:
   print _('Install PyGTK first !!!')
   quit()

pybluez = True 
try:
    import bluetooth
except ImportError:
   pybluez = False

##################################################################################
#
# Blink Icon class
#
##################################################################################

class BlinkThread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)        

    def run(self):
       gtk.gdk.threads_enter()
       gui.setIcon(gui.pixbufFlash)
       gtk.gdk.threads_leave()
       
       time.sleep(0.2)
               
       gtk.gdk.threads_enter()
       gui.setIcon(gui.pixbufOn)
       gtk.gdk.threads_leave()
       
##################################################################################
#
# BT communication thread
#
##################################################################################

# Beware:
# Can not run more than one command on BT adapter at once, since it could hungs 

class BtComm(threading.Thread):

    def __init__(self, jDir):
	threading.Thread.__init__(self) 
	self.midletDir = jDir

    def run(self):
        global debug, bt_devices, cmd_array
	
	self.keepRun = True
	
	if debug:
	    print 'BtComm: run'
	
	while self.keepRun:
	
	    ctype = ''
	    cdata = ''
            gtk.gdk.threads_enter()
	    try:
                item = cmd_array[0]
	        del cmd_array[0] 
	        ctype = item[0]
	        cdata = item[1]
 	    except NameError:
	        pass
 	    except TypeError:
	        pass
	    except IndexError:
	        pass
            gtk.gdk.threads_leave()
	    
	    if debug and ctype != '':
	        print 'BtComm: (#',len(cmd_array),') got command',ctype,cdata
	 
	    if ctype == 'scan':
	        self.doScan()
	    elif ctype == 'ping':
	        self.doPing(cdata)
	    elif ctype.startswith('pushjar'):
	        self.doPush(cdata,ctype[7:],False)
	    elif ctype.startswith('pushjad'):
	        self.doPush(cdata,ctype[7:],True)
	    elif ctype == 'info':
	        self.doInfo(cdata)
	    elif ctype == 'test_at':
	        self.doAT(cdata)
	    else:
	        time.sleep(3)
		
    def setStatus(self, address, status):
        global debug, bt_devices
        
	if debug: print 'set for',address,status

        gtk.gdk.threads_enter()
        treeiter = bt_devices.get_iter_first()
        gtk.gdk.threads_leave()

        while treeiter != None:
            gtk.gdk.threads_enter()
            addr = bt_devices.get_value(treeiter, 0)
            gtk.gdk.threads_leave()
    	
            if address == addr:
                gtk.gdk.threads_enter()
                if status != bt_devices.get_value(treeiter, 4):
        	    bt_devices.set_value(treeiter,4,status)
		
		needRun = bt_devices.get_value(treeiter,3)  
		if status == AR_AVAIL and needRun != '':
		    if debug: 
		        print 'run anyRemote with',needRun
		    startAnyRemote(needRun, False)
		
    	        return
    	
    	    gtk.gdk.threads_enter()
    	    treeiter = bt_devices.iter_next(treeiter)
    	    gtk.gdk.threads_leave()

    def doScan(self):
	global debug
	if debug: print 'BtComm: scan devices'
		    
	timer = 0
	existing = getDevSet()
	
	# Search new devices
	nearby_devices = []
	try:
	    nearby_devices = bluetooth.discover_devices(lookup_names = True)
	except bluetooth.BluetoothError,msg:
	    if debug: print "BtComm: BluetoothError",msg
	    
	    # sleep additional 5 sec
	    t2 = 0
	    while self.keepRun and t2 < 5:
	    	time.sleep(0.1)
		t2 = t2 + 0.1
	
	if debug: print "BtComm: found %d devices" % len(nearby_devices)

	availSet = getAvailableSet()
	
	for addr,name in nearby_devices:
	    if debug:
		print "  %s - %s" % (addr, name)
	    
	    if addr not in existing:
	        showDetailsWin(addr, name, name, '', True)
	    else:
		if addr in availSet:
		    availSet.discard(addr)
		else:
		    self.setStatus(addr,AR_AVAIL)
	    
	for rest in availSet:
	    self.setStatus(rest, '')
	
	if debug: print 'BtComm: verify done'

    def doPing(self, data):
	global debug, dwin
	if debug: print 'BtComm: ping device'
	
	dwin.setStatustext('')
	writePBar(AR_CONN_DEV)
	
	os.system('killall -9 hcitool')
	if debug: print 'hcitool name '+data
	ret = getResult('hcitool name '+data,'browser')
	
	stopPBar()
	if (ret == ''):
	    dwin.setStatustext(_('Ping failed !'))
	else:
	    dwin.setStatustext(_('Ping OK !'))

    def doPush(self, data, size, usejad):
	global debug, dwin
	if debug: print 'BtComm: obex push ',data,size,usejad
	
	dwin.setStatustext('')
	stopPBar()    
	if not os.path.exists(self.midletDir):        
	    dwin.setStatustext(_('Can not find anyremote-J2ME-client installation !'))
	    return
	
	midlet = 'anyRemote-' + size + '.jar'
	path = self.midletDir + os.sep + midlet
	if not os.path.isfile(path):
	    dwin.setStatustext(_('Can not find java midlet ('+midlet+_(') to upload !')))
	    return
	
	sender = ''    
	if (isInstalled('gnome-obex-send') == 'OK'):
	    sender = 'gnome-obex-send -d '
	elif (isInstalled('bluetooth-sendto') == 'OK'):
	    sender = 'bluetooth-sendto --dest='
	elif (isInstalled('kbtobexclient') == 'OK'):
	    sender = 'kbtobexclient'
	else:
	    dwin.setStatustext(_('None of gnome-obex-send, bluetooth-sendto and kbtobexclient are installed !'))
	    return

	ret = getResult(sender+data+' '+path+' &','browser')
	
	if usejad:
	    jad = 'anyRemote-' + size + '.jad'
	    path = self.midletDir + os.sep + jad
	    if not os.path.isfile(path):
	        dwin.setStatustext(_('Can not find JAD file ('+jad+_(') to upload !')))
	        return
	
	    ret = getResult(sender+data+' '+path+' &','browser')
	
	
    def doInfo(self,data):
	global debug
	if debug: print 'BtComm: get info'

	writePBar(AR_CONN_DEV)
	
	services = bluetooth.find_service(address=data)

	if len(services) > 0:
            print "found %d services on %s" % (len(services), data)
            print
	else:
            print "no services found"

	for svc in services:
	    print "Service Name: %s"    % svc["name"]
	    print "    Host:        %s" % svc["host"]
	    print "    Description: %s" % svc["description"]
	    print "    Provided By: %s" % svc["provider"]
	    print "    Protocol:    %s" % svc["protocol"]
	    print "    channel/PSM: %s" % svc["port"]
	    print "    svc classes: %s "% svc["service-classes"]
	    print "    profiles:    %s "% svc["profiles"]
	    print "    service id:  %s "% svc["service-id"]
	    print

    def getSerialPort(self,addr):
	services = bluetooth.find_service(address=addr)
	for svc in services:
	    print svc
	    try:
	        if svc["name"] == 'Serial Port' or svc["name"].startswith('COM ') or svc["name"].startswith('Dial-up'):
	            return svc["port"]
            except AttributeError, NameError:
    	        pass
	return None
	
    def send_at(self,sock,cmd):
	if len(cmd) == 0: 
	    return ''
	
	data = cmd+'\r'
	print "send",cmd
	
	sock.send(cmd+'\r')
	time.sleep(0.5)
	data = sock.recv(1024)

	print "got",data
	return data

    def doAT(self,data):
        global debug, dwin
	if debug: print 'BtComm: doAT'
	
	dwin.setStatustext('')
	writePBar(AR_CONN_DEV)	
    	port = self.getSerialPort(data)
	if debug: print 'BtComm: port',port
        
	if port == None:
	    dwin.setStatustext(_('Can not get port to connect to. Is there any device available ?'))
	else:
	    
	    sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
	    try:
	        sock.connect((data, port))
 	    except bluetooth.BluetoothError,msg:
		d = str(msg)
		print d
		stopPBar()
	        if d.startswith('(111,'):
		    dwin.setStatustext(_('Connection refused'))
	        return

  	    ret = self.send_at(sock,"ATZ")
  	    ret = self.send_at(sock,"ATE0")
  	    ret = self.send_at(sock,"AT+CMER=?")
	    
	    status = '' 
	    if ret.find('ERROR') == -1:
	        ret = ret[ret.index('+CMER'):]
	        ret = (ret.split('\n'))[0]
	    
	        AT_CMER=ret.replace(' ','').replace('\r','')
	    
	        #+CMER: (0,3),(0),(0),(0,1,2),(0)	<- bad
		#+CMER: (0,3),(0,1,2),(0),(0,1,2),(0)	<- OK
		s1 = (AT_CMER.split('('))[2]
		s2 = (s1.split(')'))[0]
		
		status = AT_CMER
		if s2 == '0':
		    status = _('AT mode is not supported by phone (')+status+')'
		else:
		    status = _('AT mode could be supported by phone (')+status+')'
	    else:
	    	status = _('AT mode is not supported by phone (ERROR response)')
		
            dwin.setStatustext(status)
            sock.close()

	stopPBar()
   
    def stop(self):
        global debug
	if debug: print 'BtComm stop'
	self.keepRun = False

##################################################################################
#
# DeviceDetail window
#
##################################################################################

class DeviceDetail:

    def initWindow(self):
        global debug

        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
	
        self.window.connect("destroy", self.close)
	
	capt = _('Device parameters')
	if self.isNew:
	    capt = _('New device')
	    
        self.window.set_title(capt)
	
        vbox = gtk.VBox(False, 0)
        self.window.add(vbox)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	label = gtk.Label(_('  Device name: ')+self.model+'       ')
        hbox.pack_start(label, 0, True, 0)

        label = gtk.Label(_('BT address: ')+self.btAddress+'         ')
        hbox.pack_end(label, 0, True, 0)
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	    
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        label = gtk.Label(_('Specify name: '))
        hbox.pack_start(label, 0, True, 0)

        self.name = gtk.Entry()
        self.name.set_max_length(64)
        hbox.pack_start(self.name, True, True, 0)
	self.name.set_text(self.dname)
		
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

	self.run_when = gtk.CheckButton(_('Run anyRemote when discovered.'), False)
        hbox.pack_start(self.run_when, 0, True, 0)
	self.run_when.set_active((self.cfile != '')) 
	self.run_when.connect('toggled', self.doWhen)
	
	tts = gtk.Tooltips()
	tts.set_tip(self.run_when,_('anyRemote will start only if no other instances of anyRemote are running'))
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.cfgFile = gtk.Entry()
        self.cfgFile.set_max_length(64)
        hbox.pack_start(self.cfgFile, True, True, 0)
	self.cfgFile.set_text(self.cfile)
	self.cfgFile.set_editable(False)
	self.cfgFile.set_sensitive((self.cfile != ''))
	self.cfgFile.set_position(len(self.cfile))
	
        self.choose = gtk.Button(label=AR_CHOOSE)
        self.choose.connect("clicked", self.chooseAction)
        hbox.pack_end(self.choose, False, True, 0)
	self.choose.set_sensitive((self.cfile != ''))

	################
	self.sBar = gtk.Statusbar()
	vbox.add(self.sBar)
	vbox.set_child_packing(self.sBar, 0, 1, 0, gtk.PACK_END)
	self.cid = self.sBar.get_context_id('a')
	self.sBar.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
                                                             
        self.btnUp = gtk.Button(label=_('Upload java'))
        self.btnUp.connect("clicked", self.upload)
        hbox.pack_start(self.btnUp, False, True, 0)
	
	label = gtk.Label(_(' with icon set '))
        hbox.pack_start(label, 0, True, 0)
	
	self.sz16 = gtk.CheckButton('16x16', False)
	self.sz16.set_active(True)
        hbox.pack_start(self.sz16, 0, True, 0)
	self.sz32 = gtk.CheckButton('32x32', False)
        hbox.pack_start(self.sz32, 0, True, 0)
	self.sz64 = gtk.CheckButton('64x64', False)
        hbox.pack_start(self.sz64, 0, True, 0)
	
        self.sz16.connect("clicked", self.clicked_sz16)
        self.sz32.connect("clicked", self.clicked_sz32)
        self.sz64.connect("clicked", self.clicked_sz64)
	
	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	
	self.uplJad = gtk.CheckButton(_('Also upload JAD'), False)
	self.uplJad.set_active(False)
        hbox.pack_start(self.uplJad, 0, True, 0)
	
 	tj = gtk.Tooltips()
	tj.set_tip(self.uplJad,_('Can be useful for Samsung phones'))

	self.bigTitleIcon = gtk.CheckButton(_('use big title icon'), False)
        hbox.pack_start(self.bigTitleIcon, 0, True, 0)
        self.bigTitleIcon.connect("clicked", self.clicked_bti)
	ts = gtk.Tooltips()
	ts.set_tip(self.bigTitleIcon,_('16x16 and 64x64 title icons are available'))
	
	if not os.path.isdir(self.midletDir): 
	    self.btnUp.set_sensitive(False)
	    self.bigTitleIcon.set_sensitive(False)
	    self.sz16.set_sensitive(False)
	    self.sz32.set_sensitive(False)
	    self.sz64.set_sensitive(False)
	    tj = gtk.Tooltips()
	    tj.set_tip(self.btnUp,_('It needs to install anyremote-J2ME-client package first'))
	
	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_END)

        self.btnPing = gtk.Button(label=_('Ping'))
        self.btnPing.connect("clicked", self.ping)
        hbox.pack_start(self.btnPing, False, True, 0)

        self.btnAT = gtk.Button(label=_('Test AT'))
        self.btnAT.connect("clicked", self.test_at)
        hbox.pack_start(self.btnAT, False, True, 0)

        btn = gtk.Button(label=AR_OK)
	addIconToButton(btn,gtk.STOCK_OK)
        btn.connect("clicked", self.ok)
        hbox.pack_end(btn, False, True, 0)
	
        btn = gtk.Button(label=AR_CLOSE)
	addIconToButton(btn,gtk.STOCK_CLOSE)
        btn.connect("clicked", self.close)
        hbox.pack_end(btn, False, True, 0)
 
 
 	bt = btVerify(False)
	if bt == 'NOK':
	    if debug: print 'DeviceDetail: Bluetooth not active'

            self.btnPing.set_sensitive(False)
            self.btnAT.set_sensitive(False)
	    self.btnUp.set_sensitive(False)
	    self.bigTitleIcon.set_sensitive(False)
	    
	    tj = gtk.Tooltips()
	    tj.set_tip(self.btnPing,_('Bluetooth service is not active'))
	    tj.set_tip(self.btnAT,_('Bluetooth service is not active'))

	self.window.set_size_request(530,280)
	self.window.show_all()
	
	self.isShown = True

    def ok(self,w):
    	global bt_devices
	
	gtk.gdk.threads_enter()
	treeiter = bt_devices.get_iter_first()
	gtk.gdk.threads_leave()
	    
	while treeiter != None:
	    gtk.gdk.threads_enter()
	    addr = bt_devices.get_value(treeiter, 0)
	    gtk.gdk.threads_leave()
	    
	    if self.btAddress == addr:
	        gtk.gdk.threads_enter()
	    	if self.name.get_text() != bt_devices.get_value(treeiter, 2):
	            bt_devices.set_value(treeiter,2,self.name.get_text())
		    
	    	if self.model != bt_devices.get_value(treeiter, 1):
	            bt_devices.set_value(treeiter,1,self.model)

		cf = self.cfgFile.get_text()
	    	if cf != bt_devices.get_value(treeiter, 3):
	            bt_devices.set_value(treeiter,3,cf)
		gtk.gdk.threads_leave()
		
		self.close(w)
		return
	    
	    gtk.gdk.threads_enter()
	    treeiter = bt_devices.iter_next(treeiter)
	    gtk.gdk.threads_leave()

	gtk.gdk.threads_enter()
	bt_devices.append([self.btAddress,self.model,self.name.get_text(),self.cfgFile.get_text(),AR_AVAIL])
	gtk.gdk.threads_leave()
	
    	self.close(w)

    def close(self,w):
        self.isShown = False
    	self.window.hide()

    def chooseAction(self,w):
    	self.choose.set_sensitive(False)
	cfgChooser(self)

    def clicked_sz16(self,w):
        if not self.sz16.get_active():
           self.sz16.set_active(True)   # do not allow to reset
           self.sz32.set_active(False)
           self.sz64.set_active(False)

    def clicked_sz32(self,w):
        if self.sz32.get_active():
           self.sz16.set_active(True)
        else:
           self.sz64.set_active(False)

    def clicked_sz64(self,w):
        if self.sz64.get_active():
           self.sz16.set_active(True)
           self.sz32.set_active(True)
           self.bigTitleIcon.set_active(True)

    def clicked_bti(self,w):
        if not self.bigTitleIcon.get_active():
           self.sz64.set_active(False)

    def test_at(self,w):
        global debug, cmd_array, pbar
	if debug:
	    print 'test_at'
	stopPBar() 
	pbar = PBar(AR_WAIT_OPS,30)
	queueBT('test_at',self.btAddress)

    def ping(self,w):
        global debug, cmd_array, pbar
	if debug:
            print _('Queue ping request')

	stopPBar() 
	pbar = PBar(_('Wait ping results'),20)
	queueBT('ping',self.btAddress)
	    
    def upload(self,w):
        global debug, cmd_array, pbar
	if debug:
            print _('Queue push request')
	 
	sz = '16'   
	if self.sz32.get_active():
	    sz = '32'
	if self.sz64.get_active():
	    sz = '64'
	if self.bigTitleIcon.get_active():
	    sz = sz+'b'
	    
	stopPBar() 
	pbar = PBar(AR_WAIT_OPS,20)
	
	push = 'pushjar'
	if self.uplJad.get_active():
	    push = 'pushjad'
	    
	queueBT(push+sz,self.btAddress)
   	
    def doWhen(self,w):
        global debug
	if debug: print 'doWhen'
	
	if self.run_when.get_active():
	    self.choose.set_sensitive(True)
	    self.cfgFile.set_sensitive(True)
	else: 
	    self.choose.set_sensitive(False)
	    self.cfgFile.set_text('')
	    self.cfgFile.set_sensitive(False)
	    
	if debug: print 'doWhen', self.cfgFile.get_text()

    def setStatustext(self,text):
	self.sBar.pop(self.cid)
	self.sBar.push(self.cid,'  ' + text)
	    
    def __init__(self, ba, m, n, act, is_new, jDir):
        global debug
	
	self.model     = m.replace('\n','')
	self.dname     = n.replace('\n','')
	self.btAddress = ba
	self.cfile     = act
	self.isNew     = is_new
	self.midletDir = jDir
	
        self.initWindow() 
	#if debug:
        #    print 'Queue info request'
	#    queueBT('info',self.btAddress)

##################################################################################
#
# Progressbar
#
##################################################################################

def progress_timeout(pbobj):
    new_val = pbobj.pbar.get_fraction() + 0.1/pbobj.tmout
    if new_val > 1.0:
        new_val = 0.0
    pbobj.pbar.set_fraction(new_val)
    return True

class PBar:
    def __init__(self, text, time):
    	self.text    = text
    	self.tmout   = time

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_resizable(True)

        self.window.set_title('')
        self.window.set_border_width(0)

        vbox = gtk.VBox(False, 5)
        vbox.set_border_width(10)
        self.window.add(vbox)

        align = gtk.Alignment(0.5, 0.5, 0, 0)
        vbox.pack_start(align, False, False, 5)

        self.pbar = gtk.ProgressBar()
        align.add(self.pbar)
        self.timer = gobject.timeout_add (100, progress_timeout, self)
	
	self.pbar.set_text(self.text)
	self.pbar.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, False, 0)
	
        self.window.show_all()

    def set_text(self, t):
        self.text = t
        self.pbar.set_text(self.text)
	
    def stop(self):
        try:
            gobject.source_remove(self.timer)
        except AttributeError, NameError:
            print 'Exception: gobject.source_remove(gui.timer)'
    	    pass
        self.window.destroy()

##################################################################################
#
# Application status updater
#
##################################################################################
class StatusUpdater(threading.Thread):

    def __init__(self, timeout):
	threading.Thread.__init__(self) 
	self.tmout = timeout

    def run(self):
        global debug, liststore
	
	self.runUpdater =  True
	
	if debug: print 'StatusUpdater',self.tmout
	
	while self.runUpdater:
	    timer = 0
	    
	    # catch stop event without waiting full timeout
	    while self.runUpdater and timer < self.tmout:
	        time.sleep(0.1)
		timer = timer + 0.1
	    
	    if self.runUpdater:
	        if debug: print 'StatusUpdater: verify start'
	    
	        gtk.gdk.threads_enter()
	        treeiter = liststore.get_iter_first()
	        gtk.gdk.threads_leave()
	    
	    while self.runUpdater and treeiter != None:
	        gtk.gdk.threads_enter()
		aRun = liststore.get_value(treeiter, 3)
	        gtk.gdk.threads_leave()
		
	        if aRun != '':
	    	    isRun  = getResult(aRun,'updater')
		    
	            gtk.gdk.threads_enter()
	    	    status = liststore.get_value(treeiter, 5)
		    gtk.gdk.threads_leave()
		    
		    if status == AR_MANAGED and isRun == 'NOK':
	    	        status = AR_AVAIL
		    elif status == AR_AVAIL and isRun == 'OK':
	    	        status = AR_RUNNING
		    elif status == AR_RUNNING and isRun == 'NOK':
	    	        status = AR_AVAIL
		    #else:
		    #    status = ''
			
		    gtk.gdk.threads_enter()
		    liststore.set_value(treeiter, 5, status)    
		    gtk.gdk.threads_leave()
		
		gtk.gdk.threads_enter()   
	        treeiter = liststore.iter_next(treeiter)
		gtk.gdk.threads_leave()
		
	    if debug: print 'StatusUpdater: verify done'
		
    def stop(self):
        global debug
	
	if debug: print 'StatusUpdater: stop'
	self.runUpdater = False

##################################################################################
#
# Reader of cfg. files
#
##################################################################################
class CfgFileReader(threading.Thread):

    def __init__(self, cfgDirs, all, apps, cust, ex, at, srv, bm):
	threading.Thread.__init__(self) 
	
	global cfgFileReaderFlag
	
	cfgFileReaderFlag = True
	
	self.cfgDirs  = cfgDirs      
	self.all   = all      
	self.apps = apps      
	self.cust = cust      
	self.ex   = ex      
	self.at   = at     
	self.srv  = srv      
	self.bm   = bm      

    def run(self):
        global debug, liststore, gui, cfgFileReaderFlag
        
	gtk.gdk.threads_enter()
        gui.treeview.set_model(None);
	liststore.clear()
        gtk.gdk.threads_leave()
        
	self.regExp  = re.compile("^[^a-zA-Z0-9]*Gui")
	self.regExpB  = re.compile("^[^a-zA-Z0-9%]*VERS[^=]*=.+$")
	self.regExpAT = re.compile("^[^a-zA-Z0-9%]*Device[^=]*=/dev/[a-zA-Z0-9]+$")
        
	for cfgDir in self.cfgDirs:
	    if cfgDir == '':
	        continue
	    if debug: print 'Collect files in '+cfgDir
	    
	    if os.path.isfile(cfgDir):
	        self.processOneFile(cfgDir)
	    else:
	        for root, dirs, files in os.walk(cfgDir):
	            for cfgFile in files:
		        #time.sleep(0.1) 
	    	        self.processOneFile(root + os.sep + cfgFile)

        #gtk.gdk.threads_enter()
        #gui.treeview.set_model(liststore)
        #gtk.gdk.threads_leave()

	gtk.gdk.threads_enter()
        if gui.treeview.get_model() == None:
            gui.treeview.set_model(liststore)
        
	ti  = liststore.get_iter_first()
	while ti != None: 
	    fName = liststore.get_value(ti, 4)
            
 	    if fName == gui.lastCfgFile:
 	        gui.treeview.get_selection().select_iter(ti)
		#gui.treeview.set_cursor(liststore.get_path(ti)) --can cause a crash
		break
	    ti = liststore.iter_next(ti)

	gtk.gdk.threads_leave()
	
	cfgFileReaderFlag = False
	
	    
    def processOneFile(self,cfgFile):
        global icons, debug, gui, liststore
	
        fd = None
        try:
	    fd = open(cfgFile,'r')
        except IOError:
            pass
         
	if fd:
	    aName    = None
	    aInst    = ''
	    aRun     = ''
	    aIcon    = ''
	    aType    = None
	    aDesc    = ''
	    aDevice  = ''
	    aBemused = ''
	
            for line in fd:
	
		if self.regExp.match(line):
	    	
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppName[^=]*=(.+)$", line)
	    	    if p != None:
	    		aName = p.group(1)

	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppBinary[^=]*=(.+)$", line)
	    	    if p != None:
	    		aInst = p.group(1)
	    	
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppRun[^=]*=(.+)$", line)
	    	    if p != None:
	    		aRun = p.group(1)
	       
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppIcon[^=]*=(.+)$", line)
	    	    if p != None:
	    		aIcon = p.group(1)

	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppType[^=]*=(.+)$", line)
	    	    if p != None:
	    		aType = p.group(1)
			
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppDesc[^=]*=(.+)$", line)
	    	    if p != None:
	    		aDesc = p.group(1)

		    # obsolete; changed to GuiAppDesc
	    	    p = re.search("^[^a-zA-Z0-9]*GuiDescription[^=]*=(.+)$", line)
	    	    if p != None:
	    		aDesc = p.group(1)

	    	if self.regExpAT.match(line):
	    	    aDevice = 'a'
	    	
	    	if self.regExpB.match(line):
	    	    aBemused = 1
	
            if (not aName) and (not aType):
               if debug: print 'Not a configuration file. Skip '+cfgFile
               fd.close()
               return
               
	    aMode = 'Server'    
	    if aBemused == 1:
		aMode = 'Bemused'
	    elif aDevice == 'a':
		aMode = 'AT'
	    	
	    if aName == '':
	    	aName = os.path.basename(cfgFile)
	    	
	    if aInst == '':
	    	isInst = AR_NOINFO
	    else:
	    	isInst = isInstalled(aInst)

	    show = 1
	    status = AR_NOTAVAIL
	    if isInst == 'OK':
	    	status = AR_AVAIL
	    elif isInst == 'NOK' and not self.all:
	        show = 0
	    elif isInst == AR_NOINFO:
	    	status = ''

	    if not self.all:
	    	if aMode == 'AT' and not self.at:
	    	    show = 0
	    	elif aMode == 'Server' and not self.srv:
	    	    show = 0
 	        elif aMode == 'Bemused' and not self.bm:
	    	    show = 0
	    
	        if aType == 'Application' and not self.apps:
	            show = 0
	        elif aType == 'Custom' and not self.cust:
	            show = 0
	        elif aType == 'Example' and not self.ex :
	            show = 0
	        elif aType == '':
	            show = 0
	    
	    if show == 1:
		if debug: print 'Proceed '+aName
	
	    	if aIcon == '':
	    	    aIcon = 'fileopen.png'
	    
	    	pbuf = findIcon(aIcon)
	    		    	
	    	if aRun == '':
	    	    isRun = AR_NOINFO
	    	else:
	    	    isRun  = getResult(aRun,'reader')
		
		if status == AR_AVAIL and isRun == 'OK':
	    	    status = AR_RUNNING
	    		
	    	gtk.gdk.threads_enter()
		item = liststore.append([aName, pbuf, aInst, aRun, cfgFile, status, _(aMode), _(aType), aDesc])
		gtk.gdk.threads_leave()
		
	    else:
		if debug: print 'Skip '+aName
	    	
	    fd.close()

##################################################################################
#
# Choose cfg. file 
#
##################################################################################
class cfgChooser:

    def __init__(self, details_win):
        global debug, liststore
	
	self.dw = details_win
    
        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(_('Choose application'))
	self.window.connect("destroy", self.closePressed)
	
        vbox = gtk.VBox(False, 0)
        self.window.add(vbox)
        vbox.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()

        self.treeview  = gtk.TreeView(liststore)
       
        self.column_app    = gtk.TreeViewColumn(AR_APP)
        self.column_mode   = gtk.TreeViewColumn(AR_MODE)
        
	self.column_app.set_resizable(True)
	self.column_mode.set_resizable(True) 

	self.column_app.set_expand(True)
	
	self.column_app.set_spacing(5)
	self.column_mode.set_spacing(5)
  
	self.treeview.append_column(self.column_app)
        self.treeview.append_column(self.column_mode)

        self.cell0 = gtk.CellRendererPixbuf()
        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()

        self.column_app.pack_start   (self.cell0, False)
        self.column_app.pack_start   (self.cell1, True)
        self.column_mode.pack_end    (self.cell2, False)
	
        self.column_app.set_attributes   (self.cell0, pixbuf=1)
        self.column_app.set_attributes   (self.cell1, text=0)
        self.column_mode.set_attributes  (self.cell2, text=6)

        self.treeview.set_search_column(0)
        self.column_app.set_sort_column_id(0)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	
	self.treeview.show()
	
	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
  
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        b = gtk.Button(label=AR_OK)
        b.connect("clicked", self.okPressed)
        hbox.pack_start(b, True, True, 0)

        b = gtk.Button(label=AR_CLOSE)
        b.connect("clicked", self.closePressed)
        hbox.pack_start(b, True, True, 0)
	
	self.window.set_size_request(400, 300)
	
	self.window.set_icon(findIcon('ganyremote.png'))
	
	self.window.show_all()

    def rowActivateAction(self, treeview, path, view_column):
	treeiter = liststore.get_iter(path)
	self.quitOk(treeiter)

    def closePressed(self, widget):
        self.window.destroy()

    def okPressed(self, widget):
    
	selection = self.treeview.get_selection()
	(model, treeiter) = selection.get_selected()
	
	self.quitOk(treeiter)
	
    def quitOk(self, treeiter):
        s = liststore.get_value(treeiter, 4)
	self.dw.cfgFile.set_text(s)
	self.dw.cfgFile.set_sensitive(True)
	self.dw.cfgFile.set_position(len(s))
	self.dw.choose.set_sensitive(True)
        self.window.destroy()
    
##################################################################################
#
# Front-End to anyRemote
#
##################################################################################

class FrontEnd(threading.Thread):
    def __init__(self): 
        global debug
    	threading.Thread.__init__(self)        
    	if debug: print 'FrontEnd init'

    def stop(self):
        global debug
    	if debug: print 'FrontEnd stop'
    	self.isRun = False

    def run(self):
    	global port, debug
    	
    	self.isRun = True
    	if debug: print 'FrontEnd thread is running'

    	s = None
    	for res in socket.getaddrinfo('localhost', port, socket.AF_INET, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
    	    af, socktype, proto, canonname, sa = res
    	    
    	    try:
    		s = socket.socket(af, socktype, proto)
    		s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    		s.setblocking(0)
    	    except socket.error, msg:
    		s = None
    		continue
    	    if debug: print 'FrontEnd socket created'
    		
    	    try:
    		s.bind(sa)
    		s.listen(1)
    	    except socket.error, msg:
    		s.close()
    		s = None
    		continue
    	    if debug: print 'FrontEnd socket after listen'
    	    
    	    break
    	    
    	if s is None:
    	    if debug: print 'FrontEnd could not open socket'
    	    sys.exit(1)

    	while self.isRun:
    	    while self.isRun:
    		#print 'FrontEnd accepting connection'
    		try:
    		    conn, addr = s.accept()
    		    if debug: print 'accept', addr
    		    break
    		except socket.error,msg:
    		    #print 'accept err', msg
    		    time.sleep(0.1)
    	   
	    if self.isRun:
    	        self.processOneConnection(conn, addr)
    	
    	if debug: print 'Close server socket' 
    	s.close()
	    
    def processOneConnection(self,conn,addr):
	global gui, liststore, cmdToSend, debug
    	
        if debug: print 'FrontEnd processOneConnection', addr
	
	cfgFile = getResult('ps aux |grep anyremote|grep cfg|awk \'{n=split($0,arr);print arr[n];}\'', 'frontend')
	if cfgFile != '':
	    gtk.gdk.threads_enter()
	    ti  = liststore.get_iter_first()
	    while ti != None:
	        fName = liststore.get_value(ti, 4)
	        if fName == cfgFile:
	            liststore.set_value(ti, 5, AR_MANAGED)  
		    break
	        ti = liststore.iter_next(ti)
	    gtk.gdk.threads_leave()
    
        self.isConn = True
    	while self.isRun and self.isConn:
    	
    	    conn.setblocking(0)
    
    	    if debug: print 'FrontEnd.Connected by', addr
    	
    	    gtk.gdk.threads_enter()
    	    gui.setStatusDisconnected()
    	    gtk.gdk.threads_leave()
    	
    	    #time.sleep(0.5)
    	
    	    while self.isRun and self.isConn:
    	    	
    	    	time.sleep(0.2)
    	
    	    	data = ''
    	    	try:
    	    	    data = conn.recv(512)
    	    	    if debug: print 'Got from backend ', data
    	    	
    	    	    gtk.gdk.threads_enter()    
    	    	    gui.translateMsg(data)
    	    	    gtk.gdk.threads_leave()
    	    	
    	    	    if not data: 
    	    		if debug: print 'FrontEnd anyRemote die?'
    	    	    
    	    		gtk.gdk.threads_enter()
    	    		gui.setStatusStopped()
    	    		gtk.gdk.threads_leave()
    	    		self.isConn = False
    	    		break

    	    	except socket.error,msg:
    	    	    pass
    	    	
    	    	try:
    	    	    #print 'Send to backend ???'
    	    	    gtk.gdk.threads_enter()
    	    	    if cmdToSend:
    	    		# need to syncronize with GUI thread
    	    		if debug: print 'Send to backend '+cmdToSend + "\n"
    	    		conn.sendall(cmdToSend)
    	    		cmdToSend = '';
    	    	    gtk.gdk.threads_leave()
    	    		
    	    	except socket.error, NameError:
    	    	    if debug: print 'EXCEPTION 1'
    	    	    pass
    	
    	    if debug: print 'Close connection'  
    	    conn.close()
	    
	    gtk.gdk.threads_enter()
	    ti  = liststore.get_iter_first()
	    while ti != None:
	        stts = liststore.get_value(ti, 5)
	        if stts == AR_MANAGED:

		    aRun = liststore.get_value(ti, 3)
	            if aRun != '':
	    	        isRun  = getResult(aRun,'frontend')
                    
		        if isRun == 'OK':
		            liststore.set_value(ti, 5, AR_RUNNING)
		        else:
		            liststore.set_value(ti, 5, AR_AVAIL)
		    else:
		        isInst = isInstalled(liststore.get_value(ti, 2))
			if isInst == 'OK':
			    liststore.set_value(ti, 5, AR_AVAIL)
			else:
		            liststore.set_value(ti, 5, '')
		    
	        ti = liststore.iter_next(ti)
	    gtk.gdk.threads_leave()
		
		
##################################################################################
#
# Device browser
#
##################################################################################

class DeviceBrowser:

    def createMenus(self, vbox):
    
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)
 
        menuitem = iconMenuItem(_('Scan for devices'), gtk.STOCK_FIND)
        menu.add(menuitem)
	menuitem.connect('activate', self.scan)

	menuitem = iconMenuItem(_('Details'),gtk.STOCK_PROPERTIES)
        menu.add(menuitem)
	menuitem.connect('activate', self.details)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_REMOVE)
        menu.add(menuitem)
	menuitem.connect('activate', self.delete)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
        menu.add(menuitem)
	menuitem.connect('activate', self.close)

    def initWindow(self):
        global debug, bt_devices
    
	if debug: print 'DeviceBrowser: initWindow'
    
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("gAnyRemote device browser")

        self.window.connect("destroy", self.close)

        vbox = gtk.VBox(False, 0)
        self.window.add(vbox)
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)

        self.treeview  = gtk.TreeView(bt_devices)
       
        self.column_name = gtk.TreeViewColumn(_('Name'))
        self.column_dnam = gtk.TreeViewColumn(_('Device name'))
        self.column_addr = gtk.TreeViewColumn(_('Address'))
        self.column_stts = gtk.TreeViewColumn(AR_STATUS)
        
	self.column_name.set_resizable(True)
	self.column_dnam.set_resizable(True)
	self.column_addr.set_resizable(True)
	self.column_stts.set_resizable(True) 

	self.column_name.set_expand(True)
	
	self.column_name.set_spacing(5)
	self.column_dnam.set_spacing(5)
	self.column_addr.set_spacing(5)
	self.column_stts.set_spacing(5)
  
	self.treeview.append_column(self.column_name)
	self.treeview.append_column(self.column_dnam)
        self.treeview.append_column(self.column_addr)
        self.treeview.append_column(self.column_stts)

        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()
        self.cell3 = gtk.CellRendererText()
        self.cell4 = gtk.CellRendererText()

        self.column_name.pack_start(self.cell1, True)
        self.column_dnam.pack_start(self.cell2, False)
        self.column_addr.pack_start(self.cell3, False)
        self.column_stts.pack_start(self.cell4, False)
	
        self.column_name.set_attributes(self.cell1, text=2)
        self.column_dnam.set_attributes(self.cell2, text=1)
        self.column_addr.set_attributes(self.cell3, text=0)
        self.column_stts.set_attributes(self.cell4, text=4)

        self.treeview.set_search_column(0)

        self.column_name.set_sort_column_id(0)
	
	bt_devices.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	self.window.set_size_request(420, 200)
	self.window.show_all()
	
	self.isShown = True

    def showDetails(self,ti):
        global dwin
	v1 = bt_devices.get_value(ti, 0)
	v2 = bt_devices.get_value(ti, 1)
	v3 = bt_devices.get_value(ti, 2)
	v4 = bt_devices.get_value(ti, 3)
	
        showDetailsWin(v1, v2, v3, v4, False)

    def scan(self,w):
        browseDevices()

    def delete(self,w):
        global bt_devices
	
	(model, titer) = self.treeview.get_selection().get_selected()
	if titer:
            treeiter = bt_devices.remove(titer)

    def details(self,w):
	(model, titer) = self.treeview.get_selection().get_selected()
	if titer:
	    self.showDetails(titer)

    def rowActivateAction(self, treeview, path, view_column):
        global bt_devices
	self.showDetails(bt_devices.get_iter(path))
		    
    def close(self,w):
        global debug
	if debug: print "DeviceBrowser.close"
	
        self.window.destroy()
	self.isShown = False

    def __init__(self):
        global gui
    
        self.initWindow()
	
	if gui.browseTmout_ > 0:
	    browseDevices()
	    self.timer = gobject.timeout_add (1000*gui.browseTmout_, browseDevices)
	    
##################################################################################
#
# Configuration checker 
#
##################################################################################

class CfgChecker:

    def createMenus(self, vbox):
    
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
        menu.add(menuitem)
	menuitem.connect('activate', self.close)

    def initWindow(self, jD):
        global debug
    
	self.javaDir = jD
    
	if debug: print 'CfgChecker: initWindow'
     
    	pbs = AR_NOTINSTALLED
	if pybluez: pbs = _('Installed')
	
        ars = isInstalled('anyremote')
        if ars == 'NOK':
	    ars = AR_NOTINSTALLED
        else:
            ars = _('Installed')

        bus = isInstalled('sdptool')
        if bus == 'NOK':
	    bus = AR_NOTINSTALLED
        else:
            bus = _('Installed')

        jDir = getJ2MEPath()
	ajs = _('Installed')
        if jDir == '':
	    ajs = AR_NOTINSTALLED

        ahs = isInstalled('anyremote2html')
        if ahs == 'NOK':
	    ahs = AR_NOTINSTALLED
        else:
            ahs = _('Installed')
    
        pkg_list = gtk.TreeStore(str,str)
	pkg_list.append(None,["anyRemote",ars])
	pkg_list.append(None,["Bluez utilities",bus])
	pkg_list.append(None,["PyBluez",pbs])
	ti = pkg_list.append(None,["anyremote-J2ME-client",ajs])
       
	if jDir != self.javaDir and jDir != '':
	    pkg_list.append(ti,[_('Warning:'),_('Installation directory of anyremote-J2ME-client not specified in current setup configuration !')])

	pkg_list.append(None,["anyremote2html",ahs])
        
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(_('gAnyRemote configuration check'))

        self.window.connect("destroy", self.close)

        vbox = gtk.VBox(False, 0)
        self.window.add(vbox)
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)

        self.treeview  = gtk.TreeView(pkg_list)
        self.treeview.expand_all()
       
        self.column_pkg  = gtk.TreeViewColumn(_('Package'))
        self.column_stat = gtk.TreeViewColumn(AR_STATUS)
        
	self.column_pkg.set_resizable(True)
	self.column_stat.set_resizable(True)

	self.column_pkg.set_expand(True)
	
	self.column_pkg.set_spacing(5)
	self.column_stat.set_spacing(5)
  
	self.treeview.append_column(self.column_pkg)
	self.treeview.append_column(self.column_stat)

        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()

        self.column_pkg.pack_start(self.cell1, True)
        self.column_stat.pack_start(self.cell2, False)
	
        self.column_pkg.set_attributes(self.cell1, text=0)
        self.column_stat.set_attributes(self.cell2, text=1)

        self.treeview.set_search_column(0)

        self.column_pkg.set_sort_column_id(0)
	
	pkg_list.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	self.window.set_size_request(300, 200)
	self.window.show_all()
	
	self.isShown = True

    def close(self,w):
        global debug
    
	if debug: print 'CfgChecker.close'
        self.window.destroy()
	self.isShown = False

    def __init__(self, jDir):
        self.initWindow(jDir)
	    
##################################################################################
#
# Editor 
#
##################################################################################

class cfgEditor:

    def __init__(self, f):
	self.editedFile = f
	
        self.eWnd = gtk.Window(gtk.WINDOW_TOPLEVEL)
	self.eWnd.set_size_request(600, 700)
        self.eWnd.set_resizable(True)  
        self.eWnd.connect("destroy", self.closeEditWindow)
        self.eWnd.set_title(_('Edit configuration file'))
        self.eWnd.set_border_width(0)

        box1 = gtk.VBox(False, 0)
        self.eWnd.add(box1)
       
        self.menubar = gtk.MenuBar()
        box1.pack_start(self.menubar, expand=False)
       
        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)

        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)
	
	menuitem = iconMenuItem(_('Save'), gtk.STOCK_SAVE)
	menu.add(menuitem)
	menuitem.connect('activate', self.saveFile)
	
	menuitem = iconMenuItem(_('Save As'), gtk.STOCK_SAVE_AS)
	menu.add(menuitem)
	menuitem.connect('activate', self.saveAs)
	
	menuitem = iconMenuItem(AR_CLOSE, gtk.STOCK_CLOSE)
	menu.add(menuitem)
	menuitem.connect('activate', self.closeEditWindow)
 
        box2 = gtk.VBox(False, 10)
        box2.set_border_width(10)
        box1.pack_start(box2, True, True, 0)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        textview = gtk.TextView()
	textview.set_editable(False);
        self.textbuffer = textview.get_buffer()
        sw.add(textview)

        box2.pack_start(sw)
	
        infile = None
        try:
            infile = open(self.editedFile, "r")
        except IOError:
            pass
            
        if infile:
            string = infile.read()
            infile.close()
            self.textbuffer.set_text(string)
	    
	    textview.set_editable(os.access(self.editedFile, os.W_OK))

	else:
	    errorMessage(_('Can not read the file ')+self.editedFile)
	    self.editedFile = ""
		
        self.eWnd.show_all()

    def closeEditWindow(self, widget):
        self.eWnd.destroy()

    def saveFile(self, widget):
	try:
	    f=open(self.editedFile, 'w')
	
	    if f:
    	        i1 = self.textbuffer.get_iter_at_offset(0)
    	        i2 = self.textbuffer.get_iter_at_offset(self.textbuffer.get_char_count())
                txt = self.textbuffer.get_text(i1, i2)
	        f.write(txt)
	        f.close()
		self.eWnd.destroy()
        except IOError:
	    errorMessage(_('Can not save the file !'))
	    self.saveAs(None)

    def saveAs(self, widget):
	self.fdialog = gtk.FileSelection(_('Save File As'))
	self.fdialog.set_filename("")
        self.fdialog.ok_button.connect("clicked", self.fileOk)
	self.fdialog.cancel_button.connect("clicked",lambda w: self.fdialog.destroy())
	self.fdialog.show()
 	   
    def fileOk(self, w):
   	f = self.fdialog.get_filename()
	self.fdialog.destroy()
        if f:
            self.editedFile = f
            self.saveFile(None)

##################################################################################
#
# Main window
#
##################################################################################

class gAnyRemote:

    ##################################################################################
    #
    # Configuration related part
    #
    ##################################################################################

    def saveConfigAction(self, action):
        self.saveConfig()

    def saveConfig(self):
        global bt_devices
	
 	# anyRemote related part
   	cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
    	if os.path.exists(cfg):
	    pass
	else:
	    os.mkdir(cfg)
	    
	f=open(cfg + os.sep + 'anyremote-fe.conf', 'w')
	if f:
 	    f.write('LastCfgFile='+self.entry.get_text()+'\n')
	    
	    if self.showAll_:
	        f.write('Show=All\n')
	    else:
	    	what = 'Show='
		if self.showApps_:
		    what = what + 'Apps,'
		if self.showCustom_:
		    what = what + 'Custom,'
		if self.showExamples_:
		    what = what + 'Examples,'
		if self.showAt_:
		    what = what + 'AT,'
		if self.showSrv_:
		    what = what + 'Server,'
		if self.showBm_:
		    what = what + 'Bemused,'
	    	
		f.write(what+'\n')

	    ac = '0'
            if self.autoReconn_:
	        ac = '1'
 	    f.write('AutoReconnectAT='+ac+'\n')
	    
	    if self.runWeb_:
	        f.write('WebInterface='+self.webParams_+'\n')

	    if self.device_ != '':
	        f.write('OverrideDevice='+self.device_+'\n')

	    #if self.updateTmout_ != -1:
	    tm = "%s" % (self.updateTmout_)
	    f.write('UpdateTimeout='+tm+'\n')
		
	    dirs = 'CfgDirs='
	    for d in self.cfgDirs:
	    	if d != '':
	            dirs = dirs +d + ';'
 	    f.write(dirs+'\n')
	    
	    if self.browseTmout_ > 0:
	        tm = "%s" % (self.browseTmout_)
	        f.write('DeviceBrowserTimeout='+tm+'\n')
            else:
	        f.write('DeviceBrowserTimeout=-1\n')
	   
	    f.write('JavaDir='+self.javaDir_+'\n')

	    f.close()
	
	# device browser related part
	f=open(cfg + os.sep + 'anyremote-peers.conf', 'w')
	if f:
	    treeiter     = bt_devices.get_iter_first()
	    while treeiter != None:
	        v1 = bt_devices.get_value(treeiter, 0)
	        v2 = bt_devices.get_value(treeiter, 1)
	        v3 = bt_devices.get_value(treeiter, 2)
	        v4 = bt_devices.get_value(treeiter, 3)
		
		f.write('Device='+v1+','+v2+','+v3+','+v4+'\n')

  	        treeiter = bt_devices.iter_next(treeiter)
	    
	    f.close()

    def setDefaultConfig(self):
    
	self.lastCfgFile   = ''
	self.cfgDirs       = []
	self.javaDir_      = ''
	self.showApps_     = True
	self.showCustom_   = False
	self.showExamples_ = False
	self.showAt_       = False
	self.showSrv_      = True
	self.showBm_       = False
	self.showAll_      = False
	self.autoReconn_   = False
	self.device_       = ''
	self.runWeb_       = False
	self.webParams_    = ''
	self.updateTmout_  = 60
	self.browseTmout_  = -1
	
    def readConfig(self):
        global bt_devices

	# anyRemote related part
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-fe.conf'
	
    	if os.path.exists(cfg):
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg) 
		    if line.startswith('LastCfgFile='):
		        self.lastCfgFile=line[12:]
		    elif line.startswith('Show='):
		    	#Show=Apps,Custom,Examples|All
			what = line[5:].split(',')
			
			# override defaults
	                self.showApps_ = False
			self.showSrv_  = False
			
			for item in what:
			   if item == 'All':
			      self.showAll_ = True
			   elif item == 'Apps':
			      self.showApps_ = True
			   elif item == 'Custom':
			      self.showCustom_ = True
			   elif item == 'Examples':
			      self.showExamples_ = True
			   elif item == 'AT':
			      self.showAt_ = True
			   elif item == 'Server':
			      self.showSrv_ = True
			   elif item == 'Bemused':
			      self.showBm_ = True
			      
		    elif line.startswith('AutoReconnectAT='):
		        self.autoReconn_ = (line == 'AutoReconnectAT=1')
		    elif line.startswith('OverrideDevice='):
		        self.device_ = line[15:]
		    elif line.startswith('WebInterface='):
		        self.runWeb_    = True
		        self.webParams_ = line[13:]
                    elif line.startswith('CfgDirs='):
		        self.cfgDirs=line[8:].split(';')
                    elif line.startswith('UpdateTimeout='):
		        self.updateTmout_=int(line[14:])
                    elif line.startswith('DeviceBrowserTimeout='):
		        tmt=line[21:]
    	    	        try:
    	    		    self.browseTmout_=int(tmt)
    	    	        except ValueError:
			    self.browseTmout_=-1

			if self.browseTmout_ <= 0:
			    self.browseTmout_=-1
                    elif line.startswith('JavaDir='):
		        self.javaDir_=line[8:]
		    
	    	f.close()
		self.entry.set_text(self.lastCfgFile)
		
		# Try to search again
		if self.javaDir_ == '':
		    self.javaDir_ = getJ2MEPath()
		
	# device browser related part
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-peers.conf'
	
    	if os.path.exists(cfg) :
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg)
		    
		    if line.startswith('Device='):
		        deviceData=line[7:].split(',')
			
			v1 = deviceData[0]
			v2 = deviceData[1]
			v3 = deviceData[2]
			v4 = deviceData[3]
			
			bt_devices.append([v1,v2,v3,v4,''])
	    	f.close()
	    
    def setAutoStartup(self, wm, isAuto):
        if wm == 'KDE':
	    autopath = os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'ganyremote'
	    if isAuto:
	    	if not os.path.exists(autopath):
		    os.system('ln -s `which ganyremote` '+autopath)
	    else:
	    	os.system('rm -f '+autopath)
	
        elif wm == 'Gnome':		# will work for gnome > 2.14 ?
	    cfgpath  = os.environ.get("HOME")+os.sep+'.config'
	    autopath = cfgpath+os.sep+'autostart'
	    autorun  = autopath+os.sep+'ganyremote.desktop'

    	    if not os.path.isdir(cfgpath):
        	os.mkdir(cfgpath)
    	    if not os.path.isdir(autopath):
        	os.mkdir(autopath)
	    if isAuto:
    	        if not os.path.isfile(autorun):
	            f=open(autorun, 'w')
	            if f:
 	                f.write('[Desktop Entry]\n')
 	                f.write('Encoding=UTF-8\n')
 	                f.write('Name=gAnyRemote\n')
 	                f.write('Exec=ganyremote\n')
 	                f.write('Icon=ganyremote\n')
 	                f.write('Type=Application\n')
 	                f.write('Comment=Remote control through bluetooth or IR connection\n')
 	                f.write('GenericName=Remote control through bluetoth or IR connection\n')
 	                f.write('Categories=Utility;\n')
		        f.close()
            else:
	        os.system('rm -f '+autorun)
		

    def populateCfgFiles(self):
        global cfgFileReaderFlag
	try:
	    if cfgFileReaderFlag:
	        return
	except NameError:
	    pass
	    
	cfgFileReader = CfgFileReader(self.cfgDirs, self.showAll_,self.showApps_,self.showCustom_,self.showExamples_,self.showAt_,self.showSrv_,self.showBm_)
	cfgFileReader.start()

    ##################################################################################
    #
    # Config Window related part
    #
    ##################################################################################
    
    def showBrowser(self, action):
	showBrowserWin()

    def showChkCfg(self, action):
	showChkCfgWin(self.javaDir_)

    def showConfAction(self, action):
	    self.showConfDialog()

    def showConfDialog(self):
	self.dirsChanged = False
	
        self.config = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.config.set_title(_('Properties'))
 	self.config.set_size_request(700, 400)
	self.config.connect("destroy", self.closeCfg)
       
	vbox = gtk.VBox(False, 0)
        self.config.add(vbox)
        vbox.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

        label = gtk.Label(_('Choose directories with configuration files and add them to the list'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
	hsep = gtk.HSeparator()
        vbox.add(hsep)
	vbox.set_child_packing(hsep, 0, 1, 0, gtk.PACK_START)
        hsep.show()
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()
	
        self.cfg_liststore = gtk.ListStore(str)
        self.cfg_treeview  = gtk.TreeView(self.cfg_liststore)
       
        self.column_dir = gtk.TreeViewColumn(_('Directories'))
	self.cfg_treeview.append_column(self.column_dir)
        self.cfg_cell = gtk.CellRendererText()
        self.column_dir.pack_start(self.cfg_cell, True)
        self.column_dir.set_attributes(self.cfg_cell, text=0)
        self.column_dir.set_sort_column_id(0)
        scrolledwin.add(self.cfg_treeview)
	self.cfg_treeview.show()
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        self.btnAdd = gtk.Button(label=AR_ADD)
        self.btnAdd.connect("clicked", self.addToCfgDirList)
        hbox.pack_start(self.btnAdd, False, False, 0)
	self.btnAdd.show()

        btn = gtk.Button(label=AR_DELETE)
        btn.connect("clicked", self.deleteFromCfgDirList)
        hbox.pack_start(btn, False, False, 0)
	btn.show()

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

        self.jLabel = gtk.Label(_('Upload java client from '))
        hbox.pack_start(self.jLabel, False, False, 0)	
        self.jLabel.show()
	
        self.javaDir = gtk.Entry()
        hbox.pack_start(self.javaDir, True, True, 0)
        self.javaDir.show()

        self.chooseJava = gtk.Button(label=AR_CHOOSE)
        self.chooseJava.connect("clicked", self.chooseJavaDir)
        hbox.pack_start(self.chooseJava, False, False, 0)
	self.chooseJava.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

        label = gtk.Label(_('Show in list : '))
        vbox1.pack_start(label, False, False, 0)
	#label.set_justify(gtk.JUSTIFY_LEFT)
	label.set_alignment(0,0)
        label.show()

	self.showAll = gtk.CheckButton(AR_ALL)
        vbox1.pack_end(self.showAll, True, True, 0)
        self.showAll.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()
	
	self.showApps = gtk.CheckButton(_('Applications'))
        vbox1.pack_start(self.showApps, True, True, 0)
        self.showApps.show()

	self.showAt = gtk.CheckButton(_('AT-mode'))
        vbox1.pack_end(self.showAt, True, True, 0)
        self.showAt.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

	self.showCustom = gtk.CheckButton(_('Custom Made'))
        vbox1.pack_start(self.showCustom, True, True, 0)
        self.showCustom.show()

	self.showSrv = gtk.CheckButton(_('Server-mode'))
        vbox1.pack_end(self.showSrv, True, True, 0)
        self.showSrv.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

	self.showExamples = gtk.CheckButton(_('Examples'))
        vbox1.pack_start(self.showExamples, True, True, 0)
        self.showExamples.show()
	
	self.showBm = gtk.CheckButton(_('Bemused-emulation'))
        vbox1.pack_end(self.showBm, True, True, 0)
        self.showBm.show()
	
	self.showAll.set_active(self.showAll_)
	self.setFilters()
	
	if not self.showAll_:
	    self.showApps.set_active(self.showApps_)
	    self.showCustom.set_active(self.showCustom_)
	    self.showExamples.set_active(self.showExamples_)
	    self.showAt.set_active(self.showAt_)
	    self.showSrv.set_active(self.showSrv_)
	    self.showBm.set_active(self.showBm_)
	
	self.showAll.connect     ('toggled', self.showAllAction)
	self.showApps.connect    ('toggled', self.filterChangedAction)
	self.showCustom.connect  ('toggled', self.filterChangedAction)
	self.showExamples.connect('toggled', self.filterChangedAction)
	self.showAt.connect      ('toggled', self.filterChangedAction)
	self.showSrv.connect     ('toggled', self.filterChangedAction)
	self.showBm.connect      ('toggled', self.filterChangedAction)
    
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        self.updLabel = gtk.Label(_('Update application list every'))
        hbox.pack_start(self.updLabel, True, True, 0)	
        self.updLabel.show()

        self.updateTmout = gtk.Entry()
        self.updateTmout.set_max_length(6)
	self.updateTmout.set_width_chars(2)
        hbox.pack_start(self.updateTmout, True, True, 0)
	self.updateTmout.connect('changed', self.tmoutChangedAction)
        self.updateTmout.show()
	tt = gtk.Tooltips()
	tt.set_tip(self.updateTmout,_('Empty field means no update'))
	
	tm = ''
	if self.updateTmout_ > 0:
	    tm = "%s" % (self.updateTmout_)
	self.updateTmout.set_text(tm)
	
        label = gtk.Label(_('sec.'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)
        separator.show()

        label = gtk.Label(_('Auto startup with'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
	self.autorunGnome = gtk.CheckButton(_('Gnome session'))
        hbox.pack_start(self.autorunGnome, True, True, 0)
	self.autorunGnome.set_active(os.path.exists(os.environ.get("HOME")+os.sep+'.config'+os.sep+'autostart'+os.sep+'ganyremote.desktop'))
        self.autorunGnome.show()
	
	self.autorunKDE = gtk.CheckButton(_('KDE session'))
        hbox.pack_start(self.autorunKDE, True, True, 0)
	self.autorunKDE.set_active(os.path.exists(os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'ganyremote'))
        self.autorunKDE.show()

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()
	
        label = gtk.Label(_('Override \"Device=\" parameter with : '))
        hbox.pack_start(label, 0, True, 0)
        label.show()
	
        self.device = gtk.Entry()
        self.device.set_max_length(512)
        hbox.pack_start(self.device, True, True, 0)
	self.device.connect('changed', self.deviceChangedAction)
        self.device.show()
	
        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)
        separator.show()
 
 	self.autoReconn = gtk.CheckButton(_('Auto reconnect in AT mode'))
        hbox.pack_start(self.autoReconn, True, True, 0)
	self.autoReconn.set_active(self.autoReconn_)
        self.autoReconn.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()

	self.runWeb = gtk.CheckButton(_('Run web interface'))
        hbox.pack_start(self.runWeb, 0, True, 0)
	self.runWeb.set_active(self.runWeb_)
        self.runWeb.connect('toggled', self.webToggledAction)
        self.runWeb.show()
       
        self.webLabel = gtk.Label(_(' with parameters '))
        hbox.pack_start(self.webLabel, 0, True, 0)
        self.webLabel.show()

        self.webParams1 = gtk.Entry()
        self.webParams1.set_max_length(64)
        hbox.pack_start(self.webParams1, True, True, 0)
        self.webParams1.set_editable(False)
        self.webParams1.show()

        self.webParams = gtk.Entry()
        self.webParams.set_max_length(256)
        hbox.pack_start(self.webParams, True, True, 0)
        self.webParams.show()
	
	self.webParams.set_text(self.webParams_)
	self.device.set_text(self.device_)
	
	self.setWebParamsActive(self.runWeb_)
	
	self.runWeb.set_active(self.runWeb_ and self.device_.startswith('socket:'))

	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()

        self.brLabel = gtk.Label(_(' Run device browser with timeout : '))
        hbox.pack_start(self.brLabel, False, True, 0)
        self.brLabel.show()
	self.brLabel.set_sensitive((self.browseTmout_ > 0))
	
        self.browseTmout = gtk.Entry()
        self.browseTmout.set_max_length(5)
        self.browseTmout.set_width_chars(3)
        hbox.pack_start(self.browseTmout, False, True, 0)
	self.browseTmout.connect('changed', self.dbrowseChangedAction)
        self.browseTmout.show()
	tt = gtk.Tooltips()
	tt.set_tip(self.browseTmout,_('Empty field means no update. Beware: Java client could fail to connect to anyRemote when browsing is in process'))
	
	tm = ''
	if self.browseTmout_ > 0:
	    tm = "%s" % (self.browseTmout_)
	self.browseTmout.set_text(tm)

        label = gtk.Label('  ')
        hbox.pack_start(label, True, True, 0)
        label.show()

	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        btn = gtk.Button(label=AR_OK)
	addIconToButton(btn,gtk.STOCK_OK)
        btn.connect("clicked", self.okCloseCfg)
        hbox.pack_end(btn, False, False, 0)
	btn.show()
 
        btn = gtk.Button(label=AR_CANCEL)
	addIconToButton(btn,gtk.STOCK_CANCEL)
        btn.connect("clicked", self.closeCfg)
        hbox.pack_end(btn, False, False, 0)
	btn.show()
	
	for d in self.cfgDirs:
	    if d != '':
	        self.cfg_liststore.append([d])
	
	self.javaDir.set_text(self.javaDir_)  
	 
	self.config.show()
	
	self.showConfItem.set_sensitive(False)
	
    def dirOk(self, w):
    	newPath = self.ddialog.get_filename()
	self.ddialog.destroy()
	
	add = True
        
	treeiter = self.cfg_liststore.get_iter_first()
	while treeiter != None:
	    value = self.cfg_liststore.get_value(treeiter, 0)
	    if value == newPath:
	        add = False
		break
	    treeiter = self.cfg_liststore.iter_next(treeiter)
	
	if add:
	    self.cfg_liststore.append([newPath])
        
        
	self.btnAdd.set_sensitive(True)
	self.dirsChanged = True

    def dirCancel(self, w):
	self.ddialog.destroy()
	self.btnAdd.set_sensitive(True)

    def addToCfgDirList(self, w):
	self.ddialog = gtk.FileSelection(AR_SEL_DIR)
	#self.ddialog.set_filename(entry.get_text())
	self.ddialog.hide_fileop_buttons()
        self.ddialog.ok_button.connect("clicked", self.dirOk)
	self.ddialog.cancel_button.connect("clicked",self.dirCancel)
	self.ddialog.show()
	
	self.btnAdd.set_sensitive(False)

    def deleteFromCfgDirList(self, w):
	(model, titer) = self.cfg_treeview.get_selection().get_selected()
	if titer:
           treeiter = self.cfg_liststore.remove(titer)
	self.dirsChanged = True

    def dirJOk(self, w):
    	newPath = self.jdialog.get_filename()
	self.jdialog.destroy()
	self.javaDir.set_text(newPath)
	self.chooseJava.set_sensitive(True)

    def dirJCancel(self, w):
	self.jdialog.destroy()
	self.chooseJava.set_sensitive(True)

    def chooseJavaDir(self, w):
	self.jdialog = gtk.FileSelection(AR_SEL_DIR)
	self.jdialog.hide_fileop_buttons()
        self.jdialog.ok_button.connect("clicked", self.dirJOk)
	self.jdialog.cancel_button.connect("clicked",self.dirJCancel)
	self.jdialog.show()
	self.chooseJava.set_sensitive(False)

    def closeCfg(self, w):
	self.config.destroy()
	self.showConfItem.set_sensitive(True)

    def okCloseCfg(self, w):

	self.setAutoStartup("KDE",     self.autorunKDE.get_active())
	self.setAutoStartup("Gnome", self.autorunGnome.get_active())
	
	self.showApps_     = self.showApps.get_active()
	self.showCustom_   = self.showCustom.get_active()
	self.showExamples_ = self.showExamples.get_active()
	self.showAll_      = self.showAll.get_active()
	self.showAt_       = self.showAt.get_active()
	self.showSrv_      = self.showSrv.get_active()
	self.showBm_       = self.showBm.get_active()

	self.autoReconn_   = self.autoReconn.get_active()
	self.runWeb_       = self.runWeb.get_active()
	self.webParams_    = self.webParams.get_text().strip()
	self.device_       = self.device.get_text().strip()
	self.javaDir_      = self.javaDir.get_text().strip()
	
	tm = self.updateTmout.get_text().strip()
	if tm == '':
	    tm = '-1'
	if self.updateTmout_ != int(tm):
	    self.updateTmout_ = int(tm)
	    if self.updateTmout_ < 0:
	        self.updateTmout_ = -1
	    stopUpdater()
	    startUpdater(self.updateTmout_)
	
	tm = self.browseTmout.get_text().strip()
	if tm == '':
	    tm = '-1'
	if self.browseTmout_ != int(tm):
	    self.browseTmout_ = int(tm)
	    if self.browseTmout_ <= 0:
	        self.browseTmout_ = -1
	    stopBtComm()
	    startBtComm(self.browseTmout_, self.javaDir_)

        self.cfgDirs = []
        
	treeiter     = self.cfg_liststore.get_iter_first()
	while treeiter != None:
	    value = self.cfg_liststore.get_value(treeiter, 0)
	    self.cfgDirs.append(value)
	    treeiter = self.cfg_liststore.iter_next(treeiter)
	       
	proceed = True
	if self.cfgDirs == []:
	    
	    dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL,
	                              _('There is no item in the list !\ngAnyRemote will not be able to manage any software !'))
	    ret = dialog.run()
	    if ret == gtk.RESPONSE_CANCEL:
	        proceed = False
		
	    dialog.destroy()

	if proceed:
	    self.saveConfig() 
	    self.config.destroy()
	
	    self.showConfItem.set_sensitive(True)
	
	    if self.dirsChanged == True:
	        self.populateCfgFiles()
	        self.dirsChanged = False
	    
    def dbrowseChangedAction(self, editable):  
	self.browseTmout_ = self.browseTmout.get_text().strip()
	if self.browseTmout_ == '':
	     self.brLabel.set_sensitive(False)
	else:     
	     self.brLabel.set_sensitive((self.browseTmout_ > 0))

    def tmoutChangedAction(self, editable):  
	self.updateTmout_ = self.updateTmout.get_text().strip()
	if self.updateTmout_ == '':
	     self.updLabel.set_sensitive(False)
	else:     
	     self.updLabel.set_sensitive((self.updateTmout_ > 0))
	    
    def deviceChangedAction(self, editable):
	self.device_ = self.device.get_text().strip()
	self.setWebParamsActiveReset()
	
    def webToggledAction(self, w):
        active = self.runWeb.get_active()
	if active:
	    isInst = isInstalled('anyremote2html')
	    if isInst == 'NOK':
	    	dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
                     _('anyremote2html is not installed !'))
	        dialog.run()
	        dialog.destroy()
	    else:
		if self.device.get_text().startswith('socket:'):
		    self.webParams1.set_text(' -a '+self.device.get_text()[7:])
		else:
	            self.device.set_text('socket:5000')
	            self.webParams1.set_text(' -a 5000')
	            self.webParams.set_text(' -w 5550')
		    
	self.webParams1.set_sensitive(active)
	self.webParams.set_sensitive(active)
	self.webLabel.set_sensitive(active)

    def filterChangedAction(self, w):
    	self.dirsChanged = True

    def showAllAction(self, w):
    	self.dirsChanged = True
	self.setFilters()
	
    def setFilters(self):
	if self.showAll.get_active():
    	    self.showApps.set_active(False)
    	    self.showCustom.set_active(False)
    	    self.showExamples.set_active(False)
    	    self.showAt.set_active(False)
    	    self.showSrv.set_active(False)
    	    self.showBm.set_active(False)
	    
    	    self.showApps.set_sensitive(False)
    	    self.showCustom.set_sensitive(False)
    	    self.showExamples.set_sensitive(False)
    	    self.showAt.set_sensitive(False)
    	    self.showSrv.set_sensitive(False)
    	    self.showBm.set_sensitive(False)
        else:
    	    self.showApps.set_sensitive(True)
    	    self.showCustom.set_sensitive(True)
    	    self.showExamples.set_sensitive(True)
    	    self.showAt.set_sensitive(True)
    	    self.showSrv.set_sensitive(True)
    	    self.showBm.set_sensitive(True)
	
    def setWebParamsActiveReset(self):
	
	active = (self.runWeb.get_active() and self.device.get_text().startswith('socket:'))
	self.setWebParamsActive(active)
	
    def setWebParamsActive(self, active):
    
	self.webParams.set_sensitive(active)
	self.webLabel.set_sensitive(active)

	if active:
	    self.webParams1.set_text(' -a '+self.device.get_text()[7:])
	else:
            self.webParams1.set_text('')
	    
    ##################################################################################
    #
    # Status related function
    #
    ##################################################################################

    def setStatustext(self,text):
	self.sBar.pop(self.cid)
	self.sBar.push(self.cid,'  ' + text)
	
    def setStatusStopped(self):
    
        global debug
	if debug: print 'setStatusStopped'

    	self.runBtn.set_sensitive(True)
	self.runItem.set_sensitive(True)
	self.stopBtn.set_sensitive(False)
	self.stopItem.set_sensitive(False)

        self.setIcon(self.pixbufOff)
	self.setStatustext(AR_STOPPED)
	if self.tray != None: self.tray.set_tooltip(AR_STOPPED)

    def setStatusDisconnected(self):
    
        global debug
	if debug: print 'setStatusDisconnected'

    	self.runBtn.set_sensitive(False)
	self.runItem.set_sensitive(False)
	self.stopBtn.set_sensitive(True)
	self.stopItem.set_sensitive(True)

        self.setIcon(self.pixbufRun)
	self.setStatustext(AR_DISCONN)
	if self.tray != None: self.tray.set_tooltip(AR_DISCONN)

    def setStatusConnected(self):
    
        global debug
	if debug: print 'setStatusConnected'
	
        self.setIcon(self.pixbufOn)
	self.setStatustext(AR_CONNECT)
	if self.tray != None: self.tray.set_tooltip(AR_CONNECT)
	
    def translateMsg(self, data):
    
    	global debug
	if debug: print 'translateMsg  ' + data

	if data == '':

	   return
	   
	elif data == 'Exiting':
	
	   #gtk.gdk.threads_enter()
	   self.setStatusStopped()
	   #gtk.gdk.threads_leave()
	   return

	elif data == 'Connected':

	   #gtk.gdk.threads_enter()
	   self.setStatusConnected()
	   #gtk.gdk.threads_leave()
	   return

	elif data == 'Disconnected':

	   #gtk.gdk.threads_enter()
	   self.setStatusDisconnected()
	   #gtk.gdk.threads_leave()
	   return
	
	if data == '(Init)':

	   msg = 'anyRemote initialized'

	else:
	
	   # Just key press   
	   #return
    	   bTh = BlinkThread()
    	   bTh.start()
	   if debug:
	       msg = data
	   else:
	       return
	
	#gtk.gdk.threads_enter()   
	self.setStatustext(msg)
	#gtk.gdk.threads_leave()  
   		
    ##################################################################################
    #
    # Button and menu handlers
    #
    ##################################################################################

    def aboutAction(self, action):
    
        try:
            dialog = gtk.AboutDialog()
            dialog.set_name("gAnyRemote")
            dialog.set_copyright('Copyright 2007,2008 Mikhail Fedotov')
            dialog.set_website("http://anyremote.sf.net/")
            dialog.connect ("response", lambda d, r: d.destroy())
            dialog.show()
        except AttributeError:
    	    infoMessage("gAnyRemote\nCopyright 2007,2008 Mikhail Fedotov\nhttp://anyremote.sf.net/")


    def helpAction(self, action):

	# open web browser on docs page if found ?
	app = 'firefox'
	isInst = isInstalled(app)
	if isInst == 'NOK':
	    app = 'konqueror'
	    isInst = isInstalled(app)
	    
	    if isInst == 'NOK':
	        errorMessage(_('Can not find browser to show help !'))
		return
		
	docpath = ''
	if os.path.isdir('/usr/share/doc/anyremote/doc-html'):
	    docpath = '/usr/share/doc/anyremote/doc-html'
	elif os.path.isdir('/usr/local/share/doc/anyremote/doc-html'):
	    docpath = '/usr/local/share/doc/anyremote/doc-html'
	elif os.path.isdir('/usr/share/anyremote/doc-html'):
	    docpath = '/usr/share/anyremote/doc-html'
	elif os.path.isdir('/usr/local/share/anyremote/doc-html'):
	    docpath = '/usr/local/share/anyremote/doc-html'
	else:    
	    errorMessage('Can not find documentation !')
	    return
	
	cmd = app + ' ' + docpath + os.sep + 'g-shots.html &'
	os.system(cmd)
	    	
    def trayPressAction(self, *args):
        if self.window.get_property('visible'):
            self.window.hide()
        else:
	    self.window.show_all()

    def showWindowAction(self, *args):
        self.trayPressAction(*args)

    def quitAction(self, *args):
        self.quit()

    def resizeEvent(self, *args):
        (w,h)=self.window.get_size()
	try:
	    self.detailsRenderer.set_property('wrap-width', w-50)
	except AttributeError:
	    pass

    def rightClickAction(self, icon, event_button, event_time):
        menu = gtk.Menu()

        item = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
	item.connect('activate', self.aboutAction)
        menu.append(item)
	
	item = gtk.ImageMenuItem(gtk.STOCK_EXECUTE)
	item.connect('activate', self.runPressed)
        menu.append(item)

        item = gtk.ImageMenuItem(gtk.STOCK_STOP)
	item.connect('activate', self.stopPressed)
        menu.append(item)
	
	title = _('Restore')
        if self.window.get_property('visible'):
            title = _('Minimize')
        self.mainWinItem = gtk.MenuItem(title)
	self.mainWinItem.connect('activate', self.showWindowAction)
        menu.append(self.mainWinItem)

        item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
	item.connect('activate', self.quitAction)
        menu.append(item)
	menu.show_all()

        menu.popup(None, None,
            gtk.status_icon_position_menu, event_button,
            event_time, icon)
	
    def runPressed(self, widget):
	global port, debug
	
	# to store last used cfg.file
        entry_text = self.entry.get_text()
	self.saveConfig()
	
	gtk.gdk.threads_enter()
	gui.setStatusDisconnected()
	gtk.gdk.threads_leave()
	
	startAnyRemote(self.entry.get_text(),self.runWeb_)	

    def stopPressed(self, widget):
	global debug
	
	if debug: print 'Stop anyRemote'
	
	# To avoid socket.error: (98, 'Address already in use') 
	# it needs to close client socket first
    	killAnyRemote()
			
	self.setStatusStopped()

    def rescanPressed(self, widget):
	self.populateCfgFiles()

    def openEditor(self, widget):
        if self.lastCfgFile:
	    e = cfgEditor(self.lastCfgFile)
	
    def execCmd(self, w):
    	global cmdToSend
        print 'Add to queue ' + self.cmd.get_text()
        cmdToSend = self.cmd.get_text() 
	
	
    ##################################################################################
    #
    # Wizard window
    #
    ##################################################################################
    
    def showWizard(self):
	dialog = gtk.MessageDialog(None,
		     gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
                     _('This is the first time gAnyRemote runs.\nPlease specify directories with anyRemote configuration files.'))
	dialog.run()
	dialog.destroy()
	self.showConfDialog()
   
    ##################################################################################
    #
    # Main window creation
    #
    ##################################################################################

    def createMenus(self, vbox):
        global usepybluez
	
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        try:
	    stock_edit = gtk.STOCK_EDIT
            menuitem = gtk.ImageMenuItem(stock_edit)
        except AttributeError:
    	    menuitem = iconMenuItem(_('Edit'), gtk.STOCK_JUSTIFY_LEFT)

        menu.add(menuitem)
	menuitem.connect('activate', self.openEditor)
        
        self.runItem = iconMenuItem(_('Start'), gtk.STOCK_EXECUTE)
	
	menu.add(self.runItem)
	self.runItem.connect('activate', self.runPressed)

        self.stopItem = gtk.ImageMenuItem(gtk.STOCK_STOP)
        menu.add(self.stopItem)
	self.stopItem.connect('activate', self.stopPressed)

        if self.tray != None:
	    menuitem = iconMenuItem(_('Close Window'), gtk.STOCK_CLOSE)
	    menu.add(menuitem)
	    menuitem.connect('activate', self.hideWindow)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        menu.add(menuitem)
	menuitem.connect('activate', self.quitAction)

        topmenuitem = gtk.MenuItem(_('Setup'))
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        self.dbrowserItem = iconMenuItem(_('Device Browser'), gtk.STOCK_FIND)
        menu.add(self.dbrowserItem)
	self.dbrowserItem.connect('activate', self.showBrowser)
	if not usepybluez:
	    self.dbrowserItem.set_sensitive(False)
        self.dbrowserItem.show()
       
       
        self.showConfItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
        menu.add(self.showConfItem)
	self.showConfItem.connect('activate', self.showConfAction)
	
        self.chkCfg = iconMenuItem(_('Check configuration'),gtk.STOCK_PROPERTIES)
        menu.add(self.chkCfg)
	self.chkCfg.connect('activate', self.showChkCfg)
        self.chkCfg.show()
	
        menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE)
        menu.add(menuitem)
	menuitem.connect('activate', self.saveConfigAction)
	
        topmenuitem = gtk.MenuItem(_('Help'))
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        try:
	    stock_about = gtk.STOCK_ABOUT
            menuitem = gtk.ImageMenuItem(stock_about)
        except AttributeError:
   	    menuitem = iconMenuItem(_('About'),gtk.STOCK_DIALOG_INFO)
            
        menu.add(menuitem)
	menuitem.connect('activate', self.aboutAction)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_HELP)
        menu.add(menuitem)
	menuitem.connect('activate', self.helpAction)

    def initWindow(self):
    
        global debug, guiMode, liststore
    
        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("gAnyRemote")
        
	if self.tray:
	    self.window.connect("delete_event", self.hideWindow2)
	else:
	    self.window.connect("destroy", self.quitAction)
	
	self.window.connect("size-allocate", self.resizeEvent)
	
        vbox = gtk.VBox(False, 0)
        self.window.add(vbox)
        vbox.show()
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()

        self.treeview  = gtk.TreeView() 
       
        self.column_app    = gtk.TreeViewColumn(AR_APP)
        self.column_status = gtk.TreeViewColumn(AR_STATUS)
        self.column_mode   = gtk.TreeViewColumn(AR_MODE)
        self.column_type   = gtk.TreeViewColumn(_('Type'))
        
	self.column_app.set_resizable(True)
	self.column_status.set_resizable(True)
	self.column_mode.set_resizable(True) 
	self.column_type.set_resizable(True)  

	self.column_app.set_expand(True)
	
	self.column_app.set_spacing(5)
	self.column_status.set_spacing(5)
	self.column_mode.set_spacing(5)
	self.column_app.set_spacing(5)
	
	#self.column_app.set_min_width(200)
  
	self.treeview.append_column(self.column_app)
        self.treeview.append_column(self.column_status)
        self.treeview.append_column(self.column_mode)
        self.treeview.append_column(self.column_type)

        self.cell0 = gtk.CellRendererPixbuf()
        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()
        self.cell3 = gtk.CellRendererText()
        self.cell4 = gtk.CellRendererText()

        self.column_app.pack_start   (self.cell0, False)
        self.column_app.pack_start   (self.cell1, True)
        self.column_status.pack_start(self.cell2, False)
        self.column_mode.pack_start  (self.cell3, False)
        self.column_type.pack_end    (self.cell4, False)
	
        self.column_app.set_attributes   (self.cell0, pixbuf=1)
        self.column_app.set_attributes   (self.cell1, text=0)
        self.column_status.set_attributes(self.cell2, text=5)
        self.column_mode.set_attributes  (self.cell3, text=6)
        self.column_type.set_attributes  (self.cell4, text=7)

        self.treeview.set_search_column(0)
        #self.treeview.set_fixed_height_mode(1)

        self.column_app.set_sort_column_id(0)
	
	liststore.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	self.treeview.connect("cursor_changed", self.rowSelectAction)
	
	self.treeview.show()
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
	if guiMode == 'expert':
            vbox.add(hbox)
	    vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
            hbox.show()
	    
        self.entry = gtk.Entry()
        self.entry.set_max_length(512)
	
	if guiMode == 'expert':
            hbox.pack_start(self.entry, True, True, 0)
            self.entry.show()

	if guiMode == 'expert':
            b = gtk.Button(label=AR_CHOOSE)
            b.connect("clicked", self.openFDialog, self.entry)
            hbox.pack_end(b, False, False, 0)
		
	################
	if debug:
            hbox = gtk.HBox(False, 0)
            vbox.add(hbox)
	    vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
            self.cmd = gtk.Entry()
            self.cmd.connect('key-press-event', self.commandRun)
            self.cmd.set_max_length(512)
            hbox.pack_start(self.cmd, True, True, 0)
 
            bExec = gtk.Button(label=_('Execute Command'))
            bExec.connect("clicked", self.execCmd)
            hbox.pack_end(bExec, False, False, 0)
  
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.detailsStore = gtk.TreeStore(str)
	self.detailsHead = self.detailsStore.append(None,[_('Details')])
	self.detailsData = self.detailsStore.append(self.detailsHead,[''])
         
        self.detailsTreeview  = gtk.TreeView(self.detailsStore)
        
        self.detailsRenderer = gtk.CellRendererText()
        self.detailsRenderer.set_property('cell-background-gdk', self.window.get_style().bg[gtk.STATE_NORMAL])
        try:
	    self.detailsRenderer.set_property('wrap-mode', gtk.WRAP_WORD)
	except AttributeError:
	    pass
	        
        self.detailsColumn = gtk.TreeViewColumn('')
        self.detailsColumn.pack_start(self.detailsRenderer, True)
        self.detailsColumn.set_attributes(self.detailsRenderer, text=0)
        self.detailsColumn.set_sort_column_id(0)
        
	self.detailsTreeview.append_column(self.detailsColumn) 
        self.detailsTreeview.set_headers_visible(False)
        self.detailsTreeview.set_enable_search(False)
        self.detailsTreeview.get_selection().set_mode(gtk.SELECTION_NONE)

        hbox.pack_start(self.detailsTreeview, True, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        btn = gtk.Button(label=_('Update Status'))
        addIconToButton(btn,gtk.STOCK_REFRESH)
        btn.connect("clicked", self.rescanPressed)
        hbox.pack_start(btn, True, True, 0)

        self.runBtn = gtk.Button(label=_('Start'))
        addIconToButton(self.runBtn,gtk.STOCK_EXECUTE)
        self.runBtn.connect("clicked", self.runPressed)
        hbox.pack_start(self.runBtn, True, True, 0)

        self.stopBtn = gtk.Button(label=_('Stop'))
        addIconToButton(self.stopBtn,gtk.STOCK_STOP)
        self.stopBtn.connect("clicked", self.stopPressed)
        hbox.pack_start(self.stopBtn, True, True, 0)
                                                             	
	self.sBar = gtk.Statusbar()
	vbox.add(self.sBar)
	vbox.set_child_packing(self.sBar, 0, 1, 0, gtk.PACK_END)
	self.cid = self.sBar.get_context_id('a')

	if debug:
	    h = 420
	else:
	    h = 390
	    
	self.window.set_size_request(500, h)
        
	try:
	    self.detailsRenderer.set_property('wrap-width', 450)
	except AttributeError:
	    pass
	    
	self.window.set_icon(findIcon('ganyremote.png'))
	
	if self.notInTray:
	     self.window.show_all()

    def commandRun(self, w, event):
        keyname = gtk.gdk.keyval_name(event.keyval)
        if keyname == 'KP_Enter' or keyname == 'Return':
            self.execCmd(self.cmd)
            return True
        return False

    def rowActivateAction(self, treeview, path, view_column):
	treeiter = liststore.get_iter(path)
	self.lastCfgFile = liststore.get_value(treeiter, 4)
	self.entry.set_text(self.lastCfgFile)
	self.useType = liststore.get_value(treeiter, 6)
	self.runPressed(self.runBtn)

    def rowSelectAction(self, treeview):
	selection = treeview.get_selection()
	(model, treeiter) = selection.get_selected()
	self.lastCfgFile = liststore.get_value(treeiter, 4)
	self.entry.set_text(self.lastCfgFile)
	self.useType = liststore.get_value(treeiter, 6)
        
        desc = liststore.get_value(treeiter, 8)
        self.detailsStore.set_value(self.detailsData, 0, desc.replace('\\n','\n'))

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

    def fileOk(self, w):
   	self.entry.set_text(self.fdialog.get_filename())
	self.fdialog.destroy()

    def openFDialog(self, w, entry):
	self.fdialog = gtk.FileSelection(_('File selection'))
	self.fdialog.set_filename(entry.get_text())
        self.fdialog.ok_button.connect("clicked", self.fileOk)
	self.fdialog.cancel_button.connect("clicked",lambda w: self.fdialog.destroy())
	self.fdialog.show()

    def hideWindow2(self,w,p):
        self.hideWindow(w)
	return True
	
    def hideWindow(self,w):
    	self.window.hide()
		    
    def quit(self):
        print 'Exiting...'
	
	stopBtComm()
	stopUpdater()
	stopFrontend();
	self.saveConfig()
	gtk.main_quit()

    def setIcon(self, pixbuf):
	self.curPixbuf = pixbuf
	if self.tray != None: self.tray.set_from_pixbuf(self.curPixbuf)

    def __init__(self, openW):
    
    	initVerify()
    
    	self.notInTray = openW
	self.useType   = ''
    
        try:
	    self.tray = gtk.StatusIcon()
            self.tray.connect('popup-menu', self.rightClickAction)
	    self.tray.connect('activate',   self.trayPressAction)
        except AttributeError:
    	    self.tray = None
            self.notInTray = True
	
        self.initWindow()
        
	self.pixbufOn    = findIcon('ganyremote.png')
	self.pixbufOff   = findIcon('ganyremote_off.png')
	self.pixbufFlash = findIcon('ganyremote_flash.png')
	self.pixbufRun   = findIcon('ganyremote_light.png')

	self.curPixbuf = self.pixbufOff
        if self.tray != None: self.tray.set_from_pixbuf(self.curPixbuf)
		
	gtk.window_set_default_icon(self.pixbufOn)
		
	self.setStatusStopped()
	
	self.setDefaultConfig()
	
	if os.path.exists(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyremote-fe.conf'):
	    self.readConfig()
	else:
	    set = 0
	    if os.path.exists('/usr/share/anyremote/cfg-data'):
	        set = 1
		self.cfgDirs.append('/usr/share/anyremote/cfg-data')
	    elif os.path.exists('/usr/local/share/anyremote/cfg-data'):
	        set = 1
		self.cfgDirs.append('/usr/local/share/anyremote/cfg-data/')

            self.javaDir_ = getJ2MEPath() 
		
	    if set == 0 or self.javaDir_ == '':
		self.showWizard()
	
	self.frontEnd = None
    	#self.populateCfgFiles()	

##################################################################################
#
# Utilities functions
#
##################################################################################

def iconMenuItem(title, stock):
    mItem = gtk.ImageMenuItem(title)
    im = gtk.Image()
    try:
	im.set_from_stock(stock, gtk.ICON_SIZE_MENU)
	mItem.set_image(im)
    except AttributeError:
	pass
    return mItem

def addIconToButton(button, stock):
 
    # on Mandriva 2008.1 it is disabled by default
    button.get_settings().set_long_property('gtk-button-images',1,'');
    try:
	im = gtk.Image()
	im.set_from_stock(stock, gtk.ICON_SIZE_BUTTON)
	button.set_image(im)
    except AttributeError:
	pass

def message(m,t):
    stopPBar()
    flag = 0
    if t == gtk.MESSAGE_ERROR:
        flag = gtk.DIALOG_MODAL
    dialog = gtk.MessageDialog(None,flag,t,gtk.BUTTONS_OK, m)
    dialog.run()
    dialog.destroy()

def errorMessage(m):
    message(m,gtk.MESSAGE_ERROR)

def infoMessage(m):
    message(m,gtk.MESSAGE_INFO)

def writePBar(txt):
    global pbar
    try:
        pbar.set_text(txt)
    except AttributeError, NameError:
        pass

def getJ2MEPath():
    path = ''
    if os.path.exists('/usr/share/anyremote-J2ME-client'):
        path = '/usr/share/anyremote-J2ME-client'
    elif os.path.exists('/usr/local/share/anyremote-J2ME-client'):
        path = '/usr/local/share/anyremote-J2ME-client'
    return path

def isInstalled(app):
    dirs = os.getenv('PATH').split(':')
    for d in dirs:
        if os.path.exists(d+'/'+app):
            return 'OK'
    return 'NOK'
	
def getResult(cmd, suffix):
    toFile = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'ganyremote-' + suffix + '.tmp'
    os.system(cmd + '> ' + toFile)
    line = getLineTmpFile(toFile)
    return line.replace('\n','')

def getLineTmpFile(toFile):
    fd = open(toFile,'r')
    ln = ''
    if fd:
    	ln=fd.readline()
    	fd.close()
    return ln
    
#####################################################################################    

def startUpdater(tmout):
    global statusUpdater
    if statusUpdater == None and tmout != -1:
    	statusUpdater = StatusUpdater(tmout)
    	statusUpdater.start()

def stopUpdater():
    global statusUpdater
    try:
    	statusUpdater.stop()
    	statusUpdater.join(2)
    except AttributeError, NameError:
        print 'Exception: statusUpdater.stop()'
    	pass
    statusUpdater = None
    
#####################################################################################    

def killAnyRemote():
    os.system('pkill -f "python .*anyremote2html"')
    os.system('killall -2 anyremote 2> /dev/null')


def startAnyRemote(cfg_file, webIface):
    global debug, gui
    
    killAnyRemote()
    
    time.sleep(0.5)

    web = ''
    if webIface:
    	web = ' -http'

    dev = ''
    if gui.device_ != '':
    	dev = ' -s '+gui.device_

    log = ''
    if debug:
    	log = ' -log'

    # TODO: add '-a' only for AT mode cfg.files
    rconn = ''
    if gui.autoReconn_ != '' and (gui.useType == 'AT' or gui.useType == ''):
        rcomm = ' -a '
    	    
    to_path = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep

    cmd = 'anyremote -fe ' + port + log + web + ' -f ' + cfg_file + dev + rconn + ' > '+ to_path + 'anyremote.stdout &'
    if debug: print cmd
    os.system(cmd)
    
    if webIface:
    	dd = ''
    	if debug: dd = '-d '

    	cmd = 'anyremote2html ' + dd + ' -a '+ gui.device_[7:] + ' ' + gui.webParams_ + ' > '+ to_path + 'anyremote2html.stdout &'
    	if debug: print cmd
    	os.system(cmd)

def stopPBar():
    global pbar
    try:
        pbar.stop()
    except AttributeError, NameError:
        pass

def browseDevices():
    global debug, cmd_array
    
    if ['scan',''] in cmd_array:
        if debug: print 'Skip device scan'
    else:
        gtk.gdk.threads_enter()
        queueBT('scan','')
        gtk.gdk.threads_leave()
    
    return True
    
def startBtComm(tmout, jDir):
    global bt, gui, usepybluez
    if usepybluez == True and bt == None: 
	bt = BtComm(jDir)
	bt.start()
	
	if tmout != '' and tmout > 0: 
            gui.timer = gobject.timeout_add (int(1000*tmout), browseDevices)

def stopBtComm():
    global debug, bt, gui
    
    try:
        gobject.source_remove(gui.timer)
    except AttributeError, NameError:
        if debug: print 'Exception: gobject.source_remove(gui.timer)'
        pass
	
    try:
    	bt.stop()
    	bt.join(2)
    except AttributeError, NameError:
        if debug: print 'Exception: bt.stop()'
    	pass
    bt = None

def startFrontend():
    global frontEnd

    frontEnd = FrontEnd()
    frontEnd.start()

def stopFrontend():
    global frontEnd, debug

    # To avoid socket.error: (98, 'Address already in use') 
    # it needs to close client socket first
    
    killAnyRemote()

    time.sleep(0.5)

    try:
    	frontEnd.stop()
    except AttributeError, NameError:
        if debug: print 'Exception: frontEnd.stop()'
    	pass
    frontEnd = None

def showBrowserWin():
    global browserWin, debug
    try:
        if debug: print 'browserWin',browserWin.isShown
	if browserWin.isShown:
	    return
    except AttributeError, NameError:
	pass
    browserWin = DeviceBrowser()

def showChkCfgWin(javaDir):
    global chkCfgWin, debug
    try:
        if debug: print 'chkCfgWin',chkCfgWin.isShown
	if chkCfgWin.isShown:
	    return
    except AttributeError, NameError:
	pass
    chkCfgWin = CfgChecker(javaDir)

def showDetailsWin(v1,v2,v3,v4,v5):
    global dwin, gui
    try:
	if dwin.isShown: 
	    return
    except AttributeError, NameError:
	pass
    dwin = DeviceDetail(v1, v2, v3, v4, v5, gui.javaDir_)

def getAvailableSet():

    global bt_devices

    gtk.gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    gtk.gdk.threads_leave()

    s = []
    while treeiter != None:
    	gtk.gdk.threads_enter()
    	addr = bt_devices.get_value(treeiter, 0)
    	st   = bt_devices.get_value(treeiter, 4)
    	gtk.gdk.threads_leave()
    	
    	if st == AR_AVAIL:
	    s.append(addr)
    	
    	gtk.gdk.threads_enter()
    	treeiter = bt_devices.iter_next(treeiter)
    	gtk.gdk.threads_leave()
    
    return Set(s)

def getDevSet():

    global bt_devices

    gtk.gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    gtk.gdk.threads_leave()

    s = []
    while treeiter != None:
    	gtk.gdk.threads_enter()
    	addr = bt_devices.get_value(treeiter, 0)
    	s.append(addr)
    	treeiter = bt_devices.iter_next(treeiter)
    	gtk.gdk.threads_leave()
    
    return s

def queueBT(tag,address):
    global debug

    if debug: print 'queueBT',cmd_array
    i = len(cmd_array)-1
    if i > 0 and cmd_array[i] == ['scan','']:
        cmd_array.insert(i,[tag,address])
    else:
        cmd_array.append([tag,address]) 
   
#####################################################################################    

def findIcon(name):
    global icon_theme, debug
    
    iName = name.split('.',1)
    
    try:
	a = icon_theme
    except NameError:    
        icon_theme = gtk.icon_theme_get_default()
	icon_theme.append_search_path('/opt/kde3/share/icons') 
	icon_theme.append_search_path('/opt/gnome/share/pixmaps') 
	icon_theme.append_search_path('/opt/gnome/share/icons') 
	
	if debug:
            print 'findIcon path',icon_theme.get_search_path()
		
    try:
        pixbuf = icon_theme.load_icon(iName[0], 16, 0)
    except gobject.GError, exc:
        try:
	   if debug: print 'Can not find',iName,'Use default.'
	       
           pixbuf = icon_theme.load_icon("fileopen", 16, 0)
        except gobject.GError, exc:
	   # Try it hard
	   if debug: print 'Can not find default icon.'
	   icon_file = getResult('find /usr/share/icons /usr/share/pixmaps /usr/share/app-install/icons/ /usr/local/share/pixmaps /opt/kde3/share/icons /opt/gnome/share/pixmaps /opt/gnome/share/icons . -name fileopen.png 2>/dev/null','main')
	   
	   if icon_file != '':
	      icon_theme.append_search_path(os.path.dirname(icon_file))
	      try:
	          pixbuf = icon_theme.load_icon(iName[0], 16, 0)
              except gobject.GError, exc:
	          pixbuf = None
	   else:
	       pixbuf = None
    
    return pixbuf

def btVerify(showmsg):
    hcid = getResult('echo \'A=`ps -ef|grep hcid|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
    if showmsg and hcid == 'NOK':
        infoMessage(_('Bluetooth service is not active'))
    return hcid

def initVerify():

    tool = isInstalled('anyremote')
    if tool == 'NOK':
        errorMessage(_('anyRemote not found !\nPlease install it or correct $PATH'))

    tool = isInstalled('sdptool')
    if tool == 'NOK':
        errorMessage(_('sdptool not found !\nPlease install bluez-util'))
	
    z = btVerify(True)

def usage():
    print 'ganyremote [-h|--help] [-p|--port <port>] [-d|--debug] [-o|--open] [-e] [-n|--npybluez]'
    
##################################################################################
#
# Main function
#
##################################################################################

def main():

    global gui, debug, guiMode, port, cmdToSend, icons, runUpdater, liststore, bt_devices, bt, pbar, cmd_array, dwin, browserWin, chkCfgWin, statusUpdater, frontEnd, usepybluez
    
    try:
        opts, args = getopt.getopt(sys.argv[1:], "dnehop:", ["debug", "expert", "help", "open", "npybluez", "port="])
    except getopt.GetoptError:
    	usage()
        sys.exit(2)
	
    browserWin = None
    chkCfgWin  = None
    bt         = None
    cmd_array  = []
    cmdToSend  = ''
    debug      = False
    dwin       = None
    guiMode    = 'simple'
    frontEnd   = None
    icons      = dict()
    openWin    = False
    pbar       = None
    port       = '5050'
    runUpdater = False
    statusUpdater = None
    usepybluez = True
    
    for o, a in opts:
        if o in ("-d", "--debug"):
            debug   = True
            guiMode = 'expert'
        if o in ("-e", "--expert"):
            guiMode = 'expert'
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-p", "--port"):
            port = a
        if o in ("-o", "--open"):
            openWin = True
        if o in ("-n", "--npybluez"):
            usepybluez = False

    if pybluez == False and usepybluez == True:
        print _('Install PyBluez first !\nOr run with --npybluez option')
	return

    confdir = os.environ.get("HOME")+os.sep+'.anyRemote'
    if not os.path.isdir(confdir):
        os.mkdir(confdir)
    
    liststore  = gtk.ListStore(str, gtk.gdk.Pixbuf, str, str, str, str, str, str, str)
    bt_devices = gtk.ListStore(str,str,str,str,str)

    gobject.threads_init()
    
    gui = gAnyRemote(openWin)
    gui.populateCfgFiles()
    
    if debug: 
        print 'Use translation from ',local_path
        print 'Starting backgroung threads'
	
    startUpdater(gui.updateTmout_)
    startBtComm(gui.browseTmout_, gui.javaDir_)
    startFrontend()

    gtk.main()
    
    return 0

if __name__ == "__main__":
    main()
