1 # -*- coding: utf-8 -*-
6 $Date: 2015-11-17 19:36:24 +0100 (Tue, 17 Nov 2015) $
7 $Id: plugin.py 1249 2015-11-17 18:36:24Z michael $
10 # C0111 (Missing docstring)
11 # C0103 (Invalid name)
12 # C0301 (line too long)
13 # W0603 (global statement)
14 # W0141 (map, filter, etc.)
15 # W0110 lambda with map,filter
16 # W0403 Relative import
17 # W1401 Anomalous backslash in string
19 # pylint: disable=C0111,C0103,C0301,W0603,W0141,W0403
21 from Screens.Screen import Screen
22 from Screens.MessageBox import MessageBox
23 from Screens.NumericalTextInputHelpDialog import NumericalTextInputHelpDialog
24 from Screens.InputBox import InputBox
25 from Screens import Standby
26 from Screens.HelpMenu import HelpableScreen
27 from Screens.LocationBox import LocationBox
29 from enigma import eTimer, eSize, ePoint #@UnresolvedImport # pylint: disable=E0611
30 from enigma import eDVBVolumecontrol, eConsoleAppContainer, eBackgroundFileEraser #@UnresolvedImport # pylint: disable=E0611
31 #BgFileEraser = eBackgroundFileEraser.getInstance()
32 #BgFileEraser.erase("blabla.txt")
34 from Components.ActionMap import ActionMap
35 from Components.Label import Label
36 from Components.Button import Button
37 from Components.Pixmap import Pixmap
38 from Components.Sources.List import List
39 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigDirectory, ConfigOnOff, getConfigListEntry, ConfigText, ConfigInteger
40 from Components.ConfigList import ConfigListScreen
42 from Components.config import ConfigPassword
44 ConfigPassword = ConfigText
46 from Plugins.Plugin import PluginDescriptor
47 from Tools import Notifications
48 from Tools.NumericalTextInput import NumericalTextInput
49 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_CONFIG
50 from Tools.LoadPixmap import LoadPixmap
51 from GlobalActions import globalActionMap # for muting
53 from twisted.internet import reactor #@UnresolvedImport
54 from twisted.internet.protocol import ReconnectingClientFactory #@UnresolvedImport
55 from twisted.protocols.basic import LineReceiver #@UnresolvedImport
57 import re, time, os, traceback
59 from nrzuname import ReverseLookupAndNotifier
60 import FritzOutlookCSV, FritzLDIF
61 from . import _, __, initDebug #@UnresolvedImport # pylint: disable=W0611,F0401
64 logger = logging.getLogger("[FritzCall]")
69 exception = logger.exception
71 from enigma import getDesktop
72 DESKTOP_WIDTH = getDesktop(0).size().width()
73 DESKTOP_HEIGHT = getDesktop(0).size().height()
77 # It returns the first value, if HD (1280x720),
78 # the second if SD (720x576),
79 # else something scaled accordingly
80 # if one of the parameters is -1, scale proportionally
87 return scale(y2, y1, 1280, 720, DESKTOP_WIDTH)
93 return scale(y2, y1, 720, 576, DESKTOP_HEIGHT)
94 def scale(y2, y1, x2, x1, x):
95 return (y2 - y1) * (x - x1) / (x2 - x1) + y1
97 my_global_session = None
101 config.plugins.FritzCall = ConfigSubsection()
102 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)
103 #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)
104 config.plugins.FritzCall.debug = ConfigOnOff(default=False)
105 #config.plugins.FritzCall.muteOnCall = ConfigSelection(choices=[(None, _("no")), ("ring", _("on ring")), ("connect", _("on connect"))])
106 #config.plugins.FritzCall.muteOnCall = ConfigSelection(choices=[(None, _("no")), ("ring", _("on ring"))])
107 config.plugins.FritzCall.muteOnCall = ConfigOnOff(default=False)
108 config.plugins.FritzCall.hostname = ConfigText(default="fritz.box", fixed_size=False)
109 config.plugins.FritzCall.afterStandby = ConfigSelection(choices=[("none", _("show nothing")), ("inList", _("show as list")), ("each", _("show each call"))])
110 config.plugins.FritzCall.filter = ConfigOnOff(default=False)
111 config.plugins.FritzCall.filtermsn = ConfigText(default="", fixed_size=False)
112 config.plugins.FritzCall.filtermsn.setUseableChars('0123456789,')
113 config.plugins.FritzCall.filterCallList = ConfigOnOff(default=True)
114 config.plugins.FritzCall.showBlacklistedCalls = ConfigOnOff(default=False)
115 config.plugins.FritzCall.showOutgoingCalls = ConfigOnOff(default=False)
116 config.plugins.FritzCall.timeout = ConfigInteger(default=15, limits=(0, 60))
117 config.plugins.FritzCall.lookup = ConfigOnOff(default=False)
118 config.plugins.FritzCall.internal = ConfigOnOff(default=False)
119 config.plugins.FritzCall.fritzphonebook = ConfigOnOff(default=False)
120 config.plugins.FritzCall.fritzphonebookName = ConfigText(default='Dreambox', fixed_size=False)
121 config.plugins.FritzCall.phonebook = ConfigOnOff(default=False)
122 config.plugins.FritzCall.addcallers = ConfigOnOff(default=False)
123 config.plugins.FritzCall.enable = ConfigOnOff(default=False)
124 config.plugins.FritzCall.username = ConfigText(default='BoxAdmin', fixed_size=False)
125 config.plugins.FritzCall.password = ConfigPassword(default="", fixed_size=False)
126 config.plugins.FritzCall.extension = ConfigText(default='1', fixed_size=False)
127 config.plugins.FritzCall.extension.setUseableChars('0123456789')
128 config.plugins.FritzCall.showType = ConfigOnOff(default=True)
129 config.plugins.FritzCall.showShortcut = ConfigOnOff(default=False)
130 config.plugins.FritzCall.showVanity = ConfigOnOff(default=False)
131 config.plugins.FritzCall.prefix = ConfigText(default="", fixed_size=False)
132 config.plugins.FritzCall.prefix.setUseableChars('0123456789')
133 config.plugins.FritzCall.connectionVerbose = ConfigOnOff(default=True)
134 config.plugins.FritzCall.ignoreUnknown = ConfigOnOff(default=False)
135 config.plugins.FritzCall.reloadPhonebookTime = ConfigInteger(default=8, limits=(0, 99))
136 config.plugins.FritzCall.FritzExtendedSearchFaces = ConfigOnOff(default=False)
137 config.plugins.FritzCall.FritzExtendedSearchNames = ConfigOnOff(default=False)
138 config.plugins.FritzCall.phonebookLocation = ConfigDirectory(default = resolveFilename(SCOPE_CONFIG))
139 config.plugins.FritzCall.guestSSID = ConfigText(default="FRITZ!Box Gastzugang", fixed_size=False)
140 config.plugins.FritzCall.guestSecure = ConfigOnOff(default=True)
141 config.plugins.FritzCall.guestPassword = ConfigText(default="guestguest!!!", fixed_size=False)
143 guestWLANUptime = [(None, _('Not deactivating after time')), "15", "30", "45", "60", "90", "120", "180", "240", "300", "360", "480", "600", "720", "900", "1080", "1260"]
144 config.plugins.FritzCall.guestUptime = ConfigSelection(choices=guestWLANUptime, default="30")
147 ("0049", _("Germany")),
148 ("0031", _("The Netherlands")),
149 ("0033", _("France")),
150 ("0039", _("Italy")),
151 ("0041", _("Switzerland")),
152 ("0043", _("Austria")),
155 config.plugins.FritzCall.country = ConfigSelection(choices=countryCodes)
159 FBF_MISSED_CALLS = "2"
161 fbfCallsChoices = {FBF_ALL_CALLS: _("All calls"),
162 FBF_IN_CALLS: _("Incoming calls"),
163 FBF_MISSED_CALLS: _("Missed calls"),
164 FBF_OUT_CALLS: _("Outgoing calls")
166 config.plugins.FritzCall.fbfCalls = ConfigSelection(choices=fbfCallsChoices)
168 config.plugins.FritzCall.name = ConfigText(default="", fixed_size=False)
169 config.plugins.FritzCall.number = ConfigText(default="", fixed_size=False)
170 config.plugins.FritzCall.number.setUseableChars('0123456789')
178 avonFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/avon.dat")
179 if os.path.exists(avonFileName):
180 for line in open(avonFileName):
181 line = line.decode("iso-8859-1").encode('utf-8')
184 parts = line.split(':')
186 avon[parts[0].replace('-','').replace('*','').replace('/','')] = parts[1]
188 def resolveNumberWithAvon(number, countrycode):
189 if not number or number[0] != '0':
192 countrycode = countrycode.replace('00','+')
193 if number[:2] == '00':
194 normNumber = '+' + number[2:]
195 elif number[:1] == '0':
196 normNumber = countrycode + number[1:]
197 else: # this should can not happen, but safety first
200 # debug('normNumer: ' + normNumber)
201 for i in reversed(range(min(10, len(number)))):
202 if avon.has_key(normNumber[:i]):
203 return '[' + avon[normNumber[:i]].strip() + ']'
206 def handleReverseLookupResult(name):
207 found = re.match("NA: ([^;]*);VN: ([^;]*);STR: ([^;]*);HNR: ([^;]*);PLZ: ([^;]*);ORT: ([^;]*)", name)
209 ( name, firstname, street, streetno, zipcode, city ) = (found.group(1),
217 name += ' ' + firstname
218 if street or streetno or zipcode or city:
223 name += ' ' + streetno
224 if (street or streetno) and (zipcode or city):
227 name += zipcode + ' ' + city
234 from xml.dom.minidom import parse
237 callbycallFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/callbycall_world.xml")
238 if os.path.exists(callbycallFileName):
239 dom = parse(callbycallFileName)
240 for top in dom.getElementsByTagName("callbycalls"):
241 for cbc in top.getElementsByTagName("country"):
242 code = cbc.getAttribute("code").replace("+","00")
243 cbcInfos[code] = cbc.getElementsByTagName("callbycall")
245 error("[FritzCall] initCbC: callbycallFileName does not exist?!?!")
247 def stripCbCPrefix(number, countrycode):
248 if number and number[:2] != "00" and cbcInfos.has_key(countrycode):
249 for cbc in cbcInfos[countrycode]:
250 if len(cbc.getElementsByTagName("length"))<1 or len(cbc.getElementsByTagName("prefix"))<1:
251 warn("[FritzCall] stripCbCPrefix: entries for " + countrycode + " %s invalid")
253 length = int(cbc.getElementsByTagName("length")[0].childNodes[0].data)
254 prefix = cbc.getElementsByTagName("prefix")[0].childNodes[0].data
255 # if re.match('^'+prefix, number):
256 if number[:len(prefix)] == prefix:
257 return number[length:]
262 class FritzAbout(Screen):
264 def __init__(self, session):
265 textFieldWidth = scaleV(350, 250)
266 width = 5 + 150 + 20 + textFieldWidth + 5 + 175 + 5
267 height = 5 + 175 + 5 + 25 + 5
269 <screen name="FritzAbout" position="center,center" size="%d,%d" title="About FritzCall" >
270 <widget name="text" position="175,%d" size="%d,%d" font="Regular;%d" />
271 <ePixmap position="5,37" size="150,110" pixmap="%s" transparent="1" alphatest="blend" />
272 <ePixmap position="%d,5" size="175,175" pixmap="%s" transparent="1" alphatest="blend" />
273 <widget name="url" position="20,185" size="%d,25" font="Regular;%d" />
275 width, height, # size
276 (height-scaleV(150,130)) / 2, # text vertical position
278 scaleV(150,130), # text height
279 scaleV(24,21), # text font size
280 resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/fritz.png"), # 150x110
281 5 + 150 + 5 + textFieldWidth + 5, # qr code horizontal offset
282 resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/website.png"), # 175x175
283 width-40, # url width
284 scaleV(24,21) # url font size
286 Screen.__init__(self, session)
287 self["aboutActions"] = ActionMap(["OkCancelActions"],
292 self["text"] = Label(
293 "FritzCall Plugin" + "\n\n" +
294 "$Author: michael $"[1:-2] + "\n" +
295 "$Revision: 1249 $"[1:-2] + "\n" +
296 "$Date: 2015-11-17 19:36:24 +0100 (Tue, 17 Nov 2015) $"[1:23] + "\n"
298 self["url"] = Label("http://wiki.blue-panel.com/index.php/FritzCall")
299 self.onLayoutFinish.append(self.setWindowTitle)
301 def setWindowTitle(self):
302 # TRANSLATORS: this is a window title.
303 self.setTitle(_("About FritzCall"))
308 from FritzCallFBF import FBF_dectActive, FBF_faxActive, FBF_rufumlActive, FBF_tamActive, FBF_wlanState
309 class FritzMenu(Screen, HelpableScreen):
310 def __init__(self, session):
311 if not fritzbox or not fritzbox.information:
314 if config.plugins.FritzCall.fwVersion.value == "old" or config.plugins.FritzCall.fwVersion.value == "05.27":
315 fontSize = scaleV(24, 21) # indeed this is font size +2
316 noButtons = 2 # reset, wlan
318 if fritzbox.information[FBF_tamActive]:
319 noButtons += 1 # toggle mailboxes
320 width = max(DESKTOP_WIDTH - scaleH(500, 250), noButtons*140+(noButtons+1)*10)
321 # boxInfo 2 lines, gap, internet 2 lines, gap, dsl/wlan each 1 line, gap, buttons
322 height = 5 + 2*fontSize + 10 + 2*fontSize + 10 + 2*fontSize + 10 + 40 + 5
323 if fritzbox.information[FBF_tamActive] is not None:
325 if fritzbox.information[FBF_dectActive] is not None:
327 if fritzbox.information[FBF_faxActive] is not None:
329 if fritzbox.information[FBF_rufumlActive] is not None:
331 buttonsGap = (width-noButtons*140)/(noButtons+1)
332 buttonsVPos = height-40-5
335 if fritzbox.information[FBF_tamActive] is not None:
337 <widget name="FBFMailbox" position="%d,%d" size="%d,%d" font="Regular;%d" />
338 <widget name="mailbox_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
339 <widget name="mailbox_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
340 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
341 <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
343 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position mailbox
344 width-40-20, fontSize, # size mailbox
346 "skin_default/buttons/button_green_off.png",
347 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button mailbox
348 "skin_default/buttons/button_green.png",
349 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button mailbox
350 noButtons*buttonsGap+(noButtons-1)*140, buttonsVPos,
351 noButtons*buttonsGap+(noButtons-1)*140, buttonsVPos,
357 if fritzbox.information[FBF_dectActive] is not None:
359 <widget name="FBFDect" position="%d,%d" size="%d,%d" font="Regular;%d" />
360 <widget name="dect_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
361 <widget name="dect_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
363 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
364 width-40-20, fontSize, # size dect
366 "skin_default/buttons/button_green_off.png",
367 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
368 "skin_default/buttons/button_green.png",
369 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
375 if fritzbox.information[FBF_faxActive] is not None:
377 <widget name="FBFFax" position="%d,%d" size="%d,%d" font="Regular;%d" />
378 <widget name="fax_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
379 <widget name="fax_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
381 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
382 width-40-20, fontSize, # size dect
384 "skin_default/buttons/button_green_off.png",
385 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
386 "skin_default/buttons/button_green.png",
387 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
393 if fritzbox.information[FBF_rufumlActive] is not None:
395 <widget name="FBFRufuml" position="%d,%d" size="%d,%d" font="Regular;%d" />
396 <widget name="rufuml_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
397 <widget name="rufuml_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
399 40, 5+2*fontSize+10+varLinePos*fontSize+10, # position dect
400 width-40-20, fontSize, # size dect
402 "skin_default/buttons/button_green_off.png",
403 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
404 "skin_default/buttons/button_green.png",
405 20, 5+2*fontSize+10+varLinePos*fontSize+10+(fontSize-16)/2, # position button dect
412 <screen name="FritzMenu" position="center,center" size="%d,%d" title="FRITZ!Box Fon Status" >
413 <widget name="FBFInfo" position="%d,%d" size="%d,%d" font="Regular;%d" />
414 <widget name="FBFInternet" position="%d,%d" size="%d,%d" font="Regular;%d" />
415 <widget name="internet_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
416 <widget name="internet_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
417 <widget name="FBFDsl" position="%d,%d" size="%d,%d" font="Regular;%d" />
418 <widget name="dsl_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
419 <widget name="dsl_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
420 <widget name="FBFWlan" position="%d,%d" size="%d,%d" font="Regular;%d" />
421 <widget name="wlan_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
422 <widget name="wlan_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
427 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
428 <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" />
429 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
430 <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
432 width, height, # size
433 40, 5, # position information
434 width-2*40, 2*fontSize, # size information
436 40, 5+2*fontSize+10, # position internet
437 width-40, 2*fontSize, # size internet
439 "skin_default/buttons/button_green_off.png",
440 20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
441 "skin_default/buttons/button_green.png",
442 20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
443 40, 5+2*fontSize+10+2*fontSize+10, # position dsl
444 width-40-20, fontSize, # size dsl
446 "skin_default/buttons/button_green_off.png",
447 20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
448 "skin_default/buttons/button_green.png",
449 20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
450 40, 5+2*fontSize+10+3*fontSize+10, # position wlan
451 width-40-20, fontSize, # size wlan
453 "skin_default/buttons/button_green_off.png",
454 20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
455 "skin_default/buttons/button_green.png",
456 20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
461 buttonsGap, buttonsVPos, "skin_default/buttons/red.png", buttonsGap, buttonsVPos,
462 buttonsGap+140+buttonsGap, buttonsVPos, "skin_default/buttons/green.png", buttonsGap+140+buttonsGap, buttonsVPos,
465 Screen.__init__(self, session)
466 HelpableScreen.__init__(self)
467 # TRANSLATORS: keep it short, this is a button
468 self["key_red"] = Button(_("Reset"))
469 # TRANSLATORS: keep it short, this is a button
470 self["key_green"] = Button(_("Toggle WLAN"))
471 self._mailboxActive = False
472 if fritzbox.information[FBF_tamActive] is not None:
473 # TRANSLATORS: keep it short, this is a button
474 self["key_yellow"] = Button(_("Toggle Mailbox"))
475 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "NumberActions", "EPGSelectActions"],
477 "cancel": self._exit,
480 "green": self._toggleWlan,
481 "yellow": (lambda: self._toggleMailbox(-1)),
482 "0": (lambda: self._toggleMailbox(0)),
483 "1": (lambda: self._toggleMailbox(1)),
484 "2": (lambda: self._toggleMailbox(2)),
485 "3": (lambda: self._toggleMailbox(3)),
486 "4": (lambda: self._toggleMailbox(4)),
487 "info": self._getInfo,
489 # TRANSLATORS: keep it short, this is a help text
490 self.helpList.append((self["menuActions"], "ColorActions", [("yellow", _("Toggle all mailboxes"))]))
491 # TRANSLATORS: keep it short, this is a help text
492 self.helpList.append((self["menuActions"], "NumberActions", [("0", _("Toggle 1. mailbox"))]))
493 # TRANSLATORS: keep it short, this is a help text
494 self.helpList.append((self["menuActions"], "NumberActions", [("1", _("Toggle 2. mailbox"))]))
495 # TRANSLATORS: keep it short, this is a help text
496 self.helpList.append((self["menuActions"], "NumberActions", [("2", _("Toggle 3. mailbox"))]))
497 # TRANSLATORS: keep it short, this is a help text
498 self.helpList.append((self["menuActions"], "NumberActions", [("3", _("Toggle 4. mailbox"))]))
499 # TRANSLATORS: keep it short, this is a help text
500 self.helpList.append((self["menuActions"], "NumberActions", [("4", _("Toggle 5. mailbox"))]))
501 self["FBFMailbox"] = Label(_('Mailbox'))
502 self["mailbox_inactive"] = Pixmap()
503 self["mailbox_active"] = Pixmap()
504 self["mailbox_active"].hide()
506 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "EPGSelectActions"],
508 "cancel": self._exit,
510 "green": self._toggleWlan,
512 "info": self._getInfo,
515 # TRANSLATORS: keep it short, this is a help text
516 self.helpList.append((self["menuActions"], "OkCancelActions", [("cancel", _("Quit"))]))
517 # TRANSLATORS: keep it short, this is a help text
518 self.helpList.append((self["menuActions"], "OkCancelActions", [("ok", _("Quit"))]))
519 # TRANSLATORS: keep it short, this is a help text
520 self.helpList.append((self["menuActions"], "ColorActions", [("green", _("Toggle WLAN"))]))
521 # TRANSLATORS: keep it short, this is a help text
522 self.helpList.append((self["menuActions"], "ColorActions", [("red", _("Reset"))]))
523 # TRANSLATORS: keep it short, this is a help text
524 self.helpList.append((self["menuActions"], "EPGSelectActions", [("info", _("Refresh status"))]))
526 self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
528 self["FBFInternet"] = Label('Internet')
529 self["internet_inactive"] = Pixmap()
530 self["internet_active"] = Pixmap()
531 self["internet_active"].hide()
533 self["FBFDsl"] = Label('DSL')
534 self["dsl_inactive"] = Pixmap()
535 self["dsl_inactive"].hide()
536 self["dsl_active"] = Pixmap()
537 self["dsl_active"].hide()
539 self["FBFWlan"] = Label('WLAN ')
540 self["wlan_inactive"] = Pixmap()
541 self["wlan_inactive"].hide()
542 self["wlan_active"] = Pixmap()
543 self["wlan_active"].hide()
544 self._wlanActive = False
546 if fritzbox.information[FBF_dectActive] is not None:
547 self["FBFDect"] = Label('DECT')
548 self["dect_inactive"] = Pixmap()
549 self["dect_active"] = Pixmap()
550 self["dect_active"].hide()
552 if fritzbox.information[FBF_faxActive] is not None:
553 self["FBFFax"] = Label('Fax')
554 self["fax_inactive"] = Pixmap()
555 self["fax_active"] = Pixmap()
556 self["fax_active"].hide()
558 if fritzbox.information[FBF_rufumlActive] is not None:
559 self["FBFRufuml"] = Label(_('Call redirection'))
560 self["rufuml_inactive"] = Pixmap()
561 self["rufuml_active"] = Pixmap()
562 self["rufuml_active"].hide()
563 else: # not (config.plugins.FritzCall.fwVersion.value == "old" or config.plugins.FritzCall.fwVersion.value == "05.27")
564 fontSize = scaleV(24, 21) # indeed this is font size +2
567 width = max(DESKTOP_WIDTH - scaleH(500, 250), noButtons*140+(noButtons+1)*10)
568 # boxInfo 2 lines, gap, internet 2 lines, gap, dsl/wlan/dect/fax/rufuml/gast each 1 line, gap
569 height = 5 + 2*fontSize + 10 + 2*fontSize + 10 + 6*fontSize + 10 + 40 + 5
570 buttonsGap = (width-noButtons*140)/(noButtons+1)
571 buttonsVPos = height-40-5
574 <screen name="FritzMenuNew" position="center,center" size="%d,%d" title="FRITZ!Box Fon Status" >
575 <widget name="FBFInfo" position="%d,%d" size="%d,%d" font="Regular;%d" />
576 <widget name="FBFInternet" position="%d,%d" size="%d,%d" font="Regular;%d" />
577 <widget name="internet_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
578 <widget name="internet_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
579 <widget name="FBFDsl" position="%d,%d" size="%d,%d" font="Regular;%d" />
580 <widget name="dsl_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
581 <widget name="dsl_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
582 <widget name="FBFWlan" position="%d,%d" size="%d,%d" font="Regular;%d" />
583 <widget name="wlan_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
584 <widget name="wlan_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
585 <widget name="FBFDect" position="%d,%d" size="%d,%d" font="Regular;%d" />
586 <widget name="dect_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
587 <widget name="dect_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
588 <widget name="FBFFax" position="%d,%d" size="%d,%d" font="Regular;%d" />
589 <widget name="fax_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
590 <widget name="fax_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
591 <widget name="FBFRufuml" position="%d,%d" size="%d,%d" font="Regular;%d" />
592 <widget name="rufuml_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
593 <widget name="rufuml_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
594 <widget name="FBFGast" position="%d,%d" size="%d,%d" font="Regular;%d" />
595 <widget name="gast_inactive" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
596 <widget name="gast_active" pixmap="%s" position="%d,%d" size="15,16" transparent="1" alphatest="on"/>
597 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
598 <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" />
599 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
600 <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;16" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
602 width, height, # size
603 40, 5, # position information
604 width-2*40, 2*fontSize, # size information
606 40, 5+2*fontSize+10, # position internet
607 width-40, 2*fontSize, # size internet
609 "skin_default/buttons/button_green_off.png",
610 20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
611 "skin_default/buttons/button_green.png",
612 20, 5+2*fontSize+10+(fontSize-16)/2, # position button internet
613 40, 5+2*fontSize+10+2*fontSize+10, # position dsl
614 width-40-20, fontSize, # size dsl
616 "skin_default/buttons/button_green_off.png",
617 20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
618 "skin_default/buttons/button_green.png",
619 20, 5+2*fontSize+10+2*fontSize+10+(fontSize-16)/2, # position button dsl
620 40, 5+2*fontSize+10+3*fontSize+10, # position wlan
621 width-40-20, fontSize, # size wlan
623 "skin_default/buttons/button_green_off.png",
624 20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
625 "skin_default/buttons/button_green.png",
626 20, 5+2*fontSize+10+3*fontSize+10+(fontSize-16)/2, # position button wlan
627 40, 5+2*fontSize+10+4*fontSize+10, # position dect
628 width-40-20, fontSize, # size dect
630 "skin_default/buttons/button_green_off.png",
631 20, 5+2*fontSize+10+4*fontSize+10+(fontSize-16)/2, # position button dect
632 "skin_default/buttons/button_green.png",
633 20, 5+2*fontSize+10+4*fontSize+10+(fontSize-16)/2, # position button dect
634 40, 5+2*fontSize+10+5*fontSize+10, # position fax
635 width-40-20, fontSize, # size fax
637 "skin_default/buttons/button_green_off.png",
638 20, 5+2*fontSize+10+5*fontSize+10+(fontSize-16)/2, # position button fax
639 "skin_default/buttons/button_green.png",
640 20, 5+2*fontSize+10+5*fontSize+10+(fontSize-16)/2, # position button fax
641 40, 5+2*fontSize+10+6*fontSize+10, # position rufuml
642 width-40-20, fontSize, # size rufuml
644 "skin_default/buttons/button_green_off.png",
645 20, 5+2*fontSize+10+6*fontSize+10+(fontSize-16)/2, # position button rufuml
646 "skin_default/buttons/button_green.png",
647 20, 5+2*fontSize+10+6*fontSize+10+(fontSize-16)/2, # position button rufuml
648 40, 5+2*fontSize+10+7*fontSize+10, # position gast
649 width-40-20, fontSize, # size gast
651 "skin_default/buttons/button_green_off.png",
652 20, 5+2*fontSize+10+7*fontSize+10+(fontSize-16)/2, # position button gast
653 "skin_default/buttons/button_green.png",
654 20, 5+2*fontSize+10+7*fontSize+10+(fontSize-16)/2, # position button gast
655 buttonsGap, buttonsVPos, "skin_default/buttons/green.png", buttonsGap, buttonsVPos,
656 2*buttonsGap+140, buttonsVPos, "skin_default/buttons/yellow.png", 2*buttonsGap+140, buttonsVPos,
659 Screen.__init__(self, session)
660 HelpableScreen.__init__(self)
661 # TRANSLATORS: keep it short, this is a button
662 self["menuActions"] = ActionMap(["OkCancelActions", "ColorActions", "EPGSelectActions"],
664 "cancel": self._exit,
666 "green": self._toggleWlan,
667 "yellow": self._toggleGast,
668 "red": self._reset, # no button, does not work
669 "info": self._getInfo,
672 # TRANSLATORS: keep it short, this is a help text
673 self.helpList.append((self["menuActions"], "OkCancelActions", [("cancel", _("Quit"))]))
674 # TRANSLATORS: keep it short, this is a help text
675 self.helpList.append((self["menuActions"], "OkCancelActions", [("ok", _("Quit"))]))
676 # TRANSLATORS: keep it short, this is a help text
677 self.helpList.append((self["menuActions"], "ColorActions", [("green", _("Toggle WLAN"))]))
678 # TRANSLATORS: keep it short, this is a help text
679 self.helpList.append((self["menuActions"], "ColorActions", [("yellow", _("Toggle WLAN guest access"))]))
680 # TRANSLATORS: keep it short, this is a help text
681 self.helpList.append((self["menuActions"], "ColorActions", [("red", _("Reset"))]))
682 # TRANSLATORS: keep it short, this is a help text
683 self.helpList.append((self["menuActions"], "EPGSelectActions", [("info", _("Refresh status"))]))
685 # TRANSLATORS: keep it short, this is a button
686 self["key_red"] = Button(_("Reset"))
687 # TRANSLATORS: keep it short, this is a button
688 self["key_green"] = Button(_("Toggle WLAN"))
689 # TRANSLATORS: keep it short, this is a button
690 self["key_yellow"] = Button(_("Activate WLAN guest access"))
692 self["FBFInfo"] = Label(_('Getting status from FRITZ!Box Fon...'))
694 self["FBFInternet"] = Label('Internet')
695 self["internet_inactive"] = Pixmap()
696 self["internet_inactive"].hide()
697 self["internet_active"] = Pixmap()
698 self["internet_active"].hide()
700 self["FBFDsl"] = Label('DSL')
701 self["dsl_inactive"] = Pixmap()
702 self["dsl_inactive"].hide()
703 self["dsl_active"] = Pixmap()
704 self["dsl_active"].hide()
706 self["FBFWlan"] = Label('WLAN ')
707 self["wlan_inactive"] = Pixmap()
708 self["wlan_inactive"].hide()
709 self["wlan_active"] = Pixmap()
710 self["wlan_active"].hide()
711 self._wlanActive = False
713 self["FBFDect"] = Label('DECT')
714 self["dect_inactive"] = Pixmap()
715 self["dect_inactive"].hide()
716 self["dect_active"] = Pixmap()
717 self["dect_active"].hide()
719 self["FBFFax"] = Label('Fax')
720 self["fax_inactive"] = Pixmap()
721 self["fax_inactive"].hide()
722 self["fax_active"] = Pixmap()
723 self["fax_active"].hide()
725 self["FBFRufuml"] = Label(_('Call redirection'))
726 self["rufuml_inactive"] = Pixmap()
727 self["rufuml_inactive"].hide()
728 self["rufuml_active"] = Pixmap()
729 self["rufuml_active"].hide()
731 self["FBFGast"] = Label(_('Guest access'))
732 self["gast_inactive"] = Pixmap()
733 self["gast_inactive"].hide()
734 self["gast_active"] = Pixmap()
735 self["gast_active"].hide()
736 self._guestActive = ""
739 self.onLayoutFinish.append(self.setWindowTitle)
741 def setWindowTitle(self):
742 # TRANSLATORS: this is a window title.
743 self.setTitle(_("FRITZ!Box Fon Status"))
747 fritzbox.getInfo(self._fillMenu)
748 self._fillMenu(fritzbox.information, True)
750 def _fillMenu(self, status, refreshing=False):
751 (boxInfo, upTime, ipAddress, wlanState, dslState, tamActive, dectActive, faxActive, rufumlActive, guestAccess) = status
753 self._wlanActive = (wlanState[0] == '1')
754 self._guestActive = guestAccess
755 self._mailboxActive = False
757 if not self.has_key("FBFInfo"): # screen is closed already
761 self["FBFInfo"].setText(_("Refreshing..."))
764 self["FBFInfo"].setText(boxInfo.replace(', ', '\n'))
766 self["FBFInfo"].setText('BoxInfo ' + _('Status not available'))
770 self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress + '\n' + _('Connected since') + ' ' + upTime)
772 self["FBFInternet"].setText('Internet ' + _('IP Address:') + ' ' + ipAddress)
773 self["internet_inactive"].hide()
774 self["internet_active"].show()
776 self["internet_active"].hide()
777 self["internet_inactive"].show()
780 if dslState[0] == '5':
781 self["dsl_inactive"].hide()
782 self["dsl_active"].show()
784 message = dslState[2]
788 message = message + ' ' + dslState[1]
789 self["FBFDsl"].setText(message)
791 self["dsl_active"].hide()
792 self["dsl_inactive"].show()
794 self["FBFDsl"].setText('DSL ' + _('Status not available'))
795 self["dsl_active"].hide()
796 self["dsl_inactive"].hide()
799 if wlanState[0 ] == '1':
800 self["wlan_inactive"].hide()
801 self["wlan_active"].show()
803 if wlanState[1] == '0':
804 message += ' ' + _('not encrypted')
805 elif wlanState[1] == '1':
806 message += ' ' + _('encrypted')
808 if wlanState[2] == '0':
809 message = message + ', ' + _('no device active')
810 elif wlanState[2] == '1' or wlanState[2] == 'ein':
811 message = message + ', ' + _('one device active')
813 message = message + ', ' + wlanState[2] + ' ' + _('devices active')
814 if len(wlanState) == 4:
815 message = message + ", " + wlanState[3]
816 self["FBFWlan"].setText(message)
818 self["wlan_active"].hide()
819 self["wlan_inactive"].show()
820 self["FBFWlan"].setText('WLAN')
822 self["FBFWlan"].setText('WLAN ' + _('Status not available'))
823 self["wlan_active"].hide()
824 self["wlan_inactive"].hide()
826 if fritzbox.information[FBF_tamActive]:
827 if not tamActive or tamActive[0] == 0:
828 self._mailboxActive = False
829 self["mailbox_active"].hide()
830 self["mailbox_inactive"].show()
831 self["FBFMailbox"].setText(_('No mailbox active'))
833 self._mailboxActive = True
835 for i in range(min(len(tamActive)-1, 5)):
837 message = message + str(i) + ','
839 message = '(' + message[:-1] + ')'
840 self["mailbox_inactive"].hide()
841 self["mailbox_active"].show()
842 if tamActive[0] == 1:
843 self["FBFMailbox"].setText(_('One mailbox active') + ' ' + message)
845 self["FBFMailbox"].setText(str(tamActive[0]) + ' ' + _('mailboxes active') + ' ' + message)
847 if dectActive and self.has_key("dect_inactive"):
848 self["dect_inactive"].hide()
849 self["dect_active"].show()
851 self["FBFDect"].setText(_('No DECT phone registered'))
853 if dectActive == "ein" or dectActive == "1" or dectActive == 1:
854 self["FBFDect"].setText(_('One DECT phone registered'))
856 self["FBFDect"].setText(str(dectActive) + ' ' + _('DECT phones registered'))
858 self["dect_active"].hide()
859 self["dect_inactive"].show()
860 self["FBFDect"].setText(_('DECT inactive'))
863 self["fax_inactive"].hide()
864 self["fax_active"].show()
865 self["FBFFax"].setText(_('Software fax active'))
867 self["fax_active"].hide()
868 self["fax_inactive"].show()
869 self["FBFFax"].setText(_('Software fax inactive'))
872 self["rufuml_inactive"].hide()
873 self["rufuml_active"].show()
874 if rufumlActive == -1: # means no number available
875 self["FBFRufuml"].setText(_('Call redirection active'))
876 elif rufumlActive == 1:
877 self["FBFRufuml"].setText(_('One call redirection active'))
879 self["FBFRufuml"].setText(str(rufumlActive) + ' ' + _('call redirections active'))
881 self["rufuml_active"].hide()
882 self["rufuml_inactive"].show()
883 self["FBFRufuml"].setText(_('No call redirection active'))
886 self["gast_inactive"].hide()
887 self["gast_active"].show()
888 self["FBFGast"].setText(_('Guest access on ') + guestAccess)
890 self["gast_active"].hide()
891 self["gast_inactive"].show()
892 self["FBFGast"].setText(_('Guest access not active'))
894 if guestAccess.find('WLAN') != -1:
895 # TRANSLATORS: keep it short, this is a button
896 self["key_yellow"].setText(_("Deactivate WLAN guest access"))
898 # TRANSLATORS: keep it short, this is a button
899 self["key_yellow"].setText(_("Activate WLAN guest access"))
903 error("[FritzCallFBF] _fillMenu: " + traceback.format_exc())
905 def _toggleWlan(self):
906 self["FBFInfo"].setText(_("Setting...") + " WLAN")
908 info("[FritzMenu] toggleWlan off")
909 fritzbox.changeWLAN('0', self._getInfo)
911 info("[FritzMenu] toggleWlan on")
912 fritzbox.changeWLAN('1', self._getInfo)
914 def _toggleMailbox(self, which):
916 if fritzbox.information[FBF_tamActive]:
917 info("[FritzMenu] toggleMailbox off")
918 fritzbox.changeMailbox(which, self._getInfo)
920 def _toggleGast(self):
921 self["FBFInfo"].setText(_("Setting...") + ' ' + _("Guest access"))
922 if fritzbox.information[FBF_wlanState][0] != '1':
923 # self["FBFInfo"].setText(_("WLAN not active"))
926 fritzbox.changeGuestAccess(self._guestActive, self._getInfo)
936 class FritzDisplayCalls(Screen, HelpableScreen):
938 def __init__(self, session, text=""): #@UnusedVariable # pylint: disable=W0613
939 self.width = DESKTOP_WIDTH * scaleH(75, 85)/100
940 self.height = DESKTOP_HEIGHT * 0.75
941 dateFieldWidth = scaleH(180, 105)
943 lengthFieldWidth = scaleH(55, 45)
944 scrollbarWidth = scaleH(35, 35)
945 entriesWidth = self.width -scaleH(40, 5) -5
946 hereFieldWidth = entriesWidth -dirFieldWidth -5 -dateFieldWidth -5 -lengthFieldWidth -scrollbarWidth
947 fieldWidth = entriesWidth -dirFieldWidth -5 -5 -scrollbarWidth
948 fontSize = scaleV(22, 20)
949 itemHeight = 2*fontSize+5
950 entriesHeight = self.height -scaleV(15, 10) -5 -fontSize -5 -5 -5 -40 -5
951 buttonGap = (self.width -4*140)/5
952 buttonV = self.height -40
953 debug("[FritzDisplayCalls] width: " + str(self.width))
955 <screen name="FritzDisplayCalls" position="center,center" size="%d,%d" title="Phone calls" >
956 <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
957 <widget name="statusbar" position="%d,%d" size="%d,%d" font="Regular;%d" backgroundColor="#aaaaaa" transparent="1" />
958 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
959 <widget source="entries" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" transparent="1">
960 <convert type="TemplatedMultiContent">
962 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
963 MultiContentEntryPixmapAlphaTest(pos = (%d,%d), size = (%d,%d), png = 2), # index 1 i direction pixmap
964 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 2 is remote name/number
965 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 3 is length of call
966 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text = 5), # index 4 is my number/name for number
968 "fonts": [gFont("Regular", %d), gFont("Regular", %d)],
973 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
974 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
975 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
976 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
977 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
978 <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" />
979 <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" />
980 <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" />
981 <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
983 # scaleH(90, 75), scaleV(100, 78), # position
984 self.width, self.height, # size
985 self.width, # eLabel width
986 scaleH(40, 5), scaleV(10, 5), # statusbar position
987 self.width, fontSize+5, # statusbar size
988 scaleV(21, 21), # statusbar font size
989 scaleV(10, 5)+5+fontSize+5, # eLabel position vertical
990 self.width, # eLabel width
991 scaleH(40, 5), scaleV(10, 5)+5+fontSize+5+5, # entries position
992 entriesWidth, entriesHeight, # entries size
993 5+dirFieldWidth+5, fontSize+5, dateFieldWidth, fontSize, # date pos/size
994 5, (itemHeight-dirFieldWidth)/2, dirFieldWidth, dirFieldWidth, # dir pos/size
995 5+dirFieldWidth+5, 5, fieldWidth, fontSize, # caller pos/size
996 2+dirFieldWidth+2+dateFieldWidth+5, fontSize+5, lengthFieldWidth, fontSize, # length pos/size
997 2+dirFieldWidth+2+dateFieldWidth+5+lengthFieldWidth+5, fontSize+5, hereFieldWidth, fontSize, # my number pos/size
998 fontSize-4, fontSize, # fontsize
999 itemHeight, # itemHeight
1000 buttonV-5, # eLabel position vertical
1001 self.width, # eLabel width
1002 buttonGap, buttonV, "skin_default/buttons/red.png", # widget red
1003 2*buttonGap+140, buttonV, "skin_default/buttons/green.png", # widget green
1004 3*buttonGap+2*140, buttonV, "skin_default/buttons/yellow.png", # widget yellow
1005 4*buttonGap+3*140, buttonV, "skin_default/buttons/blue.png", # widget blue
1006 buttonGap, buttonV, scaleV(22, 21), # widget red
1007 2*buttonGap+140, buttonV, scaleV(22, 21), # widget green
1008 3*buttonGap+2*140, buttonV, scaleV(22, 21), # widget yellow
1009 4*buttonGap+3*140, buttonV, scaleV(22, 21), # widget blue
1011 # debug("[FritzDisplayCalls] skin: " + self.skin)
1012 Screen.__init__(self, session)
1013 HelpableScreen.__init__(self)
1015 # TRANSLATORS: keep it short, this is a button
1016 self["key_yellow"] = Button(_("All"))
1017 # TRANSLATORS: keep it short, this is a button
1018 self["key_red"] = Button(_("Missed"))
1019 # TRANSLATORS: keep it short, this is a button
1020 self["key_blue"] = Button(_("Incoming"))
1021 # TRANSLATORS: keep it short, this is a button
1022 self["key_green"] = Button(_("Outgoing"))
1024 self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1026 "yellow": (lambda: self.display(FBF_ALL_CALLS)),
1027 "red": (lambda: self.display(FBF_MISSED_CALLS)),
1028 "blue": (lambda: self.display(FBF_IN_CALLS)),
1029 "green": (lambda: self.display(FBF_OUT_CALLS)),
1031 "ok": self.showEntry, }, - 2)
1033 # TRANSLATORS: keep it short, this is a help text
1034 self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("Show details of entry"))]))
1035 # TRANSLATORS: keep it short, this is a help text
1036 self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("Quit"))]))
1037 # TRANSLATORS: keep it short, this is a help text
1038 self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("Display all calls"))]))
1039 # TRANSLATORS: keep it short, this is a help text
1040 self.helpList.append((self["setupActions"], "ColorActions", [("red", _("Display missed calls"))]))
1041 # TRANSLATORS: keep it short, this is a help text
1042 self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("Display incoming calls"))]))
1043 # TRANSLATORS: keep it short, this is a help text
1044 self.helpList.append((self["setupActions"], "ColorActions", [("green", _("Display outgoing calls"))]))
1046 self["statusbar"] = Label(_("Getting calls from FRITZ!Box..."))
1048 self["entries"] = List(self.list)
1049 #=======================================================================
1050 # fontSize = scaleV(22, 18)
1051 # fontHeight = scaleV(24, 20)
1052 # self["entries"].l.setFont(0, gFont("Regular", fontSize))
1053 # self["entries"].l.setItemHeight(fontHeight)
1054 #=======================================================================
1055 debug("[FritzDisplayCalls] '''%s'''" % config.plugins.FritzCall.fbfCalls.value)
1056 self.display(config.plugins.FritzCall.fbfCalls.value)
1057 self.onLayoutFinish.append(self.setWindowTitle)
1059 def setWindowTitle(self):
1060 # TRANSLATORS: this is a window title.
1061 self.setTitle(_("Phone calls"))
1066 def display(self, which=None):
1067 debug("[FritzDisplayCalls]")
1069 config.plugins.FritzCall.fbfCalls.value = which
1070 config.plugins.FritzCall.fbfCalls.save()
1072 which = config.plugins.FritzCall.fbfCalls.value
1073 fritzbox.getCalls(self, lambda x: self.gotCalls(x, which), which)
1075 def gotCalls(self, listOfCalls, which):
1076 debug("[FritzDisplayCalls]")
1077 self.updateStatus(fbfCallsChoices[which] + " (" + str(len(listOfCalls)) + ")")
1079 directout = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callout.png"))
1080 directin = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callin.png"))
1081 directfailed = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/FritzCall/images/callinfailed.png"))
1083 if direct == FBF_OUT_CALLS:
1085 elif direct == FBF_IN_CALLS:
1088 direct = directfailed
1091 # debug("[FritzDisplayCalls] %s" %repr(listOfCalls))
1092 self.list = [(number, date[:6] + ' ' + date[9:14], pixDir(direct), remote, length, here) for (number, date, direct, remote, length, here) in listOfCalls]
1093 self["entries"].setList(self.list)
1094 #=======================================================================
1095 # if len(self.list) > 1:
1096 # self["entries"].setIndex(1)
1097 #=======================================================================
1099 def updateStatus(self, text):
1100 if self.has_key("statusbar"):
1101 self["statusbar"].setText(_("Getting calls from FRITZ!Box...") + ' ' + text)
1103 def showEntry(self):
1104 debug("[FritzDisplayCalls]")
1105 cur = self["entries"].getCurrent()
1108 # debug("[FritzDisplayCalls] %s" % (cur[0]))
1110 fullname = phonebook.search(cur[0])
1112 # we have a name for this number
1114 self.session.open(FritzOfferAction, self, number, name)
1117 self.session.open(FritzOfferAction, self, number, name)
1120 fullname = resolveNumberWithAvon(number, config.plugins.FritzCall.country.value)
1123 self.session.open(FritzOfferAction, self, number, name)
1125 self.session.open(FritzOfferAction, self, number)
1127 # we do not even have a number...
1128 self.session.open(MessageBox,
1130 type=MessageBox.TYPE_INFO)
1133 class FritzOfferAction(Screen):
1135 def __init__(self, session, parent, number, name=""):
1136 # the layout will completely be recalculated in finishLayout
1138 <screen name="FritzOfferAction" title="Do what?" >
1139 <widget name="text" size="%d,%d" font="Regular;%d" />
1140 <widget name="FacePixmap" size="%d,%d" alphatest="on" />
1141 <widget name="key_red_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1142 <widget name="key_green_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1143 <widget name="key_yellow_p" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1144 <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" />
1145 <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" />
1146 <widget name="key_yellow" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1148 DESKTOP_WIDTH, DESKTOP_HEIGHT, # set maximum size
1149 scaleV(25,22), # text
1150 DESKTOP_WIDTH, DESKTOP_HEIGHT, # set maximum size
1151 "skin_default/buttons/red.png",
1152 "skin_default/buttons/green.png",
1153 "skin_default/buttons/yellow.png",
1155 debug("[FritzOfferAction] %s, %s" %(__(number), __(name)))
1156 Screen.__init__(self, session)
1158 # TRANSLATORS: keep it short, this is a button
1159 self["key_red"] = Button(_("Lookup"))
1160 # TRANSLATORS: keep it short, this is a button
1161 self["key_green"] = Button(_("Call"))
1162 # TRANSLATORS: keep it short, this is a button
1163 self["key_yellow"] = Button(_("Save"))
1164 # TRANSLATORS: keep it short, this is a button
1165 # self["key_blue"] = Button(_("Search"))
1167 self["FritzOfferActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1169 "red": self._lookup,
1170 "green": self._call,
1171 "yellow": self._add,
1172 "cancel": self._exit,
1173 "ok": self._exit, }, - 2)
1175 self._session = session
1176 if config.plugins.FritzCall.internal.value and len(number) > 3 and number[0] == "0":
1178 self._number = number
1179 self._name = name.replace("\n", ", ")
1180 self["text"] = Label(number + "\n\n" + name.replace(", ", "\n"))
1181 self._parent = parent
1182 self._lookupState = 0
1183 self["key_red_p"] = Pixmap()
1184 self["key_green_p"] = Pixmap()
1185 self["key_yellow_p"] = Pixmap()
1186 self["FacePixmap"] = Pixmap()
1187 self.onLayoutFinish.append(self._finishLayout)
1188 self.onLayoutFinish.append(self.setWindowTitle)
1190 def setWindowTitle(self):
1191 # TRANSLATORS: this is a window title.
1192 self.setTitle(_("Do what?"))
1194 def _finishLayout(self):
1195 # pylint: disable=W0142
1196 debug("[FritzOfferAction] number: %s/%s" % (__(self._number), __(self._name)))
1198 faceFile = findFace(self._number, self._name)
1199 picPixmap = LoadPixmap(faceFile)
1200 if not picPixmap: # that means most probably, that the picture is not 8 bit...
1201 Notifications.AddNotification(MessageBox, _("Found picture\n\n%s\n\nBut did not load. Probably not PNG, 8-bit") %faceFile, type = MessageBox.TYPE_ERROR)
1202 picPixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_error.png"))
1203 picSize = picPixmap.size()
1206 # recalculate window size
1207 textSize = self["text"].getSize()
1208 textSize = (textSize[0]+20, textSize[1]+20) # don't know, why, but size is too small
1209 debug("[FritzOfferAction] textsize: %s/%s" % textSize)
1210 textSize = eSize(*textSize)
1211 width = max(scaleH(620, 545), noButtons*145, picSize.width() + textSize.width() + 30)
1212 height = max(picSize.height()+5, textSize.height()+5, scaleV(-1, 136)) + 5 + 40 + 5
1213 buttonsGap = (width-noButtons*140)/(noButtons+1)
1214 buttonsVPos = height-40-5
1215 wSize = (width, height)
1216 wSize = eSize(*wSize)
1218 # center the smaller vertically
1219 hGap = (width-picSize.width()-textSize.width())/3
1220 picPos = (hGap, (height-50-picSize.height())/2+5)
1221 textPos = (hGap+picSize.width()+hGap, (height-50-textSize.height())/2+5)
1224 self.instance.resize(wSize)
1226 self["text"].instance.resize(textSize)
1228 self["FacePixmap"].instance.resize(picSize)
1229 self["FacePixmap"].instance.setPixmap(picPixmap)
1231 buttonPos = (buttonsGap, buttonsVPos)
1232 self["key_red_p"].instance.move(ePoint(*buttonPos))
1233 self["key_red"].instance.move(ePoint(*buttonPos))
1234 buttonPos = (buttonsGap+140+buttonsGap, buttonsVPos)
1235 self["key_green_p"].instance.move(ePoint(*buttonPos))
1236 self["key_green"].instance.move(ePoint(*buttonPos))
1237 buttonPos = (buttonsGap+140+buttonsGap+140+buttonsGap, buttonsVPos)
1238 self["key_yellow_p"].instance.move(ePoint(*buttonPos))
1239 self["key_yellow"].instance.move(ePoint(*buttonPos))
1241 self["text"].instance.move(ePoint(*textPos))
1243 self["FacePixmap"].instance.move(ePoint(*picPos))
1245 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
1247 def _setTextAndResize(self, message):
1248 # pylint: disable=W0142
1249 self["text"].instance.resize(eSize(*(DESKTOP_WIDTH, DESKTOP_HEIGHT)))
1250 self["text"].setText(self._number + "\n\n" + message)
1251 self._finishLayout()
1254 phonebookLocation = config.plugins.FritzCall.phonebookLocation.value
1255 if self._lookupState == 0:
1256 self._lookupState = 1
1257 self._setTextAndResize(_("Reverse searching..."))
1258 ReverseLookupAndNotifier(self._number, self._lookedUp, "UTF-8", config.plugins.FritzCall.country.value)
1260 if self._lookupState == 1 and os.path.exists(os.path.join(phonebookLocation, "PhoneBook.csv")):
1261 self._setTextAndResize(_("Searching in Outlook export..."))
1262 self._lookupState = 2
1263 self._lookedUp(self._number, FritzOutlookCSV.findNumber(self._number, os.path.join(phonebookLocation, "PhoneBook.csv"))) #@UndefinedVariable
1266 self._lookupState = 2
1267 if self._lookupState == 2 and os.path.exists(os.path.join(phonebookLocation, "PhoneBook.ldif")):
1268 self._setTextAndResize(_("Searching in LDIF..."))
1269 self._lookupState = 0
1270 FritzLDIF.FindNumber(self._number, open(os.path.join(phonebookLocation, "PhoneBook.ldif")), self._lookedUp)
1273 self._lookupState = 0
1276 def _lookedUp(self, number, name):
1277 name = handleReverseLookupResult(name)
1279 if self._lookupState == 1:
1280 name = _("No result from reverse lookup")
1281 elif self._lookupState == 2:
1282 name = _("No result from Outlook export")
1284 name = _("No result from LDIF")
1286 self._number = number
1287 info("[FritzOfferAction] " + str(name.replace(", ", "\n")))
1288 self._setTextAndResize(str(name.replace(", ", "\n")))
1292 debug("[FritzOfferAction] %s" %self._number)
1293 self.session.open(MessageBox, _("Calling %s") %self._number, type=MessageBox.TYPE_INFO)
1294 fritzbox.dial(self._number)
1296 error("[FritzOfferAction] no fritzbox object?!?!")
1297 self.session.open(MessageBox, _("FRITZ!Box not available for calling"), type=MessageBox.TYPE_INFO)
1300 debug("[FritzOfferAction] %s, %s" %(self._number, self._name))
1301 phonebook.FritzDisplayPhonebook(self._session).add(self._parent, self._number, self._name)
1307 OneHour = 60*60*1000
1309 class FritzCallPhonebook:
1311 debug("[FritzCallPhonebook]")
1312 # Beware: strings in phonebook.phonebook have to be in utf-8!
1314 if config.plugins.FritzCall.reloadPhonebookTime.value > 0:
1315 debug("[FritzCallPhonebook] start timer with " + repr(config.plugins.FritzCall.reloadPhonebookTime.value))
1316 self.loop = eTimer()
1318 # newer OE versions don't have the callback
1320 self.loop_conn = self.loop.timeout.connect(self.reload)
1321 except AttributeError:
1322 self.loop.callback.append(self.reload)
1324 self.loop.start(config.plugins.FritzCall.reloadPhonebookTime.value*OneHour, False)
1328 debug("[FritzCallPhonebook] " + time.ctime())
1330 # Beware: strings in phonebook.phonebook have to be in utf-8!
1333 if not config.plugins.FritzCall.enable.value:
1336 phonebookFilename = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt")
1337 if config.plugins.FritzCall.phonebook.value and os.path.exists(phonebookFilename):
1338 debug("[FritzCallPhonebook] read " + phonebookFilename)
1339 phonebookTxtCorrupt = False
1341 for line in open(phonebookFilename):
1343 # Beware: strings in phonebook.phonebook have to be in utf-8!
1344 line = line.decode("utf-8")
1345 except UnicodeDecodeError: # this is just for the case, somebody wrote latin1 chars into PhoneBook.txt
1347 line = line.decode("iso-8859-1")
1348 debug("[FritzCallPhonebook] Fallback to ISO-8859-1 in %s" % line)
1349 phonebookTxtCorrupt = True
1350 except UnicodeDecodeError:
1351 error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1352 phonebookTxtCorrupt = True
1353 line = line.encode("utf-8")
1354 elems = line.split('#')
1357 # debug("[FritzCallPhonebook] Adding '''%s''' with '''%s''' from internal phonebook!" % (__(elems[1].strip()), __(elems[0], False)))
1358 self.phonebook[elems[0]] = elems[1]
1359 except ValueError: # how could this possibly happen?!?!
1360 error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1361 phonebookTxtCorrupt = True
1363 error("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1364 phonebookTxtCorrupt = True
1366 #===============================================================
1367 # found = re.match("^(\d+)#(.*)$", line)
1370 # self.phonebook[found.group(1)] = found.group(2)
1371 # except ValueError: # how could this possibly happen?!?!
1372 # debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1373 # phonebookTxtCorrupt = True
1375 # debug("[FritzCallPhonebook] Could not parse internal Phonebook Entry %s" % line)
1376 # phonebookTxtCorrupt = True
1377 #===============================================================
1379 if phonebookTxtCorrupt:
1380 # dump phonebook to PhoneBook.txt
1381 debug("[FritzCallPhonebook] dump Phonebook.txt")
1383 os.rename(phonebookFilename, phonebookFilename + ".bck")
1384 fNew = open(phonebookFilename, 'w')
1385 # Beware: strings in phonebook.phonebook are utf-8!
1386 for (number, name) in self.phonebook.iteritems():
1387 # Beware: strings in PhoneBook.txt have to be in utf-8!
1388 fNew.write(number + "#" + name.encode("utf-8"))
1390 except (IOError, OSError):
1391 error("[FritzCallPhonebook] error renaming or writing to %s" %phonebookFilename)
1393 if fritzbox and config.plugins.FritzCall.fritzphonebook.value:
1394 debug("[FritzCallPhonebook] config.plugins.FritzCall.fritzphonebook.value %s" %repr(config.plugins.FritzCall.fritzphonebook.value))
1395 fritzbox.loadFritzBoxPhonebook(self)
1397 #===============================================================================
1399 # # read entries from Outlook export
1401 # # not reliable with coding yet
1403 # # import csv exported from Outlook 2007 with csv(Windows)
1404 # csvFilename = "/tmp/PhoneBook.csv"
1405 # if config.plugins.FritzCall.phonebook.value and os.path.exists(csvFilename):
1407 # readOutlookCSV(csvFilename, self.add)
1408 # os.rename(csvFilename, csvFilename + ".done")
1409 # except ImportError:
1410 # debug("[FritzCallPhonebook] CSV import failed" %line)
1411 #===============================================================================
1414 #===============================================================================
1416 # # read entries from LDIF
1418 # # import ldif exported from Thunderbird 2.0.0.19
1419 # ldifFilename = "/tmp/PhoneBook.ldif"
1420 # if config.plugins.FritzCall.phonebook.value and os.path.exists(ldifFilename):
1422 # parser = MyLDIF(open(ldifFilename), self.add)
1424 # os.rename(ldifFilename, ldifFilename + ".done")
1425 # except ImportError:
1426 # debug("[FritzCallPhonebook] LDIF import failed" %line)
1427 #===============================================================================
1429 def search(self, number, default=None, extended=True):
1430 # debug("[FritzCallPhonebook] Searching for %s" %number)
1432 if not self.phonebook or not number:
1435 if config.plugins.FritzCall.prefix.value:
1436 prefix = config.plugins.FritzCall.prefix.value
1437 if number[0] != '0':
1438 number = prefix + number
1439 # debug("[FritzCallPhonebook] added prefix: %s" %number)
1440 elif number[:len(prefix)] == prefix and self.phonebook.has_key(number[len(prefix):]):
1441 # debug("[FritzCallPhonebook] same prefix")
1442 name = self.phonebook[number[len(prefix):]]
1443 # debug("[FritzCallPhonebook] result: %s" %name)
1447 if not name and self.phonebook.has_key(number):
1448 name = self.phonebook[number]
1450 if not name and default:
1453 if not name and extended and config.plugins.FritzCall.FritzExtendedSearchNames.value:
1454 for k in range(len(number)-1, 0, -1):
1455 # debug("[FritzCallPhonebook] extended search: check: %s" %number[:k])
1456 name = self.search(number[:k], default, False)
1458 # debug("[FritzCallPhonebook] search result for shortened number: %s" % name)
1461 return name.replace(", ", "\n").strip()
1463 def add(self, number, name):
1466 @param number: number of entry
1467 @param name: name of entry, has to be in utf-8
1469 debug("[FritzCallPhonebook]")
1470 name = name.replace("\n", ", ").replace('#','') # this is just for safety reasons. add should only be called with newlines converted into commas
1472 self.phonebook[number] = name
1473 if number and number != 0:
1474 if config.plugins.FritzCall.phonebook.value:
1476 name = name.strip() + "\n"
1477 string = "%s#%s" % (number, name)
1478 # Beware: strings in PhoneBook.txt have to be in utf-8!
1479 f = open(os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt"), 'a')
1482 info("[FritzCallPhonebook] added %s with %s to Phonebook.txt" % (number, name.strip()))
1488 def remove(self, number):
1489 if number in self.phonebook:
1490 debug("[FritzCallPhonebook]")
1491 del self.phonebook[number]
1492 if config.plugins.FritzCall.phonebook.value:
1494 phonebookFilename = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "PhoneBook.txt")
1495 debug("[FritzCallPhonebook] remove entry in Phonebook.txt")
1496 fOld = open(phonebookFilename, 'r')
1497 fNew = open(phonebookFilename + str(os.getpid()), 'w')
1498 line = fOld.readline()
1500 elems = line.split('#')
1501 if len(elems) == 2 and not elems[0] == number:
1503 line = fOld.readline()
1506 # os.remove(phonebookFilename)
1507 eBackgroundFileEraser.getInstance().erase(phonebookFilename)
1508 os.rename(phonebookFilename + str(os.getpid()), phonebookFilename)
1509 info("[FritzCallPhonebook] removed %s from Phonebook.txt" % number)
1512 except (IOError, OSError):
1513 error("[FritzCallPhonebook] error removing %s from %s" %(number, phonebookFilename))
1516 class FritzDisplayPhonebook(Screen, HelpableScreen, NumericalTextInput):
1518 def __init__(self, session):
1519 self.entriesWidth = DESKTOP_WIDTH * scaleH(75, 85)/100
1520 self.height = DESKTOP_HEIGHT * 0.75
1521 numberFieldWidth = scaleH(220, 160)
1522 fieldWidth = self.entriesWidth -5 -numberFieldWidth -10
1523 fontSize = scaleV(22, 18)
1524 fontHeight = scaleV(24, 20)
1525 buttonGap = (self.entriesWidth-4*140)/5
1526 debug("[FritzDisplayPhonebook] width: " + str(self.entriesWidth))
1528 <screen name="FritzDisplayPhonebook" position="center,center" size="%d,%d" title="Phonebook" >
1529 <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
1530 <widget source="entries" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" transparent="1">
1531 <convert type="TemplatedMultiContent">
1533 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 1), # index 0 is the name, index 1 is shortname
1534 MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 2), # index 2 is number
1536 "fonts": [gFont("Regular", %d)],
1541 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1542 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1543 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1544 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1545 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1546 <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" />
1547 <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" />
1548 <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" />
1549 <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1551 # scaleH(90, 75), scaleV(100, 73), # position
1552 self.entriesWidth, self.height, # size
1553 self.entriesWidth, # eLabel width
1554 scaleH(40, 5), scaleV(20, 5), # entries position
1555 self.entriesWidth-scaleH(40, 5), self.height-scaleV(20, 5)-5-5-40, # entries size
1556 0, 0, fieldWidth, scaleH(24,20), # name pos/size
1557 fieldWidth +5, 0, numberFieldWidth, scaleH(24,20), # dir pos/size
1558 fontSize, # fontsize
1559 fontHeight, # itemHeight
1560 self.height-40-5, # eLabel position vertical
1561 self.entriesWidth, # eLabel width
1562 buttonGap, self.height-40, "skin_default/buttons/red.png", # ePixmap red
1563 2*buttonGap+140, self.height-40, "skin_default/buttons/green.png", # ePixmap green
1564 3*buttonGap+2*140, self.height-40, "skin_default/buttons/yellow.png", # ePixmap yellow
1565 4*buttonGap+3*140, self.height-40, "skin_default/buttons/blue.png", # ePixmap blue
1566 buttonGap, self.height-40, scaleV(22, 21), # widget red
1567 2*buttonGap+140, self.height-40, scaleV(22, 21), # widget green
1568 3*buttonGap+2*140, self.height-40, scaleV(22, 21), # widget yellow
1569 4*buttonGap+3*140, self.height-40, scaleV(22, 21), # widget blue
1572 # debug("[FritzDisplayCalls] skin: " + self.skin)
1573 Screen.__init__(self, session)
1574 NumericalTextInput.__init__(self)
1575 HelpableScreen.__init__(self)
1577 # TRANSLATORS: keep it short, this is a button
1578 self["key_red"] = Button(_("Delete"))
1579 # TRANSLATORS: keep it short, this is a button
1580 self["key_green"] = Button(_("New"))
1581 # TRANSLATORS: keep it short, this is a button
1582 self["key_yellow"] = Button(_("Edit"))
1583 # TRANSLATORS: keep it short, this is a button
1584 self["key_blue"] = Button(_("Search"))
1586 self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
1590 "yellow": self.edit,
1591 "blue": self.search,
1592 "cancel": self.exit,
1593 "ok": self.showEntry, }, - 2)
1595 # TRANSLATORS: keep it short, this is a help text
1596 self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("Show details of entry"))]))
1597 # TRANSLATORS: keep it short, this is a help text
1598 self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("Quit"))]))
1599 # TRANSLATORS: keep it short, this is a help text
1600 self.helpList.append((self["setupActions"], "ColorActions", [("red", _("Delete entry"))]))
1601 # TRANSLATORS: keep it short, this is a help text
1602 self.helpList.append((self["setupActions"], "ColorActions", [("green", _("Add entry to phonebook"))]))
1603 # TRANSLATORS: keep it short, this is a help text
1604 self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("Edit selected entry"))]))
1605 # TRANSLATORS: keep it short, this is a help text
1606 self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("Search (case insensitive)"))]))
1608 self["entries"] = List([])
1609 debug("[FritzDisplayPhonebook]")
1610 self.help_window = None
1612 self.onLayoutFinish.append(self.setWindowTitle)
1615 def setWindowTitle(self):
1616 # TRANSLATORS: this is a window title.
1617 self.setTitle(_("Phonebook"))
1619 def display(self, filterNumber=""):
1620 debug("[FritzDisplayPhonebook]")
1622 # Beware: strings in phonebook.phonebook are utf-8!
1623 sortlistHelp = sorted((name.lower(), name, number) for (number, name) in phonebook.phonebook.iteritems())
1624 for (low, name, number) in sortlistHelp:
1625 if number == "01234567890":
1628 low = low.decode("utf-8")
1629 except UnicodeDecodeError: # this should definitely not happen
1631 low = low.decode("iso-8859-1")
1632 except UnicodeDecodeError:
1633 error("[FritzDisplayPhonebook] displayPhonebook/display: corrupt phonebook entry for %s" % number)
1634 # self.session.open(MessageBox, _("Corrupt phonebook entry\nfor number %s\nDeleting.") %number, type = MessageBox.TYPE_ERROR)
1635 phonebook.remove(number)
1639 filterNumber = filterNumber.lower()
1640 if low.find(filterNumber) == - 1:
1642 name = name.strip().decode("utf-8")
1643 number = number.strip().decode("utf-8")
1644 comma = name.find(',')
1646 shortname = name[:comma]
1649 number = number.encode("utf-8", "replace")
1650 name = name.encode("utf-8", "replace")
1651 shortname = shortname.encode('utf-8', 'replace')
1652 self.sortlist.append((name, shortname, number))
1654 self["entries"].setList(self.sortlist)
1656 def showEntry(self):
1657 cur = self["entries"].getCurrent()
1659 debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1662 self.session.open(FritzOfferAction, self, number, name)
1665 cur = self["entries"].getCurrent()
1667 debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1668 self.session.openWithCallback(
1669 self.deleteConfirmed,
1671 _("Do you really want to delete entry for\n\n%(number)s\n\n%(name)s?")
1672 % { 'number':str(cur[2]), 'name':str(cur[0]).replace(", ", "\n") }
1675 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1677 def deleteConfirmed(self, ret):
1678 debug("[FritzDisplayPhonebook]")
1680 # if ret: delete number from sortlist, delete number from phonebook.phonebook and write it to disk
1682 cur = self["entries"].getCurrent()
1685 # delete number from sortlist, delete number from phonebook.phonebook and write it to disk
1686 debug("[FritzDisplayPhonebook] %s" % (repr(cur)))
1687 phonebook.remove(cur[2])
1690 # self.session.open(MessageBox, _("Not deleted."), MessageBox.TYPE_INFO)
1692 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1694 def add(self, parent=None, number="", name=""):
1695 class AddScreen(Screen, ConfigListScreen):
1696 '''ConfiglistScreen with two ConfigTexts for Name and Number'''
1698 def __init__(self, session, parent, number="", name=""):
1700 # setup screen with two ConfigText and OK and ABORT button
1703 width = max(scaleH(-1, 570), noButtons*140)
1704 height = scaleV(-1, 100) # = 5 + 126 + 40 + 5; 6 lines of text possible
1705 buttonsGap = (width-noButtons*140)/(noButtons+1)
1706 buttonsVPos = height-40-5
1708 <screen position="center,center" size="%d,%d" title="Add entry to phonebook" >
1709 <widget name="config" position="5,5" size="%d,%d" scrollbarMode="showOnDemand" />
1710 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1711 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1712 <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" />
1713 <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" />
1716 width - 5 - 5, height - 5 - 40 - 5,
1717 buttonsGap, buttonsVPos, "skin_default/buttons/red.png",
1718 buttonsGap+140+buttonsGap, buttonsVPos, "skin_default/buttons/green.png",
1719 buttonsGap, buttonsVPos,
1720 buttonsGap+140+buttonsGap, buttonsVPos,
1722 Screen.__init__(self, session)
1723 self.session = session
1724 self.parent = parent
1725 # TRANSLATORS: keep it short, this is a button
1726 self["key_red"] = Button(_("Cancel"))
1727 # TRANSLATORS: keep it short, this is a button
1728 self["key_green"] = Button(_("OK"))
1729 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
1731 "cancel": self.cancel,
1738 ConfigListScreen.__init__(self, self.list, session=session)
1740 self.number = number
1741 config.plugins.FritzCall.name.value = name
1742 config.plugins.FritzCall.number.value = number
1743 self.list.append(getConfigListEntry(_("Name"), config.plugins.FritzCall.name))
1744 self.list.append(getConfigListEntry(_("Number"), config.plugins.FritzCall.number))
1745 self["config"].list = self.list
1746 self["config"].l.setList(self.list)
1747 self.onLayoutFinish.append(self.setWindowTitle)
1749 def setWindowTitle(self):
1750 # TRANSLATORS: this is a window title.
1751 self.setTitle(_("Add entry to phonebook"))
1754 # get texts from Screen
1755 # add (number,name) to sortlist and phonebook.phonebook and disk
1756 self.name = config.plugins.FritzCall.name.value
1757 self.number = config.plugins.FritzCall.number.value
1758 if not self.number or not self.name:
1759 self.session.open(MessageBox, _("Entry incomplete."), type=MessageBox.TYPE_ERROR)
1761 # add (number,name) to sortlist and phonebook.phonebook and disk
1762 # oldname = phonebook.search(self.number)
1764 # self.session.openWithCallback(
1765 # self.overwriteConfirmed,
1767 # _("Do you really want to overwrite entry for %(number)s\n\n%(name)s\n\nwith\n\n%(newname)s?")
1769 # 'number':self.number,
1771 # 'newname':self.name.replace(", ","\n")
1776 phonebook.add(self.number, self.name)
1778 self.parent.display()
1780 def overwriteConfirmed(self, ret):
1782 phonebook.remove(self.number)
1783 phonebook.add(self.number, self.name)
1784 self.parent.display()
1789 debug("[FritzDisplayPhonebook]")
1792 self.session.open(AddScreen, parent, number, name)
1795 debug("[FritzDisplayPhonebook]")
1796 cur = self["entries"].getCurrent()
1798 self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
1800 self.add(self, cur[2], cur[0])
1803 debug("[FritzDisplayPhonebook]")
1804 self.help_window = self.session.instantiateDialog(NumericalTextInputHelpDialog, self)
1805 self.help_window.show()
1806 # VirtualKeyboard instead of InputBox?
1807 self.session.openWithCallback(self.doSearch, InputBox, _("Enter Search Terms"), _("Search phonebook"))
1809 def doSearch(self, searchTerms):
1812 debug("[FritzDisplayPhonebook]: " + searchTerms)
1813 if self.help_window:
1814 self.session.deleteDialog(self.help_window)
1815 self.help_window = None
1816 self.display(searchTerms)
1821 phonebook = FritzCallPhonebook()
1823 class FritzCallSetup(Screen, ConfigListScreen, HelpableScreen):
1825 def __init__(self, session, args=None): #@UnusedVariable # pylint: disable=W0613
1826 self.width = scaleH(20+4*(140+90)+2*(35+40)+20, 4*140+2*35)
1828 debug("[FritzCallSetup] width: " + str(self.width))
1830 <screen name="FritzCallSetup" position="center,center" size="%d,%d" title="FritzCall Setup" >
1831 <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
1832 <widget name="consideration" position="%d,%d" halign="center" size="%d,%d" font="Regular;%d" backgroundColor="#20040404" transparent="1" />
1833 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1834 <widget name="config" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" backgroundColor="#20040404" transparent="1" />
1835 <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
1836 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1837 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1838 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1839 <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
1840 <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" />
1841 <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" />
1842 <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" />
1843 <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" />
1844 <ePixmap position="%d,%d" zPosition="4" size="35,25" pixmap="%s" transparent="1" alphatest="on" />
1845 <ePixmap position="%d,%d" zPosition="4" size="35,25" pixmap="%s" transparent="1" alphatest="on" />
1847 # (DESKTOP_WIDTH-width)/2, scaleV(100, 73), # position
1848 width, scaleV(560, 430), # size
1849 width, # eLabel width
1850 scaleH(40, 20), scaleV(10, 5), # consideration position
1851 scaleH(width-80, width-40), scaleV(25, 45), # consideration size
1852 scaleV(22, 20), # consideration font size
1853 scaleV(40, 50), # eLabel position vertical
1854 width, # eLabel width
1855 scaleH(40, 5), scaleV(60, 57), # config position
1856 scaleH(width-80, width-10), scaleV(453, 328), # config size
1857 scaleV(518, 390), # eLabel position vertical
1858 width, # eLabel width
1859 scaleH(20, 0), scaleV(525, 395), "skin_default/buttons/red.png", # pixmap red
1860 scaleH(20+140+90, 140), scaleV(525, 395), "skin_default/buttons/green.png", # pixmap green
1861 scaleH(20+2*(140+90), 2*140), scaleV(525, 395), "skin_default/buttons/yellow.png", # pixmap yellow
1862 scaleH(20+3*(140+90), 3*140), scaleV(525, 395), "skin_default/buttons/blue.png", # pixmap blue
1863 scaleH(20, 0), scaleV(525, 395), scaleV(21, 21), # widget red
1864 scaleH(20+(140+90), 140), scaleV(525, 395), scaleV(21, 21), # widget green
1865 scaleH(20+2*(140+90), 2*140), scaleV(525, 395), scaleV(21, 21), # widget yellow
1866 scaleH(20+3*(140+90), 3*140), scaleV(525, 395), scaleV(21, 21), # widget blue
1867 scaleH(20+4*(140+90), 4*140), scaleV(532, 402), "skin_default/buttons/key_info.png", # button information
1868 scaleH(20+4*(140+90)+(35+40), 4*140+35), scaleV(532, 402), "skin_default/buttons/key_menu.png", # button menu
1871 Screen.__init__(self, session)
1872 HelpableScreen.__init__(self)
1873 self.session = session
1875 self["consideration"] = Label(_("You need to enable the monitoring on your FRITZ!Box by dialing #96*5*!"))
1878 # Initialize Buttons
1879 # TRANSLATORS: keep it short, this is a button
1880 self["key_red"] = Button(_("Cancel"))
1881 # TRANSLATORS: keep it short, this is a button
1882 self["key_green"] = Button(_("OK"))
1883 # TRANSLATORS: keep it short, this is a button
1884 self["key_yellow"] = Button(_("Phone calls"))
1885 # TRANSLATORS: keep it short, this is a button
1886 self["key_blue"] = Button(_("Phonebook"))
1887 # TRANSLATORS: keep it short, this is a button
1888 self["key_info"] = Button(_("About FritzCall"))
1889 # TRANSLATORS: keep it short, this is a button
1890 self["key_menu"] = Button(_("FRITZ!Box Fon Status"))
1892 self["setupActions"] = ActionMap(["ColorActions", "OkCancelActions", "MenuActions", "EPGSelectActions"],
1896 "yellow": self.displayCalls,
1897 "blue": self.displayPhonebook,
1898 "cancel": self.cancel,
1904 # TRANSLATORS: keep it short, this is a help text
1905 self.helpList.append((self["setupActions"], "ColorActions", [("red", _("quit"))]))
1906 # TRANSLATORS: keep it short, this is a help text
1907 self.helpList.append((self["setupActions"], "ColorActions", [("green", _("save and quit"))]))
1908 # TRANSLATORS: keep it short, this is a help text
1909 self.helpList.append((self["setupActions"], "ColorActions", [("yellow", _("display calls"))]))
1910 # TRANSLATORS: keep it short, this is a help text
1911 self.helpList.append((self["setupActions"], "ColorActions", [("blue", _("display phonebook"))]))
1912 # TRANSLATORS: keep it short, this is a help text
1913 self.helpList.append((self["setupActions"], "OkCancelActions", [("ok", _("save and quit"))]))
1914 # TRANSLATORS: keep it short, this is a help text
1915 self.helpList.append((self["setupActions"], "OkCancelActions", [("cancel", _("quit"))]))
1916 # TRANSLATORS: keep it short, this is a help text
1917 self.helpList.append((self["setupActions"], "MenuActions", [("menu", _("FRITZ!Box Fon Status"))]))
1918 # TRANSLATORS: keep it short, this is a help text
1919 self.helpList.append((self["setupActions"], "EPGSelectActions", [("info", _("About FritzCall"))]))
1921 ConfigListScreen.__init__(self, self.list, session=session)
1923 # get new list of locations for PhoneBook.txt
1925 self.onLayoutFinish.append(self.setWindowTitle)
1927 def setWindowTitle(self):
1928 # TRANSLATORS: this is a window title.
1929 self.setTitle(_("FritzCall Setup") + " (" + "$Revision: 1249 $"[1: - 1] + "$Date: 2015-11-17 19:36:24 +0100 (Tue, 17 Nov 2015) $"[7:23] + ")")
1932 ConfigListScreen.keyLeft(self)
1936 ConfigListScreen.keyRight(self)
1939 def createSetup(self):
1941 self.list.append(getConfigListEntry(_("Call monitoring"), config.plugins.FritzCall.enable))
1942 if config.plugins.FritzCall.enable.value:
1943 self.list.append(getConfigListEntry(_("FRITZ!Box FON address (Name or IP)"), config.plugins.FritzCall.hostname))
1944 self.list.append(getConfigListEntry(_("FRITZ!Box FON firmware version"), config.plugins.FritzCall.fwVersion))
1946 self.list.append(getConfigListEntry(_("Show after Standby"), config.plugins.FritzCall.afterStandby))
1948 self.list.append(getConfigListEntry(_("Show only calls for specific MSN"), config.plugins.FritzCall.filter))
1949 if config.plugins.FritzCall.filter.value:
1950 self.list.append(getConfigListEntry(_("MSN to show (separated by ,)"), config.plugins.FritzCall.filtermsn))
1951 self.list.append(getConfigListEntry(_("Filter also list of calls"), config.plugins.FritzCall.filterCallList))
1952 self.list.append(getConfigListEntry(_("Mute on call"), config.plugins.FritzCall.muteOnCall))
1954 self.list.append(getConfigListEntry(_("Show Blocked Calls"), config.plugins.FritzCall.showBlacklistedCalls))
1955 self.list.append(getConfigListEntry(_("Show Outgoing Calls"), config.plugins.FritzCall.showOutgoingCalls))
1956 # not only for outgoing: config.plugins.FritzCall.showOutgoingCalls.value:
1957 self.list.append(getConfigListEntry(_("Areacode to add to calls without one (if necessary)"), config.plugins.FritzCall.prefix))
1958 self.list.append(getConfigListEntry(_("Timeout for Call Notifications (seconds)"), config.plugins.FritzCall.timeout))
1959 self.list.append(getConfigListEntry(_("Reverse Lookup Caller ID (select country below)"), config.plugins.FritzCall.lookup))
1960 if config.plugins.FritzCall.lookup.value:
1961 self.list.append(getConfigListEntry(_("Country"), config.plugins.FritzCall.country))
1963 if config.plugins.FritzCall.fwVersion.value != None:
1964 if config.plugins.FritzCall.fwVersion.value == "05.50" or config.plugins.FritzCall.fwVersion.value == "06.35":
1965 self.list.append(getConfigListEntry(_("User name Accessing FRITZ!Box"), config.plugins.FritzCall.username))
1966 self.list.append(getConfigListEntry(_("Password Accessing FRITZ!Box"), config.plugins.FritzCall.password))
1967 self.list.append(getConfigListEntry(_("Extension number to initiate call on"), config.plugins.FritzCall.extension))
1968 if config.plugins.FritzCall.fwVersion.value == "05.50" or config.plugins.FritzCall.fwVersion.value == "06.35":
1969 self.list.append(getConfigListEntry(_("Name of WLAN guest network"), config.plugins.FritzCall.guestSSID))
1970 self.list.append(getConfigListEntry(_("Secure WLAN guest network"), config.plugins.FritzCall.guestSecure))
1971 # TODO: make password unreadable?
1972 self.list.append(getConfigListEntry(_("Password of WLAN guest network"), config.plugins.FritzCall.guestPassword))
1973 self.list.append(getConfigListEntry(_("Minutes of uptime of WLAN guest network"), config.plugins.FritzCall.guestUptime))
1974 self.list.append(getConfigListEntry(_("Read PhoneBook from FRITZ!Box"), config.plugins.FritzCall.fritzphonebook))
1975 if config.plugins.FritzCall.fritzphonebook.value:
1976 if config.plugins.FritzCall.fwVersion.value != "06.35":
1977 self.list.append(getConfigListEntry(_("FRITZ!Box PhoneBook to read"), config.plugins.FritzCall.fritzphonebookName))
1978 self.list.append(getConfigListEntry(_("Append type of number"), config.plugins.FritzCall.showType))
1979 self.list.append(getConfigListEntry(_("Append shortcut number"), config.plugins.FritzCall.showShortcut))
1980 self.list.append(getConfigListEntry(_("Append vanity name"), config.plugins.FritzCall.showVanity))
1982 config.plugins.FritzCall.fritzphonebook.value = False
1984 if config.plugins.FritzCall.phonebook.value or config.plugins.FritzCall.fritzphonebook.value:
1985 self.list.append(getConfigListEntry(_("Reload interval for phonebooks (hours)"), config.plugins.FritzCall.reloadPhonebookTime))
1987 self.list.append(getConfigListEntry(_("Use internal PhoneBook"), config.plugins.FritzCall.phonebook))
1988 if config.plugins.FritzCall.phonebook.value:
1989 if config.plugins.FritzCall.lookup.value:
1990 self.list.append(getConfigListEntry(_("Automatically add new Caller to PhoneBook"), config.plugins.FritzCall.addcallers))
1991 self.list.append(getConfigListEntry(_("PhoneBook and Faces Location"), config.plugins.FritzCall.phonebookLocation))
1993 if config.plugins.FritzCall.phonebook.value or config.plugins.FritzCall.fritzphonebook.value:
1994 self.list.append(getConfigListEntry(_("Extended Search for names"), config.plugins.FritzCall.FritzExtendedSearchNames))
1995 self.list.append(getConfigListEntry(_("Extended Search for faces"), config.plugins.FritzCall.FritzExtendedSearchFaces))
1997 self.list.append(getConfigListEntry(_("Strip Leading 0"), config.plugins.FritzCall.internal))
1998 # self.list.append(getConfigListEntry(_("Default display mode for FRITZ!Box calls"), config.plugins.FritzCall.fbfCalls))
1999 self.list.append(getConfigListEntry(_("Display connection infos"), config.plugins.FritzCall.connectionVerbose))
2000 self.list.append(getConfigListEntry(_("Ignore callers with no phone number"), config.plugins.FritzCall.ignoreUnknown))
2001 self.list.append(getConfigListEntry(_("Debug"), config.plugins.FritzCall.debug))
2003 self["config"].list = self.list
2004 self["config"].l.setList(self.list)
2007 # debug("[FritzCallSetup]"
2008 if self["config"].getCurrent()[1] == config.plugins.FritzCall.phonebookLocation:
2009 self.session.openWithCallback(self.LocationBoxClosed, LocationBox, _("PhoneBook and Faces Location"), currDir=config.plugins.FritzCall.phonebookLocation.value)
2011 for x in self["config"].list:
2013 if config.plugins.FritzCall.phonebookLocation.isChanged() or config.plugins.FritzCall.reloadPhonebookTime.isChanged():
2017 if config.plugins.FritzCall.enable.value:
2018 fritz_call.connect()
2020 fritz_call.shutdown()
2023 def LocationBoxClosed(self, path):
2024 if path is not None:
2025 config.plugins.FritzCall.phonebookLocation.setValue(path)
2028 # debug("[FritzCallSetup]"
2029 for x in self["config"].list:
2033 def displayCalls(self):
2034 if config.plugins.FritzCall.enable.value:
2035 if fritzbox and config.plugins.FritzCall.fwVersion.value:
2036 self.session.open(FritzDisplayCalls)
2038 self.session.open(MessageBox, _("Cannot get calls from FRITZ!Box"), type=MessageBox.TYPE_INFO)
2040 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2042 def displayPhonebook(self):
2044 if config.plugins.FritzCall.enable.value:
2045 self.session.open(phonebook.FritzDisplayPhonebook)
2047 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2049 self.session.open(MessageBox, _("No phonebook"), type=MessageBox.TYPE_INFO)
2052 self.session.open(FritzAbout)
2055 if config.plugins.FritzCall.enable.value:
2056 if fritzbox and fritzbox.information:
2057 self.session.open(FritzMenu)
2059 self.session.open(MessageBox, _("Cannot get infos from FRITZ!Box yet\nStill initialising or wrong firmware version"), type=MessageBox.TYPE_INFO)
2061 self.session.open(MessageBox, _("Plugin not enabled"), type=MessageBox.TYPE_INFO)
2065 class FritzCallList:
2069 def add(self, event, date, number, caller, phone):
2070 debug("[FritzCallList] %s %s" % (number, caller))
2071 if len(self.callList) > 10:
2072 if self.callList[0] != "Start":
2073 self.callList[0] = "Start"
2074 del self.callList[1]
2076 self.callList.append((event, number, date, caller, phone))
2079 debug("[FritzCallList]")
2082 # Standby.inStandby.onClose.remove(self.display) object does not exist anymore...
2083 # build screen from call list
2086 if not self.callList:
2087 text = _("no calls")
2089 if self.callList[0] == "Start":
2090 text = text + _("Last 10 calls:\n")
2091 del self.callList[0]
2093 for call in self.callList:
2094 (event, number, date, caller, phone) = call
2100 # shorten the date information
2101 date = date[:6] + date[9:14]
2103 # our phone could be of the form "0123456789 (home)", then we only take "home"
2104 oBrack = phone.find('(')
2105 cBrack = phone.find(')')
2106 if oBrack != -1 and cBrack != -1:
2107 phone = phone[oBrack+1:cBrack]
2109 # should not happen, for safety reasons
2111 caller = _("UNKNOWN")
2113 # if we have an unknown number, show the number
2114 if caller == _("UNKNOWN") and number != "":
2117 # strip off the address part of the remote caller/callee, if there is any
2118 nl = caller.find('\n')
2120 caller = caller[:nl]
2121 elif caller[0] == '[' and caller[-1] == ']':
2122 # that means, we've got an unknown number with a city added from avon.dat
2123 if (len(number) + 1 + len(caller) + len(phone)) <= 40:
2124 caller = number + ' ' + caller
2128 while (len(caller) + len(phone)) > 40:
2129 if len(caller) > len(phone):
2130 caller = caller[: - 1]
2132 phone = phone[: - 1]
2134 text = text + "%s %s %s %s\n" % (date, caller, direction, phone)
2135 debug("[FritzCallList] '%s %s %s %s'" % (date, caller, direction, phone))
2138 Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO)
2139 # TODO please HELP: from where can I get a session?
2140 # my_global_session.open(FritzDisplayCalls, text)
2143 callList = FritzCallList()
2145 def findFace(number, name):
2146 # debug("[FritzCall] number/name: %s/%s" % (number, name))
2148 sep = name.find(',')
2151 sep = name.find('\n')
2156 # debug("[FritzCall] looking for: %s" %name)
2158 facesDir = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "FritzCallFaces")
2159 # debug("[FritzCall] looking in: %s" %facesDir)
2162 if not os.path.isdir(facesDir):
2163 error("[FritzCall] findFace facesdir does not exist: %s" %facesDir)
2165 files = os.listdir(facesDir)
2166 # debug("[FritzCall] listdir: %s" %repr(files))
2167 # TODO macthed das hier auf ????.png1 ?!?!?
2168 myFiles = [f for f in files if re.match(re.escape(number) + "\.[png|PNG]", f)]
2170 myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2173 sep = name.find(' (')
2176 myFiles = [f for f in files if re.match(re.escape(name) + "\.[png|PNG]", f)]
2179 # debug("[FritzCall] found: %s" %repr(myFiles))
2180 facesFile = os.path.join(facesDir, myFiles[0])
2182 if not facesFile and config.plugins.FritzCall.FritzExtendedSearchFaces.value:
2183 for k in range(len(number)-1, 0, -1):
2184 # debug("[FritzCall] extended search: %s" %number[:k])
2185 myFiles = [f for f in files if re.match(re.escape(number[:k]) + "\.[png|PNG]", f)]
2187 facesFile = os.path.join(facesDir, myFiles[0])
2191 facesFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
2193 info("[FritzCall] result: %s" % (__(facesFile)))
2196 class MessageBoxPixmap(Screen):
2197 def __init__(self, session, text, number = "", name = "", timeout = -1):
2199 <screen name="MessageBoxPixmap" position="center,center" size="600,10" title="New Call">
2200 <widget name="text" position="115,8" size="520,0" font="Regular;%d" />
2201 <widget name="InfoPixmap" pixmap="%s" position="5,5" size="100,100" alphatest="on" />
2204 # scaleH(350, 60), scaleV(175, 245),
2205 scaleV(25, 22), resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_info.png")
2207 debug("[FritzCall] MessageBoxPixmap number: %s" % number)
2208 Screen.__init__(self, session)
2209 # MessageBox.__init__(self, session, text, type=MessageBox.TYPE_INFO, timeout=timeout)
2210 self["text"] = Label(text)
2211 self["InfoPixmap"] = Pixmap()
2212 self._session = session
2213 self._number = number
2215 self._timerRunning = False
2217 self._timeout = timeout
2218 self._origTitle = None
2220 self.onLayoutFinish.append(self._finishLayout)
2221 self["actions"] = ActionMap(["OkCancelActions"],
2223 "cancel": self._exit,
2224 "ok": self._exit, }, - 2)
2226 def _finishLayout(self):
2227 # pylint: disable=W0142
2228 debug("[FritzCall] MessageBoxPixmap/setInfoPixmap number: %s/%s" % (self._number, self._name))
2230 self.setTitle(_("New call"))
2232 faceFile = findFace(self._number, self._name)
2233 picPixmap = LoadPixmap(faceFile)
2234 if not picPixmap: # that means most probably, that the picture is not 8 bit...
2235 Notifications.AddNotification(MessageBox, _("Found picture\n\n%s\n\nBut did not load. Probably not PNG, 8-bit") %faceFile, type = MessageBox.TYPE_ERROR)
2236 picPixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/input_error.png"))
2237 picSize = picPixmap.size()
2239 # recalculate window size
2240 textSize = self["text"].getSize()
2241 textSize = (textSize[0]+20, textSize[1]+20) # don't know, why, but size is too small
2242 textSize = eSize(*textSize)
2243 width = max(scaleH(600, 280), picSize.width() + textSize.width() + 30)
2244 height = max(scaleV(300, 250), picSize.height()+10, textSize.height()+10)
2245 wSize = (width, height)
2246 wSize = eSize(*wSize)
2248 # center the smaller vertically
2249 hGap = (width-picSize.width()-textSize.width())/3
2250 picPos = (hGap, (height-picSize.height())/2+1)
2251 textPos = (hGap+picSize.width()+hGap, (height-textSize.height())/2+1)
2254 self.instance.resize(wSize)
2256 self["text"].instance.resize(textSize)
2258 self["InfoPixmap"].instance.resize(picSize)
2259 self["InfoPixmap"].instance.setPixmap(picPixmap)
2261 self["text"].instance.move(ePoint(*textPos))
2263 self["InfoPixmap"].instance.move(ePoint(*picPos))
2265 self.instance.move(ePoint((DESKTOP_WIDTH-wSize.width())/2, (DESKTOP_HEIGHT-wSize.height())/2))
2267 def _initTimeout(self):
2268 if self._timeout > 0:
2269 self._timer = eTimer()
2271 # newer OE versions don't have the callback
2273 self._timer_conn = self._timer.timeout.connect(self._timerTick)
2274 except AttributeError:
2275 self._timer.callback.append(self._timerTick)
2277 self.onExecBegin.append(self._startTimer)
2278 self._origTitle = None
2282 self.onShown.append(self.__onShown)
2283 self._timerRunning = True
2285 self._timerRunning = False
2287 def __onShown(self):
2288 self.onShown.remove(self.__onShown)
2291 def _startTimer(self):
2292 self._timer.start(1000)
2294 #===============================================================================
2295 # def stopTimer(self):
2296 # if self._timerRunning:
2298 # self.setTitle(self._origTitle)
2299 # self._timerRunning = False
2300 #===============================================================================
2302 def _timerTick(self):
2305 if self._origTitle is None:
2306 self._origTitle = self.instance.getTitle()
2307 self.setTitle(self._origTitle + " (" + str(self._timeout) + ")")
2308 if self._timeout == 0:
2310 self._timerRunning = False
2316 def runUserActionScript(event, date, number, caller, phone):
2318 # call FritzCallserAction.sh in the same dir as Phonebook.txt with the following parameters:
2319 # event: "RING" (incomning) or "CALL" (outgoing)
2320 # date of event, format: "dd.mm.yy hh.mm.ss"
2321 # telephone number which is calling/is called
2322 # caller's name and address, format Name\n Street\n ZIP City
2323 # line/number which is called/which is used for calling
2324 userActionScript = os.path.join(config.plugins.FritzCall.phonebookLocation.value, "FritzCallUserAction.sh")
2325 if os.path.exists(userActionScript) and os.access(userActionScript, os.X_OK):
2326 cmd = userActionScript + ' "' + event + '" "' + date + '" "' + number + '" "' + caller + '" "' + phone + '"'
2327 info("[FritzCall] calling: %s" % cmd)
2328 eConsoleAppContainer().execute(cmd)
2330 userActionList = [runUserActionScript]
2331 def registerUserAction(fun):
2332 #===========================================================================
2333 # other plugins can register a function, which is then called for each displayed call
2334 # it must take the arguments event,date,number,caller,phone
2337 # def FritzCallEvent(event,date,number,caller,phone):
2341 # from Plugins.Extensions.FritzCall.plugin import registerUserAction as FritzCallRegisterUserAction
2342 # FritzCallRegisterUserAction(FritzCallEvent)
2344 # print "import of FritzCall failed"
2345 #===========================================================================
2346 info("[FritzCall] register: %s" % fun.__name__)
2347 userActionList.append(fun)
2349 mutedOnConnID = None
2350 def notifyCall(event, date, number, caller, phone, connID):
2351 if Standby.inStandby is None or config.plugins.FritzCall.afterStandby.value == "each":
2353 global mutedOnConnID
2354 if config.plugins.FritzCall.muteOnCall.value and not mutedOnConnID:
2355 info("[FritzCall] mute on connID: %s" % connID)
2356 mutedOnConnID = connID
2357 # eDVBVolumecontrol.getInstance().volumeMute() # with this, we get no mute icon...
2358 if not eDVBVolumecontrol.getInstance().isMuted():
2359 globalActionMap.actions["volumeMute"]()
2360 text = _("Incoming Call on %(date)s at %(time)s from\n---------------------------------------------\n%(number)s\n%(caller)s\n---------------------------------------------\nto: %(phone)s") % { 'date':date[:8], 'time':date[9:], 'number':number, 'caller':caller, 'phone':phone }
2362 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 }
2363 info("[FritzCall]\n%s" % text)
2364 # Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO, timeout=config.plugins.FritzCall.timeout.value)
2365 Notifications.AddNotification(MessageBoxPixmap, text, number=number, name=caller, timeout=config.plugins.FritzCall.timeout.value)
2366 elif config.plugins.FritzCall.afterStandby.value == "inList":
2368 # if not yet done, register function to show call list
2370 if not standbyMode :
2372 Standby.inStandby.onHide.append(callList.display) #@UndefinedVariable
2373 # add text/timeout to call list
2374 callList.add(event, date, number, caller, phone)
2375 info("[FritzCall] added to callList")
2376 else: # this is the "None" case
2377 info("[FritzCall] standby and no show")
2379 for fun in userActionList:
2380 info("[FritzCall] call user action: %s" % fun.__name__)
2381 fun(event, date, number, caller, phone)
2384 #===============================================================================
2385 # We need a separate class for each invocation of reverseLookup to retain
2386 # the necessary data for the notification
2387 #===============================================================================
2390 reverselookupMtime = 0
2392 class FritzReverseLookupAndNotifier:
2393 def __init__(self, event, number, caller, phone, date, connID):
2396 Initiate a reverse lookup for the given number in the configured country
2398 @param event: CALL or RING
2399 @param number: number to be looked up
2400 @param caller: caller including name and address
2401 @param phone: Number (and name) of or own phone
2402 @param date: date of call