add Nederland-Cams, thanks to karmic
[enigma2-plugins.git] / webcamviewer / src / plugin.py
1 from enigma import eListbox
2 from enigma import eListboxPythonMultiContent
3 from enigma import ePicLoad
4 from enigma import loadPNG
5 from enigma import gFont
6 ### Picturelist
7 from Screens.Screen import Screen
8 from Screens.MessageBox import MessageBox
9 from Screens.InputBox import InputBox
10 from Screens.ChoiceBox import ChoiceBox
11 from Components.ActionMap import ActionMap
12 from Components.Label import Label
13 from Components.MenuList import MenuList
14 from Components.FileList import EXTENSIONS
15 from Components.AVSwitch import AVSwitch
16 ## configmenu
17 from Components.config import config, ConfigSubsection,ConfigSelection,ConfigText,ConfigYesNo
18 ####
19 from Components.Input import Input
20 from Components.Pixmap import Pixmap
21 from Plugins.Plugin import PluginDescriptor
22 ### System
23 import os
24 from re import compile
25 ## XML
26 from pyexpat import ExpatError
27 import xml.dom.minidom
28
29 ### my
30 from WebcamViewConfig import WebcamViewerMenu
31 from PictureScreen import PictureScreen
32 from WebcamTravel import TravelWebcamviewer
33 ###
34 myname = "Webcam/Picture Viewer"
35 myversion = "1.1"
36
37 config.plugins.pictureviewer = ConfigSubsection()
38 config.plugins.pictureviewer.slideshowtime = ConfigSelection(default="5000", choices = [("5000", _("5 Seconds")), ("10000", _("10 Seconds")), ("20000", _("20 Seconds")), ("60000", _("1 Minute"))])
39 config.plugins.pictureviewer.slideshowmode = ConfigSelection(default="0", choices = [("0", _("normal")), ("1", _("endless"))])
40 #not editable configs
41 config.plugins.pictureviewer.slideshowext = ConfigText(default=".3ssl")
42 config.plugins.pictureviewer.matchingPattern = ConfigText(default="(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)")
43 config.plugins.pictureviewer.slideshowdir = ConfigText(default="/media/hdd/slideshows/")
44 config.plugins.pictureviewer.rootdir = ConfigText(default="/media/")
45 config.plugins.pictureviewer.stopserviceonstart = ConfigYesNo(default = False)
46 SLIDESHOWMODE_NORMAL = 0
47 SLIDESHOWMODE_REPEAT = 1
48
49 originalservice = None
50 mysession = None
51
52
53 def startPictureviewer(session, **kwargs):
54         global originalservice, mysession
55         mysession = session
56         originalservice = session.nav.getCurrentlyPlayingServiceReference()
57         if config.plugins.pictureviewer.stopserviceonstart.value:
58                 session.nav.stopService()
59         session.openWithCallback(mainCB, PictureViewer)
60
61 def startWebcamviewer(session, **kwargs):
62         global originalservice, mysession
63         mysession = session
64         originalservice = session.nav.getCurrentlyPlayingServiceReference()
65         if config.plugins.pictureviewer.stopserviceonstart.value:
66                 session.nav.stopService()
67         xmlfile = "/usr/lib/enigma2/python/Plugins/Extensions/WebcamViewer/webcam.xml"
68         if os.path.isfile(xmlfile):
69                 try:
70                         xmlnode = xml.dom.minidom.parse(open(xmlfile))
71                         session.openWithCallback(mainCB, WebcamViewer, xmlnode.childNodes[1])
72                 except ExpatError,e:
73                         session.open(
74                                 MessageBox,
75                                 _("Loading config file failed!\n\n%s") % e,
76                                 MessageBox.TYPE_WARNING
77                         )
78         else:
79                 session.open(
80                         MessageBox,
81                         _("Loading config file failed!\n\nconfigfile not found!"),
82                         MessageBox.TYPE_WARNING
83                 )
84
85
86
87
88 def mainCB():
89         global originalservice, mysession
90         if config.plugins.pictureviewer.stopserviceonstart.value:
91                 mysession.nav.playService(originalservice)
92
93 def Plugins(path, **kwargs):
94         p = [
95                         PluginDescriptor(
96                                                         name="PictureViewer",
97                                                         description="browse your local pictures",
98                                                         where = PluginDescriptor.WHERE_PLUGINMENU,
99                                                         fnc = startPictureviewer,
100                                                         icon="pictureviewer.png"
101                           ),
102                         PluginDescriptor(
103                                                         name="WebcamViewer",
104                                                         description="view webcams around the world",
105                                                         where = PluginDescriptor.WHERE_PLUGINMENU,
106                                                         fnc = startWebcamviewer,
107                                                         icon="webcamviewer.png"
108                         )
109                  ]
110         return p
111
112 ###################
113 class ViewerSelectScreen(Screen):
114         skin = ""
115         def __init__(self, session, args = 0):
116                 skin =  """<screen position="93,70" size="550,450">
117                 <widget name="list" position="0,0" size="550,450"  />
118                 </screen>"""
119                 self.skin = skin
120                 Screen.__init__(self, session)
121                 self.slideshowfiles = []
122                 self.slideshowfiles.append((_("WebcamViewer"),STARTWEBCAMVIEWER))
123                 self.slideshowfiles.append((_("online webcam.travel"),STARTWEBCAMTRAVEL))
124                 self["list"] = MenuList(self.slideshowfiles)
125                 self["actions"] = ActionMap(["WizardActions", "MenuActions", "DirectionActions", "ShortcutActions"],
126                         {
127                          "ok": self.go,
128                          "back": self.close
129                          }, -1)
130
131         def go(self):
132                 selection = self["list"].getCurrent()
133                 if selection:
134                         self.close(self.session,selection[1])
135
136
137 ###################
138 class Slideshow:
139         filelist = []
140         currentslideshowitem = 0
141         wbviewer = False
142
143         def __init__(self, session, callback):
144                 self.session = session
145                 self.callback = callback
146
147         def setfiles(self, filelist):
148                 self.filelist = filelist
149
150         def start(self):
151                 if len(self.filelist) > 0:
152                         self.currentslideshowitem = -1
153                         self.nextSlideshowItem()
154
155         def nextSlideshowItem(self, prev = False):
156                 currentslideshowitem = self.currentslideshowitem
157                 if prev:
158                         currentslideshowitem -= 2
159                 if currentslideshowitem < 0:
160                         currentslideshowitem = -1
161                 if currentslideshowitem is not (len(self.filelist) - 1):
162                         currentslideshowitem += 1
163                         filetoshow = self.filelist[currentslideshowitem][1]
164                         if not self.wbviewer:
165                                 self.wbviewer = self.session.openWithCallback(
166                                                                         self.cb,
167                                                                         PictureScreen,
168                                                                         filetoshow.split("/")[-1],
169                                                                         filetoshow,
170                                                                         slideshowcallback = self.nextSlideshowItem
171                                 )
172                         else:
173                                 self.wbviewer.filename = filetoshow
174                                 self.wbviewer.do()
175                         self.currentslideshowitem = currentslideshowitem
176                 elif int(config.plugins.pictureviewer.slideshowmode.value) is SLIDESHOWMODE_REPEAT:
177                         print "["+myname+"] restarting slideshow"
178                         self.start()
179                 else:
180                         print "["+myname+"] slideshow finished"
181                         self.wbviewer.exit()
182                         self.cb()
183
184         def cb(self):
185                 self.callback()
186 ###################
187 class PictureViewer(Screen):
188         skin = ""
189         filelist = []
190         currList = "slideshowlist"
191         wbviewer = False
192         loadedslideshowlistlistname = False
193
194         def __init__(self, session, args = 0):
195                 skin =  """<screen position="93,70" size="550,450" title="%s">
196                 <widget name="menu" position="1,1" size="275,400"  scrollbarMode="showOnDemand" />
197                 <widget name="pixmap" position="275,1" size="275,200" backgroundColor="red" />
198                 <widget name="slist" position="275,200" size="275,200"  scrollbarMode="showOnDemand" />
199                 <widget name="buttonred" position="6,405" size="130,40" backgroundColor="red" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
200                 <widget name="buttongreen" position="142,405" size="130,40" backgroundColor="green" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
201                 <widget name="buttonyellow" position="278,405" size="130,40" backgroundColor="yellow" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
202                 <widget name="buttonblue" position="414,405" size="130,40" backgroundColor="blue" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
203                 </screen>""" % config.plugins.pictureviewer.rootdir.value
204                 self.skin = skin
205                 Screen.__init__(self, session)
206
207                 self.filelist = PictureList(config.plugins.pictureviewer.rootdir.value, matchingPattern = config.plugins.pictureviewer.matchingPattern.value)
208                 self["menu"] = self.filelist
209
210                 self.preview = Pixmap()
211                 self["pixmap"] = self.preview
212
213                 self.slideshowfiles = []
214                 self.slideshowlist =MenuList(self.slideshowfiles)
215                 self["slist"] = self.slideshowlist
216
217                 self["buttonred"] = Label("")
218                 self["buttongreen"] = Label("")
219                 self["buttonyellow"] = Label("")
220                 self["buttonblue"] = Label("")
221
222                 self["actions"] = ActionMap(["WizardActions", "MenuActions", "DirectionActions", "ShortcutActions"],
223                         {
224                          "ok": self.go,
225                          "back": self.close,
226                          "menu": self.openMenu,
227                          "up": self.up,
228                          "down": self.down,
229                          "left": self.leftUp,
230                          "right": self.rightUp,
231                          "red": self.KeyRed,
232                          "green": self.KeyGreen,
233                          "yellow": self.KeyYellow,
234                          "blue": self.switchList,
235                          }, -1)
236
237                 self.onLayoutFinish.append(self.switchList)
238                 self.onLayoutFinish.append(self.updateInfoPanel)
239
240         def KeyGreen(self):
241                 if self.currList is "filelist":
242                         # adding all files in current dir to slideshowlist
243                         dirname = self["menu"].getCurrentDir()
244                         if os.path.isdir(dirname):
245                                 s = os.listdir(dirname)
246                                 s.sort()
247                                 for file in s:
248                                         if compile(config.plugins.pictureviewer.matchingPattern.value).search(dirname + file):
249                                                 self.slideshowfiles.append((_(file),dirname + file))
250                                 self["slist"].l.setList(self.slideshowfiles)
251                 else:
252                         #loading list
253                         list = []
254                         try:
255                                 for file in os.listdir(config.plugins.pictureviewer.slideshowdir.value):
256                                         if file.endswith(config.plugins.pictureviewer.slideshowext.value):
257                                                 list.append((_(file.split("/")[-1]),file))
258                                 self.session.openWithCallback(
259                                                 self.fileToLoadFilelistEntered,
260                                                 ChoiceBox,
261                                                 _("select List to load"),
262                                                 list
263                                 )
264                         except IOError,e:
265                                 print "["+myname+"] IOError:",e
266                         except OSError,e:
267                                 print "["+myname+"] OSError:",e
268
269         def KeyRed(self):
270                 if self.currList is "filelist" :
271                         #do slideshow
272                         self.hide()
273                         x = Slideshow(self.session, self.show)
274                         x.setfiles(self.slideshowfiles)
275                         x.start()
276                 else:
277                         # save filelist
278                         if not self.loadedslideshowlistlistname:
279                                 newname = "slideshowlist"
280                         else:
281                                 newname = self.loadedslideshowlistlistname
282                         self.session.openWithCallback(
283                                         self.fileToSaveFilelistEntered,
284                                         InputBox,
285                                         title = _("Enter filename to save the List:"),
286                                         text = newname,
287                                         maxSize = False,
288                                         type = Input.TEXT
289                         )
290
291         def fileToLoadFilelistEntered(self, fileselection):
292                 if fileselection is not None:
293                            try:
294                                    filename = fileselection[1]
295                                    fp = open(config.plugins.pictureviewer.slideshowdir.value + filename)
296                                    list = []
297                                    for x in fp.readlines():
298                                            file = x.replace("\n","")
299                                            if x.startswith("#"):
300                                                    pass
301                                            elif not os.path.exists(file):
302                                                    print "["+myname+"] loaded file from filelist isnt avaible! ignoreing ->", file
303                                            else:
304                                                    list.append((_(file.split("/")[-1]), file))
305                                    self.slideshowfiles = list
306                                    self["slist"].l.setList(self.slideshowfiles)
307                                    self.loadedslideshowlistlistname = filename.replace(config.plugins.pictureviewer.slideshowext.value, "")
308                            except IOError, e:
309                                    print "["+myname+"] error:", e
310
311         def fileToSaveFilelistEntered(self, filename):
312                 if filename is not None:
313                         print "["+myname+"] saving list to ", config.plugins.pictureviewer.slideshowdir.value+filename + config.plugins.pictureviewer.slideshowext.value
314                         try:
315                                 if not os.path.exists(config.plugins.pictureviewer.slideshowdir.value):
316                                         print "+" * 10, os.path.basename(filename)
317                                         os.mkdir(config.plugins.pictureviewer.slideshowdir.value)
318                                 fp = open(config.plugins.pictureviewer.slideshowdir.value + filename+config.plugins.pictureviewer.slideshowext.value, "w")
319                                 fp.write("# this is a slideshow file for "+myname+" made by V"+myversion+"\n")
320                                 fp.write("# you can make your own... each line with full path of the imagefile\n")
321                                 fp.write("# by importing this file,we will ignoring a file if is doesnt exist\n")
322                                 for x in self.slideshowfiles:
323                                         fp.write(x[1] + "\n")
324                                 fp.close()
325                         except IOError, e:
326                                 print "["+myname+"] error:", e
327
328         def KeyYellow(self):
329                 if self.currList is "filelist":
330                         # add picture to list
331                         fullfile = self["menu"].getSelection()[0]
332                         if os.path.isfile(fullfile):
333                                 self.slideshowfiles.append((_(fullfile.split("/")[-1]), fullfile))
334                                 self["slist"].l.setList(self.slideshowfiles)
335                 else:
336                         # deleting an Picture
337                         if len(self.slideshowfiles) >= 1:
338                                 indexinlist = self["slist"].l.getCurrentSelectionIndex()
339                                 self.slideshowfiles.pop(indexinlist)
340                                 self["slist"].l.setList(self.slideshowfiles)
341
342         def switchList(self):
343                 if self.currList is "filelist" :
344                         # Slideshow activieren
345                         self.filelist.selectionEnabled(0)
346                         self.slideshowlist.selectionEnabled(1)
347                         self["buttonred"].setText("speichern")
348                         self["buttongreen"].setText("laden")
349                         self["buttonyellow"].setText("loeschen")
350                         self["buttonblue"].setText("Dateien")
351                         self.currList = "slideshowlist"
352                 else:
353                         # filelist activieren
354                         self.filelist.selectionEnabled(1)
355                         self.slideshowlist.selectionEnabled(0)
356                         self["buttonred"].setText("starte Slideshow")
357                         self["buttongreen"].setText("alle hinzufuegen")
358                         self["buttonyellow"].setText("hinzufuegen")
359                         self["buttonblue"].setText("Slideshow bearbeiten")
360                         self.currList = "filelist"
361
362         def go(self):
363                 if self.currList is "filelist" :
364                         selection = self["menu"].getSelection()
365                         if self.filelist.canDescent():
366                                 self.setTitle(selection[0])
367                                 self.filelist.descent()
368                         else:
369                                 if selection[1] == True: # isDir
370                                         pass
371                                 else:
372                                         print "["+myname+"] file selected ", selection[0]
373                                         if os.path.isfile(selection[0]):
374                                                 self.session.open(PictureScreen,selection[0].split("/")[-1], selection[0])
375                                         else:
376                                                 print "["+myname+"] file not found ", selection[0]
377                 else:
378                         self.updateInfoPanel()
379
380         def up(self):
381                  if self.currList is "filelist":
382                          self.filelist.up()
383                          self.updateInfoPanel()
384                  else:
385                          self.slideshowlist.up()
386
387         def leftUp(self):
388                  if self.currList is "filelist":
389                          self.filelist.pageUp()
390                          self.updateInfoPanel()
391                  else:
392                          self.slideshowlist.pageUp()
393
394         def rightUp(self):
395                 if self.currList is "filelist":
396                          self.filelist.pageDown()
397                          self.updateInfoPanel()
398                 else:
399                          self.slideshowlist.pageDown()
400
401         def down(self):
402                  if self.currList is "filelist":
403                          self.filelist.down()
404                          self.updateInfoPanel()
405                  else:
406                          self.slideshowlist.down()
407
408         def updateInfoPanel(self):
409                 if self.currList is "filelist":
410                         selectedfile = self["menu"].getSelection()[0]
411                 else:
412                         selectedfile = self["slist"].l.getCurrentSelection()[1]
413                 sc=AVSwitch().getFramebufferScale()
414                 self.picload = ePicLoad()
415                 self.picload.PictureData.get().append(self.updateInfoPanelCB)
416                 self.picload.setPara((self["pixmap"].instance.size().width(), self["pixmap"].instance.size().height(), sc[0], sc[1], False, 1, "#FF000000"))
417                 self.picload.startDecode(selectedfile)
418
419
420         def updateInfoPanelCB(self, picInfo = None):
421                 ptr = self.picload.getData()
422                 if ptr is not None:
423                         self["pixmap"].instance.setPixmap(ptr.__deref__())
424                 else:
425                         pass
426
427         def output(self,str):
428                 print "+" * 10, str
429
430         def openMenu(self):
431                 self.session.open(WebcamViewerMenu)
432 ###################
433 class WebcamViewer(Screen):
434         skin = ""
435         filelist = []
436         def __init__(self, session,xmlnode, args = 0):
437                 self.xmlnode = xmlnode
438                 screen_x = 736
439                 screen_y = 576
440                 size_x = 350
441                 size_y = 250
442                 pos_x = (screen_x/2)-(size_x/2)
443                 pos_y = (screen_y/2)-(size_y/2)
444                 skin = """
445                 <screen position="%i,%i" size="%i,%i" title="%s">
446                         <widget name="menu" position="1,1" size="%i,%i"  scrollbarMode="showOnDemand"/>
447                 </screen>""" % (pos_x,pos_y,size_x,size_y,myname,size_x,size_y)
448                 self.skin = skin
449                 Screen.__init__(self, session)
450
451                 self.filelist = MenuList(self.getMenuData())
452                 self["menu"] = self.filelist
453                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
454                         {
455                          "ok": self.go,
456                          "back": self.close,
457                          }, -1)
458                 self.onLayoutFinish.append(self.settingTitle)
459
460         def settingTitle(self):
461                 self.setTitle(myname + ": " + self.menutitle)
462
463         def go(self):
464                 selected = self["menu"].l.getCurrentSelection()[1]
465                 menuitemtitle = self["menu"].l.getCurrentSelection()[0]
466                 type = selected[0]
467                 data = selected[1]
468                 if menuitemtitle.startswith("webcam.travel"):
469                         self.session.openWithCallback(self.cb, TravelWebcamviewer)
470                 elif type.startswith("cam"):
471                         self.session.open(PictureScreen, menuitemtitle, data)
472                 else:
473                         self.hide()
474                         self.session.openWithCallback(self.cb, WebcamViewer, data)
475
476         def cb(self):
477                 self.show()
478
479         def getMenuData(self):
480                 xloader = XMLloader()
481                 self.menutitle = xloader.getScreenXMLTitle(self.xmlnode)
482                 data =[]
483                 if self.menutitle =="Mainmenu":
484                         data.append((_("webcam.travel"), "webcam.travel"))
485                 for node in self.xmlnode.childNodes:
486                         if node.nodeType != xml.dom.minidom.Element.nodeType or node.tagName != 'menu':
487                                 continue
488                         nodex = {}
489                         nodex['name'] = xloader.get_txt(node, "name", "no name")
490                         data.append((_("*" + nodex['name']), ["node", node]))
491
492                 for node in self.xmlnode.childNodes:
493                         if node.nodeType != xml.dom.minidom.Element.nodeType or node.tagName != 'cam':
494                                 continue
495                         nodex = {}
496                         nodex['name'] = xloader.get_txt(node, "name", "no name")
497                         nodex['url'] =xloader.get_txt(node, "url", "no url")
498                         data.append((_(nodex['name']), ["cam", nodex['url']]))
499                 return data
500 ###################
501
502 ##################
503 class PictureList(MenuList):
504         def __init__(self, directory, matchingPattern = None, enableWrapAround = False):
505                 MenuList.__init__(self, None, enableWrapAround, eListboxPythonMultiContent)
506                 self.showDirectories = True
507                 self.showFiles = True
508                 self.isTop = False
509                 self.matchingPattern = matchingPattern
510                 self.changeDir(directory)
511                 self.l.setFont(0, gFont("Regular", 18))
512                 self.currentDir = directory
513
514         def getCurrentDir(self):
515                 return self.currentDir
516
517         def getSelection(self):
518                 return self.l.getCurrentSelection()[0]
519
520         def getFileList(self):
521                 return self.list
522
523         def changeDir(self, directory):
524                 self.currentDir = directory
525                 self.list = []
526
527                 directories = []
528                 files = []
529                 files = os.listdir(directory)
530                 files.sort()
531                 tmpfiles = files[:]
532                 for x in tmpfiles:
533                         if os.path.isdir(directory + "/" + x):
534                                 directories.append(x)
535                                 files.remove(x)
536                 directories.sort()
537                 files.sort()
538                 if directory != "/" and self.showDirectories and not self.isTop:
539                         self.list.append(self.getPictureEntryComponent("..", '/'.join(directory.split('/')[:-2]) + '/', True))
540
541                 if self.showDirectories:
542                         for x in directories:
543                                 name = (directory+x).split('/')[-1]
544                                 self.list.append(self.getPictureEntryComponent(name, '/'.join(directory.split('/')[:-1]) + '/' + x + '/', True))
545
546                 if self.showFiles:
547                         for x in files:
548                                 path = directory + x
549                                 name = x
550                                 if self.matchingPattern is not None:
551                                         if compile(self.matchingPattern).search(path):
552                                                 self.list.append(self.getPictureEntryComponent(name,path, False))
553                                 else:
554                                         pass
555
556                 self.l.setList(self.list)
557
558         def canDescent(self):
559                 return self.getSelection()[1]
560
561         def descent(self):
562                 self.changeDir(self.getSelection()[0])
563
564         def getFilename(self):
565                 return self.getSelection()[0].getPath()
566
567         def getServiceRef(self):
568                 return self.getSelection()[0]
569
570         def postWidgetCreate(self, instance):
571                 MenuList.postWidgetCreate(self, instance)
572                 instance.setItemHeight(23)
573
574         def getPictureEntryComponent(self,name, absolute, isDir):
575                 """ name={angezeigter Name}, absolute={vollstaendiger Pfad}, isDir={True,False} """
576                 res = [ (absolute, isDir) ]
577                 res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 200, 20, 0, 0, name))
578                 if isDir:
579                         png = loadPNG("/usr/share/enigma2/extensions/directory.png")
580                 else:
581                         extension = name.split('.')
582                         extension = extension[-1].lower()
583                         if EXTENSIONS.has_key(extension):
584                                 png = loadPNG("/usr/share/enigma2/extensions/" + EXTENSIONS[extension] + ".png")
585                         else:
586                                 png = None
587                 if png is not None:
588                         res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
589                 return res
590
591
592 ##################
593 class XMLloader:
594         DEFAULT_NAMESPACES = (
595                   None, # RSS 0.91, 0.92, 0.93, 0.94, 2.0
596                   'http://purl.org/rss/1.0/', # RSS 1.0
597                   'http://my.netscape.com/rdf/simple/0.9/' # RSS 0.90
598                 )
599         DUBLIN_CORE = ('http://purl.org/dc/elements/1.1/',)
600         def getElementsByTagName(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
601                 for namespace in possibleNamespaces:
602                         children = node.getElementsByTagNameNS(namespace, tagName)
603                         if len(children):
604                                 return children
605                 return []
606
607         def node_data(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
608                 children = self.getElementsByTagName(node, tagName, possibleNamespaces)
609                 node = len(children) and children[0] or None
610                 return node and "".join([child.data.encode("utf-8") for child in node.childNodes]) or None
611
612         def get_txt(self, node, tagName, default_txt = ""):
613                 """
614                 Liefert den Inhalt >tagName< des >node< zurueck, ist dieser nicht
615                 vorhanden, wird >default_txt< zurueck gegeben.
616                 """
617                 return self.node_data(node, tagName) or self.node_data(node, tagName, self.DUBLIN_CORE) or default_txt
618
619         def getScreenXMLTitle(self,node):
620                 return self.get_txt(node, "name", "no title")
621