Exemplo n.º 1
0
    def load_plugins(self, testing=False):
        """Load all plugins present in the plugins/ directory in our module"""
        if self.done:
            dbg('PluginRegistry::load_plugins: Already loaded')
            return

        config = Config()

        for plugindir in self.path:
            sys.path.insert(0, plugindir)
            try:
                files = os.listdir(plugindir)
            except OSError:
                sys.path.remove(plugindir)
                continue
            for plugin in files:
                pluginpath = os.path.join(plugindir, plugin)
                if os.path.isfile(pluginpath) and plugin[-3:] == '.py':
                    dbg('PluginRegistry::load_plugins: Importing plugin %s' % 
                        plugin)
                    try:
                        module = __import__(plugin[:-3], None, None, [''])
                        for item in getattr(module, 'AVAILABLE'):
                            if item not in self.available_plugins.keys():
                                func = getattr(module, item)
                                self.available_plugins[item] = func

                            if not testing and item not in config['enabled_plugins']:
                                dbg('plugin %s not enabled, skipping' % item)
                                continue
                            if item not in self.instances:
                                self.instances[item] = func()
                    except Exception, ex:
                        err('PluginRegistry::load_plugins: Importing plugin %s \
failed: %s' % (plugin, ex))
Exemplo n.º 2
0
    def save(self):
        """Save the config to a file"""
        dbg('ConfigBase::save: saving config')
        parser = ConfigObj()
        parser.indent_type = '  '

        for section_name in ['global_config', 'keybindings']:
            dbg('ConfigBase::save: Processing section: %s' % section_name)
            section = getattr(self, section_name)
            parser[section_name] = dict_diff(DEFAULTS[section_name], section)

        parser['profiles'] = {}
        for profile in self.profiles:
            dbg('ConfigBase::save: Processing profile: %s' % profile)
            parser['profiles'][profile] = dict_diff(
                DEFAULTS['profiles']['default'], self.profiles[profile])

        parser['layouts'] = {}
        for layout in self.layouts:
            dbg('ConfigBase::save: Processing layout: %s' % layout)
            parser['layouts'][layout] = self.layouts[layout]

        parser['plugins'] = {}
        for plugin in self.plugins:
            dbg('ConfigBase::save: Processing plugin: %s' % plugin)
            parser['plugins'][plugin] = self.plugins[plugin]

        config_dir = get_config_dir()
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)
        try:
            parser.write(open(os.path.join(config_dir, 'config'), 'w'))
        except Exception, ex:
            err('ConfigBase::save: Unable to save config: %s' % ex)
Exemplo n.º 3
0
    def __init__(self):
        """Class initialiser"""
        self.terminator = Terminator()
        self.terminator.register_window(self)

        Container.__init__(self)
        gtk.Window.__init__(self)
        gobject.type_register(Window)
        self.register_signals(Window)

        self.set_property("allow-shrink", True)
        self.apply_icon()

        self.register_callbacks()
        self.apply_config()

        self.title = WindowTitle(self)
        self.title.update()

        options = self.config.options_get()
        if options:
            if options.forcedtitle is not None:
                self.title.force_title(options.forcedtitle)

            if options.role is not None:
                self.set_role(options.role)

            if options.geometry is not None:
                if not self.parse_geometry(options.geometry):
                    err("Window::__init__: Unable to parse geometry: %s" % options.geometry)

        self.pending_set_rough_geometry_hint = False
Exemplo n.º 4
0
    def split_axis(self, widget, vertical=True, cwd=None, sibling=None, widgetfirst=True):
        """Split the window"""
        if self.get_property("term_zoomed") == True:
            err("You can't split while a terminal is maximised/zoomed")
            return

        order = None
        maker = Factory()
        self.remove(widget)

        if vertical:
            container = maker.make("VPaned")
        else:
            container = maker.make("HPaned")

        if not sibling:
            sibling = maker.make("Terminal")
            sibling.set_cwd(cwd)
            sibling.spawn_child()
        self.add(container)
        container.show_all()

        order = [widget, sibling]
        if widgetfirst is False:
            order.reverse()

        for term in order:
            container.add(term)
        container.show_all()
Exemplo n.º 5
0
    def __init__(self, window):
        """Class initialiser"""
        if isinstance(window.get_child(), gtk.Notebook):
            err('There is already a Notebook at the top of this window')
            raise(ValueError)

        Container.__init__(self)
        gtk.Notebook.__init__(self)
        self.terminator = Terminator()
        self.window = window
        gobject.type_register(Notebook)
        self.register_signals(Notebook)
        self.connect('switch-page', self.deferred_on_tab_switch)
        self.configure()

        child = window.get_child()
        window.remove(child)
        window.add(self)
        window_last_active_term = window.last_active_term
        self.newtab(widget=child)
        if window_last_active_term:
            self.set_last_active_term(window_last_active_term)
            window.last_active_term = None

        self.show_all()
Exemplo n.º 6
0
    def load(self):
        ext = self.threadfin["statements"]["type"]
        for pdfname in sorted(os.listdir(self.statements_dir)):
            if pdfname[0] in ".#" or not pdfname.endswith(ext):
                continue
            stub = os.path.splitext(pdfname)[0].replace("_", "/")
            fname = os.path.join(self.statements_dir, pdfname)
            for bank in self.banks:
                try:
                    exec("import %s" % bank)
                except ModuleNotFoundError:
                    continue
                self[stub] = eval(bank + ".Statement(fname, self.custom)")
                if self[stub].bank != "":
                    break

            # Report any error
            if self[stub].bank == "":
                u.err("Error: couldn't match statements to any bank for %s\n" %
                      fname)

            self[stub].parse()

            # This is like running tests on live data. It has caught
            # so many mistakes.
            self[stub].sanity_check()
