1 # -*- coding: utf-8 -*-
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 $
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
20 # pylint: disable=C0111,C0103,C0301,W0603,W0141,W0403
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
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")
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
43 from Components.config import ConfigPassword
45 ConfigPassword = ConfigText
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
54 from twisted.internet import reactor #@UnresolvedImport
55 from twisted.internet.protocol import ReconnectingClientFactory #@UnresolvedImport
56 from twisted.protocols.basic import LineReceiver #@UnresolvedImport
58 import re, time, os, traceback
60 from nrzuname import ReverseLookupAndNotifier
61 import FritzOutlookCSV, FritzLDIF
62 from . import _, __, initDebug, debug #@UnresolvedImport # pylint: disable=W0611,F0401
64 from enigma import getDesktop
65 DESKTOP_WIDTH = getDesktop(0).size().width()
66 DESKTOP_HEIGHT = getDesktop(0).size().height()
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
80 return scale(y2, y1, 1280, 720, DESKTOP_WIDTH)
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
90 my_global_session = None
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)
135 ("0049", _("Germany")),
136 ("0031", _("The Netherlands")),
137 ("0033", _("France")),
138 ("0039", _("Italy")),
139 ("0041", _("Switzerland")),
140 ("0043", _("Austria")),
143 config.plugins.FritzCall.country = ConfigSelection(choices=countryCodes)
147 FBF_MISSED_CALLS = "2"
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")
154 config.plugins.FritzCall.fbfCalls = ConfigSelection(choices=fbfCallsChoices)
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')
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')
172 parts = line.split(':')
174 avon[parts[0].replace('-','').replace('*','').replace('/','')] = parts[1]
176 def resolveNumberWithAvon(number, countrycode):
177 if not number or number[0] != '0':
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
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() + ']'
194 def handleReverseLookupResult(name):
195 found = re.match("NA: ([^;]*);VN: ([^;]*);STR: ([^;]*);HNR: ([^;]*);PLZ: ([^;]*);ORT: ([^;]*)", name)
197 ( name, firstname, street, streetno, zipcode, city ) = (found.group(1),
205 name += ' ' + firstname
206 if street or streetno or zipcode or city:
211 name += ' ' + streetno
212 if (street or streetno) and (zipcode or city):
215 name += zipcode + ' ' + city
222 from xml.dom.minidom import parse
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")
233 debug("[FritzCall] initCbC: callbycallFileName does not exist?!?!")
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")
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:]
250 class FritzAbout(Screen):
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
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" />
263 width, height, # size
264 (height-scaleV(150,130)) / 2, # text vertical position
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
274 Screen.__init__(self, session)
275 self["aboutActions"] = ActionMap(["OkCancelActions"],
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"
286 self["url"] = Label("http://wiki.blue-panel.com/index.php/FritzCall")
287 self.onLayoutFinish.append(self.setWindowTitle)
289 def setWindowTitle(self):
290 # TRANSLATORS: this is a window title.
291 self.setTitle(_("About FritzCall"))
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:
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
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:
313 if fritzbox.info[FBF_dectActive] is not None:
315 if fritzbox.info[FBF_faxActive] is not None:
317 if fritzbox.info[FBF_rufumlActive] is not None:
319 buttonsGap = (width-noButtons*140)/(noButtons+1)
320 buttonsVPos = height-40-5
323 if fritzbox.info[FBF_tamActive] is not None:
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" />
331 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position mailbox
332 width-40-20, fontSize, # size mailbox
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,
345 if fritzbox.info[FBF_dectActive] is not None:
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"/>
351 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
352 width-40-20, fontSize, # size dect
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
363 if fritzbox.info[FBF_faxActive] is not None:
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"/>
369 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
370 width-40-20, fontSize, # size dect
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
381 if fritzbox.info[FBF_rufumlActive] is not None:
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"/>
387 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
388 width-40-20, fontSize, # size dect
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
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"/>
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" />
420 width, height, # size
421 40, 5, # position info
422 width-2*40, 2*fontSize, # size info
424 40, 5+2*fontSize+10, # position internet
425 width-40, 2*fontSize, # size internet
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
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
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
449 buttonsGap, buttonsVPos, "skin_default/buttons/red.png", buttonsGap, buttonsVPos,
450 buttonsGap+140+buttonsGap, buttonsVPos, "skin_default/buttons/green.png", buttonsGap+140+buttonsGap, buttonsVPos,
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"],
465 "cancel": self._exit,
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,
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()
494 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "EPGSelectActions"],
496 "cancel": self._exit,
498 "green": self._toggleWlan,
500 "info": self._getInfo,
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"))]))
514 self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
516 self["FBFInternet"] = Label('Internet')
517 self["internet_inactive"] = Pixmap()
518 self["internet_active"] = Pixmap()
519 self["internet_active"].hide()
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()
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
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()
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()
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
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
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" />
590 width, height, # size
591 40, 5, # position info
592 width-2*40, 2*fontSize, # size info
594 40, 5+2*fontSize+10, # position internet
595 width-40, 2*fontSize, # size internet
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
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
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
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
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
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
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,
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"],
652 "cancel": self._exit,
654 "green": self._toggleWlan,
655 "yellow": self._toggleGast,
656 "red": self._reset, # no button, does not work
657 "info": self._getInfo,
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"))]))
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"))
680 self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
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()
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()
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
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()
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()
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()
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 = ""
727 self.onLayoutFinish.append(self.setWindowTitle)
729 def setWindowTitle(self):
730 # TRANSLATORS: this is a window title.
731 self.setTitle(_("FRITZ!Box Fon Status"))
735 fritzbox.getInfo(self._fillMenu)
736 self._fillMenu(fritzbox.info, True)
738 def _fillMenu(self, status, refreshing=False):
739 (boxInfo, upTime, ipAddress, wlanState, dslState, tamActive, dectActive, faxActive, rufumlActive, guestAccess) = status
741 self._wlanActive = (wlanState[0] == '1')
742 self._guestActive = guestAccess
743 self._mailboxActive = False
745 if not self.has_key("FBFInfo"): # screen is closed already
749 self["FBFInfo"].setText(_("Refreshing..."))
752 self["FBFInfo"].setText(boxInfo.replace(', ', '\n'))
754 self["FBFInfo"].setText('BoxInfo ' + _('Status not available'))
758 self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress + '\n' + _('Connected since') + ' ' + upTime)
760 self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress)
761 self["internet_inactive"].hide()
762 self["internet_active"].show()
764 self["internet_active"].hide()
765 self["internet_inactive"].show()
768 if dslState[0] == '5':
769 self["dsl_inactive"].hide()
770 self["dsl_active"].show()
772 message = dslState[2]
776 message = message + ' ' + dslState[1]
777 self["FBFDsl"].setText(message)
779 self["dsl_active"].hide()
780 self["dsl_inactive"].show()
782 self["FBFDsl"].setText('DSL ' + _('Status not available'))
783 self["dsl_active"].hide()
784 self["dsl_inactive"].hide()
787 if wlanState[0 ] == '1':
788 self["wlan_inactive"].hide()
789 self["wlan_active"].show()
791 if wlanState[1] == '0':
792 message += ' ' + _('not encrypted')
793 elif wlanState[1] == '1':
794 message += ' ' + _('encrypted')
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')
801 message = message + ', ' + wlanState[2] + ' ' + _('devices active')
802 if len(wlanState) == 4:
803 message = message + ", " + wlanState[3]
804 self["FBFWlan"].setText(message)
806 self["wlan_active"].hide()
807 self["wlan_inactive"].show()
808 self["FBFWlan"].setText('WLAN')
810 self["FBFWlan"].setText('WLAN ' + _('Status not available'))
811 self["wlan_active"].hide()
812 self["wlan_inactive"].hide()
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'))
821 self._mailboxActive = True
823 for i in range(min(len(tamActive)-1, 5)):
825 message = message + str(i) + ','
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)
833 self["FBFMailbox"].setText(str(tamActive[0]) + ' ' + _('mailboxes active') + ' ' + message)
835 if dectActive and self.has_key("dect_inactive"):
836 self["dect_inactive"].hide()
837 self["dect_active"].show()
839 self["FBFDect"].setText(_('No DECT phone registered'))
842 self["FBFDect"].setText(_('One DECT phone registered'))
844 self["FBFDect"].setText(str(dectActive) + ' ' + _('DECT phones registered'))
846 self["dect_active"].hide()
847 self["dect_inactive"].show()
848 self["FBFDect"].setText(_('DECT inactive'))
851 self["fax_inactive"].hide()
852 self["fax_active"].show()
853 self["FBFFax"].setText(_('Software fax active'))
855 self["fax_active"].hide()
856 self["fax_inactive"].show()
857 self["FBFFax"].setText(_('Software fax inactive'))
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'))
867 self["FBFRufuml"].setText(str(rufumlActive) + ' ' + _('call redirections active'))
869 self["rufuml_active"].hide()
870 self["rufuml_inactive"].show()
871 self["FBFRufuml"].setText(_('No call redirection active'))
874 self["gast_inactive"].hide()
875 self["gast_active"].show()
876 self["FBFGast"].setText(_('Guest access on ') + guestAccess)
878 self["gast_active"].hide()
879 self["gast_inactive"].show()
880 self["FBFGast"].setText(_('Guest access not active'))
882 if guestAccess.find('WLAN') != -1:
883 # TRANSLATORS: keep it short, this is a button
884 self["key_yellow"].setText(_("Deactivate WLAN guest access"))
886 # TRANSLATORS: keep it short, this is a button
887 self["key_yellow"].setText(_("Activate WLAN guest access"))
891 debug("[FritzCallFBF] _fillMenu: " + traceback.format_exc())
893 def _toggleWlan(self):
894 self["FBFInfo"].setText(_("Setting...") + " WLAN")
896 debug("[FritzMenu] toggleWlan off")
897 fritzbox.changeWLAN('0', self._getInfo)
899 debug("[FritzMenu] toggleWlan on")
900 fritzbox.changeWLAN('1', self._getInfo)
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)
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"))
914 fritzbox.changeGuestAccess(self._guestActive, self._getInfo)
924 class FritzDisplayCalls(Screen, HelpableScreen):
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)
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))
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">
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
956 "fonts": [gFont("Regular", %d), gFont("Regular", %d)],
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" />
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
999 # debug("[FritzDisplayCalls] skin: " + self.skin)
1000 Screen.__init__(self, session)
1001 HelpableScreen.__init__(self)
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"))
1012 self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
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)),
1019 "ok": self.showEntry, }, - 2)
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"))]))
1034 self["statusbar"] = Label(_("Getting calls from FRITZ!Box..."))
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)
1047 def setWindowTitle(self):
1048 # TRANSLATORS: this is a window title.
1049 self.setTitle(_("Phone calls"))
1054 def display(self, which=None):
1055 debug("[FritzDisplayCalls] display")
1057 config.plugins.FritzCall.fbfCalls.value = which
1058 config.plugins.FritzCall.fbfCalls.save()
1060 which = config.plugins.FritzCall.fbfCalls.value
1061 fritzbox.getCalls(self, lambda x: self.gotCalls(x, which), which)
1063 def gotCalls(self, listOfCalls, which):
1064 debug("[FritzDisplayCalls] gotCalls")
1065 self.updateStatus(fbfCallsChoices[which] + " (" + str(len(listOfCalls)) + ")")
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"))
1071 if direct == FBF_OUT_CALLS:
1073 elif direct == FBF_IN_CALLS:
1076 direct = directfailed
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 #=======================================================================
1087 def updateStatus(self, text):
1088 if self.has_key("statusbar"):
1089 self["statusbar"].setText(_("Getting calls from FRITZ!Box...") + ' ' + text)
1091 def showEntry(self):
1092 debug("[FritzDisplayCalls] showEntry")
1093 cur = self["entries"].getCurrent()
1096 # debug("[FritzDisplayCalls] showEntry %s" % (cur[0]))
1098 fullname = phonebook.search(cur[0])
1100 # we have a name for this number
1102 self.session.open(FritzOfferAction, self, number, name)
1105 self.session.open(FritzOfferAction, self, number, name)
1108 fullname = resolveNumberWithAvon(number, config.plugins.FritzCall.country.value)
1111 self.session.open(FritzOfferAction, self, number, name)
1113 self.session.open(FritzOfferAction, self, number)
1115 # we do not even have a number...
1116 self.session.open(MessageBox,
1118 type=MessageBox.TYPE_INFO)
1121 class FritzOfferAction(Screen):
1123 def __init__(self, session, parent, number, name=""):
1124 # the layout will completely be recalculated in finishLayout
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" />
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",
1143 debug("[FritzOfferAction] init: %s, %s" %(__(number), __(name)))
1144 Screen.__init__(self, session)
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"))
1155 self["FritzOfferActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1157 "red": self._lookup,
1158 "green": self._call,
1159 "yellow": self._add,
1160 "cancel": self._exit,
1161 "ok": self._exit, }, - 2)
1163 self._session = session
1164 if config.plugins.FritzCall.internal.value and len(number) > 3 and number[0] == "0":
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)
1178 def setWindowTitle(self):
1179 # TRANSLATORS: this is a window title.
1180 self.setTitle(_("Do what?"))
1182 def _finishLayout(self):
1183 # pylint: disable=W0142
1184 debug("[FritzCall] FritzOfferAction/finishLayout number: %s/%s" % (__(self._number), __(self._name)))
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()
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)
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)
1212 self.instance.resize(wSize)
1214 self["text"].instance.resize(textSize)
1216 self["FacePixmap"].instance.resize(picSize)
1217 self["FacePixmap"].instance.setPixmap(picPixmap)
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))
1229 self["text"].instance.move(ePoint(*textPos))
1231 self["FacePixmap"].instance.move(ePoint(*picPos))
1233 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
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()
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)
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
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)
1261 self._lookupState = 0
1264 def _lookedUp(self, number, name):
1265 name = handleReverseLookupResult(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")
1272 name = _("No result from LDIF")
1274 self._number = number
1275 debug("[FritzOfferAction] lookedUp: " + str(name.replace(", ", "\n")))
1276 self._setTextAndResize(str(name.replace(", ", "\n")))
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)
1284 debug("[FritzOfferAction] call: no fritzbox object?!?!")
1285 self.session.open(MessageBox, _("FRITZ!Box not available for calling"), type=MessageBox.TYPE_INFO)
1288 debug("[FritzOfferAction] add: %s, %s" %(self._number, self._name))
1289 phonebook.FritzDisplayPhonebook(self._session).add(self._parent, self._number, self._name)
1295 OneHour = 60*60*1000
1297 class FritzCallPhonebook:
1299 debug("[FritzCallPhonebook] init")
1300 # Beware: strings in phonebook.phonebook have to be in utf-8!
1302 if config.plugins.FritzCall.reloadPhonebookTime.value > 0:
1303 debug("[FritzCallPhonebook] start timer with " + repr(config.plugins.FritzCall.reloadPhonebookTime.value))
1304 self.loop = eTimer()
1306 # newer OE versions don't have the callback
1308 self.loop_conn = self.loop.timeout.connect(self.reload)
1309 except AttributeError:
1310 self.loop.callback.append(self.reload)
1312 self.loop.start(config.plugins.FritzCall.reloadPhonebookTime.value*OneHour, False)
1316 debug("[FritzCallPhonebook] reload " + time.ctime())
1318 # Beware: strings in phonebook.phonebook have to be in utf-8!
1321 if not config.plugins.FritzCall.enable.value:
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
1329 for line in open(phonebookFilename):
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
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('#')
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
1351 debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1352 phonebookTxtCorrupt = True
1354 #===============================================================
1355 # found = re.match("^(\d+)#(.*)$", line)
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
1363 # debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1364 # phonebookTxtCorrupt = True
1365 #===============================================================
1367 if phonebookTxtCorrupt:
1368 # dump phonebook to PhoneBook.txt
1369 debug("[FritzCallPhonebook] dump Phonebook.txt")
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"))
1378 except (IOError, OSError):
1379 debug("[FritzCallPhonebook] error renaming or writing to %s" %phonebookFilename)
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)
1385 #===============================================================================
1387 # # read entries from Outlook export
1389 # # not reliable with coding yet
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):
1395 # readOutlookCSV(csvFilename, self.add)
1396 # os.rename(csvFilename, csvFilename + ".done")
1397 # except ImportError:
1398 # debug("[FritzCallPhonebook] CSV import failed" %line)
1399 #===============================================================================
1402 #===============================================================================
1404 # # read entries from LDIF
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):
1410 # parser = MyLDIF(open(ldifFilename), self.add)
1412 # os.rename(ldifFilename, ldifFilename + ".done")
1413 # except ImportError:
1414 # debug("[FritzCallPhonebook] LDIF import failed" %line)
1415 #===============================================================================
1417 def search(self, number, default=None, extended=True):
1418 # debug("[FritzCallPhonebook] Searching for %s" %number)
1420 if not self.phonebook or not number:
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)
1435 if not name and self.phonebook.has_key(number):
1436 name = self.phonebook[number]
1438 if not name and default:
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)
1446 # debug("[FritzCallPhonebook] search result for shortened number: %s" % name)
1449 return name.replace(", ", "\n").strip()
1451 def add(self, number, name):
1454 @param number: number of entry
1455 @param name: name of entry, has to be in utf-8
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
1460 self.phonebook[number] = name
1461 if number and number != 0:
1462 if config.plugins.FritzCall.phonebook.value:
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')
1470 debug("[FritzCallPhonebook] added %s with %s to Phonebook.txt" % (number, name.strip()))
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:
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()
1488 elems = line.split('#')
1489 if len(elems) == 2 and not elems[0] == number:
1491 line = fOld.readline()
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)
1500 except (IOError, OSError):
1501 debug("[FritzCallPhonebook] error removing %s from %s" %(number, phonebookFilename))
1504 class FritzDisplayPhonebook(Screen, HelpableScreen, NumericalTextInput):
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))
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">
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
1524 "fonts": [gFont("Regular", %d)],
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" />
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
1560 # debug("[FritzDisplayCalls] skin: " + self.skin)
1561 Screen.__init__(self, session)
1562 NumericalTextInput.__init__(self)
1563 HelpableScreen.__init__(self)
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"))
1574 self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1578 "yellow": self.edit,
1579 "blue": self.search,
1580 "cancel": self.exit,
1581 "ok": self.showEntry, }, - 2)
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)"))]))
1596 self["entries"] = List([])
1597 debug("[FritzDisplayPhonebook] displayPhonebook init")
1598 self.help_window = None
1600 self.onLayoutFinish.append(self.setWindowTitle)
1603 def setWindowTitle(self):
1604 # TRANSLATORS: this is a window title.
1605 self.setTitle(_("Phonebook"))
1607 def display(self, filterNumber=""):
1608 debug("[FritzDisplayPhonebook] displayPhonebook/display")
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":
1616 low = low.decode("utf-8")
1617 except UnicodeDecodeError: # this should definitely not happen
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)
1627 filterNumber = filterNumber.lower()
1628 if low.find(filterNumber) == - 1:
1630 name = name.strip().decode("utf-8")
1631 number = number.strip().decode("utf-8")
1632 comma = name.find(',')
1634 shortname = name[:comma]
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))
1642 self["entries"].setList(self.sortlist)
1644 def showEntry(self):
1645 cur = self["entries"].getCurrent()
1647 debug("[FritzDisplayPhonebook] displayPhonebook/showEntry %s" % (repr(cur)))
1650 self.session.open(FritzOfferAction, self, number, name)
1653 cur = self["entries"].getCurrent()
1655 debug("[FritzDisplayPhonebook] displayPhonebook/delete %s" % (repr(cur)))
1656 self.session.openWithCallback(
1657 self.deleteConfirmed,
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") }
1663 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1665 def deleteConfirmed(self, ret):
1666 debug("[FritzDisplayPhonebook] displayPhonebook/deleteConfirmed")
1668 # if ret: delete number from sortlist, delete number from phonebook.phonebook and write it to disk
1670 cur = self["entries"].getCurrent()
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])
1678 # self.session.open(MessageBox, _("Not deleted."), MessageBox.TYPE_INFO)
1680 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1682 def add(self, parent=None, number="", name=""):
1683 class AddScreen(Screen, ConfigListScreen):
1684 '''ConfiglistScreen with two ConfigTexts for Name and Number'''
1686 def __init__(self, session, parent, number="", name=""):
1688 # setup screen with two ConfigText and OK and ABORT button
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
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" />
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,
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"],
1719 "cancel": self.cancel,
1726 ConfigListScreen.__init__(self, self.list, session=session)
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)
1737 def setWindowTitle(self):
1738 # TRANSLATORS: this is a window title.
1739 self.setTitle(_("Add entry to phonebook"))
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)
1749 # add (number,name) to sortlist and phonebook.phonebook and disk
1750 # oldname = phonebook.search(self.number)
1752 # self.session.openWithCallback(
1753 # self.overwriteConfirmed,
1755 # _("Do you really want to overwrite entry for %(number)s\n\n%(name)s\n\nwith\n\n%(newname)s?")
1757 # 'number':self.number,
1759 # 'newname':self.name.replace(", ","\n")
1764 phonebook.add(self.number, self.name)
1766 self.parent.display()
1768 def overwriteConfirmed(self, ret):
1770 phonebook.remove(self.number)
1771 phonebook.add(self.number, self.name)
1772 self.parent.display()
1777 debug("[FritzDisplayPhonebook] displayPhonebook/add")
1780 self.session.open(AddScreen, parent, number, name)
1783 debug("[FritzDisplayPhonebook] displayPhonebook/edit")
1784 cur = self["entries"].getCurrent()
1786 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1788 self.add(self, cur[2], cur[0])
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"))
1797 def doSearch(self, 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)
1809 phonebook = FritzCallPhonebook()
1811 class FritzCallSetup(Screen, ConfigListScreen, HelpableScreen):
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)
1816 debug("[FritzCallSetup] width: " + str(self.width))
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" />
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
1859 Screen.__init__(self, session)
1860 HelpableScreen.__init__(self)
1861 self.session = session
1863 self["consideration"] = Label(_("You need to enable the monitoring on your FRITZ!Box by dialing #96*5*!"))
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"))
1880 self["setupActions"] = ActionMap(["ColorActions", "OkCancelActions", "MenuActions", "EPGSelectActions"],
1884 "yellow": self.displayCalls,
1885 "blue": self.displayPhonebook,
1886 "cancel": self.cancel,
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"))]))
1909 ConfigListScreen.__init__(self, self.list, session=session)
1911 # get new list of locations for PhoneBook.txt
1913 self.onLayoutFinish.append(self.setWindowTitle)
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] + ")")
1920 ConfigListScreen.keyLeft(self)
1924 ConfigListScreen.keyRight(self)
1927 def createSetup(self):
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))
1934 self.list.append(getConfigListEntry(_("Show after Standby"), config.plugins.FritzCall.afterStandby))
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))
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))
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))
1969 config.plugins.FritzCall.fritzphonebook.value = False
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))
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))
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))
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))
1990 self["config"].list = self.list
1991 self["config"].l.setList(self.list)
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)
1998 for x in self["config"].list:
2000 if config.plugins.FritzCall.phonebookLocation.isChanged() or config.plugins.FritzCall.reloadPhonebookTime.isChanged():
2004 if config.plugins.FritzCall.enable.value:
2005 fritz_call.connect()
2007 fritz_call.shutdown()
2010 def LocationBoxClosed(self, path):
2011 if path is not None:
2012 config.plugins.FritzCall.phonebookLocation.setValue(path)
2015 # debug("[FritzCallSetup] cancel"
2016 for x in self["config"].list:
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)
2025 self.session.open(MessageBox, _("Cannot get calls from FRITZ!Box"), type=MessageBox.TYPE_INFO)
2027 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2029 def displayPhonebook(self):
2031 if config.plugins.FritzCall.enable.value:
2032 self.session.open(phonebook.FritzDisplayPhonebook)
2034 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2036 self.session.open(MessageBox, _("No phonebook"), type=MessageBox.TYPE_INFO)
2039 self.session.open(FritzAbout)
2042 if config.plugins.FritzCall.enable.value:
2043 if fritzbox and fritzbox.info:
2044 self.session.open(FritzMenu)
2046 self.session.open(MessageBox, _("Cannot get infos from FRITZ!Box yet\nStill initialising or wrong firmware version"), type=MessageBox.TYPE_INFO)
2048 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2052 class FritzCallList:
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]
2063 self.callList.append((event, number, date, caller, phone))
2066 debug("[FritzCallList] display")
2069 # Standby.inStandby.onClose.remove(self.display) object does not exist anymore...
2070 # build screen from call list
2073 if not self.callList:
2074 text = _("no calls")
2076 if self.callList[0] == "Start":
2077 text = text + _("Last 10 calls:\n")
2078 del self.callList[0]
2080 for call in self.callList:
2081 (event, number, date, caller, phone) = call
2087 # shorten the date info
2088 date = date[:6] + date[9:14]
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]
2096 # should not happen, for safety reasons
2098 caller = _("UNKNOWN")
2100 # if we have an unknown number, show the number
2101 if caller == _("UNKNOWN") and number != "":
2104 # strip off the address part of the remote caller/callee, if there is any
2105 nl = caller.find('\n')
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
2115 while (len(caller) + len(phone)) > 40:
2116 if len(caller) > len(phone):
2117 caller = caller[: - 1]
2119 phone = phone[: - 1]
2121 text = text + "%s %s %s %s\n" % (date, caller, direction, phone)
2122 debug("[FritzCallList] display: '%s %s %s %s'" % (date, caller, direction, phone))
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)
2130 callList = FritzCallList()
2132 def findFace(number, name):
2133 # debug("[FritzCall] findFace number/name: %s/%s" % (number, name))
2135 sep = name.find(',')
2138 sep = name.find('\n')
2143 # debug("[FritzCall] findFace looking for: %s" %name)
2145 facesDir = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "FritzCallFaces")
2146 # debug("[FritzCall] findFace looking in: %s" %facesDir)
2149 if not os.path.isdir(facesDir):
2150 debug("[FritzCall] findFace facesdir does not exist: %s" %facesDir)
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)]
2157 myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2160 sep = name.find(' (')
2163 myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2166 # debug("[FritzCall] findFace found: %s" %repr(myFiles))
2167 facesFile = os.path.join(facesDir, myFiles[0])
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)]
2174 facesFile = os.path.join(facesDir, myFiles[0])
2178 facesFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
2180 debug("[FritzCall] findFace result: %s" % (__(facesFile)))
2183 class MessageBoxPixmap(Screen):
2184 def __init__(self, session, text, number = "", name = "", timeout = -1):
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" />
2191 # scaleH(350, 60), scaleV(175, 245),
2192 scaleV(25, 22), resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
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
2202 self._timerRunning = False
2204 self._timeout = timeout
2205 self._origTitle = None
2207 self.onLayoutFinish.append(self._finishLayout)
2208 self["actions"] = ActionMap(["OkCancelActions"],
2210 "cancel": self._exit,
2211 "ok": self._exit, }, - 2)
2213 def _finishLayout(self):
2214 # pylint: disable=W0142
2215 debug("[FritzCall] MessageBoxPixmap/setInfoPixmap number: %s/%s" % (self._number, self._name))
2217 self.setTitle(_("New call"))
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()
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)
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)
2241 self.instance.resize(wSize)
2243 self["text"].instance.resize(textSize)
2245 self["InfoPixmap"].instance.resize(picSize)
2246 self["InfoPixmap"].instance.setPixmap(picPixmap)
2248 self["text"].instance.move(ePoint(*textPos))
2250 self["InfoPixmap"].instance.move(ePoint(*picPos))
2252 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
2254 def _initTimeout(self):
2255 if self._timeout > 0:
2256 self._timer = eTimer()
2258 # newer OE versions don't have the callback
2260 self._timer_conn = self._timer.timeout.connect(self._timerTick)
2261 except AttributeError:
2262 self._timer.callback.append(self._timerTick)
2264 self.onExecBegin.append(self._startTimer)
2265 self._origTitle = None
2269 self.onShown.append(self.__onShown)
2270 self._timerRunning = True
2272 self._timerRunning = False
2274 def __onShown(self):
2275 self.onShown.remove(self.__onShown)
2278 def _startTimer(self):
2279 self._timer.start(1000)
2281 #===============================================================================
2282 # def stopTimer(self):
2283 # if self._timerRunning:
2285 # self.setTitle(self._origTitle)
2286 # self._timerRunning = False
2287 #===============================================================================
2289 def _timerTick(self):
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:
2297 self._timerRunning = False
2303 def runUserActionScript(event, date, number, caller, phone):
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)
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
2324 # def FritzCallEvent(event,date,number,caller,phone):
2328 # from Plugins.Extensions.FritzCall.plugin import registerUserAction as FritzCallRegisterUserAction
2329 # FritzCallRegisterUserAction(FritzCallEvent)
2331 # print "import of FritzCall failed"
2332 #===========================================================================
2333 debug("[FritzCall] registerUserAction: register: %s" % fun.__name__)
2334 userActionList.append(fun)
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":
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 }
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":
2355 # if not yet done, register function to show call list
2357 if not standbyMode :
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")
2366 for fun in userActionList:
2367 debug("[FritzCall] notifyCall: call user action: %s" % fun.__name__)
2368 fun(event, date, number, caller, phone)
2371 #===============================================================================
2372 # We need a separate class for each invocation of reverseLookup to retain
2373 # the necessary data for the notification
2374 #===============================================================================
2377 reverselookupMtime = 0
2379 class FritzReverseLookupAndNotifier:
2380 def __init__(self, event, number, caller, phone, date, connID):
2383 Initiate a reverse lookup for the given number in the configured country
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
2391 debug("[FritzReverseLookupAndNotifier] reverse Lookup for %s!" % number)
2393 self.number = number
2394 self.caller = caller
2397 self.connID = connID
2399 if number[0] != "0":
2400 self.notifyAndReset(number, caller)