[FritzCall] FIX: FBF phonebook for new FW version
[enigma2-plugins.git] / fritzcall / src / plugin.py
1 # -*- coding: utf-8 -*-
2 '''
3 Update rev
4 $Author: michael $
5 $Revision: 1252 $
6 $Date: 2015-12-10 11:11:04 +0100 (Thu, 10 Dec 2015) $
7 $Id: plugin.py 1252 2015-12-10 10:11:04Z michael $
8 '''
9
10
11 # C0111 (Missing docstring)
12 # C0103 (Invalid name)
13 # C0301 (line too long)
14 # W0603 (global statement)
15 # W0141 (map, filter, etc.)
16 # W0110 lambda with map,filter
17 # W0403 Relative import
18 # W1401 Anomalous backslash in string
19 # W0110 
20 # pylint: disable=C0111,C0103,C0301,W0603,W0141,W0403
21
22 from Screens.Screen import Screen
23 from Screens.MessageBox import MessageBox
24 from Screens.NumericalTextInputHelpDialog import NumericalTextInputHelpDialog
25 from Screens.InputBox import InputBox
26 from Screens import Standby
27 from Screens.HelpMenu import HelpableScreen
28 from Screens.LocationBox import LocationBox
29
30 from enigma import eTimer, eSize, ePoint #@UnresolvedImport # pylint: disable=E0611
31 from enigma import eDVBVolumecontrol, eConsoleAppContainer, eBackgroundFileEraser #@UnresolvedImport # pylint: disable=E0611
32 #BgFileEraser = eBackgroundFileEraser.getInstance()
33 #BgFileEraser.erase("blabla.txt")
34
35 from Components.ActionMap import ActionMap
36 from Components.Label import Label
37 from Components.Button import Button
38 from Components.Pixmap import Pixmap
39 from Components.Sources.List import List
40 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigDirectory, ConfigEnableDisable, getConfigListEntry, ConfigText, ConfigInteger
41 from Components.ConfigList import ConfigListScreen
42 try:
43         from Components.config import ConfigPassword
44 except ImportError:
45         ConfigPassword = ConfigText
46
47 from Plugins.Plugin import PluginDescriptor
48 from Tools import Notifications
49 from Tools.NumericalTextInput import NumericalTextInput
50 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_CONFIG
51 from Tools.LoadPixmap import LoadPixmap
52 from GlobalActions import globalActionMap # for muting
53
54 from twisted.internet import reactor #@UnresolvedImport
55 from twisted.internet.protocol import ReconnectingClientFactory #@UnresolvedImport
56 from twisted.protocols.basic import LineReceiver #@UnresolvedImport
57
58 import re, time, os, traceback
59
60 from nrzuname import ReverseLookupAndNotifier
61 import FritzOutlookCSV, FritzLDIF
62 from . import _, __, initDebug #@UnresolvedImport # pylint: disable=W0611,F0401
63
64 import logging
65 logger = logging.getLogger("[FritzCall]")
66 debug = logger.debug
67 info = logger.info
68 warn = logger.warn
69 error = logger.error
70 exception = logger.exception
71
72 from enigma import getDesktop
73 DESKTOP_WIDTH = getDesktop(0).size().width()
74 DESKTOP_HEIGHT = getDesktop(0).size().height()
75
76 #
77 # this is pure magic.
78 # It returns the first value, if HD (1280x720),
79 # the second if SD (720x576),
80 # else something scaled accordingly
81 # if one of the parameters is -1, scale proportionally
82 #
83 def scaleH(y2, y1):
84         if y2 == -1:
85                 y2 = y1*1280/720
86         elif y1 == -1:
87                 y1 = y2*720/1280
88         return scale(y2, y1, 1280, 720, DESKTOP_WIDTH)
89 def scaleV(y2, y1):
90         if y2 == -1:
91                 y2 = y1*720/576
92         elif y1 == -1:
93                 y1 = y2*576/720
94         return scale(y2, y1, 720, 576, DESKTOP_HEIGHT)
95 def scale(y2, y1, x2, x1, x):
96         return (y2 - y1) * (x - x1) / (x2 - x1) + y1
97
98 my_global_session = None
99
100 initDebug()
101
102 config.plugins.FritzCall = ConfigSubsection()
103 config.plugins.FritzCall.fwVersion = ConfigSelection(choices=[(None, _("not configured")), ("old", _("before 05.27")), ("05.27", "05.27, 05.28"), ("05.50", _("05.29 until below 6.35")), ("06.35", _("06.35 and newer"))], default=None)
104 #config.plugins.FritzCall.fwVersion = ConfigSelection(choices=[(None, _("not configured")), ("old", _("before 05.27")), ("05.27", "05.27, 05.28"), ("05.50", _("05.29 and newer"))], default=None)
105 config.plugins.FritzCall.debug = ConfigEnableDisable(default=False)
106 #config.plugins.FritzCall.muteOnCall = ConfigSelection(choices=[(None, _("no")), ("ring", _("on ring")), ("connect", _("on connect"))])
107 #config.plugins.FritzCall.muteOnCall = ConfigSelection(choices=[(None, _("no")), ("ring", _("on ring"))])
108 config.plugins.FritzCall.muteOnCall = ConfigEnableDisable(default=False)
109 config.plugins.FritzCall.hostname = ConfigText(default="fritz.box", fixed_size=False)
110 config.plugins.FritzCall.afterStandby = ConfigSelection(choices=[("none", _("show nothing")), ("inList", _("show as list")), ("each", _("show each call"))])
111 config.plugins.FritzCall.filter = ConfigEnableDisable(default=False)
112 config.plugins.FritzCall.filtermsn = ConfigText(default="", fixed_size=False)
113 config.plugins.FritzCall.filtermsn.setUseableChars('0123456789,')
114 config.plugins.FritzCall.filterCallList = ConfigEnableDisable(default=True)
115 config.plugins.FritzCall.showBlacklistedCalls = ConfigEnableDisable(default=False)
116 config.plugins.FritzCall.showOutgoingCalls = ConfigEnableDisable(default=False)
117 config.plugins.FritzCall.timeout = ConfigInteger(default=15, limits=(0, 60))
118 config.plugins.FritzCall.lookup = ConfigEnableDisable(default=False)
119 config.plugins.FritzCall.internal = ConfigEnableDisable(default=False)
120 config.plugins.FritzCall.fritzphonebook = ConfigEnableDisable(default=False)
121 config.plugins.FritzCall.fritzphonebookName = ConfigText(default='Dreambox', fixed_size=False)
122 config.plugins.FritzCall.phonebook = ConfigEnableDisable(default=False)
123 config.plugins.FritzCall.addcallers = ConfigEnableDisable(default=False)
124 config.plugins.FritzCall.enable = ConfigEnableDisable(default=False)
125 config.plugins.FritzCall.username = ConfigText(default='BoxAdmin', fixed_size=False)
126 config.plugins.FritzCall.password = ConfigPassword(default="", fixed_size=False)
127 config.plugins.FritzCall.extension = ConfigText(default='1', fixed_size=False)
128 config.plugins.FritzCall.extension.setUseableChars('0123456789')
129 config.plugins.FritzCall.showType = ConfigEnableDisable(default=True)
130 config.plugins.FritzCall.showShortcut = ConfigEnableDisable(default=False)
131 config.plugins.FritzCall.showVanity = ConfigEnableDisable(default=False)
132 config.plugins.FritzCall.prefix = ConfigText(default="", fixed_size=False)
133 config.plugins.FritzCall.prefix.setUseableChars('0123456789')
134 config.plugins.FritzCall.connectionVerbose = ConfigEnableDisable(default=True)
135 config.plugins.FritzCall.ignoreUnknown = ConfigEnableDisable(default=False)
136 config.plugins.FritzCall.reloadPhonebookTime = ConfigInteger(default=8, limits=(0, 99))
137 config.plugins.FritzCall.FritzExtendedSearchFaces = ConfigEnableDisable(default=False)
138 config.plugins.FritzCall.FritzExtendedSearchNames = ConfigEnableDisable(default=False)
139 config.plugins.FritzCall.phonebookLocation = ConfigDirectory(default = resolveFilename(SCOPE_CONFIG))
140 config.plugins.FritzCall.guestSSID = ConfigText(default="FRITZ!Box Gastzugang", fixed_size=False)
141 config.plugins.FritzCall.guestSecure = ConfigEnableDisable(default=True)
142 config.plugins.FritzCall.guestPassword = ConfigText(default="guestguest!!!", fixed_size=False)
143
144 guestWLANUptime = [(None, _('Not deactivating after time')), "15", "30", "45", "60", "90", "120", "180", "240", "300", "360", "480", "600", "720", "900", "1080", "1260"]
145 config.plugins.FritzCall.guestUptime = ConfigSelection(choices=guestWLANUptime, default="30")
146
147 countryCodes = [
148         ("0049", _("Germany")),
149         ("0031", _("The Netherlands")),
150         ("0033", _("France")),
151         ("0039", _("Italy")),
152         ("0041", _("Switzerland")),
153         ("0043", _("Austria")),
154         ("", _("Others"))
155         ]
156 config.plugins.FritzCall.country = ConfigSelection(choices=countryCodes)
157
158 FBF_ALL_CALLS = "."
159 FBF_IN_CALLS = "1"
160 FBF_MISSED_CALLS = "2"
161 FBF_OUT_CALLS = "3"
162 fbfCallsChoices = {FBF_ALL_CALLS: _("All calls"),
163                                    FBF_IN_CALLS: _("Incoming calls"),
164                                    FBF_MISSED_CALLS: _("Missed calls"),
165                                    FBF_OUT_CALLS: _("Outgoing calls")
166                                    }
167 config.plugins.FritzCall.fbfCalls = ConfigSelection(choices=fbfCallsChoices)
168
169 config.plugins.FritzCall.name = ConfigText(default="", fixed_size=False)
170 config.plugins.FritzCall.number = ConfigText(default="", fixed_size=False)
171 config.plugins.FritzCall.number.setUseableChars('0123456789')
172
173 phonebook = None
174 fritzbox = None
175
176 avon = {}
177
178 def initAvon():
179         avonFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/avon.dat")
180         if os.path.exists(avonFileName):
181                 for line in open(avonFileName):
182                         line = line.decode("iso-8859-1").encode('utf-8')
183                         if line[0] == '#':
184                                 continue
185                         parts = line.split(':')
186                         if len(parts) == 2:
187                                 avon[parts[0].replace('-','').replace('*','').replace('/','')] = parts[1]
188
189 def resolveNumberWithAvon(number, countrycode):
190         if not number or number[0] != '0':
191                 return ""
192                 
193         countrycode = countrycode.replace('00','+')
194         if number[:2] == '00':
195                 normNumber = '+' + number[2:]
196         elif number[:1] == '0':
197                 normNumber = countrycode + number[1:]
198         else: # this should can not happen, but safety first
199                 return ""
200         
201         # debug('normNumer: ' + normNumber)
202         for i in reversed(range(min(10, len(number)))):
203                 if avon.has_key(normNumber[:i]):
204                         return '[' + avon[normNumber[:i]].strip() + ']'
205         return ""
206
207 def handleReverseLookupResult(name):
208         found = re.match("NA: ([^;]*);VN: ([^;]*);STR: ([^;]*);HNR: ([^;]*);PLZ: ([^;]*);ORT: ([^;]*)", name)
209         if found:
210                 ( name, firstname, street, streetno, zipcode, city ) = (found.group(1),
211                                                                                                 found.group(2),
212                                                                                                 found.group(3),
213                                                                                                 found.group(4),
214                                                                                                 found.group(5),
215                                                                                                 found.group(6)
216                                                                                                 )
217                 if firstname:
218                         name += ' ' + firstname
219                 if street or streetno or zipcode or city:
220                         name += ', '
221                 if street:
222                         name += street
223                 if streetno:
224                         name += ' ' + streetno
225                 if (street or streetno) and (zipcode or city):
226                         name += ', '
227                 if zipcode and city:
228                         name += zipcode + ' ' + city
229                 elif zipcode:
230                         name += zipcode
231                 elif city:
232                         name += city
233         return name
234
235 from xml.dom.minidom import parse
236 cbcInfos = {}
237 def initCbC():
238         callbycallFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/callbycall_world.xml")
239         if os.path.exists(callbycallFileName):
240                 dom = parse(callbycallFileName)
241                 for top in dom.getElementsByTagName("callbycalls"):
242                         for cbc in top.getElementsByTagName("country"):
243                                 code = cbc.getAttribute("code").replace("+","00")
244                                 cbcInfos[code] = cbc.getElementsByTagName("callbycall")
245         else:
246                 error("[FritzCall] initCbC: callbycallFileName does not exist?!?!")
247
248 def stripCbCPrefix(number, countrycode):
249         if number and number[:2] != "00" and cbcInfos.has_key(countrycode):
250                 for cbc in cbcInfos[countrycode]:
251                         if len(cbc.getElementsByTagName("length"))<1 or len(cbc.getElementsByTagName("prefix"))<1:
252                                 warn("[FritzCall] stripCbCPrefix: entries for " + countrycode + " %s invalid")
253                                 return number
254                         length = int(cbc.getElementsByTagName("length")[0].childNodes[0].data)
255                         prefix = cbc.getElementsByTagName("prefix")[0].childNodes[0].data
256                         # if re.match('^'+prefix, number):
257                         if number[:len(prefix)] == prefix:
258                                 return number[length:]
259         return number
260
261 import FritzCallFBF
262
263 class FritzAbout(Screen):
264
265         def __init__(self, session):
266                 textFieldWidth = scaleV(350, 250)
267                 width = 5 + 150 + 20 + textFieldWidth + 5 + 175 + 5
268                 height = 5 + 175 + 5 + 25 + 5
269                 self.skin = """
270                         <screen name="FritzAbout" position="center,center" size="%d,%d" title="About FritzCall" >
271                                 <widget name="text" position="175,%d" size="%d,%d" font="Regular;%d" />
272                                 <ePixmap position="5,37" size="150,110" pixmap="%s" transparent="1" alphatest="blend" />
273                                 <ePixmap position="%d,5" size="175,175" pixmap="%s" transparent="1" alphatest="blend" />
274                                 <widget name="url" position="20,185" size="%d,25" font="Regular;%d" />
275                         </screen>""" % (
276                                                         width, height, # size
277                                                         (height-scaleV(150,130)) / 2, # text vertical position
278                                                         textFieldWidth,
279                                                         scaleV(150,130), # text height
280                                                         scaleV(24,21), # text font size
281                                                         resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/fritz.png"), # 150x110
282                                                         5 + 150 + 5 + textFieldWidth + 5, # qr code horizontal offset
283                                                         resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/website.png"), # 175x175
284                                                         width-40, # url width
285                                                         scaleV(24,21) # url font size
286                                                         )
287                 Screen.__init__(self, session)
288                 self["aboutActions"] = ActionMap(["OkCancelActions"],
289                 {
290                 "cancel": self.exit,
291                 "ok": self.exit,
292                 }, -2)
293                 self["text"] = Label(
294                                                         "FritzCall Plugin" + "\n\n" +
295                                                         "$Author: michael $"[1:-2] + "\n" +
296                                                         "$Revision: 1252 $"[1:-2] + "\n" + 
297                                                         "$Date: 2015-12-10 11:11:04 +0100 (Thu, 10 Dec 2015) $"[1:23] + "\n"
298                                                         )
299                 self["url"] = Label("http://wiki.blue-panel.com/index.php/FritzCall")
300                 self.onLayoutFinish.append(self.setWindowTitle)
301
302         def setWindowTitle(self):
303                 # TRANSLATORS: this is a window title.
304                 self.setTitle(_("About FritzCall"))
305
306         def exit(self):
307                 self.close()
308
309 from FritzCallFBF import FBF_dectActive, FBF_faxActive, FBF_rufumlActive, FBF_tamActive, FBF_wlanState
310 class FritzMenu(Screen, HelpableScreen):
311         def __init__(self, session):
312                 if not fritzbox or not fritzbox.information:
313                         return
314
315                 if config.plugins.FritzCall.fwVersion.value == "old" or config.plugins.FritzCall.fwVersion.value == "05.27":
316                         fontSize = scaleV(24, 21) # indeed this is font size +2
317                         noButtons = 2 # reset, wlan
318         
319                         if fritzbox.information[FBF_tamActive]:
320                                 noButtons += 1 # toggle mailboxes
321                         width = max(DESKTOP_WIDTH - scaleH(500, 250), noButtons*140+(noButtons+1)*10)
322                         # boxInfo 2 lines, gap, internet 2 lines, gap, dsl/wlan each 1 line, gap, buttons
323                         height = 5 + 2*fontSize + 10 + 2*fontSize + 10 + 2*fontSize + 10 + 40 + 5
324                         if fritzbox.information[FBF_tamActive] is not None:
325                                 height += fontSize
326                         if fritzbox.information[FBF_dectActive] is not None:
327                                 height += fontSize
328                         if fritzbox.information[FBF_faxActive] is not None:
329                                 height += fontSize
330                         if fritzbox.information[FBF_rufumlActive] is not None:
331                                 height += fontSize
332                         buttonsGap = (width-noButtons*140)/(noButtons+1)
333                         buttonsVPos = height-40-5
334         
335                         varLinePos = 4
336                         if fritzbox.information[FBF_tamActive] is not None:
337                                 mailboxLine = """
338                                         <widget name="FBFMailbox" position="%d,%d" size="%d,%d" font="Regular;%d" />
339                                         <widget name="mailbox_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
340                                         <widget name="mailbox_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
341                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
342                                         <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
343                                         """ % (
344                                                         40, 5+2*fontSize+10+varLinePos*fontSize+10, # position mailbox
345                                                         width-40-20, fontSize, # size mailbox
346                                                         fontSize-2,
347                                                         "skin_default/buttons/button_green_off.png",
348                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button mailbox
349                                                         "skin_default/buttons/button_green.png",
350                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button mailbox
351                                                         noButtons*buttonsGap+(noButtons-1)*140, buttonsVPos,
352                                                         noButtons*buttonsGap+(noButtons-1)*140, buttonsVPos,
353                                         )
354                                 varLinePos += 1
355                         else:
356                                 mailboxLine = ""
357         
358                         if fritzbox.information[FBF_dectActive] is not None:
359                                 dectLine = """
360                                         <widget name="FBFDect" position="%d,%d" size="%d,%d" font="Regular;%d" />
361                                         <widget name="dect_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
362                                         <widget name="dect_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
363                                         """ % (
364                                                         40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
365                                                         width-40-20, fontSize, # size dect
366                                                         fontSize-2,
367                                                         "skin_default/buttons/button_green_off.png",
368                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
369                                                         "skin_default/buttons/button_green.png",
370                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
371                                         )
372                                 varLinePos += 1
373                         else:
374                                 dectLine = ""
375         
376                         if fritzbox.information[FBF_faxActive] is not None:
377                                 faxLine = """
378                                         <widget name="FBFFax" position="%d,%d" size="%d,%d" font="Regular;%d" />
379                                         <widget name="fax_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
380                                         <widget name="fax_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
381                                         """ % (
382                                                         40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
383                                                         width-40-20, fontSize, # size dect
384                                                         fontSize-2,
385                                                         "skin_default/buttons/button_green_off.png",
386                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
387                                                         "skin_default/buttons/button_green.png",
388                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
389                                         )
390                                 varLinePos += 1
391                         else:
392                                 faxLine = ""
393         
394                         if fritzbox.information[FBF_rufumlActive] is not None:
395                                 rufumlLine = """
396                                         <widget name="FBFRufuml" position="%d,%d" size="%d,%d" font="Regular;%d" />
397                                         <widget name="rufuml_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
398                                         <widget name="rufuml_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
399                                         """ % (
400                                                         40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
401                                                         width-40-20, fontSize, # size dect
402                                                         fontSize-2,
403                                                         "skin_default/buttons/button_green_off.png",
404                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
405                                                         "skin_default/buttons/button_green.png",
406                                                         20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
407                                         )
408                                 varLinePos += 1
409                         else:
410                                 rufumlLine = ""
411                 
412                         self.skin = """
413                                 <screen name="FritzMenu" position="center,center" size="%d,%d" title="FRITZ!Box Fon Status" >
414                                         <widget name="FBFInfo" position="%d,%d" size="%d,%d" font="Regular;%d" />
415                                         <widget name="FBFInternet" position="%d,%d" size="%d,%d" font="Regular;%d" />
416                                         <widget name="internet_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
417                                         <widget name="internet_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
418                                         <widget name="FBFDsl" position="%d,%d" size="%d,%d" font="Regular;%d" />
419                                         <widget name="dsl_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
420                                         <widget name="dsl_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
421                                         <widget name="FBFWlan" position="%d,%d" size="%d,%d" font="Regular;%d" />
422                                         <widget name="wlan_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
423                                         <widget name="wlan_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
424                                         %s
425                                         %s
426                                         %s
427                                         %s
428                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
429                                         <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
430                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
431                                         <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
432                                 </screen>""" % (
433                                                         width, height, # size
434                                                         40, 5, # position information
435                                                         width-2*40, 2*fontSize, # size information
436                                                         fontSize-2,
437                                                         40, 5+2*fontSize+10, # position internet
438                                                         width-40, 2*fontSize, # size internet
439                                                         fontSize-2,
440                                                         "skin_default/buttons/button_green_off.png",
441                                                         20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
442                                                         "skin_default/buttons/button_green.png",
443                                                         20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
444                                                         40, 5+2*fontSize+10+2*fontSize+10, # position dsl
445                                                         width-40-20, fontSize, # size dsl
446                                                         fontSize-2,
447                                                         "skin_default/buttons/button_green_off.png",
448                                                         20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
449                                                         "skin_default/buttons/button_green.png",
450                                                         20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
451                                                         40, 5+2*fontSize+10+3*fontSize+10, # position wlan
452                                                         width-40-20, fontSize, # size wlan
453                                                         fontSize-2,
454                                                         "skin_default/buttons/button_green_off.png",
455                                                         20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
456                                                         "skin_default/buttons/button_green.png",
457                                                         20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
458                                                         mailboxLine,
459                                                         dectLine,
460                                                         faxLine,
461                                                         rufumlLine,
462                                                         buttonsGap, buttonsVPos, "skin_default/buttons/red.png", buttonsGap, buttonsVPos,
463                                                         buttonsGap+140+buttonsGap, buttonsVPos, "skin_default/buttons/green.png", buttonsGap+140+buttonsGap, buttonsVPos,
464                                                         )
465         
466                         Screen.__init__(self, session)
467                         HelpableScreen.__init__(self)
468                         # TRANSLATORS: keep it short, this is a button
469                         self["key_red"] = Button(_("Reset"))
470                         # TRANSLATORS: keep it short, this is a button
471                         self["key_green"] = Button(_("Toggle WLAN"))
472                         self._mailboxActive = False
473                         if fritzbox.information[FBF_tamActive] is not None:
474                                 # TRANSLATORS: keep it short, this is a button
475                                 self["key_yellow"] = Button(_("Toggle Mailbox"))
476                                 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "NumberActions", "EPGSelectActions"],
477                                                                                                 {
478                                                                                                 "cancel": self._exit,
479                                                                                                 "ok": self._exit,
480                                                                                                 "red": self._reset,
481                                                                                                 "green": self._toggleWlan,
482                                                                                                 "yellow": (lambda: self._toggleMailbox(-1)),
483                                                                                                 "0": (lambda: self._toggleMailbox(0)),
484                                                                                                 "1": (lambda: self._toggleMailbox(1)),
485                                                                                                 "2": (lambda: self._toggleMailbox(2)),
486                                                                                                 "3": (lambda: self._toggleMailbox(3)),
487                                                                                                 "4": (lambda: self._toggleMailbox(4)),
488                                                                                                 "info": self._getInfo,
489                                                                                                 }, -2)
490                                 # TRANSLATORS: keep it short, this is a help text
491                                 self.helpList.append((self["menuActions"], "ColorActions", [("yellow", _("Toggle all mailboxes"))]))
492                                 # TRANSLATORS: keep it short, this is a help text
493                                 self.helpList.append((self["menuActions"], "NumberActions", [("0", _("Toggle 1. mailbox"))]))
494                                 # TRANSLATORS: keep it short, this is a help text
495                                 self.helpList.append((self["menuActions"], "NumberActions", [("1", _("Toggle 2. mailbox"))]))
496                                 # TRANSLATORS: keep it short, this is a help text
497                                 self.helpList.append((self["menuActions"], "NumberActions", [("2", _("Toggle 3. mailbox"))]))
498                                 # TRANSLATORS: keep it short, this is a help text
499                                 self.helpList.append((self["menuActions"], "NumberActions", [("3", _("Toggle 4. mailbox"))]))
500                                 # TRANSLATORS: keep it short, this is a help text
501                                 self.helpList.append((self["menuActions"], "NumberActions", [("4", _("Toggle 5. mailbox"))]))
502                                 self["FBFMailbox"] = Label(_('Mailbox'))
503                                 self["mailbox_inactive"] = Pixmap()
504                                 self["mailbox_active"] = Pixmap()
505                                 self["mailbox_active"].hide()
506                         else:
507                                 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "EPGSelectActions"],
508                                                                                                 {
509                                                                                                 "cancel": self._exit,
510                                                                                                 "ok": self._exit,
511                                                                                                 "green": self._toggleWlan,
512                                                                                                 "red": self._reset,
513                                                                                                 "info": self._getInfo,
514                                                                                                 }, -2)
515         
516                         # TRANSLATORS: keep it short, this is a help text
517                         self.helpList.append((self["menuActions"], "OkCancelActions", [("cancel", _("Quit"))]))
518                         # TRANSLATORS: keep it short, this is a help text
519                         self.helpList.append((self["menuActions"], "OkCancelActions", [("ok", _("Quit"))]))
520                         # TRANSLATORS: keep it short, this is a help text
521                         self.helpList.append((self["menuActions"], "ColorActions", [("green", _("Toggle WLAN"))]))
522                         # TRANSLATORS: keep it short, this is a help text
523                         self.helpList.append((self["menuActions"], "ColorActions", [("red", _("Reset"))]))
524                         # TRANSLATORS: keep it short, this is a help text
525                         self.helpList.append((self["menuActions"], "EPGSelectActions", [("info", _("Refresh status"))]))
526         
527                         self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
528         
529                         self["FBFInternet"] = Label('Internet')
530                         self["internet_inactive"] = Pixmap()
531                         self["internet_active"] = Pixmap()
532                         self["internet_active"].hide()
533         
534                         self["FBFDsl"] = Label('DSL')
535                         self["dsl_inactive"] = Pixmap()
536                         self["dsl_inactive"].hide()
537                         self["dsl_active"] = Pixmap()
538                         self["dsl_active"].hide()
539         
540                         self["FBFWlan"] = Label('WLAN ')
541                         self["wlan_inactive"] = Pixmap()
542                         self["wlan_inactive"].hide()
543                         self["wlan_active"] = Pixmap()
544                         self["wlan_active"].hide()
545                         self._wlanActive = False
546         
547                         if fritzbox.information[FBF_dectActive] is not None: 
548                                 self["FBFDect"] = Label('DECT')
549                                 self["dect_inactive"] = Pixmap()
550                                 self["dect_active"] = Pixmap()
551                                 self["dect_active"].hide()
552         
553                         if fritzbox.information[FBF_faxActive] is not None: 
554                                 self["FBFFax"] = Label('Fax')
555                                 self["fax_inactive"] = Pixmap()
556                                 self["fax_active"] = Pixmap()
557                                 self["fax_active"].hide()
558         
559                         if fritzbox.information[FBF_rufumlActive] is not None: 
560                                 self["FBFRufuml"] = Label(_('Call redirection'))
561                                 self["rufuml_inactive"] = Pixmap()
562                                 self["rufuml_active"] = Pixmap()
563                                 self["rufuml_active"].hide()
564                 else: # not (config.plugins.FritzCall.fwVersion.value == "old" or config.plugins.FritzCall.fwVersion.value == "05.27")
565                         fontSize = scaleV(24, 21) # indeed this is font size +2
566         
567                         noButtons = 2
568                         width = max(DESKTOP_WIDTH - scaleH(500, 250), noButtons*140+(noButtons+1)*10)
569                         # boxInfo 2 lines, gap, internet 2 lines, gap, dsl/wlan/dect/fax/rufuml/gast each 1 line, gap
570                         height = 5 + 2*fontSize + 10 + 2*fontSize + 10 + 6*fontSize + 10 + 40 + 5
571                         buttonsGap = (width-noButtons*140)/(noButtons+1)
572                         buttonsVPos = height-40-5
573         
574                         self.skin = """
575                                 <screen name="FritzMenuNew" position="center,center" size="%d,%d" title="FRITZ!Box Fon Status" >
576                                         <widget name="FBFInfo" position="%d,%d" size="%d,%d" font="Regular;%d" />
577                                         <widget name="FBFInternet" position="%d,%d" size="%d,%d" font="Regular;%d" />
578                                         <widget name="internet_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
579                                         <widget name="internet_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
580                                         <widget name="FBFDsl" position="%d,%d" size="%d,%d" font="Regular;%d" />
581                                         <widget name="dsl_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
582                                         <widget name="dsl_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
583                                         <widget name="FBFWlan" position="%d,%d" size="%d,%d" font="Regular;%d" />
584                                         <widget name="wlan_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
585                                         <widget name="wlan_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
586                                         <widget name="FBFDect" position="%d,%d" size="%d,%d" font="Regular;%d" />
587                                         <widget name="dect_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
588                                         <widget name="dect_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
589                                         <widget name="FBFFax" position="%d,%d" size="%d,%d" font="Regular;%d" />
590                                         <widget name="fax_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
591                                         <widget name="fax_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
592                                         <widget name="FBFRufuml" position="%d,%d" size="%d,%d" font="Regular;%d" />
593                                         <widget name="rufuml_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
594                                         <widget name="rufuml_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
595                                         <widget name="FBFGast" position="%d,%d" size="%d,%d" font="Regular;%d" />
596                                         <widget name="gast_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
597                                         <widget name="gast_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
598                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
599                                         <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
600                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
601                                         <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;16" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
602                                 </screen>""" % (
603                                                         width, height, # size
604                                                         40, 5, # position information
605                                                         width-2*40, 2*fontSize, # size information
606                                                         fontSize-2,
607                                                         40, 5+2*fontSize+10, # position internet
608                                                         width-40, 2*fontSize, # size internet
609                                                         fontSize-2,
610                                                         "skin_default/buttons/button_green_off.png",
611                                                         20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
612                                                         "skin_default/buttons/button_green.png",
613                                                         20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
614                                                         40, 5+2*fontSize+10+2*fontSize+10, # position dsl
615                                                         width-40-20, fontSize, # size dsl
616                                                         fontSize-2,
617                                                         "skin_default/buttons/button_green_off.png",
618                                                         20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
619                                                         "skin_default/buttons/button_green.png",
620                                                         20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
621                                                         40, 5+2*fontSize+10+3*fontSize+10, # position wlan
622                                                         width-40-20, fontSize, # size wlan
623                                                         fontSize-2,
624                                                         "skin_default/buttons/button_green_off.png",
625                                                         20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
626                                                         "skin_default/buttons/button_green.png",
627                                                         20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
628                                                         40, 5+2*fontSize+10+4*fontSize+10, # position dect
629                                                         width-40-20, fontSize, # size dect
630                                                         fontSize-2,
631                                                         "skin_default/buttons/button_green_off.png",
632                                                         20, 5+2*fontSize+10+4*fontSize+10+(fontSize-16)/2, # position button dect
633                                                         "skin_default/buttons/button_green.png",
634                                                         20, 5+2*fontSize+10+4*fontSize+10+(fontSize-16)/2, # position button dect
635                                                         40, 5+2*fontSize+10+5*fontSize+10, # position fax
636                                                         width-40-20, fontSize, # size fax
637                                                         fontSize-2,
638                                                         "skin_default/buttons/button_green_off.png",
639                                                         20, 5+2*fontSize+10+5*fontSize+10+(fontSize-16)/2, # position button fax
640                                                         "skin_default/buttons/button_green.png",
641                                                         20, 5+2*fontSize+10+5*fontSize+10+(fontSize-16)/2, # position button fax
642                                                         40, 5+2*fontSize+10+6*fontSize+10, # position rufuml
643                                                         width-40-20, fontSize, # size rufuml
644                                                         fontSize-2,
645                                                         "skin_default/buttons/button_green_off.png",
646                                                         20, 5+2*fontSize+10+6*fontSize+10+(fontSize-16)/2, # position button rufuml
647                                                         "skin_default/buttons/button_green.png",
648                                                         20, 5+2*fontSize+10+6*fontSize+10+(fontSize-16)/2, # position button rufuml
649                                                         40, 5+2*fontSize+10+7*fontSize+10, # position gast
650                                                         width-40-20, fontSize, # size gast
651                                                         fontSize-2,
652                                                         "skin_default/buttons/button_green_off.png",
653                                                         20, 5+2*fontSize+10+7*fontSize+10+(fontSize-16)/2, # position button gast
654                                                         "skin_default/buttons/button_green.png",
655                                                         20, 5+2*fontSize+10+7*fontSize+10+(fontSize-16)/2, # position button gast
656                                                         buttonsGap, buttonsVPos, "skin_default/buttons/green.png", buttonsGap, buttonsVPos,
657                                                         2*buttonsGap+140, buttonsVPos, "skin_default/buttons/yellow.png", 2*buttonsGap+140, buttonsVPos,
658                                                         )
659         
660                         Screen.__init__(self, session)
661                         HelpableScreen.__init__(self)
662                         # TRANSLATORS: keep it short, this is a button
663                         self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "EPGSelectActions"],
664                                                                                         {
665                                                                                         "cancel": self._exit,
666                                                                                         "ok": self._exit,
667                                                                                         "green": self._toggleWlan,
668                                                                                         "yellow": self._toggleGast,
669                                                                                         "red": self._reset, # no button, does not work
670                                                                                         "info": self._getInfo,
671                                                                                         }, -2)
672         
673                         # TRANSLATORS: keep it short, this is a help text
674                         self.helpList.append((self["menuActions"], "OkCancelActions", [("cancel", _("Quit"))]))
675                         # TRANSLATORS: keep it short, this is a help text
676                         self.helpList.append((self["menuActions"], "OkCancelActions", [("ok", _("Quit"))]))
677                         # TRANSLATORS: keep it short, this is a help text
678                         self.helpList.append((self["menuActions"], "ColorActions", [("green", _("Toggle WLAN"))]))
679                         # TRANSLATORS: keep it short, this is a help text
680                         self.helpList.append((self["menuActions"], "ColorActions", [("yellow", _("Toggle WLAN guest access"))]))
681                         # TRANSLATORS: keep it short, this is a help text
682                         self.helpList.append((self["menuActions"], "ColorActions", [("red", _("Reset"))]))
683                         # TRANSLATORS: keep it short, this is a help text
684                         self.helpList.append((self["menuActions"], "EPGSelectActions", [("info", _("Refresh status"))]))
685         
686                         # TRANSLATORS: keep it short, this is a button
687                         self["key_red"] = Button(_("Reset"))
688                         # TRANSLATORS: keep it short, this is a button
689                         self["key_green"] = Button(_("Toggle WLAN"))
690                         # TRANSLATORS: keep it short, this is a button
691                         self["key_yellow"] = Button(_("Activate WLAN guest access"))
692
693                         self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
694         
695                         self["FBFInternet"] = Label('Internet')
696                         self["internet_inactive"] = Pixmap()
697                         self["internet_inactive"].hide()
698                         self["internet_active"] = Pixmap()
699                         self["internet_active"].hide()
700         
701                         self["FBFDsl"] = Label('DSL')
702                         self["dsl_inactive"] = Pixmap()
703                         self["dsl_inactive"].hide()
704                         self["dsl_active"] = Pixmap()
705                         self["dsl_active"].hide()
706         
707                         self["FBFWlan"] = Label('WLAN ')
708                         self["wlan_inactive"] = Pixmap()
709                         self["wlan_inactive"].hide()
710                         self["wlan_active"] = Pixmap()
711                         self["wlan_active"].hide()
712                         self._wlanActive = False
713         
714                         self["FBFDect"] = Label('DECT')
715                         self["dect_inactive"] = Pixmap()
716                         self["dect_inactive"].hide()
717                         self["dect_active"] = Pixmap()
718                         self["dect_active"].hide()
719         
720                         self["FBFFax"] = Label('Fax')
721                         self["fax_inactive"] = Pixmap()
722                         self["fax_inactive"].hide()
723                         self["fax_active"] = Pixmap()
724                         self["fax_active"].hide()
725         
726                         self["FBFRufuml"] = Label(_('Call redirection'))
727                         self["rufuml_inactive"] = Pixmap()
728                         self["rufuml_inactive"].hide()
729                         self["rufuml_active"] = Pixmap()
730                         self["rufuml_active"].hide()
731                         
732                         self["FBFGast"] = Label(_('Guest access'))
733                         self["gast_inactive"] = Pixmap()
734                         self["gast_inactive"].hide()
735                         self["gast_active"] = Pixmap()
736                         self["gast_active"].hide()
737                         self._guestActive = ""
738                         
739                 self._getInfo()
740                 self.onLayoutFinish.append(self.setWindowTitle)
741
742         def setWindowTitle(self):
743                 # TRANSLATORS: this is a window title.
744                 self.setTitle(_("FRITZ!Box Fon Status"))
745
746         def _getInfo(self):
747                 if fritzbox:
748                         fritzbox.getInfo(self._fillMenu)
749                         self._fillMenu(fritzbox.information, True)
750
751         def _fillMenu(self, status, refreshing=False):
752                 (boxInfo, upTime, ipAddress, wlanState, dslState, tamActive, dectActive, faxActive, rufumlActive, guestAccess) = status
753                 if wlanState:
754                         self._wlanActive = (wlanState[0] == '1')
755                 self._guestActive = guestAccess
756                 self._mailboxActive = False
757                 try:
758                         if not self.has_key("FBFInfo"): # screen is closed already
759                                 return
760
761                         if refreshing:
762                                 self["FBFInfo"].setText(_("Refreshing..."))
763                         else:
764                                 if boxInfo:
765                                         self["FBFInfo"].setText(boxInfo.replace(', ', '\n'))
766                                 else:
767                                         self["FBFInfo"].setText('BoxInfo ' + _('Status not available'))
768
769                         if ipAddress:
770                                 if upTime:
771                                         self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress + '\n' + _('Connected since') + ' ' + upTime)
772                                 else:
773                                         self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress)
774                                 self["internet_inactive"].hide()
775                                 self["internet_active"].show()
776                         else:
777                                 self["internet_active"].hide()
778                                 self["internet_inactive"].show()
779
780                         if dslState:
781                                 if dslState[0] == '5':
782                                         self["dsl_inactive"].hide()
783                                         self["dsl_active"].show()
784                                         if dslState[2]:
785                                                 message = dslState[2]
786                                         else:
787                                                 message = "DSL"
788                                         if dslState[1]:
789                                                 message = message + ' ' + dslState[1]
790                                         self["FBFDsl"].setText(message)
791                                 else:
792                                         self["dsl_active"].hide()
793                                         self["dsl_inactive"].show()
794                         else:
795                                 self["FBFDsl"].setText('DSL ' + _('Status not available'))
796                                 self["dsl_active"].hide()
797                                 self["dsl_inactive"].hide()
798
799                         if wlanState:
800                                 if wlanState[0 ] == '1':
801                                         self["wlan_inactive"].hide()
802                                         self["wlan_active"].show()
803                                         message = 'WLAN'
804                                         if wlanState[1] == '0':
805                                                 message += ' ' + _('not encrypted')
806                                         elif wlanState[1] == '1':
807                                                 message += ' ' + _('encrypted')
808                                         if wlanState[2]:
809                                                 if wlanState[2] == '0':
810                                                         message = message + ', ' + _('no device active')
811                                                 elif wlanState[2] == '1' or wlanState[2] == 'ein':
812                                                         message = message + ', ' + _('one device active')
813                                                 else:
814                                                         message = message + ', ' + wlanState[2] + ' ' + _('devices active')
815                                         if len(wlanState) == 4:
816                                                 message = message + ", " + wlanState[3]
817                                         self["FBFWlan"].setText(message)
818                                 else:
819                                         self["wlan_active"].hide()
820                                         self["wlan_inactive"].show()
821                                         self["FBFWlan"].setText('WLAN')
822                         else:
823                                 self["FBFWlan"].setText('WLAN ' + _('Status not available'))
824                                 self["wlan_active"].hide()
825                                 self["wlan_inactive"].hide()
826
827                         if fritzbox.information[FBF_tamActive]:
828                                 if  not tamActive or tamActive[0] == 0:
829                                         self._mailboxActive = False
830                                         self["mailbox_active"].hide()
831                                         self["mailbox_inactive"].show()
832                                         self["FBFMailbox"].setText(_('No mailbox active'))
833                                 else:
834                                         self._mailboxActive = True
835                                         message = ''
836                                         for i in range(min(len(tamActive)-1, 5)):
837                                                 if tamActive[i+1]:
838                                                         message = message + str(i) + ','
839                                         if message:
840                                                 message = '(' + message[:-1] + ')'
841                                         self["mailbox_inactive"].hide()
842                                         self["mailbox_active"].show()
843                                         if tamActive[0] == 1:
844                                                 self["FBFMailbox"].setText(_('One mailbox active') + ' ' + message)
845                                         else:
846                                                 self["FBFMailbox"].setText(str(tamActive[0]) + ' ' + _('mailboxes active') + ' ' + message)
847         
848                         if dectActive and self.has_key("dect_inactive"):
849                                 self["dect_inactive"].hide()
850                                 self["dect_active"].show()
851                                 if dectActive == 0:
852                                         self["FBFDect"].setText(_('No DECT phone registered'))
853                                 else:
854                                         if dectActive == "ein" or dectActive == "1" or dectActive == 1:
855                                                 self["FBFDect"].setText(_('One DECT phone registered'))
856                                         else:
857                                                 self["FBFDect"].setText(str(dectActive) + ' ' + _('DECT phones registered'))
858                         else:
859                                 self["dect_active"].hide()
860                                 self["dect_inactive"].show()
861                                 self["FBFDect"].setText(_('DECT inactive'))
862
863                         if faxActive:
864                                 self["fax_inactive"].hide()
865                                 self["fax_active"].show()
866                                 self["FBFFax"].setText(_('Software fax active'))
867                         else:
868                                 self["fax_active"].hide()
869                                 self["fax_inactive"].show()
870                                 self["FBFFax"].setText(_('Software fax inactive'))
871
872                         if rufumlActive:
873                                 self["rufuml_inactive"].hide()
874                                 self["rufuml_active"].show()
875                                 if rufumlActive == -1: # means no number available
876                                         self["FBFRufuml"].setText(_('Call redirection active'))
877                                 elif rufumlActive == 1:
878                                         self["FBFRufuml"].setText(_('One call redirection active'))
879                                 else:
880                                         self["FBFRufuml"].setText(str(rufumlActive) + ' ' + _('call redirections active'))
881                         else:
882                                 self["rufuml_active"].hide()
883                                 self["rufuml_inactive"].show()
884                                 self["FBFRufuml"].setText(_('No call redirection active'))
885
886                         if guestAccess:
887                                 self["gast_inactive"].hide()
888                                 self["gast_active"].show()
889                                 self["FBFGast"].setText(_('Guest access on ') + guestAccess)
890                         else:
891                                 self["gast_active"].hide()
892                                 self["gast_inactive"].show()
893                                 self["FBFGast"].setText(_('Guest access not active'))
894
895                         if guestAccess.find('WLAN') != -1:
896                                 # TRANSLATORS: keep it short, this is a button
897                                 self["key_yellow"].setText(_("Deactivate WLAN guest access"))
898                         else:
899                                 # TRANSLATORS: keep it short, this is a button
900                                 self["key_yellow"].setText(_("Activate WLAN guest access"))
901
902
903                 except KeyError:
904                         error("[FritzCallFBF] _fillMenu: " + traceback.format_exc())
905
906         def _toggleWlan(self):
907                 self["FBFInfo"].setText(_("Setting...") + " WLAN")
908                 if self._wlanActive:
909                         info("[FritzMenu] toggleWlan off")
910                         fritzbox.changeWLAN('0', self._getInfo)
911                 else:
912                         info("[FritzMenu] toggleWlan on")
913                         fritzbox.changeWLAN('1', self._getInfo)
914
915         def _toggleMailbox(self, which):
916                 debug("[FritzMenu]")
917                 if fritzbox.information[FBF_tamActive]:
918                         info("[FritzMenu] toggleMailbox off")
919                         fritzbox.changeMailbox(which, self._getInfo)
920
921         def _toggleGast(self):
922                 self["FBFInfo"].setText(_("Setting...") + ' ' + _("Guest access"))
923                 if fritzbox.information[FBF_wlanState][0] != '1':
924                         # self["FBFInfo"].setText(_("WLAN not active"))
925                         self._toggleWlan()
926                         return
927                 fritzbox.changeGuestAccess(self._guestActive, self._getInfo)
928
929         def _reset(self):
930                 fritzbox.reset()
931                 self._exit()
932
933         def _exit(self):
934                 self.close()
935
936
937 class FritzDisplayCalls(Screen, HelpableScreen):
938
939         def __init__(self, session, text=""): #@UnusedVariable # pylint: disable=W0613
940                 self.width = DESKTOP_WIDTH * scaleH(75, 85)/100
941                 self.height = DESKTOP_HEIGHT * 0.75
942                 dateFieldWidth = scaleH(180, 105)
943                 dirFieldWidth = 16
944                 lengthFieldWidth = scaleH(55, 45)
945                 scrollbarWidth = scaleH(35, 35)
946                 entriesWidth = self.width -scaleH(40, 5) -5
947                 hereFieldWidth = entriesWidth -dirFieldWidth -5 -dateFieldWidth -5 -lengthFieldWidth -scrollbarWidth
948                 fieldWidth = entriesWidth -dirFieldWidth -5 -5 -scrollbarWidth
949                 fontSize = scaleV(22, 20)
950                 itemHeight = 2*fontSize+5
951                 entriesHeight = self.height -scaleV(15, 10) -5 -fontSize -5 -5 -5 -40 -5
952                 buttonGap = (self.width -4*140)/5
953                 buttonV = self.height -40
954                 debug("[FritzDisplayCalls] width: " + str(self.width))
955                 self.skin = """
956                         <screen name="FritzDisplayCalls" position="center,center" size="%d,%d" title="Phone calls" >
957                                 <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
958                                 <widget name="statusbar" position="%d,%d" size="%d,%d" font="Regular;%d" backgroundColor="#aaaaaa" transparent="1" />
959                                 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
960                                 <widget source="entries" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" transparent="1">
961                                         <convert type="TemplatedMultiContent">
962                                                 {"template": [
963                                                                 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 0 is the number, index 1 is date
964                                                                 MultiContentEntryPixmapAlphaTest(pos = (%d,%d), size = (%d,%d), png = 2), # index 1 i direction pixmap
965                                                                 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 2 is remote name/number
966                                                                 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 3 is length of call
967                                                                 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text = 5), # index 4 is my number/name for number
968                                                         ],
969                                                 "fonts": [gFont("Regular", %d), gFont("Regular", %d)],
970                                                 "itemHeight": %d
971                                                 }
972                                         </convert>
973                                 </widget>
974                                 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
975                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
976                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
977                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
978                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
979                                 <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
980                                 <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
981                                 <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
982                                 <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
983                         </screen>""" % (
984                                                 # scaleH(90, 75), scaleV(100, 78), # position 
985                                                 self.width, self.height, # size
986                                                 self.width, # eLabel width
987                                                 scaleH(40, 5), scaleV(10, 5), # statusbar position
988                                                 self.width, fontSize+5, # statusbar size
989                                                 scaleV(21, 21), # statusbar font size
990                                                 scaleV(10, 5)+5+fontSize+5, # eLabel position vertical
991                                                 self.width, # eLabel width
992                                                 scaleH(40, 5), scaleV(10, 5)+5+fontSize+5+5, # entries position
993                                                 entriesWidth, entriesHeight, # entries size
994                                                 5+dirFieldWidth+5, fontSize+5, dateFieldWidth, fontSize, # date pos/size
995                                                 5, (itemHeight-dirFieldWidth)/2, dirFieldWidth, dirFieldWidth, # dir pos/size
996                                                 5+dirFieldWidth+5, 5, fieldWidth, fontSize, # caller pos/size
997                                                 2+dirFieldWidth+2+dateFieldWidth+5, fontSize+5, lengthFieldWidth, fontSize, # length pos/size
998                                                 2+dirFieldWidth+2+dateFieldWidth+5+lengthFieldWidth+5, fontSize+5, hereFieldWidth, fontSize, # my number pos/size
999                                                 fontSize-4, fontSize, # fontsize
1000                                                 itemHeight, # itemHeight
1001                                                 buttonV-5, # eLabel position vertical
1002                                                 self.width, # eLabel width
1003                                                 buttonGap, buttonV, "skin_default/buttons/red.png", # widget red
1004                                                 2*buttonGap+140, buttonV, "skin_default/buttons/green.png", # widget green
1005                                                 3*buttonGap+2*140, buttonV, "skin_default/buttons/yellow.png", # widget yellow
1006                                                 4*buttonGap+3*140, buttonV, "skin_default/buttons/blue.png", # widget blue
1007                                                 buttonGap, buttonV, scaleV(22, 21), # widget red
1008                                                 2*buttonGap+140, buttonV, scaleV(22, 21), # widget green
1009                                                 3*buttonGap+2*140, buttonV, scaleV(22, 21), # widget yellow
1010                                                 4*buttonGap+3*140, buttonV, scaleV(22, 21), # widget blue
1011                                                                                                                 )
1012                 # debug("[FritzDisplayCalls] skin: " + self.skin)
1013                 Screen.__init__(self, session)
1014                 HelpableScreen.__init__(self)
1015
1016                 # TRANSLATORS: keep it short, this is a button
1017                 self["key_yellow"] = Button(_("All"))
1018                 # TRANSLATORS: keep it short, this is a button
1019                 self["key_red"] = Button(_("Missed"))
1020                 # TRANSLATORS: keep it short, this is a button
1021                 self["key_blue"] = Button(_("Incoming"))
1022                 # TRANSLATORS: keep it short, this is a button
1023                 self["key_green"] = Button(_("Outgoing"))
1024
1025                 self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1026                 {
1027                         "yellow": (lambda: self.display(FBF_ALL_CALLS)),
1028                         "red": (lambda: self.display(FBF_MISSED_CALLS)),
1029                         "blue": (lambda: self.display(FBF_IN_CALLS)),
1030                         "green": (lambda: self.display(FBF_OUT_CALLS)),
1031                         "cancel": self.ok,
1032                         "ok": self.showEntry, }, - 2)
1033
1034                 # TRANSLATORS: keep it short, this is a help text
1035                 self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("Show details of entry"))]))
1036                 # TRANSLATORS: keep it short, this is a help text
1037                 self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("Quit"))]))
1038                 # TRANSLATORS: keep it short, this is a help text
1039                 self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("Display all calls"))]))
1040                 # TRANSLATORS: keep it short, this is a help text
1041                 self.helpList.append((self["setupActions"], "ColorActions", [("red", _("Display missed calls"))]))
1042                 # TRANSLATORS: keep it short, this is a help text
1043                 self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("Display incoming calls"))]))
1044                 # TRANSLATORS: keep it short, this is a help text
1045                 self.helpList.append((self["setupActions"], "ColorActions", [("green", _("Display outgoing calls"))]))
1046
1047                 self["statusbar"] = Label(_("Getting calls from FRITZ!Box..."))
1048                 self.list = []
1049                 self["entries"] = List(self.list)
1050                 #=======================================================================
1051                 # fontSize = scaleV(22, 18)
1052                 # fontHeight = scaleV(24, 20)
1053                 # self["entries"].l.setFont(0, gFont("Regular", fontSize))
1054                 # self["entries"].l.setItemHeight(fontHeight)
1055                 #=======================================================================
1056                 debug("[FritzDisplayCalls] '''%s'''" % config.plugins.FritzCall.fbfCalls.value)
1057                 self.display(config.plugins.FritzCall.fbfCalls.value)
1058                 self.onLayoutFinish.append(self.setWindowTitle)
1059
1060         def setWindowTitle(self):
1061                 # TRANSLATORS: this is a window title.
1062                 self.setTitle(_("Phone calls"))
1063
1064         def ok(self):
1065                 self.close()
1066
1067         def display(self, which=None):
1068                 debug("[FritzDisplayCalls]")
1069                 if which:
1070                         config.plugins.FritzCall.fbfCalls.value = which
1071                         config.plugins.FritzCall.fbfCalls.save()
1072                 else:
1073                         which = config.plugins.FritzCall.fbfCalls.value
1074                 fritzbox.getCalls(self, lambda x: self.gotCalls(x, which), which)
1075
1076         def gotCalls(self, listOfCalls, which):
1077                 debug("[FritzDisplayCalls]")
1078                 self.updateStatus(fbfCallsChoices[which] + " (" + str(len(listOfCalls)) + ")")
1079
1080                 directout = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callout.png"))
1081                 directin = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callin.png"))
1082                 directfailed = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callinfailed.png"))
1083                 def pixDir(direct):
1084                         if direct == FBF_OUT_CALLS:
1085                                 direct = directout
1086                         elif direct == FBF_IN_CALLS:
1087                                 direct = directin
1088                         else:
1089                                 direct = directfailed
1090                         return direct
1091
1092                 # debug("[FritzDisplayCalls] %s" %repr(listOfCalls))
1093                 self.list = [(number, date[:6] + ' ' + date[9:14], pixDir(direct), remote, length, here) for (number, date, direct, remote, length, here) in listOfCalls]
1094                 self["entries"].setList(self.list)
1095                 #=======================================================================
1096                 # if len(self.list) > 1:
1097                 #       self["entries"].setIndex(1)
1098                 #=======================================================================
1099
1100         def updateStatus(self, text):
1101                 if self.has_key("statusbar"):
1102                         self["statusbar"].setText(_("Getting calls from FRITZ!Box...") + ' ' + text)
1103
1104         def showEntry(self):
1105                 debug("[FritzDisplayCalls]")
1106                 cur = self["entries"].getCurrent()
1107                 if cur:
1108                         if cur[0]:
1109                                 # debug("[FritzDisplayCalls] %s" % (cur[0]))
1110                                 number = cur[0]
1111                                 fullname = phonebook.search(cur[0])
1112                                 if fullname:
1113                                         # we have a name for this number
1114                                         name = fullname
1115                                         self.session.open(FritzOfferAction, self, number, name)
1116                                 elif cur[3]:
1117                                         name = cur[3]
1118                                         self.session.open(FritzOfferAction, self, number, name)
1119                                 else:
1120                                         # we don't
1121                                         fullname = resolveNumberWithAvon(number, config.plugins.FritzCall.country.value)
1122                                         if fullname:
1123                                                 name = fullname
1124                                                 self.session.open(FritzOfferAction, self, number, name)
1125                                         else:
1126                                                 self.session.open(FritzOfferAction, self, number)
1127                         else:
1128                                 # we do not even have a number...
1129                                 self.session.open(MessageBox,
1130                                                   _("UNKNOWN"),
1131                                                   type=MessageBox.TYPE_INFO)
1132
1133
1134 class FritzOfferAction(Screen):
1135
1136         def __init__(self, session, parent, number, name=""):
1137                 # the layout will completely be recalculated in finishLayout
1138                 self.skin = """
1139                         <screen name="FritzOfferAction" title="Do what?" >
1140                                 <widget name="text" size="%d,%d" font="Regular;%d" />
1141                                 <widget name="FacePixmap" size="%d,%d" alphatest="on" />
1142                                 <widget name="key_red_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1143                                 <widget name="key_green_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1144                                 <widget name="key_yellow_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1145                                 <widget name="key_red" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1146                                 <widget name="key_green" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1147                                 <widget name="key_yellow" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1148                         </screen>""" % (
1149                                                         DESKTOP_WIDTH, DESKTOP_HEIGHT, # set maximum size
1150                                                         scaleV(25,22), # text
1151                                                         DESKTOP_WIDTH, DESKTOP_HEIGHT, # set maximum size
1152                                                         "skin_default/buttons/red.png",
1153                                                         "skin_default/buttons/green.png",
1154                                                         "skin_default/buttons/yellow.png",
1155                                                         ) 
1156                 debug("[FritzOfferAction] %s, %s" %(__(number), __(name)))
1157                 Screen.__init__(self, session)
1158         
1159                 # TRANSLATORS: keep it short, this is a button
1160                 self["key_red"] = Button(_("Lookup"))
1161                 # TRANSLATORS: keep it short, this is a button
1162                 self["key_green"] = Button(_("Call"))
1163                 # TRANSLATORS: keep it short, this is a button
1164                 self["key_yellow"] = Button(_("Save"))
1165                 # TRANSLATORS: keep it short, this is a button
1166                 # self["key_blue"] = Button(_("Search"))
1167
1168                 self["FritzOfferActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1169                 {
1170                         "red": self._lookup,
1171                         "green": self._call,
1172                         "yellow": self._add,
1173                         "cancel": self._exit,
1174                         "ok": self._exit, }, - 2)
1175
1176                 self._session = session
1177                 if config.plugins.FritzCall.internal.value and len(number) > 3 and number[0] == "0":
1178                         number = number[1:]
1179                 self._number = number
1180                 self._name = name.replace("\n", ", ")
1181                 self["text"] = Label(number + "\n\n" + name.replace(", ", "\n"))
1182                 self._parent = parent
1183                 self._lookupState = 0
1184                 self["key_red_p"] = Pixmap()
1185                 self["key_green_p"] = Pixmap()
1186                 self["key_yellow_p"] = Pixmap()
1187                 self["FacePixmap"] = Pixmap()
1188                 self.onLayoutFinish.append(self._finishLayout)
1189                 self.onLayoutFinish.append(self.setWindowTitle)
1190
1191         def setWindowTitle(self):
1192                 # TRANSLATORS: this is a window title.
1193                 self.setTitle(_("Do what?"))
1194
1195         def _finishLayout(self):
1196                 # pylint: disable=W0142
1197                 debug("[FritzOfferAction] number: %s/%s" % (__(self._number), __(self._name)))
1198
1199                 faceFile = findFace(self._number, self._name)
1200                 picPixmap = LoadPixmap(faceFile)
1201                 if not picPixmap:       # that means most probably, that the picture is not 8 bit...
1202                         Notifications.AddNotification(MessageBox, _("Found picture\n\n%s\n\nBut did not load. Probably not PNG, 8-bit") %faceFile, type = MessageBox.TYPE_ERROR)
1203                         picPixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_error.png"))
1204                 picSize = picPixmap.size()
1205
1206                 noButtons = 3
1207                 # recalculate window size
1208                 textSize = self["text"].getSize()
1209                 textSize = (textSize[0]+20, textSize[1]+20) # don't know, why, but size is too small
1210                 debug("[FritzOfferAction] textsize: %s/%s" % textSize)
1211                 textSize = eSize(*textSize)
1212                 width = max(scaleH(620, 545), noButtons*145, picSize.width() + textSize.width() + 30)
1213                 height = max(picSize.height()+5, textSize.height()+5, scaleV(-1, 136)) + 5 + 40 + 5
1214                 buttonsGap = (width-noButtons*140)/(noButtons+1)
1215                 buttonsVPos = height-40-5
1216                 wSize = (width, height)
1217                 wSize = eSize(*wSize)
1218
1219                 # center the smaller vertically
1220                 hGap = (width-picSize.width()-textSize.width())/3
1221                 picPos = (hGap, (height-50-picSize.height())/2+5)
1222                 textPos = (hGap+picSize.width()+hGap, (height-50-textSize.height())/2+5)
1223
1224                 # resize screen
1225                 self.instance.resize(wSize)
1226                 # resize text
1227                 self["text"].instance.resize(textSize)
1228                 # resize pixmap
1229                 self["FacePixmap"].instance.resize(picSize)
1230                 self["FacePixmap"].instance.setPixmap(picPixmap)
1231                 # move buttons
1232                 buttonPos = (buttonsGap, buttonsVPos)
1233                 self["key_red_p"].instance.move(ePoint(*buttonPos))
1234                 self["key_red"].instance.move(ePoint(*buttonPos))
1235                 buttonPos = (buttonsGap+140+buttonsGap, buttonsVPos)
1236                 self["key_green_p"].instance.move(ePoint(*buttonPos))
1237                 self["key_green"].instance.move(ePoint(*buttonPos))
1238                 buttonPos = (buttonsGap+140+buttonsGap+140+buttonsGap, buttonsVPos)
1239                 self["key_yellow_p"].instance.move(ePoint(*buttonPos))
1240                 self["key_yellow"].instance.move(ePoint(*buttonPos))
1241                 # move text
1242                 self["text"].instance.move(ePoint(*textPos))
1243                 # move pixmap
1244                 self["FacePixmap"].instance.move(ePoint(*picPos))
1245                 # center window
1246                 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
1247
1248         def _setTextAndResize(self, message):
1249                 # pylint: disable=W0142
1250                 self["text"].instance.resize(eSize(*(DESKTOP_WIDTH, DESKTOP_HEIGHT)))
1251                 self["text"].setText(self._number + "\n\n" + message)
1252                 self._finishLayout()
1253
1254         def _lookup(self):
1255                 phonebookLocation = config.plugins.FritzCall.phonebookLocation.value
1256                 if self._lookupState == 0:
1257                         self._lookupState = 1
1258                         self._setTextAndResize(_("Reverse searching..."))
1259                         ReverseLookupAndNotifier(self._number, self._lookedUp, "UTF-8", config.plugins.FritzCall.country.value)
1260                         return
1261                 if self._lookupState == 1 and os.path.exists(os.path.join(phonebookLocation, "PhoneBook.csv")):
1262                         self._setTextAndResize(_("Searching in Outlook export..."))
1263                         self._lookupState = 2
1264                         self._lookedUp(self._number, FritzOutlookCSV.findNumber(self._number, os.path.join(phonebookLocation, "PhoneBook.csv"))) #@UndefinedVariable
1265                         return
1266                 else:
1267                         self._lookupState = 2
1268                 if self._lookupState == 2 and os.path.exists(os.path.join(phonebookLocation, "PhoneBook.ldif")):
1269                         self._setTextAndResize(_("Searching in LDIF..."))
1270                         self._lookupState = 0
1271                         FritzLDIF.FindNumber(self._number, open(os.path.join(phonebookLocation, "PhoneBook.ldif")), self._lookedUp)
1272                         return
1273                 else:
1274                         self._lookupState = 0
1275                         self._lookup()
1276
1277         def _lookedUp(self, number, name):
1278                 name = handleReverseLookupResult(name)
1279                 if not name:
1280                         if self._lookupState == 1:
1281                                 name = _("No result from reverse lookup")
1282                         elif self._lookupState == 2:
1283                                 name = _("No result from Outlook export")
1284                         else:
1285                                 name = _("No result from LDIF")
1286                 self._name = name
1287                 self._number = number
1288                 info("[FritzOfferAction] " + str(name.replace(", ", "\n")))
1289                 self._setTextAndResize(str(name.replace(", ", "\n")))
1290
1291         def _call(self):
1292                 if fritzbox:
1293                         debug("[FritzOfferAction]  %s" %self._number)
1294                         self.session.open(MessageBox, _("Calling %s") %self._number, type=MessageBox.TYPE_INFO)
1295                         fritzbox.dial(self._number)
1296                 else:
1297                         error("[FritzOfferAction] no fritzbox object?!?!")
1298                         self.session.open(MessageBox, _("FRITZ!Box not available for calling"), type=MessageBox.TYPE_INFO)
1299
1300         def _add(self):
1301                 debug("[FritzOfferAction] %s, %s" %(self._number, self._name))
1302                 phonebook.FritzDisplayPhonebook(self._session).add(self._parent, self._number, self._name)
1303                 self._exit()
1304
1305         def _exit(self):
1306                 self.close()
1307
1308 OneHour = 60*60*1000
1309 # OneHour = 1000
1310 class FritzCallPhonebook:
1311         def __init__(self):
1312                 debug("[FritzCallPhonebook]")
1313                 # Beware: strings in phonebook.phonebook have to be in utf-8!
1314                 self.phonebook = {}
1315                 if config.plugins.FritzCall.reloadPhonebookTime.value > 0:
1316                         debug("[FritzCallPhonebook] start timer with " + repr(config.plugins.FritzCall.reloadPhonebookTime.value))
1317                         self.loop = eTimer()
1318                         
1319                         # newer OE versions don't have the callback
1320                         try:
1321                                 self.loop_conn = self.loop.timeout.connect(self.reload)
1322                         except AttributeError:
1323                                 self.loop.callback.append(self.reload)
1324                                 
1325                         self.loop.start(config.plugins.FritzCall.reloadPhonebookTime.value*OneHour, False)
1326                 self.reload()
1327
1328         def reload(self):
1329                 debug("[FritzCallPhonebook] " + time.ctime())
1330
1331                 # Beware: strings in phonebook.phonebook have to be in utf-8!
1332                 self.phonebook = {}
1333
1334                 if not config.plugins.FritzCall.enable.value:
1335                         return
1336
1337                 phonebookFilename = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt")
1338                 if config.plugins.FritzCall.phonebook.value and os.path.exists(phonebookFilename):
1339                         debug("[FritzCallPhonebook] read " + phonebookFilename)
1340                         phonebookTxtCorrupt = False
1341                         self.phonebook = {}
1342                         for line in open(phonebookFilename):
1343                                 try:
1344                                         # Beware: strings in phonebook.phonebook have to be in utf-8!
1345                                         line = line.decode("utf-8")
1346                                 except UnicodeDecodeError: # this is just for the case, somebody wrote latin1 chars into PhoneBook.txt
1347                                         try:
1348                                                 line = line.decode("iso-8859-1")
1349                                                 debug("[FritzCallPhonebook] Fallback to ISO-8859-1 in %s" % line)
1350                                                 phonebookTxtCorrupt = True
1351                                         except UnicodeDecodeError:
1352                                                 error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1353                                                 phonebookTxtCorrupt = True
1354                                 line = line.encode("utf-8")
1355                                 elems = line.split('#')
1356                                 if len(elems) == 2:
1357                                         try:
1358                                                 # debug("[FritzCallPhonebook] Adding '''%s''' with '''%s''' from internal phonebook!" % (__(elems[1].strip()), __(elems[0], False)))
1359                                                 self.phonebook[elems[0]] = elems[1]
1360                                         except ValueError: # how could this possibly happen?!?!
1361                                                 error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1362                                                 phonebookTxtCorrupt = True
1363                                 else:
1364                                         error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1365                                         phonebookTxtCorrupt = True
1366                                         
1367                                 #===============================================================
1368                                 # found = re.match("^(\d+)#(.*)$", line)
1369                                 # if found:
1370                                 #       try:
1371                                 #               self.phonebook[found.group(1)] = found.group(2)
1372                                 #       except ValueError: # how could this possibly happen?!?!
1373                                 #               debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1374                                 #               phonebookTxtCorrupt = True
1375                                 # else:
1376                                 #       debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1377                                 #       phonebookTxtCorrupt = True
1378                                 #===============================================================
1379
1380                         if phonebookTxtCorrupt:
1381                                 # dump phonebook to PhoneBook.txt
1382                                 debug("[FritzCallPhonebook] dump Phonebook.txt")
1383                                 try:
1384                                         os.rename(phonebookFilename, phonebookFilename + ".bck")
1385                                         fNew = open(phonebookFilename, 'w')
1386                                         # Beware: strings in phonebook.phonebook are utf-8!
1387                                         for (number, name) in self.phonebook.iteritems():
1388                                                 # Beware: strings in PhoneBook.txt have to be in utf-8!
1389                                                 fNew.write(number + "#" + name.encode("utf-8"))
1390                                         fNew.close()
1391                                 except (IOError, OSError):
1392                                         error("[FritzCallPhonebook] error renaming or writing to %s" %phonebookFilename)
1393
1394                 if fritzbox and config.plugins.FritzCall.fritzphonebook.value:
1395                         debug("[FritzCallPhonebook] config.plugins.FritzCall.fritzphonebook.value %s" %repr(config.plugins.FritzCall.fritzphonebook.value))
1396                         fritzbox.loadFritzBoxPhonebook(self)
1397
1398 #===============================================================================
1399 #               #
1400 #               # read entries from Outlook export
1401 #               #
1402 #               # not reliable with coding yet
1403 #               # 
1404 #               # import csv exported from Outlook 2007 with csv(Windows)
1405 #               csvFilename = "/tmp/PhoneBook.csv"
1406 #               if config.plugins.FritzCall.phonebook.value and os.path.exists(csvFilename):
1407 #                       try:
1408 #                               readOutlookCSV(csvFilename, self.add)
1409 #                               os.rename(csvFilename, csvFilename + ".done")
1410 #                       except ImportError:
1411 #                               debug("[FritzCallPhonebook] CSV import failed" %line)
1412 #===============================================================================
1413
1414                 
1415 #===============================================================================
1416 #               #
1417 #               # read entries from LDIF
1418 #               #
1419 #               # import ldif exported from Thunderbird 2.0.0.19
1420 #               ldifFilename = "/tmp/PhoneBook.ldif"
1421 #               if config.plugins.FritzCall.phonebook.value and os.path.exists(ldifFilename):
1422 #                       try:
1423 #                               parser = MyLDIF(open(ldifFilename), self.add)
1424 #                               parser.parse()
1425 #                               os.rename(ldifFilename, ldifFilename + ".done")
1426 #                       except ImportError:
1427 #                               debug("[FritzCallPhonebook] LDIF import failed" %line)
1428 #===============================================================================
1429
1430         def search(self, number, default=None, extended=True):
1431                 # debug("[FritzCallPhonebook] Searching for %s" %number)
1432                 name = ""
1433                 if not self.phonebook or not number:
1434                         return name
1435
1436                 if config.plugins.FritzCall.prefix.value:
1437                         prefix = config.plugins.FritzCall.prefix.value
1438                         if number[0] != '0':
1439                                 number = prefix + number
1440                                 # debug("[FritzCallPhonebook] added prefix: %s" %number)
1441                         elif number[:len(prefix)] == prefix and self.phonebook.has_key(number[len(prefix):]):
1442                                 # debug("[FritzCallPhonebook] same prefix")
1443                                 name = self.phonebook[number[len(prefix):]]
1444                                 # debug("[FritzCallPhonebook] result: %s" %name)
1445                 else:
1446                         prefix = ""
1447                                 
1448                 if not name and self.phonebook.has_key(number):
1449                         name = self.phonebook[number]
1450
1451                 if not name and default:
1452                         name = default
1453
1454                 if not name and extended and config.plugins.FritzCall.FritzExtendedSearchNames.value:
1455                         for k in range(len(number)-1, 0, -1):
1456                                 # debug("[FritzCallPhonebook] extended search: check: %s" %number[:k])
1457                                 name = self.search(number[:k], default, False)
1458                                 if name:
1459                                         # debug("[FritzCallPhonebook] search result for shortened number: %s" % name)
1460                                         break
1461
1462                 return name.replace(", ", "\n").strip()
1463
1464         def add(self, number, name):
1465                 '''
1466                 
1467                 @param number: number of entry
1468                 @param name: name of entry, has to be in utf-8
1469                 '''
1470                 debug("[FritzCallPhonebook]")
1471                 name = name.replace("\n", ", ").replace('#','') # this is just for safety reasons. add should only be called with newlines converted into commas
1472                 self.remove(number)
1473                 self.phonebook[number] = name
1474                 if number and number != 0:
1475                         if config.plugins.FritzCall.phonebook.value:
1476                                 try:
1477                                         name = name.strip() + "\n"
1478                                         string = "%s#%s" % (number, name)
1479                                         # Beware: strings in PhoneBook.txt have to be in utf-8!
1480                                         f = open(os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt"), 'a')
1481                                         f.write(string)
1482                                         f.close()
1483                                         info("[FritzCallPhonebook] added %s with %s to Phonebook.txt" % (number, name.strip()))
1484                                         return True
1485         
1486                                 except IOError:
1487                                         return False
1488
1489         def remove(self, number):
1490                 if number in self.phonebook:
1491                         debug("[FritzCallPhonebook]")
1492                         del self.phonebook[number]
1493                         if config.plugins.FritzCall.phonebook.value:
1494                                 try:
1495                                         phonebookFilename = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt")
1496                                         debug("[FritzCallPhonebook] remove entry in Phonebook.txt")
1497                                         fOld = open(phonebookFilename, 'r')
1498                                         fNew = open(phonebookFilename + str(os.getpid()), 'w')
1499                                         line = fOld.readline()
1500                                         while (line):
1501                                                 elems = line.split('#')
1502                                                 if len(elems) == 2 and not elems[0] == number:
1503                                                         fNew.write(line)
1504                                                 line = fOld.readline()
1505                                         fOld.close()
1506                                         fNew.close()
1507                                         # os.remove(phonebookFilename)
1508                                         eBackgroundFileEraser.getInstance().erase(phonebookFilename)
1509                                         os.rename(phonebookFilename + str(os.getpid()), phonebookFilename)
1510                                         info("[FritzCallPhonebook] removed %s from Phonebook.txt" % number)
1511                                         return True
1512         
1513                                 except (IOError, OSError):
1514                                         error("[FritzCallPhonebook] error removing %s from %s" %(number, phonebookFilename))
1515                 return False
1516
1517         class FritzDisplayPhonebook(Screen, HelpableScreen, NumericalTextInput):
1518         
1519                 def __init__(self, session):
1520                         self.entriesWidth = DESKTOP_WIDTH * scaleH(75, 85)/100
1521                         self.height = DESKTOP_HEIGHT * 0.75
1522                         numberFieldWidth = scaleH(220, 160)
1523                         fieldWidth = self.entriesWidth -5 -numberFieldWidth -10
1524                         fontSize = scaleV(22, 18)
1525                         fontHeight = scaleV(24, 20)
1526                         buttonGap = (self.entriesWidth-4*140)/5
1527                         debug("[FritzDisplayPhonebook] width: " + str(self.entriesWidth))
1528                         self.skin = """
1529                                 <screen name="FritzDisplayPhonebook" position="center,center" size="%d,%d" title="Phonebook" >
1530                                         <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
1531                                         <widget source="entries" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" transparent="1">
1532                                                 <convert type="TemplatedMultiContent">
1533                                                         {"template": [
1534                                                                         MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 1), # index 0 is the name, index 1 is shortname
1535                                                                         MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 2), # index 2 is number
1536                                                                 ],
1537                                                         "fonts": [gFont("Regular", %d)],
1538                                                         "itemHeight": %d
1539                                                         }
1540                                                 </convert>
1541                                         </widget>
1542                                         <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1543                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1544                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1545                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1546                                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1547                                         <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1548                                         <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1549                                         <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1550                                         <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1551                                 </screen>""" % (
1552                                                 # scaleH(90, 75), scaleV(100, 73), # position 
1553                                                 self.entriesWidth, self.height, # size
1554                                                 self.entriesWidth, # eLabel width
1555                                                 scaleH(40, 5), scaleV(20, 5), # entries position
1556                                                 self.entriesWidth-scaleH(40, 5), self.height-scaleV(20, 5)-5-5-40, # entries size
1557                                                 0, 0, fieldWidth, scaleH(24,20), # name pos/size
1558                                                 fieldWidth +5, 0, numberFieldWidth, scaleH(24,20), # dir pos/size
1559                                                 fontSize, # fontsize
1560                                                 fontHeight, # itemHeight
1561                                                 self.height-40-5, # eLabel position vertical
1562                                                 self.entriesWidth, # eLabel width
1563                                                 buttonGap, self.height-40, "skin_default/buttons/red.png", # ePixmap red
1564                                                 2*buttonGap+140, self.height-40, "skin_default/buttons/green.png", # ePixmap green
1565                                                 3*buttonGap+2*140, self.height-40, "skin_default/buttons/yellow.png", # ePixmap yellow
1566                                                 4*buttonGap+3*140, self.height-40, "skin_default/buttons/blue.png", # ePixmap blue
1567                                                 buttonGap, self.height-40, scaleV(22, 21), # widget red
1568                                                 2*buttonGap+140, self.height-40, scaleV(22, 21), # widget green
1569                                                 3*buttonGap+2*140, self.height-40, scaleV(22, 21), # widget yellow
1570                                                 4*buttonGap+3*140, self.height-40, scaleV(22, 21), # widget blue
1571                                                 )
1572         
1573                         # debug("[FritzDisplayCalls] skin: " + self.skin)
1574                         Screen.__init__(self, session)
1575                         NumericalTextInput.__init__(self)
1576                         HelpableScreen.__init__(self)
1577                 
1578                         # TRANSLATORS: keep it short, this is a button
1579                         self["key_red"] = Button(_("Delete"))
1580                         # TRANSLATORS: keep it short, this is a button
1581                         self["key_green"] = Button(_("New"))
1582                         # TRANSLATORS: keep it short, this is a button
1583                         self["key_yellow"] = Button(_("Edit"))
1584                         # TRANSLATORS: keep it short, this is a button
1585                         self["key_blue"] = Button(_("Search"))
1586         
1587                         self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1588                         {
1589                                 "red": self.delete,
1590                                 "green": self.add,
1591                                 "yellow": self.edit,
1592                                 "blue": self.search,
1593                                 "cancel": self.exit,
1594                                 "ok": self.showEntry, }, - 2)
1595         
1596                         # TRANSLATORS: keep it short, this is a help text
1597                         self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("Show details of entry"))]))
1598                         # TRANSLATORS: keep it short, this is a help text
1599                         self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("Quit"))]))
1600                         # TRANSLATORS: keep it short, this is a help text
1601                         self.helpList.append((self["setupActions"], "ColorActions", [("red", _("Delete entry"))]))
1602                         # TRANSLATORS: keep it short, this is a help text
1603                         self.helpList.append((self["setupActions"], "ColorActions", [("green", _("Add entry to phonebook"))]))
1604                         # TRANSLATORS: keep it short, this is a help text
1605                         self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("Edit selected entry"))]))
1606                         # TRANSLATORS: keep it short, this is a help text
1607                         self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("Search (case insensitive)"))]))
1608         
1609                         self["entries"] = List([])
1610                         debug("[FritzDisplayPhonebook]")
1611                         self.help_window = None
1612                         self.sortlist = []
1613                         self.onLayoutFinish.append(self.setWindowTitle)
1614                         self.display()
1615
1616                 def setWindowTitle(self):
1617                         # TRANSLATORS: this is a window title.
1618                         self.setTitle(_("Phonebook"))
1619
1620                 def display(self, filterNumber=""):
1621                         debug("[FritzDisplayPhonebook]")
1622                         self.sortlist = []
1623                         # Beware: strings in phonebook.phonebook are utf-8!
1624                         sortlistHelp = sorted((name.lower(), name, number) for (number, name) in phonebook.phonebook.iteritems())
1625                         for (low, name, number) in sortlistHelp:
1626                                 if number == "01234567890":
1627                                         continue
1628                                 try:
1629                                         low = low.decode("utf-8")
1630                                 except UnicodeDecodeError:  # this should definitely not happen
1631                                         try:
1632                                                 low = low.decode("iso-8859-1")
1633                                         except UnicodeDecodeError:
1634                                                 error("[FritzDisplayPhonebook] displayPhonebook/display: corrupt phonebook entry for %s" % number)
1635                                                 # self.session.open(MessageBox, _("Corrupt phonebook entry\nfor number %s\nDeleting.") %number, type = MessageBox.TYPE_ERROR)
1636                                                 phonebook.remove(number)
1637                                                 continue
1638                                 else:
1639                                         if filterNumber:
1640                                                 filterNumber = filterNumber.lower()
1641                                                 if low.find(filterNumber) == - 1:
1642                                                         continue
1643                                         name = name.strip().decode("utf-8")
1644                                         number = number.strip().decode("utf-8")
1645                                         comma = name.find(',')
1646                                         if comma != -1:
1647                                                 shortname = name[:comma]
1648                                         else:
1649                                                 shortname = name
1650                                         number = number.encode("utf-8", "replace")
1651                                         name = name.encode("utf-8", "replace")
1652                                         shortname = shortname.encode('utf-8', 'replace')
1653                                         self.sortlist.append((name, shortname, number))
1654                                 
1655                         self["entries"].setList(self.sortlist)
1656         
1657                 def showEntry(self):
1658                         cur = self["entries"].getCurrent()
1659                         if cur:
1660                                 debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1661                                 number = cur[2]
1662                                 name = cur[0]
1663                                 self.session.open(FritzOfferAction, self, number, name)
1664         
1665                 def delete(self):
1666                         cur = self["entries"].getCurrent()
1667                         if cur:
1668                                 debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1669                                 self.session.openWithCallback(
1670                                         self.deleteConfirmed,
1671                                         MessageBox,
1672                                         _("Do you really want to delete entry for\n\n%(number)s\n\n%(name)s?") 
1673                                         % { 'number':str(cur[2]), 'name':str(cur[0]).replace(", ", "\n") }
1674                                                                 )
1675                         else:
1676                                 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1677         
1678                 def deleteConfirmed(self, ret):
1679                         debug("[FritzDisplayPhonebook]")
1680                         #
1681                         # if ret: delete number from sortlist, delete number from phonebook.phonebook and write it to disk
1682                         #
1683                         cur = self["entries"].getCurrent()
1684                         if cur:
1685                                 if ret:
1686                                         # delete number from sortlist, delete number from phonebook.phonebook and write it to disk
1687                                         debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1688                                         phonebook.remove(cur[2])
1689                                         self.display()
1690                                 # else:
1691                                         # self.session.open(MessageBox, _("Not deleted."), MessageBox.TYPE_INFO)
1692                         else:
1693                                 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1694         
1695                 def add(self, parent=None, number="", name=""):
1696                         class AddScreen(Screen, ConfigListScreen):
1697                                 '''ConfiglistScreen with two ConfigTexts for Name and Number'''
1698         
1699                                 def __init__(self, session, parent, number="", name=""):
1700                                         #
1701                                         # setup screen with two ConfigText and OK and ABORT button
1702                                         # 
1703                                         noButtons = 2
1704                                         width = max(scaleH(-1, 570), noButtons*140)
1705                                         height = scaleV(-1, 100) # = 5 + 126 + 40 + 5; 6 lines of text possible
1706                                         buttonsGap = (width-noButtons*140)/(noButtons+1)
1707                                         buttonsVPos = height-40-5
1708                                         self.skin = """
1709                                                 <screen position="center,center" size="%d,%d" title="Add entry to phonebook" >
1710                                                 <widget name="config" position="5,5" size="%d,%d" scrollbarMode="showOnDemand" />
1711                                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1712                                                 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1713                                                 <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1714                                                 <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1715                                                 </screen>""" % (
1716                                                                                 width, height,
1717                                                                                 width - 5 - 5, height - 5 - 40 - 5,
1718                                                                                 buttonsGap, buttonsVPos, "skin_default/buttons/red.png",
1719                                                                                 buttonsGap+140+buttonsGap, buttonsVPos, "skin_default/buttons/green.png",
1720                                                                                 buttonsGap, buttonsVPos,
1721                                                                                 buttonsGap+140+buttonsGap, buttonsVPos,
1722                                                                                 )
1723                                         Screen.__init__(self, session)
1724                                         self.session = session
1725                                         self.parent = parent
1726                                         # TRANSLATORS: keep it short, this is a button
1727                                         self["key_red"] = Button(_("Cancel"))
1728                                         # TRANSLATORS: keep it short, this is a button
1729                                         self["key_green"] = Button(_("OK"))
1730                                         self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
1731                                         {
1732                                                 "cancel": self.cancel,
1733                                                 "red": self.cancel,
1734                                                 "green": self.add,
1735                                                 "ok": self.add,
1736                                         }, - 2)
1737         
1738                                         self.list = [ ]
1739                                         ConfigListScreen.__init__(self, self.list, session=session)
1740                                         self.name = name
1741                                         self.number = number
1742                                         config.plugins.FritzCall.name.value = name
1743                                         config.plugins.FritzCall.number.value = number
1744                                         self.list.append(getConfigListEntry(_("Name"), config.plugins.FritzCall.name))
1745                                         self.list.append(getConfigListEntry(_("Number"), config.plugins.FritzCall.number))
1746                                         self["config"].list = self.list
1747                                         self["config"].l.setList(self.list)
1748                                         self.onLayoutFinish.append(self.setWindowTitle)
1749                         
1750                                 def setWindowTitle(self):
1751                                         # TRANSLATORS: this is a window title.
1752                                         self.setTitle(_("Add entry to phonebook"))
1753
1754                                 def add(self):
1755                                         # get texts from Screen
1756                                         # add (number,name) to sortlist and phonebook.phonebook and disk
1757                                         self.name = config.plugins.FritzCall.name.value
1758                                         self.number = config.plugins.FritzCall.number.value
1759                                         if not self.number or not self.name:
1760                                                 self.session.open(MessageBox, _("Entry incomplete."), type=MessageBox.TYPE_ERROR)
1761                                                 return
1762                                         # add (number,name) to sortlist and phonebook.phonebook and disk
1763         #                                       oldname = phonebook.search(self.number)
1764         #                                       if oldname:
1765         #                                               self.session.openWithCallback(
1766         #                                                       self.overwriteConfirmed,
1767         #                                                       MessageBox,
1768         #                                                       _("Do you really want to overwrite entry for %(number)s\n\n%(name)s\n\nwith\n\n%(newname)s?")
1769         #                                                       % {
1770         #                                                       'number':self.number,
1771         #                                                       'name': oldname,
1772         #                                                       'newname':self.name.replace(", ","\n")
1773         #                                                       }
1774         #                                                       )
1775         #                                               self.close()
1776         #                                               return
1777                                         phonebook.add(self.number, self.name)
1778                                         self.close()
1779                                         self.parent.display()
1780         
1781                                 def overwriteConfirmed(self, ret):
1782                                         if ret:
1783                                                 phonebook.remove(self.number)
1784                                                 phonebook.add(self.number, self.name)
1785                                                 self.parent.display()
1786         
1787                                 def cancel(self):
1788                                         self.close()
1789         
1790                         debug("[FritzDisplayPhonebook]")
1791                         if not parent:
1792                                 parent = self
1793                         self.session.open(AddScreen, parent, number, name)
1794         
1795                 def edit(self):
1796                         debug("[FritzDisplayPhonebook]")
1797                         cur = self["entries"].getCurrent()
1798                         if cur is None:
1799                                 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1800                         else:
1801                                 self.add(self, cur[2], cur[0])
1802         
1803                 def search(self):
1804                         debug("[FritzDisplayPhonebook]")
1805                         self.help_window = self.session.instantiateDialog(NumericalTextInputHelpDialog, self)
1806                         self.help_window.show()
1807                         # VirtualKeyboard instead of InputBox?
1808                         self.session.openWithCallback(self.doSearch, InputBox, _("Enter Search Terms"), _("Search phonebook"))
1809         
1810                 def doSearch(self, searchTerms):
1811                         if not searchTerms:
1812                                 searchTerms = ""
1813                         debug("[FritzDisplayPhonebook]: " + searchTerms)
1814                         if self.help_window:
1815                                 self.session.deleteDialog(self.help_window)
1816                                 self.help_window = None
1817                         self.display(searchTerms)
1818         
1819                 def exit(self):
1820                         self.close()
1821
1822 phonebook = FritzCallPhonebook()
1823
1824 class FritzCallSetup(Screen, ConfigListScreen, HelpableScreen):
1825
1826         def __init__(self, session, args=None): #@UnusedVariable # pylint: disable=W0613
1827                 self.width = scaleH(20+4*(140+90)+2*(35+40)+20, 4*140+2*35)
1828                 width = self.width
1829                 debug("[FritzCallSetup] width: " + str(self.width))
1830                 self.skin = """
1831                         <screen name="FritzCallSetup" position="center,center" size="%d,%d" title="FritzCall Setup" >
1832                         <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
1833                         <widget name="consideration" position="%d,%d" halign="center" size="%d,%d" font="Regular;%d" backgroundColor="#20040404" transparent="1" />
1834                         <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1835                         <widget name="config" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" backgroundColor="#20040404" transparent="1" />
1836                         <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1837                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1838                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1839                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1840                         <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1841                         <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1842                         <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1843                         <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1844                         <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1845                         <ePixmap position="%d,%d" zPosition="4" size="35,25" pixmap="%s" transparent="1" alphatest="on" />
1846                         <ePixmap position="%d,%d" zPosition="4" size="35,25" pixmap="%s" transparent="1" alphatest="on" />
1847                         </screen>""" % (
1848                                                 # (DESKTOP_WIDTH-width)/2, scaleV(100, 73), # position 
1849                                                 width, scaleV(560, 430), # size
1850                                                 width, # eLabel width
1851                                                 scaleH(40, 20), scaleV(10, 5), # consideration position
1852                                                 scaleH(width-80, width-40), scaleV(25, 45), # consideration size
1853                                                 scaleV(22, 20), # consideration font size
1854                                                 scaleV(40, 50), # eLabel position vertical
1855                                                 width, # eLabel width
1856                                                 scaleH(40, 5), scaleV(60, 57), # config position
1857                                                 scaleH(width-80, width-10), scaleV(453, 328), # config size
1858                                                 scaleV(518, 390), # eLabel position vertical
1859                                                 width, # eLabel width
1860                                                 scaleH(20, 0), scaleV(525, 395), "skin_default/buttons/red.png", # pixmap red
1861                                                 scaleH(20+140+90, 140), scaleV(525, 395), "skin_default/buttons/green.png", # pixmap green
1862                                                 scaleH(20+2*(140+90), 2*140), scaleV(525, 395), "skin_default/buttons/yellow.png", # pixmap yellow
1863                                                 scaleH(20+3*(140+90), 3*140), scaleV(525, 395), "skin_default/buttons/blue.png", # pixmap blue
1864                                                 scaleH(20, 0), scaleV(525, 395), scaleV(21, 21), # widget red
1865                                                 scaleH(20+(140+90), 140), scaleV(525, 395), scaleV(21, 21), # widget green
1866                                                 scaleH(20+2*(140+90), 2*140), scaleV(525, 395), scaleV(21, 21), # widget yellow
1867                                                 scaleH(20+3*(140+90), 3*140), scaleV(525, 395), scaleV(21, 21), # widget blue
1868                                                 scaleH(20+4*(140+90), 4*140), scaleV(532, 402), "skin_default/buttons/key_info.png", # button information
1869                                                 scaleH(20+4*(140+90)+(35+40), 4*140+35), scaleV(532, 402), "skin_default/buttons/key_menu.png", # button menu
1870                                                                                                         )
1871
1872                 Screen.__init__(self, session)
1873                 HelpableScreen.__init__(self)
1874                 self.session = session
1875
1876                 self["consideration"] = Label(_("You need to enable the monitoring on your FRITZ!Box by dialing #96*5*!"))
1877                 self.list = []
1878
1879                 # Initialize Buttons
1880                 # TRANSLATORS: keep it short, this is a button
1881                 self["key_red"] = Button(_("Cancel"))
1882                 # TRANSLATORS: keep it short, this is a button
1883                 self["key_green"] = Button(_("OK"))
1884                 # TRANSLATORS: keep it short, this is a button
1885                 self["key_yellow"] = Button(_("Phone calls"))
1886                 # TRANSLATORS: keep it short, this is a button
1887                 self["key_blue"] = Button(_("Phonebook"))
1888                 # TRANSLATORS: keep it short, this is a button
1889                 self["key_info"] = Button(_("About FritzCall"))
1890                 # TRANSLATORS: keep it short, this is a button
1891                 self["key_menu"] = Button(_("FRITZ!Box Fon Status"))
1892
1893                 self["setupActions"] = ActionMap(["ColorActions", "OkCancelActions", "MenuActions", "EPGSelectActions"],
1894                 {
1895                         "red": self.cancel,
1896                         "green": self.save,
1897                         "yellow": self.displayCalls,
1898                         "blue": self.displayPhonebook,
1899                         "cancel": self.cancel,
1900                         "ok": self.save,
1901                         "menu": self.menu,
1902                         "info": self.about,
1903                 }, - 2)
1904
1905                 # TRANSLATORS: keep it short, this is a help text
1906                 self.helpList.append((self["setupActions"], "ColorActions", [("red", _("quit"))]))
1907                 # TRANSLATORS: keep it short, this is a help text
1908                 self.helpList.append((self["setupActions"], "ColorActions", [("green", _("save and quit"))]))
1909                 # TRANSLATORS: keep it short, this is a help text
1910                 self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("display calls"))]))
1911                 # TRANSLATORS: keep it short, this is a help text
1912                 self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("display phonebook"))]))
1913                 # TRANSLATORS: keep it short, this is a help text
1914                 self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("save and quit"))]))
1915                 # TRANSLATORS: keep it short, this is a help text
1916                 self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("quit"))]))
1917                 # TRANSLATORS: keep it short, this is a help text
1918                 self.helpList.append((self["setupActions"], "MenuActions", [("menu", _("FRITZ!Box Fon Status"))]))
1919                 # TRANSLATORS: keep it short, this is a help text
1920                 self.helpList.append((self["setupActions"], "EPGSelectActions", [("info", _("About FritzCall"))]))
1921
1922                 ConfigListScreen.__init__(self, self.list, session=session)
1923
1924                 # get new list of locations for PhoneBook.txt
1925                 self.createSetup()
1926                 self.onLayoutFinish.append(self.setWindowTitle)
1927
1928         def setWindowTitle(self):
1929                 # TRANSLATORS: this is a window title.
1930                 self.setTitle(_("FritzCall Setup") + " (" + "$Revision: 1252 $"[1: - 1] + "$Date: 2015-12-10 11:11:04 +0100 (Thu, 10 Dec 2015) $"[7:23] + ")")
1931
1932         def keyLeft(self):
1933                 ConfigListScreen.keyLeft(self)
1934                 self.createSetup()
1935
1936         def keyRight(self):
1937                 ConfigListScreen.keyRight(self)
1938                 self.createSetup()
1939
1940         def createSetup(self):
1941                 self.list = [ ]
1942                 self.list.append(getConfigListEntry(_("Call monitoring"), config.plugins.FritzCall.enable))
1943                 if config.plugins.FritzCall.enable.value:
1944                         self.list.append(getConfigListEntry(_("FRITZ!Box FON address (Name or IP)"), config.plugins.FritzCall.hostname))
1945                         self.list.append(getConfigListEntry(_("FRITZ!Box FON firmware version"), config.plugins.FritzCall.fwVersion))
1946
1947                         self.list.append(getConfigListEntry(_("Show after Standby"), config.plugins.FritzCall.afterStandby))
1948
1949                         self.list.append(getConfigListEntry(_("Show only calls for specific MSN"), config.plugins.FritzCall.filter))
1950                         if config.plugins.FritzCall.filter.value:
1951                                 self.list.append(getConfigListEntry(_("MSN to show (separated by ,)"), config.plugins.FritzCall.filtermsn))
1952                                 self.list.append(getConfigListEntry(_("Filter also list of calls"), config.plugins.FritzCall.filterCallList))
1953                         self.list.append(getConfigListEntry(_("Mute on call"), config.plugins.FritzCall.muteOnCall))
1954
1955                         self.list.append(getConfigListEntry(_("Show Blocked Calls"), config.plugins.FritzCall.showBlacklistedCalls))
1956                         self.list.append(getConfigListEntry(_("Show Outgoing Calls"), config.plugins.FritzCall.showOutgoingCalls))
1957                         # not only for outgoing: config.plugins.FritzCall.showOutgoingCalls.value:
1958                         self.list.append(getConfigListEntry(_("Areacode to add to calls without one (if necessary)"), config.plugins.FritzCall.prefix))
1959                         self.list.append(getConfigListEntry(_("Timeout for Call Notifications (seconds)"), config.plugins.FritzCall.timeout))
1960                         self.list.append(getConfigListEntry(_("Reverse Lookup Caller ID (select country below)"), config.plugins.FritzCall.lookup))
1961                         if config.plugins.FritzCall.lookup.value:
1962                                 self.list.append(getConfigListEntry(_("Country"), config.plugins.FritzCall.country))
1963
1964                         if config.plugins.FritzCall.fwVersion.value != None:
1965                                 if config.plugins.FritzCall.fwVersion.value == "05.50" or config.plugins.FritzCall.fwVersion.value == "06.35":
1966                                         self.list.append(getConfigListEntry(_("User name Accessing FRITZ!Box"), config.plugins.FritzCall.username))
1967                                 self.list.append(getConfigListEntry(_("Password Accessing FRITZ!Box"), config.plugins.FritzCall.password))
1968                                 self.list.append(getConfigListEntry(_("Extension number to initiate call on"), config.plugins.FritzCall.extension))
1969                                 if config.plugins.FritzCall.fwVersion.value == "05.50" or config.plugins.FritzCall.fwVersion.value == "06.35":
1970                                         self.list.append(getConfigListEntry(_("Name of WLAN guest network"), config.plugins.FritzCall.guestSSID))
1971                                         self.list.append(getConfigListEntry(_("Secure WLAN guest network"), config.plugins.FritzCall.guestSecure))
1972                                         # TODO: make password unreadable?
1973                                         self.list.append(getConfigListEntry(_("Password of WLAN guest network"), config.plugins.FritzCall.guestPassword))
1974                                         self.list.append(getConfigListEntry(_("Minutes of uptime of WLAN guest network"), config.plugins.FritzCall.guestUptime))
1975                                 self.list.append(getConfigListEntry(_("Read PhoneBook from FRITZ!Box"), config.plugins.FritzCall.fritzphonebook))
1976                                 if config.plugins.FritzCall.fritzphonebook.value:
1977                                         if config.plugins.FritzCall.fwVersion.value != "06.35":
1978                                                 self.list.append(getConfigListEntry(_("FRITZ!Box PhoneBook to read"), config.plugins.FritzCall.fritzphonebookName))
1979                                         self.list.append(getConfigListEntry(_("Append type of number"), config.plugins.FritzCall.showType))
1980                                         self.list.append(getConfigListEntry(_("Append shortcut number"), config.plugins.FritzCall.showShortcut))
1981                                         self.list.append(getConfigListEntry(_("Append vanity name"), config.plugins.FritzCall.showVanity))
1982                         else:
1983                                 config.plugins.FritzCall.fritzphonebook.value = False
1984
1985                         if config.plugins.FritzCall.phonebook.value or config.plugins.FritzCall.fritzphonebook.value:
1986                                 self.list.append(getConfigListEntry(_("Reload interval for phonebooks (hours)"), config.plugins.FritzCall.reloadPhonebookTime))
1987
1988                         self.list.append(getConfigListEntry(_("Use internal PhoneBook"), config.plugins.FritzCall.phonebook))
1989                         if config.plugins.FritzCall.phonebook.value:
1990                                 if config.plugins.FritzCall.lookup.value:
1991                                         self.list.append(getConfigListEntry(_("Automatically add new Caller to PhoneBook"), config.plugins.FritzCall.addcallers))
1992                         self.list.append(getConfigListEntry(_("PhoneBook and Faces Location"), config.plugins.FritzCall.phonebookLocation))
1993
1994                         if config.plugins.FritzCall.phonebook.value or config.plugins.FritzCall.fritzphonebook.value:
1995                                 self.list.append(getConfigListEntry(_("Extended Search for names"), config.plugins.FritzCall.FritzExtendedSearchNames))
1996                         self.list.append(getConfigListEntry(_("Extended Search for faces"), config.plugins.FritzCall.FritzExtendedSearchFaces))
1997
1998                         self.list.append(getConfigListEntry(_("Strip Leading 0"), config.plugins.FritzCall.internal))
1999                         # self.list.append(getConfigListEntry(_("Default display mode for FRITZ!Box calls"), config.plugins.FritzCall.fbfCalls))
2000                         self.list.append(getConfigListEntry(_("Display connection infos"), config.plugins.FritzCall.connectionVerbose))
2001                         self.list.append(getConfigListEntry(_("Ignore callers with no phone number"), config.plugins.FritzCall.ignoreUnknown))
2002                         self.list.append(getConfigListEntry(_("Debug"), config.plugins.FritzCall.debug))
2003
2004                 self["config"].list = self.list
2005                 self["config"].l.setList(self.list)
2006
2007         def save(self):
2008 #               debug("[FritzCallSetup]"
2009                 if self["config"].getCurrent()[1] == config.plugins.FritzCall.phonebookLocation:
2010                         self.session.openWithCallback(self.LocationBoxClosed, LocationBox, _("PhoneBook and Faces Location"), currDir=config.plugins.FritzCall.phonebookLocation.value)
2011                 else:
2012                         for x in self["config"].list:
2013                                 x[1].save()
2014                         if config.plugins.FritzCall.phonebookLocation.isChanged() or config.plugins.FritzCall.reloadPhonebookTime.isChanged():
2015                                 global phonebook
2016                                 phonebook.reload()
2017                         if fritz_call:
2018                                 if config.plugins.FritzCall.enable.value:
2019                                         fritz_call.connect()
2020                                 else:
2021                                         fritz_call.shutdown()
2022                         self.close()
2023
2024         def LocationBoxClosed(self, path):
2025                 if path is not None:
2026                         config.plugins.FritzCall.phonebookLocation.setValue(path)
2027
2028         def cancel(self):
2029 #               debug("[FritzCallSetup]"
2030                 for x in self["config"].list:
2031                         x[1].cancel()
2032                 self.close()
2033
2034         def displayCalls(self):
2035                 if config.plugins.FritzCall.enable.value:
2036                         if fritzbox and config.plugins.FritzCall.fwVersion.value:
2037                                 self.session.open(FritzDisplayCalls)
2038                         else:
2039                                 self.session.open(MessageBox, _("Cannot get calls from FRITZ!Box"), type=MessageBox.TYPE_INFO)
2040                 else:
2041                         self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2042
2043         def displayPhonebook(self):
2044                 if phonebook:
2045                         if config.plugins.FritzCall.enable.value:
2046                                 self.session.open(phonebook.FritzDisplayPhonebook)
2047                         else:
2048                                 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2049                 else:
2050                         self.session.open(MessageBox, _("No phonebook"), type=MessageBox.TYPE_INFO)
2051
2052         def about(self):
2053                 self.session.open(FritzAbout)
2054
2055         def menu(self):
2056                 if config.plugins.FritzCall.enable.value:
2057                         if fritzbox and fritzbox.information:
2058                                 self.session.open(FritzMenu)
2059                         else:
2060                                 self.session.open(MessageBox, _("Cannot get infos from FRITZ!Box yet\nStill initialising or wrong firmware version"), type=MessageBox.TYPE_INFO)
2061                 else:
2062                         self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2063
2064 standbyMode = False
2065
2066 class FritzCallList:
2067         def __init__(self):
2068                 self.callList = [ ]
2069         
2070         def add(self, event, date, number, caller, phone):
2071                 debug("[FritzCallList] %s %s" % (number, caller))
2072                 if len(self.callList) > 10:
2073                         if self.callList[0] != "Start":
2074                                 self.callList[0] = "Start"
2075                         del self.callList[1]
2076
2077                 self.callList.append((event, number, date, caller, phone))
2078         
2079         def display(self):
2080                 debug("[FritzCallList]")
2081                 global standbyMode
2082                 standbyMode = False
2083                 # Standby.inStandby.onClose.remove(self.display) object does not exist anymore...
2084                 # build screen from call list
2085                 text = "\n"
2086
2087                 if not self.callList:
2088                         text = _("no calls") 
2089                 else:
2090                         if self.callList[0] == "Start":
2091                                 text = text + _("Last 10 calls:\n")
2092                                 del self.callList[0]
2093         
2094                         for call in self.callList:
2095                                 (event, number, date, caller, phone) = call
2096                                 if event == "RING":
2097                                         direction = "->"
2098                                 else:
2099                                         direction = "<-"
2100         
2101                                 # shorten the date information
2102                                 date = date[:6] + date[9:14]
2103         
2104                                 # our phone could be of the form "0123456789 (home)", then we only take "home"
2105                                 oBrack = phone.find('(')
2106                                 cBrack = phone.find(')')
2107                                 if oBrack != -1 and cBrack != -1:
2108                                         phone = phone[oBrack+1:cBrack]
2109         
2110                                 # should not happen, for safety reasons
2111                                 if not caller:
2112                                         caller = _("UNKNOWN")
2113                                 
2114                                 #  if we have an unknown number, show the number
2115                                 if caller == _("UNKNOWN") and number != "":
2116                                         caller = number
2117                                 else:
2118                                         # strip off the address part of the remote caller/callee, if there is any
2119                                         nl = caller.find('\n')
2120                                         if nl != -1:
2121                                                 caller = caller[:nl]
2122                                         elif caller[0] == '[' and caller[-1] == ']':
2123                                                 # that means, we've got an unknown number with a city added from avon.dat 
2124                                                 if (len(number) + 1 + len(caller) + len(phone)) <= 40:
2125                                                         caller = number + ' ' + caller
2126                                                 else:
2127                                                         caller = number
2128         
2129                                 while (len(caller) + len(phone)) > 40:
2130                                         if len(caller) > len(phone):
2131                                                 caller = caller[: - 1]
2132                                         else:
2133                                                 phone = phone[: - 1]
2134         
2135                                 text = text + "%s %s %s %s\n" % (date, caller, direction, phone)
2136                                 debug("[FritzCallList] '%s %s %s %s'" % (date, caller, direction, phone))
2137
2138                 # display screen
2139                 Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO)
2140                 # TODO please HELP: from where can I get a session?
2141                 # my_global_session.open(FritzDisplayCalls, text)
2142                 self.callList = [ ]
2143
2144 callList = FritzCallList()
2145
2146 def findFace(number, name):
2147         # debug("[FritzCall] number/name: %s/%s" % (number, name))
2148         if name:
2149                 sep = name.find(',')
2150                 if sep != -1:
2151                         name = name[:sep]
2152                 sep = name.find('\n')
2153                 if sep != -1:
2154                         name = name[:sep]
2155         else:
2156                 name = _("UNKNOWN")
2157         # debug("[FritzCall] looking for: %s" %name)
2158
2159         facesDir = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "FritzCallFaces")
2160         # debug("[FritzCall] looking in: %s" %facesDir)
2161         facesFile = None
2162
2163         if not os.path.isdir(facesDir):
2164                 error("[FritzCall] findFace facesdir does not exist: %s" %facesDir)
2165         else:
2166                 files = os.listdir(facesDir)
2167                 # debug("[FritzCall] listdir: %s" %repr(files))
2168                 # TODO macthed das hier auf ????.png1 ?!?!?
2169                 myFiles = [f for f in files if re.match(re.escape(number) + "\.[png|PNG]", f)]
2170                 if not myFiles:
2171                         myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2172         
2173                 if not myFiles:
2174                         sep = name.find(' (')
2175                         if sep != -1:
2176                                 name = name[:sep]
2177                         myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2178         
2179                 if myFiles:
2180                         # debug("[FritzCall] found: %s" %repr(myFiles))
2181                         facesFile = os.path.join(facesDir, myFiles[0])
2182         
2183                 if not facesFile and config.plugins.FritzCall.FritzExtendedSearchFaces.value:
2184                         for k in range(len(number)-1, 0, -1):
2185                                 # debug("[FritzCall] extended search: %s" %number[:k])
2186                                 myFiles = [f for f in files if re.match(re.escape(number[:k]) + "\.[png|PNG]", f)]
2187                                 if myFiles:
2188                                         facesFile = os.path.join(facesDir, myFiles[0])
2189                                         break
2190
2191         if not facesFile:
2192                 facesFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
2193
2194         info("[FritzCall] result: %s" % (__(facesFile)))
2195         return facesFile
2196
2197 class MessageBoxPixmap(Screen):
2198         def __init__(self, session, text, number = "", name = "", timeout = -1):
2199                 self.skin = """
2200         <screen name="MessageBoxPixmap" position="center,center" size="600,10" title="New Call">
2201                 <widget name="text" position="115,8" size="520,0" font="Regular;%d" />
2202                 <widget name="InfoPixmap" pixmap="%s" position="5,5" size="100,100" alphatest="on" />
2203         </screen>
2204                 """ % (
2205                         # scaleH(350, 60), scaleV(175, 245),
2206                         scaleV(25, 22), resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
2207                         )
2208                 debug("[FritzCall] MessageBoxPixmap number: %s" % number)
2209                 Screen.__init__(self, session)
2210                 # MessageBox.__init__(self, session, text, type=MessageBox.TYPE_INFO, timeout=timeout)
2211                 self["text"] = Label(text)
2212                 self["InfoPixmap"] = Pixmap()
2213                 self._session = session
2214                 self._number = number
2215                 self._name = name
2216                 self._timerRunning = False
2217                 self._timer = None
2218                 self._timeout = timeout
2219                 self._origTitle = None
2220                 self._initTimeout()
2221                 self.onLayoutFinish.append(self._finishLayout)
2222                 self["actions"] = ActionMap(["OkCancelActions"],
2223                 {
2224                         "cancel": self._exit,
2225                         "ok": self._exit, }, - 2)
2226
2227         def _finishLayout(self):
2228                 # pylint: disable=W0142
2229                 debug("[FritzCall] MessageBoxPixmap/setInfoPixmap number: %s/%s" % (self._number, self._name))
2230
2231                 self.setTitle(_("New call"))
2232
2233                 faceFile = findFace(self._number, self._name)
2234                 picPixmap = LoadPixmap(faceFile)
2235                 if not picPixmap:       # that means most probably, that the picture is not 8 bit...
2236                         Notifications.AddNotification(MessageBox, _("Found picture\n\n%s\n\nBut did not load. Probably not PNG, 8-bit") %faceFile, type = MessageBox.TYPE_ERROR)
2237                         picPixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_error.png"))
2238                 picSize = picPixmap.size()
2239
2240                 # recalculate window size
2241                 textSize = self["text"].getSize()
2242                 textSize = (textSize[0]+20, textSize[1]+20) # don't know, why, but size is too small
2243                 textSize = eSize(*textSize)
2244                 width = max(scaleH(600, 280), picSize.width() + textSize.width() + 30)
2245                 height = max(scaleV(300, 250), picSize.height()+10, textSize.height()+10)
2246                 wSize = (width, height)
2247                 wSize = eSize(*wSize)
2248
2249                 # center the smaller vertically
2250                 hGap = (width-picSize.width()-textSize.width())/3
2251                 picPos = (hGap, (height-picSize.height())/2+1)
2252                 textPos = (hGap+picSize.width()+hGap, (height-textSize.height())/2+1)
2253
2254                 # resize screen
2255                 self.instance.resize(wSize)
2256                 # resize text
2257                 self["text"].instance.resize(textSize)
2258                 # resize pixmap
2259                 self["InfoPixmap"].instance.resize(picSize)
2260                 self["InfoPixmap"].instance.setPixmap(picPixmap)
2261                 # move text
2262                 self["text"].instance.move(ePoint(*textPos))
2263                 # move pixmap
2264                 self["InfoPixmap"].instance.move(ePoint(*picPos))
2265                 # center window
2266                 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
2267
2268         def _initTimeout(self):
2269                 if self._timeout > 0:
2270                         self._timer = eTimer()
2271                         
2272                         # newer OE versions don't have the callback
2273                         try:
2274                                 self._timer_conn = self._timer.timeout.connect(self._timerTick)
2275                         except AttributeError:
2276                                 self._timer.callback.append(self._timerTick)
2277
2278                         self.onExecBegin.append(self._startTimer)
2279                         self._origTitle = None
2280                         if self.execing:
2281                                 self._timerTick()
2282                         else:
2283                                 self.onShown.append(self.__onShown)
2284                         self._timerRunning = True
2285                 else:
2286                         self._timerRunning = False
2287
2288         def __onShown(self):
2289                 self.onShown.remove(self.__onShown)
2290                 self._timerTick()
2291
2292         def _startTimer(self):
2293                 self._timer.start(1000)
2294
2295 #===============================================================================
2296 #       def stopTimer(self):
2297 #               if self._timerRunning:
2298 #                       del self._timer
2299 #                       self.setTitle(self._origTitle)
2300 #                       self._timerRunning = False
2301 #===============================================================================
2302
2303         def _timerTick(self):
2304                 if self.execing:
2305                         self._timeout -= 1
2306                         if self._origTitle is None:
2307                                 self._origTitle = self.instance.getTitle()
2308                         self.setTitle(self._origTitle + " (" + str(self._timeout) + ")")
2309                         if self._timeout == 0:
2310                                 self._timer.stop()
2311                                 self._timerRunning = False
2312                                 self._exit()
2313
2314         def _exit(self):
2315                 self.close()
2316
2317 def runUserActionScript(event, date, number, caller, phone):
2318         # user exit
2319         # call FritzCallserAction.sh in the same dir as Phonebook.txt with the following parameters:
2320         # event: "RING" (incomning) or "CALL" (outgoing)
2321         # date of event, format: "dd.mm.yy hh.mm.ss"
2322         # telephone number which is calling/is called
2323         # caller's name and address, format Name\n Street\n ZIP City
2324         # line/number which is called/which is used for calling
2325         userActionScript = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "FritzCallUserAction.sh")
2326         if os.path.exists(userActionScript) and os.access(userActionScript, os.X_OK):
2327                 cmd = userActionScript + ' "' + event + '" "' + date + '" "' + number + '" "' + caller + '" "' + phone + '"'
2328                 info("[FritzCall] calling: %s" % cmd)
2329                 eConsoleAppContainer().execute(cmd)
2330
2331 userActionList = [runUserActionScript]
2332 def registerUserAction(fun):
2333         #===========================================================================
2334         # other plugins can register a function, which is then called for each displayed call
2335         # it must take the arguments event,date,number,caller,phone
2336         #
2337         #example:
2338         # def FritzCallEvent(event,date,number,caller,phone):
2339         # ......
2340         # 
2341         # try:
2342         #       from Plugins.Extensions.FritzCall.plugin import registerUserAction as FritzCallRegisterUserAction
2343         #       FritzCallRegisterUserAction(FritzCallEvent)
2344         # except:
2345         #       print "import of FritzCall failed"
2346         #===========================================================================
2347         info("[FritzCall] register: %s" % fun.__name__)
2348         userActionList.append(fun)
2349                         
2350 mutedOnConnID = None
2351 def notifyCall(event, date, number, caller, phone, connID):
2352         if Standby.inStandby is None or config.plugins.FritzCall.afterStandby.value == "each":
2353                 if event == "RING":
2354                         global mutedOnConnID
2355                         if config.plugins.FritzCall.muteOnCall.value and not mutedOnConnID:
2356                                 info("[FritzCall] mute on connID: %s" % connID)
2357                                 mutedOnConnID = connID
2358                                 # eDVBVolumecontrol.getInstance().volumeMute() # with this, we get no mute icon...
2359                                 if not eDVBVolumecontrol.getInstance().isMuted():
2360                                         globalActionMap.actions["volumeMute"]()
2361                         text = _("Incoming Call on %(date)s at %(time)s from\n---------------------------------------------\n%(number)s\n%(caller)s\n---------------------------------------------\nto: %(phone)s") % { 'date':date[:8], 'time':date[9:], 'number':number, 'caller':caller, 'phone':phone }
2362                 else:
2363                         text = _("Outgoing Call on %(date)s at %(time)s to\n---------------------------------------------\n%(number)s\n%(caller)s\n---------------------------------------------\nfrom: %(phone)s") % { 'date':date[:8], 'time':date[9:], 'number':number, 'caller':caller, 'phone':phone }
2364                 info("[FritzCall]\n%s" % text)
2365                 # Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO, timeout=config.plugins.FritzCall.timeout.value)
2366                 Notifications.AddNotification(MessageBoxPixmap, text, number=number, name=caller, timeout=config.plugins.FritzCall.timeout.value)
2367         elif config.plugins.FritzCall.afterStandby.value == "inList":
2368                 #
2369                 # if not yet done, register function to show call list
2370                 global standbyMode
2371                 if not standbyMode :
2372                         standbyMode = True
2373                         Standby.inStandby.onHide.append(callList.display) #@UndefinedVariable
2374                 # add text/timeout to call list
2375                 callList.add(event, date, number, caller, phone)
2376                 info("[FritzCall] added to callList")
2377         else: # this is the "None" case
2378                 info("[FritzCall] standby and no show")
2379
2380         for fun in userActionList:
2381                 info("[FritzCall] call user action: %s" % fun.__name__)
2382                 fun(event, date, number, caller, phone)
2383
2384
2385 #===============================================================================
2386 #               We need a separate class for each invocation of reverseLookup to retain
2387 #               the necessary data for the notification
2388 #===============================================================================
2389
2390 countries = { }
2391 reverselookupMtime = 0
2392
2393 class FritzReverseLookupAndNotifier:
2394         def __init__(self, event, number, caller, phone, date, connID):
2395                 '''
2396                 
2397                 Initiate a reverse lookup for the given number in the configured country
2398                 
2399                 @param event: CALL or RING
2400                 @param number: number to be looked up
2401                 @param caller: caller including name and address
2402                 @param phone: Number (and name) of or own phone
2403                 @param date: date of call
2404         &