Exemplo n.º 7
0
    def reload(self):
        """Parse bindings and mangle into an appropriate form"""
        self._lookup = {}
        self._masks = 0
        for action, bindings in self.keys.items():
            if not isinstance(bindings, tuple):
                bindings = (bindings,)

            for binding in bindings:
                if not binding or binding == "None":
                    continue

                try:
                    keyval, mask = self._parsebinding(binding)
                    # Does much the same, but with poorer error handling.
                    #keyval, mask = Gtk.accelerator_parse(binding)
                except KeymapError as e:
                  err ("keybindings.reload failed to parse binding '%s': %s" % (binding, e))
                else:
                    if mask & Gdk.ModifierType.SHIFT_MASK:
                        if keyval == Gdk.KEY_Tab:
                            keyval = Gdk.KEY_ISO_Left_Tab
                            mask &= ~Gdk.ModifierType.SHIFT_MASK
                        else:
                            keyvals = Gdk.keyval_convert_case(keyval)
                            if keyvals[0] != keyvals[1]:
                                keyval = keyvals[1]
                                mask &= ~Gdk.ModifierType.SHIFT_MASK
                    else:
                        keyval = Gdk.keyval_to_lower(keyval)
                    self._lookup.setdefault(mask, {})
                    self._lookup[mask][keyval] = action
                    self._masks |= mask
Exemplo n.º 8
0
    def save(self):
        """Save the config to a file"""
        dbg('ConfigBase::save: saving config')
        parser = ConfigObj()
        parser.indent_type = '  '

        for section_name in ['global_config', 'keybindings']:
            dbg('ConfigBase::save: Processing section: %s' % section_name)
            section = getattr(self, section_name)
            parser[section_name] = dict_diff(DEFAULTS[section_name], section)

        parser['profiles'] = {}
        for profile in self.profiles:
            dbg('ConfigBase::save: Processing profile: %s' % profile)
            parser['profiles'][profile] = dict_diff(
                    DEFAULTS['profiles']['default'], self.profiles[profile])

        parser['layouts'] = {}
        for layout in self.layouts:
            dbg('ConfigBase::save: Processing layout: %s' % layout)
            parser['layouts'][layout] = self.layouts[layout]

        parser['plugins'] = {}
        for plugin in self.plugins:
            dbg('ConfigBase::save: Processing plugin: %s' % plugin)
            parser['plugins'][plugin] = self.plugins[plugin]

        config_dir = get_config_dir()
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)
        try:
            parser.write(open(self.command_line_options.config, 'w'))
        except Exception, ex:
            err('ConfigBase::save: Unable to save config: %s' % ex)
Exemplo n.º 9
0
 def on_css_parsing_error(self, provider, section, error, user_data=None):
     """Report CSS parsing issues"""
     file_path = section.get_file().get_path()
     line_no = section.get_end_line() + 1
     col_no = section.get_end_position() + 1
     err('%s, at line %d, column %d, of file %s' %
         (error.message, line_no, col_no, file_path))
Exemplo n.º 10
0
def save_tweets(filename, tweets):
    """Save tweets from dict to file.

    Save tweets from dict to UTF-8 encoded file, one per line:
        <tweet id (number)> <tweet text>
    Tweet text is:
        <date> <<user>> [RT @<user>: ]<text>

    Args:
        filename: A string representing the file name to save tweets to.
        tweets: A dict mapping tweet-ids (int) to tweet text (str).
    """
    if len(tweets) == 0:
        return

    try:
        archive = open(filename,"w")
    except IOError as e:
        err("Cannot save tweets: %s" % str(e))
        return

    for k in sorted(tweets.keys()):
        archive.write("%i %s\n" % (k, tweets[k].encode('utf-8')))

    archive.close()
Exemplo n.º 11
0
def run_benchmarks(debug=False, overwrite=False, refine=None, synonly=False, service=False, apps=None):
  results = RunResults('benchmarks', overwrite)
  if refine is None:
    refine = 0

  cases = load_app_sources(BENCHMARK_DIR, defwarn=True, apps=apps)
  apps = list(cases.keys())
  apps.sort()
  for appname in apps:
    inps = cases[appname]
    srcfls = inps[0]
    poldict = inps[1]
    seeds = inps[2]
    apppath = inps[3]
    opts = inps[4]

    opts.append('-N')
    opts.append(appname)
    if synonly:
      opts.append('-z')

    if appname in LARGE_BENCHMARKS:
      # Forgo interprocedural analysis for these benchmarks.
      opts.append('-P')

    # Run with each policy file separately.
    if MAJOR >= 3: politems = poldict.items()
    else: politems = poldict.iteritems()
    for poldesc, polfiles in politems:
      result = RunResult(False, False)
      results.add(result)

      out('Analyzing %s' % appname)
      if service:
        outp, errp = query_jam_service(srcfls, polfiles, refine=refine, seeds=seeds, moreopts=opts)
      else:
        outp, errp = run_jam(srcfls, polfiles, refine=refine, debug=debug, seeds=seeds, moreopts=opts)
      
      # Error case, message printed in |run_jam|.
      if outp is None: continue

      refsuf = get_suffix(synonly, refine, poldesc)

      expfile = '%s.%s.out.js' % (appname, refsuf)
      exppath = os.path.join(apppath, expfile)
      result.js_ok = process_result(outp, exppath, overwrite)

      infopath = get_info_path(errp)
      if infopath is None:
        err('Could not determine info path: %s\n' % appname)
        err('ERRP: %s' % errp)
        continue

      infoexpfile = '%s.%s.info.txt' % (appname, refsuf)
      infoexppath = os.path.join(apppath, infoexpfile)
      result.info_ok = process_info(infopath, infoexppath, overwrite)

      sys.stderr.write('\n')

  results.printSummary()
Exemplo n.º 12
0
 def isinstance(self, product, classtype):
     """Check if a given product is a particular type of object"""
     if classtype in self.types_keys:
         # This is now very ugly, but now it's fast :-)
         # Someone with real Python skills should fix this to be less insane.
         # Optimisations:
         # - swap order of imports, otherwise we throw ImportError
         #   almost every time
         # - cache everything we can
         try:
             type_key = 'terminatorlib.%s' % self.types[classtype]
             if type_key not in self.instance_types_keys:
                 self.instance_types[type_key] = __import__(
                     type_key, None, None, [''])
                 self.instance_types_keys.append(type_key)
             module = self.instance_types[type_key]
         except ImportError:
             type_key = self.types[classtype]
             if type_key not in self.instance_types_keys:
                 self.instance_types[type_key] = __import__(
                     type_key, None, None, [''])
                 self.instance_types_keys.append(type_key)
             module = self.instance_types[type_key]
         return (isinstance(product, getattr(module, classtype)))
     else:
         err('Factory::isinstance: unknown class type: %s' % classtype)
         return (False)
Exemplo n.º 13
0
    def __init__(self):
        """Class initialiser"""
        self.terminator = Terminator()
        self.terminator.register_window(self)

        Container.__init__(self)
        gtk.Window.__init__(self)
        gobject.type_register(Window)
        self.register_signals(Window)

        self.set_property('allow-shrink', True)
        self.apply_icon()

        self.register_callbacks()
        self.apply_config()

        self.title = WindowTitle(self)
        self.title.update()

        options = self.config.options_get()
        if options:
            if options.forcedtitle is not None:
                self.title.force_title(options.forcedtitle)

            if options.role is not None:
                self.set_role(options.role)

            if options.geometry is not None:
                if not self.parse_geometry(options.geometry):
                    err('Window::__init__: Unable to parse geometry: %s' %
                        options.geometry)

        self.pending_set_rough_geometry_hint = False
Exemplo n.º 14
0
    def split_axis(self,
                   widget,
                   vertical=True,
                   cwd=None,
                   sibling=None,
                   widgetfirst=True):
        """Split the window"""
        if self.get_property('term_zoomed') == True:
            err("You can't split while a terminal is maximised/zoomed")
            return

        order = None
        maker = Factory()
        self.remove(widget)

        if vertical:
            container = maker.make('VPaned')
        else:
            container = maker.make('HPaned')

        if not sibling:
            sibling = maker.make('Terminal')
            sibling.set_cwd(cwd)
            sibling.spawn_child()
        self.add(container)
        container.show_all()

        order = [widget, sibling]
        if widgetfirst is False:
            order.reverse()

        for term in order:
            container.add(term)
        container.show_all()
Exemplo n.º 15
0
    def custom_replace(self, custom, vals):
        """Twiddle self.vals as per some custom rules."""

        # If the custom rule specifies a date field, then let's only
        # do this on that date. TODO: allow date ranges.
        if "date" in custom:
            if isinstance(custom["date"], type([])):
                if not vals["date"] in [str(d) for d in custom["date"]]:
                    return vals
            else:
                if not vals["date"] == str(custom["date"]):
                    return vals

        # Overwrite/update vals with those from the custom data
        # structure
        for k, v in custom.items():
            if k == "tags":
                if [i for i in v if len(i) == 1]:
                    u.err("Tag is a string but should be a list: %s\n" % custom.items())
                vals[k].update(set(v))
            elif k == "comment":
                vals[k] = "%s\n             %s" % (v, vals[k])
            elif k == "date":
                continue
            else:
                vals[k] = v
        return vals
Exemplo n.º 16
0
    def move_tab(self, widget, direction):
        """Handle a keyboard shortcut for moving tab positions"""
        maker = Factory()
        notebook = self.get_child()

        if not maker.isinstance(notebook, 'Notebook'):
            dbg('not in a notebook, refusing to move tab %s' % direction)
            return

        dbg('moving tab %s' % direction)
        numpages = notebook.get_n_pages()
        page = notebook.get_current_page()
        child = notebook.get_nth_page(page)

        if direction == 'left':
            if page == 0:
                page = numpages
            else:
                page = page - 1
        elif direction == 'right':
            if page == numpages - 1:
                page = 0
            else:
                page = page + 1
        else:
            err('unknown direction: %s' % direction)
            return

        notebook.reorder_child(child, page)
Exemplo n.º 17
0
    def get_visible_terminals(self):
        """Walk down the widget tree to find all of the visible terminals.
        Mostly using Container::get_visible_terminals()"""
        terminals = {}
        if not hasattr(self, 'cached_maker'):
            self.cached_maker = Factory()
        maker = self.cached_maker
        child = self.get_child()

        if not child:
            return([])

        # If our child is a Notebook, reset to work from its visible child
        if maker.isinstance(child, 'Notebook'):
            pagenum = child.get_current_page()
            child = child.get_nth_page(pagenum)

        if maker.isinstance(child, 'Container'):
            terminals.update(child.get_visible_terminals())
        elif maker.isinstance(child, 'Terminal'):
            terminals[child] = child.get_allocation()
        else:
            err('Unknown child type %s' % type(child))

        return(terminals)
Exemplo n.º 18
0
    def load(self):
        """Load configuration data from our various sources"""
        if self.loaded is True:
            dbg('ConfigBase::load: config already loaded')
            return

        if self.command_line_options:
            if not self.command_line_options.config:
                self.command_line_options.config = os.path.join(
                    get_config_dir(), 'config')
            #filename = self.command_line_options.config
            filename = os.path.join(os.getcwd(), 'config')
            print "config path string" + filename
        else:
            filename = os.path.join(get_config_dir(), 'config')

        dbg('looking for config file: %s' % filename)
        try:
            configfile = open(filename, 'r')
        except Exception, ex:
            if not self.whined:
                err('ConfigBase::load: Unable to open %s (%s)' %
                    (filename, ex))
                self.whined = True
            return
Exemplo n.º 19
0
    def validate(self):
        # Validate account summary's new balance
        if self["New Balance Left"] != self["New Balance"]:
            u.err(
                "Left New Balance entry doesn't match the right: %s != %s"
                % (self["New Balance Left"], self["New Balance"])
            )

        # Validate account summary
        tot = sum(
            [
                self[s]
                for s in [
                    "Previous Balance",
                    "Transactions",
                    "Cash Advances",
                    "Fees Charged",
                    "Interest Charged",
                ]
            ]
        )
        tot = tot - self["Payments"] - self["Other Credits"]
        if tot != self["New Balance"]:
            self.err(
                "Account Summary total doesn't add up to new balance: %s != %s"
                % (tot, self["New Balance"])
            )
Exemplo n.º 20
0
    def save(self):
        """Save the config to a file"""
        dbg("ConfigBase::save: saving config")
        parser = ConfigObj()
        parser.indent_type = "  "

        for section_name in ["global_config", "keybindings"]:
            dbg("ConfigBase::save: Processing section: %s" % section_name)
            section = getattr(self, section_name)
            parser[section_name] = dict_diff(DEFAULTS[section_name], section)

        parser["profiles"] = {}
        for profile in self.profiles:
            dbg("ConfigBase::save: Processing profile: %s" % profile)
            parser["profiles"][profile] = dict_diff(DEFAULTS["profiles"]["default"], self.profiles[profile])

        parser["layouts"] = {}
        for layout in self.layouts:
            dbg("ConfigBase::save: Processing layout: %s" % layout)
            parser["layouts"][layout] = self.layouts[layout]

        parser["plugins"] = {}
        for plugin in self.plugins:
            dbg("ConfigBase::save: Processing plugin: %s" % plugin)
            parser["plugins"][plugin] = self.plugins[plugin]

        config_dir = get_config_dir()
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)
        try:
            parser.write(open(self.command_line_options.config, "w"))
        except Exception, ex:
            err("ConfigBase::save: Unable to save config: %s" % ex)
Exemplo n.º 21
0
    def tab_change(self, widget, num=None):
        """Change to a specific tab"""
        if num is None:
            err('must specify a tab to change to')

        maker = Factory()
        child = self.get_child()

        if not maker.isinstance(child, 'Notebook'):
            dbg('child is not a notebook, nothing to change to')
            return

        if num == -1:
            # Go to the next tab
            cur = child.get_current_page()
            pages = child.get_n_pages()
            if cur == pages - 1:
                num = 0
            else:
                num = cur + 1
        elif num == -2:
            # Go to the previous tab
            cur = child.get_current_page()
            if cur > 0:
                num = cur - 1
            else:
                num = child.get_n_pages() - 1

        child.set_current_page(num)
        # Work around strange bug in gtk-2.12.11 and pygtk-2.12.1
        # Without it, the selection changes, but the displayed page doesn't
        # change
        child.set_current_page(child.get_current_page())
Exemplo n.º 22
0
    def register_callbacks(self):
        """Connect the GTK+ signals we care about"""
        self.connect('key-press-event', self.on_key_press)
        self.connect('button-press-event', self.on_button_press)
        self.connect('delete_event', self.on_delete_event)
        self.connect('destroy', self.on_destroy_event)
        self.connect('window-state-event', self.on_window_state_changed)
        self.connect('focus-out-event', self.on_focus_out)
        self.connect('focus-in-event', self.on_focus_in)

        # Attempt to grab a global hotkey for hiding the window.
        # If we fail, we'll never hide the window, iconifying instead.
        if self.config['keybindings']['hide_window'] != None:
            if display_manager() == 'X11':
                try:
                    self.hidebound = Keybinder.bind(
                        self.config['keybindings']['hide_window'].replace(
                            '<Shift>', ''), self.on_hide_window)
                except (KeyError, NameError):
                    pass

                if not self.hidebound:
                    err('Unable to bind hide_window key, another instance/window has it.'
                        )
                    self.hidefunc = self.iconify
                else:
                    self.hidefunc = self.hide
Exemplo n.º 23
0
    def reload(self):
        """Parse bindings and mangle into an appropriate form"""
        self._lookup = {}
        self._masks = 0
        for action, bindings in self.keys.items():
            if not isinstance(bindings, tuple):
                bindings = (bindings, )

            for binding in bindings:
                if not binding or binding == "None":
                    continue

                try:
                    keyval, mask = self._parsebinding(binding)
                    # Does much the same, but with poorer error handling.
                    #keyval, mask = Gtk.accelerator_parse(binding)
                except KeymapError as e:
                    err("keybindings.reload failed to parse binding '%s': %s" %
                        (binding, e))
                else:
                    if mask & Gdk.ModifierType.SHIFT_MASK:
                        if keyval == Gdk.KEY_Tab:
                            keyval = Gdk.KEY_ISO_Left_Tab
                            mask &= ~Gdk.ModifierType.SHIFT_MASK
                        else:
                            keyvals = Gdk.keyval_convert_case(keyval)
                            if keyvals[0] != keyvals[1]:
                                keyval = keyvals[1]
                                mask &= ~Gdk.ModifierType.SHIFT_MASK
                    else:
                        keyval = Gdk.keyval_to_lower(keyval)
                    self._lookup.setdefault(mask, {})
                    self._lookup[mask][keyval] = action
                    self._masks |= mask
Exemplo n.º 24
0
    def move_tab(self, widget, direction):
        """Handle a keyboard shortcut for moving tab positions"""
        maker = Factory()
        notebook = self.get_child()

        if not maker.isinstance(notebook, 'Notebook'):
            dbg('not in a notebook, refusing to move tab %s' % direction)
            return

        dbg('moving tab %s' % direction)
        numpages = notebook.get_n_pages()
        page = notebook.get_current_page()
        child = notebook.get_nth_page(page)

        if direction == 'left':
            if page == 0:
                page = numpages
            else:
                page = page - 1
        elif direction == 'right':
            if page == numpages - 1:
                page = 0
            else:
                page = page + 1
        else:
            err('unknown direction: %s' % direction)
            return
        
        notebook.reorder_child(child, page)
Exemplo n.º 25
0
 def isinstance(self, product, classtype):
     """Check if a given product is a particular type of object"""
     if classtype in self.types_keys:
         # This is now very ugly, but now it's fast :-)
         # Someone with real Python skills should fix this to be less insane.
         # Optimisations:
         # - swap order of imports, otherwise we throw ImportError
         #   almost every time
         # - cache everything we can
         try:
             type_key = 'terminatorlib.%s' % self.types[classtype]
             if type_key not in self.instance_types_keys:
                 self.instance_types[type_key] = __import__(type_key, None, None, [''])
                 self.instance_types_keys.append(type_key)
             module = self.instance_types[type_key]
         except ImportError:
             type_key = self.types[classtype]
             if type_key not in self.instance_types_keys:
                 self.instance_types[type_key] = __import__(type_key, None, None, [''])
                 self.instance_types_keys.append(type_key)
             module = self.instance_types[type_key]
         return(isinstance(product, getattr(module, classtype)))
     else:
         err('Factory::isinstance: unknown class type: %s' % classtype)
         return(False)
