Select Git revision
StoreObjFrames.py
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;