#!/usr/bin/python
#
# We're using PySide, Nokia's official LGPL bindings.
# You can however easily use PyQt (Riverside Computing's GPL bindings) by commenting these and fixing the appropriate imports.
import sys, os, time
import subprocess
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtMaemo5 import QMaemo5InformationBox
import dbus
from dbus.mainloop.qt import DBusQtMainLoop
import re
 
# In Qt, everything is a class.
# We can subclass stuff to do whatever we want - it seems a bit strange at first,
# but it keeps all related functionality in one place, which helps to keep you organised.
#
# We're subclassing 'QWidget' here. QWidget is the base class for all graphical elements in Qt.
# You can do all sorts of cool things like drawing your widget yourself, but we won't get into that.
#
# See also:
#   http://doc.trolltech.com/4.6/qwidget.html

####################
# Global variables #
####################
CellNet_InfoVersion = "0.0.1-2"
infoTXT = ""
country_selected = ""
mcc_selected = ""
operator_selected = ""
mnc_selected = ""
proc = ""


class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):# first things first, we need to initialise the Qt parent, otherwise it won't work properly.
        #
	super(MyMainWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_Maemo5StackedWindow)
	global Orientation


	self.setWindowTitle(self.tr("cellnet-info"))

	self.form_widget = FormWidget(self)
	self.setCentralWidget(self.form_widget)

	self.setAttribute(Qt.WA_Maemo5AutoOrientation, True)
	###############
	# Create menu #
	###############
	aboutAction = QAction( '&About', self)

	########################
	# create menu from bar #
	########################
	menubar = self.menuBar()
	mainMenu = menubar.addMenu('&MainMenu')
	mainMenu.addAction(aboutAction)

	##################
	# Define actions #
	##################
	aboutAction.triggered.connect(self.aboutPushed)


    def aboutPushed(self):
	d = QDialog(self)
	vbox = QVBoxLayout()
	verticalLayout = QVBoxLayout()
	d.setWindowTitle(self.tr("About CellNet-Info"))
	verticalLayout.addWidget(QLabel("<center><img src=/opt/usr/share/icons/hicolor/64x64/apps/cellnet-info.png /></center>"),0)
	verticalLayout.addWidget(QLabel("<center><b><big>CellNet-Info "+CellNet_InfoVersion+"</big></b></center>"),1)
	verticalLayout.addWidget(QLabel("<center>Created by Arno Dekker (ade)</center>"),2)
	vbox.addLayout (verticalLayout)
	d.setLayout(vbox)
	d.show()

