#!/usr/bin/python # -*- coding: UTF-8 -*- ########################################################################### # mountconfig.py - description # # ------------------------------ # # begin : Fri Nov 30 2003 # # copyright : (C) 2003 by Simon Edwards # # email : simon@simonzone.com # # # ########################################################################### # # # This program 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. # # # ########################################################################### from qt import * from kdeui import * from kdecore import * from kfile import * from kio import * import sys import os import os.path from types import StringType,UnicodeType import pwd import grp import math import locale import codecs import subprocess import MicroHAL from SMBShareSelectDialog import * from SimpleCommandRunner import * from fuser import * import sizeview programname = "Disk & Filesystem Configuration" version = "0.8.0" # Are we running as a separate standalone application or in KControl? standalone = __name__=='__main__' # Running as the root user or not? isroot = os.getuid()==0 allowuuid = True allowlabel = True """ Universal Options ----------------- async/sync atime/noatime auto/noauto dev/nodev exec/noexec ro/rw suid/nosuid dirsync nouser/user/users defaults =>rw, suid, dev, exec, auto, nouser, and async. Automatically set ================= _netdev The filesystem resides on a device that requires network access (used to prevent the system from attempting to mount these filesystems until the network has been enabled on the system). remount Attempt to remount an already-mounted file system. This is commonly used to change the mount flags for a file system, especially to make a readonly file system writeable. It does not change device or mount point. Supported filesystems --------------------- nfs ext2 ext3 reiserfs vfat ntfs udf iso9660 supermount reiser4 xfs jfs hfs hfsplus cifs (replacement for smbfs) auto swap proc sysfs usbdevfs procbususb TODO ---- * SMB finished the connection username nad password fields. * SMB entry: finished writing the config. * SMBSelector: setting the username and password. """ ############################################################################ class UserComboBox(KComboBox): def __init__(self,parent,name=None): KComboBox.__init__(self,parent,name) tmplist = [] users = pwd.getpwall() for user in users: uid = int(user[2]) username = user[4] tmplist.append( (int(uid),"%s (%s)" % (username,uid)) ) tmplist.sort(lambda a,b: cmp(a[1],b[1])) self.userlist = [] for user in tmplist: self.insertItem(user[1]) self.userlist.append(user[0]) ######################################################################## def setUID(self,uid): if uid in self.userlist: self.setCurrentItem(self.userlist.index(int(uid))) return True else: return False ######################################################################## def UID(self): return self.userlist[self.currentItem()] ############################################################################ class GroupComboBox(KComboBox): def __init__(self,parent,name=None): KComboBox.__init__(self,parent,name) self.grouplist = [] groups = grp.getgrall() tmplist = [] for group in groups: gid = group[2] groupname = group[0] tmplist.append( (int(gid),"%s (%s)" % (groupname,gid)) ) tmplist.sort(lambda a,b: cmp(a[1],b[1])) self.grouplist = [] for group in tmplist: self.insertItem(group[1]) self.grouplist.append(group[0]) ######################################################################## def setGID(self,gid): if gid in self.grouplist: self.setCurrentItem(self.grouplist.index(int(gid))) return True else: return False ######################################################################## def GID(self): return self.grouplist[self.currentItem()] ############################################################################ class MountEntryExt(object): use_as_device = "devicenode" # Can be one of "devicenode", "uuid" or "label" showdevice = True showlabel = False showuuid = False ######################################################################## # Base can be either a fstab format line of text, of another MountEntry # object. def __init__(self,base=None): if base==None: self.device = unicode(i18n("")) self.mountpoint = unicode(i18n("")) self.mounttype = 'ext2' self.uuid = "" self.label = "" self.extraoptions = "noauto" self.fs_freq = 0 self.fs_passno = 0 self.enabled = False self.managed = False self.device_string = "" elif isinstance(base,StringType) or isinstance(base,UnicodeType): parts = base.split() device_ref = MountEntry.decodeMountEntryString(parts[0]) self.uuid = "" self.label = "" if device_ref.startswith("UUID="): self.uuid = device_ref[5:] self.setUseAsDevice("uuid") mapped_device = microhal.getDeviceByUUID(self.uuid) if mapped_device is not None: self.device = mapped_device.getDev() else: self.device = "" try: self.label = mapped_device.getLabel() except AttributeError: pass elif device_ref.startswith("LABEL="): self.label = device_ref[6:] self.setUseAsDevice("label") mapped_device = microhal.getDeviceByLabel(self.label) if mapped_device is not None: self.device = mapped_device.getDev() else: self.device = "" else: self.device = device_ref self.mountpoint = MountEntry.decodeMountEntryString(parts[1]) self.mounttype = MountEntry.decodeMountEntryString(parts[2]) self.extraoptions = MountEntry.decodeMountEntryString(parts[3]) self.fs_freq = int(parts[4]) self.fs_passno = int(parts[5]) self.enabled = False options = self.extraoptions.split(",") self.managed = "managed" in options try: options.remove("managed") except ValueError: pass self.extraoptions = ",".join(options) else: # This is a new entry, but it's based on another one. self.device = base.device self.mountpoint = base.mountpoint self.mounttype = base.mounttype self.extraoptions = base.extraoptions self.fs_freq = base.fs_freq self.fs_passno = base.fs_passno self.uuid = base.uuid self.enabled = base.enabled self.managed = False self.iconname = self.getIconName() ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExt() # FIXME: use "newobject = self.__class__()" and get rid of the newobject parameter. newobject.device = self.device newobject.mountpoint = self.mountpoint newobject.mounttype = self.mounttype newobject.use_as_device = self.use_as_device newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid newobject.extraoptions = self.extraoptions newobject.fs_freq = self.fs_freq newobject.fs_passno = self.fs_passno newobject.enabled = self.enabled newobject.uuid = self.uuid newobject.label = self.label return newobject ######################################################################## def cleanup(self): # This method is called after the entry has been removed from the # mounttable. pass ######################################################################## def setMountType(self,mounttypename): self.mounttype = mounttypename ######################################################################## def isFileSystemAvailable(self): return microhal.isSupportedFileSystem(self.mounttype) def getDevice(self): return self.device def setDevice(self,device): self.device = device def setUseAsDevice(self,use_as): self.use_as_device = use_as def getUseAsDevice(self): return self.use_as_device def setUUID(self,uuid): self.uuid = uuid def setLabel(self,label): self.label = label def getMountPoint(self): return self.mountpoint def setMountPoint(self,mountpoint): self.mountpoint = mountpoint def getExtraOptions(self): return self.extraoptions def setExtraOptions(self,extraoptions): self.extraoptions = extraoptions def getFSFreq(self): return self.fs_freq def setFSFreq(self,fs_freq): self.fs_freq = fs_freq def getFSPassno(self): return self.fs_passno def setFSPassno(self,fs_passno): self.fs_passno = fs_passno def isManaged(self): return self.managed def getUUID(self): if not self.uuid: return "" return self.uuid def getLabel(self): try: if not self.label: return "" return self.label except AttributeError: return "" def getDeviceString(self): if self.getUseAsDevice() == "label": if self.label != "": return MountEntry.encodeMountEntryString("LABEL="+self.label) else: print "No Label set, preventing you from shooting yourself in the foot" elif self.getUseAsDevice() == "uuid": if self.uuid != "": return "UUID="+self.uuid return MountEntry.encodeMountEntryString("UUID="+self.uuid) else: print "No UUID set, preventing you from shooting yourself in the foot" return MountEntry.encodeMountEntryString(self.device) ######################################################################## def getName(self): if os.path.basename(self.device).startswith("fd"): return "Floppy" else: return self.mountpoint ######################################################################## def getIconName(self): if self.device is not None and os.path.basename(self.device).startswith("fd"): return "hi16-floppy" else: return "hi16-blockdevice" ######################################################################## def updateStatus(self,mtablist): self.enabled = self.mountpoint in mtablist ######################################################################## def getFstabOptions(self): if self.extraoptions!="": return self.extraoptions.split(",") else: return [] ######################################################################## def getFstabLine(self): # Construct the options field. _options = self.getFstabOptions() options = [] # Remove whitespace and dupes for o in _options: if o.strip() not in options: options.append(o.strip()) return self.getDeviceString() + \ u" " + MountEntry.encodeMountEntryString(self.mountpoint.replace("%20","\040")) + \ u" " + MountEntry.encodeMountEntryString(self.mounttype) + \ u" " + MountEntry.encodeMountEntryString(u",".join(options)) + \ u" " + unicode(self.fs_freq) + u" " + unicode(self.fs_passno) ######################################################################## def getCategory(self): return self.device ######################################################################## def isEnabled(self): return self.enabled ######################################################################## def enable(self,parentdialog): self._setBusy(parentdialog,True) try: (rc,output) = SimpleCommandRunner().run(["/bin/mount",self.mountpoint]) finally: self._setBusy(parentdialog,False) if rc!=0: self.handleMountFailure(parentdialog,rc,output,True) ######################################################################## def disable(self,parentdialog): self._setBusy(parentdialog,True) try: (rc,output) = SimpleCommandRunner().run(["/bin/umount",self.mountpoint]) finally: self._setBusy(parentdialog,False) if rc!=0: self.handleMountFailure(parentdialog,rc,output,False) ######################################################################## def handleMountFailure(self,parentdialog,rc,output,mount_action=True): """ Keyword arguments: mount_action - True=enable, False=disable """ global kapp if mount_action: msg = i18n("An error occurred while enabling %1.\n\nThe system reported: %2").arg( \ self.mountpoint).arg(output) captionmsg = i18n("Unable to enable %1").arg(self.mountpoint) else: msg = i18n("An error occurred while disabling %1.\n\nThe system reported: %2").arg( self.mountpoint).arg(output) captionmsg = i18n("Unable to disable %1").arg(self.mountpoint) extramsg = unicode(i18n("Return code from mount was %1.\n").arg(rc)) if (rc & 1)!=0: extramsg += unicode(i18n("\"incorrect invocation or permissions\"\n")) if (rc & 2)!=0: extramsg += unicode(i18n("\"system error (out of memory, cannot fork, no more loop devices)\"\n")) if (rc & 4)!=0: extramsg += unicode(i18n("\"internal mount bug or missing nfs support in mount\"\n")) if (rc & 8)!=0: extramsg += unicode(i18n("\"user interrupt\"\n")) if (rc & 16)!=0: extramsg += unicode(i18n("\"problems writing or locking /etc/mtab\"\n")) if (rc & 32)!=0: extramsg += unicode(i18n("\"mount failure\"\n")) if (rc & 64)!=0: extramsg += unicode(i18n("\"some mount succeeded\"\n")) in_use = False if not mount_action: # Use lsof to find out what is blocking the device. lsof_bin = '/usr/bin/lsof' rc, output = SimpleCommandRunner().run([lsof_bin,'-FncL',str(self.mountpoint)]) if rc==0: # Check if there is one or more processes using the device. in_use = len(output.split())>3 if in_use: # Start fuser.py which lists open filedescriptors on device and offers to get # rid of them. fuser = FUser(str(self.mountpoint),None,lsof_bin,kapp) fuser.exec_loop() in_use_message = "" if fuser.result() != 0: in_use_message = unicode(i18n("Unmounting %1 failed or was cancelled.").arg(self.device)) extramsg += in_use_message else: extramsg += unicode(i18n("(none)")) if not in_use: KMessageBox.detailedSorry(parentdialog, msg, extramsg, captionmsg) ######################################################################## def _setBusy(self,parentdialog,flag): global kapp if flag: kapp.setOverrideCursor( QCursor(Qt.WaitCursor) ) parentdialog.setEnabled(False) # It is necessary to process some of the events in the event queue. # Otherwise the user won't see that the window is disabled. # ( setEnabled() here above doesn't redraw the window immediately. # Redrawing is done via the event queue.) kapp.processEvents() else: parentdialog.setEnabled(True) kapp.restoreOverrideCursor() ############################################################################ class MountEntryExtCommonUnix(MountEntryExt): USERMOUNT_NO = 0 USERMOUNT_ONE = 1 USERMOUNT_ANY = 2 USERMOUNT_OWNER = 3 ######################################################################## # Base can be either a fstab format line of text, or another MountEntry # object. def __init__(self,base=None): super(MountEntryExtCommonUnix,self).__init__(base) if isinstance(base,MountEntryExtCommonUnix): # Being initalised from an existing object. # Only mess with objects self.atime = base.atime self.auto = base.auto self.writeable = base.writeable self.usedevpoints = base.usedevpoints self.showlabel = True self.showuuid = True self.allowexecutables = base.allowexecutables self.allowsuid = base.allowsuid self.allowusermount = base.allowusermount elif isinstance(base,StringType) or isinstance(base,UnicodeType): options = self.extraoptions.split(",") self.atime = True if "noatime" in options: self.atime = False self.auto = True if "noauto" in options: self.auto = False self.writeable = True if "ro" in options: self.writeable = False self.usedevpoints = True if "nodev" in options: self.usedevpoints = False self.allowexecutables = True if "noexec" in options: self.allowexecutables = False self.allowsuid = True if "nosuid" in options: self.allowsuid = False self.allowusermount = self.USERMOUNT_NO if "user" in options: self.allowusermount = self.USERMOUNT_ONE if "users" in options: self.allowusermount = self.USERMOUNT_ANY if "owner" in options: self.allowusermount = self.USERMOUNT_OWNER self.showlabel = True self.showuuid = True for x in ["noatime","atime","auto","noauto","dev","nodev","nouser", \ "owner","users","user","suid","nosuid","exec","noexec","rw","ro"]: try: options.remove(x) except ValueError: pass self.extraoptions = ",".join(options) else: # Set some sane defaults. self.showlabel = True self.showuuid = True self.atime = True self.auto = False self.writeable = True self.usedevpoints = False self.allowexecutables = False self.allowsuid = False self.allowusermount = self.USERMOUNT_NO ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtCommonUnix() super(MountEntryExtCommonUnix,self).copy(newobject) newobject.atime = self.atime newobject.auto = self.auto newobject.use_as_device = self.use_as_device newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid newobject.uuid = self.uuid newobject.label = self.label newobject.writeable = self.writeable newobject.usedevpoints = self.usedevpoints newobject.allowexecutables = self.allowexecutables newobject.allowsuid = self.allowsuid newobject.allowusermount = self.allowusermount return newobject ######################################################################## def getFstabOptions(self): options = [] # These options must appear before the others. 'user', according to the # mount man page implies 'noexec' too, BUT the noexec can be overridden # by specifying 'exec' after the 'user' keyword. Therefore 'exec' etc # must come after 'user', 'users' and friends. options.append(['nouser','user','users','owner'][self.allowusermount]) super_options = super(MountEntryExtCommonUnix,self).getFstabOptions() options.extend(super_options) options.append(['noatime','atime'][self.atime]) options.append(['noauto','auto'][self.auto]) options.append(['ro','rw'][self.writeable]) options.append(['nodev','dev'][self.usedevpoints]) options.append(['noexec','exec'][self.allowexecutables]) options.append(['nosuid','suid'][self.allowsuid]) return options ######################################################################## # atime/noatime def getAtime(self): return self.atime def setAtime(self,val): self.atime = val # auto/noauto def getMountAtBoot(self): return self.auto def setMountAtBoot(self,val): self.auto = val # ro/rw def getWritable(self): return self.writeable def setWritable(self,val): self.writeable = val # dev, nodev def getUseDevPoints(self): return self.usedevpoints def setUseDevPoints(self,val): self.usedevpoints = val # exec/noexec def getAllowExecutables(self): return self.allowexecutables def setAllowExecutable(self,val): self.allowexecutables = val # suid/nosuid def getSUID(self): return self.allowsuid def setSUID(self,val): self.allowsuid = val # nouser/user/users/owner def setAllowUserMount(self,val): self.allowusermount = val def getAllowUserMount(self): return self.allowusermount ############################################################################ # Common unix filesystems, but for local hard disks. i.e. partitions. class MountEntryExtCommonUnixLocal(MountEntryExtCommonUnix): ######################################################################## def __init__(self,base=None): super(MountEntryExtCommonUnixLocal,self).__init__(base) ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtCommonUnixLocal() super(MountEntryExtCommonUnixLocal,self).copy(newobject) newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid return newobject ############################################################################ class MountEntryExtAlien(MountEntryExt): USERMOUNT_NO = 0 USERMOUNT_ONE = 1 USERMOUNT_ANY = 2 USERMOUNT_OWNER = 3 ######################################################################## # Base can be either a fstab format line of text, of another MountEntry # object. def __init__(self,base=None): super(MountEntryExtAlien,self).__init__(base) if isinstance(base,MountEntryExtAlien): self.uid = base.uid self.gid = base.gid self.label = base.label self.writeable = base.writeable self.auto = base.auto self.allowusermount = base.allowusermount elif isinstance(base,StringType) or isinstance(base,UnicodeType): self.uid = 0 self.gid = 0 options = self.extraoptions.split(",") newoptions = [] for line in options: if line.startswith("uid="): try: self.uid = int(line[4:]) except ValueError: self.uid = 0 elif line.startswith("gid="): try: self.gid = int(line[4:]) except ValueError: self.gid = 0 else: # We hang on to unknown options for later. newoptions.append(line) options = newoptions self.writeable = True if "ro" in options: self.writeable = False self.auto = True if "noauto" in options: self.auto = False self.allowusermount = self.USERMOUNT_NO if "user" in options: self.allowusermount = self.USERMOUNT_ONE if "users" in options: self.allowusermount = self.USERMOUNT_ANY if "owner" in options: self.allowusermount = self.USERMOUNT_OWNER for x in ["noatime","atime","auto","noauto","dev","nodev","nouser", \ "owner","users","user","suid","nosuid","exec","noexec","rw", \ "ro"]: try: options.remove(x) except ValueError: pass self.extraoptions = ",".join(options) else: self.uid = 0 self.gid = 0 self.writeable = False self.auto = False self.allowusermount = self.USERMOUNT_NO ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtAlien() super(MountEntryExtAlien,self).copy(newobject) newobject.uid = self.uid newobject.gid = self.gid newobject.use_as_device = self.use_as_device newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid newobject.writeable = self.writeable newobject.auto = self.auto newobject.allowusermount = self.allowusermount return newobject ######################################################################## def getFstabOptions(self): # Construct the options field. options = super(MountEntryExtAlien,self).getFstabOptions() options.append('uid='+unicode(self.uid)) options.append('gid='+unicode(self.gid)) options.append(['noauto','auto'][self.auto]) options.append(['ro','rw'][self.writeable]) options.append(['nouser','user','users','owner'][self.allowusermount]) return options ######################################################################## def getUID(self): return self.uid def setUID(self,val): self.uid = val def getGID(self): return self.gid def setGID(self,val): self.gid = val # ro/rw def getWritable(self): return self.writeable def setWritable(self,val): self.writeable = val # auto/noauto def getMountAtBoot(self): return self.auto def setMountAtBoot(self,val): self.auto = val # nouser/user/users/owner def setAllowUserMount(self,val): self.allowusermount = val def getAllowUserMount(self): return self.allowusermount ############################################################################ class MountEntryExtVFAT(MountEntryExtAlien): def __init__(self,base=None): super(MountEntryExtVFAT,self).__init__(base) if isinstance(base,MountEntryExtVFAT): self.suppresspermissionerrors = base.suppresspermissionerrors elif isinstance(base,StringType) or isinstance(base,UnicodeType): options = self.extraoptions.split(",") self.suppresspermissionerrors = "quiet" in options try: options.remove("quiet") except ValueError: pass self.extraoptions = ",".join(options) else: self.suppresspermissionerrors = False ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtVFAT() super(MountEntryExtVFAT,self).copy(newobject) newobject.suppresspermissionerrors = self.suppresspermissionerrors newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid return newobject ######################################################################## def getFstabOptions(self): options = super(MountEntryExtVFAT,self).getFstabOptions() if self.suppresspermissionerrors: options.append('quiet') return options def getSuppressPermissionErrors(self): return self.suppresspermissionerrors def setSuppressPermissionErrors(self,val): self.suppresspermissionerrors = val ############################################################################ class MountEntryExtSMB(MountEntryExtAlien): CREDENTIALSBASENAME = "/etc/fstab_smb_credentials_" ######################################################################## def __init__(self,base=None): super(MountEntryExtSMB,self).__init__(base) if isinstance(base,MountEntryExtSMB): self.username = base.username self.password = base.password self.credentialsfile = base.credentialsfile elif isinstance(base,StringType) or isinstance(base,UnicodeType): self.username = None self.password = "" self.credentialsfile = None newoptions = [] options = self.extraoptions.split(",") for line in options: if line.startswith("username="): self.username = line[9:] elif line.startswith("password="): self.password = line[9:] elif line.startswith("credentials="): self.credentialsfile = line[12:] try: fhandle = codecs.open(self.credentialsfile,'r',locale.getpreferredencoding()) for line in fhandle.readlines(): if line.startswith("username"): self.username = line[8:].strip()[1:].strip() elif line.startswith("password"): self.password = line[8:].strip()[1:].strip() fhandle.close() if not self.credentialsfile.startswith(self.CREDENTIALSBASENAME): self.credentialsfile = None except IOError: self.credentialsfile = None elif line=="guest": pass else: # We hang on to unknown options for later. newoptions.append(line) options = newoptions if self.username == "": self.username = None self.extraoptions = ",".join(options) else: self.username = None self.password = "" self.credentialsfile = None ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtSMB() super(MountEntryExtSMB,self).copy(newobject) newobject.username = self.username newobject.password = self.password newobject.credentialsfile = self.credentialsfile newobject.showlabel = self.showlabel newobject.showdevice = self.showdevice newobject.showuuid = self.showuuid return newobject ######################################################################## def cleanup(self): if (self.credentialsfile is not None) and os.path.exists(self.credentialsfile) and os.path.isfile(self.credentialsfile): os.remove(self.credentialsfile) ######################################################################## def getIconName(self): return "hi16-network" ######################################################################## def getFstabOptions(self): options = super(MountEntryExtSMB,self).getFstabOptions() if self.username is None: if (self.credentialsfile is not None) and os.path.exists(self.credentialsfile) and os.path.isfile(self.credentialsfile): os.remove(self.credentialsfile) options.append("guest") # This option should stop mount(8) from asking for a password. else: # Write out the credentials file if self.credentialsfile is None: i = 1 while os.path.exists(self.CREDENTIALSBASENAME+unicode(i)): i += 1 self.credentialsfile = self.CREDENTIALSBASENAME+unicode(i) fd = os.open(self.credentialsfile,os.O_WRONLY|os.O_CREAT,0600) fhandle = os.fdopen(fd,'w') fhandle.write((u"username = %s\npassword = %s\n" % (self.username,self.password)) .encode(locale.getpreferredencoding(),'replace') ) fhandle.close() options.append(u"credentials="+self.credentialsfile) return options ######################################################################## def getUsername(self): return self.username def setUsername(self,username): self.username = username def getPassword(self): return self.password def setPassword(self,password): self.password = password ############################################################################ class MountEntryExtSystem(MountEntryExt): ######################################################################## def __init__(self,base=None): super(MountEntryExtSystem,self).__init__(base) self.use_as_device = "devicenode" self.label = "" self.showuuid = False self.showlabel = False ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtSystem() super(MountEntryExtSystem,self).copy(newobject) return newobject ######################################################################## def getCategory(self): return "system" def disable(self,parentdialog): """ This shouldn't happen since system entries have the disable button disabled """ msg = i18n("Disabling %1 is not supported.").arg(self.mountpoint) extramsg = i18n("""Some system devices cannot be disabled because they are needed for \ basic functionality of the operating system.""") KMessageBox.detailedSorry(parentdialog,msg,extramsg,\ i18n("Error occurred while disabling %1").arg(self.mountpoint)) ############################################################################ class MountEntryExtSwap(MountEntryExt): ######################################################################## # Base can be either a fstab format line of text, of another MountEntry # object. def __init__(self,base=None): super(MountEntryExtSwap,self).__init__(base) if isinstance(base,StringType) or isinstance(base,UnicodeType): options = self.extraoptions.split(",") try: options.remove('defaults') except ValueError: pass self.extraoptions = u",".join(options) ######################################################################## def copy(self,newobject=None): if newobject is None: newobject = MountEntryExtSwap() super(MountEntryExtSwap,self).copy(newobject) return newobject ######################################################################## def getFstabOptions(self): options = super(MountEntryExtSwap,self).getFstabOptions() if len(options)==0: # Make sure there is at least one option in the list. options.append('defaults') return options ######################################################################## def updateStatus(self,mtablist): this_device = self.device if this_device is None: # Find the device name by its UUID. if self.uuid: hal_device = microhal.getDeviceByUUID(self.uuid) if self.label: hal_device = microhal.getDeviceByLabel(self.label) if hal_device is None: self.enabled = False return this_device = hal_device.getDev() # If the device is a symlink, then grab the complete target. if os.path.islink(this_device): this_device = os.path.join(os.path.dirname(this_device),os.readlink(this_device)) fhandle = open("/proc/swaps") lines = fhandle.readlines() fhandle.close() try: del lines[0] except IndexError: pass self.enabled = False for line in lines: parts = line.split() if parts[0]==this_device: self.enabled = True return ######################################################################## # Returns a list of command+arguments def enable(self,parentdialog): self._setBusy(parentdialog,True) try: (rc,output) = SimpleCommandRunner().run(['/sbin/swapon',self.device]) if rc!=0: msg = i18n("An error occurred while enabling swap partition %1.\n\nThe system reported: %2").arg(self.device).arg(output) KMessageBox.sorry(parentdialog,msg,\ i18n("Error occurred while enabling swap partition %1").arg(self.device)) finally: self._setBusy(parentdialog,False) ######################################################################## # Returns a list of command+arguments or None. def disable(self,parentdialog): self._setBusy(parentdialog,True) try: (rc,output) = SimpleCommandRunner().run(['/sbin/swapoff',self.device]) if rc!=0: msg = i18n("An error occurred while disabling swap partition %1.\n\nThe system reported: %2").arg(self.device).arg(output) KMessageBox.sorry(parentdialog,msg,\ i18n("Error occurred while disabling swap partition %1").arg(self.device)) finally: self._setBusy(parentdialog,False) ############################################################################ # This represents a mount entry. # # It also does a little trick with the MountEntryExt classes. MountEntry # objects kind of 'change' class under your nose when they are set to # different mount types. The handling of the different kinds of mount types # is handled by MountEntryExt objects and subclasses. class MountEntry(object): MountTypes = { 'proc' : (MountEntryExtSystem,i18n("proc")), 'sysfs' : (MountEntryExtSystem,i18n("sysfs")), 'rootfs' : (MountEntryExtSystem,i18n("rootfs")), 'bdev' : (MountEntryExtSystem,i18n("bdev")), 'sockfs' : (MountEntryExtSystem,i18n("sockfs")), 'tmpfs' : (MountEntryExtSystem,i18n("tmpfs")), 'shm' : (MountEntryExtSystem,i18n("shm")), 'pipefs' : (MountEntryExtSystem,i18n("pipefs")), 'devfs' : (MountEntryExtSystem,i18n("devfs - Device File System")), 'devpts' : (MountEntryExtSystem,i18n("devpts")), 'ramfs' : (MountEntryExtSystem,i18n("ramfs")), 'auto' : (MountEntryExtCommonUnix,i18n("Automatic")), 'usbdevfs' : (MountEntryExtSystem,i18n("usbdevfs")), 'procbususb' : (MountEntryExtSystem,i18n("procbususb")), 'usbfs' : (MountEntryExtSystem,i18n("usbfs")), 'supermount' : (MountEntryExt,i18n("supermount")), 'swap' : (MountEntryExtSwap,i18n("Swap - Linux Swap Space")), 'nfs' : (MountEntryExtCommonUnix,i18n("NFS - Network File System")), 'cifs' : (MountEntryExtSMB,i18n("Windows File Sharing")), 'ext2' : (MountEntryExtCommonUnixLocal,i18n("Ext2 - Second Extended FS")), 'ext3' : (MountEntryExtCommonUnixLocal,i18n("Ext3 - Third Extended FS")), 'reiserfs' : (MountEntryExtCommonUnixLocal,i18n("ReiserFS")), 'reiser4' : (MountEntryExtCommonUnixLocal,i18n("Reiser4")), 'xfs' : (MountEntryExtCommonUnixLocal,i18n("XFS - SGI's journaling filesystem")), 'hfs' : (MountEntryExtCommonUnixLocal,i18n("HFS - Apple's Hierarchical File System")), 'hfsplus' : (MountEntryExtVFAT,i18n("HFS+ - Apple's modernized Hierarchical File System")), 'jfs' : (MountEntryExtCommonUnixLocal,i18n("JFS - IBM's Journaled File System")), 'vfat' : (MountEntryExtVFAT,i18n("VFAT - Microsoft FAT File Systems")), 'ntfs' : (MountEntryExtVFAT,i18n("NTFS - NT File System")), 'udf' : (MountEntryExtSystem,i18n("udf")), 'iso9660' : (MountEntryExt,i18n("iso9660 - CD-ROM")), } notInFstab = False maydisable = True # Some entries, such as /proc can't be disabled. ######################################################################## # Base can be either a fstab format line of text, of another MountEntry # object. def __init__(self,base=None): try: self.extensionObjects = {} if base==None: self.mounttype = 'auto' elif isinstance(base,StringType) or isinstance(base,UnicodeType): parts = base.split() self.mounttype = parts[2] # 'udf,iso9660' seems default for some devices in fstab, # check if all listed filesystems are available, if yes set to 'auto'. if len(self.mounttype.split(',')) > 1: """ # We could check here, but then we'd need a reference to MicroHAL. #for m in self.mounttype.split(','): #if m not in supported_fs: # print "Filesystem ", m, "not supported by the kernel" # break """ self.mounttype = "auto" else: # This is a new entry, but it's based on another one. self.mounttype = base.mounttype self.extension = self.MountTypes[self.mounttype][0](base) self.extensionObjects[self.mounttype] = self.extension except (KeyError,IndexError): raise InvalidMountEntryError, u"Unable to parse mount entry:"+unicode(base) ######################################################################## def getMountType(self): return self.mounttype ######################################################################## def setMountType(self,newtypename): if newtypename not in self.extensionObjects: try: self.extensionObjects[newtypename] = self.MountTypes[newtypename][0](self.extension) except KeyError: raise NotImplementedError, "Unknown mounttype:"+newtypename self.mounttype = newtypename self.extension = self.extensionObjects[newtypename] self.extension.setMountType(newtypename) ######################################################################## def copy(self): newentry = MountEntry() newentry.mounttype = self.mounttype newext = self.extension.copy() newentry.use_as_device = self.use_as_device newentry.showlabel = self.showlabel newentry.showdevice = self.showdevice newentry.showuuid = self.showuuid newentry.extensionObjects[self.mounttype] = newext newentry.extension = newext return newentry ######################################################################## def inPlaceCopyFrom(self,sourceentry): self.extension.cleanup() tmpcopy = sourceentry.copy() self.extensionObjects = tmpcopy.extensionObjects self.mounttype = tmpcopy.mounttype self.extension = tmpcopy.extension # Override the attribute lookup, set/get, to use the extension object ######################################################################## def __getattr__(self,name): try: return getattr(self.extension,name) except AttributeError, a: print a ######################################################################## # FIXME ## def __setattr__(self,name,value): ## if 'extension' in self.__dict__: ## if name in self.extension.__dict__: ## setattr(self.extension,name,value) ## return ## self.__dict__[name] = value ######################################################################## def getMountTypes(): return MountEntry.MountTypes.keys() getMountTypes = staticmethod(getMountTypes) ######################################################################## def getMountTypeLongName(typename): return MountEntry.MountTypes[typename][1] getMountTypeLongName = staticmethod(getMountTypeLongName) ######################################################################## def encodeMountEntryString(string): newstring = u"" for c in string: if c==' ': newstring += "\\040" elif c=="\t": newstring += "\\012" elif c=='\\': newstring += "\\134" else: newstring += c return newstring encodeMountEntryString = staticmethod(encodeMountEntryString) ######################################################################## def decodeMountEntryString(string): newstring = "" while string!="": if len(string)>=4 and string[0]=='\\' and isoct(string[1]) \ and isoct(string[2]) and isoct(string[3]): newstring += chr(64*(ord(string[1])-ord('0')) + \ 8*(ord(string[2])-ord('0')) + (ord(string[3])-ord('0'))) string = string[4:] else: newstring += string[0] string = string[1:] return newstring decodeMountEntryString = staticmethod(decodeMountEntryString) ############################################################################ class MountEntryComment(MountEntry): """ This represents a comment mount entry or generally something that we don't understand (might be comment, might be fstab syntax we don't know, might be a faulty line in there). We don't want to wipe that stuff out, but we can't deal with it in a sensible way, so we keep it in a MountEntryComment, exclude it from most operations, but will write it back to fstab afterwards As a result of that we only define the stuff that's necessary, namely saving the fstab line and returning it when writing.""" ######################################################################## def __init__(self,base=None): self.row = base ######################################################################## def getFstabLine(self): return self.row ############################################################################ def isoct(c): return c in '01234567' ############################################################################ class InvalidMountEntryError(Exception): ######################################################################## def __init__(self,arg=None): self.arg = arg ######################################################################## def __str__(self): return str(self.arg) ############################################################################ class MountTable(object): ######################################################################## def __init__(self,fstab_filename,mtab_filename): self.fstab_filename = fstab_filename self.mtab_filename = mtab_filename self.entries = [] self.allentries = [] # sysfs does not need an entry in fstab, so we add it even if it's not # in there, it's mounted automatically anyway and shows up in mtab sysfs_in_fstab = False usbdevfs_in_fstab = False fhandle = codecs.open(self.fstab_filename,'r',locale.getpreferredencoding()) for row in fhandle.readlines(): row = row.strip('\n') # Carefully remove any trailing newline. if row.strip().startswith("#") or row.strip()=="": entry = MountEntryComment(row) else: try: entry = MountEntry(row) self.append(entry) if entry.getMountType() == "sysfs": sysfs_in_fstab = True if entry.getMountType() == "usbdevfs" or "procbususb": usbdevfs_in_fstab = True if entry.getMountType() == "proc": entry.maydisable = False except InvalidMountEntryError: entry = MountEntryComment(row) # We keep a list with references to _all_ entries, also the comments, # this is the one we'll use to write out our new fstab, only 'real' # entries (real == entries we understand) are added to self to let them # be handled by iterator. # allentries includes comments and invalid lines, self doesn't. self.allentries.append(entry) fhandle.close() if not sysfs_in_fstab: sysfsentry = MountEntry(u"sysfs /sys sysfs defaults 0 0") sysfsentry.notInFstab = True sysfsentry.maydisable = False #self.append(sysfsentry) if not usbdevfs_in_fstab: usbdevfsentry = MountEntry(u"procbususb /proc/bus/usb usbdevfs defaults 0 0") usbdevfsentry.notInFstab = True usbdevfsentry.maydisable = False self.append(usbdevfsentry) self.updateStatus() ######################################################################## def append(self,entry): self.entries.append(entry) ######################################################################## def remove(self,entry): self.allentries.remove(entry) entry.cleanup() ######################################################################## def updateStatus(self,entry=None): mtablist = self.getMtabList() if entry==None: for entry in self.entries: entry.updateStatus(mtablist) else: entry.updateStatus(mtablist) ######################################################################## def getMtabList(self): fhandle = open(self.mtab_filename) mtablist = [] for row in fhandle.readlines(): if row.strip()[0]!='#': parts = row.split() mtablist.append(parts[1]) fhandle.close() return mtablist ######################################################################## def updateFstabOnDisk(self): fhandle = None try: try: fhandle = codecs.open(self.fstab_filename+"~","w",locale.getpreferredencoding(),'replace') for entry in self.allentries: if not entry.notInFstab: line = entry.getFstabLine() fhandle.write(line+u"\n") print line fhandle.close() fhandle = None # Move it over the original os.rename(self.fstab_filename+"~",self.fstab_filename) return True finally: if fhandle: fhandle.close() except IOError: return False ######################################################################## # We make this class look like a container, and just forward everything # on to the entries attribute. def __contains__(self,item): return self.entries.__contains(item) ######################################################################## def __delitem__(self,key): raise NotImplementedError, "No __delitem__ on MountTable." ######################################################################## def __getitem__(self,key): return self.entries.__getitem__(key) ######################################################################## def __iter__(self): return self.entries.__iter__() ######################################################################## def __len__(self): return self.entries.__len__() ######################################################################## def __setitem__(self,key,value): raise NotImplementedError, "No __setitem__ on MountTable." ############################################################################ class MountEntryDialogOptions(QWidget): deviceexample = i18n("(for example /dev/hdb3)") ######################################################################## def __init__(self,parent,showmountpoint=True,showdevice=True, showfs_freq=True,showfs_passno=True,showuuid=True,showlabel=True): QWidget.__init__(self,parent) self.showmountpoint = showmountpoint self.showdevice = showdevice self.showfs_freq = showfs_freq self.showfs_passno = showfs_passno self.showuuid = showuuid self.showlabel = showlabel self._fillPage() # TODO: KDirSelectDialog needs "Create new Folder" self.mountpointdialog = KDirSelectDialog("/",True,self,"Select Mount Point",True) ######################################################################## def _fillPage(self): row = 0 grid = QGridLayout(self,1,2) grid.setSpacing(KDialog.spacingHint()) grid.setColStretch(0,0) grid.setColStretch(2,0) if self.showmountpoint: label = QLabel(i18n("Mount Point:"),self) grid.addWidget(label,row,0) hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.mountpointlineedit = KLineEdit(hbox) hbox.setStretchFactor(self.mountpointlineedit,1) #self.connect(self.homediredit, SIGNAL("textChanged(const QString &)"), self.slotHomeDirChanged) self.mountpointbutton = KPushButton(i18n("Browse..."),hbox) hbox.setStretchFactor(self.mountpointbutton,0) self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked) grid.addMultiCellWidget(hbox,row,row,1,3) row += 1 if self.showdevice: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicecheckbox = QRadioButton(i18n("by name"),hbox) self.connect(self.devicecheckbox,SIGNAL("clicked()"), \ self.slotDeviceCheckboxClicked) self.devicelineedit = KLineEdit(hbox) grid.addMultiCellWidget(hbox,row,row,1,3) row += 1 example = QLabel(self.deviceexample,self) grid.addMultiCellWidget(example,row,row,1,3) row += 1 if self.showuuid: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.uuidcheckbox = QRadioButton(i18n("by UUID"),hbox) self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \ self.slotUUIDCheckboxClicked) self.uuidlineedit = KLineEdit(hbox) grid.addMultiCellWidget(hbox,row,row,1,3) row += 1 if self.showlabel: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.labelcheckbox = QRadioButton(i18n("by label"),hbox) self.connect(self.labelcheckbox,SIGNAL("clicked()"), \ self.slotLabelCheckboxClicked) self.labellineedit = KLineEdit(hbox) grid.addMultiCellWidget(hbox,row,row,1,3) row += 1 else: if self.showdevice: label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicelineedit = KLineEdit(self) grid.addMultiCellWidget(self.devicelineedit,row,row,1,3) row += 1 example = QLabel(self.deviceexample,self) grid.addWidget(example,row,1) if self.showuuid: label = QLabel(i18n("Device UUID:"),self) grid.addWidget(label,row,0) self.uuidlineedit = KLineEdit(self) grid.addMultiCellWidget(self.uuidlineedit,row,row,1,3) row += 1 if self.showlabel: label = QLabel(i18n("Device Label:"),self) grid.addWidget(label,row,0) self.labellineedit = KLineEdit(self) grid.addMultiCellWidget(self.labellineedit,row,row,1,3) row += 1 label = QLabel(i18n("Options:"),self) grid.addWidget(label,row,0) self.optionslineedit = KLineEdit(self) grid.addMultiCellWidget(self.optionslineedit,row,row,1,3) row += 1 if self.showfs_freq: label = QLabel(i18n("fs_freq:"),self) grid.addWidget(label,row,0) self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,self) grid.addWidget(self.fsfreqspinbox,row,1) if self.showfs_passno: label = QLabel(i18n("fs_passno:"),self) grid.addWidget(label,row,2) self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,self) grid.addWidget(self.fspassnospinbox,row,3) row += 1 grid.addWidget(QWidget(self),row,0) for x in range(grid.numRows()): grid.setRowStretch(x,0) grid.setRowStretch(grid.numRows()-1,1) ######################################################################## def displayMountEntry(self,entry): global allowuuid, allowlabel if self.showmountpoint: self.mountpointlineedit.setText(entry.getMountPoint()) uuid = entry.getUUID() if entry.getDevice() == "" and uuid != "": device = microhal.getDeviceByUUID(uuid) self.devicelineedit.setText(uuid) else: if self.showdevice: self.devicelineedit.setText(entry.getDevice()) if self.showuuid: if entry.getUUID()!="": self.uuidlineedit.setText(entry.getUUID()) if self.showlabel: if entry.getLabel()!="": self.labellineedit.setText(entry.getLabel()) if entry.getUseAsDevice() == "devicenode": if self.showdevice: self.devicelineedit.setEnabled(True) self.devicecheckbox.setChecked(True) if self.showuuid: self.uuidcheckbox.setChecked(False) self.uuidlineedit.setEnabled(False) if self.showlabel: self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) elif entry.getUseAsDevice() == "label": if self.showlabel: self.labellineedit.setEnabled(True) self.labelcheckbox.setChecked(True) if self.showdevice: self.devicelineedit.setEnabled(False) self.devicecheckbox.setChecked(False) if self.showuuid: self.uuidlineedit.setEnabled(False) self.uuidcheckbox.setChecked(False) elif entry.getUseAsDevice() == "uuid": if self.showdevice: self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) if self.showlabel: self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) if self.showuuid: self.uuidlineedit.setEnabled(True) self.uuidcheckbox.setChecked(True) ## if allowlabel: ## self.labellineedit.setText(entry.getLabel()) ## if allowuuid: ## self.uuidlineedit.setText(entry.getUUID()) ## self.devicelineedit.setText(entry.getDevice()) self.optionslineedit.setText(entry.getExtraOptions()) if self.showfs_freq: self.fsfreqspinbox.setValue(entry.getFSFreq()) if self.showfs_passno: self.fspassnospinbox.setValue(entry.getFSPassno()) ######################################################################## def undisplayMountEntry(self,entry): if self.showmountpoint: entry.setMountPoint( unicode(self.mountpointlineedit.text()) ) if self.showdevice: entry.setDevice( unicode(self.devicelineedit.text()) ) if self.showuuid and self.showdevice: if self.devicecheckbox.isChecked(): entry.setUUID(None) else: entry.setUUID( unicode(self.uuidlineedit.text()) ) if self.showlabel and self.showdevice: if self.devicecheckbox.isChecked(): entry.setLabel(None) else: entry.setLabel( unicode(self.labellineedit.text()) ) if allowuuid and self.showuuid: if self.uuidcheckbox.isChecked(): entry.setUseAsDevice("uuid") if allowlabel and self.showlabel: if self.labelcheckbox.isChecked(): entry.setUseAsDevice("label") if self.showdevice: if self.devicecheckbox.isChecked(): entry.setUseAsDevice("devicenode") entry.setExtraOptions( unicode(self.optionslineedit.text()) ) if self.showfs_freq: entry.setFSFreq(self.fsfreqspinbox.value()) if self.showfs_passno: entry.setFSPassno(self.fspassnospinbox.value()) ######################################################################## def slotBrowseMountPointClicked(self): fileurl = KURL() fileurl.setPath(self.mountpointlineedit.text()) self.mountpointdialog.setCurrentURL(fileurl) if self.mountpointdialog.exec_loop()==QDialog.Accepted: self.mountpointlineedit.setText(self.mountpointdialog.url().path()) ######################################################################## def slotDeviceCheckboxClicked(self): self.uuidcheckbox.setChecked(False) self.labelcheckbox.setChecked(False) self.devicelineedit.setEnabled(True) self.uuidlineedit.setEnabled(False) self.labellineedit.setEnabled(False) ######################################################################## def slotUUIDCheckboxClicked(self): if self.uuidlineedit.text() == "": label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text())) self.uuidlineedit.setText(label) self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.uuidlineedit.setEnabled(True) self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) def slotLabelCheckboxClicked(self): if self.labellineedit.text() == "": label = microhal.getLabelByDevice(unicode(self.devicelineedit.text())) self.labellineedit.setText(label) self.uuidcheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.uuidlineedit.setEnabled(False) self.labelcheckbox.setChecked(True) self.labellineedit.setEnabled(True) ############################################################################ class MountEntryDialogOptionsCommonUnix(MountEntryDialogOptions): ######################################################################## def __init__(self,parent): MountEntryDialogOptions.__init__(self,parent) self.advanceddialog = MountEntryAdvancedCommonUnixDialog(None) ######################################################################## def _fillPage(self): row = 0 grid = QGridLayout(self,1,2) grid.setSpacing(KDialog.spacingHint()) grid.setColStretch(0,0) grid.setRowStretch(6,1) label = QLabel(i18n("Mount Point:"),self) grid.addWidget(label,row,0) hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.mountpointlineedit = KLineEdit(hbox) hbox.setStretchFactor(self.mountpointlineedit,1) #self.connect(self.homediredit, SIGNAL("textChanged(const QString &)"), self.slotHomeDirChanged) self.mountpointbutton = KPushButton(i18n("Browse..."),hbox) hbox.setStretchFactor(self.mountpointbutton,0) self.connect(self.mountpointbutton,SIGNAL("clicked()"), \ self.slotBrowseMountPointClicked) grid.addWidget(hbox,row,1) row += 1 if self.showuuid or self.showlabel: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicecheckbox = QRadioButton(i18n("by name"),hbox) self.connect(self.devicecheckbox,SIGNAL("clicked()"), \ self.slotDeviceCheckboxClicked) self.devicelineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 example = QLabel(self.deviceexample,self) grid.addWidget(example,row,1) row += 1 if self.showuuid: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.uuidcheckbox = QRadioButton(i18n("by UUID"),hbox) self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \ self.slotUUIDCheckboxClicked) self.uuidlineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 if self.showlabel: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.labelcheckbox = QRadioButton(i18n("by label"),hbox) self.connect(self.labelcheckbox,SIGNAL("clicked()"), \ self.slotLabelCheckboxClicked) self.labellineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 else: label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicelineedit = KLineEdit(self) grid.addWidget(self.devicelineedit,row,1) row += 1 example = QLabel(self.deviceexample,self) grid.addWidget(example,row,1) row += 1 self.autocheckbox = QCheckBox(i18n("Enable at start up"),self) grid.addWidget(self.autocheckbox,row,1) row += 1 self.writeablecheckbox = QCheckBox(i18n("Writeable"),self) grid.addWidget(self.writeablecheckbox,row,1) row += 1 label = QLabel(i18n("Mount Permission:"),self) grid.addWidget(label,row,0) self.usermountcombobox = KComboBox(self) self.usermountcombobox.insertItem(i18n("Root user only may enable/disable")) self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable")) self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime")) self.usermountcombobox.insertItem(i18n("Device owner may enable/disable")) grid.addWidget(self.usermountcombobox,row,1) row += 1 #grid.addWidget(,9,0) button = KPushButton(i18n("Advanced..."),self) button.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed) self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked) grid.addWidget(button,row,1,Qt.AlignRight) row += 1 grid.addWidget(QWidget(self),row,0) for x in range(grid.numRows()): grid.setRowStretch(x,0) grid.setRowStretch(grid.numRows()-1,1) ######################################################################## def displayMountEntry(self,entry): self.devicelineedit.setText(entry.getDevice()) if self.showuuid: if entry.getUUID()!="": self.uuidlineedit.setText(entry.getUUID()) if self.showlabel: if entry.getLabel()!="": self.labellineedit.setText(entry.getLabel()) if entry.getUseAsDevice() == "devicenode": self.devicelineedit.setEnabled(True) self.devicecheckbox.setChecked(True) self.uuidcheckbox.setChecked(False) self.uuidlineedit.setEnabled(False) self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) elif entry.getUseAsDevice() == "label": self.labellineedit.setEnabled(True) self.labelcheckbox.setChecked(True) self.devicelineedit.setEnabled(False) self.devicecheckbox.setChecked(False) self.uuidlineedit.setEnabled(False) self.uuidcheckbox.setChecked(False) elif entry.getUseAsDevice() == "uuid": self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) self.uuidlineedit.setEnabled(True) self.uuidcheckbox.setChecked(True) self.devicelineedit.setText(entry.getDevice()) self.mountpointlineedit.setText(entry.getMountPoint()) self.options = entry.getExtraOptions() self.fsfreq = entry.getFSFreq() self.fspassno = entry.getFSPassno() self.autocheckbox.setChecked(entry.getMountAtBoot()) self.writeablecheckbox.setChecked(entry.getWritable()) self.accesstime = entry.getAtime() self.allowexecutable = entry.getAllowExecutables() self.allowsuid = entry.getSUID() self.usedevpoints = entry.getUseDevPoints() self.usermountcombobox.setCurrentItem(entry.getAllowUserMount()) ######################################################################## def undisplayMountEntry(self,entry): entry.setDevice( unicode(self.devicelineedit.text()) ) if self.showuuid: if self.devicecheckbox.isChecked() or self.labelcheckbox.isChecked(): entry.setUUID(None) else: entry.setUUID( unicode(self.uuidlineedit.text()) ) if self.showlabel: if self.devicecheckbox.isChecked() or self.uuidcheckbox.isChecked(): entry.setLabel(None) else: entry.setLabel( unicode(self.labellineedit.text()) ) if not self.showlabel and not self.showuuid: if self.uuidcheckbox.isChecked() or self.labelcheckbox.isChecked(): entry.setLabel(None) else: entry.setLabel( unicode(self.devicelineedit.text()) ) if allowuuid: if self.uuidcheckbox.isChecked(): entry.setUseAsDevice("uuid") if allowlabel: if self.labelcheckbox.isChecked(): entry.setUseAsDevice("label") if self.devicecheckbox.isChecked(): entry.setUseAsDevice("devicenode") entry.setMountPoint( unicode(self.mountpointlineedit.text()) ) entry.setExtraOptions(self.options) entry.setFSFreq(self.fsfreq) entry.setFSPassno(self.fspassno) entry.setAtime(self.accesstime) entry.setMountAtBoot(self.autocheckbox.isChecked()) entry.setWritable(self.writeablecheckbox.isChecked()) entry.setUseDevPoints(self.usedevpoints) entry.setAllowExecutable(self.allowexecutable) entry.setSUID(self.allowsuid) entry.setAllowUserMount(self.usermountcombobox.currentItem()) ######################################################################## def slotAdvancedClicked(self): (self.accesstime, self.allowexecutable, self.allowsuid, self.usedevpoints, self.options, self.fsfreq, self.fspassno)\ = self.advanceddialog.do(self.accesstime, self.allowexecutable, self.allowsuid, self.usedevpoints, self.options, self.fsfreq, self.fspassno) ######################################################################## def slotDeviceCheckboxClicked(self): self.uuidcheckbox.setChecked(False) self.devicelineedit.setEnabled(True) self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) self.uuidlineedit.setEnabled(False) ######################################################################## def slotUUIDCheckboxClicked(self): if self.uuidlineedit.text() == "": label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text())) self.uuidlineedit.setText(label) self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.labelcheckbox.setChecked(False) self.labellineedit.setEnabled(False) self.uuidlineedit.setEnabled(True) def slotLabelCheckboxClicked(self): if self.labellineedit.text() == "": label = microhal.getLabelByDevice(unicode(self.devicelineedit.text())) self.labellineedit.setText(label) self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.uuidcheckbox.setChecked(False) self.uuidlineedit.setEnabled(False) self.labellineedit.setEnabled(True) ############################################################################ class MountEntryDialogOptionsSys(MountEntryDialogOptions): ######################################################################## def __init__(self,parent): MountEntryDialogOptions.__init__(self,parent,True,False,False,False,False,False) ############################################################################ class MountEntryDialogOptionsSwap(MountEntryDialogOptions): ######################################################################## def __init__(self,parent): MountEntryDialogOptions.__init__(self,parent,False,True,False,False) class MountEntryDialogOptionsNfs(MountEntryDialogOptionsCommonUnix): deviceexample = i18n("(for example 192.168.1.66:/export)") ############################################################################ class MountEntryDialogOptionsVFAT(MountEntryDialogOptions): ######################################################################## def __init__(self,parent): MountEntryDialogOptions.__init__(self,parent) self.advanceddialog = MountEntryAdvancedPlainDialog(None) self.updatinggui= False ######################################################################## def _fillPage(self): global allowuuid, allowlabel row = 0 grid = QGridLayout(self,11,2) grid.setSpacing(KDialog.spacingHint()) grid.setColStretch(0,0) grid.setColStretch(2,0) grid.setRowStretch(10,1) label = QLabel(i18n("Mount Point:"),self) grid.addWidget(label,row,0) hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.mountpointlineedit = KLineEdit(hbox) hbox.setStretchFactor(self.mountpointlineedit,1) #self.connect(self.homediredit, SIGNAL("textChanged(const QString &)"), self.slotHomeDirChanged) self.mountpointbutton = KPushButton(i18n("Browse..."),hbox) hbox.setStretchFactor(self.mountpointbutton,0) self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked) grid.addMultiCellWidget(hbox,row,row,1,3) row += 1 if allowuuid or allowlabel: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicecheckbox = QRadioButton(i18n("by name"),hbox) self.connect(self.devicecheckbox,SIGNAL("clicked()"), \ self.slotDeviceCheckboxClicked) self.devicelineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 example = QLabel(self.deviceexample,self) grid.addWidget(example,row,1) row += 1 if allowuuid and self.showuuid: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.uuidcheckbox = QRadioButton(i18n("by UUID"),hbox) self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \ self.slotUUIDCheckboxClicked) self.uuidlineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 if allowlabel and self.showlabel: hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.labelcheckbox = QRadioButton(i18n("by label"),hbox) self.connect(self.labelcheckbox,SIGNAL("clicked()"), \ self.slotLabelCheckboxClicked) self.labellineedit = KLineEdit(hbox) grid.addWidget(hbox,row,1) row += 1 else: label = QLabel(i18n("Device:"),self) grid.addWidget(label,row,0) self.devicelineedit = KLineEdit(self) grid.addMultiCellWidget(self.devicelineedit,row,row,1,3) row += 1 example = QLabel(self.deviceexample,self) grid.addWidget(example,row,1) row += 1 self.autocheckbox = QCheckBox(i18n("Enable at start up"),self) grid.addMultiCellWidget(self.autocheckbox,row,row,1,3) row += 1 # Security & Safety line. hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) tmplabel = QLabel(hbox) tmplabel.setPixmap(UserIcon("hi16-lock")) hbox.setStretchFactor(tmplabel,0) tmplabel = QLabel(hbox) tmplabel.setText(i18n("Security & Safety")) hbox.setStretchFactor(tmplabel,0) sep = KSeparator(KSeparator.Horizontal,hbox) hbox.setStretchFactor(sep,1) grid.addMultiCellWidget(hbox,row,row,0,3) row += 1 self.writeablecheckbox = QCheckBox(i18n("Writeable"),self) grid.addMultiCellWidget(self.writeablecheckbox,row,row,1,3) row += 1 label = QLabel(i18n("Files belong to user:"),self) grid.addWidget(label,row,0) self.uidcombobox = UserComboBox(self) grid.addMultiCellWidget(self.uidcombobox,row,row,1,3) row += 1 label = QLabel(i18n("Files belong to group:"),self) grid.addWidget(label,row,0) self.gidcombobox = GroupComboBox(self) grid.addMultiCellWidget(self.gidcombobox,row,row,1,3) row += 1 label = QLabel(i18n("Mount Permission:"),self) grid.addWidget(label,row,0) self.usermountcombobox = KComboBox(self) self.usermountcombobox.insertItem(i18n("Root user only may enable/disable")) self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable")) self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime")) self.usermountcombobox.insertItem(i18n("Device owner may enable/disable")) grid.addMultiCellWidget(self.usermountcombobox,row,row,1,3) row += 1 self.suppresspermissionerrorcheckbox = QCheckBox(i18n("Suppress permission errors"),self) grid.addMultiCellWidget(self.suppresspermissionerrorcheckbox,row,row,1,3) row += 1 row += 1 button = KPushButton(i18n("Advanced..."),self) button.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed) self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked) grid.addMultiCellWidget(button,row,row,1,3,Qt.AlignRight) ######################################################################## def displayMountEntry(self,entry): global allowuuid, allowlabel uuid = entry.getUUID() if entry.getDevice() == "" and uuid != "": device = microhal.getDeviceByUUID(uuid) self.devicelineedit.setText(uuid) else: self.devicelineedit.setText(entry.getDevice()) if allowuuid: self.uuidlineedit.setText(uuid) if entry.getUUID()!="": self.uuidlineedit.setEnabled(True) self.devicelineedit.setEnabled(False) self.devicecheckbox.setChecked(False) self.uuidcheckbox.setChecked(True) else: self.devicelineedit.setEnabled(True) self.uuidlineedit.setEnabled(False) self.devicecheckbox.setChecked(True) self.uuidcheckbox.setChecked(False) if allowlabel: # If the filesystem has a label override the UUID settings self.labellineedit.setText(entry.getLabel()) if entry.getLabel()!="": self.labellineedit.setEnabled(True) self.devicelineedit.setEnabled(False) self.devicecheckbox.setChecked(False) self.labelcheckbox.setChecked(True) self.uuidlineedit.setEnabled(False) self.uuidcheckbox.setChecked(False) else: if entry.getUUID()!="": self.uuidlineedit.setEnabled(True) self.devicelineedit.setEnabled(False) self.devicecheckbox.setChecked(False) self.uuidcheckbox.setChecked(True) else: self.devicelineedit.setEnabled(True) self.uuidlineedit.setEnabled(False) self.devicecheckbox.setChecked(True) self.uuidcheckbox.setChecked(False) if allowlabel: self.labellineedit.setText(entry.getLabel()) if allowuuid: self.uuidlineedit.setText(entry.getUUID()) self.devicelineedit.setText(entry.getDevice()) self.mountpointlineedit.setText(entry.getMountPoint()) self.options = entry.getExtraOptions() self.fsfreq = entry.getFSFreq() self.fspassno = entry.getFSPassno() self.writeablecheckbox.setChecked(entry.getWritable()) self.autocheckbox.setChecked(entry.getMountAtBoot()) self.usermountcombobox.setCurrentItem(entry.getAllowUserMount()) self.uidcombobox.setUID(entry.getUID()) self.gidcombobox.setGID(entry.getGID()) self.suppresspermissionerrorcheckbox.setChecked(entry.getSuppressPermissionErrors()) ######################################################################## def undisplayMountEntry(self,entry): global allowuuid, allowlabel if allowuuid: if self.devicecheckbox.isChecked(): entry.setUUID(None) else: if allowlabel: if self.labelcheckbox.isChecked(): entry.setLabel( unicode(self.labellineedit.text()) ) else: entry.setUUID( unicode(self.uuidlineedit.text()) ) else: entry.setUUID( unicode(self.uuidlineedit.text()) ) if allowlabel: if self.devicecheckbox.isChecked(): entry.setLabel(None) else: if allowuuid: if self.uuidcheckbox.isChecked(): entry.setUUID( unicode(self.uuidlineedit.text()) ) else: entry.setLabel( unicode(self.labellineedit.text()) ) else: entry.setLabel( unicode(self.labellineedit.text()) ) entry.setDevice( unicode(self.devicelineedit.text()) ) entry.setMountPoint( unicode(self.mountpointlineedit.text()) ) entry.setExtraOptions(self.options) entry.setFSFreq(self.fsfreq) entry.setFSPassno(self.fspassno) entry.setMountAtBoot(self.autocheckbox.isChecked()) entry.setWritable(self.writeablecheckbox.isChecked()) entry.setAllowUserMount(self.usermountcombobox.currentItem()) entry.setUID(self.uidcombobox.UID()) entry.setGID(self.gidcombobox.GID()) entry.setSuppressPermissionErrors(self.suppresspermissionerrorcheckbox.isChecked()) ######################################################################## def slotAdvancedClicked(self): (self.options, self.fsfreq, self.fspassno)\ = self.advanceddialog.do(self.options, self.fsfreq, self.fspassno) ######################################################################## def slotDeviceCheckboxClicked(self): self.uuidcheckbox.setChecked(False) self.devicelineedit.setEnabled(True) self.uuidlineedit.setEnabled(False) ######################################################################## def slotUUIDCheckboxClicked(self): if self.uuidlineedit.text() == "": label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text())) self.uuidlineedit.setText(label) self.devicecheckbox.setChecked(False) self.devicelineedit.setEnabled(False) self.uuidlineedit.setEnabled(True) ############################################################################ class MountEntryDialogOptionsSMB(MountEntryDialogOptions): ######################################################################## def __init__(self,parent): MountEntryDialogOptions.__init__(self,parent) self.advanceddialog = MountEntryAdvancedPlainDialog(None) self.updatinggui= False ######################################################################## def _fillPage(self): grid = QGridLayout(self,14,4) grid.setSpacing(KDialog.spacingHint()) grid.setColStretch(0,0) grid.setColStretch(2,0) grid.setRowStretch(12,1) label = QLabel(i18n("Mount Point:"),self) grid.addWidget(label,0,0) hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.mountpointlineedit = KLineEdit(hbox) hbox.setStretchFactor(self.mountpointlineedit,1) #self.connect(self.homediredit, SIGNAL("textChanged(const QString &)"), self.slotHomeDirChanged) self.mountpointbutton = KPushButton(i18n("Browse..."),hbox) hbox.setStretchFactor(self.mountpointbutton,0) self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked) grid.addMultiCellWidget(hbox,0,0,1,3) label = QLabel(i18n("Network Share:"),self) grid.addWidget(label,1,0) hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) self.devicelineedit = KLineEdit(hbox) hbox.setStretchFactor(self.devicelineedit,1) self.devicelinebutton = KPushButton(i18n("Scan..."),hbox) hbox.setStretchFactor(self.devicelinebutton,0) self.connect(self.devicelinebutton,SIGNAL("clicked()"),self.slotBrowseDeviceLineClicked) grid.addMultiCellWidget(hbox,1,1,1,3) # Connect as: connectaslabel = QLabel(self) connectaslabel.setText(i18n("Connect as:")) grid.addWidget(connectaslabel,2,0) self.guestradio = QRadioButton(self) self.guestradio.setChecked(True) grid.addWidget(self.guestradio,2,1) tmplabel = QLabel(self) tmplabel.setText(i18n("Guest")) grid.addMultiCellWidget(tmplabel,2,2,2,3) self.connect(self.guestradio,SIGNAL("stateChanged(int)"),self.slotGuestRadioClicked) self.userradio = QRadioButton(self) grid.addWidget(self.userradio,3,1) tmplabel = QLabel(self) tmplabel.setText(i18n("Username:")) grid.addWidget(tmplabel,3,2) self.connect(self.userradio,SIGNAL("stateChanged(int)"),self.slotUserRadioClicked) self.usernameedit = KLineEdit(self) grid.addWidget(self.usernameedit,3,3) tmplabel = QLabel(self) tmplabel.setText(i18n("Password:")) grid.addWidget(tmplabel,4,2) self.passwordedit = KLineEdit(self) grid.addWidget(self.passwordedit,4,3) self.autocheckbox = QCheckBox(i18n("Enable at start up"),self) grid.addMultiCellWidget(self.autocheckbox,5,5,1,3) # Security & Safety line. hbox = QHBox(self) hbox.setSpacing(KDialog.spacingHint()) tmplabel = QLabel(hbox) tmplabel.setPixmap(UserIcon("hi16-lock")) hbox.setStretchFactor(tmplabel,0) tmplabel = QLabel(hbox) tmplabel.setText(i18n("Security & Safety")) hbox.setStretchFactor(tmplabel,0) sep = KSeparator(KSeparator.Horizontal,hbox) hbox.setStretchFactor(sep,1) grid.addMultiCellWidget(hbox,6,6,0,3) self.writeablecheckbox = QCheckBox(i18n("Writeable"),self) grid.addMultiCellWidget(self.writeablecheckbox,7,7,1,3) label = QLabel(i18n("Files belong to user:"),self) grid.addWidget(label,8,0) self.uidcombobox = UserComboBox(self) grid.addMultiCellWidget(self.uidcombobox,8,8,1,3) label = QLabel(i18n("Files belong to group:"),self) grid.addWidget(label,9,0) self.gidcombobox = GroupComboBox(self) grid.addMultiCellWidget(self.gidcombobox,9,9,1,3) label = QLabel(i18n("Mount Permission:"),self) grid.addWidget(label,10,0) self.usermountcombobox = KComboBox(self) self.usermountcombobox.insertItem(i18n("Root user only may enable/disable")) self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable")) self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime")) self.usermountcombobox.insertItem(i18n("Device owner may enable/disable")) grid.addMultiCellWidget(self.usermountcombobox,10,10,1,3) button = KPushButton(i18n("Advanced..."),self) button.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed) self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked) grid.addMultiCellWidget(button,13,13,1,3,Qt.AlignRight) self.selectsmbdialog = None ######################################################################## def slotBrowseDeviceLineClicked(self): if self.updatinggui: return self.updatinggui = True if self.selectsmbdialog is None: self.selectsmbdialog = SMBShareSelectDialog(None) # This just converts a \\zootv\data\ share name to smb:/zootv/data parts = [x.replace("/",'\\') for x in unicode(self.devicelineedit.text()).split('\\') if x!=""] oldurl = u"smb:/"+("/".join(parts) ) urlobj = KURL(oldurl) if self.userradio.isChecked(): urlobj.setUser(self.usernameedit.text()) urlobj.setPass(self.passwordedit.text()) newurlobj = self.selectsmbdialog.choose(urlobj) # This just converts smb:/zootv/data to \\zootv\data. plainurl = KURL(newurlobj) plainurl.setUser(QString.null) plainurl.setPass(QString.null) parts = [x.replace('\\',"/") for x in unicode(plainurl.url())[4:].split("/") if x !=""] #convert the first part to an IP address nmboutput = subprocess.Popen(["nmblookup",parts[0]], stdout=subprocess.PIPE).stdout nmboutput.readline() ipaddress = nmboutput.readline().split(" ")[0] parts[0] = ipaddress self.devicelineedit.setText(r'\\'+('\\'.join(parts))) if not newurlobj.hasUser(): self.guestradio.setChecked(True) self.userradio.setChecked(False) self.passwordedit.setEnabled(False) self.usernameedit.setEnabled(False) self.usernameedit.setText("") self.passwordedit.setText("") else: self.guestradio.setChecked(False) self.userradio.setChecked(True) self.passwordedit.setEnabled(True) self.usernameedit.setEnabled(True) self.usernameedit.setText(newurlobj.user()) self.passwordedit.setText(newurlobj.pass_()) self.updatinggui = False ######################################################################## def displayMountEntry(self,entry): self.devicelineedit.setText(entry.getDevice()) self.mountpointlineedit.setText(entry.getMountPoint()) self.options = entry.getExtraOptions() self.fsfreq = entry.getFSFreq() self.fspassno = entry.getFSPassno() self.writeablecheckbox.setChecked(entry.getWritable()) self.autocheckbox.setChecked(entry.getMountAtBoot()) self.usermountcombobox.setCurrentItem(entry.getAllowUserMount()) self.uidcombobox.setUID(entry.getUID()) self.gidcombobox.setGID(entry.getGID()) if entry.getUsername() is None: self.guestradio.setChecked(True) self.userradio.setChecked(False) self.passwordedit.setEnabled(False) self.usernameedit.setEnabled(False) self.usernameedit.setText("") self.passwordedit.setText("") else: self.guestradio.setChecked(False) self.userradio.setChecked(True) self.passwordedit.setEnabled(True) self.usernameedit.setEnabled(True) self.usernameedit.setText(entry.getUsername()) self.passwordedit.setText(entry.getPassword()) ######################################################################## def undisplayMountEntry(self,entry): entry.setDevice( unicode(self.devicelineedit.text()) ) entry.setMountPoint( unicode(self.mountpointlineedit.text()) ) entry.setExtraOptions(self.options) entry.setFSFreq(self.fsfreq) entry.setFSPassno(self.fspassno) entry.setMountAtBoot(self.autocheckbox.isChecked()) entry.setWritable(self.writeablecheckbox.isChecked()) entry.setAllowUserMount(self.usermountcombobox.currentItem()) entry.setUID(self.uidcombobox.UID()) entry.setGID(self.gidcombobox.GID()) if self.guestradio.isChecked(): entry.setUsername(None) entry.setPassword(None) else: entry.setUsername( unicode(self.usernameedit.text()) ) entry.setPassword( unicode(self.passwordedit.text()) ) ######################################################################## def slotAdvancedClicked(self): (self.options, self.fsfreq, self.fspassno)\ = self.advanceddialog.do(self.options, self.fsfreq, self.fspassno) ######################################################################## def slotGuestRadioClicked(self,state): if self.updatinggui: return self.updatinggui = True if state==QButton.Off: self.guestradio.setChecked(True) self.userradio.setChecked(False) self.passwordedit.setEnabled(False) self.usernameedit.setEnabled(False) self.updatinggui = False ######################################################################## def slotUserRadioClicked(self,state): if self.updatinggui: return self.updatinggui = True if state==QButton.Off: self.userradio.setChecked(True) self.guestradio.setChecked(False) self.passwordedit.setEnabled(True) self.usernameedit.setEnabled(True) self.updatinggui = False ############################################################################ class ROListBoxItem(QListBoxPixmap): """A read-only ListBox item that also uses the 'alternate' background colour as background. """ def __init__(self,listbox,pix,text): QListBoxPixmap.__init__(self,listbox,pix,text) self.setSelectable(False) def paint(self,p): boldfont = QFont(p.font()) boldfont.setWeight(QFont.Bold) p.setFont(boldfont) p.setBackgroundColor(KGlobalSettings.alternateBackgroundColor()) p.eraseRect(0,0,self.listBox().width(),self.height(self.listBox())) QListBoxPixmap.paint(self,p) ############################################################################ class MountEntryDialog(KDialogBase): MountTypeEditorsDisk = { 'ext2' : MountEntryDialogOptionsCommonUnix, 'ext3' : MountEntryDialogOptionsCommonUnix, 'reiserfs' : MountEntryDialogOptionsCommonUnix, 'reiser4' : MountEntryDialogOptionsCommonUnix, 'xfs' : MountEntryDialogOptionsCommonUnix, 'jfs' : MountEntryDialogOptionsCommonUnix, 'vfat' : MountEntryDialogOptionsVFAT, 'ntfs' : MountEntryDialogOptionsVFAT, 'hfsplus' : MountEntryDialogOptionsVFAT, 'udf' : MountEntryDialogOptions, 'iso9660' : MountEntryDialogOptions, } MountTypeEditorsNetwork = { 'nfs' : MountEntryDialogOptionsNfs, 'cifs' : MountEntryDialogOptionsSMB, } MountTypeEditorsSystem = { 'proc' : MountEntryDialogOptionsSys, 'sysfs' : MountEntryDialogOptionsSys, 'rootfs' : MountEntryDialogOptions, 'bdev' : MountEntryDialogOptions, 'sockfs' : MountEntryDialogOptions, 'tmpfs' : MountEntryDialogOptions, 'shm' : MountEntryDialogOptions, 'pipefs' : MountEntryDialogOptions, 'ramfs' : MountEntryDialogOptionsSys, 'devfs' : MountEntryDialogOptions, 'devpts' : MountEntryDialogOptionsSys, 'auto' : MountEntryDialogOptionsCommonUnix, 'usbdevfs' : MountEntryDialogOptions, 'procbususb' : MountEntryDialogOptions, 'usbfs' : MountEntryDialogOptions, 'supermount' : MountEntryDialogOptions, 'swap' : MountEntryDialogOptionsSwap } ######################################################################## def __init__(self,parent): KDialogBase.__init__(self,parent,None,True,"Configuration",KDialogBase.Ok|KDialogBase.Cancel, KDialogBase.Cancel) self.updatingGUI = True # Maps MountEntry classes to MountEntryDialogOptions objects self.mountTypeToOptionWidget = {} # Maps indexes in the combobox to mounttypes self.comboIndexToMountType = [] self.currentOptionWidget = None self.topvbox = QVBox(self) self.setMainWidget(self.topvbox) self.topvbox.setSpacing(self.spacingHint()) hb = QHBox(self.topvbox) hb.setSpacing(self.spacingHint()) self.topvbox.setStretchFactor(hb,0) label = QLabel(i18n("Type:"),hb) hb.setStretchFactor(label,0) self.mounttypecombo = KComboBox(hb) # Disk types ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-hdd"),i18n("Disk Filesystems")) self.comboIndexToMountType.append(None) items = self.MountTypeEditorsDisk.keys() items.sort() for mounttype in items: self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype)) self.comboIndexToMountType.append(mounttype) # Network types ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-network"),i18n("Network Filesystems")) self.comboIndexToMountType.append(None) items = self.MountTypeEditorsNetwork.keys() items.sort() for mounttype in items: self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype)) self.comboIndexToMountType.append(mounttype) # System types ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-blockdevice"),i18n("Operating System")) self.comboIndexToMountType.append(None) items = self.MountTypeEditorsSystem.keys() items.sort() for mounttype in items: self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype)) self.comboIndexToMountType.append(mounttype) self.MountTypeEditors = self.MountTypeEditorsDisk.copy() self.MountTypeEditors.update(self.MountTypeEditorsNetwork) self.MountTypeEditors.update(self.MountTypeEditorsSystem) #hb.setStretchFactor(self.runlevelcombo,0) self.connect(self.mounttypecombo, SIGNAL("activated(int)"), self.slotMountTypeChanged) widget = QWidget(hb) hb.setStretchFactor(widget,1) # Create the stack of option edit widgets. gb = QVGroupBox(self.topvbox) self.topvbox.setStretchFactor(gb,1) self.optionsstack = QWidgetStack(gb) for mounttype in self.MountTypeEditors: editpage = self.MountTypeEditors[mounttype](self.optionsstack) self.mountTypeToOptionWidget[mounttype] = editpage self.optionsstack.addWidget(editpage) self.fsunavailablelabel = QHBox(gb) self.fsunavailablelabel.setSpacing(KDialog.spacingHint()) tmplabel = QLabel(self.fsunavailablelabel) self.fsunavailablelabel.setStretchFactor(tmplabel,0) tmplabel.setPixmap(SmallIcon('info')) label = QLabel(i18n("This filesystem type is currently unavailable on the running kernel."), self.fsunavailablelabel) self.fsunavailablelabel.setStretchFactor(label,1) self.fsunavailablelabel.hide() self.updatingGUI = False ####################################################################### def doEditMount(self,mounttable,mountentry): self.newEntry = False self.mounttable = mounttable self.originalMountEntry = mountentry self.currentMountEntry = mountentry.copy() self.updatingGUI = True self.selectEntry(self.currentMountEntry.getMountType()) self.updatingGUI = False if self.exec_loop()==QDialog.Accepted: # All of the update stuff is in slotOk() return True return False ####################################################################### def doNewMount(self,mounttable,defaultdevice): self.newEntry = True self.mounttable = mounttable self.currentMountEntry = MountEntry() if defaultdevice is not None: self.currentMountEntry.setDevice(defaultdevice) self.updatingGUI = True self.currentOptionWidget = None self.selectEntry(self.currentMountEntry.mounttype) self.updatingGUI = False if self.exec_loop()==QDialog.Accepted: self.mounttable.allentries.append(self.currentMountEntry) self.mounttable.updateFstabOnDisk() return self.currentMountEntry return None ####################################################################### def selectEntry(self,mounttype): #if self.currentOptionWidget!=None: # # Update the mount entry from the # self.currentOptionWidget.undisplayMountEntry(self.currentMountEntry) self.currentMountEntry.setMountType(mounttype) # Update GUI self.mounttypecombo.setCurrentItem(self.comboIndexToMountType.index(mounttype)) self.currentOptionWidget = self.mountTypeToOptionWidget[mounttype] self.currentOptionWidget.displayMountEntry(self.currentMountEntry) self.optionsstack.raiseWidget(self.currentOptionWidget) if microhal.isSupportedFileSystem(mounttype): self.fsunavailablelabel.hide() else: self.fsunavailablelabel.show() ####################################################################### def slotMountTypeChanged(self,index): if self.updatingGUI==False: self.updatingGUI = True self.selectEntry(self.comboIndexToMountType[index]) self.updatingGUI = False ####################################################################### def slotOk(self): global allowlabel, allowuuid self.currentOptionWidget.undisplayMountEntry(self.currentMountEntry) if allowuuid: if self.currentOptionWidget.uuidcheckbox.isChecked(): self.currentMountEntry.setUseAsDevice("uuid") if allowlabel: if self.currentOptionWidget.labelcheckbox.isChecked(): self.currentMountEntry.setUseAsDevice("label") conflictentry = None if self.newEntry: for entry in self.mounttable: if entry.getMountPoint()==self.currentMountEntry.getMountPoint(): # Conflict found. conflictentry = entry else: # Check if the mountpoint is already in use elsewhere in the mounttable. if self.originalMountEntry.getMountPoint()!=self.currentMountEntry.getMountPoint(): for entry in self.mounttable: if (entry.getMountPoint()==self.currentMountEntry.getMountPoint() and entry is not self.originalMountEntry): # Conflict found. conflictentry = entry if conflictentry is not None: if KMessageBox.warningContinueCancel(self, \ i18n("The mountpoint '%1' is already in use by another entry?\nContinue?").arg( self.currentMountEntry.getMountPoint()), \ i18n("Mountpoint already in use"))!=KMessageBox.Continue: return if self.currentMountEntry.getMountType() in MountEntryDialog.MountTypeEditorsDisk.keys(): # If device is not in /dev and it's no bind mount, ask if that's meant this way ... options = self.currentMountEntry.getFstabOptions() if (not self.currentMountEntry.getDevice().startswith("/dev/") and not ("loop" in options or "bind" in options)): ask = KMessageBox.warningYesNoCancel(self, i18n("'%1' does not seem to be a device and the option 'bind' has not been specified in the \ \"Advanced\" page?\n Should I add the 'loop' option?").arg(self.currentMountEntry.device), i18n("Options may be missing")) if ask==KMessageBox.Cancel: return elif ask==KMessageBox.Yes: # Add loop option extraoptions = self.currentMountEntry.getExtraOptions().split(',') extraoptions.append('loop') self.currentMountEntry.setExtraOptions(','.join(extraoptions)) if (not os.path.isdir(self.currentMountEntry.getMountPoint()) and not os.path.isfile(self.currentMountEntry.getMountPoint()) and not self.currentMountEntry.mounttype == 'swap'): ask = KMessageBox.warningYesNoCancel(self, i18n("""The mountpoint '%1' does not exist. You will not be able to enable it until it is created.\ \nShould I create the mountpoint?""").arg(self.currentMountEntry.getMountPoint()), i18n("Mountpoint does not exist")) if ask==KMessageBox.Cancel: return elif ask==KMessageBox.Yes: os.mkdir(self.currentMountEntry.getMountPoint()) elif os.path.isfile(self.currentMountEntry.getMountPoint()): if KMessageBox.warningContinueCancel(self, i18n("""The mountpoint '%1' is a file, but it has to be a directory. You will probably not \ be able to enable it.\nContinue?""").arg(self.currentMountEntry.getMountPoint()), i18n("Invalid mountpoint"))!=KMessageBox.Continue: return if self.newEntry==False: # How to Change a Mount Entry. # 1. Disable the exisiting entry (if needed) # 2. Update existing entry from the mount table. # 3. Enable the updated entry (if needed) # 4. Write new fstab file. # 5. Enable the new entry (if needed) # 1. Disable the exisiting entry (if needed) enabled = self.originalMountEntry.isEnabled() if enabled: self.disablingold = True self.originalMountEntry.disable(self) self.originalMountEntry.inPlaceCopyFrom(self.currentMountEntry) self.mounttable.updateFstabOnDisk() if enabled and self.originalMountEntry.isFileSystemAvailable(): self.originalMountEntry.enable(self) self.accept() ############################################################################ class MountEntryAdvancedCommonUnixDialog(KDialogBase): ######################################################################## def __init__(self,parent,name=None): KDialogBase.__init__(self,parent,name,1,"",KDialogBase.Ok|KDialogBase.Cancel) grid = self.makeGridMainWidget(2,Qt.Horizontal) grid.setSpacing(self.spacingHint()) QWidget(grid) self.accesstimecheckbox = QCheckBox(i18n("Update file access timestamps"),grid) QWidget(grid) self.allowexecutablecheckbox = QCheckBox(i18n("Allow Executables"),grid) QWidget(grid) self.allowsuidcheckbox = QCheckBox(i18n("Allow the SUID and SGID attributes"),grid) QWidget(grid) self.usedevpointscheckbox = QCheckBox(i18n("Allow device points"),grid) label = QLabel(i18n("Options:"),grid) self.optionslineedit = KLineEdit(grid) label = QLabel(i18n("fs_freq:"),grid) self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,grid) label = QLabel(i18n("fs_passno:"),grid) self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,grid) ######################################################################## def do(self,atime,allowexecutable,allowsuid,usedevpoints,options,fsfreq,fspassno): self.accesstimecheckbox.setChecked(atime) self.allowexecutablecheckbox.setChecked(allowexecutable) self.allowsuidcheckbox.setChecked(allowsuid) self.usedevpointscheckbox.setChecked(usedevpoints) self.optionslineedit.setText(options) self.fsfreqspinbox.setValue(fsfreq) self.fspassnospinbox.setValue(fspassno) self.exec_loop() return ( self.accesstimecheckbox.isChecked(), self.allowexecutablecheckbox.isChecked(), self.allowsuidcheckbox.isChecked(), self.usedevpointscheckbox.isChecked(), unicode(self.optionslineedit.text()), self.fsfreqspinbox.value(), self.fspassnospinbox.value()) ############################################################################ class MountEntryAdvancedPlainDialog(KDialogBase): ######################################################################## def __init__(self,parent,name=None): KDialogBase.__init__(self,parent,name,1,"",KDialogBase.Ok|KDialogBase.Cancel) grid = self.makeGridMainWidget(2,Qt.Horizontal) grid.setSpacing(self.spacingHint()) label = QLabel(i18n("Options:"),grid) self.optionslineedit = KLineEdit(grid) label = QLabel(i18n("fs_freq:"),grid) self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,grid) label = QLabel(i18n("fs_passno:"),grid) self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,grid) ######################################################################## def do(self,options,fsfreq,fspassno): self.optionslineedit.setText(options) self.fsfreqspinbox.setValue(fsfreq) self.fspassnospinbox.setValue(fspassno) self.exec_loop() return (unicode(self.optionslineedit.text()), self.fsfreqspinbox.value(), self.fspassnospinbox.value()) ############################################################################ class MountListViewItem(KListViewItem): ######################################################################## def __init__(self,parentitem,mountentry,haldevice=None): self.haldevice = haldevice self.mountentry = mountentry if self.mountentry is None: # There is no mount entry right now. This acts as a place holder # for now. KListViewItem.__init__(self,parentitem,self.haldevice.getName(),"","",self.haldevice.getDev(),"") else: if mountentry.isEnabled(): enabled = i18n("Enabled") else: enabled = i18n("Disabled") if self.haldevice is not None: name = self.haldevice.getName() else: name = self.mountentry.getName() KListViewItem.__init__(self, parentitem, \ name, self.mountentry.getMountPoint(), \ self.mountentry.mounttype, \ self.mountentry.getDevice(), \ enabled) if self.mountentry.isEnabled(): self.setPixmap(4,UserIcon("greenled")) else: self.setPixmap(4,UserIcon("greyled")) self.__updateIcon() ######################################################################## def hasHAL(self): return self.haldevice is not None ######################################################################## def getHAL(self): return self.haldevice ######################################################################## def updateDisplay(self): if self.mountentry is not None: if self.mountentry.isEnabled(): enabled = i18n("Enabled") self.setPixmap(4,UserIcon("greenled")) else: enabled = i18n("Disabled") self.setPixmap(4,UserIcon("greyled")) if self.haldevice is not None: self.setText(0,self.haldevice.getName()) else: self.setText(0,self.mountentry.getMountPoint()) self.setText(1,self.mountentry.getMountPoint()) self.setText(2,self.mountentry.mounttype) if self.mountentry.getDevice() is not None: self.setText(3,self.mountentry.getDevice()) else: uuid_device = microhal.getDeviceByUUID(self.mountentry.getUUID()) label_device = microhal.getDeviceByUUID(self.mountentry.getUUID()) if label_device is not None: self.setText(3,label_device.getDev()+" (Label)") elif real_device is not None: self.setText(3,real_device.getDev()+" (UUID)") else: self.setText(3,"UUID="+self.mountentry.getUUID()) self.setText(4,enabled) else: self.setText(0,self.haldevice.getName()) self.setText(1,"") self.setText(2,"") self.setText(3,self.haldevice.getDev()) self.setText(4,"") self.setPixmap(4,QPixmap()) self.__updateIcon() ######################################################################## def setMountEntry(self,entry): self.mountentry = entry self.updateDisplay() ######################################################################## def getMountEntry(self): return self.mountentry ######################################################################## def getDevice(self): return self.haldevice.getDev() ######################################################################## def __updateIcon(self): if self.haldevice is not None: self.setPixmap(0,UserIcon(self.haldevice.iconname)) else: self.setPixmap(0,UserIcon(self.mountentry.getIconName())) ############################################################################ class MountGroupListViewItem(KListViewItem): ######################################################################## def __init__(self,parentitem,haldevice): self.haldevice = haldevice KListViewItem.__init__(self,parentitem,self.haldevice.getName(),"","","","") if self.haldevice is not None: iconname = self.haldevice.iconname else: iconname = self.mountentry.getIconName() self.setPixmap(0,UserIcon(iconname)) ######################################################################## def getMountEntry(self): return None ######################################################################## def updateDisplay(self): pass def hasHAL(self): return False ############################################################################ # Try translating this code to C++. I dare ya! if standalone: programbase = KDialogBase else: programbase = KCModule class MountConfigApp(programbase): ######################################################################## def __init__(self,parent=None,name=None): global standalone,isroot KGlobal.locale().insertCatalogue("guidance") if standalone: KDialogBase.__init__(self,KJanusWidget.Plain,i18n("Disk & Filesystems"), KDialogBase.User1|KDialogBase.Close, KDialogBase.Close) self.setButtonText(KDialogBase.User1,i18n("About")) topwidget = self.plainPage() else: KCModule.__init__(self,parent,name) self.setButtons(0) self.aboutdata = MakeAboutData() topwidget = self # Create a configuration object. self.config = KConfig("mountconfigrc") KGlobal.iconLoader().addAppDir("guidance") self.updatingGUI = False self.mounttable = MountTable('/etc/fstab','/etc/mtab') self.selectedentry = None self.aboutus = KAboutApplication(self) self.sizeviewdialogs = {} toplayout = QVBoxLayout(topwidget, 0, KDialog.spacingHint()) #topwidget.setEnabled(isroot) hb = QHBox(topwidget) hb.setSpacing(KDialog.spacingHint()) #if standalone: # hb.setMargin(KDialog.marginHint()) toplayout.addWidget(hb) label = QLabel(hb) label.setPixmap(UserIcon("kcmpartitions")) hb.setStretchFactor(label,0) label = QLabel(i18n("Available Disks and Filesystems:"),hb) hb.setStretchFactor(label,1) self.mountlist = KListView(topwidget,"Mount list") toplayout.addWidget(self.mountlist) self.mountlist.addColumn(i18n("Name")) self.mountlist.addColumn(i18n("Mount Point")) self.mountlist.addColumn(i18n("Type")) self.mountlist.addColumn(i18n("Device")) self.mountlist.addColumn(i18n("Enabled")) self.mountlist.setAllColumnsShowFocus(True) self.mountlist.setSelectionMode(QListView.Single) self.mountlist.setRootIsDecorated(True) self.mountlist.setSorting(-1) self.connect(self.mountlist, SIGNAL("selectionChanged(QListViewItem *)"), self.slotListClicked) # Doubleclick in item opens modify dialogue. self.connect(self.mountlist, SIGNAL("doubleClicked(QListViewItem *)"), self.slotModifyClicked) # Rightclick: Open ContextMenu self.connect(self.mountlist, SIGNAL("contextMenu(KListView*,QListViewItem*,const QPoint&)"), self.slotContextMenu) hbox = QHBox(topwidget) toplayout.addWidget(hbox) hbox.setSpacing(KDialog.spacingHint()) toplayout.setStretchFactor(hbox,0) self.newbutton = KPushButton(i18n("New..."),hbox) hbox.setStretchFactor(self.newbutton,1) self.connect(self.newbutton,SIGNAL("clicked()"),self.slotNewClicked) self.newbutton.setEnabled(isroot) self.modifybutton = KPushButton(i18n("Modify..."),hbox) hbox.setStretchFactor(self.modifybutton,1) self.connect(self.modifybutton,SIGNAL("clicked()"),self.slotModifyClicked) self.deletebutton = KPushButton(i18n("Delete..."),hbox) hbox.setStretchFactor(self.deletebutton,1) self.connect(self.deletebutton,SIGNAL("clicked()"),self.slotDeleteClicked) self.enablebutton = KPushButton(i18n("Enable"),hbox) hbox.setStretchFactor(self.enablebutton,1) self.connect(self.enablebutton,SIGNAL("clicked()"),self.slotEnableClicked) self.disablebutton = KPushButton(i18n("Disable"),hbox) hbox.setStretchFactor(self.disablebutton,1) self.connect(self.disablebutton,SIGNAL("clicked()"),self.slotDisableClicked) self.detailsbutton = KPushButton(i18n("Details..."),hbox) hbox.setStretchFactor(self.detailsbutton,1) self.connect(self.detailsbutton,SIGNAL("clicked()"),self.slotDetailsClicked) self.devstolistitems = None self.uuidstolistitems = None self.mountentriestolistitems = None self.__updateMountList() self.__selectEntry(self.mounttable[0]) self.configuredialog = MountEntryDialog(None) ######################################################################## def exec_loop(self): global programbase self.__loadOptions() programbase.exec_loop(self) self.__saveOptions() ######################################################################## def slotContextMenu(self,lv,lv_item,p): hal_device = lv_item.haldevice if hal_device is not None and not isinstance(hal_device,MicroHAL.FakeSystemDevice): self.cmenu = KPopupMenu(self,"MyActions") if isinstance(hal_device,MicroHAL.RemovableDisk) or isinstance(lv_item,MountListViewItem): self.cmenu.insertItem(i18n("Modify..."), self.slotModifyClicked, 0, 0) self.cmenu.insertItem(i18n("Delete..."), self.slotDeleteClicked, 0, 1) if not isroot: self.cmenu.setItemEnabled(0,False) self.cmenu.setItemEnabled(1,False) elif isinstance(hal_device,MicroHAL.Disk) or isinstance(hal_device,MicroHAL.USBDisk): self.cmenu.insertItem(i18n("Show details..."), self.slotDetailsClicked, 0, 0) self.cmenu.insertItem(i18n("New..."), self.slotNewClicked, 0, 1) if not isroot: self.cmenu.setItemEnabled(1,False) self.cmenu.exec_loop(p) ######################################################################## def slotUser1(self): self.aboutus.show() ######################################################################## def slotEnableClicked(self): if self.selectedentry!=None: self.selectedentry.enable(self) self.mounttable.updateStatus(self.selectedentry) self.__updateEntry(self.selectedentry) self.enablebutton.setEnabled(not self.selectedentry.isEnabled()) self.disablebutton.setEnabled(self.selectedentry.isEnabled()) ######################################################################## def slotDisableClicked(self): if self.selectedentry!=None: self.__disableEntry() ######################################################################## def slotModifyClicked(self): global isroot if not isroot: return if self.selectedentry!=None: self.configuredialog.doEditMount(self.mounttable,self.selectedentry) lvi = self.mountentriestolistitems[self.selectedentry] if lvi.hasHAL(): if lvi.getHAL().getDev()!=self.selectedentry.getDevice(): # The (device-)item in the listview no longer matches this mount entry. del self.mountentriestolistitems[self.selectedentry] lvi.setMountEntry(None) lvi.updateDisplay() # Reinsert this mount entry into the list view. self.__insertMountEntryIntoListView(self.selectedentry) elif self.selectedentry.getDevice() is not None \ and self.selectedentry.getDevice() in self.devstolistitems: # The mount entry can now merged with any existing (HAL-)item. # Remove the existing lose item. self.mountlist.takeItem(lvi) del self.mountentriestolistitems[self.selectedentry] del self.devstolistitems[self.selectedentry.getDevice()] del lvi # Reinsert this mount entry into the list view. self.__insertMountEntryIntoListView(self.selectedentry) elif self.selectedentry.getUUID() is not None \ and self.selectedentry.getUUID() in self.uuidstolistitems: # The mount entry can now merged with any existing (HAL-)item. # Remove the existing lose item. self.mountlist.takeItem(lvi) del self.mountentriestolistitems[self.selectedentry] del self.uuidstolistitems[self.selectedentry.getUUID()] del lvi # Reinsert this mount entry into the list view. self.__insertMountEntryIntoListView(self.selectedentry) self.__updateEntry(self.selectedentry) self.__selectEntry(self.selectedentry) else: self.slotNewClicked() ######################################################################## def slotNewClicked(self): defaultdevice = None if self.selectedentry is None: lvi = self.mountlist.selectedItem() if lvi is not None and lvi.hasHAL() and (lvi.getMountEntry() is None): defaultdevice = lvi.getDevice() newentry = self.configuredialog.doNewMount(self.mounttable,defaultdevice) if newentry!=None: self.updatingGUI = True self.__insertMountEntryIntoListView(newentry) self.__selectEntry(newentry) self.updatingGUI = False ######################################################################## def slotDeleteClicked(self): if self.selectedentry!=None: if self.selectedentry.isEnabled(): if not self.__disableEntry(): return # If we couldn't disable it, then we can't continue. message = i18n("Are you sure you want to delete mount '%1' of type %2 at '%3'?\n " + "(This will only remove the mount, no data will be deleted.)") \ .arg(self.selectedentry.getMountPoint()).arg(self.selectedentry.mounttype).arg( self.selectedentry.getDevice()) if KMessageBox.warningYesNo(self,message,i18n("Delete Mount?"))==KMessageBox.Yes: lvi = self.mountentriestolistitems[self.selectedentry] if not lvi.hasHAL(): self.mountlist.takeItem(lvi) del lvi del self.mountentriestolistitems[self.selectedentry] else: lvi.setMountEntry(None) self.mounttable.remove(self.selectedentry) self.mounttable.updateFstabOnDisk() self.__selectEntry(None) ######################################################################## def slotDetailsClicked(self): # Popup a dialog showing disklayout and a graphical represenation of 'df' hal_device = self.mountlist.selectedItem().haldevice if isinstance(hal_device,MicroHAL.Disk): blk = hal_device.getDev() devicepath, devicename = ('/'.join(blk.split('/')[0:-1])+'/', blk.split('/')[-1]) # We keep a dict with those widgets, that saves us some time reading out all the values. if devicename not in self.sizeviewdialogs.keys(): self.sizeviewdialogs[devicename] = sizeview.SizeView(self,devicename,devicepath) self.sizeviewdialogs[devicename].exec_loop() else: self.sizeviewdialogs[devicename].exec_loop() else: print "Sizeview doesn't support",blk.__class__," yet." ######################################################################## def slotListClicked(self,item): if self.updatingGUI==False: self.__selectEntry(item.getMountEntry()) ######################################################################## def __disableEntry(self): self.selectedentry.disable(self) self.mounttable.updateStatus(self.selectedentry) self.__updateEntry(self.selectedentry) self.enablebutton.setEnabled(not self.selectedentry.isEnabled() and self.selectedentry.isFileSystemAvailable()) self.disablebutton.setEnabled(self.selectedentry.isEnabled()) return not self.selectedentry.isEnabled() ######################################################################## def __updateEntry(self,selectedentry): # Update the display. lvi = self.mountentriestolistitems[selectedentry] lvi.updateDisplay() ######################################################################## def __loadOptions(self): self.config.setGroup("General") size = self.config.readSizeEntry("Geometry") if size.isEmpty()==False: self.resize(size) ####################################################################### def __saveOptions(self): global isroot if isroot: return self.config.setGroup("General") self.config.writeEntry("Geometry", self.size()) self.config.sync() ######################################################################## def __updateMountList(self): self.mountentriestolistitems = {} self.mountlist.clear() self.listgroups = {} self.devstolistitems = {} self.uuidstolistitems = {} lasttopitem = None # Find out which disks are installed and should be shown in the # listview. For real disks we put a 'group' in the listview and # under the group we list the partitions, whether they are # mounted or not. for blockdevice in microhal.getDevices(): # We are looking for block devices that represent hard disks or # things that have partitions and are not removable if (blockdevice.major in microhal.partitionblockdevs and not blockdevice.removable) \ or isinstance(blockdevice,MicroHAL.USBDisk): # We have a not removable block device. # We want to create a listitem for the device and subitems # for each partition. groupitem = MountGroupListViewItem(self.mountlist,blockdevice) groupitem.setOpen(True) lasttopitem = groupitem lvi = None for partition in blockdevice.getPartitions(): # Try to find a matching mount entry for this partition. lastlvi = lvi lvi = MountListViewItem(groupitem,None,partition) if partition.getUUID() is not None: self.uuidstolistitems[partition.getUUID()] = lvi if partition.getDev() is not None: self.devstolistitems[partition.getDev()] = lvi if lastlvi is not None: lvi.moveItem(lastlvi) elif blockdevice.getMajor() in microhal.cdromsdevs or blockdevice.isRemovable(): # Removable block device, assume CDROM (even if it's a partitionblockdevice) lvi = MountListViewItem(self.mountlist,None,blockdevice) if blockdevice.getUUID() is not None: self.uuidstolistitems[blockdevice.getUUID()] = lvi if blockdevice.getDev() is not None: self.devstolistitems[blockdevice.getDev()] = lvi lasttopitem = lvi systemdevice = MicroHAL.FakeSystemDevice() systemdevice.iconname = systemdevice.getIconName() groupitem = MountGroupListViewItem(self.mountlist,systemdevice) if lasttopitem is not None: groupitem.moveItem(lasttopitem) lasttopitem = groupitem self.listgroups["system"] = groupitem self.mountentriestolistitems = {} for entry in self.mounttable: self.__insertMountEntryIntoListView(entry) ######################################################################## def __insertMountEntryIntoListView(self,mountentry): if mountentry.getDevice() in self.devstolistitems: lvi = self.devstolistitems[mountentry.getDevice()] lvi.setMountEntry(mountentry) elif mountentry.getUUID() in self.uuidstolistitems: lvi = self.uuidstolistitems[mountentry.getUUID()] lvi.setMountEntry(mountentry) else: cat = mountentry.getCategory() # Place it under a special node? if cat not in self.listgroups: lvi = MountListViewItem(self.mountlist,mountentry) item = self.mountlist.firstChild() else: lvi = MountListViewItem(self.listgroups[cat],mountentry) item = self.listgroups[cat].firstChild() # Move the item to the end of this (sub-list). while item.nextSibling() is not None: item = item.nextSibling() lvi.moveItem(item) self.mountentriestolistitems[mountentry] = lvi ######################################################################## def __selectEntry(self,mountentry): if mountentry is not None and isroot: lvi = self.mountentriestolistitems[mountentry] self.mountlist.setSelected(lvi,True) self.enablebutton.setEnabled(not mountentry.isEnabled() and mountentry.isFileSystemAvailable()) self.selectedentry = mountentry # disable unsupported stuff, such as SystemEntries that canot be disabled and modified if not mountentry.maydisable: disable = False else: disable = mountentry.isEnabled() if mountentry.notInFstab: delete = False modify = False else: delete = True modify = True self.disablebutton.setEnabled(disable) self.deletebutton.setEnabled(delete) self.modifybutton.setEnabled(modify) else: self.enablebutton.setEnabled(False) self.disablebutton.setEnabled(False) self.deletebutton.setEnabled(False) self.modifybutton.setEnabled(False) self.detailsbutton.setEnabled(False) self.selectedentry = None selected_item = self.mountlist.selectedItem() if selected_item is not None: self.detailsbutton.setEnabled(isinstance(selected_item.haldevice,MicroHAL.Disk) \ and not isinstance(selected_item.haldevice,MicroHAL.RemovableDisk)) else: self.detailsbutton.setEnabled(False) ####################################################################### # KControl virtual void methods def load(self): pass def save(self): pass def defaults(self): pass def sysdefaults(self): pass def aboutData(self): # Return the KAboutData object which we created during initialisation. return self.aboutdata def buttons(self): # Only supply a Help button. Other choices are Default and Apply. return KCModule.Help ############################################################################ # Factory function for KControl def create_mountconfig(parent,name): global kapp, microhal microhal = MicroHAL.MicroHAL() kapp = KApplication.kApplication() return MountConfigApp(parent, name) ############################################################################ def MakeAboutData(): aboutdata = KAboutData("mountconfig",programname,version,"Disk & Filesystem Configuration Tool", KAboutData.License_GPL, "Copyright (C) 2003-2007 Simon Edwards") aboutdata.addAuthor("Simon Edwards","Developer","simon@simonzone.com", "http://www.simonzone.com/software/guidance") aboutdata.addAuthor("Sebastian Kügler","Developer","sebas@kde.org","http://vizZzion.org"); return aboutdata if standalone: aboutdata = MakeAboutData() KCmdLineArgs.init(sys.argv,aboutdata) microhal = MicroHAL.MicroHAL() kapp = KApplication() sysvapp = MountConfigApp() sysvapp.exec_loop()