예제 #1
0
    def run(self):
        debug('translate running...')
        (accessible_window, gdk_window) = active_window()
        if not accessible_window:
            debug('No active window.  Do nothing.')
            return

        debug('active: %s' % accessible_window)

        qingfanyi.styles.init()

        debug('taking snapshot')
        snapshot = Snapshot(accessible_window, gdk_window)

        snapshot_matcher = SnapshotMatcher(snapshot, self.dic)

        debug('creating translate window')
        translate_win = TranslateWindow(snapshot, snapshot_matcher)
        translate_win.show()

        snapshot_matcher.start()

        PopupManager(translate_win)

        # nested loop to make run() blocking
        translate_win.connect('hide', lambda *_: Gtk.main_quit())
        Gtk.main()
예제 #2
0
 def run_in_other_thread(self):
     self.condvar.acquire()
     GLib.idle_add(self.run_in_this_thread)
     self.condvar.wait()
     debug('run in other thread done')
     if self.error:
         raise self.error
예제 #3
0
파일: record.py 프로젝트: rohanpm/qingfanyi
def _pinyin_to_diacritic(word):
    # last character should be the tone
    try:
        tone = int(word[-1])
    except ValueError:
        # must be a special case...
        return word

    w = word[0:-1]

    w = w.replace('u:', u'ü')

    # https://en.wikipedia.org/wiki/Pinyin
    #
    # "the tone mark should always be placed by the order - a, o, e, i, u, ü, with the only exception being iu,
    # where the tone mark is placed on the u instead"
    chars = [u'iu']
    chars.extend([c for c in u'aoeiuü'])
    indexes = [(c, w.lower().find(c)) for c in chars]
    indexes = [(c, i) for (c, i) in indexes if i != -1]
    if not indexes:
        # Weird, a word without vowels?
        debug('vowel-less word? %s' % word)
        return word
    (c, index) = min(indexes, key=lambda (c, i): i)

    dia = _TONE_DIACRITIC[tone]
    offset = len(c)

    w = w[0:index+offset] + dia + w[index+offset:]

    return w
예제 #4
0
파일: wm.py 프로젝트: rohanpm/qingfanyi
 def maybe_fail():
     if attempts <= 0:
         debug(' cannot find active window after several attempts')
         return _guess_active_window()
     debug(' try again to find active window')
     time.sleep(0.1)
     return active_window(attempts - 1)
예제 #5
0
 def accept_match(match):
     # Only accept the match if all of its rects are within our geometry
     for rect in match.rects:
         if not rect_within(self.snapshot.geometry, rect):
             debug('rejecting match outside of window: %s' % match)
             return False
     return True
예제 #6
0
    def _match_next(self):
        if self._stop:
            return False

        matches = []
        out = True

        begin = time.time()

        def should_stop():
            return time.time() - begin > BATCH_TIME

        while True:
            try:
                if self._cursor is None:
                    self._cursor = Cursor(*next(self._texts))
                self._cursor = self._cursor_next(self._cursor, matches)
            except StopIteration:
                debug('no more text to match')
                out = False
                break
            if should_stop():
                break

        self.emit('matches-found', matches)

        return out
예제 #7
0
    def add_matches(self, sender, matches):
        def accept_match(match):
            # Only accept the match if all of its rects are within our geometry
            for rect in match.rects:
                if not rect_within(self.snapshot.geometry, rect):
                    debug('rejecting match outside of window: %s' % match)
                    return False
            return True

        matches = [m for m in matches if accept_match(m)]

        if not matches:
            self.unmatch_count += 1
            # If we previously have found something, and now we repeatedly cannot match
            # anything, then tell the sender to stop - probably it's wasting time
            # processing text far off the screen
            if self.navigator.matches and self.unmatch_count > 5:
                debug(
                    'sender keeps sending offscreen stuff. asking it to stop.')
                sender.stop()
            return

        self.unmatch_count = 0
        self.navigator.add_matches(matches)
        self.update_pixbuf_for_matches(matches)
예제 #8
0
    def add_matches(self, sender, matches):

        def accept_match(match):
            # Only accept the match if all of its rects are within our geometry
            for rect in match.rects:
                if not rect_within(self.snapshot.geometry, rect):
                    debug('rejecting match outside of window: %s' % match)
                    return False
            return True

        matches = filter(accept_match, matches)

        if not matches:
            self.unmatch_count += 1
            # If we previously have found something, and now we repeatedly cannot match
            # anything, then tell the sender to stop - probably it's wasting time
            # processing text far off the screen
            if self.navigator.matches and self.unmatch_count > 5:
                debug('sender keeps sending offscreen stuff. asking it to stop.')
                sender.stop()
            return

        self.unmatch_count = 0
        self.navigator.add_matches(matches)
        self.update_pixbuf_for_matches(matches)
