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