Checking formatting of selected text in QTextEdit - PySide6 - python-3.8

I' m working on a rich text editor and came across a small problem which I kind of solved with what seems like a "hack".
So I wanted to check if the selected text or the text in cursor position has any formatting, bold, italics etc and check the corresponding button that does the corresponding job but it gets weird.
if I do something like
if self.ed.fontItalic() is True:
self.italic.setChecked(True)
else:
self.italic.setChecked(False)
if self.ed.fontUnderline() is True:
self.uline.setChecked(True)
else:
self.uline.setChecked(False)
where "self.italic" and "self.uline" are checkable QPushButtons;
Only the format under the cursor gets checked, but not both buttons for italic and underlined, ie, if the selected text has bot formatting.
Basically, it ignores the selected text and looks for formatting of text under cursor.
So I I'm currently parsing the html to see if it has formatting;
def check_formatting(self):
if self.ed.textCursor().hasSelection():
print(self.ed.textCursor().selection().toHtml())
if "font-style:italic;" in self.ed.textCursor().selection().toHtml():
self.italic.setChecked(True)
else:
self.italic.setChecked(False)
if "text-decoration: underline;" in self.ed.textCursor().selection().toHtml():
self.uline.setChecked(True)
else:
self.uline.setChecked(False)
else:
if self.ed.fontItalic() is True:
self.italic.setChecked(True)
else:
self.italic.setChecked(False)
if self.ed.fontUnderline() is True:
self.uline.setChecked(True)
else:
self.uline.setChecked(False)
and code for formatting selected text or text under cursor on button click is as follows
def set_italic(self):
if self.italic.isChecked():
self.ed.setFontItalic(True)
if self.ed.textCursor().hasSelection():
if self.ed.fontItalic() != QTextFormat.FontItalic:
self.ed.setFontItalic(True)
else:
self.ed.setFontItalic(False)
else:
self.ed.setFontItalic(False)
All of this works nearly as intended but it all feels super hacky. And with the html parsing, obviously, if the user enters "font-style:italic;" in the text edit and selects the entered text, button for italic gets checked.
I've been looking through a lot of stuff on the internet but none of them helps me achieve as much as the above code does.

The default behavior is expected, from the programming point of view it's not possible to know if the developer is interested in knowing whether the selection has a format set at any point, or they want to know if it does not contain that format.
Also, checking the html of the document is conceptually wrong, as the format could be set outside the selection (including the usage of a default stylesheet), and it's also important to remember that the toHtml() function returns a "translation" of the underlying QTextDocument, it's not the document object itself.
The only proper way to verify the format at a specified position is by getting the QTextCharFormat of the text cursor for a given character position.
If you really want to check if the selection contains any format change at any position, no matter the cursor position, then you need to cycle through all characters in the selection and verify their format.
Note that in this case you need to connect to both cursorPositionChanged and selectionChanged signals, as the user could click on the editor at the cursor position, which would clear the selection but won't change the cursor position.
With the following code, the check_formatting function will automatically toggle buttons, so that you don't need to check the current format in the button function, but you can directly connect to the text edit functions as they will toggle the format exclusively based on the state set by check_formatting, thus overriding the default behavior.
class Editor(QtWidgets.QWidget):
def __init__(self):
# ...
self.ed.cursorPositionChanged.connect(self.check_formatting)
self.ed.selectionChanged.connect(self.check_formatting)
self.bold.toggled.connect(self.toggle_bold)
self.italic.toggled.connect(self.ed.setFontItalic)
self.underline.toggled.connect(self.ed.setFontUnderline)
def toggle_bold(self, bold):
self.ed.setFontWeight(QtGui.QFont.Bold if bold else QtGui.QFont.Normal)
def check_formatting(self):
# assume no format by default
bold = italic = underline = False
cursor = self.ed.textCursor()
if cursor.hasSelection():
rangeEnd = cursor.selectionEnd() + 1
else:
rangeEnd = cursor.selectionStart() + 1
for pos in range(cursor.selectionStart(), rangeEnd):
cursor.setPosition(pos)
fmt = cursor.charFormat()
if fmt.fontWeight() >= QtGui.QFont.Bold:
bold = True
if fmt.fontItalic():
italic = True
if fmt.fontUnderline():
underline = True
if all((bold, italic, underline)):
# all formats are set, no need for further checking
break
# set check states of buttons but block their signals to avoid
# unnecessary calls and unwanted behavior when using keyboard
# navigation for selection (eg: shift+arrows)
with QtCore.QSignalBlocker(self.bold):
self.bold.setChecked(bold)
with QtCore.QSignalBlocker(self.italic):
self.italic.setChecked(italic)
with QtCore.QSignalBlocker(self.underline):
self.underline.setChecked(underline)

Related

Set text box value in Word VBA

I have a Word 2010 form template with various text boxes, combo lists and radio buttons. I wish to take the value from one text box and insert it as the value of another text box when a Save button is invoked. I have extracted the value from the source text box with the code below but how do I then insert it as the value of the target text box? I have tried a few things including the reverse of the code below but so far without success.
srp = ActiveDocument.SelectContentControlsByTag("RPI").Item(1).Range.Text
The Range.Text property is read/write. So you use the exact reversal of the code you have.
srp = ActiveDocument.SelectContentControlsByTag("RPI").Item(1).Range.Text ' Read
ActiveDocument.SelectContentControlsByTag("SRP").Item(1).Range.Text = srp ' Write

Insert/replace string in existing text form field in Word (VBA)