예제 #9
0
 def stop_now(sig, *_):
     stop.append(sig)
     activate_queue.close()
     debug('stop due to signal %s' % sig)
     signal.signal(signal.SIGTERM, signal.SIG_DFL)
     signal.signal(signal.SIGINT, signal.SIG_DFL)
     signal.signal(signal.SIGUSR1, signal.SIG_DFL)
예제 #10
0
def _pinyin_to_diacritic(word):
    # last character should be the tone
    try:
        tone = int(word[-1])
    except ValueError:
        # must be a special case...
        return word

    w = word[0:-1]

    w = w.replace('u:', u'ü')

    # https://en.wikipedia.org/wiki/Pinyin
    #
    # "the tone mark should always be placed by the order - a, o, e, i, u, ü, with the only exception being iu,
    # where the tone mark is placed on the u instead"
    chars = [u'iu']
    chars.extend([c for c in u'aoeiuü'])
    indexes = [(c, w.lower().find(c)) for c in chars]
    indexes = [(c, i) for (c, i) in indexes if i != -1]
    if not indexes:
        # Weird, a word without vowels?
        debug('vowel-less word? %s' % word)
        return word
    (c, index) = min(indexes, key=lambda x: x[1])

    dia = _TONE_DIACRITIC[tone]
    offset = len(c)

    w = w[0:index + offset] + dia + w[index + offset:]

    return w
예제 #11
0
    def __init__(self, parent, match):
        Gtk.Window.__init__(self, Gtk.WindowType.POPUP)

        self.set_name('popup_window')

        # FIXME: any way to do this with CSS?  Can't make it work...
        self.set_border_width(5)

        self.set_size_request(80, -1)

        layout = Gtk.Box.new(Gtk.Orientation.VERTICAL, 4)

        _add_labels(layout, match)

        layout.show()
        self.add(layout)

        # Initially set a position near the match (at least so it's on the right monitor);
        # init_position is expected to make this better later
        (x, y, _, _) = match.rects[0]
        self.move(x, y)

        debug('should popup for %s' % match)

        def do_init_position(*_):
            self.init_position(parent, match)

        self.connect('size-allocate', do_init_position)
예제 #12
0
 def accept_match(match):
     # Only accept the match if all of its rects are within our geometry
     for rect in match.rects:
         if not rect_within(self.snapshot.geometry, rect):
             debug('rejecting match outside of window: %s' % match)
             return False
     return True
예제 #13
0
def _add_labels(layout, match):
    debug('add labels')

    def add(l):
        l.show()
        l.set_alignment(0, 0)
        layout.pack_start(l, True, False, 0)

    # https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat
    text_label = Gtk.Label(match.text)
    text_label.set_name('match')
    add(text_label)

    for record in match.records:
        sep = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
        sep.show()
        layout.pack_start(sep, True, False, 0)

        label = Gtk.Label(record.pinyin)
        label.set_name('main_pinyin')
        add(label)
        for en in record.en_US:
            label = Gtk.Label(u'• %s' % en)
            label.set_name('en_US')
            add(label)
예제 #14
0
def _on_shortcut(event, queue):
    debug('shortcut %s' % event)
    try:
        queue.put_nowait(event)
    except Queue.Full:
        # this means earlier shortcut is still being processed
        debug('  dropped shortcut')
예제 #15
0
    def init_position(self, parent, match):
        self_w = self.get_allocated_width()
        self_h = self.get_allocated_height()

        screen = Gdk.Screen.get_default()
        monitor = screen.get_monitor_at_window(parent.get_window())
        debug('monitor %d' % monitor)
        monitor_rect = screen.get_monitor_geometry(monitor)
        (root_x, root_y, root_w, root_h) = (monitor_rect.x, monitor_rect.y,
                                            monitor_rect.width, monitor_rect.height)
        (mx, my, mw, mh) = match.rects[0]

        def adjust_x(val):
            debug('adjust x %s: root (%s .. %s)' % (val, root_x, root_x + root_w))
            if self_w >= root_w:
                return val
            while val + self_w > root_x + root_w:
                val -= 1
            while val < root_x:
                val += 1
            debug('adjust to %s' % val)
            return val

        # First try below.
        (x, y) = mx + mw/4, my + mh + 3
        if y + self_h < root_y + root_h:
            self.move(adjust_x(x), y)
            return

        # Then above.
        (x, y) = mx + mw/4, my - self_h - 3
        self.move(adjust_x(x), y)