Exemplo n.º 26
0
    def layout_done(self):
        """Layout operations have finished, record that fact"""
        self.doing_layout = False
        maker = Factory()

        window_last_active_term_mapping = {}
        for window in self.windows:
            if window.is_child_notebook():
                source = window.get_toplevel().get_children()[0]
            else:
                source = window
            window_last_active_term_mapping[window] = copy.copy(
                source.last_active_term)

        for terminal in self.terminals:
            if not terminal.pid:
                terminal.spawn_child()

        for window in self.windows:
            if window.is_child_notebook():
                # For windows with a notebook
                notebook = window.get_toplevel().get_children()[0]
                # Cycle through pages by number
                for page in xrange(0, notebook.get_n_pages()):
                    # Try and get the entry in the previously saved mapping
                    mapping = window_last_active_term_mapping[window]
                    page_last_active_term = mapping.get(
                        notebook.get_nth_page(page), None)
                    if page_last_active_term is None:
                        # Couldn't find entry, so we find the first child of type Terminal
                        children = notebook.get_nth_page(page).get_children()
                        for page_last_active_term in children:
                            if maker.isinstance(page_last_active_term,
                                                'Terminal'):
                                page_last_active_term = page_last_active_term.uuid
                                break
                        else:
                            err('Should never reach here!')
                            page_last_active_term = None
                    if page_last_active_term is None:
                        # Bail on this tab as we're having no luck here, continue with the next
                        continue
                    # Set the notebook entry, then ensure Terminal is visible and focussed
                    urn = page_last_active_term.urn
                    notebook.last_active_term[notebook.get_nth_page(
                        page)] = page_last_active_term
                    if urn:
                        term = self.find_terminal_by_uuid(urn)
                        if term:
                            term.ensure_visible_and_focussed()
            else:
                # For windows without a notebook ensure Terminal is visible and focussed
                if window_last_active_term_mapping[window]:
                    term = self.find_terminal_by_uuid(
                        window_last_active_term_mapping[window].urn)
                    term.ensure_visible_and_focussed()

        for window in self.windows:
            if window.uuid == self.last_active_window:
                window.show()
Exemplo n.º 27
0
    def get_visible_terminals(self):
        """Walk down the widget tree to find all of the visible terminals.
        Mostly using Container::get_visible_terminals()"""
        terminals = {}
        if not hasattr(self, 'cached_maker'):
            self.cached_maker = Factory()
        maker = self.cached_maker
        child = self.get_child()

        if not child:
            return ([])

        # If our child is a Notebook, reset to work from its visible child
        if maker.isinstance(child, 'Notebook'):
            pagenum = child.get_current_page()
            child = child.get_nth_page(pagenum)

        if maker.isinstance(child, 'Container'):
            terminals.update(child.get_visible_terminals())
        elif maker.isinstance(child, 'Terminal'):
            terminals[child] = child.get_allocation()
        else:
            err('Unknown child type %s' % type(child))

        return (terminals)
Exemplo n.º 28
0
    def __init__(self, window):
        """Class initialiser"""
        if isinstance(window.get_child(), Gtk.Notebook):
            err('There is already a Notebook at the top of this window')
            raise (ValueError)

        Container.__init__(self)
        GObject.GObject.__init__(self)
        self.terminator = Terminator()
        self.window = window
        GObject.type_register(Notebook)
        self.register_signals(Notebook)
        self.connect('switch-page', self.deferred_on_tab_switch)
        self.connect('scroll-event', self.on_scroll_event)
        self.configure()

        child = window.get_child()
        window.remove(child)
        window.add(self)
        window_last_active_term = window.last_active_term
        self.newtab(widget=child)
        if window_last_active_term:
            self.set_last_active_term(window_last_active_term)
            window.last_active_term = None

        self.show_all()
Exemplo n.º 29
0
    def tab_change(self, widget, num=None):
        """Change to a specific tab"""
        if num is None:
            err('must specify a tab to change to')

        maker = Factory()
        child = self.get_child()

        if not maker.isinstance(child, 'Notebook'):
            dbg('child is not a notebook, nothing to change to')
            return

        if num == -1:
            # Go to the next tab
            cur = child.get_current_page()
            pages = child.get_n_pages()
            if cur == pages - 1:
                num = 0
            else:
                num = cur + 1
        elif num == -2:
            # Go to the previous tab
            cur = child.get_current_page()
            if cur > 0:
                num = cur - 1
            else:
                num = child.get_n_pages() - 1

        child.set_current_page(num)
        # Work around strange bug in gtk-2.12.11 and pygtk-2.12.1
        # Without it, the selection changes, but the displayed page doesn't
        # change
        child.set_current_page(child.get_current_page())
Exemplo n.º 30
0
    def register_callbacks(self):
        """Connect the GTK+ signals we care about"""
        self.connect('key-press-event', self.on_key_press)
        self.connect('button-press-event', self.on_button_press)
        self.connect('delete_event', self.on_delete_event)
        self.connect('destroy', self.on_destroy_event)
        self.connect('window-state-event', self.on_window_state_changed)
        self.connect('focus-out-event', self.on_focus_out)
        self.connect('focus-in-event', self.on_focus_in)

        # Attempt to grab a global hotkey for hiding the window.
        # If we fail, we'll never hide the window, iconifying instead.
        if self.config['keybindings']['hide_window'] != None:
            try:
                self.hidebound = keybinder.bind(
                    self.config['keybindings']['hide_window'],
                    self.on_hide_window)
            except (KeyError, NameError):
                pass

            if not self.hidebound:
                err('Unable to bind hide_window key, another instance/window has it.')
                self.hidefunc = self.iconify
            else:
                self.hidefunc = self.hide
Exemplo n.º 31
0
    def create_layout(self, layout):
        """Apply layout configuration"""
        def child_compare(a, b):
            order_a = children[a]['order']
            order_b = children[b]['order']

            if (order_a == order_b):
                return 0
            if (order_a < order_b):
                return -1
            if (order_a > order_b):
                return 1

        if not layout.has_key('children'):
            err('layout specifies no children: %s' % layout)
            return

        children = layout['children']
        if len(children) <= 1:
            #Notebooks should have two or more children
            err('incorrect number of children for Notebook: %s' % layout)
            return

        num = 0
        keys = children.keys()
        keys.sort(child_compare)

        for child_key in keys:
            child = children[child_key]
            dbg('Making a child of type: %s' % child['type'])
            if child['type'] == 'Terminal':
                pass
            elif child['type'] == 'VPaned':
                page = self.get_nth_page(num)
                self.split_axis(page, True)
            elif child['type'] == 'HPaned':
                page = self.get_nth_page(num)
                self.split_axis(page, False)
            num = num + 1

        num = 0
        for child_key in keys:
            page = self.get_nth_page(num)
            if not page:
                # This page does not yet exist, so make it
                self.newtab(children[child_key])
                page = self.get_nth_page(num)
            if layout.has_key('labels'):
                labeltext = layout['labels'][num]
                if labeltext and labeltext != "None":
                    label = self.get_tab_label(page)
                    label.set_custom_label(labeltext)
            page.create_layout(children[child_key])
            num = num + 1

        if layout.has_key('active_page'):
            self.set_current_page(int(layout['active_page']))
        else:
            self.set_current_page(0)
Exemplo n.º 32
0
 def unload(self):
     """Handle being removed"""
     if not self.match:
         err('unload called without self.handler_name being set')
         return
     terminator = Terminator()
     for terminal in terminator.terminals:
         terminal.match_remove(self.handler_name)
Exemplo n.º 33
0
 def on_css_parsing_error(self, provider, section, error, user_data=None):
     """Report CSS parsing issues"""
     file_path = section.get_file().get_path()
     line_no = section.get_end_line() +1
     col_no = section.get_end_position() + 1
     err('%s, at line %d, column %d, of file %s' % (error.message,
                                                    line_no, col_no,
                                                    file_path))
Exemplo n.º 34
0
 def unload(self):
     """Handle being removed"""
     if not self.match:
         err('unload called without self.handler_name being set')
         return
     terminator = Terminator()
     for terminal in terminator.terminals:
         terminal.match_remove(self.handler_name)
Exemplo n.º 35
0
def proc_get_pid_cwd(pid, path):
    """Extract the cwd of a PID from proc, given the PID and the /proc path to
    insert it into, e.g. /proc/%s/cwd"""
    try:
        cwd = os.path.realpath(path % pid)
    except Exception, ex:
        err('Unable to get cwd for PID %s: %s' % (pid, ex))
        cwd = '/'
Exemplo n.º 36
0
def proc_get_pid_cwd(pid, path):
    """Extract the cwd of a PID from proc, given the PID and the /proc path to
    insert it into, e.g. /proc/%s/cwd"""
    try:
        cwd = os.path.realpath(path % pid)
    except Exception, ex:
        err('Unable to get cwd for PID %s: %s' % (pid, ex))
        cwd = '/'
Exemplo n.º 37
0
    def add(self, widget, metadata=None):
        """Add a widget to the container"""
        if len(self.children) == 0:
            self.pack1(widget, False, True)
            self.children.append(widget)
        elif len(self.children) == 1:
            if self.get_child1():
                self.pack2(widget, False, True)
            else:
                self.pack1(widget, False, True)
            self.children.append(widget)
        else:
            raise ValueError('Paned widgets can only have two children')

        if self.maker.isinstance(widget, 'Terminal'):
            top_window = self.get_toplevel()
            signals = {
                'close-term': self.wrapcloseterm,
                'split-horiz': self.split_horiz,
                'split-vert': self.split_vert,
                'title-change': self.propagate_title_change,
                'resize-term': self.resizeterm,
                'size-allocate': self.new_size,
                'zoom': top_window.zoom,
                'tab-change': top_window.tab_change,
                'group-all': top_window.group_all,
                'group-all-toggle': top_window.group_all_toggle,
                'ungroup-all': top_window.ungroup_all,
                'group-tab': top_window.group_tab,
                'group-tab-toggle': top_window.group_tab_toggle,
                'ungroup-tab': top_window.ungroup_tab,
                'move-tab': top_window.move_tab,
                'maximise': [top_window.zoom, False],
                'tab-new': [top_window.tab_new, widget],
                'navigate': top_window.navigate_terminal,
                'rotate-cw': [top_window.rotate, True],
                'rotate-ccw': [top_window.rotate, False]
            }

            for signal in signals:
                args = []
                handler = signals[signal]
                if isinstance(handler, list):
                    args = handler[1:]
                    handler = handler[0]
                self.connect_child(widget, signal, handler, *args)

            if metadata and \
               metadata.has_key('had_focus') and \
               metadata['had_focus'] == True:
                widget.grab_focus()

        elif isinstance(widget, Gtk.Paned):
            try:
                self.connect_child(widget, 'resize-term', self.resizeterm)
                self.connect_child(widget, 'size-allocate', self.new_size)
            except TypeError:
                err('Paned::add: %s has no signal resize-term' % widget)
Exemplo n.º 38
0
    def split_axis(self,
                   widget,
                   vertical=True,
                   cwd=None,
                   sibling=None,
                   widgetfirst=True):
        """Split the axis of a terminal inside us"""
        dbg('called for widget: %s' % widget)
        order = None
        page_num = self.page_num(widget)
        if page_num == -1:
            err('Notebook::split_axis: %s not found in Notebook' % widget)
            return

        label = self.get_tab_label(widget)
        self.remove(widget)

        maker = Factory()
        if vertical:
            container = maker.make('vpaned')
        else:
            container = maker.make('hpaned')

        self.get_toplevel().set_pos_by_ratio = True

        if not sibling:
            sibling = maker.make('terminal')
            sibling.set_cwd(cwd)
            if self.config['always_split_with_profile']:
                sibling.force_set_profile(None, widget.get_profile())
            sibling.spawn_child()
            if widget.group and self.config['split_to_group']:
                sibling.set_group(None, widget.group)
        elif self.config['always_split_with_profile']:
            sibling.force_set_profile(None, widget.get_profile())

        self.insert_page(container, None, page_num)
        self.child_set_property(container, 'tab-expand', True)
        self.child_set_property(container, 'tab-fill', True)
        self.set_tab_reorderable(container, True)
        self.set_tab_label(container, label)
        self.show_all()

        order = [widget, sibling]
        if widgetfirst is False:
            order.reverse()

        for terminal in order:
            container.add(terminal)
        self.set_current_page(page_num)

        self.show_all()

        while Gtk.events_pending():
            Gtk.main_iteration_do(False)
        self.get_toplevel().set_pos_by_ratio = False

        GObject.idle_add(terminal.ensure_visible_and_focussed)
Exemplo n.º 39
0
 def validate(self):
     credits = sum([self["credits"][c] for c in self["credits"]])
     debits = sum([
         self["debits"][c] for c in self["debits"] if c != "Ending Balance"
     ])
     if credits - debits != self["debits"]["Ending Balance"]:
         u.err(
             "Account Summary credits and debits don't total to ending balance."
         )
Exemplo n.º 40
0
    def update_tab_label_text(self, widget, text):
        """Update the text of a tab label"""
        notebook = self.find_tab_root(widget)
        label = self.get_tab_label(notebook)
        if not label:
            err('Notebook::update_tab_label_text: %s not found' % widget)
            return

        label.set_label(text)
Exemplo n.º 41
0
 def replace(self, oldwidget, newwidget):
     """Replace the child oldwidget with newwidget. This is the bare minimum
     required for this operation. Containers should override it if they have
     more complex requirements"""
     if not oldwidget in self.get_children():
         err('%s is not a child of %s' % (oldwidget, self))
         return
     self.remove(oldwidget)
     self.add(newwidget)
Exemplo n.º 42
0
 def commit_layout_change(self, who, key, value):
     """Update, set dict as dirty"""
     if not self._curlayoutname:
         err('LAYOUT NOT SET')
         return
     dbg('~CHANGE for %s. SET %s to %s [layout:%s]' %
         (who, key, value, self._curlayoutname))
     self.layouts[self._curlayoutname][who][key] = value
     self._dirty = True
Exemplo n.º 43
0
 def replace(self, oldwidget, newwidget):
     """Replace the child oldwidget with newwidget. This is the bare minimum
     required for this operation. Containers should override it if they have
     more complex requirements"""
     if not oldwidget in self.get_children():
         err('%s is not a child of %s' % (oldwidget, self))
         return
     self.remove(oldwidget)
     self.add(newwidget)
Exemplo n.º 44
0
 def update_tab_label_text(self, widget, text):
     """Update the text of a tab label"""
     notebook = self.find_tab_root(widget)
     label = self.get_tab_label(notebook)
     if not label:
         err('Notebook::update_tab_label_text: %s not found' % widget)
         return
     
     label.set_label(text)
Exemplo n.º 45
0
    def add(self, widget, metadata=None):
        """Add a widget to the container"""
        if len(self.children) == 0:
            self.pack1(widget, False, True)
            self.children.append(widget)
        elif len(self.children) == 1:
            if self.get_child1():
                self.pack2(widget, False, True)
            else:
                self.pack1(widget, False, True)
            self.children.append(widget)
        else:
            raise ValueError('Paned widgets can only have two children')

        if self.maker.isinstance(widget, 'Terminal'):
            top_window = self.get_toplevel()
            signals = {'close-term': self.wrapcloseterm,
                    'split-horiz': self.split_horiz,
                    'split-vert': self.split_vert,
                    'title-change': self.propagate_title_change,
                    'resize-term': self.resizeterm,
                    'size-allocate': self.new_size,
                    'zoom': top_window.zoom,
                    'tab-change': top_window.tab_change,
                    'group-all': top_window.group_all,
                    'group-all-toggle': top_window.group_all_toggle,
                    'ungroup-all': top_window.ungroup_all,
                    'group-tab': top_window.group_tab,
                    'group-tab-toggle': top_window.group_tab_toggle,
                    'ungroup-tab': top_window.ungroup_tab,
                    'move-tab': top_window.move_tab,
                    'maximise': [top_window.zoom, False],
                    'tab-new': [top_window.tab_new, widget],
                    'navigate': top_window.navigate_terminal,
                    'rotate-cw': [top_window.rotate, True],
                    'rotate-ccw': [top_window.rotate, False]}

            for signal in signals:
                args = []
                handler = signals[signal]
                if isinstance(handler, list):
                    args = handler[1:]
                    handler = handler[0]
                self.connect_child(widget, signal, handler, *args)

            if metadata and \
               metadata.has_key('had_focus') and \
               metadata['had_focus'] == True:
                    widget.grab_focus()

        elif isinstance(widget, gtk.Paned):
            try:
                self.connect_child(widget, 'resize-term', self.resizeterm)
                self.connect_child(widget, 'size-allocate', self.new_size)
            except TypeError:
                err('Paned::add: %s has no signal resize-term' % widget)
Exemplo n.º 46
0
 def toggle_zoom(self, widget, fontscale=False):
     """Toggle the existing zoom state"""
     try:
         if self.get_property('term_zoomed'):
             self.unzoom(widget)
         else:
             self.zoom(widget, fontscale)
     except TypeError:
         err('Container::toggle_zoom: %s is unable to handle zooming, for \
         %s' % (self, widget))
Exemplo n.º 47
0
    def make(self, product, **kwargs):
        """Make the requested product"""
        try:
            func = getattr(self, 'make_%s' % product.lower())
        except AttributeError:
            err('Factory::make: requested object does not exist: %s' % product)
            return(None)

        dbg('Factory::make: created a %s' % product)
        return(func(**kwargs))
Exemplo n.º 48
0
 def remove(self, widget):
     """Remove a widget from the container"""
     page_num = self.page_num(widget)
     if page_num == -1:
         err('%s not found in Notebook. Actual parent is: %s' % 
                 (widget, widget.get_parent()))
         return(False)
     self.remove_page(page_num)
     self.disconnect_child(widget)
     return(True)
Exemplo n.º 49
0
    def make(self, product, **kwargs):
        """Make the requested product"""
        try:
            func = getattr(self, 'make_%s' % product.lower())
        except AttributeError:
            err('Factory::make: requested object does not exist: %s' % product)
            return (None)

        dbg('Factory::make: created a %s' % product)
        return (func(**kwargs))
Exemplo n.º 50
0
 def remove(self, widget):
     """Remove a widget from the container"""
     page_num = self.page_num(widget)
     if page_num == -1:
         err('%s not found in Notebook. Actual parent is: %s' %
             (widget, widget.get_parent()))
         return (False)
     self.remove_page(page_num)
     self.disconnect_child(widget)
     return (True)
Exemplo n.º 51
0
 def toggle_zoom(self, widget, fontscale = False):
     """Toggle the existing zoom state"""
     try:
         if self.get_property('term_zoomed'):
             self.unzoom(widget)
         else:
             self.zoom(widget, fontscale)
     except TypeError:
         err('Container::toggle_zoom: %s is unable to handle zooming, for \
         %s' % (self, widget))
Exemplo n.º 52
0
    def describe_layout(self, count, parent, global_layout, child_order):
        """Describe our current layout"""
        layout = {}
        maker = Factory()
        mytype = maker.type(self)
        if not mytype:
            err('unable to detemine own type. %s' % self)
            return({})

        layout['type'] = mytype
        layout['parent'] = parent
        layout['order'] = child_order

        if hasattr(self, 'get_position'):
            position = self.get_position()
            if hasattr(position, '__iter__'):
                position = ':'.join([str(x) for x in position])
            layout['position'] = position
        
        if hasattr(self, 'ismaximised'):
            layout['maximised'] = self.ismaximised
        
        if hasattr(self, 'isfullscreen'):
            layout['fullscreen'] = self.isfullscreen
        if hasattr(self, 'ratio'):
            layout['ratio'] = self.ratio

        if hasattr(self, 'get_size'):
            layout['size'] = self.get_size()

        if hasattr(self, 'title'):
            layout['title'] = self.title.text

        labels = []
        if mytype == 'Notebook':
            for tabnum in xrange(0, self.get_n_pages()):
                page = self.get_nth_page(tabnum)
                label = self.get_tab_label(page)
                labels.append(label.get_custom_label())
            layout['active_page'] = self.get_current_page()
        if len(labels) > 0:
            layout['labels'] = labels

        name = 'child%d' % count
        count = count + 1

        global_layout[name] = layout

        child_order = 0
        for child in self.get_children():
            if hasattr(child, 'describe_layout'):
                count = child.describe_layout(count, name, global_layout, child_order)
            child_order = child_order + 1

        return(count)
Exemplo n.º 53
0
    def layout_done(self):
        """Layout operations have finished, record that fact"""
        self.doing_layout = False
        maker = Factory()

        window_last_active_term_mapping = {}
        for window in self.windows:
            if window.is_child_notebook():
                source = window.get_toplevel().get_children()[0]
            else:
                source = window
            window_last_active_term_mapping[window] = copy.copy(source.last_active_term)

        for terminal in self.terminals:
            if not terminal.pid:
                terminal.spawn_child()

        for window in self.windows:
            if window.is_child_notebook():
                # For windows with a notebook
                notebook = window.get_toplevel().get_children()[0]
                # Cycle through pages by number
                for page in xrange(0, notebook.get_n_pages()):
                    # Try and get the entry in the previously saved mapping
                    mapping = window_last_active_term_mapping[window]
                    page_last_active_term = mapping.get(notebook.get_nth_page(page),  None)
                    if page_last_active_term is None:
                        # Couldn't find entry, so we find the first child of type Terminal
                        children = notebook.get_nth_page(page).get_children()
                        for page_last_active_term in children:
                            if maker.isinstance(page_last_active_term, 'Terminal'):
                                page_last_active_term = page_last_active_term.uuid
                                break
                        else:
                            err('Should never reach here!')
                            page_last_active_term = None
                    if page_last_active_term is None:
                        # Bail on this tab as we're having no luck here, continue with the next
                        continue
                    # Set the notebook entry, then ensure Terminal is visible and focussed
                    urn = page_last_active_term.urn
                    notebook.last_active_term[notebook.get_nth_page(page)] = page_last_active_term
                    if urn:
                        term = self.find_terminal_by_uuid(urn)
                        if term:
                            term.ensure_visible_and_focussed()
            else:
                # For windows without a notebook ensure Terminal is visible and focussed
                if window_last_active_term_mapping[window]:
                    term = self.find_terminal_by_uuid(window_last_active_term_mapping[window].urn)
                    term.ensure_visible_and_focussed()

        for window in self.windows:
            if window.uuid == self.last_active_window:
                window.show()
Exemplo n.º 54
0
def log(message):
    "write data to log"
    d = datetime.now()
    try:
        l = open(PATH,'a')
        l.write(d.strftime("%x,%H:%M:%S,")+message+","+"\n")
        l.close()
        return True
    except:
        util.err("Log file unwritable - check that it is not opened by another program",1)
        return False
def get_register(account: Dict[str, Any]) -> Register:
    """Returns a Register class for beancount.

    ACCOUNT is a dict with at least a 'ledger_file' field.

    """

    reg = Register(account)
    if len(reg) == 0:
        u.err("Register is empty of journal entries.")
    return reg
Exemplo n.º 56
0
    def create_layout(self, layout):
        """Apply layout configuration"""
        def child_compare(a, b):
            order_a = children[a]['order']
            order_b = children[b]['order']

            if (order_a == order_b):
                return 0
            if (order_a < order_b):
                return -1
            if (order_a > order_b):
                return 1

        if not layout.has_key('children'):
            err('layout specifies no children: %s' % layout)
            return

        children = layout['children']
        if len(children) <= 1:
            #Notebooks should have two or more children
            err('incorrect number of children for Notebook: %s' % layout)
            return

        num = 0
        keys = children.keys()
        keys.sort(child_compare)

        for child_key in keys:
            child = children[child_key]
            dbg('Making a child of type: %s' % child['type'])
            if child['type'] == 'Terminal':
                pass
            elif child['type'] == 'VPaned':
                page = self.get_nth_page(num)
                self.split_axis(page, True)
            elif child['type'] == 'HPaned':
                page = self.get_nth_page(num)
                self.split_axis(page, False)
            num = num + 1

        num = 0
        for child_key in keys:
            page = self.get_nth_page(num)
            if not page:
                # This page does not yet exist, so make it
                self.newtab(children[child_key])
                page = self.get_nth_page(num)
            if layout.has_key('labels'):
                labeltext = layout['labels'][num]
                if labeltext and labeltext != "None":
                    label = self.get_tab_label(page)
                    label.set_custom_label(labeltext)
            page.create_layout(children[child_key])
            num = num + 1
Exemplo n.º 57
0
 def set_last_active_term(self, uuid):
     """Set the last active term for uuid"""
     widget = self.terminator.find_terminal_by_uuid(uuid.urn)
     if not widget:
         err("Cannot find terminal with uuid: %s, so cannot make it active" % (uuid.urn))
         return
     tabnum = self.page_num_descendant(widget)
     if tabnum == -1:
         err("No tabnum found for terminal with uuid: %s" % (uuid.urn))
         return
     nth_page = self.get_nth_page(tabnum)
     self.last_active_term[nth_page] = uuid
Exemplo n.º 58
0
    def add_profgroup(self):
        """Prepares to add a profgroup.

        Gets some information needed to insert a new profgroup record.
        @param self
        @return group id to insert
        """
        try:
            group_id = self._add_profgroup()
        except KeyError, e:
            util.err("KeyError Occurred in adding a profile group!")
            raise e
Exemplo n.º 59
0
    def new(self, widget, signal, handler, *args):
        """Register a new signal on a widget"""
        if not self.cnxids.has_key(widget):
            dbg("creating new bucket for %s" % type(widget))
            self.cnxids[widget] = {}

        if self.cnxids[widget].has_key(signal):
            err("%s already has a handler for %s" % (id(widget), signal))

        self.cnxids[widget][signal] = widget.connect(signal, handler, *args)
        dbg("connected %s::%s to %s" % (type(widget), signal, handler))
        return self.cnxids[widget][signal]