class FormWidget(QWidget):
    def __init__(self, parent):
	super(FormWidget, self).__init__(parent)

	# Now we start getting into building our interface. The first thing we need to learn about are layouts.
	# Layouts tell Qt where to put widgets, and how they fit with other widgets.
	# Unlike Gtk+, Qt layouts are *not* widgets - important difference to keep in mind.
	#
	# There are many types of layouts (from the complex, like QGridLayout) 
	# to the simple, like what we're using here.
	# See also:
	#   http://doc.trolltech.com/4.6/qlayout.html
	#   http://doc.trolltech.com/4.6/qvboxlayout.html
	self.WindowOpen = False
        # Layout
        self.grid = QGridLayout()
        infoTXT = "<h2>CellNet-Info</h2>"
        self.headerLabel = QLabel(infoTXT)
        self.headerLabel.setStyleSheet(
        "QLabel { font:bold; }"
                )
        self.headerLabel.setAlignment(Qt.AlignCenter | Qt.AlignLeft)
	self.headerLabel.setWordWrap(True)
        self.siminfoButton = QPushButton()
	self.siminfoButton.setText("  SIM info")
	self.siminfoButton.setIcon(QIcon("/opt/cellnet-info/images/sim-card.png"))
        self.cellinfoButton = QPushButton("Current \ncellular info",self)
	self.cellinfoButton.setIcon(QIcon("/opt/usr/share/icons/hicolor/64x64/apps/cellnet-info.png"))
        self.globalinfoButton = QPushButton("Mobile\nnetworks",self)
	self.globalinfoButton.setIcon(QIcon("/opt/usr/share/icons/hicolor/64x64/apps/cellnet-info.png"))
        self.queryButton = QPushButton("Query mobile\ncode info",self)
	self.queryButton.setIcon(QIcon("/opt/cellnet-info/images/information-icon.png"))
        font = QFont()
        font.setPointSize(24)
        self.siminfoButton.setFont(font)
        self.cellinfoButton.setFont(font)
        self.globalinfoButton.setFont(font)
        self.queryButton.setFont(font)
	self.siminfoButton.setMinimumHeight(150)
	self.cellinfoButton.setMinimumHeight(150)
	self.globalinfoButton.setMinimumHeight(150)
	self.queryButton.setMinimumHeight(150)
	# signals/slots
	self.connect(self.siminfoButton, SIGNAL("clicked()"),self.siminfoButtonPressed)
	self.connect(self.cellinfoButton, SIGNAL("clicked()"),self.cellinfoButtonPressed)
	self.connect(self.globalinfoButton, SIGNAL("clicked()"),self.globalinfoButtonPressed)
	self.connect(self.queryButton, SIGNAL("clicked()"),self.queryButtonPressed)
        self.setLayout(self.grid)
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
	self.orientationChanged()

    def cellinfoButtonPressed(self):
	if not self.WindowOpen:
		# prevent opening of multiple windows
		self.WindowOpen = True
		widget = cellWindow(self)
		widget.setAttribute(Qt.WA_Maemo5StackedWindow)
		widget.setAttribute(Qt.WA_DeleteOnClose)
		self.connect(widget, SIGNAL("destroyed()"),self.openManWinTrue)
		widget.show()
	
    def siminfoButtonPressed(self):
	if not self.WindowOpen:
		# prevent opening of multiple windows
		self.WindowOpen = True
		widget = simWindow(self)
		widget.setAttribute(Qt.WA_Maemo5StackedWindow)
		widget.setAttribute(Qt.WA_DeleteOnClose)
		self.connect(widget, SIGNAL("destroyed()"),self.openManWinTrue)
		widget.show()

    def globalinfoButtonPressed(self):
	if not self.WindowOpen:
		# look for other networks here, as we can't go back one the stackedwindow is opened ?
		# start it in background, as we do not get any response
		global proc
		IsCanceled = False
		ResultReceived = False
		countdown = 24
		progress = QProgressDialog(
		    "Please wait ...", "Cancel" , 0, countdown, self)
		proc = subprocess.Popen(['dbus-send' ,'--system', '--type=method_call', '--print-reply', \
			'--reply-timeout=666666', '--dest=com.nokia.phone.net', '/com/nokia/phone/net', \
			'Phone.Net.get_available_network'], stdout=subprocess.PIPE)
		# wait 0.5 seconds
		time.sleep(0.5)
		if proc.poll() is not None:
			# we must have received no celular info
			ResultReceived = True
		else:
			os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
				/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
				string:"Please wait while scanning..."')

			progress.setWindowTitle("Scanning networks")
			progress.setWindowModality(Qt.WindowModal)
			progress.setAutoClose(True)
			progress.setMinimumDuration(0)
			progress.show()
			for x in range(0,countdown):
				progress.setValue(x)
				progress.setLabelText("Approx. <b>" + str((countdown-x)) + "</b> seconds left ...")
				if proc.poll() is not None:
					# we have received output
					ResultReceived = True
					break
				if progress.wasCanceled():
					IsCanceled = True
					progress.close()
					break
				time.sleep(1)

		if not ResultReceived and not IsCanceled:
			# beyond expected time, wait in a loop or until canceled
			QApplication.processEvents() 
			progress.setLabelText("Still waiting ...")
			while (True):
				QApplication.processEvents() 
				time.sleep(1)
				if proc.poll() is not None:
					# we have received output
					break
				if progress.wasCanceled():
					IsCanceled = True
					break

		if not IsCanceled:
			# wait if we still have no output
			progress.hide()
			QApplication.processEvents() 
			# prevent opening of multiple windows
			self.WindowOpen = True
			widget = globalinfoWindow(self)
			widget.setAttribute(Qt.WA_Maemo5StackedWindow)
			widget.setAttribute(Qt.WA_DeleteOnClose)
			self.connect(widget, SIGNAL("destroyed()"),self.openManWinTrue)
			widget.show()

    def queryButtonPressed(self):
	if not self.WindowOpen:
		# prevent opening of multiple windows
		self.WindowOpen = True
		widget = queryWindow(self)
		widget.setAttribute(Qt.WA_Maemo5StackedWindow)
		widget.setAttribute(Qt.WA_DeleteOnClose)
		self.connect(widget, SIGNAL("destroyed()"),self.openManWinTrue)
		widget.show()

    def openManWinTrue(self):
	self.WindowOpen = False

    def orientationChanged(self):
        screenGeometry = QApplication.desktop().screenGeometry()
        if screenGeometry.width() > screenGeometry.height():
                # landscape 
		# first remove layout
        	self.grid.removeWidget(self.headerLabel)
		self.grid.removeWidget(self.siminfoButton)
		self.grid.removeWidget(self.cellinfoButton)
		self.grid.removeWidget(self.globalinfoButton)
		self.grid.removeWidget(self.queryButton)
		# then add new layout
        	self.grid.addWidget(self.headerLabel,0,0,1,0)
		self.grid.addWidget(self.siminfoButton,1,0)
		self.grid.addWidget(self.cellinfoButton,1,1)
		self.grid.addWidget(self.globalinfoButton,2,0)
		self.grid.addWidget(self.queryButton,2,1)
        else:
                # portrait
		# first remove layout
        	self.grid.removeWidget(self.headerLabel)
		self.grid.removeWidget(self.siminfoButton)
		self.grid.removeWidget(self.cellinfoButton)
		self.grid.removeWidget(self.globalinfoButton)
		self.grid.removeWidget(self.queryButton)
		# add new layout
        	self.grid.addWidget(self.headerLabel,0,0)
		self.grid.addWidget(self.siminfoButton,1,0)
		self.grid.addWidget(self.cellinfoButton,2,0)
		self.grid.addWidget(self.globalinfoButton,3,0)
		self.grid.addWidget(self.queryButton,4,0)

class simWindow(QMainWindow):
    def __init__(self,parent):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("Sim info")
	global infoTXT
	# layout
        area = QScrollArea()
        lay = QVBoxLayout()
        lay.addWidget(area)
        self.wg = QWidget()
        area.setWidget(self.wg)
        self.setCentralWidget(area)
        grid = QGridLayout(self.wg)
        self.wg.show()
	self.orientationChanged()
        area.show()
        self.setLayout(grid)
	# get info by using dbus
	self.bus = dbus.SystemBus()
	dbus_object = self.bus.get_object('com.nokia.phone.net', '/com/nokia/phone/net',False)
	dbus_interface = dbus.Interface(dbus_object, 'Phone.Net')
	# SIM/network status
        c_status = int(dbus_interface.get_registration_status()[0])
	if (c_status == 0): sim_status = "Normal mode"
        elif (c_status == 3): sim_status = "No SIM card found"
        elif (c_status == 4): sim_status = "Cellular modem \npowering down"
        elif (c_status == 8): sim_status = "Cellular modem \nswitched off"
        elif (c_status == 10): sim_status = "No signal"
        elif (c_status == 11): sim_status = "SIM registration failed"
        else: sim_status = "Unknown"
	dbus_object = self.bus.get_object('com.nokia.phone.SIM', '/com/nokia/phone/SIM',False)
	# IMSI
	siminfo = dbus.Interface(dbus_object, 'Phone.Sim')
	IMSI =  str(siminfo.get_imsi()[0])
	# SIM operator
	SIM_operator =  str(siminfo.get_service_provider_name()[0])
	# IMEI
	dbus_object = self.bus.get_object('com.nokia.phone.SIM', '/com/nokia/phone/SIM/security',False)
	IMEIinfo = dbus.Interface(dbus_object, 'Phone.Sim.Security')
	IMEI = str(IMEIinfo.get_imei()[0])
	# ICCID
	dbus_object = self.bus.get_object('com.nokia.phone.SSC', '/com/nokia/phone/SSC',False)
	ICCIDinfo = dbus.Interface(dbus_object, 'com.nokia.phone.SSC')
	ICCID = str(ICCIDinfo.get_iccid())

	# define screen content
	deviceRelatedTXT = QLabel("<b>Device related:</b>")
	SIMrelatedTXT = QLabel("<b>SIM related:</b>")
        font = QFont()
        font.setPointSize(20)
        SIMrelatedTXT.setFont(font)
        deviceRelatedTXT.setFont(font)
	line1 = QFrame()
	line1.setLineWidth(3)
	line1.setMidLineWidth(3)
	line1.setFrameShape(QFrame.HLine)
	line1.setFrameShadow(QFrame.Sunken)
	line2 = QFrame()
	line2.setLineWidth(3)
	line2.setMidLineWidth(3)
	line2.setFrameShape(QFrame.HLine)
	line2.setFrameShadow(QFrame.Sunken)
	line3 = QFrame()
	line3.setLineWidth(3)
	line3.setMidLineWidth(3)
	line3.setFrameShape(QFrame.HLine)
	line3.setFrameShadow(QFrame.Sunken)
	IMEIlabel = QLabel(IMEI)
	IMEIlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	IMEItxt = QLabel("IMEI:")
	IMEItxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	IMSIlabel = QLabel(IMSI)
	IMSIlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	IMSItxt = QLabel("IMSI:")
	IMSItxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	statustxt = QLabel("status:")
	statustxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	self.statuslabel = QLabel(sim_status)
	self.statuslabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	ICCIDlabel = QLabel(ICCID)
	ICCIDlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	ICCIDtxt = QLabel("ICCID:")
	ICCIDtxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	operatorlabel = QLabel(SIM_operator)
	operatorlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	operatortxt = QLabel("operator:")
	operatortxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
	# add to layout
	grid.addWidget(line1, 1, 0, 1, 2)
	grid.addWidget(deviceRelatedTXT,2,0,1,2)
	grid.addWidget(IMEItxt,3,0)
	grid.addWidget(IMEIlabel,3,1)
	grid.addWidget(line2, 4, 0, 1, 2)
	grid.addWidget(SIMrelatedTXT,5,0,1,2)
	grid.addWidget(statustxt,6,0)
	grid.addWidget(self.statuslabel,6,1)
	grid.addWidget(operatortxt,7,0)
	grid.addWidget(operatorlabel,7,1)
	grid.addWidget(IMSItxt,8,0)
	grid.addWidget(IMSIlabel,8,1)
	grid.addWidget(ICCIDtxt,9,0)
	grid.addWidget(ICCIDlabel,9,1)
	grid.addWidget(line3, 10, 0, 1, 2)
	helpButton = QPushButton("Help",self)
	grid.addWidget(helpButton,11,0,1,2)
	# help text
	infoTXT = "<html><b><u>SIM</u><br>S</b>ubscriber <b>I</b>denity <b>M</b>odule<br>" \
	"An integrated circuit that securely stores the IMSI and the related key used " \
	"to identify and authenticate subscribers on mobile telephony devices (such as mobile phones and computers).<p>" \
	"<html><b><u>IMEI</u><br>I</b>nternational <b>M</b>obile <b>S</b>tation <b>E</b>quipment <b>I</b>dentify<br>" \
	"To uniquely identify the device. It is usually found printed inside the battery compartment of the phone. " \
	"It can also be displayed on the screen of the phone by entering *#06# into the keypad on most phones.<p>" \
	"<b><u>IMSI</u><br>I</b>nternational <b>M</b>obile <b>S</b>ubscriber <b>I</b>dentity<br>" \
	"A unique identification associated with all GSM, UMTS and LTE network SIM cards.<p>" \
	"<b><u>ICCID</u><br>I</b>ntegrated <b>C</b>ircuit <b>C</b>ard <b>Id</b>entifier<br>" \
	"CCIDs are stored in the SIM cards and are also engraved or printed on the SIM card body during a process " \
	"called personalization.<p></html>"
	# act as soon as display goes off
	busobj = self.bus.get_object('com.nokia.mce', '/com/nokia/mce/signal') 
        busiface = dbus.Interface(busobj, 'com.nokia.mce.signal')
        busiface.connect_to_signal('display_status_ind', self.displaystate_change)
	# signals
	self.connect(helpButton, SIGNAL("clicked()"),self.helpButtonPressed)
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
	self.bus.add_signal_receiver(self.signal_registration_status_change, dbus_interface = "Phone.Net", signal_name = "registration_status_change")

    def signal_registration_status_change(self, *values):
        c_status = values[0]
	if (c_status == 0): sim_status = "Normal mode"
        elif (c_status == 3): sim_status = "No SIM card found"
        elif (c_status == 4): sim_status = "Cellular modem \npowering down"
        elif (c_status == 8): sim_status = "Cellular modem \nswitched off"
        elif (c_status == 10): sim_status = "No signal"
        elif (c_status == 11): sim_status = "SIM registration failed"
        else: sim_status = "Unknown"
	self.statuslabel.setText(sim_status)

    def displaystate_change(self, state):
	if (state == "off"):
		self.remove_signals()
	elif (state == "on"):
	 	self.add_signals()

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

    def	remove_signals(self):
	# remove the signal receivers at leaving page
	self.bus.remove_signal_receiver(self.signal_registration_status_change, dbus_interface = "Phone.Net", signal_name = "registration_status_change")

    def	add_signals(self):
	self.bus.add_signal_receiver(self.signal_registration_status_change, dbus_interface = "Phone.Net", signal_name = "registration_status_change")

    def helpButtonPressed(self):
	widget = helpWindow(self)
	widget.show()

    def orientationChanged(self):
        screenGeometry = QApplication.desktop().screenGeometry()
        if screenGeometry.width() > screenGeometry.height():
                # landscape
                self.wg.resize(780,300)
                self.wg.setMinimumHeight(420)
                self.wg.setMaximumHeight(420)
        else:
                # portrait
                self.wg.resize(470,680)
                self.wg.setMinimumHeight(740)
                self.wg.setMaximumHeight(740)


class cellWindow(QMainWindow):
    def __init__(self,parent):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("Cellular info")
	global infoTXT
	global bus
	operator_info_file="/opt/cellnet-info/data/operator_info.txt"
	# layout
        area = QScrollArea()
        lay = QVBoxLayout()
        lay.addWidget(area)
        self.wg = QWidget()
        area.setWidget(self.wg)
        self.setCentralWidget(area)
        grid = QGridLayout(self.wg)
        self.wg.show()
	self.orientationChanged()
        area.show()
        self.setLayout(grid)
	# dbus
	self.bus = dbus.SystemBus()
	dbus_object = self.bus.get_object('com.nokia.phone.net', '/com/nokia/phone/net',False)
	dbus_interface = dbus.Interface(dbus_object, 'Phone.Net')
        tuple_cellstatus = dbus_interface.get_registration_status()
        (c_status, c_lac, c_id, c_mnc, c_mcc, c_type, c_services, c_err) \
            = tuple_cellstatus
	operator_name = str(dbus_interface.get_operator_name(dbus.Byte(0), c_mnc, c_mcc)[0])
	commando = "cat " + operator_info_file + "|grep ^" + str(c_mcc) + " |awk -F \"\t\" '{ print $2}'|head -1"
	if not os.path.isfile(operator_info_file):
		QMessageBox.critical(self, "Critical",  "Cannot read " + operator_info_file)
		country_name = ""
	else:
		fin,fout = os.popen4(commando)
		country_name = fout.read()
        radio_technology = dbus_interface.get_selected_radio_access_technology()[0]
	if (radio_technology == 0): technology = "DUAL"
        elif (radio_technology == 1): technology = "GSM"
        elif (radio_technology == 2): technology = "3G"
        else: technology = "?"
        used_radio_technology = dbus_interface.get_radio_access_technology()[0]
        if (used_radio_technology == 1): used_technology = "GSM"
        elif (used_radio_technology == 2): used_technology = "3G"
	else: used_technology = "?"
	tuple_sigstrength = dbus_interface.get_signal_strength()
	c_sig_perc = int(tuple_sigstrength[0])
	c_sig_dbm = int(tuple_sigstrength[1])
	services = ""
	if (c_services & 0x02): services += 'CS '
	if (c_services & 0x01): services += 'GPRS '
	if (c_services & 0x04): services += 'EGPRS '
	if (c_services & 0x08): services += 'HSDPA '
	if (c_services & 0x10): services += 'HSUPA'

	# add layout
	line1 = QFrame()
	line1.setLineWidth(3)
	line1.setMidLineWidth(3)
	line1.setFrameShape(QFrame.HLine)
	line1.setFrameShadow(QFrame.Sunken)
	line2 = QFrame()
	line2.setLineWidth(3)
	line2.setMidLineWidth(3)
	line2.setFrameShape(QFrame.HLine)
	line2.setFrameShadow(QFrame.Sunken)

	grid.addWidget(line1,0,0,1,2)
	grid.addWidget(QLabel("Phone mode"),1,0)
	self.selectedTechTXT = QLabel()
	self.selectedTechTXT.setText(technology)
	grid.addWidget(self.selectedTechTXT,1,1)
	grid.addWidget(QLabel("Used mode"),2,0)
	self.usedTechTXT = QLabel()
	self.usedTechTXT.setText(used_technology)
	grid.addWidget(self.usedTechTXT,2,1)
	grid.addWidget(QLabel("MCC"),3,0)
	self.countryTXT = QLabel()
	self.countryTXT.setText(str(c_mcc)+" ("+country_name.strip()+")")
	grid.addWidget(self.countryTXT,3,1)
	grid.addWidget(QLabel("MNC"),4,0)
	self.operTXT = QLabel()
	self.operTXT.setText(str(c_mnc)+ " ("+operator_name+")")
	grid.addWidget(self.operTXT,4,1)
	grid.addWidget(QLabel("LAC"),5,0)
	self.LACtxt = QLabel()
	self.LACtxt.setText(str(c_lac))
	grid.addWidget(self.LACtxt,5,1)
	grid.addWidget(QLabel("CID"),6,0)
	self.CIDtxt = QLabel()
	self.CIDtxt.setText(str(c_id & 65535))
	grid.addWidget(self.CIDtxt,6,1)
	grid.addWidget(QLabel("RNC-ID"),7,0)
	self.RNCtxt = QLabel()
	self.RNCtxt.setText(str(c_id >> 16))
	grid.addWidget(self.RNCtxt,7,1)
	grid.addWidget(QLabel("Services"),8,0)
	grid.addWidget(QLabel(services.strip().replace(" ","+")),8,1)
	grid.addWidget(QLabel("Signal strength"),9,0)
	self.SignalTxt = QLabel()
	self.SignalTxt.setText(str(c_sig_perc) + "%, " + str(c_sig_dbm) + " dBm")
	grid.addWidget(self.SignalTxt,9,1)
	helpButton = QPushButton("Help",self)
	grid.addWidget(line2,10,0,1,2)
	grid.addWidget(helpButton,11,0,1,2)
	infoTXT = "<html><b><u>GSM</u></b><br><b>G</b>lobal <b>S</b>ystem for <b>M</b>obile Communications. " \
	"Second generation (2G) digital cellular network. Supported: GSM 850/900/1800/1900<p>" \
	"<b><u>3G</u></b><br>short for third Generation, is a term used to represent the 3rd generation " \
	"of mobile telecommunications technology. Also called Tri-Band 3G. Supported: HSDPA 900/1700/2100<p>" \
	"<b><u>DUAL</u></b><br>Both 2G and 3G<p>" \
	"<b><u>MCC</u><br>M</b>obile <b>C</b>ountry <b>C</b>ode<p>" \
	"<b><u>MNC</u><br>M</b>obile <b>N</b>etwork <b>C</b>ode<br>" \
	"The combination of both (also known as a \"MCC / MNC tuple\") is used to uniquely identify a " \
	"mobile phone operator/carrier using the GSM/LTE, CDMA, iDEN, TETRA and UMTS public land mobile " \
	"networks and some satellite mobile networks.<p>" \
	"<b><u>LAC</u><br>L</b>ocatin <b>A</b>rea <b>C</b>ode<br>" \
	"Used to identify a location area within a GSM PLMN (Public Land Mobile Network)<p>" \
	"<b><u>CID</u><br>C</b>ell <b>ID</b><br>" \
	"A generally unique number used to identify each Base transceiver station (BTS) or sector of " \
	"a BTS within a Location area code (LAC) if not within a GSM network.<p>" \
	"<b><u>RNC-ID</u><br>R</b>adio <b>N</b>etwork <b>C</b>ontroller <b>Id</b>entification<br>" \
	"The Radio Network Controller (or RNC) is a governing element in the UMTS radio access network " \
        "(UTRAN) and is responsible for controlling the Node Bs that are connected to it. " \
	"The RNC carries out radio resource management, some of the mobility management functions and " \
	"is the point where encryption is done before user data is sent to and from the mobile<p>" \
	"<b><u>CS</u><br>C</b>ircuit <b>S</b>witched<br>" \
	"a methodology of implementing a telecommunications network in which two network nodes establish " \
	"a dedicated communications channel (circuit) through the network before the nodes may communicate. " \
	"The circuit guarantees the full bandwidth of the channel and remains connected for the duration of " \
	"the communication session. The circuit functions as if the nodes were physically connected as with " \
	"an electrical circuit.<p>" \
	"<b><u>GPRS</u><br>G</b>eneral <b>P</b>acket <b>R</b>adio <b>S</b>ervice<br>" \
	"a packet oriented mobile data service on the 2G and 3G cellular communication system's " \
	"global system for mobile communications<p>" \
	"<b><u>EGPRS</u><br>E</b>nhanced <b>G</b>eneral <b>P</b>acket <b>R</b>adio <b>S</b>ervice<p>" \
	"<b><u>HSDPA</u><br>H</b>igh <b>S</b>peed <b>D</b>ownlink <b>P</b>acket <b>A</b>ccess<br>" \
	"3G mobile telephony communications protocol for high speed data transfers<p>" \
	"<b><u>HSUPA</u><br>H</b>igh <b>S</b>peed <b>U</b>plink <b>P</b>acket <b>A</b>ccess<br>" \
	"The name HSUPA was created by Nokia. The official 3GPP name for 'HSUPA' is Enhanced Uplink (EUL)</html>"
	# signals
	self.connect(helpButton, SIGNAL("clicked()"),self.helpButtonPressed)
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)

	# act as soon as display goes off
	busobj = self.bus.get_object('com.nokia.mce', '/com/nokia/mce/signal') 
        busiface = dbus.Interface(busobj, 'com.nokia.mce.signal')
        busiface.connect_to_signal('display_status_ind', self.displaystate_change)

	self.bus.add_signal_receiver(self.signal_signal_strength_change, dbus_interface = "Phone.Net", signal_name = "signal_strength_change")
	self.bus.add_signal_receiver(self.signal_cell_info_change, dbus_interface = "Phone.Net", signal_name = "cell_info_change")
	self.bus.add_signal_receiver(self.signal_operator_name_change, dbus_interface = "Phone.Net", signal_name = "operator_name_change")
	#self.bus.add_signal_receiver(self.signal_radio_access_technology_change, dbus_interface = "Phone.Net", signal_name = "radio_access_technology_change")
	self.bus.add_signal_receiver(self.signal_cellular_system_state_change, dbus_interface = "Phone.Net", signal_name = "cellular_system_state_change")

    def displaystate_change(self, state):
	if (state == "off"):
		self.remove_signals()
	elif (state == "on"):
	 	self.add_signals()

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

    def	remove_signals(self):
	# remove the signal receivers at leaving page
	self.bus.remove_signal_receiver(self.signal_signal_strength_change, dbus_interface = "Phone.Net", signal_name = "signal_strength_change")
	self.bus.remove_signal_receiver(self.signal_cell_info_change, dbus_interface = "Phone.Net", signal_name = "cell_info_change")
	self.bus.remove_signal_receiver(self.signal_operator_name_change, dbus_interface = "Phone.Net", signal_name = "operator_name_change")
#	self.bus.remove_signal_receiver(self.signal_radio_access_technology_change, dbus_interface = "Phone.Net", signal_name = "radio_access_technology_change")
	self.bus.remove_signal_receiver(self.signal_cellular_system_state_change, dbus_interface = "Phone.Net", signal_name = "cellular_system_state_change")

    def	add_signals(self):
	self.bus.add_signal_receiver(self.signal_signal_strength_change, dbus_interface = "Phone.Net", signal_name = "signal_strength_change")
	self.bus.add_signal_receiver(self.signal_cell_info_change, dbus_interface = "Phone.Net", signal_name = "cell_info_change")
	self.bus.add_signal_receiver(self.signal_operator_name_change, dbus_interface = "Phone.Net", signal_name = "operator_name_change")
#	self.bus.add_signal_receiver(self.signal_radio_access_technology_change, dbus_interface = "Phone.Net", signal_name = "radio_access_technology_change")
	self.bus.add_signal_receiver(self.signal_cellular_system_state_change, dbus_interface = "Phone.Net", signal_name = "cellular_system_state_change")
	
    def signal_signal_strength_change(self, *values):
	self.SignalTxt.setText(str(int(values[0])) + "%, " + str(int(values[1])) + " dBm")

    def signal_cell_info_change(self, *values):
	print values
	self.LACtxt.setText(str(values[1]))
	self.CIDtxt.setText(str(values[2] & 65535))
	self.RNCtxt.setText(str(values[2] >> 16))
	pattern_code = '[0-9]{1,3} \('
	self.operTXT.setText(re.sub(pattern_code,str(values[3]) + " (",self.operTXT.text()))
	self.countryTXT.setText(re.sub(pattern_code,str(values[4]) + " (",self.countryTXT.text()))
	commando = "cat /opt/cellnet-info/data/operator_info.txt|grep ^" + str(values[4]) + " |awk -F \"\t\" '{ print $2}'|head -1"
	fin,fout = os.popen4(commando)
	country_name = fout.read()
	pattern_code = '\(.*\)"'
	self.countryTXT.setText(re.sub(pattern_code, " (" + country_name + ")" ,self.countryTXT.text()))
	dbus_object = self.bus.get_object('com.nokia.phone.net', '/com/nokia/phone/net',False)
	dbus_interface = dbus.Interface(dbus_object, 'Phone.Net')
        radio_technology = dbus_interface.get_selected_radio_access_technology()[0]
	if (radio_technology == 0): technology = "DUAL"
        elif (radio_technology == 1): technology = "GSM"
        elif (radio_technology == 2): technology = "3G"
        else: technology = "?"
	self.selectedTechTXT.setText(technology)

    def signal_operator_name_change(self, *values):
	pattern_code = '\(.*\)"'
	self.operTXT.setText(re.sub(pattern_code, " (" + values[1] + ")" ,self.operTXT.text()))

    def signal_cellular_system_state_change(self, *values):
        if (values[0] == 1): used_technology = "GSM"
        elif (values[0] == 2): used_technology = "3G"
	else: used_technology = "?"
	self.usedTechTXT.setText(used_technology)
	

    def helpButtonPressed(self):
	widget = helpWindow(self)
	widget.show()

    def orientationChanged(self):
	screenGeometry = QApplication.desktop().screenGeometry()
	if screenGeometry.width() > screenGeometry.height():
		# landscape
		self.wg.resize(780,300)
		self.wg.setMinimumHeight(420)
		self.wg.setMaximumHeight(420)
	else:
		# portrait
		self.wg.resize(470,680)
		self.wg.setMinimumHeight(740)
		self.wg.setMaximumHeight(740)

