如果涉及最后一行,QPlainTextEdit 中的缩进功能会导致段错误
Dedenting function in QPlainTextEdit causes segfault if last line is involved
我正在开发一个应该具有智能 indent/dedent 行为的源代码编辑器。但是,我的缩进方法似乎导致了分段错误。如果有人能找出原因,我将非常高兴。
这是一个最小的例子:
#!/usr/bin/env python
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4 import QtGui
from PyQt4.QtCore import Qt
class Editor(QtGui.QPlainTextEdit):
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Backtab:
cursor = self.textCursor()
start, end = cursor.selectionStart(), cursor.selectionEnd()
cursor.beginEditBlock()
b = self.document().findBlock(start)
while b.isValid() and b.position() <= end:
t = b.text()
p1 = b.position()
p2 = p1 + min(4, len(t) - len(t.lstrip()))
cursor.setPosition(p1)
cursor.setPosition(p2, QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText()
b = b.next()
cursor.endEditBlock()
else:
super(Editor, self).keyPressEvent(event)
class Window(QtGui.QMainWindow):
"""
New GUI for editing ``.mmt`` files.
"""
def __init__(self, filename=None):
super(Window, self).__init__()
self.e = Editor()
self.e.setPlainText('Line 1\n Line 2\n Line 3')
self.setCentralWidget(self.e)
self.e.setFocus()
if __name__ == '__main__':
a = QtGui.QApplication([])
w = Window()
w.show()
a.exec_()
要重新创建,请选择从第二行开始到第三行结束,然后按 Shift+Tab
缩进并按 End
触发段错误。
平台:
Fedora 上的 - 运行 (linux)
- Python 2.7.8(默认,2014 年 11 月 10 日,08:19:18)[GCC 4.9.2 20141101(Red Hat 4.9.2-1)]
- PyQt 4.8.6(但它也发生在 PySide 中)
更新:
- 似乎只有在使用
cursor.beginEditBlock()
和 cursor.endEditBlock()
时才会出现此错误,另请参阅:QTextCursor and beginEditBlock
谢谢
这似乎是 Qt 中的一个错误:
https://bugreports.qt.io/browse/QTBUG-30051
显然,在 QTextCursor.beginEditBlock() 中编辑多个块会导致最后一个块的布局中断,在我的情况下会导致段错误。
解决方法可能是将缩进代码重写为单个操作(缩进后确定文本,删除所有选定行,替换为新文本)
如果有人知道更好的解决方法,请告诉我!
我正在开发一个应该具有智能 indent/dedent 行为的源代码编辑器。但是,我的缩进方法似乎导致了分段错误。如果有人能找出原因,我将非常高兴。
这是一个最小的例子:
#!/usr/bin/env python
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4 import QtGui
from PyQt4.QtCore import Qt
class Editor(QtGui.QPlainTextEdit):
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Backtab:
cursor = self.textCursor()
start, end = cursor.selectionStart(), cursor.selectionEnd()
cursor.beginEditBlock()
b = self.document().findBlock(start)
while b.isValid() and b.position() <= end:
t = b.text()
p1 = b.position()
p2 = p1 + min(4, len(t) - len(t.lstrip()))
cursor.setPosition(p1)
cursor.setPosition(p2, QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText()
b = b.next()
cursor.endEditBlock()
else:
super(Editor, self).keyPressEvent(event)
class Window(QtGui.QMainWindow):
"""
New GUI for editing ``.mmt`` files.
"""
def __init__(self, filename=None):
super(Window, self).__init__()
self.e = Editor()
self.e.setPlainText('Line 1\n Line 2\n Line 3')
self.setCentralWidget(self.e)
self.e.setFocus()
if __name__ == '__main__':
a = QtGui.QApplication([])
w = Window()
w.show()
a.exec_()
要重新创建,请选择从第二行开始到第三行结束,然后按 Shift+Tab
缩进并按 End
触发段错误。
平台:
-
Fedora 上的
- 运行 (linux)
- Python 2.7.8(默认,2014 年 11 月 10 日,08:19:18)[GCC 4.9.2 20141101(Red Hat 4.9.2-1)]
- PyQt 4.8.6(但它也发生在 PySide 中)
更新:
- 似乎只有在使用
cursor.beginEditBlock()
和cursor.endEditBlock()
时才会出现此错误,另请参阅:QTextCursor and beginEditBlock
谢谢
这似乎是 Qt 中的一个错误:
https://bugreports.qt.io/browse/QTBUG-30051
显然,在 QTextCursor.beginEditBlock() 中编辑多个块会导致最后一个块的布局中断,在我的情况下会导致段错误。
解决方法可能是将缩进代码重写为单个操作(缩进后确定文本,删除所有选定行,替换为新文本)
如果有人知道更好的解决方法,请告诉我!