# -*- 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)