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 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 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 PartitionDialog(object): def __init__(self, partition, mount_as, format_as): self.partition = partition # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/live-installer-3') self.builder = Gtk.Builder() self.builder.add_from_file(join(self.mediaDir, 'live-installer-3-dialog.glade')) # Main window objects self.go = self.builder.get_object self.window = self.go("dialog") self.window.set_transient_for(installer.window) self.window.set_destroy_with_parent(True) self.window.set_modal(True) self.window.set_title(_("Edit partition")) self.loading = True self.txt_label = self.go("txt_label") self.cmb_mount_point = self.go("combobox_mount_point") self.cmb_mount_point_handler = ComboBoxHandler(self.cmb_mount_point) self.cmb_use_as = self.go("combobox_use_as") self.cmb_use_as_handler = ComboBoxHandler(self.cmb_use_as) # Translations self.go("label_partition").set_markup("<b>%s</b>" % _("Device")) self.go("label_use_as").set_markup(_("Format as")) self.go("label_mount_point").set_markup(_("Mount point")) self.go("label_label").set_markup(_("Label (optional)")) self.go("chk_encryption").set_label(_("Encrypt partition")) self.go("label_encryption_pwd").set_label(_("Password")) # Show the selected partition path self.go("label_partition_value").set_label(self.partition.path) # Encryption self.go("chk_encryption").set_active(partition.encrypt) if partition.encrypt: self.go("frm_partition_encryption").set_sensitive(True) self.go("entry_encpass1").set_text(partition.enc_passphrase) self.go("entry_encpass2").set_text(partition.enc_passphrase) else: self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text('') self.go("entry_encpass2").set_text('') # Label label_len = 16 if "fat" in partition.type or "fat" in partition.mount_as: label_len = 11 self.txt_label.set_max_length(label_len) self.txt_label.set_text(partition.label) # Build list of pre-provided mountpoints mounts = ",/,/home,/boot,/boot/efi,/srv,/tmp,/var,swap".split(',') self.cmb_mount_point_handler.fillComboBox(mounts) # Build supported filesystems list filesystems = sorted(['', 'swap'] + [fs[11:] for fs in getoutput('echo /sbin/mkfs.*').split()], key=lambda x: 0 if x in ('', 'ext4') else 1 if x == 'swap' else 2) self.cmb_use_as_handler.fillComboBox(filesystems) self.cmb_mount_point_handler.selectValue(mount_as) self.cmb_use_as_handler.selectValue(format_as) # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() self.loading = False def on_combobox_mount_point_changed(self, widget): mount_as = self.cmb_mount_point_handler.getValue() if "boot" in mount_as: # Cannot encrypt self.go("chk_encryption").set_active(False) self.go("chk_encryption").set_sensitive(False) self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text('') self.go("entry_encpass2").set_text('') else: # Can encrypt self.loading = True self.go("chk_encryption").set_sensitive(True) self.loading = False # Set label for OS if self.txt_label.get_text() == '': if mount_as == '/': self.txt_label.set_text(get_release_name()) # swap if mount_as == 'swap' and self.partition.type != 'swap': self.cmb_use_as_handler.selectValue('swap') # efi if 'efi' in mount_as and 'fat' not in self.partition.type: self.cmb_use_as_handler.selectValue('vfat') def on_combobox_use_as_changed(self, widget): format_as = self.cmb_use_as_handler.getValue() mount_as = self.cmb_mount_point_handler.getValue() if format_as == 'swap' and mount_as != 'swap': self.cmb_mount_point_handler.selectValue('swap') def on_button_cancel_clicked(self, widget): # Close window without saving self.window.hide() def on_chk_encryption_toggled(self, widget): if self.loading: return if widget.get_active(): # Show warning message mount_as = self.cmb_mount_point_handler.getValue() if mount_as == '/': encrypt = QuestionDialog(_("Encryption"), _("You chose to encrypt the root partition.\n\n" "You will need to mount /boot on a separate non-encrypted partition (500 MB).\n" "Without a non-encrypted /boot partition your system will be unbootable.\n\n" "Encryption will erase all data from {}\n\n" "Are you sure you want to continue?").format(self.partition.path)) else: encrypt = QuestionDialog(_("Encryption"), _("Encryption will erase all data from {}\n\n" "Are you sure you want to continue?").format(self.partition.path)) if encrypt: format_as = self.cmb_use_as_handler.getValue() if not format_as: self.cmb_use_as_handler.selectValue('ext4') self.go("frm_partition_encryption").set_sensitive(True) self.go("entry_encpass1").set_text(self.partition.enc_passphrase) self.go("entry_encpass2").set_text(self.partition.enc_passphrase) self.go("entry_encpass1").grab_focus() else: widget.set_active(False) self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text("") self.go("entry_encpass2").set_text("") else: self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text("") self.go("entry_encpass2").set_text("") def on_entry_encpass1_changed(self, widget): self.assign_enc_password() def on_entry_encpass2_changed(self, widget): self.assign_enc_password() def assign_enc_password(self): encryption_pwd1 = self.go("entry_encpass1").get_text() encryption_pwd2 = self.go("entry_encpass2").get_text() if(encryption_pwd1 == "" and encryption_pwd2 == ""): self.go("image_enc_mismatch").hide() else: self.go("image_enc_mismatch").show() if(encryption_pwd1 != encryption_pwd2): self.go("image_enc_mismatch").set_from_stock(Gtk.STOCK_NO, Gtk.IconSize.BUTTON) else: self.go("image_enc_mismatch").set_from_stock(Gtk.STOCK_OK, Gtk.IconSize.BUTTON) def on_button_ok_clicked(self, widget): # Collect data format_as = self.cmb_use_as_handler.getValue() mount_as = self.cmb_mount_point_handler.getValue() encrypt = self.go("chk_encryption").get_active() enc_passphrase1 = self.go("entry_encpass1").get_text().strip() enc_passphrase2 = self.go("entry_encpass2").get_text().strip() label = self.txt_label.get_text().strip() # Check user input if encrypt: errorFound = False if enc_passphrase1 == "": errorFound = True errorMessage = _("Please provide an encryption password.") elif enc_passphrase1 != enc_passphrase2: errorFound = True errorMessage = _("Your encryption passwords do not match.") elif not format_as: errorFound = True errorMessage = "{} {}".format(_("You need to choose a format type\n" "for your encrypted partition (default: ext4):"), self.partition.path) self.cmb_use_as_handler.selectValue('ext4') if not mount_as: errorFound = True errorMessage = "{} {}".format(_("You need to choose a mount point for partition:"), self.partition.path) if errorFound: ErrorDialog(_("Encryption"), errorMessage) return True else: # For good measure enc_passphrase1 = '' # Save the settings and close the window assign_mount_point(self.partition, mount_as, format_as, encrypt, enc_passphrase1, label) self.window.hide() def on_dialog_delete_event(self, widget, data=None): self.window.hide() return True
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
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 PartitionDialog(object): def __init__(self, partition, mount_as, format_as): self.partition = partition # Load window and widgets self.scriptName = basename(__file__) self.scriptDir = abspath(dirname(__file__)) self.mediaDir = join(self.scriptDir, '../../share/live-installer-3') self.builder = Gtk.Builder() self.builder.add_from_file( join(self.mediaDir, 'live-installer-3-dialog.glade')) # Main window objects self.go = self.builder.get_object self.window = self.go("dialog") self.window.set_transient_for(installer.window) self.window.set_destroy_with_parent(True) self.window.set_modal(True) self.window.set_title(_("Edit partition")) self.loading = True self.txt_label = self.go("txt_label") self.cmb_mount_point = self.go("combobox_mount_point") self.cmb_mount_point_handler = ComboBoxHandler(self.cmb_mount_point) self.cmb_use_as = self.go("combobox_use_as") self.cmb_use_as_handler = ComboBoxHandler(self.cmb_use_as) # Translations self.go("label_partition").set_markup("<b>%s</b>" % _("Device")) self.go("label_use_as").set_markup(_("Format as")) self.go("label_mount_point").set_markup(_("Mount point")) self.go("label_label").set_markup(_("Label (optional)")) self.go("chk_encryption").set_label(_("Encrypt partition")) self.go("label_encryption_pwd").set_label(_("Password")) # Show the selected partition path self.go("label_partition_value").set_label(self.partition.path) # Encryption self.go("chk_encryption").set_active(partition.encrypt) if partition.encrypt: self.go("frm_partition_encryption").set_sensitive(True) self.go("entry_encpass1").set_text(partition.enc_passphrase) self.go("entry_encpass2").set_text(partition.enc_passphrase) else: self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text('') self.go("entry_encpass2").set_text('') # Label label_len = 16 if "fat" in partition.type or "fat" in partition.mount_as: label_len = 11 self.txt_label.set_max_length(label_len) self.txt_label.set_text(partition.label) # Build list of pre-provided mountpoints mounts = ",/,/home,/boot,/boot/efi,/srv,/tmp,/var,swap".split(',') self.cmb_mount_point_handler.fillComboBox(mounts) # Build supported filesystems list filesystems = sorted( ['', 'swap'] + [fs[11:] for fs in getoutput('echo /sbin/mkfs.*').split()], key=lambda x: 0 if x in ('', 'ext4') else 1 if x == 'swap' else 2) self.cmb_use_as_handler.fillComboBox(filesystems) self.cmb_mount_point_handler.selectValue(mount_as) self.cmb_use_as_handler.selectValue(format_as) # Connect builder signals and show window self.builder.connect_signals(self) self.window.show_all() self.loading = False def on_combobox_mount_point_changed(self, widget): mount_as = self.cmb_mount_point_handler.getValue() if "boot" in mount_as: # Cannot encrypt self.go("chk_encryption").set_active(False) self.go("chk_encryption").set_sensitive(False) self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text('') self.go("entry_encpass2").set_text('') else: # Can encrypt self.loading = True self.go("chk_encryption").set_sensitive(True) self.loading = False # Set label for OS if self.txt_label.get_text() == '': if mount_as == '/': self.txt_label.set_text(get_release_name()) # swap if mount_as == 'swap' and self.partition.type != 'swap': self.cmb_use_as_handler.selectValue('swap') # efi if 'efi' in mount_as and 'fat' not in self.partition.type: self.cmb_use_as_handler.selectValue('vfat') def on_combobox_use_as_changed(self, widget): format_as = self.cmb_use_as_handler.getValue() mount_as = self.cmb_mount_point_handler.getValue() if format_as == 'swap' and mount_as != 'swap': self.cmb_mount_point_handler.selectValue('swap') def on_button_cancel_clicked(self, widget): # Close window without saving self.window.hide() def on_chk_encryption_toggled(self, widget): if self.loading: return if widget.get_active(): # Show warning message mount_as = self.cmb_mount_point_handler.getValue() if mount_as == '/': encrypt = QuestionDialog( _("Encryption"), _("You chose to encrypt the root partition.\n\n" "You will need to mount /boot on a separate non-encrypted partition (500 MB).\n" "Without a non-encrypted /boot partition your system will be unbootable.\n\n" "Encryption will erase all data from {}\n\n" "Are you sure you want to continue?").format( self.partition.path)) else: encrypt = QuestionDialog( _("Encryption"), _("Encryption will erase all data from {}\n\n" "Are you sure you want to continue?").format( self.partition.path)) if encrypt: format_as = self.cmb_use_as_handler.getValue() if not format_as: self.cmb_use_as_handler.selectValue('ext4') self.go("frm_partition_encryption").set_sensitive(True) self.go("entry_encpass1").set_text( self.partition.enc_passphrase) self.go("entry_encpass2").set_text( self.partition.enc_passphrase) self.go("entry_encpass1").grab_focus() else: widget.set_active(False) self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text("") self.go("entry_encpass2").set_text("") else: self.go("frm_partition_encryption").set_sensitive(False) self.go("entry_encpass1").set_text("") self.go("entry_encpass2").set_text("") def on_entry_encpass1_changed(self, widget): self.assign_enc_password() def on_entry_encpass2_changed(self, widget): self.assign_enc_password() def assign_enc_password(self): encryption_pwd1 = self.go("entry_encpass1").get_text() encryption_pwd2 = self.go("entry_encpass2").get_text() if (encryption_pwd1 == "" and encryption_pwd2 == ""): self.go("image_enc_mismatch").hide() else: self.go("image_enc_mismatch").show() if (encryption_pwd1 != encryption_pwd2): self.go("image_enc_mismatch").set_from_stock( Gtk.STOCK_NO, Gtk.IconSize.BUTTON) else: self.go("image_enc_mismatch").set_from_stock( Gtk.STOCK_OK, Gtk.IconSize.BUTTON) def on_button_ok_clicked(self, widget): # Collect data format_as = self.cmb_use_as_handler.getValue() mount_as = self.cmb_mount_point_handler.getValue() encrypt = self.go("chk_encryption").get_active() enc_passphrase1 = self.go("entry_encpass1").get_text().strip() enc_passphrase2 = self.go("entry_encpass2").get_text().strip() label = self.txt_label.get_text().strip() # Check user input if encrypt: errorFound = False if enc_passphrase1 == "": errorFound = True errorMessage = _("Please provide an encryption password.") elif enc_passphrase1 != enc_passphrase2: errorFound = True errorMessage = _("Your encryption passwords do not match.") elif not format_as: errorFound = True errorMessage = "{} {}".format( _("You need to choose a format type\n" "for your encrypted partition (default: ext4):"), self.partition.path) self.cmb_use_as_handler.selectValue('ext4') if not mount_as: errorFound = True errorMessage = "{} {}".format( _("You need to choose a mount point for partition:"), self.partition.path) if errorFound: ErrorDialog(_("Encryption"), errorMessage) return True else: # For good measure enc_passphrase1 = '' # Save the settings and close the window assign_mount_point(self.partition, mount_as, format_as, encrypt, enc_passphrase1, label) self.window.hide() def on_dialog_delete_event(self, widget, data=None): self.window.hide() return True