С помощью QTextCursor выделить и удалить заданную строку из QTextBrowser
Прошу помощи с приведенным в заголовке вопросом.
В textBrowser
поступают ссылки из процесса опрашивающего сервер OTRS
на предмет заявок с флагом 'open', если этот флаг меняется на 'close', то строка предназначенная для удаления передается другим сигналом и должна быть удалена из textBrowser
.
Скитания по интернету и документации не помогли найти ответ.
main.py
import os
import sys
import requests
import pygame
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtCore import QThread, pyqtSignal
from gui import Ui_MainWindow
from pyotrs import Client
class Parser(QThread):
ticket_list_signal = pyqtSignal(str)
new_ticket_signal = pyqtSignal(str)
ticket_list_remove_signal = pyqtSignal(str)
error_signal = pyqtSignal(str)
cycle_counter = 0
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.ticket_tuple = []
self.links_list = []
self.removed_link = []
self.ticket_id_list = []
self.wait_time = None
self.url = None
self.log = None
self.pas = None
self.sound_file = None
def run(self):
while True:
self.pars()
def pars(self):
try:
response = requests.get(
f'{self.url}/otrs/nph-genericinterface.pl/Webservice/GenericTicketConnectorREST/TicketSearch?UserLogin={self.log}&Password={self.pas}',
)
response = response.content.decode("utf-8")
resp_values = eval(response)
except Exception as ex:
print(f'{ex}')
self.error_signal.emit('Problems connecting to the server')
print(resp_values)
client = Client(self.url, self.log, self.pas)
client.session_create()
for item in resp_values['TicketID']:
ticket = client.ticket_get_by_id(int(item))
self.ticket_id_list.append(item)
if ticket.field_get("TicketNumber") not in self.ticket_tuple and ticket.field_get("State") == "open":
self.ticket_tuple.append(f'{ticket.field_get("TicketNumber")}')
if self.cycle_counter > 0:
self.new_ticket_signal.emit(f'{ticket.field_get("TicketNumber")} {ticket.field_get("Title")}')
pygame.mixer.init()
pygame.mixer.music.load(self.sound_file)
pygame.mixer.music.play()
link_url = f'{self.url}/otrs/index.pl?Action=AgentTicketZoom;TicketID={item}'
self.links_list = f'<a href="{link_url}">№ {ticket.field_get("TicketNumber")} Title: {ticket.field_get("Title")}</a>'
print(f'BEFORE REMOVE: {self.links_list}')
self.ticket_list_signal.emit(self.links_list)
elif ticket.field_get("TicketNumber") in self.ticket_tuple and ticket.field_get("State") != "open":
self.ticket_tuple.remove(f'{ticket.field_get("TicketNumber")}')
link_url = f'{self.url}/otrs/index.pl?Action=AgentTicketZoom;TicketID={item}'
self.removed_link = f'<a href="{link_url}">№ {ticket.field_get("TicketNumber")} Title: {ticket.field_get("Title")}</a>'
print(f'AFTER REMOVE: {self.removed_link}')
self.ticket_list_remove_signal.emit(self.removed_link)
else:
pass
print(self.ticket_tuple)
self.cycle_counter = self.cycle_counter + 1
if self.cycle_counter > 50:
self.cycle_counter = 1
print(self.cycle_counter)
print(f'TIME WAIT: {self.wait_time}')
QThread.sleep(self.wait_time)
class ConfGUI(QtWidgets.QMainWindow):
def __init__(self):
super(ConfGUI, self).__init__(parent=None)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.file_path = os.path.dirname(__file__)
self.sound_file = os.path.join(self.file_path, 'sounds/notice_notice.mp3')
self.ui.lineEdit_4.setText(self.sound_file)
self.ui.pushButton.clicked.connect(self.get_file)
self.pars_thread = Parser()
self.ui.pushButton_2.clicked.connect(self.create_session)
self.ticket_links = self.pars_thread.ticket_list_signal.connect(self.links_add, QtCore.Qt.ConnectionType.QueuedConnection)
self.new_ticket = self.pars_thread.new_ticket_signal.connect(self.mb, QtCore.Qt.ConnectionType.QueuedConnection)
self.remove_ticket_links = self.pars_thread.ticket_list_remove_signal.connect(self.remove_links, QtCore.Qt.ConnectionType.QueuedConnection)
self.error_message = self.pars_thread.error_signal.connect(self.mb, QtCore.Qt.ConnectionType.QueuedConnection)
def get_file(self):
try:
self.sound_file = QtWidgets.QFileDialog.getOpenFileName(self, 'Выберете звук сигнала')
self.sound_file = self.ui.lineEdit_4.textChanged(self.sound_file)
except Exception as e:
logging.warning(f'Exception in get folder: {e}', exc_info=True)
def create_session(self):
wait_time = int(self.ui.lineEdit_5.text())
url = self.ui.lineEdit.text()
log = self.ui.lineEdit_2.text()
pas = self.ui.lineEdit_3.text()
self.pars_thread.wait_time = wait_time
self.pars_thread.url = url
self.pars_thread.log = log
self.pars_thread.pas = pas
self.pars_thread.sound_file = self.sound_file
self.pars_thread.start()
def links_add(self, links):
self.ui.textBrowser.append(links)
def remove_links(self, removed_links): # этот метод должен удалять строки
cursor = self.ui.textBrowser.textCursor()
# cursor.selectedText(removed_links) # TypeError: selectedText(self): too many arguments
cursor.selection(removed_links) # TypeError: selection(self): too many arguments
cursor.removeSelectedText()
cursor.clearSelection()
self.ui.textBrowser.textCursor(cursor)
def mb(self, d_msg):
dlg = QMessageBox(self)
dlg.setWindowTitle('Attention!')
dlg.setText(d_msg)
dlg.setIcon(QMessageBox.Icon.Information)
dlg.setStandardButtons(QMessageBox.StandardButton.Ok)
dlg.exec()
if __name__ == '__main__':
app = QApplication(sys.argv)
win = ConfGUI()
win.show()
sys.exit(app.exec_())
gui.py
# Form implementation generated from reading ui file 'gui.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 550)
MainWindow.setMinimumSize(QtCore.QSize(400, 550))
MainWindow.setMaximumSize(QtCore.QSize(500, 550))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setMinimumSize(QtCore.QSize(140, 20))
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.verticalLayout.addWidget(self.lineEdit)
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setMinimumSize(QtCore.QSize(140, 20))
self.label_2.setObjectName("label_2")
self.verticalLayout.addWidget(self.label_2)
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setText("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.verticalLayout.addWidget(self.lineEdit_2)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setMinimumSize(QtCore.QSize(140, 20))
self.label_3.setObjectName("label_3")
self.verticalLayout.addWidget(self.label_3)
self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_3.setText("")
self.lineEdit_3.setObjectName("lineEdit_3")
self.verticalLayout.addWidget(self.lineEdit_3)
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setMinimumSize(QtCore.QSize(140, 20))
self.label_5.setObjectName("label_5")
self.verticalLayout.addWidget(self.label_5)
self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_5.setObjectName("lineEdit_5")
self.verticalLayout.addWidget(self.lineEdit_5)
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout.addWidget(self.pushButton_2)
self.verticalLayout_3.addLayout(self.verticalLayout)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setMinimumSize(QtCore.QSize(140, 20))
self.label_4.setObjectName("label_4")
self.verticalLayout_2.addWidget(self.label_4)
self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_4.setObjectName("lineEdit_4")
self.verticalLayout_2.addWidget(self.lineEdit_4)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setMinimumSize(QtCore.QSize(140, 25))
self.pushButton.setObjectName("pushButton")
self.verticalLayout_2.addWidget(self.pushButton)
self.verticalLayout_3.addLayout(self.verticalLayout_2)
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName("textBrowser")
self.textBrowser.setOpenExternalLinks(True)
self.verticalLayout_3.addWidget(self.textBrowser)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "New ticket finder"))
self.label.setText(_translate("MainWindow", "URL"))
self.lineEdit.setText(_translate("MainWindow", "http://127.0.0.1"))
self.lineEdit_5.setText(_translate("MainWindow", "10"))
self.label_2.setText(_translate("MainWindow", "Login"))
self.label_3.setText(_translate("MainWindow", "Password"))
self.label_5.setText(_translate("MainWindow", "The interval between requests (sec)"))
self.pushButton_2.setText(_translate("MainWindow", "Connect"))
self.label_4.setText(_translate("MainWindow", "Звук уведомления"))
self.pushButton.setText(_translate("MainWindow", "Выбрать файл"))
Редакция 1:
Довел функция remove_links до такого вида:
def remove_links(self, removed_links):
cursor = self.ui.textBrowser.textCursor()
self.ui.textBrowser.moveCursor(QtGui.QTextCursor.MoveOperation.Start)
self.ui.textBrowser.find(removed_links, QtGui.QTextDocument.FindFlag.FindWholeWords)
cursor.select(QTextCursor.SelectionType.LineUnderCursor)
cursor.removeSelectedText()
self.ui.textBrowser.setTextCursor(cursor)
Теперь она удаляет последнюю строку списка, но не ищет точного совпадения с переданной ей в переменной.
Скрин интерфейса:
Источник: Stack Overflow на русском