#!/usr/bin/python2 ############################################################################## # Mount or unmount a removeable device # Author: Chris Rouch # Date: 13/10/2003 # Changelog: # # Copyright (c) Chris Rouch 2003 # # 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # or see http://www.gnu.org/licenses/gpl.txt ############################################################################## import gtk import os import getopt import sys import re import pango import commands ###################################################################### # constants MOD1_MASK = 1 << 3 SHIFT_MASK = 1 << 0 CONTROL_MASK = 1 << 2 TITLESIZE = 24000 LABELSIZE = 18000 ###################################################################### class ButtonBox: def gettip(self,drive): """get the tip for the state of this drive""" if self.state[drive]: tip=drive + ' mounted' else: tip=drive + ' not mounted' return tip def getstate(self,drive): """get the state of this drive""" mounted=commands.getoutput('mount') for x in mounted.split('\n'): if re.search(drive,x): return 1 return 0 def togglestate(self,drive): """toggle the state of this drive""" if self.state[drive]: res=commands.getoutput("umount " + drive) else: res=commands.getoutput("mount " + drive) if res: self.complain(res) def complain(self,res): """display a dialog with the output received""" dialog = gtk.Dialog("Output from mount command",self.window) label = gtk.Label(res) label.set_use_markup(gtk.TRUE) tstr='' + res + '' label.set_markup(tstr) dialog.vbox.pack_start(label, gtk.TRUE, gtk.TRUE, 0) label.show() button = gtk.Button(None,gtk.STOCK_OK); button.connect("button_press_event", self.popdown,dialog) dialog.action_area.pack_start(button, gtk.TRUE, gtk.TRUE, 0) button.show() dialog.show() def geticon(self,drive): """get the icon for the state of this drive""" if self.state[drive]: icon=self.micons[drive] else: icon=self.uicons[drive] if re.match("\$HOME",icon): icon=re.sub("\$HOME",os.environ["HOME"],icon) return icon def action(self, widget, event,drive): """toggle the drive state and update the icon""" if event.button == 1: # left button self.togglestate(drive) self.update(drive) def update(self,drive): """update the state and then the icon for this drive""" self.state[drive]=self.getstate(drive) tip=self.gettip(drive) button=self.buttons[drive] image=button.get_child(); ifile=self.geticon(drive); image.set_from_file(ifile) image.show() self.tooltips.set_tip(button, tip,"") def updateall(self): """update the state and then the icon for all drives""" drives=self.state.keys() for drive in drives: self.update(drive) return gtk.TRUE def popdown(self, widget, event,w): """popdown the dialog""" if event.button == 1: # left button w.destroy() def keypress(self, widget, event,*args): """check for keypresses, exit on ctrl-q""" key = event.keyval if event.state & CONTROL_MASK: if chr(key) == 'q': gtk.main_quit() def addtitle(self,table,title,width): """add a title to the top of the table""" label = gtk.Label(title); font_desc = pango.FontDescription('Serif') label.modify_font(font_desc) label.set_name('mytitle') label.set_use_markup(gtk.TRUE) tstr='' + title + '' label.set_markup(tstr) table.attach(label, 0, width, 0, 1,xpadding=0,ypadding=0) def addbutton(self,table,x,y,drive,icon,tip): """add a button to the table at x,y""" button = gtk.Button(); button.set_name('mybutton') self.buttons[drive]=button image = gtk.Image() image.set_from_file(icon) image.set_padding(0,0) button.add(image); button.connect("button_press_event", self.action,drive) button.set_relief(gtk.RELIEF_NONE) self.tooltips.set_tip(button, tip,"") table.attach(button, x, x+1, y, y+1,xpadding=0,ypadding=0) def __init__(self,blist,rows=1,cols=1,title=None,name=None): """Create a button box according to the supplied blist""" self.state={}; self.micons={}; self.uicons={}; self.buttons={}; # Create a new window self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_name("buttonbox") self.window.connect("key_press_event", self.keypress) # create tooltips object self.tooltips = gtk.Tooltips() # Create a table table = gtk.Table(rows, cols, gtk.FALSE) table.set_col_spacings(0) table.set_row_spacings(0) # Put the table in the main window self.window.add(table) # Set the window title x=0 y=0 if title: self.window.set_title(title) self.addtitle(table,title,cols) y=y+1 elif name: self.window.set_title(name) # add the buttons for tuple in blist: drive=tuple[0].strip() self.uicons[drive]=tuple[1].strip() self.micons[drive]=tuple[2].strip() self.state[drive]=self.getstate(drive) icon=self.geticon(drive) tip=self.gettip(drive) self.addbutton(table,x,y,drive,icon,tip); x=x+1 if x>= cols: x=0 y=y+1 self.window.show_all() msecs=secs *1000; timeout_handler_id = gtk.timeout_add(msecs, self.updateall) ###################################################################### def ReadArgs(file): """parse a file for a list of drives and icons format is drive,unmounted icon,mounted icon $HOME is understood, otherwise use full path """ options=[] try: f=open(file) except: print file, " not found" return for line in f.xreadlines(): line=line.rstrip() if line: options.append(re.split(",",line)) return options def main(): gtk.main() return 0 if __name__ == "__main__": file='' rows=-1 cols=-1 title='' name='' secs=60 options=[] opts,args = getopt.getopt(sys.argv[1:],'d:f:t:n:r:c:s:hv') for opt in opts: if opt[0] == '-f': file=opt[1] elif opt[0] == '-h': rows=1 elif opt[0] == '-v': cols=1 elif opt[0] == '-n': name=opt[1] elif opt[0] == '-t': title=opt[1] elif opt[0] == '-d': dir=opt[1] elif opt[0] == '-r': rows=opt[1] elif opt[0] == '-c': cols=opt[1] elif opt[0] == '-s': secs=opt[1] if file: options=ReadArgs(file) else: for arg in args: buttons.append(re.split(",",arg)) if options: count=len(options) if rows <= 0: if cols <=0: # default horizontal strip rows=1 cols=count else: rows=int(count)/int(cols) if int(count)%int(cols) > 0: rows+=1 else: cols=int(count)/int(rows) if int(count)%int(rows) > 0: cols+=1 cols=int(cols) rows=int(rows) ButtonBox(options,rows,cols,title,name) main() # only get here if we quit # no options