K.Mulier
K.Mulier

Reputation: 9620

QPlainTextEdit widget in PyQt5 with clickable text

I am trying to build a simple code/text editor in PyQt5. Three important functionalities of a code-editor come to my mind:
(1) Syntax highlighting
(2) Code completion
(3) Clickable functions and variables

I plan to base the code editor on a QPlainTextEdit widget. For the syntax highlighting, I will use the QSyntaxHighlighter:
https://doc.qt.io/qt-5/qsyntaxhighlighter.html#details
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.

I know that asking "how do I implement this feature?" is way too broad. So let's narrow it down to the following problem:
How can you make a certain word clickable in a QPlainTextEdit 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.

I have written a small test-code, so you have a Qt window with a QPlainTextEdit widget in the middle to play around with: enter image description here

Here is the 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 <stdio.h>\n\
# include <stdbool.h>\n\
# include <stdint.h>\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()

EDIT
I just revisited this question after long time. In the meantime, I've constructed a website about QScintilla: https://qscintilla.com
You can find all info there :-)

Upvotes: 2

Views: 1678

Answers (1)

jyapayne
jyapayne

Reputation: 610

Maybe you can utilize qutepart. 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.

Upvotes: 1

Related Questions