#!/usr/bin/env python

"""
v 5.13

kAnyRemote
KDE GUI for anyRemote - a bluetooth remote for your PC.

Copyright (C) 2007-2011 Mikhail Fedotov <anyremote@mail.ru>

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty ofF
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
"""

import gettext
import glob
import httplib
import locale
import os
import re
import signal
import socket
import SocketServer
import sys
import sys
import thread
import threading
import time

#Translation stuff

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

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

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

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

langs = []

lc = ''
encoding = ''

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

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

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

APP_NAME = "kanyremote"

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

try:
    from PyQt4.QtGui  import *
    from PyQt4.QtCore import *
except ImportError:
   print 'Install PyQt4 first !!!'
   sys.exit()

try:
    from PyKDE4.kdecore import KAboutData, KCmdLineArgs, KCmdLineOptions, KLocalizedString, ki18n  
    from PyKDE4.kdeui import KApplication, KIcon, KIconLoader, KSystemTrayIcon, KAboutApplicationDialog, KTextEdit
except ImportError:
   print 'Install PyKDE4 first !!!'
   sys.exit()

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

def _tr(string):
    ob = QObject()
    return ob.trUtf8(_(string))

#
# String constants (not all!)
#
AR_INSTALLED    = _tr('Installed')
AR_NOTINSTALLED = _tr('Not installed')

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

AR_CONN_DEV = _tr('Connecting to device')
AR_WAIT_OPS = _tr('Wait other operations to finish')

signal.signal(signal.SIGINT, signal.SIG_DFL)
	   
##################################################################################
#
# Java client uploader
#
##################################################################################
class JCUploader(threading.Thread):

    def __init__(self, parentWidget):
	threading.Thread.__init__(self) 
	self.receiver = parentWidget

    def run(self):
        global debug, jup
	
        if debug: print 'JCUploader starting'
        
	self.run = True
	
	stopPBar (self.receiver)
        startPBar(self.receiver,_tr('Downloading')+' anyRemote-16.jad')
	
	ret = True
        
	if self.run:         ret = uploadJavaWebGui(self.receiver,"anyRemote-16.jad", True)
	if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-16.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-16b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-16b.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-32.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-32.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-32b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-32b.jar")

        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-48.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-48.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-48b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-48b.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-64.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-64.jar")

        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-64b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-64b.jar")
 
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-128.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-128.jar")

        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-128b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-128b.jar")

        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote.jar")
	
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-nojsr82.jad", True)
        if self.run and ret: ret = uploadJavaWebGui(self.receiver,"anyRemote-nojsr82.jar")
    
        if self.run: stopPBar(self.receiver)
	
	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

##################################################################################
#
# Java client verifier
#
##################################################################################
class JCVerifier(threading.Thread):

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

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

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

	os.system('echo \"'+curdate+'\" > $HOME/.anyRemote/javaclient.checked')
	newver = checkJavaClientUpdate(self.receiver);
	
	if debug: print 'JCVerifier: upload done '+newver
	
	if self.anyway:    
            stopPBar(self.receiver)
	
	if newver == "":
	    if self.anyway:
		sendEvent(self.receiver, 20015, _tr("No updates for java client were found."))
	# newver == "-1" in case of connection absense
	elif newver != "-1": 
	    sendEvent(self.receiver, 20014, '')
	
	self = None

##################################################################################
#
# IViewer GUI uploader
#
##################################################################################
class IVUploader(threading.Thread):

    def __init__(self,receiver):
	threading.Thread.__init__(self) 
	self.receiver = receiver

    def run(self):
        global debug
	
        if debug: print 'IVUploader starting'
	
        stopPBar(self.receiver)
	startPBar(self.receiver,_tr('Downloading')+' anyremote-iviewer.tgz')

        uploadIViewerGui(self.receiver)
        stopPBar(self.receiver)
	
	if debug: print 'IVUploader: upload done'
	
	self = None

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

    def __init__(self, receiver, cReader):
	threading.Thread.__init__(self)
	self.receiver = receiver
	self.cfgDirs  = cReader.cfgDirs
	self.apps     = cReader.showApps_
	self.cust     = cReader.showCustom_
	self.ex       = cReader.showExamples_ 
	self.na       = cReader.showNonavail_    
	self.at       = cReader.showAt_
	self.srv      = cReader.showSrv_   
	self.bm       = cReader.showBm_   
	self.iv       = cReader.showIView_   

    def run(self):
        global debug, appData
	
	time.sleep(1)
	
	if debug: print 'CfgFileReader.run'
	
        appData.clear()
        
	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]+$")

	numProcessed = 0
	for cfgDir in self.cfgDirs:
	    
	    if cfgDir == '':
	        continue
	    if debug: 
	        print 'Collect files in '+cfgDir
	    
	    self.idx = 0
	    if os.path.isfile(cfgDir):
	        self.processOneFile(cfgDir)
		
		numProcessed = numProcessed+1
		sendEvent(self.receiver, 20017, numProcessed)
	    else:
	        for root, dirs, files in os.walk(cfgDir):
                
		    paths = root.split(os.sep)
		    if root.endswith('Utils') or paths[len(paths)-2] == 'Icons': 
		       if debug: print 'skip dir',root
		       continue

	            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
			sendEvent(self.receiver, 20017, numProcessed)
			
	# start StatusUpdater if needed
	sendEvent(self.receiver, 20007, '')
	    
    def processOneFile(self,cfgFile):
        global debug, iconsK, appData
	
        fd = None
        try:
	    fd = open(cfgFile,'r')
        except IOError:
            pass
            
	if fd:
	    aName    = None
	    aInst    = ''
	    aRun     = ''
	    aIcon    = ''
	    aType    = None
	    aDesc    = ''
	    aVers    = ''
	    aModes   = ''
	    aDevice  = ''
	    aBemused = ''
	
            for line in fd:
	
		if self.regExp.match(line):

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

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

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

	    	if self.regExpAT.match(line):
	    	    aDevice = 'a'

	    	if self.regExpB.match(line):
	    	    aBemused = 1
	    
            if (not aName) and (not aType):
               if debug: print 'Not a configuration file. Skip '+cfgFile
               fd.close()
               return
            
	    aMode = ['Server']    
	    if aModes == '': 
	        if aBemused == 1:
		    aMode = ['Bemused']
	        elif aDevice == 'a':
		    aMode = ['AT']
	    else:
	        aMode = [] 
		# not use aModes.split(',') to make more strict control
	        if aModes.find('Server') >= 0:
		    aMode.append('Server')

	        if aModes.find('Bemused') >= 0:
		    aMode.append('Bemused')
	        
		if aModes.find('AT') >= 0:
		    aMode.append('AT')
		
	        if aModes.find('iViewer') >= 0:
		    aMode.append('iViewer')
	    	
	    if aName == '' or aName == None:
	    	aName = os.path.basename(cfgFile)
	    	
            app = aInst
	    if aInst == '':
	    	isInst = 'OK'
	    else:
                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 self.na:
	        show1 = 0
	    elif isInst == AR_NOINFO:
	    	status = ''

	    if 'Server' in aMode and not self.srv:
	    	aMode.remove('Server')
	    
	    if 'AT' in aMode and not self.at:
	    	aMode.remove('AT')
 	    
	    if 'Bemused' in aMode and not self.bm:
	    	aMode.remove('Bemused')
	
	    if 'iViewer' in aMode and not self.iv:
	    	aMode.remove('iViewer')
	    	
	    if len(aMode) > 0:
	    	show = 1
	    else:
	    	show = 0
	    	
	    if aType == 'Application' and not self.apps:
	    	show2 = 0
	    elif aType == 'Custom' and not self.cust:
	    	show2 = 0
	    elif aType == 'Example' and not self.ex :
	    	show2 = 0
	    elif aType == '':
	    	show2 = 0
		    
            if show == 1 and show1 == 1 and show2 == 1:
		if debug: print 'Proceed '+aName
	
	    	if aIcon == '':
	    	    aIcon = 'document-open.png'
		
                isRun = AR_NOINFO
	    	if aRun != '':
	    	    isRun  = getResult(aRun,'reader')

		for oneMode in aMode: 
		    appData[self.idx] = [aName, aIcon, app, aRun, isRun, cfgFile, status, _tr(oneMode), _tr(aType), aDesc]
		    self.idx = self.idx + 1
		
	    else:
		if debug: print 'Skip '+aName
	    	 
	    fd.close()
	    
