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.Button import Button
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" title="Edit Tags" position="75,155" size="565,280">
30 <widget name="list" position="5,5" size="555,225" scrollbarMode="showOnDemand" />
31 <ePixmap position="0,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
32 <ePixmap position="140,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
33 <ePixmap position="280,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
34 <ePixmap position="420,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
35 <widget name="key_red" position="0,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
36 <widget name="key_green" position="140,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
37 <widget name="key_yellow" position="280,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
38 <widget name="key_blue" position="420,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
41 def __init__(self, session, tags, txt = None, args = 0, parent = None):
42 Screen.__init__(self, session, parent = parent)
45 self["key_red"] = Button(_("Cancel"))
46 self["key_green"] = Button(_("OK"))
47 self["key_yellow"] = Button(_("New"))
48 self["key_blue"] = Button(_("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,
74 self.session.openWithCallback(
75 self.addCustomCallback,
77 title = _("Please enter the new tag")
80 def addCustomCallback(self, ret):
81 ret = ret and ret.strip().replace(" ","_").capitalize()
83 if ret and ret not in tags:
85 self.updateMenuList(tags, [ret])
87 def loadTagsFile(self):
89 file = open("/etc/enigma2/movietags")
90 tags = [x.rstrip() for x in file.readlines()]
98 def saveTagsFile(self, tags):
100 file = open("/etc/enigma2/movietags", "w")
101 file.write("\n".join(tags)+"\n")
106 def joinTags(self, taglist, newtags):
108 if not tag in taglist:
111 def setTimerTags(self, timer, tags):
112 if timer.tags != tags:
114 self.timerdirty = True
116 def setMovieTags(self, ref, tags):
118 if file.endswith(".ts"):
119 file = file + ".meta"
121 file = file + ".ts.meta"
122 if os_path.exists(file):
123 metafile = open(file, "r")
124 sid = metafile.readline()
125 title = metafile.readline()
126 descr = metafile.readline()
127 time = metafile.readline()
128 oldtags = metafile.readline().rstrip()
130 tags = " ".join(tags)
132 metafile = open(file, "w")
133 metafile.write("%s%s%s%s%s" %(sid, title, descr, time, tags))
136 def foreachTimerTags(self, func):
137 self.timerdirty = False
138 for timer in self.session.nav.RecordTimer.timer_list + self.session.nav.RecordTimer.processed_timers:
140 func(timer, timer.tags[:])
142 self.session.nav.RecordTimer.saveTimer()
144 def foreachMovieTags(self, func):
145 serviceHandler = eServiceCenter.getInstance()
146 for dir in config.movielist.videodirs.value:
147 if os_path.isdir(dir):
148 root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + dir)
149 list = serviceHandler.list(root)
153 serviceref = list.getNext()
154 if not serviceref.valid():
156 if (serviceref.flags & eServiceReference.mustDescent):
158 info = serviceHandler.info(serviceref)
161 tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ')
162 if not tags or tags == ['']:
164 func(serviceref, tags)
166 def updateMenuList(self, tags, extrasel = []):
167 seltags = [x[1] for x in self["list"].getSelectionsList()] + extrasel
169 self["list"].setList([])
171 self["list"].addSelection(tag, tag, 0, tag in seltags)
173 def loadFromHdd(self):
175 self.foreachTimerTags(lambda t, tg: self.joinTags(tags, tg))
176 self.foreachMovieTags(lambda r, tg: self.joinTags(tags, tg))
177 self.updateMenuList(tags)
180 def removeUnused(self):
181 tags = [x[1] for x in self["list"].getSelectionsList()]
182 self.foreachTimerTags(lambda t, tg: self.joinTags(tags, tg))
183 self.foreachMovieTags(lambda r, tg: self.joinTags(tags, tg))
184 self.updateMenuList(tags)
187 def listReplace(self, lst, fr, to = None):
190 if to != None and not to in lst:
196 self.thistag = self["list"].list[self["list"].getSelectedIndex()][0]
197 self.session.openWithCallback(
198 self.renameTagCallback,
200 title = _("Replace tag \"%s\" everywhere with: (Note that 'Cancel' will not undo this!)") % (self.thistag[1]),
201 text = self.thistag[1]
204 def renameTagCallback(self, res):
205 res = res and res.strip().replace(" ", "_").capitalize()
206 if res and len(res) and res != self.thistag[1]:
207 thistag = self.thistag[1]
208 self.foreachTimerTags(lambda t, tg: (thistag in tg) and self.setTimerTags(t, self.listReplace(tg, thistag, res)))
209 self.foreachMovieTags(lambda r, tg: (thistag in tg) and self.setMovieTags(r, self.listReplace(tg, thistag, res)))
210 self.listReplace(self.tags, thistag, res)
211 self.listReplace(self.ghosttags, thistag, res)
212 self.listReplace(self.ghostlist, thistag, res)
213 self.updateMenuList(self.tags, self.thistag[3] and [res] or [])
216 self.thistag = self["list"].list[self["list"].getSelectedIndex()][0]
217 self.session.openWithCallback(
218 self.removeTagCallback,
220 _("Do you really want to delete tag \"%s\" everywhere?\n(Note that 'Cancel' will not undo this!)") % (self.thistag[1])
223 def removeTagCallback(self, res):
225 thistag = self.thistag[1]
226 self.foreachTimerTags(lambda t, tg: (thistag in tg) and self.setTimerTags(t, self.listReplace(tg, thistag)))
227 self.foreachMovieTags(lambda r, tg: (thistag in tg) and self.setMovieTags(r, self.listReplace(tg, thistag)))
228 self.listReplace(self.tags, thistag)
229 self.listReplace(self.ghosttags, thistag)
230 self.listReplace(self.ghostlist, thistag)
231 self.updateMenuList(self.tags)
234 self.session.openWithCallback(
235 self.removeAllCallback,
237 _("Do you really want to delete all tags everywhere?\n(Note that 'Cancel' will not undo this!)")
240 def removeAllCallback(self, res):
242 self.foreachTimerTags(lambda t, tg: tg and self.setTimerTags(t, []))
243 self.foreachMovieTags(lambda r, tg: tg and self.setMovieTags(r, []))
247 self.updateMenuList(self.tags)
251 (_("Add new tag..."), self.addCustom),
252 (_("Rename this tag..."), self.renameTag),
253 (_("Delete this tag..."), self.removeTag),
254 (_("Delete unused tags"), self.removeUnused),
255 (_("Delete all tags..."), self.removeAll)
257 self.session.openWithCallback(self.menuCallback, ChoiceBox, title = "", list = menu)
259 def menuCallback(self, choice):
264 if not self.origtags == self.ghosttags:
265 self.saveTagsFile(self.ghosttags)
266 self.close(self.ghostlist)
271 list = [x[1] for x in self["list"].getSelectionsList()]
272 if not self.origtags == self.tags:
273 self.saveTagsFile(self.tags)
276 class MovieTagEditor(TagEditor):
277 def __init__(self, session, service, parent, args = 0):
278 self.service = service
279 serviceHandler = eServiceCenter.getInstance()
280 info = serviceHandler.info(service)
281 path = service.getPath()
282 if path.endswith(".ts"):
285 tags = info.getInfoString(service, iServiceInformation.sTags)
287 tags = tags.split(' ')
290 TagEditor.__init__(self, session, tags, args, parent = parent)
292 def saveTags(self, file, tags):
293 if os_path.exists(file + ".ts.meta"):
294 metafile = open(file + ".ts.meta", "r")
295 sid = metafile.readline()
296 title = metafile.readline()
297 descr = metafile.readline()
298 time = metafile.readline()
299 oldtags = metafile.readline().rstrip()
301 tags = " ".join(tags)
303 metafile = open(file + ".ts.meta", "w")
304 metafile.write("%s%s%s%s%s" %(sid, title, descr, time, tags))
308 if not self.origtags == self.ghosttags:
309 self.saveTagsFile(self.ghosttags)
315 list = [x[1] for x in self["list"].getSelectionsList()]
316 if not self.origtags == self.tags:
317 self.saveTagsFile(self.tags)
318 self.saveTags(self.path, list)
321 def exitDialog(self):
323 # This will try to get back to an updated movie list.
324 # A proper way to do this should be provided in enigma2.
326 parentscreen = self.parent
327 parentscreen.csel.reloadList()
329 except AttributeError: