Executing "SCI_GOTOLINE" API of Qscintilla inside indicatorReleased() event handler is not functioning properly

212 Views Asked by At

I am developing a desktop application using "PyQt4". The application contains an XML editor implemented on top of Qscintilla. However I have an issue whenever I click a hyperlink-alike text defined via indicators. The "indicatorClicked" event is invoked, but when I execute "SCI_GOTOLINE" API inside it, it goes to the desirable line properly but unluckily, for some reason, it selects the text from the clicked text position till the destination line. For me, it seems as if mouse does not get released! I tried also to use "indicatorReleased" event with no luck! Do u have any idea how to resolve this?

This is how I am hooking to indicator released event:

self.__editor.indicatorReleased.connect(self.__on_indicator_released)

event handler is simply invoking SCI_GOTOLINE API to some line number:

 def __on_indicator_released(self, line_number, index, keys):
    self.__editor.SendScintilla(QsciScintilla.SCI_GOTOLINE, line_number)
1

There are 1 best solutions below

2
On

I got a response from @Matic Kukovec & @K.Mulier on another thread. I am posting it here so others can benefit from it.

@Matic Kukovec replied to me: "There are two solutions: Use a QTimer.singleShot inside the indicatorReleased event to execute the SCI_GOTOLINE after a short delay (I use 50ms), or inside the indicatorReleased event use: while mouse_state != data.Qt.NoButton: PyQt5.QTest.qWait(1) to wait until there is no muse button pressed, and then execute SCI_GOTOLINE."

After trying the two approaches, the singleShot-based solution worked as charm:

Hooking to an indicator_released handler:

self.__editor.indicatorReleased.connect(self.__on_indicator_released)

Corresponding event handler:

def __on_indicator_released(self, line_number, index, keys):
    QTimer.singleShot(50, lambda: self.__go_to_line(line_number))

Calling SCI_GOTOLINE in __go_to_line API:

def __go_to_line(self, line_number):
    self.__editor.SendScintilla(QsciScintilla.SCI_GOTOLINE, line_number)

However, The mouse_state-based solution did not work, since mouse_button equals to "Qt.NoButton" all the time.

mouse_state = QtCore.QCoreApplication.instance().mouseButtons()
while mouse_state != Qt.NoButton:
    mouse_state = QtCore.QCoreApplication.instance().mouseButtons()
    QTest.qWait(1)