Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 4eb999dd9ad89c721a22c0ff2a533f65 > files > 84

mms-1.1.0-0.rc9.2mdv2009.1.i586.rpm

'''
Author : Yann Cezard <eesprit@free.fr>
Description : A Simple File Manager for MMSv2
License : GPLv2
'''
import os
import os.path
import mmsv2gui
import commands
import shutil
import sys

### EDIT HERE :
# syntax is : [ DISPLAYED_NAME, DEVICE, MOUNTPOINT ]
mountpoints = [ ["DVD Rom", '/dev/dvd', '/media/dvd'],
               ["Archos Jukebox", '/dev/sda1', '/mnt/jukebox'], 
             ]

# To only allow a subset of the file system to be viewable :
# Note that there is no real fakeroot, just masquerading, if
# you have symbolic links, it will be possible to escape from the jail !!!
# No fakeroot : fakeroot =['/',]
fakeroot = ['/media', '/tmp', '/data/data/Videos']

# The commands to mount/umount (adjust to suit your needs, if using sudo, update the sudoers table so that
# the user MMS is launched under has the right to use mount and unmount wthout password (NOPASSWD)
mount_command  = "/usr/bin/sudo /bin/mount"
umount_command = "/usr/bin/sudo /bin/umount"

# This is for masking dot_files or not :
HIDE_DOT_FILES = False
### END USER EDITION

NAME_IDX, DEV_IDX, MP_IDX = 0, 1, 2

class MountPoint(mmsv2gui.ListItem):
    def __init__(self, label):
        mmsv2gui.ListItem.__init__(self, label)
        self.setLabel(label)
        
    def setMountPoint(self, mountpoint):
        self.mountpoint = mountpoint

    def getMountPoint(self):
        return self.mountpoint

    def check(self):
        if self.getStatus():
            self.setThumbImage('active.png')
        else:
            self.setThumbImage('inactive.png')
            
    def getStatus(self):
        command = "/bin/grep %s /etc/mtab > /dev/null"%(self.mountpoint[DEV_IDX])
        return commands.getstatusoutput(command)[0] == 0

    def mount(self):
        command = "%s %s %s"%(mount_command, self.mountpoint[DEV_IDX], self.mountpoint[MP_IDX])
        return commands.getstatusoutput(command)

    def umount(self):
        command = "%s %s"%(umount_command, self.mountpoint[DEV_IDX])
        return commands.getstatusoutput(command)



class MountPoints(mmsv2gui.Window):
    def refresh(self):
        self.mountpoints.clear()
        for mountpoint in mountpoints :
            mp = MountPoint(mountpoint[NAME_IDX])
            mp.setMountPoint(mountpoint)
            mp.check()
            self.mountpoints.addItem(mp)
            
            
    def __init__(self):
        mmsv2gui.Window.__init__(self)

        self.bg = mmsv2gui.ImageControl(0, 0, self.getWidth(), self.getHeight(), "general/bg.png")
        
        left_offset = 50
        up_offset = 150
        right_offset = 50
        down_offset = 50
        middle_offset = 50
        
        self.label = mmsv2gui.LabelControl(left_offset, 25, self.getWidth() - left_offset - right_offset, 75)
        self.label.setLabel("Mount Point Manager")
        
        width = (self.getWidth() - left_offset - right_offset - middle_offset)/2
        height = self.getHeight() - up_offset - down_offset
        
        self.mountpoints = mmsv2gui.ListControl(left_offset, up_offset, width, height,focus="list-focus.png", nofocus="list-nofocus.png", alignment="center" )
        
        self.textbox = mmsv2gui.TextBoxControl(left_offset + width + middle_offset, up_offset, width, height)
        self.textbox.setText("Messages")
        
        
        self.addControl(self.bg)
        self.addControl(self.label)
        self.addControl(self.mountpoints)
        self.addControl(self.textbox)
        
        self.refresh()
        self.setFocus(self.mountpoints)


    def onAction(self, action):
        #Importent to catch some action, otherwise user can't close window

        #self.label.setLabel("")
        #self.textbox.setVisible(False)
        if action == "back":
            self.close()
        if action == "action":
            if self.getFocus() == self.mountpoints:
                mountpoint = self.mountpoints.getSelectedItem()
                if mountpoint.getStatus():
                    self.textbox.setText(mountpoint.umount()[1])
                else:
                    self.textbox.setText(mountpoint.mount()[1])
                # Wait 2 seconds before checking status...
                #time.sleep(2)
                self.refresh()


