📄 filediff.py
字号:
self.textview[i].set_tabs(tabs) for i in range(2): self.linkmap[i].queue_draw() load = lambda x: gnomeglade.load_pixbuf( paths.share_dir("glade2/pixmaps/"+x), self.pixels_per_line) self.pixbuf_apply0 = load("button_apply0.xpm") self.pixbuf_apply1 = load("button_apply1.xpm") self.pixbuf_delete = load("button_delete.xpm") self.pixbuf_copy0 = load("button_copy0.xpm") self.pixbuf_copy1 = load("button_copy1.xpm") def on_preference_changed(self, key, value): if key == "draw_style": for l in self.linkmap: l.queue_draw() elif key == "tab_size": tabs = pango.TabArray(10, 0) for i in range(10): tabs.set_tab(i, pango.TAB_LEFT, i*value*self.pango_char_width) for i in range(3): self.textview[i].set_tabs(tabs) elif key == "use_custom_font" or key == "custom_font": self.load_font() elif key == "show_line_numbers": if sourceview_available: for t in self.textview: t.set_show_line_numbers( value ) elif key == "use_syntax_highlighting": if sourceview_available: for i in range(self.num_panes): set_highlighting_enabled( self.textview[i].get_buffer(), self.bufferdata[i].filename, self.prefs.use_syntax_highlighting ) elif key == "regexes": self._update_regexes() elif key == "edit_wrap_lines": [t.set_wrap_mode( self.prefs.edit_wrap_lines ) for t in self.textview] def on_key_press_event(self, object, event): x = self.keylookup.get(event.keyval, 0) if self.keymask | x != self.keymask: self.keymask |= x for l in self.linkmap[:self.num_panes-1]: a = l.get_allocation() w = self.pixbuf_copy0.get_width() l.queue_draw_area(0, 0, w, a[3]) l.queue_draw_area(a[2]-w, 0, w, a[3]) def on_key_release_event(self, object, event): x = self.keylookup.get(event.keyval, 0) if self.keymask & ~x != self.keymask: self.keymask &= ~x for l in self.linkmap[:self.num_panes-1]: a = l.get_allocation() w = self.pixbuf_copy0.get_width() l.queue_draw_area(0, 0, w, a[3]) l.queue_draw_area(a[2]-w, 0, w, a[3]) def is_modified(self): state = [b.modified for b in self.bufferdata] return 1 in state def _get_pane_label(self, i): return self.bufferdata[i].label or "<unnamed>" def on_delete_event(self, appquit=0): response = gtk.RESPONSE_OK modified = [b.modified for b in self.bufferdata] if 1 in modified: dialog = gnomeglade.Component( paths.share_dir("glade2/filediff.glade"), "closedialog") dialog.widget.set_transient_for(self.widget.get_toplevel()) buttons = [] for i in range(self.num_panes): b = gtk.CheckButton( self._get_pane_label(i) ) b.set_use_underline(False) buttons.append(b) dialog.box.pack_start(b, 1, 1) if not modified[i]: b.set_sensitive(0) else: b.set_active(1) dialog.box.show_all() response = dialog.widget.run() try_save = [ b.get_active() for b in buttons] dialog.widget.destroy() if response==gtk.RESPONSE_OK: for i in range(self.num_panes): if try_save[i]: if self.save_file(i) != melddoc.RESULT_OK: return gtk.RESPONSE_CANCEL return response # # text buffer undo/redo # def on_text_begin_user_action(self, *buffer): self.undosequence.begin_group() def on_text_end_user_action(self, *buffer): self.undosequence.end_group() def on_text_insert_text(self, buffer, it, text, textlen): if not self.undosequence_busy: self.undosequence.begin_group() pane = self.textview.index( buffer.textview ) if self.bufferdata[pane].modified != 1: self.undosequence.add_action( BufferModifiedAction(buffer, self) ) self.undosequence.add_action( BufferInsertionAction(buffer, it.get_offset(), text) ) self.undosequence.end_group() def on_text_delete_range(self, buffer, it0, it1): text = buffer.get_text(it0, it1, 0) pane = self.textview.index(buffer.textview) assert self.deleted_lines_pending == -1 self.deleted_lines_pending = text.count("\n") if not self.undosequence_busy: self.undosequence.begin_group() if self.bufferdata[pane].modified != 1: self.undosequence.add_action( BufferModifiedAction(buffer, self) ) self.undosequence.add_action( BufferDeletionAction(buffer, it0.get_offset(), text) ) self.undosequence.end_group() # # # def _get_focused_textview(self): for i in range(self.num_panes): t = self.textview[i] if t.is_focus(): return t return None def on_find_activate(self, *args): self.keymask = 0 self.queue_draw() if self.find_dialog: self.find_dialog.widget.present() else: class FindDialog(gnomeglade.Component): def __init__(self, app): self.parent = app self.pane = -1 gladefile = paths.share_dir("glade2/filediff.glade") gnomeglade.Component.__init__(self, gladefile, "finddialog") self.widget.set_transient_for(app.widget.get_toplevel()) self.widget.show_all() def on_destroy(self, *args): self.parent.find_dialog = None self.widget.destroy() def on_entry_search_for_activate(self, *args): self.parent._find_text( self.entry_search_for.get_chars(0,-1), self.check_case.get_active(), self.check_word.get_active(), self.check_wrap.get_active(), self.check_regex.get_active() ) return 1 self.find_dialog = FindDialog(self) def on_find_next_activate(self, *args): if self.last_search: s = self.last_search self._find_text(s.text, s.case, s.word, s.wrap, s.regex) else: self.on_find_activate() def on_copy_activate(self, *extra): t = self._get_focused_textview() if t: t.emit("copy-clipboard") #XXX .get_buffer().copy_clipboard() def on_cut_activate(self, *extra): t = self._get_focused_textview() if t: t.emit("cut-clipboard") #XXX get_buffer().cut_clipboard() def on_paste_activate(self, *extra): t = self._get_focused_textview() if t: t.emit("paste-clipboard") #XXX t.get_buffer().paste_clipboard(None, 1) def on_textview_button_press_event(self, textview, event): if event.button == 3: textview.grab_focus() pane = self.textview.index(textview) self.popup_menu.popup_in_pane( pane ) return 1 return 0 def on_textview_toggle_overwrite(self, view): self.textview_overwrite = not self.textview_overwrite for v,h in zip(self.textview, self.textview_overwrite_handlers): v.disconnect(h) if v != view: v.emit("toggle-overwrite") self.textview_overwrite_handlers = [ t.connect("toggle-overwrite", self.on_textview_toggle_overwrite) for t in self.textview ] self._update_cursor_status(view.get_buffer()) # # find/replace buffer # def _find_text(self, tofind_utf8, match_case=0, entire_word=0, wrap=1, regex=0): self.last_search = misc.struct(text=tofind_utf8, case=match_case, word=entire_word, wrap=wrap, regex=regex) view = self._get_focused_textview() or self.textview0 buf = view.get_buffer() insert = buf.get_iter_at_mark( buf.get_insert() ) tofind = tofind_utf8.decode("utf-8") # tofind is utf-8 encoded text = buf.get_text(*buf.get_bounds() ).decode("utf-8") # as is buffer if not regex: tofind = re.escape(tofind) if entire_word: tofind = r'\b' + tofind + r'\b' try: pattern = re.compile( tofind, (match_case and re.M or (re.M|re.I)) ) except re.error, e: misc.run_dialog( _("Regular expression error\n'%s'") % e, self, messagetype=gtk.MESSAGE_ERROR) else: match = pattern.search(text, insert.get_offset()+1) if match == None and wrap: match = pattern.search(text, 0) if match: it = buf.get_iter_at_offset( match.start() ) buf.place_cursor( it ) it.forward_chars( match.end() - match.start() ) buf.move_mark( buf.get_selection_bound(), it ) view.scroll_to_mark( buf.get_insert(), 0) elif regex: misc.run_dialog( _("The regular expression '%s' was not found.") % tofind_utf8, self, messagetype=gtk.MESSAGE_INFO) else: misc.run_dialog( _("The text '%s' was not found.") % tofind_utf8, self, messagetype=gtk.MESSAGE_INFO) # # text buffer loading/saving # def set_labels(self, lst): assert len(lst) <= len(self.bufferdata) for l,d in zip(lst,self.bufferdata): if len(l): d.label = l def recompute_label(self): filenames = [] for i in range(self.num_panes): filenames.append( self._get_pane_label(i) ) shortnames = misc.shorten_names(*filenames) for i in range(self.num_panes): stock = None if self.bufferdata[i].modified == 1: shortnames[i] += "*" if self.bufferdata[i].writable == 1: stock = gtk.STOCK_SAVE else: stock = gtk.STOCK_SAVE_AS elif self.bufferdata[i].writable == 0: stock = gtk.STOCK_NO if stock: self.statusimage[i].show() self.statusimage[i].set_from_stock(stock, gtk.ICON_SIZE_SMALL_TOOLBAR) else: self.statusimage[i].hide() self.label_text = " : ".join(shortnames) self.label_changed() def set_files(self, files): """Set num panes to len(files) and load each file given. If an element is None, the text of a pane is left as is. """ for i,f in enumerate(files): if f: b = self.textview[i].get_buffer() b.delete( b.get_start_iter(), b.get_end_iter() ) absfile = os.path.abspath(f) self.fileentry[i].set_filename(absfile) bold, bnew = self.bufferdata[i], MeldBufferData(absfile) if bold.filename == bnew.filename: bnew.label = bold.label self.bufferdata[i] = bnew self.recompute_label() self.scheduler.add_task( self._set_files_internal(files).next ) self.scheduler.add_task( lambda: self.next_diff(gdk.SCROLL_DOWN), True ) def _set_files_internal(self, files): yield _("[%s] Set num panes") % self.label_text self.set_num_panes( len(files) ) self._disconnect_buffer_handlers() self.linediffer.diffs = [[],[]] self.queue_draw() buffers = [t.get_buffer() for t in self.textview][:self.num_panes]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -