PyQt5 QTextEdit live HTML preview while editing - python

I am trying to edit a QTextEdit named self.chatTextField to display the HTML preview in a live format. For example if I do "" I want it to not show the tag, but bold the text. I am able to have this work if I use textBrowswer as a previewer, but I would like it all to be in one widget.
As you can see in the image above, I want match the part the displays the HTML as final product and not the tags. Is this possible?
I have tried various ways to convert .toPlainText() and then adding an HTML header and footer. I have tried to .insertHtml() and .setHtml(). I have tried to do tricks with open and close carrots, but nothing seems to be working. I am either getting it to simply remove all HTML (anything with carrots/tags) or it is causing recursion errors.
This is the only section of code that is dealing with updating the HTML. If you need further code please let me know. I can provide UI file as well.
def printMaster(self):
global my_text
if self.chatTextField.toPlainText() != "":
oldText = self.chatTextField.toPlainText()
newText = self.textBrowser.toPlainText()
if oldText != newText and oldText != my_text:
self.textBrowser.setText(self.chatTextField.toPlainText())
my_text = self.chatTextField.toPlainText()
if my_text.endswith('>'):
#my_text = self.chatTextField.toHtml()
# self.chatTextField.clear()
print(my_text)
# self.chatTextField.setHtml(my_text)
QCoreApplication.processEvents()
# cursor = self.chatTextField.textCursor()
# pos = cursor.selectionEnd()
#
# print(self.chatTextField.toHtml())
#
# my_text = self.chatTextField.toHtml()
#
# self.chatTextField.clear()
# # self.chatTextField.insertHtml(str(my_text))
#
# if my_text.endswith('<'):
# my_text = my_text + "<"
# self.chatTextField.setHtml(my_text)
# print(True)
# else:
# self.chatTextField.insertHtml(my_text)
#
#
# cursor.setPosition(pos)
#
# self.chatTextField.setTextCursor(cursor)
#
#
# QCoreApplication.processEvents()
#
# # self.chatTextField.show()

Related

How do you simulate completing a QFileDialog using PyQt and QTest?

I want to automate the testing of a GUI. In particular I want to test the "save" option from the file menu. I.e. when the save button is clicked the data from the fields in the UI are collected and then written to a json file.
The problem is, when the QFileDialog pops up asking for the user to enter the name of the file to save to, I cant get a handle on the dialog to continue testing. How do you automate this bit? I am not sure how to get a handle on the QFileDialog.
def hdl_save_report_as(self):
try:
self.dialog.setDefaultSuffix('json')
save_file, _ = self.dialog.getSaveFileName(caption="Save Report", filter="JSON Files (*.json)")
if save_file:
score = self.parent.main_tab_view.get_fields()
self.ui_model.report_path = save_file
with open(save_file, 'w') as f:
json.dump(score, f, indent=4)
except Exception as e:
result = dlg.message_dialog("Exception", "We ran into an error!", QMessageBox.Warning, e)
print(e)
def test_save_report(self):
self.main_window.menu.bt_save_file.trigger()
self.main_window.menu.dialog.selectFile('a_test_report.json')
## save_dialog = QApplication.activeModalWidget()
# save_dialog = QApplication.activeWindow()
# children = save_dialog.findChildren()
# active_line_edit = None
# confirm_button = None
# for c in children:
# if type(c) is QLineEdit:
# if c.hasFocus():
# active_line_edit = QLineEdit(c)
# # if type(c) is QPushButton:
# # if
# active_line_edit.setText("a_test_report")
self.assertTrue(os.path.exists(os.path.join(os.getcwd(), 'a_test_report.json')))
I have tried a few different approaches, is there a standard way to do this? Hopefully I have missed something obvious.
From what I can see and as explained in another post it is not possible to simulate interaction with the special QFileDialogs like getSaveFileName or getOpenFileName.
My approach is now managing the files in setup function like
def setUp(self):
self.test_report = "a_test_report.json"
# Remove an existing test report
if os.path.exists(self.test_report):
os.remove(self.test_report)
self.assertFalse(os.path.exists(os.path.join(os.getcwd(), self.test_report)))
# Create a file to test reading / writing
with open(self.test_report, 'w') as f:
f.write("")
self.assertTrue(os.path.exists(os.path.join(os.getcwd(), self.test_report)))
self.assertTrue(os.stat(self.test_report).st_size == 0)
self.main_window = MainWindow()
And testing like
def test_save_action(self):
# Trigger the save button - check if the file was overwritten with new info
self.main_window.menu.bt_save_file.trigger()
self.assertTrue(os.stat(self.test_report).st_size > 0)
Although it seems it is not possible to test a "Save As" function.

