LoginSignup
1

More than 5 years have passed since last update.

TortoiseHgのファイルビューを少し改造してみる

Last updated at Posted at 2012-12-07
  • [2012/12/07追記] masterのdefaultブランチにこの修正をマージしてもらいました。

やりたいこと

TortoiseHgで、ファイルのDiffやBlameを表示すると、変更箇所を表示するインジケータが一緒に表示されますよね?
thg-fileview

ウインドウをスクロールするとそれにあわせて灰色の箱が動いたりするんですが、ここ、クリックしたくなりませんか?
クリックしたらその位置にジャンプしてくれるととてもうれしいんですが。僕は。

やったこと

という訳で少し手を入れてみました。
https://bitbucket.org/iwata0303/thg/commits/bbb613be1df57a43c4e3f6c20aa10ad45fe26c93

tortoisehg/hgqt/blockmatcher.pyというファイルがあって、そこにあるBlockListというクラスにこのメソッドを追加してます。

blockmatcher.py
    def scrollToPos(self, y):
        # Scroll to the position which specified by Y coodinate.
        if not isinstance(self._sbar, QScrollBar):
            return
        ratio = float(y) / self.height()
        minimum, maximum, step = self._minimum, self._maximum, self._pagestep
        value = minimum + (maximum + step - minimum) * ratio - (step * 0.5)
        value = min(maximum, max(minimum, value))  # round to valid range.
        self.setValue(value)

    def mousePressEvent(self, event):
        super(BlockList, self).mousePressEvent(event)
        self.scrollToPos(event.y())

    def mouseMoveEvent(self, event):
        super(BlockList, self).mouseMoveEvent(event)
        self.scrollToPos(event.y())

これで、インジケータ上をクリックすればその位置までジャンプしますし、そのまま上下にドラッグすればスクロールも連動するようになりました。

プラグインにしてみる

さて、とはいえ、これだけのためにTortoiseHgのソースを入手してビルドして、というのも面倒な話ですね。

ちょっと良い子にはお勧めできない系になりますが 、エクステンションを使ってモンキーパッチあててみます。

thg_blocklist_patch.py
# -*- coding:utf-8 -*-
def extsetup():
    import sys
    import os
    # thg.exeやthgw.exeから実行されたときだけ処理をするようにする
    if not os.path.basename(sys.argv[0]).startswith('thg'):
        return

    from PyQt4.QtGui import QScrollBar

    from tortoisehg.hgqt.blockmatcher import BlockList
    from types import MethodType

    mousePressEvent_org = BlockList.mousePressEvent
    mouseMoveEvent_org = BlockList.mouseMoveEvent

    def scrollToPos(bl, y):
        # Scroll to the position which specified by Y coodinate.
        if not isinstance(bl._sbar, QScrollBar):
            return
        ratio = float(y) / bl.height()
        minimum, maximum, step = bl._minimum, bl._maximum, bl._pagestep
        value = minimum + (maximum + step - minimum) * ratio - (step * 0.5)
        value = min(maximum, max(minimum, value))  # round to valid range.
        bl.setValue(value)

    def mousePressEvent(self, event):
        mousePressEvent_org(self, event)
        scrollToPos(self, event.y())

    def mouseMoveEvent(self, event):
        mouseMoveEvent_org(self, event)
        scrollToPos(self, event.y())

    BlockList.mousePressEvent = MethodType(mousePressEvent, None, BlockList)
    BlockList.mouseMoveEvent = MethodType(mouseMoveEvent, None, BlockList)

ふつうにhgコマンドを叩いた時に悪さされても困るので、thg*.exeとかから実行されたときだけ処理をするようにしています。
確認してませんがLinuxとかだと sys.arg[0] はpythonのパスが入ってくると思うので、その場合は sys.arg[1] でチェックする感じで。

このファイルを適当にエクステンションとして登録すれば、本体のソースに手を入れなくてもいけるようになります。
あくまでモンキーパッチなので、バージョンアップなどの際にはご注意を。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1