So I'm trying to create a conditional dropdown in Word. I've used a Legacy Drop-Down Form Field with multiple options.
What I want to happen is when one of the options is selected from the dropdown (and then I guess you have to Tab to enter it...), the Legacy Text Form Field below, that has a simple default text, should populate with a new string from the case statement.
Things that I've already done/got working:
the drop down is working, and on exit it runs a macro
case statement is written out
the result of the case statement is in a variable (string type), let's call it StringVar
can pull the text form field's text (default text) with ActiveDocument.FormFields("TextBox").Result
What I figure out, however, is how to replace the default text in the already existing Text Form Field with the case statement's string variable text.
I've tried
ActiveDocument.FormFields("TextBox").Result = StringVar
but it doesn't change anything inside the text form field. The default text is still there.
So I can answer my own question after pondering and being hit with an "oh, duh" moment.
I had unprotected the document (ActiveDocument.Unprotect Password:="") in order to do this:
ActiveDocument.Content.InsertAfter Text:=("This is my text")
because I was wondering if I was grabbing the right string.
Turns out,
ActiveDocument.FormFields("TextBox").Result = StringVar
DOES work. BUT the file has to be protected (filling in forms) for it to replace the string in the text form field. Otherwise, nothing shows up even though the result had indeed been updated. Fancy that.

Setting shape position to book layout in vba

I want to use a word macro to set the position of the shapes in the document to book layout (see screenshot). But I can't find any reference which member I need to set for this (probably because my word is in german and this is called differently in the macro).
Can anyone tell me how to set the horizontal layout of a shape to book layout in vba?
[update] The following did the trick:
Shape.Left = -999994
Shape.LeftRelative = -999999
Shape.RelativeHorizontalPosition = wdRelativeHorizontalPositionMargin
In the most recent versions of Word the macro recorder gives no help for graphical objects. The next best thing you can do is to look at the properties available for the object in the Object Browser (F2).
If a graphical object has "text wrap" formatting then it belongs to the Shapes collection, so the list you need to look up is that of the Shape object.
In there you'll find the property RelativeHorizontalPosition, which takes a member of the WdRelativeHorizontalPosition enumeration. Looking at that list there are a number of options, none of which has "book" in it.
So the next step is to insert and format a Shape with the desired positioning. Then in the Immediate Window (Ctrl+G) you can type:
?ActiveDocument.Shapes(1).RelativeHorizontalPosition
Then press Enter. This will print a number that corresponds to the list of Enumeration members.
You can also test the effect of the various members by assigning them in the Immediate Window:
ActiveDocument.Shapes(1).RelativeHorizontalPosition = wdRelativeHorizontalPositionOuterMarginArea
Press Enter.
What you'll see is that there is not an enumeration member for every option in the dialog box. And that various positioning options in the dialog box correspond to a single enumeration member.
For your specific question, wdRelativeHorizontalPositionInnerMarginArea corresponds to the dialog box option you indicate.
ActiveDocument.Shapes(1).RelativeHorizontalPosition = wdRelativeHorizontalPositionInnerMarginArea
Besides the above, you need to use the LeftRelative and Left properties, as well. Take a look at those settings in the Immediate Window after using the dialog box and play with them, putting the image on odd/even pages.If it disappears - it's off visible portion of the page, which you can see in Reading View. In a nutshell, you need the NEGATIVE numbers to lock the image to the margin or page side. Positive numbers position it absolutely.

Automatically send barcode scanner input to textbox VB.Net / Winforms

I've reviewed dozens of options/solutions on this and I just can't get it to work.
Simply put, I have a VB.Net Winform that has a textbox where a user can manually type in text or they can use a USB connected barcode scanner (that simulates a keyboard) to capture a UPC.
What I'm trying to do is get the barcode input to get entered into the textbox regardless of which control has the current focus.
I have set the KeyPreview property of the form to True.
I then added some code to the frmMain_Keypress event as follows:
If Me.txtSearch.Focused = False Then
txtSearch.Focus()
End If
Very simple...and it works, sort of...
If txtSearch already has the focus, the entire barcode/UPC gets entered into the text box.
However, if another control has the focus, every character of the barcode/UPC EXCEPT THE FIRST CHARACTER gets entered into the text box. It always strips off the first character.
I placed some debug statements in the above code to see if the initial character was being read at all and it is being read...just not sent to the text box.
I've seen so many other REALLY complicated solutions to barcode scanning and it seems like I'm really close with something really simple, but, obviously it won't work if it strips the leading character.
Hopefully I'm missing something very obvious.
Change the code in your KeyPress event to:
If Me.txtSearch.Focused = False Then
txtSearch.Focus()
txtSearch.Text = e.KeyChar.ToString
txtSearch.SelectionStart = txtSearch.Text.Length
e.Handled = True
End If
That way you capture the first key that comes in.

get label from notebook tab

I have a gtk.Notebook and i want get text of label from current gtk.noteBook tab.
I make that:
text = self.get_tab_label(self.get_nth_page(self.get_current_page()))
if i print text i see:
But in gtk help i read that: get_tab_label_text: returnvalue: the text of the tab label, or None if the tab label widget is not a gtk.Label.
How can i get tet from label in this situation?
Thank you.
Any gtk.Widget can be a Notebook tab label. It is usually a gtk.Label, but not always. So two API methods exist to cover both situations:
gtk.Notebook.get_tab_label() returns a gtk.Widget that is the label widget. If it is a gtk.Label, you will need to call gtk.Label.get_text() to get the text.
gtk.Notebook.get_tab_label_text() returns a string of text only if the label widget is a gtk.Label, otherwise will return None.