def run(self, cmd, realTime=True, returnAsList=True, outputTreeView=None): tvHandler = None if outputTreeView is not None: tvHandler = TreeViewHandler(outputTreeView) tvHandler.fillTreeview([], columnTypesList=['str']) msg = "Command to execute: %(cmd)s" % { "cmd": cmd } if self.log: self.log.write(msg, 'execcmd.run', 'debug') else: print(msg) p = subprocess.Popen([cmd], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) lstOut = [] while True: line = p.stdout.readline() if not line: break # Strip the line, also from null spaces (strip() only strips white spaces) line = line.decode('utf-8').rstrip().rstrip("\0") lstOut.append(line) if realTime: if tvHandler is not None: tvHandler.fillTreeview([line], columnTypesList=['str'], appendToExisting=True, setCursor=tvHandler.getRowCount()) if self.log: self.log.write(line, 'execcmd.run', 'info') else: print(line) sys.stdout.flush() while Gtk.events_pending(): Gtk.main_iteration() ret = lstOut if not returnAsList: ret = "\n".join(lstOut).strip() return ret
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()
def rtobjectWrite(self, message): if self.rtobject is not None and self.typeString != '': if self.typeString == 'gtk.Label': self.rtobject.set_text(message) elif self.typeString == 'gtk.TreeView': tvHandler = TreeViewHandler(None, self.rtobject) tvHandler.fillTreeview([message], ['str'], [-1], 0, 400, False, True, True, fontSize=10000) elif self.typeString == 'gtk.Statusbar': functions.pushMessage(self.rtobject, message) else: # For obvious reasons: do not log this... print 'Return object type not implemented: %s' % self.typeString
def rtobjectWrite(self, message): if self.rtobject is not None and self.typeString != '': if 'label' in self.typeString.lower(): self.rtobject.set_text(message) elif 'treeview' in self.typeString.lower(): tvHandler = TreeViewHandler(self.rtobject) tvHandler.fillTreeview([message], ['str'], [-1], 0, 400, False, True, True, fontSize=10000) elif 'statusbar' in self.typeString.lower(): self.pushMessage(message) else: # For obvious reasons: do not log this... print(('Return object type not implemented: %s' % self.typeString))
def rtobjectWrite(self, message): if self.rtobject is not None and self.typeString != '': if 'label' in self.typeString.lower(): self.rtobject.set_text(message) elif 'treeview' in self.typeString.lower(): tvHandler = TreeViewHandler(self.rtobject) tvHandler.fillTreeview([message], ['str'], [-1], 0, 400, False, True, True, fontSize=10000) elif 'statusbar' in self.typeString.lower(): functions.pushMessage(self.rtobject, message) else: # For obvious reasons: do not log this... print('Return object type not implemented: %s' % self.typeString)
def run(self, cmd, realTime=True, returnAsList=True, outputTreeView=None): tvHandler = None if outputTreeView is not None: tvHandler = TreeViewHandler(outputTreeView) tvHandler.fillTreeview([], columnTypesList=['str']) msg = "Command to execute: %(cmd)s" % {"cmd": cmd} if self.log: self.log.write(msg, 'execcmd.run', 'debug') else: print(msg) p = subprocess.Popen([cmd], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) lstOut = [] while True: line = p.stdout.readline() if not line: break # Strip the line, also from null spaces (strip() only strips white spaces) line = line.decode('utf-8').rstrip().rstrip("\0") lstOut.append(line) if realTime: if tvHandler is not None: tvHandler.fillTreeview([line], columnTypesList=['str'], appendToExisting=True, setCursor=tvHandler.getRowCount()) if self.log: self.log.write(line, 'execcmd.run', 'info') else: print(line) try: sys.stdout.flush() except: pass while Gtk.events_pending(): Gtk.main_iteration() ret = lstOut if not returnAsList: ret = "\n".join(lstOut).strip() return ret
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)
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()
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()
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()
class Constructor(object): def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/trail/constructor') self.userAppDir = join(get_user_home_dir(), ".constructor") self.distroFile = join(self.userAppDir, "distros.list") # Create the user's application directory if it doesn't exist if not isdir(self.userAppDir): user_name = getUserLoginName() makedirs(self.userAppDir) old_distro_file = join(self.scriptDir, "distros.list") if exists(old_distro_file): move(old_distro_file, self.distroFile) system("chown -R %s:%s %s" % (user_name, user_name, self.userAppDir)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) # Add iso window translations self.lblIso.set_text(_("ISO")) go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.chkFromIso.set_active(True) self.toggleGuiElements(False) # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, getPackageVersion('constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Main Window Functions # =============================================== def on_btnAdd_clicked(self, widget): self.windowAddDistro.show() def on_btnRemove_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: qd = QuestionDialog(self.btnRemove.get_label(), _("Are you sure you want to remove the selected distribution from the list?\n" \ "(This will not remove the directory and its data)"), self.window) answer = qd.show() if answer: self.saveDistroFile(distroPath=path, addDistro=False) self.fillTreeViewDistros() def on_btnEdit_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: de = EditDistro(path) services = [] if exists(join(path, 'root/etc/apache2/apache2.conf')): services.append("apache2") if exists(join(path, 'root/etc/mysql/debian.cnf')): services.append("mysql") if services: msg = "If you need to update packages that depend on these services,\n" \ "you will need to manually start them:\n" for service in services: msg += "\nservice %s start" % service msg += "\n\nWhen done:\n" for service in services: msg += "\nservice %s stop" % service self.showInfo(_("Services detected"), msg, self.window) repaintGui() de.openTerminal() def on_btnUpgrade_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) upgraded = False for path in selected: upgraded = True rootPath = "%s/root" % path force = get_apt_force(rootPath) de = EditDistro(path) de.openTerminal("apt-get update") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 start") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql start") de.openTerminal( "apt-get -y %s -o Dpkg::Options::=\"--force-confnew\" dist-upgrade" % force) if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 stop") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql stop") # Cleanup old kernel and headers script = "rmoldkernel.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Download offline packages print(">> Start downloading offline packages") self.download_offline_packages() if upgraded and exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) def download_offline_packages(self): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path arch = getGuestEfiArchitecture(rootPath) de = EditDistro(path) script = "offline.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) offlineSource = join(rootPath, "offline") offlineTarget = join(rootPath, "../boot/offline") if exists(scriptSource): try: copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) # Run the script de.openTerminal("/bin/bash {} {}".format(script, arch)) # Remove script silent_remove(scriptTarget) # Move offline directory to boot directory if exists(offlineSource): print(("%s exists" % offlineSource)) if exists(offlineTarget): print((">> Remove %s" % offlineTarget)) silent_remove(offlineTarget) print((">> Move %s to %s" % (offlineSource, offlineTarget))) move(offlineSource, offlineTarget) else: print((">> Cannot find: %s" % offlineSource)) except Exception as detail: self.showError("Error: getting offline packages", detail, self.window) else: print((">> Cannot find: %s" % scriptSource)) def on_btnBuildIso_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) msg = "" for path in selected: self.toggleGuiElements(True) self.showOutput("Start building ISO in: %s" % path) repaintGui() # Start building the ISO in a thread t = BuildIso(path, self.queue) t.start() self.queue.join() # Thread is done # Get the data from the queue ret = self.queue.get() self.queue.task_done() if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: msg += "%s\n" % ret if msg != "": if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) self.showInfo("", msg, self.window) self.toggleGuiElements(False) def on_chkSelectAll_toggled(self, widget): self.tvHandlerDistros.treeviewToggleAll( toggleColNrList=[0], toggleValue=widget.get_active()) def on_tvDistros_row_activated(self, widget, path, column): self.tvHandlerDistros.treeviewToggleRows(toggleColNrList=[0]) def on_btnOpenDir_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: system("open-as-user %s root" % path) def fillTreeViewDistros(self, selectDistros=[]): contentList = [[ _("Select"), _("Distribution"), _("Working directory") ]] distros = self.getDistros() for distro in distros: select = False for selectDistro in selectDistros: if distro[0] == selectDistro: select = True contentList.append([select, distro[0], distro[1]]) self.tvHandlerDistros.fillTreeview( contentList=contentList, columnTypesList=['bool', 'str', 'str'], firstItemIsColName=True) def getDistros(self): distros = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: lines = f.readlines() for line in lines: line = line.strip().rstrip('/') print(line) if exists(line): dg = DistroGeneral(line) isoName = dg.description distros.append([isoName, line]) # Sort on iso name if distros: distros = sorted(distros, key=operator.itemgetter(0)) return distros # =============================================== # Add ISO Window Functions # =============================================== def on_btnIso_clicked(self, widget): fleFilter = Gtk.FileFilter() fleFilter.set_name("ISO") fleFilter.add_mime_type("application/x-cd-image") fleFilter.add_pattern("*.iso") startDir = None if exists(dirname(self.txtIso.get_text())): startDir = dirname(self.txtIso.get_text()) filePath = SelectFileDialog(title=_('Select ISO'), start_directory=startDir, parent=self.window, gtkFileFilter=fleFilter).show() if filePath is not None: self.txtIso.set_text(filePath) def on_btnDir_clicked(self, widget): startDir = None if exists(self.txtDir.get_text()): startDir = self.txtDir.get_text() dirText = SelectDirectoryDialog(title=_('Select directory'), start_directory=startDir, parent=self.window).show() if dirText is not None: self.txtDir.set_text(dirText) def on_btnSave_clicked(self, widget): self.iso = "" if self.chkFromIso.get_active(): self.iso = self.txtIso.get_text() self.dir = self.txtDir.get_text() title = _("Save existing working directory") if self.iso != "": title = _("Unpack ISO and save") if not exists(self.dir): makedirs(self.dir) if not exists(self.dir): self.showError( title, _("Could not create directory %(dir)s: exiting" % {"dir": self.dir}), self.window) else: self.windowAddDistro.hide() if self.iso != "": if not exists(self.iso): self.showInfo( self.btnSave.get_label(), _("The path to the ISO file does not exist:\n{}". format(self.iso)), self.window) return if listdir(self.dir): qd = QuestionDialog( self.btnSave.get_label(), _("The destination directory is not empty.\n" "Are you sure you want to overwrite all data in {}?". format(self.dir)), self.window) answer = qd.show() if not answer: return self.showOutput("Start unpacking the ISO...") self.toggleGuiElements(True) t = IsoUnpack(self.mountDir, self.iso, self.dir, self.queue) t.start() self.queue.join() GObject.timeout_add(1000, self.checkThread, True) else: self.saveDistroFile(self.dir, True) self.fillTreeViewDistros() self.showOutput(_("Existing working directory added")) #self.toggleGuiElements(False) def on_btnCancel_clicked(self, widget): self.windowAddDistro.hide() def on_addDistroWindow_delete_event(self, widget, data=None): self.windowAddDistro.hide() return True def on_txtIso_changed(self, widget): path = self.txtIso.get_text() if exists(path): self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) if exists(self.txtDir.get_text()): self.btnSave.set_sensitive(True) else: self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) def on_txtDir_changed(self, widget): blnFromIso = self.chkFromIso.get_active() isoPath = self.txtIso.get_text() dirText = self.txtDir.get_text() self.btnSave.set_sensitive(False) if exists(dirText): if blnFromIso: if exists(isoPath): self.btnSave.set_sensitive(True) else: self.btnSave.set_sensitive(True) def on_chkFromIso_toggled(self, widget): if widget.get_active(): self.lblIso.set_visible(True) self.boxIso.set_visible(True) self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) self.lblDir.set_text(_("Unpack ISO to directory")) self.btnSave.set_label(_("Unpack & Save")) else: self.txtIso.set_text("") self.lblIso.set_visible(False) self.boxIso.set_visible(False) self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) self.btnSave.set_sensitive(True) self.lblDir.set_text(_("Work directory")) self.btnSave.set_label(_("Save")) # =============================================== # General functions # =============================================== def showInfo(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.INFO, parent).show() def showError(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.ERROR, parent).show() def showOutput(self, message): print(message) pushMessage(self.statusbar, message) def checkThread(self, addDistro=None): #print 'Thread count = ' + str(threading.active_count()) # As long there's a thread active, keep spinning if threading.active_count() > 1: return True # Thread is done # Get the data from the queuez ret = self.queue.get() self.queue.task_done() # Thread is done if addDistro is not None: self.saveDistroFile(self.dir, addDistro) self.fillTreeViewDistros(self.isoName) self.toggleGuiElements(False) if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: self.showInfo("", ret, self.window) return False def toggleGuiElements(self, startThread): if startThread: self.chkSelectAll.set_sensitive(False) self.tvDistros.set_sensitive(False) self.btnAdd.set_sensitive(False) self.btnBuildIso.set_sensitive(False) self.btnEdit.set_sensitive(False) self.btnRemove.set_sensitive(False) self.btnUpgrade.set_sensitive(False) self.btnLocalize.set_sensitive(False) self.btnDir.set_sensitive(False) else: self.chkSelectAll.set_sensitive(True) self.tvDistros.set_sensitive(True) self.btnAdd.set_sensitive(True) self.btnBuildIso.set_sensitive(True) self.btnEdit.set_sensitive(True) self.btnRemove.set_sensitive(True) self.btnUpgrade.set_sensitive(True) self.btnLocalize.set_sensitive(True) self.btnDir.set_sensitive(True) def saveDistroFile(self, distroPath, addDistro=True): newCont = [] dg = DistroGeneral(distroPath) self.isoName = dg.description cfg = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: cfg = f.readlines() for line in cfg: line = line.strip() if distroPath not in line and exists(line): newCont.append(line) if addDistro: newCont.append(distroPath) with open(self.distroFile, 'w') as f: f.write('\n'.join(newCont)) self.iso = "" self.dir = "" # Close the gui def on_constructorWindow_destroy(self, widget): # Close the app Gtk.main_quit()
def __init__(self): self.scriptDir = abspath(dirname(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.scriptDir, '../../share/sambashare/sambashare.glade')) go = self.builder.get_object self.window = go('sambashareWindow') self.windowAdd = go('sambashareWindowAdd') self.lblTitle = go('lblTitle') self.tvShares = go('tvShares') self.btnAdd = go('btnAdd') self.btnRemove = go('btnRemove') self.txtShareDetails = go('txtShareDetails') self.lblName = go('lblName') self.lblPath = go('lblPath') self.lblComment = go('lblComment') self.lblPublic = go('lblPublic') self.lblReadOnly = go('lblReadOnly') self.txtName = go('txtName') self.txtPath = go('txtPath') self.txtComment = go('txtComment') self.chkPublic = go('chkPublic') self.chkReadOnly = go('chkReadOnly') self.btnOk = go('btnOk') self.btnCancel = go('btnCancel') # Translations self.window.set_title(_("Samba share")) self.windowAdd.set_title(_("Create samba share")) self.lblTitle.set_text(self.window.get_title()) self.lblName.set_text(_("Name")) self.lblPath.set_text(_("Path")) self.lblComment.set_text(_("Comment")) self.lblReadOnly.set_text(_("Read only")) self.lblPublic.set_text(_("Public")) # Init self.ec = ExecCmd() self.us = UserShare() self.shareName = None self.sharePath = None self.startAddNow = False # Fill treeview with shares self.tvHandler = TreeViewHandler(self.tvShares) self.refreshShares() # Command arguments args = sys.argv[1:] for arg in args: if "/" in arg: self.sharePath = arg self.startAddNow = True else: self.shareName = arg # Connect the signals and show the window self.builder.connect_signals(self) self.window.show_all() if self.startAddNow: self.on_btnAdd_clicked(None)
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)
def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() self.user = self.umglobal.getLoginName() # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) print(("UM log = %s" % self.logFile)) self.log = Logger(self.logFile, maxSizeKB=5120) # Remove scripts self.deleteScripts(self.umglobal.localUpdVersion) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.apt = UmApt(self.umglobal) self.kernelVersion = self.umglobal.getKernelVersion() self.upgradables = [] self.upgradableUM = [] self.window = None # Handle arguments parser = argparse.ArgumentParser(description='SolydXK Update Manager') parser.add_argument('-q', '--quick', action="store_true", help='Quick upgrade') parser.add_argument('-r', '--reload', action="store_true", help='') args, extra = parser.parse_known_args() self.quickUpdate = False if args.quick and not self.umglobal.newUpd: self.quickUpdate = True if args.reload: pids = self.umglobal.getProcessPids("updatemanager.py") if len(pids) > 1: print(("updatemanager.py already running - kill pid {}".format( pids[0]))) os.system("kill {}".format(pids[0])) # Set some global translations self.aptErrorText = _("Apt error") self.upgradablePackagesText = _( "The following packages will be upgraded:") self.newPackagesText = _( "The following NEW packages will be installed:") self.removedPackagesText = _("The following packages will be REMOVED:") self.heldbackPackagesText = _( "The following packages have been kept back:") self.downgradePackagesText = _( "The following packages are going to be downgraded:") # Cleanup first for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.umglobal.shareDir, 'updatemanager.glade')) go = self.builder.get_object # Quick update if self.quickUpdate: # Refresh data self.refresh() self.umglobal.collectData() self.apt.createPackagesInfoList() self.apt.createPackageLists() self.fillTreeView() # Run upgrade nid = self.run_upgrade() if nid != "": self.on_command_done(None, 0, nid) sys.exit(2) # Make sure the files directory is set correctly self.checkFilesDir() # Main window objects self.window = go("windowMain") #self.window.set_icon_from_file(join(self.umglobal.iconsDir, self.umglobal.settings["icon-connected"])) self.tvPck = go("tvPck") self.swTerminal = go("swTerminal") self.statusbar = go("statusbar") self.btnInstall = go("btnInstall") self.btnRefresh = go("btnRefresh") self.btnPackages = go("btnPackages") self.btnOutput = go("btnOutput") self.btnInfo = go("btnInfo") self.btnPreferences = go("btnPreferences") self.nbMain = go("nbMain") self.swInfo = go("swInfo") self.btnMaintenance = go("btnMaintenance") self.lblMaintenance = go("lblMaintenance") self.tvMaintenance = go("tvMaintenance") self.btnMaintenanceExecute = go("btnMaintenanceExecute") self.chkMaintenanceSelectAll = go("chkMaintenanceSelectAll") self.radUnneeded = go("radUnneeded") self.radCleanCache = go("radCleanCache") self.radDowngradable = go("radDowngradable") self.radNotavailable = go("radNotavailable") self.radOldKernel = go("radOldKernel") self.lblMaintenanceHelp = go("lblMaintenanceHelp") # Translations self.window.set_title(_("SolydXK Update Manager")) self.btnInstall.set_label(_("Install")) self.btnRefresh.set_label(_("Refresh")) self.btnOutput.set_label(_("Output")) self.btnInfo.set_label(_("Information")) self.btnPreferences.set_label(_("Preferences")) self.btnMaintenance.set_label(_("Maintenance")) self.btnPackages.set_label(_("Packages")) self.uptodateText = self.umglobal.connectedText self.lblMaintenance.set_label(self.btnMaintenance.get_label()) self.btnMaintenanceExecute.set_label(_("Execute")) self.chkMaintenanceSelectAll.set_label(_("Select all")) self.radCleanCache.set_label(_("Clean up the apt cache")) self.radUnneeded.set_label(_("Remove unneeded packages")) self.radNotavailable.set_label( _("Remove packages not available\nin the repositories")) self.radOldKernel.set_label(_("Remove old kernels")) self.radDowngradable.set_label( _("Downgrade packages with\nonly lower versions available")) self.lblMaintenanceHelp.set_label( _("Make sure you create\n" "a system image before you\n" "continue (e.g. Clonezilla).")) # VTE Terminal self.terminal = VirtualTerminal(userInputAllowed=self.umglobal. settings["allow-terminal-user-input"]) self.swTerminal.add(self.terminal) self.terminal.set_vexpand(True) self.terminal.set_hexpand(True) self.terminal.connect('command-done', self.on_command_done) self.terminal.connect('line-added', self.on_line_added) palletList = [ '#4A4A4A', '#BD1919', '#118011', '#CE6800', '#1919BC', '#8D138D', '#139494', '#A7A7A7' ] self.terminal.setTerminalColors("#000000", "#FFFFFF", palletList) self.swTerminal.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#FFFFFF")) # Disable all buttons self.btnInfo.set_sensitive(False) self.btnPreferences.set_sensitive(False) self.btnOutput.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnPackages.set_sensitive(False) self.btnMaintenance.set_sensitive(False) # Hide tabs if needed for tab in self.umglobal.settings["hide-tabs"]: if tab == "packages": self.nbMain.get_nth_page(0).set_visible(False) self.btnPackages.set_visible(False) elif tab == "output": self.nbMain.get_nth_page(1).set_visible(False) self.btnOutput.set_visible(False) elif tab == "info": self.nbMain.get_nth_page(2).set_visible(False) self.btnInfo.set_visible(False) elif tab == "maintenance": self.nbMain.get_nth_page(3).set_visible(False) self.btnMaintenance.set_visible(False) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # Force the window to show while Gtk.events_pending(): Gtk.main_iteration() # Just show something that we're busy msg = _("Gathering information...") self.terminal.executeCommand('echo "%s"' % msg, 'init') self.showOutput() # Treeview handlers self.tvHandler = TreeViewHandler(self.tvPck) self.tvMaintenanceHandler = TreeViewHandler(self.tvMaintenance) # Version information ver = _("Version") pckVer = self.apt.getPackageVersion('updatemanager') versionInfo = "%(ver)s: %(pckVer)s" % {"ver": ver, "pckVer": pckVer} if self.umglobal.localUpdVersion != "2000.01.01": versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } self.pushMessage(versionInfo) # Log basic information self.log.write("==============================================", "UM.init", "debug") self.log.write("UM version = %s" % versionInfo, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") mirrorsList = join(self.umglobal.filesDir, basename(self.umglobal.settings["mirrors-list"])) if exists(mirrorsList): self.log.write("Mirrors list", "UM.init", "debug") with open(mirrorsList, 'r') as f: for line in f.readlines(): self.log.write(line, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") # Refresh apt cache self.refresh() # Initialize maintenance screen self.fillTreeViewMaintenance()
class UpdateManager(object): def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() self.user = self.umglobal.getLoginName() # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) print(("UM log = %s" % self.logFile)) self.log = Logger(self.logFile, maxSizeKB=5120) # Remove scripts self.deleteScripts(self.umglobal.localUpdVersion) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.apt = UmApt(self.umglobal) self.kernelVersion = self.umglobal.getKernelVersion() self.upgradables = [] self.upgradableUM = [] self.window = None # Handle arguments parser = argparse.ArgumentParser(description='SolydXK Update Manager') parser.add_argument('-q', '--quick', action="store_true", help='Quick upgrade') parser.add_argument('-r', '--reload', action="store_true", help='') args, extra = parser.parse_known_args() self.quickUpdate = False if args.quick and not self.umglobal.newUpd: self.quickUpdate = True if args.reload: pids = self.umglobal.getProcessPids("updatemanager.py") if len(pids) > 1: print(("updatemanager.py already running - kill pid {}".format( pids[0]))) os.system("kill {}".format(pids[0])) # Set some global translations self.aptErrorText = _("Apt error") self.upgradablePackagesText = _( "The following packages will be upgraded:") self.newPackagesText = _( "The following NEW packages will be installed:") self.removedPackagesText = _("The following packages will be REMOVED:") self.heldbackPackagesText = _( "The following packages have been kept back:") self.downgradePackagesText = _( "The following packages are going to be downgraded:") # Cleanup first for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.umglobal.shareDir, 'updatemanager.glade')) go = self.builder.get_object # Quick update if self.quickUpdate: # Refresh data self.refresh() self.umglobal.collectData() self.apt.createPackagesInfoList() self.apt.createPackageLists() self.fillTreeView() # Run upgrade nid = self.run_upgrade() if nid != "": self.on_command_done(None, 0, nid) sys.exit(2) # Make sure the files directory is set correctly self.checkFilesDir() # Main window objects self.window = go("windowMain") #self.window.set_icon_from_file(join(self.umglobal.iconsDir, self.umglobal.settings["icon-connected"])) self.tvPck = go("tvPck") self.swTerminal = go("swTerminal") self.statusbar = go("statusbar") self.btnInstall = go("btnInstall") self.btnRefresh = go("btnRefresh") self.btnPackages = go("btnPackages") self.btnOutput = go("btnOutput") self.btnInfo = go("btnInfo") self.btnPreferences = go("btnPreferences") self.nbMain = go("nbMain") self.swInfo = go("swInfo") self.btnMaintenance = go("btnMaintenance") self.lblMaintenance = go("lblMaintenance") self.tvMaintenance = go("tvMaintenance") self.btnMaintenanceExecute = go("btnMaintenanceExecute") self.chkMaintenanceSelectAll = go("chkMaintenanceSelectAll") self.radUnneeded = go("radUnneeded") self.radCleanCache = go("radCleanCache") self.radDowngradable = go("radDowngradable") self.radNotavailable = go("radNotavailable") self.radOldKernel = go("radOldKernel") self.lblMaintenanceHelp = go("lblMaintenanceHelp") # Translations self.window.set_title(_("SolydXK Update Manager")) self.btnInstall.set_label(_("Install")) self.btnRefresh.set_label(_("Refresh")) self.btnOutput.set_label(_("Output")) self.btnInfo.set_label(_("Information")) self.btnPreferences.set_label(_("Preferences")) self.btnMaintenance.set_label(_("Maintenance")) self.btnPackages.set_label(_("Packages")) self.uptodateText = self.umglobal.connectedText self.lblMaintenance.set_label(self.btnMaintenance.get_label()) self.btnMaintenanceExecute.set_label(_("Execute")) self.chkMaintenanceSelectAll.set_label(_("Select all")) self.radCleanCache.set_label(_("Clean up the apt cache")) self.radUnneeded.set_label(_("Remove unneeded packages")) self.radNotavailable.set_label( _("Remove packages not available\nin the repositories")) self.radOldKernel.set_label(_("Remove old kernels")) self.radDowngradable.set_label( _("Downgrade packages with\nonly lower versions available")) self.lblMaintenanceHelp.set_label( _("Make sure you create\n" "a system image before you\n" "continue (e.g. Clonezilla).")) # VTE Terminal self.terminal = VirtualTerminal(userInputAllowed=self.umglobal. settings["allow-terminal-user-input"]) self.swTerminal.add(self.terminal) self.terminal.set_vexpand(True) self.terminal.set_hexpand(True) self.terminal.connect('command-done', self.on_command_done) self.terminal.connect('line-added', self.on_line_added) palletList = [ '#4A4A4A', '#BD1919', '#118011', '#CE6800', '#1919BC', '#8D138D', '#139494', '#A7A7A7' ] self.terminal.setTerminalColors("#000000", "#FFFFFF", palletList) self.swTerminal.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#FFFFFF")) # Disable all buttons self.btnInfo.set_sensitive(False) self.btnPreferences.set_sensitive(False) self.btnOutput.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnPackages.set_sensitive(False) self.btnMaintenance.set_sensitive(False) # Hide tabs if needed for tab in self.umglobal.settings["hide-tabs"]: if tab == "packages": self.nbMain.get_nth_page(0).set_visible(False) self.btnPackages.set_visible(False) elif tab == "output": self.nbMain.get_nth_page(1).set_visible(False) self.btnOutput.set_visible(False) elif tab == "info": self.nbMain.get_nth_page(2).set_visible(False) self.btnInfo.set_visible(False) elif tab == "maintenance": self.nbMain.get_nth_page(3).set_visible(False) self.btnMaintenance.set_visible(False) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # Force the window to show while Gtk.events_pending(): Gtk.main_iteration() # Just show something that we're busy msg = _("Gathering information...") self.terminal.executeCommand('echo "%s"' % msg, 'init') self.showOutput() # Treeview handlers self.tvHandler = TreeViewHandler(self.tvPck) self.tvMaintenanceHandler = TreeViewHandler(self.tvMaintenance) # Version information ver = _("Version") pckVer = self.apt.getPackageVersion('updatemanager') versionInfo = "%(ver)s: %(pckVer)s" % {"ver": ver, "pckVer": pckVer} if self.umglobal.localUpdVersion != "2000.01.01": versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } self.pushMessage(versionInfo) # Log basic information self.log.write("==============================================", "UM.init", "debug") self.log.write("UM version = %s" % versionInfo, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") mirrorsList = join(self.umglobal.filesDir, basename(self.umglobal.settings["mirrors-list"])) if exists(mirrorsList): self.log.write("Mirrors list", "UM.init", "debug") with open(mirrorsList, 'r') as f: for line in f.readlines(): self.log.write(line, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") # Refresh apt cache self.refresh() # Initialize maintenance screen self.fillTreeViewMaintenance() # =============================================== # Main window functions # =============================================== def on_btnInstall_clicked(self, widget): self.run_upgrade() def run_upgrade(self): nid = "" aptHasErrors = self.apt.aptHasErrors() if aptHasErrors is not None: MessageDialog(self.aptErrorText, aptHasErrors) elif self.upgradables: if self.apt.upgradablePackages: self.log.write( "=================== upgradable pacages ====================", "UM.run_upgrade", "debug") self.log.write( self.createLogString(self.apt.upgradablePackages), "UM.run_upgrade", "debug") if self.apt.removedPackages: self.log.write( "==================== removed packages =====================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.removedPackages), "UM.run_upgrade", "debug") if self.apt.newPackages: self.log.write( "======================= new packages =======================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.newPackages), "UM.run_upgrade", "debug") if self.apt.heldbackPackages: self.log.write( "=================== kept back packages =====================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.heldbackPackages), "UM.run_upgrade", "debug") if not self.quickUpdate: self.showOutput() contMsg = _("Continue installation?") if self.upgradableUM: cmd = "%s install updatemanager" % self.umglobal.settings[ 'apt-get-string'] cmd += "; %s install %s" % ( self.umglobal.settings['apt-get-string'], " ".join( self.apt.getPackageDependencies('updatemanager'))) nid = 'uminstallum' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.on_btnInstall_clicked", "debug") else: msg = self.getDistUpgradeInfo() answer = True if msg != "": answer = self.showConfirmationDlg(contMsg, msg) if answer: cmd = "%s dist-upgrade" % self.umglobal.settings[ 'apt-get-string'] #if self.umglobal.newUpd: pre = join( self.umglobal.filesDir, self.umglobal.settings['pre-upd'].replace( "[VERSION]", self.umglobal.serverUpdVersion)) post = join( self.umglobal.filesDir, self.umglobal.settings['post-upd'].replace( "[VERSION]", self.umglobal.serverUpdVersion)) if exists(pre): cmd = "/bin/bash %(pre)s; %(cmd)s" % { "pre": pre, "cmd": cmd } if exists(post): cmd = "%(cmd)s; /bin/bash %(post)s" % { "cmd": cmd, "post": post } nid = 'umupd' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.on_btnInstall_clicked", "debug") else: if not self.quickUpdate: MessageDialog(self.btnInstall.get_label(), self.uptodateText) return nid def on_btnRefresh_clicked(self, widget): self.refresh() def on_btnPackages_clicked(self, widget): self.showPackages() def on_btnOutput_clicked(self, widget): self.showOutput() def on_btnInfo_clicked(self, widget): self.showInfo() def on_btnPreferences_clicked(self, widget): # Run preferences in its own thread pref_thread = threading.Thread(target=self.openPreferences) pref_thread.setDaemon(True) pref_thread.start() def openPreferences(self): os.system("updatemanager -p") def on_btnMaintenance_clicked(self, widget): self.showMaintenance() def on_radCleanCache_toggled(self, widget): if widget.get_active(): self.fillTreeViewMaintenance() def on_radUnneeded_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % ( _("You might need to run this several times."), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radNotavailable_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % ( _("Removing not available packages may break your system!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radOldKernel_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % ( _("Once removed you will not be able to boot these kernels!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radDowngradable_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % ( _("Downgrading packages may break your system!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_btnMaintenanceExecute_clicked(self, widget): self.executeMaintenance() def on_chkMaintenanceSelectAll_toggled(self, widget): self.tvMaintenanceHandler.treeviewToggleAll( toggleColNrList=[0], toggleValue=widget.get_active()) # =============================================== # Maintenance functions # =============================================== def enableMaintenance(self, enable=True): self.btnMaintenanceExecute.set_sensitive(enable) self.radUnneeded.set_sensitive(enable) self.radCleanCache.set_sensitive(enable) self.radDowngradable.set_sensitive(enable) self.radOldKernel.set_sensitive(enable) self.radNotavailable.set_sensitive(enable) self.chkMaintenanceSelectAll.set_sensitive(enable) if enable: self.chkMaintenanceSelectAll.set_active(False) def fillTreeViewMaintenance(self): blnCleanCache = self.radCleanCache.get_active() blnUnneeded = self.radUnneeded.get_active() blnDowngradable = self.radDowngradable.get_active() blnNotavailable = self.radNotavailable.get_active() blnOldKernels = self.radOldKernel.get_active() self.enableMaintenance(False) columnTypesList = ['bool', 'str', 'str', 'str'] packages = [["", _("Package"), _("Installed"), _("Available")]] # Clear the treeview first self.tvMaintenanceHandler.fillTreeview(packages, columnTypesList, 0, 400, True) msg = "" if blnCleanCache: msg = _("Hit the Execute button to clean the cache.") columnTypesList = ['str'] packages.append([msg]) elif blnUnneeded: msg = self.radUnneeded.get_label() self.apt.createPackageLists("apt-get autoremove") for pck in self.apt.removedPackages: packages.append([False, pck[0], pck[1], pck[2]]) self.apt.createPackageLists() # Add orphaned files self.apt.fillOrphanedPackages() for pck in self.apt.orphanedPackages: packages.append([False, pck[0], pck[1], pck[2]]) elif blnNotavailable: msg = self.radNotavailable.get_label() self.apt.fillNotAvailablePackages() for pck in self.apt.notavailablePackages: if pck[0][0:6] != "linux-": packages.append([False, pck[0], pck[1], ""]) elif blnOldKernels: msg = self.radOldKernel.get_label() self.apt.fillKernelPackages() for pck in self.apt.kernelPackages: if "headers-486" not in pck[0] \ and "headers-586" not in pck[0] \ and "headers-686" not in pck[0] \ and "headers-amd64" not in pck[0] \ and "image-486" not in pck[0] \ and "image-586" not in pck[0] \ and "image-686" not in pck[0] \ and "image-amd64" not in pck[0]: checkVersion = self.kernelVersion if "kbuild" in pck[0]: indMinus = self.kernelVersion.index("-") indZero = self.kernelVersion.index("0") if indZero > 0 and indZero < indMinus: ind = indZero - 1 else: ind = indMinus if ind > 0: checkVersion = self.kernelVersion[0:ind] if checkVersion not in pck[0]: packages.append([False, pck[0], pck[1], ""]) elif blnDowngradable: msg = self.radDowngradable.get_label() self.apt.fillDowngradablePackages() for pck in self.apt.downgradablePackages: packages.append([False, pck[0], pck[1], pck[2]]) if len(packages) > 1: self.tvMaintenanceHandler.fillTreeview(packages, columnTypesList, 0, 400, True) else: if not blnCleanCache: msg = _("\"%s\"\n did not return any results.") % msg MessageDialog(self.btnMaintenance.get_label(), msg) self.enableMaintenance(True) def executeMaintenance(self): blnCleanCache = self.radCleanCache.get_active() blnDowngradable = self.radDowngradable.get_active() blnNotNeeded = self.radUnneeded.get_active() downgradeString = "" deleteString = "" updateGrub = False cmd = "" self.enableMaintenance(False) if blnCleanCache: safe = False msg = _( "Do you want to completely clean the apt cache?\n\n" "When No, only unavailable installation packages are removed.") answer = QuestionDialog(self.radCleanCache.get_label(), msg) if answer: safe = True self.apt.cleanCache(safe) msg = _("Apt cache has been cleaned.") MessageDialog(self.radCleanCache.get_label(), msg) else: # Get user selected packages model = self.tvMaintenance.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: pck = model.get_value(itr, 1) avVer = model.get_value(itr, 3) if blnDowngradable: downgradeString += " %(pck)s=%(avVer)s" % { "pck": pck, "avVer": avVer } else: deleteString += " %s" % pck if "linux-image" in pck: updateGrub = True itr = model.iter_next(itr) if downgradeString != "": cmd = "%s install %s" % ( self.umglobal.settings['apt-get-string'], downgradeString) elif deleteString != "": cmd = "%s purge %s" % ( self.umglobal.settings['apt-get-string'], deleteString) if cmd != "": self.apt.createPackageLists(cmd) msg = self.getDistUpgradeInfo() answer = True if msg != "": contMsg = _("Execute maintenance changes?") answer = self.showConfirmationDlg(contMsg, msg) if answer: if updateGrub: cmd += "; update-grub" if blnNotNeeded: cmd += "; %s purge $(COLUMNS=132 dpkg -l | grep ^rc | awk '{ print $2 }')" % self.umglobal.settings[ 'apt-get-string'] self.showOutput() nid = 'ummaintenance' self.prepForCommand(nid) self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.executeMaintenance", "debug") self.enableMaintenance(True) # =============================================== # General functions # =============================================== def prepForCommand(self, nid): os.system("touch %s" % self.umglobal.umfiles[nid]) if not self.quickUpdate: self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnMaintenance.set_sensitive(False) def on_line_added(self, terminal, line): if line.strip()[0:2].upper() == "E:": self.log.write(line, "UM.on_line_added", "error") else: self.log.write(line, "UM.on_line_added", "info") def on_command_done(self, terminal, pid, nid): if nid != "init": self.log.write("Command finished (pid=%s, nid=%s)" % (pid, nid), "UM.on_command_done", "info") if nid == "uminstallum": # Reload UM self.log.write( "Updating UM: kill process of updatemanagerpref.py", "UM.on_command_done", "debug") self.umglobal.killScriptProcess("updatemanagerpref.py") # Reload tray as user self.log.write( "Updating UM: kill process of updatemanagertray.py", "UM.on_command_done", "debug") self.umglobal.killScriptProcess("updatemanagertray.py") cmd = "sudo -u {} updatemanager -t -r".format(self.user) os.system(cmd) self.log.write( "UM updated: reload tray as user {}".format(self.user), "UM.on_command_done", "debug") # Reload UM window cmd = join(self.umglobal.scriptDir, "updatemanager.py") if self.quickUpdate: cmd = join(self.umglobal.scriptDir, "updatemanager.py -q") self.umglobal.reloadWindow(cmd, self.user) self.log.write( "UM updated: reload {0} as user {1}".format( cmd, self.user), "UM.on_command_done", "debug") elif nid == "umrefresh": # Build installed packages info list self.apt.createPackagesInfoList() # Run post update when needed self.postUpdate() elif nid == "ummaintenance": self.enableMaintenance(True) self.fillTreeViewMaintenance() self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.showMaintenance() elif nid == 'umupd': # Save update version in hist file self.umglobal.saveHistVersion("upd", self.umglobal.serverUpdVersion) self.log.write( "Save history upd=%s" % self.umglobal.serverUpdVersion, "UM.on_command_done", "debug") self.deleteScripts() # Refresh data after install or update self.umglobal.collectData() self.apt.createPackageLists() self.fillTreeView() # Enable the buttons and load the info page self.log.write( "Re-initiate window after terminal command: %s" % str(not self.quickUpdate), "UM.on_command_done", "debug") if not self.quickUpdate: self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.btnInfo.set_sensitive(True) self.loadInfo() if self.umglobal.newUpd: self.showInfo() else: # This throws a lock file error in Plasma5 #aptHasErrors = self.apt.aptHasErrors() #if aptHasErrors is not None: #MessageDialog(self.aptErrorText, aptHasErrors) #el if self.upgradables: self.showPackages() else: self.showInfo() MessageDialog(self.btnInfo.get_label(), self.uptodateText) self.log.write("Re-initiate window complete", "UM.on_command_done", "debug") # Cleanup name file(s) for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) def createLogString(self, packagesList): lst = [] for data in packagesList: lst.append(data[0]) return ' '.join(lst) def refresh(self): # Refresh server info print((self.umglobal.hasInternet)) self.umglobal.getServerInfo() print((self.umglobal.hasInternet)) # Check of programs locking apt prog = self.apt.getAptCacheLockedProgram( self.umglobal.settings["apt-packages"]) if prog is not None: msg = _("Another program is locking the apt cache\n\n" "Please, close the program before refreshing:\n" "* %s" % prog) MessageDialog(self.btnRefresh.get_label(), msg) self.log.write("%s is locking the apt cache" % prog, "UM.refresh", "warning") elif self.umglobal.hasInternet: if not self.quickUpdate: # Update the apt cache self.btnPreferences.set_sensitive(True) self.btnOutput.set_sensitive(True) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnMaintenance.set_sensitive(False) self.btnPackages.set_sensitive(True) self.showOutput() cmd = "dpkg --configure -a; %s -f install; apt-get update" % self.umglobal.settings[ 'apt-get-string'] nid = 'umrefresh' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.apt.initAptShowVersions() self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.refresh", "debug") else: if not self.quickUpdate: # No internet connection self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.btnInfo.set_sensitive(True) self.btnOutput.set_sensitive(True) self.btnPreferences.set_sensitive(True) self.loadInfo() self.showInfo() def postUpdate(self): # Check for changed version information if self.umglobal.newUpd and self.umglobal.serverUpdVersion is not None: self.getScripts([ self.umglobal.settings['pre-upd'].replace( "[VERSION]", self.umglobal.serverUpdVersion), self.umglobal.settings['post-upd'].replace( "[VERSION]", self.umglobal.serverUpdVersion) ]) def fillTreeView(self): # First check if this application is upgradable self.upgradableUM = self.getUpgradablePackages( packageNames=["updatemanager"]) if self.upgradableUM: self.upgradables = self.upgradableUM else: # Get a list of packages that can be upgraded self.upgradableUM = [] self.upgradables = self.getUpgradablePackages() #if not self.upgradables: ## Check for black listed packages #cmd = "dpkg --get-selections | grep hold$ | awk '{print $1}'" #lst = self.ec.run(cmd, False) #for pck in lst: #self.upgradables.append([pck.strip(), _("blacklisted"), ""]) if not self.quickUpdate: contentList = [[ _("Package"), _("Current version"), _("New version") ]] + self.upgradables self.tvHandler.fillTreeview(contentList=contentList, columnTypesList=['str', 'str', 'str'], firstItemIsColName=True) def getUpgradablePackages(self, packageNames=[]): upckList = [] if packageNames: upckList = [] for packageName in packageNames: for upck in self.apt.upgradablePackages: if upck[0] == packageName: upckList.append(upck) break else: upckList = self.apt.upgradablePackages return upckList def getDistUpgradeInfo(self, upgradablesOnly=False): info = "" if upgradablesOnly: if self.apt.upgradablePackages: info = "<strong>%s</strong><br>" % self.apt.upgradablePackagesText for pck in self.apt.upgradablePackages: info += "%s " % pck[0] else: if self.apt.removedPackages: info = "<strong>%s</strong><br>" % self.removedPackagesText for pck in self.apt.removedPackages: info += "%s " % pck[0] if self.apt.newPackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.newPackagesText for pck in self.apt.newPackages: info += "%s " % pck[0] if self.apt.heldbackPackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.heldbackPackagesText for pck in self.apt.heldbackPackages: info += "%s " % pck[0] if self.apt.downgradablePackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.downgradePackagesText for pck in self.apt.downgradablePackages: info += "%s " % pck[0] return info def showPackages(self): self.nbMain.set_current_page(0) def showOutput(self): self.nbMain.set_current_page(1) self.terminal.grab_focus() def showInfo(self): self.nbMain.set_current_page(2) def showMaintenance(self): self.nbMain.set_current_page(3) def showConfirmationDlg(self, title, message): head = "<html><head><style>body { font-family: Arial, Helvetica, Verdana, Sans-serif; font-size: 12px; color: #555555; background: #ffffff; }</style></head><body>" end = "</body></html>" html = "%s%s%s" % (head, message, end) sw = Gtk.ScrolledWindow() sw.add(SimpleBrowser(html)) return CustomQuestionDialog(title, sw, 550, 300, self.window).show() # Get pre-install script and post-install script from the server def getScripts(self, files): for fle in files: flePath = join(self.umglobal.filesDir, fle) if not exists(flePath): # Get the new scripts if they exist url = "%s/%s/%s" % (self.umglobal.settings['solydxk'], self.umglobal.settings["umfilesdir"], fle) try: txt = urlopen(url).read().decode('utf-8') if txt != '': # Save to a file and make executable self.log.write("Save script = %s" % flePath, "UM.getScripts", "debug") with open(flePath, 'w') as f: f.write(txt) chmod(flePath, 0o755) except: pass def loadInfo(self): languageDir = self.get_language_dir() url = join("file://%s" % languageDir, self.umglobal.settings['up-to-date']) self.btnInfo.set_icon_name("help-about") if self.upgradables: url = join("file://%s" % languageDir, self.umglobal.settings['updates']) if self.umglobal.newUpd: url = "%s/%s/%s" % (self.umglobal.settings['solydxk'], self.umglobal.settings["umfilesdir"], self.umglobal.settings['upd-info']) elif self.umglobal.serverUpdVersion is None: url = join("file://%s" % languageDir, self.umglobal.settings['not-found']) self.log.write("Load info url: %s" % url, "UM.loadInfo", "debug") children = self.swInfo.get_children() if children: children[0].openUrl(url) else: self.swInfo.add(SimpleBrowser(url)) 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.umglobal.htmlDir, lang) if not isdir(path): base_lang = lang.split('_')[0].lower() path = join(self.umglobal.htmlDir, base_lang) if not isdir(path): path = join(self.umglobal.htmlDir, "{}_{}".format(base_lang, base_lang.upper())) if not isdir(path): path = join(self.umglobal.htmlDir, 'en') return path def get_current_language(self): lang = os.environ.get('LANG', 'US').split('.')[0] if lang == '': lang = 'en' return lang def pushMessage(self, message): if message is not None: context = self.statusbar.get_context_id('message') self.statusbar.push(context, message) def checkFilesDir(self): if not exists(self.umglobal.filesDir): makedirs(self.umglobal.filesDir) oldFiles = glob(join(self.umglobal.scriptDir, 'pre-*')) + \ glob(join(self.umglobal.scriptDir, 'post-*')) + \ [join(self.umglobal.scriptDir, 'updatemanager.hist')] + \ [join(self.umglobal.scriptDir, 'mirrors.list')] for fle in oldFiles: if exists(fle): fleName = basename(fle) if not exists(join(self.umglobal.filesDir, fleName)): move(fle, self.umglobal.filesDir) else: remove(fle) chmod(self.umglobal.filesDir, 0o777) def deleteScripts(self, UpdVersion=None): UpdVersion = "*" if UpdVersion is not None: UpdVersion = "*%s" % UpdVersion oldFiles = glob(join( self.umglobal.filesDir, "pre-%s" % UpdVersion)) + glob( join(self.umglobal.filesDir, "post-%s" % UpdVersion)) for fle in oldFiles: remove(fle) self.log.write("Cleanup file: %s" % fle, "UM.deleteScripts", "debug") # Close the gui def on_windowMain_destroy(self, widget): # Close the app Gtk.main_quit()
def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/solydxk/constructor') # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.btnHelp = go('btnHelp') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("SolydXK Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) self.btnHelp.set_label("_{}".format(_("Help"))) # Add iso window translations self.lblIso.set_text(_("ISO")) go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroFile = join(self.scriptDir, "distros.list") self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.doneWav = join(self.shareDir, 'done.wav') self.help = join(self.shareDir, 'help.html') self.chkFromIso.set_active(True) self.toggleGuiElements(False) self.hostEfiArchitecture = functions.getHostEfiArchitecture() # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, functions.getPackageVersion('solydxk-constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show()
class Constructor(object): def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/solydxk/constructor') # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.btnHelp = go('btnHelp') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("SolydXK Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) self.btnHelp.set_label("_{}".format(_("Help"))) # Add iso window translations self.lblIso.set_text(_("ISO")) go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroFile = join(self.scriptDir, "distros.list") self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.doneWav = join(self.shareDir, 'done.wav') self.help = join(self.shareDir, 'help.html') self.chkFromIso.set_active(True) self.toggleGuiElements(False) self.hostEfiArchitecture = functions.getHostEfiArchitecture() # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, functions.getPackageVersion('solydxk-constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Main Window Functions # =============================================== def on_btnAdd_clicked(self, widget): self.windowAddDistro.show() def on_btnRemove_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: qd = QuestionDialog(self.btnRemove.get_label(), _("Are you sure you want to remove the selected distribution from the list?\n" \ "(This will not remove the directory and its data)"), self.window) answer = qd.show() if answer: self.saveDistroFile(distroPath=path, addDistro=False) self.fillTreeViewDistros() def on_btnEdit_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: de = EditDistro(path) services = [] if exists(join(path, 'root/etc/apache2/apache2.conf')): services.append("apache2") if exists(join(path, 'root/etc/mysql/debian.cnf')): services.append("mysql") if services: msg = "If you need to update packages that depend on these services,\n" \ "you will need to manually start them:\n" for service in services: msg += "\nservice %s start" % service msg += "\n\nWhen done:\n" for service in services: msg += "\nservice %s stop" % service self.showInfo(_("Services detected"), msg, self.window) functions.repaintGui() de.openTerminal() def on_btnUpgrade_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) upgraded = False for path in selected: upgraded = True rootPath = "%s/root" % path de = EditDistro(path) de.openTerminal("apt-get update") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 start") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql start") de.openTerminal("apt-get -y --force-yes -o Dpkg::Options::=\"--force-confnew\" dist-upgrade") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 stop") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql stop") # Cleanup old kernel and headers script = "rmoldkernel.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x %s" % scriptTarget) de.openTerminal("/bin/bash %s" % script) remove(scriptTarget) # Build EFI files if self.hostEfiArchitecture != "": print(">> Start building EFI files") self.build_efi_files() # Download offline packages print(">> Start downloading offline packages") self.download_offline_packages() if upgraded and exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x %s" % scriptTarget) de.openTerminal("/bin/bash %s" % script) remove(scriptTarget) def build_efi_files(self): # TODO - also 32-bit installs (haven't tested this) modules = "part_gpt part_msdos ntfs ntfscomp hfsplus fat ext2 normal chain boot configfile linux " \ "multiboot iso9660 gfxmenu gfxterm loadenv efi_gop efi_uga loadbios fixvideo png " \ "ext2 ntfscomp loopback search minicmd cat cpuid appleldr elf usb videotest " \ "halt help ls reboot echo test normal sleep memdisk tar font video_fb video " \ "gettext true video_bochs video_cirrus multiboot2 acpi gfxterm_background gfxterm_menu" selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path bootPath = "{}/boot".format(path) arch = functions.getGuestEfiArchitecture(rootPath) grubEfiName = "bootx64" efiName = "x64" if arch != "x86_64": arch = "i386" grubEfiName = "bootia32" efiName = "ia32" try: if not exists("{}/efi/boot".format(bootPath)): makedirs("{}/efi/boot".format(bootPath)) self.ec.run("efi-image {}/~tmp {}-efi {}".format(bootPath, arch, efiName)) if exists("{}/~tmp/efi.img".format(bootPath) and exists("{}/~tmp/boot/grub/{}-efi".format(bootPath, arch))): self.ec.run("rm -r {}/boot/grub/{}-efi".format(bootPath, arch)) self.ec.run("mv -vf {}/~tmp/boot/grub/{}-efi {}/boot/grub/".format(bootPath, arch, bootPath)) self.ec.run("mv -vf {}/~tmp/efi.img {}/boot/grub/".format(bootPath, bootPath)) self.ec.run("rm -r {}/~tmp".format(bootPath)) self.ec.run("grub-mkimage -O {}-efi -d /usr/lib/grub/{}-efi " "-o {}/efi/boot/{}.efi " "-p \"/boot/grub\" {}".format(arch, arch, bootPath, grubEfiName, modules)) print((">> Finished building EFI files")) except Exception as detail: self.showError("Error: build EFI files", detail, self.window) def download_offline_packages(self): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path arch = functions.getGuestEfiArchitecture(rootPath) de = EditDistro(path) script = "offline.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) offlineSource = join(rootPath, "offline") offlineTarget = join(rootPath, "../boot/offline") if exists(scriptSource): try: copy(scriptSource, scriptTarget) self.ec.run("chmod a+x %s" % scriptTarget) # Run the script de.openTerminal("/bin/bash {} {}".format(script, arch)) # Remove script remove(scriptTarget) # Move offline directory to boot directory if exists(offlineSource): print(("%s exists" % offlineSource)) if exists(offlineTarget): print((">> Remove %s" % offlineTarget)) rmtree(offlineTarget) print((">> Move %s to %s" % (offlineSource, offlineTarget))) move(offlineSource, offlineTarget) else: print((">> Cannot find: %s" % offlineSource)) except Exception as detail: self.showError("Error: getting offline packages", detail, self.window) else: print((">> Cannot find: %s" % scriptSource)) def on_btnBuildIso_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) msg = "" for path in selected: self.toggleGuiElements(True) self.showOutput("Start building ISO in: %s" % path) functions.repaintGui() # Start building the ISO in a thread t = BuildIso(path, self.queue) t.start() self.queue.join() # Thread is done # Get the data from the queue ret = self.queue.get() self.queue.task_done() if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: msg += "%s\n" % ret if msg != "": if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) self.showInfo("", msg, self.window) self.toggleGuiElements(False) def on_chkSelectAll_toggled(self, widget): self.tvHandlerDistros.treeviewToggleAll(toggleColNrList=[0], toggleValue=widget.get_active()) def on_tvDistros_row_activated(self, widget, path, column): self.tvHandlerDistros.treeviewToggleRows(toggleColNrList=[0]) def on_btnHelp_clicked(self, widget): if functions.isPackageInstalled("firefox"): system("firefox file://%s &" % self.help) else: system("xdg-open file://%s &" % self.help) def on_btnOpenDir_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: system("xdg-open %s &" % path) def fillTreeViewDistros(self, selectDistros=[]): contentList = [[_("Select"), _("Distribution"), _("Working directory")]] distros = self.getDistros() for distro in distros: select = False for selectDistro in selectDistros: if distro[0] == selectDistro: select = True contentList.append([select, distro[0], distro[1]]) self.tvHandlerDistros.fillTreeview(contentList=contentList, columnTypesList=['bool', 'str', 'str'], firstItemIsColName=True) def getDistros(self): distros = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: lines = f.readlines() for line in lines: line = line.strip().rstrip('/') print(line) if exists(line): dg = DistroGeneral(line) isoName = dg.description distros.append([isoName, line]) # Sort on iso name if distros: distros = sorted(distros, key=operator.itemgetter(0)) return distros # =============================================== # Add ISO Window Functions # =============================================== def on_btnIso_clicked(self, widget): fleFilter = Gtk.FileFilter() fleFilter.set_name("ISO") fleFilter.add_mime_type("application/x-cd-image") fleFilter.add_pattern("*.iso") startDir = None if exists(dirname(self.txtIso.get_text())): startDir = dirname(self.txtIso.get_text()) filePath = SelectFileDialog(title=_('Select SolydXK ISO'), start_directory=startDir, parent=self.window, gtkFileFilter=fleFilter).show() if filePath is not None: self.txtIso.set_text(filePath) def on_btnDir_clicked(self, widget): startDir = None if exists(self.txtDir.get_text()): startDir = self.txtDir.get_text() dirText = SelectDirectoryDialog(title=_('Select directory'), start_directory=startDir, parent=self.window).show() if dirText is not None: self.txtDir.set_text(dirText) def on_btnSave_clicked(self, widget): self.iso = "" if self.chkFromIso.get_active(): self.iso = self.txtIso.get_text() self.dir = self.txtDir.get_text() title = _("Save existing working directory") if self.iso != "": title = _("Unpack ISO and save") if not exists(self.dir): makedirs(self.dir) if not exists(self.dir): self.showError(title, _("Could not create directory %(dir)s: exiting" % {"dir": self.dir}), self.window) else: self.windowAddDistro.hide() if self.iso != "": if not exists(self.iso): self.showInfo(self.btnSave.get_label(), _("The path to the ISO file does not exist:\n{}".format(self.iso)), self.window) return if listdir(self.dir): qd = QuestionDialog(self.btnSave.get_label(), _("The destination directory is not empty.\n" "Are you sure you want to overwrite all data in {}?".format(self.dir)), self.window) answer = qd.show() if not answer: return self.showOutput("Start unpacking the ISO...") self.toggleGuiElements(True) t = IsoUnpack(self.mountDir, self.iso, self.dir, self.queue) t.start() self.queue.join() GObject.timeout_add(1000, self.checkThread, True) else: self.saveDistroFile(self.dir, True) self.fillTreeViewDistros() self.showOutput(_("Existing working directory added")) #self.toggleGuiElements(False) def on_btnCancel_clicked(self, widget): self.windowAddDistro.hide() def on_addDistroWindow_delete_event(self, widget, data=None): self.windowAddDistro.hide() return True def on_txtIso_changed(self, widget): path = self.txtIso.get_text() if exists(path): self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) if exists(self.txtDir.get_text()): self.btnSave.set_sensitive(True) else: self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) def on_txtDir_changed(self, widget): blnFromIso = self.chkFromIso.get_active() isoPath = self.txtIso.get_text() dirText = self.txtDir.get_text() self.btnSave.set_sensitive(False) if exists(dirText): if blnFromIso: if exists(isoPath): self.btnSave.set_sensitive(True) else: self.btnSave.set_sensitive(True) def on_chkFromIso_toggled(self, widget): if widget.get_active(): self.lblIso.set_visible(True) self.boxIso.set_visible(True) self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) self.lblDir.set_text(_("Unpack ISO to directory")) self.btnSave.set_label(_("Unpack & Save")) else: self.txtIso.set_text("") self.lblIso.set_visible(False) self.boxIso.set_visible(False) self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) self.btnSave.set_sensitive(True) self.lblDir.set_text(_("Work directory")) self.btnSave.set_label(_("Save")) # =============================================== # General functions # =============================================== def showInfo(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.INFO, parent).show() def showError(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.ERROR, parent).show() def showOutput(self, message): print(message) functions.pushMessage(self.statusbar, message) def checkThread(self, addDistro=None): #print 'Thread count = ' + str(threading.active_count()) # As long there's a thread active, keep spinning if threading.active_count() > 1: return True # Thread is done # Get the data from the queuez ret = self.queue.get() self.queue.task_done() # Thread is done if addDistro is not None: self.saveDistroFile(self.dir, addDistro) self.fillTreeViewDistros(self.isoName) self.toggleGuiElements(False) if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: self.showInfo("", ret, self.window) return False def toggleGuiElements(self, startThread): if startThread: self.chkSelectAll.set_sensitive(False) self.tvDistros.set_sensitive(False) self.btnAdd.set_sensitive(False) self.btnBuildIso.set_sensitive(False) self.btnEdit.set_sensitive(False) self.btnRemove.set_sensitive(False) self.btnUpgrade.set_sensitive(False) else: self.chkSelectAll.set_sensitive(True) self.tvDistros.set_sensitive(True) self.btnAdd.set_sensitive(True) self.btnBuildIso.set_sensitive(True) self.btnEdit.set_sensitive(True) self.btnRemove.set_sensitive(True) self.btnUpgrade.set_sensitive(True) def saveDistroFile(self, distroPath, addDistro=True): newCont = [] dg = DistroGeneral(distroPath) self.isoName = dg.description cfg = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: cfg = f.readlines() for line in cfg: line = line.strip() if distroPath not in line and exists(line): newCont.append(line) if addDistro: newCont.append(distroPath) with open(self.distroFile, 'w') as f: f.write('\n'.join(newCont)) self.iso = "" self.dir = "" # Close the gui def on_constructorWindow_destroy(self, widget): # Close the app Gtk.main_quit()
class USBCreator(Gtk.Window): def __init__(self): super(USBCreator, self).__init__() # Where do we live? self.scriptDir = abspath(dirname(__file__)) + "/" # Now, get our configuration data self.settingsData = config.Config(join(self.scriptDir, "files/multi-usb-creator.conf")) # Get the path to our dialog glade file and then # create the object self.dialogBox = USBCreatorDialogBox(join(self.scriptDir, self.settingsData.getValue("localfiles", "icon-path"))) self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, self.settingsData.getValue("localfiles", "glade-file"))) # Main window objects go = self.builder.get_object self.USBCreatorWindow = go("USBCreatorWindow") self.btnClose = go("btnClose") self.btnExecute = go("btnExecute") self.btnHelp = go("btnHelp") self.btnListDownLoadISOs = go("btnListDownLoadISOs") self.btnRefresh = go("btnRefresh") self.btnSelectISOFile = go("btnSelectISOFile") self.cmbSelectedUSBDevice = go("cmbSelectedUSBDevice") self.cmbDeleteISO = go("cmbDeleteISO") self.cmbDownLoad = go("cmbDownLoad") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.lblUSBCreatorWindowTitle = go("lblUSBCreatorWindowTitle") self.rbAddISO = go("rbAddISO") self.rbCleanUSB = go("rbCleanUSB") self.rbDelete = go("rbDelete") self.rbDownLoad = go("rbDownLoad") self.txtAvailable = go("txtAvailable") self.txtISOFileName = go("txtISOFileName") self.txtRequired = go("txtRequired") self.pbCopy = go("pbCopy") self.lblIServerSOListWindowTitle = go("lblIServerSOListWindowTitle") # Cleaning the USB device is a function only available to # user running as (or logged in as) root. Of course, a note # to this effect is in the help! self.rbCleanUSB.set_sensitive(bool(os.getuid() == 0)) # FileChooserDialog objects self.FileChooserDialog = go("FileChooserDialog") self.btnFileChooserDialogCancel = go("btnFileChooserDialogCancel") self.btnFileChooserDialogOpen = go("btnFileChooserDialogOpen") # The Server ISO List window self.ServerISOListWindow = go("ServerISOListWindow") self.lblIServerSOListWindowTitle = go("lblIServerSOListWindowTitle") self.btnServerISOListWindowClose = go("btnServerISOListWindowClose") self.tvServerISOData = go("tvServerISOData") # Help window objects self.HelpWindow = go("HelpWindow") self.lblHelpWindowTitle = go("lblHelpWindowTitle") self.lblHelpWindowHelpText = go("lblHelpWindowHelpText") # Create our handlers # First, our ComboBox handlers self.cmbHandlerSelectUSB = ComboBoxHandler(self.cmbSelectedUSBDevice, None) self.cmbHandlerDownLoad = ComboBoxHandler(self.cmbDownLoad, None) self.cmbHandlerDeleteISO = ComboBoxHandler(self.cmbDeleteISO, None) self.tvHandlerServerISOData = TreeViewHandler(self.tvServerISOData, None) self.cmbHandlerServerISO = ComboBoxHandler(self.cmbDownLoad, None) # Now, the data handlers self.usbDataHandler = USBDataListHandler() self.installedFilesHandler = InstalledFilesListHandler() self.serverISOHandler = ServerISOListHandler() # Might as well get the server ISO list while we're here self.serverISOHandler.getServerISOList(self.settingsData.getValue("url", "solydxk-iso-list-URL"), self.settingsData.getValue("localfiles", "local-iso-list")) # And populate the Server ISO TreeView self.tvHandlerServerISOData.fillTreeview(contentList=self.serverISOHandler.getTreeViewList(), columnTypesList=["str", "str", "str", "str", "str", "str"], firstItemIsColName=True) self.cmbHandlerDownLoad.fillComboBox(self.serverISOHandler.getComboBoxList()) if self.serverISOHandler.rowCount > 0: self.cmbDownLoad.set_active(0) # Get the USB data because it all starts with the USB devices # and, then, populate the USB ComboBox #self.usbDataHandler.getUSBData() self.RefreshUSBSelector() # Translations self.USBCreatorWindow.set_title(_("SolydXK Multi-Boot USB Creator")) self.rbAddISO.set_label(_("Add ISO")) self.rbDownLoad.set_label(_("Down Load")) self.rbDelete.set_label(_("Delete")) self.rbCleanUSB.set_label(_("Clean USB")) self.lblAvailable.set_label(_("Space Available (GiB):")) self.lblRequired.set_label(_("Required:")) self.lblIServerSOListWindowTitle.set_label(_("ISOs Available for Download")) self.HelpWindow.set_title(_("Multi-Boot Help")) self.lblHelpWindowTitle.set_label(_("Multi-Boot Help")) self.HelpWindowPopulateText() # Finally, we can connect our signals, hide the FileChooserDialog # (just in case) # and show our main window. self.FileChooserDialog.hide() self.HelpWindow.hide() theHeight = self.USBCreatorWindow.get_size()[1] #theWidth = self.USBCreatorWindow.get_size()[0] self.USBCreatorWindow.resize(626, theHeight) self.pbCopy.set_visible(False) self.theQ = Queue(-1) self.builder.connect_signals(self) self.USBCreatorWindow.show() Gtk.main() ########################################## # # USBCreatorWindow Event Handlers # ########################################## def IsEnoughSpace(self): if self.requiredSpace > self.availableSpace: self.dialogBox.infoDialog(_("Insufficient Space Available"), _("The selected USB device has insuffiecient\nspace for the indicate operation.")) return(False) else: return(True) def on_btnExecute_clicked(self, widget): if self.cmbSelectedUSBDevice.get_active() == -1: self.dialogBox.infoDialog(_("No USB Device"), (_("Please select a USB device to which to copy the .iso file"))) else: if self.rbAddISO.get_active(): if self.IsEnoughSpace(): self.DoISOAdd() elif self.rbDownLoad.get_active(): if self.IsEnoughSpace(): self.DoISODownLoad() elif self.rbDelete.get_active(): self.DoISODelete() elif self.rbCleanUSB.get_active(): self.CleanTheUSBDevice() else: logging.debug(_("Problem with Radio Buttons")) def on_btnHelp_clicked(self, widget): self.HelpWindow.show() def on_btnListDownLoadISOs_clicked(self, widget): self.ServerISOListWindow.show() def on_btnRefresh_clicked(self, widget): self.usbDataHandler.getUSBData() self.RefreshUSBSelector() self.rbAddISO.set_active(True) def on_btnSelectISOFile_clicked(self, widget): self.FileChooserDialog.show() def on_cmbDeleteISO_changed(self, widget): self.rbDelete.set_active(True) #self.on_RadioButton_toggled(self.rbDelete) def on_cmbDownLoad_changed(self, widget): self.rbDownLoad.set_active(True) #self.on_RadioButton_toggled(self.rbDownLoad) def on_cmbSelectedUSBDevice_changed(self, widget): self.DoNewUSBSelected() self.rbAddISO.set_active(True) #self.on_RadioButton_toggled(self.rbAddISO) def on_RadioButton_toggled(self, widget): if widget.get_active(): if self.rbAddISO.get_active(): # Get the filename from the text entry control (if there is one). # Check to see if the text is the path to a file. If it is, # then get the size of the file and show it to the user. theFileName = self.txtISOFileName.get_text() if os.path.isfile(theFileName): self.requiredSpace = int(os.path.getsize(theFileName)) self.txtRequired.set_text(self.Convert2Gigs(self.requiredSpace)) elif self.rbDownLoad.get_active(): # Get the index of the ComboBox, use that as a pointer to the data if self.cmbDownLoad.get_active() != -1: self.requiredSpace = int(self.serverISOHandler.getFileSize(self.cmbDownLoad.get_active())) self.txtRequired.set_text(self.Convert2Gigs(self.requiredSpace)) elif self.rbDelete.get_active(): pass elif self.rbCleanUSB.get_active(): pass else: logging.debug(_("Unknown RadioButton selected")) def on_USBCreatorWindow_destroy(self, widget): Gtk.main_quit() ########################################## # # USBCreatorWindow utility functions # ########################################## # Clean the USB device indicated in the cmbSelectedUSBDevice def CleanTheUSBDeviceCheck(self): if self.theThread.is_alive(): retVal = True self.pbCopy.pulse() if not self.theQ.empty(): lst = self.theQ.get(False) if lst: if isinstance(lst[0], str): self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CleanTheUSBDeviceCheck - Error: {}").format(lst[0])) self.theQ.task_done() else: retVal = False try: if not self.theQ.empty(): lst = self.theQ.get(False) if lst: if isinstance(lst[0], str): self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CleanTheUSBDeviceCheck - Error: {}").format(lst[0])) else: if bool(lst[0]): self.dialogBox.infoDialog(_("Cleaning Is Complete"), _("The USB Device has been re-initialized.\nIt is safe to remove it and re-insert it for\nISO file copy/download operations.")) else: self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CleanTheUSBDeviceCheck\n - Error encountered during cleaning operation.")) except Exception as detail: logging.debug(_("Error Encountered"), _("MultiBootISOCreator:CleanTheUSBDeviceCheck - Error: {}").format(detail)) self.dialogBox.errorDialog("MultiBootISOCreator:CleanTheUSBDeviceCheck - Error: {}".format(detail)) finally: # Save our current index localActiveIndex = self.cmbSelectedUSBDevice.get_active() # Relaod all the USB related data self.RefreshUSBSelector() # Point our ComboBox back where it was if localActiveIndex <= self.usbDataHandler.rowCount: self.cmbSelectedUSBDevice.set_active(localActiveIndex) elif self.usbDataHandler.rowCount > 0: self.cmbSelectedUSBDevice.set_active(0) else: self.cmbSelectedUSBDevice.set_active(-1) self.DoNewUSBSelected() self.rbAddISO.set_active(True) self.on_RadioButton_toggled(self.rbAddISO) self.SetButtonsSensitive(True) return(retVal) def CleanTheUSBDevice(self): if self.usbDataHandler.rowCount <= 0: self.dialogBox.infoDialog(_("Ummm ... No USB device"), _("Did you forget to mount a USB device with which we can play?")) else: response = self.dialogBox.warningDialog(_("Please confirm"), _("Please confirm you wish to re-initialize\nthe device\n\n{}").format(self.usbDataHandler.getDevice(self.cmbSelectedUSBDevice.get_active()))) if response != Gtk.ResponseType.OK: self.dialogBox.infoDialog(_("Operation Cancelled"), _("Operation to re-initialize the\n" + "USB device has been cancelled.")) else: theCommandList = [] theCommandList.clear() # The device in the data comes back with the partition number on it. theDevice = self.usbDataHandler.getDevice(self.cmbSelectedUSBDevice.get_active())[:-1] # This is where we are going to mount the device to install grub. We need to # ensure that whatever mount point we choose is not already in use. One way # to do that is to create it and then blow it away when we are done. while True: rootMountPoint = "/media/{}".format((uuid.uuid1()).hex) if not os.path.exists(rootMountPoint): os.makedirs(rootMountPoint) break # The device is mounted at /media/<user>/<usb label>. We want to unmount that puppy so # we can do our thang to it. theCommandList.append("umount {}".format(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active()))) theCommandList.append("dd if=/dev/zero of={} bs=4M count=25".format(theDevice)) theCommandList.append("parted -a optimal -s {} mklabel msdos".format(theDevice)) theCommandList.append("parted -a optimal -s {} mkpart primary fat32 0% 100% set 1 boot on".format(theDevice)) theCommandList.append("mkdosfs -F32 -n 'SOLYDXK' -I {}1".format(theDevice)) # OK, now mount it where we can find it. theCommandList.append("mount {0}1 {1}".format(theDevice, rootMountPoint)) theCommandList.append("tar zxf {0}/files/solydxk-usb.tar.gz -C {1}".format(self.scriptDir, rootMountPoint)) theCommandList.append("grub-install --root-directory={0} --no-floppy --recheck --force {1}".format(rootMountPoint, theDevice)) theCommandList.append("umount {}1".format(theDevice)) theCommandList.append("rmdir {0}".format(rootMountPoint)) self.theThread = ExecuteCommandList(theCommandList, self.theQ) self.theThread.daemon = True self.theThread.start() self.theQ.join() self.pbCopy.set_text(_("Cleaning Device")) self.pbCopy.set_show_text(True) self.SetButtonsSensitive(False) GLib.timeout_add(100, self.CleanTheUSBDeviceCheck) def Convert2Gigs(self, theSize): return("{:.2f}".format((float(theSize) / float(2 ** 30)))) def CopyCheck(self, destFileName): if self.theThread.is_alive(): retVal = True self.pbCopy.pulse() if not self.theQ.empty(): lst = self.theQ.get(False) if lst: if isinstance(lst[0], str): self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CopyCheck - Error: {}").format(lst[0])) removeFile = True self.theQ.task_done() else: removeFile = False retVal = False try: if not self.theQ.empty(): lst = self.theQ.get(False) if lst: if isinstance(lst[0], str): self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CopyCheck - Error: {}").format(lst[0])) removeFile = True else: if bool(lst[0]): self.txtISOFileName.set_text("") self.dialogBox.infoDialog(_("Copy Is Complete"), _("The USB Device has been updated.\n" + "It is safe to unmount and remove it.")) else: self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CopyCheck - Error encountered during copy.")) removeFile = True self.theQ.task_done() except Exception as detail: logging.debug(_("MultiBootISOCreator:CopyCheck - Error: {}").format(detail)) self.dialogBox.errorDialog(_("Error Encountered"), _("MultiBootISOCreator:CopyCheck - Error: {}").format(detail)) removeFile = True finally: if removeFile: if os.path.isfile(destFileName): os.remove(destFileName) del self.theThread # Save our current index localActiveIndex = self.cmbSelectedUSBDevice.get_active() # Relaod all the USB related data self.RefreshUSBSelector() # Point our ComboBox back where it was if localActiveIndex <= self.usbDataHandler.rowCount: self.cmbSelectedUSBDevice.set_active(localActiveIndex) elif self.usbDataHandler.rowCount > 0: self.cmbSelectedUSBDevice.set_active(0) else: self.cmbSelectedUSBDevice.set_active(-1) self.DoNewUSBSelected() self.UpdateUSBGrubConfig() self.rbAddISO.set_active(True) self.on_RadioButton_toggled(self.rbAddISO) self.SetButtonsSensitive(True) return(retVal) def CopyFile(self, theFileName): commandList = [] commandList.clear() commandList.append("cp {0} {1}".format(self.txtISOFileName.get_text(), theFileName)) self.theThread = ExecuteCommandList(commandList, self.theQ) self.theThread.daemon = True self.theThread.start() self.theQ.join() self.pbCopy.set_text(_("Copying File")) self.pbCopy.set_show_text(True) self.SetButtonsSensitive(False) GLib.timeout_add(100, self.CopyCheck, theFileName) def DownLoadCheck(self, destFileName): if self.theThread.is_alive(): retVal = True self.pbCopy.pulse() if not self.theQ.empty(): lst = self.theQ.get(False) if lst: self.pbCopy.set_text(lst[0]) self.pbCopy.set_show_text(True) self.theQ.task_done() else: retVal = False removeFile = False try: if not self.theQ.empty(): lst = self.theQ.get(False) if lst: if isinstance(lst[0], str): # We have an error message self.dialogBox.errorDialog(_("Error Encountered"), _("Error encountered during download: {}").format(lst[0])) removeFile = True else: # Take care of the results of the MD5Sum calculation if lst[0]: # All is right in the world self.dialogBox.infoDialog(_("Download Is Complete"), _("The USB Device has been updated.\nIt is safe to unmount and remove it.")) else: # Bad MD5Sum self.dialogBox.errorDialog(_("MD5Sum is not a match"), _("Download complete but appears to be\n" + "corrupted. The computed MD5Sum does\n" + "not match the value from the server.\n\n" + "The file has been removed from the USG device.")) removeFile = True except Exception as detail: logging.debug(_("MultiBootISOCreator:DownLoadCheck - exception: {}").format(detail)) self.dialogBox(_("Error in DownLoad."), _("MultiBootISOCreator:DownLoadCheck - exception: {}").format(detail)) removeFile = True finally: self.theQ.task_done() del self.theThread if removeFile: if os.path.isfile(destFileName): os.remove(destFileName) # No matter whether we were successful or not, we need to clean # up our mess and set the controls back to their rightful state. # Save our current index localActiveIndex = self.cmbSelectedUSBDevice.get_active() # Relaod all the USB related data self.RefreshUSBSelector() # Point our ComboBox back where it was if localActiveIndex <= self.usbDataHandler.rowCount: self.cmbSelectedUSBDevice.set_active(localActiveIndex) elif self.usbDataHandler.rowCount > 0: self.cmbSelectedUSBDevice.set_active(0) else: self.cmbSelectedUSBDevice.set_active(-1) self.DoNewUSBSelected() self.UpdateUSBGrubConfig() self.rbDownLoad.set_active(True) self.on_RadioButton_toggled(self.rbDownLoad) self.SetButtonsSensitive(True) return(retVal) def DownLoadFile(self): sourceURL = self.serverISOHandler.getDownLoadURL(self.cmbDownLoad.get_active()) theMD5 = self.serverISOHandler.getMD5Sum(self.cmbDownLoad.get_active()) destFileName = "{0}/{1}.iso".format(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active()), self.serverISOHandler.getSpinID(self.cmbDownLoad.get_active())) self.theThread = DownLoadISO(sourceURL, theMD5, destFileName, self.theQ) self.theThread.daemon = True self.theThread.start() self.theQ.join() self.pbCopy.set_show_text(True) self.SetButtonsSensitive(False) GLib.timeout_add(100, self.DownLoadCheck, destFileName) def DoISOAdd(self): if self.txtISOFileName.get_text() != "": theMessage = _("Please confirm you wish to copy the file\n\n\"{0}\"\n\nto the selected USB device.").format(self.txtISOFileName.get_text()) response = self.dialogBox.warningDialog("Please Confirm ISO Copy", theMessage) if response == Gtk.ResponseType.OK: thePattern = re.compile(self.settingsData.getValue("regex-patterns", "solydxk-iso-file-pattern")) theBaseName = basename(self.txtISOFileName.get_text()) if not thePattern.match(theBaseName): self.dialogBox.infoDialog(_("Not a Known SolydXK ISO"), _("The filename supplied does not match that\n" + "of a known SolydXK ISO file.\n\n" + "Please check your information and try again.")) else: theBaseName = theBaseName[:8] + ".iso" theFileName = "{0}/{1}".format(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active()), theBaseName) if os.path.isfile(theFileName): response = self.dialogBox.questionDialog(_("Over-Write File?"), _("The selected file already exists on the USB device.\n\nOver-write this file?")) else: response = Gtk.ResponseType.YES if response == Gtk.ResponseType.YES: self.CopyFile(theFileName) else: self.dialogBox.infoDialog(_("No file selected"), _("Please select a file to be copied to the selected USB Device")) def DoISODownLoad(self): if self.cmbDownLoad.get_active() == -1: self.dialogBox.infoDialog(_("No file selected"), _("Please select a file to be downloaded to the USB device")) else: self.DownLoadFile() def DoISODelete(self): localActiveIndex = self.cmbDeleteISO.get_active() if localActiveIndex == -1: self.dialogBox.infoDialog(_("No file selected"), _("Please select a file to be deleted from the USB device.")) else: theFileName = "{0}/{1}".format(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active()), self.installedFilesHandler.getFileName(localActiveIndex)) response = self.dialogBox.questionDialog(_("Please confirm file deletion"), _("Please confirm you wish to delete the file\n\n{}\n\nfrom the selected USB device.").format(theFileName)) if response == Gtk.ResponseType.YES: if os.path.isfile(theFileName): os.remove(theFileName) # Rebuild all our USB data localActiveIndex = self.cmbSelectedUSBDevice.get_active() self.RefreshUSBSelector() self.cmbSelectedUSBDevice.set_active(localActiveIndex) self.UpdateUSBGrubConfig() self.dialogBox.infoDialog(_("Operation complete"), _("The selected file has been deleted.")) else: self.dialogBox.errorDialog(_("File not found."), _("The indicated file was not found on the USB device.")) def DoNewUSBSelected(self): if(len(self.usbDataHandler.getList())) > 0: self.installedFilesHandler.buildInstalledFilesList(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active())) self.cmbHandlerDeleteISO.fillComboBox(self.installedFilesHandler.getFilesListComboBoxData()) if self.installedFilesHandler.rowCount > 0: self.cmbDeleteISO.set_active(0) self.availableSpace = int(self.usbDataHandler.getAvailableSpace(self.cmbSelectedUSBDevice.get_active())) self.txtAvailable.set_text(self.Convert2Gigs(self.availableSpace)) self.requiredSpace = 0 self.txtRequired.set_text("") else: self.txtAvailable.set_text("") self.availableSpace = int(0) # Refresh the cmbSelectedUSBDevice and associated data def RefreshUSBSelector(self): self.usbDataHandler.getUSBData() if len(self.usbDataHandler.getList()) > 0: self.cmbHandlerSelectUSB.fillComboBox(self.usbDataHandler.getUSBComboBoxData()) self.cmbSelectedUSBDevice.set_active(0) self.DoNewUSBSelected() else: self.cmbHandlerSelectUSB.clearComboBox() self.DoNewUSBSelected() def SetButtonsSensitive(self, newState): self.pbCopy.set_visible(not newState) self.btnClose.set_sensitive(newState) self.btnExecute.set_sensitive(newState) self.btnHelp.set_sensitive(newState) self.btnListDownLoadISOs.set_sensitive(newState) self.btnRefresh.set_sensitive(newState) self.btnSelectISOFile.set_sensitive(newState) def UpdateUSBGrubConfig(self): if self.installedFilesHandler.rowCount <= 0: self.dialogBox.infoDialog(_("No USB Device found."), _("It appears you forgot to mount a USB device!")) else: self.SetButtonsSensitive(False) theGrubFile = "{0}/boot/grub/grub.cfg".format(self.usbDataHandler.getMountPoint(self.cmbSelectedUSBDevice.get_active())) if os.path.isfile(theGrubFile): os.remove(theGrubFile) with open(theGrubFile, "w") as outFile: outFile.write("# Set the paths to the iso files\n") for i in range(self.installedFilesHandler.rowCount): theFileName = self.installedFilesHandler.getFileName(i) outFile.write("set {0}=\"/{1}\"\n".format(theFileName[:-4], theFileName)) outFile.write("\n# Seconds to wait until starting the default menu entry\n") outFile.write("set timeout=10\n\n") outFile.write("# Default menu entry (0 = first)\nset default=0\n\n") outFile.write("loadfont /boot/grub/fonts/unicode.pf2\n") outFile.write("set gfxmode=auto\n") outFile.write("#set gfxmode=1024x768\n") outFile.write("insmod efi_gop\n") outFile.write("insmod efi_uga\n") outFile.write("insmod gfxterm\n") outFile.write("set gfxpayload=keep\n") outFile.write("terminal_output gfxterm\n\n") outFile.write("insmod png\n") outFile.write("background_image -m stretch /boot/grub/grubbg.png\n") outFile.write("set menu_color_normal=white/black\n") outFile.write("set menu_color_highlight=dark-gray/white\n\n") outFile.write("# Create the menu entries here:\n") # This block of code is for the way SolydXK names the various spins, as of 23AUG2014. # At some time in the future, Debian will promote Jessie to stable and SolydXK # will be changing the names of the spins. At that time, this block of code should # be removed from the application and the next (commented) block should be uncommented # and tested. for i in range(self.installedFilesHandler.rowCount): theFileName = self.installedFilesHandler.getFileName(i)[:-4] if theFileName[-2:] == "be": theEdition = _("Business Edition 64-bit") elif theFileName[-2:] == "bo": theEdition = _("Back Office 64-bit") else: theEdition = _("Home Edition ") + theFileName[-2:] + "-bit" if theFileName[-3:-2] == "k": theDeskTop = "KDE" else: theDeskTop = "Xfce" outFile.write("menuentry \"Solyd{0} {1} (with {2} desktop)\" {3}\n".format(theFileName[-3:-2], theEdition, theDeskTop, "{")) outFile.write("bootoptions=\"findiso=${0} boot=live config username=solydxk hostname=solydxk quite splash\"\n".format(theFileName)) outFile.write("search --set -f ${0}\n".format(theFileName)) outFile.write("loopback loop ${0}\n".format(theFileName)) outFile.write("linux (loop)/live/vmlinuz $bootoptions\n") outFile.write("initrd (loop)/live/initrd.img\n}\n") # This is the block of code that should be uncommented when Jessie is promoted to stable. # This block assumes that the first two columns of iso-data.csv file will be formatted as: # solydk32 SolydK 32-bit # solydk64 SolydK 64-bit # solydx32 SolydX 32-bit # solydx64 SolydX 64-bit # solydkbo SolydK BO 64-bit # solydkee32 SolydK EE 32-bit # solydkee64 SolydK EE 64-bit # solydxee32 SolydX EE 32-bit # solydxee64 SolydX EE 64-bit #for i in range(self.installedFilesHandler.rowCount): #theFileName = self.installedFilesHandler.getFileName(i)[:-4] #if theFileName[-2:] == "be": #theEdition = _(" Back Office Edition") #theArch = "64" #else: #theArch = theFileName[-2:] #if theFileName[-4:-2] == "ee": #theEdition = _(" Enthusiast's Edition") #else: #theEdition = "" #if theFileName[-3:-2] == "k": #theDeskTop = "KDE" #else: #theDeskTop = "Xfce" #outFile.write("menuentry \"Solyd{} {}-bit (with {} desktop\" {}".format(theEdition, theArch, theDeskTop, "{")) #outFile.write("bootoptions=\"findiso=${0} boot=live config username=solydxk hostname=solydxk quite splash\"\n".format(theFileName)) #outFile.write("search --set -f ${0}\n".format(theFileName)) #outFile.write("loopback loop ${0}\n".format(theFileName)) #outFile.write("linux (loop)/live/vmlinuz $bootoptions\n") #outFile.write("initrd (loop)/live/initrd.img\n}\n") self.dialogBox.infoDialog(_("GRUB re-write complete"), _("Please remove the USB device.\n\n" + "Please re-insert the USB device\n" + "If you wish to install ISO files.\n")) self.SetButtonsSensitive(True) ########################################## # # FileChooserDialog Event Handlers # ########################################## def on_FileChooserDialog_cancel(self, widget): self.txtISOFileName.set_text("") self.FileChooserDialog.hide() self.rbAddISO.set_active(True) self.on_RadioButton_toggled(self.rbAddISO) def on_FileChooserDialog_open(self, widget): self.txtISOFileName.set_text(self.FileChooserDialog.get_filename()) self.FileChooserDialog.hide() self.rbAddISO.set_active(True) self.on_RadioButton_toggled(self.rbAddISO) def on_btnHelpWindowOK_clicked(self, widget): self.HelpWindow.hide() def on_HelpWindow_destroy(self, widget): self.HelpWindow.hide() def HelpWindowPopulateText(self): self.lblHelpWindowHelpText.set_label( _("""- Select USB - Using the ComboBox, select the USB device to be used as the Multi-Boot device. - Refresh - Clicking this button will cause the list of USB devices to be refreshed. This can be useful if one starts the application before inserting the intended target USB device. - Add ISO - This option allows for the copying of an already downloaded SolydXK .iso file to the target USB device. - File - This button opens a FileChooserDialog to be used to select the source .iso file. The path to the selected .iso file will be written to the TextEntry control. - Down Load - This option allows for downloading a SolydXK .iso file from the distro servers. The downloaded file will be written directly to the selected USB device. - Information - Opens a window showing a list of all the .iso files available for download, with associated metadata (size, m35sum, etc). - Delete - Use this option to remove an .iso file from the target USB device. Can be useful if there are old files there and you need more space for a new file ... or to over-write an old file with an updated version. - Clean USB - It sometimes happens that a USB device will need to be completely and thoroughly erased before the created USB will successfully boot. This option (available only run application is run as root) allows the user to completely re-initialize the USB device. All data will be deleted, a new partition table, a new data partition created, all required files written, and grub installed. - USB Space - This line indicates the amount of spaces available on the target USB device and the amount of space required to write the selected .iso file to the target USB device. - Help - This message - Execute - Perform the user selected operation. - Close - Exit the program.""")) ########################################## # # ServerISOListWindow Event Handlers # ########################################## def on_btnServerISOListWindowClose_clicked(self, widget): self.ServerISOListWindow.hide()
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)
def __init__(self): # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/usb-creator') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'usb-creator.glade')) # Main window objects go = self.builder.get_object self.window = go("usb-creator") self.lblDevice = go("lblDevice") self.lblIso = go("lblIso") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.cmbDevice = go("cmbDevice") self.cmbDeviceHandler = ComboBoxHandler(self.cmbDevice) self.txtIso = go("txtIso") self.btnRefresh = go("btnRefresh") self.btnUnmount = go("btnUnmount") self.btnBrowseIso = go("btnBrowseIso") self.btnClear = go("btnClear") self.chkFormatDevice = go("chkFormatDevice") self.chkRepairDevice = go("chkRepairDevice") self.btnExecute = go("btnExecute") self.lblUsb = go("lblUsb") self.tvUsbIsos = go("tvUsbIsos") self.btnDelete = go("btnDelete") self.pbUsbCreator = go("pbUsbCreator") self.statusbar = go("statusbar") # Translations self.window.set_title(_("USB Creator")) self.lblDevice.set_label(_("Device")) self.lblUsb.set_label(_("USB")) self.available_text = _("Available") self.required_text = _("Required") self.chkFormatDevice.set_label(_("Format device")) self.chkFormatDevice.set_tooltip_text(_("Warning: all data will be lost")) self.chkRepairDevice.set_label(_("Repair device")) self.chkRepairDevice.set_tooltip_text(_("Tries to repair an unbootable USB")) self.btnExecute.set_label("_{}".format(_("Execute"))) self.lblIso.set_label(_("ISO")) self.btnDelete.set_label("_{}".format(_("Delete"))) self.btnRefresh.set_tooltip_text(_("Refresh device list")) self.btnUnmount.set_tooltip_text(_("Unmount device")) self.btnBrowseIso.set_tooltip_text(_("Browse for ISO file")) self.btnClear.set_tooltip_text(_("Clear the ISO field")) # Log lines to show: check string, percent done (0=pulse, appends last word in log line), show line (translatable) self.log_lines = [] self.log_lines.append(["partitioning usb", 5, _("Partitioning USB...")]) self.log_lines.append(["searching for bad blocks", 0, _("Searching for bad block")]) self.log_lines.append(["installing", 15, _("Installing Grub...")]) self.log_lines.append(["rsync", 25, _("Start copying ISO...")]) self.log_lines.append(["left to copy", 0, _("kB left to copy:")]) self.log_lines.append(["check hash", 85, _("Check hash of ISO...")]) # Initiate variables self.devices = [] self.device = {} self.device['path'] = '' self.device['size'] = 0 self.device['has_partition'] = False self.device['mount'] = '' self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.logos = self.get_logos() self.queue = Queue(-1) self.threads = {} self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput("cat /usr/bin/usb-creator | grep 'LOG=' | cut -d'=' -f 2") self.log_file = log[0] self.log = Logger(self.log_file, addLogTime=False, maxSizeKB=5120) self.tvUsbIsosHandler = TreeViewHandler(self.tvUsbIsos) self.lblAvailable.set_label('') self.lblRequired.set_label('') # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Get attached devices self.on_btnRefresh_clicked() # Init log init_log = ">>> Start USB Creator: {} <<<".format(datetime.now()) self.log.write(init_log) # Version information self.version_text = _("Version") self.pck_version = getPackageVersion('usb-creator') self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version))
def __init__(self): super(USBCreator, self).__init__() # Where do we live? self.scriptDir = abspath(dirname(__file__)) + "/" # Now, get our configuration data self.settingsData = config.Config(join(self.scriptDir, "files/multi-usb-creator.conf")) # Get the path to our dialog glade file and then # create the object self.dialogBox = USBCreatorDialogBox(join(self.scriptDir, self.settingsData.getValue("localfiles", "icon-path"))) self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, self.settingsData.getValue("localfiles", "glade-file"))) # Main window objects go = self.builder.get_object self.USBCreatorWindow = go("USBCreatorWindow") self.btnClose = go("btnClose") self.btnExecute = go("btnExecute") self.btnHelp = go("btnHelp") self.btnListDownLoadISOs = go("btnListDownLoadISOs") self.btnRefresh = go("btnRefresh") self.btnSelectISOFile = go("btnSelectISOFile") self.cmbSelectedUSBDevice = go("cmbSelectedUSBDevice") self.cmbDeleteISO = go("cmbDeleteISO") self.cmbDownLoad = go("cmbDownLoad") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.lblUSBCreatorWindowTitle = go("lblUSBCreatorWindowTitle") self.rbAddISO = go("rbAddISO") self.rbCleanUSB = go("rbCleanUSB") self.rbDelete = go("rbDelete") self.rbDownLoad = go("rbDownLoad") self.txtAvailable = go("txtAvailable") self.txtISOFileName = go("txtISOFileName") self.txtRequired = go("txtRequired") self.pbCopy = go("pbCopy") self.lblIServerSOListWindowTitle = go("lblIServerSOListWindowTitle") # Cleaning the USB device is a function only available to # user running as (or logged in as) root. Of course, a note # to this effect is in the help! self.rbCleanUSB.set_sensitive(bool(os.getuid() == 0)) # FileChooserDialog objects self.FileChooserDialog = go("FileChooserDialog") self.btnFileChooserDialogCancel = go("btnFileChooserDialogCancel") self.btnFileChooserDialogOpen = go("btnFileChooserDialogOpen") # The Server ISO List window self.ServerISOListWindow = go("ServerISOListWindow") self.lblIServerSOListWindowTitle = go("lblIServerSOListWindowTitle") self.btnServerISOListWindowClose = go("btnServerISOListWindowClose") self.tvServerISOData = go("tvServerISOData") # Help window objects self.HelpWindow = go("HelpWindow") self.lblHelpWindowTitle = go("lblHelpWindowTitle") self.lblHelpWindowHelpText = go("lblHelpWindowHelpText") # Create our handlers # First, our ComboBox handlers self.cmbHandlerSelectUSB = ComboBoxHandler(self.cmbSelectedUSBDevice, None) self.cmbHandlerDownLoad = ComboBoxHandler(self.cmbDownLoad, None) self.cmbHandlerDeleteISO = ComboBoxHandler(self.cmbDeleteISO, None) self.tvHandlerServerISOData = TreeViewHandler(self.tvServerISOData, None) self.cmbHandlerServerISO = ComboBoxHandler(self.cmbDownLoad, None) # Now, the data handlers self.usbDataHandler = USBDataListHandler() self.installedFilesHandler = InstalledFilesListHandler() self.serverISOHandler = ServerISOListHandler() # Might as well get the server ISO list while we're here self.serverISOHandler.getServerISOList(self.settingsData.getValue("url", "solydxk-iso-list-URL"), self.settingsData.getValue("localfiles", "local-iso-list")) # And populate the Server ISO TreeView self.tvHandlerServerISOData.fillTreeview(contentList=self.serverISOHandler.getTreeViewList(), columnTypesList=["str", "str", "str", "str", "str", "str"], firstItemIsColName=True) self.cmbHandlerDownLoad.fillComboBox(self.serverISOHandler.getComboBoxList()) if self.serverISOHandler.rowCount > 0: self.cmbDownLoad.set_active(0) # Get the USB data because it all starts with the USB devices # and, then, populate the USB ComboBox #self.usbDataHandler.getUSBData() self.RefreshUSBSelector() # Translations self.USBCreatorWindow.set_title(_("SolydXK Multi-Boot USB Creator")) self.rbAddISO.set_label(_("Add ISO")) self.rbDownLoad.set_label(_("Down Load")) self.rbDelete.set_label(_("Delete")) self.rbCleanUSB.set_label(_("Clean USB")) self.lblAvailable.set_label(_("Space Available (GiB):")) self.lblRequired.set_label(_("Required:")) self.lblIServerSOListWindowTitle.set_label(_("ISOs Available for Download")) self.HelpWindow.set_title(_("Multi-Boot Help")) self.lblHelpWindowTitle.set_label(_("Multi-Boot Help")) self.HelpWindowPopulateText() # Finally, we can connect our signals, hide the FileChooserDialog # (just in case) # and show our main window. self.FileChooserDialog.hide() self.HelpWindow.hide() theHeight = self.USBCreatorWindow.get_size()[1] #theWidth = self.USBCreatorWindow.get_size()[0] self.USBCreatorWindow.resize(626, theHeight) self.pbCopy.set_visible(False) self.theQ = Queue(-1) self.builder.connect_signals(self) self.USBCreatorWindow.show() Gtk.main()
class UserManager(object): def __init__(self): self.scriptDir = abspath(dirname(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, '../../share/usermanager/usermanager.glade')) # Main window objects go = self.builder.get_object self.window = go('usermanagerWindow') self.tvUsersMain = go('tvUsersMain') self.tvUserGroupsMain = go('tvUserGroupsMain') self.chkShowSystemUsers = go('chkShowSystemUsers') self.btnUserEdit = go('btnUserEdit') self.btnUserRemove = go('btnUserRemove') # User window objects self.windowUser = go('usermanagerUserWindow') self.nbUser = go('nbUser') self.txtLoginName = go('txtLoginName') self.txtRealName = go('txtRealName') self.txtUserID = go('txtUserID') self.txtHomeDirectory = go('txtHomeDirectory') self.cmbShells = go('cmbShells') self.cmbPrimaryGroup = go('cmbPrimaryGroup') self.cmbPrimaryGroupEntry = go('cmbPrimaryGroupEntry') self.tvUserGroups = go('tvUserGroups') self.ebFace = go('ebFace') self.imgFace = go('imgFace') self.lblUserID = go('lblUserID') self.txtPassword = go('txtPassword') self.txtLastChanged = go('txtLastChanged') self.cmbValidUntilMonth = go('cmbValidUntilMonth') self.spbValidUntilDay = go('spbValidUntilDay') self.spbValidUntilYear = go('spbValidUntilYear') self.radEnabled = go('radEnabled') self.radDisabled = go('radDisabled') self.radValidUntilAlways = go('radValidUntilAlways') self.radValidUntilDate = go('radValidUntilDate') self.spbRequirePasswordAfter = go('spbRequirePasswordAfter') self.spbWarnBeforePasswordExpires = go('spbWarnBeforePasswordExpires') self.spbDisableAccountWhenPasswordExpires = go('spbDisableAccountWhenPasswordExpires') self.spbEnforceMinimumPasswordAge = go('spbEnforceMinimumPasswordAge') self.chkRequirePasswordAfter = go('chkRequirePasswordAfter') self.chkEnforceMinimumPasswordAge = go('chkEnforceMinimumPasswordAge') self.tvGroupsMain = go('tvGroupsMain') # Group window objects self.windowGroup = go('usermanagerGroupWindow') self.txtGroupName = go('txtGroupName') self.txtGroupID = go('txtGroupID') self.tvAccounts = go('tvAccounts') self.tvSelectedAccounts = go('tvSelectedAccounts') self.tvGroupAccounts = go('tvGroupAccounts') # Main window translations self.window.set_title(_("User manager")) self.chkShowSystemUsers.set_label(_("Show system users")) self.btnUserEdit.set_label(_("Edit")) self.btnUserRemove.set_label(_("Remove")) go('btnUserAdd').set_label(_("Add")) go('lblUsersTab').set_text(_("Users")) go('lblGroupsTab').set_text(_("Groups")) go('lblUsersMain').set_text(go('lblUsersTab').get_text()) go('lblUserGroupsMain').set_text(_("User groups")) go('lblGroupsMain').set_text(go('lblGroupsTab').get_text()) go('lblGroupAccountsMain').set_text(_("Group accounts")) # User window translations self.windowUser.set_title(_("User settings")) go('lblUserDetails').set_text(_("Details")) go('lblStatus').set_text(_("Status")) go('lblLoginName').set_text(_("Login name")) go('lblRealName').set_text(_("Real name")) go('lblUserID').set_text(_("User ID")) go('lblPrimaryGroup').set_text(_("Primary group")) go('lblHomeDirectory').set_text(_("Home directory")) go('lblShell').set_text(_("Shell")) self.radEnabled.set_label(_("Enabled")) self.radDisabled.set_label(_("Disabled")) #go('lblPrivilegesAndGroups').set_text(_("Privileges and groups")) go('lblPrivilegesAndGroups').set_text(go('lblGroupsTab').get_text()) go('lblPrivileges').set_text(_("Privileges")) go('lblUserGroups').set_text(go('lblGroupsTab').get_text()) go('lblPasswordSecurity').set_text(_("Password")) go('lblPassword').set_text(go('lblPasswordSecurity').get_text()) go('lblLastChanged').set_text(_("Last changed")) go('lblValidUntil').set_text(_("Valid until")) self.radValidUntilAlways.set_label(_("Always")) go('lblPasswordAging').set_text(_("Password aging")) self.chkRequirePasswordAfter.set_label(_("Require password after")) go('lblWarnBeforePasswordExpires').set_text(_("Warn before password expires after")) go('lblDisableAccountWhenPasswordExpires').set_text(_("Disable account when password expires after")) self.chkEnforceMinimumPasswordAge.set_label(_("Enforce minimum password age")) go('lblDays1').set_text(_("days")) go('lblDays2').set_text(go('lblDays1').get_text()) go('lblDays3').set_text(go('lblDays1').get_text()) go('lblDays4').set_text(go('lblDays1').get_text()) go('btnSaveUser').set_label(_("Save")) go('btnCancelUser').set_label(_("Cancel")) # Group window translations self.windowGroup.set_title(_("Group settings")) go('lblGroupName').set_text(_("Group name")) go('lblGroupID').set_text(_("Group ID")) go('lblAccounts').set_text(_("Available accounts")) go('lblSelectedAccounts').set_text(_("Selected accounts")) go('btnOkGroup').set_label(go('btnSaveUser').get_label()) go('btnCancelGroup').set_label(go('btnCancelUser').get_label()) go('btnAddAccount').set_label(go('btnUserAdd').get_label()) go('btnRemoveAccount').set_label(self.btnUserRemove.get_label()) # Init self.ec = ExecCmd() self.usr = User() self.usersInfo = {} self.user = {} self.users = [] self.accounts = [] self.shells = self.usr.getShells() self.groups = None self.loggedinUser = self.usr.getLoggedinUser() self.loggedinUserPrimaryGroup = self.usr.getUserPrimaryGroupName(self.loggedinUser) self.selectedUser = None self.selectedGroup = None self.selectedGroupAccounts = None self.userFace = None self.radEnabled.set_active(True) self.radValidUntilAlways.set_active(True) self.setValidUntil(False) self.setRequirePasswordAfter(False) self.setEnforceMinimumPasswordAge(False) self.txtUserID.set_editable(False) self.txtUserID.set_can_focus(False) self.txtLastChanged.set_editable(False) self.txtLastChanged.set_can_focus(False) self.txtGroupID.set_editable(False) self.txtGroupID.set_can_focus(False) self.passwordChanged = False self.homeDirChanged = False self.tempFace = "/tmp/face.png" self.filterText(self.txtLoginName) self.filterText(self.txtGroupName) self.filterText(self.cmbPrimaryGroupEntry) # Treeviews self.tvHandlerUsersMain = TreeViewHandler(self.tvUsersMain) self.tvHandlerUserGroupsMain = TreeViewHandler(self.tvUserGroupsMain) self.tvHandlerUserGroups = TreeViewHandler(self.tvUserGroups) self.tvHandlerAccounts = TreeViewHandler(self.tvAccounts) self.tvHandlerSelectedAccounts = TreeViewHandler(self.tvSelectedAccounts) self.tvHandlerGroupsMain = TreeViewHandler(self.tvGroupsMain) self.tvHandlerGroupAccounts = TreeViewHandler(self.tvGroupAccounts) # Comboboxes self.cmbHandlerShells = ComboBoxHandler(self.cmbShells) self.cmbHandlerPrimaryGroup = ComboBoxHandler(self.cmbPrimaryGroup) self.cmbHandlerValidUntilMonth = ComboBoxHandler(self.cmbValidUntilMonth) # Get data self.refreshData() self.cmbHandlerShells.fillComboBox(self.shells) self.cmbHandlerValidUntilMonth.fillComboBox(functions.getMonthsList()) year = datetime.now().year adj = Gtk.Adjustment(value=year, lower=year, upper=year + 10, step_incr=1, page_incr=0, page_size=0) self.spbValidUntilYear.set_adjustment(adj) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # User functions # =============================================== def on_tvUsersMain_cursor_changed(self, widget, event=None): self.showUserData() def on_tvUsersMain_row_activated(self, widget, path, column): self.on_btnUserEdit_clicked(None) def on_btnUserAdd_clicked(self, widget): self.imgFace.set_from_pixbuf(self.usr.getUserFacePixbuf()) self.tvHandlerUserGroups.fillTreeview(contentList=self.getUserGroupsComplete(), columnTypesList=['bool', 'str']) self.cmbHandlerShells.selectValue('/bin/bash') self.cmbHandlerPrimaryGroup.fillComboBox(self.groups) self.txtLoginName.set_editable(True) self.txtLoginName.set_can_focus(True) self.txtLoginName.set_text("new_user") self.txtUserID.set_text(str(self.usr.getNewUserID())) self.updateNewLogin() self.txtPassword.set_text("") self.radValidUntilAlways.set_active(True) self.windowUser.show() def on_btnUserEdit_clicked(self, widget): if self.selectedUser is not None: if not self.userFace is None: self.imgFace.set_from_pixbuf(self.userFace) self.imgFace.show() self.nbUser.get_nth_page(2).show() else: self.imgFace.hide() # Hide passwords tab self.nbUser.get_nth_page(2).hide() self.txtLoginName.set_editable(False) self.txtLoginName.set_can_focus(False) self.txtLoginName.set_text(self.user['user'].pw_name) if ",,," in self.user['user'].pw_gecos: self.txtRealName.set_text(self.user['user'].pw_name) else: self.txtRealName.set_text(self.user['user'].pw_gecos) self.txtUserID.set_text(str(self.user['user'].pw_uid)) self.txtHomeDirectory.set_text(self.user['user'].pw_dir) self.tvHandlerUserGroups.fillTreeview(contentList=self.getUserGroupsComplete(self.user['groups']), columnTypesList=['bool', 'str']) self.cmbHandlerShells.selectValue(self.user['user'].pw_shell) self.cmbHandlerPrimaryGroup.fillComboBox(self.groups, self.user['prgrp']) self.txtPassword.set_text("") self.txtLastChanged.set_text(self.usr.intToDate(nr_days=self.user['pwd'].sp_lstchg, format_string='%d %B %Y', start_date=datetime(1970, 1, 1))) daysMin = self.user['pwd'].sp_min print((">>> daysMin = %d" % daysMin)) if daysMin > 0: self.radValidUntilDate.set_active(True) dt = self.usr.intToDate(nr_days=daysMin) self.spbValidUntilDay.set_value(dt.day) self.cmbValidUntilMonth.set_active(dt.month - 1) self.spbValidUntilYear.set_value(dt.year) else: self.radValidUntilAlways.set_active(True) daysMax = self.user['pwd'].sp_max daysWarn = self.user['pwd'].sp_warn daysInact = self.user['pwd'].sp_inact print((">>> daysMax = %d" % daysMax)) print((">>> daysWarn = %d" % daysWarn)) print((">>> daysInact = %d" % daysInact)) if daysMax < 1000 and daysWarn >= 0 and daysInact >= 0: self.chkRequirePasswordAfter.set_active(True) self.spbRequirePasswordAfter.set_value(daysMax) self.spbWarnBeforePasswordExpires.set_value(daysWarn) self.spbDisableAccountWhenPasswordExpires.set_value(daysInact) else: self.chkRequirePasswordAfter.set_active(False) daysExpire = self.user['pwd'].sp_expire print((">>> daysExpire = %d" % daysExpire)) if daysExpire >= 0: self.chkEnforceMinimumPasswordAge.set_active(True) self.spbEnforceMinimumPasswordAge.set_value(daysExpire) else: self.chkEnforceMinimumPasswordAge.set_active(False) self.windowUser.show() def on_btnUserRemove_clicked(self, widget): # Remove user if self.selectedUser is not None: title = _("Remove user") if self.selectedUser != self.loggedinUser: qd = QuestionDialog(title, _("Are you sure you want to remove the following user:\n\n'%(user)s'") % { "user": self.selectedUser }, self.window) answer = qd.show() if answer: # TODO ret = self.usr.deleteUser(self.selectedUser) if ret == "": self.showInfo(title, _("User successfully removed: %(user)s") % {"user": self.selectedUser}, self.window) self.refreshData() else: retMsg = "\n\n%s" % ret self.showError(title, _("Could not remove user: %(user)s %(retmsg)s") % {"user": self.selectedUser, "retmsg": retMsg}, self.window) else: self.showError(title, _("You cannot remove the currently logged in user"), self.window) def on_chkShowSystemUsers_toggled(self, widget): self.refreshData() def on_btnBrowse_clicked(self, widget): directory = SelectDirectoryDialog(_('Select user directory'), self.txtHomeDirectory.get_text(), self.windowUser).show() if directory is not None: self.user['user'].pw_dir = directory self.txtHomeDirectory.set_text(self.user['user'].pw_dir) def on_radEnabled_toggled(self, widget): if widget.get_active(): print(">>> Enable user") def on_radDisabled_toggled(self, widget): if widget.get_active(): print(">>> Disable user") def on_radValidUntilAlways_toggled(self, widget): if widget.get_active(): self.setValidUntil(False) def on_radValidUntilDate_toggled(self, widget): if widget.get_active(): self.setValidUntil(True) def setValidUntil(self, boolean=True): self.spbValidUntilDay.set_sensitive(boolean) self.cmbValidUntilMonth.set_sensitive(boolean) self.spbValidUntilYear.set_sensitive(boolean) if not boolean: self.spbValidUntilDay.set_value(0) self.cmbValidUntilMonth.set_active(-1) self.spbValidUntilYear.set_value(0) def on_chkRequirePasswordAfter_toggled(self, widget): if widget.get_active(): self.setRequirePasswordAfter(True) else: self.setRequirePasswordAfter(False) def setRequirePasswordAfter(self, boolean=True): self.spbRequirePasswordAfter.set_sensitive(boolean) self.spbWarnBeforePasswordExpires.set_sensitive(boolean) self.spbDisableAccountWhenPasswordExpires.set_sensitive(boolean) if not boolean: self.spbRequirePasswordAfter.set_value(0) self.spbWarnBeforePasswordExpires.set_value(0) self.spbDisableAccountWhenPasswordExpires.set_value(0) def on_chkEnforceMinimumPasswordAge_toggled(self, widget): if widget.get_active(): self.setEnforceMinimumPasswordAge(True) else: self.setEnforceMinimumPasswordAge(False) def setEnforceMinimumPasswordAge(self, boolean=True): self.spbEnforceMinimumPasswordAge.set_sensitive(boolean) if not boolean: self.spbEnforceMinimumPasswordAge.set_value(0) def on_txtLoginName_changed(self, widget): self.updateNewLogin() def on_btnSaveUser_clicked(self, widget): errMsgs = [] changed = False name = self.txtLoginName.get_text().strip() if name != "": userExists = self.usr.doesUserExist(name) realName = self.txtRealName.get_text().strip() if realName != "": if self.user['user'].pw_gecos == realName: realName = "" else: print(">>> realName changed") changed = True prGroup = self.cmbHandlerPrimaryGroup.getValue() if prGroup != "": if self.user['prgrp'] == prGroup: prGroup = "" else: print(">>> prGroup changed") changed = True elif not userExists: errMsgs.append(_("You need to provide a primary group for a new user")) home = self.txtHomeDirectory.get_text().strip() facePath = "" if home != "": if exists(self.tempFace): facePath = join(home, ".face") if self.user['user'].pw_dir == home: home = "" else: print(">>> home changed") changed = True groups = self.tvHandlerUserGroups.getToggledValues() if functions.areListsEqual(groups, self.user['groups']): groups = [] else: print(">>> groups changed") changed = True password = self.txtPassword.get_text().strip() if password != "": encPwd = self.usr.encryptPassword(password) if self.user['pwd'].sp_pwd == encPwd: password = "" else: print(">>> password changed") changed = True elif not userExists: errMsgs.append(_("You need to provide a password for a new user")) else: errMsgs.append(_("You need to provide a name for a new user")) shell = self.cmbHandlerShells.getValue() # TODO #if self.radValidUntilDate.get_active(): #vuDay = self.spbValidUntilDay.get_value_as_int() #vuMonth = self.cmbValidUntilMonth.get_active() + 1 #vuYear = self.spbValidUntilYear.get_value_as_int() #(datetime(vuYear, vuMonth, vuDay, 0, 0, 0) - datetime.now()).days #manageUser(self, user, primary_group="", group_list=[], shell="", home_dir="", full_name="", password="", expire_date="", inactive_days=""): title = _("Save user settings") if errMsgs: msg = "\n".join(errMsgs) self.showError(title, msg, self.windowUser) elif changed or facePath != "": err = 0 if changed: err = self.usr.manageUser(user=name, full_name=realName, primary_group=prGroup, home_dir=home, group_list=groups, shell=shell, password=password) if err == 0: if exists(self.tempFace): move(self.tempFace, facePath) self.showInfo(title, _("User saved: %(user)s") % {"user": name}, self.windowUser) self.refreshData() else: # TODO pass if exists(self.tempFace): os.remove(self.tempFace) self.windowUser.hide() else: self.showInfo(title, _("Nothing was changed on user: %(user)s") % {"user": name}, self.windowUser) self.windowUser.hide() if exists(self.tempFace): os.remove(self.tempFace) def on_cmbValidUntilMonth_changed(self, widget): monthDays = functions.getDaysInMonth(widget.get_active() + 1) adj = Gtk.Adjustment(value=1, lower=1, upper=monthDays, step_incr=1, page_incr=0, page_size=0) self.spbValidUntilDay.set_adjustment(adj) self.spbValidUntilDay.set_value(1) def updateNewLogin(self): txt = self.txtLoginName.get_text() self.txtRealName.set_text(txt) self.txtHomeDirectory.set_text("/home/%s" % txt) self.cmbHandlerPrimaryGroup.setValue(txt) def getUsers(self): self.users = [] self.usersInfo = self.usr.getAllUsersInfoDict(self.chkShowSystemUsers.get_active()) for ui in self.usersInfo: self.users.append([ui['face'], ui['user'].pw_name]) def showUserData(self): # Show user groups in tvUserGroupsMain self.selectedUser = self.tvHandlerUsersMain.getSelectedValue(1) print((">>> selectedUser = %s" % self.selectedUser)) for ui in self.usersInfo: if ui['user'].pw_name == self.selectedUser: self.user = ui break self.tvHandlerUserGroupsMain.fillTreeview(contentList=self.user['groups'], columnTypesList=['str']) self.userFace = self.usr.getUserFacePixbuf(self.user['user'].pw_name, None, 32) def getUserGroupsComplete(self, userGroups=None): ugc = [] for group in self.groups: if group != self.user['prgrp']: isUg = False if userGroups is not None: for ug in userGroups: if ug == group: isUg = True break ugc.append([isUg, group]) return ugc def on_btnCancelUser_clicked(self, widget): # Close add share window without saving if exists(self.tempFace): os.remove(self.tempFace) self.windowUser.hide() def on_ebFace_button_release_event(self, widget, data=None): imagePath = SelectImageDialog(_('Select user image'), self.user['user'].pw_dir, self.windowUser).show() if imagePath is not None: ih = ImageHandler(imagePath) ih.makeFaceImage(self.tempFace) if exists(self.tempFace): self.imgFace.set_from_pixbuf(ih.pixbuf) def on_usermanagerUserWindow_delete_event(self, widget, data=None): if exists(self.tempFace): os.remove(self.tempFace) self.windowUser.hide() return True def fillTreeViewUsers(self): self.tvHandlerUsersMain.fillTreeview(contentList=self.users, columnTypesList=['GdkPixbuf.Pixbuf', 'str'], fixedImgHeight=48) def on_ebFace_enter_notify_event(self, widget, data=None): self.windowUser.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) def on_ebFace_leave_notify_event(self, widget, data=None): self.windowUser.get_window().set_cursor(None) # =============================================== # Group functions # =============================================== def on_tvGroupsMain_cursor_changed(self, widget, event=None): self.selectedGroup = self.tvHandlerGroupsMain.getSelectedValue() self.selectedGroupAccounts = self.usr.getGroupAccounts(self.selectedGroup) print((">>> selectedGroup 1 = %s" % str(self.selectedGroup))) print((">>> selectedGroupAccounts 1 = %s" % str(self.selectedGroupAccounts))) self.tvHandlerGroupAccounts.fillTreeview(self.selectedGroupAccounts, ['str']) def on_tvGroupsMain_row_activated(self, widget, path, column): self.on_btnGroupEdit_clicked(None) def on_btnGroupAdd_clicked(self, widget): self.selectedGroup = None self.selectedGroupAccounts = None print((">>> selectedGroup 2 = %s" % str(self.selectedGroup))) print((">>> selectedGroupAccounts 2 = %s" % str(self.selectedGroupAccounts))) self.txtGroupName.set_editable(True) self.txtGroupName.set_can_focus(True) self.txtGroupName.set_text("") self.txtGroupID.set_text(str(self.usr.getNewGroupID())) self.fillTreeViewAccounts(self.users) self.windowGroup.show() def on_btnGroupEdit_clicked(self, widget): if self.selectedGroup is not None: availableAccounts = [] groupAccounts = [] for acc in self.users: if acc[1] in self.selectedGroupAccounts: groupAccounts.append(acc) else: availableAccounts.append(acc) self.fillTreeViewAccounts(availableAccounts, groupAccounts) self.txtGroupName.set_text(self.selectedGroup) self.txtGroupName.set_editable(False) self.txtGroupName.set_can_focus(False) self.txtGroupID.set_text(str(self.usr.getGroupID(self.selectedGroup))) self.tvAccounts.grab_focus() self.windowGroup.show() def on_btnGroupRemove_clicked(self, widget): # Remove group if self.selectedGroup is not None: title = _("Remove group") if self.selectedGroup != self.loggedinUserPrimaryGroup: qd = QuestionDialog(title, _("Are you sure you want to remove the following group:\n\n'%(group)s'") % { "group": self.selectedGroup }, self.windowGroup) answer = qd.show() if answer: ret = self.usr.deleteGroup(self.selectedGroup) if ret == "": self.showInfo(title, _("Group successfully removed: %(group)s") % {"group": self.selectedGroup}, self.windowGroup) self.refreshData() else: retMsg = "\n\n%s" % ret self.showError(title, _("Could not remove group: %(group)s %(retmsg)s") % {"group": self.selectedGroup, "retmsg": retMsg}, self.windowGroup) else: self.showError(title, _("You cannot remove the currently logged in user's primary group"), self.windowGroup) def on_btnAddAccount_clicked(self, widget): rows = self.tvHandlerAccounts.getSelectedRows() for row in rows: self.tvHandlerAccounts.delRow(row[0]) self.tvHandlerSelectedAccounts.addRow(row[1]) def on_btnRemoveAccount_clicked(self, widget): # TODO: check if you want to remove an account from its own primary group rows = self.tvHandlerSelectedAccounts.getSelectedRows() for row in rows: acc = row[1][1] pg = self.usr.getUserPrimaryGroupName(acc) if pg != self.selectedGroup: self.tvHandlerSelectedAccounts.delRow(row[0]) self.tvHandlerAccounts.addRow(row[1]) else: self.showError(_("Remove account"), _("You cannot remove an account from its own primary group"), self.windowGroup) def on_btnOkGroup_clicked(self, widget): group = self.txtGroupName.get_text() if group != "": newSelAccs = self.tvHandlerSelectedAccounts.getColumnValues(1) if self.selectedGroupAccounts is not None: # New accounts in group for a in newSelAccs: if a not in self.selectedGroupAccounts: # Add group to account self.usr.addGroupToAccount(a, group) # Removed accounts in group for a in self.selectedGroupAccounts: if a not in newSelAccs: # Remove group from account self.usr.removeGroupFromAccount(a, group) else: # Create new group self.usr.createGroup(group) # Add group to each selected account for a in newSelAccs: self.usr.addGroupToAccount(a, group) # Close the user window self.windowGroup.hide() self.refreshData() def on_btnCancelGroup_clicked(self, widget): self.windowGroup.hide() def on_usermanagerGroupWindow_delete_event(self, widget, data=None): self.windowGroup.hide() return True def on_tvAccounts_row_activated(self, widget, path, column): self.on_btnAddAccount_clicked(None) def on_tvSelectedAccounts_row_activated(self, widget, path, column): self.on_btnRemoveAccount_clicked(None) def fillTreeViewAccounts(self, availableAccounts, selectedAccounts=None): if (availableAccounts is None or not availableAccounts) and selectedAccounts: # Dirty hack to prepare the available accounts treeview self.tvHandlerAccounts.fillTreeview(contentList=selectedAccounts, columnTypesList=['GdkPixbuf.Pixbuf', 'str'], fixedImgHeight=24) self.tvHandlerAccounts.clearTreeView() else: self.tvHandlerAccounts.fillTreeview(contentList=availableAccounts, columnTypesList=['GdkPixbuf.Pixbuf', 'str'], fixedImgHeight=24) if (selectedAccounts is None or not selectedAccounts) and availableAccounts: # Dirty hack to prepare the selected accounts treeview self.tvHandlerSelectedAccounts.fillTreeview(contentList=availableAccounts, columnTypesList=['GdkPixbuf.Pixbuf', 'str'], fixedImgHeight=24) self.tvHandlerSelectedAccounts.clearTreeView() else: self.tvHandlerSelectedAccounts.fillTreeview(contentList=selectedAccounts, columnTypesList=['GdkPixbuf.Pixbuf', 'str'], fixedImgHeight=24) def fillTreeViewGroups(self): self.tvHandlerGroupsMain.fillTreeview(contentList=self.groups, columnTypesList=['str']) self.on_tvGroupsMain_cursor_changed(None) # =============================================== # General functions # =============================================== def refreshData(self): self.getUsers() self.groups = self.usr.getGroups() self.fillTreeViewUsers() self.fillTreeViewGroups() self.showUserData() def showInfo(self, title, message, parent): MessageDialogSave(title, message, Gtk.MessageType.INFO, parent).show() def showError(self, title, message, parent): MessageDialogSave(title, message, Gtk.MessageType.ERROR, parent).show() def filterText(self, widget): def filter(entry, *args): text = entry.get_text().strip().lower() entry.set_text(''.join([i for i in text if i in '0123456789abcdefghijklmnopqrstuvwxyz-._'])) widget.connect('changed', filter) # Close the gui def on_usermanagerWindow_destroy(self, widget): # Close the app Gtk.main_quit()
class SambaShare(object): def __init__(self): self.scriptDir = abspath(dirname(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file( join(self.scriptDir, '../../share/sambashare/sambashare.glade')) go = self.builder.get_object self.window = go('sambashareWindow') self.windowAdd = go('sambashareWindowAdd') self.lblTitle = go('lblTitle') self.tvShares = go('tvShares') self.btnAdd = go('btnAdd') self.btnRemove = go('btnRemove') self.txtShareDetails = go('txtShareDetails') self.lblName = go('lblName') self.lblPath = go('lblPath') self.lblComment = go('lblComment') self.lblPublic = go('lblPublic') self.lblReadOnly = go('lblReadOnly') self.txtName = go('txtName') self.txtPath = go('txtPath') self.txtComment = go('txtComment') self.chkPublic = go('chkPublic') self.chkReadOnly = go('chkReadOnly') self.btnOk = go('btnOk') self.btnCancel = go('btnCancel') # Translations self.window.set_title(_("Samba share")) self.windowAdd.set_title(_("Create samba share")) self.lblTitle.set_text(self.window.get_title()) self.lblName.set_text(_("Name")) self.lblPath.set_text(_("Path")) self.lblComment.set_text(_("Comment")) self.lblReadOnly.set_text(_("Read only")) self.lblPublic.set_text(_("Public")) # Init self.ec = ExecCmd() self.us = UserShare() self.shareName = None self.sharePath = None self.startAddNow = False # Fill treeview with shares self.tvHandler = TreeViewHandler(self.tvShares) self.refreshShares() # Command arguments args = sys.argv[1:] for arg in args: if "/" in arg: self.sharePath = arg self.startAddNow = True else: self.shareName = arg # Connect the signals and show the window self.builder.connect_signals(self) self.window.show_all() if self.startAddNow: self.on_btnAdd_clicked(None) # =============================================== # Menu section functions # =============================================== def on_tvShares_cursor_changed(self, widget, event=None): # Show share details self.setDetailText() def on_btnAdd_clicked(self, widget): # Show add share window if self.sharePath is None: self.sharePath = os.getcwd() self.shareName = basename(self.sharePath) if self.sharePath is None: self.sharePath = "" if self.shareName is None: self.shareName = "" self.txtName.set_text(self.shareName) self.txtPath.set_text(self.sharePath) self.windowAdd.show_all() def on_btnBrowse_clicked(self, widget): directory = SelectDirectoryDialog(_('Select directory to share'), self.txtPath.get_text(), self.window).show() if directory is not None: self.sharePath = directory self.txtPath.set_text(self.sharePath) def on_btnRemove_clicked(self, widget): # TODO: remove selected share title = _("Remove share") qd = QuestionDialog( title, _("Are you sure you want to remove the following share:\n\n'%(share)s'" ) % {"share": self.shareName}, self.window) answer = qd.show() if answer: ret = self.us.removeShare(self.shareName) self.showUserFeedback(ret, title, "remove", self.window) self.refreshShares() def on_btnOk_clicked(self, widget): # Create network share, and close add share window title = _("Create share") self.shareName = self.txtName.get_text() comment = self.txtComment.get_text() public = self.chkPublic.get_active() readonly = self.chkReadOnly.get_active() ret = self.us.createShare(self.sharePath, self.shareName, comment, public, readonly) closeWin = self.showUserFeedback(ret, title, "create", self.windowAdd) if closeWin: self.windowAdd.hide() self.refreshShares() def on_txtPath_changed(self, widget): self.sharePath = self.txtPath.get_text() name = basename(self.sharePath) if name == "": name = basename(dirname(self.sharePath)) self.txtName.set_text(name) def on_txtName_changed(self, widget): name = self.txtName.get_text() if name in self.us.systemNames: name += "_" self.txtName.set_text(name) self.shareName = name def showUserFeedback(self, returnList, title, action, parent): msg = "" closeWin = False for line in returnList: msg += "%s\n" % line if msg != "": MessageDialogSafe(title, msg, Gtk.MessageType.ERROR, parent).show() else: shareExists = self.us.doesShareExist(self.shareName) if action == "removed" and shareExists: msg = _("Could not remove share: '%(share)s'") % { "share": self.shareName } elif action == "created" and not shareExists: msg = _("Could not create share: '%(share)s'") % { "share": self.shareName } else: msg = _( "Share successfully %(action)s:\n\n'%(share)s' on %(path)s" ) % { "action": action, "share": self.shareName, "path": self.sharePath } closeWin = True MessageDialogSafe(title, msg, Gtk.MessageType.INFO, parent).show() return closeWin def refreshShares(self): self.shareName = None self.sharePath = None self.shares = self.us.getShares() self.shareDetail = self.us.getShares(True, True) self.fillTreeView() self.setDetailText() print("Refresh done") def on_btnCancel_clicked(self, widget): # Close add share window without saving self.windowAdd.hide() def on_sambashareWindowAdd_delete_event(self, widget, data=None): self.windowAdd.hide() return True def fillTreeView(self): # Very dirty hack: add and remove a dummy row to the treeview when treeview is empty # GtkTreeView has a problem refreshing when there's no data present if self.tvHandler.getRowCount() == 0: self.tvHandler.fillTreeview('-', ['str']) self.tvHandler.clearTreeView() self.tvHandler.fillTreeview(self.shares, ['str']) def setDetailText(self): buf = Gtk.TextBuffer() txt = "" try: self.shareName = self.tvHandler.getSelectedValue() if self.shareName is not None: if self.shareDetail[self.shareName]: txt = "Name:\t\t%s\n" % self.shareName for line in self.shareDetail[self.shareName]: line = line.strip() if line != "" and line != "[%s]" % self.shareName: if line.startswith("path="): self.sharePath = line.replace("path=", "") txt += "Path:\t\t%s\n" % self.sharePath elif line.startswith("comment="): txt += "Comment:\t%s\n" % line.replace( "comment=", "") elif ':R' in line: txt += "Share:\t\tRead permission" elif ':F' in line: txt += "Share:\t\tRead/write permission" elif line == "guest_ok=y": txt += ", public\n" elif line == "guest_ok=n": txt += ", private\n" else: self.sharePath = None except: # Best effort pass buf.set_text(txt) self.txtShareDetails.set_buffer(buf) # Close the gui def on_sambashareWindow_destroy(self, widget): # Close the app Gtk.main_quit()
def __init__(self): self.scriptDir = abspath(dirname(__file__)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.scriptDir, '../../share/usermanager/usermanager.glade')) # Main window objects go = self.builder.get_object self.window = go('usermanagerWindow') self.tvUsersMain = go('tvUsersMain') self.tvUserGroupsMain = go('tvUserGroupsMain') self.chkShowSystemUsers = go('chkShowSystemUsers') self.btnUserEdit = go('btnUserEdit') self.btnUserRemove = go('btnUserRemove') # User window objects self.windowUser = go('usermanagerUserWindow') self.nbUser = go('nbUser') self.txtLoginName = go('txtLoginName') self.txtRealName = go('txtRealName') self.txtUserID = go('txtUserID') self.txtHomeDirectory = go('txtHomeDirectory') self.cmbShells = go('cmbShells') self.cmbPrimaryGroup = go('cmbPrimaryGroup') self.cmbPrimaryGroupEntry = go('cmbPrimaryGroupEntry') self.tvUserGroups = go('tvUserGroups') self.ebFace = go('ebFace') self.imgFace = go('imgFace') self.lblUserID = go('lblUserID') self.txtPassword = go('txtPassword') self.txtLastChanged = go('txtLastChanged') self.cmbValidUntilMonth = go('cmbValidUntilMonth') self.spbValidUntilDay = go('spbValidUntilDay') self.spbValidUntilYear = go('spbValidUntilYear') self.radEnabled = go('radEnabled') self.radDisabled = go('radDisabled') self.radValidUntilAlways = go('radValidUntilAlways') self.radValidUntilDate = go('radValidUntilDate') self.spbRequirePasswordAfter = go('spbRequirePasswordAfter') self.spbWarnBeforePasswordExpires = go('spbWarnBeforePasswordExpires') self.spbDisableAccountWhenPasswordExpires = go('spbDisableAccountWhenPasswordExpires') self.spbEnforceMinimumPasswordAge = go('spbEnforceMinimumPasswordAge') self.chkRequirePasswordAfter = go('chkRequirePasswordAfter') self.chkEnforceMinimumPasswordAge = go('chkEnforceMinimumPasswordAge') self.tvGroupsMain = go('tvGroupsMain') # Group window objects self.windowGroup = go('usermanagerGroupWindow') self.txtGroupName = go('txtGroupName') self.txtGroupID = go('txtGroupID') self.tvAccounts = go('tvAccounts') self.tvSelectedAccounts = go('tvSelectedAccounts') self.tvGroupAccounts = go('tvGroupAccounts') # Main window translations self.window.set_title(_("User manager")) self.chkShowSystemUsers.set_label(_("Show system users")) self.btnUserEdit.set_label(_("Edit")) self.btnUserRemove.set_label(_("Remove")) go('btnUserAdd').set_label(_("Add")) go('lblUsersTab').set_text(_("Users")) go('lblGroupsTab').set_text(_("Groups")) go('lblUsersMain').set_text(go('lblUsersTab').get_text()) go('lblUserGroupsMain').set_text(_("User groups")) go('lblGroupsMain').set_text(go('lblGroupsTab').get_text()) go('lblGroupAccountsMain').set_text(_("Group accounts")) # User window translations self.windowUser.set_title(_("User settings")) go('lblUserDetails').set_text(_("Details")) go('lblStatus').set_text(_("Status")) go('lblLoginName').set_text(_("Login name")) go('lblRealName').set_text(_("Real name")) go('lblUserID').set_text(_("User ID")) go('lblPrimaryGroup').set_text(_("Primary group")) go('lblHomeDirectory').set_text(_("Home directory")) go('lblShell').set_text(_("Shell")) self.radEnabled.set_label(_("Enabled")) self.radDisabled.set_label(_("Disabled")) #go('lblPrivilegesAndGroups').set_text(_("Privileges and groups")) go('lblPrivilegesAndGroups').set_text(go('lblGroupsTab').get_text()) go('lblPrivileges').set_text(_("Privileges")) go('lblUserGroups').set_text(go('lblGroupsTab').get_text()) go('lblPasswordSecurity').set_text(_("Password")) go('lblPassword').set_text(go('lblPasswordSecurity').get_text()) go('lblLastChanged').set_text(_("Last changed")) go('lblValidUntil').set_text(_("Valid until")) self.radValidUntilAlways.set_label(_("Always")) go('lblPasswordAging').set_text(_("Password aging")) self.chkRequirePasswordAfter.set_label(_("Require password after")) go('lblWarnBeforePasswordExpires').set_text(_("Warn before password expires after")) go('lblDisableAccountWhenPasswordExpires').set_text(_("Disable account when password expires after")) self.chkEnforceMinimumPasswordAge.set_label(_("Enforce minimum password age")) go('lblDays1').set_text(_("days")) go('lblDays2').set_text(go('lblDays1').get_text()) go('lblDays3').set_text(go('lblDays1').get_text()) go('lblDays4').set_text(go('lblDays1').get_text()) go('btnSaveUser').set_label(_("Save")) go('btnCancelUser').set_label(_("Cancel")) # Group window translations self.windowGroup.set_title(_("Group settings")) go('lblGroupName').set_text(_("Group name")) go('lblGroupID').set_text(_("Group ID")) go('lblAccounts').set_text(_("Available accounts")) go('lblSelectedAccounts').set_text(_("Selected accounts")) go('btnOkGroup').set_label(go('btnSaveUser').get_label()) go('btnCancelGroup').set_label(go('btnCancelUser').get_label()) go('btnAddAccount').set_label(go('btnUserAdd').get_label()) go('btnRemoveAccount').set_label(self.btnUserRemove.get_label()) # Init self.ec = ExecCmd() self.usr = User() self.usersInfo = {} self.user = {} self.users = [] self.accounts = [] self.shells = self.usr.getShells() self.groups = None self.loggedinUser = self.usr.getLoggedinUser() self.loggedinUserPrimaryGroup = self.usr.getUserPrimaryGroupName(self.loggedinUser) self.selectedUser = None self.selectedGroup = None self.selectedGroupAccounts = None self.userFace = None self.radEnabled.set_active(True) self.radValidUntilAlways.set_active(True) self.setValidUntil(False) self.setRequirePasswordAfter(False) self.setEnforceMinimumPasswordAge(False) self.txtUserID.set_editable(False) self.txtUserID.set_can_focus(False) self.txtLastChanged.set_editable(False) self.txtLastChanged.set_can_focus(False) self.txtGroupID.set_editable(False) self.txtGroupID.set_can_focus(False) self.passwordChanged = False self.homeDirChanged = False self.tempFace = "/tmp/face.png" self.filterText(self.txtLoginName) self.filterText(self.txtGroupName) self.filterText(self.cmbPrimaryGroupEntry) # Treeviews self.tvHandlerUsersMain = TreeViewHandler(self.tvUsersMain) self.tvHandlerUserGroupsMain = TreeViewHandler(self.tvUserGroupsMain) self.tvHandlerUserGroups = TreeViewHandler(self.tvUserGroups) self.tvHandlerAccounts = TreeViewHandler(self.tvAccounts) self.tvHandlerSelectedAccounts = TreeViewHandler(self.tvSelectedAccounts) self.tvHandlerGroupsMain = TreeViewHandler(self.tvGroupsMain) self.tvHandlerGroupAccounts = TreeViewHandler(self.tvGroupAccounts) # Comboboxes self.cmbHandlerShells = ComboBoxHandler(self.cmbShells) self.cmbHandlerPrimaryGroup = ComboBoxHandler(self.cmbPrimaryGroup) self.cmbHandlerValidUntilMonth = ComboBoxHandler(self.cmbValidUntilMonth) # Get data self.refreshData() self.cmbHandlerShells.fillComboBox(self.shells) self.cmbHandlerValidUntilMonth.fillComboBox(functions.getMonthsList()) year = datetime.now().year adj = Gtk.Adjustment(value=year, lower=year, upper=year + 10, step_incr=1, page_incr=0, page_size=0) self.spbValidUntilYear.set_adjustment(adj) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show()
def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/trail/constructor') self.userAppDir = join(get_user_home_dir(), ".constructor") self.distroFile = join(self.userAppDir, "distros.list") # Create the user's application directory if it doesn't exist if not isdir(self.userAppDir): user_name = getUserLoginName() makedirs(self.userAppDir) old_distro_file = join(self.scriptDir, "distros.list") if exists(old_distro_file): move(old_distro_file, self.distroFile) system("chown -R %s:%s %s" % (user_name, user_name, self.userAppDir)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) # Add iso window translations self.lblIso.set_text(_("ISO")) go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.chkFromIso.set_active(True) self.toggleGuiElements(False) # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, getPackageVersion('constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show()
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()
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()
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 Constructor(object): def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/solydxk/constructor') self.userAppDir = join(get_user_home_dir(), ".constructor") self.distroFile = join(self.userAppDir, "distros.list") # Create the user's application directory if it doesn't exist if not isdir(self.userAppDir): user_name = getUserLoginName() makedirs(self.userAppDir) old_distro_file = join(self.scriptDir, "distros.list") if exists(old_distro_file): move(old_distro_file, self.distroFile) system("chown -R %s:%s %s" % (user_name, user_name, self.userAppDir)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.btnHelp = go('btnHelp') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("SolydXK Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) self.btnHelp.set_label("_{}".format(_("Help"))) # Add iso window translations self.windowAddDistro.set_title(_("Add Distribution")) self.lblIso.set_text(_("ISO")) go('lblFromIso').set_label("Create from ISO") go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.doneWav = join(self.shareDir, 'done.wav') self.htmlDir = join(self.shareDir, "html") self.help = join(self.get_language_dir(), "help.html") self.chkFromIso.set_active(True) self.toggleGuiElements(False) # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, getPackageVersion('solydxk-constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # =============================================== # Main Window Functions # =============================================== def on_btnAdd_clicked(self, widget): self.windowAddDistro.show() def on_btnRemove_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: qd = QuestionDialog(self.btnRemove.get_label(), _("Are you sure you want to remove the selected distribution from the list?\n" \ "(This will not remove the directory and its data)"), self.window) answer = qd.show() if answer: self.saveDistroFile(distroPath=path, addDistro=False) self.fillTreeViewDistros() def on_btnEdit_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: de = EditDistro(path) services = [] if exists(join(path, 'root/etc/apache2/apache2.conf')): services.append("apache2") if exists(join(path, 'root/etc/mysql/debian.cnf')): services.append("mysql") if services: msg = "If you need to update packages that depend on these services,\n" \ "you will need to manually start them:\n" for service in services: msg += "\nservice %s start" % service msg += "\n\nWhen done:\n" for service in services: msg += "\nservice %s stop" % service self.showInfo(_("Services detected"), msg, self.window) repaintGui() de.openTerminal() def on_btnUpgrade_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) upgraded = False for path in selected: upgraded = True rootPath = "%s/root" % path force = get_apt_force(rootPath) de = EditDistro(path) de.openTerminal("apt-get update") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 start") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql start") de.openTerminal("apt-get -y %s -o Dpkg::Options::=\"--force-confnew\" dist-upgrade" % force) if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 stop") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql stop") # Cleanup old kernel and headers script = "rmoldkernel.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Download offline packages print(">> Start downloading offline packages") self.download_offline_packages(path) if upgraded and exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Copy Grub locale files to ISO boot directory and configure grub.cfg grub_path = "%s/boot/boot/grub/" % path grubcfg_path = "%s/grub.cfg" % grub_path locale_path = "%s/root/boot/grub/locale" % path default_path = "%s/root/etc/default" % path locale = self.ec.run("grep -oP '(?<=LANG=).*?(?=\.)' %s/locale" % default_path)[0] if exists(locale_path) and \ exists(grubcfg_path) and \ locale: self.ec.run("cp -rf %s %s" % (locale_path, grub_path)) self.ec.run("sed -i 's/set lang=.*/set lang=%s/' %s" % (locale, grubcfg_path)) def download_offline_packages(self, path): rootPath = "%s/root" % path arch = getGuestEfiArchitecture(rootPath) de = EditDistro(path) script = "offline.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) offlineSource = join(rootPath, "offline") offlineTarget = join(rootPath, "../boot/offline") if exists(scriptSource): try: copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) # Run the script de.openTerminal("/bin/bash {} {}".format(script, arch)) # Remove script silent_remove(scriptTarget) # Move offline directory to boot directory if exists(offlineSource): print(("%s exists" % offlineSource)) if exists(offlineTarget): print((">> Remove %s" % offlineTarget)) silent_remove(offlineTarget) print((">> Move %s to %s" % (offlineSource, offlineTarget))) move(offlineSource, offlineTarget) else: print((">> Cannot find: %s" % offlineSource)) except Exception as detail: self.showError("Error: getting offline packages", detail, self.window) else: print((">> Cannot find: %s" % scriptSource)) def on_btnBuildIso_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) msg = "" for path in selected: self.toggleGuiElements(True) self.showOutput("Start building ISO in: %s" % path) repaintGui() # Start building the ISO in a thread t = BuildIso(path, self.queue) t.start() self.queue.join() # Thread is done # Get the data from the queue ret = self.queue.get() self.queue.task_done() if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: msg += "%s\n" % ret if msg != "": if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) self.showInfo("", msg, self.window) self.toggleGuiElements(False) def on_chkSelectAll_toggled(self, widget): self.tvHandlerDistros.treeviewToggleAll(toggleColNrList=[0], toggleValue=widget.get_active()) def on_tvDistros_row_activated(self, widget, path, column): self.tvHandlerDistros.treeviewToggleRows(toggleColNrList=[0]) def on_btnHelp_clicked(self, widget): system("open-as-user %s" % self.help) def on_btnOpenDir_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: system("open-as-user %s" % path) def fillTreeViewDistros(self, selectDistros=[]): contentList = [[_("Select"), _("Distribution"), _("Working directory")]] distros = self.getDistros() for distro in distros: select = False for selectDistro in selectDistros: if distro[0] == selectDistro: select = True contentList.append([select, distro[0], distro[1]]) self.tvHandlerDistros.fillTreeview(contentList=contentList, columnTypesList=['bool', 'str', 'str'], firstItemIsColName=True) def getDistros(self): distros = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: lines = f.readlines() for line in lines: line = line.strip().rstrip('/') print(line) if exists(line): dg = DistroGeneral(line) isoName = dg.description distros.append([isoName, line]) # Sort on iso name if distros: distros = sorted(distros, key=operator.itemgetter(0)) return distros # =============================================== # Add ISO Window Functions # =============================================== def on_btnIso_clicked(self, widget): fleFilter = Gtk.FileFilter() fleFilter.set_name("ISO") fleFilter.add_mime_type("application/x-cd-image") fleFilter.add_pattern("*.iso") startDir = None if exists(dirname(self.txtIso.get_text())): startDir = dirname(self.txtIso.get_text()) filePath = SelectFileDialog(title=_('Select SolydXK ISO'), start_directory=startDir, parent=self.window, gtkFileFilter=fleFilter).show() if filePath is not None: self.txtIso.set_text(filePath) def on_btnDir_clicked(self, widget): startDir = None if exists(self.txtDir.get_text()): startDir = self.txtDir.get_text() dirText = SelectDirectoryDialog(title=_('Select directory'), start_directory=startDir, parent=self.window).show() if dirText is not None: self.txtDir.set_text(dirText) def on_btnSave_clicked(self, widget): self.iso = "" if self.chkFromIso.get_active(): self.iso = self.txtIso.get_text() self.dir = self.txtDir.get_text() title = _("Save existing working directory") if self.iso != "": title = _("Unpack ISO and save") if not exists(self.dir): makedirs(self.dir) if not exists(self.dir): self.showError(title, _("Could not create directory %(dir)s: exiting" % {"dir": self.dir}), self.window) else: self.windowAddDistro.hide() if self.iso != "": if not exists(self.iso): self.showInfo(self.btnSave.get_label(), _("The path to the ISO file does not exist:\n{}".format(self.iso)), self.window) return if listdir(self.dir): qd = QuestionDialog(self.btnSave.get_label(), _("The destination directory is not empty.\n" "Are you sure you want to overwrite all data in {}?".format(self.dir)), self.window) answer = qd.show() if not answer: return self.showOutput("Start unpacking the ISO...") self.toggleGuiElements(True) t = IsoUnpack(self.mountDir, self.iso, self.dir, self.queue) t.start() self.queue.join() GObject.timeout_add(1000, self.checkThread, True) else: self.saveDistroFile(self.dir, True) self.fillTreeViewDistros() self.showOutput(_("Existing working directory added")) #self.toggleGuiElements(False) def on_btnCancel_clicked(self, widget): self.windowAddDistro.hide() def on_addDistroWindow_delete_event(self, widget, data=None): self.windowAddDistro.hide() return True def on_txtIso_changed(self, widget): path = self.txtIso.get_text() if exists(path): self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) if exists(self.txtDir.get_text()): self.btnSave.set_sensitive(True) else: self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) def on_txtDir_changed(self, widget): blnFromIso = self.chkFromIso.get_active() isoPath = self.txtIso.get_text() dirText = self.txtDir.get_text() self.btnSave.set_sensitive(False) if exists(dirText): if blnFromIso: if exists(isoPath): self.btnSave.set_sensitive(True) else: self.btnSave.set_sensitive(True) def on_chkFromIso_toggled(self, widget): if widget.get_active(): self.lblIso.set_visible(True) self.boxIso.set_visible(True) self.txtDir.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnSave.set_sensitive(False) self.lblDir.set_text(_("Unpack ISO to directory")) self.btnSave.set_label(_("Unpack & Save")) else: self.txtIso.set_text("") self.lblIso.set_visible(False) self.boxIso.set_visible(False) self.txtDir.set_sensitive(True) self.btnDir.set_sensitive(True) self.btnSave.set_sensitive(True) self.lblDir.set_text(_("Work directory")) self.btnSave.set_label(_("Save")) # =============================================== # General functions # =============================================== def showInfo(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.INFO, parent).show() def showError(self, title, message, parent=None): MessageDialogSafe(title, message, Gtk.MessageType.ERROR, parent).show() def showOutput(self, message): print(message) pushMessage(self.statusbar, message) def checkThread(self, addDistro=None): #print 'Thread count = ' + str(threading.active_count()) # As long there's a thread active, keep spinning if threading.active_count() > 1: return True # Thread is done # Get the data from the queuez ret = self.queue.get() self.queue.task_done() # Thread is done if addDistro is not None: self.saveDistroFile(self.dir, addDistro) self.fillTreeViewDistros(self.isoName) self.toggleGuiElements(False) if exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False) if ret is not None: self.showOutput(ret) if "error" in ret.lower(): self.showError("Error", ret, self.window) else: self.showInfo("", ret, self.window) return False def toggleGuiElements(self, startThread): if startThread: self.chkSelectAll.set_sensitive(False) self.tvDistros.set_sensitive(False) self.btnAdd.set_sensitive(False) self.btnBuildIso.set_sensitive(False) self.btnEdit.set_sensitive(False) self.btnRemove.set_sensitive(False) self.btnUpgrade.set_sensitive(False) self.btnLocalize.set_sensitive(False) self.btnDir.set_sensitive(False) self.btnHelp.set_sensitive(False) else: self.chkSelectAll.set_sensitive(True) self.tvDistros.set_sensitive(True) self.btnAdd.set_sensitive(True) self.btnBuildIso.set_sensitive(True) self.btnEdit.set_sensitive(True) self.btnRemove.set_sensitive(True) self.btnUpgrade.set_sensitive(True) self.btnLocalize.set_sensitive(True) self.btnDir.set_sensitive(True) self.btnHelp.set_sensitive(True) def saveDistroFile(self, distroPath, addDistro=True): newCont = [] dg = DistroGeneral(distroPath) self.isoName = dg.description cfg = [] if exists(self.distroFile): with open(self.distroFile, 'r') as f: cfg = f.readlines() for line in cfg: line = line.strip() if distroPath != line and exists(line): newCont.append(line) if addDistro: newCont.append(distroPath) with open(self.distroFile, 'w') as f: f.write('\n'.join(newCont)) self.iso = "" self.dir = "" # Close the gui def on_constructorWindow_destroy(self, widget): # Close the app Gtk.main_quit() # =============================================== # 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 = environ.get('LANG', 'US').split('.')[0] if lang == '': lang = 'en' return lang
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 UpdateManager(object): def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() self.user = self.umglobal.getLoginName() # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) print(("UM log = %s" % self.logFile)) self.log = Logger(self.logFile, maxSizeKB=5120) # Remove scripts self.deleteScripts(self.umglobal.localUpdVersion) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.apt = UmApt(self.umglobal) self.kernelVersion = self.umglobal.getKernelVersion() self.upgradables = [] self.upgradableUM = [] self.window = None # Handle arguments parser = argparse.ArgumentParser(description='SolydXK Update Manager') parser.add_argument('-q','--quick', action="store_true", help='Quick upgrade') parser.add_argument('-r','--reload', action="store_true", help='') args, extra = parser.parse_known_args() self.quickUpdate = False if args.quick and not self.umglobal.newUpd: self.quickUpdate = True if args.reload: pids = self.umglobal.getProcessPids("updatemanager.py") if len(pids) > 1: print(("updatemanager.py already running - kill pid {}".format(pids[0]))) os.system("kill {}".format(pids[0])) # Set some global translations self.aptErrorText = _("Apt error") self.upgradablePackagesText = _("The following packages will be upgraded:") self.newPackagesText = _("The following NEW packages will be installed:") self.removedPackagesText = _("The following packages will be REMOVED:") self.heldbackPackagesText = _("The following packages have been kept back:") self.downgradePackagesText = _("The following packages are going to be downgraded:") # Cleanup first for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.umglobal.shareDir, 'updatemanager.glade')) go = self.builder.get_object # Quick update if self.quickUpdate: # Refresh data self.refresh() self.umglobal.collectData() self.apt.createPackagesInfoList() self.apt.createPackageLists() self.fillTreeView() # Run upgrade nid = self.run_upgrade() if nid != "": self.on_command_done(None, 0, nid) sys.exit(2) # Make sure the files directory is set correctly self.checkFilesDir() # Main window objects self.window = go("windowMain") #self.window.set_icon_from_file(join(self.umglobal.iconsDir, self.umglobal.settings["icon-connected"])) self.tvPck = go("tvPck") self.swTerminal = go("swTerminal") self.statusbar = go("statusbar") self.btnInstall = go("btnInstall") self.btnRefresh = go("btnRefresh") self.btnPackages = go("btnPackages") self.btnOutput = go("btnOutput") self.btnInfo = go("btnInfo") self.btnPreferences = go("btnPreferences") self.nbMain = go("nbMain") self.swInfo = go("swInfo") self.btnMaintenance = go("btnMaintenance") self.lblMaintenance = go("lblMaintenance") self.tvMaintenance = go("tvMaintenance") self.btnMaintenanceExecute = go("btnMaintenanceExecute") self.chkMaintenanceSelectAll = go("chkMaintenanceSelectAll") self.radUnneeded = go("radUnneeded") self.radCleanCache = go("radCleanCache") self.radDowngradable = go("radDowngradable") self.radNotavailable = go("radNotavailable") self.radOldKernel = go("radOldKernel") self.lblMaintenanceHelp = go("lblMaintenanceHelp") # Translations self.window.set_title(_("SolydXK Update Manager")) self.btnInstall.set_label(_("Install")) self.btnRefresh.set_label(_("Refresh")) self.btnOutput.set_label(_("Output")) self.btnInfo.set_label(_("Information")) self.btnPreferences.set_label(_("Preferences")) self.btnMaintenance.set_label(_("Maintenance")) self.btnPackages.set_label(_("Packages")) self.uptodateText = self.umglobal.connectedText self.lblMaintenance.set_label(self.btnMaintenance.get_label()) self.btnMaintenanceExecute.set_label(_("Execute")) self.chkMaintenanceSelectAll.set_label(_("Select all")) self.radCleanCache.set_label(_("Clean up the apt cache")) self.radUnneeded.set_label(_("Remove unneeded packages")) self.radNotavailable.set_label(_("Remove packages not available\nin the repositories")) self.radOldKernel.set_label(_("Remove old kernels")) self.radDowngradable.set_label(_("Downgrade packages with\nonly lower versions available")) self.lblMaintenanceHelp.set_label(_("Make sure you create\n" "a system image before you\n" "continue (e.g. Clonezilla).")) # VTE Terminal self.terminal = VirtualTerminal(userInputAllowed=self.umglobal.settings["allow-terminal-user-input"]) self.swTerminal.add(self.terminal) self.terminal.set_vexpand(True) self.terminal.set_hexpand(True) self.terminal.connect('command-done', self.on_command_done) self.terminal.connect('line-added', self.on_line_added) palletList = ['#4A4A4A', '#BD1919', '#118011', '#CE6800', '#1919BC', '#8D138D', '#139494', '#A7A7A7'] self.terminal.setTerminalColors("#000000", "#FFFFFF", palletList) self.swTerminal.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#FFFFFF")) # Disable all buttons self.btnInfo.set_sensitive(False) self.btnPreferences.set_sensitive(False) self.btnOutput.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnPackages.set_sensitive(False) self.btnMaintenance.set_sensitive(False) # Hide tabs if needed for tab in self.umglobal.settings["hide-tabs"]: if tab == "packages": self.nbMain.get_nth_page(0).set_visible(False) self.btnPackages.set_visible(False) elif tab == "output": self.nbMain.get_nth_page(1).set_visible(False) self.btnOutput.set_visible(False) elif tab == "info": self.nbMain.get_nth_page(2).set_visible(False) self.btnInfo.set_visible(False) elif tab == "maintenance": self.nbMain.get_nth_page(3).set_visible(False) self.btnMaintenance.set_visible(False) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # Force the window to show while Gtk.events_pending(): Gtk.main_iteration() # Just show something that we're busy msg = _("Gathering information...") self.terminal.executeCommand('echo "%s"' % msg, 'init') self.showOutput() # Treeview handlers self.tvHandler = TreeViewHandler(self.tvPck) self.tvMaintenanceHandler = TreeViewHandler(self.tvMaintenance) # Version information ver = _("Version") pckVer = self.apt.getPackageVersion('updatemanager') versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } if self.umglobal.localUpdVersion != "2000.01.01": versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } self.pushMessage(versionInfo) # Log basic information self.log.write("==============================================", "UM.init", "debug") self.log.write("UM version = %s" % versionInfo, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") mirrorsList = join(self.umglobal.filesDir, basename(self.umglobal.settings["mirrors-list"])) if exists(mirrorsList): self.log.write("Mirrors list", "UM.init", "debug") with open(mirrorsList, 'r') as f: for line in f.readlines(): self.log.write(line, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") # Refresh apt cache self.refresh() # Initialize maintenance screen self.fillTreeViewMaintenance() # =============================================== # Main window functions # =============================================== def on_btnInstall_clicked(self, widget): self.run_upgrade() def run_upgrade(self): nid = "" aptHasErrors = self.apt.aptHasErrors() if aptHasErrors is not None: MessageDialog(self.aptErrorText, aptHasErrors) elif self.upgradables: if self.apt.upgradablePackages: self.log.write("=================== upgradable pacages ====================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.upgradablePackages), "UM.run_upgrade", "debug") if self.apt.removedPackages: self.log.write("==================== removed packages =====================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.removedPackages), "UM.run_upgrade", "debug") if self.apt.newPackages: self.log.write("======================= new packages =======================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.newPackages), "UM.run_upgrade", "debug") if self.apt.heldbackPackages: self.log.write("=================== kept back packages =====================", "UM.run_upgrade", "debug") self.log.write(self.createLogString(self.apt.heldbackPackages), "UM.run_upgrade", "debug") if not self.quickUpdate: self.showOutput() contMsg = _("Continue installation?") if self.upgradableUM: cmd = "%s install updatemanager" % self.umglobal.settings['apt-get-string'] cmd += "; %s install %s" % (self.umglobal.settings['apt-get-string'], " ".join(self.apt.getPackageDependencies('updatemanager'))) nid = 'uminstallum' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.on_btnInstall_clicked", "debug") else: msg = self.getDistUpgradeInfo() answer = True if msg != "": answer = self.showConfirmationDlg(contMsg, msg) if answer: cmd = "%s dist-upgrade" % self.umglobal.settings['apt-get-string'] #if self.umglobal.newUpd: pre = join(self.umglobal.filesDir, self.umglobal.settings['pre-upd'].replace("[VERSION]", self.umglobal.serverUpdVersion)) post = join(self.umglobal.filesDir, self.umglobal.settings['post-upd'].replace("[VERSION]", self.umglobal.serverUpdVersion)) if exists(pre): cmd = "/bin/bash %(pre)s; %(cmd)s" % { "pre": pre, "cmd": cmd } if exists(post): cmd = "%(cmd)s; /bin/bash %(post)s" % { "cmd": cmd, "post": post } nid = 'umupd' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.on_btnInstall_clicked", "debug") else: if not self.quickUpdate: MessageDialog(self.btnInstall.get_label(), self.uptodateText) return nid def on_btnRefresh_clicked(self, widget): self.refresh() def on_btnPackages_clicked(self, widget): self.showPackages() def on_btnOutput_clicked(self, widget): self.showOutput() def on_btnInfo_clicked(self, widget): self.showInfo() def on_btnPreferences_clicked(self, widget): # Run preferences in its own thread pref_thread = threading.Thread(target=self.openPreferences) pref_thread.setDaemon(True) pref_thread.start() def openPreferences(self): os.system("updatemanager -p") def on_btnMaintenance_clicked(self, widget): self.showMaintenance() def on_radCleanCache_toggled(self, widget): if widget.get_active(): self.fillTreeViewMaintenance() def on_radUnneeded_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % (_("You might need to run this several times."), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radNotavailable_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % (_("Removing not available packages may break your system!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radOldKernel_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % (_("Once removed you will not be able to boot these kernels!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_radDowngradable_toggled(self, widget): if widget.get_active(): message = "%s\n\n%s" % (_("Downgrading packages may break your system!"), self.lblMaintenanceHelp.get_label().replace("\n", " ")) WarningDialog(self.btnMaintenance.get_label(), message) self.fillTreeViewMaintenance() def on_btnMaintenanceExecute_clicked(self, widget): self.executeMaintenance() def on_chkMaintenanceSelectAll_toggled(self, widget): self.tvMaintenanceHandler.treeviewToggleAll(toggleColNrList=[0], toggleValue=widget.get_active()) # =============================================== # Maintenance functions # =============================================== def enableMaintenance(self, enable=True): self.btnMaintenanceExecute.set_sensitive(enable) self.radUnneeded.set_sensitive(enable) self.radCleanCache.set_sensitive(enable) self.radDowngradable.set_sensitive(enable) self.radOldKernel.set_sensitive(enable) self.radNotavailable.set_sensitive(enable) self.chkMaintenanceSelectAll.set_sensitive(enable) if enable: self.chkMaintenanceSelectAll.set_active(False) def fillTreeViewMaintenance(self): blnCleanCache = self.radCleanCache.get_active() blnUnneeded = self.radUnneeded.get_active() blnDowngradable = self.radDowngradable.get_active() blnNotavailable = self.radNotavailable.get_active() blnOldKernels = self.radOldKernel.get_active() self.enableMaintenance(False) columnTypesList = ['bool', 'str', 'str', 'str'] packages = [["", _("Package"), _("Installed"), _("Available")]] # Clear the treeview first self.tvMaintenanceHandler.fillTreeview(packages, columnTypesList, 0, 400, True) msg = "" if blnCleanCache: msg = _("Hit the Execute button to clean the cache.") columnTypesList = ['str'] packages.append([msg]) elif blnUnneeded: msg = self.radUnneeded.get_label() self.apt.createPackageLists("apt-get autoremove") for pck in self.apt.removedPackages: packages.append([False, pck[0], pck[1], pck[2]]) self.apt.createPackageLists() # Add orphaned files self.apt.fillOrphanedPackages() for pck in self.apt.orphanedPackages: packages.append([False, pck[0], pck[1], pck[2]]) elif blnNotavailable: msg = self.radNotavailable.get_label() self.apt.fillNotAvailablePackages() for pck in self.apt.notavailablePackages: if pck[0][0:6] != "linux-": packages.append([False, pck[0], pck[1], ""]) elif blnOldKernels: msg = self.radOldKernel.get_label() self.apt.fillKernelPackages() for pck in self.apt.kernelPackages: if "headers-486" not in pck[0] \ and "headers-586" not in pck[0] \ and "headers-686" not in pck[0] \ and "headers-amd64" not in pck[0] \ and "image-486" not in pck[0] \ and "image-586" not in pck[0] \ and "image-686" not in pck[0] \ and "image-amd64" not in pck[0]: checkVersion = self.kernelVersion if "kbuild" in pck[0]: indMinus = self.kernelVersion.index("-") indZero = self.kernelVersion.index("0") if indZero > 0 and indZero < indMinus: ind = indZero - 1 else: ind = indMinus if ind > 0: checkVersion = self.kernelVersion[0:ind] if checkVersion not in pck[0]: packages.append([False, pck[0], pck[1], ""]) elif blnDowngradable: msg = self.radDowngradable.get_label() self.apt.fillDowngradablePackages() for pck in self.apt.downgradablePackages: packages.append([False, pck[0], pck[1], pck[2]]) if len(packages) > 1: self.tvMaintenanceHandler.fillTreeview(packages, columnTypesList, 0, 400, True) else: if not blnCleanCache: msg = _("\"%s\"\n did not return any results.") % msg MessageDialog(self.btnMaintenance.get_label(), msg) self.enableMaintenance(True) def executeMaintenance(self): blnCleanCache = self.radCleanCache.get_active() blnDowngradable = self.radDowngradable.get_active() blnNotNeeded = self.radUnneeded.get_active() downgradeString = "" deleteString = "" updateGrub = False cmd = "" self.enableMaintenance(False) if blnCleanCache: safe = False msg = _("Do you want to completely clean the apt cache?\n\n" "When No, only unavailable installation packages are removed.") answer = QuestionDialog(self.radCleanCache.get_label(), msg) if answer: safe = True self.apt.cleanCache(safe) msg = _("Apt cache has been cleaned.") MessageDialog(self.radCleanCache.get_label(), msg) else: # Get user selected packages model = self.tvMaintenance.get_model() itr = model.get_iter_first() while itr is not None: sel = model.get_value(itr, 0) if sel: pck = model.get_value(itr, 1) avVer = model.get_value(itr, 3) if blnDowngradable: downgradeString += " %(pck)s=%(avVer)s" % {"pck": pck, "avVer": avVer} else: deleteString += " %s" % pck if "linux-image" in pck: updateGrub = True itr = model.iter_next(itr) if downgradeString != "": cmd = "%s install %s" % (self.umglobal.settings['apt-get-string'], downgradeString) elif deleteString != "": cmd = "%s purge %s" % (self.umglobal.settings['apt-get-string'], deleteString) if cmd != "": self.apt.createPackageLists(cmd) msg = self.getDistUpgradeInfo() answer = True if msg != "": contMsg = _("Execute maintenance changes?") answer = self.showConfirmationDlg(contMsg, msg) if answer: if updateGrub: cmd += "; update-grub" if blnNotNeeded: cmd += "; %s purge $(COLUMNS=132 dpkg -l | grep ^rc | awk '{ print $2 }')" % self.umglobal.settings['apt-get-string'] self.showOutput() nid = 'ummaintenance' self.prepForCommand(nid) self.terminal.executeCommand(cmd, nid) self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.executeMaintenance", "debug") self.enableMaintenance(True) # =============================================== # General functions # =============================================== def prepForCommand(self, nid): os.system("touch %s" % self.umglobal.umfiles[nid]) if not self.quickUpdate: self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnMaintenance.set_sensitive(False) def on_line_added(self, terminal, line): if line.strip()[0:2].upper() == "E:": self.log.write(line, "UM.on_line_added", "error") else: self.log.write(line, "UM.on_line_added", "info") def on_command_done(self, terminal, pid, nid): if nid != "init": self.log.write("Command finished (pid=%s, nid=%s)" % (pid, nid), "UM.on_command_done", "info") if nid == "uminstallum": # Reload UM self.log.write("Updating UM: kill process of updatemanagerpref.py", "UM.on_command_done", "debug") self.umglobal.killScriptProcess("updatemanagerpref.py") # Reload tray as user self.log.write("Updating UM: kill process of updatemanagertray.py", "UM.on_command_done", "debug") self.umglobal.killScriptProcess("updatemanagertray.py") cmd = "sudo -u {} updatemanager -t -r".format(self.user) os.system(cmd) self.log.write("UM updated: reload tray as user {}".format(self.user), "UM.on_command_done", "debug") # Reload UM window cmd = join(self.umglobal.scriptDir, "updatemanager.py") if self.quickUpdate: cmd = join(self.umglobal.scriptDir, "updatemanager.py -q") self.umglobal.reloadWindow(cmd, self.user) self.log.write("UM updated: reload {0} as user {1}".format(cmd, self.user), "UM.on_command_done", "debug") elif nid == "umrefresh": # Build installed packages info list self.apt.createPackagesInfoList() # Run post update when needed self.postUpdate() elif nid == "ummaintenance": self.enableMaintenance(True) self.fillTreeViewMaintenance() self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.showMaintenance() elif nid == 'umupd': # Save update version in hist file self.umglobal.saveHistVersion("upd", self.umglobal.serverUpdVersion) self.log.write("Save history upd=%s" % self.umglobal.serverUpdVersion, "UM.on_command_done", "debug") self.deleteScripts() # Refresh data after install or update self.umglobal.collectData() self.apt.createPackageLists() self.fillTreeView() # Enable the buttons and load the info page self.log.write("Re-initiate window after terminal command: %s" % str(not self.quickUpdate), "UM.on_command_done", "debug") if not self.quickUpdate: self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.btnInfo.set_sensitive(True) self.loadInfo() if self.umglobal.newUpd: self.showInfo() else: # This throws a lock file error in Plasma5 #aptHasErrors = self.apt.aptHasErrors() #if aptHasErrors is not None: #MessageDialog(self.aptErrorText, aptHasErrors) #el if self.upgradables: self.showPackages() else: self.showInfo() MessageDialog(self.btnInfo.get_label(), self.uptodateText) self.log.write("Re-initiate window complete", "UM.on_command_done", "debug") # Cleanup name file(s) for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) def createLogString(self, packagesList): lst = [] for data in packagesList: lst.append(data[0]) return ' '.join(lst) def refresh(self): # Refresh server info print((self.umglobal.hasInternet)) self.umglobal.getServerInfo() print((self.umglobal.hasInternet)) # Check of programs locking apt prog = self.apt.getAptCacheLockedProgram(self.umglobal.settings["apt-packages"]) if prog is not None: msg = _("Another program is locking the apt cache\n\n" "Please, close the program before refreshing:\n" "* %s" % prog) MessageDialog(self.btnRefresh.get_label(), msg) self.log.write("%s is locking the apt cache" % prog, "UM.refresh", "warning") elif self.umglobal.hasInternet: if not self.quickUpdate: # Update the apt cache self.btnPreferences.set_sensitive(True) self.btnOutput.set_sensitive(True) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnMaintenance.set_sensitive(False) self.btnPackages.set_sensitive(True) self.showOutput() cmd = "dpkg --configure -a; %s -f install; apt-get update" % self.umglobal.settings['apt-get-string'] nid = 'umrefresh' self.prepForCommand(nid) if self.quickUpdate: self.ec.run(cmd) else: self.terminal.executeCommand(cmd, nid) self.apt.initAptShowVersions() self.log.write("Execute command: %s (%s)" % (cmd, nid), "UM.refresh", "debug") else: if not self.quickUpdate: # No internet connection self.btnInstall.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnPackages.set_sensitive(True) self.btnMaintenance.set_sensitive(True) self.btnInfo.set_sensitive(True) self.btnOutput.set_sensitive(True) self.btnPreferences.set_sensitive(True) self.loadInfo() self.showInfo() def postUpdate(self): # Check for changed version information if self.umglobal.newUpd and self.umglobal.serverUpdVersion is not None: self.getScripts([self.umglobal.settings['pre-upd'].replace("[VERSION]", self.umglobal.serverUpdVersion), self.umglobal.settings['post-upd'].replace("[VERSION]", self.umglobal.serverUpdVersion)]) def fillTreeView(self): # First check if this application is upgradable self.upgradableUM = self.getUpgradablePackages(packageNames=["updatemanager"]) if self.upgradableUM: self.upgradables = self.upgradableUM else: # Get a list of packages that can be upgraded self.upgradableUM = [] self.upgradables = self.getUpgradablePackages() #if not self.upgradables: ## Check for black listed packages #cmd = "dpkg --get-selections | grep hold$ | awk '{print $1}'" #lst = self.ec.run(cmd, False) #for pck in lst: #self.upgradables.append([pck.strip(), _("blacklisted"), ""]) if not self.quickUpdate: contentList = [[_("Package"), _("Current version"), _("New version")]] + self.upgradables self.tvHandler.fillTreeview(contentList=contentList, columnTypesList=['str', 'str', 'str'], firstItemIsColName=True) def getUpgradablePackages(self, packageNames=[]): upckList = [] if packageNames: upckList = [] for packageName in packageNames: for upck in self.apt.upgradablePackages: if upck[0] == packageName: upckList.append(upck) break else: upckList = self.apt.upgradablePackages return upckList def getDistUpgradeInfo(self, upgradablesOnly=False): info = "" if upgradablesOnly: if self.apt.upgradablePackages: info = "<strong>%s</strong><br>" % self.apt.upgradablePackagesText for pck in self.apt.upgradablePackages: info += "%s " % pck[0] else: if self.apt.removedPackages: info = "<strong>%s</strong><br>" % self.removedPackagesText for pck in self.apt.removedPackages: info += "%s " % pck[0] if self.apt.newPackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.newPackagesText for pck in self.apt.newPackages: info += "%s " % pck[0] if self.apt.heldbackPackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.heldbackPackagesText for pck in self.apt.heldbackPackages: info += "%s " % pck[0] if self.apt.downgradablePackages: if info != "": info += "<p> </p>" info += "<strong>%s</strong><br>" % self.downgradePackagesText for pck in self.apt.downgradablePackages: info += "%s " % pck[0] return info def showPackages(self): self.nbMain.set_current_page(0) def showOutput(self): self.nbMain.set_current_page(1) self.terminal.grab_focus() def showInfo(self): self.nbMain.set_current_page(2) def showMaintenance(self): self.nbMain.set_current_page(3) def showConfirmationDlg(self, title, message): head = "<html><head><style>body { font-family: Arial, Helvetica, Verdana, Sans-serif; font-size: 12px; color: #555555; background: #ffffff; }</style></head><body>" end = "</body></html>" html = "%s%s%s" % (head, message, end) sw = Gtk.ScrolledWindow() sw.add(SimpleBrowser(html)) return CustomQuestionDialog(title, sw, 550, 300, self.window).show() # Get pre-install script and post-install script from the server def getScripts(self, files): for fle in files: flePath = join(self.umglobal.filesDir, fle) if not exists(flePath): # Get the new scripts if they exist url = "%s/%s/%s" % (self.umglobal.settings['solydxk'], self.umglobal.settings["umfilesdir"], fle) try: txt = urlopen(url).read().decode('utf-8') if txt != '': # Save to a file and make executable self.log.write("Save script = %s" % flePath, "UM.getScripts", "debug") with open(flePath, 'w') as f: f.write(txt) chmod(flePath, 0o755) except: pass def loadInfo(self): languageDir = self.get_language_dir() url = join("file://%s" % languageDir, self.umglobal.settings['up-to-date']) self.btnInfo.set_icon_name("help-about") if self.upgradables: url = join("file://%s" % languageDir, self.umglobal.settings['updates']) if self.umglobal.newUpd: url = "%s/%s/%s" % (self.umglobal.settings['solydxk'], self.umglobal.settings["umfilesdir"], self.umglobal.settings['upd-info']) elif self.umglobal.serverUpdVersion is None: url = join("file://%s" % languageDir, self.umglobal.settings['not-found']) self.log.write("Load info url: %s" % url, "UM.loadInfo", "debug") children = self.swInfo.get_children() if children: children[0].openUrl(url) else: self.swInfo.add(SimpleBrowser(url)) 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.umglobal.htmlDir, lang) if not isdir(path): base_lang = lang.split('_')[0].lower() path = join(self.umglobal.htmlDir, base_lang) if not isdir(path): path = join(self.umglobal.htmlDir, "{}_{}".format(base_lang, base_lang.upper())) if not isdir(path): path = join(self.umglobal.htmlDir, 'en') return path def get_current_language(self): lang = os.environ.get('LANG', 'US').split('.')[0] if lang == '': lang = 'en' return lang def pushMessage(self, message): if message is not None: context = self.statusbar.get_context_id('message') self.statusbar.push(context, message) def checkFilesDir(self): if not exists(self.umglobal.filesDir): makedirs(self.umglobal.filesDir) oldFiles = glob(join(self.umglobal.scriptDir, 'pre-*')) + \ glob(join(self.umglobal.scriptDir, 'post-*')) + \ [join(self.umglobal.scriptDir, 'updatemanager.hist')] + \ [join(self.umglobal.scriptDir, 'mirrors.list')] for fle in oldFiles: if exists(fle): fleName = basename(fle) if not exists(join(self.umglobal.filesDir, fleName)): move(fle, self.umglobal.filesDir) else: remove(fle) chmod(self.umglobal.filesDir, 0o777) def deleteScripts(self, UpdVersion=None): UpdVersion = "*" if UpdVersion is not None: UpdVersion = "*%s" % UpdVersion oldFiles = glob(join(self.umglobal.filesDir, "pre-%s" % UpdVersion)) + glob(join(self.umglobal.filesDir, "post-%s" % UpdVersion)) for fle in oldFiles: remove(fle) self.log.write("Cleanup file: %s" % fle, "UM.deleteScripts", "debug") # Close the gui def on_windowMain_destroy(self, widget): # Close the app Gtk.main_quit()
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()
def __init__(self): # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/usb-creator') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'usb-creator.glade')) # Main window objects go = self.builder.get_object self.window = go("usb-creator") self.lblDevice = go("lblDevice") self.lblIso = go("lblIso") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.cmbDevice = go("cmbDevice") self.cmbDeviceHandler = ComboBoxHandler(self.cmbDevice) self.txtIso = go("txtIso") self.btnRefresh = go("btnRefresh") self.btnUnmount = go("btnUnmount") self.btnBrowseIso = go("btnBrowseIso") self.btnClear = go("btnClear") self.chkFormatDevice = go("chkFormatDevice") self.chkRepairDevice = go("chkRepairDevice") self.btnExecute = go("btnExecute") self.lblUsb = go("lblUsb") self.tvUsbIsos = go("tvUsbIsos") self.btnDelete = go("btnDelete") self.pbUsbCreator = go("pbUsbCreator") self.statusbar = go("statusbar") # Translations self.window.set_title(_("USB Creator")) self.lblDevice.set_label(_("Device")) self.lblUsb.set_label(_("USB")) self.available_text = _("Available") self.required_text = _("Required") self.chkFormatDevice.set_label(_("Format device")) self.chkFormatDevice.set_tooltip_text( _("Warning: all data will be lost")) self.chkRepairDevice.set_label(_("Repair device")) self.chkRepairDevice.set_tooltip_text( _("Tries to repair an unbootable USB")) self.btnExecute.set_label("_{}".format(_("Execute"))) self.lblIso.set_label(_("ISO")) self.btnDelete.set_label("_{}".format(_("Delete"))) self.btnRefresh.set_tooltip_text(_("Refresh device list")) self.btnUnmount.set_tooltip_text(_("Unmount device")) self.btnBrowseIso.set_tooltip_text(_("Browse for ISO file")) self.btnClear.set_tooltip_text(_("Clear the ISO field")) # Log lines to show: check string, percent done (0=pulse, appends last word in log line), show line (translatable) self.log_lines = [] self.log_lines.append( ["partitioning usb", 5, _("Partitioning USB...")]) self.log_lines.append( ["searching for bad blocks", 0, _("Searching for bad block")]) self.log_lines.append(["installing", 15, _("Installing Grub...")]) self.log_lines.append(["rsync", 25, _("Start copying ISO...")]) self.log_lines.append(["left to copy", 0, _("kB left to copy:")]) self.log_lines.append(["check hash", 85, _("Check hash of ISO...")]) # Initiate variables self.device = {} self.device['path'] = '' self.device['mount'] = '' self.device['size'] = 0 self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.logos = self.get_logos() self.queue = Queue(-1) self.threads = {} self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput( "cat /usr/bin/usb-creator | grep 'LOG=' | cut -d'=' -f 2") self.log_file = log[0] self.log = Logger(self.log_file, addLogTime=False, maxSizeKB=5120) self.tvUsbIsosHandler = TreeViewHandler(self.tvUsbIsos) self.udisks2 = Udisks2() self.lblAvailable.set_label('') self.lblRequired.set_label('') # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Get attached devices self.on_btnRefresh_clicked() # Init log init_log = ">>> Start USB Creator: {} <<<".format(datetime.now()) self.log.write(init_log) # Version information self.version_text = _("Version") self.pck_version = getPackageVersion('usb-creator') self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version))
class USBCreator(object): def __init__(self): # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/usb-creator') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'usb-creator.glade')) # Main window objects go = self.builder.get_object self.window = go("usb-creator") self.lblDevice = go("lblDevice") self.lblIso = go("lblIso") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.cmbDevice = go("cmbDevice") self.cmbDeviceHandler = ComboBoxHandler(self.cmbDevice) self.txtIso = go("txtIso") self.btnRefresh = go("btnRefresh") self.btnUnmount = go("btnUnmount") self.btnBrowseIso = go("btnBrowseIso") self.btnClear = go("btnClear") self.chkFormatDevice = go("chkFormatDevice") self.chkRepairDevice = go("chkRepairDevice") self.btnExecute = go("btnExecute") self.lblUsb = go("lblUsb") self.tvUsbIsos = go("tvUsbIsos") self.btnDelete = go("btnDelete") self.pbUsbCreator = go("pbUsbCreator") self.statusbar = go("statusbar") # Translations self.window.set_title(_("USB Creator")) self.lblDevice.set_label(_("Device")) self.lblUsb.set_label(_("USB")) self.available_text = _("Available") self.required_text = _("Required") self.chkFormatDevice.set_label(_("Format device")) self.chkFormatDevice.set_tooltip_text(_("Warning: all data will be lost")) self.chkRepairDevice.set_label(_("Repair device")) self.chkRepairDevice.set_tooltip_text(_("Tries to repair an unbootable USB")) self.btnExecute.set_label("_{}".format(_("Execute"))) self.lblIso.set_label(_("ISO")) self.btnDelete.set_label("_{}".format(_("Delete"))) self.btnRefresh.set_tooltip_text(_("Refresh device list")) self.btnUnmount.set_tooltip_text(_("Unmount device")) self.btnBrowseIso.set_tooltip_text(_("Browse for ISO file")) self.btnClear.set_tooltip_text(_("Clear the ISO field")) # Log lines to show: check string, percent done (0=pulse, appends last word in log line), show line (translatable) self.log_lines = [] self.log_lines.append(["partitioning usb", 5, _("Partitioning USB...")]) self.log_lines.append(["searching for bad blocks", 0, _("Searching for bad block")]) self.log_lines.append(["installing", 15, _("Installing Grub...")]) self.log_lines.append(["rsync", 25, _("Start copying ISO...")]) self.log_lines.append(["left to copy", 0, _("kB left to copy:")]) self.log_lines.append(["check hash", 85, _("Check hash of ISO...")]) # Initiate variables self.devices = [] self.device = {} self.device['path'] = '' self.device['size'] = 0 self.device['has_partition'] = False self.device['mount'] = '' self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.logos = self.get_logos() self.queue = Queue(-1) self.threads = {} self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput("cat /usr/bin/usb-creator | grep 'LOG=' | cut -d'=' -f 2") self.log_file = log[0] self.log = Logger(self.log_file, addLogTime=False, maxSizeKB=5120) self.tvUsbIsosHandler = TreeViewHandler(self.tvUsbIsos) self.lblAvailable.set_label('') self.lblRequired.set_label('') # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Get attached devices self.on_btnRefresh_clicked() # Init log init_log = ">>> Start USB Creator: {} <<<".format(datetime.now()) self.log.write(init_log) # Version information self.version_text = _("Version") self.pck_version = getPackageVersion('usb-creator') self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version)) # =============================================== # Main window functions # =============================================== def on_btnExecute_clicked(self, widget): if exists(self.device["path"]): arguments = [] arguments.append("-d {}".format(self.device["path"])) clear = self.chkFormatDevice.get_active() repair = self.chkRepairDevice.get_active() iso = self.device["new_iso"] iso_path = self.txtIso.get_text().strip() # ISO path does not exist if iso != iso_path: msg = _("Cannot add ISO from path: {}.\n" "Please, remove the ISO path or browse for an existing ISO.") WarningDialog(self.btnExecute.get_label(), msg.format(iso_path)) return True # Check if there is enough space available = self.device["available"] if self.chkFormatDevice.get_active(): available = self.device["size"] if available - self.device["new_iso_required"] < 0: msg = _("There is not enough space available on the pen drive.\n" "Please, remove unneeded files before continuing.") WarningDialog(self.btnExecute.get_label(), msg) return True if clear: arguments.append("-f") arguments.append("-b") if repair: arguments.append("-r") arguments.append("-b") arguments.append("-g") # This should use the history file to get the original hash arguments.append("-s") if exists(iso): arguments.append("-i \"{}\"".format(iso)) arguments.append("-s") cmd = "usb-creator {}".format(" ".join(arguments)) self.log.write("Execute command: {}".format(cmd)) self.exec_command(cmd) def on_btnDelete_clicked(self, widget): selected_isos = self.tvUsbIsosHandler.getToggledValues(toggleColNr=0, valueColNr=2) if selected_isos: msg = _("Are you sure you want to remove the selected ISO from the device?") answer = QuestionDialog(self.btnDelete.get_label(), msg) if answer: for iso in selected_isos: iso_path = join(self.device["mount"], iso) if exists(iso_path): os.remove(iso_path) self.log.write("Remove ISO: {}".format(iso_path)) shell_exec("usb-creator -d {} -g".format(self.device["path"])) self.on_cmbDevice_changed() self.fill_treeview_usbcreator(self.device["mount"]) def on_btnBrowseIso_clicked(self, widget): file_filter = Gtk.FileFilter() file_filter.set_name("ISO") file_filter.add_mime_type("application/x-cd-image") file_filter.add_pattern("*.iso") start_dir = dirname(self.txtIso.get_text().strip()) if not exists(start_dir): start_dir = expanduser("~") iso = SelectFileDialog(title=_('Select ISO'), start_directory=start_dir, gtkFileFilter=file_filter).show() if iso is not None: self.log.write("Add ISO: {}".format(iso)) self.txtIso.set_text(iso) def on_btnClear_clicked(self, widget): self.txtIso.set_text('') def on_txtIso_changed(self, widget=None): iso_path = self.txtIso.get_text().strip() if exists(iso_path): if isdir(iso_path): isos = glob(join(iso_path, '*.iso')) if isos: required = 0 for iso in isos: # Check if these ISOs overwrite current USB ISOs check_usb_iso_size = 0 if not self.chkFormatDevice.get_active(): check_usb_iso = join(self.device["mount"], basename(iso)) if exists(check_usb_iso): check_usb_iso_size = self.get_iso_size(check_usb_iso) required += (self.get_iso_size(iso) - check_usb_iso_size) if required < 0: required = 0 self.lblRequired.set_label("{}: {} MB".format(self.required_text, int(required / 1024))) # Save the info self.device["new_iso"] = iso_path self.device["new_iso_required"] = required self.log.write("New ISO directory: {}, {}".format(iso_path, required)) else: self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.log.write("New ISO directory does not contain ISOs: {}".format(iso_path)) else: # Check if this ISO overwrites current USB ISO check_usb_iso_size = 0 if not self.chkFormatDevice.get_active(): check_usb_iso = join(self.device["mount"], basename(iso_path)) if exists(check_usb_iso): check_usb_iso_size = self.get_iso_size(check_usb_iso) required = (self.get_iso_size(iso_path) - check_usb_iso_size) self.lblRequired.set_label("{}: {} MB".format(self.required_text, int(required / 1024))) # Save the info self.device["new_iso"] = iso_path self.device["new_iso_required"] = required self.log.write("New ISO: {}, {}".format(iso_path, required)) else: self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.lblRequired.set_text('') def on_btnRefresh_clicked(self, widget=None): self.devices = self.get_devices() self.cmbDeviceHandler.fillComboBox(self.devices, 0) def on_btnUnmount_clicked(self, widget): unmount_text = _("Unmount") device = self.device["path"] self.unmount_device(device) self.on_btnRefresh_clicked() if device in self.devices: msg = _("Could not unmount the device.\n" "Please unmount the device manually.") else: msg = _("You can now safely remove the device.") MessageDialog(unmount_text, msg) def on_cmbDevice_changed(self, widget=None): device = self.cmbDeviceHandler.getValue() if device is not None: mount = '' size = 0 available = 0 # Get the size of the USB usb_size = getoutput("env LANG=C udisks --show-info {} | grep size".format(device)) if usb_size: # udisks returns bytes, while df returns kbs size = int(int(usb_size[0].split(":")[1].strip()) / 1024) # Assume that the USB is empty (will check later) available = size # Get free size on USB has_partition = self.device_has_partition(device) if has_partition: mount = self.get_device_mount(device) # This function can be called from on_chkFormatDevice_toggled if widget != self.chkFormatDevice: self.chkFormatDevice.set_sensitive(True) self.chkFormatDevice.set_active(False) free_size = getoutput("df --output=avail {}1 | awk 'NR==2'".format(device)) if free_size: available = int(free_size[0]) else: self.chkFormatDevice.set_active(True) self.chkFormatDevice.set_sensitive(False) self.chkRepairDevice.set_active(False) self.fill_treeview_usbcreator(mount) self.lblAvailable.set_label("{}: {} MB".format(self.available_text, int(available / 1024))) # Save the info self.device['path'] = device self.device['size'] = size self.device['has_partition'] = has_partition self.device['mount'] = mount self.device['available'] = available self.log.write("Selected device info: {}".format(self.device)) # Update info iso_path = self.txtIso.get_text().strip() if iso_path != "" and exists(iso_path): self.on_txtIso_changed() else: self.fill_treeview_usbcreator() self.lblAvailable.set_label('') self.lblRequired.set_label('') self.txtIso.set_text('') self.device['path'] = '' self.device['size'] = 0 self.device['has_partition'] = False self.device['mount'] = '' self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 def on_chkFormatDevice_toggled(self, widget): # Recalculate available space and requied space self.on_cmbDevice_changed(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 fill_treeview_usbcreator(self, mount=''): isos_list = [] # columns: checkbox, image (logo), device, driver column_types = ['bool', 'GdkPixbuf.Pixbuf', 'str', 'str'] if exists(mount): isos = glob(join(mount, '*.iso')) for iso in isos: iso_name = basename(iso) iso_name_lower = iso_name.lower() iso_size = "{} MB".format(int(self.get_iso_size(iso) / 1024)) iso_logo = "" for key, logo in list(self.logos.items()): if key != "iso": if key in iso_name_lower: if len(logo) > len(iso_logo): iso_logo = logo if iso_logo == "": iso_logo = self.logos["iso"] self.log.write("ISO on {}: {}, {}, {}".format(mount, iso_name, iso_size, iso_logo)) isos_list.append([False, iso_logo, iso_name, iso_size]) # Fill treeview self.tvUsbIsosHandler.fillTreeview(contentList=isos_list, columnTypesList=column_types) 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(1000, self.check_thread, name) except Exception as detail: ErrorDialog(self.btnExecute.get_label(), detail) def check_thread(self, name): if self.threads[name].is_alive(): self.set_progress() 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) self.on_cmbDevice_changed() self.fill_treeview_usbcreator(self.device["mount"]) self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version)) return False def set_buttons_state(self, enable): if not enable: # Disable buttons self.btnExecute.set_sensitive(False) self.btnDelete.set_sensitive(False) self.btnBrowseIso.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnUnmount.set_sensitive(False) self.btnClear.set_sensitive(False) self.chkFormatDevice.set_sensitive(False) self.chkRepairDevice.set_sensitive(False) self.cmbDevice.set_sensitive(False) self.txtIso.set_sensitive(False) else: # Enable buttons and reset progress bar self.btnExecute.set_sensitive(True) self.btnDelete.set_sensitive(True) self.btnBrowseIso.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnUnmount.set_sensitive(True) self.btnClear.set_sensitive(True) self.chkFormatDevice.set_sensitive(True) self.chkRepairDevice.set_sensitive(True) self.cmbDevice.set_sensitive(True) self.txtIso.set_sensitive(True) self.pbUsbCreator.set_fraction(0) def get_logos(self): logos_dict = {} logos_path = join(self.mediaDir, 'logos') logos = glob(join(logos_path, '*.png')) for logo in logos: key = splitext(basename(logo))[0] logos_dict[key] = logo return logos_dict def set_progress(self): if exists(self.log_file): msg = '' last_line = getoutput("tail -50 {} | grep -v DEBUG | grep -v ==".format(self.log_file)) for line in reversed(last_line): # Check for session start line: that is the last line to check if ">>>>>" in line and "<<<<<" in line: break for chk_line in self.log_lines: if chk_line[0] in line.lower(): #print((line)) word = '' if chk_line[1] == 0: self.pbUsbCreator.pulse() words = line.split(' ') for word in reversed(words): if word.strip() != '': break else: self.pbUsbCreator.set_fraction(float(chk_line[1] / 100)) msg = "{} {}".format(chk_line[2], word) break if msg != '': break self.set_statusbar_message(msg) def set_statusbar_message(self, message): if message is not None: context = self.statusbar.get_context_id('message') self.statusbar.push(context, message) def get_devices(self): devices = [] my_devices = getoutput("udisks --enumerate-device-files | egrep '/dev/sd[a-z]$'") for device in my_devices: info = getoutput("env LANG=C udisks --show-info {}".format(device)) detachable = False has_partition = False for line in info: if "detachable" in line and "1" in line: detachable = True elif "partition" in line: has_partition = True if detachable and has_partition: devices.append(device) break devices.sort() return devices def device_has_partition(self, device): part_count = getoutput("udisks --show-info {} | grep count | grep -v block".format(device)) if part_count: if "1" in part_count[0]: return True return False def get_device_mount(self, device): shell_exec("udisks --mount {}1".format(device)) mount = getoutput("grep %s1 /etc/mtab | awk '{print $2}' | sed 's/\\040/ /g'" % device) if mount: return mount[0] return '' def get_iso_size(self, iso): iso_size = getoutput("du -Lk \"%s\" | awk '{print $1}'" % iso) if iso_size: return int(iso_size[0]) return 0 def unmount_device(self, device): shell_exec("udisks --unmount {}1".format(device)) shell_exec("udisks --detach {}".format(device)) # Close the gui def on_usbcreator_destroy(self, widget): # Unmount devices for device in self.devices: if self.get_device_mount(device) != "": self.unmount_device(device) # Close the app Gtk.main_quit() 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.btnExecute.get_label(), _("Run this application with root permission.")) elif ret == 2: ErrorDialog(self.btnExecute.get_label(), _("Wrong arguments were passed to usb-creator.")) elif ret == 3: ErrorDialog(self.btnExecute.get_label(), _("The device was not found or no device was given.")) elif ret == 4: ErrorDialog(self.btnExecute.get_label(), _("Given ISO path was not found.")) elif ret == 5: ErrorDialog(self.btnExecute.get_label(), _("Device is in use by another application.")) elif ret == 6: ErrorDialog(self.btnExecute.get_label(), _("Unable to mount the device.")) elif ret == 7: ErrorDialog(self.btnExecute.get_label(), _("Hash mismatch.")) elif ret == 8: ErrorDialog(self.btnExecute.get_label(), _("The device has no fat32 partition.")) elif ret == 9: ErrorDialog(self.btnExecute.get_label(), _("The device has no bootloader installed.")) elif ret == 10: ErrorDialog(self.btnExecute.get_label(), _("There is not enough space available on the device.")) elif ret == 11: ErrorDialog(self.btnExecute.get_label(), _("Unable to guess distribution from ISO name.\n" "Make sure you have the distribution name in the ISO name.")) else: msg = _("An unknown error accured.\n" "Please, visit our forum for support: http://forums.solydxk.com") ErrorDialog(self.window.get_title(), msg) else: msg = _("The USB was successfully written.") MessageDialog(self.window.get_title(), msg) except: ErrorDialog(self.btnExecute.get_label(), cmdOutput) # =============================================== # 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
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()
def __init__(self): self.scriptDir = abspath(dirname(__file__)) self.shareDir = join(self.scriptDir, '../../../share/solydxk/constructor') self.userAppDir = join(get_user_home_dir(), ".constructor") self.distroFile = join(self.userAppDir, "distros.list") # Create the user's application directory if it doesn't exist if not isdir(self.userAppDir): user_name = getUserLoginName() makedirs(self.userAppDir) old_distro_file = join(self.scriptDir, "distros.list") if exists(old_distro_file): move(old_distro_file, self.distroFile) system("chown -R %s:%s %s" % (user_name, user_name, self.userAppDir)) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.shareDir, 'constructor.glade')) # Main window objects go = self.builder.get_object self.window = go('constructorWindow') self.tvDistros = go('tvDistros') self.lblOutput = go('lblOutput') self.statusbar = go('statusbar') self.btnAdd = go('btnAdd') self.chkSelectAll = go('chkSelectAll') self.btnRemove = go('btnRemove') self.btnEdit = go('btnEdit') self.btnUpgrade = go('btnUpgrade') self.btnLocalize = go('btnLocalize') self.btnBuildIso = go('btnBuildIso') # Add iso window objects self.windowAddDistro = go('addDistroWindow') self.txtIso = go('txtIso') self.txtDir = go('txtDir') self.btnDir = go('btnDir') self.btnSave = go('btnSave') self.btnHelp = go('btnHelp') self.lblIso = go('lblIso') self.boxIso = go('boxIso') self.lblDir = go('lblDir') self.chkFromIso = go('chkFromIso') # Main window translations self.window.set_title(_("SolydXK Constructor")) self.chkSelectAll.set_label(_("Select all")) self.btnAdd.set_label("_{}".format(_("Add"))) self.btnRemove.set_label("_{}".format(_("Remove"))) self.btnEdit.set_label("_{}".format(_("Edit"))) self.btnUpgrade.set_label("_{}".format(_("Upgrade"))) self.btnLocalize.set_label("_{}".format(_("Localize"))) self.btnBuildIso.set_label("_{}".format(_("Build"))) self.btnHelp.set_label("_{}".format(_("Help"))) # Add iso window translations self.windowAddDistro.set_title(_("Add Distribution")) self.lblIso.set_text(_("ISO")) go('lblFromIso').set_label("Create from ISO") go('btnCancel').set_label("_{}".format(_("Cancel"))) # Init self.ec = ExecCmd() self.ec.run("modprobe loop", False) self.queue = Queue() self.mountDir = "/mnt/constructor" self.distroAdded = False self.iso = None self.dir = None self.isoName = None self.doneWav = join(self.shareDir, 'done.wav') self.htmlDir = join(self.shareDir, "html") self.help = join(self.get_language_dir(), "help.html") self.chkFromIso.set_active(True) self.toggleGuiElements(False) # Treeviews self.tvHandlerDistros = TreeViewHandler(self.tvDistros) self.fillTreeViewDistros() # Version information ver = _("Version") self.version = "%s: %s" % (ver, getPackageVersion('solydxk-constructor')) self.showOutput(self.version) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show()
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)
def __init__(self): # Check if script is running self.scriptName = basename(__file__) self.umglobal = UmGlobal() self.user = self.umglobal.getLoginName() # Initiate logging self.logFile = join('/var/log', self.umglobal.settings['log']) print(("UM log = %s" % self.logFile)) self.log = Logger(self.logFile, maxSizeKB=5120) # Remove scripts self.deleteScripts(self.umglobal.localUpdVersion) # Initialize self.ec = ExecCmd(loggerObject=self.log) self.apt = UmApt(self.umglobal) self.kernelVersion = self.umglobal.getKernelVersion() self.upgradables = [] self.upgradableUM = [] self.window = None # Handle arguments parser = argparse.ArgumentParser(description='SolydXK Update Manager') parser.add_argument('-q','--quick', action="store_true", help='Quick upgrade') parser.add_argument('-r','--reload', action="store_true", help='') args, extra = parser.parse_known_args() self.quickUpdate = False if args.quick and not self.umglobal.newUpd: self.quickUpdate = True if args.reload: pids = self.umglobal.getProcessPids("updatemanager.py") if len(pids) > 1: print(("updatemanager.py already running - kill pid {}".format(pids[0]))) os.system("kill {}".format(pids[0])) # Set some global translations self.aptErrorText = _("Apt error") self.upgradablePackagesText = _("The following packages will be upgraded:") self.newPackagesText = _("The following NEW packages will be installed:") self.removedPackagesText = _("The following packages will be REMOVED:") self.heldbackPackagesText = _("The following packages have been kept back:") self.downgradePackagesText = _("The following packages are going to be downgraded:") # Cleanup first for fle in glob(join(self.umglobal.filesDir, '.um*')): remove(fle) # Load window and widgets self.builder = Gtk.Builder() self.builder.add_from_file(join(self.umglobal.shareDir, 'updatemanager.glade')) go = self.builder.get_object # Quick update if self.quickUpdate: # Refresh data self.refresh() self.umglobal.collectData() self.apt.createPackagesInfoList() self.apt.createPackageLists() self.fillTreeView() # Run upgrade nid = self.run_upgrade() if nid != "": self.on_command_done(None, 0, nid) sys.exit(2) # Make sure the files directory is set correctly self.checkFilesDir() # Main window objects self.window = go("windowMain") #self.window.set_icon_from_file(join(self.umglobal.iconsDir, self.umglobal.settings["icon-connected"])) self.tvPck = go("tvPck") self.swTerminal = go("swTerminal") self.statusbar = go("statusbar") self.btnInstall = go("btnInstall") self.btnRefresh = go("btnRefresh") self.btnPackages = go("btnPackages") self.btnOutput = go("btnOutput") self.btnInfo = go("btnInfo") self.btnPreferences = go("btnPreferences") self.nbMain = go("nbMain") self.swInfo = go("swInfo") self.btnMaintenance = go("btnMaintenance") self.lblMaintenance = go("lblMaintenance") self.tvMaintenance = go("tvMaintenance") self.btnMaintenanceExecute = go("btnMaintenanceExecute") self.chkMaintenanceSelectAll = go("chkMaintenanceSelectAll") self.radUnneeded = go("radUnneeded") self.radCleanCache = go("radCleanCache") self.radDowngradable = go("radDowngradable") self.radNotavailable = go("radNotavailable") self.radOldKernel = go("radOldKernel") self.lblMaintenanceHelp = go("lblMaintenanceHelp") # Translations self.window.set_title(_("SolydXK Update Manager")) self.btnInstall.set_label(_("Install")) self.btnRefresh.set_label(_("Refresh")) self.btnOutput.set_label(_("Output")) self.btnInfo.set_label(_("Information")) self.btnPreferences.set_label(_("Preferences")) self.btnMaintenance.set_label(_("Maintenance")) self.btnPackages.set_label(_("Packages")) self.uptodateText = self.umglobal.connectedText self.lblMaintenance.set_label(self.btnMaintenance.get_label()) self.btnMaintenanceExecute.set_label(_("Execute")) self.chkMaintenanceSelectAll.set_label(_("Select all")) self.radCleanCache.set_label(_("Clean up the apt cache")) self.radUnneeded.set_label(_("Remove unneeded packages")) self.radNotavailable.set_label(_("Remove packages not available\nin the repositories")) self.radOldKernel.set_label(_("Remove old kernels")) self.radDowngradable.set_label(_("Downgrade packages with\nonly lower versions available")) self.lblMaintenanceHelp.set_label(_("Make sure you create\n" "a system image before you\n" "continue (e.g. Clonezilla).")) # VTE Terminal self.terminal = VirtualTerminal(userInputAllowed=self.umglobal.settings["allow-terminal-user-input"]) self.swTerminal.add(self.terminal) self.terminal.set_vexpand(True) self.terminal.set_hexpand(True) self.terminal.connect('command-done', self.on_command_done) self.terminal.connect('line-added', self.on_line_added) palletList = ['#4A4A4A', '#BD1919', '#118011', '#CE6800', '#1919BC', '#8D138D', '#139494', '#A7A7A7'] self.terminal.setTerminalColors("#000000", "#FFFFFF", palletList) self.swTerminal.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#FFFFFF")) # Disable all buttons self.btnInfo.set_sensitive(False) self.btnPreferences.set_sensitive(False) self.btnOutput.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnInstall.set_sensitive(False) self.btnPackages.set_sensitive(False) self.btnMaintenance.set_sensitive(False) # Hide tabs if needed for tab in self.umglobal.settings["hide-tabs"]: if tab == "packages": self.nbMain.get_nth_page(0).set_visible(False) self.btnPackages.set_visible(False) elif tab == "output": self.nbMain.get_nth_page(1).set_visible(False) self.btnOutput.set_visible(False) elif tab == "info": self.nbMain.get_nth_page(2).set_visible(False) self.btnInfo.set_visible(False) elif tab == "maintenance": self.nbMain.get_nth_page(3).set_visible(False) self.btnMaintenance.set_visible(False) # Connect the signals and show the window self.builder.connect_signals(self) self.window.show() # Force the window to show while Gtk.events_pending(): Gtk.main_iteration() # Just show something that we're busy msg = _("Gathering information...") self.terminal.executeCommand('echo "%s"' % msg, 'init') self.showOutput() # Treeview handlers self.tvHandler = TreeViewHandler(self.tvPck) self.tvMaintenanceHandler = TreeViewHandler(self.tvMaintenance) # Version information ver = _("Version") pckVer = self.apt.getPackageVersion('updatemanager') versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } if self.umglobal.localUpdVersion != "2000.01.01": versionInfo = "%(ver)s: %(pckVer)s" % { "ver": ver, "pckVer": pckVer } self.pushMessage(versionInfo) # Log basic information self.log.write("==============================================", "UM.init", "debug") self.log.write("UM version = %s" % versionInfo, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") mirrorsList = join(self.umglobal.filesDir, basename(self.umglobal.settings["mirrors-list"])) if exists(mirrorsList): self.log.write("Mirrors list", "UM.init", "debug") with open(mirrorsList, 'r') as f: for line in f.readlines(): self.log.write(line, "UM.init", "debug") self.log.write("==============================================", "UM.init", "debug") # Refresh apt cache self.refresh() # Initialize maintenance screen self.fillTreeViewMaintenance()
class USBCreator(object): def __init__(self): # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/usb-creator') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'usb-creator.glade')) # Main window objects go = self.builder.get_object self.window = go("usb-creator") self.lblDevice = go("lblDevice") self.lblIso = go("lblIso") self.lblAvailable = go("lblAvailable") self.lblRequired = go("lblRequired") self.cmbDevice = go("cmbDevice") self.cmbDeviceHandler = ComboBoxHandler(self.cmbDevice) self.txtIso = go("txtIso") self.btnRefresh = go("btnRefresh") self.btnUnmount = go("btnUnmount") self.btnBrowseIso = go("btnBrowseIso") self.btnClear = go("btnClear") self.chkFormatDevice = go("chkFormatDevice") self.chkRepairDevice = go("chkRepairDevice") self.btnExecute = go("btnExecute") self.lblUsb = go("lblUsb") self.tvUsbIsos = go("tvUsbIsos") self.btnDelete = go("btnDelete") self.pbUsbCreator = go("pbUsbCreator") self.statusbar = go("statusbar") # Translations self.window.set_title(_("USB Creator")) self.lblDevice.set_label(_("Device")) self.lblUsb.set_label(_("USB")) self.available_text = _("Available") self.required_text = _("Required") self.chkFormatDevice.set_label(_("Format device")) self.chkFormatDevice.set_tooltip_text( _("Warning: all data will be lost")) self.chkRepairDevice.set_label(_("Repair device")) self.chkRepairDevice.set_tooltip_text( _("Tries to repair an unbootable USB")) self.btnExecute.set_label("_{}".format(_("Execute"))) self.lblIso.set_label(_("ISO")) self.btnDelete.set_label("_{}".format(_("Delete"))) self.btnRefresh.set_tooltip_text(_("Refresh device list")) self.btnUnmount.set_tooltip_text(_("Unmount device")) self.btnBrowseIso.set_tooltip_text(_("Browse for ISO file")) self.btnClear.set_tooltip_text(_("Clear the ISO field")) # Log lines to show: check string, percent done (0=pulse, appends last word in log line), show line (translatable) self.log_lines = [] self.log_lines.append( ["partitioning usb", 5, _("Partitioning USB...")]) self.log_lines.append( ["searching for bad blocks", 0, _("Searching for bad block")]) self.log_lines.append(["installing", 15, _("Installing Grub...")]) self.log_lines.append(["rsync", 25, _("Start copying ISO...")]) self.log_lines.append(["left to copy", 0, _("kB left to copy:")]) self.log_lines.append(["check hash", 85, _("Check hash of ISO...")]) # Initiate variables self.device = {} self.device['path'] = '' self.device['mount'] = '' self.device['size'] = 0 self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.logos = self.get_logos() self.queue = Queue(-1) self.threads = {} self.htmlDir = join(self.mediaDir, "html") self.helpFile = join(self.get_language_dir(), "help.html") log = getoutput( "cat /usr/bin/usb-creator | grep 'LOG=' | cut -d'=' -f 2") self.log_file = log[0] self.log = Logger(self.log_file, addLogTime=False, maxSizeKB=5120) self.tvUsbIsosHandler = TreeViewHandler(self.tvUsbIsos) self.udisks2 = Udisks2() self.lblAvailable.set_label('') self.lblRequired.set_label('') # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() # Get attached devices self.on_btnRefresh_clicked() # Init log init_log = ">>> Start USB Creator: {} <<<".format(datetime.now()) self.log.write(init_log) # Version information self.version_text = _("Version") self.pck_version = getPackageVersion('usb-creator') self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version)) # =============================================== # Main window functions # =============================================== def on_btnExecute_clicked(self, widget): if exists(self.device["path"]): arguments = [] arguments.append("-d {}".format(self.device["path"])) clear = self.chkFormatDevice.get_active() repair = self.chkRepairDevice.get_active() iso = self.device["new_iso"] iso_path = self.txtIso.get_text().strip() # ISO path does not exist if iso != iso_path: msg = _( "Cannot add ISO from path: {}.\n" "Please, remove the ISO path or browse for an existing ISO." ) WarningDialog(self.btnExecute.get_label(), msg.format(iso_path)) return True # Check if there is enough space available = self.device["available"] if self.chkFormatDevice.get_active(): available = self.device["size"] if (available) - self.device["new_iso_required"] < 0: msg = _( "There is not enough space available on the pen drive.\n" "Please, remove unneeded files before continuing.") WarningDialog(self.btnExecute.get_label(), msg) return True if clear: arguments.append("-f") arguments.append("-b") if repair: arguments.append("-r") arguments.append("-b") arguments.append("-g") # This should use the history file to get the original hash arguments.append("-s") if exists(iso): arguments.append("-i \"{}\"".format(iso)) arguments.append("-s") cmd = "usb-creator {}".format(" ".join(arguments)) self.log.write("Execute command: {}".format(cmd)) self.exec_command(cmd) def on_btnDelete_clicked(self, widget): selected_isos = self.tvUsbIsosHandler.getToggledValues(toggleColNr=0, valueColNr=2) if selected_isos: msg = _( "Are you sure you want to remove the selected ISO from the device?" ) answer = QuestionDialog(self.btnDelete.get_label(), msg) if answer: for iso in selected_isos: iso_path = join(self.device["mount"], iso) if exists(iso_path): os.remove(iso_path) self.log.write("Remove ISO: {}".format(iso_path)) shell_exec("usb-creator -d {} -g".format(self.device["path"])) self.on_btnRefresh_clicked() self.fill_treeview_usbcreator(self.device["mount"]) def on_btnBrowseIso_clicked(self, widget): file_filter = Gtk.FileFilter() file_filter.set_name("ISO") file_filter.add_mime_type("application/x-cd-image") file_filter.add_pattern("*.iso") start_dir = dirname(self.txtIso.get_text().strip()) if not exists(start_dir): start_dir = expanduser("~") iso = SelectFileDialog(title=_('Select ISO'), start_directory=start_dir, gtkFileFilter=file_filter).show() if iso is not None: self.log.write("Add ISO: {}".format(iso)) self.txtIso.set_text(iso) def on_btnClear_clicked(self, widget): self.txtIso.set_text('') def on_txtIso_changed(self, widget=None): iso_path = self.txtIso.get_text().strip() if exists(iso_path): if isdir(iso_path): isos = glob(join(iso_path, '*.iso')) if isos: required = 0 for iso in isos: # Check if these ISOs overwrite current USB ISOs check_usb_iso_size = 0 if not self.chkFormatDevice.get_active(): check_usb_iso = join(self.device["mount"], basename(iso)) if exists(check_usb_iso): check_usb_iso_size = self.get_iso_size( check_usb_iso) required += (self.get_iso_size(iso) - check_usb_iso_size) if required < 0: required = 0 self.lblRequired.set_label("{}: {} MB".format( self.required_text, int(required / 1024))) # Save the info self.device["new_iso"] = iso_path self.device["new_iso_required"] = required self.log.write("New ISO directory: {}, {}".format( iso_path, required)) else: self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.log.write( "New ISO directory does not contain ISOs: {}".format( iso_path)) else: # Check if this ISO overwrites current USB ISO check_usb_iso_size = 0 if not self.chkFormatDevice.get_active(): check_usb_iso = join(self.device["mount"], basename(iso_path)) if exists(check_usb_iso): check_usb_iso_size = self.get_iso_size(check_usb_iso) required = (self.get_iso_size(iso_path) - check_usb_iso_size) self.lblRequired.set_label("{}: {} MB".format( self.required_text, int(required / 1024))) # Save the info self.device["new_iso"] = iso_path self.device["new_iso_required"] = required self.log.write("New ISO: {}, {}".format(iso_path, required)) else: self.device["new_iso"] = '' self.device["new_iso_required"] = 0 self.lblRequired.set_text('') def on_btnRefresh_clicked(self, widget=None): self.udisks2.fill_devices() drives = self.udisks2.get_drives() self.cmbDeviceHandler.fillComboBox(drives, 0) def on_btnUnmount_clicked(self, widget): unmount_text = _("Unmount") device = self.device["path"] try: self.udisks2.unmount_drive(device) self.on_btnRefresh_clicked() msg = _("You can now safely remove the device.") except Exception as e: msg = _("Could not unmount the device.\n" "Please unmount the device manually.") self.log.write("ERROR: %s" % str(e)) MessageDialog(unmount_text, msg) def on_cmbDevice_changed(self, widget=None): drive_path = self.cmbDeviceHandler.getValue() device_paths = [] if drive_path is not None: drive = self.udisks2.devices[drive_path] device_paths = self.udisks2.get_drive_device_paths(drive_path) device = '' if device_paths: device = device_paths[0] mount = '' size = 0 available = 0 # Get free size on USB size = drive['total_size'] available = drive['free_size'] if self.chkFormatDevice.get_active(): available = size if device != '': mount = drive[device]['mount_point'] if not exists(mount): # Mount if not already mounted try: mount = self.udisks2.mount_device(device) except Exception as e: self.show_message(6) self.log.write("ERROR: %s" % str(e)) if exists(mount) and not self.chkFormatDevice.get_active(): size = drive[device]['total_size'] available = drive[device]['free_size'] # This function can be called from on_chkFormatDevice_toggled if widget != self.chkFormatDevice: self.chkFormatDevice.set_sensitive(True) self.chkFormatDevice.set_active(False) else: # No partition: always format the device self.chkFormatDevice.set_active(True) self.chkFormatDevice.set_sensitive(False) self.chkRepairDevice.set_active(False) self.fill_treeview_usbcreator(mount) self.lblAvailable.set_label("{}: {} MB".format( self.available_text, int(available / 1024))) # Save the info self.device['path'] = drive_path self.device['mount'] = mount self.device['size'] = size self.device['available'] = available self.log.write("Selected device info: {}".format(self.device)) # Update info iso_path = self.txtIso.get_text().strip() if iso_path != "" and exists(iso_path): self.on_txtIso_changed() else: self.fill_treeview_usbcreator() self.lblAvailable.set_label('') self.lblRequired.set_label('') self.txtIso.set_text('') self.device['path'] = '' self.device['mount'] = '' self.device['size'] = 0 self.device['available'] = 0 self.device["new_iso"] = '' self.device["new_iso_required"] = 0 def on_chkFormatDevice_toggled(self, widget): # Recalculate available space and requied space self.on_cmbDevice_changed(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 fill_treeview_usbcreator(self, mount=''): isos_list = [] # columns: checkbox, image (logo), device, driver column_types = ['bool', 'GdkPixbuf.Pixbuf', 'str', 'str'] if exists(mount): isos = glob(join(mount, '*.iso')) for iso in isos: iso_name = basename(iso) iso_name_lower = iso_name.lower() iso_size = "{} MB".format(int(self.get_iso_size(iso) / 1024)) iso_logo = "" for key, logo in list(self.logos.items()): if key != "iso": if key in iso_name_lower: if len(logo) > len(iso_logo): iso_logo = logo if iso_logo == "": iso_logo = self.logos["iso"] self.log.write("ISO on {}: {}, {}, {}".format( mount, iso_name, iso_size, iso_logo)) isos_list.append([False, iso_logo, iso_name, iso_size]) # Fill treeview self.tvUsbIsosHandler.fillTreeview(contentList=isos_list, columnTypesList=column_types) 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(1000, self.check_thread, name) except Exception as detail: ErrorDialog(self.btnExecute.get_label(), detail) def check_thread(self, name): if self.threads[name].is_alive(): self.set_progress() 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') ret = 0 if not self.queue.empty(): ret = self.queue.get() self.queue.task_done() del self.threads[name] self.set_buttons_state(True) self.on_btnRefresh_clicked() self.fill_treeview_usbcreator(self.device["mount"]) self.set_statusbar_message("{}: {}".format(self.version_text, self.pck_version)) self.show_message(ret) return False def set_buttons_state(self, enable): if not enable: # Disable buttons self.btnExecute.set_sensitive(False) self.btnDelete.set_sensitive(False) self.btnBrowseIso.set_sensitive(False) self.btnRefresh.set_sensitive(False) self.btnUnmount.set_sensitive(False) self.btnClear.set_sensitive(False) self.chkFormatDevice.set_sensitive(False) self.chkRepairDevice.set_sensitive(False) self.cmbDevice.set_sensitive(False) self.txtIso.set_sensitive(False) else: # Enable buttons and reset progress bar self.btnExecute.set_sensitive(True) self.btnDelete.set_sensitive(True) self.btnBrowseIso.set_sensitive(True) self.btnRefresh.set_sensitive(True) self.btnUnmount.set_sensitive(True) self.btnClear.set_sensitive(True) self.chkFormatDevice.set_sensitive(True) self.chkRepairDevice.set_sensitive(True) self.cmbDevice.set_sensitive(True) self.txtIso.set_sensitive(True) self.pbUsbCreator.set_fraction(0) def get_logos(self): logos_dict = {} logos_path = join(self.mediaDir, 'logos') logos = glob(join(logos_path, '*.png')) for logo in logos: key = splitext(basename(logo))[0] logos_dict[key] = logo return logos_dict def set_progress(self): if exists(self.log_file): msg = '' last_line = getoutput( "tail -50 {} | grep -v DEBUG | grep -v ==".format( self.log_file)) for line in reversed(last_line): # Check for session start line: that is the last line to check if ">>>>>" in line and "<<<<<" in line: break for chk_line in self.log_lines: if chk_line[0] in line.lower(): #print((line)) word = '' if chk_line[1] == 0: self.pbUsbCreator.pulse() words = line.split(' ') for word in reversed(words): if word.strip() != '': break else: self.pbUsbCreator.set_fraction( float(chk_line[1] / 100)) msg = "{} {}".format(chk_line[2], word) break if msg != '': break self.set_statusbar_message(msg) def set_statusbar_message(self, message): if message is not None: context = self.statusbar.get_context_id('message') self.statusbar.push(context, message) def get_iso_size(self, iso): # Returns kilobytes iso_info = os.stat(iso) if iso_info: return int(iso_info.st_size / 1024) return 0 # Close the gui def on_usbcreator_destroy(self, widget): # Unmount devices of drive and power-off drive try: if exists(self.device['path']) and \ exists(self.device['mount']): self.udisks2.unmount_drive(self.device['path']) self.udisks2.poweroff_drive(self.device['path']) except Exception as e: self.log.write("ERROR: %s" % str(e)) # Close the app Gtk.main_quit() 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.btnExecute.get_label(), _("Run this application with root permission.")) elif ret == 2: ErrorDialog( self.btnExecute.get_label(), _("Wrong arguments were passed to usb-creator.")) elif ret == 3: ErrorDialog( self.btnExecute.get_label(), _("The device was not found or no device was given.")) elif ret == 4: ErrorDialog(self.btnExecute.get_label(), _("Given ISO path was not found.")) elif ret == 5: ErrorDialog(self.btnExecute.get_label(), _("Device is in use by another application.")) elif ret == 6: ErrorDialog(self.btnExecute.get_label(), _("Unable to mount the device.")) elif ret == 7: ErrorDialog(self.btnExecute.get_label(), _("Hash mismatch.")) elif ret == 8: ErrorDialog(self.btnExecute.get_label(), _("The device has no fat32 partition.")) elif ret == 9: ErrorDialog(self.btnExecute.get_label(), _("The device has no bootloader installed.")) elif ret == 10: ErrorDialog( self.btnExecute.get_label(), _("There is not enough space available on the device.") ) elif ret == 11: ErrorDialog( self.btnExecute.get_label(), _("Unable to guess distribution from ISO name.\n" "Make sure you have the distribution name in the ISO name." )) else: msg = _( "An unknown error accured.\n" "Please, visit our forum for support: http://forums.solydxk.com" ) ErrorDialog(self.window.get_title(), msg) else: msg = _("The USB was successfully written.") MessageDialog(self.window.get_title(), msg) except: ErrorDialog(self.btnExecute.get_label(), cmdOutput) # =============================================== # 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