def setupViews(self): self.tableViews = { 'left': self.fileHistoryLeft, 'right': self.fileHistoryRight } # viewers are Scintilla editors self.viewers = {} # block are diff-block displayers self.block = {} self.diffblock = blockmatcher.BlockMatch(self.frame) lay = QHBoxLayout(self.frame) lay.setSpacing(0) lay.setContentsMargins(0, 0, 0, 0) try: contents = open(self.repo.wjoin(self.filename), "rb").read(1024) lexer = lexers.get_lexer(self.filename, contents, self) except Exception: lexer = None for side, idx in (('left', 0), ('right', 3)): sci = Scintilla(self.frame) sci.verticalScrollBar().setFocusPolicy(Qt.StrongFocus) sci.setFocusProxy(sci.verticalScrollBar()) sci.verticalScrollBar().installEventFilter(self) sci.setContextMenuPolicy(Qt.CustomContextMenu) sci.customContextMenuRequested.connect( functools.partial(self.fileViewMenuRequest, sci)) sci.setFrameShape(QFrame.NoFrame) sci.setMarginLineNumbers(1, True) sci.SendScintilla(sci.SCI_SETSELEOLFILLED, True) sci.setLexer(lexer) if lexer is None: sci.setFont(qtlib.getfont('fontdiff').font()) sci.setReadOnly(True) sci.setUtf8(True) lay.addWidget(sci) # hide margin 0 (markers) sci.SendScintilla(sci.SCI_SETMARGINTYPEN, 0, 0) sci.SendScintilla(sci.SCI_SETMARGINWIDTHN, 0, 0) # setup margin 1 for line numbers only sci.SendScintilla(sci.SCI_SETMARGINTYPEN, 1, 1) sci.SendScintilla(sci.SCI_SETMARGINWIDTHN, 1, 20) sci.SendScintilla(sci.SCI_SETMARGINMASKN, 1, 0) # define markers for colorize zones of diff self.markerplus = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markerplus, 0xB0FFA0) self.markerminus = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markerminus, 0xA0A0FF) self.markertriangle = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markertriangle, 0xFFA0A0) self.viewers[side] = sci blk = blockmatcher.BlockList(self.frame) blk.linkScrollBar(sci.verticalScrollBar()) self.diffblock.linkScrollBar(sci.verticalScrollBar(), side) lay.insertWidget(idx, blk) self.block[side] = blk lay.insertWidget(2, self.diffblock) for side in sides: table = getattr(self, 'tableView_revisions_%s' % side) table.setTabKeyNavigation(False) #table.installEventFilter(self) table.revisionSelected.connect(self.onRevisionSelected) table.revisionActivated.connect(self.onRevisionActivated) self.viewers[side].verticalScrollBar().valueChanged.connect( lambda value, side=side: self.sbar_changed( value, side, 'vertical')) self.viewers[side].horizontalScrollBar().valueChanged.connect( lambda value, side=side: self.sbar_changed( value, side, 'horizontal')) self.setTabOrder(table, self.viewers['left']) self.setTabOrder(self.viewers['left'], self.viewers['right']) # timer used to fill viewers with diff block markers during GUI idle time self.timer = QTimer() self.timer.setSingleShot(False) self.timer.timeout.connect(self.idle_fill_files)
def displayFile(self, filename=None, status=None): if isinstance(filename, (unicode, QString)): filename = hglib.fromunicode(filename) status = hglib.fromunicode(status) if filename and self._filename == filename: # Get the last visible line to restore it after reloading the editor lastCursorPosition = self.sci.getCursorPosition() lastScrollPosition = self.sci.firstVisibleLine() else: lastCursorPosition = (0, 0) lastScrollPosition = 0 self._filename, self._status = filename, status self.clearMarkup() self._diffs = [] if filename is None: self.restrictModes(False, False, False) return if self._ctx2: ctx2 = self._ctx2 elif self._parent == 0 or len(self._ctx.parents()) == 1: ctx2 = self._ctx.p1() else: ctx2 = self._ctx.p2() fd = filedata.FileData(self._ctx, ctx2, filename, status) if fd.elabel: self.extralabel.setText(fd.elabel) self.extralabel.show() else: self.extralabel.hide() self.filenamelabel.setText(fd.flabel) if not fd.isValid(): self.sci.setText(fd.error) self.sci.setLexer(None) self.sci.setFont(qtlib.getfont("fontlog").font()) self.sci.setMarginWidth(1, 0) self.blk.setVisible(False) self.restrictModes(False, False, False) return candiff = bool(fd.diff) canfile = bool(fd.contents or fd.ucontents) canann = bool(fd.contents) and type(self._ctx.rev()) is int if not candiff or not canfile: self.restrictModes(candiff, canfile, canann) else: self.actionDiffMode.setEnabled(True) self.actionFileMode.setEnabled(True) self.actionAnnMode.setEnabled(True) if self._lostMode: self._mode = self._lostMode if self._lostMode == DiffMode: self.actionDiffMode.trigger() elif self._lostMode == FileMode: self.actionFileMode.trigger() elif self._lostMode == AnnMode: self.actionAnnMode.trigger() self._lostMode = None self.blk.setVisible(self._mode != DiffMode) self.sci.setAnnotationEnabled(self._mode == AnnMode) if self._mode == DiffMode: self.sci.setMarginWidth(1, 0) lexer = lexers.get_diff_lexer(self) self.sci.setLexer(lexer) if lexer is None: self.sci.setFont(qtlib.getfont("fontlog").font()) # trim first three lines, for example: # diff -r f6bfc41af6d7 -r c1b18806486d tortoisehg/hgqt/thgrepo.py # --- a/tortoisehg/hgqt/thgrepo.py # +++ b/tortoisehg/hgqt/thgrepo.py if fd.diff: out = fd.diff.split("\n", 3) if len(out) == 4: self.sci.setText(hglib.tounicode(out[3])) else: # there was an error or rename without diffs self.sci.setText(hglib.tounicode(fd.diff)) elif fd.ucontents: # subrepo summary and perhaps other data self.sci.setText(fd.ucontents) self.sci.setLexer(None) self.sci.setFont(qtlib.getfont("fontlog").font()) self.sci.setMarginWidth(1, 0) self.blk.setVisible(False) return elif fd.contents: lexer = lexers.get_lexer(filename, fd.contents, self) self.sci.setLexer(lexer) if lexer is None: self.sci.setFont(qtlib.getfont("fontlog").font()) self.sci.setText(hglib.tounicode(fd.contents)) self.blk.setVisible(True) self.sci._updatemarginwidth() if self._mode == AnnMode: self.sci._updateannotation(self._ctx, filename) else: return # Recover the last cursor/scroll position self.sci.setCursorPosition(*lastCursorPosition) # Make sure that lastScrollPosition never exceeds the amount of # lines on the editor lastScrollPosition = min(lastScrollPosition, self.sci.lines() - 1) self.sci.verticalScrollBar().setValue(lastScrollPosition) self.highlightText(*self._lastSearch) uf = hglib.tounicode(filename) uc = hglib.tounicode(fd.contents) or "" self.fileDisplayed.emit(uf, uc) if self._mode != DiffMode: self.blk.setVisible(True) self.blk.syncPageStep() if fd.contents and fd.olddata: if self.timer.isActive(): self.timer.stop() self._fd = fd self.timer.start() self.actionNextDiff.setEnabled(bool(self._diffs)) self.actionPrevDiff.setEnabled(bool(self._diffs)) lexer = self.sci.lexer() if lexer: font = self.sci.lexer().font(0) else: font = self.sci.font() fm = QFontMetrics(font) self.maxWidth = fm.maxWidth() lines = unicode(self.sci.text()).splitlines() if lines: # assume that the longest line has the largest width; # fm.width() is too slow to apply to each line. try: longestline = max(lines, key=len) except TypeError: # Python<2.5 has no key support longestline = max((len(l), l) for l in lines)[1] self.maxWidth += fm.width(longestline) self.updateScrollBar()
def setupViews(self): self.tableViews = {'left': self.fileHistoryLeft, 'right': self.fileHistoryRight} # viewers are Scintilla editors self.viewers = {} # block are diff-block displayers self.block = {} self.diffblock = blockmatcher.BlockMatch(self.frame) lay = QHBoxLayout(self.frame) lay.setSpacing(0) lay.setContentsMargins(0, 0, 0, 0) try: contents = open(self.repo.wjoin(self.filename), "rb").read(1024) lexer = lexers.get_lexer(self.filename, contents, self) except Exception: lexer = None for side, idx in (('left', 0), ('right', 3)): sci = Scintilla(self.frame) sci.verticalScrollBar().setFocusPolicy(Qt.StrongFocus) sci.setFocusProxy(sci.verticalScrollBar()) sci.verticalScrollBar().installEventFilter(self) sci.setContextMenuPolicy(Qt.CustomContextMenu) sci.customContextMenuRequested.connect( functools.partial(self.fileViewMenuRequest, sci)) sci.setFrameShape(QFrame.NoFrame) sci.setMarginLineNumbers(1, True) sci.SendScintilla(sci.SCI_SETSELEOLFILLED, True) sci.setLexer(lexer) if lexer is None: sci.setFont(qtlib.getfont('fontdiff').font()) sci.setReadOnly(True) sci.setUtf8(True) lay.addWidget(sci) # hide margin 0 (markers) sci.SendScintilla(sci.SCI_SETMARGINTYPEN, 0, 0) sci.SendScintilla(sci.SCI_SETMARGINWIDTHN, 0, 0) # setup margin 1 for line numbers only sci.SendScintilla(sci.SCI_SETMARGINTYPEN, 1, 1) sci.SendScintilla(sci.SCI_SETMARGINWIDTHN, 1, 20) sci.SendScintilla(sci.SCI_SETMARGINMASKN, 1, 0) # define markers for colorize zones of diff self.markerplus = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markerplus, 0xB0FFA0) self.markerminus = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markerminus, 0xA0A0FF) self.markertriangle = sci.markerDefine(QsciScintilla.Background) sci.SendScintilla(sci.SCI_MARKERSETBACK, self.markertriangle, 0xFFA0A0) self.viewers[side] = sci blk = blockmatcher.BlockList(self.frame) blk.linkScrollBar(sci.verticalScrollBar()) self.diffblock.linkScrollBar(sci.verticalScrollBar(), side) lay.insertWidget(idx, blk) self.block[side] = blk lay.insertWidget(2, self.diffblock) for side in sides: table = getattr(self, 'tableView_revisions_%s' % side) table.setTabKeyNavigation(False) #table.installEventFilter(self) table.revisionSelected.connect(self.onRevisionSelected) table.revisionActivated.connect(self.onRevisionActivated) self.viewers[side].verticalScrollBar().valueChanged.connect( lambda value, side=side: self.sbar_changed(value, side, 'vertical')) self.viewers[side].horizontalScrollBar().valueChanged.connect( lambda value, side=side: self.sbar_changed(value, side, 'horizontal')) self.setTabOrder(table, self.viewers['left']) self.setTabOrder(self.viewers['left'], self.viewers['right']) # timer used to fill viewers with diff block markers during GUI idle time self.timer = QTimer() self.timer.setSingleShot(False) self.timer.timeout.connect(self.idle_fill_files)
def displayFile(self, filename=None, status=None): if isinstance(filename, (unicode, QString)): filename = hglib.fromunicode(filename) status = hglib.fromunicode(status) if filename and self._filename == filename: # Get the last visible line to restore it after reloading the editor lastCursorPosition = self.sci.getCursorPosition() lastScrollPosition = self.sci.firstVisibleLine() else: lastCursorPosition = (0, 0) lastScrollPosition = 0 self._filename, self._status = filename, status self.clearMarkup() self._diffs = [] if filename is None: self.restrictModes(False, False, False) return if self._ctx2: ctx2 = self._ctx2 elif self._parent == 0 or len(self._ctx.parents()) == 1: ctx2 = self._ctx.p1() else: ctx2 = self._ctx.p2() fd = filedata.FileData(self._ctx, ctx2, filename, status) if fd.elabel: self.extralabel.setText(fd.elabel) self.extralabel.show() else: self.extralabel.hide() self.filenamelabel.setText(fd.flabel) if not fd.isValid(): self.sci.setText(fd.error) self.sci.setLexer(None) self.sci.setFont(qtlib.getfont('fontlog').font()) self.sci.setMarginWidth(1, 0) self.blk.setVisible(False) self.restrictModes(False, False, False) return candiff = bool(fd.diff) canfile = bool(fd.contents or fd.ucontents) canann = bool(fd.contents) and type(self._ctx.rev()) is int if not candiff or not canfile: self.restrictModes(candiff, canfile, canann) else: self.actionDiffMode.setEnabled(True) self.actionFileMode.setEnabled(True) self.actionAnnMode.setEnabled(True) if self._lostMode: self._mode = self._lostMode if self._lostMode == DiffMode: self.actionDiffMode.trigger() elif self._lostMode == FileMode: self.actionFileMode.trigger() elif self._lostMode == AnnMode: self.actionAnnMode.trigger() self._lostMode = None self.blk.setVisible(self._mode != DiffMode) self.sci.setAnnotationEnabled(self._mode == AnnMode) if self._mode == DiffMode: self.sci.setMarginWidth(1, 0) lexer = lexers.get_diff_lexer(self) self.sci.setLexer(lexer) if lexer is None: self.sci.setFont(qtlib.getfont('fontlog').font()) # trim first three lines, for example: # diff -r f6bfc41af6d7 -r c1b18806486d tortoisehg/hgqt/thgrepo.py # --- a/tortoisehg/hgqt/thgrepo.py # +++ b/tortoisehg/hgqt/thgrepo.py if fd.diff: out = fd.diff.split('\n', 3) if len(out) == 4: self.sci.setText(hglib.tounicode(out[3])) else: # there was an error or rename without diffs self.sci.setText(hglib.tounicode(fd.diff)) elif fd.ucontents: # subrepo summary and perhaps other data self.sci.setText(fd.ucontents) self.sci.setLexer(None) self.sci.setFont(qtlib.getfont('fontlog').font()) self.sci.setMarginWidth(1, 0) self.blk.setVisible(False) return elif fd.contents: lexer = lexers.get_lexer(filename, fd.contents, self) self.sci.setLexer(lexer) if lexer is None: self.sci.setFont(qtlib.getfont('fontlog').font()) self.sci.setText(hglib.tounicode(fd.contents)) self.blk.setVisible(True) self.sci._updatemarginwidth() if self._mode == AnnMode: self.sci._updateannotation(self._ctx, filename) else: return # Recover the last cursor/scroll position self.sci.setCursorPosition(*lastCursorPosition) # Make sure that lastScrollPosition never exceeds the amount of # lines on the editor lastScrollPosition = min(lastScrollPosition, self.sci.lines() - 1) self.sci.verticalScrollBar().setValue(lastScrollPosition) self.highlightText(*self._lastSearch) uf = hglib.tounicode(filename) uc = hglib.tounicode(fd.contents) or '' self.fileDisplayed.emit(uf, uc) if self._mode != DiffMode: self.blk.setVisible(True) self.blk.syncPageStep() if fd.contents and fd.olddata: if self.timer.isActive(): self.timer.stop() self._fd = fd self.timer.start() self.actionNextDiff.setEnabled(bool(self._diffs)) self.actionPrevDiff.setEnabled(bool(self._diffs)) lexer = self.sci.lexer() if lexer: font = self.sci.lexer().font(0) else: font = self.sci.font() fm = QFontMetrics(font) self.maxWidth = fm.maxWidth() lines = unicode(self.sci.text()).splitlines() if lines: # assume that the longest line has the largest width; # fm.width() is too slow to apply to each line. try: longestline = max(lines, key=len) except TypeError: # Python<2.5 has no key support longestline = max((len(l), l) for l in lines)[1] self.maxWidth += fm.width(longestline) self.updateScrollBar()
def __init__(self, path, parent): super(RejectsDialog, self).__init__(parent) self.setWindowTitle(_('Merge rejected patch chunks into %s') % hglib.tounicode(path)) self.setWindowFlags(Qt.Window) self.path = path self.setLayout(QVBoxLayout()) editor = qscilib.Scintilla() editor.setBraceMatching(qsci.SloppyBraceMatch) editor.setFolding(qsci.BoxedTreeFoldStyle) editor.installEventFilter(qscilib.KeyPressInterceptor(self)) editor.setContextMenuPolicy(Qt.CustomContextMenu) editor.customContextMenuRequested.connect(self.menuRequested) self.baseLineColor = editor.markerDefine(qsci.Background, -1) editor.setMarkerBackgroundColor(QColor('lightblue'), self.baseLineColor) self.layout().addWidget(editor, 3) searchbar = qscilib.SearchToolBar(self, hidable=True) searchbar.searchRequested.connect(editor.find) searchbar.conditionChanged.connect(editor.highlightText) searchbar.hide() def showsearchbar(): searchbar.show() searchbar.setFocus(Qt.OtherFocusReason) qtlib.newshortcutsforstdkey(QKeySequence.Find, self, showsearchbar) self.layout().addWidget(searchbar) hbox = QHBoxLayout() hbox.setContentsMargins(2, 2, 2, 2) self.layout().addLayout(hbox, 1) self.chunklist = QListWidget(self) self.updating = True self.chunklist.currentRowChanged.connect(self.showChunk) hbox.addWidget(self.chunklist, 1) bvbox = QVBoxLayout() bvbox.setContentsMargins(2, 2, 2, 2) self.resolved = tb = QToolButton() tb.setIcon(qtlib.geticon('thg-success')) tb.setToolTip(_('Mark this chunk as resolved, goto next unresolved')) tb.pressed.connect(self.resolveCurrentChunk) self.unresolved = tb = QToolButton() tb.setIcon(qtlib.geticon('thg-warning')) tb.setToolTip(_('Mark this chunk as unresolved')) tb.pressed.connect(self.unresolveCurrentChunk) bvbox.addStretch(1) bvbox.addWidget(self.resolved, 0) bvbox.addWidget(self.unresolved, 0) bvbox.addStretch(1) hbox.addLayout(bvbox, 0) self.editor = editor self.rejectbrowser = RejectBrowser(self) hbox.addWidget(self.rejectbrowser, 5) BB = QDialogButtonBox bb = QDialogButtonBox(BB.Save|BB.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.layout().addWidget(bb) self.saveButton = bb.button(BB.Save) s = QSettings() self.restoreGeometry(s.value('rejects/geometry').toByteArray()) self.editor.loadSettings(s, 'rejects/editor') self.rejectbrowser.loadSettings(s, 'rejects/rejbrowse') f = QFile(path) if not f.open(QIODevice.ReadOnly): qtlib.ErrorMsgBox(_('Unable to merge rejects'), _("Can't read this file (maybe deleted)")) self.hide() QTimer.singleShot(0, self.reject) return earlybytes = f.readData(4096) if '\0' in earlybytes: qtlib.ErrorMsgBox(_('Unable to merge rejects'), _('This appears to be a binary file')) self.hide() QTimer.singleShot(0, self.reject) return f.seek(0) editor.read(f) editor.setModified(False) lexer = lexers.get_lexer(path, earlybytes, self) editor.setLexer(lexer) editor.setMarginLineNumbers(1, True) editor.setMarginWidth(1, str(editor.lines())+'X') buf = cStringIO.StringIO() try: buf.write('diff -r aaaaaaaaaaaa -r bbbbbbbbbbb %s\n' % path) buf.write(open(path + '.rej', 'rb').read()) buf.seek(0) except IOError, e: pass
def __init__(self, path, parent): super(RejectsDialog, self).__init__(parent) self.setWindowTitle(_("Merge rejected patch chunks into %s") % hglib.tounicode(path)) self.setWindowFlags(Qt.Window) self.path = path self.setLayout(QVBoxLayout()) editor = qscilib.Scintilla() editor.setBraceMatching(qsci.SloppyBraceMatch) editor.setFolding(qsci.BoxedTreeFoldStyle) editor.installEventFilter(qscilib.KeyPressInterceptor(self)) editor.setContextMenuPolicy(Qt.CustomContextMenu) editor.customContextMenuRequested.connect(self.menuRequested) self.baseLineColor = editor.markerDefine(qsci.Background, -1) editor.setMarkerBackgroundColor(QColor("lightblue"), self.baseLineColor) self.layout().addWidget(editor, 3) searchbar = qscilib.SearchToolBar(self, hidable=True) searchbar.searchRequested.connect(editor.find) searchbar.conditionChanged.connect(editor.highlightText) searchbar.hide() def showsearchbar(): searchbar.show() searchbar.setFocus(Qt.OtherFocusReason) qtlib.newshortcutsforstdkey(QKeySequence.Find, self, showsearchbar) self.layout().addWidget(searchbar) hbox = QHBoxLayout() hbox.setContentsMargins(2, 2, 2, 2) self.layout().addLayout(hbox, 1) self.chunklist = QListWidget(self) self.updating = True self.chunklist.currentRowChanged.connect(self.showChunk) hbox.addWidget(self.chunklist, 1) bvbox = QVBoxLayout() bvbox.setContentsMargins(2, 2, 2, 2) self.resolved = tb = QToolButton() tb.setIcon(qtlib.geticon("thg-success")) tb.setToolTip(_("Mark this chunk as resolved, goto next unresolved")) tb.pressed.connect(self.resolveCurrentChunk) self.unresolved = tb = QToolButton() tb.setIcon(qtlib.geticon("thg-warning")) tb.setToolTip(_("Mark this chunk as unresolved")) tb.pressed.connect(self.unresolveCurrentChunk) bvbox.addStretch(1) bvbox.addWidget(self.resolved, 0) bvbox.addWidget(self.unresolved, 0) bvbox.addStretch(1) hbox.addLayout(bvbox, 0) self.editor = editor self.rejectbrowser = RejectBrowser(self) hbox.addWidget(self.rejectbrowser, 5) BB = QDialogButtonBox bb = QDialogButtonBox(BB.Save | BB.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.layout().addWidget(bb) self.saveButton = bb.button(BB.Save) s = QSettings() self.restoreGeometry(s.value("rejects/geometry").toByteArray()) self.editor.loadSettings(s, "rejects/editor") self.rejectbrowser.loadSettings(s, "rejects/rejbrowse") f = QFile(path) if not f.open(QIODevice.ReadOnly): qtlib.ErrorMsgBox(_("Unable to merge rejects"), _("Can't read this file (maybe deleted)")) self.hide() QTimer.singleShot(0, self.reject) return earlybytes = f.readData(4096) if "\0" in earlybytes: qtlib.ErrorMsgBox(_("Unable to merge rejects"), _("This appears to be a binary file")) self.hide() QTimer.singleShot(0, self.reject) return f.seek(0) editor.read(f) editor.setModified(False) lexer = lexers.get_lexer(path, earlybytes, self) editor.setLexer(lexer) editor.setMarginLineNumbers(1, True) editor.setMarginWidth(1, str(editor.lines()) + "X") buf = cStringIO.StringIO() try: buf.write("diff -r aaaaaaaaaaaa -r bbbbbbbbbbb %s\n" % path) buf.write(open(path + ".rej", "rb").read()) buf.seek(0) except IOError, e: pass