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

commit: switch to QsciScintilla for message entry pane.

This breaks a number of features that will be fixed in later commits

Changeset 73d5f5b3301d

Parent 32ea749ddae8

by Steve Borho

Changes to one file · Browse files at 73d5f5b3301d Showing diff from parent 32ea749ddae8 Diff from another changeset...

 
12
13
14
 
15
16
17
18
19
 
20
21
22
 
25
26
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
29
30
 
48
49
50
 
51
52
53
 
97
98
99
100
101
102
103
104
105
106
107
 
 
 
 
 
 
108
109
110
 
127
128
129
130
131
132
133
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
136
137
 
168
169
170
 
 
171
172
173
 
194
195
196
197
198
199
 
200
201
202
203
 
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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
 
271
272
273
274
 
275
276
277
 
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
 
320
321
322
323
324
325
326
327
328
329
330
331
332
333
 
369
370
371
372
 
373
374
375
 
377
378
379
 
 
380
381
382
 
384
385
386
387
388
389
 
390
391
 
 
 
 
 
 
 
 
 
 
392
393
394
 
407
408
409
410
411
412
 
413
414
415
 
431
432
433
434
 
435
436
437
 
592
593
594
595
 
596
597
598
 
935
936
937
 
938
939
940
 
12
13
14
15
16
17
18
19
 
20
21
22
23
 
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
 
99
100
101
102
103
104
105
 
149
150
151
 
 
 
 
 
 
 
 
152
153
154
155
156
157
158
159
160
 
177
178
179
 
 
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
 
246
247
248
249
250
251
252
253
 
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
 
314
315
316
 
317
318
319
320
 
329
330
331
332
333
334
335
336
337
 
 
 
338
339
340
341
342
 
343
344
345
346
347
348
349
350
351
352
353
 
 
 
 
 
354
355
356
357
 
363
364
365
 
 
 
 
 
 
 
 
366
367
368
 
404
405
406
 
407
408
409
410
 
412
413
414
415
416
417
418
419
 
421
422
423
 
 
 
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
 
452
453
454
 
 
 
455
456
457
458
 
474
475
476
 
477
478
479
480
 
635
636
637
 
638
639
640
641
 