class helpWindow(QWidget):
    def __init__(self,parent):
	super(helpWindow, self).__init__(parent)
	self.wg = QDialog(self)
	self.wg.resize(398, 692)
	sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
	sizePolicy.setHorizontalStretch(0)
	sizePolicy.setVerticalStretch(0)
	sizePolicy.setHeightForWidth(self.wg.sizePolicy().hasHeightForWidth())
	self.wg.setSizePolicy(sizePolicy)
	self.wg.setWindowTitle("Terms explained")
	self.grid = QGridLayout(self.wg)

	termsInfo = QTextBrowser()
	termsInfo.setMinimumSize(QSize(330, 340))
	termsInfo.setHtml( infoTXT )
        font = QFont()
        font.setPointSize(16)
        termsInfo.setFont(font)
	self.grid.addWidget(termsInfo, 0, 0)
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
	self.HelpWindowOpen = False
	self.wg.show()

    def orientationChanged(self):
	screenGeometry = QApplication.desktop().screenGeometry()
	if screenGeometry.width() < screenGeometry.height():
		# portrait
		self.wg.resize(398, 692)

class globalinfoWindow(QMainWindow):
    def __init__(self,parent):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("Mobile networks")
	global infoTXT
	# layout
        area = QScrollArea()
        lay = QVBoxLayout()
        lay.addWidget(area)
        self.wg = QWidget()
        area.setWidget(self.wg)
        self.setCentralWidget(area)
        grid = QGridLayout(self.wg)
        self.wg.show()
	self.orientationChanged()
        area.show()
        self.setLayout(grid)

	infoTXT = "<html><b><u>MCC</u><br>M</b>obile <b>C</b>ountry <b>C</b>ode<p>" \
	"<b><u>MNC</u><br>M</b>obile <b>N</b>etwork <b>C</b>ode<p>" \
	"The combination of both (also known as a \"MCC / MNC tuple\") is used to uniquely identify " \
	"a mobile phone operator/carrier using the GSM/LTE, CDMA, iDEN, TETRA and UMTS public land " \
	"mobile networks and some satellite mobile networks.<p></html>"

	output = proc.stdout.read()
	output = output.splitlines()
	list_MNC = []
	list_MCC = []
	list_Oper = []
	pattern_code = r'"[0-9]{1,3}"'
	pattern_operator = r'"[a-zA-Z]'
	array_count = 0
	for line in output:
		if "array [" in line:
			array_count += 1
		if array_count == 2:
			# MNC list
			if re.search(pattern_code, line):
				list_MNC.append(re.findall(r'\d+',line))
		if array_count == 3:
			# MCC list
			if re.search(pattern_code, line):
				list_MCC.append(re.findall(r'\d+',line))
		if array_count == 4:
			# Operator list
			if re.search(pattern_operator, line):
				pattern = r'"(.*)"'
				m = re.search(pattern,line)
				if m is not None:
					x= m.group().replace('"','')
					list_Oper.append(x)

	# layout
	line1 = QFrame()
	line1.setLineWidth(3)
	line1.setMidLineWidth(3)
	line1.setFrameShape(QFrame.HLine)
	line1.setFrameShadow(QFrame.Sunken)
	MCClabel = QLabel("<center><b>MCC</b></center>")
	MCClabel.setStyleSheet("QLabel { background-color : #0000A0; color : white; }")
	MNClabel = QLabel("<center><b>MNC</b></center>")
	MNClabel.setStyleSheet("QLabel { background-color : #0000A0; color : white; }")
	Operlabel = QLabel("<center><b>Operator</b></center>")
	Operlabel.setStyleSheet("QLabel { background-color : #0000A0; color : white; }")
	grid.addWidget(line1,0,0,1,3)
	grid.addWidget(MCClabel,1,0)
	grid.addWidget(MNClabel,1,1)
	grid.addWidget(Operlabel,1,2)
	line2 = QFrame()
	line2.setFrameShape(QFrame.HLine)
	line2.setFrameShadow(QFrame.Sunken)
	grid.addWidget(line2,2,0,1,3)
	list_MNC = tuple(list_MNC)
	list_MNC = tuple(tuple(x) for x in list_MNC)
	list_MNC = sum(list_MNC,())
	list_MCC = tuple(list_MCC)
	list_MCC = tuple(tuple(x) for x in list_MCC)
	list_MCC = sum(list_MCC,())
	list_Oper = tuple(list_Oper)

	for index_nr in range (0, len(list_Oper)):
		grid.addWidget(QLabel("<center>"+list_MCC[index_nr]+"</center>"),index_nr+3,0)
		grid.addWidget(QLabel("<center>"+list_MNC[index_nr]+"</center>"),index_nr+3,1)
		grid.addWidget(QLabel("<center>"+list_Oper[index_nr]+"</center>"),index_nr+3,2)
	if 'index_nr' in locals():
		# only show of index_nr exists as variable
		os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
			/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
			string:"' + str(index_nr+1) + ' operator(s) found..."')
	else:
		grid.addWidget(QLabel("<h1> </h1> "),3,0,1,3)
		grid.addWidget(QLabel("<h1><center>no result</center</h1>"),4,0,1,3)
		grid.addWidget(QLabel("<h1> </h1> "),5,0,1,3)
		os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
			/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
			string:"No operators found..."')

	helpButton = QPushButton("Help",self)
	grid.addWidget(helpButton,20,0,1,3)
	# signals
	self.connect(helpButton, SIGNAL("clicked()"),self.helpButtonPressed)
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)

    def helpButtonPressed(self):
	widget = helpWindow(self)
	widget.show()

    def orientationChanged(self):
	screenGeometry = QApplication.desktop().screenGeometry()
	if screenGeometry.width() > screenGeometry.height():
		# landscape
		self.wg.resize(780,300)
		self.wg.setMinimumHeight(420)
		self.wg.setMaximumHeight(420)
	else:
		# portrait
		self.wg.resize(470,680)
		self.wg.setMinimumHeight(740)
		self.wg.setMaximumHeight(740)