예제 #16
0
def _on_shortcut(event, queue):
    debug('shortcut %s' % event)
    try:
        queue.put_nowait(event)
    except Full:
        # this means earlier shortcut is still being processed
        debug('  dropped shortcut')
예제 #17
0
    def _match_next(self):
        if self._stop:
            return False

        matches = []
        out = True

        begin = time.time()

        def should_stop():
            return time.time() - begin > BATCH_TIME

        while True:
            try:
                if self._cursor is None:
                    self._cursor = Cursor(*self._texts.next())
                self._cursor = self._cursor_next(self._cursor, matches)
            except StopIteration:
                debug('no more text to match')
                out = False
                break
            if should_stop():
                break

        self.emit('matches-found', matches)

        return out
예제 #18
0
    def __init__(self, parent, match):
        Gtk.Window.__init__(self, Gtk.WindowType.POPUP)

        self.set_name('popup_window')

        # FIXME: any way to do this with CSS?  Can't make it work...
        self.set_border_width(5)

        self.set_size_request(80, -1)

        layout = Gtk.Box.new(Gtk.Orientation.VERTICAL, 4)

        _add_labels(layout, match)

        layout.show()
        self.add(layout)

        # Initially set a position near the match (at least so it's on the right monitor);
        # init_position is expected to make this better later
        (x, y, _, _) = match.rects[0]
        self.move(x, y)

        debug('should popup for %s' % match)

        def do_init_position(*_):
            self.init_position(parent, match)

        self.connect('size-allocate', do_init_position)
예제 #19
0
파일: main.py 프로젝트: rohanpm/qingfanyi
 def stop_now(sig, *_):
     stop.append(sig)
     activate_queue.close()
     debug('stop due to signal %s' % sig)
     signal.signal(signal.SIGTERM, signal.SIG_DFL)
     signal.signal(signal.SIGINT, signal.SIG_DFL)
     signal.signal(signal.SIGUSR1, signal.SIG_DFL)
예제 #20
0
    def invert(self, rect):
        (x, y, w, h) = rect
        sub = self.pixbuf.new_subpixbuf(*rect).copy()
        pix = sub.get_pixels()
        alpha = sub.get_has_alpha()
        istride = sub.get_rowstride()
        bytes_per_pixel = 4 if alpha else 3
        ostride = w * bytes_per_pixel
        bytes_total = ostride * h

        npix = bytearray(bytes_total)
        for i in range(h):
            for j in range(0, w * bytes_per_pixel, bytes_per_pixel):
                npix[i * ostride + j] = 255 - ord(pix[i * istride + j])
                npix[i * ostride + j + 1] = 255 - ord(pix[i * istride + j + 1])
                npix[i * ostride + j + 2] = 255 - ord(pix[i * istride + j + 2])
                if alpha:
                    npix[i * ostride + j + 3] = 255

        bytes = GLib.Bytes.new(npix)
        debug('have bytes: %s for rect: %s' % (bytes.get_size(), rect))
        sub = GdkPixbuf.Pixbuf.new_from_bytes(
            bytes,
            GdkPixbuf.Colorspace.RGB,
            alpha,
            8,
            w,
            h,
            ostride
        )
        sub.copy_area(0, 0, w, h, self.pixbuf, x, y)
        self.img.set_from_pixbuf(self.pixbuf)
예제 #21
0
    def init_position(self, parent, match):
        self_w = self.get_allocated_width()
        self_h = self.get_allocated_height()

        screen = Gdk.Screen.get_default()
        monitor = screen.get_monitor_at_window(parent.get_window())
        debug('monitor %d' % monitor)
        monitor_rect = screen.get_monitor_geometry(monitor)
        (root_x, root_y, root_w,
         root_h) = (monitor_rect.x, monitor_rect.y, monitor_rect.width,
                    monitor_rect.height)
        (mx, my, mw, mh) = match.rects[0]

        def adjust_x(val):
            debug('adjust x %s: root (%s .. %s)' %
                  (val, root_x, root_x + root_w))
            if self_w >= root_w:
                return val
            while val + self_w > root_x + root_w:
                val -= 1
            while val < root_x:
                val += 1
            debug('adjust to %s' % val)
            return val

        # First try below.
        (x, y) = mx + mw / 4, my + mh + 3
        if y + self_h < root_y + root_h:
            self.move(adjust_x(x), y)
            return

        # Then above.
        (x, y) = mx + mw / 4, my - self_h - 3
        self.move(adjust_x(x), y)
