📄 meldapp.py
字号:
### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org>### This program is free software; you can redistribute it and/or modify### it under the terms of the GNU General Public License as published by### the Free Software Foundation; either version 2 of the License, or### (at your option) any later version.### This program is distributed in the hope that it will be useful,### but WITHOUT ANY WARRANTY; without even the implied warranty of### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the### GNU General Public License for more details.### You should have received a copy of the GNU General Public License### along with this program; if not, write to the Free Software### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA# systemimport sysimport os# gnomeimport gtkimport gtk.gladeimport gobject# projectimport pathsimport prefsimport gnomegladeimport miscimport filediffimport vcviewimport dirdiffimport task# optionalsourceview_available = 0for sourceview in "gtksourceview sourceview".split(): try: __import__(sourceview) sourceview_available = 1 break except ImportError: passversion = "1.1.4"# magic developer switch, changes some behaviourdeveloper = 0################################################################################## NewDocDialog#################################################################################class NewDocDialog(gnomeglade.Component): TYPE = misc.struct(DIFF2=0, DIFF3=1, DIR2=2, DIR3=3, VC=4) def __init__(self, parentapp, type): self.parentapp = parentapp gnomeglade.Component.__init__(self, paths.share_dir("glade2/meldapp.glade"), "newdialog") self._map_widgets_into_lists( ("fileentry", "direntry", "vcentry", "three_way_compare", "tablabel") ) self.entrylists = self.fileentry, self.direntry, self.vcentry self.widget.set_transient_for(parentapp.widget) cur_page = type // 2 self.notebook.set_current_page( cur_page ) self.widget.show_all() def on_entry_activate(self, entry): for el in self.entrylists: if entry in el: i = el.index(entry) if i == len(el) - 1: self.button_ok.grab_focus() else: el[i+1].gtk_entry().grab_focus() def on_three_way_toggled(self, button): page = self.three_way_compare.index(button) self.entrylists[page][0].set_sensitive( button.get_active() ) self.entrylists[page][ not button.get_active() ].gtk_entry().grab_focus() def on_response(self, dialog, arg): if arg==gtk.RESPONSE_OK: page = self.notebook.get_current_page() paths = [ e.get_full_path(0) or "" for e in self.entrylists[page] ] if page < 2 and not self.three_way_compare[page].get_active(): paths.pop(0) methods = (self.parentapp.append_filediff, self.parentapp.append_dirdiff, self.parentapp.append_vcview ) methods[page](paths) self.widget.destroy()################################################################################## ListWidget#################################################################################class ListWidget(gnomeglade.Component): def __init__(self, columns, prefs, key): gnomeglade.Component.__init__(self, paths.share_dir("glade2/meldapp.glade"), "listwidget") self.prefs = prefs self.key = key self.treeview.set_model( gtk.ListStore( *[c[1] for c in columns] ) ) view = self.treeview def addTextCol(label, colnum, expand=0): model = view.get_model() rentext = gtk.CellRendererText() rentext.set_property("editable", 1) def change_text(ren, row, text): it = model.get_iter( (int(row),)) model.set_value( it, colnum, text) self._update_filter_string() rentext.connect("edited", change_text) column = gtk.TreeViewColumn(label) column.pack_start(rentext, expand=expand) column.set_attributes(rentext, markup=colnum) view.append_column(column) def addToggleCol(label, colnum): model = view.get_model() rentoggle = gtk.CellRendererToggle() def change_toggle(ren, row): it = model.get_iter( (int(row),)) model.set_value( it, colnum, not ren.get_active() ) self._update_filter_string() rentoggle.connect("toggled", change_toggle) column = gtk.TreeViewColumn(label) column.pack_start(rentoggle, expand=0) column.set_attributes(rentoggle, active=colnum) view.append_column(column) for c,i in zip( columns, range(len(columns))): if c[1] == type(""): e = (i == (len(columns)-1)) addTextCol( c[0], i, expand=e) elif c[1] == type(0): addToggleCol( c[0], 1) self._update_filter_model() def on_item_new_clicked(self, button): model = self.treeview.get_model() it = model.append() model.set_value(it, 0, _("label")) model.set_value(it, 2, _("pattern")) self._update_filter_string() def _get_selected(self): selected = [] self.treeview.get_selection().selected_foreach( lambda store, path, it: selected.append( path ) ) return selected def on_item_delete_clicked(self, button): model = self.treeview.get_model() for s in self._get_selected(): model.remove( model.get_iter(s) ) self._update_filter_string() def on_item_up_clicked(self, button): model = self.treeview.get_model() for s in self._get_selected(): if s[0] > 0: # XXX need model.swap old = model.get_iter(s[0]) it = model.insert( s[0]-1 ) for i in range(3): model.set_value(it, i, model.get_value(old, i) ) model.remove(old) self.treeview.get_selection().select_iter(it) self._update_filter_string() def on_item_down_clicked(self, button): model = self.treeview.get_model() for s in self._get_selected(): if s[0] < len(model)-1: # XXX need model.swap old = model.get_iter(s[0]) it = model.insert( s[0]+2 ) for i in range(3): model.set_value(it, i, model.get_value(old, i) ) model.remove(old) self.treeview.get_selection().select_iter(it) self._update_filter_string() def on_items_revert_clicked(self, button): setattr( self.prefs, self.key, self.prefs.get_default(self.key) ) self._update_filter_model() def _update_filter_string(self): model = self.treeview.get_model() pref = [] for row in model: pref.append("%s\t%s\t%s" % (row[0], row[1], misc.unescape(row[2]))) setattr( self.prefs, self.key, "\n".join(pref) ) def _update_filter_model(self): model = self.treeview.get_model() model.clear() for filtstring in getattr( self.prefs, self.key).split("\n"): filt = misc.ListItem(filtstring) it = model.append() model.set_value( it, 0, filt.name) model.set_value( it, 1, filt.active) model.set_value( it, 2, misc.escape(filt.value)) ################################################################################## PreferencesDialog#################################################################################class PreferencesDialog(gnomeglade.Component): editor_radio_values = {"internal":0, "gnome":1, "custom":2} def __init__(self, parentapp): gnomeglade.Component.__init__(self, paths.share_dir("glade2/meldapp.glade"), "preferencesdialog") self.widget.set_transient_for(parentapp.widget) self.notebook.set_show_tabs(0) # tab selector self.model = gtk.ListStore(type("")) column = gtk.TreeViewColumn() rentext = gtk.CellRendererText() column.pack_start(rentext, expand=0) column.set_attributes(rentext, text=0) self.treeview.append_column(column) self.treeview.set_model(self.model) for c in self.notebook.get_children(): label = self.notebook.get_tab_label(c).get_text() if not label.startswith("_"): self.model.append( (label,) ) self.prefs = parentapp.prefs # editor self._map_widgets_into_lists( ["editor_command"] ) if self.prefs.use_custom_font: self.radiobutton_custom_font.set_active(1) else: self.radiobutton_gnome_font.set_active(1) self.fontpicker.set_font_name( self.prefs.custom_font ) self.spinbutton_tabsize.set_value( self.prefs.tab_size ) self.option_wrap_lines.set_history( self.prefs.edit_wrap_lines ) self.checkbutton_supply_newline.set_active( self.prefs.supply_newline ) self.checkbutton_show_line_numbers.set_active( self.prefs.show_line_numbers ) self.checkbutton_use_syntax_highlighting.set_active( self.prefs.use_syntax_highlighting ) self.editor_command[ self.editor_radio_values.get(self.prefs.edit_command_type, "internal") ].set_active(1) self.gnome_default_editor_label.set_text( "(%s)" % " ".join(self.prefs.get_gnome_editor_command([])) ) self.custom_edit_command_entry.set_text( " ".join(self.prefs.get_custom_editor_command([])) ) # display self._map_widgets_into_lists( ["draw_style"] ) self._map_widgets_into_lists( ["toolbar_style"] ) self.draw_style[self.prefs.draw_style].set_active(1) self.toolbar_style[self.prefs.toolbar_style].set_active(1) # file filters cols = [ (_("Name"), type("")), (_("Active"), type(0)), (_("Pattern"), type("")) ] self.filefilter = ListWidget( cols, self.prefs, "filters") self.file_filters_box.pack_start(self.filefilter.widget) self.checkbutton_ignore_symlinks.set_active( self.prefs.ignore_symlinks) # text filters cols = [ (_("Name"), type("")), (_("Active"), type(0)), (_("Regex"), type("")) ] self.textfilter = ListWidget( cols, self.prefs, "regexes") self.text_filters_box.pack_start(self.textfilter.widget) self.checkbutton_ignore_blank_lines.set_active( self.prefs.ignore_blank_lines ) # encoding self.entry_text_codecs.set_text( self.prefs.text_codecs ) self._map_widgets_into_lists( ["save_encoding"] ) self.save_encoding[self.prefs.save_encoding].set_active(1) # cvs self.cvs_quiet_check.set_active( self.prefs.cvs_quiet ) self.cvs_compression_check.set_active( self.prefs.cvs_compression ) self.cvs_compression_value_spin.set_value( self.prefs.cvs_compression_value ) self.cvs_ignore_cvsrc_check.set_active( self.prefs.cvs_ignore_cvsrc ) self.cvs_binary_fileentry.set_filename( self.prefs.cvs_binary ) self.cvs_create_missing_check.set_active( self.prefs.cvs_create_missing ) self.cvs_prune_empty_check.set_active( self.prefs.cvs_prune_empty ) # # treeview # def on_treeview_cursor_changed(self, tree): path, column = tree.get_cursor() self.notebook.set_current_page(path[0]) # # editor # def on_fontpicker_font_set(self, picker, font): self.prefs.custom_font = font def on_radiobutton_font_toggled(self, radio): if radio.get_active(): custom = radio == self.radiobutton_custom_font self.fontpicker.set_sensitive(custom) self.prefs.use_custom_font = custom def on_spinbutton_tabsize_changed(self, spin): self.prefs.tab_size = int(spin.get_value()) def on_option_wrap_lines_changed(self, option): self.prefs.edit_wrap_lines = option.get_history() def on_checkbutton_supply_newline_toggled(self, check): self.prefs.supply_newline = check.get_active() def on_checkbutton_show_line_numbers_toggled(self, check): self.prefs.show_line_numbers = check.get_active() if check.get_active() and not sourceview_available: misc.run_dialog(_("Line numbers are only available if you have pysourceview installed.") ) def on_checkbutton_use_syntax_highlighting_toggled(self, check): self.prefs.use_syntax_highlighting = check.get_active() if check.get_active() and not sourceview_available: misc.run_dialog(_("Syntax highlighting is only available if you have pysourceview installed.") ) def on_editor_command_toggled(self, radio):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -