Example #1
0
 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'
Example #2
0
 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'
Example #3
0
 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, 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'
Example #5
0
    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, 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
Example #7
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)
Example #8
0
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()
Example #9
0
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
Example #10
0
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')
Example #11
0
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)
Example #12
0
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)
Example #13
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)
Example #14
0
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')