예제 #22
0
    def run(self):
        debug('translate running...')
        (accessible_window, gdk_window) = active_window()
        if not accessible_window:
            debug('No active window.  Do nothing.')
            return

        debug('active: %s' % accessible_window)

        qingfanyi.styles.init()

        debug('taking snapshot')
        snapshot = Snapshot(accessible_window, gdk_window)

        snapshot_matcher = SnapshotMatcher(snapshot, self.dic)

        debug('creating translate window')
        translate_win = TranslateWindow(snapshot, snapshot_matcher)
        translate_win.show()

        snapshot_matcher.start()

        PopupManager(translate_win)

        # nested loop to make run() blocking
        translate_win.connect('hide', lambda *_: Gtk.main_quit())
        Gtk.main()
예제 #23
0
    def invert(self, rect):
        (x, y, w, h) = rect
        sub = self.pixbuf.new_subpixbuf(*rect).copy()
        pix = sub.get_pixels()
        alpha = sub.get_has_alpha()
        istride = sub.get_rowstride()
        bytes_per_pixel = 4 if alpha else 3
        ostride = w * bytes_per_pixel
        bytes_total = ostride * h

        npix = bytearray(bytes_total)
        for i in range(h):
            for j in range(0, w * bytes_per_pixel, bytes_per_pixel):
                npix[i * ostride + j] = 255 - pix[i * istride + j]
                npix[i * ostride + j + 1] = 255 - pix[i * istride + j + 1]
                npix[i * ostride + j + 2] = 255 - pix[i * istride + j + 2]
                if alpha:
                    npix[i * ostride + j + 3] = 255

        bytes = GLib.Bytes.new(npix)
        debug('have bytes: %s for rect: %s' % (bytes.get_size(), rect))
        sub = GdkPixbuf.Pixbuf.new_from_bytes(bytes, GdkPixbuf.Colorspace.RGB,
                                              alpha, 8, w, h, ostride)
        sub.copy_area(0, 0, w, h, self.pixbuf, x, y)
        self.img.set_from_pixbuf(self.pixbuf)
예제 #24
0
 def maybe_fail():
     if attempts <= 0:
         debug(' cannot find active window after several attempts')
         return _guess_active_window()
     debug(' try again to find active window')
     time.sleep(0.1)
     return active_window(attempts - 1)
예제 #25
0
 def run_in_other_thread(self):
     self.condvar.acquire()
     GLib.idle_add(self.run_in_this_thread)
     self.condvar.wait()
     debug('run in other thread done')
     if self.error:
         raise self.error
예제 #26
0
파일: main.py 프로젝트: rohanpm/qingfanyi
def _start_keybind_process(queue):
    debug('keybind process starting')
    import qingfanyi.process.keybind
    try:
        qingfanyi.process.keybind.run(queue)
    except:
        os.kill(os.getppid(), signal.SIGUSR1)
        raise
예제 #27
0
파일: wm.py 프로젝트: rohanpm/qingfanyi
def _atspi_windows():
    desktop = pyatspi.Registry.getDesktop(0)
    for app in desktop:
        try:
            for window in app:
                yield window
        except GLib.Error as e:
            debug('error from app %s: %s' % (app, e))
예제 #28
0
def _atspi_windows():
    desktop = pyatspi.Registry.getDesktop(0)
    for app in desktop:
        try:
            for window in app:
                yield window
        except GLib.Error as e:
            debug('error from app %s: %s' % (app, e))
예제 #29
0
def _start_keybind_process(queue):
    debug('keybind process starting')
    import qingfanyi.process.keybind
    try:
        qingfanyi.process.keybind.run(queue)
    except:
        os.kill(os.getppid(), signal.SIGUSR1)
        raise
예제 #30
0
    def on_current_match_changed(self, _sender, prev_match, match):
        debug('match has changed from %s to %s' % (prev_match, match))

        if prev_match:
            self.invert_for_match(prev_match)

        if match:
            self.invert_for_match(match)
            self.emit('lookup-requested', match)
예제 #31
0
    def on_current_match_changed(self, _sender, prev_match, match):
        debug('match has changed from %s to %s' % (prev_match, match))

        if prev_match:
            self.invert_for_match(prev_match)

        if match:
            self.invert_for_match(match)
            self.emit('lookup-requested', match)
