#!/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, subprocess
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtMaemo5 import QMaemo5InformationBox
import dbus
from dbus.mainloop.qt import DBusQtMainLoop
import re
import urllib2
import socket

 
# 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-8"
infoTXT = ""
country_selected = ""
mcc_selected = ""
operator_selected = ""
mnc_selected = ""
proc = ""
CommentChar = '#'
OptionChar =  ' '
Home = os.path.expanduser("~")
Cellnet_CfgDir = Home + '/.config/cellnet-info/'
Cellnet_CfgFile = Cellnet_CfgDir + 'cellnet-info.cfg'
NetWorkAccess = True

def parse_config(self, filename):
	options = {}
	f = open(filename,"r")
	for line in f:
		# First, remove comments:
		if CommentChar in line:
			# split on comment char, keep only the part before
			line, comment = line.split(CommentChar, 1)
		# Second, find lines with an option=value:
		if OptionChar in line:
			# split on option char:
			option, value = line.split(OptionChar, 1)
			# strip spaces:
			option = option.strip()
			value = value.strip()
			# store in dictionary:
			options[option] = value
	f.close()
	return options


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
		global NetWorkAccess

		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)
		self.networkAction = QAction( '&Access internet for location' ,self)
		self.networkAction.setCheckable(True)


		# Create config dir if needed
		if not os.path.exists(Cellnet_CfgDir):
			os.mkdir(Cellnet_CfgDir)
		# Create config files if needed
		if not os.path.isfile(Cellnet_CfgFile):
			try:
				newConfigFile = open(Cellnet_CfgFile,"w")
			except:
				QMessageBox.critical(self, "Warning",  "Cannot write " + Cellnet_CfgFile)
			else:
				newConfigFile.write("access_internet true\n")
				newConfigFile.close()
		else:
			access_internetset = False
			ConfigFile = open(Cellnet_CfgFile,"r")
			lines = ConfigFile.readlines()
			for line in lines:
				if 'access_internet' in line:
					access_internetset = True
			ConfigFile.close()
			if not access_internetset:
				ConfigFile = open(Cellnet_CfgFile,"a")
				ConfigFile.write("access_internet true\n")
				ConfigFile.close()
	
		###############
		# read config #
		###############
		global OptionChar
		OptionChar = " "
		self.cellnet_opts = parse_config(self,Cellnet_CfgFile)

		if self.cellnet_opts["access_internet"] == "true":
			self.networkAction.setChecked(True)
		else:
			NetWorkAccess = False

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

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

	def saveSettings(self):
		if self.networkAction.isChecked():
			self.cellnet_opts["access_internet"] = "true"
		else: self.cellnet_opts["access_internet"] = "false"
		try:
			newConfigFile = open(Cellnet_CfgFile,"w")
			for option in self.cellnet_opts:
				newConfigFile.write(option + " " + self.cellnet_opts[option] + "\n")
			newConfigFile.close()
			os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
				/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
				string:"Configuration is successfully saved"')
		except:
			os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
				/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
				string:"Could NOT save Configuration!"')

	def networkPushed(self):
		global NetWorkAccess
		if self.networkAction.isChecked():
			NetWorkAccess = True
		else:
			NetWorkAccess = False
		self.saveSettings()

	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("  Provider info")
		self.siminfoButton.setIcon(QIcon("/opt/cellnet-info/images/sim-card.png"))
		self.deviceinfoButton = QPushButton()
		self.deviceinfoButton.setText("  Device info")
		self.deviceinfoButton.setIcon(QIcon.fromTheme("general_call"))
		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.deviceinfoButton.setFont(font)
		self.cellinfoButton.setFont(font)
		self.globalinfoButton.setFont(font)
		self.queryButton.setFont(font)
		# sizes
		self.headerLabel.setMinimumHeight(64)
		self.deviceinfoButton.setMinimumHeight(138)
		self.siminfoButton.setMinimumHeight(138)
		self.cellinfoButton.setMinimumHeight(138)
		self.globalinfoButton.setMinimumHeight(138)
		self.queryButton.setMinimumHeight(138)
		# signals/slots
		self.connect(self.siminfoButton, SIGNAL("clicked()"),self.siminfoButtonPressed)
		self.connect(self.deviceinfoButton, SIGNAL("clicked()"),self.deviceinfoButtonPressed)
		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
			# show progress indicator
			self.progress_sign = QMovie("/opt/cellnet-info/images/spinning-wheel.gif", QByteArray(), self)
			self.progress_sign.setCacheMode(QMovie.CacheAll)
			self.progress_sign.setSpeed(100)
			self.headerLabel.setMovie(self.progress_sign)
			self.progress_sign.start()
			# call widget
			widget = simWindow(self)
			widget.setAttribute(Qt.WA_Maemo5StackedWindow)
			widget.setAttribute(Qt.WA_DeleteOnClose)
			self.connect(widget, SIGNAL("destroyed()"),self.openManWinTrue)
			widget.show()
			self.progress_sign.stop()

	def deviceinfoButtonPressed(self):
		if not self.WindowOpen:
			# prevent opening of multiple windows
			self.WindowOpen = True
			widget = deviceWindow(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):
		infoTXT = "<h2>CellNet-Info</h2>"
		self.headerLabel.setText(infoTXT)
		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.deviceinfoButton)
			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)
			self.grid.addWidget(self.siminfoButton,0,1)
			self.grid.addWidget(self.deviceinfoButton,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.deviceinfoButton)
			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.deviceinfoButton,2,0)
			self.grid.addWidget(self.cellinfoButton,3,0)
			self.grid.addWidget(self.globalinfoButton,4,0)
			self.grid.addWidget(self.queryButton,5,0)