##################################################################################
#
# Device Browser
#
##################################################################################
class DeviceBrowser(QMainWindow):

    def __init__(self,parent = None,fl = 0):
        QMainWindow.__init__(self)
        
	self.receiver = parent

        self.setCentralWidget(QWidget(self))
        DeviceBrowserLayout = QGridLayout(self.centralWidget())

        self.treeview = QTreeWidget(self.centralWidget())
	self.treeview.setColumnCount(4)
	self.treeview.headerItem().setText(0,_tr("Name")+"    ")
	self.treeview.headerItem().setText(0,_tr("Device Name")+"    ")
	self.treeview.headerItem().setText(0,_tr("Address")+"    ")
	self.treeview.headerItem().setText(0,_tr("Status")+"    ")
	
	self.treeview.header().setResizeMode(0,QHeaderView.ResizeToContents)
	self.treeview.header().setResizeMode(1,QHeaderView.ResizeToContents)
	self.treeview.header().setResizeMode(2,QHeaderView.ResizeToContents)
	self.treeview.header().setResizeMode(3,QHeaderView.Stretch)

        DeviceBrowserLayout.addWidget(self.treeview,0,0)

        self.scanAction    = QAction(loadIcon("zoom-in",     "filefind"),  _tr("Scan for devices"), self)
        self.detailsAction = QAction(loadIcon("configure",   "configure"), _tr("Details"), self)
        self.deleteAction  = QAction(loadIcon("edit-delete", "editdelete"),_tr('Delete'), self)
        self.closeAction   = QAction(loadIcon("dialog-close","fileclose"), _tr('Close'), self)
        
        self.MenuBar = self.menuBar()

        self.fileMenu = self.MenuBar.addMenu(_tr("File"))
        self.fileMenu.addAction(self.scanAction)
        self.fileMenu.addAction(self.detailsAction)
        self.fileMenu.addAction(self.deleteAction)
        self.fileMenu.addAction(self.closeAction)

        self.languageChange()

        self.resize(QSize(500,250).expandedTo(self.minimumSizeHint()))

        self.connect(self.scanAction,   SIGNAL("triggered()"),self.scan)
        self.connect(self.detailsAction,SIGNAL("triggered()"),self.details)
        self.connect(self.deleteAction, SIGNAL("triggered()"),self.deleteDev)
        self.connect(self.closeAction,  SIGNAL("triggered()"),self.closeAct)

	self.connect(self.treeview,SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'), self.listDClicked)
	
	self.treeview.setSelectionMode(QAbstractItemView.SingleSelection)
	self.treeview.sortByColumn(0,Qt.AscendingOrder)
	
	self.populateDeviceList()

    def languageChange(self):
        self.setWindowTitle(_tr("Device Browser"))
        self.treeview.headerItem().setText(0,_tr("Name"))
        self.treeview.headerItem().setText(1,_tr("Device Name"))
        self.treeview.headerItem().setText(2,_tr("Address"))
        self.treeview.headerItem().setText(3,_tr("Status"))
        self.treeview.clear()

        self.scanAction.setText(_tr("Scan for devices"))
        self.detailsAction.setText(_tr("Details"))
        self.deleteAction.setText(_tr('Delete'))
        self.closeAction.setText(_tr('Close'))
        self.fileMenu.menuAction().setText(_tr("File"))
	
	self.detailsWin = None
	self.selected = None

    def populateDeviceList(self):
        global bt_devices
	self.treeview.clear()
	
	for k, v in bt_devices.iteritems():
            lvi = QTreeWidgetItem(self.treeview)
            lvi.setText(0,bt_devices[k][2])       
            lvi.setText(1,bt_devices[k][1])
            lvi.setText(2,bt_devices[k][0])
            lvi.setText(3,bt_devices[k][5])

    def scan(self):
	stopPBar (self.receiver) 
	startPBar(self.receiver,_tr('Scanning'))
        browseDevices('T')

    def details(self):
        global bt_devices
	
	idx = 0
	item = None
        while idx < self.treeview.topLevelItemCount():
	    if self.treeview.isItemSelected(self.treeview.topLevelItem(idx)):
		item = self.treeview.topLevelItem(idx)
		break
	    idx = idx + 1 

    	if item == None:
	    return
	try:
	    row = bt_devices[str(item.text(2))]
	except KeyError:
	    print 'DeviceBrowser.details: KeyError'
	    return
	    
        showDetailsWin(self.receiver,[row[0],row[1],row[2],row[3],row[4],False])

    def listDClicked(self, listItem, column):
	self.details()

    def deleteDev(self):
        global bt_devices
 	
	idx = 0
        while idx < self.treeview.topLevelItemCount():
	    if self.treeview.isItemSelected(self.treeview.topLevelItem(idx)):
		btAddr = str(self.treeview.takeTopLevelItem(idx).text(2))
		
		if btAddr in bt_devices:
                    del bt_devices[btAddr]
		
		break
	    idx = idx + 1 

    def closeEvent(self, event):
        self.closeAct()
	
    def closeAct(self):
        self.hide()
	saveDevices()

    def customEvent(self,event):
        if event.type() == 30000:
           self.populateDeviceList()

##################################################################################
#
# Device Details
#
##################################################################################
class DeviceDetail(QMainWindow):
    def __init__(self, ba, m, n, channels, cfgFile, is_new, jDir, receiver):
        QMainWindow.__init__(self)
        self.statusBar()
	
	self.receiver = receiver

	self.model     = str(m).replace('\n','')
	self.dname     = str(n).replace('\n','')
	self.btAddr    = str(ba)
	self.channels  = channels
	self.cfile     = str(cfgFile)
	self.isNew     = str(is_new)
	self.midletDir = jDir

        self.setCentralWidget(QWidget(self))
        DeviceDetailLayout = QGridLayout(self.centralWidget())

        self.deviceName = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.deviceName,0,0)
	
        self.deviceNameValue = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.deviceNameValue,0,1)

        self.btAddress = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.btAddress,0,3,1,2)
	
        self.btAddressValue = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.btAddressValue,0,5,1,2)

        self.specifyName = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.specifyName,1,0)
	
        self.devName = QLineEdit(self.centralWidget())
        DeviceDetailLayout.addWidget(self.devName,1,1,1,6)

        self.runWhen = QCheckBox(self.centralWidget())
	self.runWhen.setToolTip(_tr('anyRemote will start only if no other instances of anyRemote are running'))
        DeviceDetailLayout.addWidget(self.runWhen,2,0,1,3)
	
        self.fileWhen = QLineEdit(self.centralWidget())
        DeviceDetailLayout.addWidget(self.fileWhen,3,0,1,6)
        self.choose = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.choose,3,6)

	self.kSeparator1 = QFrame(self.centralWidget())
        self.kSeparator1.setFrameShape(QFrame.HLine)
        self.kSeparator1.setFrameShadow(QFrame.Sunken)
        self.kSeparator1.setFrameShape(QFrame.HLine)
        DeviceDetailLayout.addWidget(self.kSeparator1,4,0,1,6)

        self.uploadjava = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.uploadjava,5,0)
	
        self.iSet = QLabel(self.centralWidget())
        DeviceDetailLayout.addWidget(self.iSet,5,1)
	
        self.buttons = QButtonGroup(self.centralWidget())
	
        self.sz16 = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.sz16,5,2)
	self.sz16.setChecked(True)

        self.sz32 = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.sz32,5,3)

        self.sz48 = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.sz48,5,4)

        self.sz64 = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.sz64,5,5)
 
        self.sz128 = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.sz128,5,6)

        self.szAll = QRadioButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.szAll,6,2,1,2)
	
	self.buttons.addButton(self.sz16)
	self.buttons.addButton(self.sz32)
	self.buttons.addButton(self.sz48)
	self.buttons.addButton(self.sz64)
	self.buttons.addButton(self.sz128)
	self.buttons.addButton(self.szAll)
	
	self.sz32.setChecked(True)

        self.uplJad = QCheckBox(self.centralWidget())
	self.uplJad.setToolTip(_tr('Can be useful for Samsung phones'))
        DeviceDetailLayout.addWidget(self.uplJad,7,0,1,2)

        self.bigTitleIcon = QCheckBox(self.centralWidget())
	self.bigTitleIcon.setToolTip(_tr('16x16 and 64x64 title icons are available'))
        DeviceDetailLayout.addWidget(self.bigTitleIcon,7,2,1,4)
	
	self.noJsr82 = QCheckBox(self.centralWidget())
	self.noJsr82.setToolTip(_tr('Can be used on WinMobile devices'))
        DeviceDetailLayout.addWidget(self.noJsr82,8,0,1,4)

        self.ping = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.ping,9,0)
        self.testat = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.testat,9,1,1,2)

        self.close = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.close,9,4,1,2)
        self.ok = QPushButton(self.centralWidget())
        DeviceDetailLayout.addWidget(self.ok,9,6)

        self.languageChange()
        
	self.connect(self.choose,     SIGNAL("clicked()"),self.chooseAction)
	self.connect(self.ping,       SIGNAL("clicked()"),self.pingAction)
        self.connect(self.testat,     SIGNAL("clicked()"),self.testatAction)
        self.connect(self.uploadjava, SIGNAL("clicked()"),self.uploadjAction)
        self.connect(self.close,      SIGNAL("clicked()"),self.closeAction)
        self.connect(self.ok,         SIGNAL("clicked()"),self.okAction)
        
	self.connect(self.runWhen,    SIGNAL("toggled(bool)"),self.runWhenChecked)
	
	self.connect(self.szAll,     SIGNAL("toggled(bool)"),self.clicked_szAll)
	self.connect(self.bigTitleIcon, SIGNAL("toggled(bool)"),self.clicked_bti)
	self.connect(self.noJsr82,  SIGNAL("toggled(bool)"),self.clicked_nojsr82)

	self.deviceNameValue.setText(self.model)
	self.btAddressValue.setText(self.btAddr)
	self.devName.setText(self.dname);
	
	if self.cfile == '':
	   self.fileWhen.setEnabled(False)
	   self.choose.setEnabled(False)
	else:
	   self.fileWhen.setEnabled(True)
	   self.fileWhen.setText(self.cfile)
	   self.runWhen.setChecked(True)
	   self.choose.setEnabled(True)
	   
	if not os.path.isdir(self.midletDir): 
	    self.uploadjava.setEnabled(False)
	    self.uploadjava.setToolTip(_tr('It needs to install anyremote-J2ME-client package first'))

 	bt = btVerify(self.receiver,False)
	if bt == 'NOK': 
	    print 'DeviceDetail: Bluetooth not active'
	    
	    self.ping.setEnabled(False)
	    self.ping.setToolTip(_tr('Bluetooth service is not active'))
	    self.testat.setEnabled(False)
	    self.testat.setToolTip(_tr('Bluetooth service is not active'))
	    self.uploadjava.setEnabled(False)
	    self.bigTitleIcon.setEnabled(False)

    def runWhenChecked(self,w):
	if self.runWhen.isChecked():
	   self.fileWhen.setEnabled(True)
	   self.choose.setEnabled(True)
	else:
	   self.fileWhen.setEnabled(False)
	   self.fileWhen.setText('')
	   self.choose.setEnabled(False)

    def clicked_szAll(self,w):
        if self.szAll.isChecked():
	   self.bigTitleIcon.setChecked(False)

    def clicked_bti(self,w):
	if self.szAll.isChecked() and not self.noJsr82.isChecked():
	   self.bigTitleIcon.setChecked(False)
	   	   
        if not self.bigTitleIcon.isChecked():
	   self.noJsr82.setChecked(False)

    def clicked_nojsr82(self,w):
        
	self.szAll.setEnabled(not self.noJsr82.isChecked())
        self.sz16.setEnabled (not self.noJsr82.isChecked())
        self.sz32.setEnabled (not self.noJsr82.isChecked())
        self.sz48.setEnabled (not self.noJsr82.isChecked())
        self.sz64.setEnabled (not self.noJsr82.isChecked())

        if self.noJsr82.isChecked():
           self.bigTitleIcon.setChecked(True)
    
    def chooseAction(self):
    	global chooserWin
	chooserWin = Chooser()
	chooserWin.show()

    def closeEvent(self,arg):
        self.closeAction()

    def closeAction(self):
        self.hide()
    
    def sendReRead(self):
    	global browserWin
	sendEvent(browserWin,30000," ") 
    
    def okAction(self):
    	global bt_devices

	for k, v in bt_devices.iteritems():
	    
	    row = bt_devices[k]
	    addr = row[0]
	    
	    if self.btAddr == addr:

	    	if self.devName.text() != row[2]:
	            row[2] = self.devName.text()
		    
	    	if self.model != row[1]:
	           row[1] = self.model

		cf = self.fileWhen.text()
	    	if cf != row[4]:
	            row[4] = cf
		
		self.sendReRead()
		self.hide()
		return

	bt_devices[self.btAddr] = [self.btAddr,self.model,str(self.devName.text()),self.channels,str(self.fileWhen.text()),AR_AVAIL]

	self.sendReRead()
        self.hide()
    
    def testatAction(self):
        global debug
	if debug: print 'Queue test AT'
	    
	stopPBar (self.receiver) 
	startPBar(self.receiver,AR_WAIT_OPS)
	queueBT('test_at',self.btAddr)
    
    def uploadjAction(self):
        global debug
	if debug: print 'Queue push request'
	
	sz = '16'
	if self.noJsr82.isChecked():
	    sz = 'nojsr82'
	elif self.szAll.isChecked():
	    sz = ''
	else:
	    if self.sz32.isChecked():
	       sz = '32'
	    elif self.sz48.isChecked():
	       sz = '48'
	    elif self.sz64.isChecked():
	       sz = '64'
	    elif self.sz128.isChecked():
	       sz = '128'
	       
	    if self.bigTitleIcon.isChecked():
	       sz = sz+'b'
	   
	push = 'pushjar'
	if self.uplJad.isChecked():
	    push = 'pushjad'
	   
	stopPBar (self.receiver) 
	startPBar(self.receiver,AR_WAIT_OPS)
	queueBT(push+sz,self.btAddr)
    
    def pingAction(self):
        global debug
	if debug: print 'Queue ping request'

	stopPBar (self.receiver) 
	startPBar(self.receiver,_tr('Wait ping results'))
	queueBT('ping',self.btAddr)
	
    def setStatustext(self,text):
        self.statusBar().clearMessage()
        self.statusBar().showMessage(text)

    def customEvent(self,event):
        if event.type() == 31000:
	    self.cfile = event.getData()
	    self.fileWhen.setText(self.cfile)
        elif event.type() == 31100:
	    self.setStatustext(event.getData())

    def languageChange(self):
        self.setWindowTitle(_tr("Device Parameters"))
        self.deviceNameValue.setText("")
        self.btAddress.setText(_tr("BT address")+': ')
        self.btAddressValue.setText("")
        self.deviceName.setText(_tr("Device Name")+':')
        self.specifyName.setText(_tr("Specify Name")+': ')
        self.iSet.setText(_tr(" with icon set "))
        self.runWhen.setText(_tr("Run anyRemote when discovered"))
        self.bigTitleIcon.setText(_tr("use big title icon"))
        self.noJsr82.setText(_tr("use version without JSR-82"))
        self.uplJad.setText(_tr("Also upload JAD"))
        self.sz16.setText("16x16")
        self.sz32.setText("32x32")
        self.sz48.setText("48x48")
        self.sz64.setText("64x64")
        self.sz128.setText("128x128")
        self.szAll.setText(_tr("with all icon sets"))
        self.choose.setText(_tr('Choose'))
        self.ping.setText(_tr("Ping"))
        self.uploadjava.setText(_tr("Upload Java"))
        self.testat.setText(_tr("Test AT"))
        self.close.setText(_tr('Close'))
        self.ok.setText(_tr('OK'))

##################################################################################
#
# Configuration checker
#
##################################################################################
class CfgChecker(QMainWindow):

    def __init__(self,parent = None,fl = 0):
    
        global cfgReader
	
	self.receiver = parent
        
        QMainWindow.__init__(self)

        self.setCentralWidget(QWidget(self))
        CfgCheckerLayout = QGridLayout(self.centralWidget())

        self.treeview = QTreeWidget(self.centralWidget())
	self.treeview.setColumnCount(2)
	self.treeview.headerItem().setText(0,_tr("Package")+"    ")
	self.treeview.headerItem().setText(1,_tr("Status")+"	 ")
	
	self.treeview.header().setResizeMode(0,QHeaderView.ResizeToContents)
	self.treeview.header().setResizeMode(1,QHeaderView.Stretch)

        CfgCheckerLayout.addWidget(self.treeview,0,0)

        self.closeAction   = QAction(loadIcon("dialog-close","fileclose"), _tr("Close"), self)

        self.MenuBar = self.menuBar()

        self.fileMenu = self.MenuBar.addMenu(_tr("File"))
        self.fileMenu.addAction(self.closeAction)
 
        self.languageChange()

        self.resize(QSize(450,250).expandedTo(self.minimumSizeHint()))

        self.connect(self.closeAction,  SIGNAL("triggered()"),self.closeAct)
	
	self.treeview.setSelectionMode(QAbstractItemView.SingleSelection)
	self.treeview.setSortingEnabled(True)
	self.treeview.sortByColumn(0,Qt.DescendingOrder)
        self.treeview.setRootIsDecorated(False)
	
    	pbs = AR_NOTINSTALLED
	if pybluez: pbs = AR_INSTALLED
	
        ars = isInstalled('anyremote')
        if ars == 'NOK':
	    ars = AR_NOTINSTALLED
        else:
            ars = AR_INSTALLED

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

        jDir = getJ2MEPath()
        jVer = ''
 	ajs = AR_INSTALLED
        if jDir == '':
	    ajs = AR_NOTINSTALLED
        else:
            jVer = getJavaClientVersion(jDir+os.sep+'anyRemote-16.jad')
	    
        if jDir == os.environ.get("HOME")+os.sep+'.anyRemote':
	    ajs = _tr('Downloaded')
	
	ajs = ajs+' v.'+jVer

        ahs = isInstalled('anyremote2html')
        if ahs == 'NOK':
	    ahs = AR_NOTINSTALLED
        else:
            ahs = AR_INSTALLED

	bts = btVerify(self.receiver,False)
        if bts == 'NOK':
	    bts = _tr('Not active')
        else:
            bts = _tr('Active')
	    
	webs = isInstalled('lighttpd')
        if webs == 'NOK':
	    webs = AR_NOTINSTALLED
        else:
            webs = AR_INSTALLED

        ivgui = AR_NOTINSTALLED
        if os.path.exists(jDir+os.sep+'iviewer'+os.sep+'anyremote.gui'):
            ivgui = _tr('Downloaded')
	    
    
        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"anyRemote")       
        lvi.setText(1,ars)
	
        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"Bluez utilities")       
        lvi.setText(1,bus)

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"PyBluez")       
        lvi.setText(1,pbs)

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"anyremote-J2ME-client")       
        lvi.setText(1,ajs)

	if jDir != cfgReader.javaDir_:
           lvi.setExpanded(True)
           lvi2 = QTreeWidgetItem(lvi)
           lvi2.setText(0,_tr('Warning:'))       
           lvi2.setText(1,_tr('Installation directory of anyremote-J2ME-client not specified in current setup configuration !'))

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"anyremote2html")       
        lvi.setText(1,ahs)

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"Bluetooth service")       
        lvi.setText(1,bts)

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"lighttpd")       
        lvi.setText(1,webs)

        lvi = QTreeWidgetItem(self.treeview)
        lvi.setText(0,"iViewer GUI files")       
        lvi.setText(1,ivgui)
 
    def languageChange(self):
        self.setWindowTitle(_tr("Configuration Check"))
 	self.treeview.headerItem().setText(0,_tr("Package")+"    ")
	self.treeview.headerItem().setText(1,_tr("Status")+"	 ")
        self.treeview.clear()
        item = QTreeWidgetItem(self.treeview,None)

        self.closeAction.setText(_tr('Close'))
        self.fileMenu.menuAction().setText(_tr("File"))
	
	self.cfgChkWin = None
	self.selected = None

    def closeEvent(self, event):
        self.closeAct()

    def closeAct(self):
        self.hide()

##################################################################################
#
# Choose app. to manage when phone is discovered
#
##################################################################################

