# page_medium.py - Handler for the project settings page # # (c) Copyright 2010 Michael Towers (larch42 at googlemail dot com) # # This file is part of the larch project. # # larch is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # larch is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with larch; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------------- # 2010.07.13 """This page can also handle sources other than the normal larch installation. It should convert any larch image into another, with different medium and/or different bootloader, so long as the bootloader is supported by the source image. """ import os BOOTLOADERS = ('grub', 'syslinux') class Medium: def __init__(self): ui.widgetlist(fss('fetch_layout', 'page_medium.uim')) ui.connectlist( (':source_larch*toggled', self.src_larch), (':source_dev*toggled', self.src_dev), (':source_iso*toggled', self.src_iso), (':source_path*toggled', self.src_path), (':source_select*clicked', self.src_select), (':vlabelb*clicked', self.newlabel), (':grub*toggled', self.grub), (':syslinux*toggled', self.syslinux), (':selectpart*clicked', self.choosepartition), (':search*toggled', self.searchtoggled), (':destination*toggled', self.activate_actions), (':make_medium*clicked', self.make), (':bootcd*clicked', self.makeboot), ) ui.command(':bootcd.enable', False) def enter(self): """This is called when the page is entered/selected/shown. It performs initializations which depend on the state. """ self.source = '' self.destination = '' ui.command(':larchpart.text') docviewer.gohome('gui_medium.html') if ui.command(':source_larch.active'): self.src_larch(True) else: ui.command(':source_larch.set', True) ui.command(':%s.set' % fss('getitem', 'medium_search'), True) ui.command(':vlabele.text', fss('get_mediumlabel')) def data(self, key): return ui.command('medium_page_data.get', key) def setupbootloader(self, init=False): if init: self.bootloaders = [] self.nosave = False self.source = '' for b in BOOTLOADERS: ui.command(':%s.set' % b, False) ui.command(':%s.enable' % b, False) pbl = fss('getitem', 'medium_btldr') for b in self.bootloaders: ui.command(':%s.enable' % b, True) if self.bootloaders: if pbl not in self.bootloaders: pbl = self.bootloaders[0] ui.command(':%s.set' % pbl, True) ui.command(':dosave.set', not self.nosave) ui.command(':source_show.text', self.source) self.activate_actions() def activate_actions(self, *args): # There needs to be a bootloader bl = self.get_bootloader() bcdok = (ui.command(':source_dev.active') and bool(self.source) and bool(bl)) ui.command(':bootcd.enable', bcdok) # If using a destination partition, that needs to be available. wp = ui.command(':destination.active') if wp: # If writing to a partition without installing a bootloader if ui.command(':nombr.active'): bl = True # bootloader not necessary dp = bool(self.destination) else: dp = True ui.command(':make_medium.enable', bool(self.source) and bl and dp) ui.command(':detection.enable', bcdok or wp) def get_bootloader(self): if ui.command(':grub.active'): return 'grub' if ui.command(':syslinux.active'): return 'syslinux' return None def _testmedium(self, cc): # Runs in background thread ... self.bootloaders = [] if not (cc & 8): self.bootloaders.append('syslinux') if not (cc & 16): self.bootloaders.append('grub') self.nosave = bool(cc & 2) ui.idle_add(self.setupbootloader, bool(cc & 1)) return True # return immediately to normal view def src_larch(self, on): if on: mpath, ok, self.bootloaders, self.nosave = fss('testmedium') if ok: self.source = mpath else: self.source = '' run_error(self.data('msg_med') % mpath) self.setupbootloader() ui.command(':source_select.enable', not on) ui.command(':chroot.set', on) def src_dev(self, on): """The source system is on a mountable device, which must be selected from a list of available devices (via the Choose button) and tested for validity, maybe the presence of larch/system.sqf. """ if on: self.setupbootloader(init=True) def src_iso(self, on): """The source system is in an 'iso' file, which must be selected by browsing the file system (via the Choose button) and tested for validity, maybe the presence of larch/system.sqf. """ if on: self.setupbootloader(init=True) def src_path(self, on): """The source system is in a directory, which must be selected by browsing the file system (via the Choose button) and tested for validity, maybe the presence of larch/system.sqf. """ if on: self.setupbootloader(init=True) def src_select(self): """The function of this button varies according to the selected source ... """ src = None if ui.command(':source_dev.active'): part = self.selectpart() if part: src = part elif ui.command(':source_iso.active'): iso = ui.fileDialog(self.data('iso_src'), filter=(self.data('iso_type'), '*.iso')) if iso: src = iso elif ui.command(':source_path.active'): medium = ui.fileDialog(self.data('medium_src'), dirsonly=True) if medium: src = medium if src: self.source = src larchscripts.testmedium(src, self._testmedium) def grub(self, on): if on: fss('setitem', 'medium_btldr', 'grub') def syslinux(self, on): if on: fss('setitem', 'medium_btldr', 'syslinux') def newlabel(self): ok, l = ui.command('textLineDialog', self.data('prompt_label'), None, fss('getitem', 'medium_label')) if ok: ui.command(':vlabele.text', fss('set_mediumlabel', l)) def choosepartition(self): p = self.selectpart(True) if p: ui.command(':larchpart.text', p) self.destination = p self.activate_actions() def selectpart(self, write=False): # Present a list of available partitions (only unmounted ones # are included) self.partlist = fss('get_partitions') ok, choice = ui.command('listDialog', self.data('parts_dst') if write else self.data('parts_src'), self.data('parts_t'), self.partlist, len(self.partlist) - 1) # The partition to be used is fetched from the gui, so there is no # need to save it anywhere else. if ok: return choice.split()[0] else: return None def searchtoggled(self, on): ui.command(':nolarchboot.enable', not on) def make(self): """Write the larch medium. """ args = ['-l', ui.command(':vlabele.get')] if ui.command(':syslinux.active'): args.append('-b') # Is it standard (using profile, etc.) or copying? if ui.command(':source_larch.active'): # Normal larch build path = '' if not ui.command(':chroot.active'): args.append('-c') else: # Copying from another larch medium path = self.source if ui.command(':chroot.active'): args.append('-C') # Write to iso file or to partition? if ui.command(':destination.active'): # Write to partition for db in ('label', 'uuid', 'device', 'search'): if ui.command(':%s.active' % db): detect = db args += ['-d', detect] if (detect != 'search') and ui.command(':nolarchboot.active'): args.append('-n') args.append('-a' if ui.command(':dosave.active') else '-A') if ui.command(':noformat.active'): args.append('-x') if ui.command(':nombr.active'): args.append('-m') larchscripts.writemedium(path, args, os.path.basename(self.destination)) else: # Write an 'iso' file df = self.isopath() if df: args += ['-D', df[0], '-o', df[1]] larchscripts.writemedium(path, args) def makeboot(self): return args = ['-l', fss('getbootisolabel')] if ui.command(':syslinux.active'): args.append('-b') path = os.path.basename(self.source) if ui.command(':chroot.active'): args.append('-C') df = self.isopath(bootiso=True) if df: args += ['-D', df[0], '-o', df[1]] larchscripts.writemedium(path, args, 'BOOTISO') def isopath(self, bootiso=False): sdir = fss('getisosavedir') ifname = fss('getbootisofile' if bootiso else 'getisofile') path = ui.fileDialog(self.data('isopath'), startdir=sdir, create=True, file=ifname, filter=(self.data('iso_type'), '*.iso')) if path: f = os.path.basename(path) d = os.path.dirname(path) if d != sdir: fss('setitem', 'isosavedir', d) if f != ifname: fss('setitem', 'bootisofile' if bootiso else 'isofile', f) return (d, f) return None