class MessageDialog(mmsv2gui.Window):
    def __init__(self):
        mmsv2gui.Window.__init__(self)
        button_width = 150
        button_height = 40
        border = 25
        msg_border = 5
        self.bg = mmsv2gui.RectangleControl(self.getWidth()/4, self.getHeight()/4, self.getWidth()/2, self.getHeight()/2, 200, '0xff0000')
        self.ok = mmsv2gui.ButtonControl(self.getWidth()/2 + border - button_width/2, 3*self.getHeight()/4 - border - button_height, button_width, button_height, "Ok", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        
        self.message = mmsv2gui.TextBoxControl(self.getWidth()/4 + msg_border, self.getHeight()/4 + msg_border, self.getWidth()/2 - 2*msg_border, self.getHeight()/2 - 2*msg_border)
        #self.message = mmsv2gui.TextBoxControl(self.getWidth()/4 + msg_border, self.getHeight()/4 + msg_border, 1000, 100)
        
        self.addControl(self.bg)
        self.addControl(self.message)
        self.addControl(self.ok)
                
        self.setFocus(self.ok)

    def setMessage(self, text):
        self.message.setText(text) 
    
    def display(self):
        self.doModal()
    
    def onAction(self, action):
        self.close()

class Dialog(mmsv2gui.Window):
    def __init__(self):
        mmsv2gui.Window.__init__(self)
        button_width = 150
        button_height = 40
        border = 25
        msg_border = 5
        self.bg = mmsv2gui.RectangleControl(self.getWidth()/4, self.getHeight()/4, self.getWidth()/2, self.getHeight()/2, 200, '0x000000')
        self.ok = mmsv2gui.ButtonControl(self.getWidth()/4 + border, 3*self.getHeight()/4 - border - button_height, button_width, button_height, "Ok", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        self.cancel = mmsv2gui.ButtonControl(3*self.getWidth()/4 - border - button_width, 3*self.getHeight()/4 - border - button_height, button_width, button_height, "Cancel", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        self.choice = False
        
        self.message = mmsv2gui.TextBoxControl(self.getWidth()/4 + msg_border, self.getHeight()/4 + msg_border, self.getWidth()/2 - 2*msg_border, self.getHeight()/2 - 2*msg_border)
        #self.message = mmsv2gui.TextBoxControl(self.getWidth()/4 + msg_border, self.getHeight()/4 + msg_border, 1000, 100)
        
        self.addControl(self.bg)
        self.addControl(self.message)
        self.addControl(self.ok)
        self.addControl(self.cancel)
        
        self.ok.controlRight(self.cancel)
        self.cancel.controlRight(self.ok)
        self.ok.controlLeft(self.cancel)
        self.cancel.controlLeft(self.ok)
        
        self.setFocus(self.cancel)

    def setMessage(self, text):
        self.message.setText(text)

    def getChoice(self):
        self.doModal()
        print >> sys.stderr, "Returning : %s" % str(self.choice)
        return self.choice
    
    def onAction(self, action):
        if action == "action":
            if self.getFocus() == self.ok:
                self.choice = True
                self.close()
            elif self.getFocus() == self.cancel:
                self.choice = False
                self.close()


class File(mmsv2gui.ListItem):
    def __init__(self, label):
        mmsv2gui.ListItem.__init__(self, label)
        self.setLabel(label)
        self.setThumbImage('file.png')


class Folder(mmsv2gui.ListItem):
    def __init__(self, label):
        mmsv2gui.ListItem.__init__(self, label)
        self.setLabel(label)
        self.setThumbImage('folder.png')


class FileLink(mmsv2gui.ListItem):
    def __init__(self, label):
        mmsv2gui.ListItem.__init__(self, label)
        self.setLabel(label)
        self.setThumbImage('file-link.png')


class FolderLink(mmsv2gui.ListItem):
    def __init__(self, label):
        mmsv2gui.ListItem.__init__(self, label)
        self.setLabel(label)
        self.setThumbImage('folder-link.png')

def fakeRoot(path):
    depth = path.count('/')
    if path[-1] == '/':
        depth -= 1
    for folder in fakeroot:
        f_depth = folder.count('/')
        if folder[-1] == '/':
            f_depth -= 1
        test = None
        if f_depth <= depth:
            test = folder
        else:
            test = folder.rsplit('/', f_depth - depth)[0]
        if path.startswith(test):
            return True
    return False
        
class Browser(mmsv2gui.ListControl):
    def sortList(self, liste):
        folders = []
        files = []
        for item in liste:
            if HIDE_DOT_FILES and item.startswith('.'):
                continue
            item_path = os.path.join(self.path, item)
            if fakeRoot(item_path):
                if os.path.islink(item_path):
                    if os.path.isfile(os.path.realpath(item_path)):
                        files.append(item)
                    elif os.path.isdir(os.path.realpath(item_path)):
                        folders.append(item)
                elif os.path.isfile(item_path):
                    files.append(item)
                elif os.path.isdir(item_path):
                    folders.append(item)
            
        folders.sort()
        files.sort()
        folders.extend(files)
        return folders
             
    def setPath(self, path):
        self.path = path
        self.clear()
        content = self.sortList(os.listdir(self.path))
        if self.path != '/':
            self.addItem(Folder('..'))
        for item in content:
            item_path = os.path.join(self.path, item)
            if os.path.islink(item_path):
                if os.path.isfile(os.path.realpath(item_path)):
                    self.addItem(FileLink(item))
                elif os.path.isdir(os.path.realpath(item_path)):
                    self.addItem(FolderLink(item))
            elif os.path.isfile(item_path):
                self.addItem(File(item))
            elif os.path.isdir(item_path):
                self.addItem(Folder(item))
        
    def getPath(self):
        return self.path
    
    def refresh(self):
        self.setPath(self.path)
    
    def getSelectedPath(self):
        return os.path.join(self.path, self.getSelectedItem().getLabel())
    
    def __init__(self, x, y, w, h, focus, nofocus, alignment):
        mmsv2gui.ListControl.__init__(self, x, y, w, h, focus=focus, nofocus=nofocus, alignment=alignment)
        self.path = '/'

    def changePath(self):
        selected = self.getSelectedItem().getLabel()
        if selected == '..':
            self.setPath(os.path.split(self.getPath())[0])
        else:
            self.setPath(os.path.join(self.getPath(), selected))


class FileManager(mmsv2gui.Window):
    def __init__(self):
        mmsv2gui.Window.__init__(self)
        up_offset = 50
        left_offset = 50
        right_offset = 50
        down_offset = 125 
        action_offset = 150
        bg_border = 5

        self.bg = mmsv2gui.ImageControl(0, 0, self.getWidth(), self.getHeight(), "general/bg.png")

        browser_width = (self.getWidth() - left_offset - action_offset - right_offset)/2
        browser_height = self.getHeight() - up_offset - down_offset
        
        self.l_browser_path = mmsv2gui.LabelControl(left_offset, up_offset - 30 - bg_border, browser_width, 30)
        self.r_browser_path = mmsv2gui.LabelControl(browser_width + action_offset + left_offset, up_offset - 30 - bg_border, browser_width, 30)
        
        self.l_browser_bg = mmsv2gui.RectangleControl(left_offset - bg_border, up_offset - bg_border, browser_width+2*bg_border, browser_height +2*bg_border, 20, '0xffffff')
        self.l_browser = Browser(left_offset, up_offset, browser_width, browser_height, "list-focus.png", "list-nofocus.png", "center")

        nb_buttons = 4
        button_height = 30
        buttons_offset = (browser_height - nb_buttons*button_height)/(nb_buttons+1)
        self.cp_button = mmsv2gui.ButtonControl(left_offset + browser_width + bg_border, up_offset + buttons_offset, action_offset - 2* bg_border, button_height, "Copy", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        self.mv_button = mmsv2gui.ButtonControl(left_offset + browser_width + bg_border, up_offset + 2*buttons_offset + button_height, action_offset - 2* bg_border, button_height, "Move", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        self.ln_button = mmsv2gui.ButtonControl(left_offset + browser_width + bg_border, up_offset + 3*buttons_offset + 2*button_height, action_offset - 2* bg_border, button_height, "Link", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)
        self.mount_button = mmsv2gui.ButtonControl(left_offset + browser_width + bg_border, up_offset + 4*buttons_offset + 3*button_height, action_offset - 2* bg_border, button_height, "Mount...", focus="button-focus.png", nofocus="button-nofocus.png", textoffset=15)

        self.r_browser_bg = mmsv2gui.RectangleControl(self.getWidth() - right_offset - browser_width - bg_border, up_offset - bg_border, browser_width+2*bg_border, browser_height+2*bg_border, 20, '0xffffff')
        self.r_browser = Browser(self.getWidth() - right_offset - browser_width, up_offset, browser_width, browser_height, "list-focus.png", "list-nofocus.png", "center" ) 

        self.messages_bg = mmsv2gui.RectangleControl(left_offset- bg_border, self.getHeight() - down_offset + 2*bg_border, self.getWidth() - 2*bg_border, down_offset-4*bg_border, 10, '0xffffff')
        message_line_height = (down_offset-4*bg_border)/3
        
        self.message1 = mmsv2gui.TextBoxControl(left_offset, self.getHeight() - down_offset + 4*bg_border, 2*browser_width, message_line_height)
        self.message2 = mmsv2gui.TextBoxControl(left_offset, self.getHeight() - down_offset + 4*bg_border + message_line_height, 2*browser_width, message_line_height)
        self.message3 = mmsv2gui.TextBoxControl(left_offset, self.getHeight() - down_offset + 4*bg_border + 2*message_line_height, 2*browser_width, message_line_height)
        self.messages = ['', '', '']
        self.msgidx = 0
        
        self.l_browser.setPath('/')
        self.l_browser_path.setLabel(self.l_browser.getPath())
        self.r_browser.setPath('/')
        self.r_browser_path.setLabel(self.r_browser.getPath())
        
        self.addControl(self.bg)
        
        self.addControl(self.l_browser_path)
        self.addControl(self.l_browser_bg)
        self.addControl(self.l_browser)
        
        self.addControl(self.cp_button)
        self.addControl(self.mv_button)
        self.addControl(self.ln_button)
        self.addControl(self.mount_button)
        
        self.addControl(self.r_browser_path)
        self.addControl(self.r_browser_bg)
        self.addControl(self.r_browser)
        
        self.addControl(self.messages_bg)
        self.addControl(self.message1)
        self.addControl(self.message2)
        self.addControl(self.message3)

        self.l_browser.controlRight(self.cp_button)
        
        self.cp_button.controlRight(self.r_browser)
        self.mv_button.controlRight(self.r_browser)
        self.ln_button.controlRight(self.r_browser)
        self.mount_button.controlRight(self.r_browser)
        
        self.cp_button.controlLeft(self.l_browser)
        self.mv_button.controlLeft(self.l_browser)
        self.ln_button.controlLeft(self.l_browser)
        self.mount_button.controlLeft(self.l_browser)
        
        self.cp_button.controlNext(self.mv_button)
        self.cp_button.controlPrev(self.mount_button)
        self.mv_button.controlNext(self.ln_button)
        self.mv_button.controlPrev(self.cp_button)
        self.ln_button.controlNext(self.mount_button)
        self.ln_button.controlPrev(self.mv_button)
        self.mount_button.controlNext(self.cp_button)
        self.mount_button.controlPrev(self.ln_button)
        
        self.l_browser.controlLeft(self.r_browser)
        self.r_browser.controlRight(self.l_browser)
        self.r_browser.controlLeft(self.cp_button)
        
        self.setFocus(self.l_browser)

    def appendMessage(self, message):
        if self.msgidx >= 3:
            self.messages[0] = self.messages[1]
            self.messages[1] = self.messages[2]
            self.messages[2] = message
        else:
            self.messages[self.msgidx] = message
            self.msgidx += 1
        self.message1.setText(self.messages[0])
        self.message2.setText(self.messages[1])
        self.message3.setText(self.messages[2])

    #def onClick(self, control):
        #self.appendMessage("Left Selection : " + self.l_browser.getSelectedPath() + " - Right Selection : " + self.r_browser.getSelectedPath())

    def onFocus(self, control):
        if self.getFocus() == self.cp_button:
            self.appendMessage("Copying " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " ??")
        elif self.getFocus() == self.mv_button:
            self.appendMessage("Moving " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " ??")
        elif self.getFocus() == self.ln_button:
            self.appendMessage("Linking " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " ??")

    def copy(self):
        self.dialog = Dialog()
        self.dialog.setMessage("Are you sure you want to copy " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + "?")
        if self.dialog.getChoice():
            del self.dialog
            self.appendMessage("Copying " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " . . .")
            print >> sys.stderr, 'shutil.copytree("%s", "%s")' % (self.l_browser.getSelectedPath(), self.r_browser.getPath())
            try:
                if os.path.isdir(self.l_browser.getSelectedPath()):
                    shutil.copytree(self.l_browser.getSelectedPath(), self.r_browser.getPath())
                elif os.path.isfile(self.l_browser.getSelectedPath()):
                    shutil.copy(self.l_browser.getSelectedPath(), self.r_browser.getPath())
                self.appendMessage("Copy OK")
	    except IOError, exc:
                self.appendMessage("Copy Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display() 
                del self.dialog
	    except OSError, exc:
                self.appendMessage("Copy Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display() 
                del self.dialog
        else:
            del self.dialog
            self.appendMessage("Copy Canceled")
        
    def move(self):
        dialog = Dialog()
        dialog.setMessage("Are you sure you want to move " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + "?")
        if dialog.getChoice():
            del dialog
            self.appendMessage("Moving " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " . . .")
            try:
                if os.path.isfile(self.l_browser.getSelectedPath()):
                    print >> sys.stderr, 'shutil.move("%s", "%s")' % (self.l_browser.getSelectedPath(), self.r_browser.getPath())
                    shutil.move(self.l_browser.getSelectedPath(), self.r_browser.getPath())
                    self.appendMessage("Move OK")
                elif os.path.isdir(self.l_browser.getSelectedPath()):
                    print >> sys.stderr, 'shutil.move("%s", "%s")' % (self.l_browser.getSelectedPath(), os.path.join(self.r_browser.getPath(), os.path.basename(self.l_browser.getSelectedPath())))
                    shutil.move(self.l_browser.getSelectedPath(), os.path.join(self.r_browser.getPath(), os.path.basename(self.l_browser.getSelectedPath())))
                    self.appendMessage("Move OK")
	    except IOError, exc:
                self.appendMessage("Move Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display() 
                del self.dialog
	    except OSError, exc:
                self.appendMessage("Move Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display() 
                del self.dialog
        else:
            del dialog
            self.appendMessage("Move Canceled")

    def link(self):
        dialog = Dialog()
        dialog.setMessage("Are you sure you want to link " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + "?")
        if dialog.getChoice():
            del dialog
            self.appendMessage("Linking " + self.l_browser.getSelectedPath() + " to " + self.r_browser.getPath() + " . . .")
            try:
                if os.path.isfile(self.l_browser.getSelectedPath()):
	            print >> sys.stderr, 'os.link("%s", "%s")' % (self.l_browser.getSelectedPath(), os.path.join(self.r_browser.getPath(), os.path.basename(self.l_browser.getSelectedPath()))) 
                    os.link(self.l_browser.getSelectedPath(), os.path.join(self.r_browser.getPath(), os.path.basename(self.l_browser.getSelectedPath()))) 
                    self.appendMessage("Link OK")
                else:
                    self.dialog = MessageDialog()
                    self.dialog.setMessage("Error: can't hard link to a dir")
                    self.dialog.display() 
	    except IOError, exc:
                self.appendMessage("Link Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display()
                del self.dialog
	    except OSError, exc:
                self.appendMessage("Link Error")
                self.dialog = MessageDialog()
                self.dialog.setMessage("Error: " + str(exc))
                self.dialog.display() 
                del self.dialog
        else:
            del dialog
            self.appendMessage("Link Canceled")

    def onAction(self, action):
        #Importent to catch some action, otherwise user can't close window
        if action == "back":
            self.close()
        if action == "action":
            if self.getFocus() == self.l_browser:
                self.l_browser.changePath()
                self.l_browser_path.setLabel(self.l_browser.getPath())
                self.appendMessage("Left Selection : " + self.l_browser.getSelectedPath() + " - Right Selection : " + self.r_browser.getSelectedPath())
            elif self.getFocus() == self.r_browser:
                self.r_browser.changePath()
                self.r_browser_path.setLabel(self.r_browser.getPath())
                self.appendMessage("Left Selection : " + self.l_browser.getSelectedPath() + "- Right Selection : " + self.r_browser.getSelectedPath())
            elif self.getFocus() == self.cp_button:
                self.copy()
                self.r_browser.refresh()
            elif self.getFocus() == self.mv_button:
                self.move()
		self.l_browser.refresh()
                self.r_browser.refresh()
            elif self.getFocus() == self.ln_button:
                self.link()
                self.r_browser.refresh()
            elif self.getFocus() == self.mount_button:
                mountpoints = MountPoints()
                mountpoints.doModal()
                del mountpoints

win = FileManager()
win.doModal()
del win