1 # for localized messages
4 from Plugins.Plugin import PluginDescriptor
5 from Screens.Screen import Screen
6 from Screens.InputBox import InputBox
7 from Screens.ChoiceBox import ChoiceBox
8 from Screens.MessageBox import MessageBox
9 from Components.config import config
10 from Components.ActionMap import ActionMap
11 from Components.Sources.StaticText import StaticText
12 from Components.SelectionList import SelectionList
13 from enigma import eServiceReference, eServiceCenter, iServiceInformation
14 from os import path as os_path
16 def main(session, service, **kwargs):
17 session.open(MovieTagEditor, service, session.current_dialog, **kwargs)
19 def Plugins(**kwargs):
21 from Screens.MovieSelection import setPreferredTagEditor
22 setPreferredTagEditor(TagEditor)
25 return PluginDescriptor(name = "TagEditor", description = _("edit tags..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc = main)
27 class TagEditor(Screen):
29 <screen name="TagEditor" position="center,center" size="565,280">
30 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
31 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
32 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
33 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
34 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
35 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
36 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
37 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
38 <widget name="list" position="5,40" size="555,240" scrollbarMode="showOnDemand" />
41 def __init__(self, session, tags, txt = None, args = 0, parent = None):
42 Screen.__init__(self, session, parent = parent)
45 self["key_red"] = StaticText(_("Cancel"))
46 self["key_green"] = StaticText(_("OK"))
47 self["key_yellow"] = StaticText(_("New"))
48 self["key_blue"] = StaticText(_("Load"))
50 self["list"] = SelectionList()
52 allTags = self.loadTagsFile()
53 self.joinTags(allTags, tags)
54 self.updateMenuList(allTags, tags)
56 self.ghostlist = tags[:]
57 self.ghosttags = allTags[:]
58 self.origtags = allTags[:]
62 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MenuActions"],
64 "ok": self["list"].toggleSelection,
65 "cancel": self.cancel,
68 "yellow": self.addCustom,
69 "blue": self.loadFromHdd,
73 self.onLayoutFinish.append(self.setCustomTitle)
75 def setCustomTitle(self):
76 self.setTitle(_("Edit Tags"))
79 self.session.openWithCallback(
80 self.addCustomCallback,
82 title = _("Please enter the new tag")
85 def addCustomCallback(self, ret):
86 ret = ret and ret.strip().replace(" ","_").capitalize()
88 if ret and ret not in tags:
90 self.updateMenuList(tags, [ret])
92 def loadTagsFile(self):
94 file = open("/etc/enigma2/movietags")
95 tags = [x.rstrip() for x in file.readlines()]
103 def saveTagsFile(self, tags):
105 file = open("/etc/enigma2/movietags", "w")
106 file.write("\n".join(tags)+"\n")
111 def joinTags(self, taglist, newtags):
113 if not tag in taglist:
116 def setTimerTags(self, timer, tags):
117 if timer.tags != tags:
119 self.timerdirty = True
121 def setMovieTags(self, ref, tags):
123 if file.endswith(".ts"):
124 file = file + ".meta"
126 file = file + ".ts.meta"
127 if os_path.exists(file):
128 metafile = open(file, "r")
129 sid = metafile.readline()
130 title = metafile.readline()
131 descr = metafile.readline()
132 time = metafile.readline()
133 oldtags = metafile.readline().rstrip()
135 tags = " ".join(tags)
137 metafile = open(file, "w")
138 metafile.write("%s%s%s%s%s" %(sid, title, descr, time, tags))
141 def foreachTimerTags(self, func):
142 self.timerdirty = False
143 for timer in self.session.nav.RecordTimer.timer_list + self.session.nav.RecordTimer.processed_timers:
145 func(timer, timer.tags[:])
147 self.session.nav.RecordTimer.saveTimer()
149 def foreachMovieTags(self, func):
150 serviceHandler = eServiceCenter.getInstance()
151 for dir in config.movielist.videodirs.value:
152 if os_path.isdir(dir):
153 root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + dir)
154 list = serviceHandler.list(root)
158 serviceref = list.getNext()
159 if not serviceref.valid():
161 if (serviceref.flags & eServiceReference.mustDescent):
163 info = serviceHandler.info(serviceref)
166 tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ')
167 if not tags or tags == ['']:
169 func(serviceref, tags)
171 def updateMenuList(self, tags, extrasel = []):
172 seltags = [x[1] for x in self["list"].getSelectionsList()] + extrasel
174 self["list"].setList([])
176 self["list"].addSelection(tag, tag, 0, tag in seltags)
178 def loadFromHdd(self):
180 self.foreachTimerTags(lambda t, tg: self.joinTags(tags, tg))
181 self.foreachMovieTags(lambda r, tg: self.joinTags(tags, tg))
182 self.updateMenuList(tags)
185 def removeUnused(self):
186 tags = [x[1] for x in self["list"].getSelectionsList()]
187 self.foreachTimerTags(lambda t, tg: self.joinTags(tags, tg))
188 self.foreachMovieTags(lambda r, tg: self.joinTags(tags, tg))
189 self.updateMenuList(tags)
192 def listReplace(self, lst, fr, to = None):
195 if to != None and not to in lst:
201 self.thistag = self["list"].list[self["list"].getSelectedIndex()][0]
202 self.session.openWithCallback(
203 self.renameTagCallback,
205 title = _("Replace tag \"%s\" everywhere with: (Note that 'Cancel' will not undo this!)") % (self.thistag[1]),
206 text = self.thistag[1]
209 def renameTagCallback(self, res):
210 res = res and res.strip().replace(" ", "_").capitalize()
211 if res and len(res) and res != self.thistag[1]:
212 thistag = self.thistag[1]
213 self.foreachTimerTags(lambda t, tg: (thistag in tg) and self.setTimerTags(t, self.listReplace(tg, thistag, res)))
214 self.foreachMovieTags(lambda r, tg: (thistag in tg) and self.setMovieTags(r, self.listReplace(tg, thistag, res)))
215 self.listReplace(self.tags, thistag, res)
216 self.listReplace(self.ghosttags, thistag, res)
217 self.listReplace(self.ghostlist, thistag, res)
218 self.updateMenuList(self.tags, self.thistag[3] and [res] or [])
221 self.thistag = self["list"].list[self["list"].getSelectedIndex()][0]
222 self.session.openWithCallback(
223 self.removeTagCallback,
225 _("Do you really want to delete tag \"%s\" everywhere?\n(Note that 'Cancel' will not undo this!)") % (self.thistag[1])
228 def removeTagCallback(self, res):
230 thistag = self.thistag[1]
231 self.foreachTimerTags(lambda t, tg: (thistag in tg) and self.setTimerTags(t, self.listReplace(tg, thistag)))
232 self.foreachMovieTags(lambda r, tg: (thistag in tg) and self.setMovieTags(r, self.listReplace(tg, thistag)))
233 self.listReplace(self.tags, thistag)
234 self.listReplace(self.ghosttags, thistag)
235 self.listReplace(self.ghostlist, thistag)
236 self.updateMenuList(self.tags)
239 self.session.openWithCallback(
240 self.removeAllCallback,
242 _("Do you really want to delete all tags everywhere?\n(Note that 'Cancel' will not undo this!)")
245 def removeAllCallback(self, res):
247 self.foreachTimerTags(lambda t, tg: tg and self.setTimerTags(t, []))
248 self.foreachMovieTags(lambda r, tg: tg and self.setMovieTags(r, []))
252 self.updateMenuList(self.tags)
256 (_("Add new tag..."), self.addCustom),
257 (_("Rename this tag..."), self.renameTag),
258 (_("Delete this tag..."), self.removeTag),
259 (_("Delete unused tags"), self.removeUnused),
260 (_("Delete all tags..."), self.removeAll)
262 self.session.openWithCallback(self.menuCallback, ChoiceBox, title = "", list = menu)
264 def menuCallback(self, choice):
269 if not self.origtags == self.ghosttags:
270 self.saveTagsFile(self.ghosttags)
271 self.close(self.ghostlist)
276 list = [x[1] for x in self["list"].getSelectionsList()]
277 if not self.origtags == self.tags:
278 self.saveTagsFile(self.tags)
281 class MovieTagEditor(TagEditor):
282 def __init__(self, session, service, parent, args = 0):
283 self.service = service
284 serviceHandler = eServiceCenter.getInstance()
285 info = serviceHandler.info(service)
286 path = service.getPath()
287 if path.endswith(".ts"):
290 tags = info.getInfoString(service, iServiceInformation.sTags)
292 tags = tags.split(' ')
295 TagEditor.__init__(self, session, tags, args, parent = parent)
297 def saveTags(self, file, tags):
298 if os_path.exists(file + ".ts.meta"):
299 metafile = open(file + ".ts.meta", "r")
300 sid = metafile.readline()
301 title = metafile.readline()
302 descr = metafile.readline()
303 time = metafile.readline()
304 oldtags = metafile.readline().rstrip()
306 tags = " ".join(tags)
308 metafile = open(file + ".ts.meta", "w")
309 metafile.write("%s%s%s%s%s" %(sid, title, descr, time, tags))
313 if not self.origtags == self.ghosttags:
314 self.saveTagsFile(self.ghosttags)
320 list = [x[1] for x in self["list"].getSelectionsList()]
321 if not self.origtags == self.tags:
322 self.saveTagsFile(self.tags)
323 self.saveTags(self.path, list)
326 def exitDialog(self):
328 # This will try to get back to an updated movie list.
329 # A proper way to do this should be provided in enigma2.
331 parentscreen = self.parent
332 parentscreen.csel.reloadList()
334 except AttributeError: