Python GtkSourceView/缓冲区崩溃:Gtk错误:字节索引超出了行的末尾
我一直在为写故事而编写文本编辑器。我正在使用Python、GTK+3和GtkSourceView 3。编辑器的要点是折叠某些区域。虽然没有-还没有由于内置了对GTK TextView/SourceView中折叠的支持,我一直在使用不可见=True的标记和SourceView的源代码标记来实现该功能 此处提供的源代码: 核心编辑器(SourceBuffer和SourceView)位于以下位置: 出于测试目的,您可以克隆回购协议,并使用以下工具运行应用程序:Python GtkSourceView/缓冲区崩溃:Gtk错误:字节索引超出了行的末尾,python,gtk3,gtksourceview,Python,Gtk3,Gtksourceview,我一直在为写故事而编写文本编辑器。我正在使用Python、GTK+3和GtkSourceView 3。编辑器的要点是折叠某些区域。虽然没有-还没有由于内置了对GTK TextView/SourceView中折叠的支持,我一直在使用不可见=True的标记和SourceView的源代码标记来实现该功能 此处提供的源代码: 核心编辑器(SourceBuffer和SourceView)位于以下位置: 出于测试目的,您可以克隆回购协议,并使用以下工具运行应用程序: mawe$ ./mawe.py tes
mawe$ ./mawe.py test/test.txt
现在,应用程序经常随机崩溃,出现如下错误:
(mawe.py:10556): Gtk-WARNING **: /build/gtk+3.0-2Ut_nl/gtk+3.0-3.18.9/./gtk/gtktextbtree.c:4034: byte index off the end of the line
(mawe.py:10556): Gtk-ERROR **: Byte index 1362 is off the end of the line
Trace/breakpoint trap
def filter_event(widget, event, *args):
# Allow these
if event.type == Gdk.EventType.KEY_PRESS: return False
if event.type == Gdk.EventType.KEY_RELEASE: return False
# Block these
if event.type == Gdk.EventType.LEAVE_NOTIFY: return True
if event.type == Gdk.EventType.MOTION_NOTIFY: return True
# Print & allow the rest
print(event)
return False
self.text.connect("event", filter_event)
<mark 1><at>Scene 1 heading<eol>
Line
Line
<mark 2>Scene 2 heading
没有其他错误或警告日志。我一直在用谷歌搜索错误,但没有成功
其他症状似乎是:
- 即使编辑器处于空闲状态,也会发生崩溃
- 今天我发现,奇怪的是,我可以通过将鼠标移到隐藏的部分上很快得到崩溃:o
更新:我用标签做了一些更广泛的测试。似乎没有其他属性对鼠标移动做出反应,但当打开“不可见性”时,鼠标在整个区域的移动会使应用程序崩溃。我一直在搜索导致gtktextbtree崩溃的鼠标事件报告,但迄今为止没有成功。看起来这适用于几个v3.x GTK版本
更新:我想我几乎找到了一个解决方法:从GtkSource中过滤掉运动通知事件。视图似乎工作正常,如下所示:
(mawe.py:10556): Gtk-WARNING **: /build/gtk+3.0-2Ut_nl/gtk+3.0-3.18.9/./gtk/gtktextbtree.c:4034: byte index off the end of the line
(mawe.py:10556): Gtk-ERROR **: Byte index 1362 is off the end of the line
Trace/breakpoint trap
def filter_event(widget, event, *args):
# Allow these
if event.type == Gdk.EventType.KEY_PRESS: return False
if event.type == Gdk.EventType.KEY_RELEASE: return False
# Block these
if event.type == Gdk.EventType.LEAVE_NOTIFY: return True
if event.type == Gdk.EventType.MOTION_NOTIFY: return True
# Print & allow the rest
print(event)
return False
self.text.connect("event", filter_event)
<mark 1><at>Scene 1 heading<eol>
Line
Line
<mark 2>Scene 2 heading
如果在隐藏线附近按下鼠标按钮,应用程序仍然会崩溃,但看起来它不再因鼠标移动而崩溃
更新:更多调查。虽然阻止鼠标事件可以防止崩溃,但也会导致一些怪癖,例如无法使用鼠标放置光标、选择区域、DnD等。。。此外,鼠标光标可能会消失,因为它不是每次都正确更新。我敢肯定,将鼠标/窗口坐标转换为缓冲区位置(当文本中有较大的隐藏块时)的算法中存在缺陷,因此任何鼠标事件都可能导致应用程序崩溃
更新:我一直在尝试为主题创建简单的测试用例。好事情:隐藏似乎起作用了。坏事情:还不能重现问题。可以在此处找到测试脚本:
更新:试图找出它-测试用例工作,编辑器不工作。和测试用例的区别至少在于编辑器在事件循环(*)中放置了隐藏标记。试着做一个测试案例 (*)使用当前Gtk SourceView/TextView实现折叠肯定有许多不同的解决方案。我选择了使用“标记”语言并在编辑时应用折叠的方法,因为它与undo/redo一起工作。我也尝试过其他解决方案,如:
更新:仍然无法在我的测试脚本中重现该问题,但发现了一些可能有趣的问题:折叠最后一个场景不会导致崩溃-仅当折叠另一个场景之后的场景时(折叠或不折叠)。我已修复该问题。我只是不明白为什么它能工作,为什么我不能用测试脚本重现这个问题。下面是执行折叠的代码段:
fold_start = at.copy()
fold_start.forward_to_line_end()
fold_start.forward_char() # Comment this line -> crash
fold_end = self.scene_end_iter(end)
self.apply_tag(self.tag_fold_hide, fold_start, fold_end)
at
在insert text或delete range回调时派生,并指向行的开始fold_end
是指向下一个场景标记或文件结尾的文本。如果我们查看缓冲区内容,它是这样的:
(mawe.py:10556): Gtk-WARNING **: /build/gtk+3.0-2Ut_nl/gtk+3.0-3.18.9/./gtk/gtktextbtree.c:4034: byte index off the end of the line
(mawe.py:10556): Gtk-ERROR **: Byte index 1362 is off the end of the line
Trace/breakpoint trap
def filter_event(widget, event, *args):
# Allow these
if event.type == Gdk.EventType.KEY_PRESS: return False
if event.type == Gdk.EventType.KEY_RELEASE: return False
# Block these
if event.type == Gdk.EventType.LEAVE_NOTIFY: return True
if event.type == Gdk.EventType.MOTION_NOTIFY: return True
# Print & allow the rest
print(event)
return False
self.text.connect("event", filter_event)
<mark 1><at>Scene 1 heading<eol>
Line
Line
<mark 2>Scene 2 heading
场景1标题
线
线
场景2标题
将隐藏标记从
应用到
会导致崩溃。将标记从
应用到
可以正常工作。如果折叠到文件的末尾(==buffer.get\u end\u iter()
),则可以进行折叠。在某些情况下,如果只需要隐藏换行符,它也可以工作,但不是在所有情况下都可以
如前所述,我不明白为什么这样做,为什么我不能用更简单的脚本重现问题,但我一直在进行更多的研究,尽管现在有了修复,这并不是那么紧迫。好的,昨天我这样做了,可见和不可见部分都使用类似的字体描述进行格式化。我仍然不能用简单的测试脚本重现这个问题,但似乎如果可见和隐藏部分离它们太远,偏移量计算就会出错。到目前为止,我知道:
- 错误消息(如
与隐藏部分的长度相差约5-7字节字节索引1362)不在该行末尾 跟踪/断点陷阱
- 当可见部分和不可见部分在字体大小、填充和重量方面彼此“足够接近”时,不会出现错误。在我的工作示例中,我使用完全相同的字体、重量、大小等格式化不可见的部分,程序会这样做