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