⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcview.py

📁 LINUX下的文件比较工具
💻 PY
📖 第 1 页 / 共 2 页
字号:
### 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  USAfrom __future__ import generatorsimport tempfileimport shutilimport gtkimport osimport reimport treeimport miscimport gnomegladeimport melddocimport pathsimport vc################################################################################## Local Functions#################################################################################def _expand_to_root( treeview, path ):    """Expand rows from path up to root"""    start = path[:]    while len(start) and not treeview.row_expanded(start):        start = start[:-1]    level = len(start)    while level < len(path):        level += 1        treeview.expand_row( path[:level], 0)def _commonprefix(files):    if len(files) != 1:        workdir = misc.commonprefix(files)    else:        workdir = os.path.dirname(files[0])    return workdir################################################################################## CommitDialog#################################################################################class CommitDialog(gnomeglade.Component):    def __init__(self, parent):        gnomeglade.Component.__init__(self, paths.share_dir("glade2/vcview.glade"), "commitdialog")        self.parent = parent        self.widget.set_transient_for( parent.widget.get_toplevel() )        selected = parent._get_selected_files()        topdir = _commonprefix(selected)        selected = [ s[len(topdir):] for s in selected ]        self.changedfiles.set_text( ("(in %s) "%topdir) + " ".join(selected) )        self.widget.show_all()    def run(self):        self.previousentry.list.select_item(0)        self.textview.grab_focus()        buf = self.textview.get_buffer()        buf.place_cursor( buf.get_start_iter() )        buf.move_mark( buf.get_selection_bound(), buf.get_end_iter() )        response = self.widget.run()        msg = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), 0)        if response == gtk.RESPONSE_OK:            self.parent._command_on_selected( self.parent.vc.commit_command(msg) )        if len(msg.strip()):            self.previousentry.prepend_history(1, msg)        self.widget.destroy()    def on_previousentry_activate(self, gentry):        buf = self.textview.get_buffer()        buf.set_text( gentry.gtk_entry().get_text() )COL_LOCATION, COL_STATUS, COL_REVISION, COL_TAG, COL_OPTIONS, COL_END = range(tree.COL_END, tree.COL_END+6)class VcTreeStore(tree.DiffTreeStore):    def __init__(self):        types = [type("")] * COL_END        types[tree.COL_ICON] = type(tree.pixbuf_file)        gtk.TreeStore.__init__(self, *types)        self.ntree = 1        self._setup_default_styles()        self.textstyle[tree.STATE_MISSING] = '<span foreground="#000088" strikethrough="true" weight="bold">%s</span>'################################################################################## DirDiffMenu#################################################################################class VcMenu(gnomeglade.Component):    def __init__(self, app, event):        gladefile = paths.share_dir("glade2/vcview.glade")        gnomeglade.Component.__init__(self, gladefile, "menu_popup")        self.parent = app        self.widget.popup( None, None, None, 3, event.time )    def on_diff_activate(self, menuitem):        self.parent.on_button_diff_clicked( menuitem )    def on_edit_activate(self, menuitem):        self.parent._edit_files( self.parent._get_selected_files() )    def on_update_activate(self, menuitem):        self.parent.on_button_update_clicked( menuitem )    def on_commit_activate(self, menuitem):        self.parent.on_button_commit_clicked( menuitem )    def on_add_activate(self, menuitem):        self.parent.on_button_add_clicked( menuitem )    def on_add_binary_activate(self, menuitem):        self.parent.on_button_add_binary_clicked( menuitem )    def on_remove_activate(self, menuitem):        self.parent.on_button_remove_clicked( menuitem )    def on_revert_activate(self, menuitem):        self.parent.on_button_revert_clicked( menuitem )    def on_remove_locally_activate(self, menuitem):        self.parent.on_button_delete_clicked( menuitem )################################################################################# filters################################################################################entry_modified = lambda x: (x.state >= tree.STATE_NEW) or (x.isdir and (x.state > tree.STATE_NONE))entry_normal   = lambda x: (x.state == tree.STATE_NORMAL)entry_nonvc    = lambda x: (x.state == tree.STATE_NONE) or (x.isdir and (x.state > tree.STATE_IGNORED))entry_ignored  = lambda x: (x.state == tree.STATE_IGNORED) or x.isdir################################################################################## VcView#################################################################################class VcView(melddoc.MeldDoc, gnomeglade.Component):    def __init__(self, prefs):        melddoc.MeldDoc.__init__(self, prefs)        gnomeglade.Component.__init__(self, paths.share_dir("glade2/vcview.glade"), "vcview")        self.toolbar.set_style( self.prefs.get_toolbar_style() )        self.tempdirs = []        self.model = VcTreeStore()        self.treeview.set_model(self.model)        self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)        self.treeview.set_headers_visible(1)        column = gtk.TreeViewColumn( _("Name") )        renpix = gtk.CellRendererPixbuf()        rentext = gtk.CellRendererText()        column.pack_start(renpix, expand=0)        column.pack_start(rentext, expand=1)        column.set_attributes(renpix, pixbuf=self.model.column_index(tree.COL_ICON, 0))        column.set_attributes(rentext, markup=self.model.column_index(tree.COL_TEXT, 0))        self.treeview.append_column(column)        def addCol(name, num):            column = gtk.TreeViewColumn(name)            rentext = gtk.CellRendererText()            column.pack_start(rentext, expand=0)            column.set_attributes(rentext, markup=self.model.column_index(num, 0))            self.treeview.append_column(column)            return column        self.treeview_column_location = addCol( _("Location"), COL_LOCATION)        addCol(_("Status"), COL_STATUS)        addCol(_("Rev"), COL_REVISION)        addCol(_("Tag"), COL_TAG)        addCol(_("Options"), COL_OPTIONS)        class ConsoleStream(object):            def __init__(this, textview):                this.textview = textview                b = textview.get_buffer()                this.mark = b.create_mark("END", b.get_end_iter(), 0)            def write(this, s):                if s:                    b = this.textview.get_buffer()                    b.insert(b.get_end_iter(), s)                    this.textview.scroll_mark_onscreen( this.mark )        self.consolestream = ConsoleStream(self.consoleview)        self.location = None        self.treeview_column_location.set_visible( self.button_flatten.get_active() )        size = self.fileentry.size_request()[1]        self.button_jump.set_size_request(size, size)        self.button_jump.hide()        if not self.prefs.vc_console_visible:            self.on_console_view_toggle(self.console_hide_box)    def set_location(self, location):        self.model.clear()        self.location = location = os.path.abspath(location or ".")        self.fileentry.gtk_entry().set_text(location)        self.vc = vc.Vc(location)        it = self.model.add_entries( None, [location] )        self.treeview.get_selection().select_iter(it)        self.model.set_state(it, 0, tree.STATE_NORMAL, isdir=1)        self.recompute_label()        self.scheduler.remove_all_tasks()        self.scheduler.add_task( self._search_recursively_iter(self.model.get_iter_root()).next )    def recompute_label(self):        self.label_text = os.path.basename(self.location)        self.label_changed()    def _search_recursively_iter(self, iterstart):        yield _("[%s] Scanning %s") % (self.label_text,"")        rootpath = self.model.get_path( iterstart  )        rootname = self.model.value_path( self.model.get_iter(rootpath), 0 )        prefixlen = 1 + len( self.model.value_path( self.model.get_iter_root(), 0 ) )        todo = [ (rootpath, rootname) ]        filters = []        if self.button_modified.get_active():            filters.append( entry_modified )        if self.button_normal.get_active():            filters.append( entry_normal )        if self.button_nonvc.get_active():            filters.append( entry_nonvc )        if self.button_ignored.get_active():            filters.append( entry_ignored )        def showable(entry):            for f in filters:                if f(entry): return 1        recursive = self.button_flatten.get_active()        self.vc.cache_inventory(rootname)        while len(todo):            todo.sort() # depth first            path, name = todo.pop(0)            if path:                it = self.model.get_iter( path )                root = self.model.value_path( it, 0 )            else:                it = self.model.get_iter_root()                root = name            yield _("[%s] Scanning %s") % (self.label_text, root[prefixlen:])            #import time; time.sleep(1.0)                        entries = filter(showable, self.vc.listdir(root))            differences = 0            for e in entries:                differences |= (e.state != tree.STATE_NORMAL)                if e.isdir and recursive:                    todo.append( (None, e.path) )                    continue                child = self.model.add_entries(it, [e.path])                self._update_item_state( child, e, root[prefixlen:] )                if e.isdir:                    todo.append( (self.model.get_path(child), None) )            if not recursive: # expand parents                if len(entries) == 0:                    self.model.add_empty(it, _("(Empty)"))                if differences or len(path)==1:                    _expand_to_root( self.treeview, path )            else: # just the root                self.treeview.expand_row( (0,), 0)        self.vc.uncache_inventory()    def on_preference_changed(self, key, value):        if key == "toolbar_style":            self.toolbar.set_style( self.prefs.get_toolbar_style() )    def on_fileentry_activate(self, fileentry):        path = fileentry.get_full_path(0)        self.set_location(path)    def on_quit_event(self):        self.scheduler.remove_all_tasks()        for f in self.tempdirs:            if os.path.exists(f):                shutil.rmtree(f, ignore_errors=1)    def on_delete_event(self, appquit=0):        self.on_quit_event()        return gtk.RESPONSE_OK    def on_row_activated(self, treeview, path, tvc):        it = self.model.get_iter(path)        if self.model.iter_has_child(it):            if self.treeview.row_expanded(path):                self.treeview.collapse_row(path)            else:                self.treeview.expand_row(path,0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -