pythonpyqtqtexteditqtextbrowserqtextcursor

How can I erase the last lines in a QTextBrowser?


As I cannot write whole code here, I simplified it with the same problem.

The simplified program is python code connected with a ui file, which is:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>275</width>
    <height>267</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QTextBrowser" name="textBrowser">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>50</y>
      <width>256</width>
      <height>192</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="OkButton">
    <property name="geometry">
     <rect>
      <x>110</x>
      <y>10</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Ok</string>
    </property>
   </widget>
   <widget class="QPushButton" name="UndoButton">
    <property name="geometry">
     <rect>
      <x>190</x>
      <y>10</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Undo</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="textEdit">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>91</width>
      <height>31</height>
     </rect>
    </property>
    <property name="html">
     <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Gulim'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
    </property>
   </widget>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

and looks like:

program image

and the simplified python file is:

import sys
import os
from PyQt5.QtWidgets import *               
from PyQt5 import uic                       
from PyQt5 import QtGui

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
form_class = uic.loadUiType(BASE_DIR + "./tester2.ui")[0]

class WindowClass(QMainWindow, form_class) :
    def __init__(self) :
        super().__init__()
        self.setupUi(self)
    
        self.OkButton.clicked.connect(self.Do_Append)
        self.UndoButton.clicked.connect(self.Do_Undo)
    
    def Do_Append(self):
        data = self.textEdit.toPlainText()
        self.textBrowser.append(data)
        self.textBrowser.append('Test command')
        self.textBrowser.append('\n')
    
    def Do_Undo(self):
        cursor = self.textBrowser.textCursor()
    
        cursor.movePosition(QtGui.QTextCursor.StartOfLine)
        cursor.select(QtGui.QTextCursor.LineUnderCursor)
        cursor.removeSelectedText()
        cursor.movePosition(QtGui.QTextCursor.End)

if __name__ == "__main__" :
    app = QApplication(sys.argv)  
    myWindow = WindowClass()
    myWindow.show()
    app.exec_()

This code writes an input string into the textbrowser when you click the Ok button. And I am trying to erase only the latest two lines if I click the Undo button.

I found out about QTextCursor and used it (StartOfLine, Up, StartofBlock, PreviousBlock, LineUnderCursor, BlockUnderCursor....), but I cannot do what I want, as all I could do was just erasing one line. I think the problem is about enter (\n) but I cannot solve the problem.

What can I do to solve the problem?


Solution

  • The textCursor() function is const, which means the cursor object it returns is a copy. Thus, any changes made to it won't have any affect until it's reset it on the editor (i.e. by using setTextCursor()).

    Here is how to fix your example:

    def Do_Undo(self):
        cursor = self.textBrowser.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.movePosition(
            QtGui.QTextCursor.PreviousBlock,
            QtGui.QTextCursor.KeepAnchor, 4)
        cursor.removeSelectedText()
        self.textBrowser.setTextCursor(cursor)
    

    This moves the cursor to the end of the document, and sets the selection anchor there; then it moves back four lines, extending the selection as it goes; then finally it removes the selected text (once the cursor has been applied to the editor).