by
Changes to 18 files · Browse files at 5df8bcb46c23 Showing diff from parent c969f014c035 de4a2cbd7d05 Diff from another changeset...
@@ -44,11 +44,8 @@ demandimport.ignore.append('tortoisehg.util.config')
demandimport.ignore.append('icons_rc')
demandimport.enable()
-from mercurial import ui as uimod, util
-from tortoisehg.util.hgversion import hgversion, checkhgversion
-import cStringIO
-import traceback
+# Verify we can reach TortoiseHg sources first
try:
import tortoisehg.hgqt.run
except ImportError, e:
@@ -58,50 +55,18 @@ sys.stderr.write("(check your install and PYTHONPATH)\n")
sys.exit(-1)
-ui = uimod.ui()
-capt = ui.configbool('tortoisehg', 'stderrcapt', True)
-
-errors = ('Traceback', 'TypeError', 'NameError', 'AttributeError',
- 'NotImplementedError')
-
-err = checkhgversion(hgversion)
-if err:
+# Verify we have an acceptable version of Mercurial
+from tortoisehg.util.hgversion import hgversion, checkhgversion
+errmsg = checkhgversion(hgversion)
+if errmsg:
from tortoisehg.hgqt.bugreport import run
from tortoisehg.hgqt.run import qtrun
opts = {}
opts['cmd'] = ' '.join(sys.argv[1:])
- opts['error'] = '\n' + err + '\n'
+ opts['error'] = '\n' + errmsg + '\n'
opts['nofork'] = True
qtrun(run, ui, **opts)
sys.exit(1)
-if not capt or 'THGDEBUG' in os.environ or '--profile' in sys.argv:
- sys.exit(tortoisehg.hgqt.run.dispatch(sys.argv[1:]))
-else:
- mystderr = cStringIO.StringIO()
- origstderr = sys.stderr
- sys.stderr = mystderr
- ret = 0
- try:
- ret = tortoisehg.hgqt.run.dispatch(sys.argv[1:])
- sys.stderr = origstderr
- mystderr.seek(0)
- for l in mystderr.readlines():
- if l.startswith(errors):
- from tortoisehg.hgqt.bugreport import run
- from tortoisehg.hgqt.run import qtrun
- error = 'Recoverable runtime error (stderr):\n'
- error += mystderr.getvalue()
- opts = {}
- opts['cmd'] = ' '.join(sys.argv[1:])
- opts['error'] = error
- opts['nofork'] = True
- qtrun(run, ui, **opts)
- break
- sys.exit(ret)
- except:
- if sys.exc_info()[0] not in [SystemExit, KeyboardInterrupt]:
- sys.stderr = origstderr
- traceback.print_exc()
- else:
- raise SystemExit(ret)
+ret = tortoisehg.hgqt.run.dispatch(sys.argv[1:])
+sys.exit(ret)
|
@@ -9,7 +9,7 @@
from mercurial import ui, error, util
-from tortoisehg.hgqt import visdiff, qtlib, qscilib, wctxactions, thgrepo, lexers
+from tortoisehg.hgqt import visdiff, qtlib, qscilib, thgrepo, lexers
from tortoisehg.util import paths, hglib, colormap, thread2
from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt.grep import SearchWidget
@@ -398,7 +398,7 @@
base, _ = visdiff.snapshot(repo, [wfile], repo[rev])
files = [os.path.join(base, wfile)]
- wctxactions.edit(self, repo.ui, repo, files, line, pattern)
+ qtlib.editfiles(repo, files, line, pattern, self)
@pyqtSlot(unicode, dict)
def _openSearchWidget(self, pattern, opts):
|
@@ -8,7 +8,7 @@ import os
import sys
-from mercurial import extensions, ui
+from mercurial import extensions
from tortoisehg.util import hglib, version
from tortoisehg.hgqt.i18n import _
@@ -147,6 +147,7 @@ self._textlabel = QLabel(text, wordWrap=True,
textInteractionFlags=labelflags)
self._textlabel.linkActivated.connect(self._openlink)
+ self._textlabel.setWordWrap(False)
self.layout().addWidget(self._textlabel)
bb = QDialogButtonBox(QDialogButtonBox.Close, centerButtons=True)
@@ -159,11 +160,20 @@ if ref == '#bugreport':
return BugReport(self._opts, self).exec_()
if ref.startswith('#edit:'):
- from tortoisehg.hgqt import wctxactions
fname, lineno = ref[6:].rsplit(':', 1)
- # A chicken-egg problem here, we need a ui to get your
- # editor in order to repair your ui config file.
- wctxactions.edit(self, ui.ui(), None, [fname], lineno, None)
+ try:
+ # A chicken-egg problem here, we need a ui to get your
+ # editor in order to repair your ui config file.
+ from mercurial import ui as uimod
+ from tortoisehg.hgqt import qtlib
+ class FakeRepo(object):
+ def __init__(self):
+ self.root = os.getcwd()
+ self.ui = uimod.ui()
+ fake = FakeRepo()
+ qtlib.editfiles(fake, [fname], lineno, parent=self)
+ except Exception, e:
+ QDesktopServices.openUrl(QUrl.fromLocalFile(fname))
def run(ui, *pats, **opts):
return BugReport(opts)
|
@@ -15,7 +15,7 @@ from tortoisehg.util import hglib
from tortoisehg.util.patchctx import patchctx
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, thgrepo, qscilib, lexers, wctxactions
+from tortoisehg.hgqt import qtlib, thgrepo, qscilib, lexers
from tortoisehg.hgqt import filelistmodel, filelistview, fileview
from PyQt4.QtCore import *
@@ -141,8 +141,8 @@ if isinstance(ctx, patchctx):
path = ctx._path
else:
- path = self.repo.wjoin(self.currentFile)
- wctxactions.edit(self, self.repo.ui, self.repo, [path])
+ path = self.currentFile
+ qtlib.editfiles(self.repo, [path], parent=self)
def getSelectedFileAndChunks(self):
chunks = self.diffbrowse.curchunks
|
@@ -18,9 +18,8 @@
from tortoisehg.util import hglib
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib
+from tortoisehg.hgqt import qtlib, visdiff, revert
from tortoisehg.hgqt.filedialogs import FileLogDialog, FileDiffDialog
-from tortoisehg.hgqt import visdiff, wctxactions, revert
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -164,12 +163,11 @@ repo = model.repo
rev = model._ctx.rev()
if rev is None:
- files = [repo.wjoin(filename)]
- wctxactions.edit(self, repo.ui, repo, files)
+ qtlib.editfiles(repo, [filename], parent=self)
else:
base, _ = visdiff.snapshot(repo, [filename], repo[rev])
files = [os.path.join(base, filename)]
- wctxactions.edit(self, repo.ui, repo, files)
+ qtlib.editfiles(repo, files, parent=self)
def editlocal(self):
filename = self.currentFile()
@@ -177,8 +175,7 @@ return
model = self.model()
repo = model.repo
- path = repo.wjoin(filename)
- wctxactions.edit(self, repo.ui, repo, [path])
+ qtlib.editfiles(repo, [path], parent=self)
def revertfile(self):
filename = self.currentFile()
|
@@ -27,7 +27,7 @@ from tortoisehg.util import hglib, patchctx
from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt import annotate, qscilib, qtlib, blockmatcher, lexers
-from tortoisehg.hgqt import visdiff, wctxactions
+from tortoisehg.hgqt import visdiff
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -260,6 +260,10 @@ if rev != self._p_rev:
self.displayFile(rev=rev)
+ def showLine(self, line):
+ if line < self.sci.lines():
+ self.sci.setCursorPosition(line, 0)
+
@pyqtSlot()
def clearDisplay(self):
self._filename = None
@@ -397,7 +401,7 @@ base = visdiff.snapshot(self.repo, [path], self.repo[rev])[0]
files = [os.path.join(base, path)]
pattern = hglib.fromunicode(self._lastSearch[0])
- wctxactions.edit(self, self.repo.ui, self.repo, files, line, pattern)
+ qtlib.editfiles(self.repo, files, line, pattern, self)
@pyqtSlot(unicode, bool, bool, bool)
def find(self, exp, icase=True, wrap=False, forward=True):
|
@@ -632,7 +632,6 @@ return
def onViewFile(self):
- from tortoisehg.hgqt import wctxactions
repo, ui, pattern = self.repo, self.repo.ui, self.pattern
seen = set()
for rev, path, line in self.selectedRows:
@@ -642,12 +641,11 @@ else:
seen.add(path)
if rev is None:
- files = [repo.wjoin(path)]
- wctxactions.edit(self, ui, repo, files, line, pattern)
+ qtlib.editfiles(repo, [path], line, pattern, self)
else:
base, _ = visdiff.snapshot(repo, [path], repo[rev])
files = [os.path.join(base, path)]
- wctxactions.edit(self, ui, repo, files, line, pattern)
+ qtlib.editfiles(repo, files, line, pattern, self)
def onVisualDiff(self):
rows = self.selectedRows[:]
|
|
|
@@ -18,11 +18,15 @@ from tortoisehg.util import paths, hglib
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, qscilib, annotate, status, thgrepo
-from tortoisehg.hgqt import visdiff, wctxactions, revert
+from tortoisehg.hgqt import qtlib, qscilib, fileview, status, thgrepo
+from tortoisehg.hgqt import visdiff, revert
from tortoisehg.hgqt.filedialogs import FileLogDialog, FileDiffDialog
from tortoisehg.hgqt.manifestmodel import ManifestModel
+# TODO
+# Communicate status (MARC) from model to HgFileView
+# Allow manifest mode in HgFileView even when no diffs are available
+
class ManifestDialog(QMainWindow):
"""
Qt4 dialog to display all files of a repo at a given revision
@@ -39,19 +43,12 @@ self._manifest_widget = ManifestWidget(repo, rev)
self._manifest_widget.revChanged.connect(self._updatewindowtitle)
self._manifest_widget.pathChanged.connect(self._updatewindowtitle)
- self._manifest_widget.editSelected.connect(self._openInEditor)
self._manifest_widget.grepRequested.connect(self._openSearchWidget)
self.setCentralWidget(self._manifest_widget)
self.addToolBar(self._manifest_widget.toolbar)
- self._searchbar = qscilib.SearchToolBar()
- connectsearchbar(self._manifest_widget, self._searchbar)
- self.addToolBar(self._searchbar)
- QShortcut(QKeySequence.Find, self,
- lambda: self._searchbar.setFocus(Qt.OtherFocusReason))
-
self.setStatusBar(QStatusBar())
- self._manifest_widget.revisionHint.connect(self.statusBar().showMessage)
+ self._manifest_widget.showMessage.connect(self.statusBar().showMessage)
self._readsettings()
self._updatewindowtitle()
@@ -81,7 +78,7 @@
def setSearchPattern(self, text):
"""Set search pattern [unicode]"""
- self._searchbar.setPattern(text)
+ self._fileview.searchbar.setPattern(text)
@pyqtSlot(unicode, dict)
def _openSearchWidget(self, pattern, opts):
@@ -93,7 +90,7 @@ def _openInEditor(self, path, rev, line):
"""Open editor to show the specified file"""
_openineditor(self._repo, path, rev, line,
- pattern=self._searchbar.pattern(), parent=self)
+ pattern=self._fileview.searchbar.pattern(), parent=self)
class ManifestWidget(QWidget):
"""Display file tree and contents at the specified revision"""
@@ -104,15 +101,12 @@ pathChanged = pyqtSignal(unicode)
"""Emitted (path) when the current file path changed"""
- revisionHint = pyqtSignal(unicode)
+ showMessage = pyqtSignal(unicode)
"""Emitted when to show revision summary as a hint"""
searchRequested = pyqtSignal(unicode)
"""Emitted (pattern) when user request to search content"""
- editSelected = pyqtSignal(unicode, object, int)
- """Emitted (path, rev, line) when user requests to open editor"""
-
grepRequested = pyqtSignal(unicode, dict)
"""Emitted (pattern, opts) when user request to search changelog"""
@@ -150,19 +144,14 @@ navlayoutw = QWidget()
navlayoutw.setLayout(navlayout)
- self._contentview = QStackedWidget()
self._splitter.addWidget(navlayoutw)
- self._splitter.addWidget(self._contentview)
self._splitter.setStretchFactor(0, 1)
+
+ self._fileview = fileview.HgFileView(self._repo, self)
+ self._splitter.addWidget(self._fileview)
self._splitter.setStretchFactor(1, 3)
-
- self._nullcontent = QWidget()
- self._contentview.addWidget(self._nullcontent)
- self._fileview = annotate.AnnotateView(self._repo)
- self._fileview.sourceChanged.connect(self.setSource)
- self._contentview.addWidget(self._fileview)
- for name in ('revisionHint', 'searchRequested', 'editSelected',
- 'grepRequested'):
+ self._fileview.revisionSelected.connect(self.setRev)
+ for name in ('showMessage', 'searchRequested', 'grepRequested'):
getattr(self._fileview, name).connect(getattr(self, name))
def loadSettings(self, qs, prefix):
@@ -180,18 +169,6 @@ statustext='MAC', text=_('Status'))
self._toolbar.addWidget(self._statusfilter)
- self._action_annotate_mode = QAction(_('Annotate'), self, checkable=True)
- self._action_annotate_mode.toggled.connect(
- self._fileview.setAnnotationEnabled)
- self._action_annotate_mode.setEnabled(self.rev is not None)
- self._toolbar.addAction(self._action_annotate_mode)
-
- if hasattr(self, '_searchbar'):
- self._action_find = self._searchbar.toggleViewAction()
- self._action_find.setIcon(qtlib.geticon('edit-find'))
- self._action_find.setShortcut(QKeySequence.Find)
- self._toolbar.addAction(self._action_find)
-
self._actions = {}
for name, desc, icon, key, tip, cb in [
('navigate', _('File history'), 'hg-log', 'Shift+Return',
@@ -252,19 +229,17 @@ if self.path is None:
return
if self.rev is None:
- files = [self._repo.wjoin(self.path)]
- wctxactions.edit(self, self._repo.ui, self._repo, files)
+ qtlib.editfiles(self._repo, [self.path], parent=self)
else:
base, _ = visdiff.snapshot(self._repo, [self.path],
self._repo[self.rev])
files = [os.path.join(base, self.path)]
- wctxactions.edit(self, self._repo.ui, self._repo, files)
+ qtlib.editfiles(self._repo, files, parent=self)
def editlocal(self):
if self.path is None:
return
- path = self._repo.wjoin(self.path)
- wctxactions.edit(self, self._repo.ui, self._repo, [path])
+ qtlib.editfiles(self._repo, [self.path], parent=self)
def revertfile(self):
if self.path is None:
@@ -376,11 +351,15 @@ self._rev = rev
self._setupmodel()
self.setPath(path)
- if self.path in self._repo[rev]:
- self._fileview.setSource(path, rev, line)
+ ctx = self._repo[rev]
+ if self.path in ctx:
+ self._fileview.setContext(ctx)
+ self._fileview.displayFile(path, rev)
+ if line:
+ self._fileview.showLine(int(line) - 1)
+ else:
+ self._fileview.clearDisplay()
if revchanged:
- # annotate working copy is not supported
- self._action_annotate_mode.setEnabled(rev is not None)
self.revChanged.emit(rev)
@property
@@ -395,38 +374,13 @@
@pyqtSlot()
def _updatecontent(self):
- if hglib.fromunicode(self.path) not in self._repo[self._rev]:
- self._contentview.setCurrentWidget(self._nullcontent)
- return
-
- self._contentview.setCurrentWidget(self._fileview)
- self._fileview.setSource(self.path, self._rev)
+ self._fileview.setContext(self._repo[self._rev])
+ self._fileview.displayFile(self.path, self._rev, 'C') # TODO
@pyqtSlot()
def _emitPathChanged(self):
self.pathChanged.emit(self.path)
-class ManifestTaskWidget(ManifestWidget):
- """Manifest widget designed for task tab"""
-
- def __init__(self, repo, rev, parent):
- super(ManifestTaskWidget, self).__init__(repo, rev, parent)
- self.editSelected.connect(self._openInEditor)
-
- @util.propertycache
- def _searchbar(self):
- searchbar = qscilib.SearchToolBar(hidable=True)
- searchbar.hide()
- self.layout().addWidget(searchbar)
- connectsearchbar(self, searchbar)
- return searchbar
-
- @pyqtSlot(unicode, object, int)
- def _openInEditor(self, path, rev, line):
- """Open editor to show the specified file"""
- _openineditor(self._repo, path, rev, line,
- pattern=self._searchbar.pattern(), parent=self)
-
def connectsearchbar(manifestwidget, searchbar):
"""Connect searchbar to manifest widget"""
searchbar.conditionChanged.connect(manifestwidget.highlightText)
@@ -439,7 +393,7 @@ pattern = hglib.fromunicode(pattern)
base = visdiff.snapshot(repo, [path], repo[rev])[0]
files = [os.path.join(base, path)]
- wctxactions.edit(parent, repo.ui, repo, files, line, pattern)
+ qtlib.editfiles(repo, files, line, pattern, parent=self)
def run(ui, *pats, **opts):
|
@@ -20,6 +20,7 @@ from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt import qtlib, cmdui, rejects, commit, qscilib
from tortoisehg.hgqt import qqueue, fileview
+from tortoisehg.hgqt.qtlib import geticon
# TODO
# keep original file name in file list item
@@ -81,36 +82,41 @@ qtbarhbox.setSpacing(5)
layout.addLayout(qtbarhbox, 0)
qtbarhbox.setContentsMargins(0, 0, 0, 0)
- self.qpushAllBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qpush-all'))
- tb.setToolTip(_('Apply all patches'))
- self.qpushBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qpush'))
- tb.setToolTip(_('Apply one patch'))
- self.setGuardsBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qguard'))
- tb.setToolTip(_('Configure guards for selected patch'))
- self.qpushMoveBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('thg-qreorder'))
- tb.setToolTip(_('Apply selected patch next (change queue order)'))
- self.qdeleteBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qdelete'))
- tb.setToolTip(_('Delete selected patches'))
- self.qpopBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qpop'))
- tb.setToolTip(_('Unapply one patch'))
- self.qpopAllBtn = tb = QToolButton()
- tb.setIcon(qtlib.geticon('hg-qpop-all'))
- tb.setToolTip(_('Unapply all patches'))
- qtbarhbox.addWidget(self.qpushAllBtn)
- qtbarhbox.addWidget(self.qpushBtn)
- qtbarhbox.addStretch(1)
- qtbarhbox.addWidget(self.setGuardsBtn)
- qtbarhbox.addWidget(self.qpushMoveBtn)
- qtbarhbox.addWidget(self.qdeleteBtn)
- qtbarhbox.addStretch(1)
- qtbarhbox.addWidget(self.qpopBtn)
- qtbarhbox.addWidget(self.qpopAllBtn)
+ self.qpushAllBtn = a = QAction(
+ geticon('hg-qpush-all'), _('Push all'), self)
+ a.setToolTip(_('Apply all patches'))
+ self.qpushBtn = a = QAction(
+ geticon('hg-qpush'), _('Push'), self)
+ a.setToolTip(_('Apply one patch'))
+ self.setGuardsBtn = a = QAction(
+ geticon('hg-qguard'), _('Guards'), self)
+ a.setToolTip(_('Configure guards for selected patch'))
+ self.qpushMoveBtn = a = QAction(
+ geticon('hg-qreorder'), _('Push selected'), self)
+ a.setToolTip(_('Apply selected patch next (change queue order)'))
+ self.qdeleteBtn = a = QAction(
+ geticon('hg-qdelete'), _('Delete'), self)
+ a.setToolTip(_('Delete selected patches'))
+ self.qpopBtn = a = QAction(
+ geticon('hg-qpop'), _('Pop'), self)
+ a.setToolTip(_('Unapply one patch'))
+ self.qpopAllBtn = a = QAction(
+ geticon('hg-qpop-all'), _('Pop all'), self)
+ a.setToolTip(_('Unapply all patches'))
+ tbar = QToolBar(_('Patch Queue Actions Toolbar'))
+ tbar.setIconSize(QSize(18, 18))
+ qtbarhbox.addWidget(tbar)
+ tbar.addAction(self.qpushBtn)
+ tbar.addAction(self.qpushAllBtn)
+ tbar.addSeparator()
+ tbar.addAction(self.qpopBtn)
+ tbar.addAction(self.qpopAllBtn)
+ tbar.addSeparator()
+ tbar.addAction(self.qpushMoveBtn)
+ tbar.addSeparator()
+ tbar.addAction(self.qdeleteBtn)
+ tbar.addSeparator()
+ tbar.addAction(self.setGuardsBtn)
self.queueListWidget = QListWidget(self)
layout.addWidget(self.queueListWidget, 1)
@@ -183,13 +189,13 @@ self.queueListWidget.currentRowChanged.connect(self.onPatchSelected)
self.queueListWidget.itemActivated.connect(self.onGotoPatch)
self.queueListWidget.itemChanged.connect(self.onRenamePatch)
- self.qpushAllBtn.clicked.connect(self.onPushAll)
- self.qpushBtn.clicked.connect(self.onPush)
- self.qpushMoveBtn.clicked.connect(self.onPushMove)
- self.qpopAllBtn.clicked.connect(self.onPopAll)
- self.qpopBtn.clicked.connect(self.onPop)
- self.setGuardsBtn.clicked.connect(self.onGuardConfigure)
- self.qdeleteBtn.clicked.connect(self.onDelete)
+ self.qpushAllBtn.triggered.connect(self.onPushAll)
+ self.qpushBtn.triggered.connect(self.onPush)
+ self.qpushMoveBtn.triggered.connect(self.onPushMove)
+ self.qpopAllBtn.triggered.connect(self.onPopAll)
+ self.qpopBtn.triggered.connect(self.onPop)
+ self.setGuardsBtn.triggered.connect(self.onGuardConfigure)
+ self.qdeleteBtn.triggered.connect(self.onDelete)
self.newCheckBox.toggled.connect(self.onNewModeToggled)
self.qnewOrRefreshBtn.clicked.connect(self.onQNewOrQRefresh)
|
|
@@ -10,10 +10,11 @@ import atexit
import shutil
import stat
+import subprocess
import tempfile
import re
-from mercurial import extensions
+from mercurial import extensions, util
from tortoisehg.util import hglib, paths, wconfig
from hgext.color import _styles
@@ -28,6 +29,12 @@ (QT_VERSION_STR, PYQT_VERSION_STR))
sys.exit()
+try:
+ import win32con
+ openflags = win32con.CREATE_NO_WINDOW
+except ImportError:
+ openflags = 0
+
tmproot = None
def gettempdir():
global tmproot
@@ -79,6 +86,64 @@
return fn, wconfig.readfile(fn)
+def editfiles(repo, files, lineno=None, search=None, parent=None):
+ files = [util.shellquote(util.localpath(f)) for f in files]
+ editor = repo.ui.config('tortoisehg', 'editor')
+ assert len(files) == 1 or lineno == None
+ if editor:
+ try:
+ regexp = re.compile('\[([^\]]*)\]')
+ expanded = []
+ pos = 0
+ for m in regexp.finditer(editor):
+ expanded.append(editor[pos:m.start()-1])
+ phrase = editor[m.start()+1:m.end()-1]
+ pos=m.end()+1
+ if '$LINENUM' in phrase:
+ if lineno is None:
+ # throw away phrase
+ continue
+ phrase = phrase.replace('$LINENUM', str(lineno))
+ elif '$SEARCH' in phrase:
+ if search is None:
+ # throw away phrase
+ continue
+ phrase = phrase.replace('$SEARCH', search)
+ if '$FILE' in phrase:
+ phrase = phrase.replace('$FILE', files[0])
+ files = []
+ expanded.append(phrase)
+ expanded.append(editor[pos:])
+ cmdline = ' '.join(expanded + files)
+ except ValueError, e:
+ # '[' or ']' not found
+ cmdline = ' '.join([editor] + files)
+ except TypeError, e:
+ # variable expansion failed
+ cmdline = ' '.join([editor] + files)
+ else:
+ editor = os.environ.get('HGEDITOR') or repo.ui.config('ui', 'editor') \
+ or os.environ.get('EDITOR', 'vi')
+ cmdline = ' '.join([editor] + files)
+ if os.path.basename(editor) in ('vi', 'vim', 'hgeditor'):
+ res = QMessageBox.critical(parent,
+ _('No visual editor configured'),
+ _('Please configure a visual editor.'))
+ from tortoisehg.hgqt.settings import SettingsDialog
+ dlg = SettingsDialog(False, focus='tortoisehg.editor')
+ dlg.exec_()
+ return
+
+ cmdline = util.quotecommand(cmdline)
+ try:
+ subprocess.Popen(cmdline, shell=True, creationflags=openflags,
+ stderr=None, stdout=None, stdin=None, cwd=repo.root)
+ except (OSError, EnvironmentError), e:
+ QMessageBox.warning(parent,
+ _('Editor launch failure'),
+ _('%s : %s') % (cmd, str(e)))
+ return False
+
# _styles maps from ui labels to effects
# _effects maps an effect to font style properties. We define a limited
# set of _effects, since we convert color effect names to font style
|
@@ -27,7 +27,7 @@ from tortoisehg.hgqt.repoview import HgRepoView
from tortoisehg.hgqt.revdetails import RevDetailsWidget
from tortoisehg.hgqt.commit import CommitWidget
-from tortoisehg.hgqt.manifestdialog import ManifestTaskWidget
+from tortoisehg.hgqt.manifestdialog import ManifestWidget
from tortoisehg.hgqt.sync import SyncWidget
from tortoisehg.hgqt.grep import SearchWidget
from tortoisehg.hgqt.pbranch import PatchBranchWidget
@@ -261,10 +261,10 @@ rev = None
else:
rev = self.rev
- w = ManifestTaskWidget(self.repo, rev, self)
+ w = ManifestWidget(self.repo, rev, self)
w.loadSettings(QSettings(), 'workbench')
w.revChanged.connect(self.repoview.goto)
- w.revisionHint.connect(self.showMessage)
+ w.showMessage.connect(self.showMessage)
w.grepRequested.connect(self.grep)
return w
|
@@ -14,7 +14,7 @@
from tortoisehg.util import hglib
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, cmdui, wctxactions, visdiff, thgrepo
+from tortoisehg.hgqt import qtlib, cmdui, visdiff, thgrepo
MARGINS = (8, 0, 0, 0)
@@ -192,7 +192,7 @@ paths = self.getSelectedPaths(self.rtree)
if paths:
abspaths = [os.path.join(r,w) for r,w in paths]
- wctxactions.edit(self, self.repo.ui, self.repo, abspaths)
+ qtlib.editfiles(self.repo, abspaths, parent=self)
def getVdiffFiles(self, tree):
paths = self.getSelectedPaths(self.rtree)
|
|
|
@@ -21,7 +21,7 @@ from PyQt4.QtCore import *
from PyQt4.QtGui import *
-import mercurial.ui as _ui
+import mercurial.ui as uimod
from mercurial import hg, util, fancyopts, cmdutil, extensions, error
from tortoisehg.hgqt.i18n import agettext as _
@@ -35,37 +35,44 @@except ImportError:
config_nofork = None
-try:
- import win32con
- openflags = win32con.CREATE_NO_WINDOW
-except ImportError:
- openflags = 0
-
nonrepo_commands = '''userconfig shellconfig clone debugcomplete init
about help version thgstatus serve rejects log'''
def dispatch(args):
"""run the command specified in args"""
try:
- u = _ui.ui()
+ u = uimod.ui()
if '--traceback' in args:
u.setconfig('ui', 'traceback', 'on')
if '--debugger' in args:
pdb.set_trace()
return _runcatch(u, args)
+ except error.ParseError, e:
+ from tortoisehg.hgqt.bugreport import ExceptionMsgBox
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['values'] = e
+ opts['error'] = traceback.format_exc()
+ opts['nofork'] = True
+ errstring = _('Error string "%(arg0)s" at %(arg1)s<br>Please '
+ '<a href="#edit:%(arg1)s">edit</a> your config')
+ main = QApplication(sys.argv)
+ dlg = ExceptionMsgBox(hglib.tounicode(str(e)), errstring, opts,
+ parent=None)
+ dlg.exec_()
+ except Exception, e:
+ # generic errors before the QApplication is started
+ if '--debugger' in args:
+ pdb.post_mortem(sys.exc_info()[2])
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['error'] = traceback.format_exc()
+ opts['nofork'] = True
+ return qtrun(bugrun, u, **opts)
except SystemExit:
pass
except KeyboardInterrupt:
print _('\nCaught keyboard interrupt, aborting.\n')
- except:
- if '--debugger' in args:
- pdb.post_mortem(sys.exc_info()[2])
- error = traceback.format_exc()
- opts = {}
- opts['cmd'] = ' '.join(sys.argv[1:])
- opts['error'] = error
- opts['nofork'] = True
- return qtrun(bugrun, u, **opts)
origwdir = os.getcwd()
def portable_fork(ui, opts):
@@ -87,7 +94,7 @@ cmdline = subprocess.list2cmdline(args)
os.chdir(origwdir)
subprocess.Popen(cmdline,
- creationflags=openflags,
+ creationflags=qtlib.openflags,
shell=True)
sys.exit(0)
@@ -179,7 +186,7 @@ try:
args = fancyopts.fancyopts(args, globalopts, options)
except fancyopts.getopt.GetoptError, inst:
- raise error.ParseError(None, inst)
+ raise error.CommandError(None, inst)
if args:
alias, args = args[0], args[1:]
@@ -203,7 +210,7 @@ try:
args = fancyopts.fancyopts(args, c, cmdoptions)
except fancyopts.getopt.GetoptError, inst:
- raise error.ParseError(cmd, inst)
+ raise error.CommandError(cmd, inst)
# separate global options back out
for o in globalopts:
@@ -228,19 +235,19 @@ return runcommand(ui, args)
finally:
ui.flush()
- except error.ParseError, inst:
+ except error.AmbiguousCommand, inst:
+ ui.status(_("thg: command '%s' is ambiguous:\n %s\n") %
+ (inst.args[0], " ".join(inst.args[1])))
+ except error.UnknownCommand, inst:
+ ui.status(_("thg: unknown command '%s'\n") % inst.args[0])
+ help_(ui, 'shortlist')
+ except error.CommandError, inst:
if inst.args[0]:
ui.status(_("thg %s: %s\n") % (inst.args[0], inst.args[1]))
help_(ui, inst.args[0])
else:
ui.status(_("thg: %s\n") % inst.args[1])
help_(ui, 'shortlist')
- except error.AmbiguousCommand, inst:
- ui.status(_("thg: command '%s' is ambiguous:\n %s\n") %
- (inst.args[0], " ".join(inst.args[1])))
- except error.UnknownCommand, inst:
- ui.status(_("thg: unknown command '%s'\n") % inst.args[0])
- help_(ui, 'shortlist')
except error.RepoError, inst:
ui.status(_("abort: %s!\n") % inst)
@@ -302,7 +309,7 @@ try:
return cmdfunc()
except error.SignatureError:
- raise error.ParseError(cmd, _("invalid arguments"))
+ raise error.CommandError(cmd, _("invalid arguments"))
if options['profile']:
format = ui.config('profiling', 'format', default='text')
@@ -364,6 +371,7 @@ error.RepoLookupError: _('Try refreshing your repository.'),
error.ParseError: _('Error string "%(arg0)s" at %(arg1)s<br>Please '
'<a href="#edit:%(arg1)s">edit</a> your config'),
+ error.Abort: _('Operation aborted:<br><br>%(arg0)s.'),
}
def __init__(self):
@@ -415,8 +423,13 @@ etype, evalue = self.errors[0][:2]
if len(self.errors) == 1 and etype in self._recoverableexc:
opts['values'] = evalue
+ errstr = self._recoverableexc[etype]
+ if etype == error.Abort and evalue.hint:
+ errstr = u''.join([errstr, u'<br><b>', _('hint:'),
+ u'</b> %(arg1)s'])
+ opts['values'] = [str(evalue), evalue.hint]
dlg = ExceptionMsgBox(hglib.tounicode(str(evalue)),
- self._recoverableexc[etype], opts,
+ errstr, opts,
parent=self._mainapp.activeWindow())
elif etype is KeyboardInterrupt:
if qtlib.QuestionMsgBox(_('Keyboard interrupt'),
|
@@ -303,9 +303,6 @@ _('The maximum size file (in KB) that TortoiseHg will '
'show changes for in the changelog, status, and commit windows. '
'A value of zero implies no limit. Default: 1024 (1MB)')),
- _fi(_('Capture stderr'), 'tortoisehg.stderrcapt', genBoolCombo,
- _('Redirect stderr to a buffer which is parsed at the end of '
- 'the process for runtime errors. Default: True')),
_fi(_('Fork GUI'), 'tortoisehg.guifork', genBoolCombo,
_('When running from the command line, fork a background '
'process to run graphical dialogs. Default: True')),
|
|
|
@@ -121,6 +121,7 @@ self.filelistToolbar.addWidget(self.statusfilter)
self.filelistToolbar.addSeparator()
self.filelistToolbar.addWidget(self.refreshBtn)
+ self.actions = wctxactions.WctxActions(self.repo, self)
tv = WctxFileTree(self.repo)
vbox.addLayout(hbox)
vbox.addWidget(tv)
@@ -152,11 +153,12 @@ hcbox.addStretch(1)
hcbox.addWidget(self.countlbl)
- tv.menuAction.connect(self.refreshWctx)
tv.setItemsExpandable(False)
tv.setRootIsDecorated(False)
tv.sortByColumn(COL_STATUS, Qt.AscendingOrder)
tv.clicked.connect(self.onRowClicked)
+ tv.doubleClicked.connect(self.onRowDoubleClicked)
+ tv.menuRequest.connect(self.onMenuRequest)
le.textEdited.connect(self.setFilter)
def statusTypeTrigger(status):
@@ -207,6 +209,12 @@ self.fileview.saveSettings(qs, prefix+'/fileview')
qs.setValue(prefix+'/state', self.split.saveState())
+ @pyqtSlot(QPoint, object)
+ def onMenuRequest(self, point, selected):
+ menu = self.actions.makeMenu(selected)
+ if menu.exec_(point):
+ self.refreshWctx()
+
def refreshWctx(self):
if self.refthread:
return
@@ -287,9 +295,11 @@ curidx = tm.index(i, 0)
else:
selmodel.select(curidx, flags)
- selmodel.currentChanged.connect(self.currentChanged)
+ selmodel.currentChanged.connect(self.onCurrentChange)
+ selmodel.selectionChanged.connect(self.onSelectionChange)
if curidx and curidx.isValid():
selmodel.setCurrentIndex(curidx, QItemSelectionModel.Current)
+ self.onSelectionChange(None, None)
# Disabled decorator because of bug in older PyQt releases
#@pyqtSlot(QModelIndex)
@@ -298,6 +308,16 @@ if index.column() == COL_PATH:
self.tv.model().toggleRow(index)
+ # Disabled decorator because of bug in older PyQt releases
+ #@pyqtSlot(QModelIndex)
+ def onRowDoubleClicked(self, index):
+ 'tree view emitted a doubleClicked signal, index guarunteed valid'
+ path, status, mst, u, ext, sz = self.tv.model().getRow(index)
+ if status in 'MAR!':
+ self.actions.allactions[0].trigger()
+ elif status == 'S':
+ self.linkActivated.emit(u'subrepo:'+hglib.tounicode(path))
+
@pyqtSlot(QString)
def setFilter(self, match):
self.tv.model().setFilter(match)
@@ -328,9 +348,17 @@ else:
return []
+ @pyqtSlot(QItemSelection, QItemSelection)
+ def onSelectionChange(self, selected, deselected):
+ selrows = []
+ for index in self.tv.selectedRows():
+ path, status, mst, u, ext, sz = self.tv.model().getRow(index)
+ selrows.append((set(status+mst.lower()), path))
+ self.actions.updateActionSensitivity(selrows)
+
# Disabled decorator because of bug in older PyQt releases
#@pyqtSlot(QModelIndex, QModelIndex)
- def currentChanged(self, index, old):
+ def onCurrentChange(self, index, old):
'Connected to treeview "currentChanged" signal'
row = index.model().getRow(index)
if row is None:
@@ -396,7 +424,7 @@
class WctxFileTree(QTreeView):
- menuAction = pyqtSignal()
+ menuRequest = pyqtSignal(QPoint, object)
def __init__(self, repo, parent=None):
QTreeView.__init__(self, parent)
@@ -416,15 +444,7 @@ if event.key() == 32:
for index in self.selectedRows():
self.model().toggleRow(index)
- if event.key() == Qt.Key_D and event.modifiers() == Qt.ControlModifier:
- selfiles = []
- for index in self.selectedRows():
- selfiles.append(self.model().getRow(index)[COL_PATH])
- dlg = visdiff.visualdiff(self.repo.ui, self.repo, selfiles, {})
- if dlg:
- dlg.exec_()
- else:
- return super(WctxFileTree, self).keyPressEvent(event)
+ return super(WctxFileTree, self).keyPressEvent(event)
def dragObject(self):
urls = []
@@ -458,10 +478,8 @@ for index in self.selectedRows():
path, status, mst, u, ext, sz = self.model().getRow(index)
selrows.append((set(status+mst.lower()), path))
- point = self.mapToGlobal(point)
- action = wctxactions.wctxactions(self, point, self.repo, selrows)
- if action:
- self.menuAction.emit()
+ if selrows:
+ self.menuRequest.emit(self.mapToGlobal(point), selrows)
def selectedRows(self):
return self.selectionModel().selectedRows()
|
@@ -23,12 +23,6 @@ from PyQt4.QtCore import *
from PyQt4.QtGui import *
-try:
- import win32con
- openflags = win32con.CREATE_NO_WINDOW
-except ImportError:
- openflags = 0
-
# Match parent2 first, so 'parent1?' will match both parent1 and parent
_regex = '\$(parent2|parent1?|child|plabel1|plabel2|clabel|repo|phash1|phash2|chash)'
@@ -128,7 +122,7 @@ cmdline = util.quotecommand(cmdline)
try:
proc = subprocess.Popen(cmdline, shell=True,
- creationflags=openflags,
+ creationflags=qtlib.openflags,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
|
|
|
@@ -7,64 +7,109 @@
import os
import re
-import subprocess
from mercurial import util, error, merge, commands
from tortoisehg.hgqt import qtlib, htmlui, visdiff
from tortoisehg.util import hglib, shlib
from tortoisehg.hgqt.i18n import _
-from PyQt4.QtCore import Qt
+from PyQt4.QtCore import Qt, QObject
from PyQt4.QtGui import *
-def wctxactions(parent, point, repo, selrows):
- if not selrows:
- return
- alltypes = set()
- for t, path in selrows:
- alltypes |= t
+class WctxActions(QObject):
+ 'container class for working context actions'
- def make(text, func, types, icon=None):
- files = [f for t, f in selrows if t & types]
- if not files:
- return None
- action = menu.addAction(text)
- if icon:
- action.setIcon(qtlib.getmenuicon(icon))
- action.args = (func, parent, files, repo)
- action.run = lambda: run(*action.args)
- action.triggered.connect(action.run)
- return action
+ def __init__(self, repo, parent):
+ super(WctxActions, self).__init__(parent)
- if hasattr(parent, 'contextmenu'):
- menu = parent.contextmenu
+ self.menu = QMenu(parent)
+ self.repo = repo
+ allactions = []
+
+ def make(text, func, types, icon=None, keys=None):
+ action = QAction(text, parent)
+ action._filetypes = types
+ action._runfunc = func
+ if icon:
+ action.setIcon(qtlib.getmenuicon(icon))
+ if keys:
+ action.setShortcut(QKeySequence(keys))
+ action.triggered.connect(self.runAction)
+ parent.addAction(action)
+ allactions.append(action)
+
+ make(_('&Visual Diff'), vdiff, frozenset('MAR!'), 'visualdiff', 'CTRL+D')
+ make(_('Copy patch'), copyPatch, frozenset('MAR!'), 'copy-patch')
+ make(_('Edit'), edit, frozenset('MACI?'), 'edit-file', 'SHIFT+CTRL+E')
+ make(_('View missing'), viewmissing, frozenset('R!'))
+ allactions.append(None)
+ make(_('&Revert'), revert, frozenset('MAR!'), 'hg-revert')
+ make(_('&Add'), add, frozenset('R'), 'fileadd')
+ allactions.append(None)
+ make(_('File History'), log, frozenset('MARC!'), 'hg-log')
+ make(_('&Annotate'), annotate, frozenset('MARC!'), 'hg-annotate')
+ allactions.append(None)
+ make(_('&Forget'), forget, frozenset('MAC!'), 'filedelete')
+ make(_('&Add'), add, frozenset('I?'), 'fileadd')
+ make(_('&Detect Renames...'), guessRename, frozenset('A?!'),
+ 'detect_rename')
+ make(_('&Ignore'), ignore, frozenset('?'), 'ignore')
+ make(_('Remove versioned'), remove, frozenset('C'), 'remove')
+ make(_('&Delete unversioned'), delete, frozenset('?I'), 'hg-purge')
+ allactions.append(None)
+ make(_('Mark unresolved'), unmark, frozenset('r'))
+ make(_('Mark resolved'), mark, frozenset('u'))
+ self.allactions = allactions
+
+ def updateActionSensitivity(self, selrows):
+ 'Enable/Disable permanent actions based on current selection'
+ self.selrows = selrows
+ alltypes = set()
+ for types, wfile in selrows:
+ alltypes |= types
+ for action in self.allactions:
+ if action is not None:
+ action.setEnabled(bool(action._filetypes & alltypes))
+
+ def makeMenu(self, selrows):
+ self.selrows = selrows
+ repo, menu = self.repo, self.menu
+
+ alltypes = set()
+ for types, wfile in selrows:
+ alltypes |= types
+
menu.clear()
- else:
- menu = QMenu(parent)
- parent.contextmenu = menu
- make(_('&Visual Diff'), vdiff, frozenset('MAR!'), 'visualdiff')
- make(_('Copy patch'), copyPatch, frozenset('MAR!'), 'copy-patch')
- make(_('Edit'), edit, frozenset('MACI?'), 'edit-file')
- make(_('View missing'), viewmissing, frozenset('R!'))
- if len(repo.parents()) > 1:
- make(_('View other'), viewother, frozenset('MA'))
- menu.addSeparator()
- make(_('&Revert'), revert, frozenset('MAR!'), 'hg-revert')
- make(_('&Add'), add, frozenset('R'), 'fileadd')
- menu.addSeparator()
- make(_('File History'), log, frozenset('MARC!'), 'hg-log')
- make(_('&Annotate'), annotate, frozenset('MARC!'), 'hg-annotate')
- menu.addSeparator()
- make(_('&Forget'), forget, frozenset('MAC!'), 'filedelete')
- make(_('&Add'), add, frozenset('I?'), 'fileadd')
- make(_('&Detect Renames...'), guessRename, frozenset('A?!'), 'detect_rename')
- make(_('&Ignore'), ignore, frozenset('?'), 'ignore')
- make(_('Remove versioned'), remove, frozenset('C'), 'remove')
- make(_('&Delete unversioned'), delete, frozenset('?I'), 'hg-purge')
- if len(selrows) == 1:
- menu.addSeparator()
+ addedActions = False
+ for action in self.allactions:
+ if action is None and addedActions:
+ menu.addSeparator()
+ addedActions = False
+ elif action._filetypes & alltypes:
+ menu.addAction(action)
+ addedActions = True
+
+ def make(text, func, types, icon=None):
+ if not types & alltypes:
+ return
+ action = menu.addAction(text)
+ action._filetypes = types
+ action._runfunc = func
+ if icon:
+ action.setIcon(qtlib.getmenuicon(icon))
+ action.triggered.connect(self.runAction)
+
+ if len(repo.parents()) > 1:
+ make(_('View other'), viewother, frozenset('MA'))
+
+ if len(selrows) == 1:
+ menu.addSeparator()
+ make(_('&Copy...'), copy, frozenset('MC'), 'edit-copy')
+ make(_('Rename...'), rename, frozenset('MC'), 'hg-rename')
+
+ # Add 'was renamed from' actions for unknown files
t, path = selrows[0]
- wctx = repo[None]
+ wctx = self.repo[None]
if t & frozenset('?') and wctx.deleted():
rmenu = QMenu(_('Was renamed from'))
for d in wctx.deleted()[:15]:
@@ -73,63 +118,61 @@ a.triggered.connect(lambda: renamefromto(repo, deleted, path))
mkaction(d)
menu.addMenu(rmenu)
- else:
- make(_('&Copy...'), copy, frozenset('MC'), 'edit-copy')
- make(_('Rename...'), rename, frozenset('MC'), 'hg-rename')
- menu.addSeparator()
- make(_('Mark unresolved'), unmark, frozenset('r'))
- make(_('Mark resolved'), mark, frozenset('u'))
- f = make(_('Restart Merge...'), resolve, frozenset('u'))
- if f:
- files = [f for t, f in selrows if 'u' in t]
- rmenu = QMenu(_('Restart merge with'))
- for tool in hglib.mergetools(repo.ui):
- def mkaction(rtool):
- a = rmenu.addAction(hglib.tounicode(rtool))
- a.triggered.connect(lambda: resolve_with(rtool, repo, files))
- mkaction(tool)
- menu.addMenu(rmenu)
- return menu.exec_(point)
-def run(func, parent, files, repo):
- 'run wrapper for all action methods'
- hu = htmlui.htmlui()
- name = func.__name__.title()
- notify = False
- cwd = os.getcwd()
- try:
- os.chdir(repo.root)
+ # Add restart merge actions for resolved files
+ if alltypes & frozenset('u'):
+ f = make(_('Restart Merge...'), resolve, frozenset('u'))
+ files = [f for t, f in selrows if 'u' in t]
+ rmenu = QMenu(_('Restart merge with'))
+ for tool in hglib.mergetools(repo.ui):
+ def mkaction(rtool):
+ a = rmenu.addAction(hglib.tounicode(rtool))
+ a.triggered.connect(lambda: resolve_with(rtool, repo, files))
+ mkaction(tool)
+ menu.addMenu(rmenu)
+ return menu
+
+ def runAction(self):
+ 'run wrapper for all action methods'
+
+ repo, action, parent = self.repo, self.sender(), self.parent()
+ func = action._runfunc
+ files = [wfile for t, wfile in self.selrows if t & action._filetypes]
+
+ hu = htmlui.htmlui()
+ name = func.__name__.title()
+ notify = False
+ cwd = os.getcwd()
try:
- # All operations should quietly succeed. Any error should
- # result in a message box
- notify = func(parent, hu, repo, files)
- o, e = hu.getdata()
- if e:
- QMessageBox.warning(parent, name + _(' errors'), str(e))
- elif o:
- QMessageBox.information(parent, name + _(' output'), str(o))
- elif notify:
- wfiles = [repo.wjoin(x) for x in files]
- shlib.shell_notify(wfiles)
- except (IOError, OSError), e:
- err = hglib.tounicode(str(e))
- QMessageBox.critical(parent, name + _(' Aborted'), err)
- except util.Abort, e:
- if e.hint:
- err = _('%s (hint: %s)') % (hglib.tounicode(str(e)),
- hglib.tounicode(e.hint))
- else:
+ os.chdir(repo.root)
+ try:
+ # All operations should quietly succeed. Any error should
+ # result in a message box
+ notify = func(parent, hu, repo, files)
+ o, e = hu.getdata()
+ if e:
+ QMessageBox.warning(parent, name + _(' errors'), str(e))
+ elif o:
+ QMessageBox.information(parent, name + _(' output'), str(o))
+ elif notify:
+ wfiles = [repo.wjoin(x) for x in files]
+ shlib.shell_notify(wfiles)
+ except (IOError, OSError), e:
err = hglib.tounicode(str(e))
- QMessageBox.critical(parent, name + _(' Aborted'), err)
- except (error.LookupError), e:
- err = hglib.tounicode(str(e))
- QMessageBox.critical(parent, name + _(' Aborted'), err)
- except NotImplementedError:
- QMessageBox.critical(parent, name + _(' not implemented'),
- 'Please add it :)')
- finally:
- os.chdir(cwd)
- return notify
+ QMessageBox.critical(parent, name + _(' Aborted'), err)
+ except util.Abort, e:
+ if e.hint:
+ err = _('%s (hint: %s)') % (hglib.tounicode(str(e)),
+ hglib.tounicode(e.hint))
+ else:
+ err = hglib.tounicode(str(e))
+ QMessageBox.critical(parent, name + _(' Aborted'), err)
+ except (error.LookupError), e:
+ err = hglib.tounicode(str(e))
+ QMessageBox.critical(parent, name + _(' Aborted'), err)
+ finally:
+ os.chdir(cwd)
+ return notify
def renamefromto(repo, deleted, unknown):
repo[None].copy(deleted, unknown)
@@ -154,63 +197,7 @@ dlg.exec_()
def edit(parent, ui, repo, files, lineno=None, search=None):
- files = [util.shellquote(util.localpath(f)) for f in files]
- editor = ui.config('tortoisehg', 'editor')
- assert len(files) == 1 or lineno == None
- if editor:
- try:
- regexp = re.compile('\[([^\]]*)\]')
- expanded = []
- pos = 0
- for m in regexp.finditer(editor):
- expanded.append(editor[pos:m.start()-1])
- phrase = editor[m.start()+1:m.end()-1]
- pos=m.end()+1
- if '$LINENUM' in phrase:
- if lineno is None:
- # throw away phrase
- continue
- phrase = phrase.replace('$LINENUM', str(lineno))
- elif '$SEARCH' in phrase:
- if search is None:
- # throw away phrase
- continue
- phrase = phrase.replace('$SEARCH', search)
- if '$FILE' in phrase:
- phrase = phrase.replace('$FILE', files[0])
- files = []
- expanded.append(phrase)
- expanded.append(editor[pos:])
- cmdline = ' '.join(expanded + files)
- except ValueError, e:
- # '[' or ']' not found
- cmdline = ' '.join([editor] + files)
- except TypeError, e:
- # variable expansion failed
- cmdline = ' '.join([editor] + files)
- else:
- editor = os.environ.get('HGEDITOR') or ui.config('ui', 'editor') or \
- os.environ.get('EDITOR', 'vi')
- cmdline = ' '.join([editor] + files)
- if os.path.basename(editor) in ('vi', 'vim', 'hgeditor'):
- res = QMessageBox.critical(parent,
- _('No visual editor configured'),
- _('Please configure a visual editor.'))
- from tortoisehg.hgqt.settings import SettingsDialog
- dlg = SettingsDialog(False, focus='tortoisehg.editor')
- dlg.exec_()
- return
-
- cmdline = util.quotecommand(cmdline)
- try:
- subprocess.Popen(cmdline, shell=True, creationflags=visdiff.openflags,
- stderr=None, stdout=None, stdin=None)
- except (OSError, EnvironmentError), e:
- QMessageBox.warning(parent,
- _('Editor launch failure'),
- _('%s : %s') % (cmd, str(e)))
- return False
-
+ qtlib.editfiles(repo, files, lineno, search, parent)
def viewmissing(parent, ui, repo, files):
base, _ = visdiff.snapshot(repo, files, repo['.'])
@@ -239,10 +226,10 @@ commands.revert(ui, repo, *files, **revertopts)
else:
res = qtlib.CustomPrompt(
- _('Confirm Revert'),
- _('Revert local file changes?'), parent,
- (_('&Revert with backup'), _('&Discard changes'),
- _('Cancel')), 2, 2, files).run()
+ _('Confirm Revert'),
+ _('Revert local file changes?'), parent,
+ (_('&Revert with backup'), _('&Discard changes'),
+ _('Cancel')), 2, 2, files).run()
if res == 2:
return False
if res == 1:
|
@@ -348,7 +348,14 @@ repopath = hglib.fromunicode(repopath)
self._openRepo(path=repopath, reuse=reuse)
- @pyqtSlot(unicode)
+ @pyqtSlot(QString)
+ def openLinkedRepo(self, path):
+ self.showRepo(path)
+ rw = self.repoTabsWidget.currentWidget()
+ if rw:
+ rw.taskTabsWidget.setCurrentIndex(rw.commitTabIndex)
+
+ @pyqtSlot(QString)
def showRepo(self, path):
"""Activate the repo tab or open it if not available [unicode]"""
for i in xrange(self.repoTabsWidget.count()):
@@ -483,7 +490,7 @@ rw.output.connect(self.log.output)
rw.makeLogVisible.connect(self.log.setShown)
rw.revisionSelected.connect(self.updateHistoryActions)
- rw.repoLinkClicked.connect(self.showRepo)
+ rw.repoLinkClicked.connect(self.openLinkedRepo)
rw.taskTabsWidget.currentChanged.connect(self.updateTaskViewMenu)
rw.toolbarVisibilityChanged.connect(self.updateToolBarActions)
|
Loading...