class Chooser(QMainWindow):

    def __init__(self,parent = None,fl = 0):
        QMainWindow.__init__(self)

        self.setCentralWidget(QWidget(self))
        Form1Layout = QGridLayout(self.centralWidget())

        self.listView1 = QTreeWidget(self.centralWidget())
	
	self.listView1.setColumnCount(3)
	self.listView1.headerItem().setText(0,_tr("Application")+"    ")
	self.listView1.headerItem().setText(1,_tr("Mode")+"    ")
	self.listView1.headerItem().setText(2,_tr("F")+"    ")

	self.listView1.header().setResizeMode(0,QHeaderView.ResizeToContents)
	self.listView1.header().setResizeMode(1,QHeaderView.Stretch)
	
	self.listView1.setSelectionMode(QAbstractItemView.SingleSelection)
	self.listView1.hideColumn(2)
	self.listView1.sortByColumn(0,Qt.AscendingOrder)
	
	self.connect(self.listView1,SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'), self.listDClicked)
	
        Form1Layout.addWidget(self.listView1,0,0,1,2)

        self.ok = QPushButton(self.centralWidget())
        Form1Layout.addWidget(self.ok,1,0)
	
        self.cancel = QPushButton(self.centralWidget())
        Form1Layout.addWidget(self.cancel,1,1)


        self.languageChange()

        self.resize(QSize(350,400).expandedTo(self.minimumSizeHint()))

	self.connect(self.cancel, SIGNAL("clicked()"),self.cancelAction)
	self.connect(self.ok,     SIGNAL("clicked()"),self.okAction)
	
	self.populateChooseList()
    
    def populateChooseList(self):
        global appData
	
    	for k, v in appData.iteritems():
	    lvi = QTreeWidgetItem(self.listView1)
	    
	    ic = loadIcon(v[1],"document-open")	# reset if not found
	    lvi.setIcon(0,ic)
	    lvi.setText(0,v[0])	  
	    lvi.setText(1,v[7])
	    lvi.setText(2,str(k))
	    	
    def listDClicked(self, listItem, column):
	self.okAction()

    def cancelAction(self):
        self.hide()

    def okAction(self):
        global appData

	idx  = 0
	item = None
        while idx < self.listView1.topLevelItemCount():
	    item = self.listView1.topLevelItem(idx)
	    if self.listView1.isItemSelected(self.listView1.topLevelItem(idx)):
                item = self.listView1.topLevelItem(idx)
		break
	    idx = idx + 1

    	if item == None:
	    return

	try:
	    idx = int(str(item.text(2)))
	except ValueError:
	    return
	try:
	    row = appData[idx]
	except KeyError:
	    return
	
	sendEvent(dwin,31000,appData[idx][5]) 
        self.hide()
   
    def closeEvent(self, event):
        self.cancelAction()

    def languageChange(self):
        self.setWindowTitle(_tr("Choose application"))
        self.listView1.headerItem().setText(0,_tr("Application"))
        self.listView1.headerItem().setText(1,_tr("Mode"))
        self.listView1.clear()
        item = QTreeWidgetItem(self.listView1,None)

        self.cancel.setText(_tr('Close'))
        self.ok.setText(_tr('OK'))


##################################################################################
#
# Progress bar window
#
##################################################################################
class PBar(QProgressDialog):
    def __init__(self, text, steps):
        QProgressDialog.__init__(self, text, '', 0,steps)
	
	bar = QProgressBar(self)
	bar.setTextVisible(False)
	self.setBar(bar)
	self.setMinimum(0)
	self.setMaximum(10)
	self.setCancelButton(None)
	self.setAutoReset(True)
	self.setAutoClose(False)
	self.show()
	

def startPBar(receiver, text):
    sendEvent(receiver, 20019, text)	

def stopPBar(receiver):
    sendEvent(receiver, 20018, '')	
	
def writePBar(receiver,text):
    sendEvent(receiver, 20021, text)	
	
def timerPBar():
    global pbar, pbarTimer, quitFlag

    if not quitFlag:
    	try:
    	    pbar.setValue(pbar.value()+1)
    	except AttributeError, NameError:
    	    return
    	pbarTimer = QTimer.singleShot(200,timerPBar)
	
##################################################################################
#
# 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, parent, jDir):
	threading.Thread.__init__(self) 
	self.midletDir = jDir
	self.receiver  = parent

    def run(self):
        global debug, bt_devices, cmd_array
	
	self.keepRun = True
	
	if debug: print 'BtComm: run'
	
	while self.keepRun:
	
	    ctype = ''
	    cdata = ''

	    try:
                item = cmd_array[0]
	        del cmd_array[0] 
	        ctype = item[0]
	        cdata = item[1]
 	    except NameError:
	        pass
 	    except TypeError:
	        pass
	    except IndexError:
	        pass

	    
	    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(1)
		
    def setStatus(self, address, status):
        global debug, bt_devices

	for k, v in bt_devices.iteritems():
 
            if address == v[0]:
                if status != v[5]:
        	    v[5] = status
		
		needRun = v[4]  
		if status == AR_AVAIL and needRun != '':
		    if debug: print 'run anyRemote with',needRun
			
		    startAnyRemote(needRun)
		    
		try:
	    	    if browserWin != None:
			sendEvent(browserWin,30000," ") 
   		except AttributeError, NameError:
	    	    pass

    	        return

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

	availSet = getAvailableSet()
	
	for addr,name in nearby_devices:
	    if debug:
		print "  %s - %s" % (addr, name)
	
	    channels = ''
	    
	    services = bluetooth.find_service(address=addr)
	    
	    for svc in services:
	        try:
		    if debug: print addr,svc["name"],svc["port"]
		
	            if svc["name"] == 'Serial Port' or svc["name"].startswith('COM ') or svc["name"].startswith('Dial-up') or svc["name"].startswith('Dialup'):
	                
			if channels != '':
			    channels = channels+':'
			channels = channels+str(svc["port"])
		    
                except AttributeError, NameError:
    	            pass
	    if addr not in existing:
	        showDetailsWin(self.receiver,[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(self.receiver)

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

    def doPush(self, data, size, usejad):
	global debug, dwin
	if debug: print 'BtComm: obex push'

	sendEvent(dwin,31100,'') 
	stopPBar(self.receiver)   
	
	if not os.path.exists(self.midletDir):       
	    sendEvent(dwin,31100,_tr('Can not find anyremote-J2ME-client installation !'))
	    return
	
	dash = '-'
	if size == '':
	    dash = ''
	midlet = 'anyRemote' + dash + size + '.jar'
	path = self.midletDir + os.sep + midlet
	if not os.path.isfile(path):
	    sendEvent(dwin,31100,_tr('Can not find java midlet ('+midlet+_tr(') to upload !')))
	    return
		     
	sender = ''    
	if (isInstalled('gnome-obex-send') == 'OK'):
	    sender = 'gnome-obex-send -d '+data
	elif (isInstalled('bluetooth-sendto') == 'OK'):
	    sender = 'bluetooth-sendto --dest='+data
	elif (isInstalled('kbtobexclient') == 'OK'):
	    sender = 'kbtobexclient'
	else:
	    sendEvent(dwin,31100,_tr('None of gnome-obex-send, bluetooth-sendto and kbtobexclient are installed !'))
	    return
	
	ret = getResult(sender+' '+path+' &','browser')
	
	if usejad:
	    jad = 'anyRemote' + dash + size + '.jad'
	    path = self.midletDir + os.sep + jad
	    if not os.path.isfile(path):
	        sendEvent(dwin,31100,_tr('Can not find JAD file ('+jad+_tr(') to upload !')))
	        return
	    
	    ret = getResult(sender+' '+path+' &','browser')
	
    def doInfo(self,data):
	global debug
	if debug: print 'BtComm: get info'

	writePBar(self.receiver,'Connecting to device')
	
	services = bluetooth.find_service(address=data)

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

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

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

	if debug: print "got",data
	return data

    def doAT(self,data):
        global debug, dwin
	if debug: print 'BtComm: doAT'
	    
	sendEvent(dwin,31100,'')
	writePBar(self.receiver,AR_CONN_DEV)	
    	port = self.getSerialPort(data)
	if debug: print 'BtComm: port',port
        
	if port == None:
	    sendEvent(dwin,31100,_tr('Can not get port to connect to. Is there any device available ?'))
	    pass
	else:
	    sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
	    try:
	        sock.connect((data, port))
 	    except bluetooth.BluetoothError,msg:
		d = str(msg)
		print d
		stopPBar(self.receiver)
	        if d.startswith('(111,'):
		    sendEvent(dwin,31100,_tr('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 = _tr('AT mode is not supported by phone (')+status+')'
		else:
		    status = _tr('AT mode could be supported by phone (')+status+')'
	    else:
	    	status = _tr('AT mode is not supported by phone (ERROR response)')
		
            sendEvent(dwin,31100,status)
            sock.close()

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

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

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

    def run(self):
        global debug, appData
	
	if debug: print 'StatusUpdater.run',self.tmout
	self.runUpdater = True
	
	while self.runUpdater:
	    timer = 0
	    
	    # catch stop event without waiting full timeout
	    while self.runUpdater and timer < self.tmout:
	        time.sleep(0.1)
		timer = timer + 0.1
	    
	    if debug: print 'StatusUpdater: verify'
	    
	    for k, v in appData.iteritems():
	        if not self.runUpdater:
		    break
		
		aRun = v[3]
	        if aRun != '':
	    	    isRun  = getResult(aRun,'updater')
		    
		    if isRun != v[4]:
		        v[4] = isRun
		        sendEvent(self.receiver, 20006, [k,v[6],isRun])	

    def stop(self):
        global debug
	if debug: print 'StatusUpdater.stop'
        self.runUpdater = False
	   
##################################################################################
#
# Frontend to anyRemote
#
##################################################################################

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

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

    def run(self):
    	global port, cmdToSend, debug
	if debug: print 'FrontEnd thread is running', port

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

    	while self.isRun:
    	    while self.isRun:

    		try:
    		    conn, addr = s.accept()
    		    if debug: print 'accept', addr
    		    break
    		except socket.error,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 cmdToSend, debug
    	
	if debug: print 'FrontEnd processOneConnection', addr
    
        self.isConn = True
    	while self.isRun and self.isConn:
    	
    	    conn.setblocking(0)
    
    	    if debug: print 'FrontEnd.Connected by', addr
    	
    	    sendEvent(self.receiver,20003,'')
    	
    	    while self.isRun and self.isConn:
    	    	
    	    	time.sleep(0.2)
    	
    	    	data = ''
    	    	try:
    	    	    data = conn.recv(512)
    	    	    if debug: print 'Got from backend ', data
    	    	
		    if self.isRun:
		        sendEvent(self.receiver,10000,data)
    	    	
    	    	    if not data: 
    	    		if debug: print 'FrontEnd anyRemote die?'
    	    	    
		        if self.isRun:
		            sendEvent(self.receiver,20000,'') 
    	    		    self.isConn = False
    	    		break

    	    	except socket.error,msg:
    	    	    pass
    	    	
    	    	try:
    	    	    if cmdToSend:
    	    		if debug: print 'Send to backend '+cmdToSend + "\n"
    	    		conn.sendall(cmdToSend)
    	    		cmdToSend = '';
    	    	except socket.error, NameError:
    	    	    if debug: print 'FrontEnd.processOneConnection exception'
    	    	    pass
    	
    	    if debug: print 'Close connection' 
	    sendEvent(self.receiver,20012,'')  
    	    conn.close()

##################################################################################
#
# Edit window
#
##################################################################################

class EditWin(QMainWindow):
    def __init__(self,efile,parent = None,fl = 0):
        QMainWindow.__init__(self)
        
        global iconsK
	
	print "Edit ",efile
	self.eFile    = efile
	self.receiver = parent

        self.setCentralWidget(QWidget(self))
        EditWinLayout = QGridLayout(self.centralWidget())
       

        self.textEdit1 = QTextEdit(self.centralWidget())

        EditWinLayout.addWidget(self.textEdit1,0,0)

        self.saveEditor   = QAction(loadIcon("document-save",   "filesave"),  _tr("Save"),   self)
        self.saveAsEditor = QAction(loadIcon("document-save-as","filesaveas"),_tr("Save As"),self)
        self.closeEditor  = QAction(loadIcon("dialog-close",    "fileclose"), _tr("Close"),  self)
	
        self.Menu = self.menuBar()
        
	self.fileMenu = self.Menu.addMenu(_tr("File"))
        self.fileMenu.addAction(self.saveEditor)
        self.fileMenu.addAction(self.saveAsEditor)
        self.fileMenu.addAction(self.closeEditor)

        self.languageChange()

        self.resize(QSize(550,600).expandedTo(self.minimumSizeHint()))
        #self.clearWState(Qt.WState_Polished)
	
        self.connect (self.saveEditor,  SIGNAL ("triggered()"), self.saveFile)
        self.connect (self.saveAsEditor,SIGNAL ("triggered()"), self.saveAs)
        self.connect (self.closeEditor, SIGNAL ("triggered()"), self.cancel_clicked)
	
	self.loadEditFile()
	
    def loadEditFile(self):
    
        infile = None
        
	writable = False
        try:
            infile = open(self.eFile, "r")
	    writable = QFileInfo(self.eFile).isWritable()
        except IOError:
            pass
            
        if infile:
            string = infile.read()
            infile.close()
            self.textEdit1.setText(string)
	    self.textEdit1.setReadOnly(not writable)
	else:
	    self.eFile = ""

    def languageChange(self):
        self.setWindowTitle(_tr("Edit configuration file"))
        self.closeEditor.setText(_tr("Close"))
        self.saveEditor.setText(_tr("Save"))
        self.saveEditor.setShortcut(QKeySequence(_tr("Ctrl+S")))
        self.saveAsEditor.setText(_tr("Save As"))
        self.fileMenu.menuAction().setText(_tr("File"))


    def saveFile(self):
	try:
	    f=open(self.eFile, 'w')
	    if f:
	        #text = self.textEdit1.text() not work ?
	        text = self.textEdit1.document().toPlainText()
	        f.write(str(text))
	        f.close()
                self.deleteLater()   

        except IOError:
	    if self.receiver:
	        #errorMessage(self, _tr("Can not save the file !"))
		sendEvent(self.receiver, 20016, _tr("Can not save the file !"))
	    self.saveAs()
 
    def saveAs(self):
    
 	f = QFileDialog.getSaveFileName(None,"", "");
	if f:
	    self.eFile = f
	    self.saveFile()
	
    def cancel_clicked(self):
        self.deleteLater()   

    def closeEvent(self, event):
        self.cancel_clicked()
	
##################################################################################
#
# Preferences window
#
##################################################################################

class Preferences(QMainWindow):
    def __init__(self,mainWin,cfgReader,parent = None,fl = 0):

        QMainWindow.__init__(self)
 
        self.setMinimumSize(QSize(670,300))

        self.setCentralWidget(QWidget(self))
        PreferencesLayout = QGridLayout(self.centralWidget())
	
	self.tabs = QTabWidget(self.centralWidget())
        PreferencesLayout.addWidget(self.tabs,0,0,5,5)

        #############################
        ### Common tab
        #############################
	commonFrame = QFrame()
	self.tabs.addTab(commonFrame,_tr("General"))
        PreferencesCommonLayout = QGridLayout(commonFrame)

        self.dirView = QTreeWidget(commonFrame)
	self.dirView.setColumnCount(1)
	self.dirView.headerItem().setText(0,_tr("Directories"))
	self.dirView.setMinimumHeight(60)
	self.dirView.setMaximumHeight(90)
	self.dirView.setToolTip(_tr("Choose directories with configuration files and add them to the list"))
        PreferencesCommonLayout.addWidget(self.dirView,0,0,1,12)

	self.addButton = QPushButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.addButton,1,0,1,2)
        self.delButton = QPushButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.delButton,1,2,1,2)

        ###
        self.line10 = QFrame(commonFrame)
        self.line10.setFrameShape(QFrame.HLine)
        self.line10.setFrameShadow(QFrame.Sunken)
        self.line10.setFrameShape(QFrame.HLine)
        PreferencesCommonLayout.addWidget(self.line10,2,0,1,12)

        ###
        self.showInList = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.showInList,3,0,1,3)
        self.at = QRadioButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.at,3,3,1,2)
        self.srv = QRadioButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.srv,3,5,1,2)
        self.bem = QRadioButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.bem,3,7,1,2)
        self.iv = QRadioButton(commonFrame)
        PreferencesCommonLayout.addWidget(self.iv,3,9,1,2)
       
        ###
        self.appl = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.appl,4,3,1,2)
        self.custom = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.custom,4,5,1,2)
        self.examples = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.examples,4,7,1,2)
        self.nonAv = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.nonAv,4,9,1,2)
	
        ###
        self.line12 = QFrame(commonFrame)
        self.line12.setFrameShape(QFrame.HLine)
        self.line12.setFrameShadow(QFrame.Sunken)
        self.line12.setFrameShape(QFrame.HLine)
        PreferencesCommonLayout.addWidget(self.line12,5,0,1,12)
	
        ###
        self.autoStart = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.autoStart,6,0,1,4)
 	self.autoGnome = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.autoGnome,6,4,1,4)
        self.autoKDE = QCheckBox(commonFrame)
        PreferencesCommonLayout.addWidget(self.autoKDE,6,8,1,4)

        ###
	
	self.line15 = QFrame(commonFrame)
        self.line15.setFrameShape(QFrame.HLine)
        self.line15.setFrameShadow(QFrame.Sunken)
        self.line15.setFrameShape(QFrame.HLine)
        PreferencesCommonLayout.addWidget(self.line15,7,0,1,10)
			
        ###
        self.updateAppList = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.updateAppList,8,0,1,4)
        self.tmout = QLineEdit(commonFrame)
	self.tmout.setToolTip(_tr('Empty field means no update'))
        PreferencesCommonLayout.addWidget(self.tmout,8,4)
        self.secLabel1 = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.secLabel1,8,5)
	
        self.labelRunWhen = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.labelRunWhen,8,6,1,4,Qt.AlignRight)
        self.browseTmout = QLineEdit(commonFrame)
	self.browseTmout.setToolTip(_tr('Empty field means no update. Beware: Java client could fail to connect to anyRemote when browsing is in process'))
        PreferencesCommonLayout.addWidget(self.browseTmout,8,10)

        self.secLabel2 = QLabel(commonFrame)
        PreferencesCommonLayout.addWidget(self.secLabel2,8,11)

        #############################
	### Server mode tab	
        #############################
	srvFrame = QFrame()
	self.tabs.addTab(srvFrame,_tr("Server Mode"))
        PreferencesSrvLayout = QGridLayout(srvFrame)
	
        ###
        self.deviceSrvL = QLabel(srvFrame)
        PreferencesSrvLayout.addWidget(self.deviceSrvL,0,0,1,2)
        self.deviceSrv = QLineEdit(srvFrame)
        PreferencesSrvLayout.addWidget(self.deviceSrv,0,2,1,5)

        self.line11 = QFrame(srvFrame)
        self.line11.setFrameShape(QFrame.HLine)
        self.line11.setFrameShadow(QFrame.Sunken)
        self.line11.setFrameShape(QFrame.HLine)
        PreferencesSrvLayout.addWidget(self.line11,1,0,1,6)

        ###
        self.runWeb = QCheckBox(srvFrame)
        PreferencesSrvLayout.addWidget(self.runWeb,2,0,1,2)
        self.webParams1 = QLineEdit(srvFrame)
        self.webParams1.setReadOnly(True);
        PreferencesSrvLayout.addWidget(self.webParams1,2,2,1,3)
        self.webParams = QLineEdit(srvFrame)
        PreferencesSrvLayout.addWidget(self.webParams,2,5,1,2)

        ###
        self.line11 = QFrame(srvFrame)
        self.line11.setFrameShape(QFrame.HLine)
        self.line11.setFrameShadow(QFrame.Sunken)
        self.line11.setFrameShape(QFrame.HLine)
        PreferencesSrvLayout.addWidget(self.line11,3,0,1,6)

        ###
        self.jdirLabel = QLabel(srvFrame)
        PreferencesSrvLayout.addWidget(self.jdirLabel,4,0,1,2)
        self.javaDir = QLineEdit(srvFrame)
        PreferencesSrvLayout.addWidget(self.javaDir,4,2,1,4)
        self.jDir = QPushButton(srvFrame)
        PreferencesSrvLayout.addWidget(self.jDir,4,6)

        ###
	self.checkJava = QCheckBox(srvFrame)
	PreferencesSrvLayout.addWidget(self.checkJava,5,0,1,6)

        self.checkJavaNow = QPushButton(srvFrame)
	PreferencesSrvLayout.addWidget(self.checkJavaNow,5,5,1,2)
        
	self.downloadJavaNow  = QPushButton(srvFrame)
	self.downloadJavaNow.setToolTip(_tr('Files will be saved to $HOME/.anyRemote'))
        PreferencesSrvLayout.addWidget(self.downloadJavaNow,6,5,1,2)
	        
	self.empty = QLabel(srvFrame)
 	self.empty.setText('')
        PreferencesSrvLayout.addWidget(self.empty,9,0)
	
	
        #############################
	### AT mode tab	
        #############################
	atFrame = QFrame()
	self.tabs.addTab(atFrame,_tr("AT mode"))
        PreferencesATLayout = QGridLayout(atFrame)
	
        ###
        self.deviceATL = QLabel(atFrame)
        PreferencesATLayout.addWidget(self.deviceATL,0,0,1,2)
        self.deviceAT = QComboBox(atFrame)
        PreferencesATLayout.addWidget(self.deviceAT,0,2)

        ###
        self.auto_reconnect = QCheckBox(atFrame)
        PreferencesATLayout.addWidget(self.auto_reconnect,2,0,1,6)
	        
	self.empty = QLabel(atFrame)
 	self.empty.setText('')
        PreferencesATLayout.addWidget(self.empty,10,0)

        #############################
	### Bemused tab	
        #############################
	bmFrame = QFrame()
	self.tabs.addTab(bmFrame,_tr("Bemused"))
        PreferencesBmLayout = QGridLayout(bmFrame)
	
        ###
        self.deviceBmL = QLabel(bmFrame)
        PreferencesBmLayout.addWidget(self.deviceBmL,0,0,1,2)
        self.deviceBm = QLineEdit(bmFrame)
        PreferencesBmLayout.addWidget(self.deviceBm,0,2)
	
	self.empty = QLabel(bmFrame)
 	self.empty.setText('')
        PreferencesBmLayout.addWidget(self.empty,10,0)

        #############################
	### iViewer tab	
        #############################
	ivFrame = QFrame()
	self.tabs.addTab(ivFrame,_tr("iViewer"))
        PreferencesIVLayout = QGridLayout(ivFrame)

	###
        self.deviceIVL = QLabel(ivFrame)
        PreferencesIVLayout.addWidget(self.deviceIVL,0,0)
        self.deviceIV = QLineEdit(ivFrame)
        PreferencesIVLayout.addWidget(self.deviceIV,0,1,1,5)

	###
        self.ipIVL = QLabel(ivFrame)
        PreferencesIVLayout.addWidget(self.ipIVL,1,0)
	
        self.ipIV = QLineEdit(ivFrame)
        PreferencesIVLayout.addWidget(self.ipIV,1,1)
	self.ipIV.setToolTip(_tr('You need to specify the same address and port 5003 in CF iViewer setup on iPhone/iPod Touch'))
        
	self.dummy = QLabel(ivFrame)
        PreferencesIVLayout.addWidget(self.dummy,1,2)
	self.dummy.setText (':')
	
	self.portIV = QLineEdit(ivFrame)
        PreferencesIVLayout.addWidget(self.portIV,1,3)
	self.portIV.setEnabled(False)
        
	
        self.downloadIViewerNow = QPushButton(ivFrame)
	PreferencesIVLayout.addWidget(self.downloadIViewerNow,1,4,1,2)
	
	
 	self.empty = QLabel(ivFrame)
 	self.empty.setText('')
        PreferencesIVLayout.addWidget(self.empty,10,0)

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

        self.cancel = QPushButton(self.centralWidget())
        PreferencesLayout.addWidget(self.cancel,6,3)
	self.ok = QPushButton(self.centralWidget())
        PreferencesLayout.addWidget(self.ok,6,4)

        self.languageChange()

        self.resize(QSize(500,300).expandedTo(self.minimumSizeHint()))
        #self.clearWState(Qt.WState_Polished)

        self.connect(self.delButton,SIGNAL("clicked()"),self.delete_clicked)
        self.connect(self.addButton,SIGNAL("clicked()"),self.add_clicked)
        self.connect(self.jDir,     SIGNAL("clicked()"),self.chooseJavaDir)
        self.connect(self.cancel,   SIGNAL("clicked()"),self.cancel_clicked)
        self.connect(self.ok,       SIGNAL("clicked()"),self.ok_clicked)
	
        self.connect(self.checkJavaNow, SIGNAL("clicked()"),   self.checkJavaWeb)
        self.connect(self.downloadJavaNow, SIGNAL("clicked()"),self.uploadJavaWeb)
        self.connect(self.downloadIViewerNow, SIGNAL("clicked()"),self.uploadIViewer)
	
        self.connect(self.nonAv,    SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.appl,     SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.custom,   SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.examples, SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.at,       SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.srv,      SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.bem,      SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.iv,       SIGNAL("toggled(bool)"),self.filterChangedAction)
        self.connect(self.runWeb,   SIGNAL("toggled(bool)"),self.webToggledAction)
	
        self.connect(self.deviceSrv,SIGNAL("textChanged(const QString&)"),self.deviceSrvChangedAction)
        #self.connect(self.deviceAT, SIGNAL("textChanged(const QString&)"),self.deviceATChangedAction)
        self.connect(self.deviceBm, SIGNAL("textChanged(const QString&)"),self.deviceBmChangedAction)
        self.connect(self.deviceIV, SIGNAL("textChanged(const QString&)"),self.deviceIVChangedAction)
        self.connect(self.ipIV,     SIGNAL("textChanged(const QString&)"),self.ipIViewerChangedAction)

        self.connect(self.tmout,       SIGNAL("textChanged(const QString&)"),self.updateAppChangedAction)
        self.connect(self.browseTmout, SIGNAL("textChanged(const QString&)"),self.browseDevChangedAction)
        
	self.updateAppChangedAction('')
        self.browseDevChangedAction('')

	self.receiver = mainWin
	self.cReader  = cfgReader

	self.makeGuiSetup()
	
    def makeGuiSetup(self):
        global bt_devices
	
	self.appl.setChecked	(self.cReader.showApps_)
	self.custom.setChecked  (self.cReader.showCustom_)
	self.examples.setChecked(self.cReader.showExamples_)
	self.nonAv.setChecked   (self.cReader.showNonavail_)
	
	self.at.setChecked	(self.cReader.showAt_)
	self.srv.setChecked	(self.cReader.showSrv_)
	self.bem.setChecked	(self.cReader.showBm_)
	self.iv.setChecked	(self.cReader.showIView_)
	
	tm = ''
	if self.cReader.updateTmout_ > 0:
	    tm = "%s" % (self.cReader.updateTmout_)
	self.tmout.setText(tm)

	tm = ''
	if self.cReader.browseTmout_ > 0:
	    tm = "%s" % (self.cReader.browseTmout_)
	self.browseTmout.setText(tm)
	
	self.autoGnome.setChecked(os.path.exists(os.environ.get("HOME")+os.sep+'.config'+os.sep+'autostart'+os.sep+'kanyremote.desktop'))
	self.autoKDE.setChecked(os.path.exists(os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'kanyremote'))	
	
	self.auto_reconnect.setChecked(self.cReader.autoReconn_)

	self.deviceSrv.setText(self.cReader.deviceSrv_)
	
	if self.cReader.deviceAT_ != "":
	    self.deviceAT.addItem(self.cReader.deviceAT_)
	    self.deviceAT.setCurrentIndex(0)
	    
    	for k, v in bt_devices.iteritems():

    	    row = bt_devices[k]
    	    v1 = row[0]
    	    v4 = row[3]
	    
	    # use channel 1 as default
	    if v4 == "":
	        v4 = "1"
	    
	    channels = v4.split(':')
            for ch in channels:
	        if str(ch).isdigit():
		    crow = "rfcomm:"+v1+":"+ch
		    if self.cReader.deviceAT_ != crow:
	                self.deviceAT.addItem(crow)
	
	self.deviceBm.setText(self.cReader.deviceBm_)
	self.deviceIV.setText(self.cReader.deviceIV_)
	self.ipIV.setText(self.cReader.ipIV_)
	
	self.webParams.setText(self.cReader.webParams_)
	
	self.javaDir.setText(self.cReader.javaDir_)
	
	self.setWebParamsActive(self.cReader.runWeb_)
	
	self.checkJava.setChecked(self.cReader.checkJavaUpdate_)
	
	self.runWeb.setChecked(self.cReader.runWeb_ and self.cReader.deviceSrv_.startswith('socket:'))
	
	self.dirView.clear()
	for d in self.cReader.cfgDirs:
	    if d != '':
        	lvi = QTreeWidgetItem(self.dirView)
        	lvi.setText(0,d)
	
	self.addDir      = ''
	self.dirsChanged = False
	
	self.deviceIVChangedAction(self)
	
    def uploadJavaWeb(self):
        global debug,jup
	
        try:
            if jup != None:
	       if debug: print 'Uploading already active. Skip request.'
	       return
        except NameError:
            pass

        jup = JCUploader(self.receiver)
        jup.start()
	
	jdir = os.environ.get("HOME")+os.sep+'.anyRemote'
	if self.cReader.javaDir_ != jdir:
	    ret = yesno(self,_tr('Would You like to change upload java client path ?'))
	    if ret:
	        self.cReader.javaDir_ = os.environ.get("HOME")+os.sep+'.anyRemote'
		try:
		    self.javaDir.setText(self.cReader.javaDir_)
		except AttributeError:
		    # OK. config window was not yet shown
		    pass
		    
    def checkJavaWeb(self):
	jv = JCVerifier(True,self.receiver)
	jv.start()
    
    def uploadIViewer(self):
        iv = IVUploader(self.receiver)
        iv.start()

    def closeEvent(self, event):
        self.cancel_clicked()

    def languageChange(self):
        self.setWindowTitle(_tr("Preferences"))
        self.showInList.setText(_tr("Show in list : "))
	self.jdirLabel.setText(_tr("Upload java client from "))
        self.examples.setText(_tr("Examples"))
        self.appl.setText(_tr("Applications"))
        self.custom.setText(_tr("Custom Made"))
        self.srv.setText(_tr("Server-mode"))
        self.bem.setText(_tr("Bemused emulation"))
        self.at.setText(_tr("AT-mode"))
        self.iv.setText(_tr("iViewer"))
        self.nonAv.setText(_tr('Non-available'))
        self.updateAppList.setText(_tr("Update application list every"))
        self.secLabel1.setText(_tr("sec."))
        self.secLabel2.setText(_tr("sec."))
        
	self.deviceSrvL.setText(_tr("Use connect string"))
	self.deviceATL.setText (_tr("Use connect string"))
	self.deviceBmL.setText (_tr("Use connect string"))
	self.deviceIVL.setText (_tr("Use connect string"))
	
	self.ipIVL.setText (_tr("Use host ip"))
	
        self.labelRunWhen.setText(_tr("Run device browser with timeout"))
        self.runWeb.setText(_tr("Run web interface with parameters"))
        self.addButton.setText(_tr('Add'))
        self.delButton.setText(_tr('Delete'))
	self.jDir.setText(_tr('Choose'))
        self.auto_reconnect.setText(_tr("Auto reconnect"))
        self.autoGnome.setText(_tr("Gnome session"))
        self.autoStart.setText(_tr("Auto startup with"))
        self.autoKDE.setText(_tr("KDE session"))
        self.ok.setText(_tr('OK'))
        self.dirView.headerItem().setText(0,_tr("Directories"))
        self.cancel.setText(_tr('Cancel'))
        self.downloadJavaNow.setText(_tr('Download java client from Web'))
        self.checkJavaNow.setText(_tr('Check java client updates'))
        self.downloadIViewerNow.setText(_tr('Download iViewer GUI files'))
        self.checkJava.setText(_tr('Check java client updates at start'))

    def setWebParamsActiveReset(self):
	
	active = (self.runWeb.isChecked() and str(self.deviceSrv.text()).startswith('socket:'))
	self.setWebParamsActive(active)

    def setWebParamsActive(self, active):
 
 	self.webParams.setEnabled(active)

	if active:
	    self.webParams1.setText(' -a '+self.deviceSrv.text()[7:])
	else:   
            self.webParams1.setText('')

    def delete_clicked(self):
	
	idx = 0
        while idx < self.dirView.topLevelItemCount():
	    item = self.dirView.topLevelItem(idx)
	    if self.dirView.isItemSelected(item):
                self.dirView.takeTopLevelItem(idx)
		continue
		
	    idx = idx + 1 
             
	self.dirsChanged = True

    def add_clicked(self):
	f = QFileDialog().getExistingDirectory(None,_tr('Add'),self.addDir)
	self.addDir = os.path.dirname(str(f))
	
	add = True

	idx = 0
	item = self.dirView.topLevelItem(idx) 
        while item != None:
	    if self.addDir == item.text(0):
	        add = False
		break
	    idx = idx+1 
	    item = self.dirView.topLevelItem(idx)
	
	if add:
       	    lvi = QTreeWidgetItem(self.dirView)
            lvi.setText(0,str(f))

    def chooseJavaDir(self):
	f = QFileDialog().getExistingDirectory(None,_tr('Choose'),self.addDir)
	self.addDir = os.path.dirname(str(f))
	self.javaDir.setText(self.addDir)

    def deviceSrvChangedAction(self,a0):
        self.cReader.deviceSrv_ = str(self.deviceSrv.text()).strip()
	self.setWebParamsActiveReset()
    
    #def deviceATChangedAction(self,a0):
    #    self.cReader.deviceAT_ = str(self.deviceAT.text()).strip()
    # 	 self.setWebParamsActiveReset()
    
    def deviceBmChangedAction(self,a0):
        self.cReader.deviceBm_ = str(self.deviceBm.text()).strip()
	self.setWebParamsActiveReset()
    
    def deviceIVChangedAction(self,a0):
        self.cReader.deviceIV_ = str(self.deviceIV.text()).strip()

	if self.cReader.deviceIV_.startswith('socket:'):
	    self.portIV.setText(self.cReader.deviceIV_[7:])
	else:
	    self.portIV.setText('')

    def ipIViewerChangedAction(self,a0):
        self.cReader.ipIV_ = str(self.ipIV.text()).strip()

    def updateAppChangedAction(self,a0):
        self.updateAppList.setEnabled((str(self.tmout.text()).strip() != ''))
        self.secLabel1.setEnabled    ((str(self.tmout.text()).strip() != ''))
    
    def browseDevChangedAction(self,a0):
        self.labelRunWhen.setEnabled((str(self.browseTmout.text()).strip() != ''))
        self.secLabel2.setEnabled   ((str(self.browseTmout.text()).strip() != ''))

    def webToggledAction(self, w):
        active = self.runWeb.isChecked()
	if active:
	    isInst = isInstalled('anyremote2html')
	    if isInst == 'NOK':
		QMessageBox.warning(self, "kAnyRemote",
	                 _tr('anyremote2html is not installed !'),QMessageBox.Ok);
	    else:
		if str(self.deviceSrv.text()).startswith('socket:'):
		    self.webParams1.setText(' -a '+self.deviceSrv.text()[7:])
		else:
	            self.deviceSrv.setText('socket:5000')
	            self.webParams1.setText(' -a 5000')
	            self.webParams.setText(' -w 5550')
		    
	self.webParams1.setEnabled(active)
	self.webParams.setEnabled(active)

    def cancel_clicked(self):
        self.hide()
	self.makeGuiSetup()
        sendEvent(self.receiver,20005,False)

    def ok_clicked(self):
 	self.setAutoStartup("KDE",   self.autoKDE.isChecked())
	self.setAutoStartup("Gnome", self.autoGnome.isChecked())
	
	self.cReader.showApps_     = self.appl.isChecked()
	self.cReader.showCustom_   = self.custom.isChecked()
	self.cReader.showExamples_ = self.examples.isChecked()
	self.cReader.showNonavail_ = self.nonAv.isChecked()
	self.cReader.showAt_       = self.at.isChecked()
	self.cReader.showSrv_      = self.srv.isChecked()
	self.cReader.showBm_       = self.bem.isChecked()
	self.cReader.showIView_    = self.iv.isChecked()

	self.cReader.autoReconn_   = self.auto_reconnect.isChecked()
	self.cReader.runWeb_       = self.runWeb.isChecked()
	self.cReader.webParams_    = str(self.webParams.text()).strip()
	self.cReader.deviceSrv_    = str(self.deviceSrv.text()).strip()
	self.cReader.deviceAT_     = str(self.deviceAT.currentText()).strip()
	self.cReader.deviceBm_     = str(self.deviceBm.text()).strip()
	self.cReader.deviceIV_     = str(self.deviceIV.text()).strip()
	self.cReader.ipIV_         = str(self.ipIV.text()).strip()
	self.cReader.javaDir_      = str(self.javaDir.text()).strip()
	self.cReader.checkJavaUpdate_ = self.checkJava.isChecked()
	
	tm = str(self.tmout.text()).strip()
	if tm == '':
	    tm = '-1'
	if self.cReader.updateTmout_ != int(tm):
	    self.cReader.updateTmout_ = int(tm)
	    if self.cReader.updateTmout_ < 0:
	        self.cReader.updateTmout_ = -1
	    
	    # start/stop browser
	    sendEvent(self.receiver,20010,'')

	tm = str(self.browseTmout.text()).strip()
	if tm == '':
	    tm = '-1'
	if self.cReader.browseTmout_ != int(tm):
	    self.cReader.browseTmout_ = int(tm)
	    if self.cReader.browseTmout_ <= 0:
	        self.cReader.browseTmout_ = -1
	    
	    # start/stop updater
	    sendEvent(self.receiver,20011,'')
        
	self.cReader.cfgDirs = []
	
        idx = 0
	item = self.dirView.topLevelItem(idx)
	while item != None:
	    self.cReader.cfgDirs.append(str(item.text(0)))
	    idx = idx+1 
	    item = self.dirView.topLevelItem(idx)
	
	ret = QMessageBox.Ok
	if self.cReader.cfgDirs == []:
	    ret = QMessageBox.warning(self, "kAnyRemote",
	                 _tr("There is no item in the list !\nkAnyRemote will not be able to manage any software !"),QMessageBox.Ok,QMessageBox.Cancel);

	if ret == QMessageBox.Ok:
	    self.cReader.saveConfig() 
	    self.hide()
	    
	    sendEvent(self.receiver,20005,self.dirsChanged)
	    self.dirsChanged = False

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

    def setAutoStartup(self, wm, isAuto):
        if wm == 'KDE':
	    autopath = os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'kanyremote'
	    if isAuto:
	    	if not os.path.exists(autopath):
		    os.system('ln -s `which kanyremote` '+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+'kanyremote.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=kAnyRemote\n')
 	                f.write('Exec=kanyremote\n')
 	                f.write('Icon=kanyremote\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)

###############################################################################	
#
#	Handle Return/Enter in QLineEdit
#
###############################################################################	

class QLineEditEx(QLineEdit):

    def __init__(self,parent = None,toplevel = None):
        QLineEdit.__init__(self,parent)
        self.top = toplevel
        
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
            self.top.exec_clicked()
        else:
            QLineEdit.keyPressEvent(self,event)

###############################################################################	
#
#	Custom Event
#
###############################################################################	

class QEventEx(QEvent):

    def __init__(self, eid, data=None):
        QEvent.__init__(self,eid)
        self.data = data

    def getData(self):
        return self.data

###############################################################################	
#
#	kAnyRemote
#
###############################################################################	

class kAnyRemote(QMainWindow):
    def __init__(self,cfgReader,runWizard,name = None):
        QMainWindow.__init__(self)

	global app, debug, guiMode, lastCfgFile
	
	self.cReader = cfgReader
	
        self.statusBar()
	
	if debug:
	    row = 4
	else:
	    row = 3

	if guiMode == 'simple':
	    row = row - 1
	    
        if not name:
            self.setName("kAnyRemote")


        self.setCentralWidget(QWidget(self))
        kAnyRemoteLayout = QGridLayout(self.centralWidget())

        self.stop_button  = QPushButton(loadIcon("dialog-close","stop"), _tr("Stop"),  self.centralWidget())
        self.run_button   = QPushButton(loadIcon("system-run",  "run"),  _tr("Start"), self.centralWidget())
        
        kAnyRemoteLayout.addWidget(self.run_button, row,0,1,4)
        kAnyRemoteLayout.addWidget(self.stop_button,row,4,1,4)

        self.listView1 = QTreeWidget(self.centralWidget())
	self.listView1.setColumnCount(5)
	self.listView1.headerItem().setText(0,_tr("Application")+"    ")
	self.listView1.headerItem().setText(1,_tr("Status")+"	 ")
	self.listView1.headerItem().setText(2,_tr("Mode")+"    ")
	self.listView1.headerItem().setText(3,_tr("Type")+"    ")
	self.listView1.headerItem().setText(4,_tr("F")+"    ")
	
	self.listView1.header().setResizeMode(0,QHeaderView.ResizeToContents)
	self.listView1.header().setResizeMode(1,QHeaderView.ResizeToContents)
	self.listView1.header().setResizeMode(2,QHeaderView.ResizeToContents)
	self.listView1.header().setResizeMode(3,QHeaderView.Stretch)
	
	self.listView1.setSelectionMode(QAbstractItemView.SingleSelection)
	
	self.listView1.hideColumn(4)
        self.listView1.setSortingEnabled(True)
	self.listView1.sortByColumn(0,Qt.AscendingOrder)

        self.connect(self.listView1,SIGNAL('itemClicked (QTreeWidgetItem *,int)'),self.listClicked)
	self.connect(self.listView1,SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.listDClicked)
        self.connect(self.listView1,SIGNAL('currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)'), self.cursorMoved)

        kAnyRemoteLayout.addWidget(self.listView1,0,0,1,8)
        
        self.details = QTreeWidget(self.centralWidget())
	self.details.setHeaderHidden(True)
	self.details.setColumnCount(1)

        self.details.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Maximum)
        self.details.setRootIsDecorated(True)
        self.details.setSelectionMode(QAbstractItemView.NoSelection)
        self.details.setFrameStyle(QFrame.NoFrame)

	p = QPalette(self.details.palette())
	p.setColor(QPalette.Base, QApplication.palette().color(QPalette.Window))
	self.details.setPalette(p)
	
        self.connect(self.details,SIGNAL('itemExpanded(QTreeWidgetItem *)'),self.detailExpanded)
        self.connect(self.details,SIGNAL('itemCollapsed(QTreeWidgetItem *)'),self.detailCollapsed)
        
        kAnyRemoteLayout.addWidget(self.details,1,0,1,8)
  
        self.detailsHead = QTreeWidgetItem(self.details)
        self.detailsHead.setText(0,_tr("Details"))       
	self.detailsHead.setExpanded(False)
        self.detailsItem = QTreeWidgetItem(self.detailsHead)
        self.detailsItem.setText(0,'') 
	
	h = self.details.visualItemRect(self.detailsHead).height()
	if h == 0: h = 18
        self.details.setMinimumHeight(h)
        self.details.setMaximumHeight(h)

	if guiMode == 'expert':
            self.cfgFile = QLineEdit(self.centralWidget())
            kAnyRemoteLayout.addWidget(self.cfgFile,2,0,1,6)
            self.choose = QPushButton(loadIcon("document-open","fileopen"), _tr("Choose"), self.centralWidget())
            kAnyRemoteLayout.addWidget(self.choose,2,6,1,2)

	if debug:
            self.command = QLineEditEx(self.centralWidget(),self)
            kAnyRemoteLayout.addWidget(self.command,3,0,1,6)
            self.execcmd = QPushButton(loadIcon("system-run","exec"), _tr("Execute Command"), self.centralWidget())
            kAnyRemoteLayout.addWidget(self.execcmd,3,6,1,2)
            self.execcmd.setEnabled(True)


        # File menu
        self.fileExitAction = QAction(loadIcon("application-exit","exit"),     _tr("Quit"), self)
        self.edit_file      = QAction(loadIcon("document-edit",   "edit"),     _tr("Edit"), self)
        self.start          = QAction(loadIcon("system-run",      "run"),      _tr("Start"),self)
        self.stop           = QAction(loadIcon("dialog-close",    "stop"),     _tr("Stop"), self)
        self.update         = QAction(loadIcon("reload", "appointment-recurring"), _tr("Update Status"), self)
        self.close_window   = QAction(loadIcon("edit-delete", "fileclose"),    _tr("Close Window"), self)
        
        # Edit menu
        self.save_prefs = QAction(loadIcon("document-save","filesave"),   _tr("Save"),  	     self)
        self.properties = QAction(loadIcon("configure","configure"),      _tr("Preferences"),	     self)
        self.chkCfg     = QAction(loadIcon("dialog-ok-apply","button_ok"),_tr("Check Configuration"),self)
        self.dbrowser   = QAction(loadIcon("zoom-in","filefind"),         _tr("Device Browser"),     self)
        
        # Help menu
        self.helpContentsAction = QAction(loadIcon("help-about",    "help"),     _tr("Help"),  self)
        self.helpAboutAction    = QAction(loadIcon("start-here-kde","about_kde"),_tr("About"), self)
        
        self.start.setEnabled(False)

        self.Menu = self.menuBar()

        self.fileMenu = self.Menu.addMenu(_tr("File"));
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.edit_file)
        self.fileMenu.addAction(self.start)
        self.fileMenu.addAction(self.stop)
        self.fileMenu.addAction(self.update)
        self.fileMenu.addAction(self.close_window)
        self.fileMenu.addAction(self.fileExitAction)

        self.cfgMenu = self.Menu.addMenu(_tr("Setup"))
        self.cfgMenu.addAction(self.dbrowser)
        self.cfgMenu.addAction(self.properties)
        self.cfgMenu.addAction(self.chkCfg)
        self.cfgMenu.addAction(self.save_prefs)

        self.helpMenu = self.Menu.addMenu(_tr("Help"))
        self.helpMenu.addAction(self.helpAboutAction)
        self.helpMenu.addAction(self.helpContentsAction)

        self.Menu.addSeparator()

        self.languageChange()

        self.resize(QSize(370,300).expandedTo(self.minimumSizeHint()))

        self.connect(self.fileExitAction,SIGNAL("triggered()"),self.fileExit)
        self.connect(self.edit_file,     SIGNAL("triggered()"),self.edit_file_activated)
        self.connect(self.start,         SIGNAL("triggered()"),self.runAction)
        self.connect(self.stop,          SIGNAL("triggered()"),self.stopAction)
        self.connect(self.update,        SIGNAL("triggered()"),self.rescan_dirs_clicked)
        self.connect(self.close_window,  SIGNAL("triggered()"),self.close_window_clicked)
        
	self.connect(self.dbrowser  ,    SIGNAL("triggered()"),self.showBrowser)
	self.connect(self.save_prefs,    SIGNAL("triggered()"),self.saveCfg)
        self.connect(self.properties,    SIGNAL("triggered()"),self.showConfDialog)
        self.connect(self.chkCfg,        SIGNAL("triggered()"),self.showChkWin)

	self.connect(self.helpContentsAction,SIGNAL("triggered()"),self.helpContents)
        self.connect(self.helpAboutAction,   SIGNAL("triggered()"),self.helpAbout)
	
	if guiMode == 'expert':
            self.connect(self.choose,  SIGNAL("clicked()"),self.choose_clicked)
        self.connect(self.stop_button, SIGNAL("clicked()"),self.stopAction)
        self.connect(self.run_button,  SIGNAL("clicked()"),self.runAction)
        self.connect(self,             SIGNAL("destroyed()"),self.close_window_clicked)
	
	h = 500
	if debug:
	    h = 470
            self.connect(self.execcmd,SIGNAL("clicked()"),self.exec_clicked)
	
        self.resize(QSize(470,h).expandedTo(self.minimumSizeHint()))
	self.win_width = 470
	
	self.stop.setEnabled(False)
	self.stop_button.setEnabled(False)
	
	if guiMode == 'expert':
	    self.cfgFile.setText(lastCfgFile)

	self.cfgWin        = None
	self.frontEnd      = None
	self.statusUpdater = None		
	
	# will send event to start (if needed) StatusUpdater 
	#self.populateCfgFiles()	
	
	# will start device browser (if needed)
	startBtComm(self)
	
	if runWizard:
	    self.showWizard()

    def languageChange(self):
    	global debug, guiMode
    
        self.setWindowTitle("kAnyRemote")
        self.listView1.headerItem().setText(0,_tr("Application"))
        self.listView1.headerItem().setText(1,_tr("Status"))
        self.listView1.headerItem().setText(2,_tr("Mode"))
        self.listView1.headerItem().setText(3,_tr("Type"))
	if guiMode == 'expert':
            self.choose.setText(_tr('Choose'))
	if debug:
            self.execcmd.setText(_tr("Execute Command"))
	
        self.close_window.setText(_tr("Close Window"))
        self.stop_button.setText(_tr("Stop"))
        self.run_button.setText(_tr("Start"))
        self.fileExitAction.setText(_tr("Quit"))
        
	self.helpContentsAction.setText(_tr("Help"))
        
	self.helpAboutAction.setText(_tr("About"))
        
	self.edit_file.setText(_tr("Edit"))
        self.edit_file.setToolTip(_tr("Edit configuration file"))
        self.start.setText(_tr("Start"))
        self.stop.setText(_tr("Stop"))
        self.stop.setToolTip(_tr("Stop anyRemote"))
        self.save_prefs.setText(_tr("Save"))
        self.properties.setText(_tr("Preferences"))
        self.chkCfg.setText(_tr("Check Configuration"))
        self.dbrowser.setText(_tr("Device Browser"))
        
	self.fileMenu.menuAction().setText(_tr("File"))
        self.cfgMenu.menuAction().setText(_tr("Setup"))
        self.helpMenu.menuAction().setText(_tr("Help"))
  
    def showWizard(self):
   	ret = QMessageBox.information(self, "kAnyRemote",
	             _tr("This is the first time kAnyRemote runs.\nPlease specify directories with anyRemote configuration files."),QMessageBox.Ok);
	self.showConfDialog()

    def showConfDialog(self):
    	if not self.cfgWin:
            self.cfgWin = Preferences(self, self.cReader);
	self.cfgWin.show()
	self.properties.setEnabled(False)
	
	if getJ2MEPath() == '': 
	    ret  = yesno(self,_tr('Would You like to download java client from Web ?'))
	    if ret:
	        self.cfgWin.uploadJavaWeb()

    def showChkWin(self):
	showChkCfgWin(self)

    def saveCfg(self):
        self.cReader.saveConfig()
    
    def showBrowser(self):
        showBrowserWin(self)

    def getStatus(self,isRun,status):
       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
 
       return status

    def addRow(self,rowData):
        #[aName, pbuf, isRun, status, aMode, aType, idx]
       lvi = QTreeWidgetItem(self.listView1)
       
       ic = loadIcon(rowData[1],"document-open")	# reset if not found

       lvi.setIcon(0,ic)
       lvi.setText(0,rowData[0])       
       lvi.setText(1,self.getStatus(rowData[2],rowData[3]))
       lvi.setText(2,rowData[4])
       lvi.setText(3,rowData[5])
       lvi.setText(4,str(rowData[6]))
  
    def listClicked(self, listItem, column):
        global debug, lastCfgFile, appData, guiMode
	try:
	    lastCfgFile = appData[int(str(listItem.text(4)))][5]
	    desc = appData[int(str(listItem.text(4)))][9]
            self.setDetails(desc)

	    if guiMode == 'expert':
 	        self.cfgFile.setText(lastCfgFile)
	except AttributeError:
	    if debug: print 'kAnyRemote.listClicked: AttributeError'
	

    def listDClicked(self, listItem, column):
	self.listClicked(listItem, column)
	self.runAction()

    def cursorMoved(self,listItem,previous):
        global debug, lastCfgFile, appData, guiMode
	try:
	    lastCfgFile = appData[int(str(listItem.text(4)))][5]
	    desc = appData[int(str(listItem.text(4)))][9]
	    self.setDetails(desc)
	
	    if guiMode == 'expert':
 	        self.cfgFile.setText(lastCfgFile)
	except AttributeError, KeyError:
	    if debug: print 'kAnyRemote.cursorMoved: an Error'
	
    def fileExit(self):
    	global app, quitFlag, debug, jup
	
        if debug: print "kAnyRemote.fileExit"
	quitFlag = True
	
	closeDetailsWin()
	closeBrowserWin()
	closeChkCfgWin()
	
	self.stopUpdater()
	stopFrontend()
	stopBtComm()
	stopJCUploader()
	while jup != None:
	    time.sleep(0.5)
	stopPBar(self)
	
	time.sleep(0.5)
	
	if debug: print "kAnyRemote.fileExit -> app.quit"
	app.quit()

    def helpContents(self):
    
	# open web browser on docs page if found ?
	app = 'xdg-open'
	isInst = isInstalled(app) 
	if isInst == 'NOK':
	
	    app = 'firefox'
	    isInst = isInstalled(app)
	    
	    if isInst == 'NOK':
	        
		app = 'konqueror'
	        isInst = isInstalled(app)
		
		if isInst == 'NOK':
	            errorMessage(_tr('Can not find browser to show help !'))
		    return
		
	docpath = ''
	
	
	dirv = glob.glob('/usr/share/doc/'+os.sep+'anyremote*'+os.sep+'*html')
        if len(dirv) > 0 and os.path.isdir(dirv[0]):
            docpath = dirv[0]
	else:
	    dirv = glob.glob('/usr/local/share/doc/'+os.sep+'anyremote*'+os.sep+'*html')
	    if len(dirv) > 0 and os.path.isdir(dirv[0]):
                docpath = dirv[0]
	    else :
	        dirv = glob.glob('/usr/share/'+os.sep+'anyremote*'+os.sep+'*html')
		if len(dirv) > 0 and os.path.isdir(dirv[0]):
                    docpath = dirv[0]
		else:
		    dirv = glob.glob('/usr/local/share/'+os.sep+'anyremote*'+os.sep+'*html')
		    if len(dirv) > 0 and os.path.isdir(dirv[0]):
                        docpath = dirv[0]
		    else:
	                errorMessage(_tr('Can not find documentation !'))
	                return
	
	cmd = app + ' ' + docpath + os.sep + 'k-shots.html &'
	if debug: print cmd
	os.system(cmd)

    def helpAbout(self):
 	global aboutData
	a = KAboutApplicationDialog(aboutData,self)
	a.show()

    def edit_file_activated(self):
        global lastCfgFile
        if lastCfgFile:
	    self.eWin = EditWin(lastCfgFile,self)
	    self.eWin.show()

    def choose_clicked(self):
	fileName = QFileDialog.getOpenFileName(None,"", "");
	self.cfgFile.setText(fileName)

    def rescan_dirs_clicked(self):
	self.listView1.clear()
	self.populateCfgFiles()
    
    def closeEvent(self, event):
	event.ignore()
        self.close_window_clicked()
    
    def close_window_clicked(self):
        global systray
	if systray:
            self.hide()
	else:
	    self.fileExit()

    def stopAction(self):
    	global debug
        if debug: print "kAnyRemote.stopAction()"

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

	self.setStatusStopped()

    def exec_clicked(self):
    	global cmdToSend, debug
       
	if debug:
            print 'Add to queue ' + self.command.text()
            cmdToSend = self.command.text()

    def runAction(self):
	global debug, lastCfgFile

        if debug: print "kAnyRemote.runAction()"
        
	self.cReader.saveConfig()
	
	self.setStatusDisconnected()
        
        cfile = lastCfgFile
        if guiMode == 'expert':
 	     cfile = self.cfgFile.text()

	startAnyRemote(cfile)	
			    
    def restartUpdater(self):
        self.stopUpdater()
	self.startUpdater()

    def startUpdater(self):
        if self.cReader.updateTmout_ > 0:
    	    self.statusUpdater = StatusUpdater(self,self.cReader.updateTmout_)
    	    self.statusUpdater.start()

    def stopUpdater(self):
	try:
	    self.statusUpdater.stop()
	except AttributeError, NameError:
	    pass

	time.sleep(0.5)

    def showEvent(self, event):
        global debug
	if debug: print 'showEvent'
        self.populateCfgFiles()

    def resizeEvent(self, event):
        w = self.width() - self.win_width
	
	if w > -5 and w < 5: # resize is too small
	   return
	
	self.win_width = self.width()  
	desc = str(self.detailsItem.text(0)).replace('\n',' ')
	self.setDetails(desc)

    def populateCfgFiles(self):
        global debug
	if debug: print 'populateCfgFiles'
	    
	self.stopUpdater()

	cfgFileReader = CfgFileReader(self, self.cReader)
	cfgFileReader.start()
	
    def setStatustext(self,text):
        self.statusBar().clearMessage()
        self.statusBar().showMessage(text)
	
    def setStatusStopped(self):
        setTrayIcon("kanyremote_off")
	self.conn_status = 0
	
	self.setStatustext(_tr('anyRemote stopped'))
        self.stop.setEnabled(False)
	self.start.setEnabled(True)
	self.stop_button.setEnabled(False)
	self.run_button.setEnabled(True)

    def setStatusDisconnected(self):
        setTrayIcon("kanyremote_light")
	self.conn_status = 1
	self.setStatustext(_tr('Disconnected from phone'))
	
        self.stop.setEnabled(True)
	self.start.setEnabled(False)
	self.stop_button.setEnabled(True)
	self.run_button.setEnabled(False)

    def setStatusConnected(self):
        setTrayIcon("kanyremote")
	self.conn_status = 2
	
	msg = _tr('Connected to phone')
	if self.cReader.runWeb_:
	    msg = _tr('Connected') 
	self.setStatustext(msg)
	
    def listUpdate(self, data):
        #print 'listUpdate',data
	st = self.getStatus(data[2],data[1])
	
	idx = 0
	item = self.listView1.topLevelItem(idx) 
        while item != None:
	    try:
	        if int(item.text(4)) == data[0]:
	            item.setText(1,st)
	            break
            except ValueError:
	        pass
	    idx = idx+1 
	    item = self.listView1.topLevelItem(idx)

    def sliceString(self, string, font, width):

	fm =  QFontMetrics(font)
        sliced = ''
        line   = ''
	
        wordList = string.split(' ')
	for word in wordList:
	    line1 = line+' '+word
	    if fm.width(line1) > width:
	        if len(sliced) != 0:
	            sliced = sliced + '\n'
		sliced = sliced + line
		line = word
	    else:
	        line = line1
		
        return sliced + '\n' + line

    def setDetails(self, desc):
	slicedString = self.sliceString(desc, self.details.font(), self.width()-80)
        self.detailsItem.setText(0,slicedString.lstrip())
        cnt = slicedString.count('\n')
        
        if self.detailsHead.isExpanded():
	    h = self.details.visualItemRect(self.detailsHead).height()*(cnt+2)
	    if h == 0: h = 18*(cnt+2)
            self.details.setMinimumHeight(h)
            self.details.setMaximumHeight(h)

    def selectLastInList(self):
        global lastCfgFile
    
        idx = None
    	for k, v in appData.iteritems():
	    if v[5] == lastCfgFile:
		idx = k

	idx = 0
	item = self.listView1.topLevelItem(idx)
        while item != None:
	    try:
	        if int(str(item.text(4))) == idx:
		    self.listView1.setCurrentItem(item)
		    
		    desc = appData[int(str(item.text(4)))][9]
		    self.setDetails(desc)
 
	            return
            except ValueError:
	        pass   
	    idx = idx+1 
	    item = self.listView1.topLevelItem(idx)
    
    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:
	   if debug: print 'translateMsg BlinkThread'
	   
	   # Just key press
	   setTrayIcon("kanyremote_flash") 
	   QTimer.singleShot(200, resetIcon)  
 
 	   if debug:
	       msg = data
	   else:
	       return
	
	self.setStatustext(msg)

	    
    def customEvent(self,event):
        global appData
	
	if event.type() == 20000:
           self.setStatusStopped()
        elif event.type() == 20003:
	   cfgFile = getResult('ps aux |grep anyremote|grep cfg|awk \'{n=split($0,arr);print arr[n];}\'', 'frontend')

	   if cfgFile != '':
		for k, v in appData.iteritems():
	            if appData[k][5] == cfgFile:
		        appData[k][6] = AR_MANAGED
			self.listUpdate([k,appData[k][6],'OK'])
           self.setStatusDisconnected()
        elif event.type() == 20001:
           setTrayIcon("kanyremote_flash")
        elif event.type() == 20002:
           setTrayIcon("kanyremote")
        elif event.type() == 20005:
           self.cfgWinClosed(event.getData())
        elif event.type() == 20006:
           self.listUpdate(event.getData())
        elif event.type() == 20007:
	   self.listView1.clear()
	   for k, v in appData.iteritems():
	       self.addRow([appData[k][0],appData[k][1],appData[k][4],appData[k][6],appData[k][7],appData[k][8],k])
	   self.selectLastInList()
	   self.setStatusStopped()
           self.restartUpdater()
        elif event.type() == 20008:
           self.dcopHandleSend(event.getData())
        elif event.type() == 20009:
           self.dcopHandleGetMode()
        elif event.type() == 20010:
           self.restartUpdater()
        elif event.type() == 20011:
           restartBtComm(self)
        elif event.type() == 20012:
	   for k, v in appData.iteritems():
	       if appData[k][6] == AR_MANAGED:
	           aRun = appData[k][3]
		   isRun = ''
	           if aRun != '':
	    	        isRun  = getResult(aRun,'main')
                    
		        if isRun == 'OK':
		            appData[k][6] = AR_RUNNING
		        else:
		            appData[k][6] = AR_AVAIL
		   else:
		        appData[k][6] = '' 

	   	   self.listUpdate([k,appData[k][6],isRun])
        elif event.type() == 20014:
            ret = yesno(self,_tr("New version of java client is available. Would You like to download it ?"))
	    if ret :
	        if not self.cfgWin:
                    self.cfgWin = Preferences(self, self.cReader);
	        self.cfgWin.uploadJavaWeb() 
        elif event.type() == 20015:
	    infoMessage(self,event.getData())
        elif event.type() == 20016:
	    errorMessage(self,event.getData())
        elif event.type() == 20017:
	   self.setStatustext(str(int(event.getData())))
        elif event.type() == 20018:
	   self.stopProgressBar()
        elif event.type() == 20019:
	   self.startProgressBar(event.getData())
        elif event.type() == 20020:
	   self.showDevDetails(event.getData())
        elif event.type() == 20021:
	   self.writeProgressBar(event.getData())
        elif event.type() == 20022:
	   self.listView1.clear()
        else:
           self.translateMsg(str(event.getData()))
           
    def pushTrayIcon(self):
        if self.isShown == 1:
            self.hide()
            self.isShown = 0
        else:
            self.show()
            self.isShown = 1
	    
    def cfgWinClosed(self, isChanged):
        self.properties.setEnabled(True)
	if isChanged:
	    self.populateCfgFiles()
	    
    def dcopHandleSend(self, cmd):
        global cmdToSend
	if debug: print 'Add to queue ' + cmd
        cmdToSend = cmd
    
    def detailExpanded(self, item):
        cnt = str(self.detailsItem.text(0)).count('\n')
	h = self.details.visualItemRect(self.detailsHead).height()*(cnt+2)
	if h == 0: h = 18*(cnt+2)
        self.details.setMinimumHeight(h)
        self.details.setMaximumHeight(h)

    def detailCollapsed(self, item):
	h = self.details.visualItemRect(self.detailsHead).height()
	if h == 0: h = 18
        self.details.setMinimumHeight(h)
        self.details.setMaximumHeight(h)
    
    def  stopProgressBar(self):
        global pbar, pbarTimer,debug
    
        if debug: print 'stopProgressBar'

        try:
            pbarTimer.stop()
        except AttributeError:
            pass
	
        try:
            pbar.hide()
            pbar.cancel()
	    pbar = None
        except AttributeError, NameError:
            pass
	    
    def startProgressBar(self,text):
        global debug, pbar, pbarTimer
        
	if debug: print 'startProgressBar'
    
        pbar = PBar(text,100)
        timerPBar()

    def writeProgressBar(self,text):
        global pbar

        try:
            pbar.setLabelText(text)
        except AttributeError, NameError:
	    pass

    def showDevDetails(self,dataList):
        global dwin, cfgReader
        dwin = DeviceDetail(dataList[0], dataList[1], dataList[2], dataList[3], dataList[4], dataList[5], cfgReader.javaDir_,self)
        dwin.show()

    
