diff options
| author | acid-burn <acidburn@opendreambox.org> | 2009-02-13 11:47:46 +0100 |
|---|---|---|
| committer | acid-burn <acidburn@opendreambox.org> | 2009-02-13 11:47:46 +0100 |
| commit | 95fa0e8c06f26bc2c4d3b5ab6afc772cd991e9dc (patch) | |
| tree | e837a99b868be5d3b8163bb54345492875143d2e /lib/python/Plugins/SystemPlugins | |
| parent | 7da4f25976773b0e1f8a06c13f2455c4bdb88349 (diff) | |
| download | enigma2-95fa0e8c06f26bc2c4d3b5ab6afc772cd991e9dc.tar.gz enigma2-95fa0e8c06f26bc2c4d3b5ab6afc772cd991e9dc.zip | |
add SoftwareManager and show it inside Setup Menu
Diffstat (limited to 'lib/python/Plugins/SystemPlugins')
16 files changed, 1294 insertions, 0 deletions
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/.cvsignore b/lib/python/Plugins/SystemPlugins/SoftwareManager/.cvsignore new file mode 100644 index 00000000..138b9cc2 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/.cvsignore @@ -0,0 +1,4 @@ +*.pyc +*.pyo +Makefile +Makefile.in diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py new file mode 100755 index 00000000..f92472d3 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py @@ -0,0 +1,313 @@ +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 diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/ImageWizard.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/ImageWizard.py new file mode 100755 index 00000000..1797e4fe --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/ImageWizard.py @@ -0,0 +1,120 @@ +from Screens.Wizard import WizardSummary +from Screens.WizardLanguage import WizardLanguage +from Screens.Wizard import wizardManager +from Screens.Rc import Rc +from Components.Label import Label +from Components.MenuList import MenuList +from Components.PluginComponent import plugins +from Plugins.Plugin import PluginDescriptor +from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE +from Components.Pixmap import Pixmap, MovingPixmap, MultiPixmap +from os import popen, path, makedirs, listdir, access, stat, rename, remove, W_OK, R_OK + +from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations, ConfigBoolean +from Components.Harddisk import harddiskmanager +config.misc.firstrun = ConfigBoolean(default = True) +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']) + + +backupfile = "enigma2settingsbackup.tar.gz" + +def checkConfigBackup(): + parts = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)] + for x in parts: + if x[1] == '/': + parts.remove(x) + if len(parts): + for x in parts: + if x[1].endswith('/'): + fullbackupfile = x[1] + 'backup/' + backupfile + if fileExists(fullbackupfile): + config.plugins.configurationbackup.backuplocation.value = str(x[1]) + config.plugins.configurationbackup.backuplocation.save() + config.plugins.configurationbackup.save() + return x + else: + fullbackupfile = x[1] + '/backup/' + backupfile + if fileExists(fullbackupfile): + config.plugins.configurationbackup.backuplocation.value = str(x[1]) + config.plugins.configurationbackup.backuplocation.save() + config.plugins.configurationbackup.save() + return x + return None + +def checkBackupFile(): + backuplocation = config.plugins.configurationbackup.backuplocation.value + if backuplocation.endswith('/'): + fullbackupfile = backuplocation + 'backup/' + backupfile + if fileExists(fullbackupfile): + return True + else: + return False + else: + fullbackupfile = backuplocation + '/backup/' + backupfile + if fileExists(fullbackupfile): + return True + else: + return False + +if checkConfigBackup() is None: + backupAvailable = 0 +else: + backupAvailable = 1 + +class ImageWizard(WizardLanguage, Rc): + skin = """ + <screen name="ImageWizard" position="0,0" size="720,576" title="Welcome..." flags="wfNoBorder" > + <widget name="text" position="153,40" size="340,330" font="Regular;22" /> + <widget source="list" render="Listbox" position="43,340" size="490,180" scrollbarMode="showOnDemand" > + <convert type="StringList" /> + </widget> + <widget name="config" position="53,340" zPosition="1" size="440,180" transparent="1" scrollbarMode="showOnDemand" /> + <ePixmap pixmap="skin_default/buttons/button_red.png" position="40,225" zPosition="0" size="15,16" transparent="1" alphatest="on" /> + <widget name="languagetext" position="55,225" size="95,30" font="Regular;18" /> + <widget name="wizard" pixmap="skin_default/wizard.png" position="40,50" zPosition="10" size="110,174" alphatest="on" /> + <widget name="rc" pixmaps="skin_default/rc.png,skin_default/rcold.png" position="530,50" zPosition="10" size="154,500" alphatest="on" /> + <widget name="arrowdown" pixmap="skin_default/arrowdown.png" position="-100,-100" zPosition="11" size="37,70" alphatest="on" /> + <widget name="arrowdown2" pixmap="skin_default/arrowdown.png" position="-100,-100" zPosition="11" size="37,70" alphatest="on" /> + <widget name="arrowup" pixmap="skin_default/arrowup.png" position="-100,-100" zPosition="11" size="37,70" alphatest="on" /> + <widget name="arrowup2" pixmap="skin_default/arrowup.png" position="-100,-100" zPosition="11" size="37,70" alphatest="on" /> + </screen>""" + def __init__(self, session): + self.xmlfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/imagewizard.xml") + WizardLanguage.__init__(self, session, showSteps = False, showStepSlider = False) + Rc.__init__(self) + self.session = session + self["wizard"] = Pixmap() + self.selectedDevice = None + + def markDone(self): + pass + + def listDevices(self): + list = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)] + for x in list: + result = access(x[1], W_OK) and access(x[1], R_OK) + if result is False or x[1] == '/': + list.remove(x) + for x in list: + if x[1].startswith('/autofs/'): + list.remove(x) + return list + + def deviceSelectionMade(self, index): + self.deviceSelect(index) + + def deviceSelectionMoved(self): + self.deviceSelect(self.selection) + + def deviceSelect(self, device): + self.selectedDevice = device + config.plugins.configurationbackup.backuplocation.value = self.selectedDevice + config.plugins.configurationbackup.backuplocation.save() + config.plugins.configurationbackup.save() + + +if config.misc.firstrun.value: + wizardManager.registerWizard(ImageWizard, backupAvailable, priority = 10) + diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/LICENSE b/lib/python/Plugins/SystemPlugins/SoftwareManager/LICENSE new file mode 100755 index 00000000..835b9dc6 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/LICENSE @@ -0,0 +1,17 @@ +This plugin is licensed under the Creative Commons +Attribution-NonCommercial-ShareAlike 3.0 Unported +License. To view a copy of this license, visit +http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative +Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. + +Alternatively, this plugin may be distributed and executed on hardware which +is licensed by Dream Multimedia GmbH. + +This plugin is NOT free software. It is open source, you are allowed to +modify it (if you keep the license), but it may not be commercially +distributed other than under the conditions noted above. + +Some Icons used are taken from NX10 icons by Mazenl77 +(http://www.iconspedia.com/pack/nx10-1-6/) +licensed under Creative Commons Attribution 3.0 Unported +http://creativecommons.org/licenses/by/3.0/ diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am new file mode 100755 index 00000000..f94498f5 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am @@ -0,0 +1,12 @@ +installdir = $(LIBDIR)/enigma2/python/Plugins/SystemPlugins/SoftwareManager + +install_PYTHON = \ + __init__.py \ + plugin.py \ + BackupRestore.py \ + ImageWizard.py \ + imagewizard.xml \ + *.png + +install_DATA = LICENSE + diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/__init__.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/__init__.py diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/blue.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/blue.png Binary files differnew file mode 100755 index 00000000..a392bbe6 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/blue.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/green.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/green.png Binary files differnew file mode 100755 index 00000000..f168e4d0 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/green.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/imagewizard.xml b/lib/python/Plugins/SystemPlugins/SoftwareManager/imagewizard.xml new file mode 100755 index 00000000..98658b7d --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/imagewizard.xml @@ -0,0 +1,100 @@ +<wizard>
+ <step id="restorequestion">
+ <condition>
+from Plugins.SystemPlugins.SoftwareManager.ImageWizard import checkConfigBackup
+self.backuppath = checkConfigBackup()
+self.condition = (self.backuppath is not None and config.misc.firstrun.value)
+ </condition>
+ <text value="Do you want to restore your settings?" />
+ <list>
+ <listentry caption="Yes, restore the settings now" step="restore" />
+ <listentry caption="No, just start my dreambox" step="end" />
+ </list>
+ <code>
+self.clearSelectedKeys()
+self.selectKey("OK")
+ </code>
+ </step>
+
+ <step id="welcome">
+ <text value="Welcome to the Image upgrade wizard. The wizard will assist you in upgrading the firmware of your Dreambox by providing a backup facility for your current settings and a short explanation of how to upgrade your firmware." />
+ <list>
+ <listentry caption="OK, guide me through the upgrade process" step="backupquestion" />
+ <listentry caption="Exit the wizard" step="end" />
+ </list>
+ </step>
+
+ <step id="backupquestion">
+ <text value="The wizard can backup your current settings. Do you want to do a backup now?" />
+ <list>
+ <listentry caption="Yes, backup my settings!" step="backupwhere" />
+ <listentry caption="No backup needed" step="upgrade" />
+ </list>
+ </step>
+
+ <step id="backupwhere" nextstep="backup">
+ <text value="Where do you want to backup your settings?" />
+ <list type="dynamic" source="listDevices" evaluation="deviceSelectionMade" onselect="deviceSelectionMoved" />
+ </step>
+
+ <step id="backup" nextstep="backupresult">
+ <text value="You have chosen to backup your settings. Please press OK to start the backup now." />
+ <config screen="BackupScreen" module="Plugins.SystemPlugins.SoftwareManager.BackupRestore" type="ConfigList" />
+ <code pos="after" async="yes">
+self.currStep = self.getStepWithID('backupresult')
+self.afterAsyncCode()
+ </code>
+ </step>
+
+ <step id="backupresult" nextstep="upgrade">
+ <condition>
+from Plugins.SystemPlugins.SoftwareManager.ImageWizard import checkBackupFile
+self.backuppath = checkBackupFile()
+self.condition = (self.backuppath is True)
+ </condition>
+ <text value="Your backup succeeded. We will now continue to explain the further upgrade process." />
+ </step>
+
+ <step id="backupresult" nextstep="backupwhere">
+ <condition>
+from Plugins.SystemPlugins.SoftwareManager.ImageWizard import checkBackupFile
+self.backuppath = checkBackupFile()
+self.condition = (self.backuppath is False)
+ </condition>
+ <text value="The backup failed. Please choose a different backup location." />
+ </step>
+
+ <step id="restore" nextstep="backupresult">
+ <text value="You have chosen to restore your settings. Enigma2 will restart after restore. Please press OK to start the restore now." />
+ <config screen="RestoreScreen" module="Plugins.SystemPlugins.SoftwareManager.BackupRestore" type="ConfigList" />
+ </step>
+
+
+ <step id="upgradehow">
+ <text value="The wizard can backup your current settings. Do you want to do a backup now?" />
+ <list>
+ <listentry caption="Install a new image with your web browser" step="upgrade" />
+ <listentry caption="Install a new image with a USB stick" step="upgradeUSB" />
+ </list>
+ </step>
+
+ <step id="upgrade">
+ <text value="You need a PC connected to your dreambox. If you need further instructions, please visit the website http://www.dm7025.de.\nYour dreambox will now be halted. After you have performed the update instructions from the website, your new firmware will ask you to restore your settings." />
+ <list>
+ <listentry caption="Yes, perform a shutdown now." step="shutdown" />
+ <listentry caption="No, do nothing." step="end" />
+ </list>
+ </step>
+
+ <step id="shutdown" nextstep="shutdown">
+ <code>
+from enigma import quitMainloop
+quitMainloop(1)
+ </code>
+ <text value="Your dreambox is shutting down. Please stand by..." />
+ </step>
+
+ <step id="end">
+ <text value="The wizard is finished now." />
+ </step>
+</wizard>
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/installable.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/installable.png Binary files differnew file mode 100755 index 00000000..710f4201 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/installable.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/installed.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/installed.png Binary files differnew file mode 100755 index 00000000..d6a1bc10 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/installed.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py new file mode 100755 index 00000000..1835a2ed --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py @@ -0,0 +1,728 @@ +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) + ] diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/red.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/red.png Binary files differnew file mode 100755 index 00000000..8096045f --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/red.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/update.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/update.png Binary files differnew file mode 100755 index 00000000..0ece6c76 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/update.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/upgradeable.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/upgradeable.png Binary files differnew file mode 100755 index 00000000..edbbdee1 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/upgradeable.png diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/yellow.png b/lib/python/Plugins/SystemPlugins/SoftwareManager/yellow.png Binary files differnew file mode 100755 index 00000000..dacb80e6 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/yellow.png |
