I would like to create a function for searching for words and highlight them in Qscintilla editor and another function to go to specific line in the editor.
I know these functions works in QPlainTextEdit but since I am learning Qscintilla and most of the documents are written in C++, it's difficult for me to understand and the methods are quite different in Scintilla.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import *
#from PyQt5.QtCore import *
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.textEdit = QsciScintilla(self.centralwidget)
self.textEdit.setObjectName("textEdit")
self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
self.menuSearch = QtWidgets.QMenu(self.menubar)
self.menuSearch.setObjectName("menuSearch")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionOpen = QtWidgets.QAction(MainWindow)
self.actionOpen.setObjectName("actionOpen")
self.actionSave = QtWidgets.QAction(MainWindow)
self.actionSave.setObjectName("actionSave")
self.actionExit = QtWidgets.QAction(MainWindow)
self.actionExit.setObjectName("actionExit")
self.actionFind = QtWidgets.QAction(MainWindow)
self.actionFind.setObjectName("actionFind")
self.actionWord_Count = QtWidgets.QAction(MainWindow)
self.actionWord_Count.setObjectName("actionWord_Count")
self.actionNew = QtWidgets.QAction(MainWindow)
self.actionNew.setObjectName("actionNew")
self.menuFile.addAction(self.actionNew)
self.menuFile.addAction(self.actionOpen)
self.menuFile.addAction(self.actionSave)
self.menuFile.addAction(self.actionExit)
self.menuSearch.addAction(self.actionFind)
self.menuSearch.addAction(self.actionWord_Count)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuSearch.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuSearch.setTitle(_translate("MainWindow", "Search"))
self.actionOpen.setText(_translate("MainWindow", "Open"))
self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
self.actionSave.setText(_translate("MainWindow", "Save"))
self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
self.actionExit.setText(_translate("MainWindow", "Exit"))
self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q"))
self.actionFind.setText(_translate("MainWindow", "Find"))
self.actionFind.setShortcut(_translate("MainWindow", "Ctrl+F"))
self.actionWord_Count.setText(_translate("MainWindow", "Go to Line"))
self.actionNew.setText(_translate("MainWindow", "New"))
self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))
class Ui_Dock_Find(object):
def setupUi(self, Dock_Find):
Dock_Find.setObjectName("Dock_Find")
Dock_Find.resize(320, 65)
Dock_Find.setMinimumSize(QtCore.QSize(320, 65))
font = QtGui.QFont()
font.setPointSize(10)
Dock_Find.setFont(font)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("Ok.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dock_Find.setWindowIcon(icon)
self.dockWidgetContents = QtWidgets.QWidget()
self.dockWidgetContents.setObjectName("dockWidgetContents")
self.serachLabel = QtWidgets.QLabel(self.dockWidgetContents)
self.serachLabel.setGeometry(QtCore.QRect(10, 10, 71, 16))
self.serachLabel.setObjectName("serachLabel")
self.findLine = QtWidgets.QLineEdit(self.dockWidgetContents)
self.findLine.setGeometry(QtCore.QRect(80, 10, 151, 20))
self.findLine.setObjectName("findLine")
self.findButton = QtWidgets.QPushButton(self.dockWidgetContents)
self.findButton.setGeometry(QtCore.QRect(240, 10, 75, 23))
self.findButton.setObjectName("findButton")
Dock_Find.setWidget(self.dockWidgetContents)
self.retranslateUi(Dock_Find)
QtCore.QMetaObject.connectSlotsByName(Dock_Find)
def retranslateUi(self, Dock_Find):
_translate = QtCore.QCoreApplication.translate
Dock_Find.setWindowTitle(_translate("Dock_Find", "Find"))
self.serachLabel.setText(_translate("Dock_Find", "Search For:"))
self.findButton.setText(_translate("Dock_Find", "Find"))
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
#Defining Menu Actions
self.actionNew.triggered.connect(self.newFile)
self.actionOpen.triggered.connect(self.openFile)
#self.actionSave.triggered.connect(self.saveFile)
#self.actionExit.triggered.connect(self.exitFile)
self.actionFind.triggered.connect(self.findWord)
self.actionWord_Count.triggered.connect(self.gotoLine)
self.showMaximized()
def newFile(self):
self.textEdit.clear()
def openFile(self):
filename = QFileDialog.getOpenFileName(self, 'Open File', ".","(*.txt *.py *.log *.csv)")
if filename[0]:
#wordcounts = Counter()
with open(filename[0], 'rt') as fp:
for line in fp:
#wordcounts.update(line.split())
data = fp.read()
self.textEdit.setText(data)
def saveFile(self):
filename = QFileDialog.getSaveFileName(self, 'Save File', ".", "(*.txt)")
if filename[0]:
f = open(filename[0], 'wt')
with f:
text = self.textEdit.toPlainText()
f.write(text)
QMessageBox.about(self, "Save File", "File Saved Successfully")
def exitFile(self):
choice = QMessageBox.question(self, 'Close', "Do you want to close?", QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
self.saveFile()
self.close()
else:
pass
def findWord(self):
self.dock = Dock_Find()
self.addDockWidget(Qt.TopDockWidgetArea, self.dock)
self.dock.show()
def handleFind():
word = self.dock.findLine.text()
if self.textEdit.SCI_FINDTEXT(self.textEdit.SCFIND_WHOLEWORD(), word):
self.textEdit.SCFIND_WHOLEWORD(word)
else:
self.textEdit.SCFIND_WHOLEWORD(word)
return
self.dock.findButton.clicked.connect(handleFind)
def gotoLine(self):
window = GoTo()
window.show()
def handleGoTo():
ln = int(window.findText.text())
"""messenger = self.textEdit.SendScintilla()
messenger(self.textEdit.SCI_SETTARGETSTART, 0)
messenger(self.textEdit.SCI_SETTARGETEND, len(self.textEdit))
pos = messenger(self.textEdit.SCI_SEARCHINTARGET, len("ln"), "ln")
print(pos)"""
linecursor = self.textEdit.wordAtLineIndex(ln, self.textEdit.getCursorPosition()[1])
print(linecursor)
self.textEdit.SCI_GOTOPOS(window.findText.text())
window.hide()
window.findButton.clicked.connect(handleGoTo)
class Dock_Find(QtWidgets.QDockWidget, Ui_Dock_Find):
def __init__(self, parent=None):
super(Dock_Find, self).__init__(parent)
self.setupUi(self)
self.findLine.setPlaceholderText("Type Here")
class GoTo(QDialog):
def __init__(self):
super(GoTo, self).__init__()
self.initUI()
self.setWindowTitle("GoTo")
icon = QIcon()
icon.addPixmap(QPixmap(":/image/graphy_100px.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(icon)
def initUI(self):
self.lb1 = QLabel("Go To Line:", self)
self.lb1.setStyleSheet("font-size: 15px")
self.lb1.move(10, 10)
self.findText = QLineEdit(self)
self.findText.move(10, 40)
self.findText.resize(200, 20)
self.findText.setPlaceholderText('Type the line number')
self.findText.setClearButtonEnabled(True)
self.findText.setInputMask("9999999999") #For allowing up to number digit only as input
self.findButton = QPushButton('GO', self)
self.findButton.move(220, 40)
if __name__ == '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Fusion'))
myGUI = MainWindow()
sys.exit(app.exec_())
I don't understand how to implement these two functions and I have been trying, but no positive result for finding the word. However for second function, I can print the word which starts with the line number but I want to highlight that word with line number when the function go to line is searched.
Firstly, let me point out that your code has several problems:
self.text.SCFIND_WHOLEWORD()in your finding module, which tends to call the method, as considered by the Python interpreter.self.textEdit.SCI_GOTOPOS()in your go-to module, which is also tend to be called as a function even it isn't a function and doesn't have the ability to do so.Solutions for your problems
Find whole-word problems
According to the documentation, the
QsciScintillawidget and its framework,QScintilla, have already provided you a complete-set of finding utilities. For example, your desired functionality, as commented above by @ekhumoro, looks like the following.Consider the above parameters index.
expr- the string that you want to find.re- if enabled, regular-expression find mode is enabled.cs- if enabled, case-sensitive search mode is enabled.wo- if enabled, whole-word-only search mode is enabled.wrap- if enabled, the search will wrap around the end of the text.forward- ifTrue, the search occurs forward; otherwise backward from the current position of the text, or thelineandindexof the text.line- if negative (invalid), the search will start at the current position of the text. Else it starts with theindex(column) of theline. Counted from0.index- See thelineparameter.posix- if enabled, the search will be treated as a POSIX-compatible manner.cxx11- if enabled and thereoption is enabled, the ReGeX is treated as the C++11 standard regular expression.After the consideration, replace your code,
with
Goto line problem
According to the documentation, we have the
setCursorPositionmethod (the method is so straightforward that I won't list them here).So, replace your code
with
This single-line comment is basically and ideally, same as your ten-lines one.
Comment me if your problem is, still, no solved.