###############################################################################	
#
#	Configuration management
#
###############################################################################	

class ConfigReader:
    def saveConfig(self):
    
    	global lastCfgFile
	
    	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='+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.runWeb_:
	        f.write('WebInterface='+self.webParams_+'\n')

	    if self.deviceSrv_ != '':
	        f.write('DeviceServer='+self.deviceSrv_+'\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')

	    if self.ipIV_ != '':
	        f.write('IP_IViewer='+self.ipIV_+'\n')

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

    def setDefaultConfig(self):
    	global lastCfgFile

	lastCfgFile        = ''
	self.cfgDirs       = []
	self.javaDir_      = ''
	self.checkJavaUpdate_ = 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.deviceSrv_    = ''
	self.deviceAT_     = 'rfcomm:'
	self.deviceBm_     = ''
	self.deviceIV_     = 'socket:5000'
	
	ip_loc = getResult('which ip 2> /dev/null', 'cfg')
	if ip_loc == '':
	    ip_loc = getResult('ls /sbin/ip 2> /dev/null', 'cfg')
	
	self.ipIV_         = getResult(ip_loc + ' -o -f inet addr show|tr -s " "|cut -f 4 -d " "|grep -v 127.0.0.1|cut -f 1 -d"/"|head -1', 'cfg')
	self.runWeb_       = False
	self.webParams_    = ''
	self.updateTmout_  = 60
	self.browseTmout_  = -1
	
    def readConfig(self):
    	global lastCfgFile, bt_devices
	
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-fe.conf'
	
    	if os.path.exists(cfg) :
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg) 
		    if line.startswith('LastCfgFile='):
		        lastCfgFile=line[12:]
		    elif line.startswith('Show='):
		    	#Show=Apps,Custom,Examples|All
			what = line[5:].split(',')
			
			# override defaults
	                self.showApps_ = False
			self.showSrv_  = False
			
			for item in what:
			   if item == '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('DeviceServer='):
		        self.deviceSrv_ = line[13:]
		    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('IP_IViewer='):
		        self.ipIV_ = line[11:]
		    elif line.startswith('WebInterface='):
		        self.runWeb_    = True
		        self.webParams_ = line[13:]
                    elif line.startswith('CfgDirs='):
		        self.cfgDirs=line[8:].split(';')
                    elif line.startswith('UpdateTimeout='):
		        self.updateTmout_=int(line[14:])
                    elif line.startswith('DeviceBrowserTimeout='):
		        tmt=line[21:]
    	    	        try:
    	    		    self.browseTmout_=int(tmt)
    	    	        except ValueError:
			    self.browseTmout_=-1

			if self.browseTmout_ <= 0:
			    self.browseTmout_=-1
                    elif line.startswith('JavaDir='):
		        self.javaDir_=line[8:]
                    elif line.startswith('CheckJavaUpdate=true'):
		        self.checkJavaUpdate_=True
					    
		    # compatibility with old versions
		    elif line.startswith('OverrideDevice='):
		        self.deviceSrv_ = line[15:]

	    	f.close()
	        
		# Try to search again
		if self.javaDir_ == '':
		    self.javaDir_ = getJ2MEPath()

		
	# device browser related part
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-peers.conf'
	
    	if os.path.exists(cfg) :
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg)
		    
		    if line.startswith('Device='):
		        deviceData=line[7:].split(',')
			
			# 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]
			
			bt_devices[v1] = [v1,v2,v3,v4,v5,'']
	    	f.close()
	
