#!/usr/bin/env python3

"""
v 8.1

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

Copyright (C) 2007-2020 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 
"""

import locale
import gettext
import getopt
import glob
import os
import re
import signal
import socket
import sys
import threading
import _thread
import time
import http.client
import queue
import datetime

import gi
gi.require_version("Gtk", "3.0")

try:
    gi.require_version('AppIndicator3', '0.1')
except ValueError:
    pass

from gi.repository import GObject as gobject
from gi.repository import Gtk as gtk
from gi.repository import Gdk
from gi.repository.GdkPixbuf import Pixbuf
from gi.repository import GLib

try:
    from gi.repository import AppIndicator3 as appindicator
except ImportError:
    print('Warning: No support for AppIndicator3')
#try:
#    import appindicator
#except ImportError:
#    print ('Warning: No support for AppIndicator')

def sigint_handler(signal, frame):
    print('sigint_handle')
    gui.quitAction('')   

signal.signal(signal.SIGINT, sigint_handler)

#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 as 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.gettext

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

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

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

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

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'

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,sep=' ')
            
                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 = ''
	    
            try:
                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

            except (UnicodeDecodeError):
               if debug: print('File decode error ',cfgFile)
               fd.close()
               return
       
            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,'
                if self.dvSrvUseAVH_:
                    useTypes = useTypes + 'Avahi,'
            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=false\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_     = 'bluetooth:19 -log'
        self.dvSrvUseBT_   = True
        self.dvSrvUseTCP_  = True
        self.dvSrvUseWEB_  = True
        self.dvSrvUseAVH_  = True
        self.dvSrvUseADV_  = False
        self.deviceAT_     = 'rfcomm:'
        self.deviceBm_     = ''
        self.deviceIV_     = 'tcp: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='):
                        
                        self.dvSrvUseBT_  = False
                        self.dvSrvUseTCP_ = False
                        self.dvSrvUseWEB_ = False
                        self.dvSrvUseAVH_ = False
                        self.dvSrvUseADV_ = False
			
                        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 == 'Avahi':
                                self.dvSrvUseAVH_ = True
                            elif item == 'ADV':
                                self.dvSrvUseBT_  = False
                                self.dvSrvUseTCP_ = False
                                self.dvSrvUseWEB_ = False
                                self.dvSrvUseAVH_ = 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()
		
                # override
                if self.doAutoStart_ and self.autoStart_ != '':
                	self.lastCfgFile_ = self.autoStart_
                
                # 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 = "tcp:"+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_

            if connStr != '':
                sep = ','
            
            if self.dvSrvUseAVH_:
                connStr = connStr + sep + 'avahi'
        
            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('tcp:',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_

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

                if self.dvSrvUseAVH_:
                    connStr = connStr + sep + 'Avahi'

                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 < int(self.tmout):
                time.sleep(0.1)
                timer = timer + 0.1
            
            if self.runUpdater:
                if debug: print('StatusUpdater: verify start')
            
                Gdk.threads_enter()
                treeiter = liststore.get_iter_first()
                Gdk.threads_leave()
            
            while self.runUpdater and treeiter != None:
                Gdk.threads_enter()
                aRun = liststore.get_value(treeiter, 3)
                Gdk.threads_leave()
                
                if aRun != '':
                    isRun  = getResult(aRun,'updater')
                    
                    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)    
                    Gdk.threads_leave()
                    
                    putToMainQueue(['UPDATE_LIST',strIter,status])
                
                Gdk.threads_enter()   
                treeiter = liststore.iter_next(treeiter)
                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 = ''
            Gdk.threads_enter()
            try:
                item = cmd_array[0]
                del cmd_array[0] 
                ctype = item[0]
                cdata = item[1]
            except (IndexError, NameError, TypeError):
                pass
            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)

        Gdk.threads_enter()
        treeiter = bt_devices.get_iter_first()
        Gdk.threads_leave()

        while treeiter != None:
            Gdk.threads_enter()
            addr = bt_devices.get_value(treeiter, 0)
            Gdk.threads_leave()
            
            if address == addr:
                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)  
                Gdk.threads_leave()
                
                if status == AR_AVAIL and needRun != '':
                    if debug: 
                        print('run anyRemote with',needRun)
                    startAnyRemote(needRun)
                
                    return
            
                Gdk.threads_enter()
                treeiter = bt_devices.iter_next(treeiter)
                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 as 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
        except OSError as msg:
            if debug: print('BtComm: OSError',msg)
            return
        
        if debug: print('BtComm: found ',len(nearby_devices),' devices')

        availSet = getAvailableSet()
        
        for addr,name in nearby_devices:
            if debug: print(' ',addr,' - ',name)
            
            channels = ''
            
            services = bluetooth.find_service(address=addr)
            
            for svc in services:
                try:
                    if debug: print(addr,svc["name"],svc["port"],sep=' ')
                
                    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 ',len(services), data)
            print('')
        else:
            print('no services found')

        for svc in services:
            print('Service Name:    ',svc["name"])
            print('    Host:        ',svc["host"])
            print('    Description: ',svc["description"])
            print('    Provided By: ',svc["provider"])
            print('    Protocol:    ',svc["protocol"])
            print('    channel/PSM: ',svc["port"])
            print('    svc classes: ',svc["service-classes"])
            print('    profiles:    ',svc["profiles"])
            print('    service id:  ',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 as 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(homogeneous=False, spacing=0)
        self.add(vbox)

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

        ################
        hbox = addHbox(vbox)
        
        label = gtk.Label(label='  '+_('Device Name')+': '+self.model+'       ')
        hbox.pack_start(label, 0, True, 0)

        label = gtk.Label(label=_('BT Address')+': '+self.btAddress+'         ')
        hbox.pack_end(label, 0, True, 0)
        
        ################
        hbox = addHbox(vbox)
            
        label = gtk.Label(label='')
        hbox.pack_start(label, 0, True, 0)

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

        label = gtk.Label(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(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.PackType.END)
        self.cid = self.sBar.get_context_id('a')
        self.sBar.show()

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

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

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

        ################
        hbox = gtk.HBox(homogeneous=False, spacing=4)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
                                                             
        vbox1 = gtk.VBox(homogeneous=False, spacing=0)
        hbox.add(vbox1)

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

        hbox1 = gtk.HBox(homogeneous=False, spacing=4)
        vbox1.add(hbox1)
        vbox1.set_child_packing(hbox, False, True, 0, gtk.PackType.START)

        hbox2 = gtk.HBox(homogeneous=False, spacing=4)
        vbox2.add(hbox2)
        vbox2.set_child_packing(hbox, False, True, 0, gtk.PackType.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(label=_(' with icon set '))
        hbox1.pack_start(label, 0, True, 0)
        
        dummy = gtk.Label(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(homogeneous=False, spacing=4)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.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(homogeneous=False, spacing=4)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.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(homogeneous=False, spacing=4)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.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,msg = btVerify()
        if bt == 'NOK':
            if debug: print('DeviceDetail: ',msg)

            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 = GLib.timeout_add(300, self.checkQueue)

    def ok(self,w):
        global bt_devices
        
        Gdk.threads_enter()
        treeiter = bt_devices.get_iter_first()
        Gdk.threads_leave()
            
        while treeiter != None:
            Gdk.threads_enter()
            addr = bt_devices.get_value(treeiter, 0)
            Gdk.threads_leave()
            
            if self.btAddress == addr:
                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)
                Gdk.threads_leave()
                
                self.close(w)
                return
            
            Gdk.threads_enter()
            treeiter = bt_devices.iter_next(treeiter)
            Gdk.threads_leave()

        Gdk.threads_enter()
        bt_devices.append([self.btAddress,self.model,self.pname.get_text(),self.channels,self.cfgFile.get_text(),AR_AVAIL])
        Gdk.threads_leave()
        
        self.close(w)

    def close(self,w):
        global debug
        self.isShown = False
        self.hide()
        try:
            GLib.source_remove(self.ddQueueTimer)
        except (AttributeError, NameError):
            if debug: print('Exception: AttributeError GLib.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(homogeneous=False, spacing=5)
        vbox.set_border_width(10)
        self.add(vbox)

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

        self.pbar = gtk.ProgressBar()
        align.add(self.pbar)
        self.timer = GLib.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:
            GLib.source_remove(self.timer)
        except (AttributeError, NameError):
            print('Exception: Pbar ',GLib.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(homogeneous=False, spacing=0)
        self.add(vbox)
        vbox.show()

        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 1, 1, 0, gtk.PackType.START)
        hbox.show()
        
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
        hbox.add(scrolledwin)
        hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PackType.START)
        scrolledwin.show()

        self.treeview  = gtk.TreeView(model=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 as msg:
                s = None
                continue
            if debug: print('FrontEnd socket created')
                
            try:
                s.bind(sa)
                s.listen(1)
            except socket.error as 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 as 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 != '':
            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)
                
            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:
                        pass
                        
                    try:
                        #print 'Send to backend ???'
                        Gdk.threads_enter()
                        if cmdToSend:
                            # need to syncronize with GUI thread
                            if debug: print('Send to backend ',cmdToSend,"\n")
                            conn.sendall(cmdToSend)
                            cmdToSend = '';
                        Gdk.threads_leave()
                            
                    except (socket.error, NameError):
                        if debug: print('EXCEPTION 1')
                        pass
            
                if debug: print('Close connection')
                conn.close()
            
            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)
            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(homogeneous=False, spacing=0)
        self.add(vbox)
        
        self.createMenus(vbox)

        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 1, 1, 0, gtk.PackType.START)
        
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
        hbox.add(scrolledwin)
        hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PackType.START)

        self.treeview  = gtk.TreeView(model=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.SortType.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 = GLib.timeout_add (int(1000)*int(cfgReader.browseTmout_), timerBrowseDevices)

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

        topmenuitem = gtk.MenuItem(label=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
        
    
        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 !')])
 
        state,bts = btVerify()
        pkg_list.append(None,["Bluetooth service",bts])

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

        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 1, 1, 0, gtk.PackType.START)
        
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
        hbox.add(scrolledwin)
        hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PackType.START)

        self.treeview  = gtk.TreeView(model=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.SortType.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, False, True, 0)

        topmenuitem = gtk.MenuItem(label=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(homogeneous=False, spacing=0)
        self.add(box1)
       
        self.menubar = gtk.MenuBar()
        box1.pack_start(self.menubar, False, True, 0)
       
        topmenuitem = gtk.MenuItem(label=AR_FILE)
        self.menubar.add(topmenuitem)

        menu = gtk.Menu()
        topmenuitem.set_submenu(menu)
        
        addMenuItem(menu, '', gtk.STOCK_SAVE,    self.saveFile)
        addMenuItem(menu, '', gtk.STOCK_SAVE_AS, self.saveAs)
        addMenuItem(menu, '', gtk.STOCK_CLOSE,   self.closeEditWindow)
 
        box2 = gtk.VBox(homogeneous=False, spacing=10)
        box2.set_border_width(10)
        box1.pack_start(box2, True, True, 0)

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

        box2.pack_start(sw, True, True, 0)
        
        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.FileChooserAction.SAVE,
                                (gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_SAVE, gtk.ResponseType.OK))
         
        self.fdialog.set_default_response(gtk.ResponseType.OK)
        response = self.fdialog.run()
        
        if response == gtk.ResponseType.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(homogeneous=False, spacing=0)
        self.add(vbox)
        
        self.createMenus(vbox)

        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 1, 1, 0, gtk.PackType.START)
        
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
        hbox.add(scrolledwin)
        hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PackType.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.SortType.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(homogeneous=False, spacing=0)
        if guiMode == 'expert':
            vbox.add(hbox)
            vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.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(homogeneous=False, spacing=0)
            vbox.add(hbox)
            vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.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(model=self.detailsStore)
        
        self.detailsRenderer = gtk.CellRendererText()

        style = self.get_style_context()
        bg = style.get_background_color(gtk.StateFlags.NORMAL)
        self.detailsRenderer.set_property('background-gdk', bg.to_color())

        try:
            self.detailsRenderer.set_property('wrap-mode', gtk.WrapMode.WORD)
        except (AttributeError, TypeError):
            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.SelectionMode.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.PackType.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 (AttributeError, TypeError):
            pass
            
        self.set_icon(findIcon('ganyremote_small.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_ != '':
            GLib.timeout_add(500, self.autoStartBackend)
        
        self.frontEnd = None

        self.inQueueTimer = GLib.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

        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)
        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(type=gtk.WindowType.TOPLEVEL)
        self.config.set_title(_('Preferences'))
        self.config.set_size_request(730, 300)
        self.config.connect("destroy", self.closeCfg)
       

        vbox_top = gtk.VBox(homogeneous=False, spacing=0)
        self.config.add(vbox_top)
        
        notebook = gtk.Notebook()
        notebook.set_tab_pos(gtk.PositionType.TOP)
        vbox_top.add(notebook)
        
        vbox = gtk.VBox(homogeneous=False, spacing=0)
        notebook.append_page(vbox, gtk.Label(label=_('General')))
        
        vbox_server = gtk.VBox(homogeneous=False, spacing=0)
        notebook.append_page(vbox_server, gtk.Label(label=_('Server mode')))
        
        vbox_at = gtk.VBox(homogeneous=False, spacing=0)
        notebook.append_page(vbox_at, gtk.Label(label=_('AT mode')))
        
        vbox_bm = gtk.VBox(homogeneous=False, spacing=0)
        notebook.append_page(vbox_bm, gtk.Label(label=_('Bemused')))
        
        vbox_iv = gtk.VBox(homogeneous=False, spacing=0)
        notebook.append_page(vbox_iv, gtk.Label(label=_('iViewer')))
 
        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PackType.START)

        ################
        # Common tab
        ################
          
        hsep = gtk.HSeparator()
        vbox.add(hsep)
        vbox.set_child_packing(hsep, 0, 1, 0, gtk.PackType.START)
        
        ################
        hbox = addHbox(vbox)
        
        self.autoRun = gtk.CheckButton(label=_('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(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 1, 1, 0, gtk.PackType.START)

        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
        hbox.add(scrolledwin)
        hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PackType.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(model=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(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PackType.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(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PackType.START)

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

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

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

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

        self.showIView = gtk.RadioButton.new_from_widget(self.showSrv)
        self.showIView.set_label(_('iViewer'))
        vbox1.pack_start(self.showIView, True, True, 0)
        
        self.showNonavail = gtk.CheckButton(label=_('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(homogeneous=False, spacing=0)
        vbox.add(hbox)
        vbox.set_child_packing(hbox, 0, 1, 0, gtk.PackType.START)
        
        label = gtk.Label(label=_('Auto startup with'))
        hbox.pack_start(label, True, True, 0)
        
        self.autorunGnome = gtk.CheckButton(label=_('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(label=_('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(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(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(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(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(homogeneous=False, spacing=0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
        
        vbox2 = gtk.VBox(homogeneous=False, spacing=0)
        hbox.add(vbox2)
        hbox.set_child_packing(vbox2, False, True, 0, gtk.PackType.START)
        
        self.connBT = gtk.CheckButton(label=_('Use Bluetooth connection, channel '))
        vbox2.pack_start(self.connBT, True, True, 0)
        
        self.connTCP = gtk.CheckButton(label=_('Use TCP/IP connection, port'))
        vbox2.pack_start(self.connTCP, True, True, 0)
        
        self.connWEB = gtk.CheckButton(label=_('Use Web Interface, port'))
        vbox2.pack_start(self.connWEB, True, True, 0)

        self.connAVH = gtk.CheckButton(label=_('Advertise service through Avahi'))
        vbox2.pack_start(self.connAVH, True, True, 0)
        
        self.connMan = gtk.CheckButton(label=_('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.connAVH.set_active(cfgReader.dvSrvUseAVH_)
        self.connMan.set_active(cfgReader.dvSrvUseADV_)
    
        vbox4 = gtk.VBox(homogeneous=False, spacing=0)
        hbox.add(vbox4)
        hbox.set_child_packing(vbox4, True, True, 0, gtk.PackType.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.avhData = gtk.Label(label='')
        vbox4.pack_start(self.avhData, True, True, 0)
        
        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)
        self.connAVH.connect('toggled', self.typeToggled)
 
        ################
        hsep = gtk.HSeparator()
        vbox_server.add(hsep)
        vbox_server.set_child_packing(hsep, 0, 1, 0, gtk.PackType.START)

        ################
        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, 0, 1, 0, gtk.PackType.START)

        self.jLabel = gtk.Label(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.PackType.START)
        
        ################
        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, 0, 1, 0, gtk.PackType.START)
        
        self.checkJ2ME = gtk.CheckButton(label=_('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(homogeneous=False, spacing=0)
        vbox_server.add(hbox)
        vbox_server.set_child_packing(hbox, 0, 1, 0, gtk.PackType.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(homogeneous=False, spacing=0)
        vbox_at.add(hbox)
        vbox_at.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
        
        label = gtk.Label(label=_('Use connect string')+'  ')
        hbox.pack_start(label, 0, True, 0)
        
        btAddresses = []
        if cfgReader.deviceAT_ != "":
            btAddresses.append(cfgReader.deviceAT_)

        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.ComboBoxText()
        self.device_at.set_entry_text_column(0)
        for addr in btAddresses:
            self.device_at.append_text(addr)
        
        if cfgReader.deviceAT_ != "":
            self.device_at.set_active(0)
            
        hbox.pack_start(self.device_at, True, True, 0)

        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox_at.add(hbox)
        vbox_at.set_child_packing(hbox, False, True, 0, gtk.PackType.START)

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

        ################
        # Bemused tab
        ################
        hbox = gtk.HBox(homogeneous=False, spacing=0)
        vbox_bm.add(hbox)
        vbox_bm.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
        
        label = gtk.Label(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(homogeneous=False, spacing=0)
        vbox_iv.add(hbox)
        vbox_iv.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
        
        label = gtk.Label(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(homogeneous=False, spacing=0)
        vbox_top.add(hbox)
        vbox_top.set_child_packing(hbox, 0, 1, 0, gtk.PackType.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.FileChooserAction.SELECT_FOLDER,
                         (gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OPEN, gtk.ResponseType.OK))
        dialog.set_default_response(gtk.ResponseType.OK)
        response = dialog.run()
        
        if response == gtk.ResponseType.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.FileChooserAction.SELECT_FOLDER,
                                (gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OPEN, gtk.ResponseType.OK))
        dialog.set_default_response(gtk.ResponseType.OK)
        response = dialog.run()
        
        if response == gtk.ResponseType.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.DialogFlags.MODAL, 
                                       gtk.MessageType.WARNING, 
                                       gtk.ButtonsType.OK_CANCEL,
                                       _('There is no item in the list !\ngAnyRemote will not be able to manage any software !'))
            ret = dialog.run()
            if ret == gtk.ResponseType.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(int(cfgReader.updateTmout_) > 0)
             self.secLabel1.set_sensitive(int(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)
                self.connAVH.set_active(False)
                cfgReader.dvSrvUseBT_  = False
                cfgReader.dvSrvUseTCP_ = False
                cfgReader.dvSrvUseWEB_ = False
                cfgReader.dvSrvUseAVH_ = False
        
                if self.manData.get_text().strip() == '':
                    self.manData.set_text("-log -s bluetooth:19,tcp:5197,web:5080,avahi")

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

        if w == self.connAVH:
            cfgReader.dvSrvUseAVH_ = self.connAVH.get_active()
            if self.connAVH.get_active():
                self.connMan.set_active(False)
                cfgReader.dvSrvUseADV_ = False

        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())
        self.connAVH.set_sensitive(self.connTCP.get_active() or self.connWEB.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.runBtn.set_sensitive(False)
        self.runItem.set_sensitive(False)
        self.stopBtn.set_sensitive(True)
        self.stopItem.set_sensitive(True)
        
        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 = GLib.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(self,data[1],gtk.MessageType.INFO)
                elif data[0] == 'MSG_ERR':
                    message(self,data[1],gtk.MessageType.ERROR)
                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######
    #
    # 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_small.png')

        # Try appIndicator first
        try:
            
            self.appInd = appindicator.Indicator("gAnyRemote", "indicator-messages", AppIndicator.IndicatorCategory.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(label='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_small.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)

    def rightClickAction(self, icon, event_button, event_time):

        menu = gtk.Menu()

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

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

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

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

        menu.popup(None, None, 
                   lambda a,b,c,d: gtk.StatusIcon.position_menu(menu, 0, 0,icon),
                   None, event_button, event_time)

    def setTrayTooltip(self, ttip):
        if self.tray: 
            try:
                self.tray.set_tooltip_text(ttip)
            except AttributeError:
                pass

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

    def aboutAction(self, action):
    
        try:
            dialog = gtk.AboutDialog(transient_for=self)
            dialog.set_name("gAnyRemote")
            dialog.set_version("8.1")
            dialog.set_copyright('Copyright 2007-2020 Mikhail Fedotov')
            dialog.set_website("http://anyremote.sf.net/")
            dialog.set_logo(self.pixbufOn)
            dialog.set_license("GNU GPL v3")
            dialog.set_license_type(gtk.License.GPL_3_0)
            dialog.set_destroy_with_parent(True)
            dialog.connect ("response", lambda d, r: d.destroy())
            dialog.show()
        except AttributeError:
            infoMessage("gAnyRemote\nCopyright 2007-2019 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 + 'g-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:
            GLib.source_remove(self.inQueueTimer)
        except (AttributeError, NameError):
            print('Exception: GLib.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.setStatusStopped()

        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.DialogFlags.MODAL, 
                        gtk.MessageType.INFO, 
                        gtk.ButtonsType.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.ResponseType.YES:
        #        self.uploadJ2MEWeb(self)
        
   
    ##################################################################################
    #
    # Main window creation
    #
    ##################################################################################

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

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

        # ???
        try:
            addMenuItem(menu, '', gtk.STOCK_EDIT, self.openEditor)
        except AttributeError:
            addMenuItem(menu, _('Edit'), gtk.STOCK_JUSTIFY_LEFT, 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(label=_('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(label=_('Help'))
        self.menubar.add(topmenuitem)
        
        menu = gtk.Menu()
        topmenuitem.set_submenu(menu)

        # ???
        try:
            menuitem = iconMenuItem(_('About'), gtk.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()
        if treeiter != None:
            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.FileChooserAction.OPEN,
                                (gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OPEN, gtk.ResponseType.OK))
        self.fdialog.set_filename(entry.get_text())
        self.fdialog.set_default_response(gtk.ResponseType.OK)
        response = self.fdialog.run()
        
        if response == gtk.ResponseType.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(homogeneous=False, spacing=0)
    vbox.add(hbox)
    vbox.set_child_packing(hbox, False, True, 0, gtk.PackType.START)
    return hbox

def getHttp(hname,fname,tmp):
    global debug

    try:
        conn = http.client.HTTPConnection(hname,80,timeout=10)
    # old pythons (<2.6)
    except TypeError:
        conn = http.client.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'),sep=' ')
    
    ret = True
    
    if r.status == http.client.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, 'wb')
        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)
        menuitem.set_use_stock(True)
    else:
        menuitem = iconMenuItem(title, stock)
    menu.add(menuitem)
    menuitem.connect('activate', callback)
    return menuitem

def iconMenuItem(title, stock):
    menuitem = gtk.ImageMenuItem(stock)
    #menuitem.set_use_stock(True)
    menuitem.set_label(title)
    return menuitem

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_icon_name(stock, gtk.IconSize.BUTTON)
        button.set_image(im)
    except AttributeError:
        pass

def yesno(p,m):
    dialog = gtk.MessageDialog(p, gtk.DialogFlags.MODAL, gtk.MessageType.INFO, gtk.ButtonsType.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(p,m,t):
    stopPBar()
    flag = 0
    if t == gtk.MessageType.ERROR:
        flag = gtk.DialogFlags.MODAL
    dialog = gtk.MessageDialog(p, flag, t, gtk.ButtonsType.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

    Gdk.threads_enter()
    gui.treeview.set_model(None);
    liststore.clear()
    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)
    
    Gdk.threads_enter()
    for oneMode in aMode: 
        item = liststore.append([aName, pbuf, app, aRun, cfgFile, status, _(oneMode), _(aType), aDesc])
    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():
    global debug
    if debug: print('killall -2 anyremote')
    os.system('killall -2 anyremote > /dev/null')


def startAnyRemote(cfg_file):
    global debug, cfgReader

    if debug: print('startAnyRemote',cfg_file)

    if cfg_file == '':
        errorMessage(_('Can not start anyRemote. No configuation file specified!'))
        return

    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:
        Gdk.threads_enter()
        queueBT('scan',force)
        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 = GLib.timeout_add (int(1000*tmout), timerBrowseDevices)

def stopBtComm():
    global debug, bt, gui
    
    try:
        GLib.source_remove(gui.timer)
    except (AttributeError, NameError):
        if debug: print('Exception: BtComm GLib.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

    Gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    Gdk.threads_leave()

    s = []
    while treeiter != None:
        Gdk.threads_enter()
        addr = bt_devices.get_value(treeiter, 0)
        st   = bt_devices.get_value(treeiter, 5)
        Gdk.threads_leave()
            
        if st == AR_AVAIL:
            
            Gdk.threads_enter()
            treeiter = bt_devices.iter_next(treeiter)
            Gdk.threads_leave()
    
    return s

def getDevSet():

    global bt_devices

    Gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    Gdk.threads_leave()

    s = []
    while treeiter != None:
        Gdk.threads_enter()
        addr = bt_devices.get_value(treeiter, 0)
        s.append(addr)
        treeiter = bt_devices.iter_next(treeiter)
        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.IconTheme.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:
        try:
           if debug: print('Can not find ',iName,' Use default.')
               
           pixbuf = icon_theme.load_icon("fileopen", 16, 0)
        except:
           # 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:
                  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():
    bts = _('Active')
    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)
        if hcid == 'OK':
            hcid = getResult('echo \'A=`ps -ef|grep bluetoothd|grep "\-C"|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
            if hcid == 'NOK':
                bts = _('Bluetooth connection will not work. It needs to run bluetoothd daemon with -C option')
        else:
            bts = _('Not active')
     
    return hcid,bts

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, Pixbuf, str, str, str, str, str, str, str)
    
    guiQueue = queue.Queue(0)
    ddQueue  = queue.Queue(0)
    
    gui = gAnyRemote(openWin, cfgSet)
    gui.entry.set_text(cfgReader.lastCfgFile_)
    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()