class queryWindow(QMainWindow):
    def __init__(self,parent):
        QMainWindow.__init__(self, parent)
	global infoTXT
        self.setWindowTitle("Code info")
	# layout
        area = QScrollArea()
        lay = QVBoxLayout()
        lay.addWidget(area)
        self.wg = QWidget()
        area.setWidget(self.wg)
        self.setCentralWidget(area)
        grid = QGridLayout(self.wg)
        self.wg.show()
	self.orientationChanged()
        area.show()
        self.setLayout(grid)
	self.countryButton = QPushButton("Choose country")
	self.operatorButton = QPushButton("Choose operator")
	self.operatorButton.setEnabled(False)
	helpButton = QPushButton("Help",self)
	findButton = QPushButton("mobile code info")
	line1 = QFrame()
	line1.setLineWidth(3)
	line1.setMidLineWidth(3)
	line1.setFrameShape(QFrame.HLine)
	line1.setFrameShadow(QFrame.Sunken)
	line2 = QFrame()
	line2.setLineWidth(3)
	line2.setMidLineWidth(3)
	line2.setFrameShape(QFrame.HLine)
	line2.setFrameShadow(QFrame.Sunken)
	line3 = QFrame()
	line3.setLineWidth(3)
	line3.setMidLineWidth(3)
	line3.setFrameShape(QFrame.HLine)
	line3.setFrameShadow(QFrame.Sunken)
	grid.addWidget(line1,0,0)
	grid.addWidget(QLabel("<center><h2>Country:</h2></center>"),1,0)
	grid.addWidget(self.countryButton,2,0)
	grid.addWidget(QLabel("<center><b> </b></center>"),3,0)
	grid.addWidget(line2,4,0)
	grid.addWidget(QLabel("<center><h2>Operator:</h2></center>"),5,0)
	grid.addWidget(self.operatorButton,6,0)
	grid.addWidget(QLabel("<center><b> </b></center>"),7,0)
	grid.addWidget(line3,8,0)
	grid.addWidget(helpButton,9,0)
	self.setLayout(grid)
	infoTXT = "<html><b><u>MCC</u><br>M</b>obile <b>C</b>ountry <b>C</b>ode<p>" \
	"<b><u>MNC</u><br>M</b>obile <b>N</b>etwork <b>C</b>ode<p>" \
	"The combination of both (also known as a \"MCC / MNC tuple\") is used to uniquely " \
        "identify a mobile phone operator/carrier using the GSM/LTE, CDMA, iDEN, TETRA and " \
        "UMTS public land mobile networks and some satellite mobile networks.<p><html>"
	# signals
	self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
	self.connect(helpButton, SIGNAL("clicked()"),self.helpButtonPressed)
	self.connect(self.countryButton, SIGNAL("clicked()"),self.countryButtonPressed)
	self.connect(self.operatorButton, SIGNAL("clicked()"),self.operatorButtonPressed)

    def helpButtonPressed(self):
	widget = helpWindow(self)
	widget.show()

    def printMsg(self,message,duration):
	box = QMaemo5InformationBox()
	box.information(self, message, duration)
	box.show()

    def countryButtonPressed(self):
        countryPick = countryPickDialog(self)
        countryPick.show()
	if country_selected:
		self.countryButton.setText(country_selected.replace("~","'"))
		self.operatorButton.setEnabled(True)

    def operatorButtonPressed(self):
        operatorPick = operatorPickDialog(self)
        operatorPick.show()
	if operator_selected:
		self.operatorButton.setText(operator_selected.replace("~","'"))
		# show info
		self.printMsg("<br><b>Country:</b> " + country_selected.replace("~","'") + \
		"<br><b>MCC:</b> " + mcc_selected + \
		"<br><b>Operator:</b> " + operator_selected.replace("~","'") + \
		"<br><b>MNC:</b> " + mnc_selected + "<br>",0)

    def orientationChanged(self):
	screenGeometry = QApplication.desktop().screenGeometry()
	if screenGeometry.width() > screenGeometry.height():
		# landscape
		self.wg.resize(780,300)
		self.wg.setMinimumHeight(420)
		self.wg.setMaximumHeight(420)
	else:
		# portrait
		self.wg.resize(470,680)
		self.wg.setMinimumHeight(740)
		self.wg.setMaximumHeight(740)