##################################################################################
#
# Utilities functions
#
##################################################################################

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

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

    try:
        conn.request("GET", fname)
    except Exception: 
	sendEvent(receiver, 20016, _tr('Can not establish the connection !'))
        return False
	
    r = conn.getresponse()

    if debug: print fname, r.status, r.reason,r.getheader('content-length')
    
    ret = True
    
    if r.status == httplib.OK:
        if debug: print 'download',fname
	
	try:
            data = r.read()
	except Exception:
	    sendEvent(receiver, 20016, _tr('Download failed !'))
	    return False
	
	f=open(os.environ.get("HOME")+os.sep+'.anyRemote'+fname+tmp, 'w')
	if f:
 	    f.write(data)
	    f.close()
    else:
        if tmp == "":
	    sendEvent(receiver, 20016, _tr('Can not download ')+hname+fname)
	    ret = False
	
    conn.close()
    
    return ret
    
def uploadJavaWebGui(receiver, fname, strip=False):
    global debug
    
    if debug: print 'uploadJavaWebGui',fname
    
    writePBar(receiver,_tr('Downloading')+' '+fname)
    
    if not getHttp(receiver, "anyremote.sourceforge.net",os.sep+fname,""):
        stopPBar(receiver)
	if debug: print 'uploadJavaWebGui: fails to upload',fname
	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 getJavaClientVersion(fname):
    global debug
    if debug: print 'Check version of Java Client from file',fname
    return getResult('cat '+fname+'|grep MIDlet-Version|tr -d \" \"|cut -f 2 -d \":\"','main')

