Merge branch 'bug_532_fixed_servicelist_contextmenu_crash'
[enigma2.git] / lib / python / Plugins / SystemPlugins / SoftwareManager / BackupRestore.py
1 from Screens.Screen import Screen
2 from Screens.MessageBox import MessageBox
3 from Screens.Console import Console
4 from Components.ActionMap import ActionMap, NumberActionMap
5 from Components.Pixmap import Pixmap
6 from Components.Label import Label
7 from Components.Sources.StaticText import StaticText
8 from Components.MenuList import MenuList
9 from Components.config import getConfigListEntry, configfile, ConfigSelection, ConfigSubsection, ConfigText, ConfigLocations
10 from Components.config import config
11 from Components.ConfigList import ConfigList,ConfigListScreen
12 from Components.FileList import MultiFileSelectList
13 from Plugins.Plugin import PluginDescriptor
14 from enigma import eTimer
15 from Tools.Directories import *
16 from os import popen, path, makedirs, listdir, access, stat, rename, remove, W_OK, R_OK
17 from time import gmtime, strftime, localtime
18 from datetime import date
19
20
21 config.plugins.configurationbackup = ConfigSubsection()
22 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
23 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
24
25 def getBackupPath():
26         backuppath = config.plugins.configurationbackup.backuplocation.value
27         if backuppath.endswith('/'):
28                 return backuppath + 'backup'
29         else:
30                 return backuppath + '/backup'
31
32 def getBackupFilename():
33         return "enigma2settingsbackup.tar.gz"
34                 
35
36 class BackupScreen(Screen, ConfigListScreen):
37         skin = """
38                 <screen position="135,144" size="350,310" title="Backup is running" >
39                 <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
40                 </screen>"""
41                 
42         def __init__(self, session, runBackup = False):
43                 Screen.__init__(self, session)
44                 self.session = session
45                 self.runBackup = runBackup
46                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"], 
47                 {
48                         "ok": self.close,
49                         "back": self.close,
50                         "cancel": self.close,
51                 }, -1)
52                 self.finished_cb = None
53                 self.backuppath = getBackupPath()
54                 self.backupfile = getBackupFilename()
55                 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
56                 self.list = []
57                 ConfigListScreen.__init__(self, self.list)
58                 self.onLayoutFinish.append(self.layoutFinished)
59                 if self.runBackup:
60                         self.onShown.append(self.doBackup)
61
62         def layoutFinished(self):
63                 self.setWindowTitle()
64
65         def setWindowTitle(self):
66                 self.setTitle(_("Backup is running..."))
67
68         def doBackup(self):
69                 configfile.save()
70                 try:
71                         if (path.exists(self.backuppath) == False):
72                                 makedirs(self.backuppath)
73                         self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
74                         if path.exists(self.fullbackupfilename):
75                                 dt = str(date.fromtimestamp(stat(self.fullbackupfilename).st_ctime))
76                                 self.newfilename = self.backuppath + "/" + dt + '-' + self.backupfile
77                                 if path.exists(self.newfilename):
78                                         remove(self.newfilename)
79                                 rename(self.fullbackupfilename,self.newfilename)
80                         if self.finished_cb:
81                                 self.session.openWithCallback(self.finished_cb, Console, title = _("Backup is running..."), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB,closeOnSuccess = True)
82                         else:
83                                 self.session.open(Console, title = _("Backup is running..."), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB, closeOnSuccess = True)
84                 except OSError:
85                         if self.finished_cb:
86                                 self.session.openWithCallback(self.finished_cb, MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO, timeout = 10 )
87                         else:
88                                 self.session.openWithCallback(self.backupErrorCB,MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO, timeout = 10 )
89
90         def backupFinishedCB(self,retval = None):
91                 self.close(True)
92
93         def backupErrorCB(self,retval = None):
94                 self.close(False)
95
96         def runAsync(self, finished_cb):
97                 self.finished_cb = finished_cb
98                 self.doBackup()
99                 
100
101 class BackupSelection(Screen):
102         skin = """
103                 <screen name="BackupSelection" position="center,center" size="560,400" title="Select files/folders to backup">
104                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
105                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
106                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
107                         <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" />
108                         <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" />
109                         <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" />
110                         <widget name="checkList" position="5,50" size="550,250" transparent="1" scrollbarMode="showOnDemand" />
111                 </screen>"""
112
113         def __init__(self, session):
114                 Screen.__init__(self, session)
115                 self["key_red"] = StaticText(_("Cancel"))
116                 self["key_green"] = StaticText(_("Save"))
117                 self["key_yellow"] = StaticText()
118                 
119                 self.selectedFiles = config.plugins.configurationbackup.backupdirs.value
120                 defaultDir = '/'
121                 inhibitDirs = ["/bin", "/boot", "/dev", "/autofs", "/lib", "/proc", "/sbin", "/sys", "/hdd", "/tmp", "/mnt", "/media"]
122                 self.filelist = MultiFileSelectList(self.selectedFiles, defaultDir, inhibitDirs = inhibitDirs )
123                 self["checkList"] = self.filelist
124                 
125                 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ShortcutActions"],
126                 {
127                         "cancel": self.exit,
128                         "red": self.exit,
129                         "yellow": self.changeSelectionState,
130                         "green": self.saveSelection,
131                         "ok": self.okClicked,
132                         "left": self.left,
133                         "right": self.right,
134                         "down": self.down,
135                         "up": self.up
136                 }, -1)
137                 if not self.selectionChanged in self["checkList"].onSelectionChanged:
138                         self["checkList"].onSelectionChanged.append(self.selectionChanged)
139                 self.onLayoutFinish.append(self.layoutFinished)
140
141         def layoutFinished(self):
142                 idx = 0
143                 self["checkList"].moveToIndex(idx)
144                 self.setWindowTitle()
145                 self.selectionChanged()
146
147         def setWindowTitle(self):
148                 self.setTitle(_("Select files/folders to backup"))
149
150         def selectionChanged(self):
151                 current = self["checkList"].getCurrent()[0]
152                 if current[2] is True:
153                         self["key_yellow"].setText(_("Deselect"))
154                 else:
155                         self["key_yellow"].setText(_("Select"))
156                 
157         def up(self):
158                 self["checkList"].up()
159
160         def down(self):
161                 self["checkList"].down()
162
163         def left(self):
164                 self["checkList"].pageUp()
165
166         def right(self):
167                 self["checkList"].pageDown()
168
169         def changeSelectionState(self):
170                 self["checkList"].changeSelectionState()
171                 self.selectedFiles = self["checkList"].getSelectedList()
172
173         def saveSelection(self):
174                 self.selectedFiles = self["checkList"].getSelectedList()
175                 config.plugins.configurationbackup.backupdirs.value = self.selectedFiles
176                 config.plugins.configurationbackup.backupdirs.save()
177                 config.plugins.configurationbackup.save()
178                 config.save()
179                 self.close(None)
180
181         def exit(self):
182                 self.close(None)
183
184         def okClicked(self):
185                 if self.filelist.canDescent():
186                         self.filelist.descent()
187
188
189 class RestoreMenu(Screen):
190         skin = """
191                 <screen name="RestoreMenu" position="center,center" size="560,400" title="Restore backups" >
192                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
193                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
194                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
195                         <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" />
196                         <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" />
197                         <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" />
198                         <widget name="filelist" position="5,50" size="550,230" scrollbarMode="showOnDemand" />
199                 </screen>"""
200
201         def __init__(self, session, plugin_path):
202                 Screen.__init__(self, session)
203                 self.skin_path = plugin_path
204                 
205                 self["key_red"] = StaticText(_("Cancel"))
206                 self["key_green"] = StaticText(_("Restore"))
207                 self["key_yellow"] = StaticText(_("Delete"))
208
209                 self.sel = []
210                 self.val = []
211                 self.entry = False
212                 self.exe = False
213                 
214                 self.path = ""
215
216                 self["actions"] = NumberActionMap(["SetupActions"],
217                 {
218                         "ok": self.KeyOk,
219                         "cancel": self.keyCancel
220                 }, -1)
221
222                 self["shortcuts"] = ActionMap(["ShortcutActions"],
223                 {
224                         "red": self.keyCancel,
225                         "green": self.KeyOk,
226                         "yellow": self.deleteFile,
227                 })
228                 self.flist = []
229                 self["filelist"] = MenuList(self.flist)
230                 self.fill_list()
231                 self.onLayoutFinish.append(self.layoutFinished)
232
233         def layoutFinished(self):
234                 self.setWindowTitle()
235
236         def setWindowTitle(self):
237                 self.setTitle(_("Restore backups"))
238
239
240         def fill_list(self):
241                 self.flist = []
242                 self.path = getBackupPath()
243                 if (path.exists(self.path) == False):
244                         makedirs(self.path)
245                 for file in listdir(self.path):
246                         if (file.endswith(".tar.gz")):
247                                 self.flist.append((file))
248                                 self.entry = True
249                 self["filelist"].l.setList(self.flist)
250
251         def KeyOk(self):
252                 if (self.exe == False) and (self.entry == True):
253                         self.sel = self["filelist"].getCurrent()
254                         if self.sel:
255                                 self.val = self.path + "/" + self.sel
256                                 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore\nfollowing backup:\n") + self.sel + _("\nSystem will restart after the restore!"))
257
258         def keyCancel(self):
259                 self.close()
260
261         def startRestore(self, ret = False):
262                 if (ret == True):
263                         self.exe = True
264                         self.session.open(Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.path + "/" + self.sel + " -C /", "killall -9 enigma2"])
265
266         def deleteFile(self):
267                 if (self.exe == False) and (self.entry == True):
268                         self.sel = self["filelist"].getCurrent()
269                         if self.sel:
270                                 self.val = self.path + "/" + self.sel
271                                 self.session.openWithCallback(self.startDelete, MessageBox, _("Are you sure you want to delete\nfollowing backup:\n" + self.sel ))
272
273         def startDelete(self, ret = False):
274                 if (ret == True):
275                         self.exe = True
276                         print "removing:",self.val
277                         if (path.exists(self.val) == True):
278                                 remove(self.val)
279                         self.exe = False
280                         self.fill_list()
281
282 class RestoreScreen(Screen, ConfigListScreen):
283         skin = """
284                 <screen position="135,144" size="350,310" title="Restore is running..." >
285                 <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
286                 </screen>"""
287                 
288         def __init__(self, session, runRestore = False):
289                 Screen.__init__(self, session)
290                 self.session = session
291                 self.runRestore = runRestore
292                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
293                 {
294                         "ok": self.close,
295                         "back": self.close,
296                         "cancel": self.close,
297                 }, -1)
298                 self.finished_cb = None
299                 self.backuppath = getBackupPath()
300                 self.backupfile = getBackupFilename()
301                 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
302                 self.list = []
303                 ConfigListScreen.__init__(self, self.list)
304                 self.onLayoutFinish.append(self.layoutFinished)
305                 if self.runRestore:
306                         self.onShown.append(self.doRestore)
307
308         def layoutFinished(self):
309                 self.setWindowTitle()
310
311         def setWindowTitle(self):
312                 self.setTitle(_("Restore is running..."))
313
314         def doRestore(self):
315                 if path.exists("/proc/stb/vmpeg/0/dst_width"):
316                         restorecmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "echo 0 > /proc/stb/vmpeg/0/dst_height", "echo 0 > /proc/stb/vmpeg/0/dst_left", "echo 0 > /proc/stb/vmpeg/0/dst_top", "echo 0 > /proc/stb/vmpeg/0/dst_width", "killall -9 enigma2"]
317                 else:
318                         restorecmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "killall -9 enigma2"]
319                 if self.finished_cb:
320                         self.session.openWithCallback(self.finished_cb, Console, title = _("Restore is running..."), cmdlist = restorecmdlist)
321                 else:
322                         self.session.open(Console, title = _("Restore is running..."), cmdlist = restorecmdlist)
323
324         def backupFinishedCB(self,retval = None):
325                 self.close(True)
326
327         def backupErrorCB(self,retval = None):
328                 self.close(False)
329
330         def runAsync(self, finished_cb):
331                 self.finished_cb = finished_cb
332                 self.doRestore()