What would the QRegExp pattern be for capturing single quoted text for QSyntaxHighlighter? The matches should include the quotes, because I am building a sql code editor.
Test Pattern
string1 = 'test' and string2 = 'ajsijd'
So far I have tried:
QRegExp("\'.*\'")
I got it working on this regex tester: https://regex101.com/r/eq7G1v/2
but when I try to use that regex in python its not working probably because I need to escape a character?
self.highlightingRules.append((QRegExp("(['])(?:(?=(\\?))\2.)*?\1"), quotationFormat))
I am using Python 3.6 and PyQt5.
I am not an expert in regex but using a C++ answer to detect texts between double quotes changing it to single quote I see that it works:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class SyntaxHighlighter(QtGui.QSyntaxHighlighter):
def __init__(self, parent=None):
super(SyntaxHighlighter, self).__init__(parent)
keywordFormat = QtGui.QTextCharFormat()
keywordFormat.setForeground(QtCore.Qt.darkBlue)
keywordFormat.setFontWeight(QtGui.QFont.Bold)
keywordPatterns = ["'([^'']*)'"]
self.highlightingRules = [(QtCore.QRegExp(pattern), keywordFormat)
for pattern in keywordPatterns]
def highlightBlock(self, text):
for pattern, _format in self.highlightingRules:
expression = QtCore.QRegExp(pattern)
index = expression.indexIn(text)
while index >= 0:
length = expression.matchedLength()
self.setFormat(index, length, _format)
index = expression.indexIn(text, index + length)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
editor = QtWidgets.QTextEdit()
editor.append("string1 = 'test' and string2 = 'ajsijd'")
highlighter = SyntaxHighlighter(editor.document())
editor.show()
sys.exit(app.exec_())
Related
Please help me to complete this code. I want make a text editor and when I give a number in the input dialog, some text or some symbol or some numbers insert to my text lines to number in input dialog and starts with 1 to input dialog number ... Below is the code, you can know what I want to do.
Please see the code and tell me how can I do this?
from PyQt5.QtWidgets import (QWidget,QApplication,QTextEdit,
QInputDialog,QPushButton,QVBoxLayout)
import sys
class Tbx(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.vbox = QVBoxLayout()
self.btn = QPushButton('ClickMe',self)
self.btn.clicked.connect(self.dollar)
self.te = QTextEdit(self)
self.vbox.addWidget(self.te)
self.vbox.addWidget(self.btn)
self.setLayout(self.vbox)
self.setGeometry(300,300,400,250)
self.setWindowTitle('Application')
self.show()
def dollar(self):
text_1_int , ok = QInputDialog.getInt(self,'HowMany?','Enter How Many dollar do you want ?')
if not ok:
return
try:
current_lines = self.te.toPlainText().split('\n')
new_lines = list()
for dollar_counter in range(1, text_1_int + 1):
word = '$' * dollar_counter
new_lines += [text + word for text in current_lines]
self.te.setPlainText("\n".join(new_lines))
#I want this:
#...Texts in TextEditor at first:
#Hi
#User
#agent
#========================================================================
#...Text in TextEditor when I press the button and give 3 in InputDialog:
#Hi$
#Hi$$
#Hi$$$
#User$
#User$$
#User$$$
#agent$
#agent$$
#agent$$$
#Hi#
#Hi##
#Hi###
#User#
#User##
#User###
#agent#
#agent##
#agent###
#Hi#
#Hi##
#Hi###
#User#
#User##
#User###
#agent#
#agent##
#agent###
#Hi!
#Hi!!
#Hi!!!
#User!
#User!!
#User!!!
#agent!
#agent!!
#agent!!!
#Hi1
#Hi12
#Hi123
#User1
#User12
#User123
#agent1
#agent12
#agent123
#========================================================================
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Tbx()
sys.exit(app.exec_())
You are replacing the the text in your text edit at each iteration.
The easiest (clearer) way to do that, would be to generate all your lines before trying to add it to the text edit.
For example:
def dollar(self):
text_1_int , ok = QInputDialog.getInt(self,'HowMany?','Enter How Many dollar do you want ?')
if not ok:
return
try:
current_lines = self.te.toPlainText().split('\n')
new_lines = list()
for dollar_counter in range(1, text_1_int + 1):
word = '$' * dollar_counter
new_lines += [text + word for text in current_lines]
self.te.setPlainText("\n".join(new_lines))
except:
error_msg = QMessageBox()
error_msg.setIcon(QMessageBox.Critical)
error_msg.setText('Please Enter Just Number')
error_msg.setWindowTitle("Error")
error_msg.exec_()
If I enter 3 in the text input:
Btw, the dollar_counter increment is useless: it will be handled by the for loop.
I am creating a GUI application in python 3.4 using PyQt4 GUI-tool & NLTK. Here below i am explaining what task i have to perform in my application and what part i have completed:
Goal:
1) User will create category and provide very large text to save into database
2) based on uploaded text, user will search phrases( group of words). Phrases can occur on multiple line.
3) matched phrases list will be maintain according to lines where they found on document.
4) When user will select matched phrase line, cursor should move to that matched phrase line and highlight that phrase.
Completed:
1) I can upload documents and search phrase based on matched line.
2) and highlight in QEditText text box
Issue:
1) I am not able to highlight phrase. It only highlights single word from phrase
Code provided below what i have perform to highlight phrase:
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
import string
# list view class
from view_matched_phrases_ui import Ui_ViewList
from PyDB import DatabaseHandle
class ViewList(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ViewList, self).__init__(parent)
self.list = Ui_ViewList()
self.list.setupUi(self)
def show_list(self, phrases):
# self.list.phrase_text_view.setText("<div>Hello</div> Sahadev")
# cursor = self.list.phrase_line_view.setCursor()
# cursor.movePosition(QtGui.QTextCursor.Start)
# self.list.phrase_text_view.setTextCursor(curson)
ids = phrases[1]['pid']
with DatabaseHandle() as db:
for id in ids:
sql = "SELECT document FROM contracts WHERE id="+str(id)
data = db.get_single_data(sql)
phrase_data = str.maketrans({key: None for key in string.punctuation})
new_s = data[0].translate(phrase_data).lower()
for line in new_s.splitlines():
if phrases[0].replace('_', ' ') in line:
self.list.phrase_line_view.addItem(line)
# set selected contract in QTextEdit
self.list.phrase_text_view.setPlainText(new_s)
# self.list.phrase_text_view
cursor = self.list.phrase_text_view.textCursor()
# setup match
format = QtGui.QTextCharFormat()
format.setBackground(QtGui.QBrush(QtGui.QColor("yellow")))
# Setup the regex engine
pattern = phrases[0].replace("_", " ")
regex = QtCore.QRegExp(pattern)
# Process the displayed document
pos = 0
index = regex.indexIn(self.list.phrase_text_view.toPlainText(), pos)
while index != -1:
# Select the matched text and apply the desired format
cursor.setPosition(index)
cursor.movePosition(QtGui.QTextCursor.EndOfWord, 1)
cursor.mergeCharFormat(format)
# Move to the next match
pos = index + regex.matchedLength()
index = regex.indexIn(self.list.phrase_text_view.toPlainText(), pos)
# print(self.list.phrase_text_view)
# print(phrases)
This contribution will be great help for me.
I solved this issue by counting phrase length and nextWord method with Qt Text Object.
Rest of the code will be same only changes part i am providing here:
while index != -1:
# Select the matched text and apply the desired format
cursor.setPosition(index)
# go to next word
for i in range(len(self.matched_phrase.split(" "))):
cursor.movePosition(QtGui.QTextCursor.NextWord, 1)
cursor.mergeCharFormat(format)
# Move to the next match
pos = index + regex.matchedLength()
index = regex.indexIn(self.list.phrase_text_view.toPlainText(), pos)
I'm using mergeCharFormat on several words within my QTextEdit, in an effort to highlight them. Something like this:
import sys
from PyQt4 import QtGui, uic
from PyQt4.QtCore import *
def drawGUI():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
w.setGeometry(200, 200, 200, 50)
editBox = QtGui.QTextEdit(w)
text = 'Hello stack overflow, this is a test and tish is a misspelled word'
editBox.setText(text)
""" Now there'd be a function that finds misspelled words """
# Highlight misspelled words
misspelledWord = 'tish'
cursor = editBox.textCursor()
format_ = QtGui.QTextCharFormat()
format_.setBackground(QtGui.QBrush(QtGui.QColor("pink")))
pattern = "\\b" + misspelledWord + "\\b"
regex = QRegExp(pattern)
index = regex.indexIn(editBox.toPlainText(), 0)
cursor.setPosition(index)
cursor.movePosition(QtGui.QTextCursor.EndOfWord, 1)
cursor.mergeCharFormat(format_)
w.showFullScreen()
sys.exit(app.exec_())
if __name__ == '__main__':
drawGUI()
So, this highlighting feature works exactly as intended. However, I can't find a good way to clear the highlights from the textarea. What is a good method of doing such a thing- essentially just setting the char format of the entire QTextEdit back to its defaults?
What I've tried so far is getting the cursor again, and setting its format to a new format with a clear background, then putting the cursor over the entire selection and using QTextCursor.setCharFormat(), but this appears to do nothing.
Applying a new QTextCharFormat to the whole document works for me:
def drawGUI():
...
cursor.mergeCharFormat(format_)
def clear():
cursor = editBox.textCursor()
cursor.select(QtGui.QTextCursor.Document)
cursor.setCharFormat(QtGui.QTextCharFormat())
cursor.clearSelection()
editBox.setTextCursor(cursor)
button = QtGui.QPushButton('Clear')
button.clicked.connect(clear)
layout = QtGui.QVBoxLayout(w)
layout.addWidget(editBox)
layout.addWidget(button)
I'm trying to append nodes of namedtuple object to a treeView but I'm not sure how to subclass QAbstractItem (if that's even the proper way). I'm still very new to Python so this is confusing to me. Here is my problem code:
Exercise = namedtuple('Exercise','name html list')
e_list = []
for i in range(1,6,1):
dummy_list = [1,2,3,'a','b','c']
ntup = Exercise("exercise{0}".format(i),'html here',dummy_list)
e_list.append(ntup)
for e in e_list:
item = QtGui.QStandardItem(e) # gives error
self.tree_model.appendRow(item) # doesnt execute
And here is the the whole program:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from collections import namedtuple
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButton = QtGui.QPushButton(self)
self.pushButton.setText("Test 1 - doesn't work")
self.pushButton.clicked.connect(self.on_pushbutton)
self.pushButton2 = QtGui.QPushButton(self)
self.pushButton2.setText("Test 2 - works")
self.pushButton2.clicked.connect(self.on_pushbutton2)
self.treeView = QtGui.QTreeView(self)
self.treeView.clicked[QModelIndex].connect(self.on_clickitem)
self.tree_model = QtGui.QStandardItemModel()
self.treeView.setModel(self.tree_model)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.pushButton)
self.layoutVertical.addWidget(self.pushButton2)
self.layoutVertical.addWidget(self.treeView)
def on_pushbutton(self):
Exercise = namedtuple('Exercise','name html list')
e_list = []
for i in range(1,3,1):
dummy_list = [1,2,3,'a','b','c']
ntup = Exercise("exercise{}".format(i),'html here',dummy_list)
e_list.append(ntup)
for e in e_list:
item = QtGui.QStandardItem(e) # gives error
self.tree_model.appendRow(item) # never occurs
def on_pushbutton2(self):
txt = 'hello world'
item = QtGui.QStandardItem(txt)
self.tree_model.appendRow(item)
def on_clickitem(self,index):
item = self.tree_model.itemFromIndex(index) # doesn't work
print "item name:",item.getName() # doesn't work
print "item html:",item.getHtml() # doesn't work
print "item list:",item.getList() # doesn't work
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
I want to append the nodes into a tree and when I click on an item I want to get the values of the namedtuple (i.e. the values of 'name', 'html', and 'alist'). Thanks for your help.
Paul
I just ended up using QTreeWidget and setting the tree item data like this:
item = QtGui.QTreeWidgetItem()
item.mydata = my_namedtuple
I found the answer here: QtGui QTreeWidgetItem setData holding a float number
I didn't know you could just dynamically make an attribute for the tree item.
I have a QTextEdit window that shows the content of a file.
I would like to be able to find all matches inside the text using a regex and highlight them either by making the match background different or by changing the match text color or making it bold. How can I do this?
I think the simplest solution to your problem is to use the cursor associated to your editor in order to do the formatting. This way you can set the foreground, the background, the font style... The following example marks the matches with a different background.
from PyQt4 import QtGui
from PyQt4 import QtCore
class MyHighlighter(QtGui.QTextEdit):
def __init__(self, parent=None):
super(MyHighlighter, self).__init__(parent)
# Setup the text editor
text = """In this text I want to highlight this word and only this word.\n""" +\
"""Any other word shouldn't be highlighted"""
self.setText(text)
cursor = self.textCursor()
# Setup the desired format for matches
format = QtGui.QTextCharFormat()
format.setBackground(QtGui.QBrush(QtGui.QColor("red")))
# Setup the regex engine
pattern = "word"
regex = QtCore.QRegExp(pattern)
# Process the displayed document
pos = 0
index = regex.indexIn(self.toPlainText(), pos)
while (index != -1):
# Select the matched text and apply the desired format
cursor.setPosition(index)
cursor.movePosition(QtGui.QTextCursor.EndOfWord, 1)
cursor.mergeCharFormat(format)
# Move to the next match
pos = index + regex.matchedLength()
index = regex.indexIn(self.toPlainText(), pos)
if __name__ == "__main__":
import sys
a = QtGui.QApplication(sys.argv)
t = MyHighlighter()
t.show()
sys.exit(a.exec_())
The code is self-explanatory but if you have any questions just ask them.
Here is a sample of how can you highlight text in a QTextEdit:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class highlightSyntax(QSyntaxHighlighter):
def __init__(self, listKeywords, parent=None):
super(highlightSyntax, self).__init__(parent)
brush = QBrush(Qt.darkBlue, Qt.SolidPattern)
keyword = QTextCharFormat()
keyword.setForeground(brush)
keyword.setFontWeight(QFont.Bold)
self.highlightingRules = [ highlightRule(QRegExp("\\b" + key + "\\b"), keyword)
for key in listKeywords
]
def highlightBlock(self, text):
for rule in self.highlightingRules:
expression = QRegExp(rule.pattern)
index = expression.indexIn(text)
while index >= 0:
length = expression.matchedLength()
self.setFormat(index, length, rule.format)
index = text.indexOf(expression, index + length)
self.setCurrentBlockState(0)
class highlightRule(object):
def __init__(self, pattern, format):
self.pattern = pattern
self.format = format
class highlightTextEdit(QTextEdit):
def __init__(self, fileInput, listKeywords, parent=None):
super(highlightTextEdit, self).__init__(parent)
highlightSyntax(QStringList(listKeywords), self)
with open(fileInput, "r") as fInput:
self.setPlainText(fInput.read())
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = highlightTextEdit("/path/to/file", ["foo", "bar", "baz"])
main.show()
sys.exit(app.exec_())
QT5 has updated the RegEx, see QRegularExpression https://dangelog.wordpress.com/2012/04/07/qregularexpression/
I have updated the first example using cursors.
Note the following changes:
This doesn't wrap an edit, but uses the edit box inside, it could easily be changed to allow you to pass in the edit widget.
This does a proper regex find, not just a single word.
def do_find_highlight(self, pattern):
cursor = self.editor.textCursor()
# Setup the desired format for matches
format = QTextCharFormat()
format.setBackground(QBrush(QColor("red")))
# Setup the regex engine
re = QRegularExpression(pattern)
i = re.globalMatch(self.editor.toPlainText()) # QRegularExpressionMatchIterator
# iterate through all the matches and highlight
while i.hasNext():
match = i.next() #QRegularExpressionMatch
# Select the matched text and apply the desired format
cursor.setPosition(match.capturedStart(), QTextCursor.MoveAnchor)
cursor.setPosition(match.capturedEnd(), QTextCursor.KeepAnchor)
cursor.mergeCharFormat(format)