예제 #32
0
    def step(self):
        self.index -= 1
        while not may_contain_chinese(self.current_text[0]) and not self.finished:
            self.index -= 1
        if self.finished:
            return

        extents = self.text_object.getCharacterExtents(self.index, 0)
        debug('get rect for index %d == %s' % (self.index, extents))
        self.rects[self.index] = extents
예제 #33
0
def _atspi_active_windows():
    """
    :return: all windows AT-SPI claims are active (there can be more than one)
    """
    for window in _atspi_windows():
        state = window.getState()
        debug('  window %s state %s' % (window, state.states))
        if state.contains(pyatspi.STATE_ACTIVE):
            debug('    ACTIVE')
            yield window
예제 #34
0
 def adjust_x(val):
     debug('adjust x %s: root (%s .. %s)' % (val, root_x, root_x + root_w))
     if self_w >= root_w:
         return val
     while val + self_w > root_x + root_w:
         val -= 1
     while val < root_x:
         val += 1
     debug('adjust to %s' % val)
     return val
예제 #35
0
파일: wm.py 프로젝트: rohanpm/qingfanyi
def _atspi_active_windows():
    """
    :return: all windows AT-SPI claims are active (there can be more than one)
    """
    for window in _atspi_windows():
        state = window.getState()
        debug('  window %s state %s' % (window, state.states))
        if state.contains(pyatspi.STATE_ACTIVE):
            debug('    ACTIVE')
            yield window
예제 #36
0
 def adjust_x(val):
     debug('adjust x %s: root (%s .. %s)' %
           (val, root_x, root_x + root_w))
     if self_w >= root_w:
         return val
     while val + self_w > root_x + root_w:
         val -= 1
     while val < root_x:
         val += 1
     debug('adjust to %s' % val)
     return val
예제 #37
0
    def step(self):
        self.index -= 1
        while not may_contain_chinese(
                self.current_text[0]) and not self.finished:
            self.index -= 1
        if self.finished:
            return

        extents = self.text_object.getCharacterExtents(self.index, 0)
        debug('get rect for index %d == %s' % (self.index, extents))
        self.rects[self.index] = extents
예제 #38
0
    def __init__(self, accessible_window, gdk_window):
        (_, _, w, h) = gdk_window.get_geometry()
        (_, x, y) = gdk_window.get_origin()

        self.geometry = (x, y, w, h)
        debug('taking snapshot of %s' % gdk_window)
        self.pixbuf = Gdk.pixbuf_get_from_window(gdk_window, 0, 0, w, h)
        if not self.pixbuf:
            raise IOError('Could not get pixbuf from active window')

        self.accessible_window = accessible_window
        self.texts = _extract_texts(accessible_window)
예제 #39
0
    def collect_chinese(accessible_object, _):
        text_object = get_text_object(accessible_object)
        if not text_object:
            return

        text = text_object.getText(0, -1)
        # NOTE: what if app is not using utf-8?
        debug('TEXT: %s' % text)
        if not may_contain_chinese(text):
            return

        out.append((text, text_object, accessible_object))
예제 #40
0
    def __init__(self, accessible_window, gdk_window):
        (_, _, w, h) = gdk_window.get_geometry()
        (_, x, y) = gdk_window.get_origin()

        self.geometry = (x, y, w, h)
        debug('taking snapshot of %s' % gdk_window)
        self.pixbuf = Gdk.pixbuf_get_from_window(gdk_window, 0, 0, w, h)
        if not self.pixbuf:
            raise IOError('Could not get pixbuf from active window')

        self.accessible_window = accessible_window
        self.texts = _extract_texts(accessible_window)
예제 #41
0
    def collect_chinese(accessible_object, _):
        text_object = get_text_object(accessible_object)
        if not text_object:
            return

        text = text_object.getText(0, -1)
        # NOTE: what if app is not using utf-8?
        text = unicode(text, 'utf-8')
        debug('TEXT: %s' % text)
        if not may_contain_chinese(text):
            return

        out.append((text, text_object, accessible_object))
예제 #42
0
    def on_key_pressed(self, widget, event):
        debug('key pressed: %s' % ((event.keyval, event.string),))

        key = event.keyval
        if key == Gdk.KEY_Left:
            self.navigator.navigate_offset(-1)
        elif key == Gdk.KEY_Right:
            self.navigator.navigate_offset(1)
        elif key == Gdk.KEY_Up:
            self.navigator.navigate_offset(-len(self.matches) / 10)
        elif key == Gdk.KEY_Down:
            self.navigator.navigate_offset(len(self.matches) / 10)
        elif event.string:
            self.destroy()
