Skip to content
Snippets Groups Projects
Select Git revision
  • a44cd42ec728bb00ebd004b7aff74f077a9d53b2
  • master default
2 results

StoreObjFrames.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    StoreObjFrames.py 11.34 KiB
    # -*- coding: utf-8 -*-
    
    """
     TK Frames for Representation of Storage Abstraction
     (C) 2014 Martin Süfke
     License: GPLv3 or newer: http://www.gnu.org/licenses/gpl.html
    """
    # Proper logging
    from pprint import pprint, pformat
    import logging
    #import os         # A dirty hack here 
    import subprocess 
    import shlex
    import signal      # future
    
    
    if __name__ == "__main__":
      #logging.basicConfig(level=logging.WARN)
      raise Exception("{0} cannot run as the main python program".format(__file__))
    
    if len(logging.root.handlers) == 0:
    # SPE compatible logging format
      logging.basicConfig(level=logging.DEBUG,format='%(levelno)2d:%(funcName)s:%(message)s:File "%(filename)s", line %(lineno)d')
    logger = logging.getLogger(__name__)
    
    import inspect
    
    import StorageObjects
    
    import  Tkinter as Tk
    #from    Tkinter import BooleanVar, IntVar, DoubleVar, StringVar
    #import  tkMessageBox as dialog
    #import  tkFileDialog as filedialog
    from    Tkconstants import N, E, S, W, HORIZONTAL, LEFT, RIGHT, TOP, BOTTOM, \
                               BOTH, NORMAL, DISABLED, X, Y
    
    def Implement(msg=""):
      logger.warn('Implement File "%s", line %s, %s'+msg,*inspect.stack()[1][1:4])
    
    def SizeStr(size):
      """ Print size with thousands separators """
      return "{0:,d} bytes".format(size)
        
    class TkFStorage(StorageObjects.Storage):
      """ Tk Frame for Storage """
      def __init__(self, ParentFrame):
        #logger.debug(self.__class__.__name__)
        super(self.__class__,self).__init__()
        self._ChildClass = TkFDrive
        self.TKFrame = Tk.Frame(ParentFrame, borderwidth=2, relief='groove')
        self.TKFrame.pack(side=TOP, fill=X)
        #Tk.Label(self.TKFrame,text=self.__class__.__name__).pack(side=LEFT, fill=X)    
    
      def FilterViewDriveAdd(self, MoreFiltersAsDict):
        """ Adds view filters on drives 
          example: FilterViewDriveAdd(self, {'Removable': True})
        """
        #logger.debug("Num Drives %d", len(self.StorageDrives))
        for k,v in self.StorageDrives.iteritems():
    #      logger.debug("\nDrive %s %s", k, str(v))
          v.FilterViewAdd(MoreFiltersAsDict)
    # TODO: Idea here is to retain the order of hidden/visible drives. 
    #       That may not be possible in all circumstances
    #       Also, is may not be desirable. When showing devices, add them at the TOP
    #      f = v.TKFrame
    #      x = f.tk.call('pack', 'info', str(f))
    ##      f._saved_w = f._w
    ##      f._w = str(f)
    ##      logger.debug("repr(f) %s",repr(f))
    ##      logger.debug(" str(f) %s", str(f))
    ##      x = f.pack_info()
    ##      f._saved_w = f._w
    ##      v.TKFrame.pack_forget()
    #      logger.debug("Pack_info: %s", x)
    #      
    #    logger.debug("Slave Frames %s", self.TKFrame.pack_slaves())
    
      def FilterViewDriveRemove(self, FilterKeysAsList):
        """ Removes view filters from drives 
          example: FilterViewDriveRemove(self, ['Removable', 'Ejectable']})
        """
        for k,v in self.StorageDrives.iteritems():
          v.FilterViewRemove(FilterKeysAsList)
    
    class TkFDrive(StorageObjects.StorageDrive):
      """ Tk Frame for Drive """
      def __init__(self, *args, **kwargs):
        """
          Pass argment to StorageObjects.StoragedDrive
    
          FilterView = {} :
            Dictionary of Key = Value pairs that make this entry invisible if found inside UDisks2Dict
        """
        #logger.debug(self.__class__.__name__)
        self.ViewFilter = kwargs.pop('FilterView', {})
        super(self.__class__,self).__init__(*args, **kwargs)
        self._ChildClass = TkFBlockdevice
        self.TKFrame = Tk.Frame(self.Parent.TKFrame, borderwidth=2, relief='groove', background='light blue')
        self.visible = False    # Not pack()'ed yet
        self.FilterView() # leads to self.TKFrame.Pack() if visible
        Tk.Label(self.TKFrame,text="Drive", background='light blue').pack(side=LEFT, anchor="nw")    
        InfoFrame = Tk.Frame(self.TKFrame, borderwidth=2)
        Tk.Button(InfoFrame,text="ignore", command = self.OnBtnIgnore, background='light blue').pack(side=RIGHT, anchor="e")
        if self.UDisks2Dict.get('Ejectable',False):
          Tk.Button(InfoFrame,text="Eject", command = self.OnBtnEject).pack(side=RIGHT, anchor="e")
        if self.UDisks2Dict.get('CanPowerOff',False):
          Tk.Button(InfoFrame,text="PowerOff", command = self.OnBtnPowerOff).pack(side=RIGHT, anchor="e")
        Tk.Label( InfoFrame,text=self.Id).pack(anchor="nw")
        # Size as a str ?!?
        try:
          Tk.Label( InfoFrame,text=SizeStr(self.Size)).pack(anchor="nw")
        except ValueError:
          logger.debug("self.Size: s:%s r:%s",str(self.Size), repr(self.Size))
        InfoFrame.pack(side=TOP, fill=X, padx=5, pady=5)
    
      def _close(self):
        """ A manual destructor"""
        self.TKFrame.pack_forget()  # Remove visible component
        self.TKFrame.destroy()      # Kill visible component
        self.TKFrame = None
        super(self.__class__,self)._close()
    
      def OnBtnEject(self):
        self.Eject()
     
      def OnBtnPowerOff(self):
        self.PowerOff()
    
      def OnBtnIgnore(self):
        #self.Ignore = True   # Make a Filter that always makes thisone ingnore itself.
        self.FilterViewAdd({'Id':self.UDisks2Dict['Id']})
        #logger.debug("UDisk2Dict: %s", pformat(self.UDisks2Dict))
        #self.FilterMakeInvisible()
    
      def FilterViewAdd(self, MoreFiltersAsDict):
        """ Adds view filters on this drive 
          Filtered drives will not show themselves in the main gui.
          example: FilterViewDriveAdd(self, {'Removable': True})
          see also: FilterViewRemove, FilterView
        """
        self.ViewFilter.update(MoreFiltersAsDict)
        self.FilterView()
    
      def FilterViewRemove(self, FilterKeysAsList):
        """ Removes view filters from this drive
          example: FilterViewDriveRemove(self, ['Removable', 'Ejectable']})
          see also: FilterViewAdd, FilterView
        """
        for k in FilterKeysAsList:    
          if k in self.ViewFilter:
            del self.ViewFilter[k]
        self.FilterView()
    
      def FilterView(self):
        """ Apply Filter against this drive 
          see also: FilterViewAdd, FilterViewRemove
        """
        visible = True
        for key, test in self.ViewFilter.iteritems():
          # A little suprising, but self.UDisks2Dict[dbus.String(u'Foo')] is as 
          # good as self.UDisks2Dict['Foo']
          #logger.debug("Testing key %s",key)
          if self.UDisks2Dict.has_key(key):
            #logger.debug("key found, value is %s", self.UDisks2Dict[key])
            #logger.debug("Testing %s == %s", test, self.UDisks2Dict[key] == test)
            if self.UDisks2Dict[key] == test:
              visible = False
        if visible:
          self.FilterMakeVisible()
        else:
          self.FilterMakeInvisible()
    
      def FilterMakeVisible(self):
        if not self.visible:
          #logger.debug("")
          self.TKFrame.pack(side=BOTTOM, fill=X)  # Pack on  Bottom, so that new entries end up on top.
          self.visible = True
        
      def FilterMakeInvisible(self):
        if self.visible:
          #logger.debug("")
          self.TKFrame.pack_forget()
          self.visible = False
        
    class TkFBlockdevice(StorageObjects.StorageBlockDevice):
      """ Tk Frame for Blockdevice """
      def __init__(self, *args, **kwargs):
        #logger.debug(self.__class__.__name__)
        #logger.debug("args %s kwargs %s", args, kwargs)
        kwargs['ChildClass'] = TkFFilesystem
        super(self.__class__,self).__init__(*args, **kwargs)
        self.TKFrame = Tk.Frame(self.Parent.TKFrame, borderwidth=2, relief='groove', background='light green')
        self.TKFrame.pack(side=BOTTOM, fill=X)
        Tk.Label(self.TKFrame,text="BlkDev", background='light green').pack(side=LEFT, anchor="nw")    
        InfoFrame = Tk.Frame(self.TKFrame, borderwidth=2, relief='flat')
        #Tk.Label(self.TKFrame,text=self.__class__.__name__).pack(side=TOP, fill=X)    
        Tk.Button(InfoFrame, text="Write", command=self.TkCmdWrite).pack(side=RIGHT)
        Tk.Label( InfoFrame, text="{0:s}".format(self.PreferredDevice)).pack(anchor="nw")    
        Tk.Label( InfoFrame, text="Size "+SizeStr(self.Size)).pack(anchor="nw")    
        InfoFrame.pack(side=TOP, fill=X, padx=5, pady=5)
    
      def _close(self):
        """ A manual destructor"""
        self.TKFrame.pack_forget()  # Remove visible component
        self.TKFrame.destroy()      # Kill visible component
        self.TKFrame = None
        super(self.__class__,self)._close()
        
      def TkCmdWrite(self):
        logger.debug("Write to %s  -> execute write.sh %s", self.PreferredDevice, self.PreferredDevice)
        # TODO: This would need a nice subprocess.popen() ... 
        #os.system("./write.sh %s"%(self.PreferredDevice))
    
        if True: #not self.proc:
          cmdarray=" ".join( [
                          "./write.sh %s"%(self.PreferredDevice),
                        ] )
    
          args = shlex.split(cmdarray)
      
          self.proc = subprocess.Popen(args,
                                       #bufsize = 1, # line buffered
                                       bufsize = 4096, # byte buffered
                                       stdin = None,
                                       stdout = None, #subprocess.PIPE,
                                       stderr = None, #subprocess.STDOUT,
                                       # preexec_fn unneeded
                                       close_fds = True, # Do not leak file descriptors
                                       #cwd = Current Working Directory
                                       #env Environment mapping
                                       )
    
        logger.debug("write.sh executed")
    
    class TkFFilesystem(StorageObjects.StorageFileSystem):
      """ Tk Frame for Filesystem """
      def __init__(self, *args, **kwargs):
        #logger.debug(self.__class__.__name__)
        super(self.__class__,self).__init__(*args, **kwargs)
        self._ChildClass = TkFMountpoint
        self.TKFrame = Tk.Frame(self.Parent.TKFrame, borderwidth=2, relief='groove')
        self.TKFrame.pack(side=TOP, fill=X)
        InfoFrame = Tk.Frame(self.TKFrame, borderwidth=2, relief='flat')
        #Tk.Label(self.TKFrame,text="Filesystem").pack(anchor="nw")    
        Tk.Button(InfoFrame,text="Mount", command=self.TkCmdMount).pack(side=RIGHT)
        Tk.Label( InfoFrame,text=self.IdUsage + " " + self.IdType + " " + self.IdVersion).pack(anchor="nw")    
        Tk.Label( InfoFrame,text=self.IdUUID + " " + self.IdLabel).pack(anchor="nw")    
        InfoFrame.pack(side=TOP, fill=X)
    
      def _close(self):
        """ A manual destructor"""
        self.TKFrame.pack_forget()  # Remove visible component
        self.TKFrame.destroy()      # Kill visible component
        self.TKFrame = None
        super(self.__class__,self)._close()
    
      def TkCmdMount(self, *args, **kwargs):
        #logger.debug("TkFFilesystem args:%s %s",args,kwargs)
        self.Mount()
    
        #logger.debug("TkFFilesystem args:%s %s",args,kwargs)
    
    class TkFMountpoint(StorageObjects.StorageMountPoint):
      """ Tk Frame for Mountpoint """
      def __init__(self, *args, **kwargs):
        #logger.debug("args %s kwargs %s", args, kwargs)
        #logger.debug(self.__class__.__name__)
        super(self.__class__,self).__init__(*args, **kwargs)
        self.TKFrame = Tk.Frame(self.Parent.TKFrame, borderwidth=2, relief='groove', background='#FFC4C4')
        self.TKFrame.pack(side=TOP, fill=X, ipadx=5, ipady=2)
        Tk.Button(self.TKFrame,text="Unmount", command=self.TkCmdUnmount).pack(side=RIGHT)
        Tk.Label(self.TKFrame,text="mounted on " + self.MountPoint).pack(side=LEFT)
    
    #  def __del__(self):
    #    logger.debug("%s.__del__()",self.__class__.__name__)
    #    super(self.__class__,self).__del__()
    
      def _close(self):
        """ A 'manual' destructor"""
        #logger.debug("%s _close for %s",self.__class__.__name__,str(self))
        self.TKFrame.pack_forget()  # Remove visible component
        self.TKFrame.destroy()      # Kill visible component
        self.TKFrame = None
        super(self.__class__,self)._close()
        
      def TkCmdUnmount(self, *args, **kwargs):
        #logger.debug("TkFMountpoint args:%s %s",args,kwargs)
        self.Unmount()
      
      
    #end;