def __init__(self, loggerObject): self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.avlThemesSearchstr = 'plymouth-themes' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.modulesPath = '/etc/initramfs-tools/modules'
def __init__(self, loggerObject=None): self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.avlThemesSearchstr = '^plymouth-theme' self.setThemePath = which('plymouth-set-default-theme') self.modulesPath = '/etc/initramfs-tools/modules' self.grubcfg = '/boot/grub/grub.cfg'
def __init__(self, loggerObject, theme=None, resolution=None): threading.Thread.__init__(self) self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.theme = None self.resolution = None self.modulesPath = '/etc/initramfs-tools/modules' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.plymouth = Plymouth(self.log) self.installedThemes = self.plymouth.getInstalledThemes() if theme in self.installedThemes and resolution is not None: self.log.write("Set theme: {0} ({1})".format(theme, resolution), 'PlymouthSave.init', 'debug') self.theme = theme self.resolution = resolution
def __init__(self, theme=None, resolution=None, queue=None, loggerObject=None): threading.Thread.__init__(self) self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.theme = None self.resolution = None self.queue = queue self.modulesPath = '/etc/initramfs-tools/modules' self.setThemePath = which('plymouth-set-default-theme') self.plymouth = Plymouth(self.log) self.installedThemes = self.plymouth.getInstalledThemes() if theme in self.installedThemes and resolution is not None: self.write_log("Set theme: {0} ({1})".format(theme, resolution)) self.theme = theme self.resolution = resolution # Steps self.max_steps = 6 self.current_step = 0
def __init__(self): self.scriptDir = dirname(realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, '../../share/debian-plymouth-manager/debian-plymouth-manager.glade')) # Main window objects go = self.builder.get_object self.window = go('dpmWindow') self.tv1 = go('tv1') self.tv2 = go('tv2') self.sw2 = go('sw2') self.statusbar = go('statusbar') self.btnPlymouth = go('btnPlymouth') self.btnThemes = go('btnThemes') self.btnGrub = go('btnGrub') self.pbDPM = go('pbDPM') self.btn1 = go('btn1') self.btn2 = go('btn2') self.lblTitle1 = go('lblTitle1') self.lblTitle2 = go('lblTitle2') # Translations title = _("Debian Plymouth Manager") self.window.set_title(title) self.btnPlymouth.set_label("_" + _("Plymouth")) self.btnThemes.set_label("_" + _("Themes")) self.btnGrub.set_label("_" + _("Grub")) self.selectedMenuItem = None self.selectedAvailableTheme = None self.selectedRemoveTheme = None self.threadPackage = None self.queue = Queue() self.noPlymouth = _('None: no plymouth splash') # Set some variables self.logFile = '/var/log/dpm.log' self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=1024) self.version = utils.getPackageVersion('debian-plymouth-manager') self.plymouth = Plymouth(self.log) self.grub = Grub(self.log) self.resolutions = utils.getResolutions('800x600', '', True, False) self.currentResolution = self.plymouth.getCurrentResolution() self.selectedResolution = self.currentResolution self.currentGrubResolution = self.grub.getCurrentResolution() self.selectedGrubResolution = self.currentGrubResolution self.currentTheme = self.plymouth.getCurrentTheme() self.selectedTheme = self.currentTheme self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() self.tv1Handler = TreeViewHandler(self.tv1, self.log) self.tv2Handler = TreeViewHandler(self.tv2, self.log) self.force = utils.get_apt_force() self.on_btnPlymouth_clicked() # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # TODO: Hide the tool bar for now go('tlbMain').set_visible(False)
class DPM: def __init__(self): self.scriptDir = dirname(realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, '../../share/debian-plymouth-manager/debian-plymouth-manager.glade')) # Main window objects go = self.builder.get_object self.window = go('dpmWindow') self.tv1 = go('tv1') self.tv2 = go('tv2') self.sw2 = go('sw2') self.statusbar = go('statusbar') self.btnPlymouth = go('btnPlymouth') self.btnThemes = go('btnThemes') self.btnGrub = go('btnGrub') self.pbDPM = go('pbDPM') self.btn1 = go('btn1') self.btn2 = go('btn2') self.lblTitle1 = go('lblTitle1') self.lblTitle2 = go('lblTitle2') # Translations title = _("Debian Plymouth Manager") self.window.set_title(title) self.btnPlymouth.set_label("_" + _("Plymouth")) self.btnThemes.set_label("_" + _("Themes")) self.btnGrub.set_label("_" + _("Grub")) self.selectedMenuItem = None self.selectedAvailableTheme = None self.selectedRemoveTheme = None self.threadPackage = None self.queue = Queue() self.noPlymouth = _('None: no plymouth splash') # Set some variables self.logFile = '/var/log/dpm.log' self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=1024) self.version = utils.getPackageVersion('debian-plymouth-manager') self.plymouth = Plymouth(self.log) self.grub = Grub(self.log) self.resolutions = utils.getResolutions('800x600', '', True, False) self.currentResolution = self.plymouth.getCurrentResolution() self.selectedResolution = self.currentResolution self.currentGrubResolution = self.grub.getCurrentResolution() self.selectedGrubResolution = self.currentGrubResolution self.currentTheme = self.plymouth.getCurrentTheme() self.selectedTheme = self.currentTheme self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() self.tv1Handler = TreeViewHandler(self.tv1, self.log) self.tv2Handler = TreeViewHandler(self.tv2, self.log) self.force = utils.get_apt_force() self.on_btnPlymouth_clicked() # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # TODO: Hide the tool bar for now go('tlbMain').set_visible(False) # =============================================== # Menu section functions # =============================================== def on_btnPlymouth_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[0] or refresh: self.selectedMenuItem = menuItems[0] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Set Plymouth Theme")) self.btn2.set_label(_("Preview")) self.btn2.show() self.lblTitle2.set_visible(True) self.sw2.show() # Show Installed Themes self.lblTitle1.set_label(_("Installed Themes")) # Clone the installedThemes list listInst = list(self.installedThemes) listInst.append(self.noPlymouth) # Get current theme and set setcursor ind = -1 if self.currentTheme: try: ind = listInst.index(self.currentTheme) except: # Theme is set but removed from system ind = 0 else: ind = len(listInst) - 1 if len(listInst) > 0: self.tv1Handler.fillTreeview(listInst, ['str'], ind, 700) # Show Resolutios self.lblTitle2.set_label(_("Resolutions")) ind = -1 if self.currentResolution: try: ind = self.resolutions.index(self.currentResolution) except: ind = 0 if len(self.resolutions) > 0: self.tv2Handler.fillTreeview(self.resolutions, ['str'], ind, 700) def on_btnThemes_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[1] or refresh: self.selectedMenuItem = menuItems[1] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Install Theme")) self.btn2.set_label(_("Remove Theme")) self.btn2.show() self.lblTitle2.set_visible(True) self.sw2.show() # Show Available Themes self.lblTitle1.set_label(_("Available Themes")) if len(self.availableThemes) > 0: self.tv1Handler.fillTreeview(self.availableThemes, ['str'], 0) # Show Installed Themes self.lblTitle2.set_label(_("Installed Themes")) if len(self.installedThemes) > 0: self.tv2Handler.fillTreeview(self.installedThemes, ['str'], 0) def on_btnGrub_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[2] or refresh: self.selectedMenuItem = menuItems[2] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Set Grub Resolution")) self.btn2.hide() self.lblTitle2.set_visible(False) self.sw2.hide() # Show Resolutios self.lblTitle1.set_text(_("Grub Resolutions")) ind = -1 if self.currentGrubResolution: try: ind = self.resolutions.index(self.currentGrubResolution) except: ind = 0 if len(self.resolutions) > 0: self.tv1Handler.fillTreeview(self.resolutions, ['str'], ind, 700) # =============================================== # Treeview functions # =============================================== def on_tv1_cursor_changed(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes Menu self.selectedTheme = self.tv1Handler.getSelectedValue() self.log.write("Themes menu - seleceted theme: %(theme)s" % { "theme": self.selectedTheme }, 'dpm.tv1Changed') elif self.selectedMenuItem == menuItems[1]: # Install Menu self.selectedAvailableTheme = self.tv1Handler.getSelectedValue() self.log.write("Install menu - seleceted available theme: %(theme)s" % { "theme": self.selectedAvailableTheme }, 'dpm.tv1Changed') elif self.selectedMenuItem == menuItems[2]: # Grub Menu self.selectedGrubResolution = self.tv1Handler.getSelectedValue() self.log.write("Grub menu - seleceted grub resolution: %(res)s" % { "res": self.selectedGrubResolution }, 'dpm.tv1Changed') def on_tv2_cursor_changed(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes Menu self.selectedResolution = self.tv2Handler.getSelectedValue() self.log.write("Themes menu - seleceted resolution: %(res)s" % { "res": self.selectedResolution }, 'dpm.tv2Changed') elif self.selectedMenuItem == menuItems[1]: # Install Menu self.selectedRemoveTheme = self.tv2Handler.getSelectedValue() self.log.write("Install menu - seleceted theme to remove: %(theme)s" % { "theme": self.selectedRemoveTheme }, 'dpm.tv2Changed') # =============================================== # Button functions # =============================================== def on_btn1_clicked(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes self.setTheme() elif self.selectedMenuItem == menuItems[1]: # Install self.installTheme() elif self.selectedMenuItem == menuItems[2]: # Grub self.setGrubResolution() def on_btn2_clicked(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes self.preview() elif self.selectedMenuItem == menuItems[1]: # Install self.removeTheme() elif self.selectedMenuItem == menuItems[2]: # Grub pass # =============================================== # Themes section functions # =============================================== def preview(self): # Check if the selected have been saved if self.currentTheme == self.selectedTheme and self.currentResolution == self.selectedResolution: self.plymouth.previewPlymouth() else: title = _("Preview") msg = _("You must save before you can preview:\n\nTheme: %(theme)s\nResolution: %(res)s") % { "theme": self.selectedTheme, "res": self.selectedResolution } MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def setTheme(self): self.toggleGuiElements(True) if self.selectedTheme != self.noPlymouth: if self.selectedResolution is None: self.selectedResolution = self.tv2Handler.getValue(self.tv2Handler.getRowCount() - 1) else: self.selectedTheme = None self.selectedResolution = None self.log.write(_("Save setting: %(theme)s (%(res)s)") % { "theme": self.selectedTheme, "res": self.selectedResolution }, 'dpm.setTheme', 'info') # Start saving in a separate thread t = PlymouthSave(self.log, self.selectedTheme, self.selectedResolution) t.start() GObject.timeout_add(250, self.checkSaveThread) def checkSaveThread(self): #print 'Thread count = ' + str(threading.active_count()) # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Get the new data self.pbDPM.set_fraction(0) self.currentTheme = self.plymouth.getCurrentTheme() self.currentResolution = self.plymouth.getCurrentResolution() self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() if self.selectedMenuItem == menuItems[0]: self.on_btnPlymouth_clicked(None, None, True) # Thread is done: make button sensitive again self.toggleGuiElements(False) self.log.write(_("Done saving settings: %(theme)s (%(res)s)") % { "theme": self.currentTheme, "res": self.currentResolution }, 'dpm.checkSaveThread', 'info') title = _("Save settings") msg = _("Theme: %(theme)s\nResolution: %(res)s\n\nDone") % { "theme": self.currentTheme, "res": str(self.currentResolution) } self.log.write(msg, 'dpm.checkSaveThread') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False def toggleGuiElements(self, startSave): if startSave: self.btn1.set_sensitive(False) self.btn2.set_sensitive(False) else: self.btn1.set_sensitive(True) self.btn2.set_sensitive(True) # =============================================== # Install section functions # =============================================== def installTheme(self): self.threadAction = _("install") self.threadPackage = self.plymouth.getPackageName(self.selectedAvailableTheme) if self.threadPackage: dialog = QuestionDialog(_("Install theme"), _("Continue installing theme:\n%(theme)s") % { "theme": self.threadPackage }, self.window) go = dialog.show() if (go): self.toggleGuiElements(True) self.log.write(_("Start installing theme: %(theme)s") % { "theme": self.threadPackage }, 'dpm.installTheme', 'info') # Start apt in a separate thread cmd = 'apt-get install -y %s %s' % (self.force, self.threadPackage) t = ExecuteApt(self.log, cmd, self.queue) t.daemon = True t.start() self.queue.join() #self.log.write("Check every 250 miliseconds if thread is still active", 'dpm.installTheme') GObject.timeout_add(250, self.checkAptThread) else: self.log.write(_("User cancel install theme: %(theme)s") % { "theme": self.threadPackage }, 'dpm.installTheme', 'info') else: title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } msg = _("The package cannot be installed: %(pck)s\nTry apt instead") % { "pck": self.threadPackage } self.log.write(msg, 'dpm.installTheme') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def removeTheme(self): self.threadAction = _("remove") self.threadPackage = self.plymouth.getRemovablePackageName(self.selectedRemoveTheme) if self.threadPackage: dialog = QuestionDialog(_("Remove theme"), _("Continue removing theme:\n%(theme)s") % { "theme": self.threadPackage }, self.window) go = dialog.show() if (go): self.toggleGuiElements(True) # Start apt in a separate thread self.log.write(_("Start removing theme: %(theme)s") % { "theme": self.threadPackage }, 'dpm.removeTheme', 'info') cmd = 'apt-get purge -y %s %s' % (self.force, self.threadPackage) t = ExecuteApt(self.log, cmd, self.queue) t.daemon = True t.start() self.queue.join() #self.log.write("Check every 250 miliseconds if thread is still active", 'dpm.removeTheme') GObject.timeout_add(250, self.checkAptThread) else: self.log.write(_("User cancel remove theme: %(theme)s") % { "theme": self.threadPackage }, 'dpm.removeTheme', 'info') else: title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } msg = _("The package cannot be removed: %(pck)s\nIt is part of a meta package.\nTry apt instead") % { "pck": self.selectedRemoveTheme } self.log.write(msg, 'dpm.removeTheme') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def checkAptThread(self): # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Thread is done self.pbDPM.set_fraction(0) # Get the error data from the queue aptError = self.queue.get() # Get the new data self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() if self.selectedMenuItem == menuItems[1]: self.on_btnThemes_clicked(None, None, True) self.toggleGuiElements(False) title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } if aptError: msg = _("Could not %(action)s theme:\n%(theme)s\nTry apt instead.\n\nError message:\n%(err)s") % { "action": self.threadAction, "theme": self.threadPackage, "err": aptError } else: msg = _("%(action)s successfully of:\n%(pck)s") % { "action": self.threadAction[0].capitalize() + self.threadAction[1:], "pck": self.threadPackage } self.log.write(msg, 'dpm.checkAptThread') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False # =============================================== # Grub section functions # =============================================== def setGrubResolution(self): self.toggleGuiElements(True) self.log.write(_("Save grub resolution: %(res)s") % { "res": self.selectedGrubResolution }, 'dpm.setGrubResolution', 'info') # Start saving in a separate thread t = GrubSave(self.log, self.selectedGrubResolution) t.start() GObject.timeout_add(250, self.checkGrubThread) def checkGrubThread(self): # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Thread is done self.pbDPM.set_fraction(0) self.currentGrubResolution = self.grub.getCurrentResolution() if self.selectedMenuItem == menuItems[2]: self.on_btnGrub_clicked(None, None, True) self.toggleGuiElements(False) title = _("Grub resolution") msg = _("Grub resolution saved: %(res)s") % { "res": self.selectedGrubResolution } self.log.write(msg, 'dpm.setGrubResolution', 'info') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False def on_dpmWindow_destroy(self, widget, data=None): # Close the app Gtk.main_quit()
class Plymouth(): def __init__(self, loggerObject): self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.avlThemesSearchstr = 'plymouth-themes' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.modulesPath = '/etc/initramfs-tools/modules' # Get a list of installed Plymouth themes def getInstalledThemes(self): instThemes = [] if os.path.isfile(self.setThemePath): cmd = '%s --list' % self.setThemePath instThemes = utils.getoutput(cmd) return instThemes # Get the currently used Plymouth theme def getCurrentTheme(self): curTheme = None if os.path.isfile(self.setThemePath): if self.boot is not None: grubCont = "" with open(self.boot, 'r') as f: grubCont = f.read() matchObj = re.search('GRUB_CMDLINE_LINUX_DEFAULT="(.*)"', grubCont) if matchObj: if ' splash' in matchObj.group(1): curThemeList = utils.getoutput(self.setThemePath) if curThemeList: curTheme = curThemeList[0] return curTheme # Get a list of Plymouth themes in the repositories that can be installed def getAvailableThemes(self): cmd = 'aptitude search %s | grep ^p' % self.avlThemesSearchstr availableThemes = utils.getoutput(cmd) avlThemes = [] for line in availableThemes: matchObj = re.search( '%s-([a-zA-Z0-9-]*)' % self.avlThemesSearchstr, line) if matchObj: theme = matchObj.group(1) if not 'all' in theme: avlThemes.append(theme) return avlThemes def previewPlymouth(self): try: cmd = "su -c 'plymouthd; plymouth --show-splash ; for ((I=0; I<10; I++)); do plymouth --update=test$I ; sleep 1; done; plymouth quit'" utils.shell_exec(cmd) except Exception as detail: self.log.write(detail, 'plymouth.previewPlymouth', 'error') # Get the package name that can be uninstalled of a given Plymouth theme def getRemovablePackageName(self, theme): cmd = 'dpkg -S %s.plymouth' % theme package = None packageNames = utils.getoutput(cmd) for line in packageNames: if self.avlThemesSearchstr in line: matchObj = re.search('(^.*):', line) if matchObj: package = matchObj.group(1) break self.log.write("Package found %(pck)s" % {"pck": package}, 'plymouth.getRemovablePackageName', 'debug') return package # Get valid package name of a Plymouth theme (does not have to exist in the repositories) def getPackageName(self, theme): return self.avlThemesSearchstr + "-" + theme # Get current Plymouth resolution def getCurrentResolution(self): lines = [] res = self.grub.getCurrentResolution() # The Wheezy way of configuring if res is None: with open(self.modulesPath, 'r') as f: lines = f.readlines() for line in lines: matchObj = re.search('^uvesafb\s+mode_option\s*=\s*([0-9x]+)', line) if matchObj: res = matchObj.group(1) self.log.write( "Current Plymouth resolution: %(res)s" % {"res": res}, 'plymouth.getCurrentResolution', 'debug') break # Old way of configuring Plymouth if res is None: if self.boot is not None: with open(self.boot, 'r') as f: lines = f.readlines() for line in lines: # Search text for resolution matchObj = re.search('^GRUB_GFXPAYLOAD_LINUX=(.*)', line) if matchObj: res = matchObj.group(1) self.log.write( "Current Plymouth resolution: %(res)s" % {"res": res}, 'plymouth.getCurrentResolution', 'debug') break else: self.log.write( _("Neither grub nor burg found in /etc/default"), 'plymouth.getCurrentResolution', 'error') return res
class PlymouthSave(threading.Thread): def __init__(self, loggerObject, theme=None, resolution=None): threading.Thread.__init__(self) self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.theme = None self.resolution = None self.modulesPath = '/etc/initramfs-tools/modules' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.plymouth = Plymouth(self.log) self.installedThemes = self.plymouth.getInstalledThemes() if theme in self.installedThemes and resolution is not None: self.log.write("Set theme: {0} ({1})".format(theme, resolution), 'PlymouthSave.init', 'debug') self.theme = theme self.resolution = resolution # Save given theme and resolution def run(self): try: if not os.path.exists(self.modulesPath): utils.shell_exec("touch {}".format(self.modulesPath)) # Cleanup first utils.shell_exec("sed -i -e 's/^ *//; s/ *$//' %s" % self.modulesPath) # Trim all lines utils.shell_exec("sed -i -e '/^.*KMS$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^intel_agp$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^drm$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^nouveau modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^radeon modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^i915 modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^uvesafb\s*mode_option.*/d' %s" % self.modulesPath) if os.path.exists(self.boot): utils.shell_exec("sed -i -e '/^GRUB_GFXPAYLOAD_LINUX.*/d' %s" % self.boot) splashFile = '/etc/initramfs-tools/conf.d/splash' if os.path.exists(splashFile): os.remove(splashFile) # Set/Unset splash cmd = "sed -i -e 's/\s*[a-z]*splash//' {}".format(self.boot) utils.shell_exec(cmd) if self.theme is None: self.log.write("Set nosplash", 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ nosplash\"/' {}".format( self.boot) utils.shell_exec(cmd) # Comment the GRUB_GFXMODE line if needed cmd = "sed -i '/GRUB_GFXMODE=/s/^/#/' %s" % self.boot utils.shell_exec(cmd) else: self.log.write("Set splash", 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ splash\"/' {}".format( self.boot) utils.shell_exec(cmd) # Set resolution if self.resolution is not None: self.log.write("GRUB_GFXMODE={}".format(self.resolution), 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/GRUB_GFXMODE=/ c GRUB_GFXMODE={0}' {1}".format( self.resolution, self.boot) utils.shell_exec(cmd) # Only for plymouth version older than 9 if self.theme is not None and self.resolution is not None: plymouthVersion = utils.strToNumber( utils.getPackageVersion("plymouth").replace('.', '')[0:2], True) self.log.write("plymouthVersion={}".format(plymouthVersion), 'PlymouthSave.run', 'debug') if plymouthVersion < 9: # Write uvesafb command to modules file self.log.write("> Use uvesafb to configure Plymouth", 'PlymouthSave.run', 'debug') line = "\nuvesafb mode_option=%s-24 mtrr=3 scroll=ywrap\ndrm\n" % self.resolution with open(self.modulesPath, 'a') as f: f.write(line) # Use framebuffer line = "FRAMEBUFFER=y" with open('/etc/initramfs-tools/conf.d/splash', 'w') as f: f.write(line) # Read grub for debugging purposes with open(self.boot, 'r') as f: content = f.read() self.log.write("\nNew grub:\n{}\n".format(content), 'PlymouthSave.run', 'debug') # Update grub if 'grub' in self.boot: utils.shell_exec('update-grub') else: utils.shell_exec('update-burg') # Set the theme and update initramfs if self.theme is not None: utils.shell_exec("{0} -R {1}".format(self.setThemePath, self.theme)) except Exception as detail: self.log.write(detail, 'PlymouthSave.run', 'exception')
class Plymouth(): def __init__(self, loggerObject=None): self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.avlThemesSearchstr = '^plymouth-theme' self.setThemePath = which('plymouth-set-default-theme') self.modulesPath = '/etc/initramfs-tools/modules' self.grubcfg = '/boot/grub/grub.cfg' # Get a list of installed Plymouth themes def getInstalledThemes(self): instThemes = [] try: if isfile(self.setThemePath): cmd = '%s --list' % self.setThemePath instThemes = getoutput(cmd) except: pass return instThemes def is_plymouth_booted(self): cmdline = getoutput("cat /proc/cmdline")[0] if ' splash' in cmdline: return True else: # It could be that the user manually removed splash in Grub when booting # Check grub.cfg matchObj = re.search('\/.*=[0-9a-z\-]+', cmdline) if matchObj: if exists(self.grubcfg): grubcfg_splash = getoutput( 'grep "{}" "{}" | grep " splash"'.format( matchObj.group(0), self.grubcfg))[0] if grubcfg_splash: return True return False # Get the currently used Plymouth theme def getCurrentTheme(self): try: if isfile(self.setThemePath) and \ self.is_plymouth_booted(): return getoutput(self.setThemePath)[0] except: pass return '' # Get a list of Plymouth themes in the repositories that can be installed def getAvailableThemes(self): cmd = 'apt-cache pkgnames {}'.format(self.avlThemesSearchstr) availableThemes = getoutput(cmd) avlThemes = [] for line in availableThemes: matchObj = re.search( '%s-([a-zA-Z0-9-]*)' % self.avlThemesSearchstr, line) if matchObj: theme = matchObj.group(1) if not 'all' in theme: avlThemes.append(theme) return avlThemes def previewPlymouth(self): try: cmd = "su -c 'plymouthd; plymouth --show-splash ; for ((I=0; I<10; I++)); do plymouth --update=test$I ; sleep 1; done; plymouth quit'" shell_exec(cmd) except Exception as detail: self.write_log(detail, 'exception') # Get the package name that can be uninstalled of a given Plymouth theme def getRemovablePackageName(self, theme): cmd = 'dpkg -S %s.plymouth' % theme package = None packageNames = getoutput(cmd) for line in packageNames: if self.avlThemesSearchstr in line: matchObj = re.search('(^.*):', line) if matchObj: package = matchObj.group(1) break self.write_log("Package found %(pck)s" % {"pck": package}) return package # Get valid package name of a Plymouth theme (does not have to exist in the repositories) def getPackageName(self, theme): return self.avlThemesSearchstr + "-" + theme # Get current Plymouth resolution def getCurrentResolution(self): lines = [] res = self.grub.getCurrentResolution() # The Wheezy way of configuring if res is None: with open(self.modulesPath, 'r') as f: lines = f.readlines() for line in lines: matchObj = re.search('^uvesafb\s+mode_option\s*=\s*([0-9x]+)', line) if matchObj: res = matchObj.group(1) self.write_log("Current Plymouth resolution: %(res)s" % {"res": res}) break # Old way of configuring Plymouth if res is None: if self.boot is not None: with open(self.boot, 'r') as f: lines = f.readlines() for line in lines: # Search text for resolution matchObj = re.search( '^GRUB_GFXPAYLOAD_LINUX\s*=[\s"]*([0-9]+x[0-9]+)', line) if matchObj: res = matchObj.group(1) self.write_log("Current Plymouth resolution: %(res)s" % {"res": res}) break else: self.write_log( _("Neither grub nor burg found in /etc/default"), 'warning') return res def write_log(self, message, level='debug'): if self.log is not None: self.log.write(message, 'Plymouth', level)
class PlymouthSave(threading.Thread): def __init__(self, theme=None, resolution=None, queue=None, loggerObject=None): threading.Thread.__init__(self) self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.theme = None self.resolution = None self.queue = queue self.modulesPath = '/etc/initramfs-tools/modules' self.setThemePath = which('plymouth-set-default-theme') self.plymouth = Plymouth(self.log) self.installedThemes = self.plymouth.getInstalledThemes() if theme in self.installedThemes and resolution is not None: self.write_log("Set theme: {0} ({1})".format(theme, resolution)) self.theme = theme self.resolution = resolution # Steps self.max_steps = 6 self.current_step = 0 # Save given theme and resolution def run(self): if self.setThemePath is None: self.write_log('Plymouth not installed - exiting', 'warning') return try: if not exists(self.modulesPath): shell_exec("touch {}".format(self.modulesPath)) # Cleanup first self.queue_progress() shell_exec("sed -i -e 's/^ *//; s/ *$//' %s" % self.modulesPath) # Trim all lines shell_exec("sed -i -e '/^.*KMS$/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^intel_agp$/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^drm$/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^nouveau modeset.*/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^radeon modeset.*/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^i915 modeset.*/d' %s" % self.modulesPath) shell_exec("sed -i -e '/^uvesafb\s*mode_option.*/d' %s" % self.modulesPath) if self.boot is not None: shell_exec("sed -i -e '/^GRUB_GFXPAYLOAD_LINUX.*/d' %s" % self.boot) splashFile = '/etc/initramfs-tools/conf.d/splash' if exists(splashFile): os.remove(splashFile) # Set/Unset splash self.queue_progress() if self.boot is not None: cmd = "sed -i -e 's/\s*[a-z]*splash//' {}".format(self.boot) shell_exec(cmd) if self.theme is None: self.write_log("Set nosplash") cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ nosplash\"/' {}".format( self.boot) shell_exec(cmd) # Comment the GRUB_GFXMODE line if needed cmd = "sed -i '/GRUB_GFXMODE=/s/^/#/' %s" % self.boot shell_exec(cmd) else: self.write_log("Set splash") cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ splash\"/' {}".format( self.boot) shell_exec(cmd) # Set resolution if self.resolution is not None: self.write_log("GRUB_GFXMODE={}".format( self.resolution)) cmd = "sed -i -e '/GRUB_GFXMODE=/ c GRUB_GFXMODE={0}' {1}".format( self.resolution, self.boot) shell_exec(cmd) # Only for plymouth version older than 9 self.queue_progress() if self.theme is not None and self.resolution is not None: plymouthVersion = str_to_nr( get_package_version("plymouth").replace('.', '')[0:2], True) self.write_log("plymouthVersion={}".format(plymouthVersion)) if plymouthVersion < 9: # Write uvesafb command to modules file self.write_log("> Use uvesafb to configure Plymouth") line = "\nuvesafb mode_option=%s-24 mtrr=3 scroll=ywrap\ndrm\n" % self.resolution with open(self.modulesPath, 'a') as f: f.write(line) # Use framebuffer line = "FRAMEBUFFER=y" with open('/etc/initramfs-tools/conf.d/splash', 'w') as f: f.write(line) if self.boot is not None: # Read grub for debugging purposes with open(self.boot, 'r') as f: content = f.read() self.write_log("\nNew grub:\n{}\n".format(content)) # Update grub self.queue_progress() if 'grub' in self.boot: shell_exec('update-grub') else: shell_exec('update-burg') # Set the theme and update initramfs self.queue_progress() if self.theme is not None: shell_exec("{0} -R {1}".format(self.setThemePath, self.theme)) except Exception as detail: self.write_log(detail, 'exception') def queue_progress(self): self.current_step += 1 if self.current_step > self.max_steps: self.current_step = self.max_steps if self.queue is not None: #print((">> step %d of %d" % (self.current_step, self.max_steps))) self.queue.put([self.max_steps, self.current_step]) def write_log(self, message, level='debug'): if self.log is not None: self.log.write(message, 'PlymouthSave', level)
def __init__(self): self.scriptDir = dirname(realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join( self.scriptDir, '../../share/debian-plymouth-manager/debian-plymouth-manager.glade' )) # Main window objects go = self.builder.get_object self.window = go('dpmWindow') self.tv1 = go('tv1') self.tv2 = go('tv2') self.sw2 = go('sw2') self.statusbar = go('statusbar') self.btnPlymouth = go('btnPlymouth') self.btnThemes = go('btnThemes') self.btnGrub = go('btnGrub') self.pbDPM = go('pbDPM') self.btn1 = go('btn1') self.btn2 = go('btn2') self.lblTitle1 = go('lblTitle1') self.lblTitle2 = go('lblTitle2') # Translations title = _("Debian Plymouth Manager") self.window.set_title(title) self.btnPlymouth.set_label("_" + _("Plymouth")) self.btnThemes.set_label("_" + _("Themes")) self.btnGrub.set_label("_" + _("Grub")) self.selectedMenuItem = None self.selectedAvailableTheme = None self.selectedRemoveTheme = None self.threadPackage = None self.queue = Queue() self.noPlymouth = _('None: no plymouth splash') # Set some variables self.logFile = '/var/log/dpm.log' self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=1024) self.version = utils.getPackageVersion('debian-plymouth-manager') self.plymouth = Plymouth(self.log) self.grub = Grub(self.log) self.resolutions = utils.getResolutions('800x600', '', True, False) self.currentResolution = self.plymouth.getCurrentResolution() self.selectedResolution = self.currentResolution self.currentGrubResolution = self.grub.getCurrentResolution() self.selectedGrubResolution = self.currentGrubResolution self.currentTheme = self.plymouth.getCurrentTheme() self.selectedTheme = self.currentTheme self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() self.tv1Handler = TreeViewHandler(self.tv1, self.log) self.tv2Handler = TreeViewHandler(self.tv2, self.log) self.force = utils.get_apt_force() self.on_btnPlymouth_clicked() # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # TODO: Hide the tool bar for now go('tlbMain').set_visible(False)
class DPM: def __init__(self): self.scriptDir = dirname(realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join( self.scriptDir, '../../share/debian-plymouth-manager/debian-plymouth-manager.glade' )) # Main window objects go = self.builder.get_object self.window = go('dpmWindow') self.tv1 = go('tv1') self.tv2 = go('tv2') self.sw2 = go('sw2') self.statusbar = go('statusbar') self.btnPlymouth = go('btnPlymouth') self.btnThemes = go('btnThemes') self.btnGrub = go('btnGrub') self.pbDPM = go('pbDPM') self.btn1 = go('btn1') self.btn2 = go('btn2') self.lblTitle1 = go('lblTitle1') self.lblTitle2 = go('lblTitle2') # Translations title = _("Debian Plymouth Manager") self.window.set_title(title) self.btnPlymouth.set_label("_" + _("Plymouth")) self.btnThemes.set_label("_" + _("Themes")) self.btnGrub.set_label("_" + _("Grub")) self.selectedMenuItem = None self.selectedAvailableTheme = None self.selectedRemoveTheme = None self.threadPackage = None self.queue = Queue() self.noPlymouth = _('None: no plymouth splash') # Set some variables self.logFile = '/var/log/dpm.log' self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=1024) self.version = utils.getPackageVersion('debian-plymouth-manager') self.plymouth = Plymouth(self.log) self.grub = Grub(self.log) self.resolutions = utils.getResolutions('800x600', '', True, False) self.currentResolution = self.plymouth.getCurrentResolution() self.selectedResolution = self.currentResolution self.currentGrubResolution = self.grub.getCurrentResolution() self.selectedGrubResolution = self.currentGrubResolution self.currentTheme = self.plymouth.getCurrentTheme() self.selectedTheme = self.currentTheme self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() self.tv1Handler = TreeViewHandler(self.tv1, self.log) self.tv2Handler = TreeViewHandler(self.tv2, self.log) self.force = utils.get_apt_force() self.on_btnPlymouth_clicked() # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # TODO: Hide the tool bar for now go('tlbMain').set_visible(False) # =============================================== # Menu section functions # =============================================== def on_btnPlymouth_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[0] or refresh: self.selectedMenuItem = menuItems[0] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Set Plymouth Theme")) self.btn2.set_label(_("Preview")) self.btn2.show() self.lblTitle2.set_visible(True) self.sw2.show() # Show Installed Themes self.lblTitle1.set_label(_("Installed Themes")) # Clone the installedThemes list listInst = list(self.installedThemes) listInst.append(self.noPlymouth) # Get current theme and set setcursor ind = -1 if self.currentTheme: try: ind = listInst.index(self.currentTheme) except: # Theme is set but removed from system ind = 0 else: ind = len(listInst) - 1 if len(listInst) > 0: self.tv1Handler.fillTreeview(listInst, ['str'], ind, 700) # Show Resolutios self.lblTitle2.set_label(_("Resolutions")) ind = -1 if self.currentResolution: try: ind = self.resolutions.index(self.currentResolution) except: ind = 0 if len(self.resolutions) > 0: self.tv2Handler.fillTreeview(self.resolutions, ['str'], ind, 700) def on_btnThemes_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[1] or refresh: self.selectedMenuItem = menuItems[1] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Install Theme")) self.btn2.set_label(_("Remove Theme")) self.btn2.show() self.lblTitle2.set_visible(True) self.sw2.show() # Show Available Themes self.lblTitle1.set_label(_("Available Themes")) if len(self.availableThemes) > 0: self.tv1Handler.fillTreeview(self.availableThemes, ['str'], 0) # Show Installed Themes self.lblTitle2.set_label(_("Installed Themes")) if len(self.installedThemes) > 0: self.tv2Handler.fillTreeview(self.installedThemes, ['str'], 0) def on_btnGrub_clicked(self, widget=None, event=None, refresh=False): if self.selectedMenuItem != menuItems[2] or refresh: self.selectedMenuItem = menuItems[2] # Clear treeviews self.tv1Handler.clearTreeView() self.tv2Handler.clearTreeView() # Set object properties self.btn1.set_label(_("Set Grub Resolution")) self.btn2.hide() self.lblTitle2.set_visible(False) self.sw2.hide() # Show Resolutios self.lblTitle1.set_text(_("Grub Resolutions")) ind = -1 if self.currentGrubResolution: try: ind = self.resolutions.index(self.currentGrubResolution) except: ind = 0 if len(self.resolutions) > 0: self.tv1Handler.fillTreeview(self.resolutions, ['str'], ind, 700) # =============================================== # Treeview functions # =============================================== def on_tv1_cursor_changed(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes Menu self.selectedTheme = self.tv1Handler.getSelectedValue() self.log.write( "Themes menu - seleceted theme: %(theme)s" % {"theme": self.selectedTheme}, 'dpm.tv1Changed') elif self.selectedMenuItem == menuItems[1]: # Install Menu self.selectedAvailableTheme = self.tv1Handler.getSelectedValue() self.log.write( "Install menu - seleceted available theme: %(theme)s" % {"theme": self.selectedAvailableTheme}, 'dpm.tv1Changed') elif self.selectedMenuItem == menuItems[2]: # Grub Menu self.selectedGrubResolution = self.tv1Handler.getSelectedValue() self.log.write( "Grub menu - seleceted grub resolution: %(res)s" % {"res": self.selectedGrubResolution}, 'dpm.tv1Changed') def on_tv2_cursor_changed(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes Menu self.selectedResolution = self.tv2Handler.getSelectedValue() self.log.write( "Themes menu - seleceted resolution: %(res)s" % {"res": self.selectedResolution}, 'dpm.tv2Changed') elif self.selectedMenuItem == menuItems[1]: # Install Menu self.selectedRemoveTheme = self.tv2Handler.getSelectedValue() self.log.write( "Install menu - seleceted theme to remove: %(theme)s" % {"theme": self.selectedRemoveTheme}, 'dpm.tv2Changed') # =============================================== # Button functions # =============================================== def on_btn1_clicked(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes self.setTheme() elif self.selectedMenuItem == menuItems[1]: # Install self.installTheme() elif self.selectedMenuItem == menuItems[2]: # Grub self.setGrubResolution() def on_btn2_clicked(self, widget): if self.selectedMenuItem == menuItems[0]: # Themes self.preview() elif self.selectedMenuItem == menuItems[1]: # Install self.removeTheme() elif self.selectedMenuItem == menuItems[2]: # Grub pass # =============================================== # Themes section functions # =============================================== def preview(self): # Check if the selected have been saved if self.currentTheme == self.selectedTheme and self.currentResolution == self.selectedResolution: self.plymouth.previewPlymouth() else: title = _("Preview") msg = _( "You must save before you can preview:\n\nTheme: %(theme)s\nResolution: %(res)s" ) % { "theme": self.selectedTheme, "res": self.selectedResolution } MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def setTheme(self): self.toggleGuiElements(True) if self.selectedTheme != self.noPlymouth: if self.selectedResolution is None: self.selectedResolution = self.tv2Handler.getValue( self.tv2Handler.getRowCount() - 1) else: self.selectedTheme = None self.selectedResolution = None self.log.write( _("Save setting: %(theme)s (%(res)s)") % { "theme": self.selectedTheme, "res": self.selectedResolution }, 'dpm.setTheme', 'info') # Start saving in a separate thread t = PlymouthSave(self.log, self.selectedTheme, self.selectedResolution) t.start() GObject.timeout_add(250, self.checkSaveThread) def checkSaveThread(self): #print 'Thread count = ' + str(threading.active_count()) # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Get the new data self.pbDPM.set_fraction(0) self.currentTheme = self.plymouth.getCurrentTheme() self.currentResolution = self.plymouth.getCurrentResolution() self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() if self.selectedMenuItem == menuItems[0]: self.on_btnPlymouth_clicked(None, None, True) # Thread is done: make button sensitive again self.toggleGuiElements(False) self.log.write( _("Done saving settings: %(theme)s (%(res)s)") % { "theme": self.currentTheme, "res": self.currentResolution }, 'dpm.checkSaveThread', 'info') title = _("Save settings") msg = _("Theme: %(theme)s\nResolution: %(res)s\n\nDone") % { "theme": self.currentTheme, "res": str(self.currentResolution) } self.log.write(msg, 'dpm.checkSaveThread') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False def toggleGuiElements(self, startSave): if startSave: self.btn1.set_sensitive(False) self.btn2.set_sensitive(False) else: self.btn1.set_sensitive(True) self.btn2.set_sensitive(True) # =============================================== # Install section functions # =============================================== def installTheme(self): self.threadAction = _("install") self.threadPackage = self.plymouth.getPackageName( self.selectedAvailableTheme) if self.threadPackage: dialog = QuestionDialog( _("Install theme"), _("Continue installing theme:\n%(theme)s") % {"theme": self.threadPackage}, self.window) go = dialog.show() if (go): self.toggleGuiElements(True) self.log.write( _("Start installing theme: %(theme)s") % {"theme": self.threadPackage}, 'dpm.installTheme', 'info') # Start apt in a separate thread cmd = 'apt-get install -y %s %s' % (self.force, self.threadPackage) t = ExecuteApt(self.log, cmd, self.queue) t.daemon = True t.start() self.queue.join() #self.log.write("Check every 250 miliseconds if thread is still active", 'dpm.installTheme') GObject.timeout_add(250, self.checkAptThread) else: self.log.write( _("User cancel install theme: %(theme)s") % {"theme": self.threadPackage}, 'dpm.installTheme', 'info') else: title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } msg = _("The package cannot be installed: %(pck)s\nTry apt instead" ) % { "pck": self.threadPackage } self.log.write(msg, 'dpm.installTheme') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def removeTheme(self): self.threadAction = _("remove") self.threadPackage = self.plymouth.getRemovablePackageName( self.selectedRemoveTheme) if self.threadPackage: dialog = QuestionDialog( _("Remove theme"), _("Continue removing theme:\n%(theme)s") % {"theme": self.threadPackage}, self.window) go = dialog.show() if (go): self.toggleGuiElements(True) # Start apt in a separate thread self.log.write( _("Start removing theme: %(theme)s") % {"theme": self.threadPackage}, 'dpm.removeTheme', 'info') cmd = 'apt-get purge -y %s %s' % (self.force, self.threadPackage) t = ExecuteApt(self.log, cmd, self.queue) t.daemon = True t.start() self.queue.join() #self.log.write("Check every 250 miliseconds if thread is still active", 'dpm.removeTheme') GObject.timeout_add(250, self.checkAptThread) else: self.log.write( _("User cancel remove theme: %(theme)s") % {"theme": self.threadPackage}, 'dpm.removeTheme', 'info') else: title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } msg = _( "The package cannot be removed: %(pck)s\nIt is part of a meta package.\nTry apt instead" ) % { "pck": self.selectedRemoveTheme } self.log.write(msg, 'dpm.removeTheme') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() def checkAptThread(self): # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Thread is done self.pbDPM.set_fraction(0) # Get the error data from the queue aptError = self.queue.get() # Get the new data self.installedThemes = self.plymouth.getInstalledThemes() self.availableThemes = self.plymouth.getAvailableThemes() if self.selectedMenuItem == menuItems[1]: self.on_btnThemes_clicked(None, None, True) self.toggleGuiElements(False) title = _("%(act1)s%(act2)s theme") % { "act1": self.threadAction[0].capitalize(), "act2": self.threadAction[1:] } if aptError: msg = _( "Could not %(action)s theme:\n%(theme)s\nTry apt instead.\n\nError message:\n%(err)s" ) % { "action": self.threadAction, "theme": self.threadPackage, "err": aptError } else: msg = _("%(action)s successfully of:\n%(pck)s") % { "action": self.threadAction[0].capitalize() + self.threadAction[1:], "pck": self.threadPackage } self.log.write(msg, 'dpm.checkAptThread') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False # =============================================== # Grub section functions # =============================================== def setGrubResolution(self): self.toggleGuiElements(True) self.log.write( _("Save grub resolution: %(res)s") % {"res": self.selectedGrubResolution}, 'dpm.setGrubResolution', 'info') # Start saving in a separate thread t = GrubSave(self.log, self.selectedGrubResolution) t.start() GObject.timeout_add(250, self.checkGrubThread) def checkGrubThread(self): # As long there's a thread active, keep spinning if threading.active_count() > 1: self.pbDPM.pulse() return True # Thread is done self.pbDPM.set_fraction(0) self.currentGrubResolution = self.grub.getCurrentResolution() if self.selectedMenuItem == menuItems[2]: self.on_btnGrub_clicked(None, None, True) self.toggleGuiElements(False) title = _("Grub resolution") msg = _("Grub resolution saved: %(res)s") % { "res": self.selectedGrubResolution } self.log.write(msg, 'dpm.setGrubResolution', 'info') MessageDialogSafe(title, msg, Gtk.MessageType.INFO, self.window).show() return False def on_dpmWindow_destroy(self, widget, data=None): # Close the app Gtk.main_quit()
class Plymouth(): def __init__(self, loggerObject): self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.avlThemesSearchstr = 'plymouth-themes' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.modulesPath = '/etc/initramfs-tools/modules' # Get a list of installed Plymouth themes def getInstalledThemes(self): instThemes = [] if os.path.isfile(self.setThemePath): cmd = '%s --list' % self.setThemePath instThemes = utils.getoutput(cmd) return instThemes # Get the currently used Plymouth theme def getCurrentTheme(self): curTheme = None if os.path.isfile(self.setThemePath): if self.boot is not None: grubCont = "" with open(self.boot, 'r') as f: grubCont = f.read() matchObj = re.search('GRUB_CMDLINE_LINUX_DEFAULT="(.*)"', grubCont) if matchObj: if ' splash' in matchObj.group(1): curThemeList = utils.getoutput(self.setThemePath) if curThemeList: curTheme = curThemeList[0] return curTheme # Get a list of Plymouth themes in the repositories that can be installed def getAvailableThemes(self): cmd = 'aptitude search %s | grep ^p' % self.avlThemesSearchstr availableThemes = utils.getoutput(cmd) avlThemes = [] for line in availableThemes: matchObj = re.search('%s-([a-zA-Z0-9-]*)' % self.avlThemesSearchstr, line) if matchObj: theme = matchObj.group(1) if not 'all' in theme: avlThemes.append(theme) return avlThemes def previewPlymouth(self): try: cmd = "su -c 'plymouthd; plymouth --show-splash ; for ((I=0; I<10; I++)); do plymouth --update=test$I ; sleep 1; done; plymouth quit'" utils.shell_exec(cmd) except Exception as detail: self.log.write(detail, 'plymouth.previewPlymouth', 'error') # Get the package name that can be uninstalled of a given Plymouth theme def getRemovablePackageName(self, theme): cmd = 'dpkg -S %s.plymouth' % theme package = None packageNames = utils.getoutput(cmd) for line in packageNames: if self.avlThemesSearchstr in line: matchObj = re.search('(^.*):', line) if matchObj: package = matchObj.group(1) break self.log.write("Package found %(pck)s" % { "pck": package }, 'plymouth.getRemovablePackageName', 'debug') return package # Get valid package name of a Plymouth theme (does not have to exist in the repositories) def getPackageName(self, theme): return self.avlThemesSearchstr + "-" + theme # Get current Plymouth resolution def getCurrentResolution(self): lines = [] res = self.grub.getCurrentResolution() # The Wheezy way of configuring if res is None: with open(self.modulesPath, 'r') as f: lines = f.readlines() for line in lines: matchObj = re.search('^uvesafb\s+mode_option\s*=\s*([0-9x]+)', line) if matchObj: res = matchObj.group(1) self.log.write("Current Plymouth resolution: %(res)s" % { "res": res }, 'plymouth.getCurrentResolution', 'debug') break # Old way of configuring Plymouth if res is None: if self.boot is not None: with open(self.boot, 'r') as f: lines = f.readlines() for line in lines: # Search text for resolution matchObj = re.search('^GRUB_GFXPAYLOAD_LINUX=(.*)', line) if matchObj: res = matchObj.group(1) self.log.write("Current Plymouth resolution: %(res)s" % { "res": res }, 'plymouth.getCurrentResolution', 'debug') break else: self.log.write(_("Neither grub nor burg found in /etc/default"), 'plymouth.getCurrentResolution', 'error') return res
class PlymouthSave(threading.Thread): def __init__(self, loggerObject, theme=None, resolution=None): threading.Thread.__init__(self) self.log = loggerObject self.grub = Grub(self.log) self.boot = self.grub.getConfig() self.theme = None self.resolution = None self.modulesPath = '/etc/initramfs-tools/modules' self.setThemePath = '/usr/sbin/plymouth-set-default-theme' self.plymouth = Plymouth(self.log) self.installedThemes = self.plymouth.getInstalledThemes() if theme in self.installedThemes and resolution is not None: self.log.write("Set theme: {0} ({1})".format(theme, resolution), 'PlymouthSave.init', 'debug') self.theme = theme self.resolution = resolution # Save given theme and resolution def run(self): try: if not os.path.exists(self.modulesPath): utils.shell_exec("touch {}".format(self.modulesPath)) # Cleanup first utils.shell_exec("sed -i -e 's/^ *//; s/ *$//' %s" % self.modulesPath) # Trim all lines utils.shell_exec("sed -i -e '/^.*KMS$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^intel_agp$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^drm$/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^nouveau modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^radeon modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^i915 modeset.*/d' %s" % self.modulesPath) utils.shell_exec("sed -i -e '/^uvesafb\s*mode_option.*/d' %s" % self.modulesPath) if os.path.exists(self.boot): utils.shell_exec("sed -i -e '/^GRUB_GFXPAYLOAD_LINUX.*/d' %s" % self.boot) splashFile = '/etc/initramfs-tools/conf.d/splash' if os.path.exists(splashFile): os.remove(splashFile) # Set/Unset splash cmd = "sed -i -e 's/\s*[a-z]*splash//' {}".format(self.boot) utils.shell_exec(cmd) if self.theme is None: self.log.write("Set nosplash", 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ nosplash\"/' {}".format(self.boot) utils.shell_exec(cmd) # Comment the GRUB_GFXMODE line if needed cmd = "sed -i '/GRUB_GFXMODE=/s/^/#/' %s" % self.boot utils.shell_exec(cmd) else: self.log.write("Set splash", 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ splash\"/' {}".format(self.boot) utils.shell_exec(cmd) # Set resolution if self.resolution is not None: self.log.write("GRUB_GFXMODE={}".format(self.resolution), 'PlymouthSave.run', 'debug') cmd = "sed -i -e '/GRUB_GFXMODE=/ c GRUB_GFXMODE={0}' {1}".format(self.resolution, self.boot) utils.shell_exec(cmd) # Only for plymouth version older than 9 if self.theme is not None and self.resolution is not None: plymouthVersion = utils.strToNumber(utils.getPackageVersion("plymouth").replace('.', '')[0:2], True) self.log.write("plymouthVersion={}".format(plymouthVersion), 'PlymouthSave.run', 'debug') if plymouthVersion < 9: # Write uvesafb command to modules file self.log.write("> Use uvesafb to configure Plymouth", 'PlymouthSave.run', 'debug') line = "\nuvesafb mode_option=%s-24 mtrr=3 scroll=ywrap\ndrm\n" % self.resolution with open(self.modulesPath, 'a') as f: f.write(line) # Use framebuffer line = "FRAMEBUFFER=y" with open('/etc/initramfs-tools/conf.d/splash', 'w') as f: f.write(line) # Read grub for debugging purposes with open(self.boot, 'r') as f: content = f.read() self.log.write("\nNew grub:\n{}\n".format(content), 'PlymouthSave.run', 'debug') # Update grub if 'grub' in self.boot: utils.shell_exec('update-grub') else: utils.shell_exec('update-burg') # Set the theme and update initramfs if self.theme is not None: utils.shell_exec("{0} -R {1}".format(self.setThemePath, self.theme)) except Exception as detail: self.log.write(detail, 'PlymouthSave.run', 'exception')