def checkJavaClientUpdate(receiver):
    global debug
    
    if not getHttp(receiver,"anyremote.sourceforge.net",os.sep+"anyRemote-16.jad",".check"):
        return "-1"
	
    newver = getJavaClientVersion(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyRemote-16.jad.check')
    oldver = getJavaClientVersion(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 ""

#
# iViewer support
#

def uploadIViewerGui(receiver):
 
    path = os.environ.get("HOME")+os.sep+'.anyRemote'
    os.system('rm -rf '+path+os.sep+'iviewer'+os.sep+'anyremote-iviewer.tgz')
    
    if not getHttp(receiver,"anyremote.sourceforge.net",os.sep+'anyremote-iviewer.tgz',""):
	return False
	
    os.system('rm -rf '+path+os.sep+'iviewer')
    os.system('cd '+path+';tar xvfz anyremote-iviewer.tgz > /dev/null')
    
    dirv = glob.glob(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyremote-iviewer-*')
    if os.path.isdir(dirv[0]):
        os.system('cd '+path+';mv '+dirv[0]+' iviewer')
      
        f1 = path+os.sep+'iviewer'+os.sep+'lighttpd.conf'
        os.system('cat '+f1+'|sed \'s/\/home\/user/'+os.environ.get("HOME").replace('/', '\/')+'/\' > '+f1+'.tmp;mv '+f1+'.tmp '+f1);
    
    return True

def prepareIViewerGui(ip, port):

    print "prepareIViewerGui",ip, port
    
    guis =  glob.glob(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'iviewer'+os.sep+'*.gui')
     
    for f2 in guis:
        os.system('cat '+f2+'|sed \'s/<hostname>[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/<hostname>'+ip  +'/\' > '+f2+'.tmp;mv '+f2+'.tmp '+f2);
        os.system('cat '+f2+'|sed \'s/<commandPort>[0-9]*/<commandPort>'+port+'/\' > '+f2+'.tmp;mv '+f2+'.tmp '+f2);

#
#
#
def getMode(cfile):
    global appData
    for k, v in appData.iteritems():
	if appData[k][5] == cfile:
	    return appData[k][7]

    return ''

def killAnyRemote():
    os.system('pkill lighttpd')
    os.system('pkill -f "python .*anyremote2html"')
    os.system('killall -2 anyremote 2> /dev/null')
    
def startAnyRemote(cfile):
    global debug, cfgReader, port
    
    killAnyRemote()
	
    time.sleep(0.5)
    
    useType = getMode(cfile)
    
    mode = 'Server'
    if cfgReader.showAt_:
    	mode = 'AT'
    if cfgReader.showBm_:
    	gui = 'Bemused'
    if cfgReader.showIView_:
    	mode = 'iViewer'

    log = ''
    if debug:
    	log = ' -log'
   
    web = ''
    dev = ''
    rconn = ''
    
    if mode == 'Server':
        if cfgReader.runWeb_:
    	    web = ' -http'

        if cfgReader.deviceSrv_ != '':
    	    dev = ' -s '+cfgReader.deviceSrv_
   
    elif mode == 'AT':
        if cfgReader.deviceAT_ != '':
    	    dev = ' -s '+cfgReader.deviceAT_
    
        if cfgReader.autoReconn_ != '':
            rcomm = ' -a '
	
    elif mode == 'Bemused':
        if cfgReader.deviceBm_ != '':
    	    dev = ' -s '+cfgReader.deviceBm_
    
    elif mode == 'iViewer':
	
        if cfgReader.deviceIV_ != '':
    	    dev = ' -s '+cfgReader.deviceIV_
	    
	    if cfgReader.deviceIV_.startswith('socket:'):
	        prepareIViewerGui(cfgReader.ipIV_,cfgReader.deviceIV_[7:])
	        os.system('lighttpd -f '+os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'iviewer'+os.sep+'lighttpd.conf')    
    
    else:
         if cfgReader.autoReconn_ != '':
            rconn = ' -a '

    	    
    to_path = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep

    cmd = 'anyremote -fe ' + port + log + web + ' -f ' + str(cfile) + dev + rconn + ' > '+ to_path + 'anyremote.stdout &'
    if debug: print cmd
    os.system(cmd)
    
    if web != '':
        dd = ''
    	if debug: dd = '-d '
  
        cmd = 'anyremote2html ' + dd + ' -a ' + cfgReader.deviceSrv_[7:] + ' ' + cfgReader.webParams_ + ' > '+ to_path + 'anyremote2html.stdout &'
        if debug: print cmd
        os.system(cmd)

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

def sendEvent(receiver, eid, data):
    global quitFlag, app
    
    if quitFlag: return
    
    event = QEventEx(eid,data)
    app.postEvent(receiver, event)

#
# Handle crystalsvg/oxygen name collisions
#
def loadIcon(name1,name2):
    global debug,iconsK

    pixmap = iconsK.loadIcon(name1, KIconLoader.Small,0,KIconLoader.DefaultState,QStringList(),QString(),True)
    #if debug: print name1,pixmap
    if pixmap.isNull():
        pixmap = iconsK.loadIcon(name2, KIconLoader.Small,0,KIconLoader.DefaultState,QStringList(),QString(),True)
        if debug: print "use second attempt",name2,pixmap
	
    return QIcon(pixmap)

def resetIcon():
    setTrayIcon("kanyremote")

def loadCustomIcon(iconName):
    global debug,iconsK
    
    pixmap = QPixmapCache.find(iconName)
    if pixmap == None:
        pixmap = iconsK.loadIcon(iconName, KIconLoader.Small,0,KIconLoader.DefaultState,QStringList(),QString(),True)
    
        # hardcode it, last resort
        if pixmap.isNull():
            pixmap = QPixmap("/usr/share/pixmaps/"+iconName+".svg")

        if pixmap.isNull():
            pixmap = QPixmap("/usr/share/pixmaps/"+iconName+".png")
        
	# use from current directory, the latest resort
        if debug and pixmap.isNull():
            pixmap = QPixmap("data/"+iconName+".svg")
        
	if debug and pixmap.isNull():
            pixmap = QPixmap("data/"+iconName+".png")
	
	QPixmapCache.insert(iconName,pixmap)
    
    return pixmap   
    
def setTrayIcon(iconName):
    global systray

    if systray:
        systray.setIcon(QIcon(loadCustomIcon(iconName)))

def yesno(widget, message):
    ret = QMessageBox.question(widget,"kAnyRemote",message,QMessageBox.Yes|QMessageBox.Default,QMessageBox.No|QMessageBox.Escape)
    return (ret == QMessageBox.Yes)

def errorMessage(widget, msg):
    ret = QMessageBox.warning(widget,"kAnyRemote",msg,QMessageBox.Ok);

def infoMessage(widget, msg):
    ret = QMessageBox.warning(widget,"kAnyRemote",msg,QMessageBox.Ok);

def getJ2MEPath():
    path = ''
    if os.path.exists('/usr/share/anyremote-J2ME-client/anyRemote-16.jar'):
        path = '/usr/share/anyremote-J2ME-client'
    elif os.path.exists('/usr/local/share/anyremote-J2ME-client/anyRemote-16.jar'):
        path = '/usr/local/share/anyremote-J2ME-client'
    elif os.path.exists(os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'anyRemote-16.jar'):
        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+'/'+app):
            return 'OK'
    return 'NOK'

def reqVersion(cmd):
    res = getResult(cmd,'main')
    if res == 'OK':
         return 'OK'
    return 'NOK'
	
def getResult(cmd, suffix):
    #print 'getResult',cmd, suffix

    toFile = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'kanyremote-' + suffix + '.tmp'
    os.system(cmd + '> ' + toFile)
    line = getLineTmpFile(toFile)
    return line.replace('\n','')

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

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

def 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 + 'anyremote-peers.conf', 'w')
    if f:
    	for k, v in bt_devices.iteritems():

    	    row = bt_devices[k]
    	    v0 = row[0]
    	    v1 = row[1]
    	    v2 = row[2]
    	    v3 = row[3]
    	    v4 = row[4]
    	    
    	    f.write('Device='+v0+','+v1+','+v2+','+v3+','+v4+'\n')

    	f.close()

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

def btVerify(window,showmsg):
    hcid = getResult('echo \'A=`ps -ef|grep hcid|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
    if 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 showmsg and hcid == 'NOK':
        #infoMessage(window,_tr("Bluetooth service is not active"))
	sendEvent(self.receiver, 20015, _tr("Bluetooth service is not active"))
    return hcid

def initVerify(window):

    tool = isInstalled('anyremote')
    if tool == 'NOK':
        sendEvent(window, 20016, _tr("anyRemote not found !\nPlease install it or correct $PATH"))

    tool = isInstalled('sdptool')
    if tool == 'NOK':
         sendEvent(window, 20016, _tr("sdptool not found !\nPlease install bluez-util"))

def showDetailsWin(receiver,dataList):
    sendEvent(receiver, 20020, dataList)
    
def closeDetailsWin():
    global dwin
    try:
        dwin.destroy()
        dwin = None
    except AttributeError, NameError:
	pass

def showBrowserWin(receiver):
    global browserWin
    browserWin = DeviceBrowser(receiver)
    browserWin.show()

def closeBrowserWin():
    global browserWin
    try:
    	browserWin.destroy()
    	browserWin = None
    except AttributeError, NameError:
    	pass

def showChkCfgWin(parent):
    global chkCfgWin
    chkCfgWin = CfgChecker(parent)
    chkCfgWin.show()

def closeChkCfgWin():
    global chkCfgWin
    try:
    	chkCfgWin.destroy()
    	chkCfgWin = None
    except AttributeError, NameError:
    	pass

def getAvailableSet():
    global bt_devices

    s = []
    for k, v in bt_devices.iteritems():
    	if v[5] == AR_AVAIL:
	    s.append(v[0])
    
    return s

def getDevSet():
    global bt_devices

    s = []
    for k, v in bt_devices.iteritems():
    	s.append(v[0])
    
    return s
    
def browseDevices(force):
    global cmd_array, debug
    
    if ['scan',force] in cmd_array:
        if debug:
	    print 'Skip device scan'
    else:
	queueBT('scan',force)

    return True

def restartBtComm(parent):
    stopBtComm()
    startBtComm(parent)
	
def timerBrowseDevices():
    global cfgReader, quitFlag, browseTimer

    if cfgReader.browseTmout_ > 0 and not quitFlag:
    	browseDevices('F')
    	browseTimer = QTimer.singleShot(1000*cfgReader.browseTmout_, timerBrowseDevices)

def startBtComm(parent):
    global bt, usepybluez, cfgReader, browseTimer, browseFlag, debug
    if debug: print 'startBtComm'

    if usepybluez == True and bt == None: 
    	bt = BtComm(parent,cfgReader.javaDir_)
    	bt.start()
	
	if cfgReader.browseTmout_ > 0:
	    # give 5 sec. to thread for start
    	    browseTimer = QTimer.singleShot(5000, timerBrowseDevices)

def stopBtComm():
    global bt, browseTimer, debug
    if debug: print 'stopBtComm'
    
    try:
    	bt.stop()
    except AttributeError, NameError:
        if debug: print 'Exception: bt.stop()'
    	pass
    time.sleep(0.5)
    bt = None

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 startFrontend(receiver):
    if debug: print 'startFrontend',cmd_array
    global frontEnd
    frontEnd = FrontEnd(receiver)
    frontEnd.start()

def stopFrontend():
    global debug, frontEnd
    if debug: print 'stopFrontend'

    # 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:
    	pass
	
    frontEnd = None

##################################################################################
#
# Main function
#
##################################################################################

def main():

    global app, aboutData, systray, iconsK, debug, port, statusUpdater, cmdToSend, guiMode, usepybluez, usetray, cfgReader
	
    cmdToSend     = ''
    statusUpdater = ''
    guiMode       = 'simple'
    usepybluez    = True
    usetray       = True
    startintray   = False
    
    version     = "5.13"

    aboutData = KAboutData("KApplication","kanyremote",KLocalizedString(), 
                            version, 
			    ki18n('KDE front-end for anyRemote (bluetooth remote control for PC)'), 
			    KAboutData.License_GPL, 
			    ki18n("(C) 2007 - 2011 Mikhail Fedotov"))
    aboutData.addAuthor(ki18n("Mikhail Fedotov"), KLocalizedString(), 
                        "anyremote@mail.ru", "http://anyremote.sf.net")
    sys.argv.extend(['--caption', "kAnyRemote"])
		     
    KCmdLineArgs.init (sys.argv, aboutData)
    
    options = KCmdLineOptions()
    options.add("d",      ki18n("Debug"))
    options.add("debug",  ki18n("Debug"))
    options.add("n",      ki18n("Do not use PyBluez"))
    options.add("npybluez", ki18n("Do not use PyBluez"))
    options.add("t",      ki18n("Start in tray"))
    options.add("tray",   ki18n("Start in tray"))
    options.add("y",      ki18n("Do not use tray icon"))
    options.add("ntray",  ki18n("Do not use tray icon"))
    options.add("e",      ki18n("Expert mode"))
    options.add("expert", ki18n("Expert mode"))
    options.add("p ",     ki18n("Port"))
    options.add("port ",  ki18n("Port"))
    
    # obsoleted
    options.add("o",      ki18n("Open window"))
   
    KCmdLineArgs.addCmdLineOptions(options)
    
    app = KApplication()
    
    args = KCmdLineArgs.parsedArgs();
    
    if args.isSet("d") | args.isSet("debug"):
	debug   = True
        guiMode = 'expert'

    if args.isSet("t") | args.isSet("tray"):
        startintray = True
    
    if args.isSet("e") | args.isSet("expert"):
        guiMode = 'expert'
   
    if args.isSet("p"):
	q = args.getOption('p')
	port = str(q.data()).replace('\0','')

    if args.isSet('port'):
	q = args.getOption('port')
	port = str(q.data()).replace('\0','')

    if args.isSet("y") | args.isSet('ntray'):
        usetray = False
	
    if args.isSet("n") | args.isSet("npybluez"):
        usepybluez = False
    
    if pybluez == False and usepybluez == True:
        print _tr('Install PyBluez first !\nOr run with --npybluez option')
	return
	
    if debug: print 'Use port ' + port
   
    cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
    if not os.path.exists(cfg):
	os.mkdir(cfg)

    needWiz = False
    cfgReader = ConfigReader()
    cfgReader.setDefaultConfig()
    if os.path.exists(cfg+os.sep+'anyremote-fe.conf'):
	cfgReader.readConfig()
    else: 
        cfgSet = False
    
	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'):
	    set = 1
	    cfgReader.cfgDirs.append('/etc/anyremote/cfg-data')
	    
	cfgReader.javaDir_ = getJ2MEPath()
	
        if not cfgSet or cfgReader.javaDir_ == '':
            needWiz = True
    
    iconsK = KIconLoader()
    app.setWindowIcon(QIcon(loadCustomIcon("kanyremote")))
    
    ic = loadCustomIcon("kanyremote_logo")
    aboutData.setProgramLogo(QVariant(ic.toImage()))
	
    mainWindow = kAnyRemote(cfgReader, needWiz, "kAnyRemote")
    
    if cfgReader.checkJavaUpdate_:
        if debug: print 'Check java client updates at web'
    
	jv = JCVerifier(False,mainWindow)
	jv.start()
    
    if startintray:
        mainWindow.isShown = 0
    else:
        mainWindow.isShown = 1
        mainWindow.show()
    
    initVerify(mainWindow)

    systray = None
    if usetray:
        systray = KSystemTrayIcon(mainWindow)
	setTrayIcon("kanyremote_off")
 	
        mainWindow.trayStartAction   = QAction(loadIcon("system-run",  "run"), _tr("Start"), mainWindow)
        mainWindow.trayStopAction    = QAction(loadIcon("dialog-close","stop"),_tr("Stop"),  mainWindow)
	
        mainWindow.connect(mainWindow.trayStartAction,  SIGNAL("triggered()"), mainWindow.runAction)
        mainWindow.connect(mainWindow.trayStopAction,   SIGNAL("triggered()"), mainWindow.stopAction)

        systray.contextMenu().addAction(mainWindow.trayStartAction)
        systray.contextMenu().addAction(mainWindow.trayStopAction)

        app.connect(systray, SIGNAL("quitSelected()"), mainWindow.fileExit)
        systray.show()

    app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
	    
    mainWindow.setStatusStopped()
   
    startFrontend(mainWindow)
    
    app.exec_()

if __name__ == "__main__":
    global debug, port, cmdToSend, appData, bt_devices, quitFlag, jup, cmd_array, browserWin, chkCfgWin, dwin, bt, pbarTimer, pbar, lastCfgFile

    port       = '5050'
    debug      = False
    appData    = dict()
    bt_devices = dict()
    cmdToSend  = ''
    lastCfgFile = ''
    quitFlag   = False
    cmd_array  = []    
    dwin       = None    
    browserWin = None    
    chkCfgWin  = None    
    bt         = None
    pbarTimer  = None
    pbar       = None
    jup        = None
    
    main()
