def showException(ex_type, tb): title = _("An error occured") closeButton = True if ex_type in (yali.exception_fatal, yali.exception_pisi): closeButton = False ctx.debugger.log(tb) d = Dialog(title, ExceptionWidget(tb, not closeButton), None, closeButton, icon="error") d.resize(300,160) d.exec_()
def showException(error_type, error_traceback): title = _("An error occured") closeButton = True if error_type in (yali.exception_yali, yali.exception_pisi): closeButton = False ctx.logger.debug(error_traceback) d = Dialog(title, ExceptionWidget(error_traceback, not closeButton), None, closeButton, icon="error") d.resize(300,160) d.exec_()
class ShrinkEditor: def __init__(self, parent, storage): self.storage = storage self.intf = parent.intf self.parent = parent self.dialog = Dialog(_("Partitions to Shrink"), closeButton=False) self.dialog.addWidget(ShrinkWidget(self)) self.dialog.resize(QSize(0,0)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return (rc, operations) widget = self.dialog.content request = widget.partitions.itemData(widget.partitions.currentIndex())#.toPyObject() burada hata olabilir newsize = widget.sizeSpin.value() try: operations.append(OperationResizeFormat(request, newsize)) except ValueError as e: self.intf.messageWindow(_("Resize FileSystem Error"), _("%(device)s: %(msg)s") % {'device': request.format.device, 'msg': e.message}, type="error") continue try: operations.append(OperationResizeDevice(request, newsize)) except ValueError as e: self.intf.messageWindow(_("Resize Device Error"), _("%(name)s: %(msg)s") % {'name': request.name, 'msg': e.message}, type="warning") continue # everything ok, fall out of loop break self.dialog.destroy() return (rc, operations) def destroy(self): if self.dialog: self.dialog = None
class ShrinkEditor: def __init__(self, parent, storage): self.storage = storage self.intf = parent.intf self.parent = parent self.dialog = Dialog(_("Partitions to Shrink"), closeButton=False) self.dialog.addWidget(ShrinkWidget(self)) self.dialog.resize(QSize(0,0)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return (rc, operations) widget = self.dialog.content request = widget.partitions.itemData(widget.partitions.currentIndex()).toPyObject() newsize = widget.sizeSpin.value() try: operations.append(OperationResizeFormat(request, newsize)) except ValueError as e: self.intf.messageWindow(_("Resize FileSystem Error"), _("%(device)s: %(msg)s") % {'device': request.format.device, 'msg': e.message}, type="error") continue try: operations.append(OperationResizeDevice(request, newsize)) except ValueError as e: self.intf.messageWindow(_("Resize Device Error"), _("%(name)s: %(msg)s") % {'name': request.name, 'msg': e.message}, type="warning") continue # everything ok, fall out of loop break self.dialog.destroy() return (rc, operations) def destroy(self): if self.dialog: self.dialog = None
class Widget(QWidget): signalProcessEvents = pyqtSignal() def __init__(self): QWidget.__init__(self, None) # Set pixmaps resource before Main Window initialized self._resource = os.path.join(ctx.consts.theme_dir, ctx.flags.theme, ctx.consts.pixmaps_resource_file) if os.path.exists(self._resource): resource = QResource() resource.registerResource(self._resource) else: raise yali.Error, _("Pixmaps resources file doesn't exists") self.ui = Ui_YaliMain() self.ui.setupUi(self) self.font = 10 self.animation_type = None self.screens = None self.screens_content = None self.pds_helper = HelpWidget(self.ui.scrollAreaWidgetContents) # shortcut to open help self.help_shortcut = QShortcut(QKeySequence(Qt.Key_F1), self) # shortcut to open debug window #self.debugShortCut = QtWidgets.QShortcut(QtWidgets.QKeySequence(Qt.Key_F2),self) # something funny self.tetris_shortcut = QShortcut(QKeySequence(Qt.Key_F6), self) self.cursor_shortcut = QShortcut(QKeySequence(Qt.Key_F7), self) self.theme_shortcut = QShortcut(QKeySequence(Qt.Key_F8), self) # shortcut to open a console self.console_shortcut = QShortcut(QKeySequence(Qt.Key_F11), self) # set style self._style = os.path.join(ctx.consts.theme_dir, ctx.flags.theme, ctx.consts.style_file) if os.path.exists(self._style): self.updateStyle() else: raise yali.Error, _("Style file doesn't exists") # set screens content release_file = os.path.join(ctx.consts.branding_dir, ctx.flags.branding, ctx.consts.release_file) if os.path.exists(release_file): self.screens_content = yali.util.parse_branding_screens( release_file) else: raise yali.Error, _("Release file doesn't exists") # move one step at a time self.step_increment = 1 # ToolButton Popup Menu self.menu = QMenu() self.shutdown = self.menu.addAction( QIcon(QPixmap(":/images/system-shutdown.png")), _("Turn Off Computer")) self.reboot = self.menu.addAction( QIcon(QPixmap(":/images/system-reboot.png")), _("Restart Computer")) self.restart = self.menu.addAction( QIcon(QPixmap(":/images/system-yali-reboot.png")), _("Restart YALI")) #self.menu.setDefaultAction(self.shutdown) self.ui.system_menu.setMenu(self.menu) self.ui.system_menu.setDefaultAction(self.shutdown) # Main Slots self.help_shortcut.activated.connect(self.pds_helper.toggleHelp) #self.debugShortCut.activated.connect(self.toggleDebug) self.console_shortcut.activated.connect(self.toggleConsole) self.cursor_shortcut.activated.connect(self.toggleCursor) self.theme_shortcut.activated.connect(self.toggleTheme) self.tetris_shortcut.activated.connect(self.toggleTetris) self.ui.buttonNext.clicked.connect(self.slotNext) self.ui.buttonBack.clicked.connect(self.slotBack) self.ui.toggleHelp.clicked.connect(self.pds_helper.toggleHelp) if not ctx.flags.install_type == ctx.STEP_FIRST_BOOT: self.ui.releaseNotes.clicked.connect(self.showReleaseNotes) else: self.ui.releaseNotes.hide() self.menu.triggered[QAction].connect(self.slotMenu) self.cmb = _("right") self.dont_ask_again = False self.terminal = None self.tetris = None self.ui.helpContentFrame.hide() self.effect = QGraphicsOpacityEffect(self) self.ui.mainStack.setGraphicsEffect(self.effect) self.effect.setOpacity(1.0) self.anime = QTimer(self) self.anime.timeout.connect(self.animate) def mousePressEvent(self, event): if event.button() == Qt.RightButton and not self.dont_ask_again: if self.cmb == _("left"): ocmb = _("right") else: ocmb = _("left") reply = QuestionDialog( _("Mouse Settings"), _("You just clicked the <b>%s</b> mouse button.") % self.cmb, _("Do you want to switch to the <b>%s</b> handed configuration?" ) % ocmb, dontAsk=True) if reply == "yes": yali.sysutils.setMouse(self.cmb) self.cmb = ocmb elif reply == "dontask": self.dont_ask_again = True def updateStyle(self): self.setStyleSheet(file(self._style).read()) self.font = 10 def setFontPlus(self): self.increaseFontSize(1) def setFontMinus(self): self.increaseFontSize(-1) def increaseFontSize(self, num): # We have to edit style sheet to set new fonts # Because if you use a style sheet in your application # ::setFont gets useless :( http://doc.trolltech.com/4.5/qapplication.html#setFont old = "QWidget{font:%dpt;}" % self.font self.font = self.font + num new = "QWidget{font:%dpt;}" % self.font self.setStyleSheet(self.styleSheet().replace(old, new)) def slotMenu(self, action): if action == self.shutdown: reply = QuestionDialog( _("Warning"), _("Are you sure you want to shut down your computer now?")) if reply == "yes": yali.util.shutdown() elif action == self.reboot: reply = QuestionDialog( _("Warning"), _("Are you sure you want to restart your computer now?")) if reply == "yes": yali.util.reboot() else: reply = QuestionDialog( _("Warning"), _("Are you sure you want to restart the YALI installer now?")) if reply == "yes": os.execv("/usr/bin/yali-bin", sys.argv) def toggleTheme(self): "This easter egg will be implemented later" """ if self._style == os.path.join(ctx.consts.theme_dir, "%s/style.qss" % ctx.flags.theme): if os.path.join(ctx.consts.theme_dir, "%s/style.glass.qss" % ctx.flags.theme): self._style = os.path.join(ctx.consts.theme_dir, "%s/style.glass.qss" % ctx.flags.theme) else: self._style = os.path.join(ctx.consts.theme_dir, "%s/style.qss" % ctx.flags.theme) self.updateStyle() """ def toggleConsole(self): if not self.terminal: terminal = QTermWidget() terminal.setScrollBarPosition(QTermWidget.ScrollBarRight) terminal.setColorScheme(1) terminal.sendText("export TERM='xterm'\nclear\n") self.terminal = Dialog(_("Terminal"), terminal, True, QKeySequence(Qt.Key_F11)) self.terminal.resize(700, 500) self.terminal.exec_() def toggleTetris(self): self.tetris = Dialog(_("Tetris"), None, True, QKeySequence(Qt.Key_F6)) _tetris = Tetris(self.tetris) self.tetris.addWidget(_tetris) self.tetris.resize(240, 500) _tetris.start() self.tetris.exec_() def toggleCursor(self): if self.cursor().shape() == QCursor(Qt.ArrowCursor).shape(): raw = QPixmap(":/gui/pics/pardusman-icon.png") raw.setMask(raw.mask()) self.setCursor(QCursor(raw, 2, 2)) else: self.unsetCursor() # show/hide help text def slotToggleHelp(self): self.ui.helpContentFrame.setFixedHeight(self.ui.helpContent.height()) if self.ui.helpContentFrame.isVisible(): self.ui.helpContentFrame.hide() else: self.ui.helpContentFrame.show() widget = self.ui.mainStack.currentWidget() widget.update() # show/hide debug window def toggleDebug(self): if ctx.debugger.isVisible(): ctx.debugger.hideWindow() else: ctx.debugger.showWindow() # returns the id of current stack def getCurrent(self, index): new_index = self.ui.mainStack.currentIndex() + index total_index = self.ui.mainStack.count() if new_index < 0: new_index = 0 if new_index > total_index: new_index = total_index return new_index # move to id numbered step def setCurrent(self, index=None): if index: self.stackMove(index) # execute next step def slotNext(self, dry_run=False): widget = self.ui.mainStack.currentWidget() ret = True if not dry_run: ret = widget.execute() if ret: self.pds_helper.hideHelp() self.ui.toggleHelp.setChecked(False) self.stackMove(self.getCurrent(self.step_increment)) self.step_increment = 1 # execute previous step def slotBack(self): widget = self.ui.mainStack.currentWidget() if widget.backCheck(): self.stackMove(self.getCurrent(self.step_increment * -1)) self.pds_helper.hideHelp() self.ui.toggleHelp.setChecked(False) self.step_increment = 1 # move to id numbered stack def stackMove(self, index): if not index == self.ui.mainStack.currentIndex() or index == 0: self.effect.setOpacity(0.0) self.animation_type = "fade-in" self.anime.start(50) self.ui.mainStack.setCurrentIndex(index) widget = self.ui.mainStack.currentWidget() # Hack to fix goodbye screen help content # BUG:#15860, #15444 if widget.name == "goodbye": widget_id = "%s%s" % (widget.name, ctx.flags.install_type) else: widget_id = widget.name widget_icon = self.screens_content[widget_id][0] if self.screens_content[widget_id][1].has_key(ctx.consts.lang): widget_title = self.screens_content[widget_id][1][ ctx.consts.lang] else: widget_title = self.screens_content[widget_id][1]["en"] if self.screens_content[widget_id][2].has_key(ctx.consts.lang): widget_help = self.screens_content[widget_id][2][ ctx.consts.lang] else: widget_help = self.screens_content[widget_id][2]["en"] self.ui.screenName.setText(widget_title) self.pds_helper.ui.helpContent.setText(widget_help) self.pds_helper.setHelp(widget_help) self.ui.screenIcon.setPixmap( QPixmap(":/gui/pics/%s.png" % (widget_icon))) ctx.mainScreen.processEvents() widget.update() ctx.mainScreen.processEvents() widget.shown() def animate(self): if self.animation_type == "fade-in": if self.effect.opacity() < 1.0: self.effect.setOpacity(self.effect.opacity() + 0.2) else: self.anime.stop() if self.animation_type == "fade-out": if self.effect.opacity() > 0.0: self.effect.setOpacity(self.effect.opacity() - 0.2) else: self.anime.stop() def createWidgets(self, screens=[]): if not self.screens: self.screens = screens self.ui.mainStack.removeWidget(self.ui.page) for screen in screens: #if ctx.flags.debug: # debug all screens. # weave_all_object_methods(ctx.aspect, screen) # enable navigation buttons before shown weave_object_method(enableNavButtonsAspect, screen, "shown") # disable navigation buttons before the execute. weave_object_method(disableNavButtonsAspect, screen, "execute") try: self.ui.mainStack.addWidget(screen()) except Exception, msg: rc = ctx.interface.messageWindow( _("Error"), _("An error occurred when attempting " "to load screens:%s") % msg, type="custom", customIcon="error", customButtons=[_("Exit")]) if not rc: sys.exit(0) #weave_all_object_methods(ctx.aspect, self) self.stackMove(ctx.flags.startup)
def showReleaseNotes(self): # make a release notes dialog dialog = Dialog(_('Release Notes'), ReleaseNotes(self), self) dialog.resize(500, 400) dialog.exec_()
class LogicalVolumeEditor: def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.parent.storage self.intf = parent.parent.intf self.origrequest = request self.isNew = isNew if isNew: title = _("Make Logical Volume") else: title = _("Edit Logical Volume: %s") % request.lvname self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(LogicalVolumeWidget(self, request, isNew)) self.dialog.resize(QSize(0, 0)) def run(self): if self.dialog is None: return None while 1: rc = self.dialog.exec_() if not rc: if self.isNew: if self.parent.parent.lvs.has_key(self.origrequest.lvname): del self.parent.parent.lvs[self.origrequest.lvname] self.destroy() return None format = None widget = self.dialog.content format = self.origrequest.format mountpoint = unicode(widget.mountpointMenu.currentText()) if mountpoint and widget.mountpointMenu.isEditable(): msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue if not self.origrequest.exists: format_type = str(widget.filesystemMenu.currentText()) else: format_type = str(widget.formatCombo.currentText()) format_class = formats.getFormat(format_type) if mountpoint and format_class.mountable: used = False current_mountpoint = getattr(format, "mountpoint", None) for lv in self.parent.parent.lvs.values(): format = lv["format"] if not format.mountable or current_mountpoint and \ format.mountpoint == current_mountpoint: continue if format.mountpoint == mountpoint: used = True break for (mp, dev) in self.parent.parent.storage.mountpoints.iteritems(): if (dev.type != "lvmlv" or dev.vg.id != self.origrequest.vg.id) and mp == mountpoint: used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue name = str(widget.name.text()) if not self.origrequest.exists: msg = sanityCheckLogicalVolumeName(name) if msg: self.intf.messageWindow(_("Illegal Logical Volume Name"), msg, type="warning") continue # check that the name is not already in use used = 0 for lv in self.parent.parent.lvs.values(): if self.origrequest.lvname != name and lv['name'] == name: used = 1 break if used: self.intf.messageWindow(_("Illegal logical volume name"), _("The logical volume name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue if not self.origrequest.exists: badsize = 0 try: size = long(widget.sizeSpin.value()) except: size = 1 if badsize or size <= 0: self.intf.messageWindow(_("Illegal size"), _("The requested size as entered is " "not a valid number greater than 0."), type="warning") continue else: size = self.origrequest.size # check that size specification is within limits peSize = self.parent.physicalExtends.itemData(self.parent.physicalExtends.currentIndex()).toInt()[0] / 1024 size = lvm.clampSize(size, peSize, roundup=True) maximumVolumeSize = lvm.getMaxLVSize() if size > maximumVolumeSize: self.intf.messageWindow(_("Not enough space"), _("The current requested size " "(%(size)10.2f MB) is larger than " "the maximum logical volume size " "(%(maxlv)10.2f MB). " "To increase this limit you can " "create more Physical Volumes from " "unpartitioned disk space and " "add them to this Volume Group.") % {'size': size, 'maxlv': maximumVolumeSize}, type="warning") continue # Get format origname = self.origrequest.lvname if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) self.origrequest._name = name try: self.origrequest.size = size except ValueError, msg: self.intf.messageWindow(_("Not enough space"), _("The size entered for this " "logical volume (%(size)d MB) " "combined with the size of the " "other logical volume(s) " "exceeds the size of the " "volume group (%(tmpvgsize)d " "MB). Please make the volume " "group larger or make the " "logical volume smaller.") % {'size': size, 'tmpvgsize': self.origrequest.vg.size}, type="warning") continue else: self.origrequest.format = format else: if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) self.origrequest.format = format else: self.origrequest.format = self.origrequest.originalFormat if widget.migrateRadio.isChecked(): self.origrequest.format.migrate = True if widget.resizeRadio.isChecked(): self.origrequest.targetSize = widget.resizeSpin.value() if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if self.origrequest.format.exists and \ self.origrequest.format.mountable and \ self.origrequest.format.mountpoint: if self.storage.formatByDefault(self.origrequest) and \ not queryNoFormatPreExisting(self.intf): continue # everything ok break if self.parent.parent.lvs.has_key(origname) and origname != self.origrequest.lvname: del self.parent.parent.lvs[origname] return {'name': self.origrequest.lvname, 'size': self.origrequest.size, 'format': self.origrequest.format, 'originalFormat': self.origrequest.originalFormat, 'stripes': self.origrequest.stripes, 'logSize': self.origrequest.logSize, 'snapshotSpace': self.origrequest.snapshotSpace, 'exists': self.origrequest.exists}
class PartitionEditor: def __init__(self, parent, origrequest, isNew=False, partedPartition=None, restricts=None): self.storage = parent.storage self.intf = parent.intf self.origrequest = origrequest self.isNew = isNew self.parent = parent self.partedPartition = partedPartition if isNew: title = _("Create Partition on %(path)s (%(model)s)") % {"path":os.path.basename(partedPartition.disk.device.path), "model":partedPartition.disk.device.model} else: try: title = _("Edit Partition %s") % origrequest.path except: title = _("Edit Partition") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(PartitionWidget(self, origrequest, isNew, restricts)) self.dialog.resize(QSize(350, 175)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: ctx.interface.messageWindow(_("Mount Point Error"), msg, type="warning") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: ctx.interface.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue if not self.origrequest.exists: if widget.primaryCheck.isChecked(): primary = True else: primary = None size = widget.sizeSpin.value() formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) if self.isNew: disk = self.storage.devicetree.getDeviceByPath(self.partedPartition.disk.device.path) else: disk = self.origrequest.disk err = doUIRAIDLVMChecks(format, [disk.name], self.storage) if err: self.intf.messageWindow(_("Error With Request"), err, type="error") continue weight = partitioning.weight(mountpoint=mountpoint, fstype=format.type) if self.isNew: request = self.storage.newPartition(size=size, grow=None, maxsize=0, primary=primary, format=format, parents=disk) else: request = self.origrequest request.weight = weight usedev = request if self.isNew: operations.append(OperationCreateDevice(request)) else: request.req_size = size request.req_base_size = size request.req_grow = None request.req_max_size = 0 request.req_primary = primary request.req_disks = [disk] operations.append(OperationCreateFormat(usedev, format)) else: # preexisting partition request = self.origrequest usedev = request origformat = usedev.format devicetree = self.storage.devicetree if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=usedev.path) operations.append(OperationCreateFormat(usedev, format)) else: cancel = [] cancel.extend(devicetree.findOperations(type="destroy", object="format", devid=request.id)) cancel.extend(devicetree.findOperations(type="create", object="format", devid=request.id)) cancel.reverse() for operation in cancel: devicetree.removeOperation(operation) request.format = request.originalFormat usedev = request if usedev.format.mountable: usedev.format.mountpoint = mountpoint if self.origrequest.protected and usedev.format.mountable: # users can set a mountpoint for protected partitions usedev.format.mountpoint = mountpoint request.weight = partitioning.weight(mountpoint=mountpoint, fstype=request.format.type) if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(usedev)) if widget.resizeRadio.isChecked(): size = widget.resizeSpin.value() try: operations.append(OperationResizeDevice(request, size)) if request.format.type and request.format.exists: operations.append(OperationResizeFormat(request, size)) except ValueError: pass if request.format.exists and \ getattr(request, "mountpoint", None) and \ self.storage.formatByDefault(request): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations def destroy(self): if self.dialog: self.dialog = None
class LVMEditor(object): def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.storage self.origrequest = request self.peSize = request.peSize self.pvs = request.pvs[:] self.isNew = isNew self.intf = parent.intf self.operations = [] self.dialog = None self.lvs = {} for lv in self.origrequest.lvs: self.lvs[lv.lvname] = {"name": lv.lvname, "size": lv.size, "format": copy.copy(lv.format), "originalFormat": lv.originalFormat, "stripes": lv.stripes, "logSize": lv.logSize, "snapshotSpace": lv.snapshotSpace, "exists": lv.exists} self.availlvmparts = self.storage.unusedPVS(vg=request) # if no PV exist, raise an error message and return if len(self.availlvmparts) < 1: self.intf.messageWindow(_("Not enough physical volumes"), _("At least one unused physical " "volume partition is " "needed to\ncreate an LVM Volume Group.\n" "Create a partition or RAID array " "of type \"physical volume\n(LVM)\" and then " "select the \"LVM\" option again."), type="warning") self.dialog = None return if isNew: title = _("Make LVM Volume Group") else: try: title = _("Edit LVM Volume Group: %s") % (request.name,) except AttributeError: title = _("Edit LVM Volume Group") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(VolumeGroupWidget(self, self.origrequest, isNew=isNew)) self.dialog.resize(QSize(450, 200)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: if self.isNew: if self.lvs.has_key(self.origrequest.name): del self.lvs[self.origrequest.name] self.destroy() return [] widget = self.dialog.content name = str(widget.name.text()) pvs = widget.selectedPhysicalVolumes msg = sanityCheckVolumeGroupName(name) if msg: self.intf.messageWindow(_("Invalid Volume Group Name"), msg, type="warning") continue origname = self.origrequest.name if origname != name: if name in [vg.name for vg in self.storage.vgs]: self.intf.messageWindow(_("Name in use"), _("The volume group name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue peSize = widget.physicalExtends.itemData(widget.physicalExtends.currentIndex()).toInt()[0] / 1024.0 origlvs = self.origrequest.lvs if not self.origrequest.exists: ctx.logger.debug("non-existing vg -- setting up lvs, pvs, name, peSize") for lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) for pv in self.origrequest.pvs: if pv not in self.pvs: self.origrequest._removePhysicalVolume(pv) for pv in self.pvs: if pv not in self.origrequest.pvs: self.origrequest._addPhysicalVolume(pv) self.origrequest.name = name self.origrequest.peSize = peSize if self.isNew: operations = [OperationCreateDevice(self.origrequest)] for lv in origlvs: ctx.logger.debug("old lv %s..." % lv.lvname) if not lv.exists or lv.lvname not in self.lvs or \ (not self.lvs[lv.lvname]['exists'] and lv.exists): ctx.logger.debug("removing lv %s" % lv.lvname) if lv.format.type: operations.append(OperationDestroyFormat(lv)) if lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) operations.append(OperationDestroyDevice(lv)) # schedule creation of all new lvs, their formats, luks devices, &c tempvg = widget.tmpVolumeGroup for lv in tempvg.lvs: ctx.logger.debug("new lv %s" % lv) if not lv.exists: ctx.logger.debug("creating lv %s" % lv.lvname) logicalvolume = LogicalVolume(lv.lvname, self.origrequest, size=lv.size) operations.append(OperationCreateDevice(logicalvolume)) # create the format mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=logicalvolume.path) operations.append(OperationCreateFormat(logicalvolume, format)) else: ctx.logger.debug("lv %s already exists" % lv.lvname) origlv = widget.getLogicalVolumeByName(lv.lvname) if lv.resizable and lv.targetSize != origlv.size: operations.append(OperationResizeDevice(origlv, lv.targetSize)) if lv.format.exists: ctx.logger.debug("format already exists") usedev = origlv format = lv.format if format == usedev.originalFormat: cancel = [] cancel.extend(self.parent.storage.devicetree.findOperations(type="create", object="format", devid=origlv.id)) cancel.extend(self.parent.storage.devicetree.findOperations(type="destroy", object="format", devid=origlv.id)) for operation in cancel: self.storage.devicetree.cancelOperation(operation) if hasattr(format, "mountpoint"): usedev.format.mountpoint = format.mountpoint if format.migratable and format.migrate and \ not usedev.format.migrate: usedev.format.migrate = format.migrate operations.append(OperationMigrateFormat(usedev)) if format.resizable and lv.format.resizable and \ lv.targetSize != format.targetSize and \ lv.targetSize != lv.currentSize and \ usedev.format.exists: ctx.logger.debug("resizing format on %s to %d" % (usedev.lvname, lv.targetSize)) operations.append(OperationResizeFormat(usedev, lv.targetSize)) elif lv.format.type: ctx.logger.debug("new format: %s" % lv.format.type) if origlv.format.type: operations.append(OperationDestroyFormat(origlv)) mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=origlv.path) operations.append(OperationCreateFormat(origlv, format)) else: ctx.logger.debug("no format!") break return operations def destroy(self): if self.dialog: self.dialog = None
class LVMEditor(object): def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.storage self.origrequest = request self.peSize = request.peSize self.pvs = request.pvs[:] self.isNew = isNew self.intf = parent.intf self.operations = [] self.dialog = None self.lvs = {} for lv in self.origrequest.lvs: self.lvs[lv.lvname] = {"name": lv.lvname, "size": lv.size, "format": copy.copy(lv.format), "originalFormat": lv.originalFormat, "stripes": lv.stripes, "logSize": lv.logSize, "snapshotSpace": lv.snapshotSpace, "exists": lv.exists} self.availlvmparts = self.storage.unusedPVS(vg=request) # if no PV exist, raise an error message and return if len(self.availlvmparts) < 1: self.intf.messageWindow(_("Not enough physical volumes"), _("At least one unused physical " "volume partition is " "needed to\ncreate an LVM Volume Group.\n" "Create a partition or RAID array " "of type \"physical volume\n(LVM)\" and then " "select the \"LVM\" option again."), type="warning") self.dialog = None return if isNew: title = _("Make LVM Volume Group") else: try: title = _("Edit LVM Volume Group: %s") % (request.name,) except AttributeError: title = _("Edit LVM Volume Group") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(VolumeGroupWidget(self, self.origrequest, isNew=isNew)) self.dialog.resize(QSize(450, 200)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: if self.isNew: if self.lvs.has_key(self.origrequest.name): del self.lvs[self.origrequest.name] self.destroy() return [] widget = self.dialog.content name = str(widget.name.text()) pvs = widget.selectedPhysicalVolumes msg = sanityCheckVolumeGroupName(name) if msg: self.intf.messageWindow(_("Invalid Volume Group Name"), msg, type="warning") continue origname = self.origrequest.name if origname != name: if name in [vg.name for vg in self.storage.vgs]: self.intf.messageWindow(_("Name in use"), _("The volume group name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue peSize = int(widget.physicalExtends.itemData(widget.physicalExtends.currentIndex())) / 1024.0 origlvs = self.origrequest.lvs if not self.origrequest.exists: ctx.logger.debug("non-existing vg -- setting up lvs, pvs, name, peSize") for lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) for pv in self.origrequest.pvs: if pv not in self.pvs: self.origrequest._removePhysicalVolume(pv) for pv in self.pvs: if pv not in self.origrequest.pvs: self.origrequest._addPhysicalVolume(pv) self.origrequest.name = name self.origrequest.peSize = peSize if self.isNew: operations = [OperationCreateDevice(self.origrequest)] for lv in origlvs: ctx.logger.debug("old lv %s..." % lv.lvname) if not lv.exists or lv.lvname not in self.lvs or \ (not self.lvs[lv.lvname]['exists'] and lv.exists): ctx.logger.debug("removing lv %s" % lv.lvname) if lv.format.type: operations.append(OperationDestroyFormat(lv)) if lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) operations.append(OperationDestroyDevice(lv)) # schedule creation of all new lvs, their formats, luks devices, &c tempvg = widget.tmpVolumeGroup for lv in tempvg.lvs: ctx.logger.debug("new lv %s" % lv) if not lv.exists: ctx.logger.debug("creating lv %s" % lv.lvname) logicalvolume = LogicalVolume(lv.lvname, self.origrequest, size=lv.size) operations.append(OperationCreateDevice(logicalvolume)) # create the format mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=logicalvolume.path) operations.append(OperationCreateFormat(logicalvolume, format)) else: ctx.logger.debug("lv %s already exists" % lv.lvname) origlv = widget.getLogicalVolumeByName(lv.lvname) if lv.resizable and lv.targetSize != origlv.size: operations.append(OperationResizeDevice(origlv, lv.targetSize)) if lv.format.exists: ctx.logger.debug("format already exists") usedev = origlv format = lv.format if format == usedev.originalFormat: cancel = [] cancel.extend(self.parent.storage.devicetree.findOperations(type="create", object="format", devid=origlv.id)) cancel.extend(self.parent.storage.devicetree.findOperations(type="destroy", object="format", devid=origlv.id)) for operation in cancel: self.storage.devicetree.cancelOperation(operation) if hasattr(format, "mountpoint"): usedev.format.mountpoint = format.mountpoint if format.migratable and format.migrate and \ not usedev.format.migrate: usedev.format.migrate = format.migrate operations.append(OperationMigrateFormat(usedev)) if format.resizable and lv.format.resizable and \ lv.targetSize != format.targetSize and \ lv.targetSize != lv.currentSize and \ usedev.format.exists: ctx.logger.debug("resizing format on %s to %d" % (usedev.lvname, lv.targetSize)) operations.append(OperationResizeFormat(usedev, lv.targetSize)) elif lv.format.type: ctx.logger.debug("new format: %s" % lv.format.type) if origlv.format.type: operations.append(OperationDestroyFormat(origlv)) mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=origlv.path) operations.append(OperationCreateFormat(origlv, format)) else: ctx.logger.debug("no format!") break return operations def destroy(self): if self.dialog: self.dialog = None
class RaidEditor(object): def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.storage self.intf = parent.intf self.origrequest = request self.isNew = isNew availraidparts = self.parent.storage.unusedRaidMembers( array=self.origrequest) if availraidparts < 2: self.intf.messageWindow(_("Invalid Raid Members"), _("At least two unused software RAID " "partitions are needed to create " "a RAID device.\n\n" "First create at least two partitions " "of type \"software RAID\", and then " "select the \"RAID\" option again."), type="error") return if isNew: title = _("Make RAID Device") else: if request.minor is not None: title = _("Edit RAID Device: %s") % request.path else: title = _("Edit RAID Device") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(RaidWidget(self, request, isNew)) self.dialog.resize(QSize(450, 200)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] raidmembers = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint, ), type="warning") continue for index in range(widget.raidMembers.count()): if widget.raidMembers.item(index).checkState() == Qt.Checked: raidmembers.append( widget.raidMembers.item(index).partition) # The user has to select some devices to be part of the array. if not raidmembers: raidlevel = int( widget.raidLevels.itemData( widget.raidLevels.currentIndex())) self.intf.messageWindow( _("Invalid Raid Members"), _("A RAID%(level)d set requires at least %(min_member)d member" ) % { "level": raidlevel, "min_member": raid.get_raid_min_members(raidlevel) }, type="warning") continue if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) raidminor = int( widget.raidMinors.itemData( widget.raidMinors.currentIndex())) raidlevel = int( widget.raidLevels.itemData( widget.raidLevels.currentIndex())) if not raid.isRaid(raid.RAID0, raidlevel): spares = widget.spareSpin.value() else: spares = 0 format = formats.getFormat(formatType, mountpoint=mountpoint) members = len(raidmembers) - spares try: request = self.storage.newRaidArray( minor=raidminor, level=raidlevel, format=format, parents=raidmembers, totalDevices=len(raidmembers), memberDevices=members) except ValueError, msg: self.intf.messageWindow(_("Invalid Raid Members"), unicode(msg), type="warning") continue if not self.isNew: # This may be handled in devicetree.registerAction, # but not in case when we change minor and thus # device name/path (at least with current md) operations.append(OperationDestroyDevice(self.origrequest)) operations.append(OperationCreateDevice(request)) operations.append(OperationCreateFormat(request)) else: format = None if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) operations.append( OperationCreateFormat(self.origrequest, format)) else: cancel = [] cancel.extend( self.storage.devicetree.findOperations( type="destroy", object="format", devid=self.origrequest.id)) cancel.extend( self.storage.devicetree.findOperations( type="create", object="format", devid=self.origrequest.id)) for operation in cancel: self.storage.devicetree.removeOperation(operation) self.origrequest.format = self.origrequest.originalFormat if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(self.origrequest)) if self.origrequest.format.exists and not format and \ self.storage.formatByDefault(self.origrequest): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations
class Widget(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self, None) self.ui = Ui_YaliMain() self.ui.setupUi(self) self.font = 10 self.screenData = None # shortcut to open help self.helpShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F1),self) # shortcut to open debug window #self.debugShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F2),self) # something funny self.tetrisShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F6),self) self.cursorShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F7),self) self.themeShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F8),self) # shortcut to open a console self.consoleShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F11),self) # set style self._style = ctx.consts.stylesheet self.updateStyle() # move one step at a time self.stepIncrement = 1 # ToolButton Popup Menu self.popupMenu = QtGui.QMenu() self.shutDownAction = self.popupMenu.addAction(QtGui.QIcon(QtGui.QPixmap(":/images/system-shutdown.png")), _("Turn Off Computer")) self.rebootAction = self.popupMenu.addAction(QtGui.QIcon(QtGui.QPixmap(":/images/system-reboot.png")), _("Restart Computer")) self.restartAction = self.popupMenu.addAction(QtGui.QIcon(QtGui.QPixmap(":/images/system-yali-reboot.png")), _("Restart YALI")) #self.popupMenu.setDefaultAction(self.shutDownAction) self.ui.toolButton.setMenu(self.popupMenu) self.ui.toolButton.setDefaultAction(self.shutDownAction) # Main Slots self.connect(self.helpShortCut, SIGNAL("activated()"), self.slotToggleHelp) #self.connect(self.debugShortCut, SIGNAL("activated()"), self.toggleDebug) self.connect(self.consoleShortCut, SIGNAL("activated()"), self.toggleConsole) self.connect(self.cursorShortCut, SIGNAL("activated()"), self.toggleCursor) self.connect(self.themeShortCut, SIGNAL("activated()"), self.toggleTheme) self.connect(self.tetrisShortCut, SIGNAL("activated()"), self.toggleTetris) self.connect(self.ui.buttonNext, SIGNAL("clicked()"), self.slotNext) self.connect(self.ui.buttonBack, SIGNAL("clicked()"), self.slotBack) self.connect(self.ui.toggleHelp, SIGNAL("clicked()"), self.slotToggleHelp) self.connect(self.ui.releaseNotes, SIGNAL("clicked()"), self.showReleaseNotes) self.connect(self.popupMenu, SIGNAL("triggered(QAction*)"), self.slotMenu) self._terminal = QTermWidget.QTermWidget() self._terminal.sendText("export TERM='xterm'\nclear\n") self.cmb = _("right") self.dontAskCmbAgain = False self.terminal = None self.tetris = None self.ui.helpContentFrame.hide() self.effect = QtGui.QGraphicsOpacityEffect(self) self.ui.mainStack.setGraphicsEffect(self.effect) self.effect.setOpacity(1.0) self.anime = QTimer(self) self.connect(self.anime, SIGNAL("timeout()"), self.animate) def mousePressEvent(self, event): if event.button() == Qt.RightButton and not self.dontAskCmbAgain: if self.cmb == _("left"): ocmb = _("right") else: ocmb = _("left") reply = QuestionDialog(_("Mouse Settings"), _("You just clicked the <b>%s</b> mouse button.") % self.cmb, _("Do you want to switch to the <b>%s</b> handed configuration?") % ocmb, dontAsk = True) if reply == "yes": yali.sysutils.setMouse(self.cmb) self.cmb = ocmb elif reply == "dontask": self.dontAskCmbAgain = True def updateStyle(self): self.setStyleSheet(file(self._style).read()) self.font = 10 def setFontPlus(self): self._set_font(1) def setFontMinus(self): self._set_font(-1) def _set_font(self, num): # We have to edit style sheet to set new fonts # Because if you use a style sheet in your application # ::setFont gets useless :( http://doc.trolltech.com/4.5/qapplication.html#setFont old = "QWidget{font:%dpt;}" % self.font self.font = self.font + num new = "QWidget{font:%dpt;}" % self.font self.setStyleSheet(self.styleSheet().replace(old, new)) def slotMenu(self, action): if action == self.shutDownAction: reply = QuestionDialog(_("Warning"), _("Are you sure you want to shut down your computer now?")) if reply == "yes": yali.util.shutdown() elif action == self.rebootAction: reply = QuestionDialog(_("Warning"), _("Are you sure you want to restart your computer now?")) if reply == "yes": yali.util.reboot() else: reply = QuestionDialog(_("Warning"), _("Are you sure you want to restart the YALI installer now?")) if reply == "yes": os.execv("/usr/bin/yali-bin", sys.argv) def toggleTheme(self): if self._style == ctx.consts.stylesheet: self._style = ctx.consts.alternatestylesheet else: self._style = ctx.consts.stylesheet self.updateStyle() def toggleConsole(self): if not self.terminal: self.terminal = Dialog(_("Terminal"), self._terminal, self, True, QtGui.QKeySequence(Qt.Key_F11)) self.terminal.resize(700,500) self.terminal.exec_() def toggleTetris(self): self.tetris = Dialog(_("Tetris"), None, self, True, QtGui.QKeySequence(Qt.Key_F6)) _tetris = Tetris(self.tetris) self.tetris.addWidget(_tetris) self.tetris.resize(240,500) _tetris.start() self.tetris.exec_() def toggleCursor(self): if self.cursor().shape() == QtGui.QCursor(Qt.ArrowCursor).shape(): raw = QtGui.QPixmap(":/gui/pics/pardusman-icon.png") raw.setMask(raw.mask()) self.setCursor(QtGui.QCursor(raw,2,2)) else: self.unsetCursor() # show/hide help text def slotToggleHelp(self): self.ui.helpContentFrame.setFixedHeight(self.ui.helpContent.height()) if self.ui.helpContentFrame.isVisible(): self.ui.helpContentFrame.hide() else: self.ui.helpContentFrame.show() _w = self.ui.mainStack.currentWidget() _w.update() # show/hide debug window def toggleDebug(self): if ctx.debugger.isVisible(): ctx.debugger.hideWindow() else: ctx.debugger.showWindow() # returns the id of current stack def getCurrent(self, d): new = self.ui.mainStack.currentIndex() + d total = self.ui.mainStack.count() if new < 0: new = 0 if new > total: new = total return new # move to id numbered step def setCurrent(self, id=None): if id: self.stackMove(id) # execute next step def slotNext(self,dryRun=False): widget = self.ui.mainStack.currentWidget() ret = True if not dryRun: ret = widget.execute() if ret: self.stackMove(self.getCurrent(self.stepIncrement)) self.stepIncrement = 1 # execute previous step def slotBack(self): widget = self.ui.mainStack.currentWidget() if widget.backCheck(): self.stackMove(self.getCurrent(self.stepIncrement * -1)) self.stepIncrement = 1 # move to id numbered stack def stackMove(self, id): if not id == self.ui.mainStack.currentIndex() or id==0: self.effect.setOpacity(0.0) self.animationType = "fade-in" self.anime.start(50) self.ui.mainStack.setCurrentIndex(id) _w = self.ui.mainStack.currentWidget() self.ui.screenName.setText(_w.title) #self.ui.screenDescription.setText(_w.desc) self.ui.screenIcon.setPixmap(QtGui.QPixmap(":/gui/pics/%s.png" % (_w.icon))) self.ui.helpContent.setText(_w.help) # shown functions contain necessary instructions before # showing a stack ( updating gui, disabling some buttons etc. ) ctx.mainScreen.processEvents() _w.update() ctx.mainScreen.processEvents() _w.shown() def animate(self): if self.animationType == "fade-in": if self.effect.opacity() < 1.0: self.effect.setOpacity(self.effect.opacity() + 0.2) else: self.anime.stop() if self.animationType == "fade-out": if self.effect.opacity() > 0.0: self.effect.setOpacity(self.effect.opacity() - 0.2) else: self.anime.stop() # create all widgets and add inside stack # see runner.py/_all_screens for the list def createWidgets(self, screens=[]): if not self.screenData: self.screenData = screens self.ui.mainStack.removeWidget(self.ui.page) for screen in screens: _scr = screen.Widget() if ctx.options.debug == True or yali.sysutils.checkYaliParams(param="debug"): # debug all screens. weave_all_object_methods(ctx.aspect, _scr) # enable navigation buttons before shown weave_object_method(enableNavButtonsAspect, _scr, "shown") # disable navigation buttons before the execute. weave_object_method(disableNavButtonsAspect, _scr, "execute") self.ui.mainStack.addWidget(_scr) #weave_all_object_methods(ctx.aspect, self) self.stackMove(0) # Enable/Disable buttons def disableNext(self): self.ui.buttonNext.setEnabled(False) def disableBack(self): self.ui.buttonBack.setEnabled(False) def enableNext(self): self.ui.buttonNext.setEnabled(True) def enableBack(self): self.ui.buttonBack.setEnabled(True) def isNextEnabled(self): return self.ui.buttonNext.isEnabled() def isBackEnabled(self): return self.ui.buttonBack.isEnabled() # processEvents def processEvents(self): QObject.emit(self, SIGNAL("signalProcessEvents")) def showReleaseNotes(self): # make a release notes dialog d = Dialog(_('Release Notes'), ReleaseNotes(self), self) d.resize(500,400) d.exec_()
def showGPL(self): d = Dialog("GPL", LicenseBrowser(self), self) d.resize(500,400) d.exec_()
def showReleaseNotes(self): # make a release notes dialog d = Dialog(_('Release Notes'), ReleaseNotes(self), self) d.resize(500,400) d.exec_()
def showGPL(self): dialog = Dialog("GPL", LicenseBrowser(self), self) dialog.resize(500, 400) dialog.exec_()
class RaidEditor(object): def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.storage self.intf = parent.intf self.origrequest = request self.isNew = isNew availraidparts = self.parent.storage.unusedRaidMembers(array=self.origrequest) if availraidparts < 2: self.intf.messageWindow(_("Invalid Raid Members"), _("At least two unused software RAID " "partitions are needed to create " "a RAID device.\n\n" "First create at least two partitions " "of type \"software RAID\", and then " "select the \"RAID\" option again."), customIcon="error") return if isNew: title = _("Make RAID Device") else: if request.minor is not None: title = _("Edit RAID Device: %s") % request.path else: title = _("Edit RAID Device") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(RaidWidget(self, request, isNew)) if self.origrequest.exists: self.dialog.resize(QSize(450, 200)) else: self.dialog.resize(QSize(450, 400)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] raidmembers = [] if not rc: self.destroy() return [] widget = self.dialog.content for index in range(widget.raidMembers.count()): if widget.raidMembers.item(index).checkState() == Qt.Checked: raidmembers.append(widget.raidMembers.item(index).partition) # The user has to select some devices to be part of the array. if not raidmembers: continue mountpoint = str(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, customIcon="error") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), customIcon="error") continue if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) raidminor = widget.raidMinors.itemData(widget.raidMinors.currentIndex()).toInt()[0] raidlevel = widget.raidMinors.itemData(widget.raidLevels.currentIndex()).toInt()[0] if not raid.isRaid(raid.RAID0, raidlevel): spares = widget.spareSpin.value() else: spares = 0 format = formats.getFormat(formatType, mountpoint=mountpoint) members = len(raidmembers) - spares try: request = self.storage.newRaidArray(minor=raidminor, level=raidlevel, format=format, parents=raidmembers, totalDevices=len(raidmembers), memberDevices=members) except ValueError, e: self.intf.messageWindow(_("Error"), str(e), customIcon="error") continue if not self.isNew: # This may be handled in devicetree.registerAction, # but not in case when we change minor and thus # device name/path (at least with current md) operations.append(OperationDestroyDevice(self.origrequest)) operations.append(OperationCreateDevice(request)) operations.append(OperationCreateFormat(request)) else: format = None if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) operations.append(OperationCreateFormat(self.origrequest, format)) else: cancel = [] cancel.extend(self.storage.devicetree.findOperations(type="destroy", object="format", devid=self.origrequest.id)) cancel.extend(self.storage.devicetree.findOperations(type="create", object="format", devid=self.origrequest.id)) for operation in cancel: devicetree.removeOperation(operation) self.origrequest.format = self.origrequest.originalFormat if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(self.origrequest)) if self.origrequest.format.exists and not format and \ self.storage.formatByDefault(self.origrequest): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations
def showError(self, title, message, parent=None): r = ErrorWidget(parent) r.label.setText(message) d = Dialog(title, r, self, closeButton=False) d.resize(300,200) d.exec_()
def showReleaseNotes(self): # make a release notes dialog dialog = Dialog(_("Release Notes"), ReleaseNotes(self), self) dialog.resize(500, 400) dialog.exec_()
class PartitionEditor: def __init__(self, parent, origrequest, isNew=False, partedPartition=None, restricts=None): self.storage = parent.storage self.intf = parent.intf self.origrequest = origrequest self.isNew = isNew self.parent = parent self.partedPartition = partedPartition if isNew: title = _("Create Partition on %(path)s (%(model)s)") % { "path": os.path.basename(partedPartition.disk.device.path), "model": partedPartition.disk.device.model } else: try: title = _("Edit Partition %s") % origrequest.path except: title = _("Edit Partition") self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget( PartitionWidget(self, origrequest, isNew, restricts)) self.dialog.resize(QSize(350, 175)) def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: ctx.interface.messageWindow(_("Mount Point Error"), msg, type="warning") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: ctx.interface.messageWindow( _("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint, ), type="warning") continue if not self.origrequest.exists: if widget.primaryCheck.isChecked(): primary = True else: primary = None size = widget.sizeSpin.value() formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) if self.isNew: disk = self.storage.devicetree.getDeviceByPath( self.partedPartition.disk.device.path) else: disk = self.origrequest.disk err = doUIRAIDLVMChecks(format, [disk.name], self.storage) if err: self.intf.messageWindow(_("Error With Request"), err, type="error") continue weight = partitioning.weight(mountpoint=mountpoint, fstype=format.type) if self.isNew: request = self.storage.newPartition(size=size, grow=None, maxsize=0, primary=primary, format=format, parents=disk) else: request = self.origrequest request.weight = weight usedev = request if self.isNew: operations.append(OperationCreateDevice(request)) else: request.req_size = size request.req_base_size = size request.req_grow = None request.req_max_size = 0 request.req_primary = primary request.req_disks = [disk] operations.append(OperationCreateFormat(usedev, format)) else: # preexisting partition request = self.origrequest usedev = request origformat = usedev.format devicetree = self.storage.devicetree if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=usedev.path) operations.append(OperationCreateFormat(usedev, format)) else: cancel = [] cancel.extend( devicetree.findOperations(type="destroy", object="format", devid=request.id)) cancel.extend( devicetree.findOperations(type="create", object="format", devid=request.id)) cancel.reverse() for operation in cancel: devicetree.removeOperation(operation) request.format = request.originalFormat usedev = request if usedev.format.mountable: usedev.format.mountpoint = mountpoint if self.origrequest.protected and usedev.format.mountable: # users can set a mountpoint for protected partitions usedev.format.mountpoint = mountpoint request.weight = partitioning.weight( mountpoint=mountpoint, fstype=request.format.type) if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(usedev)) if widget.resizeRadio.isChecked(): size = widget.resizeSpin.value() try: operations.append(OperationResizeDevice(request, size)) if request.format.type and request.format.exists: operations.append( OperationResizeFormat(request, size)) except ValueError: pass if request.format.exists and \ getattr(request, "mountpoint", None) and \ self.storage.formatByDefault(request): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations def destroy(self): if self.dialog: self.dialog = None
class Widget(QWidget): def __init__(self): QWidget.__init__(self, None) # Set pixmaps resource before Main Window initialized self._resource = os.path.join(ctx.consts.theme_dir, ctx.flags.theme, ctx.consts.pixmaps_resource_file) if os.path.exists(self._resource): resource = QResource() resource.registerResource(self._resource) else: raise yali.Error, _("Pixmaps resources file doesn't exists") self.ui = Ui_YaliMain() self.ui.setupUi(self) self.font = 10 self.animation_type = None self.screens = None self.screens_content = None self.pds_helper = HelpWidget(self.ui.scrollAreaWidgetContents) # shortcut to open help self.help_shortcut = QShortcut(QKeySequence(Qt.Key_F1), self) # shortcut to open debug window # self.debugShortCut = QtGui.QShortcut(QtGui.QKeySequence(Qt.Key_F2),self) # something funny self.tetris_shortcut = QShortcut(QKeySequence(Qt.Key_F6), self) self.cursor_shortcut = QShortcut(QKeySequence(Qt.Key_F7), self) self.theme_shortcut = QShortcut(QKeySequence(Qt.Key_F8), self) # shortcut to open a console self.console_shortcut = QShortcut(QKeySequence(Qt.Key_F11), self) # set style self._style = os.path.join(ctx.consts.theme_dir, ctx.flags.theme, ctx.consts.style_file) if os.path.exists(self._style): self.updateStyle() else: raise yali.Error, _("Style file doesn't exists") # set screens content release_file = os.path.join(ctx.consts.branding_dir, ctx.flags.branding, ctx.consts.release_file) if os.path.exists(release_file): self.screens_content = yali.util.parse_branding_screens(release_file) else: raise yali.Error, _("Release file doesn't exists") # move one step at a time self.step_increment = 1 # ToolButton Popup Menu self.menu = QMenu() self.shutdown = self.menu.addAction(QIcon(QPixmap(":/images/system-shutdown.png")), _("Turn Off Computer")) self.reboot = self.menu.addAction(QIcon(QPixmap(":/images/system-reboot.png")), _("Restart Computer")) self.restart = self.menu.addAction(QIcon(QPixmap(":/images/system-yali-reboot.png")), _("Restart YALI")) # self.menu.setDefaultAction(self.shutdown) self.ui.system_menu.setMenu(self.menu) self.ui.system_menu.setDefaultAction(self.shutdown) # Main Slots self.connect(self.help_shortcut, SIGNAL("activated()"), self.pds_helper.toggleHelp) # self.connect(self.debugShortCut, SIGNAL("activated()"), self.toggleDebug) self.connect(self.console_shortcut, SIGNAL("activated()"), self.toggleConsole) self.connect(self.cursor_shortcut, SIGNAL("activated()"), self.toggleCursor) self.connect(self.theme_shortcut, SIGNAL("activated()"), self.toggleTheme) self.connect(self.tetris_shortcut, SIGNAL("activated()"), self.toggleTetris) self.connect(self.ui.buttonNext, SIGNAL("clicked()"), self.slotNext) self.connect(self.ui.buttonBack, SIGNAL("clicked()"), self.slotBack) self.connect(self.ui.toggleHelp, SIGNAL("clicked()"), self.pds_helper.toggleHelp) if not ctx.flags.install_type == ctx.STEP_FIRST_BOOT: self.connect(self.ui.releaseNotes, SIGNAL("clicked()"), self.showReleaseNotes) else: self.ui.releaseNotes.hide() self.connect(self.menu, SIGNAL("triggered(QAction*)"), self.slotMenu) self.cmb = _("right") self.dont_ask_again = False self.terminal = None self.tetris = None self.ui.helpContentFrame.hide() self.effect = QGraphicsOpacityEffect(self) self.ui.mainStack.setGraphicsEffect(self.effect) self.effect.setOpacity(1.0) self.anime = QTimer(self) self.connect(self.anime, SIGNAL("timeout()"), self.animate) def mousePressEvent(self, event): if event.button() == Qt.RightButton and not self.dont_ask_again: if self.cmb == _("left"): ocmb = _("right") else: ocmb = _("left") reply = QuestionDialog( _("Mouse Settings"), _("You just clicked the <b>%s</b> mouse button.") % self.cmb, _("Do you want to switch to the <b>%s</b> handed configuration?") % ocmb, dontAsk=True, ) if reply == "yes": yali.sysutils.setMouse(self.cmb) self.cmb = ocmb elif reply == "dontask": self.dont_ask_again = True def updateStyle(self): self.setStyleSheet(file(self._style).read()) self.font = 10 def setFontPlus(self): self.increaseFontSize(1) def setFontMinus(self): self.increaseFontSize(-1) def increaseFontSize(self, num): # We have to edit style sheet to set new fonts # Because if you use a style sheet in your application # ::setFont gets useless :( http://doc.trolltech.com/4.5/qapplication.html#setFont old = "QWidget{font:%dpt;}" % self.font self.font = self.font + num new = "QWidget{font:%dpt;}" % self.font self.setStyleSheet(self.styleSheet().replace(old, new)) def slotMenu(self, action): if action == self.shutdown: reply = QuestionDialog(_("Warning"), _("Are you sure you want to shut down your computer now?")) if reply == "yes": yali.util.shutdown() elif action == self.reboot: reply = QuestionDialog(_("Warning"), _("Are you sure you want to restart your computer now?")) if reply == "yes": yali.util.reboot() else: reply = QuestionDialog(_("Warning"), _("Are you sure you want to restart the YALI installer now?")) if reply == "yes": os.execv("/usr/bin/yali-bin", sys.argv) def toggleTheme(self): "This easter egg will be implemented later" """ if self._style == os.path.join(ctx.consts.theme_dir, "%s/style.qss" % ctx.flags.theme): if os.path.join(ctx.consts.theme_dir, "%s/style.glass.qss" % ctx.flags.theme): self._style = os.path.join(ctx.consts.theme_dir, "%s/style.glass.qss" % ctx.flags.theme) else: self._style = os.path.join(ctx.consts.theme_dir, "%s/style.qss" % ctx.flags.theme) self.updateStyle() """ def toggleConsole(self): if not self.terminal: terminal = QTermWidget() terminal.setScrollBarPosition(QTermWidget.ScrollBarRight) terminal.setColorScheme(1) terminal.sendText("export TERM='xterm'\nclear\n") self.terminal = Dialog(_("Terminal"), terminal, True, QKeySequence(Qt.Key_F11)) self.terminal.resize(700, 500) self.terminal.exec_() def toggleTetris(self): self.tetris = Dialog(_("Tetris"), None, True, QKeySequence(Qt.Key_F6)) _tetris = Tetris(self.tetris) self.tetris.addWidget(_tetris) self.tetris.resize(240, 500) _tetris.start() self.tetris.exec_() def toggleCursor(self): if self.cursor().shape() == QCursor(Qt.ArrowCursor).shape(): raw = QPixmap(":/gui/pics/pardusman-icon.png") raw.setMask(raw.mask()) self.setCursor(QCursor(raw, 2, 2)) else: self.unsetCursor() # show/hide help text def slotToggleHelp(self): self.ui.helpContentFrame.setFixedHeight(self.ui.helpContent.height()) if self.ui.helpContentFrame.isVisible(): self.ui.helpContentFrame.hide() else: self.ui.helpContentFrame.show() widget = self.ui.mainStack.currentWidget() widget.update() # show/hide debug window def toggleDebug(self): if ctx.debugger.isVisible(): ctx.debugger.hideWindow() else: ctx.debugger.showWindow() # returns the id of current stack def getCurrent(self, index): new_index = self.ui.mainStack.currentIndex() + index total_index = self.ui.mainStack.count() if new_index < 0: new_index = 0 if new_index > total_index: new_index = total_index return new_index # move to id numbered step def setCurrent(self, index=None): if index: self.stackMove(index) # execute next step def slotNext(self, dry_run=False): widget = self.ui.mainStack.currentWidget() ret = True if not dry_run: ret = widget.execute() if ret: self.pds_helper.hideHelp() self.ui.toggleHelp.setChecked(False) self.stackMove(self.getCurrent(self.step_increment)) self.step_increment = 1 # execute previous step def slotBack(self): widget = self.ui.mainStack.currentWidget() if widget.backCheck(): self.stackMove(self.getCurrent(self.step_increment * -1)) self.pds_helper.hideHelp() self.ui.toggleHelp.setChecked(False) self.step_increment = 1 # move to id numbered stack def stackMove(self, index): if not index == self.ui.mainStack.currentIndex() or index == 0: self.effect.setOpacity(0.0) self.animation_type = "fade-in" self.anime.start(50) self.ui.mainStack.setCurrentIndex(index) widget = self.ui.mainStack.currentWidget() # Hack to fix goodbye screen help content # BUG:#15860, #15444 if widget.name == "goodbye": widget_id = "%s%s" % (widget.name, ctx.flags.install_type) else: widget_id = widget.name widget_icon = self.screens_content[widget_id][0] if self.screens_content[widget_id][1].has_key(ctx.consts.lang): widget_title = self.screens_content[widget_id][1][ctx.consts.lang] else: widget_title = self.screens_content[widget_id][1]["en"] if self.screens_content[widget_id][2].has_key(ctx.consts.lang): widget_help = self.screens_content[widget_id][2][ctx.consts.lang] else: widget_help = self.screens_content[widget_id][2]["en"] self.ui.screenName.setText(widget_title) self.pds_helper.ui.helpContent.setText(widget_help) self.pds_helper.setHelp(widget_help) self.ui.screenIcon.setPixmap(QPixmap(":/gui/pics/%s.png" % (widget_icon))) ctx.mainScreen.processEvents() widget.update() ctx.mainScreen.processEvents() widget.shown() def animate(self): if self.animation_type == "fade-in": if self.effect.opacity() < 1.0: self.effect.setOpacity(self.effect.opacity() + 0.2) else: self.anime.stop() if self.animation_type == "fade-out": if self.effect.opacity() > 0.0: self.effect.setOpacity(self.effect.opacity() - 0.2) else: self.anime.stop() def createWidgets(self, screens=[]): if not self.screens: self.screens = screens self.ui.mainStack.removeWidget(self.ui.page) for screen in screens: # if ctx.flags.debug: # debug all screens. # weave_all_object_methods(ctx.aspect, screen) # enable navigation buttons before shown weave_object_method(enableNavButtonsAspect, screen, "shown") # disable navigation buttons before the execute. weave_object_method(disableNavButtonsAspect, screen, "execute") try: self.ui.mainStack.addWidget(screen()) except Exception, msg: rc = ctx.interface.messageWindow( _("Error"), _("An error occurred when attempting " "to load screens:%s") % msg, type="custom", customIcon="error", customButtons=[_("Exit")], ) if not rc: sys.exit(0) # weave_all_object_methods(ctx.aspect, self) self.stackMove(ctx.flags.startup)
class LogicalVolumeEditor: def __init__(self, parent, request, isNew=False): self.parent = parent self.storage = parent.parent.storage self.intf = parent.parent.intf self.origrequest = request self.isNew = isNew if isNew: title = _("Make Logical Volume") else: title = _("Edit Logical Volume: %s") % request.lvname self.dialog = Dialog(title, closeButton=False) self.dialog.addWidget(LogicalVolumeWidget(self, request, isNew)) self.dialog.resize(QSize(0, 0)) def run(self): if self.dialog is None: return None while 1: rc = self.dialog.exec_() if not rc: if self.isNew: if self.parent.parent.lvs.has_key(self.origrequest.lvname): del self.parent.parent.lvs[self.origrequest.lvname] self.destroy() return None format = None widget = self.dialog.content format = self.origrequest.format mountpoint = unicode(widget.mountpointMenu.currentText()) if mountpoint and widget.mountpointMenu.isEditable(): msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue if not self.origrequest.exists: format_type = str(widget.filesystemMenu.currentText()) else: format_type = str(widget.formatCombo.currentText()) format_class = formats.getFormat(format_type) if mountpoint and format_class.mountable: used = False current_mountpoint = getattr(format, "mountpoint", None) for lv in self.parent.parent.lvs.values(): format = lv["format"] if not format.mountable or current_mountpoint and \ format.mountpoint == current_mountpoint: continue if format.mountpoint == mountpoint: used = True break for (mp, dev) in self.parent.parent.storage.mountpoints.iteritems(): if (dev.type != "lvmlv" or dev.vg.id != self.origrequest.vg.id) and mp == mountpoint: used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue name = str(widget.name.text()) if not self.origrequest.exists: msg = sanityCheckLogicalVolumeName(name) if msg: self.intf.messageWindow(_("Illegal Logical Volume Name"), msg, type="warning") continue # check that the name is not already in use used = 0 for lv in self.parent.parent.lvs.values(): if self.origrequest.lvname != name and lv['name'] == name: used = 1 break if used: self.intf.messageWindow(_("Illegal logical volume name"), _("The logical volume name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue if not self.origrequest.exists: badsize = 0 try: size = long(widget.sizeSpin.value()) except: size = 1 if badsize or size <= 0: self.intf.messageWindow(_("Illegal size"), _("The requested size as entered is " "not a valid number greater than 0."), type="warning") continue else: size = self.origrequest.size # check that size specification is within limits peSize = int(self.parent.physicalExtends.itemData(self.parent.physicalExtends.currentIndex())) / 1024 size = lvm.clampSize(size, peSize, roundup=True) maximumVolumeSize = lvm.getMaxLVSize() if size > maximumVolumeSize: self.intf.messageWindow(_("Not enough space"), _("The current requested size " "(%(size)10.2f MB) is larger than " "the maximum logical volume size " "(%(maxlv)10.2f MB). " "To increase this limit you can " "create more Physical Volumes from " "unpartitioned disk space and " "add them to this Volume Group.") % {'size': size, 'maxlv': maximumVolumeSize}, type="warning") continue # Get format origname = self.origrequest.lvname if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) self.origrequest._name = name try: self.origrequest.size = size except ValueError, msg: self.intf.messageWindow(_("Not enough space"), _("The size entered for this " "logical volume (%(size)d MB) " "combined with the size of the " "other logical volume(s) " "exceeds the size of the " "volume group (%(tmpvgsize)d " "MB). Please make the volume " "group larger or make the " "logical volume smaller.") % {'size': size, 'tmpvgsize': self.origrequest.vg.size}, type="warning") continue else: self.origrequest.format = format else: if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) self.origrequest.format = format else: self.origrequest.format = self.origrequest.originalFormat if widget.migrateRadio.isChecked(): self.origrequest.format.migrate = True if widget.resizeRadio.isChecked(): self.origrequest.targetSize = widget.resizeSpin.value() if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if self.origrequest.format.exists and \ self.origrequest.format.mountable and \ self.origrequest.format.mountpoint: if self.storage.formatByDefault(self.origrequest) and \ not queryNoFormatPreExisting(self.intf): continue # everything ok break if self.parent.parent.lvs.has_key(origname) and origname != self.origrequest.lvname: del self.parent.parent.lvs[origname] return {'name': self.origrequest.lvname, 'size': self.origrequest.size, 'format': self.origrequest.format, 'originalFormat': self.origrequest.originalFormat, 'stripes': self.origrequest.stripes, 'logSize': self.origrequest.logSize, 'snapshotSpace': self.origrequest.snapshotSpace, 'exists': self.origrequest.exists}
def showGPL(self): # make a GPL dialog d = Dialog("GPL", Gpl(self), self) d.resize(500,400) d.exec_()