예제 #43
0
    def from_line(line):
        out = Record()
        m = Record._CEDICT_PATTERN.match(line)

        if not m:
            raise ValueError("Not a valid CEDICT-formatted record: %s" % line)

        out.zh_TW = m.group(1)
        out.zh_CN = m.group(2)
        out.pinyin_num = m.group(3)
        out.en_US_num = m.group(4).split('/')
        debug('type of en_US_num: %s' % type(out.en_US_num[0]))

        return out
예제 #44
0
파일: record.py 프로젝트: rohanpm/qingfanyi
    def from_line(line):
        out = Record()
        m = Record._CEDICT_PATTERN.match(line)

        if not m:
            raise ValueError("Not a valid CEDICT-formatted record: %s" % line)

        out.zh_TW = m.group(1)
        out.zh_CN = m.group(2)
        out.pinyin_num = m.group(3)
        out.en_US_num = m.group(4).split('/')
        debug('type of en_US_num: %s' % type(out.en_US_num[0]))

        return out
예제 #45
0
def ensure_index_built(index_filename=qingfanyi.dict.INDEX_FILENAME,
                       dict_filename=qingfanyi.dict.DICT_FILENAME):
    if os.path.exists(index_filename):
        debug('Index is already built.')
        return

    print('Building index on first use.')

    resource_name = 'data/cedict_1_0_ts_utf-8_mdbg.txt'
    stream = resource_stream('qingfanyi', resource_name)
    assert stream
    build(resource_name, stream, logger=print,
          out_dict_filename=dict_filename,
          out_index_filename=index_filename)
예제 #46
0
    def _cursor_next(self, cursor, matches):
        cursor.step()
        text = cursor.current_text
        debug('cursor idx %d, match text: %s' % (cursor.index, text))
        if cursor.finished:
            return

        prefixes = self._dic.prefixes(text)
        for pref in prefixes:
            debug('prefix: %s' % pref)
            records = self._dic[pref]
            rects = cursor.current_rects(len(pref))
            rects = join_rects(rects)
            matches.append(Match(pref, records, rects))

        return cursor
예제 #47
0
    def on_key_pressed(self, widget, event):
        debug('key pressed: %s' % ((event.keyval, event.string), ))

        key = event.keyval
        if key == Gdk.KEY_Left:
            self.navigator.navigate_offset(-1)
        elif key == Gdk.KEY_Right:
            self.navigator.navigate_offset(1)
        elif key == Gdk.KEY_Up:
            self.navigator.navigate_offset(
                int(-len(self.navigator.matches) / 10))
        elif key == Gdk.KEY_Down:
            self.navigator.navigate_offset(
                int(len(self.navigator.matches) / 10))
        elif event.string:
            self.destroy()
예제 #48
0
def ensure_index_built(index_filename=qingfanyi.dict.INDEX_FILENAME,
                       dict_filename=qingfanyi.dict.DICT_FILENAME):
    if os.path.exists(index_filename):
        debug('Index is already built.')
        return

    print('Building index on first use.')

    resource_name = 'data/cedict_1_0_ts_utf-8_mdbg.txt'
    stream = resource_stream('qingfanyi', resource_name)
    assert stream
    build(resource_name,
          stream,
          logger=print,
          out_dict_filename=dict_filename,
          out_index_filename=index_filename)
예제 #49
0
    def _cursor_next(self, cursor, matches):
        cursor.step()
        text = cursor.current_text
        debug('cursor idx %d, match text: %s' % (cursor.index,
                                                 text))
        if cursor.finished:
            return

        prefixes = self._dic.prefixes(text)
        for pref in prefixes:
            debug('prefix: %s' % pref)
            records = self._dic[pref]
            rects = cursor.current_rects(len(pref))
            rects = join_rects(rects)
            matches.append(Match(pref, records, rects))

        return cursor
예제 #50
0
파일: main.py 프로젝트: rohanpm/qingfanyi
def run():
    ensure_index_built()

    activate_queue = Queue(1)
    keybind_process = Process(target=_start_keybind_process, args=(activate_queue,))
    keybind_process.start()

    translate_pool = Pool(processes=1, initializer=_init_translate_process,
                          maxtasksperchild=1)

    stop = []

    def stop_now(sig, *_):
        stop.append(sig)
        activate_queue.close()
        debug('stop due to signal %s' % sig)
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGUSR1, signal.SIG_DFL)

    signal.signal(signal.SIGTERM, stop_now)
    signal.signal(signal.SIGINT, stop_now)
    signal.signal(signal.SIGUSR1, stop_now)

    while not stop:
        got = None
        try:
            got = activate_queue.get()
        except:
            if not stop:
                raise
        debug('parent got: %s' % got)

        if not got:
            break

        debug('invoke translate')
        try:
            translate_pool.apply(_run_translate_process)
        except StandardError as e:
            debug('failed: %s' % e)

    if stop[0] == signal.SIGUSR1:
        # keybind child signaled an error
        keybind_process.join(10)
        os._exit(7)

    debug('exiting normally')
    keybind_process.terminate()

    # FIXME: this always hangs.  Why?
    # That's why we use _exit instead.
    #translate_pool.terminate()

    os._exit(0)
예제 #51
0
def run():
    ensure_index_built()

    activate_queue = Queue(1)
    keybind_process = Process(target=_start_keybind_process, args=(activate_queue,))
    keybind_process.start()

    translate_pool = Pool(processes=1, initializer=_init_translate_process,
                          maxtasksperchild=1)

    stop = []

    def stop_now(sig, *_):
        stop.append(sig)
        activate_queue.close()
        debug('stop due to signal %s' % sig)
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGUSR1, signal.SIG_DFL)

    signal.signal(signal.SIGTERM, stop_now)
    signal.signal(signal.SIGINT, stop_now)
    signal.signal(signal.SIGUSR1, stop_now)

    while not stop:
        got = None
        try:
            got = activate_queue.get()
        except:
            if not stop:
                raise
        debug('parent got: %s' % got)

        if not got:
            break

        debug('invoke translate')
        try:
            translate_pool.apply(_run_translate_process)
        except Exception as e:
            debug('failed: %s' % e)

    if stop[0] == signal.SIGUSR1:
        # keybind child signaled an error
        keybind_process.join(10)
        os._exit(7)

    debug('exiting normally')
    keybind_process.terminate()

    # FIXME: this always hangs.  Why?
    # That's why we use _exit instead.
    #translate_pool.terminate()

    os._exit(0)
예제 #52
0
def visit_visible(root, callback, level=0):
    """
    Visit every visible object in a hierarchy and invoke a provided callback.

    :param root: an AtSpi.Accessible object
    :param callback: invoked for each visible object with two parameters: the object,
                     and the distance from root (e.g. 0 == root, 1 == child of root,
                     2 == grandchild ...)
    """
    debug('%s%s' % ('  ' * level, root))
    if not _is_showing(root):
        debug('%s PRUNE' % ('  ' * level))
        return

    callback(root, level)

    for child in root:
        visit_visible(child, callback, level + 1)
예제 #53
0
파일: geom.py 프로젝트: rohanpm/qingfanyi
def join_rects(rects):
    """
    Given a list of rects for character extents, which must be ordered left-to-right
    and top-to-bottom, attempts to return a smaller list of larger rects covering the
    same area.

    Rects will be joined left-to-right, but not top-to-bottom, i.e. rects will not be
    extended over a line break.

    For example, if given rects for text like this:

       你好吗

    ... the 3 rects for each character will be joined to 1, but if given rects for
    text like this:

       你好
       吗

    ... the 3 rects for each character will be joined to 1 for the first line and 1
    for the second line, returning 2 rects total, neither spanning the line break.
    """
    i = 0
    end = len(rects)
    out = []
    current_rect = None

    while i < end:
        this_rect = rects[i]
        debug('index %d rect %s' % (i, this_rect))
        if current_rect:
            # Can we extend the current_rect to cover this_rect without increasing
            # its height?
            (curr_x, curr_y, curr_w, curr_h) = current_rect
            (this_x, this_y, this_w, this_h) = this_rect

            if curr_y == this_y and curr_h == this_h:
                # Yes. Keep extending current rect.
                debug('  extending')
                current_rect = rect_extend(current_rect, this_rect)
            else:
                # No. Save current rect and start a new one.
                debug('  new rect')
                out.append(current_rect)
                current_rect = this_rect
        else:
            current_rect = this_rect
        i += 1

    debug('  end')
    out.append(current_rect)

    return out