class countryPickDialog(QWidget):
    def __init__(self,parent):
	super(countryPickDialog, self).__init__(parent)
	# layout
	self.d = QDialog(self)
	self.d.setMinimumHeight(680)
	self.d.setMaximumHeight(680)
	self.d.setWindowTitle("[Choose country]")
        hbox = QGridLayout()
        horizontalLayout = QGridLayout()
        self.countryWidget = QListWidget()

	operator_info_file="/opt/cellnet-info/data/operator_info.txt"
	if not os.path.isfile(operator_info_file):
		QMessageBox.critical(self, "Critical",  "Cannot read " + operator_info_file)
		countries = ""
	else:
		commando = "cat " + operator_info_file +"|awk -F \"\t\" '{print $2}'|sort -u"
		fin,fout = os.popen4(commando)
		countries = fout.read()

	# fill country list
        for country in countries.strip().split("\n"):
                item = QListWidgetItem(country.decode('utf-8'))
                item.setTextAlignment(Qt.AlignCenter)
                self.countryWidget.addItem(item)

        horizontalLayout.addWidget(self.countryWidget,0,0)
        self.d.setLayout(hbox)
        hbox.addLayout (horizontalLayout,0,0)
	# signals
        self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
        self.connect(self.countryWidget, SIGNAL("itemClicked(QListWidgetItem *)"), self.itemClicked)
        self.d.exec_()

    def itemClicked(self, item):
	global country_selected
	global mcc_selected
        country_selected = item.text().replace("'","~")
	operator_info_file="/opt/cellnet-info/data/operator_info.txt"
	if os.path.isfile(operator_info_file):
		commando = "cat " + operator_info_file + "|tr \"'\" \"~\"|awk -F \"\t\" '$2 == \"" \
			 + country_selected + "\"'|awk -F \"\t\" '{print $1}'|head -1"
		fin,fout = os.popen4(commando)
		mcc_selected = fout.read()
	self.d.close()

    def orientationChanged(self):
        screenGeometry = QApplication.desktop().screenGeometry()
        if screenGeometry.width() > screenGeometry.height():
                # landscape
                self.d.setMinimumHeight(680)
                self.d.setMaximumHeight(680)
                self.countryWidget.scrollToItem(self.countryWidget.currentItem(),QAbstractItemView.PositionAtTop)
        else:
                # portrait
                self.d.resize(680,740)
                self.d.setMinimumHeight(680)
                self.d.setMaximumHeight(680)
                self.countryWidget.scrollToItem(self.countryWidget.currentItem(),QAbstractItemView.PositionAtCenter)

		
class operatorPickDialog(QWidget):
    def __init__(self,parent):
	super(operatorPickDialog, self).__init__(parent)
	# layout
	global operator_selected
	operator_selected = ""
	self.d = QDialog(self)
	self.d.setMinimumHeight(680)
	self.d.setMaximumHeight(680)
	self.d.setWindowTitle("[Choose operator]")
        hbox = QGridLayout()
        horizontalLayout = QGridLayout()
        self.operatorWidget = QListWidget()

	commando = "cat /opt/cellnet-info/data/operator_info.txt|tr \"'\" \"~\"|awk -F \"\t\" '$2 == \"" \
		+ country_selected + "\"'|awk -F \"\t\" '{print $NF}'|sort -u"
	fin,fout = os.popen4(commando)
	operators = fout.read()

	# add operators for coutry
        for operator in operators.strip().split("\n"):
                item = QListWidgetItem(operator.decode('utf-8').replace("~","'"))
                item.setTextAlignment(Qt.AlignCenter)
                self.operatorWidget.addItem(item)

        horizontalLayout.addWidget(self.operatorWidget,0,0)

        self.d.setLayout(hbox)
        hbox.addLayout (horizontalLayout,0,0)
	# signals
        self.connect(QApplication.desktop(), SIGNAL("resized(int)"), self.orientationChanged)
        self.connect(self.operatorWidget, SIGNAL("itemClicked(QListWidgetItem *)"), self.itemClicked)
        self.d.exec_()

    def itemClicked(self, item):
	global operator_selected
	global mnc_selected
        operator_selected = item.text().replace("'","~")
	commando = "cat /opt/cellnet-info/data/operator_info.txt|tr \"'\" \"~\"|awk -F \"\t\" '$2 == \"" \
		+ country_selected + "\"'|awk -F \"\t\" '$NF == \"" + operator_selected + "\"'|awk -F \"\t\" '{print $3}'|head -1"
	fin,fout = os.popen4(commando)
	mnc_selected = fout.read().replace("~","'")
	self.d.close()

    def orientationChanged(self):
        screenGeometry = QApplication.desktop().screenGeometry()
        if screenGeometry.width() > screenGeometry.height():
                # landscape
                self.d.setMinimumHeight(680)
                self.d.setMaximumHeight(680)
                self.operatorWidget.scrollToItem(self.operatorWidget.currentItem(),QAbstractItemView.PositionAtTop)
        else:
                # portrait
                self.d.resize(680,740)
                self.d.setMinimumHeight(680)
                self.d.setMaximumHeight(680)
                self.operatorWidget.scrollToItem(self.operatorWidget.currentItem(),QAbstractItemView.PositionAtCenter)


if __name__ == '__main__':
    # QApplication controls things relating to a Qt application, like the main loop.
    # You should always instantiate it before using any QtGui related stuff.
    # See also:
    #   http://doc.trolltech.com/4.6/qapplication.html
    app = QApplication(sys.argv)

    # Create an instance (calling __init__, too, of course) of our window subclassing QWidget
    w = MyMainWindow()
    dbus_loop = DBusQtMainLoop()
    dbus.set_default_main_loop(dbus_loop)     

    # Show our window
    w.show()
 
    # Main event loop of Qt. This won't return until the program exits.

    #mainloop = DBusQtMainLoop(set_as_default=True)
    #dbus.set_default_main_loop(mainloop)
    #loop = DBusQtMainLoop()
    #dbus.set_default_main_loop(loop)
    app.exec_()
    sys.exit()
