#!/usr/bin/env python

"""
v 6.3.1

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

Copyright (C) 2007-2013 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 glob
import gobject
import os
import re
import pango
import pygtk
import signal
import socket
import sys
import threading
import thread
import time
import httplib
import Queue
import datetime

try:
    import appindicator
except ImportError:
    print 'Warning: No support for AppIndicator'

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 !!!'
   sys.exit()

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(":")

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.ugettext

#
# 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_DEV_BROWSER = _("Device Browser")

AR_STOPPED  = _('anyRemote stopped')
AR_DISCONN  = _('Ready to connect on')
AR_CONNECT  = _('Connected')
AR_DOWNLOADING = _('Downloading')
AR_J2ME_CHECK  = _('Checking J2ME client updates')
AR_NO_J2ME_UPD = _('No updates for J2ME client were found.')

AR_TCP_PORT=_('TCP port')
AR_BT_PORT=_('Bluetooth channel')
AR_HTTP_PORT=_('HTTP port')

AR_CODE_J2ME_UPD = 'UPDATE_AVAIL'
AR_CODE_LOADED   = 'LOADED'

AR_FILE_DEVICES='anyremote-peers.conf'

try:
   import gtk
except ImportError:
   print _('Install PyGTK first !!!')
   sys.exit()

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

###############################################################################
#
# J2ME client uploader
# unified
#
###############################################################################
class JCUploader(threading.Thread):

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

    def run(self):
        global debug,jup
        
        if debug: print 'JCUploader starting'
    
        self.run = True
        
        stopPBar()
        startPBar(AR_DOWNLOADING+' anyRemote-16.jad')
         
        ret = True
        
        jars = ["-16","-32","-48","-64","-128","","-nojsr82"]
        
        for sz in jars:
        
            for bi in ["", "b"]:
                
                # no big icons for these variants
                if bi == "b" and (sz == "" or sz == "-nojsr82"):
                    continue
                
                if self.run and ret:
                    ret = uploadJ2MEWebGui('anyRemote'+sz+bi+'.jad', True)

                if self.run and ret: 
                    ret = uploadJ2MEWebGui('anyRemote'+sz+bi+'.jar')
    
        if self.run: stopPBar()
        
        if debug: print 'JCUploader: upload done'
        
        jup = None

    def stop(self):
        global debug
        if debug: print 'stop JCUploader'
        
        self.run = False

def stopJCUploader():
    global jup
    try:
        if jup != None:
            jup.stop()
    except NameError:
        pass

##################################################################################
#
# J2ME client verifier
# unified
#
##################################################################################
class JCVerifier(threading.Thread):

    def __init__(self, force):
        threading.Thread.__init__(self) 
        self.anyway = force

    def run(self):
        global debug
        
        if debug: print 'JCVerifier starting'
        
        curdate = time.strftime("%d%m", time.gmtime())
        
        if self.anyway:
            startPBar(AR_J2ME_CHECK)
        else:
            try:
                f = open(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'j2me-client.checked', 'r')
                date = f.read() 
                f.close()        
                date = date.replace('\n','')
                    
                if debug: print 'JCVerifier',date,curdate
            
                if date == curdate:
                    if debug: print 'JCVerifier: already checked. Exiting'
                    self = None
                    return

            except IOError:
                pass
            
        if debug: print 'JCVerifier: check new version'

        os.system('echo \"'+curdate+'\" > $HOME/.anyRemote/j2me-client.checked')
        newver = checkJ2MEClientUpdate();
        
        if debug: print 'JCVerifier: upload done '+newver
        
        if self.anyway:    
            stopPBar()
        
        if newver == "":
            if self.anyway:
                infoMessage(AR_NO_J2ME_UPD)
        # newver == "-1" in case of connection absense
        elif newver != "-1": 
            codeMessage(AR_CODE_J2ME_UPD)
        
        self = None

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

    def __init__(self):
        global cfgFileReaderFlag
        
        threading.Thread.__init__(self) 
        
        cfgFileReaderFlag = True

    def run(self):
        global debug, cfgFileReaderFlag, cfgReader

        if debug: print 'CfgFileReader.run'
        
        clearAppsList()
        
        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]+$")
        
        t1 = datetime.datetime.now()
        
        numProcessed = 0
        for cfgDir in cfgReader.cfgDirs:
              
            if cfgDir == '':
                continue
            if debug: print 'Collect files in '+cfgDir
            
            if os.path.isfile(cfgDir):
                self.processOneFile(cfgDir)
                
                numProcessed = numProcessed+1
                codeMessage2(AR_CODE_LOADED, numProcessed)
                
            else:
                for root, dirs, files in os.walk(cfgDir):
                    
                     
                    if 'Utils' in dirs:
                       dirs.remove('Utils')
                       if debug: print 'skip dir',root+os.sep+'Utils'
                    if 'Icons' in dirs:
                       dirs.remove('Icons')
                       if debug: print 'skip dir',root+os.sep+'Icons'
                    if '.svn' in dirs:
                       dirs.remove('.svn')
                       if debug: print 'skip dir',root+os.sep+'.svn'
                    
                    for cfgFile in files:

                        nameext = cfgFile.split('.')
                        ext = nameext[len(nameext)-1]

                        if ext == 'png' or ext == 'sh' or ext == 'py' or ext == 'gz':
                            if debug: print 'Not a configuration file '+cfgFile
                            continue

                        self.processOneFile(root + os.sep + cfgFile)

                        numProcessed = numProcessed+1
                        codeMessage2(AR_CODE_LOADED, numProcessed)
        
        codeMessage2(AR_CODE_LOADED, -1)
        
        cfgFileReaderFlag = False
        
        t2 = datetime.datetime.now()
        #print "Load time ",(t2-t1)
            
    def processOneFile(self,cfgFile):
        global debug, cfgReader
        
        fd = None
        try:
            fd = open(cfgFile,'r')
        except IOError:
            pass
         
        if fd:
            aName    = None
            aInst    = ''
            aRun     = ''
            aIcon    = ''
            aType    = None
            aDesc    = ''
            aVers    = ''
            aModes   = ''
            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)

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

                    # deprecated, use GuiAppProtocols        
                    p = re.search("^[^a-zA-Z0-9]*GuiAppModes[^=]*=(.+)$", line)
                    if p != None:
                        aModes = p.group(1)

                    p = re.search("^[^a-zA-Z0-9]*GuiAppProtocols[^=]*=(.+)$", line)
                    if p != None:
                        aModes = 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 aModes == '': 
                if aBemused == 1:
                    aMode = ['Bemused']
                elif aDevice == 'a':
                    aMode = ['AT']
            else:
                aMode = [] 
                # not use aModes.split(',') to make more strict control
                if aModes.find('Server') >= 0:
                    aMode.append('Server')

                if aModes.find('Bemused') >= 0:
                    aMode.append('Bemused')
                
                if aModes.find('AT') >= 0:
                    aMode.append('AT')
                
                if aModes.find('iViewer') >= 0:
                    aMode.append('iViewer')
                    
            if aName == '' or aName == None:
                    aName = os.path.basename(cfgFile)
                    
            app = aInst
            isInst = 'OK'
            if aInst != '':
                cnt = aInst.count(' ')
                
                if cnt > 0: # treat this like a command to execute
                    app = getResult(aInst, 'bin')
                
                isInst = isInstalled(app)

            show  = 1
            show1 = 1
            show2 = 1
            status = AR_NOTAVAIL
            if isInst == 'OK':
                status = AR_AVAIL
                
                # check version if requested
                if aVers != '':
                    version = reqVersion(aVers)

                    if version == 'NOK':
                        isInst = 'NOK'
                        status = AR_NOTAVAIL
            
            if isInst == 'NOK' and not cfgReader.showNonavail_:
                show1 = 0
            elif isInst == AR_NOINFO:
                status = ''

            if 'Server' in aMode and not cfgReader.showSrv_:
                aMode.remove('Server')
            
            if 'AT' in aMode and not cfgReader.showAt_:
                aMode.remove('AT')
             
            if 'Bemused' in aMode and not cfgReader.showBm_:
                aMode.remove('Bemused')
        
            if 'iViewer' in aMode and not cfgReader.showIView_:
                aMode.remove('iViewer')
                    
            if len(aMode) > 0:
                show = 1
            else:
                show = 0

            if aType == 'Application' and not cfgReader.showApps_:
                show2 = 0
            elif aType == 'Custom' and not cfgReader.showCustom_:
                show2 = 0
            elif aType == 'Example' and not cfgReader.showExamples_:
                show2 = 0
            elif aType == '':
                show2 = 0
            
            if show == 1 and show1 == 1 and show2 == 1:
                if debug: print 'Proceed '+aName
                                    
                isRun = AR_NOINFO
                if aRun != '':
                    isRun  = getResult(aRun,'reader')
                
                if status == AR_AVAIL and isRun == 'OK':
                    status = AR_RUNNING
                 
                addAppToList(aName, aIcon, app, aRun, isRun, cfgFile, status, aMode, aType, aDesc)
                
                if debug: print 'Processed',cfgFile
            else:
                if debug: print 'Skip',cfgFile
                    
            fd.close()

###############################################################################        
#
# Configuration management
# unified
#
###############################################################################        

class ConfigReader:
    def saveConfig(self):
        
        cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
        if not os.path.exists(cfg):
            os.mkdir(cfg)
            
        f=open(cfg + os.sep + 'anyremote-fe.conf', 'w')
        if f:
            f.write('LastCfgFile='+self.lastCfgFile_+'\n')
            
            what = 'Show='
            if self.showApps_:
                what = what + 'Apps,'
            if self.showCustom_:
                what = what + 'Custom,'
            if self.showExamples_:
                what = what + 'Examples,'
            if self.showNonavail_:
                what = what + 'NonAvail,'
            if self.showAt_:
                what = what + 'AT,'
            if self.showSrv_:
                what = what + 'Server,'
            if self.showBm_:
                what = what + 'Bemused,'
            if self.showIView_:
                what = what + 'IViewer,'
            
            f.write(what+'\n')

            ac = '0'
            if self.autoReconn_:
                ac = '1'
            f.write('AutoReconnectAT='+ac+'\n')
            
            if self.dvSrvBT_ != '':
                f.write('DeviceServerBT='+self.dvSrvBT_+'\n')
            
            if self.dvSrvTCP_ != '':
                f.write('DeviceServerTCP='+self.dvSrvTCP_+'\n')
            
            if self.dvSrvWEB_ != '':
                f.write('DeviceServerWEB='+self.dvSrvWEB_+'\n')
            
            if self.dvSrvADV_ != '':
                f.write('DeviceServerManual='+self.dvSrvADV_+'\n')
             
            useTypes = 'DeviceUseType='
            if self.dvSrvUseADV_:
                useTypes = useTypes + 'ADV'
            else:
                if self.dvSrvUseBT_:
                    useTypes = useTypes + 'BT,'
                if self.dvSrvUseTCP_:
                    useTypes = useTypes + 'TCP,'
                if self.dvSrvUseWEB_:
                    useTypes = useTypes + 'WEB,'
            f.write(useTypes+'\n')

            if self.deviceAT_ != '':
                f.write('DeviceAT='+self.deviceAT_+'\n')

            if self.deviceBm_ != '':
                f.write('DeviceBemused='+self.deviceBm_+'\n')

            if self.deviceIV_ != '':
                f.write('DeviceIViewer='+self.deviceIV_+'\n')

            tm = "%s" % (self.updateTmout_)
            f.write('UpdateTimeout='+tm+'\n')
                
            if self.autoStart_ != '':
                f.write('AutoStartFile='+self.autoStart_+'\n')

            if self.doAutoStart_:
                f.write('AutoStart=true\n')
            else:
                f.write('AutoStart=false\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('J2MEDir='+self.j2meDir_+'\n')
            
            if self.checkJ2MEUpdate_:
                f.write('CheckJ2MEUpdate=true\n')
            
            f.close()
            
        saveDevices()

    def setDefaultConfig(self):

        self.lastCfgFile_  = ''
        self.cfgDirs       = []
        self.autoStart_    = ''
        self.doAutoStart_  = False
        self.j2meDir_      = ''
        self.checkJ2MEUpdate_ = False
        self.showApps_     = True
        self.showCustom_   = False
        self.showExamples_ = False
        self.showNonavail_ = False
        self.showAt_       = False
        self.showSrv_      = True
        self.showBm_       = False
        self.showIView_    = False
        self.autoReconn_   = False
        self.dvSrvBT_      = '19'
        self.dvSrvTCP_     = '5197'
        self.dvSrvWEB_     = '5080'
        self.dvSrvADV_     = '-log -s bluetooth:19'
        self.dvSrvUseBT_   = True
        self.dvSrvUseTCP_  = True
        self.dvSrvUseWEB_  = True
        self.dvSrvUseADV_  = False
        self.deviceAT_     = 'rfcomm:'
        self.deviceBm_     = ''
        self.deviceIV_     = 'socket:5197,web:5198'

        self.updateTmout_  = 60
        self.browseTmout_  = -1
        
    def readConfig(self):
        
        # 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','')
 
                    if line.startswith('LastCfgFile='):
                        self.lastCfgFile_=line[12:]
                    elif line.startswith('Show='):
                        #Show=Apps,Custom,Examples
                        what = line[5:].split(',')

                        # override defaults
                        self.showApps_ = False
                        self.showSrv_  = False
                        
                        for item in what:
                            if item == 'Apps':
                                self.showApps_ = True
                            elif item == 'Custom':
                                self.showCustom_ = True
                            elif item == 'Examples':
                                self.showExamples_ = True
                            elif item == 'NonAvail':
                                self.showNonavail_ = True
                            elif item == 'AT':
                                self.showAt_ = True
                            elif item == 'Server':
                                self.showSrv_ = True
                            elif item == 'Bemused':
                                self.showBm_ = True
                            elif item == 'IViewer':
                                self.showIView_ = True
                          
                            # compatibility with old versions
                            elif item == 'All':
                                self.showSrv_      = True
                                self.showApps_     = True
                                self.showCustom_   = True
                                self.showExamples_ = True
                                self.showNonavail_ = True
                              
                    elif line.startswith('AutoReconnectAT='):
                        self.autoReconn_ = (line == 'AutoReconnectAT=1')
                    elif line.startswith('AutoStart='):
                        useM = line[10:]
                        if useM == '1' or useM == 'true' or useM == 'True':
                            self.doAutoStart_ = True
                        else:
                            self.doAutoStart_ = False
                    elif line.startswith('AutoStartFile='):
                        self.autoStart_ = line[14:]
                    elif line.startswith('DeviceServerBT='):
                        self.dvSrvBT_ = line[15:]
                    elif line.startswith('DeviceServerTCP='):
                        self.dvSrvTCP_ = line[16:]
                    elif line.startswith('DeviceServerWEB='):
                        self.dvSrvWEB_ = line[16:]
                    elif line.startswith('DeviceServerManual='):
                        self.dvSrvADV_ = line[19:]
                    elif line.startswith('DeviceUseType='):
                        what = line[14:].split(',')
                        
                        for item in what:
                            if item == 'BT':
                                self.dvSrvUseBT_  = True
                                self.dvSrvUseADV_ = False
                            elif item == 'TCP':
                                self.dvSrvUseTCP_ = True
                                self.dvSrvUseADV_ = False
                            elif item == 'WEB':
                                self.dvSrvUseWEB_ = True
                                self.dvSrvUseADV_ = False
                            elif item == 'ADV':
                                self.dvSrvUseBT_  = False
                                self.dvSrvUseTCP_ = False
                                self.dvSrvUseWEB_ = False
                                self.dvSrvUseADV_ = True
                            
                    elif line.startswith('DeviceAT='):
                        self.deviceAT_ = line[9:]
                    elif line.startswith('DeviceBemused='):
                        self.deviceBm_ = line[14:]
                    elif line.startswith('DeviceIViewer='):
                        self.deviceIV_ = line[14:]
                    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('J2MEDir='):
                        self.j2meDir_=line[8:]
                    elif line.startswith('CheckJ2MEUpdate=true'):
                        self.checkJ2MEUpdate_=True
                        
                    # compatibility
                    elif line.startswith('JavaDir='):
                        self.j2meDir_=line[8:]
                    # compatibility
                    elif line.startswith('CheckJavaUpdate=true'):
                        self.checkJ2MEUpdate_=True

                f.close()
                
                # Try to search again
                if self.j2meDir_ == '':
                    self.j2meDir_ = getJ2MEPath()
                
        # device browser related part
        cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + AR_FILE_DEVICES
        
        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(',')
                        
                        # try to be backward compatible
                        if len(deviceData) < 5:
                            print 'Skip peer',deviceData[0],'because of wrong format'
                            continue

                        v1 = deviceData[0]
                        v2 = deviceData[1]
                        v3 = deviceData[2]
                        v4 = deviceData[3]
                        v5 = deviceData[4]
                        
                        addDevice(v1,v2,v3,v4,v5)
                f.close()
                
    def getConnectString(self):
        if self.dvSrvUseADV_:
            return self.dvSrvADV_
        else:
            connStr = ''

            if self.dvSrvUseTCP_ and self.dvSrvTCP_ != '':
                connStr = "socket:"+self.dvSrvTCP_
            
            sep = ''
            if connStr != '':
                sep = ','

            if self.dvSrvUseBT_ and self.dvSrvBT_ != '':
                connStr = connStr + sep + "bluetooth:"+self.dvSrvBT_

            if connStr != '':
                sep = ','
            
            if self.dvSrvUseWEB_ and self.dvSrvWEB_ != '':
                connStr = connStr + sep +  "web:"+self.dvSrvWEB_
        
            return connStr
	    
    def getConnectStatusString(self):
	
	    if cfgReader.showAt_:
                return '';
	    if cfgReader.showBm_:
                return '';
	    if cfgReader.showIView_:

	        temp = cfgReader.deviceIV_;
	        temp = temp.replace('web:',AR_HTTP_PORT+' ');
	        temp = temp.replace('socket:',AR_TCP_PORT+' ');
	        return temp;

            if self.dvSrvUseADV_:
                return ''
            else:
                connStr = ''

                if self.dvSrvUseTCP_ and self.dvSrvTCP_ != '':
        	    connStr = AR_TCP_PORT+' '+self.dvSrvTCP_

                sep = ''
                if connStr != '':
        	    sep = ', '

                if self.dvSrvUseBT_ and self.dvSrvBT_ != '':
        	    connStr = connStr + sep + AR_BT_PORT+' '+self.dvSrvBT_

                if connStr != '':
        	    sep = ', '

                if self.dvSrvUseWEB_ and self.dvSrvWEB_ != '':
        	    connStr = connStr + sep + AR_HTTP_PORT+' '+self.dvSrvWEB_

                return connStr
        
    def setAutoStartFile(self):

        for cfgDir in self.cfgDirs:
        
            if cfgDir == '':
                continue
        
            if os.path.isfile(cfgDir):
                if cfgDir.find('mediacenter.cfg') >= 0:
                    self.autoStart_ = root + os.sep + cfgFile
                    self.doAutoStart_ = True
                    return 
            else:
                for root, dirs, files in os.walk(cfgDir):
                    if 'Utils' in dirs:
                        dirs.remove('Utils')
                    if 'Icons' in dirs:
                        dirs.remove('Icons')
                    if '.svn' in dirs:
                        dirs.remove('.svn')
            
                    for cfgFile in files:
                        nameext = cfgFile.split('.')
                        ext = nameext[len(nameext)-1]
                        
                        if ext == 'png' or ext == 'sh' or ext == 'py' or ext == 'gz':
                            continue
                        
                        if cfgFile == 'mediacenter.cfg':
                            self.autoStart_ = root + os.sep + cfgFile
                            self.doAutoStart_ = True
                            return 

##################################################################################
#
# 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)
                    
                    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 = ''
                    
                    strIter = liststore.get_string_from_iter(treeiter)
                    
                    # PyGTK works non stable with threads_enter/threads_leave
                    #liststore.set_value(treeiter, 5, status)    
                    gtk.gdk.threads_leave()
                    
                    putToMainQueue(['UPDATE_LIST',strIter,status])
                
                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

##################################################################################
#
# 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, 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(cdata)
            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, 5):
                    bt_devices.set_value(treeiter,5,status)
                                     
                needRun = bt_devices.get_value(treeiter,4)  
                gtk.gdk.threads_leave()
                
                if status == AR_AVAIL and needRun != '':
                    if debug: 
                        print 'run anyRemote with',needRun
                    startAnyRemote(needRun)
                
                    return
            
                gtk.gdk.threads_enter()
                treeiter = bt_devices.iter_next(treeiter)
                gtk.gdk.threads_leave()

    def doScan(self,force):
        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)
            
            channels = ''
            
            services = bluetooth.find_service(address=addr)
            
            for svc in services:
                try:
                    if debug: print addr,svc["name"],svc["port"]
                
                    if svc["name"] == 'Serial Port' or svc["name"].startswith('COM ') or svc["name"].startswith('Dial-up') or svc["name"].startswith('Dialup'):
                        
                        if channels != '':
                            channels = channels+':'
                        channels = channels+str(svc["port"])
                    
                except AttributeError, NameError:
                        pass
        
            
            if addr not in existing:
                showDetailsWin(addr, name, name, channels, '', True)
            else:
                if addr in availSet:
                    availSet.remove(addr)
                else:
                    self.setStatus(addr,AR_AVAIL)
            
        for rest in availSet:
            self.setStatus(rest, '')
        
        if debug: print 'BtComm: verify done'
        
        if force == 'T':
            stopPBar()

    def doPing(self, data):
        global debug
        if debug: print 'BtComm: ping device'
        
        putToDevWQueue(['SET_STATUS',''])
        writePBar(AR_CONN_DEV)
        
        os.system('killall -9 hcitool 2> /dev/null')
        if debug: print 'hcitool name '+data
        ret = getResult('hcitool name '+data,'browser')
        
        stopPBar()
        if (ret == ''):
            putToDevWQueue(['SET_STATUS',_('Ping failed !')])
        else:
            putToDevWQueue(['SET_STATUS',_('Ping OK !')])

    def doPush(self, data, size, usejad):
        global debug
        if debug: print 'BtComm: obex push ',data,size,usejad
        
        putToDevWQueue(['SET_STATUS',''])
        stopPBar() 
	  
        dash = '-'
        if size == '':
            dash = ''
        midlet = 'anyRemote' + dash + size + '.jar'
	
        if not os.path.exists(self.midletDir):        
            putToDevWQueue(['SET_STATUS',_('Can not find J2ME midlet ('+midlet+_(') to upload !'))])
            return
        
        path = self.midletDir + os.sep + midlet
        if not os.path.isfile(path):
            putToDevWQueue(['SET_STATUS',_('Can not find J2ME midlet ('+midlet+_(') to upload !'))])
            return
        
        sender = ''    
        suffix = ' '    
        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'
        elif (isInstalled('bluedevil-sendfile') == 'OK'):
            sender = 'bluedevil-sendfile -u '
            suffix = ' -f '
        elif (isInstalled('blueman-sendto') == 'OK'):
            sender = 'blueman-sendto -d '
        else:
            putToDevWQueue(['SET_STATUS',_('None of bluedevil-sendfile, gnome-obex-send, bluetooth-sendto, blueman-sendto  and kbtobexclient are installed !')])
            return

        ret = getResult(sender + data + suffix + path + ' &','browser')
        
        if usejad:
            jad = 'anyRemote' + dash + size + '.jad'
            path = self.midletDir + os.sep + jad
            if not os.path.isfile(path):
                putToDevWQueue(['SET_STATUS',_('Can not find JAD file ('+jad+_(') to upload !'))])
                return
        
            ret = getResult(sender + data + suffix + 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:
            try:
                if svc["name"] == 'Serial Port' or svc["name"].startswith('COM ') or svc["name"].startswith('Dial-up') or svc["name"].startswith('Dialup'):
                    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
        if debug: print 'BtComm: doAT'
        
        putToDevWQueue(['SET_STATUS',''])
        writePBar(AR_CONN_DEV)        
        
        port = self.getSerialPort(data)
        if debug: print 'BtComm: port',port
        
        if port == None:
            putToDevWQueue(['SET_STATUS',_('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)
                if debug: print d
                
                stopPBar()
                if d.startswith('(111,'):
                    putToDevWQueue(['SET_STATUS',_('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)')
                
            putToDevWQueue(['SET_STATUS',status])
            sock.close()

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

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

class DeviceDetail(gtk.Window):

    def __init__(self, ba, m, n, channels, cfgFile, is_new, jDir):
        global debug 
        
        gtk.Window.__init__(self)
        
        self.model     = m.replace('\n','')
        self.dname     = n.replace('\n','')
        self.btAddress = ba
        self.cfile     = cfgFile
        self.isNew     = is_new
        self.channels  = channels
        self.midletDir = jDir
        
        self.initWindow() 

    def initWindow(self):
        global debug
        
        self.connect("destroy", self.close)
        
        capt = _('Device Parameters')
        if self.isNew:
            capt = _('New device')
            
        self.set_title(capt)
        
        vbox = gtk.VBox(False, 0)
        self.add(vbox)

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

        ################
        hbox = addHbox(vbox)
        
        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 = addHbox(vbox)
            
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

        ################
        hbox = addHbox(vbox)

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

        self.pname = gtk.Entry()
        self.pname.set_max_length(64)
        hbox.pack_start(self.pname, True, True, 0)
        self.pname.set_text(self.dname)
                
        ################
        hbox = addHbox(vbox)
        
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

        ################
        hbox = addHbox(vbox)

        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)
        
        # support PyGTK<2.12
        try:
            self.run_when.set_tooltip_text(_('anyRemote will start only if no other instances of anyRemote are running'))
        except AttributeError:
            pass
        
        ################
        hbox = addHbox(vbox)

        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 = addHbox(vbox)

        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)
                                                             
        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)

        vbox2 = gtk.VBox(False, 0)
        hbox.add(vbox2)

        hbox1 = gtk.HBox(False, 4)
        vbox1.add(hbox1)
        vbox1.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        hbox2 = gtk.HBox(False, 4)
        vbox2.add(hbox2)
        vbox2.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.btnUp = gtk.Button(label=_('Upload J2ME'))
        self.btnUp.connect("clicked", self.upload)
        hbox1.pack_start(self.btnUp, False, True, 0)
        
        label = gtk.Label(_(' with icon set '))
        hbox1.pack_start(label, 0, True, 0)
        
        dummy = gtk.Label('')
        vbox1.pack_start(dummy, 0, True, 0)

        self.sz16 = gtk.RadioButton(None,'16x16', False)
        self.sz16.set_active(True)
        hbox2.pack_start(self.sz16, 0, True, 0)
        self.sz32 = gtk.RadioButton(self.sz16,'32x32', False)
        hbox2.pack_start(self.sz32, 0, True, 0)
        self.sz48 = gtk.RadioButton(self.sz16,'48x48', False)
        hbox2.pack_start(self.sz48, 0, True, 0)
        self.sz64 = gtk.RadioButton(self.sz16,'64x64', False)
        hbox2.pack_start(self.sz64, 0, True, 0)
        self.sz128 = gtk.RadioButton(self.sz16,'128x128', False)
        hbox2.pack_start(self.sz128, 0, True, 0)
        
        self.szAll = gtk.RadioButton(self.sz16,_('with all icon sets'), False)
        vbox2.pack_start(self.szAll, 0, True, 0)

        self.sz32.set_active(True)
        self.szAll.connect("clicked", self.clicked_szAll)

        ################
        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)
        
        # support PyGTK<2.12
        try:
             self.uplJad.set_tooltip_text(_('Can be useful for Samsung phones'))
        except AttributeError:
            pass

        self.bigTitleIcon = gtk.CheckButton(_('use big title icon'), False)
        hbox.pack_start(self.bigTitleIcon, 0, True, 0)
        self.bigTitleIcon.connect("clicked", self.clicked_bti)

        # support PyGTK<2.12
        try:
             self.bigTitleIcon.set_tooltip_text(_('16x16 and 64x64 title icons are available'))
        except AttributeError:
            pass

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

        self.noJsr82 = gtk.CheckButton(_('use version without JSR-82'), False)
        hbox.pack_start(self.noJsr82, 0, True, 0)
        self.noJsr82.connect("clicked", self.clicked_nojsr82)

        # support PyGTK<2.12
        try:
            self.noJsr82.set_tooltip_text(_('Can be used on WinMobile devices'))
        except AttributeError:
            pass
        
        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.sz48.set_sensitive(False)
            self.sz64.set_sensitive(False)
            self.sz128.set_sensitive(False)
            
            # support PyGTK<2.12
            try:
                self.btnUp.set_tooltip_text(_('It needs to install anyremote-j2me-client package first'))
            except AttributeError:
                pass
        
        ################
        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()
        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)

            # support PyGTK<2.12
            try:
                self.btnPing.set_tooltip_text(_('Bluetooth service is not active'))
                self.btnAT.set_tooltip_text(_('Bluetooth service is not active'))
            except AttributeError:
                pass

        self.set_size_request(650,320)
        self.show_all()
        
        self.isShown = True
        
        self.ddQueueTimer = gobject.timeout_add(300, self.checkQueue)

    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.pname.get_text() != bt_devices.get_value(treeiter, 2):
                    bt_devices.set_value(treeiter,2,self.pname.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, 4):
                    bt_devices.set_value(treeiter,4,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.pname.get_text(),self.channels,self.cfgFile.get_text(),AR_AVAIL])
        gtk.gdk.threads_leave()
        
        self.close(w)

    def close(self,w):
        global debug
        self.isShown = False
        self.hide()
        try:
            gobject.source_remove(self.ddQueueTimer)
        except AttributeError, NameError:
            if debug: print 'Exception: gobject.source_remove(gui.ddQueueTimer)'

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

    def setupFile(self, name):
        self.cfgFile.set_text(name)
        self.cfgFile.set_sensitive(True)
        self.cfgFile.set_position(len(name))
        self.choose.set_sensitive(True)
   
    def unlockFile(self):
        self.choose.set_sensitive(True)

    def clicked_szAll(self,w):
        if self.szAll.get_active():
           self.bigTitleIcon.set_active(False)
           
    def clicked_bti(self,w):
        if self.szAll.get_active() and not self.noJsr82.get_active():
           self.bigTitleIcon.set_active(False)
           
        if not self.bigTitleIcon.get_active():
           self.noJsr82.set_active(False)
           
    def clicked_nojsr82(self,w):
        
	sensitive = (not self.noJsr82.get_active())
	
	switches = [self.szAll, self.sz16, self.sz32, self.sz48, self.sz64, self.sz128]
	for switch in switches:
	    switch.set_sensitive(sensitive)
 
        if self.noJsr82.get_active():
           self.bigTitleIcon.set_active(True)
        
    def test_at(self,w):
        global debug, cmd_array
        if debug: print 'test_at'
        stopPBar() 
        startPBar(AR_WAIT_OPS)
        queueBT('test_at',self.btAddress)

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

        stopPBar() 
        startPBar(_('Wait ping results'))
        queueBT('ping',self.btAddress)
            
    def upload(self,w):
        global debug, cmd_array, pbar
        if debug: print _('Queue push request')
         
        sz = '16'   
        if self.noJsr82.get_active():
            sz = 'nojsr82'
        elif self.szAll.get_active():
            sz = ''
        else:
            if self.sz32.get_active():
                sz = '32'
            elif self.sz48.get_active():
                sz = '48'
            elif self.sz64.get_active():
                sz = '64'
            elif self.sz128.get_active():
                sz = '128'
            
            if self.bigTitleIcon.get_active():
                sz = sz+'b'
            
        stopPBar() 
        startPBar(AR_WAIT_OPS)
        
        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 checkQueue(self):
        global ddQueue
        try:
            data = ddQueue.get(False)
            
            if data[0] == 'SET_STATUS':
                self.setStatustext(data[1])
            
        except Queue.Empty:
            pass
        return True
            
##################################################################################
#
# Progressbar
#
##################################################################################

def startPBar(text):
    putToMainQueue(['PBAR_START',text,30])

def writePBar(text):
    putToMainQueue(['PBAR_WRITE',text])

def stopPBar():
    putToMainQueue(['PBAR_STOP'])

def progress_timeout(pbobj):
    pbobj.pbar.pulse()
    return True

class PBar(gtk.Window):
    def __init__(self, text, size, filename=None):
    
        gtk.Window.__init__(self)

        self.reset   = False
         
        self.text    = text
        self.tmout   = size
        self.fname   = filename

        self.set_resizable(True)

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

        vbox = gtk.VBox(False, 5)
        vbox.set_border_width(10)
        self.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_pulse_step(0.05)
        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.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: Pbar gobject.source_remove(gui.timer)'
            pass
        self.destroy()
         
##################################################################################
#
# Choose cfg. file 
#
##################################################################################
class cfgChooser (gtk.Window):

    def __init__(self, details_win):
        global debug, liststore
        
        gtk.Window.__init__(self)

        self.dw = details_win
    
        self.set_title(_('Choose application'))
        self.connect("destroy", self.closePressed)
        
        vbox = gtk.VBox(False, 0)
        self.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 = addHbox(vbox)

        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.set_size_request(400, 300)
        
        self.show_all()

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

    def closePressed(self, widget):
        self.dw.unlockFile()   
        self.destroy()

    def okPressed(self, widget):
    
        (model, titer) = self.treeview.get_selection().get_selected()
        self.quitOk(titer)
        
    def quitOk(self, treeiter):
        global liststore
        
        try:
            s = liststore.get_value(treeiter, 4)
        except TypeError:
            # nothing was chosen
            return
    
        self.dw.setupFile(s)   
        self.destroy()
    
##################################################################################
#
# Front-End to anyRemote
#
##################################################################################

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

    def ready(self):
        return self.isReady

    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', port

        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:
                self.isReady = True
                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-2];}\'', 'frontend')

        if cfgFile != '':
            gtk.gdk.threads_enter()
            ti  = liststore.get_iter_first()
            while ti != None:
                fName = liststore.get_value(ti, 4)
                if fName == cfgFile:
                    strIter = liststore.get_string_from_iter(ti)
                    putToMainQueue(['UPDATE_LIST',strIter,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
            
                statusMessage('D')
            
                #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
                            
                        putToMainQueue(['GET_DATA',data])
                         
                        if not data: 
                            if debug: print 'FrontEnd anyRemote die?'
                            
                            putToMainQueue(['SET_STATUS','S'])
                            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')
                    
                        status = AR_AVAIL
                        if isRun == 'OK':
                            status = AR_RUNNING
                        
                        strIter = liststore.get_string_from_iter(ti)
                        putToMainQueue(['UPDATE_LIST',strIter,status])
                        
                    else:
                        isInst = isInstalled(liststore.get_value(ti, 2))
                        
                        status = ''
                        if isInst == 'OK':
                            status = AR_AVAIL
                            
                        strIter = liststore.get_string_from_iter(ti)
                        putToMainQueue(['UPDATE_LIST',strIter,status])
                    
                ti = liststore.iter_next(ti)
            gtk.gdk.threads_leave()
                
                
##################################################################################
#
# Device browser
#
##################################################################################

class DeviceBrowser (gtk.Window):

    def __init__(self):
        global gui, debug, bt_devices, cfgReader
        
        gtk.Window.__init__(self)
    
        self.set_title(AR_DEV_BROWSER)
        self.connect("destroy", self.close)

        vbox = gtk.VBox(False, 0)
        self.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=5)

        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 = addHbox(vbox)
        
        self.set_size_request(420, 200)
        self.show_all()
        
        self.isShown = True

        if cfgReader.browseTmout_ > 0:
            browseDevices('F')
            self.timer = gobject.timeout_add (int(1000)*int(cfgReader.browseTmout_), timerBrowseDevices)

    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)
 
        addMenuItem(menu, _('Scan for devices'), gtk.STOCK_FIND,       self.scan)
        addMenuItem(menu, _('Details'),          gtk.STOCK_PROPERTIES, self.details)
        addMenuItem(menu, '',                    gtk.STOCK_REMOVE,     self.delete)
        addMenuItem(menu, '',                    gtk.STOCK_CLOSE,      self.close)

    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)
        v5 = bt_devices.get_value(ti, 4)
        
        showDetailsWin(v1, v2, v3, v4, v5, False)

    def scan(self,w):
        stopPBar () 
        startPBar(_('Scanning'))
        browseDevices('T')

    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"
        
        saveDevices()
        
        self.destroy()
        self.isShown = False
            
##################################################################################
#
# Configuration checker 
#
##################################################################################

class CfgChecker (gtk.Window):

    def __init__(self, jDir):
        global debug
    
        gtk.Window.__init__(self)

        self.j2meDir = jDir
       
        self.set_title(_('Configuration Check'))
        self.connect("destroy", self.close)
    
        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()
        jVer = ''
        ajs = _('Installed')
        if jDir == '':
            ajs = AR_NOTINSTALLED
        else:
            jVer = getJ2MEClientVersion(jDir+os.sep+'anyRemote-16.jad')
            
        if jDir == os.environ.get("HOME")+os.sep+'.anyRemote':
            ajs = _('Downloaded')

        ajs = ajs+' v.'+jVer
        
        bts = btVerify()
        if bts == 'NOK':
            bts = _('Not active')
        else:
            bts = _('Active')
    
        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.j2meDir and jDir != '':
            pkg_list.append(ti,[_('Warning:'),_('Installation directory of anyremote-j2me-client not specified in current setup configuration !')])
 
        pkg_list.append(None,["Bluetooth service",bts])

        vbox = gtk.VBox(False, 0)
        self.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 = addHbox(vbox)
        
        self.set_size_request(320, 220)
        self.show_all()
        
        self.isShown = True

    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)
        
        addMenuItem(menu, '', gtk.STOCK_CLOSE, self.close)

    def close(self,w):
        self.destroy()
        self.isShown = False
            
##################################################################################
#
# Editor 
#
##################################################################################

class cfgEditor (gtk.Window):

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

        box1 = gtk.VBox(False, 0)
        self.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)
        
        addMenuItem(menu, _('Save'),    gtk.STOCK_SAVE,    self.saveFile)
        addMenuItem(menu, _('Save As'), gtk.STOCK_SAVE_AS, self.saveAs)
        addMenuItem(menu, AR_CLOSE,     gtk.STOCK_CLOSE,   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.show_all()

    def closeEditWindow(self, widget):
        self.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.destroy()
        except IOError:
            errorMessage(_('Can not save the file !'))
            self.saveAs(None)

    def saveAs(self, widget):
        self.fdialog = gtk.FileChooserDialog(_('Save File As'),None,gtk.FILE_CHOOSER_ACTION_SAVE,
                                (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
         
        self.fdialog.set_default_response(gtk.RESPONSE_OK)
        response = self.fdialog.run()
        
        if response == gtk.RESPONSE_OK:
            f = self.fdialog.get_filename()
            if f:
                self.editedFile = f
                self.saveFile(None)
        self.fdialog.destroy()

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

class gAnyRemote(gtk.Window):

    def __init__(self, openW, cfgSet):
        global debug, guiMode, liststore, cfgReader

        gtk.Window.__init__(self)
        self.get_settings().set_long_property('gtk-menu-images', True, '')

        initVerify()

        self.notInTray = openW
        self.initTray(openW)

        self.set_title("gAnyRemote")

        self.connect("size-allocate", self.resizeEvent)

        vbox = gtk.VBox(False, 0)
        self.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() 
       
        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 = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
 
        ################
        hbox = gtk.HBox(False, 0)
        if guiMode == 'expert':
            vbox.add(hbox)
            vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
             
        self.entry = gtk.Entry()
        self.entry.set_max_length(512)
        
        if guiMode == 'expert':
            hbox.pack_start(self.entry, True, True, 0)

            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 = addHbox(vbox)

        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.get_style().bg[gtk.STATE_NORMAL])
        try:
            self.detailsRenderer.set_property('wrap-mode', pango.WRAP_WORD) #gtk.WRAP_WORD ?
        except TypeError, 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 = addHbox(vbox)

        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.set_size_request(500, h)
        
        try:
            self.detailsRenderer.set_property('wrap-width', 450)
        except TypeError, AttributeError:
            pass
            
        self.set_icon(findIcon('ganyremote.png'))
        
        if self.notInTray:
            self.show_all()
                 
        gtk.window_set_default_icon(self.pixbufOn)
                
        self.setStatusStopped()
        
        if cfgSet == 0 or cfgReader.j2meDir_ == '':
            self.showWizard(cfgSet, cfgReader.j2meDir_)

        if cfgReader.doAutoStart_ and cfgReader.autoStart_ != '':
            gobject.timeout_add(500, self.autoStartBackend)
        
        self.frontEnd = None

        self.inQueueTimer = gobject.timeout_add(300, self.checkInputQueue)
    
    def saveConfigAction(self, action):
        self.saveCfg()

    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 selectLastInList(self):
        global cfgReader

        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 == cfgReader.lastCfgFile_:
                try:
                     gui.treeview.get_selection().select_iter(ti)
                except AttributeError:
                    pass
                break
                
            ti = liststore.iter_next(ti)
        gtk.gdk.threads_leave()

    def populateCfgFiles(self):
        global debug, cfgFileReaderFlag, cfgReader
        if debug: print 'populateCfgFiles'
        try:
            if cfgFileReaderFlag:
                return
        except NameError:
            pass
            
        stopUpdater()
        
        cfgFileReader = CfgFileReader()
        cfgFileReader.start()

    def autoStartBackend(self):
        global cfgReader, frontEnd, cfgFileReaderFlag
        
        if cfgReader.doAutoStart_ and cfgReader.autoStart_ != '':
            if not frontEnd or not frontEnd.ready() or cfgFileReaderFlag:
                # respawn timer
                return True
    
            startAnyRemote(cfgReader.autoStart_)
        
        return False

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

    def showChkCfg(self, action):
        global cfgReader
        showChkCfgWin(cfgReader.j2meDir_)

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

    def showConfDialog(self):
        global bt_devices, cfgReader
        
        self.dirsChanged = False
        
        self.config = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.config.set_title(_('Preferences'))
        self.config.set_size_request(730, 300)
        self.config.connect("destroy", self.closeCfg)
       

        vbox_top = gtk.VBox(False, 0)
        self.config.add(vbox_top)
        
        notebook = gtk.Notebook()
        notebook.set_tab_pos(gtk.POS_TOP)
        vbox_top.add(notebook)
        
        vbox = gtk.VBox(False, 0)
        notebook.append_page(vbox, gtk.Label(_('General')))
        
        vbox_server = gtk.VBox(False, 0)
        notebook.append_page(vbox_server, gtk.Label(_('Server mode')))
        
        vbox_at = gtk.VBox(False, 0)
        notebook.append_page(vbox_at, gtk.Label(_('AT mode')))
        
        vbox_bm = gtk.VBox(False, 0)
        notebook.append_page(vbox_bm, gtk.Label(_('Bemused')))
        
        vbox_iv = gtk.VBox(False, 0)
        notebook.append_page(vbox_iv, gtk.Label(_('iViewer')))
 
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)

        ################
        # Common tab
        ################
          
        hsep = gtk.HSeparator()
        vbox.add(hsep)
        vbox.set_child_packing(hsep, 0, 1, 0, gtk.PACK_START)
        
        ################
        hbox = addHbox(vbox)
        
        self.autoRun = gtk.CheckButton(_('Run on startup'))
        hbox.pack_start(self.autoRun, False, False, 0)
        self.autoRun.set_active(cfgReader.doAutoStart_)
        self.autoRun.connect('toggled',  self.autoRunToggled)
        
        self.autoFile = gtk.Entry()
        self.autoFile.set_max_length(512)
        hbox.pack_start(self.autoFile, True, True, 0)
        self.autoFile.set_text(cfgReader.autoStart_)
        self.autoFile.set_editable(True)
        self.autoFile.set_sensitive(cfgReader.doAutoStart_)
        self.autoFile.set_position(len(cfgReader.autoStart_))

        self.chooseAuto = gtk.Button(label=AR_CHOOSE)
        self.chooseAuto.connect("clicked", self.chooseAutoStart)
        hbox.pack_end(self.chooseAuto, False, False, 0)
        self.chooseAuto.set_sensitive(cfgReader.doAutoStart_)

        ################
        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)

        # support PyGTK<2.12
        try:
            scrolledwin.set_tooltip_text(_('Choose directories with configuration files and add them to the list'))
        except AttributeError:
            pass
        
        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)
         
        ################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        
        self.btnAdd = gtk.Button(label=AR_ADD)
        self.btnAdd.connect("clicked", self.addToCfgDirList)
        hbox.pack_start(self.btnAdd, False, False, 0)

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

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

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

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

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

        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        
        self.showSrv = gtk.RadioButton(None,_('Server-mode'))
        vbox1.pack_start(self.showSrv, True, True, 0)
        
        self.showApps = gtk.CheckButton(_('Applications'))
        vbox1.pack_end(self.showApps, True, True, 0)
        self.showApps.set_active(cfgReader.showApps_)
        
        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        
        self.showAt = gtk.RadioButton(self.showSrv, _('AT-mode'))
        vbox1.pack_start(self.showAt, True, True, 0)
        
        self.showCustom = gtk.CheckButton(_('Custom Made'))
        vbox1.pack_end(self.showCustom, True, True, 0)
        self.showCustom.set_active(cfgReader.showCustom_)
        
        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)

        self.showBm = gtk.RadioButton(self.showSrv, _('Bemused-emulation'))
        vbox1.pack_start(self.showBm, True, True, 0)
        
        self.showExamples = gtk.CheckButton(_('Examples'))
        vbox1.pack_end(self.showExamples, True, True, 0)
        self.showExamples.set_active(cfgReader.showExamples_)
        
        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)

        self.showIView = gtk.RadioButton(self.showSrv, _('iViewer'))
        vbox1.pack_start(self.showIView, True, True, 0)
        
        self.showNonavail = gtk.CheckButton(_('Non-available'))
        vbox1.pack_end(self.showNonavail, True, True, 0)
        self.showNonavail.set_active(cfgReader.showNonavail_)
        
        self.showBm.set_active   (cfgReader.showBm_)
        self.showIView.set_active(cfgReader.showIView_)
        self.showAt.set_active   (cfgReader.showAt_)
        self.showSrv.set_active  (cfgReader.showSrv_)
        
        self.showApps.connect    ('toggled', self.filterChangedAction)
        self.showCustom.connect  ('toggled', self.filterChangedAction)
        self.showExamples.connect('toggled', self.filterChangedAction)
        self.showNonavail.connect('toggled', self.filterChangedAction)
        self.showAt.connect      ('toggled', self.filterChangedAction)
        self.showSrv.connect     ('toggled', self.filterChangedAction)
        self.showBm.connect      ('toggled', self.filterChangedAction)
        self.showIView.connect   ('toggled', self.filterChangedAction)
    
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

        ################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        
        label = gtk.Label(_('Auto startup with'))
        hbox.pack_start(label, True, True, 0)
        
        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.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'))

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

        ################
        hbox = addHbox(vbox)

        self.updLabel = gtk.Label(_('Update application list every'))
        hbox.pack_start(self.updLabel, True, True, 0)        

        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)
        
        # support PyGTK<2.12
        try:
            self.updateTmout.set_tooltip_text(_('Empty field means no update'))
        except AttributeError:
            pass
        
        self.secLabel1 = gtk.Label(_('sec.'))
        hbox.pack_start(self.secLabel1, True, True, 0)
        
        tm = ''
        if cfgReader.updateTmout_ > 0:
            tm = "%s" % (cfgReader.updateTmout_)
        self.updateTmout.set_text(tm)
        
        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)
       
        self.brLabel = gtk.Label(' '+_('Run device browser with timeout')+'  ')
        hbox.pack_start(self.brLabel, False, True, 0)
        self.brLabel.set_sensitive((cfgReader.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)
        
        # support PyGTK<2.12
        try:
            self.browseTmout.set_tooltip_text(_('Empty field means no update. Beware: Android/J2ME clients could fail to connect to anyRemote when browsing is in process'))
        except AttributeError:
            pass
        
        self.secLabel2 = gtk.Label(_('sec.'))
        hbox.pack_start(self.secLabel2, True, True, 0)
        
        tm = ''
        if cfgReader.browseTmout_ > 0:
            tm = "%s" % (cfgReader.browseTmout_)
        self.browseTmout.set_text(tm)

        ################
        # Server tab
        ################
        hbox = gtk.HBox(False, 0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        
        vbox2 = gtk.VBox(False, 0)
        hbox.add(vbox2)
        hbox.set_child_packing(vbox2, False, True, 0, gtk.PACK_START)
        
        self.connBT = gtk.CheckButton(_('Use Bluetooth connection, channel '))
        vbox2.pack_start(self.connBT, True, True, 0)
        
        self.connTCP = gtk.CheckButton(_('Use TCP/IP connection, port'))
        vbox2.pack_start(self.connTCP, True, True, 0)
        
        self.connWEB = gtk.CheckButton(_('Use Web Interface, port'))
        vbox2.pack_start(self.connWEB, True, True, 0)
        
        self.connMan = gtk.CheckButton(_('Specify options manually'))
        vbox2.pack_start(self.connMan, True, True, 0)
        
        self.connBT.set_active (cfgReader.dvSrvUseBT_)
        self.connTCP.set_active(cfgReader.dvSrvUseTCP_)
        self.connWEB.set_active(cfgReader.dvSrvUseWEB_)
        self.connMan.set_active(cfgReader.dvSrvUseADV_)
    
        vbox4 = gtk.VBox(False, 0)
        hbox.add(vbox4)
        hbox.set_child_packing(vbox4, True, True, 0, gtk.PACK_START)
        
        self.btData = gtk.Entry()
        self.btData.set_max_length(512)
        vbox4.pack_start(self.btData, True, True, 0)
        self.btData.set_text(cfgReader.dvSrvBT_)
        self.btData.connect('changed', self.deviceSrvChangedAction)
 
        self.tcpData = gtk.Entry()
        self.tcpData.set_max_length(512)
        vbox4.pack_start(self.tcpData, True, True, 0)
        self.tcpData.set_text(cfgReader.dvSrvTCP_)
        self.tcpData.connect('changed', self.deviceSrvChangedAction)
        
        self.webData = gtk.Entry()
        self.webData.set_max_length(512)
        vbox4.pack_start(self.webData, True, True, 0)
        self.webData.set_text(cfgReader.dvSrvWEB_)
        self.webData.connect('changed', self.deviceSrvChangedAction)
        
        self.manData = gtk.Entry()
        self.manData.set_max_length(512)
        vbox4.pack_start(self.manData, True, True, 0)
        self.manData.set_text(cfgReader.dvSrvADV_)
        self.manData.connect('changed', self.deviceSrvChangedAction)
        
        self.typeToggled(None)
        
        self.connMan.connect('toggled', self.typeToggled)
        self.connBT.connect('toggled',  self.typeToggled)
        self.connTCP.connect('toggled', self.typeToggled)
        self.connWEB.connect('toggled', self.typeToggled)
 
        ################
        hsep = gtk.HSeparator()
        vbox_server.add(hsep)
        vbox_server.set_child_packing(hsep, 0, 1, 0, gtk.PACK_START)

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

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

        self.chooseJ2ME = gtk.Button(label=AR_CHOOSE)
        self.chooseJ2ME.connect("clicked", self.chooseJ2MEDir)
        hbox.pack_start(self.chooseJ2ME, False, False, 0)

        ################
        hsep = gtk.HSeparator()
        vbox_server.add(hsep)
        vbox_server.set_child_packing(hsep, 0, 1, 0, gtk.PACK_START)
        
        ################
        hbox = gtk.HBox(False, 0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        
        self.checkJ2ME = gtk.CheckButton(_('Check J2ME client updates at start'))
        hbox.pack_start(self.checkJ2ME, True, True, 0)
        self.checkJ2ME.set_active(cfgReader.checkJ2MEUpdate_)

        self.checkJ2MENow = gtk.Button(label=_('Check J2ME client updates'))
        self.checkJ2MENow.connect("clicked", self.checkJ2MEWeb)
        hbox.pack_end(self.checkJ2MENow, False, False, 0)
        
        ################
        hbox = gtk.HBox(False, 0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)

        self.downloadJ2MENow = gtk.Button(label=_('Download J2ME client from Web'))
        self.downloadJ2MENow.connect("clicked", self.uploadJ2MEWeb)
        hbox.pack_end(self.downloadJ2MENow, False, False, 0)
         
        # support PyGTK<2.12
        try:
            self.downloadJ2MENow.set_tooltip_text(_('Files will be saved to $HOME/.anyRemote'))
        except AttributeError:
            pass

        ################
        # AT tab
        ################
        hbox = gtk.HBox(False, 0)
        vbox_at.add(hbox)
        vbox_at.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        
        label = gtk.Label(_('Use connect string')+'  ')
        hbox.pack_start(label, 0, True, 0)
        
        btAddresses = gtk.ListStore(str)

        treeiter = bt_devices.get_iter_first()
        while treeiter != None:
            v1 = bt_devices.get_value(treeiter, 0)
            v4 = bt_devices.get_value(treeiter, 3)
            
            # use channel 1 as default
            if v4 == "":
                v4 = "1"
            
            channels = v4.split(':')
            for ch in channels:
                if str(ch).isdigit():
                    row = "rfcomm:"+v1+":"+ch
                    if cfgReader.deviceAT_ != row:
                        btAddresses.append([row])
                
            treeiter = bt_devices.iter_next(treeiter)

        self.device_at = gtk.ComboBoxEntry(btAddresses)
        
        if cfgReader.deviceAT_ != "":
            btAddresses.prepend([cfgReader.deviceAT_])
            self.device_at.set_active(0)
            
        hbox.pack_start(self.device_at, True, True, 0)

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

        self.autoReconn = gtk.CheckButton(_('Auto reconnect'))
        hbox.pack_start(self.autoReconn, True, True, 0)
        self.autoReconn.set_active(cfgReader.autoReconn_)

        ################
        # Bemused tab
        ################
        hbox = gtk.HBox(False, 0)
        vbox_bm.add(hbox)
        vbox_bm.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        
        label = gtk.Label(_('Use connect string')+'  ')
        hbox.pack_start(label, 0, True, 0)
        
        self.device_bm = gtk.Entry()
        self.device_bm.set_max_length(512)
        hbox.pack_start(self.device_bm, True, True, 0)
        self.device_bm.set_text(cfgReader.deviceBm_)
        self.device_bm.connect('changed', self.deviceBemusedChangedAction)

        ################
        # iViewer tab
        ################
        hbox = gtk.HBox(False, 0)
        vbox_iv.add(hbox)
        vbox_iv.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        
        label = gtk.Label(_('Use connect string')+'  ')
        hbox.pack_start(label, 0, True, 0)
        
        self.device_iv = gtk.Entry()
        self.device_iv.set_max_length(512)
        hbox.pack_start(self.device_iv, True, True, 0)
        self.device_iv.set_text(cfgReader.deviceIV_)
        self.device_iv.connect('changed', self.deviceIViewerChangedAction)

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

        hbox = gtk.HBox(False, 0)
        vbox_top.add(hbox)
        vbox_top.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        
        btn = gtk.Button(label=AR_OK)
        addIconToButton(btn,gtk.STOCK_OK)
        btn.connect("clicked", self.okCloseCfg)
        hbox.pack_end(btn, False, False, 0)
 
        btn = gtk.Button(label=AR_CANCEL)
        addIconToButton(btn,gtk.STOCK_CANCEL)
        btn.connect("clicked", self.closeCfg)
        hbox.pack_end(btn, False, False, 0)
        
        for d in cfgReader.cfgDirs:
            if d != '':
                self.cfg_liststore.append([d])
        
        self.j2meDir.set_text(cfgReader.j2meDir_)  
         
        self.config.show_all()
        
        self.showConfItem.set_sensitive(False)
                
    def chooseAutoStart(self,w):
        self.chooseAuto.set_sensitive(False)
        self.autoFile.set_sensitive(False)
        cfgChooser(self)

    def setupFile(self, name):
        self.autoFile.set_text(name)
        self.autoFile.set_sensitive(True)
        self.autoFile.set_position(len(name))
        self.chooseAuto.set_sensitive(True)

    def unlockFile(self):
        self.autoFile.set_sensitive(True)
        self.chooseAuto.set_sensitive(True)

    def addToCfgDirList(self, w):
        self.btnAdd.set_sensitive(False)
        
        dialog = gtk.FileChooserDialog(AR_SEL_DIR,None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                         (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)
        response = dialog.run()
        
        if response == gtk.RESPONSE_OK:
            self.dirsChanged = True
            
            newPath = dialog.get_filename()

            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])
            
        dialog.destroy()
        self.btnAdd.set_sensitive(True)

    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 chooseJ2MEDir(self, w):
        self.chooseJ2ME.set_sensitive(False)
                
        dialog = gtk.FileChooserDialog(AR_SEL_DIR,None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)
        response = dialog.run()
        
        if response == gtk.RESPONSE_OK:
            self.j2meDir.set_text(dialog.get_filename())
            
        dialog.destroy()
        
        self.chooseJ2ME.set_sensitive(True)

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

    def okCloseCfg(self, w):
        global cfgReader

        self.setAutoStartup("KDE",   self.autorunKDE.get_active())
        self.setAutoStartup("Gnome", self.autorunGnome.get_active())
        
        cfgReader.showApps_     = self.showApps.get_active()
        cfgReader.showCustom_   = self.showCustom.get_active()
        cfgReader.showExamples_ = self.showExamples.get_active()
        cfgReader.showNonavail_ = self.showNonavail.get_active()
        cfgReader.showAt_       = self.showAt.get_active()
        cfgReader.showSrv_      = self.showSrv.get_active()
        cfgReader.showBm_       = self.showBm.get_active()
        cfgReader.showIView_    = self.showIView.get_active()

        cfgReader.autoReconn_   = self.autoReconn.get_active()
        
        cfgReader.dvSrvBT_  = self.btData.get_text().strip()
        cfgReader.dvSrvTCP_ = self.tcpData.get_text().strip()
        cfgReader.dvSrvWEB_ = self.webData.get_text().strip()
        cfgReader.dvSrvADV_ = self.manData.get_text().strip()

        cfgReader.deviceAT_     = self.device_at.get_active_text().strip()
        cfgReader.deviceBm_     = self.device_bm.get_text().strip()
        cfgReader.deviceIV_     = self.device_iv.get_text().strip()
        
        cfgReader.j2meDir_      = self.j2meDir.get_text().strip()
        cfgReader.checkJ2MEUpdate_ = self.checkJ2ME.get_active()
        
        tm = self.updateTmout.get_text().strip()
        if tm == '':
            tm = '-1'
        if cfgReader.updateTmout_ != int(tm):
            cfgReader.updateTmout_ = int(tm)
            if cfgReader.updateTmout_ < 0:
                cfgReader.updateTmout_ = -1
            stopUpdater()
            startUpdater(cfgReader.updateTmout_)
        
        tm = self.browseTmout.get_text().strip()
        if tm == '':
            tm = '-1'
        if cfgReader.browseTmout_ != int(tm):
            cfgReader.browseTmout_ = int(tm)
            if cfgReader.browseTmout_ <= 0:
                cfgReader.browseTmout_ = -1
            stopBtComm()
            startBtComm(cfgReader.browseTmout_, cfgReader.j2meDir_)

        cfgReader.autoStart_   = self.autoFile.get_text().strip()
        cfgReader.doAutoStart_ = self.autoRun.get_active()

        cfgReader.cfgDirs = []
        
        treeiter     = self.cfg_liststore.get_iter_first()
        while treeiter != None:
            value = self.cfg_liststore.get_value(treeiter, 0)
            cfgReader.cfgDirs.append(value)
            treeiter = self.cfg_liststore.iter_next(treeiter)
               
        proceed = True
        if cfgReader.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:
            cfgReader.saveConfig() 
            self.config.destroy()
        
            self.showConfItem.set_sensitive(True)
        
            if self.dirsChanged == True:
                self.populateCfgFiles()
                self.dirsChanged = False
            
    def dbrowseChangedAction(self, editable):  
        global cfgReader
        cfgReader.browseTmout_ = self.browseTmout.get_text().strip()
        if cfgReader.browseTmout_ == '':
             self.brLabel.set_sensitive(False)
             self.secLabel2.set_sensitive(False)
        else:     
             self.brLabel.set_sensitive((cfgReader.browseTmout_ > 0))
             self.secLabel2.set_sensitive((cfgReader.browseTmout_ > 0))

    def tmoutChangedAction(self, editable):  
        global cfgReader
        cfgReader.updateTmout_ = self.updateTmout.get_text().strip()
        if cfgReader.updateTmout_ == '':
             self.updLabel.set_sensitive(False)
             self.secLabel1.set_sensitive(False)
        else:     
             self.updLabel.set_sensitive((cfgReader.updateTmout_ > 0))
             self.secLabel1.set_sensitive((cfgReader.updateTmout_ > 0))
            
    def deviceSrvChangedAction(self, editable):
        global cfgReader
        cfgReader.dvSrvBT_  = self.btData.get_text().strip()
        cfgReader.dvSrvTCP_ = self.tcpData.get_text().strip()
        cfgReader.dvSrvWEB_ = self.webData.get_text().strip()
        cfgReader.dvSrvADV_ = self.manData.get_text().strip()
   
    def deviceATChangedAction(self, editable):
        global cfgReader
        cfgReader.deviceAT_ = self.device_at.get_text().strip()
    
    def deviceBemusedChangedAction(self, editable):
        global cfgReader
        cfgReader.deviceBm_ = self.device_bm.get_text().strip()
    
    def deviceIViewerChangedAction(self, editable):
        global cfgReader
        cfgReader.deviceIV_ = self.device_iv.get_text().strip()
 
    def typeToggled(self, w):
        global cfgReader
        
        if w == self.connMan:
            cfgReader.dvSrvUseADV_ = self.connMan.get_active()
            if self.connMan.get_active():
                self.connBT.set_active(False)
                self.connTCP.set_active(False)
                self.connWEB.set_active(False)
                cfgReader.dvSrvUseBT_  = False
                cfgReader.dvSrvUseTCP_ = False
                cfgReader.dvSrvUseWEB_ = False
        
                if self.manData.get_text().strip() == '':
                    self.manData.set_text("-log -s bluetooth:19")

        if w == self.connBT:
            cfgReader.dvSrvUseBT_ = self.connBT.get_active()
            if self.connBT.get_active():
                self.connMan.set_active(False)
                cfgReader.dvSrvUseADV_ = False

                if self.btData.get_text().strip() == '':
                    self.btData.set_text("19")

        if w == self.connTCP:
            cfgReader.dvSrvUseTCP_ = self.connTCP.get_active()
            if self.connTCP.get_active():
                self.connMan.set_active(False)
                cfgReader.dvSrvUseADV_ = False

                if self.tcpData.get_text().strip() == '':
                    self.tcpData.set_text("5197")
        
 
        if w == self.connWEB:
            cfgReader.dvSrvUseWEB_ = self.connWEB.get_active()
            if self.connWEB.get_active():
                self.connMan.set_active(False)
                cfgReader.dvSrvUseADV_ = False

                if self.webData.get_text().strip() == '':
                   self.webData.set_text("5080")

        self.btData.set_sensitive(self.connBT.get_active())
        self.tcpData.set_sensitive(self.connTCP.get_active())
        self.webData.set_sensitive(self.connWEB.get_active())
        self.manData.set_sensitive(self.connMan.get_active())

    def autoRunToggled(self, w):
        self.autoFile.set_sensitive(self.autoRun.get_active())
        self.chooseAuto.set_sensitive(self.autoRun.get_active())

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

    def uploadJ2MEWeb(self,w):
        global debug,jup,cfgReader

        try:
            if jup != None:
               if debug: print 'Uploading already active. Skip request.'
               return
        except NameError:
            pass
            
        jup = JCUploader()
        jup.start()
        
        cfgReader.j2meDir_ = os.environ.get("HOME")+os.sep+'.anyRemote'

    def checkJ2MEWeb(self,w):
        jv = JCVerifier(True)
        jv.start()

    def updateAvail(self):
        ret = yesno(self,_("New version of J2ME client is available. Would You like to download it ?"))
        if ret == gtk.RESPONSE_YES:
            self.uploadJ2MEWeb(self) 
            
    ##################################################################################
    #
    # Status related function
    #
    ##################################################################################

    def setStatustext(self,text):
        self.sBar.pop(self.cid)
        self.sBar.push(self.cid,'  ' + text)

    def setStatusValue(self, val):
        self.statusValue = val
        self.setStatustext(val)
        self.setTrayTooltip(val)

    def setTempStatus(self, val):
        self.setStatustext(val)
        
    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.setTrayIcon("OFF")
        self.setStatusValue(AR_STOPPED)

    def setStatusDisconnected(self):
    
        global debug, cfgReader
        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.setTrayIcon("RUN")
        self.setStatusValue(AR_DISCONN+' '+cfgReader.getConnectStatusString())

    def setStatusConnected(self):
    
        global debug
        if debug: print 'setStatusConnected'
        
        self.setTrayIcon("ON")
        self.setStatusValue(AR_CONNECT)
        
    def translateMsg(self, data):
    
        global debug
        if debug: print 'translateMsg  ' + data

        if data == '':

           return
           
        elif data == 'Exiting':
        
           self.setStatusStopped()
           return

        elif data == 'Connected':

           self.setStatusConnected()
           return

        elif data == 'Disconnected':

           self.setStatusDisconnected()
           return
        
        if data == '(Init)':

           msg = 'anyRemote initialized'

        else:
        
           # Just key press 
           self.setTrayIcon("FLASH")
           self.blinkTimer = gobject.timeout_add(200, self.resetTrayIcon)           
           
           if debug:
               msg = data
           else:
               return
        
        self.setStatustext(msg)
        
    def resetTrayIcon(self):
    
        self.setTrayIcon("ON")
        return False
                   
    def checkInputQueue(self):
        global guiQueue
        
        while True:
            try:
                data = guiQueue.get(False)

                if data[0] == 'MSG_INF':
                    message(data[1],gtk.MESSAGE_INFO)
                elif data[0] == 'MSG_ERR':
                    message(data[1],gtk.MESSAGE_INFO)
                elif data[0] == 'UPDATE_AVAIL':
                    self.updateAvail()
                elif data[0] == 'PBAR_START':
                    self.startProgressBar(data[1],data[2])
                elif data[0] == 'PBAR_STOP':
                    self.stopProgressBar()
                elif data[0] == 'PBAR_WRITE':
                    self.writeProgressBar(data[1])
                elif data[0] == 'SET_STATUS':
                    if data[1] == 'S':
                        self.setStatusStopped()
                    elif data[1] == 'D':
                        self.setStatusDisconnected()
                    elif data[1] == 'C':
                        self.setStatusConnected()
                elif data[0] == AR_CODE_LOADED:
                    cnt = int(data[1])
                    if cnt >= 0:
                        self.setTempStatus(str(data[1]))
                    else:
                        self.setStatusValue(self.statusValue) 
                        self.selectLastInList()
                        restartUpdater()

                elif data[0] == 'UPDATE_LIST':
                    treeiter = liststore.get_iter_from_string(data[1])
                    liststore.set_value(treeiter, 5, data[2])    
                elif data[0] == 'GET_DATA':
                    self.translateMsg(data[1])
             
            except Queue.Empty:
                break
            
        return True

    def startProgressBar(self,m,t):
        global pbar
        pbar = PBar(m,t)
        
    def stopProgressBar(self):
        global pbar
        try:
            pbar.stop()
        except AttributeError, NameError:
            pass

    def writeProgressBar(self,m):
        global pbar
        try:
            pbar.set_text(m)
        except AttributeError, NameError:
            pass
        
    ##################################################################################
    #
    # Tray & AppIndicator support
    #
    ##################################################################################

    def hasTray(self):
        return (self.tray != None or self.appInd != None)

    def initTray(self,openW):
        
        self.tray = None
        
        # used as window icon
        self.pixbufOn = findIcon('ganyremote.png')

        # Try appIndicator first
        try:
            
            self.appInd = appindicator.Indicator("gAnyRemote", "indicator-messages", appindicator.CATEGORY_APPLICATION_STATUS)

            self.appInd.set_status (appindicator.STATUS_ACTIVE)
            self.appIndMenu = gtk.Menu()
            
            item = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
            item.connect('activate', self.aboutAction)
            item.show()
            self.appIndMenu.append(item)

            item = gtk.ImageMenuItem(gtk.STOCK_EXECUTE)
            item.connect('activate', self.runPressed)
            self.appIndMenu.append(item)

            item = gtk.ImageMenuItem(gtk.STOCK_STOP)
            item.connect('activate', self.stopPressed)
            self.appIndMenu.append(item)

            item = gtk.MenuItem('Minimize/Restore')
            item.connect('activate', self.showWindowAction)
            self.appIndMenu.append(item)
         
            item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
            item.connect('activate', self.quitAction)
            self.appIndMenu.append(item)
            
            self.appIndMenu.show_all()
            
            self.appInd.set_menu(self.appIndMenu)
            
            # cache tray icons
            self.iconFileOn    = findTrayIconFile('ganyremote.png')
            self.iconFileOff   = findTrayIconFile('ganyremote_off.png')
            self.iconFileFlash = findTrayIconFile('ganyremote_flash.png')
            self.iconFileRun   = findTrayIconFile('ganyremote_light.png')
       
        except NameError:
            self.appInd = None
            
            # if no appIndicator try to use tray
            
            try:
                self.tray = gtk.StatusIcon()
                self.tray.connect('popup-menu', self.rightClickAction)
                self.tray.connect('activate',   self.trayPressAction)
                
                # cache tray icons
                self.pixbufOff   = findIcon('ganyremote_off.png')
                self.pixbufFlash = findIcon('ganyremote_flash.png')
                self.pixbufRun   = findIcon('ganyremote_light.png')
                
            except AttributeError:
                self.tray = None
                self.notInTray = True
            
            
        if self.hasTray():
            self.connect("delete_event", self.hideWindow2)
        else:
            self.connect("destroy", self.quitAction)

    def setTrayIcon(self, icon):
        
        if self.appInd:
        
            if icon == "ON":
                self.appInd.set_icon(self.iconFileOn)
            elif icon == "OFF":
                self.appInd.set_icon(self.iconFileOff)
            elif icon == "RUN":
                self.appInd.set_icon(self.iconFileRun)
            elif icon == "FLASH":
                self.appInd.set_icon(self.iconFileFlash)
            else:
                return
       
        elif self.tray: 
        
            pixbuf = None

            if icon == "ON":
                pixbuf = self.pixbufOn
            elif icon == "OFF":
                pixbuf = self.pixbufOff
            elif icon == "RUN":
                pixbuf = self.pixbufRun
            elif icon == "FLASH":
                pixbuf = self.pixbufFlash
            else:
                return

            self.tray.set_from_pixbuf(pixbuf)

    # RMB on tray icon
    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.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 setTrayTooltip(self, ttip):
       if self.tray: 
           self.tray.set_tooltip(ttip)

    ##################################################################################
    #
    # Button and menu handlers
    #
    ##################################################################################

    def aboutAction(self, action):
    
        try:
            dialog = gtk.AboutDialog()
            dialog.set_name("gAnyRemote v6.3.1")
            dialog.set_copyright('Copyright 2007-2013 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-2013 Mikhail Fedotov\nhttp://anyremote.sf.net/")


    # open web browser on docs page if found ?
    def helpAction(self, action):
    
        app = ''
        apps = ['xdg-open', 'firefox', 'konqueror', 'chromium']
        for test in apps:
            isInst = isInstalled(test) 
            if isInst == 'OK':
                app = test
        if app == '':
            errorMessage(_('Can not find browser to show help !'))
            return

        docpath = ''
        docDirs = ['/usr/share/doc/anyremote*/*html', 
                   '/usr/share/anyremote*/*html', 
                   '/usr/share/doc/anyremote-doc', 
                   '/usr/local/share/doc/anyremote*/*html', 
                   '/usr/local/share/anyremote*/*html']

        for docDir in docDirs:
            dirv = glob.glob(docDir)
            if len(dirv) > 0 and os.path.isdir(dirv[0]):
                docpath = dirv[0]
                break
        if docpath == '':
            errorMessage(_('Can not find documentation !'))
            return
        
        cmd = app + ' ' + docpath + os.sep + 'k-shots.html &'
        if debug: print cmd
        os.system(cmd)
                    
    def trayPressAction(self, *args):
        if self.get_property('visible'):
            self.hide()
        else:
            self.show_all()

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

    def quitAction(self, *args):
        try:
            gobject.source_remove(self.inQueueTimer)
        except AttributeError, NameError:
            print 'Exception: gobject.source_remove(gui.inQueueTimer)'
 
        self.quit()

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

        # to store last used cfg.file
        entry_text = self.entry.get_text()
        
        self.saveCfg()
        
        self.setStatusDisconnected()

        startAnyRemote(entry_text)        

    def stopPressed(self, widget):
        global debug
        
        if debug: print 'Stop anyRemote'

        self.saveCfg()
        
        # 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):
        global cfgReader
        if cfgReader.lastCfgFile_:
            e = cfgEditor(cfgReader.lastCfgFile_)
        
    def execCmd(self, w):
        global cmdToSend
        print 'Add to queue ' + self.cmd.get_text()
        cmdToSend = self.cmd.get_text() 
        
    def saveCfg(self):
        global cfgReader
        cfgReader.saveConfig()
       
    ##################################################################################
    #
    # Wizard window
    #
    ##################################################################################
    
    def showWizard(self, cfgdirs, jclient):
        
        if cfgdirs == 0:
           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()
        
        if jclient == '': 
            ret  = yesno(self,_('Would You like to download J2ME client from the web ?'))
            if ret == gtk.RESPONSE_YES:
                self.uploadJ2MEWeb(self)
        
   
    ##################################################################################
    #
    # 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    = addMenuItem(menu, _('Start'), gtk.STOCK_EXECUTE, self.runPressed)
        self.stopItem   = addMenuItem(menu, '',         gtk.STOCK_STOP,    self.stopPressed)
        self.updateItem = addMenuItem(menu, '',         gtk.STOCK_REFRESH, self.rescanPressed)

        if self.hasTray():
            addMenuItem(menu, _('Close Window'), gtk.STOCK_CLOSE, self.hideWindow)
        
        addMenuItem(menu, '', gtk.STOCK_QUIT, self.quitAction)

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

        self.dbrowserItem = addMenuItem(menu, AR_DEV_BROWSER, gtk.STOCK_FIND, self.showBrowser)
        if not usepybluez:
            self.dbrowserItem.set_sensitive(False)
        self.dbrowserItem.show()
       
        self.showConfItem = addMenuItem(menu, '',   gtk.STOCK_PREFERENCES, self.showConfAction)
        
        addMenuItem(menu, _('Check Configuration'), gtk.STOCK_PROPERTIES,  self.showChkCfg)
        addMenuItem(menu, '',                       gtk.STOCK_SAVE,        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)

        addMenuItem(menu, '', gtk.STOCK_HELP, self.helpAction)

    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):
        global cfgReader
        treeiter = liststore.get_iter(path)

        cfgReader.lastCfgFile_ = liststore.get_value(treeiter, 4)

        self.entry.set_text(cfgReader.lastCfgFile_)
        self.runPressed(self.runBtn)

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

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

    def openFDialog(self, w, entry):
        self.fdialog = gtk.FileChooserDialog(_('File selection'),None,gtk.FILE_CHOOSER_ACTION_OPEN,
                                (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
        self.fdialog.set_filename(entry.get_text())
        self.fdialog.set_default_response(gtk.RESPONSE_OK)
        response = self.fdialog.run()
        
        if response == gtk.RESPONSE_OK:
            self.entry.set_text(self.fdialog.get_filename())
        self.fdialog.destroy()
 
    def hideWindow2(self,w,p):
        self.hideWindow(w)
        return True
        
    def hideWindow(self,w):
        self.hide()
                    
    def quit(self):
        print 'Exiting...'
        
        stopBtComm()
        stopJCUploader()
        stopPBar()
        stopUpdater()
        stopFrontend()
        self.saveCfg()
        gtk.main_quit()

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

def addHbox(vbox):
    hbox = gtk.HBox(False, 0)
    vbox.add(hbox)
    vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
    return hbox
def getHttp(hname,fname,tmp):
    global debug

    try:
        conn = httplib.HTTPConnection(hname,80,timeout=10)
    # old pythons (<2.6)
    except TypeError:
        conn = httplib.HTTPConnection(hname)

    try:
        conn.request("GET", fname)
    except Exception: 
        errorMessage(_('Can not establish the connection !'))
        return False
    
    r = conn.getresponse()
    
    if debug: print fname, r.status, r.reason,r.getheader('content-length')
    
    ret = True
    
    if r.status == httplib.OK:
        if debug: print 'download',fname
        
        try:
            data = r.read()
        except Exception:
            errorMessage(_('Download failed !'))
            return False

        f=open(os.environ.get("HOME")+os.sep+'.anyRemote'+fname+tmp, 'w')
        if f:
            f.write(data)
            f.close()
    else:
        if tmp == "":
            errorMessage(_('Can not download ')+hname+fname)
            ret = False
            
        
    conn.close()
    
    return ret
    
def uploadJ2MEWebGui(fname, strip=False):
 
    writePBar(_('Downloading')+' '+fname)
    
    if not getHttp("anyremote.sourceforge.net",os.sep+fname,""):
        stopPBar()
        return False
    
    if strip:
        f1 = os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+fname
        os.system('rm -f '+f1+'.tmp; cat '+f1+'|sed \'s/MIDlet-Jar-URL: http:\/\/anyremote.sourceforge.net\//MIDlet-Jar-URL: /\' > '+f1+'.tmp;mv '+f1+'.tmp '+f1);
    
    return True

def getJ2MEClientVersion(fname):
    global debug
    if debug: print 'Check version of J2ME Client from file',fname
    return getResult('cat '+fname+'|grep MIDlet-Version|tr -d \" \"|cut -f 2 -d \":\"','main')

def checkJ2MEClientUpdate():
    global debug
    
    if not getHttp("anyremote.sourceforge.net",os.sep+"anyRemote-16.jad",".check"):
        return ""
        
    newver = getJ2MEClientVersion(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyRemote-16.jad.check')
    oldver = getJ2MEClientVersion(getJ2MEPath()+os.sep+'anyRemote-16.jad')
    
    if debug: print 'compare new=',newver,' and old=',oldver
    
    nvers = newver.split('.')
    overs = oldver.split('.')
    
    l = len(nvers)
    if len(overs) > l: 
        l = len(overs)
    
    foundnew = False
    for i in range(l):
        
        if len(overs) < i:
            oi = 0
        else:
            oi = overs[i]
            
        if len(nvers) < i:
            ni = 0
        else:
            ni = nvers[i]
        
        #if debug: print '(',i,') compare new=',ni,' and old=',oi
        if ni > oi:
            foundnew = True
            break

    if (foundnew):
        return  newver
        
    return ""

def addMenuItem(menu, title, stock, callback):
    if title == '':
        menuitem = gtk.ImageMenuItem(stock)
    else:
        menuitem = iconMenuItem(title, stock)
    menu.add(menuitem)
    menuitem.connect('activate', callback)
    return menuitem

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 yesno(p,m):
    dialog = gtk.MessageDialog(p,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_YES_NO, m)
    # force it to show to avoid some warnings
    dialog.show()
    dialog.set_keep_above(True)
    rid = dialog.run()
    dialog.destroy()
    return rid

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.show() 
    dialog.set_keep_above(True)
    dialog.run()
    dialog.destroy()

def putToDevWQueue(data):
    global ddQueue
    try:
        ddQueue.put(data)
    except Queue.Full:
        pass

def codeMessage(code):
    putToMainQueue([code])

def codeMessage2(code,val):
    putToMainQueue([code,val])

def statusMessage(val):
    putToMainQueue(['SET_STATUS',val])
    
def putToMainQueue(data):
    global guiQueue
    try:
        guiQueue.put(data)
    except Queue.Full:
        pass

def errorMessage(m):
    putToMainQueue(['MSG_ERR',m])

def infoMessage(m):
    putToMainQueue(['MSG_INF',m])

def getJ2MEPath():
    path = ''
    if os.path.exists(os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'anyRemote-16.jad'):
        path = os.environ.get("HOME") + os.sep + '.anyRemote'
    return path

def isInstalled(app):
    dirs = os.getenv('PATH').split(':')
    for d in dirs:
        if os.path.exists(d+os.sep+app):
            return 'OK'
    return 'NOK'

def reqVersion(cmd):
    res = getResult(cmd,'main')
    if res == 'OK':
         return 'OK'
    return 'NOK'
        
def getResult(cmd, suffix):
        
    toFile = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'ganyremote-' + suffix + '.tmp'
    
    #if debug: print 'getResult: '+cmd + '> ' + toFile
    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 clearAppsList():   
    global gui, liststore

    gtk.gdk.threads_enter()
    gui.treeview.set_model(None);
    liststore.clear()
    gtk.gdk.threads_leave()

def addAppToList(aName, aIcon, app, aRun, isRun, cfgFile, status, aMode, aType, aDesc):
    global liststore
    
    if aIcon == '':
        aIcon = 'fileopen.png'
    
    pbuf = findIcon(aIcon)
                 
    gtk.gdk.threads_enter()
    for oneMode in aMode: 
        item = liststore.append([aName, pbuf, app, aRun, cfgFile, status, _(oneMode), _(aType), aDesc])
    gtk.gdk.threads_leave()

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

def addDevice(v1, v2, v3, v4, v5):
    global bt_devices
    bt_devices.append([v1,v2,v3,v4,v5,''])

def saveDevices():
    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 + AR_FILE_DEVICES, 'w')
    if f:
        treeiter     = bt_devices.get_iter_first()
        while treeiter != None:
            v0 = bt_devices.get_value(treeiter, 0)
            v1 = bt_devices.get_value(treeiter, 1)
            v2 = bt_devices.get_value(treeiter, 2)
            v3 = bt_devices.get_value(treeiter, 3)
            v4 = bt_devices.get_value(treeiter, 4)
            
            f.write('Device='+v0+','+v1+','+v2+','+v3+','+v4+'\n')

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

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

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

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

def restartUpdater():
    global cfgReader
    stopUpdater()
    startUpdater(cfgReader.updateTmout_)
    
#####################################################################################    

def killAnyRemote():
    os.system('killall -2 anyremote 2> /dev/null')


def startAnyRemote(cfg_file):
    global debug, cfgReader
    
    if debug: print 'startAnyRemote',cfg_file
    
    killAnyRemote()
    
    time.sleep(0.5)

    mode = 'Server'
    if cfgReader.showAt_:
        mode = 'AT'
    if cfgReader.showBm_:
        mode = 'Bemused'
    if cfgReader.showIView_:
        mode = 'iViewer'

    log = ''
    if debug:
        log = ' -log'
   
    dev = ''
    rconn = ''
    
    if mode == 'Server':
         connStr = cfgReader.getConnectString()
         if connStr != '':
             dev = ' -s '+connStr
   
    elif mode == 'AT':
        if cfgReader.deviceAT_ != '':
            dev = ' -s '+cfgReader.deviceAT_
    
        if cfgReader.autoReconn_ != '':
            rconn = ' -a '
        
    elif mode == 'Bemused':
        if cfgReader.deviceBm_ != '':
            dev = ' -s '+cfgReader.deviceBm_
    
    elif mode == 'iViewer':
        
        if cfgReader.deviceIV_ != '':
            dev = ' -s '+cfgReader.deviceIV_
    
    else:
         if cfgReader.autoReconn_ != '':
            rcomm = ' -a '
                
    to_path = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep

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

def timerBrowseDevices():
    browseDevices('F')
    
def browseDevices(force):
    global debug, cmd_array
    
    if force == 'F' and ['scan','F'] in cmd_array:
        if debug: print 'Skip device scan'
    else:
        gtk.gdk.threads_enter()
        queueBT('scan',force)
        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), timerBrowseDevices)

def stopBtComm():
    global debug, bt, gui
    
    try:
        gobject.source_remove(gui.timer)
    except AttributeError, NameError:
        if debug: print 'Exception: BtComm 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(jDir):
    global chkCfgWin, debug
    try:
        if debug: print 'chkCfgWin',chkCfgWin.isShown
        if chkCfgWin.isShown:
            return
    except AttributeError, NameError:
        pass
    chkCfgWin = CfgChecker(jDir)

def showDetailsWin(addr,v2,v3,channels,cfgFile,isNew):
    global dwin, cfgReader 
    
    try:
        if dwin.isShown: 
            return
    except AttributeError, NameError:
        pass
    dwin = DeviceDetail(addr, v2, v3, channels, cfgFile, isNew, cfgReader.j2meDir_)

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, 5)
        gtk.gdk.threads_leave()
            
        if st == AR_AVAIL:
            
            gtk.gdk.threads_enter()
            treeiter = bt_devices.iter_next(treeiter)
            gtk.gdk.threads_leave()
    
    return 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:
            icon_theme.append_search_path('./data') 
        
        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 findTrayIconFile(name):

    return getResult('find /usr/share/pixmaps ./data /usr/share/icons /usr/share/app-install/icons/ /usr/local/share/pixmaps /opt/kde3/share/icons /opt/gnome/share/pixmaps /opt/gnome/share/icons . -name '+name+' 2>/dev/null','main')

def btVerify():
    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 debug: print 'btVerify1',hcid
    if hcid == 'NOK':
        hcid = getResult('echo \'A=`ps -ef|grep bluetoothd|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
        if debug: print 'btVerify2',hcid
    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'))

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

def main():

    global gui, cfgReader, debug, bt_devices, guiMode, guiQueue, ddQueue, 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:], "dnehotp:", ["debug", "expert", "help", "open", "tray", "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    = True
    pbar       = None
    port       = '5050'
    runUpdater = False
    statusUpdater = None
    usepybluez = True
    bt_devices = gtk.ListStore(str,str,str,str,str,str)
    
    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 ("-t", "--tray"):
            openWin = False
        if o in ("-n", "--npybluez"):
            usepybluez = False

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

    cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
    if not os.path.isdir(cfg):
        os.mkdir(cfg)
    
    cfgSet = False
    
    cfgReader = ConfigReader()
    cfgReader.setDefaultConfig()
    if os.path.exists(cfg+os.sep+'anyremote-fe.conf'):
        cfgReader.readConfig()
        cfgSet = True
    else: 
        if os.path.exists('/usr/share/anyremote/cfg-data'):
            cfgSet = True
            cfgReader.cfgDirs.append('/usr/share/anyremote/cfg-data')
        elif os.path.exists('/usr/local/share/anyremote/cfg-data'):
            cfgSet = True
            cfgReader.cfgDirs.append('/usr/local/share/anyremote/cfg-data/')
        # quick fix for ubuntu
        elif os.path.exists('/etc/anyremote/cfg-data'):
            cfgSet = 1
            cfgReader.cfgDirs.append('/etc/anyremote/cfg-data')
            
        cfgReader.j2meDir_ = getJ2MEPath()
        
        if cfgSet == 1:
           cfgReader.setAutoStartFile()

    liststore  = gtk.ListStore(str, gtk.gdk.Pixbuf, str, str, str, str, str, str, str)

    gobject.threads_init()
    
    guiQueue = Queue.Queue(0)
    ddQueue  = Queue.Queue(0)
    
    gui = gAnyRemote(openWin, cfgSet)
    gui.populateCfgFiles()
    
    if debug: 
        print 'Use translation from ',local_path
        print 'Starting backgroung threads'
        
    startUpdater(cfgReader.updateTmout_)
    startBtComm(cfgReader.browseTmout_, cfgReader.j2meDir_)
    startFrontend()
    
    if cfgReader.checkJ2MEUpdate_:
        if debug: print 'Check J2ME client updates at web'
        jv = JCVerifier(False)
        jv.start()

    gtk.main()
    
    return 0

if __name__ == "__main__":
    main()

