QPlainTextEdit widget in PyQt5 with clickable text
<p>I am trying to build a simple code/text editor in PyQt5. Three important functionalities of a code-editor come to my mind:<br>
(1) <em>Syntax highlighting</em><br>
(2) <em>Code completion</em><br>
(3) <em>Clickable functions and variables</em><br>
<br>
I plan to base the code editor on a <code>QPlainTextEdit</code> widget. For the syntax highlighting, I will use the <code>QSyntaxHighlighter</code>:<br>
<a href="https://doc.qt.io/qt-5/qsyntaxhighlighter.html#details" rel="nofollow">https://doc.qt.io/qt-5/qsyntaxhighlighter.html#details</a> <br>
I have not yet figured out how to do code completion, but will worry about that feature later on. The showstopper right now is 'clickable functions and variables'. In mature code editors, one can click on a function call and jump to the definition of that function. The same holds for variables.<br>
<br>
I know that asking "how do I implement this feature?" is way too broad. So let's narrow it down to the following problem:<br>
<em>How can you make a certain word clickable in a <code>QPlainTextEdit</code> widget? An arbitrary Python function should get called when the word gets clicked. That Python function should also know what word was clicked to take appropriate action. Making the word light up blue-ish when the mouse hovers over it would be a nice bonus.</em>
<br>
<br>
I have written a small test-code, so you have a Qt window with a <code>QPlainTextEdit</code> widget in the middle to play around with:
<a href="http://i.stack.imgur.com/BmK5L.png" rel="nofollow"><img src="http://i.stack.imgur.com/BmK5L.png" alt="enter image description here"></a></p>

<p>Here is the code:</p>

<pre><code>import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

##################################################
#   'testText' is a snippet of C-code that       #
#   will get displayed in the text editor.       #
##################################################
testText = '\
# include &lt;stdio.h&gt;\n\
# include &lt;stdbool.h&gt;\n\
# include &lt;stdint.h&gt;\n\
# include "../FreeRTOS/Kernel/kernel.h"\n\
\n\
int main(void)\n\
{\n\
    /* Reset all peripherals*/\n\
    HAL_Init();\n\
\n\
    /* Configure the system clock */\n\
    SystemClock_Config();\n\
\n\
    /* Initialize all configured peripherals */\n\
    MX_GPIO_Init();\n\
    MX_SPI1_Init();\n\
    MX_SPI2_Init();\n\
    MX_SPI3_Init();\n\
}\n\
'

##################################################
#   A simple text editor                         #
#                                                #
##################################################
class MyMainWindow(QMainWindow):
    def __init__(self):
        super(MyMainWindow, self).__init__()
        # Define the geometry of the main window
        self.setGeometry(200, 200, 800, 800)
        self.setWindowTitle("text editor test")

        # Create center frame
        self.centerFrm = QFrame(self)
        self.centerFrm.setStyleSheet("QWidget { background-color: #ddeeff; }")
        self.centerLyt = QVBoxLayout()
        self.centerFrm.setLayout(self.centerLyt)
        self.setCentralWidget(self.centerFrm)

        # Create QTextEdit
        self.myTextEdit = QPlainTextEdit()
        self.myTextEdit.setPlainText(testText)
        self.myTextEdit.setStyleSheet("QPlainTextEdit { background-color: #ffffff; }")
        self.myTextEdit.setMinimumHeight(500)
        self.myTextEdit.setMaximumHeight(500)
        self.myTextEdit.setMinimumWidth(700)
        self.myTextEdit.setMaximumWidth(700)

        self.centerLyt.addWidget(self.myTextEdit)
        self.show()


if __name__== '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Fusion'))
    myGUI = MyMainWindow()
    app.exec_()
    del app
    sys.exit()
</code></pre>

<p>Maybe you can utilize <a href="https://github.com/hlamer/qutepart" rel="nofollow">qutepart</a>. It looks like it does what you need. If you can't use it, then maybe you can look at the source code to see how they implemented different features, like clickable text.</p>

python qt pyqt pyqt5