class simWindow(QMainWindow):
	def __init__(self,parent):
		QMainWindow.__init__(self, parent)
		self.setWindowTitle("Provider 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())
		# MCUSW/DSPSW
		dbus_object = self.bus.get_object('com.nokia.csd.Info', '/com/nokia/csd/info',False)
		MCUSWinfo = dbus.Interface(dbus_object, 'com.nokia.csd.Info')
		MCUSW = str(MCUSWinfo.GetDSPSWVersion())
		# Unconditional Divert
		proc = subprocess.Popen(['dbus-send' ,'--system', '--dest=com.nokia.csd.SS', '--type=method_call', '--print-reply=literal', \
			'/com/nokia/csd/ss', 'com.nokia.csd.SS.DivertCheck', 'uint32:1'], stdout=subprocess.PIPE)
		while (True):
			QApplication.processEvents()
			time.sleep(1)
			if proc.poll() is not None:
				# we have received output
				break
		UncondDivert = proc.stdout.read().decode('UTF8').strip().split()
		if not UncondDivert:
			UncondDivert = "----"
		elif UncondDivert[1] == "true":
			UncondDivert = UncondDivert[2]
		else:
			UncondDivert = "----"
		# Busy divert
		proc = subprocess.Popen(['dbus-send' ,'--system', '--dest=com.nokia.csd.SS', '--type=method_call', '--print-reply=literal', \
			'/com/nokia/csd/ss', 'com.nokia.csd.SS.DivertCheck', 'uint32:2'], stdout=subprocess.PIPE)
		while (True):
			QApplication.processEvents()
			time.sleep(1)
			if proc.poll() is not None:
				# we have received output
				break
		BusyDivert = proc.stdout.read().decode('UTF8').strip().split()
		if not BusyDivert:
			BusyDivert = "----"
		elif BusyDivert[1] == "true":
			BusyDivert = BusyDivert[2]
		else:
			BusyDivert = "----"
		# No reply divert
		proc = subprocess.Popen(['dbus-send' ,'--system', '--dest=com.nokia.csd.SS', '--type=method_call', '--print-reply=literal', \
			'/com/nokia/csd/ss', 'com.nokia.csd.SS.DivertCheck', 'uint32:3'], stdout=subprocess.PIPE)
		while (True):
			QApplication.processEvents()
			time.sleep(1)
			if proc.poll() is not None:
				# we have received output
				break
		NoreplyDivert = proc.stdout.read().decode('UTF8').strip().split()
		if not NoreplyDivert:
			NoreplyDivert = "----"
		elif NoreplyDivert[1] == "true":
			NoreplyDivert = NoreplyDivert[2]
		else:
			NoreplyDivert = "----"
		# Not reachable divert
		proc = subprocess.Popen(['dbus-send' ,'--system', '--dest=com.nokia.csd.SS', '--type=method_call', '--print-reply=literal', \
			'/com/nokia/csd/ss', 'com.nokia.csd.SS.DivertCheck', 'uint32:4'], stdout=subprocess.PIPE)
		while (True):
			QApplication.processEvents()
			time.sleep(1)
			if proc.poll() is not None:
				# we have received output
				break
		NotreachableDivert = proc.stdout.read().decode('UTF8').strip().split()
		if not NotreachableDivert:
			NotreachableDivert = "----"
		elif NotreachableDivert[1] == "true":
			NotreachableDivert = NotreachableDivert[2]
		else:
			NotreachableDivert = "----"
		# network time:
		dbus_object = self.bus.get_object('com.nokia.phone.net', '/com/nokia/phone/net',False)
		networktimeInfo = dbus.Interface(dbus_object, 'Phone.Net')
		networktime = networktimeInfo.get_network_time_info()
		(yy, mm, dd, hh, mi, ss, tz, dl, err) = networktime
		if yy == 100:
			# assuming this means no networktime provided
			networktimeVal = "----"
		else:
			networktimeVal = yy+"/"+mm+"/"+dd+" "+hh+":"+mm+":"+ss
		# define screen content
		font = QFont()
		font.setPointSize(20)
		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)
		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';")
		unconditionalDivertTxt = QLabel("uncondit divert")
		unconditionalDivertTxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		UncondDivertlabel = QLabel(UncondDivert)
		UncondDivertlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		busyDivertTxt = QLabel("busy divert")
		busyDivertTxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		busyDivertlabel = QLabel(BusyDivert)
		busyDivertlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		noreplyDivertTxt = QLabel("no reply divert")
		noreplyDivertTxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		noreplyDivertlabel = QLabel(NoreplyDivert)
		noreplyDivertlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		notreachableDivertTxt = QLabel("notreach divert")
		notreachableDivertTxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		notreachableDivertlabel = QLabel(NoreplyDivert)
		notreachableDivertlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		networktimeTxt = QLabel("network time")
		networktimeTxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		networktimelabel = QLabel(networktimeVal)
		networktimelabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignRight';")
		# add to layout
		grid.addWidget(line1, 1, 0, 1, 2)
		grid.addWidget(statustxt,8,0)
		grid.addWidget(self.statuslabel,8,1)
		grid.addWidget(operatortxt,9,0)
		grid.addWidget(operatorlabel,9,1)
		grid.addWidget(IMSItxt,10,0)
		grid.addWidget(IMSIlabel,10,1)
		grid.addWidget(ICCIDtxt,11,0)
		grid.addWidget(ICCIDlabel,11,1)
		grid.addWidget(unconditionalDivertTxt,12,0)
		grid.addWidget(UncondDivertlabel,12,1)
		grid.addWidget(busyDivertTxt,13,0)
		grid.addWidget(busyDivertlabel,13,1)
		grid.addWidget(noreplyDivertTxt,14,0)
		grid.addWidget(noreplyDivertlabel,14,1)
		grid.addWidget(notreachableDivertTxt,15,0)
		grid.addWidget(notreachableDivertlabel,15,1)
		grid.addWidget(networktimeTxt,16,0)
		grid.addWidget(networktimelabel,16,1)
		grid.addWidget(line3, 17, 0, 1, 2)
		helpButton = QPushButton("Help",self)
		grid.addWidget(helpButton,18,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 deviceWindow(QMainWindow):
	def __init__(self,parent):
		QMainWindow.__init__(self, parent)
		self.setWindowTitle("Device 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
		# IMEI 
		self.bus = dbus.SystemBus()
		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]) 
		# MCUSW/DSPSW
		dbus_object = self.bus.get_object('com.nokia.csd.Info', '/com/nokia/csd/info',False)
		MCUSWinfo = dbus.Interface(dbus_object, 'com.nokia.csd.Info')
		MCUSW = str(MCUSWinfo.GetMCUSWVersion()).replace("\n", " ").replace("(c) Nokia","")
		# Emergency numbers
		dbus_object = self.bus.get_object('com.nokia.csd.Call', '/com/nokia/csd/call',False)
		EmergencyNbrInfo = dbus.Interface(dbus_object, 'com.nokia.csd.Call')
		EmergencyNbr = EmergencyNbrInfo.GetEmergencyNumbers()
		EmergNbrs = ""
		for index_nr in range (0, len(EmergencyNbr)):
			EmergNbr = ''.join([character for character in EmergencyNbr[index_nr]])
			EmergNbrs = EmergNbrs + EmergNbr + "/"
		EmergNbrs = EmergNbrs.strip("/")
		# Profile
		profile = subprocess.Popen(['dbus-send' , '--dest=com.nokia.profiled', '--type=method_call', '--print-reply=literal', \
			'/com/nokia/profiled', 'com.nokia.profiled.get_profile'], stdout=subprocess.PIPE).stdout.read().strip()
		font = QFont()
		font.setPointSize(20)
		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|AlignCenter';")
		IMEItxt = QLabel("<u>IMEI:</u>")
		IMEItxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		MCUSWlabel = QLabel(MCUSW)
		MCUSWlabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		MCUSWtxt = QLabel("<u>MCUSW:</u>")
		MCUSWtxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		Emergencylabel = QLabel(EmergNbrs)
		Emergencylabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		Emergencytxt = QLabel("<u>emergency numbers:</u>")
		Emergencytxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		profilelabel = QLabel(profile)
		profilelabel.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		profiletxt = QLabel("<u>current profile:</u>")
		profiletxt.setStyleSheet("qproperty-alignment: 'AlignCenter|AlignCenter';")
		# add to layout
		grid.addWidget(line1,1,0,1,2)
		grid.addWidget(IMEItxt,2,0,1,2)
		grid.addWidget(IMEIlabel,3,0,1,2)
		grid.addWidget(MCUSWtxt,4,0,1,2)
		grid.addWidget(MCUSWlabel,5,0,1,2)
		grid.addWidget(Emergencytxt,6,0,1,2)
		grid.addWidget(Emergencylabel,7,0,1,2)
		grid.addWidget(profiletxt,8,0,1,2)
		grid.addWidget(profilelabel,9,0,1,2)
		grid.addWidget(line3,10,0,1,2)
		helpButton = QPushButton("Help",self)
		grid.addWidget(helpButton,11,0,1,2)
		# help text
		infoTXT = "<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>MCUSW</u></b><br>Micro Controller Software version. Related to the DSP for audio processing (telephony)<p>"
		"</html>"
		# 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 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'
		# try to fetch internet data
		self.get_cell_id_info(c_mcc,c_mnc,c_id,c_lac)
			
		# 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)
		self.selectedTechTXT = QLabel()
		self.selectedTechTXT.setText("Phone mode: " + technology)
		grid.addWidget(self.selectedTechTXT,1,0)
		self.usedTechTXT = QLabel()
		self.usedTechTXT.setText("Used mode: " + used_technology)
		grid.addWidget(self.usedTechTXT,1,1)
		grid.addWidget(QLabel("MCC"),2,0)
		self.countryTXT = QLabel()
		self.countryTXT.setText(str(c_mcc)+" ("+country_name.strip()+")")
		grid.addWidget(self.countryTXT,2,1)
		grid.addWidget(QLabel("MNC"),3,0)
		self.operTXT = QLabel()
		self.operTXT.setText(str(c_mnc)+ " ("+operator_name+")")
		grid.addWidget(self.operTXT,3,1)
		self.LACtxt = QLabel()
		self.LACtxt.setText("LAC: " + str(c_lac))
		grid.addWidget(self.LACtxt,4,0)
		self.CIDtxt = QLabel()
		self.CIDtxt.setText("CID: " + str(c_id & 65535))
		grid.addWidget(self.CIDtxt,4,1)
		self.Lattxt = QLabel()
		self.Lattxt.setText("Lat: " + self.latitude[:11] + u"\u00b0")
		grid.addWidget(self.Lattxt,5,0)
		self.Longtxt = QLabel()
		self.Longtxt.setText("Long: " + self.longitude[:11] + u"\u00b0")
		grid.addWidget(self.Longtxt,5,1)
		self.Loctxt = QLabel()
		self.Loctxt.setText("Loc: " + self.location)
		grid.addWidget(self.Loctxt,6,0,1,2)
		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)<p>" \
		"<b>Lat:</b> The latitude in decimal degrees<br>" \
		"<b>Long:</b> The longitude in decimal degrees<br>" \
		"<b>Loc:</b> The possible postal location of the cell tower<p>" \
		"<i>N.b. an internet connection is needed for location details.</i><br>" \
		"<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 get_cell_id_info(self,mcc,mnc,id,lac):
		# timeout in seconds
		timeout = 10
		socket.setdefaulttimeout(timeout)
		if str(id) != "0" and NetWorkAccess:
			# we have CellId info
			cellinf_url = "http://www.opencellid.org/cell/get?key=myapikey&mcc=" + str(mcc) + "&mnc=" + str(mnc) + "&cellid=" + str(id) + "&lac=" + str(lac)
			req = urllib2.Request(cellinf_url)
			try:
				response = urllib2.urlopen(req)
			except:
				os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
					/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
					string:"No info from opencellid.org"')
				self.location = "?"
				self.latitude = "?"
				self.longitude = "?"
			else:
				xml_str = response.read()
				if "fail" in xml_str:
					os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
						/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
						string:"cellinfo not found on opencellid.org"')
					self.location = "?"
					self.latitude = "?"
					self.longitude = "?"
				else:
					for line in xml_str.split("\n"):
						if "lat=" in line:
							self.latitude = line[line.find("lat=")+5:line.find("\" ",line.index("lat="))-2]
							self.longitude = line[line.find("lon=")+5:line.find("\" ",line.index("lon="))-2]
					maps_url = "http://maps.googleapis.com/maps/api/geocode/xml?latlng=" + self.latitude + "," + self.longitude + "&sensor=false"
					req = urllib2.Request(maps_url)
					try:
						response = urllib2.urlopen(req)
					except:
						os.system('run-standalone.sh dbus-send --type=method_call --dest=org.freedesktop.Notifications  \
							/org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteInfoprint \
							string:"No info from googleapis.com"')
						self.location = "?"
						self.latitude = "?"
						self.longitude = "?"
					else:
						xml_str = response.read().decode("utf8")
						for line in xml_str.split("\n"):
							if "formatted_address" in line:
								self.location=line[line.find(",")+2:line.find("\" ",line.index("</format"))-19]
								break
		elif not NetWorkAccess:
			self.location = "blocked"
			self.latitude = "blocked"
			self.longitude = "blocked"
		else:
			self.location = "?"
			self.latitude = "?"
			self.longitude = "?"
		if self.longitude == "0.0" or self.latitude == "0.0":
			self.location = "unknown"
			

	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):
		self.LACtxt.setText("LAC: " + str(values[1]))
		self.CIDtxt.setText("CID: " + str(values[2] & 65535))
		self.RNCtxt.setText(str(values[2] >> 16))
		self.get_cell_id_info(values[4],values[3],values[2] & 65535,values[1])
		self.Lattxt.setText("Lat: " + self.latitude[:11] + u"\u00b0")
		self.Longtxt.setText("Long: " + self.longitude[:11] + u"\u00b0")
		self.Loctxt.setText("Loc: " + self.location)
		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("Phone mode: " + 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 mode: " + 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.exec_()

	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.exec_()

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