PyQt5 - Changing font color under cursor

I'm trying to change the color (Red) of the font that will be highlighted. The problem I'm facing is, as soon as I highlight the first word, all the following text becomes Red.
def cursorPosition(self):
logging.debug("Cursor Positiong changed")
self.cursor = self.ui.captureWindow.textCursor()
if self.cursor.hasSelection():
fmt = QTextCharFormat()
fmt.setForeground(Qt.red)
logging.debug(self.cursor.selectedText())
# We insert the new text, which will override the selected text
self.cursor.insertText(self.cursor.selectedText(), fmt)
# txt = '<p style="color:red;">' + self.cursor.selectedText() + '</p> '
# self.cursor.insertHtml(txt)
# And set the new cursor
self.ui.captureWindow.setTextCursor(self.cursor)
I've tried doing it with two methods, insertText and insertHtml.
insertHtml works if there is a space after the closing tag. Remove that space, it behaves the same way as insertText, everything will be red after the first highlight.

xlsxwriter's set_header not working as expected

I am using xlsxwriter 1.1.0 and Microsoft Excel 2016 I copied the example listed here (my version pasted below):
######################################################################
#
# This program shows several examples of how to set up headers and
# footers with XlsxWriter.
#
# The control characters used in the header/footer strings are:
#
# Control Category Description
# ======= ======== ===========
# &L Justification Left
# &C Center
# &R Right
#
# &P Information Page number
# &N Total number of pages
# &D Date
# &T Time
# &F File name
# &A Worksheet name
#
# &fontsize Font Font size
# &"font,style" Font name and style
# &U Single underline
# &E Double underline
# &S Strikethrough
# &X Superscript
# &Y Subscript
#
# &[Picture] Images Image placeholder
# &G Same as &[Picture]
#
# && Miscellaneous Literal ampersand &
#
# See the main XlsxWriter documentation for more information.
#
# Copyright 2013-2018, John McNamara, jmcnamara#cpan.org
#
import xlsxwriter
workbook = xlsxwriter.Workbook('E:\\headers_footers.xlsx')
preview = 'Select Print Preview to see the header and footer'
######################################################################
#
# A simple example to start
#
worksheet1 = workbook.add_worksheet('Simple')
header1 = '&CHere is some centered text.'
footer1 = '&LHere is some left aligned text.'
worksheet1.set_header(header1)
worksheet1.set_footer(footer1)
worksheet1.set_column('A:A', 50)
worksheet1.write('A1', preview)
######################################################################
#
# Insert a header image.
#
worksheet2 = workbook.add_worksheet('Image')
header2 = '&L&G'
# Adjust the page top margin to allow space for the header image.
worksheet2.set_margins(top=1.3)
worksheet2.set_header(header2, {'image_left': 'logo.png'})
worksheet2.set_column('A:A', 50)
worksheet2.write('A1', preview)
######################################################################
#
# This is an example of some of the header/footer variables.
#
worksheet3 = workbook.add_worksheet('Variables')
header3 = '&LPage &P of &N' + '&CFilename: &F' + '&RSheetname: &A'
footer3 = '&LCurrent date: &D' + '&RCurrent time: &T'
worksheet3.set_header(header3)
worksheet3.set_footer(footer3)
worksheet3.set_column('A:A', 50)
worksheet3.write('A1', preview)
worksheet3.write('A21', 'Next sheet')
worksheet3.set_h_pagebreaks([20])
######################################################################
#
# This example shows how to use more than one font
#
worksheet4 = workbook.add_worksheet('Mixed fonts')
header4 = '&C&"Courier New,Bold"Hello &"Arial,Italic"World'
footer4 = '&C&"Symbol"e&"Arial" = mc&X2'
worksheet4.set_header(header4)
worksheet4.set_footer(footer4)
worksheet4.set_column('A:A', 50)
worksheet4.write('A1', preview)
######################################################################
#
# Example of line wrapping
#
worksheet5 = workbook.add_worksheet('Word wrap')
header5 = "&CHeading 1\nHeading 2"
worksheet5.set_header(header5)
worksheet5.set_column('A:A', 50)
worksheet5.write('A1', preview)
######################################################################
#
# Example of inserting a literal ampersand &
#
worksheet6 = workbook.add_worksheet('Ampersand')
header6 = '&CCuriouser && Curiouser - Attorneys at Law'
worksheet6.set_header(header6)
worksheet6.set_column('A:A', 50)
worksheet6.write('A1', preview)
workbook.close()
On line 40, I changed the destination of the file and on line 68 I changed the name of the image; I have changed nothing apart from that. When I run the said program I don't see the images as well as the fonts. I have attached a screenshot below:
The program finished correctly without throwing any exception. Most of the other functions like set_column, insert_image etc. are working. But set_header isn't.
I don't know if any more information is required. Please feel free to demand for the same if required.
Headers and Footers in Excel don't show up in the normal view of the worksheet. As the output from the example says "Select Print Preview to see the header and footer".
In Print Preview mode the output looks like this:
Or in "Page Layout" view it looks like this:

