1# qfold.py - QFold dialog for TortoiseHg 2# 3# Copyright 2010 Steve Borho <steve@borho.org> 4# Copyright 2010 Johan Samyn <johan.samyn@gmail.com> 5# 6# This software may be used and distributed according to the terms of the 7# GNU General Public License version 2, incorporated herein by reference. 8 9from __future__ import absolute_import 10 11from .qtcore import ( 12 QSettings, 13 Qt, 14 pyqtSlot, 15) 16from .qtgui import ( 17 QCheckBox, 18 QDialog, 19 QDialogButtonBox, 20 QGroupBox, 21 QLabel, 22 QListView, 23 QListWidget, 24 QListWidgetItem, 25 QShortcut, 26 QTextEdit, 27 QVBoxLayout, 28) 29 30from hgext import mq 31from mercurial import ( 32 context, 33 pycompat, 34) 35 36from ..util import hglib 37from ..util.i18n import _ 38from . import ( 39 messageentry, 40 qscilib, 41 qtlib, 42) 43 44class QFoldDialog(QDialog): 45 46 def __init__(self, repoagent, patches, parent): 47 super(QFoldDialog, self).__init__(parent) 48 self._repoagent = repoagent 49 self.setWindowTitle(_('Patch fold - %s') % repoagent.displayName()) 50 self.setWindowIcon(qtlib.geticon('hg-qfold')) 51 52 f = self.windowFlags() 53 self.setWindowFlags(f & ~Qt.WindowContextHelpButtonHint 54 | Qt.WindowMaximizeButtonHint) 55 56 self.setLayout(QVBoxLayout()) 57 58 mlbl = QLabel(_('New patch message:')) 59 self.layout().addWidget(mlbl) 60 self.msgte = messageentry.MessageEntry(self) 61 self.msgte.installEventFilter(qscilib.KeyPressInterceptor(self)) 62 self.layout().addWidget(self.msgte) 63 64 self.keepchk = QCheckBox(_('Keep patch files')) 65 self.keepchk.setChecked(True) 66 self.layout().addWidget(self.keepchk) 67 68 q = self.repo.mq 69 q.parseseries() 70 patches = [p for p in q.series if p in patches] 71 72 class PatchListWidget(QListWidget): 73 def __init__(self, parent): 74 QListWidget.__init__(self, parent) 75 self.setCurrentRow(0) 76 def focusInEvent(self, event): 77 i = self.item(self.currentRow()) 78 if i: 79 self.parent().parent().showSummary(i) 80 QListWidget.focusInEvent(self, event) 81 def dropEvent(self, event): 82 QListWidget.dropEvent(self, event) 83 spp = self.parent().parent() 84 spp.msgte.setText(spp.composeMsg(self.getPatchList())) 85 def getPatchList(self): 86 return [hglib.fromunicode(self.item(i).text()) \ 87 for i in pycompat.xrange(0, self.count())] 88 89 ugb = QGroupBox(_('Patches to fold')) 90 ugb.setLayout(QVBoxLayout()) 91 ugb.layout().setContentsMargins(*(0,)*4) 92 self.ulw = PatchListWidget(self) 93 self.ulw.setDragDropMode(QListView.InternalMove) 94 ugb.layout().addWidget(self.ulw) 95 self.ulw.currentItemChanged.connect(lambda: 96 self.showSummary(self.ulw.item(self.ulw.currentRow()))) 97 self.layout().addWidget(ugb) 98 99 for p in patches: 100 item = QListWidgetItem(hglib.tounicode(p)) 101 item.setFlags(Qt.ItemIsSelectable | 102 Qt.ItemIsEnabled | 103 Qt.ItemIsDragEnabled) 104 self.ulw.addItem(item) 105 106 slbl = QLabel(_('Summary:')) 107 self.layout().addWidget(slbl) 108 self.summ = QTextEdit() 109 self.summ.setFont(qtlib.getfont('fontcomment').font()) 110 self.summ.setMaximumHeight(80) 111 self.summ.setReadOnly(True) 112 self.summ.setFocusPolicy(Qt.NoFocus) 113 self.layout().addWidget(self.summ) 114 115 BB = QDialogButtonBox 116 bbox = QDialogButtonBox(BB.Ok|BB.Cancel) 117 bbox.accepted.connect(self.accept) 118 bbox.rejected.connect(self.reject) 119 self.layout().addWidget(bbox) 120 self.bbox = bbox 121 122 QShortcut('Ctrl+Return', self, self.accept) 123 QShortcut('Ctrl+Enter', self, self.accept) 124 125 self._repoagent.configChanged.connect(self.configChanged) 126 127 self._readsettings() 128 129 self.msgte.setText(self.composeMsg(patches)) 130 self.msgte.refresh(self.repo) 131 132 @property 133 def repo(self): 134 return self._repoagent.rawRepo() 135 136 def showSummary(self, item): 137 patchname = hglib.fromunicode(item.text()) 138 txt = '\n'.join(mq.patchheader(self.repo.mq.join(patchname)).message) 139 self.summ.setText(hglib.tounicode(txt)) 140 141 def composeMsg(self, patches): 142 descs = [hglib.revsymbol(self.repo, b'qtip').description()] 143 # lookup of unapplied patches is handled by thgrepo hack 144 descs.extend(self.repo[p].description() for p in patches) 145 return u'\n* * *\n'.join(map(hglib.tounicode, descs)) 146 147 @pyqtSlot() 148 def configChanged(self): 149 '''Repository is reporting its config files have changed''' 150 self.msgte.refresh(self.repo) 151 152 def options(self): 153 return {'keep': self.keepchk.isChecked(), 154 'message': pycompat.unicode(self.msgte.text())} 155 156 def patches(self): 157 return pycompat.maplist(hglib.tounicode, self.ulw.getPatchList()) 158 159 def accept(self): 160 self._writesettings() 161 QDialog.accept(self) 162 163 def closeEvent(self, event): 164 self._writesettings() 165 super(QFoldDialog, self).closeEvent(event) 166 167 def _readsettings(self): 168 s = QSettings() 169 self.restoreGeometry(qtlib.readByteArray(s, 'qfold/geom')) 170 171 def _writesettings(self): 172 s = QSettings() 173 s.setValue('qfold/geom', self.saveGeometry()) 174