예제 #54
0
def join_rects(rects):
    """
    Given a list of rects for character extents, which must be ordered left-to-right
    and top-to-bottom, attempts to return a smaller list of larger rects covering the
    same area.

    Rects will be joined left-to-right, but not top-to-bottom, i.e. rects will not be
    extended over a line break.

    For example, if given rects for text like this:

       你好吗

    ... the 3 rects for each character will be joined to 1, but if given rects for
    text like this:

       你好
       吗

    ... the 3 rects for each character will be joined to 1 for the first line and 1
    for the second line, returning 2 rects total, neither spanning the line break.
    """
    i = 0
    end = len(rects)
    out = []
    current_rect = None

    while i < end:
        this_rect = rects[i]
        debug('index %d rect %s' % (i, this_rect))
        if current_rect:
            # Can we extend the current_rect to cover this_rect without increasing
            # its height?
            (curr_x, curr_y, curr_w, curr_h) = current_rect
            (this_x, this_y, this_w, this_h) = this_rect

            if curr_y == this_y and curr_h == this_h:
                # Yes. Keep extending current rect.
                debug('  extending')
                current_rect = rect_extend(current_rect, this_rect)
            else:
                # No. Save current rect and start a new one.
                debug('  new rect')
                out.append(current_rect)
                current_rect = this_rect
        else:
            current_rect = this_rect
        i += 1

    debug('  end')
    out.append(current_rect)

    return out
예제 #55
0
    def add_matches(self, matches):
        debug('BEGIN add %d matches' % len(matches))

        # Retain the current match if there is one.
        current = self.current_match

        self.matches.extend(matches)
        self.matches.sort(key=_match_sort_key)

        if current:
            # Update current_match_index to new correct value.
            # It could be anywhere from its previous value up to +len(matches).
            for i in range(self.current_match_index,
                           self.current_match_index + len(matches) + 1):
                if self.matches[i] is current:
                    self.current_match_index = i
                    break

        debug('END add matches')

        pass
예제 #56
0
    def add_matches(self, matches):
        debug('BEGIN add %d matches' % len(matches))

        # Retain the current match if there is one.
        current = self.current_match

        self.matches.extend(matches)
        self.matches.sort(key=_match_sort_key)

        if current:
            # Update current_match_index to new correct value.
            # It could be anywhere from its previous value up to +len(matches).
            for i in range(self.current_match_index,
                           self.current_match_index + len(matches) + 1):
                if self.matches[i] is current:
                    self.current_match_index = i
                    break

        debug('END add matches')

        pass
예제 #57
0
    def update_pixbuf_for_matches(self, matches):
        debug('BEGIN redraw...')

        (window_x, window_y, width, height) = self.snapshot.geometry

        copy_pb = []

        current_match = self.navigator.current_match
        # Note: could improve to only process current_match if it overlaps.
        # But time savings are probably negligible.
        if current_match:
            matches.append(current_match)

        for m in matches:
            for (x, y, w, h) in m.rects:
                x -= window_x
                y -= window_y
                rect = (x, y, w, h)
                sub = self.snapshot.pixbuf.new_subpixbuf(*rect)
                if sub:
                    sub = sub.copy()
                    copy_pb.append((sub, rect))

        for (pb, rect) in copy_pb:
            (x, y, w, h) = rect
            pb.copy_area(0, 0, w, h, self.pixbuf, x, y)

        if current_match:
            debug('inverting current match - %s' % current_match)
            self.invert_for_match(current_match)

        self.img.set_from_pixbuf(self.pixbuf)

        debug('END redraw')
예제 #58
0
    def update_pixbuf_for_matches(self, matches):
        debug('BEGIN redraw...')

        (window_x, window_y, width, height) = self.snapshot.geometry

        copy_pb = []

        current_match = self.navigator.current_match
        # Note: could improve to only process current_match if it overlaps.
        # But time savings are probably negligible.
        if current_match:
            matches.append(current_match)

        for m in matches:
            for (x, y, w, h) in m.rects:
                x -= window_x
                y -= window_y
                rect = (x, y, w, h)
                sub = self.snapshot.pixbuf.new_subpixbuf(*rect)
                if sub:
                    sub = sub.copy()
                    copy_pb.append((sub, rect))

        for (pb, rect) in copy_pb:
            (x, y, w, h) = rect
            pb.copy_area(0, 0, w, h, self.pixbuf, x, y)

        if current_match:
            debug('inverting current match - %s' % current_match)
            self.invert_for_match(current_match)

        self.img.set_from_pixbuf(self.pixbuf)

        debug('END redraw')
예제 #59
0
    def navigate_offset(self, offset):
        if not self.matches:
            return

        idx = prev_idx = self.current_match_index
        if idx is None:
            if offset == 1:
                idx = 0
            else:
                idx = -1
        else:
            idx += offset

        size = len(self.matches)
        while idx >= size:
            idx -= size
        while idx < 0:
            idx += size

        debug('navigate from %s by %s gives %s' % (prev_idx, offset, idx))

        self.set_current_match(idx, self.matches[idx])