Kiln » TortoiseHg » TortoiseHg
Clone URL:  
Pushed to one repository · View In Graph Contained in 1.9, 1.9.1, and 1.9.2

status: move context menus to new wctxactions.py

Changeset 413ab4d8102c

Parent c4212d1cf1d2

by Steve Borho

Changes to 2 files · Browse files at 413ab4d8102c Showing diff from parent c4212d1cf1d2 Diff from another changeset...

 
8
9
10
11
 
12
13
14
15
16
17
18
 
19
20
21
 
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
 
 
 
 
 
 
 
 
322
323
324
 
8
9
10
 
11
12
13
14
15
16
17
 
18
19
20
21
 
225
226
227
 
228
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
231
232
233
234
235
236
237
238
239
240
@@ -8,14 +8,14 @@
 import os    from mercurial import ui, hg, util, patch, cmdutil, error, mdiff, context, merge -from tortoisehg.hgqt import qtlib, htmlui, chunkselect +from tortoisehg.hgqt import qtlib, htmlui, chunkselect, wctxactions  from tortoisehg.util import paths, hglib  from tortoisehg.util.i18n import _    from PyQt4.QtCore import Qt, QVariant, SIGNAL, QAbstractTableModel  from PyQt4.QtCore import QObject, QEvent, QMimeData, QUrl  from PyQt4.QtGui import QWidget, QVBoxLayout, QSplitter, QTreeView -from PyQt4.QtGui import QTextEdit, QFont, QColor, QDrag, QAction, QMenu +from PyQt4.QtGui import QTextEdit, QFont, QColor, QDrag    # This widget can be used as the basis of the commit tool or any other  # working copy browser. @@ -225,100 +225,16 @@
    def customContextMenuRequested(self, point):   rows = set() - selstats = set()   selrows = []   for index in self.selectedIndexes(): - if index.row() not in rows: - rows.add(index.row()) - r = self.model().getRow(index) - selrows.append(r) - selstats.add(r[COL_STATUS]) - selstats.add(r[COL_MERGE_STATE].lower()) - if not selrows: - return None - - def vdiff(files): - print 'vdiff', files - def edit(files): - print 'edit' - def viewmissing(files): - print 'viewmissing' - def other(files): - print 'other' - def revert(files): - print 'revert' - def log(files): - print 'log' - def forget(files): - print 'forget' - def add(files): - print 'add' - def guess_rename(files): - print 'guess_rename' - def ignore(files): - print 'ignore' - def remove(files): - print 'remove' - def delete(files): - print 'delete' - def copy(files): - print 'copy' - def rename(files): - print 'rename' - def resolve(files): - print 'resolve' - def unmark(files): - print 'unmark' - def mark(files): - print 'mark' - def resolve_with(tool, files): - print 'resolve_with', tool - - menu = QMenu() - def make(text, func, types, icon=None, test=True): - if not test or not (frozenset(types) & selstats): - return None - action = menu.addAction(text) - if icon: - action.setIcon(icon) - files = [r[COL_PATH] for r in selrows if r[COL_STATUS] in types or \ - r[COL_MERGE_STATE].lower() in types] - action.wrapper = lambda files=files: func(files) - self.connect(action, SIGNAL('triggered()'), action.wrapper) - return action - make(_('&Visual Diff'), vdiff, 'MAR!ru') - make(_('Edit'), edit, 'MACI?ru') - make(_('View missing'), viewmissing, 'R!') - make(_('View other'), other, 'MAru', None, len(self.repo.parents())>1) - menu.addSeparator() - make(_('&Revert'), revert, 'MAR!ru') - menu.addSeparator() - make(_('L&og'), log, 'MARC!ru') - menu.addSeparator() - make(_('&Forget'), forget, 'MAC!ru') - make(_('&Add'), add, 'I?') - make(_('&Guess Rename...'), guess_rename, '?!') - make(_('&Ignore'), ignore, '?') - make(_('Remove versioned'), remove, 'C') - make(_('&Delete unversioned'), delete, '?I') - if len(selrows) == 1: - menu.addSeparator() - make(_('&Copy...'), copy, 'MC') - make(_('Rename...'), rename, 'MC') - menu.addSeparator() - make(_('Mark unresolved'), unmark, 'r') - make(_('Mark resolved'), mark, 'u') - f = make(_('Restart Merge...'), resolve, 'u') - if f: - files = [r[COL_PATH] for r in selrows if r[COL_MERGE_STATE] == 'U'] - rmenu = QMenu(_('Restart merge with')) - for tool in hglib.mergetools(self.repo.ui): - action = rmenu.addAction(tool) - action.wrapper = lambda tool=tool: resolve_with(tool, files) - self.connect(action, SIGNAL('triggered()'), action.wrapper) - menu.addMenu(rmenu) - menu.exec_(point) - + if index.row() in rows: + continue + rows.add(index.row()) + c, status, mst, u, path = self.model().getRow(index) + selrows.append((set(status+mst.lower()), path)) + action = wctxactions.wctxactions(self, point, self.repo, selrows) + if action: + print action.text(), 'performed' # maybe should refresh    COL_CHECK = 0  COL_STATUS = 1
