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

status: begin to implement intelligent context menus

We'll want to pull over the bulk of statusact.py from the
GTK side, but I also may decide to move most of the menu
logic there as well.

Changeset b2ac11bf05b8

Parent a65328eae56d

by Steve Borho

Changes to one file · Browse files at b2ac11bf05b8 Showing diff from parent a65328eae56d Diff from another changeset...

 
15
16
17
18
 
19
20
21
 
62
63
64
65
 
66
67
68
 
189
190
191
192
 
193
194
 
 
 
 
195
196
197
 
208
209
210
211
 
212
213
214
 
220
221
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
224
225
 
346
347
348
 
 
 
 
349
350
351
 
15
16
17
 
18
19
20
21
 
62
63
64
 
65
66
67
68
 
189
190
191
 
192
193
 
194
195
196
197
198
199
200
 
211
212
213
 
214
215
216
217
 
223
224
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
 
445
446
447
448
449
450
451
452
453
454
@@ -15,7 +15,7 @@
 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 +from PyQt4.QtGui import QTextEdit, QFont, QColor, QDrag, QAction, QMenu    # This widget can be used as the basis of the commit tool or any other  # working copy browser. @@ -62,7 +62,7 @@
  layout.addWidget(split)   self.setLayout(layout)   - self.tv = WctxFileTree(root, split) + self.tv = WctxFileTree(self.repo, split)   self.connect(self.tv, SIGNAL('clicked(QModelIndex)'), self.rowSelected)     self.te = QTextEdit(split) @@ -189,9 +189,12 @@
     class WctxFileTree(QTreeView): - def __init__(self, root, parent=None): + def __init__(self, repo, parent=None):   QTreeView.__init__(self, parent) - self.root = root + self.repo = repo + self.setContextMenuPolicy(Qt.CustomContextMenu) + self.connect(self, SIGNAL('customContextMenuRequested(const QPoint &)'), + self.customContextMenuRequested)     def keyPressEvent(self, event):   if event.key() == 32: @@ -208,7 +211,7 @@
  rows.add(index.row())   path = self.model().getPath(index)   u = QUrl() - u.setPath('file://' + os.path.join(self.root, path)) + u.setPath('file://' + os.path.join(self.repo.root, path))   urls.append(u)   if rows:   d = QDrag(self) @@ -220,6 +223,102 @@
  def mouseMoveEvent(self, event):   self.dragObject()   + 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) +    COL_CHECK = 0  COL_STATUS = 1 @@ -346,6 +445,10 @@
  assert index.isValid()   return self.rows[index.row()][COL_PATH]   + def getRow(self, index): + assert index.isValid() + return self.rows[index.row()] +   def toggleRow(self, index):   'Connected to "activated" signal, emitted by dbl-click or enter'   assert index.isValid()