|
# qreorder.py - reorder unapplied MQ patches
#
# Copyright 2010 Steve Borho <steve@borho.org>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
import os
from hgext import mq
from tortoisehg.hgqt import qtlib, thgrepo, qrename
from tortoisehg.util import hglib, paths
from tortoisehg.hgqt.i18n import _
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# TODO:
# This approach will nuke any user configured guards
# Explicit refresh
class QReorderDialog(QDialog):
def __init__(self, repo, parent=None):
QDialog.__init__(self, parent)
self.setWindowTitle(_('Reorder Unapplied Patches'))
self.setWindowFlags(Qt.Window)
self.setWindowIcon(qtlib.geticon('hg-qreorder'))
self.repo = repo
self.cached = None
repo.repositoryChanged.connect(self.refresh)
layout = QVBoxLayout()
layout.setMargin(4)
self.setLayout(layout)
hb = QHBoxLayout()
hb.setMargin(2)
lbl = QLabel(_('Repository:'))
hb.addWidget(lbl)
le = QLineEdit()
hb.addWidget(le)
le.setReadOnly(True)
le.setFont(qtlib.getfont('fontlist').font())
le.setText(repo.displayname)
le.setFocusPolicy(Qt.NoFocus)
layout.addLayout(hb)
hl = qtlib.LabeledSeparator('')
layout.addWidget(hl)
class PatchListWidget(QListWidget):
menuRequested = pyqtSignal(QPoint, object)
def __init__(self, parent):
QListWidget.__init__(self, parent)
self.setCurrentRow(0)
def contextMenuEvent(self, event):
i = self.item(self.currentRow())
if i:
self.menuRequested.emit(event.globalPos(), i.patchname)
def focusInEvent(self, e):
i = self.item(self.currentRow())
if i:
self.parent().parent().showSummary(i)
QListWidget.focusInEvent(self, e)
ugb = QGroupBox(_('Unapplied Patches - drag to reorder'))
ugb.setLayout(QVBoxLayout())
ugb.layout().setContentsMargins(*(0,)*4)
self.ulw = PatchListWidget(self)
self.ulw.setDragDropMode(QListView.InternalMove)
ugb.layout().addWidget(self.ulw)
self.ulw.currentItemChanged.connect(lambda:
self.showSummary(self.ulw.item(self.ulw.currentRow())))
self.ulw.menuRequested.connect(self.patchlistMenuRequest)
layout.addWidget(ugb)
agb = QGroupBox(_('Applied Patches'))
agb.setLayout(QVBoxLayout())
agb.layout().setContentsMargins(*(0,)*4)
self.alw = PatchListWidget(self)
agb.layout().addWidget(self.alw)
self.alw.currentItemChanged.connect(lambda:
self.showSummary(self.alw.item(self.alw.currentRow())))
self.alw.menuRequested.connect(self.patchlistMenuRequest)
layout.addWidget(agb)
slbl = QLabel(_('Summary:'))
layout.addWidget(slbl)
self.summ = QTextEdit()
self.summ.setFont(qtlib.getfont('fontcomment').font())
self.summ.setMinimumWidth(500) # min 80 chars
self.summ.setMaximumHeight(100)
self.summ.setReadOnly(True)
self.summ.setFocusPolicy(Qt.NoFocus)
layout.addWidget(self.summ)
self._readsettings()
self.refresh()
# dialog buttons
BB = QDialogButtonBox
bb = QDialogButtonBox(BB.Ok|BB.Cancel)
self.apply_button = bb.button(BB.Apply)
bb.accepted.connect(self.accept)
bb.rejected.connect(self.reject)
bb.button(BB.Ok).setDefault(True)
layout.addWidget(bb)
self.alw.setCurrentRow(0)
self.ulw.setCurrentRow(0)
self.ulw.setFocus()
def patchlistMenuRequest(self, point, selection):
self.menuselection = selection
menu = QMenu(self)
act = QAction(_('Rename patch'), self)
act.triggered.connect(self.qrenamePatch)
menu.addAction(act)
menu.exec_(point)
def qrenamePatch(self):
patchname = self.menuselection
dlg = qrename.QRenameDialog(self.repo, patchname, self)
dlg.finished.connect(dlg.deleteLater)
if self.parent():
dlg.output.connect(self.parent().output)
dlg.makeLogVisible.connect(self.parent().makeLogVisible)
dlg.exec_()
def refresh(self):
patchnames = self.repo.mq.series[:]
applied = [p.name for p in self.repo.mq.applied]
if (patchnames, applied) == self.cached:
return
alw, ulw = self.alw, self.ulw
if self.cached:
if applied != self.cached[1]:
cw = alw
else:
cw = ulw
else:
cw = ulw
ar = alw.currentRow()
ur = ulw.currentRow()
ulw.clear()
alw.clear()
for p in reversed(patchnames):
ctx = self.repo.changectx(p)
desc = ctx.longsummary()
item = QListWidgetItem('[%s]\t%s' % (hglib.tounicode(p), desc))
# Save the patchname with the item so that we can easily
# retrieve it later
item.patchname = p
if p in applied:
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
item.setForeground(QColor(111,111,111)) # gray, like disabled
alw.addItem(item)
else:
item.setFlags(Qt.ItemIsSelectable |
Qt.ItemIsEnabled |
Qt.ItemIsDragEnabled)
ulw.addItem(item)
self.cached = patchnames, applied
if cw == ulw:
alw.setCurrentRow(ar)
ulw.setCurrentRow(ur)
self.ulw.setFocus()
else:
ulw.setCurrentRow(ur)
alw.setCurrentRow(ar)
self.alw.setFocus()
def showSummary(self, item):
if item is None:
self.summ.clear()
else:
ctx = self.repo.changectx(item.patchname)
self.summ.setText(hglib.tounicode(ctx.description()))
def accept(self):
self._writesettings()
applied = [self.alw.item(x).patchname
for x in xrange(self.alw.count())]
unapplied = [self.ulw.item(x).patchname
for x in xrange(self.ulw.count())]
writeSeries(self.repo, applied, unapplied)
QDialog.accept(self)
def reject(self):
QDialog.reject(self)
def closeEvent(self, event):
self._writesettings()
self.repo.repositoryChanged.disconnect(self.refresh)
super(QReorderDialog, self).closeEvent(event)
def _readsettings(self):
s = QSettings()
self.restoreGeometry(s.value('qreorder/geom').toByteArray())
def _writesettings(self):
s = QSettings()
s.setValue('qreorder/geom', self.saveGeometry())
def writeSeries(repo, applied, unapplied):
try:
repo.incrementBusyCount()
# The series file stores the oldest unapplied patch at the bottom, and
# the first applied patch at the top
lines = reversed(unapplied + applied)
if lines:
fp = repo.mq.opener('series', 'wb')
fp.write('\n'.join(lines))
fp.close()
finally:
repo.decrementBusyCount()
def run(ui, *pats, **opts):
repo = thgrepo.repository(None, paths.find_root())
if hasattr(repo, 'mq'):
return QReorderDialog(repo)
else:
qtlib.ErrorMsgBox(_('TortoiseHg Error'),
_('Please enable the MQ extension first.'))
|
Loading...