978
979
980
981
982
983
984
@@ -12,11 +12,12 @@
   from PyQt4.QtCore import *  from PyQt4.QtGui import * +from PyQt4.Qsci import QsciScintilla, QsciAPIs, QsciLexerMakefile    from tortoisehg.hgqt.i18n import _  from tortoisehg.util import hglib, shlib, paths, wconfig   -from tortoisehg.hgqt import qtlib, status, cmdui, branchop, revpanel +from tortoisehg.hgqt import qtlib, status, cmdui, branchop, revpanel, lexers  from tortoisehg.hgqt.sync import loadIniFile    # Technical Debt for CommitWidget @@ -25,6 +26,56 @@
 # spell check / tab completion  # in-memory patching / committing chunk selected files   +class MessageEntry(QsciScintilla): + escapePressed = pyqtSignal() + refreshPressed = pyqtSignal() + + def __init__(self, parent=None): + super(MessageEntry, self).__init__(parent) + self.setEdgeColor(QColor('LightSalmon')) + self.setEdgeMode(QsciScintilla.EdgeLine) + self.setWrapMode(QsciScintilla.WrapNone) + self.setReadOnly(False) + self.setUtf8(True) + self.setMarginWidth(1, 0) + self.setFont(qtlib.getfont('fontcomment').font()) + self.setCaretWidth(10) + self.setCaretLineBackgroundColor(QColor("#e6fff0")) + self.setCaretLineVisible(True) + self.setAutoIndent(True) + self.setAutoCompletionThreshold(2) + self.setAutoCompletionSource(QsciScintilla.AcsAPIs) + self.setAutoCompletionFillupsEnabled(True) + self.setLexer(QsciLexerMakefile(self)) + self.lexer().setFont(qtlib.getfont('fontcomment').font()) + self.setMatchedBraceBackgroundColor(Qt.yellow) + self.setIndentationsUseTabs(False) + self.setBraceMatching(QsciScintilla.SloppyBraceMatch) + #self.setIndentationGuidesBackgroundColor(QColor("#e6e6de")) + #self.setFolding(QsciScintilla.BoxedFoldStyle) + self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) + self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) + + def refresh(self, repo): + self.setEdgeColumn(repo.summarylen) + self.setIndentationWidth(repo.tabwidth) + self.setTabWidth(repo.tabwidth) + if repo.wsvisible == 'Visible': + self.setWhitespaceVisibility(QsciScintilla.WsVisible) + elif repo.wsvisible == 'VisibleAfterIndent': + self.setWhitespaceVisibility(QsciScintilla.WsVisibleAfterIndent) + else: + self.setWhitespaceVisibility(QsciScintilla.WsInvisible) + + def keyPressEvent(self, event): + if event.key() == Qt.Key_Escape: + self.escapePressed.emit() + return + if event.matches(QKeySequence.Refresh): + self.refreshPressed.emit() + return + super(MessageEntry, self).keyPressEvent(event) +  class CommitWidget(QWidget):   'A widget that encompasses a StatusWidget and commit extras'   commitButtonName = pyqtSignal(QString) @@ -48,6 +99,7 @@
  self.stwidget.linkActivated.connect(self.linkActivated)   self.stwidget.escapePressed.connect(self.escapePressed)   self.stwidget.refreshPressed.connect(self.refreshPressed) + self.stwidget.fileDisplayed.connect(self.fileDisplayed)   self.msghistory = []   self.qref = False   @@ -97,14 +149,12 @@
  self.pcsinfo = revpanel.ParentWidget(repo)   vbox.addWidget(self.pcsinfo, 0)   - msgte = QPlainTextEdit() - msgte.setLineWrapMode(QPlainTextEdit.NoWrap) - msgfont = qtlib.getfont('fontcomment') - msgte.setFont(msgfont.font()) - msgfont.changed.connect(lambda fnt: msgte.setFont(fnt)) - msgte.textChanged.connect(self.msgChanged) - msgte.setContextMenuPolicy(Qt.CustomContextMenu) - msgte.customContextMenuRequested.connect(self.menuRequested) + msgte = MessageEntry(self) + msgte.escapePressed.connect(self.escapePressed) + msgte.refreshPressed.connect(self.refreshPressed) + #msgte.textChanged.connect(self.msgChanged) + #msgte.setContextMenuPolicy(Qt.CustomContextMenu) + #msgte.customContextMenuRequested.connect(self.menuRequested)   vbox.addWidget(msgte, 1)   upperframe = QFrame()   @@ -127,11 +177,39 @@
    # add our splitter where the docf used to be   self.stwidget.split.addWidget(self.split) - msgte.setFocus() - # Yuki's Mockup: http://bitbucket.org/kuy/thg-qt/wiki/Home   self.msgte = msgte   self.msgcombo = msgcombo   + @pyqtSlot(QString, QString) + def fileDisplayed(self, wfilestr, contents): + 'Status widget is displaying a new file' + wfile = hglib.fromunicode(wfilestr) + contents = hglib.fromunicode(contents) + if not (wfile and contents): + return + self._apis = QsciAPIs(self.msgte.lexer()) + tokens = set() + for wfile in self.stwidget.getChecked(): + tokens.add(wfile) + tokens.add(os.path.basename(wfile)) + try: + from pygments.lexers import guess_lexer_for_filename + from pygments.token import Token + lexer = guess_lexer_for_filename(wfile, contents) + for tokentype, value in lexer.get_tokens(contents): + if tokentype is Token.Name and len(value) > 4: + tokens.add(value) + except (pygments.util.ClassNotFound, ImportError): + pass + for n in sorted(list(tokens)): + self._apis.add(n) + self._apis.apiPreparationFinished.connect(self.apiPrepFinished) + self._apis.prepare() + + def apiPrepFinished(self): + 'QsciAPIs has finished parsing displayed file' + self.msgte.lexer().setAPIs(self._apis) +   def details(self):   dlg = DetailsDialog(self.opts, self.userhist, self)   dlg.setWindowFlags(Qt.Sheet) @@ -168,6 +246,8 @@
  if self.qref:   self.endQRefreshMode()   + self.msgte.refresh(self.repo) +   # Update message list   self.msgcombo.reset(self.msghistory)   @@ -194,62 +274,25 @@
  return   self.opts['user'] = qtip.user()   self.opts['date'] = hglib.displaytime(qtip.date()) - self.msgte.setPlainText(hglib.tounicode(qtip.description())) - self.msgte.document().setModified(False) - self.msgte.moveCursor(QTextCursor.End) + self.setMessage(hglib.tounicode(qtip.description()))   self.qref = True     def endQRefreshMode(self): - self.msgte.clear() + self.setMessage('')   self.opts['user'] = ''   self.opts['date'] = ''   self.qref = False   - def msgChanged(self): - text = self.msgte.toPlainText() - self.buttonHBox.setEnabled(not text.isEmpty()) - sumlen, maxlen = self.getLengths() - if not sumlen and not maxlen: - self.msgte.setExtraSelections([]) - return - pos, nextpos = 0, 0 - sels = [] - for i, line in enumerate(text.split('\n')): - length = len(line) - pos = nextpos - nextpos += length + 1 # include \n - if i == 0: - if length < sumlen or not sumlen: - continue - pos += sumlen - elif i == 1: - if length == 0 or not sumlen: - continue - else: - if length < maxlen or not maxlen: - continue - pos += maxlen - sel = QTextEdit.ExtraSelection() - sel._bgcolor = QColor('LightSalmon') - sel._fgcolor = QColor('Black') - sel.format.setBackground(sel._bgcolor) - sel.format.setForeground(sel._fgcolor) - sel.cursor = QTextCursor(self.msgte.document()) - sel.cursor.setPosition(pos) - sel.cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) - sels.append(sel) - self.msgte.setExtraSelections(sels) -   def msgReflow(self):   'User pressed Control-E, reflow current paragraph'   if QApplication.focusWidget() != self.msgte:   return + # TODO: broken by Qsci + return   self.reflowBlock(self.msgte.textCursor().block())     def reflowBlock(self, block): - sumlen, maxlen = self.getLengths() - if not maxlen: - return + sumlen = self.repo.summarylen   # In QtTextDocument land, a block is a sequence of text ending   # in (and including) a carriage return. Aka, a line of text.   while block.length() and block.previous().length() > 1: @@ -271,7 +314,7 @@
  line = QStringList()   partslen = 0   for part in parts: - if partslen + len(line) + len(part) + 1 > maxlen: + if partslen + len(line) + len(part) + 1 > sumlen:   if line:   lines.append(line.join(' '))   line, partslen = QStringList(), 0 @@ -286,29 +329,29 @@
  return cursor.block()     def menuRequested(self, point): + # TODO: broken by Qsci + return   cursor = self.msgte.cursorForPosition(point)   point = self.msgte.mapToGlobal(point)     def apply(): - sumlen, maxlen = self.getLengths() - if not maxlen: - return + # TODO: broken by Qsci + return + sumlen = self.repo.summarylen   block = self.msgte.document().firstBlock()   while block != self.msgte.document().end(): - if block.length() > maxlen: + if block.length() > sumlen:   block = self.reflowBlock(block)   block = block.next()   def paste(): + # TODO: broken by Qsci + return   files = self.stwidget.getChecked()   cursor.insertText(', '.join(files))   def settings():   from tortoisehg.hgqt.settings import SettingsDialog   dlg = SettingsDialog(True, focus='tortoisehg.summarylen') - self.repo.incrementBusyCount() - ret = dlg.exec_() - self.repo.decrementBusyCount() - if ret == QDialog.Accepted: - self.msgChanged() + dlg.exec_()     menu = self.msgte.createStandardContextMenu()   for name, func in [(_('Paste &Filenames'), paste), @@ -320,14 +363,6 @@
  add(name, func)   return menu.exec_(point)   - def getLengths(self): - try: - sumlen = int(self.repo.ui.config('tortoisehg', 'summarylen', 0)) - maxlen = int(self.repo.ui.config('tortoisehg', 'messagewrap', 0)) - except (TypeError, ValueError): - sumlen, maxlen = 0, 0 - return sumlen, maxlen -   def restoreState(self, data):   return self.stwidget.restoreState(data)   @@ -369,7 +404,7 @@
  QTimer.singleShot(500, lambda: shlib.shell_notify([self.repo.root]))     def getMessage(self): - text = self.msgte.toPlainText() + text = self.msgte.text()   try:   text = hglib.fromunicode(text, 'strict')   except UnicodeEncodeError: @@ -377,6 +412,8 @@
  return text     def msgSelected(self, index): + # TODO: broken by QSci + return   doc = self.msgte.document()   if not doc.isEmpty() and doc.isModified():   d = QMessageBox.question(self, _('Confirm Discard Message'), @@ -384,11 +421,19 @@
  QMessageBox.Ok | QMessageBox.Cancel)   if d != QMessageBox.Ok:   return - self.msgte.setPlainText(self.msghistory[index]) - self.msgte.document().setModified(False) - self.msgte.moveCursor(QTextCursor.End) + self.setMessage(self.msghistory[index])   self.msgte.setFocus()   + def setMessage(self, msg): + self.msgte.setText(msg) + lines = self.msgte.lines() + if lines: + lines -= 1 + pos = self.msgte.lineLength(lines) + self.msgte.setCursorPosition(lines, pos) + self.msgte.ensureLineVisible(lines) + self.msgte.setModified(False) +   def canExit(self):   # Usually safe to exit, since we're saving messages implicitly   # We'll ask the user for confirmation later, if they have any @@ -407,9 +452,7 @@
  self.userhist = [u for u in self.userhist if u]   try:   curmsg = self.repo.opener('cur-message.txt').read() - self.msgte.setPlainText(hglib.tounicode(curmsg)) - self.msgte.document().setModified(False) - self.msgte.moveCursor(QTextCursor.End) + self.setMessage(hglib.tounicode(curmsg))   except EnvironmentError:   pass   @@ -431,7 +474,7 @@
  pass     def addMessageToHistory(self): - umsg = self.msgte.toPlainText() + umsg = self.msgte.text()   if not umsg:   return   if umsg in self.msghistory: @@ -592,7 +635,7 @@
  self.addMessageToHistory()   if not self.qref:   self.msgte.clear() - self.msgte.document().setModified(False) + self.msgte.setModified(False)   self.commitComplete.emit()   self.stwidget.refreshWctx()   @@ -935,6 +978,7 @@
  self.commit = commit   self.commit.reload()   self.updateUndo() + self.commit.msgte.setFocus()     def linkActivated(self, link):   link = hglib.fromunicode(link)