# -*- mode: python; coding: utf-8 -*-
import logging
import time
import gobject, gtk
import zope.interface as interface
import util
import menu
import factory
import exc
# Base class for all inspector's exceptions
class InspectorException(Exception):
def __init__(self, msg): self.msg = msg
# Base class for all inspectors.
class Inspector(util.Observable):
"""
Clase base de los inspectores: métodos de instrospección
"""
class OperationFailed(Exception): pass
INIT, WORKING, READY, UNKNOWN = range(4) #status values
TOPIC_STATUS = 'status'
TOPIC_ISSUE = 'error'
MANUAL, AUTO, MINI, STRICT = [2**x for x in range(4)] # boolean flags on the rocks
flags = AUTO
def __init__(self, subject, name=None):
util.Observable.__init__(self, [Inspector.TOPIC_STATUS,
Inspector.TOPIC_ISSUE])
self.subject = subject
if not name: name = self.name
self.logger = logging.getLogger(name)
import mixin
allowed_do_refresh = [\
mixin.ThreadMixIn.do_refresh.im_func,
mixin.DataTableHelper.do_refresh.im_func,
Inspector.do_refresh.im_func
]
if self.do_refresh.im_func not in allowed_do_refresh:
msg = "Method '%s.do_refresh()' is forbidden" % \
(self.__class__.__name__)
self.logger.critical(msg)
raise exc.InternalError(msg)
self.callbacks = {}
# UI Manager
self.ui_actions = menu.ActionManager(None)
def do_define_actions(self, actionmgr):
# common actions
self.actionmgr = actionmgr
if hasattr(self, 'refresh'):
actionmgr.add_action(name = 'Refresh',
icon = gtk.STOCK_REFRESH,
label = '_Refresh',
accel = 'F5',
callback = self.__refresh,
location = menu.TOOLBAR)
if hasattr(self, 'clear'):
actionmgr.add_action(name = 'Clear',
icon = gtk.STOCK_CLEAR,
label = '_Clear',
callback = self.clear,
location = menu.TOOLBAR)
if self.subject and factory.method_get_info(self.subject.uri.method):
actionmgr.add_action(name = 'Info',
icon = gtk.STOCK_INFO,
label = '_Info',
callback = self.info,
location = menu.TOOLBAR)
if hasattr(self, 'stop'):
# FIXME: añadir action
pass
self.define_actions(actionmgr)
def define_actions(self, actionmgr):
"must be redefined in each inspector subclass"
pass
def clean_openwith_actions(self):
try:
if self.__last_open_with_actionmgr:
self.__last_open_with_actionmgr.remove_ui(self.actionmgr.uimgr)
self.__last_open_with_actionmgr = None
except AttributeError: pass
def update_openwith_actions(self, path):
# First clean all
try:
uri = util.parse_uri("ice://%s" % self.store[path][0].proxy)
subject = self.icemgr.to_object(uri)
except exc.UnavailableResource, e:
return
OPEN_WITH_MENU = '''
'''
INSPECTOR_MENU = '''
'''
INSPECTOR_ITEM = '''
'''
SKIN_ITEM = '''
'''
def ui_add_inspectors(actionmgr, avail, place, cb, uri):
for i in avail:
auto, non_auto, _ = factory.available_skins(i)
if len(auto) == 1:
s = auto[0]
actionname = '%s_%s' % (i.name, s.name)
actionmgr.append_action_with_desc(
(actionname, None, '%s (%s)' % \
(i.name, s.name), '', '', cb),
[uri, i.name, s.name],
INSPECTOR_ITEM % (self.actionmgr.ui_name, actionname))
continue;
actionmgr.add_menu((i.name, None, i.name),
INSPECTOR_MENU % (self.actionmgr.ui_name, i.name))
for s in auto:
actionname = '%s_%s' % (i.name, s.name)
actionmgr.append_action_with_desc(
(actionname, None, s.name, '', '', cb),
[uri, i.name, s.name],
SKIN_ITEM % (self.actionmgr.ui_name, i.name, actionname))
auto = factory.available_auto_inspectors(subject)
manual = factory.available_manual_inspectors(subject)
name = self.actionmgr.ui_name+".last_open_with"
self.__last_open_with_actionmgr = menu.ActionManager(name)
self.__last_open_with_actionmgr.add_menu(\
('Open with', None, 'Open with'),
OPEN_WITH_MENU % self.actionmgr.ui_name)
if auto:
ui_add_inspectors(\
self.__last_open_with_actionmgr, auto, 'auto',
lambda a, args: self.on_open_with(*args), uri)
if manual:
ui_add_inspectors(\
self.__last_open_with_actionmgr, manual, 'manual',
lambda a, args: self.on_open_with(*args), uri)
self.__last_open_with_actionmgr.insert_ui(self.actionmgr.uimgr)
def on_open_with(self, uri, inspector_name, skin_name):
assert(self.manager)
self.manager.create_new_panel(uri, inspector_name, skin_name)
def info(self, args=None):
self.manager.create_new_panel(\
util.parse_uri('about://info/%s' % self.subject.uri.method))
def delete(self):
del self
def __refresh(self, *args):
self.notify(self.INIT, self.TOPIC_STATUS)
self.do_refresh(*args)
# it may be overwritten by mixin classes
def do_refresh(self, args=None):
if not hasattr(self, 'refresh'):
self.logger.debug("There isn't refresh()")
return
self.refresh()
def cancel(self):
pass
def is_volatile(self):
return True
def get_uri(self):
return self.subject.uri
def ui_update_actions(self, current, selected):
raise NotImplementedError
def get_property(self, name):
raise NotImplementedError
def set_property(self, name, value):
raise NotImplementedError
def __str__(self):
return self.__class__.__name__
@classmethod
def can_manage(cls, prx):
return False
# Interface for those inspectors which can manage objects with scalar state
class IDataTypeInspector(interface.Interface):
"that holds a individual value"
def readable():
"is readable?"
def writable():
"is writeable?"
def set_state(value):
"set inspector value"
def get_state():
"get inspector value"
class ITextInspector(IDataTypeInspector): pass
class ITextBufferInspector(ITextInspector): pass
class IFileInspector(interface.Interface):
"Fof inspectors that behaves as a posix file"
def readable(): pass
def writeable(): pass
def read(nbytes): pass
def write(data): pass
def container_inspector_invariant(obj):
try:
assert hasattr(obj, 'callbacks')
assert isinstance(obj.store, gtk.ListStore) or \
isinstance(obj.store, gtk.TreeStore)
except AssertionError:
raise exc.InterfaceViolation
# Interface for those inspectors which can manage containers
class IContainerInspector(interface.Interface):
"That holds a collection of inspection-able objects"
callbacks = interface.Attribute("callback dict")
store = interface.Attribute("a TreeStore or ListStore")
interface.invariant(container_inspector_invariant)
def get_matching_actions(self, items):
"get applicable actions"
def dataset_inspector_invariant(obj):
try:
assert hasattr(obj, 'store')
assert isinstance(obj.store, gtk.ListStore)
except AssertionError:
raise exc.InterfaceViolation
class IDataSetInspector(interface.Interface):
"a set of primitive values (non objects)"
store = interface.Attribute("a ListStore")
interface.invariant(dataset_inspector_invariant)
class IDataListInspector(interface.Interface):
""
store = interface.Attribute("a list")
interface.invariant(dataset_inspector_invariant)
class Tracker(Inspector):
"Create a model using the data provided by the tracked inspector"
name = 'tracker'
def __init__(self, inspector):
Inspector.__init__(self, inspector.subject)
self.inspector = inspector
self.store = util.TPListStore()
self.actions.add(icon = 'gtk-media-next',
tip = 'next',
where = menu.TOOLBAR,
callback = self.next)
# redirected methods:
self.clear = self.store.clear
self.next = self.inspector.refresh
def time(self):
t = time.time()
return "%s.%s" % (time.strftime("%H:%M:%S", time.localtime(t)),
str(t % 1)[2:5])
@classmethod
def filter_inspector(cls, subject, iface):
auto, non_auto = factory.available_inspectors(subject)
for i in auto+non_auto:
if iface.implementedBy(i) and i != cls:
return i
return None
class StateTracker(Tracker):
name = "state tracker"
flags = Inspector.MANUAL
interface.implements(IDataSetInspector)
metamodel = [\
util.MItem(title='Time', _text='key', id=100),
util.MItem(title='Value', _text='val', __xalign=1)]
def __init__(self, inspector):
Tracker.__init__(self, inspector)
assert IStateInspector.providedBy(inspector)
inspector.attach(self.update)
inspector.refresh()
def update(self, value):
self.store.append_item(util.Record(key=self.time(), val=value))
@classmethod
def can_manage(cls, inspector):
return IStateInspector.providedBy(inspector)
class DataSetTracker(Tracker):
name = "dataSet tracker"
flags = Inspector.MANUAL
interface.implements(IDataSetInspector)
def __init__(self, inspector):
Tracker.__init__(self, inspector)
assert IDataSetInspector.providedBy(inspector)
self.metamodel = [util.MItem(title='Time', _text='key', id=100)]
for col in self.inspector.datamodel:
if hasattr(col, 'var') and col.var:
self.metamodel.append(col)
inspector.attach(self.update)
inspector.refresh()
def update(self, pholder):
item = self.inspector.dataset
item.key = self.time()
self.store.append_item(item)
# FIXME: que el inspector provea la interfaz IDataSet no es
# suficiente para determinar que se puede usar este tracker con él
@classmethod
def can_manage(cls, inspector):
return IDataSetInspector.providedBy(inspector)