GtkSourceView/缓冲区崩溃:GtkERROR:字节索引离开lin的末尾

2024-10-03 21:36:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在写故事的文本编辑器工作。我正在使用Python、GTK+3和GtkSourceView 3。编辑的要点是折叠某些区域。当没有-还没有?-在GTK TextView/SourceView中内置了对折叠的支持,我一直在使用invisible=True和SourceView的源代码标记来实现这个特性。你知道吗

此处提供源代码:https://github.com/mkoskim/mawe

核心编辑器(SourceBuffer和SourceView)位于这里:https://github.com/mkoskim/mawe/blob/master/gui/gtk/SceneView.pyhttps://github.com/mkoskim/mawe/blob/master/gui/gtk/SceneBuffer.py

出于测试目的,您可以克隆repo,并使用以下工具运行应用程序:

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

没有其他错误或警告日志。我一直在谷歌上搜索错误,但没有成功。你知道吗

其他症状似乎是:

  • 即使编辑器处于空闲状态,也会发生崩溃

  • 今天我奇怪地发现,把鼠标移到隐藏的部分上,我可以很快得到崩溃:o

我不能百分之百肯定,但我认为这与不可见区域有关。你知道吗

问:有人知道这是不是某个已知的bug吗?你知道吗

问:有人知道我可以在哪里寻找可能的解决方案吗?有什么想法会导致坠机,还有什么我可以更深入的探索?你知道吗


更新:我用标签做了一些更广泛的测试。似乎没有其他属性对鼠标移动做出反应,但当打开“不可见性”时,鼠标跨区域移动会使应用程序崩溃。我一直在搜索报告鼠标事件崩溃gtktextbtree,但没有成功到目前为止。看起来这适用于几个v3.xgtk版本。你知道吗


更新:我想我已经找到了一个解决方法:过滤掉运动通知事件GtkSource.视图好像在工作,像这样:

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)

应用程序仍然崩溃,如果你按下鼠标按钮附近的隐藏线,但似乎它不会崩溃鼠标移动了。你知道吗


更新:更多调查。虽然阻止鼠标事件可以防止崩溃,但它也会导致一些问题,例如,无法使用鼠标放置光标、选择区域、DnD、。。。此外,鼠标光标可能会消失,因为它不会每次都正确更新。我敢肯定,将鼠标/窗口坐标转换为缓冲区位置的算法(当文本中有较大的隐藏块时)中存在错误,因此任何鼠标事件都可能导致应用程序崩溃。你知道吗


更新:我一直在尝试为这个主题创建简单的测试用例。好事:躲起来似乎奏效了。坏事:还不能重现问题。测试脚本可以在以下位置找到:

https://github.com/mkoskim/mawe/blob/master/gui/gtk/test/hidecrash/hidecrash.py


更新:试图弄清楚-测试用例工作,编辑器不工作。与测试用例的区别至少在于编辑器在事件循环(*)中放置了隐藏的标记。试着做一个测试用例。。。你知道吗

(*)使用当前的Gtk SourceView/TextView实现折叠肯定有许多不同的解决方案。我选择的方法是使用“标记”语言,并在编辑时应用折叠,因为它与undo/redo一起工作。我也尝试过其他解决方案,比如:

  1. 剪切折叠场景&将小部件插入文本缓冲区(包含文本本身)。想法:“text[part selected for folding]text”->;“text[anchor+widget with cut text]text”-遗憾的是,它不能与undo/redo一起工作。

  2. 剪切文本,给它一个ID,然后在缓冲区中放置一个包含ID的指定标记部分。想法“text[part selected for folding]text”->;“text[ID w/hidden+protected tags]text”-不起作用,因为剪切粘贴或撤消/重做不应用标记,所以用户可以销毁标记。

  3. 普通标记:用折叠指示器保持标记是非常困难的。你需要像“[char][mark][char]”这样的带有受保护标签的东西来确保你不会丢失标记是的。

不管怎样,我会继续调查的。你知道吗


更新:仍然无法在我的测试脚本中重现这个问题,但是发现了一些可能有趣的事情:折叠最后一个场景不会导致崩溃-只有在折叠紧跟在另一个场景之后的场景时(折叠或不折叠)。你知道吗


Tags: thetextpyhttps标记githubevent应用程序
2条回答

昨天我做了,可见部分和不可见部分都用相似的字体描述格式化。我仍然不能用简单的测试脚本重现这个问题,但似乎如果可见部分和隐藏部分离它们太远,偏移量计算就会出错。到目前为止我知道:

  • 错误消息,如Byte index 1362 is off the end of the line Trace/breakpoint trap,与隐藏部分的长度相差约5-7字节。

  • 当可见部分和不可见部分在字体大小、填充和重量方面彼此“足够接近”时,不会出现错误。在我的工作示例中,我使用完全相同的字体、重量、大小等格式化不可见的部分,程序不再崩溃。

我有办法解决这个问题。我只是不明白为什么它能工作,为什么我不能用测试脚本重现这个问题。下面是执行折叠的代码段:

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是指向下一个场景标记或文件结尾的文本。如果我们查看缓冲区内容,它是这样的:

<mark 1><at>Scene 1 heading<eol>
Line
Line
<mark 2>Scene 2 heading

将隐藏标记从<eol>应用到<mark 2>会导致崩溃。将标记从<eol + 1>应用到<mark 2>可以按预期工作。如果折叠到文件的末尾(<mark 2> == buffer.get_end_iter()),则可以进行折叠。在某些情况下,如果只需要隐藏换行符,它也可以工作,但不是在所有情况下都可以。你知道吗

如前所述,我不明白为什么这样做,为什么我不能用更简单的脚本重现问题,但我继续调查更多的问题,虽然现在有一个修复,它不是那么紧迫。你知道吗

相关问题 更多 >