Merge branch 'master' into master_internal
[enigma2-plugins.git] / networkbrowser / src / NetworkBrowser.py
1 # -*- coding: utf-8 -*-
2 # for localized messages
3 #from __init__ import _
4 from enigma import eTimer, getDesktop
5 from Screens.Screen import Screen
6 from Screens.MessageBox import MessageBox
7 from Components.Label import Label
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.Sources.List import List
10 from Components.Sources.StaticText import StaticText
11 from Components.Network import iNetwork
12 from Components.Input import Input
13 from Components.config import getConfigListEntry, NoSave, config, ConfigIP
14 from Components.ConfigList import ConfigList, ConfigListScreen
15 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
16 from Tools.LoadPixmap import LoadPixmap
17 from cPickle import dump, load
18 from os import path as os_path, stat, mkdir, remove
19 from time import time
20 from stat import ST_MTIME
21
22 import netscan
23 from MountManager import AutoMountManager
24 from AutoMount import iAutoMount
25 from MountEdit import AutoMountEdit
26 from UserDialog import UserDialog
27
28 def write_cache(cache_file, cache_data):
29         #Does a cPickle dump
30         if not os_path.isdir( os_path.dirname(cache_file) ):
31                 try:
32                         mkdir( os_path.dirname(cache_file) )
33                 except OSError:
34                         print os_path.dirname(cache_file), '[Networkbrowser] is a file'
35         fd = open(cache_file, 'w')
36         dump(cache_data, fd, -1)
37         fd.close()
38
39 def valid_cache(cache_file, cache_ttl):
40         #See if the cache file exists and is still living
41         try:
42                 mtime = stat(cache_file)[ST_MTIME]
43         except:
44                 return 0
45         curr_time = time()
46         if (curr_time - mtime) > cache_ttl:
47                 return 0
48         else:
49                 return 1
50
51 def load_cache(cache_file):
52         #Does a cPickle load
53         fd = open(cache_file)
54         cache_data = load(fd)
55         fd.close()
56         return cache_data
57
58 class NetworkDescriptor:
59         def __init__(self, name = "NetworkServer", description = ""):
60                 self.name = name
61                 self.description = description
62
63 class NetworkBrowser(Screen):
64         skin = """
65                 <screen name="NetworkBrowser" position="90,80" size="560,450" title="Network Neighbourhood">
66                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
67                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
68                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
69                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
70                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
71                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
72                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
73                         <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
74                         <widget source="list" render="Listbox" position="5,50" size="540,350" zPosition="10" scrollbarMode="showOnDemand">
75                                 <convert type="TemplatedMultiContent">
76                                         {"template": [
77                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (48, 48), png = 1), # index 1 is the expandable/expanded/verticalline icon
78                                                         MultiContentEntryText(pos = (50, 4), size = (420, 26), font=2, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the Hostname
79                                                         MultiContentEntryText(pos = (140, 5), size = (320, 25), font=0, flags = RT_HALIGN_LEFT, text = 3), # index 3 is the sharename
80                                                         MultiContentEntryText(pos = (140, 26), size = (320, 17), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 4 is the sharedescription
81                                                         MultiContentEntryPixmapAlphaTest(pos = (45, 0), size = (48, 48), png = 5), # index 5 is the nfs/cifs icon
82                                                         MultiContentEntryPixmapAlphaTest(pos = (90, 0), size = (48, 48), png = 6), # index 6 is the isMounted icon
83                                                 ],
84                                         "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 24)],
85                                         "itemHeight": 50
86                                         }
87                                 </convert>
88                         </widget>
89                         <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="1" size="560,2" />         
90                         <widget source="infotext" render="Label" position="0,420" size="560,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
91                 </screen>"""
92
93         def __init__(self, session, iface,plugin_path):
94                 Screen.__init__(self, session)
95                 self.skin_path = plugin_path
96                 self.session = session
97                 self.iface = iface
98                 if self.iface is None:
99                         self.iface = 'eth0'
100                 self.networklist = None
101                 self.device = None
102                 self.mounts = None
103                 self.expanded = []
104                 self.cache_ttl = 604800 #Seconds cache is considered valid, 7 Days should be ok
105                 self.cache_file = '/etc/enigma2/networkbrowser.cache' #Path to cache directory
106
107                 self["key_red"] = StaticText(_("Close"))
108                 self["key_green"] = StaticText(_("Mounts management"))
109                 self["key_yellow"] = StaticText(_("Rescan"))
110                 self["key_blue"] = StaticText(_("Expert"))
111                 self["infotext"] = StaticText(_("Press OK to mount!"))
112                 
113                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
114                 {
115                         "ok": self.go,
116                         "back": self.close,
117                         "red": self.close,
118                         "green": self.keyGreen,
119                         "yellow": self.keyYellow,
120                         "blue": self.keyBlue,
121                 })
122
123                 self.list = []
124                 self.statuslist = []
125                 self.listindex = 0
126                 self["list"] = List(self.list)
127                 self["list"].onSelectionChanged.append(self.selectionChanged)
128
129                 self.onLayoutFinish.append(self.startRun)
130                 self.onShown.append(self.setWindowTitle)
131                 self.onClose.append(self.cleanup)
132                 self.Timer = eTimer()
133                 self.Timer_conn = self.Timer.timeout.connect(self.TimerFire)
134
135         def cleanup(self):
136                 del self.Timer
137                 iAutoMount.stopMountConsole()
138                 iNetwork.stopRestartConsole()
139                 iNetwork.stopGetInterfacesConsole()
140
141         def startRun(self):
142                 self.expanded = []
143                 self.setStatus('update')
144                 self.mounts = iAutoMount.getMountsList()
145                 self["infotext"].setText("")
146                 self.vc = valid_cache(self.cache_file, self.cache_ttl)
147                 if self.cache_ttl > 0 and self.vc != 0:
148                         self.process_NetworkIPs()
149                 else:
150                         self.Timer.start(3000)
151
152         def TimerFire(self):
153                 self.Timer.stop()
154                 self.process_NetworkIPs()
155
156         def setWindowTitle(self):
157                 self.setTitle(_("Browse network neighbourhood"))
158
159         def keyGreen(self):
160                 self.session.open(AutoMountManager, None, self.skin_path)
161
162         def keyYellow(self):
163                 if (os_path.exists(self.cache_file) == True):
164                         remove(self.cache_file)
165                 self.startRun()
166
167         def keyBlue(self):
168                 self.session.openWithCallback(self.scanIPclosed,ScanIP)
169
170         def scanIPclosed(self,result):
171                 if result[0]:
172                         if result[1] == "address":
173                                 print "[Networkbrowser] got IP:",result[1]
174                                 nwlist = []
175                                 nwlist.append(netscan.netzInfo(result[0] + "/24"))
176                                 self.networklist += nwlist[0]
177                         elif result[1] == "nfs":
178                                 self.networklist.append(['host', result[0], result[0] , '00:00:00:00:00:00', result[0], 'Master Browser'])
179
180                 if len(self.networklist) > 0:
181                         write_cache(self.cache_file, self.networklist)
182                         self.updateHostsList()
183
184         def setStatus(self,status = None):
185                 if status:
186                         self.statuslist = []
187                         if status == 'update':
188                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/update.png"))
189                                 self.statuslist.append(( ['info'], statuspng, _("Searching your network. Please wait..."), None, None, None, None ))
190                                 self['list'].setList(self.statuslist)
191                         elif status == 'error':
192                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/error.png"))
193                                 self.statuslist.append(( ['info'], statuspng, _("No network devices found!"), None, None, None, None ))
194                                 self['list'].setList(self.statuslist)
195
196         def process_NetworkIPs(self):
197                 self.inv_cache = 0
198                 self.vc = valid_cache(self.cache_file, self.cache_ttl)
199                 if self.cache_ttl > 0 and self.vc != 0:
200                         print '[Networkbrowser] Loading network cache from ',self.cache_file
201                         try:
202                                 self.networklist = load_cache(self.cache_file)
203                         except:
204                                 self.inv_cache = 1
205                 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
206                         print '[Networkbrowser] Getting fresh network list'
207                         self.networklist = self.getNetworkIPs()
208                         write_cache(self.cache_file, self.networklist)
209                 if len(self.networklist) > 0:
210                         self.updateHostsList()
211                 else:
212                         self.setStatus('error')
213
214         def getNetworkIPs(self):
215                 nwlist = []
216                 sharelist = []
217                 self.IP = iNetwork.getAdapterAttribute(self.iface, "ip")
218                 if len(self.IP):
219                         strIP = str(self.IP[0]) + "." + str(self.IP[1]) + "." + str(self.IP[2]) + ".0/24"
220                         nwlist.append(netscan.netzInfo(strIP))
221                 tmplist = nwlist[0]
222                 return tmplist
223
224         def getNetworkShares(self,hostip,hostname,devicetype):
225                 sharelist = []
226                 self.sharecache_file = None
227                 self.sharecache_file = '/etc/enigma2/' + hostname.strip() + '.cache' #Path to cache directory
228                 if os_path.exists(self.sharecache_file):
229                         print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
230                         try:
231                                 self.hostdata = load_cache(self.sharecache_file)
232                                 username = self.hostdata['username']
233                                 password = self.hostdata['password']
234                         except:
235                                 username = "username"
236                                 password = "password"
237                 else:
238                         username = "username"
239                         password = "password"
240
241                 if devicetype == 'unix':
242                         smblist=netscan.smbShare(hostip,hostname,username,password)
243                         for x in smblist:
244                                 if len(x) == 6:
245                                         if x[3] != 'IPC$':
246                                                 sharelist.append(x)
247                         nfslist=netscan.nfsShare(hostip,hostname)
248                         for x in nfslist:
249                                 if len(x) == 6:
250                                         sharelist.append(x)
251                 else:
252                         smblist=netscan.smbShare(hostip,hostname,username,password)
253                         for x in smblist:
254                                 if len(x) == 6:
255                                         if x[3] != 'IPC$':
256                                                 sharelist.append(x)
257                 return sharelist
258
259         def updateHostsList(self):
260                 self.list = []
261                 self.network = {}
262                 for x in self.networklist:
263                         if not self.network.has_key(x[2]):
264                                 self.network[x[2]] = []
265                         self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
266                 
267                 for x in self.network.keys():
268                         hostentry = self.network[x][0][1]
269                         name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
270                         expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
271                         self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
272
273                 if len(self.list):
274                         for entry in self.list:
275                                 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
276                         self.list.sort(key=lambda x: x[0][2])
277                         for entry in self.list:
278                                 entry[0][2]= entry[0][2].replace(" ", "")
279                 self["list"].setList(self.list)
280                 self["list"].setIndex(self.listindex)
281
282         def updateNetworkList(self):
283                 self.list = []
284                 self.network = {}
285                 self.mounts = iAutoMount.getMountsList() # reloading mount list
286                 for x in self.networklist:
287                         if not self.network.has_key(x[2]):
288                                 self.network[x[2]] = []
289                         self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
290                 self.network.keys().sort()
291                 for x in self.network.keys():
292                         if self.network[x][0][1][3] == '00:00:00:00:00:00':
293                                 self.device = 'unix'
294                         else:
295                                 self.device = 'windows'
296                         if x in self.expanded:
297                                 networkshares = self.getNetworkShares(x,self.network[x][0][1][1].strip(),self.device)
298                                 hostentry = self.network[x][0][1]
299                                 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
300                                 expandedIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
301                                 self.list.append(( hostentry, expandedIcon, name, None, None, None, None ))
302                                 for share in networkshares:
303                                         self.list.append(self.BuildNetworkShareEntry(share))
304                         else: # HOSTLIST - VIEW
305                                 hostentry = self.network[x][0][1]
306                                 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
307                                 expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
308                                 self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
309                 if len(self.list):
310                         for entry in self.list:
311                                 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
312                         self.list.sort(key=lambda x: x[0][2])
313                         for entry in self.list:
314                                 entry[0][2]= entry[0][2].replace(" ", "")
315                 self["list"].setList(self.list)
316                 self["list"].setIndex(self.listindex)
317
318         def BuildNetworkShareEntry(self,share):
319                 verticallineIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/verticalLine.png"))
320                 sharetype = share[0]
321                 localsharename = share[1]
322                 sharehost = share[2]
323
324                 if sharetype == 'smbShare':
325                         sharedir = share[3]
326                         sharedescription = share[5]
327                 else:
328                         sharedir = share[4]
329                         sharedescription = share[3]
330
331                 if sharetype == 'nfsShare':
332                         newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-nfs.png"))
333                 else:
334                         newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-smb.png"))
335
336                 self.isMounted = False
337                 for sharename, sharedata in self.mounts.items():
338                         if sharedata['ip'] == sharehost:
339                                 if sharetype == 'nfsShare' and sharedata['mounttype'] == 'nfs':
340                                         if sharedir == sharedata['sharedir']:
341                                                 if sharedata["isMounted"] is True:
342                                                         self.isMounted = True
343                                 if sharetype == 'smbShare' and sharedata['mounttype'] == 'cifs':
344                                         if sharedir == sharedata['sharedir']:
345                                                 if sharedata["isMounted"] is True:
346                                                         self.isMounted = True
347                 if self.isMounted is True:
348                         isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/ok.png"))
349                 else:
350                         isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/cancel.png"))
351
352                 return((share, verticallineIcon, None, sharedir, sharedescription, newpng, isMountedpng))
353
354         def selectionChanged(self):
355                 current = self["list"].getCurrent()
356                 self.listindex = self["list"].getIndex()
357                 if current:
358                         if len(current[0]) >= 2:
359                                 if current[0][0] in ("nfsShare", "smbShare"):
360                                         self["infotext"].setText(_("Press OK to mount this share!"))
361                                 else:
362                                         selectedhost = current[0][2]
363                                         if selectedhost in self.expanded:
364                                                 self["infotext"].setText(_("Press OK to collapse this host"))
365                                         else:
366                                                 self["infotext"].setText(_("Press OK to expand this host"))
367
368         def go(self):
369                 sel = self["list"].getCurrent()
370                 if sel is None:
371                         return
372                 if len(sel[0]) <= 1:
373                         return
374                 selectedhost = sel[0][2]
375                 selectedhostname = sel[0][1]
376
377                 self.hostcache_file = None
378                 if sel[0][0] == 'host': # host entry selected
379                         if selectedhost in self.expanded:
380                                 self.expanded.remove(selectedhost)
381                                 self.updateNetworkList()
382                         else:
383                                 self.hostcache_file = None
384                                 self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
385                                 if os_path.exists(self.hostcache_file):
386                                         print '[Networkbrowser] Loading userinfo cache from ',self.hostcache_file
387                                         try:
388                                                 self.hostdata = load_cache(self.hostcache_file)
389                                                 self.passwordQuestion(False)
390                                         except:
391                                                 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
392                                 else:
393                                         self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
394
395                 if sel[0][0] == 'nfsShare': # share entry selected
396                         print '[Networkbrowser] sel nfsShare'
397                         self.openMountEdit(sel[0])
398                 if sel[0][0] == 'smbShare': # share entry selected
399                         print '[Networkbrowser] sel cifsShare'
400                         self.hostcache_file = None
401                         self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
402                         if os_path.exists(self.hostcache_file):
403                                 print '[Networkbrowser] userinfo found from ',self.sharecache_file
404                                 self.openMountEdit(sel[0])
405                         else:
406                                 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
407
408         def passwordQuestion(self, ret = False):
409                 sel = self["list"].getCurrent()
410                 selectedhost = sel[0][2]
411                 selectedhostname = sel[0][1]
412                 if (ret == True):
413                         self.session.openWithCallback(self.UserDialogClosed, UserDialog, self.skin_path, selectedhostname.strip())
414                 else:
415                         if sel[0][0] == 'host': # host entry selected
416                                 if selectedhost in self.expanded:
417                                         self.expanded.remove(selectedhost)
418                                 else:
419                                         self.expanded.append(selectedhost)
420                                 self.updateNetworkList()
421                         if sel[0][0] == 'nfsShare': # share entry selected
422                                 self.openMountEdit(sel[0])
423                         if sel[0][0] == 'smbShare': # share entry selected
424                                 self.openMountEdit(sel[0])
425
426         def UserDialogClosed(self, *ret):
427                 if ret is not None and len(ret):
428                         self.go()
429
430         def openMountEdit(self, selection):
431                 if selection is not None and len(selection):
432                         mounts = iAutoMount.getMountsList()
433                         if selection[0] == 'nfsShare': # share entry selected
434                                 #Initialize blank mount enty
435                                 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
436                                 # add data
437                                 data['mounttype'] = 'nfs'
438                                 data['active'] = True
439                                 data['ip'] = selection[2]
440                                 data['sharename'] = selection[1]
441                                 data['sharedir'] = selection[4]
442                                 data['options'] = "rw,nolock,tcp"
443
444                                 for sharename, sharedata in mounts.items():
445                                         if sharedata['ip'] == selection[2] and sharedata['sharedir'] == selection[4]:
446                                                 data = sharedata
447                                 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
448                         if selection[0] == 'smbShare': # share entry selected
449                                 #Initialize blank mount enty
450                                 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
451                                 # add data
452                                 data['mounttype'] = 'cifs'
453                                 data['active'] = True
454                                 data['ip'] = selection[2]
455                                 data['sharename'] = selection[1]
456                                 data['sharedir'] = selection[3]
457                                 data['options'] = "rw"
458                                 self.sharecache_file = None
459                                 self.sharecache_file = '/etc/enigma2/' + selection[1].strip() + '.cache' #Path to cache directory
460                                 if os_path.exists(self.sharecache_file):
461                                         print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
462                                         try:
463                                                 self.hostdata = load_cache(self.sharecache_file)
464                                                 data['username'] = self.hostdata['username']
465                                                 data['password'] = self.hostdata['password']
466                                         except:
467                                                 data['username'] = "username"
468                                                 data['password'] = "password"
469                                 else:
470                                         data['username'] = "username"
471                                         data['password'] = "password"
472
473                                 for sharename, sharedata in mounts.items():
474                                         if sharedata['ip'] == selection[2].strip() and sharedata['sharedir'] == selection[3].strip():
475                                                 data = sharedata
476                                 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
477
478         def MountEditClosed(self, returnValue = None):
479                 if returnValue == None:
480                         self.updateNetworkList()
481
482 class ScanIP(Screen, ConfigListScreen):
483         skin = """
484                 <screen name="ScanIP" position="center,center" size="560,80" title="Scan IP" >
485                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
486                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
487                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
488                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
489                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
490                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
491                         <widget name="config" position="5,50" size="540,25" scrollbarMode="showOnDemand" />
492                 </screen>"""
493
494         def __init__(self, session):
495                 Screen.__init__(self, session)
496                 self.session = session
497
498                 self["key_red"] = StaticText(_("Cancel"))
499                 self["key_green"] = StaticText(_("Scan NFS share"))
500                 self["key_yellow"] = StaticText(_("Scan range"))
501
502                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
503                 {
504                         "back": self.exit,
505                         "red": self.exit,
506                         "cancel": self.exit,
507                         "green": self.goNfs,
508                         "yellow": self.goAddress,
509                 }, -1)
510                 
511                 self.ipAddress = ConfigIP(default=[0,0,0,0])
512                 
513                 ConfigListScreen.__init__(self, [
514                         getConfigListEntry(_("IP Address"), self.ipAddress),
515                 ], self.session)
516
517                 self.onLayoutFinish.append(self.layoutFinished)
518
519         def exit(self):
520                 self.close((None,None))
521
522         def layoutFinished(self):
523                 self.setWindowTitle()
524
525         def setWindowTitle(self):
526                 self.setTitle(_("Enter IP to scan..."))
527
528         def goAddress(self):
529                 if self.ipAddress.getText() != "0.0.0.0":
530                         self.close((self.ipAddress.getText(), "address"))
531                 else:
532                         self.exit
533
534         def goNfs(self):
535                 if self.ipAddress.getText() != "0.0.0.0":
536                         self.close((self.ipAddress.getText(), "nfs"))
537                 else:
538                         self.exit
539