--- /dev/null
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+from Screens.Console import Console
+from Components.ActionMap import ActionMap, NumberActionMap
+from Components.Pixmap import Pixmap
+from Components.Label import Label
+from Components.MenuList import MenuList
+from Components.config import getConfigListEntry, configfile, ConfigSelection, ConfigSubsection, ConfigText, ConfigLocations
+from Components.config import config
+from Components.ConfigList import ConfigList,ConfigListScreen
+from Components.FileList import MultiFileSelectList
+from Plugins.Plugin import PluginDescriptor
+from enigma import eTimer
+from Tools.Directories import *
+from os import popen, path, makedirs, listdir, access, stat, rename, remove, W_OK, R_OK
+from time import gmtime, strftime, localtime
+from datetime import date
+
+
+config.plugins.configurationbackup = ConfigSubsection()
+config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
+config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf'])
+
+def getBackupPath():
+ backuppath = config.plugins.configurationbackup.backuplocation.value
+ if backuppath.endswith('/'):
+ return backuppath + 'backup'
+ else:
+ return backuppath + '/backup'
+
+def getBackupFilename():
+ return "enigma2settingsbackup.tar.gz"
+
+
+class BackupScreen(Screen, ConfigListScreen):
+ skin = """
+ <screen position="135,144" size="350,310" title="Backup running..." >
+ <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
+ </screen>"""
+
+ def __init__(self, session, runBackup = False):
+ Screen.__init__(self, session)
+ self.session = session
+ self.runBackup = runBackup
+ self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
+ {
+ "ok": self.close,
+ "back": self.close,
+ "cancel": self.close,
+ }, -1)
+ self.finished_cb = None
+ self.backuppath = getBackupPath()
+ self.backupfile = getBackupFilename()
+ self.fullbackupfilename = self.backuppath + "/" + self.backupfile
+ self.list = []
+ ConfigListScreen.__init__(self, self.list)
+ self.onLayoutFinish.append(self.layoutFinished)
+ if self.runBackup:
+ self.onShown.append(self.doBackup)
+
+ def layoutFinished(self):
+ self.setWindowTitle()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Backup running..."))
+
+ def doBackup(self):
+ try:
+ if (path.exists(self.backuppath) == False):
+ makedirs(self.backuppath)
+ self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
+ if path.exists(self.fullbackupfilename):
+ dt = str(date.fromtimestamp(stat(self.fullbackupfilename).st_ctime))
+ self.newfilename = self.backuppath + "/" + dt + '-' + self.backupfile
+ if path.exists(self.newfilename):
+ remove(self.newfilename)
+ rename(self.fullbackupfilename,self.newfilename)
+ if self.finished_cb:
+ self.session.openWithCallback(self.finished_cb, Console, title = _("Backup running"), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB,closeOnSuccess = True)
+ else:
+ self.session.open(Console, title = _("Backup running"), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB, closeOnSuccess = True)
+ except OSError:
+ if self.finished_cb:
+ self.session.openWithCallback(self.finished_cb, MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO)
+ else:
+ self.session.openWithCallback(self.backupErrorCB,MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO)
+
+ def backupFinishedCB(self,retval = None):
+ self.close(True)
+
+ def backupErrorCB(self,retval = None):
+ self.close(False)
+
+ def runAsync(self, finished_cb):
+ self.finished_cb = finished_cb
+ self.doBackup()
+
+
+class BackupSelection(Screen):
+ skin = """
+ <screen position="135,125" size="450,310" title="Select files/folders to backup...">
+ <widget name="checkList" position="10,10" size="430,250" transparent="1" scrollbarMode="showOnDemand" />
+ <ePixmap position="0,265" zPosition="1" size="135,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+ <widget name="key_red" position="0,265" zPosition="2" size="135,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
+ <ePixmap position="135,265" zPosition="1" size="135,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+ <widget name="key_green" position="135,265" zPosition="2" size="135,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
+ <ePixmap position="270,265" zPosition="1" size="135,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
+ <widget name="key_yellow" position="270,265" zPosition="2" size="135,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
+ </screen>"""
+
+ def __init__(self, session):
+ Screen.__init__(self, session)
+ self.skin_path = plugin_path
+ self["key_red"] = Label(_("Cancel"))
+ self["key_green"] = Label(_("Save"))
+ self["key_yellow"] = Label()
+
+ self.selectedFiles = config.plugins.configurationbackup.backupdirs.value
+ defaultDir = '/'
+ inhibitDirs = ["/bin", "/boot", "/dev", "/autofs", "/lib", "/proc", "/sbin", "/sys", "/hdd", "/tmp", "/mnt", "/media"]
+ self.filelist = MultiFileSelectList(self.selectedFiles, defaultDir, inhibitDirs = inhibitDirs )
+ self["checkList"] = self.filelist
+
+ self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ShortcutActions"],
+ {
+ "cancel": self.exit,
+ "red": self.exit,
+ "yellow": self.changeSelectionState,
+ "green": self.saveSelection,
+ "ok": self.okClicked,
+ "left": self.left,
+ "right": self.right,
+ "down": self.down,
+ "up": self.up
+ }, -1)
+ if not self.selectionChanged in self["checkList"].onSelectionChanged:
+ self["checkList"].onSelectionChanged.append(self.selectionChanged)
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ idx = 0
+ self["checkList"].moveToIndex(idx)
+ self.setWindowTitle()
+ self.selectionChanged()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Select files/folders to backup..."))
+
+ def selectionChanged(self):
+ current = self["checkList"].getCurrent()[0]
+ if current[2] is True:
+ self["key_yellow"].setText(_("Deselect"))
+ else:
+ self["key_yellow"].setText(_("Select"))
+
+ def up(self):
+ self["checkList"].up()
+
+ def down(self):
+ self["checkList"].down()
+
+ def left(self):
+ self["checkList"].pageUp()
+
+ def right(self):
+ self["checkList"].pageDown()
+
+ def changeSelectionState(self):
+ self["checkList"].changeSelectionState()
+ self.selectedFiles = self["checkList"].getSelectedList()
+
+ def saveSelection(self):
+ self.selectedFiles = self["checkList"].getSelectedList()
+ config.plugins.configurationbackup.backupdirs.value = self.selectedFiles
+ config.plugins.configurationbackup.backupdirs.save()
+ config.plugins.configurationbackup.save()
+ config.save()
+ self.close(None)
+
+ def exit(self):
+ self.close(None)
+
+ def okClicked(self):
+ if self.filelist.canDescent():
+ self.filelist.descent()
+
+
+class RestoreMenu(Screen):
+ skin = """
+ <screen position="135,144" size="450,300" title="Restore backups..." >
+ <widget name="filelist" position="10,10" size="430,240" scrollbarMode="showOnDemand" />
+ <widget name="cancel" position="120,255" size="100,40" pixmap="~/red.png" transparent="1" alphatest="on" />
+ <widget name="canceltext" position="0,0" size="0,0" valign="center" halign="center" zPosition="2" font="Regular;20" transparent="1" foregroundColor="black" />
+ <widget name="restore" position="230,255" size="100,40" pixmap="~/yellow.png" transparent="1" alphatest="on" />
+ <widget name="restoretext" position="0,0" size="0,0" valign="center" halign="center" zPosition="2" font="Regular;20" transparent="1" foregroundColor="black" />
+ </screen>"""
+
+ def __init__(self, session, plugin_path):
+ Screen.__init__(self, session)
+ self.skin_path = plugin_path
+
+ self["canceltext"] = Label(_("Cancel"))
+ self["restoretext"] = Label(_("Restore"))
+ self["restore"] = Pixmap()
+ self["cancel"] = Pixmap()
+
+ self.sel = []
+ self.val = []
+ self.entry = False
+ self.exe = False
+
+ self.path = ""
+
+ self["actions"] = NumberActionMap(["SetupActions"],
+ {
+ "ok": self.KeyOk,
+ "cancel": self.keyCancel
+ }, -1)
+
+ self["shortcuts"] = ActionMap(["ShortcutActions"],
+ {
+ "red": self.keyCancel,
+ "yellow": self.KeyOk,
+ })
+ self.flist = []
+ self["filelist"] = MenuList(self.flist)
+ self.fill_list()
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ self.setWindowTitle()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Restore backups..."))
+
+
+ def fill_list(self):
+ self.flist = []
+ self.path = getBackupPath()
+ if (path.exists(self.path) == False):
+ makedirs(self.path)
+ for file in listdir(self.path):
+ if (file.endswith(".tar.gz")):
+ self.flist.append((file))
+ self.entry = True
+ self["filelist"].l.setList(self.flist)
+
+ def KeyOk(self):
+ if (self.exe == False) and (self.entry == True):
+ self.sel = self["filelist"].getCurrent()
+ self.val = self.path + self.sel
+ self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore\nfollowing backup:\n" + self.sel + "\nSystem will restart after the restore!"))
+
+ def keyCancel(self):
+ self.close()
+
+ def startRestore(self, ret = False):
+ if (ret == True):
+ self.exe = True
+ self.session.open(Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.path + "/" + self.sel + " -C /", "killall -9 enigma2"])
+
+ def Exit(self):
+ self.close()
+
+class RestoreScreen(Screen, ConfigListScreen):
+ skin = """
+ <screen position="135,144" size="350,310" title="Restore running..." >
+ <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
+ </screen>"""
+
+ def __init__(self, session, runRestore = False):
+ Screen.__init__(self, session)
+ self.session = session
+ self.runRestore = runRestore
+ self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
+ {
+ "ok": self.close,
+ "back": self.close,
+ "cancel": self.close,
+ }, -1)
+ self.finished_cb = None
+ self.backuppath = getBackupPath()
+ self.backupfile = getBackupFilename()
+ self.fullbackupfilename = self.backuppath + "/" + self.backupfile
+ self.list = []
+ ConfigListScreen.__init__(self, self.list)
+ self.onLayoutFinish.append(self.layoutFinished)
+ if self.runRestore:
+ self.onShown.append(self.doRestore)
+
+ def layoutFinished(self):
+ self.setWindowTitle()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Restore running..."))
+
+ def doRestore(self):
+ if self.finished_cb:
+ self.session.openWithCallback(self.finished_cb, Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "killall -9 enigma2"])
+ else:
+ self.session.open(Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "killall -9 enigma2"])
+
+ def backupFinishedCB(self,retval = None):
+ self.close(True)
+
+ def backupErrorCB(self,retval = None):
+ self.close(False)
+
+ def runAsync(self, finished_cb):
+ self.finished_cb = finished_cb
+ self.doRestore()
+
+
\ No newline at end of file
--- /dev/null
+from Plugins.Plugin import PluginDescriptor
+from Screens.Console import Console
+from Screens.ChoiceBox import ChoiceBox
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from Screens.Ipkg import Ipkg
+from Components.ActionMap import ActionMap, NumberActionMap
+from Components.Input import Input
+from Components.Ipkg import IpkgComponent
+from Components.Label import Label
+from Components.MenuList import MenuList
+from Components.Sources.List import List
+from Components.Slider import Slider
+from Components.Harddisk import harddiskmanager
+from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
+from Components.Console import Console
+from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
+from Components.SelectionList import SelectionList
+from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
+from Tools.LoadPixmap import LoadPixmap
+from enigma import eTimer, loadPNG, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont
+from cPickle import dump, load
+
+from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
+from time import time, gmtime, strftime, localtime
+from stat import ST_MTIME
+from datetime import date
+
+from ImageWizard import ImageWizard
+from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
+
+config.plugins.configurationbackup = ConfigSubsection()
+config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
+config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf'])
+
+
+def write_cache(cache_file, cache_data):
+ #Does a cPickle dump
+ if not os_path.isdir( os_path.dirname(cache_file) ):
+ try:
+ mkdir( os_path.dirname(cache_file) )
+ except OSError:
+ print os_path.dirname(cache_file), 'is a file'
+ fd = open(cache_file, 'w')
+ dump(cache_data, fd, -1)
+ fd.close()
+
+def valid_cache(cache_file, cache_ttl):
+ #See if the cache file exists and is still living
+ try:
+ mtime = stat(cache_file)[ST_MTIME]
+ except:
+ return 0
+ curr_time = time()
+ if (curr_time - mtime) > cache_ttl:
+ return 0
+ else:
+ return 1
+
+def load_cache(cache_file):
+ #Does a cPickle load
+ fd = open(cache_file)
+ cache_data = load(fd)
+ fd.close()
+ return cache_data
+
+
+class UpdatePluginMenu(Screen):
+ skin = """
+ <screen name="UpdatePluginMenu" position="90,130" size="550,330" title="Softwaremanager..." >
+ <ePixmap pixmap="skin_default/border_menu.png" position="10,10" zPosition="1" size="250,300" transparent="1" alphatest="on" />
+ <widget source="menu" render="Listbox" position="20,20" size="230,260" scrollbarMode="showOnDemand">
+ <convert type="TemplatedMultiContent">
+ {"template": [
+ MultiContentEntryText(pos = (2, 2), size = (230, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
+ ],
+ "fonts": [gFont("Regular", 20)],
+ "itemHeight": 25
+ }
+ </convert>
+ </widget>
+ <widget name="description" position="280,10" size="230,300" font="Regular;19" halign="center" valign="center" />
+ </screen>"""
+
+ def __init__(self, session, args = 0):
+ Screen.__init__(self, session)
+ self.skin_path = plugin_path
+ self.menu = args
+ self.list = []
+ self.oktext = _("\nPress OK on your remote control to continue.")
+ self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
+ if self.menu == 0:
+ self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext) )
+ self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext))
+ self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext))
+ self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext))
+ if config.usage.setup_level.index >= 2: # expert+
+ self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext))
+ elif self.menu == 1:
+ self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext))
+ self.list.append(("ipkg-install", _("Install local IPKG"), _("\nScan for local packages and install them." ) + self.oktext))
+ self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext))
+ self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext ))
+ self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext))
+ self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext))
+
+ self["menu"] = List(self.list)
+ self["menu"].onSelectionChanged.append(self.selectionChanged)
+ self["description"] = Label()
+
+ self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
+ {
+ "ok": self.go,
+ "back": self.close,
+ "red": self.close,
+ }, -1)
+
+ self.onLayoutFinish.append(self.layoutFinished)
+ self.backuppath = getBackupPath()
+ self.backupfile = getBackupFilename()
+ self.fullbackupfilename = self.backuppath + "/" + self.backupfile
+ self.onShown.append(self.setWindowTitle)
+
+ def layoutFinished(self):
+ idx = 0
+ self["menu"].index = idx
+ self.loadDescription()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Software manager..."))
+
+ def loadDescription(self):
+ if self["menu"].getCurrent()[0] == 'software-update':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'software-restore':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'ipkg-install':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'system-backup':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'system-restore':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'advanced':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'ipkg-source':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'ipkg-manager':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'advancedrestore':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'backuplocation':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+ if self["menu"].getCurrent()[0] == 'backupfiles':
+ self["description"].setText(self["menu"].getCurrent()[2] )
+
+ def go(self):
+ if self.menu == 0:
+ if (self["menu"].getCurrent()[0] == "software-restore"):
+ self.session.open(ImageWizard)
+ if (self["menu"].getCurrent()[0] == "software-update"):
+ self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
+ if (self["menu"].getCurrent()[0] == "advanced"):
+ self.session.open(UpdatePluginMenu, 1)
+ if (self["menu"].getCurrent()[0] == "system-backup"):
+ self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
+ if (self["menu"].getCurrent()[0] == "system-restore"):
+ if os_path.exists(self.fullbackupfilename):
+ self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
+ else:
+ self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO)
+ if self.menu == 1:
+ if (self["menu"].getCurrent()[0] == "ipkg-manager"):
+ self.session.open(PacketManager, self.skin_path)
+ if (self["menu"].getCurrent()[0] == "ipkg-source"):
+ self.session.open(IPKGSource)
+ if (self["menu"].getCurrent()[0] == "ipkg-install"):
+ try:
+ from Plugins.Extensions.MediaScanner.plugin import main
+ main(self.session)
+ except:
+ self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO)
+ if (self["menu"].getCurrent()[0] == "backuplocation"):
+ parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
+ for x in parts:
+ if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
+ parts.remove(x)
+ for x in parts:
+ if x[1].startswith('/autofs/'):
+ parts.remove(x)
+ if len(parts):
+ self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
+ if (self["menu"].getCurrent()[0] == "backupfiles"):
+ self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
+ if (self["menu"].getCurrent()[0] == "advancedrestore"):
+ self.session.open(RestoreMenu, self.skin_path)
+
+ def selectionChanged(self):
+ self.loadDescription()
+
+ def backupfiles_choosen(self, ret):
+ self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
+ self.loadDescription()
+
+ def backuplocation_choosen(self, option):
+ if option is not None:
+ config.plugins.configurationbackup.backuplocation.value = str(option[1])
+ config.plugins.configurationbackup.backuplocation.save()
+ config.plugins.configurationbackup.save()
+ config.save()
+ self.createBackupfolders()
+ self.loadDescription()
+
+ def runUpgrade(self, result):
+ if result:
+ self.session.openWithCallback(self.runFinished,UpdatePlugin, self.skin_path)
+
+ def runFinished(self):
+ self.session.openWithCallback(self.reboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
+
+ def reboot(self, result):
+ if result is None:
+ return
+ if result:
+ quitMainloop(3)
+
+ def createBackupfolders(self):
+ print "Creating backup folder if not already there..."
+ self.backuppath = getBackupPath()
+ try:
+ if (os_path.exists(self.backuppath) == False):
+ makedirs(self.backuppath)
+ except OSError:
+ self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO)
+
+ def backupDone(self,retval = None):
+ if retval is True:
+ self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO)
+ else:
+ self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO)
+
+ def startRestore(self, ret = False):
+ if (ret == True):
+ self.exe = True
+ self.session.open(RestoreScreen, runRestore = True)
+
+
+class IPKGSource(Screen):
+ skin = """
+ <screen position="100,100" size="550,60" title="IPKG source" >
+ <widget name="text" position="0,0" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
+ </screen>"""
+
+ def __init__(self, session, args = None):
+ Screen.__init__(self, session)
+ self.session = session
+
+ fp = file('/etc/ipkg/official-feed.conf', 'r')
+ sources = fp.readlines()
+ fp.close()
+
+ self["text"] = Input(sources[0], maxSize=False, type=Input.TEXT)
+
+ self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions"],
+ {
+ "ok": self.go,
+ "back": self.close,
+ "left": self.keyLeft,
+ "right": self.keyRight,
+ "home": self.keyHome,
+ "end": self.keyEnd,
+ "deleteForward": self.keyDeleteForward,
+ "deleteBackward": self.keyDeleteBackward,
+ "1": self.keyNumberGlobal,
+ "2": self.keyNumberGlobal,
+ "3": self.keyNumberGlobal,
+ "4": self.keyNumberGlobal,
+ "5": self.keyNumberGlobal,
+ "6": self.keyNumberGlobal,
+ "7": self.keyNumberGlobal,
+ "8": self.keyNumberGlobal,
+ "9": self.keyNumberGlobal,
+ "0": self.keyNumberGlobal
+ }, -1)
+
+ def go(self):
+ fp = file('/etc/ipkg/official-feed.conf', 'w')
+ fp.write(self["text"].getText())
+ fp.close()
+ self.close()
+
+ def keyLeft(self):
+ self["text"].left()
+
+ def keyRight(self):
+ self["text"].right()
+
+ def keyHome(self):
+ self["text"].home()
+
+ def keyEnd(self):
+ self["text"].end()
+
+ def keyDeleteForward(self):
+ self["text"].delete()
+
+ def keyDeleteBackward(self):
+ self["text"].deleteBackward()
+
+ def keyNumberGlobal(self, number):
+ print "pressed", number
+ self["text"].number(number)
+
+
+class PacketList(MenuList):
+ def __init__(self, list, enableWrapAround=True):
+ MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
+ self.l.setFont(0, gFont("Regular", 22))
+ self.l.setFont(1, gFont("Regular", 14))
+ self.l.setItemHeight(52)
+
+class PacketManager(Screen):
+ skin = """
+ <screen position="90,80" size="530,420" title="IPKG upgrade..." >
+ <widget name="list" position="5,10" size="520,365" zPosition="1" scrollbarMode="showOnDemand" />
+ <widget name="status" position="30,160" size="530,40" zPosition="4" font="Regular;22" halign="left" transparent="1" />
+ <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
+ <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
+ <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
+ </screen>"""
+
+ def __init__(self, session, plugin_path, args = None):
+ Screen.__init__(self, session)
+ self.session = session
+ self.skin_path = plugin_path
+
+ self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
+ {
+ "ok": self.go,
+ "back": self.close,
+ "red": self.close,
+ "green": self.reload,
+ }, -1)
+
+ self.list = []
+ self["list"] = PacketList(self.list)
+ self.status = Label()
+ self["closetext"] = Label(_("Close"))
+ self["reloadtext"] = Label(_("Reload"))
+ self["status"] = self.status
+
+ self.list_updating = True
+ self.packetlist = []
+ self.installed_packetlist = {}
+ self.Console = Console()
+ self.cmdList = []
+ self.cachelist = []
+ self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
+ self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
+ self.oktext = _("\nAfter pressing OK, please wait!")
+
+ self.ipkg = IpkgComponent()
+ self.ipkg.addCallback(self.ipkgCallback)
+ self.onShown.append(self.setWindowTitle)
+ self.onLayoutFinish.append(self.rebuildList)
+ self.onClose.append(self.cleanup)
+
+ def cleanup(self):
+ self.ipkg.stop()
+ if self.Console is not None:
+ del self.Console
+
+ def reload(self):
+ if (os_path.exists(self.cache_file) == True):
+ remove(self.cache_file)
+ self.list_updating = True
+ self.rebuildList()
+
+ def setWindowTitle(self):
+ self.setTitle(_("Packet manager"))
+
+ def rebuildList(self):
+ self["list"].instance.hide()
+ self.status.setText(_("Package list update"))
+ self.status.show()
+ self.inv_cache = 0
+ self.vc = valid_cache(self.cache_file, self.cache_ttl)
+ if self.cache_ttl > 0 and self.vc != 0:
+ try:
+ self.buildPacketList()
+ except:
+ self.inv_cache = 1
+ if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
+ self.run = 0
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+
+ def go(self, returnValue = None):
+ returnValue = self['list'].l.getCurrentSelection()[0]
+ self.cmdList = []
+ if returnValue[3] == 'installed':
+ self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": returnValue[0] }))
+ if len(self.cmdList):
+ self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n" + returnValue[0] + "\n" + self.oktext))
+ elif returnValue[3] == 'upgradeable':
+ self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
+ if len(self.cmdList):
+ self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n" + returnValue[0] + "\n" + self.oktext))
+ else:
+ self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
+ if len(self.cmdList):
+ self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n" + returnValue[0] + "\n" + self.oktext))
+
+ def runRemove(self, result):
+ if result:
+ self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
+
+ def runRemoveFinished(self):
+ self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
+
+ def RemoveReboot(self, result):
+ if result is None:
+ return
+ if result is False:
+ entry = self['list'].l.getCurrentSelection()[0]
+ item = self['list'].l.getCurrentSelectionIndex()
+ self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installable'])
+ self.cachelist[item] = [entry[0], entry[1], entry[2], 'installable']
+ self['list'].l.setList(self.list)
+ write_cache(self.cache_file, self.cachelist)
+ if result:
+ quitMainloop(3)
+
+ def runUpgrade(self, result):
+ if result:
+ self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
+
+ def runUpgradeFinished(self):
+ self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
+
+ def UpgradeReboot(self, result):
+ if result is None:
+ return
+ if result is False:
+ entry = self['list'].l.getCurrentSelection()[0]
+ item = self['list'].l.getCurrentSelectionIndex()
+ self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installed'])
+ self.cachelist[item] = [entry[0], entry[1], entry[2], 'installed']
+ self['list'].l.setList(self.list)
+ write_cache(self.cache_file, self.cachelist)
+ if result:
+ quitMainloop(3)
+
+ def ipkgCallback(self, event, param):
+ if event == IpkgComponent.EVENT_ERROR:
+ self.list_updating = False
+ self.status.setText(_("An error occured!"))
+ elif event == IpkgComponent.EVENT_DONE:
+ if self.list_updating:
+ self.list_updating = False
+ if not self.Console:
+ self.Console = Console()
+ cmd = "ipkg list"
+ self.Console.ePopen(cmd, self.IpkgList_Finished)
+ #print event, "-", param
+ pass
+
+ def IpkgList_Finished(self, result, retval, extra_args = None):
+ if len(result):
+ self.packetlist = []
+ for x in result.splitlines():
+ split = x.split(' - ')
+ self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
+ cmd = "ipkg list_installed"
+ self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
+
+ def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
+ if len(result):
+ self.installed_packetlist = {}
+ for x in result.splitlines():
+ split = x.split(' - ')
+ self.installed_packetlist[split[0].strip()] = split[1].strip()
+ self.buildPacketList()
+
+ def PacketEntryComponent(self,entry):
+ res = [ entry ]
+ res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
+ res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
+
+ return res
+
+
+ def buildPacketList(self):
+ self.list = []
+ self.cachelist = []
+ installedpng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
+ upgradeablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
+ installablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
+ divpng = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
+
+ if self.cache_ttl > 0 and self.vc != 0:
+ print 'Loading packagelist cache from ',self.cache_file
+ try:
+ self.cachelist = load_cache(self.cache_file)
+ if len(self.cachelist) > 0:
+ for x in self.cachelist:
+ if x[3] == 'installed':
+ self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installedpng,divpng]))
+ elif x[3] == 'upgradeable':
+ self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],upgradeablepng,divpng]))
+ else:
+ self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installablepng,divpng]))
+ self['list'].l.setList(self.list)
+ self["list"].instance.show()
+ self.status.hide()
+ except:
+ self.inv_cache = 1
+
+ if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
+ print 'rebuilding fresh package list'
+ for x in self.packetlist:
+ status = ""
+ if self.installed_packetlist.has_key(x[0].strip()):
+ if self.installed_packetlist[x[0].strip()] == x[1].strip():
+ status = "installed"
+ self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installedpng,divpng]))
+ else:
+ status = "upgradeable"
+ self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,upgradeablepng,divpng]))
+ else:
+ status = "installable"
+ self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installablepng,divpng]))
+ self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
+ write_cache(self.cache_file, self.cachelist)
+ self['list'].l.setList(self.list)
+ self["list"].instance.show()
+ self.status.hide()
+
+
+class UpdatePlugin(Screen):
+ skin = """
+ <screen position="100,100" size="550,200" title="Software Update..." >
+ <widget name="activityslider" position="0,0" size="550,5" />
+ <widget name="slider" position="0,100" size="550,30" />
+ <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
+ <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
+ </screen>"""
+
+ def __init__(self, session, args = None):
+ self.skin = UpdatePlugin.skin
+ Screen.__init__(self, session)
+
+ self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
+
+ self.slider = Slider(0, 4)
+ self["slider"] = self.slider
+ self.activityslider = Slider(0, 100)
+ self["activityslider"] = self.activityslider
+ self.status = Label(_("Upgrading Dreambox... Please wait"))
+ self["status"] = self.status
+ self.package = Label()
+ self["package"] = self.package
+
+ self.packages = 0
+ self.error = 0
+
+ self.activity = 0
+ self.activityTimer = eTimer()
+ self.activityTimer.callback.append(self.doActivityTimer)
+ self.activityTimer.start(100, False)
+
+ self.ipkg = IpkgComponent()
+ self.ipkg.addCallback(self.ipkgCallback)
+
+ self.updating = True
+ self.package.setText(_("Package list update"))
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+
+ self["actions"] = ActionMap(["WizardActions"],
+ {
+ "ok": self.exit,
+ "back": self.exit
+ }, -1)
+
+ def doActivityTimer(self):
+ self.activity += 1
+ if self.activity == 100:
+ self.activity = 0
+ self.activityslider.setValue(self.activity)
+
+ def ipkgCallback(self, event, param):
+ if event == IpkgComponent.EVENT_DOWNLOAD:
+ self.status.setText(_("Downloading"))
+ elif event == IpkgComponent.EVENT_UPGRADE:
+ if self.sliderPackages.has_key(param):
+ self.slider.setValue(self.sliderPackages[param])
+ self.package.setText(param)
+ self.status.setText(_("Upgrading"))
+ self.packages += 1
+ elif event == IpkgComponent.EVENT_INSTALL:
+ self.package.setText(param)
+ self.status.setText(_("Installing"))
+ self.packages += 1
+ elif event == IpkgComponent.EVENT_CONFIGURING:
+ self.package.setText(param)
+ self.status.setText(_("Configuring"))
+ elif event == IpkgComponent.EVENT_MODIFIED:
+ self.session.openWithCallback(
+ self.modificationCallback,
+ MessageBox,
+ _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
+ )
+ elif event == IpkgComponent.EVENT_ERROR:
+ self.error += 1
+ elif event == IpkgComponent.EVENT_DONE:
+ if self.updating:
+ self.updating = False
+ self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
+ elif self.error == 0:
+ self.slider.setValue(4)
+
+ self.activityTimer.stop()
+ self.activityslider.setValue(0)
+
+ self.package.setText("")
+ self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
+ else:
+ self.activityTimer.stop()
+ self.activityslider.setValue(0)
+ error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
+ if self.packages == 0:
+ error = _("No packages were upgraded yet. So you can check your network and try again.")
+ if self.updating:
+ error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
+ self.status.setText(_("Error") + " - " + error)
+ #print event, "-", param
+ pass
+
+ def modificationCallback(self, res):
+ self.ipkg.write(res and "N" or "Y")
+
+ def exit(self):
+ if not self.ipkg.isRunning():
+ if self.packages != 0 and self.error == 0:
+ self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
+ else:
+ self.close()
+
+ def exitAnswer(self, result):
+ if result is not None and result:
+ quitMainloop(2)
+ self.close()
+
+
+
+class IpkgInstaller(Screen):
+ skin = """
+ <screen position="100,100" size="550,400" title="..." >
+ <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
+ <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
+ <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
+ <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
+ <widget name="list" position="0,60" size="550,360" />
+ </screen>
+ """
+
+ def __init__(self, session, list):
+ self.skin = IpkgInstaller.skin
+ Screen.__init__(self, session)
+
+ self.list = SelectionList()
+ self["list"] = self.list
+ for listindex in range(len(list)):
+ self.list.addSelection(list[listindex], list[listindex], listindex, True)
+
+ self["red"] = Label()
+ self["green"] = Label()
+ self["yellow"] = Label()
+ self["blue"] = Label()
+
+ self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
+ {
+ "ok": self.list.toggleSelection,
+ "cancel": self.close,
+ "green": self.install
+ }, -1)
+
+ def install(self):
+ list = self.list.getSelectionsList()
+ cmdList = []
+ for item in list:
+ cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
+ self.session.open(Ipkg, cmdList = cmdList)
+
+def filescan_open(list, session, **kwargs):
+ filelist = [x.path for x in list]
+ session.open(IpkgInstaller, filelist) # list
+
+def filescan(**kwargs):
+ from Components.Scanner import Scanner, ScanPath
+ return \
+ Scanner(mimetypes = ["application/x-debian-package"],
+ paths_to_scan =
+ [
+ ScanPath(path = "ipk", with_subdirs = True),
+ ScanPath(path = "", with_subdirs = False),
+ ],
+ name = "Ipkg",
+ description = "Install software updates...",
+ openfnc = filescan_open, )
+
+def UpgradeMain(session, **kwargs):
+ session.open(UpdatePluginMenu)
+
+def startSetup(menuid):
+ if menuid != "setup":
+ return [ ]
+ return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
+
+def Plugins(path, **kwargs):
+ global plugin_path
+ plugin_path = path
+ return [
+ PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
+ #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
+ PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
+ ]