天天看点

编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

问题描述:

我正在做IDE(嵌入式系统用的集成开发环境)的代码跳转功能,也就是按下 ctrl+鼠标左键释放 实现一个标识符跳转到 定义/声明 的功能(eclipse,vscode,qtcreator等IDE都具备这个功能)。遇到了这个问题。

首先看我这个博客了解一下信号:​​QScintilla的信号汇总和解释_我是标同学的博客/一个是关联qsci这个封装层的信号

connect(this, &QsciScintilla::indicatorReleased, this, &EditorCpp::onIndicatorReleased);

//或者关联qsciBasei这个封装层的信号

connect(this, &QsciScintillaBase::SCN_INDICATORRELEASE, this, &EditorCpp::onIndicatorReleasedSci);

这两个信号传出的参数都是一样的,这里以qsci这个封装层为例,如下:

void indicatorReleased(int line, int index, Qt::KeyboardModifiers state);

其中state指明了,我们鼠标点击这个indicator释放鼠标的时候我们按下的ctrl、alt、shift键的状态。但是我运行,始终打印出来的按键都是0???

但是我实测,关联那个按下信号 void indicatorClicked(int line, int index, Qt::KeyboardModifiers state);就能正确打印出按键信息的。

查找问题过程:(追踪qsci的源码)

首先看这个信号发射出来的位置

编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

因此,我们看到,QsciScintilla的信号,其实就是更底层的 QsciScintillaBase的信号来的。所以,我们需要追踪 SCN_INDICATORRELEASE 这个信号又是怎么来的。

编辑器库QsciScintilla的indicator点击没有按键信息的bug解决
编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

此时来到了Scintilla这个底层开源库这边了(关于这个库的继承结构,可以看我这个博客:​​QScintilla学习大全_我是标同学的博客-CSDN博客_qscintilla​​)

我们可以看到,其实 NotifyParent()这个函数发出的信号,也就是这里就是底层库 Scintilla 和qt的QsciScintilla 的接口处了,被qt全部转为对应的信号了。如果不是用qt进行封装,那么就可能是通过回调函数形式把这个接口暴漏出去了。很明显,qt的信号和槽机制很好用,清晰,灵活。

编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

继续追踪这个 NotifyIndicatorClick()函数被谁调用,我们发现是 :(一个是鼠标按下,一个是鼠标弹起,这两个函数都会调用到NotifyIndicatorClick()函数,从上面一张图可以看到,是靠第一个参数 true,表示按下,false表示弹起,来区分状态的)

void Editor::ButtonUpWithModifiers(Point pt, unsigned int curTime, int modifiers)
void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers)      

原因:

到这里,其实仍然会传进来按键的状态modifiers的,但是,我们可以看到鼠标弹起这里,直接传入的是0作为ctrl,alt、shift等的按键状态值,导致我们在qt那边程序的槽函数中,打印出来的按键值始终是0,这里终于找到原因了。真是坑啊!!!

而鼠标按下这个消息,就是正确的传入了按键信息,这就解释了我文章开头说的实测的结果:鼠标按下indicator能检测到ctrl、alt、shift等按键状态的,但是鼠标弹起时,检测到的始终是0了。

解决方法:

主要有两个方法:

  1. qt自己是可以获取到按键信息的,自己记录下来使用就行了。推荐用这个方法。
  2. 把这个库这里修改一下,让modifiers变量给传进去。但是如果我们使用QsciScintilla这个dll库来使用的话(看我这个博客 ​​QScintilla如何安装和入门(初学者)_我是标同学的博客-CSDN博客_qscintilla​​),就还得重新编译这个库,是个麻烦事,所以不推荐这个方法了。

从下图中可以看出,而另一个样式hostpot触发,人家就是按键状态给带着的。关于hostpot资料可以看这个 ​​https://qscintilla.com/#clickable_text/hotspots​​

编辑器库QsciScintilla的indicator点击没有按键信息的bug解决
编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

总结:

继续阅读