Gtk TextView dynamic styling

I have a textview widget and I can apply tags such as bold, underline etc.
self.tags = {}
self.tags['bold'] = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD)
self.tags['italic'] = self.textbuffer.create_tag("italic", style=Pango.Style.ITALIC)
self.tags['underline'] = self.textbuffer.create_tag("underline", underline=Pango.Underline.SINGLE)
self.tags['ubuntu'] = self.textbuffer.create_tag("ubuntu", family = "Ubuntu Mono")
self.tags['size'] = self.textbuffer.create_tag("size", font_desc=Pango.FontDescription.from_string("32"))
The problem is with the last one, If I apply the font size tag, then the rest don't work.
The function that handles the insert-text signal is the following :
def insert_with_tags(self, buffer, start_iter, data, data_len):
if data_len == 1:
start_iter.backward_char()
end = self.textbuffer.props.cursor_position
end_iter = self.textbuffer.get_iter_at_offset(end)
self.textbuffer.apply_tag(self.tags['size'], start_iter, end_iter)
for tag in self.format_toolbar.buttons:
if self.format_toolbar.buttons[tag].get_active():
self.textbuffer.apply_tag(self.tags[tag], start_iter, end_iter)
If I remove the line that applies the font size everything works, but I want to let the user to be able to modify the font (here im testing it with just 1 font, but its the same when I add tags for the rest) while typing and not just modify it for the entire buffer.

ReportLab: Flowable too large on page 1 in frame 'normal' of template 'First'

I build PDF using ReportLab. My program has a MyDocTemplate(SimpleDocTemplate) class with two methods: beforePage(self) and afterPage(self) which add header and footer (as PNG image) on every page. There is also a MyDocStyle class which describe ParagraphStyle.
Main method looks like this:
TITLE = Paragraph(Title, MyDocStyle.h1)
TO = Paragraph(To, MyDocStyle.h2)
FROM = Paragraph(From, MyDocStyle.h2)
SUBJECT = Paragraph(Subject, MyDocStyle.h2)
LONG_PARAGRAPH = Paragraph(Text, MyDocStyle.h3)
...
Elements = [TITLE, TO, FROM, SUBJECT, LONG_PARAGRAPH, ...]
doc = MyDocTemplete('output.pdf', pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=4*cm, bottomMargin=4*cm)
doc.build(Elements)
Data comes from CSV files and GUI. From time to time (depends on data length) I receive an error:
Flowable <Spacer at 0x2631120 frame=normal>...(1 x 5.66929133858) too large
on page 1 in frame 'normal'(469.88976378 x 603.118110236) of template 'First'
This exception stop my program. For short Paragraphs I set in MyDocStyle class h2.keepWithNext = 1 however it's not perfect solution. ReportLab split correctly long paragraph if end of paragraph does not "coincide" with end of page (text area).
How can I deal with it?
This error occurs when ReportLab try to split a Spacer over two pages. It seems that the only way to workaround this issue is wrap your Spacer into a KeepTogether element:
elements.append(KeepTogether(Spacer(width, height)))
Solved. Don't use Spacer (e.g. Spacer(1, 0.2*cm)) as a separator for Paragraph. Instead, define spaceBefore and spaceAfter in ParagraphStyle, for example:
ParagraphStyle(name = 'Normal',
fontName = "Verdana",
fontSize = 11,
leading = 15,
alignment = TA_JUSTIFY,
allowOrphans = 0,
spaceBefore = 20,
spaceAfter = 20,
wordWrap = 1)

Categories

Resources