Функция отступа в QPlainTextEdit вызывает segfault, если задействована последняя строка
Я работаю над редактором исходного кода, который должен иметь умное поведение отступа / отступа. Тем не менее, мой метод выделения, кажется, вызывает ошибку сегментации. Я был бы очень рад, если бы кто-то мог понять почему.
Вот минимальный пример:
#!/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
вызвать segfault.
Платформа:
- Работает на Fedora (Linux)
- Python 2.7.8 (по умолчанию, 10 ноября 2014 г., 08:19:18) [GCC 4.9.2 20141101 (Red Hat 4.9.2-1)]
- PyQt 4.8.6 (но это происходит и в PySide)
Обновить:
- Кажется, эта ошибка возникает только если
cursor.beginEditBlock()
а такжеcursor.endEditBlock()
используются, см. также: QTextCursor и beginEditBlock
Спасибо
1 ответ
Кажется, это ошибка в Qt:
https://bugreports.qt.io/browse/QTBUG-30051
Видимо, редактирование нескольких блоков внутри QTextCursor.beginEditBlock() приводит к разрыву макета последнего блока, что в моем случае вызывало segfault.
Обходной путь может заключаться в том, чтобы переписать код отступа как одну операцию (определить текст после отступа, удалить все выделенные строки, заменить новым текстом)
Если кто-то знает лучший обходной путь, пожалуйста, дайте мне знать!