Change 1 of 1 Show Entire File tortoisehg/​hgqt/​wctxactions.py Stacked
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
@@ -0,0 +1,186 @@
+# wctxactions.py - menu and responses for working copy files +# +# 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. + +from mercurial import util, cmdutil, error, merge, commands +from tortoisehg.hgqt import qtlib, htmlui +from tortoisehg.util import hglib, shlib +from tortoisehg.util.i18n import _ + +from PyQt4.QtCore import Qt, SIGNAL +from PyQt4.QtGui import QAction, QMenu, QMessageBox + +def wctxactions(parent, point, repo, selrows): + if not selrows: + return + alltypes = set() + for t, path in selrows: + alltypes |= t + + 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(icon) + action.wrapper = lambda files=files: run(func, files, repo) + parent.connect(action, SIGNAL('triggered()'), action.wrapper) + return action + + menu = QMenu(parent) + make(_('&Visual Diff'), vdiff, frozenset('MAR!')) + make(_('Edit'), edit, frozenset('MACI?')) + make(_('View missing'), viewmissing, frozenset('R!')) + if len(repo.parents()) > 1: + make(_('View other'), other, frozenset('MA')) + menu.addSeparator() + make(_('&Revert'), revert, frozenset('MAR!')) + menu.addSeparator() + make(_('L&og'), log, frozenset('MARC!')) + menu.addSeparator() + make(_('&Forget'), forget, frozenset('MAC!')) + make(_('&Add'), add, frozenset('I?')) + make(_('&Guess Rename...'), guessRename, frozenset('?!')) + make(_('&Ignore'), ignore, frozenset('?')) + make(_('Remove versioned'), remove, frozenset('C')) + make(_('&Delete unversioned'), delete, frozenset('?I')) + if len(selrows) == 1: + menu.addSeparator() + make(_('&Copy...'), copy, frozenset('MC')) + make(_('Rename...'), rename, frozenset('MC')) + 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): + action = rmenu.addAction(tool) + action.wrapper = lambda tool=tool: resolve_with(tool, repo, files) + parent.connect(action, SIGNAL('triggered()'), action.wrapper) + menu.addMenu(rmenu) + return menu.exec_(point) + +def run(func, files, repo): + 'run wrapper for all action methods' + wfiles = [repo.wjoin(x) for x in files] + hu = htmlui.htmlui() + name = func.__name__.title() + try: + # All operations should quietly succeed. Any error should + # result in a message box + notify = func(hu, wfiles, repo) + o, e = hu.getdata() + if e: + QMessageBox.warning(None, name + _(' reported errors'), str(e)) + elif o: + QMessageBox.information(None, name + _(' reported errors'), str(o)) + elif notify: + shlib.shell_notify(wfiles) + return notify + except (util.Abort, IOError, OSError), e: + QMessageBox.critical(None, name + _(' Aborted'), str(e)) + except (error.LookupError), e: + QMessageBox.critical(None, name + _(' Aborted'), str(e)) + return False + +def filelist(files): + 'utility function to present file list' + text = '\n'.join(files[:5]) + if len(files) > 5: + text += ' ...\n' + return hglib.tounicode(text) + +def vdiff(ui, repo, files): + raise NotImplementedError() + +def edit(ui, repo, files): + raise NotImplementedError() + +def viewmissing(ui, repo, files): + raise NotImplementedError() + +def other(ui, repo, files): + raise NotImplementedError() + +def revert(ui, repo, files): + raise NotImplementedError() + # Needs work + revertopts = {} + + if len(repo.parents()) > 1: + res = QMessageBox.Question( + None, + _('Uncommited merge - please select a parent revision'), + _('Revert files to local or other parent?'), + (_('&Local'), _('&Other'), _('&Cancel')), 2).run() + if res == 0: + revertopts['rev'] = repo[None].p1().rev() + elif res == 1: + revertopts['rev'] = repo[None].p2().rev() + else: + return + response = None + else: + # response: 0=Yes, 1=Yes,no backup, 2=Cancel + revs = revertopts['rev'] + if revs and type(revs) == list: + revertopts['rev'] = revs[0] + else: + revertopts['rev'] = str(self.stat.repo['.'].rev()) + response = gdialog.CustomPrompt(_('Confirm Revert'), + _('Revert files to revision %s?\n\n%s') % (revertopts['rev'], + filelist(files)), self.stat, (_('&Yes (backup changes)'), + _('Yes (&discard changes)'), + _('&Cancel')), 2, 2).run() + if response in (None, 0, 1): + if response == 1: + revertopts['no_backup'] = True + commands.revert(ui, repo, *wfiles, **revertopts) + return True + +def log(ui, repo, files): + raise NotImplementedError() + +def forget(ui, repo, files): + commands.forget(ui, repo, *files) + return True + +def add(ui, repo, files): + raise NotImplementedError() + +def guessRename(ui, repo, files): + raise NotImplementedError() + +def ignore(ui, repo, files): + raise NotImplementedError() + +def remove(ui, repo, files): + commands.remove(ui, repo, *files) + return True + +def delete(ui, repo, files): + raise NotImplementedError() + +def copy(ui, repo, files): + raise NotImplementedError() + +def rename(ui, repo, files): + raise NotImplementedError() + +def resolve(ui, repo, files): + raise NotImplementedError() + +def unmark(ui, repo, files): + raise NotImplementedError() + +def mark(ui, repo, files): + raise NotImplementedError() + +def resolve_with(tool, repo, files): + raise NotImplementedError()