Commits

Yuya Nishihara committed 042be1e

refactoring reporeg

  • Participants
  • Parent commits 8010663

Comments (0)

Files changed (20)

+# HG changeset patch
+# User Yuya Nishihara <yuya@tcha.org>
+# Date 1343836385 -32400
+# Node ID 9b06a725b537d9ce91d57328cf1f7a777f205d93
+# Parent 2c34ed39de8e6f954744d10b2c2d4d913945898f
+qscilib: don't use lambda to emit "search backward" request by button
+
+XXX update comment why
+
+Normal function goes nicely with Qt signal than lambda. 1f16cc87f8a9
+
+diff --git a/tortoisehg/hgqt/qscilib.py b/tortoisehg/hgqt/qscilib.py
+--- a/tortoisehg/hgqt/qscilib.py
++++ b/tortoisehg/hgqt/qscilib.py
+@@ -414,8 +414,7 @@ class SearchToolBar(QToolBar):
+         self._wrapchk = QCheckBox(_('Wrap search'))
+         self.addWidget(self._wrapchk)
+         self._btprev = QPushButton('<< ' + _('Prev'))
+-        self._btprev.clicked.connect(
+-            lambda: self._emitSearchRequested(forward=False))
++        self._btprev.clicked.connect(self._emitSearchBackwardRequested)
+         self.addWidget(self._btprev)
+         self._bt = QPushButton(_('Next') + ' >>')
+         self._bt.clicked.connect(self._emitSearchRequested)
+@@ -482,6 +481,10 @@ class SearchToolBar(QToolBar):
+                                   self.wrapAround(), forward)
+ 
+     @pyqtSlot()
++    def _emitSearchBackwardRequested(self):
++        self._emitSearchRequested(forward=False)
++
++    @pyqtSlot()
+     def _updateSearchButtons(self):
+         enabled = bool(self._le.text())
+         self._btprev.setEnabled(enabled)

File annotate-new-icon.diff

+# HG changeset patch
+# Parent 175c8819e13cb4743a796b3fe24aa213e4e192bd
+diff --git a/icons/32x32/actions/view-annotate.png b/icons/32x32/actions/view-annotate.png
+new file mode 100644
+index 0000000000000000000000000000000000000000..1d97c9e1adc8be23e918fcf5d76bd3ab23a2e9e6
+GIT binary patch
+literal 1594
+zc$@(`2F3Y_P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800006VoOIv0RI60
+z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru+z1aBHVrTTbzT4f1;<H5
+zK~z}7y_aij9A_1VpYd+?lFd%m_By_796NDCnr7X4qsE~vO>NQ^K|u)A3RNglOB+=9
+zQAmW4P#}o>L=Y>MK$SpsX<DhG3ZY6tq9O^s$e}UVZJov&W5+diVsF;#+wRQl&Ns6k
+zKV}@qaw;})(vjxhXrA}H=bU%GQOtkt;dWdnKRhaf;YJ$bKOm;}DxdaT+3kQQ4Uc?a
+zcPGuwPcYtpke=~=Y29^5ekKBvhDXj_K1O&=nDVvdJh1aQ%6*dVV+o8q_Ae8m+^QBN
+z4Uf#G-letu*LayjX3tSH1X9=(^C?WNpY;3yLm6nhdyjHU9dO|9xo{24)FQkvh0u}+
+zZGeygn-s{_e@EUj0SoY*U+i$;ViIXiA%%@JXA#;3Ozk5?4ulS6S?GJ~8<6Ofw?x1K
+z+@t7=@Vr2ZEJC}0(0Z|S2QD<{_Rr6f?B2I>2a<+I?%dt!z)cr!<S7;`gf@toJL^EN
+zfm;StD{yJ>rIiVAtUrSX7hae|8hNB?yVZ9u!gH<w0~9Z4K~O7OZc;#^Q}&Ga%WUcl
+zt-FtaNFl`((kwV|%fK>57U2uG0g49#DrCG7;%!|wxQ2;N*>j>DEQ8jEe}k7Sh&08y
+zB(h*3g^AFH5!t^Z42d=grdzp`;9m>=N*Dwl+_t!e-ck$iInj=)HgV_n@8MN+Fw;nL
+z@+#ai#t_<Bgdwl?TNsP*)fF(LK-I>l0Q&}$FwrShwTbwB2k@4e?!ZkV3-d_JcHzAU
+zZO#Gbz|=w7;15F}0;vFa)E4f%zvBj@*tI@>-vJPlV5Sz~hKXfda^VwK`@R78t${!}
+z<U)`U5fYCchrZ{P(gnEiu(}yU+J#Sm$RhKWQ@!556z=xj7ji0>5g5}U@#t~9=MO5S
+ze~hkyH{bs=H)JNjoN;2-vMCnQnAzdQo@-#~U<>d^AQ*+@JZ#<7MR@E*rKGRn`^Gor
+zuDvJZ-FIwecw!szd!GZXADR1@;@lPN`8;+mMIrMx+Lb?IOo2WHS{jTQ=Z$I|WK_7I
+zwD3^#9%bFksnX8_-EY4^X4;3a6n=m7eNO)E6{q^VSd#BTck<oT9NX<Ycms~@!Kl;o
+z9bY^Be@ATD8h(F&2mkJQm-Ji}vHBRld*vOf*BWfCsalfn*G8<J2anHzua1Hlf*lW^
+zUN&$gIp9D4yi#4aiI6WvZ2dY~cRj(2#|B;a@_e@pC|l+1dawdK<#2uyf<uRuQa1d$
+zL+JGe2t_tAaq%SUs#My({B4FuKSpTXSjN(PSG;b}R5{iUOu_nXKP)-fuPZ>yX4t%C
+zD|N9Z&Yb!KYS>4|u@oZ<@p?_Z2UN%QU=&8Ouqx6<Q&~nSRlu?t7%kr~%XpgYiAEx8
+zw_w|nxBl{1^s*g1dnANuWO(wyD||iXR342(t_;pza)z!{>#ys;X!(Bmi=RBr^mLlQ
+zDhu0|jE&DB{f&$czQb&03SF1Hd@{-}KM0`*!4AN{7{uGUZWzAIfdl)#N>ltXVzuS`
+z`L*Bj`Q3ZDIFe#`=)a_|NUEZiyQ1)3?`l$WYxrp-#fE!+PDScZ%FUcBmI!EyKSo1C
+zEj86Dm669e{`w0P{Vfc9cn*{RLWZfSnPPTULDwb2Ba(mgxA5c57nPem*j#Oa_nuB!
+znEwwo)hcS(hd)$D&4w>9JkW>FC#bI9K<)Z^*2NOUY89%Yf-TK0eCwI66`d))0NzBW
+z)L(6<-n@vBO;9Y>(cAY4J^vacm$iu2#(4Ib$7$TSk(#<j8fFeFnfgQWg(LfDm^rMh
+zM1WE(%*gzk?O3B9P&fxiEtL`fPCh!Xaru)WqO~!0-1|9x^^|W#pidQW`YXu0Ding-
+zCDsIp35D@#iT&LUlG6r{eCbIl#}3{WIDn!}j>z<@hY0q)L~y(0@)@Yu+eJh@b=#oV
+s|2M4sku=_X2w&^Vcs#FvCUAiN0ktVjO>qKZdjJ3c07*qoM6N<$g3t&CZ2$lO
+
+diff --git a/icons/scalable/actions/view-annotate.svg b/icons/scalable/actions/view-annotate.svg
+deleted file mode 100644
+--- a/icons/scalable/actions/view-annotate.svg
++++ /dev/null
+@@ -1,140 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-
+-<svg
+-   xmlns:dc="http://purl.org/dc/elements/1.1/"
+-   xmlns:cc="http://creativecommons.org/ns#"
+-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+-   xmlns:svg="http://www.w3.org/2000/svg"
+-   xmlns="http://www.w3.org/2000/svg"
+-   xmlns:xlink="http://www.w3.org/1999/xlink"
+-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+-   width="48"
+-   height="48"
+-   id="svg2"
+-   version="1.1"
+-   inkscape:version="0.48.0 r9654"
+-   sodipodi:docname="view-annotate.svg">
+-  <title
+-     id="title3887">view annotations</title>
+-  <defs
+-     id="defs4">
+-    <linearGradient
+-       id="linearGradient3897">
+-      <stop
+-         style="stop-color:#427fbf;stop-opacity:1;"
+-         offset="0"
+-         id="stop3899" />
+-      <stop
+-         style="stop-color:#a6c2e1;stop-opacity:0.99130434;"
+-         offset="1"
+-         id="stop3901" />
+-    </linearGradient>
+-    <linearGradient
+-       gradientTransform="translate(-29.642857,849.92853)"
+-       y2="104.93361"
+-       x2="61.142857"
+-       y1="112.43361"
+-       x1="68.64286"
+-       gradientUnits="userSpaceOnUse"
+-       id="linearGradient2846"
+-       xlink:href="#linearGradient3897"
+-       inkscape:collect="always" />
+-  </defs>
+-  <sodipodi:namedview
+-     id="base"
+-     pagecolor="#ffffff"
+-     bordercolor="#666666"
+-     borderopacity="0.50196078"
+-     inkscape:pageopacity="0.0"
+-     inkscape:pageshadow="2"
+-     inkscape:zoom="8.9791667"
+-     inkscape:cx="3.6751741"
+-     inkscape:cy="24"
+-     inkscape:document-units="px"
+-     inkscape:current-layer="layer1"
+-     showgrid="true"
+-     inkscape:showpageshadow="true"
+-     showborder="true"
+-     inkscape:window-width="990"
+-     inkscape:window-height="603"
+-     inkscape:window-x="1611"
+-     inkscape:window-y="0"
+-     inkscape:window-maximized="0">
+-    <inkscape:grid
+-       type="xygrid"
+-       id="grid2997"
+-       empspacing="6"
+-       visible="true"
+-       enabled="true"
+-       snapvisiblegridlinesonly="true"
+-       spacingx="0.5px"
+-       spacingy="0.5px" />
+-  </sodipodi:namedview>
+-  <metadata
+-     id="metadata7">
+-    <rdf:RDF>
+-      <cc:Work
+-         rdf:about="">
+-        <dc:format>image/svg+xml</dc:format>
+-        <dc:type
+-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+-        <dc:title>view annotations</dc:title>
+-        <dc:date>2011-02-16</dc:date>
+-        <dc:creator>
+-          <cc:Agent>
+-            <dc:title>Peer Sommerlund</dc:title>
+-          </cc:Agent>
+-        </dc:creator>
+-        <cc:license
+-           rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+-      </cc:Work>
+-      <cc:License
+-         rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
+-        <cc:permits
+-           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+-        <cc:permits
+-           rdf:resource="http://creativecommons.org/ns#Distribution" />
+-        <cc:requires
+-           rdf:resource="http://creativecommons.org/ns#Notice" />
+-        <cc:requires
+-           rdf:resource="http://creativecommons.org/ns#Attribution" />
+-        <cc:permits
+-           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+-        <cc:requires
+-           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+-      </cc:License>
+-    </rdf:RDF>
+-  </metadata>
+-  <g
+-     inkscape:label="Layer 1"
+-     inkscape:groupmode="layer"
+-     id="layer1"
+-     transform="translate(0,-1004.3622)">
+-    <rect
+-       style="fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+-       id="rect3777"
+-       width="35"
+-       height="41"
+-       x="6.5"
+-       y="1007.8622" />
+-    <path
+-       style="fill:url(#linearGradient2846);fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+-       d="m 33,950.3622 0,6 -6,0 0,3 6,0 c 0,2.21541 0,6.94931 0,9 l -6,0 0,3 6,0 0,6 3,0 0,-6 9,0 0,6 3,0 0,-6 6,0 0,-3 -6,0 0,-9 6,0 0,-3 -6,0 0,-6 -3,0 0,6 -9,0 0,-6 z m 3,9 9,0 0,9 -9,0 z"
+-       id="path2900"
+-       inkscape:connector-curvature="0"
+-       sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc" />
+-    <text
+-       xml:space="preserve"
+-       style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+-       x="13"
+-       y="1042.3622"
+-       id="text3079"
+-       sodipodi:linespacing="125%"><tspan
+-         sodipodi:role="line"
+-         id="tspan3081"
+-         x="13"
+-         y="1042.3622">#</tspan></text>
+-  </g>
+-</svg>

File cmdhist2.patch

-# HG changeset patch
-# User Angel Ezquerra <angel.ezquerra@gmail.com>
-# Date 1343146716 -7200
-# Node ID 7bb163c0ef14957979a287220a79ae994193d607
-# Parent 369e0b23fbe5c8a7c9ade3ceb666d824481bb0ec
-docklog: add 'hg/thg command' completion
-
-If the user types a mercurial or tortoisehg command (i.e. starting with 'hg' or
-'thg') and presses TAB in addition to showing matching history items, show
-relevant mercurial/tortoisehg commands and/or command options.
-
-If both matching history commands and mercurial/thg commands are shown, the
-matching mercurial/thg commands are shown after the history commands.
-
-Also, do not show the list of matching commands if there is only a single
-matching command (just complete it).
-
-diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
---- a/tortoisehg/hgqt/docklog.py
-+++ b/tortoisehg/hgqt/docklog.py
-@@ -11,10 +11,10 @@ from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- from PyQt4.Qsci import QsciScintilla
- 
--from mercurial import util
-+from mercurial import commands, util
- 
- from tortoisehg.hgqt.i18n import _
--from tortoisehg.hgqt import cmdui
-+from tortoisehg.hgqt import cmdui, run
- from tortoisehg.util import hglib
- 
- class _LogWidgetForConsole(cmdui.LogWidget):
-@@ -215,8 +215,6 @@ class ConsoleWidget(QWidget):
- 
-     _cmdtable = _ConsoleCmdTable()
- 
--    # TODO: command history and completion
--
-     def __init__(self, parent=None):
-         super(ConsoleWidget, self).__init__(parent)
-         self.setLayout(QVBoxLayout())
-@@ -284,6 +282,58 @@ class ConsoleWidget(QWidget):
-     def historyNext(self, text):
-         self.historySearch(text, backwards=False)
- 
-+    def _commandComplete(self, cmdtype, cmdline):
-+        matches = []
-+        detailedmatches = []
-+        cmd = cmdline.split()
-+        if cmdtype == 'hg':
-+            cmdtable = commands.table
-+        else:
-+            cmdtable = run.table
-+        subcmd = ''
-+        if len(cmd) >= 2:
-+            subcmd = cmd[1].lower()
-+        def findhgcmd(cmdstart):
-+            matchinfo = {}
-+            for cmdspec in cmdtable:
-+                for cmdname in cmdspec.split('|'):
-+                    if cmdname[0] == '^':
-+                        cmdname = cmdname[1:]
-+                    if cmdname.startswith(cmdstart):
-+                        matchinfo[cmdname] = cmdspec
-+            return matchinfo
-+        matchingcmds = findhgcmd(subcmd)
-+        if not matchingcmds:
-+            return matches
-+        if len(matchingcmds) > 1:
-+            basecmdline = '%s %%s' % (cmdtype)
-+            matches = [basecmdline % c for c in matchingcmds]
-+        else:
-+            scmdtype = matchingcmds.keys()[0]
-+            cmdspec = matchingcmds[scmdtype]
-+            opts = cmdtable[cmdspec][1]
-+            def findcmdopt(cmdopt):
-+                cmdopt = cmdopt.lower()
-+                while(cmdopt.startswith('-')):
-+                    cmdopt = cmdopt[1:]
-+                matchingopts = []
-+                for opt in opts:
-+                    if opt[1].startswith(cmdopt):
-+                        matchingopts.append(opt)
-+                return matchingopts
-+            basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
-+            if len(cmd) == 2:
-+                matches = ['%s %s ' % (cmdtype, scmdtype)]
-+                matches += [basecmdline % opt[1] for opt in opts]
-+            else:
-+                cmdopt = cmd[-1]
-+                if cmdopt.startswith('-'):
-+                    # find the matching options
-+                    basecmdline = ' '.join(cmd[:-1]) + ' --%s'
-+                    cmdopts = findcmdopt(cmdopt)
-+                    matches = [basecmdline % opt[1] for opt in cmdopts]
-+        return sorted(matches)
-+
-     @pyqtSlot(unicode)
-     def historyComplete(self, text):
-         """
-@@ -296,17 +346,30 @@ class ConsoleWidget(QWidget):
-             self._logwidget.flash()
-             return
-         history = set(self._commandHistory)
-+        commonprefix = ''
-         matches = []
-         for cmdline in history:
-             if cmdline.startswith(text):
-                 matches.append(cmdline)
-+        if matches:
-+            matches.sort()
-+            commonprefix = os.path.commonprefix(matches)
-+        cmd = text.split()
-+        cmdtype = cmd[0].lower()
-+        if cmdtype in ('hg', 'thg'):
-+            hgcommandmatches = self._commandComplete(cmdtype, text)
-+            if hgcommandmatches:
-+                if not commonprefix:
-+                    commonprefix = os.path.commonprefix(hgcommandmatches)
-+                if matches:
-+                    matches.append('------ %s commands ------' % cmdtype)
-+                matches += hgcommandmatches
-         if not matches:
-             self._logwidget.flash()
-             return
--        matches.sort()
--        commonprefix = os.path.commonprefix(matches)
-         self._logwidget.setCommandText(commonprefix)
--        self._logwidget.append('\n' + '\n'.join(matches) + '\n')
-+        if len(matches) > 1:
-+            self._logwidget.append('\n' + '\n'.join(matches) + '\n')
- 
-     @util.propertycache
-     def _cmdcore(self):

File curbring.diff

+# HG changeset patch
+# Parent b25bc24d4bd289fcad3ac317e887b17ebc6834cb
+docklog: put original command at end of the history
+
+It's the common behavior of Bash or Zsh.
+
+diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
+--- a/tortoisehg/hgqt/docklog.py
++++ b/tortoisehg/hgqt/docklog.py
+@@ -288,7 +288,9 @@ class ConsoleWidget(QWidget):
+     def historySearch(self, text, direction):
+         cmdline, idx = _searchhistory(self._commandHistory, unicode(text),
+                                       direction, self._commandIdx)
+-        if cmdline:
++        if idx == 0:
++            cmdline = unicode(text)  # restore original command
++        if cmdline is not None:
+             self._commandIdx = idx
+             self._logwidget.setCommandText(cmdline, candidate=True)
+         else:

File docklog-left-by-angel.diff

-# HG changeset patch
-# User Angel Ezquerra <angel.ezquerra@gmail.com>
-# Date 1343393123 -7200
-# Node ID 012cb8f7bf67481fd3dced59a236f7c1d94c0f3f
-# Parent  804e9aab5c949190ed419e31e95726a572d5d658
-docklog: prompt line keyboard handling improvements
-
-This fixes several small command prompt inconsistencies in the way in which the
-prompt line was handled. In particular, we now make sure that the cursor always
-stays beyond the prompt:
-
-- Hitting "left" or "backspace" will never move the cursor into the prompt.
-- Typing any other key while the cursor is on the prompt part of the prompt line
-automatically moves the cursor to the end of the prompt line.
-- Hitting "ESC" clears the search string.
-
-diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
---- a/tortoisehg/hgqt/docklog.py
-+++ b/tortoisehg/hgqt/docklog.py
-@@ -39,23 +39,43 @@ class _LogWidgetForConsole(cmdui.LogWidg
-         self._flashtimer.timeout.connect(self._restoreColor)
- 
-     def keyPressEvent(self, event):
-+        if event.key() == Qt.Key_Escape:
-+            # When ESC is pressed, if the cursor is on the prompt,
-+            # this clears it, if not, this moves the cursor to the prompt
-+            self.setCommandText('')
-         cursoronprompt = self._cursoronpromptline()
-         if cursoronprompt:
-+            # Ensure the cursor is located after the prompt
-+            cursorpos = self.getCursorPosition()
-+            curcmd = self.commandText()
-+            promptlen = len(self._prompt)
-+            if cursorpos[1] <= promptlen:
-+                if event.key() in (Qt.Key_Backspace, Qt.Key_Left):
-+                    # Make sure that the cursor is right after the prompt
-+                    self.setCursorPosition(cursorpos[0], promptlen)
-+                    return
-+                if cursorpos[1] < promptlen:
-+                    # If the user types a key while the cursor is to the left
-+                    # of the prompt (e.g. if it clicked there with the mouse),
-+                    # move the cursor to the end of the prompt
-+                    self.setCursorPosition(cursorpos[0], promptlen + len(curcmd))
-+            # Up/Down trigger command and history search
-             if event.key() == Qt.Key_Up:
-                 return self.historyPrev.emit(self._searchText)
-             elif event.key() == Qt.Key_Down:
-                 return self.historyNext.emit(self._searchText)
-+            # Enter/Return trigger command execution
-             if event.key() in (Qt.Key_Return, Qt.Key_Enter):
-                 self._searchText = ''
--                return self.returnPressed.emit(self.commandText())
-+                return self.returnPressed.emit(curcmd)
-+            # Once we know that no history navigation or command execution was
-+            # requested, update the search text
-             if self._searchText == '':
-                 self._searchText = self.commandText()
-+            # Tab performs command completion
-+            # This _must_ be done _after_ the search text has been updated
-             if event.key() == Qt.Key_Tab:
--                return self.historyComplete.emit(self.commandText())
--        if event.key() == Qt.Key_Escape:
--            # When ESC is pressed, if the cursor is on the prompt,
--            # this clears it, if not, this moves the cursor to the prompt
--            self.setCommandText('')
-+                return self.historyComplete.emit(curcmd)
- 
-         super(_LogWidgetForConsole, self).keyPressEvent(event)
- 

File expandall-exp.diff

+# HG changeset patch
+# Parent 1e18cfa4f9167d95556b0804670d08441990f80c
+
+diff --git a/tortoisehg/hgqt/manifestdialog.py b/tortoisehg/hgqt/manifestdialog.py
+--- a/tortoisehg/hgqt/manifestdialog.py
++++ b/tortoisehg/hgqt/manifestdialog.py
+@@ -7,6 +7,7 @@
+ # 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.
++import time
+ 
+ from PyQt4.QtCore import *
+ from PyQt4.QtGui import *
+@@ -282,8 +283,16 @@ class ManifestWidget(QWidget, qtlib.Task
+     def _setupfilterupdater(self):
+         self._filterupdatetimer = QTimer(self, interval=200, singleShot=True)
+         self.le.textChanged.connect(self._filterupdatetimer.start)
+-        self._filterupdatetimer.timeout.connect(
+-            lambda: self._treemodel.setNameFilter(self.le.text()))
++        self._filterupdatetimer.timeout.connect(self._updateFilter)
++
++    @pyqtSlot()
++    def _updateFilter(self):
++        a = time.clock()
++        self._treemodel.setNameFilter(self.le.text())
++        b = time.clock()
++        self._treeview.expandAll()
++        c = time.clock()
++        print 'filter:', b - a, '; expand:', c - b, '; total:', c - a
+ 
+     @pyqtSlot()
+     def _autoexpandtree(self):

File historyexp.diff

-# HG changeset patch
-# Parent 78082b806be587a120efebd8e843776fe32971dd
-
-diff --git a/tortoisehg/hgqt/cmdui.py b/tortoisehg/hgqt/cmdui.py
---- a/tortoisehg/hgqt/cmdui.py
-+++ b/tortoisehg/hgqt/cmdui.py
-@@ -381,6 +381,8 @@ class _LogWidgetForConsole(LogWidget):
-     returnPressed = pyqtSignal(unicode)
-     """Return key pressed when cursor is on prompt line"""
- 
-+    historyRequested = pyqtSignal(int)
-+
-     _prompt = '% '
- 
-     def __init__(self, parent=None):
-@@ -394,6 +396,10 @@ class _LogWidgetForConsole(LogWidget):
-             if self._cursoronpromptline():
-                 self.returnPressed.emit(self.commandText())
-             return
-+        if event.key() in (Qt.Key_Up, Qt.Key_Down):
-+            if self._cursoronpromptline():
-+                self.historyRequested.emit(event.key() == Qt.Key_Up and -1 or 1)
-+            return
-         super(_LogWidgetForConsole, self).keyPressEvent(event)
- 
-     def setPrompt(self, text):
-@@ -463,6 +469,15 @@ class _LogWidgetForConsole(LogWidget):
-                 break
-         self.setCursorPosition(line, self.lineLength(line))
- 
-+    def setCommandText(self, text):
-+        """Replace the cunnret command text by the given one"""
-+        line = self.lines() - 1
-+        self._ensurePrompt(line)
-+        self.setSelection(line, len(self._prompt), line, self.lineLength(line))
-+        self.removeSelectedText()
-+        self.append(text)
-+        self.setCursorPosition(line, self.lineLength(line))
-+
-     def commandText(self):
-         """Return the current command text"""
-         l = self.lines() - 1
-@@ -502,7 +517,7 @@ class ConsoleWidget(QWidget):
- 
-     _cmdtable = _ConsoleCmdTable()
- 
--    # TODO: command history and completion
-+    # TODO: completion
- 
-     def __init__(self, parent=None):
-         super(ConsoleWidget, self).__init__(parent)
-@@ -513,10 +528,13 @@ class ConsoleWidget(QWidget):
-         self.setRepository(None)
-         self.openPrompt()
-         self.suppressPrompt = False
-+        self._cmdhistory = []
-+        self._cmdhistorypos = 0
- 
-     def _initlogwidget(self):
-         self._logwidget = _LogWidgetForConsole(self)
-         self._logwidget.returnPressed.connect(self._runcommand)
-+        self._logwidget.historyRequested.connect(self._showhistory)
-         self.layout().addWidget(self._logwidget)
- 
-         # compatibility methods with LogWidget
-@@ -564,6 +582,7 @@ class ConsoleWidget(QWidget):
-     def appendLog(self, msg, label):
-         """Append log text from another cmdui"""
-         self._logwidget.clearPrompt()
-+        self._cmdhistorypos = 0
-         try:
-             self._logwidget.appendLog(msg, label)
-         finally:
-@@ -588,6 +607,7 @@ class ConsoleWidget(QWidget):
- 
-     @pyqtSlot(unicode)
-     def _runcommand(self, cmdline):
-+        self._cmdhistorypos = 0
-         try:
-             args = list(self._parsecmdline(cmdline))
-         except ValueError, e:
-@@ -598,6 +618,8 @@ class ConsoleWidget(QWidget):
-         if not args:
-             self.openPrompt()
-             return
-+        if not self._cmdhistory or self._cmdhistory[-1] != cmdline:
-+            self._cmdhistory.append(cmdline)
-         cmd = args.pop(0)
-         try:
-             self._cmdtable[cmd](self, args)
-@@ -626,6 +648,17 @@ class ConsoleWidget(QWidget):
-         self._extproc.setWorkingDirectory(hglib.tounicode(self.cwd))
-         self._extproc.start(cmdline, QIODevice.ReadOnly)
- 
-+    @pyqtSlot(int)
-+    def _showhistory(self, inc):
-+        self._cmdhistorypos = min(max(self._cmdhistorypos + inc,
-+                                      -len(self._cmdhistory)),
-+                                  0)
-+        if self._cmdhistorypos < 0:
-+            cmdline = self._cmdhistory[self._cmdhistorypos]
-+        else:
-+            cmdline = ''  # XXX push/pop editing line
-+        self._logwidget.setCommandText(cmdline)
-+
-     @_cmdtable
-     def _cmd_hg(self, args):
-         self.closePrompt()

File import-history.patch

+# HG changeset patch
+# User Angel Ezquerra <angel.ezquerra@gmail.com>
+# Date 1343405897 -7200
+# Node ID 5a17c2bcc4c0cf1e348fce457a563a5e77622a07
+# Parent  7fd0c95d55c2516b76b0319cea4213a799f37646
+thgimport: save source list when the import dialog is closed
+
+New sources are added to the sources combobox when the "Browse" and "Browse Dir"
+buttons are used. These are saved when the dialog is closed, and the last 8
+are restored when the dialog is open again.
+
+I had to change the behavior of the dialog when the user hits enter and the
+focus is on the source combobox. It used to trigger an import, but now it will
+trigger a preview first. Hitting it again will import.
+
+Note that the sources are saved per repository.
+
+diff --git a/tortoisehg/hgqt/thgimport.py b/tortoisehg/hgqt/thgimport.py
+--- a/tortoisehg/hgqt/thgimport.py
++++ b/tortoisehg/hgqt/thgimport.py
+@@ -51,6 +51,8 @@
+         self.src_combo = QComboBox()
+         self.src_combo.setEditable(True)
+         self.src_combo.setMinimumWidth(310)
++        self.src_combo.setMaxVisibleItems(8)
++
+         self.file_btn = QPushButton(_('Browse...'))
+         self.file_btn.setAutoDefault(False)
+         self.file_btn.clicked.connect(self.browsefiles)
+@@ -123,9 +125,10 @@
+         self.detail_btn.toggled.connect(self.detail_toggled)
+         box.addWidget(buttons)
+ 
++        self.loadSettings()
++
+         # signal handlers
+-        self.src_combo.editTextChanged.connect(lambda *a: self.preview())
+-        self.src_combo.lineEdit().returnPressed.connect(self.thgimport)
++        self.src_combo.lineEdit().returnPressed.connect(self.preview)
+         self.p0chk.toggled.connect(lambda *a: self.preview())
+ 
+         # dialog setting
+@@ -181,8 +184,11 @@
+         if filelist:
+             # Qt file browser uses '/' in paths, even on Windows.
+             nl = QStringList([QDir.toNativeSeparators(x) for x in filelist])
+-            self.src_combo.setEditText(nl.join(os.pathsep))
++            qpath = nl.join(os.pathsep)
++            self.src_combo.insertItem(0, qpath)
++            self.src_combo.setEditText(qpath)
+             self.src_combo.setFocus()
++            self.preview()
+ 
+     def browsedir(self):
+         caption = _("Select Directory containing patches")
+@@ -190,8 +196,11 @@
+                                                 directory=self.repo.root,
+                                                 caption=caption)
+         if path:
+-            self.src_combo.setEditText(QDir.toNativeSeparators(path))
++            qpath = QDir.toNativeSeparators(path)
++            self.src_combo.insertItem(0, qpath)
++            self.src_combo.setEditText(qpath)
+             self.src_combo.setFocus()
++            self.preview()
+ 
+     def getcliptext(self):
+         text = hglib.fromunicode(QApplication.clipboard().text())
+@@ -203,6 +212,7 @@
+             self.src_combo.setEditText(curtext + os.pathsep + filename)
+         else:
+             self.src_combo.setEditText(filename)
++        self.preview()
+ 
+     def updatestatus(self):
+         items = self.cslist.curitems
+@@ -286,6 +296,37 @@
+         for path in self.tempfiles:
+             os.unlink(path)
+ 
++    def _getSources(self):
++        sources = []
++        for row in range(self.src_combo.count()):
++            sources.append(self.src_combo.model().item(row).text())
++        return sources
++
++    def _getSettingsName(self):
++        if not self.repo:
++            return None
++        return "import/sources/" + self.repo.root            
++
++    def loadSettings(self):
++        wb = self._getSettingsName()
++        if wb is None:
++            return  
++        s = QSettings()
++        sources = s.value(wb)
++        sources = sources.toStringList()
++        self.src_combo.addItems(QStringList(sources)) 
++        # make sure that the repo root is always on the source list
++        if self.repo.root not in sources:
++            self.src_combo.insertItem(0, QDir.toNativeSeparators(self.repo.root)) 
++        self.src_combo.setEditText('')
++
++    def saveSettings(self):
++        wb = self._getSettingsName()
++        if wb is None:
++            return
++        s = QSettings()
++        s.setValue(wb, self._getSources())
++
+     ### Override Handlers ###
+ 
+     def accept(self):
+@@ -294,6 +335,7 @@
+ 
+     def reject(self):
+         self.unlinktempfiles()
++        self.saveSettings()
+         super(ImportDialog, self).reject()
+ 
+     ### Signal Handlers ###

File mani-autoexpand.patch

+# HG changeset patch
+# User Angel Ezquerra <angel.ezquerra@gmail.com>
+# Date 1344374954 -7200
+# Node ID 07638e2f5444499048240ed38fa74c2c3c11b3e4
+# Parent  c1718bb37efd902533495110b1b913e4daa7ee27
+manifest: automatically expand the tree if the number of items is large, collapse it otherwise
+
+Up until now, using the manifest file filter would not automatically expand the
+manifest tree unless the clean files were not being shown. The result was that
+many filter matches would be hidden by default, and the user had to expand the
+correspoding tree folders to view them, with no way to expand them all.
+
+The reason for this behavoir was that it is expensive to expand a tree when the
+number of items is large.
+
+This change makes it so that if the number of items in the tree is less than 40,
+the tree will be automatically expanded. Otherwise the tree is automatically
+collapsed.
+
+In addition, it is possible to change this number of items limit, and whether
+the tree is collapsed when the number of items is greater than that limit. In
+order to do so, you can set the following configuration keys on the tortoisehg
+section:
+
+- manifest.autoexpand: Can be an integer or a boolean. Defaults to 40.
+    - integer: The maximum number of items that causes the tree to be
+    automatically expanded
+    - boolean: if True, always expand the tree; if False, never expand it
+    automatically
+- manifest.autocollapse: A boolean. Defaults to True
+    - if True, automatically collapse the tree when it is not automatically
+    expanded.
+
+diff --git a/tortoisehg/hgqt/manifestdialog.py b/tortoisehg/hgqt/manifestdialog.py
+--- a/tortoisehg/hgqt/manifestdialog.py
++++ b/tortoisehg/hgqt/manifestdialog.py
+@@ -260,6 +260,7 @@
+         self._treemodel = ManifestModel(self._repo, self._rev,
+                                         statusfilter=self._statusfilter.status(),
+                                         parent=self)
++        self._treemodel.fileringCompleted.connect(self._autoexpandtree)
+         self._treemodel.setNameFilter(self.le.text())
+ 
+         oldmodel = self._treeview.model()
+@@ -294,8 +295,33 @@
+     @pyqtSlot()
+     def _autoexpandtree(self):
+         """expand file tree if the number of the items isn't large"""
+-        if 'C' not in self._statusfilter.status():
++        model = self._treeview.model()
++        if model.numitems == 0:
++            return
++        # There may several conditions that may lead us to expand the tree
++        # Always expand if:
++        # 1. clean files are not being shown
++        expand = 'C' not in self._statusfilter.status()
++        if not expand:
++            # 2. an autoexpand limit has not been set and there
++            #    are not many files in the tree
++            # 3. an autoexpand limit has been set
++            #     This can be set as a number of items or as a boolean
++            try:
++                expandlimit = self._repo.ui.configint('tortoisehg',
++                    'manifest.autoexpand', 40)
++                expand = (model.numitems <= expandlimit)
++            except:
++                expand = self._repo.ui.configbool('tortoisehg',
++                    'manifest.autoexpand', False)
++        if expand:
+             self._treeview.expandAll()
++        else:
++            collapse = self._repo.ui.configbool('tortoisehg',
++                'manifest.autocollapse', True)
++            if collapse:
++                self._treeview.collapseAll()
++
+ 
+     def reload(self):
+         # TODO
+diff --git a/tortoisehg/hgqt/manifestmodel.py b/tortoisehg/hgqt/manifestmodel.py
+--- a/tortoisehg/hgqt/manifestmodel.py
++++ b/tortoisehg/hgqt/manifestmodel.py
+@@ -23,6 +23,7 @@
+     Qt model to display a hg manifest, ie. the tree of files at a
+     given revision. To be used with a QTreeView.
+     """
++    fileringCompleted = pyqtSignal()
+ 
+     StatusRole = Qt.UserRole + 1
+     """Role for file change status"""
+@@ -36,6 +37,7 @@
+ 
+         self._diricon = QApplication.style().standardIcon(QStyle.SP_DirIcon)
+         self._fileicon = QApplication.style().standardIcon(QStyle.SP_FileIcon)
++        self.numitems = 0
+         self._repo = repo
+         self._rev = rev
+         self._subinfo = {}
+@@ -232,6 +234,7 @@
+             return
+         self._namefilter = pattern
+         self._rebuildrootentry()
++        self.fileringCompleted.emit()
+ 
+     @property
+     def nameFilter(self):
+@@ -305,7 +308,9 @@
+             """Add files to the tree according to their state"""
+             if self._namefilter:
+                 files = fnmatch.filter(files, '*%s*' % self._namefilter)
++            numfiles = 0
+             for path in files:
++                numfiles += 1
+                 if not pathinstatus(path, status, uncleanpaths):
+                     continue
+ 
+@@ -324,9 +329,11 @@
+                         break
+                 else:
+                     e.setstatus('C')
++            return numfiles
+ 
+         # Add subrepos to the tree
+         def addrepocontentstotree(roote, ctx, toproot=''):
++            numitems = 0
+             subpaths = ctx.substate.keys()
+             for path in subpaths:
+                 if not 'S' in self._statusfilter:
+@@ -374,20 +381,22 @@
+                             self._subinfo[toprelpath]['ctx'] = sctx
+ 
+                             # Add the subrepo contents to the tree
+-                            e = addrepocontentstotree(e, sctx, toprelpath)
++                            e, numitemsinsub = \
++                                addrepocontentstotree(e, sctx, toprelpath)
++                            numitems += numitemsinsub
+ 
+             # Add regular files to the tree
+             status, uncleanpaths, files = getctxtreeinfo(ctx)
+ 
+-            addfilestotree(roote, files, status, uncleanpaths)
+-            return roote
++            numitems += addfilestotree(roote, files, status, uncleanpaths)
++            return roote, numitems
+ 
+         # Clear the _subinfo
+         self._subinfo = {}
+         roote = _Entry()
+         ctx = self._repo[self._rev]
+ 
+-        addrepocontentstotree(roote, ctx)
++        e, self.numitems = addrepocontentstotree(roote, ctx)
+         roote.sort()
+         return roote
+ 
+# HG changeset patch
+# Parent b0d15930286f5f16bfa5af098ba4eff1984d6463
+docklog: change _commandComplete() to a free function
+
+It does not depend on self.
+
+diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
+--- a/tortoisehg/hgqt/docklog.py
++++ b/tortoisehg/hgqt/docklog.py
+@@ -238,6 +238,57 @@ def _searchhistory(items, text, directio
+         idx += direction
+     return None, idx
+ 
++def _findsubcommands(cmdtype, cmdline):
++    matches = []
++    cmd = cmdline.split()
++    if cmdtype == 'hg':
++        cmdtable = commands.table
++    else:
++        cmdtable = run.table
++    subcmd = ''
++    if len(cmd) >= 2:
++        subcmd = cmd[1].lower()
++    def findhgcmd(cmdstart):
++        matchinfo = {}
++        for cmdspec in cmdtable:
++            for cmdname in cmdspec.split('|'):
++                if cmdname[0] == '^':
++                    cmdname = cmdname[1:]
++                if cmdname.startswith(cmdstart):
++                    matchinfo[cmdname] = cmdspec
++        return matchinfo
++    matchingcmds = findhgcmd(subcmd)
++    if not matchingcmds:
++        return matches
++    if len(matchingcmds) > 1:
++        basecmdline = '%s %%s' % (cmdtype)
++        matches = [basecmdline % c for c in matchingcmds]
++    else:
++        scmdtype = matchingcmds.keys()[0]
++        cmdspec = matchingcmds[scmdtype]
++        opts = cmdtable[cmdspec][1]
++        def findcmdopt(cmdopt):
++            cmdopt = cmdopt.lower()
++            while(cmdopt.startswith('-')):
++                cmdopt = cmdopt[1:]
++            matchingopts = []
++            for opt in opts:
++                if opt[1].startswith(cmdopt):
++                    matchingopts.append(opt)
++            return matchingopts
++        basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
++        if len(cmd) == 2:
++            matches = ['%s %s ' % (cmdtype, scmdtype)]
++            matches += [basecmdline % opt[1] for opt in opts]
++        else:
++            cmdopt = cmd[-1]
++            if cmdopt.startswith('-'):
++                # find the matching options
++                basecmdline = ' '.join(cmd[:-1]) + ' --%s'
++                cmdopts = findcmdopt(cmdopt)
++                matches = [basecmdline % opt[1] for opt in cmdopts]
++    return sorted(matches)
++
+ class _ConsoleCmdTable(dict):
+     """Command table for ConsoleWidget"""
+     _cmdfuncprefix = '_cmd_'
+@@ -294,57 +345,6 @@ class ConsoleWidget(QWidget):
+         else:
+             self._logwidget.flash()
+ 
+-    def _commandComplete(self, cmdtype, cmdline):
+-        matches = []
+-        cmd = cmdline.split()
+-        if cmdtype == 'hg':
+-            cmdtable = commands.table
+-        else:
+-            cmdtable = run.table
+-        subcmd = ''
+-        if len(cmd) >= 2:
+-            subcmd = cmd[1].lower()
+-        def findhgcmd(cmdstart):
+-            matchinfo = {}
+-            for cmdspec in cmdtable:
+-                for cmdname in cmdspec.split('|'):
+-                    if cmdname[0] == '^':
+-                        cmdname = cmdname[1:]
+-                    if cmdname.startswith(cmdstart):
+-                        matchinfo[cmdname] = cmdspec
+-            return matchinfo
+-        matchingcmds = findhgcmd(subcmd)
+-        if not matchingcmds:
+-            return matches
+-        if len(matchingcmds) > 1:
+-            basecmdline = '%s %%s' % (cmdtype)
+-            matches = [basecmdline % c for c in matchingcmds]
+-        else:
+-            scmdtype = matchingcmds.keys()[0]
+-            cmdspec = matchingcmds[scmdtype]
+-            opts = cmdtable[cmdspec][1]
+-            def findcmdopt(cmdopt):
+-                cmdopt = cmdopt.lower()
+-                while(cmdopt.startswith('-')):
+-                    cmdopt = cmdopt[1:]
+-                matchingopts = []
+-                for opt in opts:
+-                    if opt[1].startswith(cmdopt):
+-                        matchingopts.append(opt)
+-                return matchingopts
+-            basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
+-            if len(cmd) == 2:
+-                matches = ['%s %s ' % (cmdtype, scmdtype)]
+-                matches += [basecmdline % opt[1] for opt in opts]
+-            else:
+-                cmdopt = cmd[-1]
+-                if cmdopt.startswith('-'):
+-                    # find the matching options
+-                    basecmdline = ' '.join(cmd[:-1]) + ' --%s'
+-                    cmdopts = findcmdopt(cmdopt)
+-                    matches = [basecmdline % opt[1] for opt in cmdopts]
+-        return sorted(matches)
+-
+     @pyqtSlot(unicode)
+     def completeCommandText(self, text):
+         """Show the list of history or known commands matching the search text
+@@ -367,7 +367,7 @@ class ConsoleWidget(QWidget):
+         cmd = text.split()
+         cmdtype = cmd[0].lower()
+         if cmdtype in ('hg', 'thg'):
+-            hgcommandmatches = self._commandComplete(cmdtype, text)
++            hgcommandmatches = _findsubcommands(cmdtype, text)
+             if hgcommandmatches:
+                 if not commonprefix:
+                     commonprefix = os.path.commonprefix(hgcommandmatches)

File reporeg-cache-exp.diff

+# HG changeset patch
+# Parent 48ce38b4cb4f0f198cb25d56869c5a8f9c4d0141
+address slow startup speed caused by subrepo scan (issue #940)
+
+This patch shows a rough idea to avoid overhead of scanning subrepos at
+startup.
+
+https://bitbucket.org/tortoisehg/thg/issue/940/
+
+It includes:
+
+ - save subrepo items in thg-reporegistry.xml
+ - reload subrepo items when user opens the repository
+ - add option to scan all sub-repositories at startup (default: off),
+   which is currently called as "Show Subrepos on Registry"
+
+As you can see, this is an experimental patch and will introduce several
+bugs. I'll start writing a production code in this direction.
+
+diff --git a/tortoisehg/hgqt/reporegistry.py b/tortoisehg/hgqt/reporegistry.py
+--- a/tortoisehg/hgqt/reporegistry.py
++++ b/tortoisehg/hgqt/reporegistry.py
+@@ -401,6 +401,9 @@ class RepoRegistryView(QDockWidget):
+         if it:
+             self._activeTabRepo = it
+             it.setActive(True)
++            # XXX missing begin/endInsertRows() may cause crash
++            if not it.childs:  # XXX should refresh subrepos instead
++                it.appendSubrepos()
+             self.tview.dataChanged(QModelIndex(), QModelIndex())
+ 
+             # Make sure that the active tab is visible by expanding its parent
+diff --git a/tortoisehg/hgqt/repotreeitem.py b/tortoisehg/hgqt/repotreeitem.py
+--- a/tortoisehg/hgqt/repotreeitem.py
++++ b/tortoisehg/hgqt/repotreeitem.py
+@@ -248,6 +248,7 @@ class RepoItem(RepoTreeItem):
+         xw.writeAttribute('root', hglib.tounicode(self._root))
+         xw.writeAttribute('shortname', self.shortname())
+         xw.writeAttribute('basenode', node.hex(self.basenode()))
++        RepoTreeItem.dump(self, xw)
+ 
+     def undump(self, xr):
+         self._valid = True
+diff --git a/tortoisehg/hgqt/workbench.py b/tortoisehg/hgqt/workbench.py
+--- a/tortoisehg/hgqt/workbench.py
++++ b/tortoisehg/hgqt/workbench.py
+@@ -209,12 +209,12 @@ class Workbench(QMainWindow):
+                   checkable=True, menu='viewregistryopts')
+ 
+         self.actionShowSubrepos = \
+-            newaction(_("Show Subrepos on Registry"),
++            newaction(_("Scan repositories at Startup"),
+                 self.reporegistry.setShowSubrepos,
+                   checkable=True, menu='viewregistryopts')
+ 
+         self.actionShowNetworkSubrepos = \
+-            newaction(_("Show Subrepos for remote repositories"),
++            newaction(_("Scan remote repositories"),
+                 self.reporegistry.setShowNetworkSubrepos,
+                   checkable=True, menu='viewregistryopts')
+ 
+@@ -1055,9 +1055,9 @@ class Workbench(QMainWindow):
+         # settings), we tell the setters to avoid reloading the repo tree
+         # model, and then we  manually reload the model
+         ssr = s.value(wb + 'showSubrepos',
+-            defaultValue=QVariant(True)).toBool()
++            defaultValue=QVariant(False)).toBool()
+         snsr = s.value(wb + 'showNetworkSubrepos',
+-            defaultValue=QVariant(True)).toBool()
++            defaultValue=QVariant(False)).toBool()
+         ssp = s.value(wb + 'showShortPaths',
+             defaultValue=QVariant(True)).toBool()
+         self.reporegistry.setShowSubrepos(ssr, False)

File reporeg-moveactions.diff

+# HG changeset patch
+# Parent 554ec5dcf0089a8c9bbe823e72de81cf636fdcf5
+reporegistry: move QAction instances for setting flags from workbench
+
+This prepares to unify boolean flags and QAction instances.
+
+diff --git a/tortoisehg/hgqt/reporegistry.py b/tortoisehg/hgqt/reporegistry.py
+--- a/tortoisehg/hgqt/reporegistry.py
++++ b/tortoisehg/hgqt/reporegistry.py
+@@ -232,6 +232,7 @@ class RepoRegistryView(QDockWidget):
+         self.showSubrepos = showSubrepos
+         self.showNetworkSubrepos = showNetworkSubrepos
+         self.showShortPaths = showShortPaths
++        self._setupSettingActions()
+ 
+         self.setFeatures(QDockWidget.DockWidgetClosable |
+                          QDockWidget.DockWidgetMovable  |
+@@ -280,6 +281,25 @@ class RepoRegistryView(QDockWidget):
+         self._pendingReloadModel = False
+         self._activeTabRepo = None
+ 
++    def _setupSettingActions(self):
++        def newaction(text, slot):
++            a = QAction(text, self, checkable=True)
++            a.toggled.connect(slot)
++            return a
++
++        self._actionShowPaths = newaction(_("Show Paths"), self.showPaths)
++        self._actionShowSubrepos = newaction(_("Show Subrepos on Registry"),
++                                             self.setShowSubrepos)
++        self._actionShowNetworkSubrepos = newaction(_("Show Subrepos for "
++                                                      "remote repositories"),
++                                                    self.setShowNetworkSubrepos)
++        self._actionShowShortPaths = newaction(_("Show Short Paths"),
++                                               self.setShowShortPaths)
++
++    def settingActions(self):
++        return [self._actionShowPaths, self._actionShowSubrepos,
++                self._actionShowNetworkSubrepos, self._actionShowShortPaths]
++
+     def setShowSubrepos(self, show, reloadModel=True):
+         if self.showSubrepos != show:
+             self.showSubrepos = show
+diff --git a/tortoisehg/hgqt/workbench.py b/tortoisehg/hgqt/workbench.py
+--- a/tortoisehg/hgqt/workbench.py
++++ b/tortoisehg/hgqt/workbench.py
+@@ -203,24 +203,7 @@ class Workbench(QMainWindow):
+ 
+         newseparator(menu='view')
+         self.menuViewregistryopts = self.menuView.addMenu(_('Repository Registry Options'))
+-        self.actionShowPaths = \
+-        newaction(_("Show Paths"), self.reporegistry.showPaths,
+-                  checkable=True, menu='viewregistryopts')
+-
+-        self.actionShowSubrepos = \
+-            newaction(_("Show Subrepos on Registry"),
+-                self.reporegistry.setShowSubrepos,
+-                  checkable=True, menu='viewregistryopts')
+-
+-        self.actionShowNetworkSubrepos = \
+-            newaction(_("Show Subrepos for remote repositories"),
+-                self.reporegistry.setShowNetworkSubrepos,
+-                  checkable=True, menu='viewregistryopts')
+-
+-        self.actionShowShortPaths = \
+-            newaction(_("Show Short Paths"),
+-                self.reporegistry.setShowShortPaths,
+-                  checkable=True, menu='viewregistryopts')
++        self.menuViewregistryopts.addActions(self.reporegistry.settingActions())
+ 
+         newseparator(menu='view')
+         newaction(_("Choose Log Columns..."), self.setHistoryColumns,
+@@ -1017,11 +1000,11 @@ class Workbench(QMainWindow):
+         wb = "Workbench/"
+         s.setValue(wb + 'geometry', self.saveGeometry())
+         s.setValue(wb + 'windowState', self.saveState())
+-        s.setValue(wb + 'showPaths', self.actionShowPaths.isChecked())
+-        s.setValue(wb + 'showSubrepos', self.actionShowSubrepos.isChecked())
++        s.setValue(wb + 'showPaths', self.reporegistry._actionShowPaths.isChecked())
++        s.setValue(wb + 'showSubrepos', self.reporegistry._actionShowSubrepos.isChecked())
+         s.setValue(wb + 'showNetworkSubrepos',
+-            self.actionShowNetworkSubrepos.isChecked())
+-        s.setValue(wb + 'showShortPaths', self.actionShowShortPaths.isChecked())
++            self.reporegistry._actionShowNetworkSubrepos.isChecked())
++        s.setValue(wb + 'showShortPaths', self.reporegistry._actionShowShortPaths.isChecked())
+         s.setValue(wb + 'saveRepos', self.actionSaveRepos.isChecked())
+         repostosave = []
+         lastactiverepo = ''
+@@ -1064,9 +1047,9 @@ class Workbench(QMainWindow):
+ 
+         # Note that calling setChecked will NOT reload the model if the new
+         # setting is the same as the one in the repo registry
+-        QTimer.singleShot(0, lambda: self.actionShowSubrepos.setChecked(ssr))
+-        QTimer.singleShot(0, lambda: self.actionShowNetworkSubrepos.setChecked(ssr))
+-        QTimer.singleShot(0, lambda: self.actionShowShortPaths.setChecked(ssp))
++        QTimer.singleShot(0, lambda: self.reporegistry._actionShowSubrepos.setChecked(ssr))
++        QTimer.singleShot(0, lambda: self.reporegistry._actionShowNetworkSubrepos.setChecked(ssr))
++        QTimer.singleShot(0, lambda: self.reporegistry._actionShowShortPaths.setChecked(ssp))
+ 
+         # Manually reload the model now, to apply the settings
+         self.reporegistry.reloadModel()
+@@ -1103,7 +1086,7 @@ class Workbench(QMainWindow):
+ 
+         # Allow repo registry to assemble itself before toggling path state
+         sp = s.value(wb + 'showPaths').toBool()
+-        QTimer.singleShot(0, lambda: self.actionShowPaths.setChecked(sp))
++        QTimer.singleShot(0, lambda: self.reporegistry._actionShowPaths.setChecked(sp))
+ 
+     def goto(self, root, rev):
+         for rw in self._findrepowidget(root):

File reporeg-saverestore.diff

+# HG changeset patch
+# Parent c494758f7ed9422f98df3f95c4720c58ce0f5896
+reporegistry: load/save settings by itself
+
+With this change, the progress of reloadModel() happens to disappear due to
+the execution order. It should be fixed later.
+
+diff --git a/tortoisehg/hgqt/reporegistry.py b/tortoisehg/hgqt/reporegistry.py
+--- a/tortoisehg/hgqt/reporegistry.py
++++ b/tortoisehg/hgqt/reporegistry.py
+@@ -281,6 +281,54 @@ class RepoRegistryView(QDockWidget):
+         self._pendingReloadModel = False
+         self._activeTabRepo = None
+ 
++        self._loadSettings()
++
++    def _loadSettings(self):
++        s = QSettings()
++        wb = 'Workbench/'  # for compatibility with old release
++
++        # Load the repo registry settings. Note that we must allow the
++        # repo registry to assemble itself before toggling its settings
++        # Also the view path setttings should be enabled last, once we have
++        # loaded the repo subrepositories (if needed)
++
++        # Normally, checking the "show subrepos" and the "show network subrepos"
++        # settings will trigger a reload of the repo registry.
++        # To avoid reloading it twice (every time we set one of its view
++        # settings), we tell the setters to avoid reloading the repo tree
++        # model, and then we  manually reload the model
++        ssr = s.value(wb + 'showSubrepos',
++            defaultValue=QVariant(True)).toBool()
++        snsr = s.value(wb + 'showNetworkSubrepos',
++            defaultValue=QVariant(True)).toBool()
++        ssp = s.value(wb + 'showShortPaths',
++            defaultValue=QVariant(True)).toBool()
++        self.setShowSubrepos(ssr, False)
++        self.setShowNetworkSubrepos(snsr, False)
++        self.setShowShortPaths(ssp)
++
++        # Note that calling setChecked will NOT reload the model if the new
++        # setting is the same as the one in the repo registry
++        QTimer.singleShot(0, lambda: self._actionShowSubrepos.setChecked(ssr))
++        QTimer.singleShot(0, lambda: self._actionShowNetworkSubrepos.setChecked(ssr))
++        QTimer.singleShot(0, lambda: self._actionShowShortPaths.setChecked(ssp))
++
++        # Manually reload the model now, to apply the settings
++        self.reloadModel()
++
++        # Allow repo registry to assemble itself before toggling path state
++        sp = s.value(wb + 'showPaths').toBool()
++        QTimer.singleShot(0, lambda: self._actionShowPaths.setChecked(sp))
++
++    def _saveSettings(self):
++        s = QSettings()
++        wb = 'Workbench/'  # for compatibility with old release
++        s.setValue(wb + 'showPaths', self._actionShowPaths.isChecked())
++        s.setValue(wb + 'showSubrepos', self._actionShowSubrepos.isChecked())
++        s.setValue(wb + 'showNetworkSubrepos',
++            self._actionShowNetworkSubrepos.isChecked())
++        s.setValue(wb + 'showShortPaths', self._actionShowShortPaths.isChecked())
++
+     def _setupSettingActions(self):
+         def newaction(text, slot):
+             a = QAction(text, self, checkable=True)
+@@ -439,6 +487,7 @@ class RepoRegistryView(QDockWidget):
+         sfile = settingsfilename()
+         self.watcher.removePath(sfile)
+         self.tview.model().write(sfile)
++        self._saveSettings()
+ 
+     def _action_defs(self):
+         a = [("reloadRegistry", _("Refresh repository list"), 'view-refresh',
+diff --git a/tortoisehg/hgqt/workbench.py b/tortoisehg/hgqt/workbench.py
+--- a/tortoisehg/hgqt/workbench.py
++++ b/tortoisehg/hgqt/workbench.py
+@@ -1000,11 +1000,6 @@ class Workbench(QMainWindow):
+         wb = "Workbench/"
+         s.setValue(wb + 'geometry', self.saveGeometry())
+         s.setValue(wb + 'windowState', self.saveState())
+-        s.setValue(wb + 'showPaths', self.reporegistry._actionShowPaths.isChecked())
+-        s.setValue(wb + 'showSubrepos', self.reporegistry._actionShowSubrepos.isChecked())
+-        s.setValue(wb + 'showNetworkSubrepos',
+-            self.reporegistry._actionShowNetworkSubrepos.isChecked())
+-        s.setValue(wb + 'showShortPaths', self.reporegistry._actionShowShortPaths.isChecked())
+         s.setValue(wb + 'saveRepos', self.actionSaveRepos.isChecked())
+         repostosave = []
+         lastactiverepo = ''
+@@ -1025,35 +1020,6 @@ class Workbench(QMainWindow):
+         self.restoreGeometry(s.value(wb + 'geometry').toByteArray())
+         self.restoreState(s.value(wb + 'windowState').toByteArray())
+ 
+-        # Load the repo registry settings. Note that we must allow the
+-        # repo registry to assemble itself before toggling its settings
+-        # Also the view path setttings should be enabled last, once we have
+-        # loaded the repo subrepositories (if needed)
+-
+-        # Normally, checking the "show subrepos" and the "show network subrepos"
+-        # settings will trigger a reload of the repo registry.
+-        # To avoid reloading it twice (every time we set one of its view
+-        # settings), we tell the setters to avoid reloading the repo tree
+-        # model, and then we  manually reload the model
+-        ssr = s.value(wb + 'showSubrepos',
+-            defaultValue=QVariant(True)).toBool()
+-        snsr = s.value(wb + 'showNetworkSubrepos',
+-            defaultValue=QVariant(True)).toBool()
+-        ssp = s.value(wb + 'showShortPaths',
+-            defaultValue=QVariant(True)).toBool()
+-        self.reporegistry.setShowSubrepos(ssr, False)
+-        self.reporegistry.setShowNetworkSubrepos(snsr, False)
+-        self.reporegistry.setShowShortPaths(ssp)
+-
+-        # Note that calling setChecked will NOT reload the model if the new
+-        # setting is the same as the one in the repo registry
+-        QTimer.singleShot(0, lambda: self.reporegistry._actionShowSubrepos.setChecked(ssr))
+-        QTimer.singleShot(0, lambda: self.reporegistry._actionShowNetworkSubrepos.setChecked(ssr))
+-        QTimer.singleShot(0, lambda: self.reporegistry._actionShowShortPaths.setChecked(ssp))
+-
+-        # Manually reload the model now, to apply the settings
+-        self.reporegistry.reloadModel()
+-
+         save = s.value(wb + 'saveRepos').toBool()
+         self.actionSaveRepos.setChecked(save)
+ 
+@@ -1084,10 +1050,6 @@ class Workbench(QMainWindow):
+         s.setValue(wb + 'openrepos', '')
+         s.setValue(wb + 'lastactiverepo', '')
+ 
+-        # Allow repo registry to assemble itself before toggling path state
+-        sp = s.value(wb + 'showPaths').toBool()
+-        QTimer.singleShot(0, lambda: self.reporegistry._actionShowPaths.setChecked(sp))
+-
+     def goto(self, root, rev):
+         for rw in self._findrepowidget(root):
+             rw.goto(rev)
-signal.diff
-cmdhist2.patch
-docklog-left-by-angel.diff
-historyexp.diff
-stdkey.diff
+reporeg-moveactions.diff
+reporeg-saverestore.diff
+wb-delayload-exp.diff
+reporeg-cache-exp.diff
+annotate-new-icon.diff
+sync-exc.diff
+expandall-exp.diff
+syncwidget-test.diff
+mani-autoexpand.patch
+status-show-all-exp.diff
+13074.diff
+import-history.patch
+move.diff
+curbring.diff
 fd-filled.diff
 try1.diff
 setpathdebug.diff

File signal.diff

-# HG changeset patch
-# Parent c67b7e004fcc408fd819f053866ebddc8dc1cddd
-docklog: unify historyPrev and historyNext signals
-
-diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
---- a/tortoisehg/hgqt/docklog.py
-+++ b/tortoisehg/hgqt/docklog.py
-@@ -22,8 +22,7 @@ class _LogWidgetForConsole(cmdui.LogWidg
- 
-     returnPressed = pyqtSignal(unicode)
-     """Return key pressed when cursor is on prompt line"""
--    historyPrev = pyqtSignal(unicode)
--    historyNext = pyqtSignal(unicode)
-+    historyRequested = pyqtSignal(unicode, int)  # keyword, direction
-     historyComplete = pyqtSignal(unicode)
- 
-     _prompt = '% '
-@@ -42,9 +41,9 @@ class _LogWidgetForConsole(cmdui.LogWidg
-         cursoronprompt = not self.isReadOnly()
-         if cursoronprompt:
-             if event.key() == Qt.Key_Up:
--                return self.historyPrev.emit(self.commandText())
-+                return self.historyRequested.emit(self.commandText(), -1)
-             elif event.key() == Qt.Key_Down:
--                return self.historyNext.emit(self.commandText())
-+                return self.historyRequested.emit(self.commandText(), +1)
-             del self._savedcommands[:]  # settle candidate by user input
-             if event.key() in (Qt.Key_Return, Qt.Key_Enter):
-                 return self.returnPressed.emit(self.commandText())
-@@ -232,8 +231,7 @@ class ConsoleWidget(QWidget):
-     def _initlogwidget(self):
-         self._logwidget = _LogWidgetForConsole(self)
-         self._logwidget.returnPressed.connect(self._runcommand)
--        self._logwidget.historyPrev.connect(self.historyPrev)
--        self._logwidget.historyNext.connect(self.historyNext)
-+        self._logwidget.historyRequested.connect(self.historySearch)
-         self._logwidget.historyComplete.connect(self.historyComplete)
-         self.layout().addWidget(self._logwidget)
- 
-@@ -241,19 +239,18 @@ class ConsoleWidget(QWidget):
-         for name in ('openPrompt', 'closePrompt', 'clear'):
-             setattr(self, name, getattr(self._logwidget, name))
- 
--    def historySearch(self, text, backwards=True):
-+    @pyqtSlot(unicode, int)
-+    def historySearch(self, text, direction):
-+        assert direction != 0
-         if not self._commandHistory:
-             self._logwidget.flash()
-             return
-         text = unicode(text)
--        def getNextIdx(backwards, curIdx):
-+        def getNextIdx(curIdx):
-             nextIdx = curIdx
-             if nextIdx is None:
-                 nextIdx = len(self._commandHistory)
--            if backwards:
--                nextIdx -= 1
--            else:
--                nextIdx += 1
-+            nextIdx += direction
-             if 0 <= nextIdx < len(self._commandHistory):
-                 return nextIdx
-             else:
-@@ -262,7 +259,7 @@ class ConsoleWidget(QWidget):
-         cmdline = ''
-         idx = self._commandIdx
-         while True:
--            idx = getNextIdx(backwards, idx)
-+            idx = getNextIdx(idx)
-             if idx is None:
-                 break
-             curcmdline = self._commandHistory[idx]
-@@ -277,14 +274,6 @@ class ConsoleWidget(QWidget):
-             self._logwidget.flash()
- 
-     @pyqtSlot(unicode)
--    def historyPrev(self, text):
--        self.historySearch(text, backwards=True)
--
--    @pyqtSlot(unicode)
--    def historyNext(self, text):
--        self.historySearch(text, backwards=False)
--
--    @pyqtSlot(unicode)
-     def historyComplete(self, text):
-         """
-         Show the list of history items matching the search text

File status-show-all-exp.diff

+# HG changeset patch
+# Parent 0e17491f648a432f01568c3c9ec8774b8aa3328b
+
+diff --git a/tortoisehg/hgqt/status.py b/tortoisehg/hgqt/status.py
+--- a/tortoisehg/hgqt/status.py
++++ b/tortoisehg/hgqt/status.py
+@@ -241,7 +241,7 @@ class StatusWidget(QWidget):
+         if model and model.rowCount(QModelIndex()):
+             smodel = self.tv.selectionModel()
+             curidx = smodel.currentIndex()
+-            if curidx.isValid():
++            if curidx.isValid() and curidx.row() != model.rowCount() - 1:
+                 curpath = model.getRow(curidx)[COL_PATH]
+             else:
+                 curpath = None
+@@ -401,6 +401,10 @@ class StatusWidget(QWidget):
+     #@pyqtSlot(QModelIndex, QModelIndex)
+     def onCurrentChange(self, index, old):
+         'Connected to treeview "currentChanged" signal'
++        if index.row() == self.tv.model().rowCount() - 1:
++            # assume that "show unmodified" link clicked
++            self.statusfilter.setStatus(self.statusfilter.status() + 'C')
++            return
+         row = index.model().getRow(index)
+         if row is None:
+             return
+@@ -627,10 +631,10 @@ class WctxModel(QAbstractTableModel):
+         self.rows = rows
+         self.checkable = checkable
+ 
+-    def rowCount(self, parent):
++    def rowCount(self, parent=QModelIndex()):
+         if parent.isValid():
+             return 0 # no child
+-        return len(self.rows)
++        return len(self.rows) + 1
+ 
+     def check(self, files, state=True):
+         for f in files:
+@@ -652,6 +656,8 @@ class WctxModel(QAbstractTableModel):
+     def data(self, index, role):
+         if not index.isValid():
+             return QVariant()
++        if index.row() == len(self.rows):
++            return self._epilogueData(index, role)
+ 
+         path, status, mst, upath, ext, sz = self.rows[index.row()]
+         if index.column() == COL_PATH:
+@@ -683,6 +689,23 @@ class WctxModel(QAbstractTableModel):
+         '''
+         return QVariant()
+ 
++    def _epilogueData(self, index, role):
++        if index.column() != COL_PATH_DISPLAY:
++            return
++        if role == Qt.DisplayRole:
++            # XXX should only be available if 'clean' files are hidden
++            return _('Show unmodified files...')
++        if role == Qt.SizeHintRole:
++            return QSize(80, 30)  # XXX just want to increase height
++        # imitate hyper-link style
++        if role == Qt.ForegroundRole:
++            return QBrush(QColor('blue'))
++        if role == Qt.FontRole:
++            font = QFont()
++            font.setItalic(True)
++            font.setUnderline(True)
++            return font
++
+     def headerData(self, col, orientation, role):
+         if role != Qt.DisplayRole or orientation != Qt.Horizontal:
+             return QVariant()
+@@ -690,6 +713,8 @@ class WctxModel(QAbstractTableModel):
+             return QVariant(self.headers[col])
+ 
+     def flags(self, index):
++        if index.row() == len(self.rows):
++            return Qt.ItemIsEnabled
+         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled
+         if index.column() == COL_PATH and self.checkable:
+             flags |= Qt.ItemIsUserCheckable

File stdkey.diff

-# HG changeset patch
-# Parent 894ecf0ab97f7b6cdb9cbb57cafeaa18b9a64481
-honor secondary key of QKeySequence.StandardKey (fixes #2045)
-
-XXX incomplete
-
-diff --git a/tortoisehg/hgqt/commit.py b/tortoisehg/hgqt/commit.py
---- a/tortoisehg/hgqt/commit.py
-+++ b/tortoisehg/hgqt/commit.py
-@@ -1295,7 +1295,8 @@ class CommitDialog(QDialog):
-         self.commit.reload()
-         self.updateUndo()
-         self.commit.msgte.setFocus()
--        QShortcut(QKeySequence.Refresh, self, self.refresh)
-+        for key in QKeySequence.keyBindings(QKeySequence.Refresh):
-+            QShortcut(key, self, self.refresh)
- 
-     def done(self, ret):
-         self.commit.repo.configChanged.disconnect(self.commit.configChanged)
-diff --git a/tortoisehg/hgqt/filedialogs.py b/tortoisehg/hgqt/filedialogs.py
---- a/tortoisehg/hgqt/filedialogs.py
-+++ b/tortoisehg/hgqt/filedialogs.py
-@@ -114,8 +114,10 @@ class FileLogDialog(_AbstractFileDialog)
-         self.editToolbar = QToolBar(self)
-         self.editToolbar.setContextMenuPolicy(Qt.PreventContextMenu)
-         self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.editToolbar)
--        self.actionClose = QAction(self, shortcut=QKeySequence.Close)
--        self.actionReload = QAction(self, shortcut=QKeySequence.Refresh)
-+        self.actionClose = QAction(self)
-+        self.actionClose.setShortcuts(QKeySequence.Close)
-+        self.actionReload = QAction(self)
-+        self.actionReload.setShortcuts(QKeySequence.Refresh)
-         self.editToolbar.addAction(self.actionReload)
-         self.addAction(self.actionClose)
- 
-@@ -357,8 +359,10 @@ class FileDiffDialog(_AbstractFileDialog
-         self.editToolbar = QToolBar(self)
-         self.editToolbar.setContextMenuPolicy(Qt.PreventContextMenu)
-         self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.editToolbar)
--        self.actionClose = QAction(self, shortcut=QKeySequence.Close)
--        self.actionReload = QAction(self, shortcut=QKeySequence.Refresh)
-+        self.actionClose = QAction(self)
-+        self.actionClose.setShortcuts(QKeySequence.Close)
-+        self.actionReload = QAction(self)
-+        self.actionReload.setShortcuts(QKeySequence.Refresh)
-         self.editToolbar.addAction(self.actionReload)
-         self.addAction(self.actionClose)
- 
-diff --git a/tortoisehg/hgqt/fileview.py b/tortoisehg/hgqt/fileview.py
---- a/tortoisehg/hgqt/fileview.py
-+++ b/tortoisehg/hgqt/fileview.py
-@@ -179,7 +179,7 @@ class HgFileView(QFrame):
-         self.actionFind = self.searchbar.toggleViewAction()
-         self.actionFind.setIcon(qtlib.geticon('edit-find'))
-         self.actionFind.setToolTip(_('Toggle display of text search bar'))
--        self.actionFind.setShortcut(QKeySequence.Find)
-+        self.actionFind.setShortcuts(QKeySequence.Find)
- 
-         self.actionShelf = QAction('Shelve', self)
-         self.actionShelf.setIcon(qtlib.geticon('shelve'))
-diff --git a/tortoisehg/hgqt/mq.py b/tortoisehg/hgqt/mq.py
---- a/tortoisehg/hgqt/mq.py
-+++ b/tortoisehg/hgqt/mq.py
-@@ -705,7 +705,8 @@ class MQWidget(QWidget, qtlib.TaskWidget
-             self.layout().addWidget(self.statusbar)
-             self.progress.connect(self.statusbar.progress)
-             self.showMessage.connect(self.statusbar.showMessage)
--            QShortcut(QKeySequence.Refresh, self, self.reload)
-+            for key in QKeySequence.keyBindings(QKeySequence.Refresh):
-+                QShortcut(key, self, self.reload)
-             self.resize(850, 550)
- 
-         self.loadConfigs()
-diff --git a/tortoisehg/hgqt/workbench.py b/tortoisehg/hgqt/workbench.py
---- a/tortoisehg/hgqt/workbench.py
-+++ b/tortoisehg/hgqt/workbench.py
-@@ -439,7 +439,11 @@ class Workbench(QMainWindow):
-             else:
-                 action.setIcon(qtlib.getmenuicon(icon))
-         if shortcut:
--            action.setShortcut(qtlib.keysequence(shortcut))
-+            keyseq = qtlib.keysequence(shortcut)
-+            if isinstance(keyseq, QKeySequence.StandardKey):
-+                action.setShortcuts(keyseq)
-+            else:
-+                action.setShortcut(keyseq)
-         if tooltip:
-             action.setToolTip(tooltip)
-         if data is not None:

File sync-exc.diff

+# HG changeset patch
+# Parent 3367f8f7b0c223356e77a532ad890b2fa06d240a
+
+diff --git a/tortoisehg/hgqt/sync.py b/tortoisehg/hgqt/sync.py
+--- a/tortoisehg/hgqt/sync.py
++++ b/tortoisehg/hgqt/sync.py
+@@ -1041,12 +1041,8 @@ class SyncWidget(QWidget, qtlib.TaskWidg
+         if branch == '':
+             branch = None
+         if pushall and (rev is not None or branch is not None):
+-            # This should never happen
+-            qtlib.ErrorMsg(_('Internal TortoiseHg Error'),
+-                _('Inconsistent call to SyncWidget.pushclicked()'),
+-                _('Cannot call SyncWidget.pushclicked() with pushall=True, '
+-                'rev!=None and branch!=None'))
+-            return
++            raise ValueError('inconsistent call with pushall=%r, rev=%r and '
++                             'branch=%r' % (pushall, rev, branch))
+         validopts = ('force', 'new-branch', 'branch', 'rev', 'bookmark', 'mq')
+         self.syncStarted.emit()
+         url = self.currentPushUrl()

File syncwidget-test.diff

+# HG changeset patch
+# Parent d1f1fd1cecedb0eb2f857efa0bf0bf45b6140bfd
+
+diff --git a/tests/widget/sync_widget_test.py b/tests/widget/sync_widget_test.py
+new file mode 100644
+--- /dev/null
++++ b/tests/widget/sync_widget_test.py
+@@ -0,0 +1,30 @@
++import unittest
++from tortoisehg.hgqt import qtlib, sync, thgrepo
++
++import helpers
++
++class SyncWidgetUrlEntryTest(unittest.TestCase):
++    @classmethod
++    def setUpClass(cls):
++        hg = helpers.HgClient(helpers.mktmpdir(__name__))
++        hg.init()
++        cls.repo = thgrepo.repository(path=hg.path)
++
++    @classmethod
++    def tearDownClass(cls):
++        del cls.repo
++
++    def setUp(self):
++        qtlib.initfontcache(self.repo.ui)
++        self.widget = sync.SyncWidget(self.repo, parent=None)
++
++    def tearDown(self):
++        del self.widget
++        qtlib._fontcache.clear()
++
++    def test_xxx(self):
++        self.widget.setUrl('https://example.org::8000/bar/baz')
++        self.assertEqual('https', self.widget.schemecombo.currentText())
++        self.assertEqual('example.org', self.widget.hostentry.text())
++        self.assertEqual('8000', self.widget.portentry.text())
++        self.assertEqual('bar/baz', self.widget.pathentry.text())

File wb-delayload-exp.diff

+# HG changeset patch
+# Parent 554ec5dcf0089a8c9bbe823e72de81cf636fdcf5
+diff --git a/tortoisehg/hgqt/workbench.py b/tortoisehg/hgqt/workbench.py
+--- a/tortoisehg/hgqt/workbench.py
++++ b/tortoisehg/hgqt/workbench.py
+@@ -1068,9 +1068,6 @@ class Workbench(QMainWindow):
+         QTimer.singleShot(0, lambda: self.actionShowNetworkSubrepos.setChecked(ssr))
+         QTimer.singleShot(0, lambda: self.actionShowShortPaths.setChecked(ssp))
+ 
+-        # Manually reload the model now, to apply the settings
+-        self.reporegistry.reloadModel()
+-
+         save = s.value(wb + 'saveRepos').toBool()
+         self.actionSaveRepos.setChecked(save)
+ 
+@@ -1260,23 +1257,27 @@ def run(ui, *pats, **opts):
+         mustcreateserver = not serverexists
+ 
+     w = Workbench(createserver=mustcreateserver)
+-    if root:
+-        root = hglib.tounicode(root)
+-        bundle = opts.get('bundle')
+-        if bundle:
+-            w._openRepo(root, False, bundle=bundle)
+-        else:
+-            w.showRepo(root)
++    def init():
++        # Manually reload the model now, to apply the settings
++        w.reporegistry.reloadModel()
++        if root:
++            uroot = hglib.tounicode(root)
++            bundle = opts.get('bundle')
++            if bundle:
++                w._openRepo(uroot, False, bundle=bundle)
++            else:
++                w.showRepo(uroot)
+ 
+-        if pats:
+-            q = []
+-            for pat in pats:
+-                f = repo.wjoin(pat)
+-                if os.path.isdir(f):
+-                    q.append('file("%s/**")' % pat)
+-                elif os.path.isfile(f):
+-                    q.append('file("%s")' % pat)
+-            w.setRevsetFilter(root, ' or '.join(q))
+-    if w.repoTabsWidget.count() <= 0:
+-        w.reporegistry.setVisible(True)
++            if pats:
++                q = []
++                for pat in pats:
++                    f = repo.wjoin(pat)
++                    if os.path.isdir(f):
++                        q.append('file("%s/**")' % pat)
++                    elif os.path.isfile(f):
++                        q.append('file("%s")' % pat)
++                w.setRevsetFilter(uroot, ' or '.join(q))
++        if w.repoTabsWidget.count() <= 0:
++            w.reporegistry.setVisible(True)
++    QTimer.singleShot(0, init)
+     return w