#!/usr/bin/env python # -*- mode: python; coding: utf-8 -*- # TwinPanel # # Copyright (C) 2007,2008,2009 David Villa, Oscar Aceña, Cleto Martin # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #try: # import psyco # psyco.full() #except ImportError: # pass import os os.environ['LANG'] = 'C' import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)-8s %(name)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filename='/tmp/inspector_%s.log' % os.getpid(), filemode='w') import logutil console = logging.StreamHandler() console.setLevel(logging.ERROR) console.setFormatter(logutil.ColorFormatter(' %(levelname)s[%(name)s]: %(message)s')) logging.getLogger().addHandler(console) import config import sys, optparse from domain_twinpanel import LogInspector inspector_handler = LogInspector() inspector_handler.setLevel(logging.DEBUG) import threading, time tIni = time.time() import gtk, gtk.glade, gobject, pango gobject.threads_init() import gc import util sys.excepthook = util.excepthook_logger import menu util.set_ident() import factory import random import inspector_base import widgets #gdk_enter = gtk.gdk.threads_enter #gdk_leave = gtk.gdk.threads_leave # #class Mutex(object): # def __init__(self): # self.lock = threading.RLock() # # def enter(self): # logging.info('enter') # if self.lock._RLock__count == 0: # gdk_enter() # # self.lock.acquire() # # def leave(self): # logging.info('leave') # if self.lock._RLock__count == 1: # gdk_leave() # # self.lock.release() class Notebook(gtk.Notebook): 'A notebook with tab label and close buttons' def __init__(self): gtk.Notebook.__init__(self) self.popup_enable() #self.set_property("tab-hborder", 2) self.set_property("scrollable", True) self.set_property("show-tabs", False) self.set_group_id(1) self.connect("create-window", self.__on_create_window) self.show() self.npage = 0 def delete(self): for child in self.get_children(): child.delete() def append_page(self, child, text='(empty tab)'): label = gtk.Label(text) label.set_ellipsize(pango.ELLIPSIZE_END) label.set_alignment(0.0, 0.5) ebtip = gtk.EventBox() ebtip.add(label) ebtip.set_visible_window(False) def __tip(self, x, y, something, tooltip): tooltip.set_icon_from_stock("gtk-info", gtk.ICON_SIZE_LARGE_TOOLBAR) tooltip.set_markup(label.get_text()) return True ebtip.set_property("has-tooltip", True) ebtip.connect("query-tooltip", __tip) close_button_img = gtk.image_new_from_stock("gtk-close", gtk.ICON_SIZE_MENU) close_button = gtk.Button() close_button.set_relief(gtk.RELIEF_NONE) close_button.set_focus_on_click(False) close_button.add(close_button_img) close_button.set_size_request(20, 20) hbox = gtk.HBox(False, 0) hbox.pack_start(ebtip, True, True, 0) hbox.pack_start(close_button, False, False, 0) hbox.show_all() menu_label = gtk.Label(text) gtk.Notebook.append_page_menu(self, child, hbox, menu_label) self.set_tab_label_packing(child, True, True, gtk.PACK_START) self.set_tab_reorderable(child, True) self.set_tab_detachable(child, True) self.set_current_page(self.get_n_pages()-1) self.npage += 1 close_button.connect('clicked', self.__on_close_clicked, child) child.attach(label.set_text, Panel.TOPIC_URI) child.attach(menu_label.set_text, Panel.TOPIC_URI) child.attach(child.wg_comboboxentry_uri.set_text, Panel.TOPIC_URI) child.notify() def __on_close_clicked(self, button, child): nb = child.parent nb.remove_page(nb.page_num(child)) child.delete() gc.collect() def __on_create_window(self, nb, child, *args): # Old (and valid) code (18/09/08) nb.remove_page(nb.page_num(child)) InspectorManager(panel=child) # This code create a new skin, instead of reusing old one #p = Panel(child.mySide) #p.setup(child.inspector, child.skin.name) #InspectorManager(panel=p) #nb.remove_page(nb.page_num(child)) class GuiContext: def __init__(self, name, uimgr=None): self.name = name self.actionmgrs = [] self.append = self.actionmgrs.append self.remove = self.actionmgrs.remove def __repr__(self): return "" % (self.name, id(self)) class Side(util.GladeWrapper, gtk.VBox): def __init__(self, manager): gtk.VBox.__init__(self) util.GladeWrapper.__init__(self, config.path("twinpanel.glade"), "side") self.manager = manager self.pack_start(self.wg_side) self.notebook = Notebook() self.notebook.connect('switch-page', self.on_notebook_switch_page) self.notebook.connect('page-removed', self.on_notebook_page_removed) self.notebook.connect('page-added', self.on_notebook_page_added) #self.notebook.connect_closed(self.on_notebook_page_closed) self.notebook.connect('button-press-event', self.__set_focus_child) self.wg_hbox_bookcontainer.pack_start(self.notebook) self.wg_active_region.connect("button-press-event", self.__set_focus_child) #self.current_panel.set_active(False) # Initially inactive def delete(self): self.notebook.delete() def create_new_panel(self, uri=None, inspector_name=None, skin_name=None): panel = Panel(self) if uri: if not isinstance(uri, util.URI): uri = util.parse_uri(uri) panel.setup_from_uri(uri, inspector_name, skin_name) self.add_panel(panel) def add_panel(self, panel): self.notebook.append_page(panel) panel.mySide = self @property def current_panel(self): return self.notebook.get_nth_page(self.notebook.get_current_page()) def set_active(self, state): self.current_panel.set_active(state) # gui callbacks def __set_focus_child(self, widget, *args): # FIXME: esto es un trik muy sucio... self.current_panel.wg_button_combo_ok.grab_focus() def on_notebook_switch_page(self, notebook, page, pagenum): panel = notebook.get_nth_page(pagenum) # hasta que no acabe este callback, current_panel sigue siendo # el child anterior. # old_panel = self.current_panel assert panel.uicontext self.manager.ui_select_context(panel.uicontext) #self.wg_comboboxentry_uri.set_text('') #panel.attach(self.wg_comboboxentry_uri.set_text, Panel.TOPIC_URI) #panel.notify() def on_notebook_page_closed(self, notebook, child, data): child.delete() gc.collect() def on_notebook_page_removed(self, nb, panel, *args): if nb.get_n_pages() < 2: nb.set_property("show-tabs", False) # FIXME: esto se debe hacer en el panel #try: # panel.detach(self.wg_comboboxentry_uri.set_text, Panel.TOPIC_URI) #except Panel.NotSuchObserver: # pass # #if not nb.get_n_pages(): # self.wg_comboboxentry_uri.set_text('') # FIXME: Esto hace que se destruya el panel, cuando quizá sólo # se quiere sacar del side #panel.delete() #gc.collect() def on_notebook_page_added(self, nb, panel, pos): if nb.get_n_pages() > 1: nb.set_property("show-tabs", True) panel.mySide = self class IssueManager: def __init__(self): self.__slider = widgets.Slider() self.wg_issue_gui.pack_start(self.__slider) self.__slider.show() self.wg_issue_next.set_sensitive(True) self.wg_issue_prev.set_sensitive(True) def __update(self): index = self.__slider.index+1 if len(self.__slider) else 0 self.wg_label_number_issues.set_label(\ '%s/%s' % (index, len(self.__slider))) def on_close_clicked(self, btn): self.wg_issue_container.hide() def clear_issues(self): self.__slider.clear() self.__update() def on_clear_clicked(self, btn): self.clear_issues() def on_prev_clicked(self, btn): self.__slider.prev() self.__update() def on_next_clicked(self, btn): self.__slider.next() self.__update() def push_issue(self, new_issue): # FIXME: si no estaba oculto, debe cambiar al nuevo issue self.wg_issue_container.show() skin = factory.IssueSkin(issue=new_issue) self.__slider.push(skin.get_content()) self.wg_issue_gui.show() self.__update() def get_content(self): return self.wg_issue_gui class Panel(util.GladeWrapper, util.Observable, gtk.VBox, IssueManager): TOPIC_URI = 'uri' TOOLBAR = ''' ''' def __init__(self, mySide, uri=None): util.GladeWrapper.__init__(\ self, config.path("twinpanel.glade"), "panel") util.Observable.__init__(self, topics=[Panel.TOPIC_URI]) gtk.VBox.__init__(self) IssueManager.__init__(self) # FIXME: Glade parece ignorar esta propiedad, se establece aquí self.wg_toolbutton5.set_expand(True) self.mySide = mySide self.pack_start(self.wg_panel) # barra de botones del panel self.ui_name = str(id(self)) self.uimgr = self.mySide.manager.uimgr self.toolbar_id = 'Toolbar_%s' % self.ui_name self.ui_toolbar_id = self.uimgr.add_ui_from_string(\ self.TOOLBAR % self.toolbar_id) toolbar = self.uimgr.get_widget("/Toolbar_"+self.ui_name) toolbar.set_property('icon-size', gtk.ICON_SIZE_MENU) toolbar.set_style(gtk.TOOLBAR_ICONS) self.wg_panel_toolbar_container.pack_start(toolbar) self.show() # individual inspector logger self.log_handler = LogInspector() self.log_handler.setLevel(logging.DEBUG) # by default, log hidden self.wg_vbox_log.hide() self.uri = None self.inspector = None self.skin = None self.busy_thread = None self.busy_timer = None self.busy_source = None self.uicontext = GuiContext('Panel:%s' % uri) logging.info("New panel: %s" % (uri)) if uri: self.setup_from_uri(uri) # Focus on uri entry gobject.idle_add(self.wg_comboboxentry_uri.grab_focus) def __str__(self): return "" % (self.uri, self.skin, self.inspector) def set_message(self, msg): self.wg_statusbar.push(self.wg_statusbar.get_context_id("one"), msg) def create_new_panel(self, *args): self.mySide.create_new_panel(*args) def set_busy(self, value): @util.gtksafe def pulse(): self.wg_progressbar.pulse() return True if value and self.busy_source == None: self.wg_progressbar.show() self.wg_progressbar.set_pulse_step(0.1) self.wg_progressbar.set_text('working') self.busy_source = gobject.timeout_add(200, pulse) else: self.wg_progressbar.hide() if self.busy_source: gobject.source_remove(self.busy_source) self.busy_source = None # def set_busy2(self, value): # # def pulse(): # util.gtkexec(self.wg_progressbar.pulse) # return True # # if value and self.busy_thread == None: # util.gtkexec(self.wg_progressbar.show) # self.busy_thread = util.ThreadTimeout(0.2, pulse) # else: # util.gtkexec(self.wg_progressbar.hide) # if self.busy_thread: # self.busy_thread.cancel() # self.busy_thread = None def update_status(self, status): if status == inspector_base.Inspector.INIT: self.set_message('') self.issues_hide() self.set_busy(status == inspector_base.Inspector.WORKING) @property def current(self): return self.skin.current() @property def selected(self): return self.skin.selected() @property def toolbar(self): return def issues_hide(self): # reset issue slider self.clear_issues() self.wg_issue_container.hide() def setup(self, inspector, skin_name=None): self.issues_hide() # Inspector for this uri self.inspector = inspector self.inspector.attach(self.update_status, self.inspector.TOPIC_STATUS) self.inspector.attach(self.push_issue, self.inspector.TOPIC_ISSUE) self.log_handler.clear() self.inspector.logger.addHandler(self.log_handler) # Skin de este inspector self.setup_skin(skin_name) self.notify() # Para arrancar el hilo del inspector después de hacer el attach self.inspector.do_refresh() # self.wg_statusbar.push(self.wg_statusbar.get_context_id("one"), # "ready: %.2fs" % (time.time()-tIni)) def setup_from_uri(self, uri, inspector_name=None, skin_name=None): self.uri = uri self.setup_inspector_and_skin(inspector_name, skin_name) # si es una nueva uri, hay que rehacer el menú de inspectores self.uicontext = GuiContext('Panel:%s' % self.uri) self.uicontext.append(self.__view_as_actions(self.inspector.subject)) self.mySide.manager.ui_select_context(self.uicontext) def setup_inspector_and_skin(self, inspector_name=None, skin_name=None): self.delete_inspector() inspector = factory.create_inspector(self.uri, self, inspector_name) inspector.ui_actions = menu.ActionManager(self.ui_name) inspector.do_define_actions(inspector.ui_actions) self.setup(inspector, skin_name) self.skin.do_define_actions(inspector.ui_actions) inspector.ui_actions.insert_ui(self.uimgr) del inspector def setup_skin(self, skin_name=None): # para evitar que el menú quede congelado mientras se cambia el skin while gtk.events_pending(): gtk.main_iteration(False) if self.skin: self.delete_skin() self.skin = factory.create_skin(self.inspector, skin_name) self.wg_skin_container.add(self.skin.get_content()) if self.skin.expand == self.skin.BOTH: self.wg_skin_container.set_shadow_type(gtk.SHADOW_NONE) else: self.wg_skin_container.set_shadow_type(gtk.SHADOW_ETCHED_OUT) if self.skin.expand == self.skin.BOTH: self.wg_align_skin.set(0, 0, 1, 1) elif self.skin.expand == self.skin.HORIZONTAL: self.wg_align_skin.set(0.5, 0.5, 0.9, 0) elif self.skin.expand == self.skin.VERTICAL: self.wg_align_skin.set(0.5, 0.5, 0, 0.9) else: self.wg_align_skin.set(0.5, 0.5, 0, 0) # FIXME: Hack to video 'Bad Drawable' problems if self.skin.name in ["video", "camera"]: self.skin.dropingcenterid = self.mySide.wg_dropingcenter.window.xid def setup_tracker(self, tracker_name, skin_name): inspector = factory.create_tracker(self.inspector, tracker_name) self.setup(inspector, skin_name) self.mySide.manager.ui_select_context(ui_context) #def show_issue(self, issue): # self.push_issue(issue) # self.wg_issue_container.show() # Rellena el menú "view as" de panel_menubar con los inspectores y # los skins disponibles, según la factoría para el subject indicado def __view_as_actions(self, subject): VIEW_AS_MENU = ''' ''' INSPECTOR_MENU = ''' ''' INSPECTOR_ITEM = ''' ''' SKIN_ITEM = ''' ''' def ui_add_inspectors(avail, place): for i in avail: auto, manual, mini = factory.available_skins(i) for s in auto: actionname = 'viewas_%s_%s_%s' % (self.ui_name, i.name, s.name) where = self.ui_name + '_' + i.name if place == 'auto' else 'manual' self.desc += INSPECTOR_ITEM % (place, where, actionname) self.entries.append((actionname, None, '%s :: %s' % (i.name, s.name), '', '', self.n)) radio_map.append((i.name, s.name)) self.n += 1 auto = factory.available_auto_inspectors(subject) manual = factory.available_manual_inspectors(subject) #UIMANAGER name = subject.uri if subject else "issue" actionmgr = menu.ActionManager("menu inspectores '%s'" % name) actionmgr.add_menu(('ViewAs', None, '_View as'), VIEW_AS_MENU) radio_map = [] self.entries = [] self.desc = '' self.n = 0 if auto: ui_add_inspectors(auto, place='auto') if manual: ui_add_inspectors(manual, place='manual') actionmgr.add_desc(self.desc) actionmgr.group.add_radio_actions(\ self.entries, 0, self.change_inspector_and_skin, radio_map) return actionmgr # FIXME: que pasa si self.inspector es un tracker? existen los trackers de los trackers? #def __append_trackers_to_menu(self): # trackers = factory.available_trackers(self.inspector) # # for t in trackers: # for skin in factory.available_skins(t)[0]: # Only auto skins # path = 'Trace changes->%s->%s' % (t.name, skin.name) # self.context.action_set.add(\ # path = path, # where = menu.MENUBAR, # callback = self.setup_tracker, # args = [t.name, skin.name]) # # #def __append_options_to_menu(self): # self.__show_log_action = self.context.action_set.add( # path = 'Debug->Show log', # where = menu.MENUBAR, # callback = self.on_show_log_activate, # kind = menu.TOGGLE) def delete_skin(self): if self.skin == None: return if self.busy_thread: self.busy_thread.cancel() self.wg_skin_container.remove(self.skin.get_content()) logging.debug('Deleting skin: %s' % self.skin.name) self.skin.delete() del self.skin self.skin = None def delete_inspector(self): if self.inspector == None: return self.delete_skin() logging.debug('Deleting inspector: %s' % self.inspector.name) self.inspector.ui_actions.remove_ui(self.uimgr) del self.inspector.ui_actions self.inspector.logger.removeHandler(self.log_handler) self.inspector.delete() # Hide and remove the old log-skin if hasattr(self, "log_skin"): self.wg_vbox_log.hide() self.wg_vbox_log.remove(self.log_skin.gui) self.log_skin.delete() del self.log_skin del self.inspector self.inspector = None def delete(self): logging.debug('Deleting panel: %s' % self) self.delete_inspector() self.delete_skin() self.uimgr.remove_ui(self.ui_toolbar_id) def __del__(self): logging.debug("__del__: %s" % self) self.delete() def notify(self): if self.inspector == None: return self.uri = self.inspector.get_uri() if self.uri: util.Observable.notify(self, str(self.uri), Panel.TOPIC_URI) # GUI callback def change_inspector_and_skin(self, action, widget, arg): logging.info("CHANGE VIEW AS: %s %s" % (action, arg)) inspector_name, skin_name = arg[widget.get_current_value()] #print inspector_name, skin_name if self.inspector.name == inspector_name: if self.skin.name == skin_name: return self.setup_skin(skin_name) else: self.setup_inspector_and_skin(inspector_name, skin_name) self.mySide.manager.ui_select_context(self.uicontext) def set_active(self, state): if state: base_color = gtk.gdk.Color(0xffff, 0xffff, 0xffff) else: base_color = gtk.gdk.Color(0xd6d6, 0xd4d4, 0xd2d2) self.wg_comboboxentry_uri.modify_base(gtk.STATE_NORMAL, base_color) self.mySide.manager.ui_select_context(self.uicontext) def on_comboboxentry_uri_activate(self, entry): text_uri = entry.get_text().strip() if not text_uri: return uri = util.parse_uri(text_uri) if uri != self.uri: self.setup_from_uri(uri) def on_button_combo_ok_clicked(self, widget): # First, make this side as active (if not yet) self.mySide.manager.on_change_side(self) self.wg_combobox_uri.child.activate() def on_show_log_activate(self): # Show log if self.__show_log_action.views[0][0].get_active(): self.log_skin = factory.create_skin(self.log_handler, "list") self.wg_vbox_log.pack_start(self.log_skin.gui) self.wg_vbox_log.show_all() self.__show_log_action.check(True) # FIXME: this is temporal, until fix the slow appearing effect h = self.wg_vpaned_panel.allocation.height self.wg_vpaned_panel.set_position(h-200) # Slow appearing effect #a = self.wg_vpaned_panel.allocation #t = a.height #while t>(a.height-200): # self.wg_vpaned_panel.set_position(t) # t -= 10 # while gtk.events_pending(): # gtk.main_iteration() # Hide log else: # Slow disappearing effect #a = self.wg_vpaned_panel.allocation #t = self.wg_vpaned_panel.get_position() #while t < a.height: # self.wg_vpaned_panel.set_position(t) # t += 10 # while gtk.events_pending(): # gtk.main_iteration() self.__show_log_action.check(False) self.wg_vbox_log.hide() self.wg_vbox_log.remove(self.log_skin.gui) self.log_skin.delete() del self.log_skin def on_clear_log_clicked(self, widget): self.log_handler.clear() def on_close_log_clicked(self, widget): self.__show_log_action.views[0][0].set_active(False) # Splash screen class SplashScreen(util.GladeWrapper): def __init__(self): util.GladeWrapper.__init__(self, config.path("twinpanel.glade"), "splash_screen") self.wg_splash_screen.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0xffff, 0xffff, 0xffff)) self.wg_image.set_from_file(config.path("pixmaps/logo.png")) self.gui = self.wg_splash_screen self.bars = {\ 'domain': self.wg_progressbar_domain, 'inspector': self.wg_progressbar_inspector, 'skin': self.wg_progressbar_skin} self.keys = ['domain', 'inspector', 'skin'] self.nv = {} self.step = {} for k in self.keys: self.nv[k] = 0 self.step[k] = .1 def start(self): self.gui.show_all() def setup(self, value): name, steps = value self.nv[name] = 0 self.step[name] = 1.0 /steps self.bars[name].set_fraction(0) def stop(self): self.wg_label.set_markup('Load complete!') for k in self.keys: self.bars[k].set_fraction(1.0) while gtk.events_pending(): gtk.main_iteration() gobject.timeout_add(100, self.gui.hide_all) def update(self, value): name, fname = value self.wg_label.set_markup("Loading %s '%s'" % value) if self.nv[name] >= 0.99: self.nv[name] = self.step[name] else: self.nv[name] += self.step[name] self.bars[name].set_fraction(self.nv[name]) while gtk.events_pending(): gtk.main_iteration() #raw_input() class InspectorManager(util.GladeWrapper): main_inspector = None ui_desc = ''' ''' # # # # # # # # # # def __init__(self, uri='', panel=None): util.GladeWrapper.__init__(self, config.path("twinpanel.glade")) self.wg_main.set_title("Twin Panel v1.%04s" % config.revision()) self.wg_main.show() self.setup_uimgr() self.leftside = Side(self) self.rightside = Side(self) self.leftside.connect("set-focus-child", self.on_change_side) self.rightside.connect("set-focus-child", self.on_change_side) # Only show the right side, the active side self.rightside.show() #self.rightside.set_active(True) self.__active_side = self.rightside self.wg_hpaned_sides_container.pack1(self.leftside, resize=False) self.wg_hpaned_sides_container.pack2(self.rightside, resize=False) self.tips = gtk.Tooltips() if uri: self.__active_side.create_new_panel(util.parse_uri(uri)) # If there is a panel, inserts it elif panel: self.add_panel(panel) # Other way, create one else: self.rightside.create_new_panel() util.Reference.ref() def update_actions(self, wd): pass #self.__active_side.current_panel.inspector.ui_update_actions() def setup_uimgr(self): self.uimgr = gtk.UIManager() accelgroup = self.uimgr.get_accel_group() self.wg_main.add_accel_group(accelgroup) self.main_actiongrp = gtk.ActionGroup('Window') self.main_actiongrp.add_actions(\ [('Application', None, '_Application'), ('LSide', None, '_Left Side'), ('NewLeftPanel', gtk.STOCK_NEW, '_New panel', '', 'New panel at left side', self.on_menu_item_new_left_tab_activate), ('RSide', None, '_Right Side'), ('NewRightPanel', gtk.STOCK_NEW, '_New panel','', 'New panel at right side', self.on_menu_item_new_right_tab_activate), ('NewWindow', gtk.STOCK_NEW, '_New Window', 'n', 'New window', self.on_new_window_activate), ('ClearQuit', gtk.STOCK_QUIT, '_Clear & Quit', '', 'Clear plugins cache and exit program', self.clear_and_quit), ('Quit', gtk.STOCK_QUIT, '_Quit', 'q', 'Exit program', self.on_main_delete_event), ('View', None, '_View'), ('Tabs', None, '_Tabs'), ('Bookmarks', None, '_Bookmarks'), ('AddBookmark', gtk.STOCK_ADD, '_Add Bookmark'), ('Panel', None, '_Panel', '', '', self.update_actions), ('Help', None, '_Help'), ('About', None, '_About', '', 'TwinPanel introspection', self.on_menuitem_about_activate), ('Credits', gtk.STOCK_ABOUT, '_Credits', '', 'TwinPanel credits', self.on_menuitem_credits_activate), ('NewPanel', gtk.STOCK_NEW, '_New panel', 't', 'New panel on current side', self.on_toolbutton_newpanel_clicked)]) self.main_actiongrp.add_toggle_actions(\ [('ViewRootLog', None, '_Root log', None, 'Shows the root log', self.on_menuitem_show_root_log_toggled, False), ('ViewLeftSide', None, '_Left side', 'l', 'Shows the left side', self.on_menuitem_show_left_panel_toggled, False), ('Fullscreen', None, '_Fullscreen', 'F11', 'Toggle fullscreen mode', self.on_fullscreen_toggled, False), ('ViewToolbar', None, 'Tool_bar', None, None, self.on_menuitem_show_toolbars, True), # ('ViewIssues', None, 'Issues', None, # None, self.on_menuitem_show_issues, False), ('ViewTearOffs', None, 'Tear _Offs', None, 'Shows menu tear offs handlers', self.on_menuitem_show_tearoff, False)]) self.main_actiongrp.add_radio_actions(\ [('TabsTop', None, '_Top', None, None, 0), ('TabsBottom', None, 'Bottom', None, None, 1)], 0, self.on_menutitem_tab_position) self.uimgr.insert_action_group(self.main_actiongrp, 0) self.uimgr.add_ui_from_string(self.ui_desc) menubar = self.uimgr.get_widget('/Menubar') self.wg_uimenubar_container.pack_start(menubar) #toolbar = self.uimgr.get_widget('/Toolbar') #toolbar.set_property('icon-size', gtk.ICON_SIZE_MENU) #toolbar.set_style(gtk.TOOLBAR_ICONS) #self.wg_toolbar_container.pack_start(toolbar) self.uicontext = GuiContext('main') def delete(self): self.leftside.delete() self.rightside.delete() def add_panel(self, panel): self.__active_side.add_panel(panel) def ui_select_context(self, new_context): if self.uicontext.actionmgrs == new_context.actionmgrs: logging.debug("El contexto no ha cambiado") return # borrar los que no están en el nuevo contexto logging.debug("Se ELIMINAN los action mgrs") for am in set(self.uicontext.actionmgrs) - set(new_context.actionmgrs): logging.debug(str(am)) am.remove_ui(self.uimgr) # añadir los que no estaban en el contexto anterior logging.debug("Se AÑADEN los action mgrs") for i, am in enumerate(set(new_context.actionmgrs) - set(self.uicontext.actionmgrs)): logging.debug(str(am)) am.insert_ui(self.uimgr, i) self.uicontext = new_context #print self.uimgr.get_ui() # gui callbacks def on_main_delete_event(self, widget, event=None): self.delete() if util.Reference.unref(): gtk.main_quit() # if it is called from menu self.wg_main.destroy() def clear_and_quit(self, widget): self.delete() gtk.main_quit() self.wg_main.destroy() factory.clear_cache() def on_menu_item_new_left_tab_activate(self, widget): self.leftside.create_new_panel() self.uimgr.get_widget('/Menubar/View/ViewLeftSide').set_active(True) def on_menu_item_new_right_tab_activate(self, widget): self.rightside.create_new_panel() def on_fullscreen_toggled(self, widget): if widget.get_active(): self.wg_main.fullscreen() else: self.wg_main.unfullscreen() #def on_tab_unpack_activate(self, widget): # nb = self.__active_side.notebook # npage = nb.get_current_page() # # if npage == -1: # logging.warning("There is no tab to unpack!") # return # # child = nb.get_nth_page(npage) # # nb.remove_page(npage) # (panel=child) def on_new_window_activate(self, widget): InspectorManager() def on_change_side(self, side, event=None): if side == self.__active_side: return self.__active_side.set_active(False) # Old side side.set_active(True) # New side self.__active_side = side def on_menuitem_about_activate(self, widget): self.__active_side.create_new_panel(util.parse_uri('about://')) def on_menuitem_credits_activate(self, widget): self.__active_side.create_new_panel(util.parse_uri('about://credits')) def on_menuitem_show_root_log_toggled(self, widget): if widget.get_active(): # Skin for root log inspector log_skin = factory.create_skin(inspector_handler, "list") self.wg_log_box.pack_start(log_skin.gui) self.wg_root_log.show_all() else: for c in self.wg_log_box.get_children(): self.wg_log_box.remove(c) self.wg_root_log.hide() def on_menuitem_show_left_panel_toggled(self, widget): if widget.get_active(): # Create a panel if it not exists if not self.leftside.current_panel: self.leftside.create_new_panel() self.leftside.show() self.on_change_side(self.leftside) else: self.leftside.hide() self.on_change_side(self.rightside) def on_menuitem_show_toolbars(self, widget): if widget.get_active(): self.__active_side.current_panel.toolbar.show() else: self.__active_side.current_panel.toolbar.hide() def on_menuitem_show_tearoff(self, widget): self.uimgr.set_add_tearoffs(widget.get_active()) def on_menutitem_tab_position(self, action, current): for side in [self.rightside, self.leftside]: side.notebook.set_property('tab-pos',\ [gtk.POS_TOP, gtk.POS_BOTTOM][action.get_current_value()]) def on_toolbutton_newpanel_clicked(self, wd): self.__active_side.create_new_panel() def on_root_log_delete_event(self, widget, event): self.uimgr.get_widget('/Menubar/View/ViewRootLog').set_active(False) return True def on_button_clean_root_log_clicked(self, widget): inspector_handler.clear() def factory_load(): sp = SplashScreen() sp.start() factory.load(sp) sp.stop() if __name__ == "__main__": optparser = optparse.OptionParser(usage="%prog [options] ") optparser.add_option("-v", action="count", dest="verbosity", help="increases verbosity") optparser.add_option("--reset-plugins-cache", dest="reset_cache", action="store_true", help="resets the current plugin cache") optparser.add_option("--Ice.Config", dest="ice_config", help="config file for ice") options,args = optparser.parse_args() if options.verbosity: if options.verbosity > 3: options.verbosity = 3 level = [logging.WARNING, logging.INFO, logging.DEBUG][options.verbosity-1] console.setLevel(level) logging.debug("verbosity: %s" % logging.getLevelName(level)) logging.info("config: BASE set to %s" % config.BASE) param = '' gtk.gdk.threads_init() #m = Mutex() #gtk.gdk.threads_enter = m.enter #gtk.gdk.threads_leave = m.leave if len(sys.argv) > 1: args = [x for x in sys.argv[1:] if x[0] != '-'] if args: param = args[0] #if not param: # param = config.Config.get('Session.RightPanel.uri') if options.reset_cache: factory.clear_cache() factory_load() im = InspectorManager(uri=param) #r_uri = config.Config.get('Session.LeftPanel.uri') #if r_uri: # im.leftside.create_new_panel(util.parse_uri(r_uri)) # im.leftside.show() logging.getLogger().addHandler(inspector_handler) try: gtk.main() except KeyboardInterrupt: im.delete() gtk.gdk.threads_leave() # cleaning logging.info('Shutting down...') factory.shutdown() ini = time.time() while 1: n = len([x for x in threading.enumerate() if not isinstance(x, threading._DummyThread)]) logging.debug('waiting for thread finish: %s' % n) if n < 2: break if time.time() - ini > 5: logging.warning('-- Non finished threads:') for t in threading.enumerate(): logging.warning(str(t)) logging.shutdown() sys.exit(1) time.sleep(1) logging.info('Ok') logging.shutdown() sys.excephook = sys.__excepthook__