class UpdateManagerPref(object): def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() # Handle arguments parser = argparse.ArgumentParser( description='SolydXK Update Manager Preferences') parser.add_argument('-r', '--reload', action="store_true", help='') args, extra = parser.parse_known_args() print(("args = {}".format(args))) if args.reload: pids = self.umglobal.getProcessPids("updatemanagerpref.py") if len(pids) > 1: print(("updatemanagerpref.py already running - kill pid {}". format(pids[0]))) os.system("kill {}".format(pids[0])) # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) self.log = Logger(self.logFile) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.umglobal.shareDir, 'updatemanagerpref.glade')) # Preferences window objects go = self.builder.get_object self.window = go("windowPref") self.nbPref = go('nbPref') self.btnSaveMirrors = go('btnSaveMirrors') self.btnCheckMirrorsSpeed = go("btnCheckMirrorsSpeed") self.lblMirrors = go('lblMirrors') self.tvMirrors = go("tvMirrors") self.btnRemoveBlackList = go("btnRemoveBlacklist") self.btnAddBlackList = go("btnAddBlacklist") self.tvBlacklist = go("tvBlacklist") self.tvAvailable = go("tvAvailable") self.lblGeneral = go("lblGeneral") self.btnSaveGeneral = go("btnSaveGeneral") self.chkHideMaintenance = go("chkHideMaintenance") self.chkAutostart = go("chkAutostart") # GUI translations self.window.set_title(_("Update Manager Preferences")) self.btnSaveMirrors.set_label(_("Save mirrors")) self.btnCheckMirrorsSpeed.set_label(_("Check mirrors speed")) self.btnRemoveBlackList.set_label(_("Remove")) self.btnAddBlackList.set_label(_("Blacklist")) self.lblMirrors.set_label(_("Repository mirrors")) self.lblGeneral.set_label(_("General")) go("lblHideMaintenance").set_label(_("Hide maintenance")) go("lblBlacklist").set_label(_("Blacklisted packages")) go("lblMirrorsText").set_label(_("Select the fastest repository")) go("lblBlacklistText").set_label(_("Blacklisted packages")) go("lblAvailableText").set_label(_("Available packages")) go("lblGlobalSettings").set_label(_("Global settings")) # Initiate the treeview handler and connect the custom toggle event with on_tvMirrors_toggle self.tvMirrorsHandler = TreeViewHandler(self.tvMirrors) self.tvMirrorsHandler.connect('checkbox-toggled', self.on_tvMirrors_toggle) self.tvBlacklistHandler = TreeViewHandler(self.tvBlacklist) self.tvAvailableHandler = TreeViewHandler(self.tvAvailable) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.queue = Queue() self.excludeMirrors = ['security', 'community'] self.activeMirrors = self.umglobal.getMirrorData( excludeMirrors=self.excludeMirrors) self.deadMirrors = self.umglobal.getMirrorData(getDeadMirrors=True) self.mirrors = self.getMirrors() self.threads = {} self.blacklist = [] self.available = [] self.fillGeneralSettings() self.fillTreeViewMirrors() self.fillTreeViewBlackList() self.fillTreeViewAvailable() # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Main window functions # =============================================== def on_btnSaveGeneral_clicked(self, widget): self.saveGeneralSettings() def on_btnCheckMirrorsSpeed_clicked(self, widget): self.checkMirrorsSpeed() def on_btnSaveMirrors_clicked(self, widget): self.saveMirrors() def on_btnCancel_clicked(self, widget): self.window.destroy() def on_btnRemoveBlacklist_clicked(self, widget): self.removeBlacklist() def on_btnAddBlacklist_clicked(self, widget): self.addBlacklist() # =============================================== # Blacklist functions # =============================================== def fillGeneralSettings(self): for tab in self.umglobal.settings["hide-tabs"]: if tab == "maintenance": self.chkHideMaintenance.set_active(True) self.chkAutostart.set_active(self.umglobal.settings["autostart"]) def fillTreeViewBlackList(self): self.blacklist = [] cmd = "env LANG=C dpkg --get-selections | grep hold$ | awk '{print $1}'" lst = self.ec.run(cmd, False) for pck in lst: self.blacklist.append([False, pck.strip()]) # Fill treeview columnTypesList = ['bool', 'str'] self.tvBlacklistHandler.fillTreeview(self.blacklist, columnTypesList, 0, 400, False) def fillTreeViewAvailable(self): self.available = [] cmd = "env LANG=C dpkg --get-selections | grep install$ | awk '{print $1}'" lst = self.ec.run(cmd, False) for pck in lst: self.available.append([False, pck.strip()]) # Fill treeview columnTypesList = ['bool', 'str'] self.tvAvailableHandler.fillTreeview(self.available, columnTypesList, 0, 400, False) def addBlacklist(self): packages = self.tvAvailableHandler.getToggledValues() for pck in packages: self.log.write("Blacklist package: %s" % pck, "UMPref.addBlacklist", "debug") cmd = "echo '%s hold' | dpkg --set-selections" % pck system(cmd) self.fillTreeViewBlackList() self.fillTreeViewAvailable() def removeBlacklist(self): packages = self.tvBlacklistHandler.getToggledValues() for pck in packages: self.log.write("Remove package from blacklist: %s" % pck, "UMPref.removeBlacklist", "debug") cmd = "echo '%s install' | dpkg --set-selections" % pck system(cmd) self.fillTreeViewBlackList() self.fillTreeViewAvailable() # =============================================== # Mirror functions # =============================================== def fillTreeViewMirrors(self): # Fill mirror list if len(self.mirrors) > 1: # Fill treeview columnTypesList = ['bool', 'str', 'str', 'str', 'str'] self.tvMirrorsHandler.fillTreeview(self.mirrors, columnTypesList, 0, 400, True) # TODO - We have no mirrors: hide the tab until we do #self.nbPref.get_nth_page(1).set_visible(False) else: self.nbPref.get_nth_page(1).set_visible(False) def saveMirrors(self): # Safe mirror settings replaceRepos = [] # Get user selected mirrors model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: repo = model.get_value(itr, 2) url = model.get_value(itr, 3) not_changed = '' # Get currently selected data for mirror in self.mirrors: if mirror[0] and mirror[2] == repo: if mirror[3] != url: # Currently selected mirror replaceRepos.append([mirror[3], url]) else: not_changed = url break if url not in replaceRepos and url not in not_changed: # Append the repositoriy to the sources file replaceRepos.append(['', url]) itr = model.iter_next(itr) if not replaceRepos: # Check for dead mirrors model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: repo = model.get_value(itr, 2) url = model.get_value(itr, 3) # Get currently selected data for mirror in self.deadMirrors: if mirror[1] == repo and mirror[2] != url: # Currently selected mirror replaceRepos.append([mirror[2], url]) break itr = model.iter_next(itr) if replaceRepos: self.btnSaveMirrors.set_sensitive(False) self.btnCheckMirrorsSpeed.set_sensitive(False) m = Mirror() ret = m.save(replaceRepos, self.excludeMirrors) if ret == '': self.ec.run(cmd="apt-get update", outputTreeView=self.tvMirrors) self.umglobal.getLocalInfo() self.mirrors = self.getMirrors() self.fillTreeViewMirrors() else: self.log.write(ret, "UMPref.saveMirrors", "exception") self.btnSaveMirrors.set_sensitive(True) self.btnCheckMirrorsSpeed.set_sensitive(True) else: msg = _("There are no repositories to save.") MessageDialog(self.lblMirrors.get_label(), msg) def getMirrors(self): mirrors = [[ _("Current"), _("Country"), _("Repository"), _("URL"), _("Speed") ]] for mirror in self.activeMirrors: if mirror: self.log.write("Mirror data: %s" % ' '.join(mirror), "UMPref.getMirrors", "debug") blnCurrent = self.isUrlInSources(mirror[2]) mirrors.append( [blnCurrent, mirror[0], mirror[1], mirror[2], '']) return mirrors def isUrlInSources(self, url): url = "://%s" % url blnRet = False for repo in self.umglobal.repos: if url in repo: blnRet = True for excl in self.excludeMirrors: if excl in repo: blnRet = False break break return blnRet def checkMirrorsSpeed(self): name = 'mirrorspeed' self.btnCheckMirrorsSpeed.set_sensitive(False) self.btnSaveMirrors.set_sensitive(False) t = MirrorGetSpeed(self.mirrors, self.queue, self.umglobal) self.threads[name] = t t.daemon = True t.start() self.queue.join() GObject.timeout_add(5, self.checkThread, name) def checkThread(self, name): if self.threads[name].is_alive(): lst = self.queue.get() if lst: self.writeSpeed(lst[0], lst[1]) self.queue.task_done() return True # Thread is done if not self.queue.empty(): lst = self.queue.get() if lst: self.writeSpeed(lst[0], lst[1]) self.queue.task_done() del self.threads[name] self.btnCheckMirrorsSpeed.set_sensitive(True) self.btnSaveMirrors.set_sensitive(True) return False def writeSpeed(self, url, speed): model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: repo = model.get_value(itr, 3) if repo == url: self.log.write("Mirror speed for %s = %s" % (url, speed), "UMPref.writeSpeed", "debug") model.set_value(itr, 4, speed) path = model.get_path(itr) self.tvMirrors.scroll_to_cell(path) itr = model.iter_next(itr) self.tvMirrors.set_model(model) # Repaint GUI, or the update won't show while Gtk.events_pending(): Gtk.main_iteration() def on_tvMirrors_toggle(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvMirrors.get_model() selectedIter = model.get_iter(path) selectedRepo = model.get_value(selectedIter, 2) rowCnt = 0 itr = model.get_iter_first() while itr is not None: if rowCnt != path: repo = model.get_value(itr, 2) if repo == selectedRepo: model[itr][0] = False itr = model.iter_next(itr) rowCnt += 1 # =============================================== # General functions # =============================================== def saveGeneralSettings(self): lst = [] for tab in self.umglobal.settings["hide-tabs"]: if tab != "maintenance": lst.append(tab) if self.chkHideMaintenance.get_active(): lst.append("maintenance") if lst: self.umglobal.saveSettings('misc', 'hide-tabs', ",".join(lst)) else: self.umglobal.saveSettings('misc', 'hide-tabs', "") # Automatically start updatemanager on boot autostart = self.chkAutostart.get_active() self.umglobal.settings["autostart"] = autostart if autostart: if exists(self.umglobal.autostartSourceFile) and \ exists(self.umglobal.autostartDir): copy(self.umglobal.autostartSourceFile, self.umglobal.autostartDir) elif exists(self.umglobal.autostartDestFile): remove(self.umglobal.autostartDestFile) msg = _("The new settings will take effect after UM restart.") MessageDialog(self.lblGeneral.get_label(), msg) # Close the gui def on_windowPref_destroy(self, widget): Gtk.main_quit()
class LightDMManager: def __init__(self): self.scriptDir = os.path.dirname(os.path.realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.scriptDir, '../../share/lightdm-manager/lightdm-manager.glade')) # Main window objects go = self.builder.get_object self.window = go('ldmWindow') self.swUsers = go('swUsers') self.tvUsers = go('tvUsers') self.btnSave = go('btnSave') self.imgBackground = go('imgBackground') self.btnUsers = go('btnUsers') self.btnAppearance = go('btnAppearance') self.chkHideUsers = go('chkHideUsers') self.ebFace = go('ebFace') self.imgFace = go('imgFace') self.nbLightDM = go('nbLightDM') self.cmbThemes = go('cmbThemes') # Read from config file self.cfg = Config('lightdm-manager.conf') self.lightdmConf = self.cfg.getValue('CONFIG', 'lightdmConf') self.desktopbaseDir = self.cfg.getValue('CONFIG', 'desktopbaseDir') gktGreeterConf = self.cfg.getValue('CONFIG', 'gtkGreeterConf') kdeGreeterConf = self.cfg.getValue('CONFIG', 'kdeGreeterConf') if exists(gktGreeterConf): self.greeterConf = gktGreeterConf else: self.greeterConf = kdeGreeterConf # Translations title = _("LightDM Manager") self.window.set_title(title) self.btnUsers.set_label("_{}".format(_("Users"))) self.btnAppearance.set_label("_{}".format(_("Appearance"))) go('lblBackground').set_label(_("Background")) go('lblTheme').set_label(_("Theme")) go('lblLightDmMenu').set_label(_("Menu")) self.chkHideUsers.set_label(_("Hide users")) go('lblUsersFace').set_label(_("User icon")) go('lblUsersAutologin').set_label(_("Auto-login")) # Get current background image self.cfgGreeter = Config(self.greeterConf) try: self.curBgPath = self.cfgGreeter.getValue('greeter', 'background') self.curTheme = self.cfgGreeter.getValue('greeter', 'theme-name') except: self.curBgPath = None self.curTheme = None # Get current auto-login user self.cfgLightdm = Config(self.lightdmConf) try: self.curAutoUser = self.cfgLightdm.getValue( 'SeatDefaults', 'autologin-user').strip() self.curHideUsers = False ghu = self.cfgLightdm.getValue('SeatDefaults', 'greeter-hide-users').strip() if 'true' in ghu: self.curHideUsers = True except: self.curAutoUser = None self.curHideUsers = False # Init self.usr = User() self.newbgImg = self.curBgPath self.newAutoUser = self.curAutoUser self.newTheme = self.curTheme self.themes = [] self.selectedMenuItem = None self.debug = False self.logPath = '' self.prevPath = None self.tempFace = "/tmp/face" self.newFaces = [] self.loggedUser = functions.getUserLoginName() self.curUser = self.loggedUser self.selectImg = join(self.scriptDir, '../../share/lightdm-manager/select.png') # Handle arguments try: opts, args = getopt.getopt(sys.argv[1:], 'dl:', ['debug', 'log=']) except getopt.GetoptError: print(("Arguments cannot be parsed: %s" % str(sys.argv[1:]))) sys.exit(1) for opt, arg in opts: if opt in ('-d', '--debug'): self.debug = True elif opt in ('-l', '--log'): self.logPath = arg # Initialize logging if self.debug: if not self.logPath: self.logPath = 'lightdm-manager.log' self.log = Logger(self.logPath, 'debug', True, None, self.window) # Backup config files because ConfigParser does not preserve commented lines if not exists("%s.org" % self.greeterConf): copy(self.greeterConf, "%s.org" % self.greeterConf) self.log.write( "%(conf1)s copied to %(conf2)s.org" % { "conf1": self.greeterConf, "conf2": self.greeterConf }, 'LightDMManager.main', 'debug') if not exists("%s.org" % self.lightdmConf): copy(self.lightdmConf, "%s.org" % self.lightdmConf) self.log.write( "%(conf1)s copied to %(conf2)s.org" % { "conf1": self.lightdmConf, "conf2": self.lightdmConf }, 'LightDMManager.main', 'debug') # Initiate the treeview handler and connect the custom toggle event with usersCheckBoxToggled self.tvHandler = TreeViewHandler(self.tvUsers, self.log) self.tvHandler.connect('checkbox-toggled', self.usersCheckBoxToggled) # Get users self.users = self.usr.getUsers() self.fillUsers() self.tvHandler.selectValue(self.curUser, 1) self.setBackground(self.curBgPath) self.cmbHandlerThemes = ComboBoxHandler(self.cmbThemes) self.listThemes() self.chkHideUsers.set_active(self.curHideUsers) # Show users menu self.on_btnUsers_clicked(None) self.on_tvUsers_cursor_changed(None) self.version = functions.getPackageVersion('lightdm-manager') # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Menu section functions # =============================================== def on_btnUsers_clicked(self, widget, event=None): if self.selectedMenuItem != menuItems[0]: self.selectedMenuItem = menuItems[0] self.nbLightDM.set_current_page(0) def on_btnAppearance_clicked(self, widget, event=None): if self.selectedMenuItem != menuItems[1]: self.selectedMenuItem = menuItems[1] self.nbLightDM.set_current_page(1) # =============================================== # Functions # =============================================== def on_ebFace_enter_notify_event(self, widget, event): self.window.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) def on_ebFace_leave_notify_event(self, widget, event): self.window.get_window().set_cursor(None) def on_ebFace_button_release_event(self, widget, event): home = self.usr.getUserHomeDir(self.curUser) primaryGroup = self.usr.getUserPrimaryGroupName(self.curUser) imagePath = SelectImageDialog(_('Select user image'), home, self.window).show() if imagePath is not None: tempUserImg = "%(tempFace)s.%(curUser)s" % { "tempFace": self.tempFace, "curUser": self.curUser } self.newFaces.append( [tempUserImg, join(home, ".face"), self.curUser, primaryGroup]) print((">>> self.newFaces = %s" % self.newFaces)) ih = ImageHandler(imagePath) ih.makeFaceImage(tempUserImg) if exists(tempUserImg): self.imgFace.set_from_pixbuf(ih.pixbuf) else: # This should never happen self.imgFace.set_from_file(self.selectImg) def on_tvUsers_cursor_changed(self, widget): self.curUser = self.tvHandler.getSelectedValue(1) showFace = None if self.newFaces: for face in self.newFaces: if face[2] == self.curUser and exists(face[0]): showFace = GdkPixbuf.Pixbuf.new_from_file(face[0]) if showFace is None: showFace = self.usr.getUserFacePixbuf(self.curUser) if showFace is None: # Still no user icon found: show select image self.imgFace.set_from_file(self.selectImg) else: self.imgFace.set_from_pixbuf(showFace) def on_btnSave_clicked(self, widget): saved = False saveHideUsers = False saveAutoUser = False saveFaces = False saveBackground = False saveTheme = False if self.chkHideUsers.get_active() != self.curHideUsers: saveHideUsers = True if self.curAutoUser != self.newAutoUser: saveAutoUser = True if self.newFaces: saveFaces = True if self.curBgPath != self.newbgImg: saveBackground = True self.newTheme = self.cmbHandlerThemes.getValue() if self.curTheme != self.newTheme: saveTheme = True if saveHideUsers or saveAutoUser or saveFaces or saveBackground or saveTheme: qd = QuestionDialog( _("LightDM settings"), _("Settings have changed\n\nDo you want to save the new settings?" ), self.window) answer = qd.show() if answer: if saveAutoUser: if self.newAutoUser is not None: # Save the auto-login user self.cfgLightdm.setValue('SeatDefaults', 'autologin-user', self.newAutoUser) self.cfgLightdm.setValue('SeatDefaults', 'autologin-user-timeout', '0') self.curAutoUser = self.newAutoUser self.log.write( "New auto-login user: %(usr)s" % {"usr": self.curAutoUser}, 'LightDMManager.saveSettings', 'debug') else: self.cfgLightdm.removeOption('SeatDefaults', 'autologin-user') self.cfgLightdm.removeOption('SeatDefaults', 'autologin-user-timeout') self.curAutoUser = None self.log.write("Auto-login disabled", 'LightDMManager.saveSettings', 'debug') if saveHideUsers: hideUsers = str(self.chkHideUsers.get_active()).lower() self.cfgLightdm.setValue('SeatDefaults', 'greeter-hide-users', hideUsers) self.log.write( "Hide users saved: %(users)s" % {"users": hideUsers}, 'LightDMManager.saveSettings', 'debug') if saveFaces: for face in self.newFaces: if exists(face[0]): copy(face[0], face[1]) if exists(face[1]): os.system( "chown %(owner)s:%(group)s %(path)s" % { "owner": face[2], "group": face[3], "path": face[1] }) self.log.write("User icons saved", 'LightDMManager.saveSettings', 'debug') if saveTheme: self.cfgGreeter.setValue('greeter', 'theme-name', self.newTheme) self.curTheme = self.newTheme self.log.write( "Theme saved: %(theme)s" % {"theme": self.curTheme}, 'LightDMManager.saveSettings', 'debug') if saveBackground: if os.path.exists(self.newbgImg): self.cfgGreeter.setValue('greeter', 'background', self.newbgImg) self.curBgPath = self.newbgImg self.log.write( "Background saved: %(background)s" % {"background": self.curBgPath}, 'LightDMManager.saveSettings', 'debug') saved = True else: if os.path.exists(self.curBgPath): self.setBackground(self.curBgPath) self.log.write( "Current background: %(background)s" % {"background": self.curBgPath}, 'LightDMManager.saveSettings', 'debug') else: self.imgBackground.set_from_file( join(self.scriptDir, '../../share/lightdm-manager/select.png')) self.log.write("No background set", 'LightDMManager.saveSettings', 'debug') self.fillUsers() if saved: self.curHideUsers = self.chkHideUsers.get_active() self.curAutoUser = self.newAutoUser self.newFaces = [] self.curBgPath = self.newbgImg self.curTheme = self.newTheme MessageDialogSafe(_("Saved"), _("LightDM settings saved successfully."), Gtk.MessageType.INFO, self.window).show() def on_ebBackground_button_release_event(self, widget, event): self.newbgImg = SelectImageDialog(_("Choose background image"), self.desktopbaseDir, self.window).show() if exists(self.newbgImg) and self.newbgImg != self.curBgPath: self.setBackground(self.newbgImg) self.log.write( _("New background: %(bg)s") % {"bg": self.newbgImg}, 'LightDMManager.chooseFile', 'info') def on_ebBackground_enter_notify_event(self, widget, event): self.window.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) def on_ebBackground_leave_notify_event(self, widget, event): self.window.get_window().set_cursor(None) # This method is fired by the TreeView.checkbox-toggled event def usersCheckBoxToggled(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvUsers.get_model() itr = model.get_iter(path) user = model[itr][1] if self.prevPath != path or toggleValue: # Only one toggle box can be selected (or none) self.tvHandler.treeviewToggleAll([0], False, 1, user) # Save current path self.prevPath = path # Save selected user self.newAutoUser = user self.log.write( _("Auto-login user selected: %(usr)s") % {"usr": user}, 'LightDMManager.usersCheckBoxToggled', 'info') elif self.prevPath == path and not toggleValue: self.newAutoUser = None def listThemes(self): themeDir = '/usr/share/themes' themeDirLocal = '~/.local/share/themes' dirs = functions.locate('gtk-*', themeDir, True) + functions.locate( 'gtk-*', themeDirLocal, True) for path in dirs: dirList = path.split('/') for d in dirList: if 'gtk-' in d: break themeName = d if themeName not in self.themes: self.themes.append(themeName) if self.themes: self.cmbHandlerThemes.fillComboBox(self.themes) if self.curTheme in self.themes: self.cmbHandlerThemes.selectValue(self.curTheme) def fillUsers(self): selUsr = False contentList = [] i = 0 for usr in self.users: if usr == self.curAutoUser: selUsr = True self.prevPath = i else: selUsr = False contentList.append([selUsr, usr]) i += 1 # Fill treeview with users #fillTreeview(contentList, columnTypesList, columnHideList=[-1], setCursor=0, setCursorWeight=400, firstItemIsColName=False, appendToExisting=False, appendToTop=False) columnTypesList = ['bool', 'str'] self.tvHandler.fillTreeview(contentList, columnTypesList) def setBackground(self, path): # Set Background if path is not None: if exists(path): ih = ImageHandler(path) ih.resizeImage(height=200) self.imgBackground.set_from_pixbuf(ih.pixbuf) else: self.imgBackground.set_from_file(self.selectImg) else: self.imgBackground.set_from_file(self.selectImg) # =============================================== # General functions # =============================================== def on_ldmWindow_destroy(self, widget, data=None): # Close the app self.on_btnSave_clicked(None) for tmp in self.newFaces: os.remove(tmp[0]) Gtk.main_quit()
class LightDMManager: def __init__(self): self.scriptDir = os.path.dirname(os.path.realpath(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, '../../share/lightdm-manager/lightdm-manager.glade')) # Main window objects go = self.builder.get_object self.window = go('ldmWindow') self.swUsers = go('swUsers') self.tvUsers = go('tvUsers') self.btnSave = go('btnSave') self.imgBackground = go('imgBackground') self.btnUsers = go('btnUsers') self.btnAppearance = go('btnAppearance') self.chkHideUsers = go('chkHideUsers') self.ebFace = go('ebFace') self.imgFace = go('imgFace') self.nbLightDM = go('nbLightDM') self.cmbThemes = go('cmbThemes') # Read from config file self.cfg = Config('lightdm-manager.conf') self.lightdmConf = self.cfg.getValue('CONFIG', 'lightdmConf') self.desktopbaseDir = self.cfg.getValue('CONFIG', 'desktopbaseDir') gktGreeterConf = self.cfg.getValue('CONFIG', 'gtkGreeterConf') kdeGreeterConf = self.cfg.getValue('CONFIG', 'kdeGreeterConf') if exists(gktGreeterConf): self.greeterConf = gktGreeterConf else: self.greeterConf = kdeGreeterConf # Translations title = _("LightDM Manager") self.window.set_title(title) self.btnUsers.set_label("_{}".format(_("Users"))) self.btnAppearance.set_label("_{}".format(_("Appearance"))) go('lblBackground').set_label(_("Background")) go('lblTheme').set_label(_("Theme")) go('lblLightDmMenu').set_label(_("Menu")) self.chkHideUsers.set_label(_("Hide users")) go('lblUsersFace').set_label(_("User icon")) go('lblUsersAutologin').set_label(_("Auto-login")) # Get current background image self.cfgGreeter = Config(self.greeterConf) try: self.curBgPath = self.cfgGreeter.getValue('greeter', 'background') self.curTheme = self.cfgGreeter.getValue('greeter', 'theme-name') except: self.curBgPath = None self.curTheme = None # Get current auto-login user self.cfgLightdm = Config(self.lightdmConf) try: self.curAutoUser = self.cfgLightdm.getValue('SeatDefaults', 'autologin-user').strip() self.curHideUsers = False ghu = self.cfgLightdm.getValue('SeatDefaults', 'greeter-hide-users').strip() if 'true' in ghu: self.curHideUsers = True except: self.curAutoUser = None self.curHideUsers = False # Init self.usr = User() self.newbgImg = self.curBgPath self.newAutoUser = self.curAutoUser self.newTheme = self.curTheme self.themes = [] self.selectedMenuItem = None self.debug = False self.logPath = '' self.prevPath = None self.tempFace = "/tmp/face" self.newFaces = [] self.loggedUser = functions.getUserLoginName() self.curUser = self.loggedUser self.selectImg = join(self.scriptDir, '../../share/lightdm-manager/select.png') # Handle arguments try: opts, args = getopt.getopt(sys.argv[1:], 'dl:', ['debug', 'log=']) except getopt.GetoptError: print(("Arguments cannot be parsed: %s" % str(sys.argv[1:]))) sys.exit(1) for opt, arg in opts: if opt in ('-d', '--debug'): self.debug = True elif opt in ('-l', '--log'): self.logPath = arg # Initialize logging if self.debug: if not self.logPath: self.logPath = 'lightdm-manager.log' self.log = Logger(self.logPath, 'debug', True, None, self.window) # Backup config files because ConfigParser does not preserve commented lines if not exists("%s.org" % self.greeterConf): copy(self.greeterConf, "%s.org" % self.greeterConf) self.log.write("%(conf1)s copied to %(conf2)s.org" % { "conf1": self.greeterConf, "conf2": self.greeterConf }, 'LightDMManager.main', 'debug') if not exists("%s.org" % self.lightdmConf): copy(self.lightdmConf, "%s.org" % self.lightdmConf) self.log.write("%(conf1)s copied to %(conf2)s.org" % { "conf1": self.lightdmConf, "conf2": self.lightdmConf }, 'LightDMManager.main', 'debug') # Initiate the treeview handler and connect the custom toggle event with usersCheckBoxToggled self.tvHandler = TreeViewHandler(self.tvUsers, self.log) self.tvHandler.connect('checkbox-toggled', self.usersCheckBoxToggled) # Get users self.users = self.usr.getUsers() self.fillUsers() self.tvHandler.selectValue(self.curUser, 1) self.setBackground(self.curBgPath) self.cmbHandlerThemes = ComboBoxHandler(self.cmbThemes) self.listThemes() self.chkHideUsers.set_active(self.curHideUsers) # Show users menu self.on_btnUsers_clicked(None) self.on_tvUsers_cursor_changed(None) self.version = functions.getPackageVersion('lightdm-manager') # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Menu section functions # =============================================== def on_btnUsers_clicked(self, widget, event=None): if self.selectedMenuItem != menuItems[0]: self.selectedMenuItem = menuItems[0] self.nbLightDM.set_current_page(0) def on_btnAppearance_clicked(self, widget, event=None): if self.selectedMenuItem != menuItems[1]: self.selectedMenuItem = menuItems[1] self.nbLightDM.set_current_page(1) # =============================================== # Functions # =============================================== def on_ebFace_enter_notify_event(self, widget, event): self.window.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) def on_ebFace_leave_notify_event(self, widget, event): self.window.get_window().set_cursor(None) def on_ebFace_button_release_event(self, widget, event): home = self.usr.getUserHomeDir(self.curUser) primaryGroup = self.usr.getUserPrimaryGroupName(self.curUser) imagePath = SelectImageDialog(_('Select user image'), home, self.window).show() if imagePath is not None: tempUserImg = "%(tempFace)s.%(curUser)s" % {"tempFace": self.tempFace, "curUser": self.curUser} self.newFaces.append([tempUserImg, join(home, ".face"), self.curUser, primaryGroup]) print((">>> self.newFaces = %s" % self.newFaces)) ih = ImageHandler(imagePath) ih.makeFaceImage(tempUserImg) if exists(tempUserImg): self.imgFace.set_from_pixbuf(ih.pixbuf) else: # This should never happen self.imgFace.set_from_file(self.selectImg) def on_tvUsers_cursor_changed(self, widget): self.curUser = self.tvHandler.getSelectedValue(1) showFace = None if self.newFaces: for face in self.newFaces: if face[2] == self.curUser and exists(face[0]): showFace = GdkPixbuf.Pixbuf.new_from_file(face[0]) if showFace is None: showFace = self.usr.getUserFacePixbuf(self.curUser) if showFace is None: # Still no user icon found: show select image self.imgFace.set_from_file(self.selectImg) else: self.imgFace.set_from_pixbuf(showFace) def on_btnSave_clicked(self, widget): saved = False saveHideUsers = False saveAutoUser = False saveFaces = False saveBackground = False saveTheme = False if self.chkHideUsers.get_active() != self.curHideUsers: saveHideUsers = True if self.curAutoUser != self.newAutoUser: saveAutoUser = True if self.newFaces: saveFaces = True if self.curBgPath != self.newbgImg: saveBackground = True self.newTheme = self.cmbHandlerThemes.getValue() if self.curTheme != self.newTheme: saveTheme = True if saveHideUsers or saveAutoUser or saveFaces or saveBackground or saveTheme: qd = QuestionDialog(_("LightDM settings"), _("Settings have changed\n\nDo you want to save the new settings?"), self.window) answer = qd.show() if answer: if saveAutoUser: if self.newAutoUser is not None: # Save the auto-login user self.cfgLightdm.setValue('SeatDefaults', 'autologin-user', self.newAutoUser) self.cfgLightdm.setValue('SeatDefaults', 'autologin-user-timeout', '0') self.curAutoUser = self.newAutoUser self.log.write("New auto-login user: %(usr)s" % { "usr": self.curAutoUser }, 'LightDMManager.saveSettings', 'debug') else: self.cfgLightdm.removeOption('SeatDefaults', 'autologin-user') self.cfgLightdm.removeOption('SeatDefaults', 'autologin-user-timeout') self.curAutoUser = None self.log.write("Auto-login disabled", 'LightDMManager.saveSettings', 'debug') if saveHideUsers: hideUsers = str(self.chkHideUsers.get_active()).lower() self.cfgLightdm.setValue('SeatDefaults', 'greeter-hide-users', hideUsers) self.log.write("Hide users saved: %(users)s" % {"users": hideUsers}, 'LightDMManager.saveSettings', 'debug') if saveFaces: for face in self.newFaces: if exists(face[0]): copy(face[0], face[1]) if exists(face[1]): os.system("chown %(owner)s:%(group)s %(path)s" % {"owner": face[2], "group": face[3], "path": face[1]}) self.log.write("User icons saved", 'LightDMManager.saveSettings', 'debug') if saveTheme: self.cfgGreeter.setValue('greeter', 'theme-name', self.newTheme) self.curTheme = self.newTheme self.log.write("Theme saved: %(theme)s" % { "theme": self.curTheme }, 'LightDMManager.saveSettings', 'debug') if saveBackground: if os.path.exists(self.newbgImg): self.cfgGreeter.setValue('greeter', 'background', self.newbgImg) self.curBgPath = self.newbgImg self.log.write("Background saved: %(background)s" % { "background": self.curBgPath }, 'LightDMManager.saveSettings', 'debug') saved = True else: if os.path.exists(self.curBgPath): self.setBackground(self.curBgPath) self.log.write("Current background: %(background)s" % { "background": self.curBgPath }, 'LightDMManager.saveSettings', 'debug') else: self.imgBackground.set_from_file(join(self.scriptDir, '../../share/lightdm-manager/select.png')) self.log.write("No background set", 'LightDMManager.saveSettings', 'debug') self.fillUsers() if saved: self.curHideUsers = self.chkHideUsers.get_active() self.curAutoUser = self.newAutoUser self.newFaces = [] self.curBgPath = self.newbgImg self.curTheme = self.newTheme MessageDialogSafe(_("Saved"), _("LightDM settings saved successfully."), Gtk.MessageType.INFO, self.window).show() def on_ebBackground_button_release_event(self, widget, event): self.newbgImg = SelectImageDialog(_("Choose background image"), self.desktopbaseDir, self.window).show() if exists(self.newbgImg) and self.newbgImg != self.curBgPath: self.setBackground(self.newbgImg) self.log.write(_("New background: %(bg)s") % { "bg": self.newbgImg }, 'LightDMManager.chooseFile', 'info') def on_ebBackground_enter_notify_event(self, widget, event): self.window.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) def on_ebBackground_leave_notify_event(self, widget, event): self.window.get_window().set_cursor(None) # This method is fired by the TreeView.checkbox-toggled event def usersCheckBoxToggled(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvUsers.get_model() itr = model.get_iter(path) user = model[itr][1] if self.prevPath != path or toggleValue: # Only one toggle box can be selected (or none) self.tvHandler.treeviewToggleAll([0], False, 1, user) # Save current path self.prevPath = path # Save selected user self.newAutoUser = user self.log.write(_("Auto-login user selected: %(usr)s") % { "usr": user }, 'LightDMManager.usersCheckBoxToggled', 'info') elif self.prevPath == path and not toggleValue: self.newAutoUser = None def listThemes(self): themeDir = '/usr/share/themes' themeDirLocal = '~/.local/share/themes' dirs = functions.locate('gtk-*', themeDir, True) + functions.locate('gtk-*', themeDirLocal, True) for path in dirs: dirList = path.split('/') for d in dirList: if 'gtk-' in d: break themeName = d if themeName not in self.themes: self.themes.append(themeName) if self.themes: self.cmbHandlerThemes.fillComboBox(self.themes) if self.curTheme in self.themes: self.cmbHandlerThemes.selectValue(self.curTheme) def fillUsers(self): selUsr = False contentList = [] i = 0 for usr in self.users: if usr == self.curAutoUser: selUsr = True self.prevPath = i else: selUsr = False contentList.append([selUsr, usr]) i += 1 # Fill treeview with users #fillTreeview(contentList, columnTypesList, columnHideList=[-1], setCursor=0, setCursorWeight=400, firstItemIsColName=False, appendToExisting=False, appendToTop=False) columnTypesList = ['bool', 'str'] self.tvHandler.fillTreeview(contentList, columnTypesList) def setBackground(self, path): # Set Background if path is not None: if exists(path): ih = ImageHandler(path) ih.resizeImage(height=200) self.imgBackground.set_from_pixbuf(ih.pixbuf) else: self.imgBackground.set_from_file(self.selectImg) else: self.imgBackground.set_from_file(self.selectImg) # =============================================== # General functions # =============================================== def on_ldmWindow_destroy(self, widget, data=None): # Close the app self.on_btnSave_clicked(None) for tmp in self.newFaces: os.remove(tmp[0]) Gtk.main_quit()
class UpdateManagerPref(object): def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() # Handle arguments parser = argparse.ArgumentParser(description='SolydXK Update Manager Preferences') parser.add_argument('-r','--reload', action="store_true", help='') args, extra = parser.parse_known_args() print(("args = {}".format(args))) if args.reload: pids = self.umglobal.getProcessPids("updatemanagerpref.py") if len(pids) > 1: print(("updatemanagerpref.py already running - kill pid {}".format(pids[0]))) os.system("kill {}".format(pids[0])) # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) self.log = Logger(self.logFile) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.umglobal.shareDir, 'updatemanagerpref.glade')) # Preferences window objects go = self.builder.get_object self.window = go("windowPref") self.nbPref = go('nbPref') self.btnSaveMirrors = go('btnSaveMirrors') self.btnCheckMirrorsSpeed = go("btnCheckMirrorsSpeed") self.lblMirrors = go('lblMirrors') self.tvMirrors = go("tvMirrors") self.btnRemoveBlackList = go("btnRemoveBlacklist") self.btnAddBlackList = go("btnAddBlacklist") self.tvBlacklist = go("tvBlacklist") self.tvAvailable = go("tvAvailable") self.lblGeneral = go("lblGeneral") self.btnSaveGeneral = go("btnSaveGeneral") self.chkHideMaintenance = go("chkHideMaintenance") self.chkAutostart = go("chkAutostart") # GUI translations self.window.set_title(_("Update Manager Preferences")) self.btnSaveMirrors.set_label(_("Save mirrors")) self.btnCheckMirrorsSpeed.set_label(_("Check mirrors speed")) self.btnRemoveBlackList.set_label(_("Remove")) self.btnAddBlackList.set_label(_("Blacklist")) self.lblMirrors.set_label(_("Repository mirrors")) self.lblGeneral.set_label(_("General")) go("lblHideMaintenance").set_label(_("Hide maintenance")) go("lblBlacklist").set_label(_("Blacklisted packages")) go("lblMirrorsText").set_label(_("Select the fastest repository")) go("lblBlacklistText").set_label(_("Blacklisted packages")) go("lblAvailableText").set_label(_("Available packages")) go("lblGlobalSettings").set_label(_("Global settings")) # Initiate the treeview handler and connect the custom toggle event with on_tvMirrors_toggle self.tvMirrorsHandler = TreeViewHandler(self.tvMirrors) self.tvMirrorsHandler.connect('checkbox-toggled', self.on_tvMirrors_toggle) self.tvBlacklistHandler = TreeViewHandler(self.tvBlacklist) self.tvAvailableHandler = TreeViewHandler(self.tvAvailable) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.queue = Queue() self.excludeMirrors = ['security', 'community'] self.activeMirrors = self.umglobal.getMirrorData(excludeMirrors=self.excludeMirrors) self.deadMirrors = self.umglobal.getMirrorData(getDeadMirrors=True) self.mirrors = self.getMirrors() self.threads = {} self.blacklist = [] self.available = [] self.fillGeneralSettings() self.fillTreeViewMirrors() self.fillTreeViewBlackList() self.fillTreeViewAvailable() # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Main window functions # =============================================== def on_btnSaveGeneral_clicked(self, widget): self.saveGeneralSettings() def on_btnCheckMirrorsSpeed_clicked(self, widget): self.checkMirrorsSpeed() def on_btnSaveMirrors_clicked(self, widget): self.saveMirrors() def on_btnCancel_clicked(self, widget): self.window.destroy() def on_btnRemoveBlacklist_clicked(self, widget): self.removeBlacklist() def on_btnAddBlacklist_clicked(self, widget): self.addBlacklist() # =============================================== # Blacklist functions # =============================================== def fillGeneralSettings(self): for tab in self.umglobal.settings["hide-tabs"]: if tab == "maintenance": self.chkHideMaintenance.set_active(True) self.chkAutostart.set_active(self.umglobal.settings["autostart"]) def fillTreeViewBlackList(self): self.blacklist = [] cmd = "env LANG=C dpkg --get-selections | grep hold$ | awk '{print $1}'" lst = self.ec.run(cmd, False) for pck in lst: self.blacklist.append([False, pck.strip()]) # Fill treeview columnTypesList = ['bool', 'str'] self.tvBlacklistHandler.fillTreeview(self.blacklist, columnTypesList, 0, 400, False) def fillTreeViewAvailable(self): self.available = [] cmd = "env LANG=C dpkg --get-selections | grep install$ | awk '{print $1}'" lst = self.ec.run(cmd, False) for pck in lst: self.available.append([False, pck.strip()]) # Fill treeview columnTypesList = ['bool', 'str'] self.tvAvailableHandler.fillTreeview(self.available, columnTypesList, 0, 400, False) def addBlacklist(self): packages = self.tvAvailableHandler.getToggledValues() for pck in packages: self.log.write("Blacklist package: %s" % pck, "UMPref.addBlacklist", "debug") cmd = "echo '%s hold' | dpkg --set-selections" % pck system(cmd) self.fillTreeViewBlackList() self.fillTreeViewAvailable() def removeBlacklist(self): packages = self.tvBlacklistHandler.getToggledValues() for pck in packages: self.log.write("Remove package from blacklist: %s" % pck, "UMPref.removeBlacklist", "debug") cmd = "echo '%s install' | dpkg --set-selections" % pck system(cmd) self.fillTreeViewBlackList() self.fillTreeViewAvailable() # =============================================== # Mirror functions # =============================================== def fillTreeViewMirrors(self): # Fill mirror list if len(self.mirrors) > 1: # Fill treeview columnTypesList = ['bool', 'str', 'str', 'str', 'str'] self.tvMirrorsHandler.fillTreeview(self.mirrors, columnTypesList, 0, 400, True) # TODO - We have no mirrors: hide the tab until we do #self.nbPref.get_nth_page(1).set_visible(False) else: self.nbPref.get_nth_page(1).set_visible(False) def saveMirrors(self): # Safe mirror settings replaceRepos = [] # Get user selected mirrors model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: repo = model.get_value(itr, 2) url = model.get_value(itr, 3) not_changed = '' # Get currently selected data for mirror in self.mirrors: if mirror[0] and mirror[2] == repo: if mirror[3] != url: # Currently selected mirror replaceRepos.append([mirror[3], url]) else: not_changed = url break if url not in replaceRepos and url not in not_changed: # Append the repositoriy to the sources file replaceRepos.append(['', url]) itr = model.iter_next(itr) if not replaceRepos: # Check for dead mirrors model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: repo = model.get_value(itr, 2) url = model.get_value(itr, 3) # Get currently selected data for mirror in self.deadMirrors: if mirror[1] == repo and mirror[2] != url: # Currently selected mirror replaceRepos.append([mirror[2], url]) break itr = model.iter_next(itr) if replaceRepos: self.btnSaveMirrors.set_sensitive(False) self.btnCheckMirrorsSpeed.set_sensitive(False) m = Mirror() ret = m.save(replaceRepos, self.excludeMirrors) if ret == '': self.ec.run(cmd="apt-get update", outputTreeView=self.tvMirrors) self.umglobal.getLocalInfo() self.mirrors = self.getMirrors() self.fillTreeViewMirrors() else: self.log.write(ret, "UMPref.saveMirrors", "exception") self.btnSaveMirrors.set_sensitive(True) self.btnCheckMirrorsSpeed.set_sensitive(True) else: msg = _("There are no repositories to save.") MessageDialog(self.lblMirrors.get_label(), msg) def getMirrors(self): mirrors = [[_("Current"), _("Country"), _("Repository"), _("URL"), _("Speed")]] for mirror in self.activeMirrors: if mirror: self.log.write("Mirror data: %s" % ' '.join(mirror), "UMPref.getMirrors", "debug") blnCurrent = self.isUrlInSources(mirror[2]) mirrors.append([blnCurrent, mirror[0], mirror[1], mirror[2], '']) return mirrors def isUrlInSources(self, url): url = "://%s" % url blnRet = False for repo in self.umglobal.repos: if url in repo: blnRet = True for excl in self.excludeMirrors: if excl in repo: blnRet = False break break return blnRet def checkMirrorsSpeed(self): name = 'mirrorspeed' self.btnCheckMirrorsSpeed.set_sensitive(False) self.btnSaveMirrors.set_sensitive(False) t = MirrorGetSpeed(self.mirrors, self.queue, self.umglobal) self.threads[name] = t t.daemon = True t.start() self.queue.join() GObject.timeout_add(5, self.checkThread, name) def checkThread(self, name): if self.threads[name].is_alive(): lst = self.queue.get() if lst: self.writeSpeed(lst[0], lst[1]) self.queue.task_done() return True # Thread is done if not self.queue.empty(): lst = self.queue.get() if lst: self.writeSpeed(lst[0], lst[1]) self.queue.task_done() del self.threads[name] self.btnCheckMirrorsSpeed.set_sensitive(True) self.btnSaveMirrors.set_sensitive(True) return False def writeSpeed(self, url, speed): model = self.tvMirrors.get_model() itr = model.get_iter_first() while itr is not None: repo = model.get_value(itr, 3) if repo == url: self.log.write("Mirror speed for %s = %s" % (url, speed), "UMPref.writeSpeed", "debug") model.set_value(itr, 4, speed) path = model.get_path(itr) self.tvMirrors.scroll_to_cell(path) itr = model.iter_next(itr) self.tvMirrors.set_model(model) # Repaint GUI, or the update won't show while Gtk.events_pending(): Gtk.main_iteration() def on_tvMirrors_toggle(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvMirrors.get_model() selectedIter = model.get_iter(path) selectedRepo = model.get_value(selectedIter, 2) rowCnt = 0 itr = model.get_iter_first() while itr is not None: if rowCnt != path: repo = model.get_value(itr, 2) if repo == selectedRepo: model[itr][0] = False itr = model.iter_next(itr) rowCnt += 1 # =============================================== # General functions # =============================================== def saveGeneralSettings(self): lst = [] for tab in self.umglobal.settings["hide-tabs"]: if tab != "maintenance": lst.append(tab) if self.chkHideMaintenance.get_active(): lst.append("maintenance") if lst: self.umglobal.saveSettings('misc', 'hide-tabs', ",".join(lst)) else: self.umglobal.saveSettings('misc', 'hide-tabs', "") # Automatically start updatemanager on boot autostart = self.chkAutostart.get_active() self.umglobal.settings["autostart"] = autostart if autostart: if exists(self.umglobal.autostartSourceFile) and \ exists(self.umglobal.autostartDir): copy(self.umglobal.autostartSourceFile, self.umglobal.autostartDir) elif exists(self.umglobal.autostartDestFile): remove(self.umglobal.autostartDestFile) msg = _("The new settings will take effect after UM restart.") MessageDialog(self.lblGeneral.get_label(), msg) # Close the gui def on_windowPref_destroy(self, widget): Gtk.main_quit()
class DDM(object): def __init__(self, test=False): # Testing self.test = test # Set to true for testing Optimus self.test_optimus = False # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/ddm') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'ddm.glade')) # Main window objects go = self.builder.get_object self.window = go("ddmWindow") self.tvDDM = go("tvDDM") self.btnSave = go("btnSave") self.btnHelp = go("btnHelp") self.btnQuit = go("btnQuit") self.pbDDM = go("pbDDM") self.chkBackports = go("chkBackports") self.window.set_title(_("Device Driver Manager")) self.btnSave.set_label(_("Install")) self.btnHelp.set_label(_("Help")) self.btnQuit.set_label(_("Quit")) self.chkBackports.set_label(_("Use Backports")) # Initiate variables self.queue = Queue(-1) self.threads = {} self.hardware = [] self.loadedDrivers = [] self.notSupported = [] self.paeBooted = False self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput("cat /usr/bin/ddm | grep 'LOG=' | cut -d'=' -f 2") self.logFile = log[0] self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=5120) self.tvDDMHandler = TreeViewHandler(self.tvDDM) self.tvDDMHandler.connect('checkbox-toggled', self.tv_checkbox_toggled) # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Fill treeview self.fill_treeview_ddm() # Check backports if len(self.hardware) < 2 or not has_backports(): self.chkBackports.hide() self.get_loaded_graphical_driver() self.get_loaded_wireless_driver() # =============================================== # Language specific functions # =============================================== def get_language_dir(self): # First test if full locale directory exists, e.g. html/pt_BR, # otherwise perhaps at least the language is there, e.g. html/pt # and if that doesn't work, try html/pt_PT lang = self.get_current_language() path = join(self.htmlDir, lang) if not isdir(path): base_lang = lang.split('_')[0].lower() path = join(self.htmlDir, base_lang) if not isdir(path): path = join(self.htmlDir, "{}_{}".format(base_lang, base_lang.upper())) if not isdir(path): path = join(self.htmlDir, 'en') return path def get_current_language(self): lang = os.environ.get('LANG', 'US').split('.')[0] if lang == '': lang = 'en' return lang # =============================================== # Main window functions # =============================================== def on_btnSave_clicked(self, widget): # Save selected hardware arguments = [] model = self.tvDDM.get_model() itr = model.get_iter_first() while itr is not None: action = 'no change' selected = model.get_value(itr, 0) device = model.get_value(itr, 2) manufacturerId = '' # Check currently selected state with initial state # This decides whether we should install or purge the drivers for hw in self.hardware: self.log.write("Device = {} in {}".format(device, hw[2]), 'on_btnSave_clicked') if device in hw[2]: manufacturerId = hw[4] if hw[0] and not selected: action = 'purge' elif not hw[0] and selected: action = 'install' break self.log.write("{}: {} ({})".format(action, device, manufacturerId), 'on_btnSave_clicked') # Install/purge selected driver option = "" if action == 'install': option = "-i" elif action == 'purge': option = "-p" if option: driver = '' # Run the manufacturer specific bash script if manufacturerId == '1002': driver = 'ati' elif manufacturerId == '10de': driver = 'nvidia ' elif manufacturerId == '14e4': driver = 'broadcom ' elif 'pae' in manufacturerId: driver = 'pae ' if driver: arguments.append("{} {}".format(option, driver)) # Get the next in line itr = model.iter_next(itr) # Execute the command if arguments: if '-i' in arguments and not hasInternetConnection(): title = _("No internet connection") msg = _("You need an internet connection to install the additional software.\n" "Please, connect to the internet and try again.") WarningDialog(title, msg) else: # Warn for use of Backports if self.chkBackports.get_active(): answer = QuestionDialog(self.chkBackports.get_label(), _("You have selected to install drivers from the backports repository whenever they are available.\n\n" "Although you can run more up to date software using the backports repository,\n" "you introduce a greater risk of breakage doing so.\n\n" "Are you sure you want to continue?")) if not answer: self.chkBackports.set_active(False) return True arguments.append("-b") # Testing if self.test: arguments.append("-t") command = "ddm {}".format(" ".join(arguments)) self.log.write("Command to execute: {}".format(command), 'on_btnSave_clicked') self.exec_command(command) def on_btnQuit_clicked(self, widget): self.on_ddmWindow_destroy(widget) def on_btnHelp_clicked(self, widget): # Open the help file as the real user (not root) shell_exec("%s/open-as-user \"%s\"" % (self.scriptDir, self.helpFile)) def get_supported_hardware(self): # Fill self.hardware self.hardware = [] # First row are column names self.hardware.append([_("Install"), '', _("Device"), 'driver', 'manid', 'deviceid']) # Get hardware information self.get_ati() self.get_nvidia() self.get_broadcom() self.get_pae() # This method is fired by the TreeView.checkbox-toggled event def tv_checkbox_toggled(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvDDM.get_model() itr = model.get_iter(path) description = model[itr][2].lower() if 'pae' in description and not toggleValue and self.paeBooted: title = _("Remove kernel") msg = _("You cannot remove a booted kernel.\nPlease, boot another kernel and try again.") self.log.write(msg, 'tv_checkbox_toggled') WarningDialog(title, msg) model[itr][0] = True def fill_treeview_ddm(self): # Fill a list with supported hardware self.get_supported_hardware() # columns: checkbox, image (logo), device, driver columnTypes = ['bool', 'GdkPixbuf.Pixbuf', 'str'] # Keep some info from the user showHw = [] for hw in self.hardware: showHw.append([hw[0], hw[1], hw[2]]) # Fill treeview self.tvDDMHandler.fillTreeview(contentList=showHw, columnTypesList=columnTypes, firstItemIsColName=True, fontSize=12000) # Show message if nothing is found or hardware is not supported title = _("Hardware scan") if self.notSupported: if len(self.hardware) < 2: self.set_buttons_state(False) msg = _("There are no available drivers for your hardware:") msg = "{}\n\n{}".format(msg, '\n'.join(self.notSupported)) self.log.write(msg, 'fill_treeview_ddm') WarningDialog(title, msg) elif len(self.hardware) < 2: self.set_buttons_state(False) msg = _("DDM did not find any supported hardware.") self.log.write(msg, 'fill_treeview_ddm') MessageDialog(title, msg) def exec_command(self, command): try: # Run the command in a separate thread self.set_buttons_state(False) name = 'cmd' t = ExecuteThreadedCommands([command], self.queue) self.threads[name] = t t.daemon = True t.start() self.queue.join() GObject.timeout_add(250, self.check_thread, name) except Exception as detail: ErrorDialog(self.btnSave.get_label(), detail) def set_buttons_state(self, enable): if not enable: # Disable buttons self.btnSave.set_sensitive(False) else: # Enable buttons and reset progress bar self.btnSave.set_sensitive(True) self.pbDDM.set_fraction(0) def check_thread(self, name): if self.threads[name].is_alive(): self.pbDDM.pulse() if not self.queue.empty(): ret = self.queue.get() self.log.write("Queue returns: {}".format(ret), 'check_thread') self.queue.task_done() self.show_message(ret) return True # Thread is done self.log.write(">> Thread is done", 'check_thread') if not self.queue.empty(): ret = self.queue.get() self.queue.task_done() self.show_message(ret) del self.threads[name] self.set_buttons_state(True) return False # Close the gui def on_ddmWindow_destroy(self, widget): # Close the app Gtk.main_quit() # =============================================== # Hardware functions # =============================================== def get_ati(self): # Debian Wiki: https://wiki.debian.org/ATIProprietary # Supported devices 14.9 (Jessie): http://support.amd.com/en-us/kb-articles/Pages/AMDCatalyst14-9LINReleaseNotes.aspx manufacturerId = '1002' startSeries = 5000 deviceArray = self.get_lspci_info(manufacturerId, 'VGA') if self.test: #deviceArray = [['Advanced Micro Devices [AMD] nee ATI Manhattan [Mobility Radeon HD 5400 Series]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices, Inc. [AMD/ATI] RV710 [Radeon HD 4350/4550]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices [AMD/ATI] RS880 [Radeon HD 4290]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices, Inc. [AMD/ATI] Tonga PRO [Radeon R9 285]', manufacturerId, '6939']] deviceArray = [['Advanced Micro Devices, Inc. [AMD/ATI] Bonaire [FirePro W5100]', manufacturerId, '6649']] if deviceArray: self.log.write("Device(s): {}".format(deviceArray), 'get_ati') # Check if fglrx is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_graphical_driver() self.log.write("Loaded graphical driver: {}".format(loadedDrv), 'get_ati') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/ati.png') # Fill the hardware array for device in deviceArray: self.log.write("ATI device found: {}".format(device[0]), 'get_ati') # Check for supported cards matchObj = re.search('radeon\s+[0-9a-z ]+|fire[a-z]+\s+[0-9a-z -]+', device[0], flags=re.IGNORECASE) if matchObj: if " hd " in matchObj.group(0).lower(): # Check if ATI series is above 5000 matchObjSeries = re.search('[0-9]{4}', matchObj.group(0)) if matchObjSeries: series = int(matchObjSeries.group(0)) # Don't show older ATI Radeon HD cards if series < startSeries: break elif 'fire' in matchObj.group(0).lower(): title = _("ATI FirePro/Gl card found") msg = _("Installing the proprietary driver for an ATI FirePro/Gl card may render your system unbootable.\n\n" "Proceed at your own risk.") self.log.write(msg, 'get_ati') WarningDialog(title, msg) self.log.write("ATI series: {}".format(matchObj.group(0)), 'get_ati') # Check if the available driver is already loaded selected = False driver = 'fglrx' if loadedDrv == driver: selected = True # Fill self.hardware #shortDevice = self.shorten_long_string(device[0], 100) self.hardware.append([selected, logo, device[0], driver, device[1], device[2]]) else: self.notSupported.append(device[0]) def get_nvidia(self): manufacturerId = '10de' deviceArray = self.get_lspci_info(manufacturerId, 'VGA') if self.test: deviceArray = [['NVIDIA Corporation GT218 [GeForce G210M]', manufacturerId, '0a74']] if self.test_optimus: deviceArray = [['Intel Corporation Haswell-ULT Integrated Graphics Controller', '8086', '0a16'], \ ['NVIDIA Corporation GK107M [GeForce GT 750M]', manufacturerId, '0fe4']] if deviceArray: optimus = False devices = [] self.log.write("Device(s): {}".format(deviceArray), 'get_nvidia') # Check if nvidia is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_graphical_driver() self.log.write("Loaded graphical driver: {}".format(loadedDrv), 'get_nvidia') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/nvidia.png') # Fill the hardware array for device in deviceArray: if device[1] == '8086': optimus = True else: devices.append(device) for device in devices: self.log.write("Nvidia device found: {}".format(device[0]), 'get_nvidia') optimusString = "" if optimus: optimusString = "(Optimus) " # Check if the available driver is already loaded selected = False if optimus: if loadedDrv == 'nvidia' or loadedDrv == 'intel': bbversion = getPackageVersion("bumblebee-nvidia") self.log.write("bumblebee-nvidia version: {}".format(bbversion), 'get_nvidia') if bbversion != '': selected = True elif loadedDrv == 'nvidia': selected = True driver = "" if optimus: driver = "bumblebee-nvidia" else: if self.test: driver = 'nvidia-driver' else: nvidiaDetect = getoutput("nvidia-detect | grep nvidia- | tr -d ' '") if nvidiaDetect: driver = nvidiaDetect[0] self.log.write("Nvidia driver to use: {}".format(driver), 'get_nvidia') # Fill self.hardware if driver != "": #shortDevice = "{0}{1}".format(optimusString, self.shorten_long_string(device[0], 100)) self.hardware.append([selected, logo, "{0}{1}".format(optimusString, device[0]), driver, device[1], device[2]]) def get_broadcom_ids(self, driver_name): driver_name = driver_name.upper() ids = getoutput("cat /usr/bin/ddm | grep '{}=' | cut -d'=' -f 2".format(driver_name)) if len(ids) > 0: return ids[0].split('|') return [] def get_broadcom(self): ## Hardware list (device ids) ## http://linuxwireless.org/en/users/Drivers/b43 deviceIds = {} deviceIds['b43'] = self.get_broadcom_ids('b43') deviceIds['b43legacy'] = self.get_broadcom_ids('b43legacy') deviceIds['wldebian'] = self.get_broadcom_ids('wldebian') deviceIds['brcmdebian'] = self.get_broadcom_ids('brcmdebian') deviceIds['unknown'] = self.get_broadcom_ids('unknown') self.log.write("Broadcom deviceIds = {}".format(deviceIds)) manufacturerId = '14e4' deviceArray = self.get_lspci_info(manufacturerId) if self.test: deviceArray = [['Broadcom Corporation BCM43142 802.11a/b/g', manufacturerId, '4365']] if deviceArray: self.log.write("Device(s): {}".format(deviceArray), 'get_broadcom') # Check if broadcom is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_wireless_driver() self.log.write("Loaded wireless driver: {}".format(loadedDrv), 'get_broadcom') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/broadcom.png') # Fill the hardware array for device in deviceArray: self.log.write("Broadcom device found: {}".format(device[0]), 'get_broadcom') driver = '' for key, did in list(deviceIds.items()): #print(("{}:{} in {}:{}".format(device[0], device[2], key, did))) if device[2] in did: driver = key break if driver != '': if driver == 'unknown': self.notSupported.append(device[0]) self.log.write("Broadcom device not supported: {}".format(device[0]), 'get_broadcom') else: self.log.write("Broadcom driver to use: {}".format(driver), 'get_broadcom') # Check if the available driver is already loaded selected = False if loadedDrv == driver: selected = True # Fill self.hardware #shortDevice = self.shorten_long_string(device[0], 100) self.hardware.append([selected, logo, device[0], driver, device[1], device[2]]) def get_pae(self): machine = getoutput('uname -m')[0] release = getoutput('uname -r')[0] if self.test: machine = 'i686' release = '3.16.0-4-586' self.log.write("PAE check: machine={} / release={}".format(machine, release), 'get_pae') if machine == 'i686': # Check if PAE is installed and running selected = False if 'pae' in release: self.paeBooted = True selected = True else: if getPackageVersion('linux-image-686-pae') != '': selected = True # Get the logo logo = join(self.mediaDir, 'images/pae.png') # Fill self.hardware paeDescription = _("PAE capable system") self.hardware.append([selected, logo, paeDescription, '', 'pae', '']) def get_lspci_info(self, manufacturerId, filterString=''): deviceArray = [] output = [] # Check for Optimus if manufacturerId == '10de': output = getoutput("lspci -vnn | grep '\[030[02]\]'") if self.test_optimus: output = ['00:02.0 VGA compatible controller [0300]: Intel Corporation Haswell-ULT Integrated Graphics Controller [8086:0a16] (rev 09) (prog-if 00 [VGA controller])', \ '01:00.0 3D controller [0302]: NVIDIA Corporation GK107M [GeForce GT 750M] [10de:0fe4] (rev a1)'] # Optimus will return 2 devices # If there are less than 2 devices, do regular check if len(output) < 2: if filterString != '': filterString = " | grep {}".format(filterString) output = getoutput("lspci -nn -d {}:{}".format(manufacturerId, filterString)) if output: self.log.write("lspci output = {}".format(output), 'get_lspci_info') for line in output: matchObj = re.search(':\W(.*)\W\[(.+):(.+)\]', line) if matchObj: deviceArray.append([matchObj.group(1), matchObj.group(2), matchObj.group(3)]) return deviceArray def shorten_long_string(self, longString, charLen, breakOnWord=True): tmpArr = [] if breakOnWord: stringArr = longString.split(' ') nrChrs = 0 for s in stringArr: nrChrs += len(s) + 1 if nrChrs < charLen: tmpArr.append(s) else: break else: if len(longString) > charLen: tmpArr.append("{}...".format(longString[0:charLen])) else: tmpArr.append(longString) return ' '.join(tmpArr) # Return graphics module used by X.org # TODO: is lsmod an alternative? def get_loaded_graphical_driver(self): # sort on the most recent X.org log module = '' log = '' logDir = '/var/log/' logPath = None logs = glob(os.path.join(logDir, 'Xorg.*.log*')) logs.sort() for logPath in logs: # Search for "depth" in each line and check the used module # Sometimes these logs are saved as binary: open as read-only binary # When opening as ascii, read() will throw error: "UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80" with open(logPath, 'rb') as f: # replace utf-8 binary read errors (with ?) log = f.read().decode(encoding='utf-8', errors='replace') #print((log)) matchObj = re.search('([a-zA-Z]*)\(\d+\):\s+depth.*framebuffer', log, flags=re.IGNORECASE) if matchObj: module = matchObj.group(1).lower() self.log.write("Log module={}".format(module)) break return module # Return used wireless driver def get_loaded_wireless_driver(self): driver = '' logDir = '/var/log/' for logPath in glob(os.path.join(logDir, 'syslog*')): if driver == '' and not 'gz' in logPath: # Open the log file lines = [] with open(logPath, 'rb') as f: log = f.read().decode(encoding='utf-8', errors='replace') lines = list(log.splitlines()) for line in reversed(lines): # First check for Network Manager entry # Search for wlan0 in each line and get the listed driver matchObj = re.search('\(wlan\d\):.*driver:\s*\'([a-zA-Z0-9\-]*)', line, flags=re.IGNORECASE) if matchObj: driver = matchObj.group(1) self.log.write("Network Manager driver={}".format(driver)) break else: # Wicd # Search for ieee in each line and get the listed driver matchObj = re.search('ieee.*implement', line, flags=re.IGNORECASE) if matchObj: driver = matchObj.group(0) self.log.write("Wicd driver={}".format(driver)) break return driver def show_message(self, cmdOutput): try: self.log.write("Command output: {}".format(cmdOutput), 'show_message') ret = int(cmdOutput) if ret > 1 and ret != 255: if ret == 1: ErrorDialog(self.btnSave.get_label(), _("Run as root.")) elif ret == 2: ErrorDialog(self.btnSave.get_label(), _("Wrong arguments passed to ddm.")) elif ret == 3: ErrorDialog(self.btnSave.get_label(), _("There are no driver available.")) elif ret == 4: ErrorDialog(self.btnSave.get_label(), _("The driver cannot be found in repository.")) elif ret == 5: ErrorDialog(self.btnSave.get_label(), _("Download error.\nCheck your internet connection.")) elif ret == 6: ErrorDialog(self.btnSave.get_label(), _("DDM cannot purge the driver.")) elif ret == 7: ErrorDialog(self.btnSave.get_label(), _("This card is not supported.")) else: msg = _("There was an error during the installation.\n" "Please, run 'sudo apt-get -f install' in a terminal.\n" "Visit our forum for support: http://forums.solydxk.com") ErrorDialog(self.btnSave.get_label(), msg) else: msg = _("The software has been successfully installed.") msg_restart = _("You will need to restart your system.") MessageDialog(self.btnSave.get_label(), "{}\n\n{}".format(msg, msg_restart)) except: ErrorDialog(self.btnSave.get_label(), cmdOutput)
class DDM(object): def __init__(self, test=False): # Testing self.test = test # Set to true for testing Optimus self.test_optimus = False # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/ddm') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'ddm.glade')) # Main window objects go = self.builder.get_object self.window = go("ddmWindow") self.tvDDM = go("tvDDM") self.btnSave = go("btnSave") self.btnHelp = go("btnHelp") self.btnQuit = go("btnQuit") self.pbDDM = go("pbDDM") self.chkBackports = go("chkBackports") self.window.set_title(_("Device Driver Manager")) self.btnSave.set_label(_("Install")) self.btnHelp.set_label(_("Help")) self.btnQuit.set_label(_("Quit")) self.chkBackports.set_label(_("Use Backports")) # Initiate variables self.queue = Queue(-1) self.threads = {} self.hardware = [] self.loadedDrivers = [] self.notSupported = [] self.paeBooted = False self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput("cat /usr/bin/ddm | grep 'LOG=' | cut -d'=' -f 2") self.logFile = log[0] self.log = Logger(self.logFile, addLogTime=False, maxSizeKB=5120) self.tvDDMHandler = TreeViewHandler(self.tvDDM) self.tvDDMHandler.connect('checkbox-toggled', self.tv_checkbox_toggled) # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Fill treeview self.fill_treeview_ddm() # Check backports if len(self.hardware) < 2 or not has_backports(): self.chkBackports.hide() self.get_loaded_graphical_driver() self.get_loaded_wireless_driver() # =============================================== # Language specific functions # =============================================== def get_language_dir(self): # First test if full locale directory exists, e.g. html/pt_BR, # otherwise perhaps at least the language is there, e.g. html/pt # and if that doesn't work, try html/pt_PT lang = self.get_current_language() path = join(self.htmlDir, lang) if not isdir(path): base_lang = lang.split('_')[0].lower() path = join(self.htmlDir, base_lang) if not isdir(path): path = join(self.htmlDir, "{}_{}".format(base_lang, base_lang.upper())) if not isdir(path): path = join(self.htmlDir, 'en') return path def get_current_language(self): lang = os.environ.get('LANG', 'US').split('.')[0] if lang == '': lang = 'en' return lang # =============================================== # Main window functions # =============================================== def on_btnSave_clicked(self, widget): # Save selected hardware arguments = [] model = self.tvDDM.get_model() itr = model.get_iter_first() while itr is not None: action = 'no change' selected = model.get_value(itr, 0) device = model.get_value(itr, 2) manufacturerId = '' # Check currently selected state with initial state # This decides whether we should install or purge the drivers for hw in self.hardware: self.log.write("Device = {} in {}".format(device, hw[2]), 'on_btnSave_clicked') if device in hw[2]: manufacturerId = hw[4] if hw[0] and not selected: action = 'purge' elif not hw[0] and selected: action = 'install' break self.log.write( "{}: {} ({})".format(action, device, manufacturerId), 'on_btnSave_clicked') # Install/purge selected driver option = "" if action == 'install': option = "-i" elif action == 'purge': option = "-p" if option: driver = '' # Run the manufacturer specific bash script if manufacturerId == '1002': driver = 'ati' elif manufacturerId == '10de': driver = 'nvidia ' elif manufacturerId == '14e4': driver = 'broadcom ' elif 'pae' in manufacturerId: driver = 'pae ' if driver: arguments.append("{} {}".format(option, driver)) # Get the next in line itr = model.iter_next(itr) # Execute the command if arguments: if '-i' in arguments and not hasInternetConnection(): title = _("No internet connection") msg = _( "You need an internet connection to install the additional software.\n" "Please, connect to the internet and try again.") WarningDialog(title, msg) else: # Warn for use of Backports if self.chkBackports.get_active(): answer = QuestionDialog( self.chkBackports.get_label(), _("You have selected to install drivers from the backports repository whenever they are available.\n\n" "Although you can run more up to date software using the backports repository,\n" "you introduce a greater risk of breakage doing so.\n\n" "Are you sure you want to continue?")) if not answer: self.chkBackports.set_active(False) return True arguments.append("-b") # Testing if self.test: arguments.append("-t") command = "ddm {}".format(" ".join(arguments)) self.log.write("Command to execute: {}".format(command), 'on_btnSave_clicked') self.exec_command(command) def on_btnQuit_clicked(self, widget): self.on_ddmWindow_destroy(widget) def on_btnHelp_clicked(self, widget): # Open the help file as the real user (not root) shell_exec("%s/open-as-user \"%s\"" % (self.scriptDir, self.helpFile)) def get_supported_hardware(self): # Fill self.hardware self.hardware = [] # First row are column names self.hardware.append( [_("Install"), '', _("Device"), 'driver', 'manid', 'deviceid']) # Get hardware information self.get_ati() self.get_nvidia() self.get_broadcom() self.get_pae() # This method is fired by the TreeView.checkbox-toggled event def tv_checkbox_toggled(self, obj, path, colNr, toggleValue): path = int(path) model = self.tvDDM.get_model() itr = model.get_iter(path) description = model[itr][2].lower() if 'pae' in description and not toggleValue and self.paeBooted: title = _("Remove kernel") msg = _( "You cannot remove a booted kernel.\nPlease, boot another kernel and try again." ) self.log.write(msg, 'tv_checkbox_toggled') WarningDialog(title, msg) model[itr][0] = True def fill_treeview_ddm(self): # Fill a list with supported hardware self.get_supported_hardware() # columns: checkbox, image (logo), device, driver columnTypes = ['bool', 'GdkPixbuf.Pixbuf', 'str'] # Keep some info from the user showHw = [] for hw in self.hardware: showHw.append([hw[0], hw[1], hw[2]]) # Fill treeview self.tvDDMHandler.fillTreeview(contentList=showHw, columnTypesList=columnTypes, firstItemIsColName=True, fontSize=12000) # Show message if nothing is found or hardware is not supported title = _("Hardware scan") if self.notSupported: if len(self.hardware) < 2: self.set_buttons_state(False) msg = _("There are no available drivers for your hardware:") msg = "{}\n\n{}".format(msg, '\n'.join(self.notSupported)) self.log.write(msg, 'fill_treeview_ddm') WarningDialog(title, msg) elif len(self.hardware) < 2: self.set_buttons_state(False) msg = _("DDM did not find any supported hardware.") self.log.write(msg, 'fill_treeview_ddm') MessageDialog(title, msg) def exec_command(self, command): try: # Run the command in a separate thread self.set_buttons_state(False) name = 'cmd' t = ExecuteThreadedCommands([command], self.queue) self.threads[name] = t t.daemon = True t.start() self.queue.join() GObject.timeout_add(250, self.check_thread, name) except Exception as detail: ErrorDialog(self.btnSave.get_label(), detail) def set_buttons_state(self, enable): if not enable: # Disable buttons self.btnSave.set_sensitive(False) else: # Enable buttons and reset progress bar self.btnSave.set_sensitive(True) self.pbDDM.set_fraction(0) def check_thread(self, name): if self.threads[name].is_alive(): self.pbDDM.pulse() if not self.queue.empty(): ret = self.queue.get() self.log.write("Queue returns: {}".format(ret), 'check_thread') self.queue.task_done() self.show_message(ret) return True # Thread is done self.log.write(">> Thread is done", 'check_thread') if not self.queue.empty(): ret = self.queue.get() self.queue.task_done() self.show_message(ret) del self.threads[name] self.set_buttons_state(True) return False # Close the gui def on_ddmWindow_destroy(self, widget): # Close the app Gtk.main_quit() # =============================================== # Hardware functions # =============================================== def get_ati(self): # Debian Wiki: https://wiki.debian.org/ATIProprietary # Supported devices 14.9 (Jessie): http://support.amd.com/en-us/kb-articles/Pages/AMDCatalyst14-9LINReleaseNotes.aspx manufacturerId = '1002' startSeries = 5000 deviceArray = self.get_lspci_info(manufacturerId, 'VGA') if self.test: #deviceArray = [['Advanced Micro Devices [AMD] nee ATI Manhattan [Mobility Radeon HD 5400 Series]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices, Inc. [AMD/ATI] RV710 [Radeon HD 4350/4550]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices [AMD/ATI] RS880 [Radeon HD 4290]', manufacturerId, '68e0']] #deviceArray = [['Advanced Micro Devices, Inc. [AMD/ATI] Tonga PRO [Radeon R9 285]', manufacturerId, '6939']] deviceArray = [[ 'Advanced Micro Devices, Inc. [AMD/ATI] Bonaire [FirePro W5100]', manufacturerId, '6649' ]] if deviceArray: self.log.write("Device(s): {}".format(deviceArray), 'get_ati') # Check if fglrx is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_graphical_driver() self.log.write("Loaded graphical driver: {}".format(loadedDrv), 'get_ati') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/ati.png') # Fill the hardware array for device in deviceArray: self.log.write("ATI device found: {}".format(device[0]), 'get_ati') # Check for supported cards matchObj = re.search( 'radeon\s+[0-9a-z ]+|fire[a-z]+\s+[0-9a-z -]+', device[0], flags=re.IGNORECASE) if matchObj: if " hd " in matchObj.group(0).lower(): # Check if ATI series is above 5000 matchObjSeries = re.search('[0-9]{4}', matchObj.group(0)) if matchObjSeries: series = int(matchObjSeries.group(0)) # Don't show older ATI Radeon HD cards if series < startSeries: break elif 'fire' in matchObj.group(0).lower(): title = _("ATI FirePro/Gl card found") msg = _( "Installing the proprietary driver for an ATI FirePro/Gl card may render your system unbootable.\n\n" "Proceed at your own risk.") self.log.write(msg, 'get_ati') WarningDialog(title, msg) self.log.write("ATI series: {}".format(matchObj.group(0)), 'get_ati') # Check if the available driver is already loaded selected = False driver = 'fglrx' if loadedDrv == driver: selected = True # Fill self.hardware #shortDevice = self.shorten_long_string(device[0], 100) self.hardware.append([ selected, logo, device[0], driver, device[1], device[2] ]) else: self.notSupported.append(device[0]) def get_nvidia(self): manufacturerId = '10de' deviceArray = self.get_lspci_info(manufacturerId, 'VGA') if self.test: deviceArray = [[ 'NVIDIA Corporation GT218 [GeForce G210M]', manufacturerId, '0a74' ]] if self.test_optimus: deviceArray = [['Intel Corporation Haswell-ULT Integrated Graphics Controller', '8086', '0a16'], \ ['NVIDIA Corporation GK107M [GeForce GT 750M]', manufacturerId, '0fe4']] if deviceArray: optimus = False devices = [] self.log.write("Device(s): {}".format(deviceArray), 'get_nvidia') # Check if nvidia is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_graphical_driver() self.log.write("Loaded graphical driver: {}".format(loadedDrv), 'get_nvidia') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/nvidia.png') # Fill the hardware array for device in deviceArray: if device[1] == '8086': optimus = True else: devices.append(device) for device in devices: self.log.write("Nvidia device found: {}".format(device[0]), 'get_nvidia') optimusString = "" if optimus: optimusString = "(Optimus) " # Check if the available driver is already loaded selected = False if optimus: if loadedDrv == 'nvidia' or loadedDrv == 'intel': bbversion = getPackageVersion("bumblebee-nvidia") self.log.write( "bumblebee-nvidia version: {}".format(bbversion), 'get_nvidia') if bbversion != '': selected = True elif loadedDrv == 'nvidia': selected = True driver = "" if optimus: driver = "bumblebee-nvidia" else: if self.test: driver = 'nvidia-driver' else: nvidiaDetect = getoutput( "nvidia-detect | grep nvidia- | tr -d ' '") if nvidiaDetect: driver = nvidiaDetect[0] self.log.write("Nvidia driver to use: {}".format(driver), 'get_nvidia') # Fill self.hardware if driver != "": #shortDevice = "{0}{1}".format(optimusString, self.shorten_long_string(device[0], 100)) self.hardware.append([ selected, logo, "{0}{1}".format(optimusString, device[0]), driver, device[1], device[2] ]) def get_broadcom_ids(self, driver_name): driver_name = driver_name.upper() ids = getoutput( "cat /usr/bin/ddm | grep '{}=' | cut -d'=' -f 2".format( driver_name)) if len(ids) > 0: return ids[0].split('|') return [] def get_broadcom(self): ## Hardware list (device ids) ## http://linuxwireless.org/en/users/Drivers/b43 deviceIds = {} deviceIds['b43'] = self.get_broadcom_ids('b43') deviceIds['b43legacy'] = self.get_broadcom_ids('b43legacy') deviceIds['wldebian'] = self.get_broadcom_ids('wldebian') deviceIds['brcmdebian'] = self.get_broadcom_ids('brcmdebian') deviceIds['unknown'] = self.get_broadcom_ids('unknown') self.log.write("Broadcom deviceIds = {}".format(deviceIds)) manufacturerId = '14e4' deviceArray = self.get_lspci_info(manufacturerId) if self.test: deviceArray = [[ 'Broadcom Corporation BCM43142 802.11a/b/g', manufacturerId, '4365' ]] if deviceArray: self.log.write("Device(s): {}".format(deviceArray), 'get_broadcom') # Check if broadcom is loaded # If it is: checkbox is selected loadedDrv = self.get_loaded_wireless_driver() self.log.write("Loaded wireless driver: {}".format(loadedDrv), 'get_broadcom') # Get the manufacturer's logo logo = join(self.mediaDir, 'images/broadcom.png') # Fill the hardware array for device in deviceArray: self.log.write("Broadcom device found: {}".format(device[0]), 'get_broadcom') driver = '' for key, did in list(deviceIds.items()): #print(("{}:{} in {}:{}".format(device[0], device[2], key, did))) if device[2] in did: driver = key break if driver != '': if driver == 'unknown': self.notSupported.append(device[0]) self.log.write( "Broadcom device not supported: {}".format( device[0]), 'get_broadcom') else: self.log.write( "Broadcom driver to use: {}".format(driver), 'get_broadcom') # Check if the available driver is already loaded selected = False if loadedDrv == driver: selected = True # Fill self.hardware #shortDevice = self.shorten_long_string(device[0], 100) self.hardware.append([ selected, logo, device[0], driver, device[1], device[2] ]) def get_pae(self): machine = getoutput('uname -m')[0] release = getoutput('uname -r')[0] if self.test: machine = 'i686' release = '3.16.0-4-586' self.log.write( "PAE check: machine={} / release={}".format(machine, release), 'get_pae') if machine == 'i686': # Check if PAE is installed and running selected = False if 'pae' in release: self.paeBooted = True selected = True else: if getPackageVersion('linux-image-686-pae') != '': selected = True # Get the logo logo = join(self.mediaDir, 'images/pae.png') # Fill self.hardware paeDescription = _("PAE capable system") self.hardware.append( [selected, logo, paeDescription, '', 'pae', '']) def get_lspci_info(self, manufacturerId, filterString=''): deviceArray = [] output = [] # Check for Optimus if manufacturerId == '10de': output = getoutput("lspci -vnn | grep '\[030[02]\]'") if self.test_optimus: output = ['00:02.0 VGA compatible controller [0300]: Intel Corporation Haswell-ULT Integrated Graphics Controller [8086:0a16] (rev 09) (prog-if 00 [VGA controller])', \ '01:00.0 3D controller [0302]: NVIDIA Corporation GK107M [GeForce GT 750M] [10de:0fe4] (rev a1)'] # Optimus will return 2 devices # If there are less than 2 devices, do regular check if len(output) < 2: if filterString != '': filterString = " | grep {}".format(filterString) output = getoutput("lspci -nn -d {}:{}".format( manufacturerId, filterString)) if output: self.log.write("lspci output = {}".format(output), 'get_lspci_info') for line in output: matchObj = re.search(':\W(.*)\W\[(.+):(.+)\]', line) if matchObj: deviceArray.append( [matchObj.group(1), matchObj.group(2), matchObj.group(3)]) return deviceArray def shorten_long_string(self, longString, charLen, breakOnWord=True): tmpArr = [] if breakOnWord: stringArr = longString.split(' ') nrChrs = 0 for s in stringArr: nrChrs += len(s) + 1 if nrChrs < charLen: tmpArr.append(s) else: break else: if len(longString) > charLen: tmpArr.append("{}...".format(longString[0:charLen])) else: tmpArr.append(longString) return ' '.join(tmpArr) # Return graphics module used by X.org # TODO: is lsmod an alternative? def get_loaded_graphical_driver(self): # sort on the most recent X.org log module = '' log = '' logDir = '/var/log/' logPath = None logs = glob(os.path.join(logDir, 'Xorg.*.log*')) logs.sort() for logPath in logs: # Search for "depth" in each line and check the used module # Sometimes these logs are saved as binary: open as read-only binary # When opening as ascii, read() will throw error: "UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80" with open(logPath, 'rb') as f: # replace utf-8 binary read errors (with ?) log = f.read().decode(encoding='utf-8', errors='replace') #print((log)) matchObj = re.search('([a-zA-Z]*)\(\d+\):\s+depth.*framebuffer', log, flags=re.IGNORECASE) if matchObj: module = matchObj.group(1).lower() self.log.write("Log module={}".format(module)) break return module # Return used wireless driver def get_loaded_wireless_driver(self): driver = '' logDir = '/var/log/' for logPath in glob(os.path.join(logDir, 'syslog*')): if driver == '' and not 'gz' in logPath: # Open the log file lines = [] with open(logPath, 'rb') as f: log = f.read().decode(encoding='utf-8', errors='replace') lines = list(log.splitlines()) for line in reversed(lines): # First check for Network Manager entry # Search for wlan0 in each line and get the listed driver matchObj = re.search( '\(wlan\d\):.*driver:\s*\'([a-zA-Z0-9\-]*)', line, flags=re.IGNORECASE) if matchObj: driver = matchObj.group(1) self.log.write( "Network Manager driver={}".format(driver)) break else: # Wicd # Search for ieee in each line and get the listed driver matchObj = re.search('ieee.*implement', line, flags=re.IGNORECASE) if matchObj: driver = matchObj.group(0) self.log.write("Wicd driver={}".format(driver)) break return driver def show_message(self, cmdOutput): try: self.log.write("Command output: {}".format(cmdOutput), 'show_message') ret = int(cmdOutput) if ret > 1 and ret != 255: if ret == 1: ErrorDialog(self.btnSave.get_label(), _("Run as root.")) elif ret == 2: ErrorDialog(self.btnSave.get_label(), _("Wrong arguments passed to ddm.")) elif ret == 3: ErrorDialog(self.btnSave.get_label(), _("There are no driver available.")) elif ret == 4: ErrorDialog(self.btnSave.get_label(), _("The driver cannot be found in repository.")) elif ret == 5: ErrorDialog( self.btnSave.get_label(), _("Download error.\nCheck your internet connection.")) elif ret == 6: ErrorDialog(self.btnSave.get_label(), _("DDM cannot purge the driver.")) elif ret == 7: ErrorDialog(self.btnSave.get_label(), _("This card is not supported.")) else: msg = _( "There was an error during the installation.\n" "Please, run 'sudo apt-get -f install' in a terminal.\n" "Visit our forum for support: http://forums.solydxk.com" ) ErrorDialog(self.btnSave.get_label(), msg) else: msg = _("The software has been successfully installed.") msg_restart = _("You will need to restart your system.") MessageDialog(self.btnSave.get_label(), "{}\n\n{}".format(msg, msg_restart)) except: ErrorDialog(self.btnSave.get_label(), cmdOutput)