2 # Generic Screen to select a path/filename combination
6 from Screens.Screen import Screen
7 from Screens.MessageBox import MessageBox
8 from Screens.InputBox import InputBox
11 from Tools.BoundFunction import boundFunction
14 from Tools.NumericalTextInput import NumericalTextInput
17 from Components.ActionMap import NumberActionMap
18 from Components.Label import Label
19 from Components.Pixmap import Pixmap
20 from Components.Button import Button
21 from Components.FileList import FileList
24 from enigma import eTimer
26 class LocationBox(Screen, NumericalTextInput):
27 """Simple Class similar to MessageBox / ChoiceBox but used to choose a folder/pathname combination"""
29 skin = """<screen name="LocationBox" position="100,130" size="540,340" >
30 <widget name="text" position="0,2" size="540,22" font="Regular;22" />
31 <widget name="filelist" position="0,25" size="540,235" />
32 <widget name="target" position="0,260" size="540,40" valign="center" font="Regular;22" />
33 <widget name="yellow" position="260,300" zPosition="1" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
34 <widget name="key_yellow" position="260,300" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
35 <widget name="green" position="400,300" zPosition="1" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
36 <widget name="key_green" position="400,300" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
39 def __init__(self, session, text = "", filename = "", currDir = None, windowTitle = _("Select Location"), minFree = None):
41 Screen.__init__(self, session)
42 NumericalTextInput.__init__(self, handleTimeout = False)
45 self.setUseableChars(u'1234567890abcdefghijklmnopqrstuvwxyz')
48 self.qs_timer = eTimer()
49 self.qs_timer.callback.append(self.timeout)
50 self.qs_timer_type = 0
52 # Initialize Quickselect
57 self["text"] = Label(text)
59 # Save parameters locally
61 self.filename = filename
62 self.minFree = minFree
65 self["filelist"] = FileList(currDir, showDirectories = True, showFiles = False)
68 self["key_green"] = Button(_("Confirm"))
69 self["key_yellow"] = Button(_("Rename"))
71 # Background for Buttons
72 self["green"] = Pixmap()
73 self["yellow"] = Pixmap()
76 self["target"] = Label()
78 # Custom Action Handler
79 class LocationBoxActionMap(NumberActionMap):
80 def __init__(self, box, contexts = [ ], actions = { }, prio=0):
81 NumberActionMap.__init__(self, contexts, actions, prio)
84 def action(self, contexts, action):
86 self.box.timeout(force = True)
88 return NumberActionMap.action(self, contexts, action)
90 # Actions that will reset quickselect
91 self["actions"] = LocationBoxActionMap(self, ["WizardActions", "ColorActions"],
96 "yellow": self.changeName,
103 # Actions used by quickselect
104 self["NumberActions"] = NumberActionMap(["NumberActions"],
106 "1": self.keyNumberGlobal,
107 "2": self.keyNumberGlobal,
108 "3": self.keyNumberGlobal,
109 "4": self.keyNumberGlobal,
110 "5": self.keyNumberGlobal,
111 "6": self.keyNumberGlobal,
112 "7": self.keyNumberGlobal,
113 "8": self.keyNumberGlobal,
114 "9": self.keyNumberGlobal,
115 "0": self.keyNumberGlobal
118 # Run some functions when shown
119 self.onShown.extend([
120 boundFunction(self.setTitle, windowTitle),
125 # Make sure we remove our callback
126 self.onClose.append(self.disableTimer)
128 def disableTimer(self):
129 self.qs_timer.callback.remove(self.timeout)
131 def showHideRename(self):
132 # Don't allow renaming when filename is empty
133 if self.filename == "":
134 self["yellow"].hide()
135 self["key_yellow"].hide()
138 self["filelist"].up()
141 self["filelist"].down()
144 self["filelist"].pageUp()
147 self["filelist"].pageDown()
150 if self["filelist"].canDescent():
151 self["filelist"].descent()
157 def selectConfirmed(self, res):
159 self.close(''.join([self["filelist"].getCurrentDirectory(), self.filename]))
162 # Do nothing unless current Directory is valid
163 if self["filelist"].getCurrentDirectory() is not None:
164 # Check if we need to have a minimum of free Space available
165 if self.minFree is not None:
166 # Try to read fs stats
168 from os import statvfs
170 s = statvfs(self["filelist"].getCurrentDirectory())
171 if (s.f_bavail * s.f_bsize) / 1000000 > self.minFree:
172 # Automatically confirm if we have enough free disk Space available
173 return self.selectConfirmed(True)
177 # Ask User if he really wants to select this folder
178 self.session.openWithCallback(
179 self.selectConfirmed,
181 _("There might not be enough Space on the selected Partition.\nDo you really want to continue?"),
182 type = MessageBox.TYPE_YESNO
184 # No minimum free Space means we can safely close
186 self.selectConfirmed(True)
188 def changeName(self):
189 if self.filename != "":
190 # TODO: Add Information that changing extension is bad? disallow?
191 # TODO: decide if using an inputbox is ok - we could also keep this in here
192 self.session.openWithCallback(
195 title = _("Please enter a new filename"),
199 def nameChanged(self, res):
207 _("An empty filename is illegal."),
208 type = MessageBox.TYPE_ERROR,
212 def updateTarget(self):
213 # Write Combination of Folder & Filename when Folder is valid
214 if self["filelist"].getCurrentDirectory() is not None:
215 self["target"].setText(''.join([self["filelist"].getCurrentDirectory(), self.filename]))
218 self["target"].setText(_("Invalid Location"))
220 def keyNumberGlobal(self, number):
224 # See if another key was pressed before
225 if number != self.lastKey:
226 # Reset lastKey again so NumericalTextInput triggers its keychange
229 # Try to select what was typed
235 # Get char and append to text
236 char = self.getKey(number)
237 self.quickselect = self.quickselect[:self.curr_pos] + unicode(char)
240 self.qs_timer_type = 0
241 self.qs_timer.start(1000, 1)
243 def selectByStart(self):
244 # Don't do anything on initial call
245 if not len(self.quickselect):
248 # Don't select if no dir
249 if self["filelist"].getCurrentDirectory():
250 # TODO: implement proper method in Components.FileList
251 files = self["filelist"].getFileList()
256 # We select by filename which is absolute
257 lookfor = self["filelist"].getCurrentDirectory() + self.quickselect
259 # Select file starting with generated text
261 if file[0][0] and file[0][0].lower().startswith(lookfor):
262 self["filelist"].instance.moveSelectionTo(idx)
266 def timeout(self, force = False):
268 if not force and self.qs_timer_type == 0:
269 # Try to select what was typed
276 self.qs_timer_type = 1
278 # Start timeout again
279 self.qs_timer.start(1000, 1)
280 # Timeout Quickselect
282 # Eventually stop Timer
288 self.quickselect = ""
291 return str(type(self)) + "(" + self.text + ")"