Way to save QTextEdit scroll state?
-
wrote on 16 Oct 2023, 17:23 last edited by
Is there any way the scroll state of QTextEdit be saved to a local file or within code itself? I tried taking scrollbar position, but it gets reset while switching between files. I set up a QTextEdit to load a EPUB file's content when a element in QTreeview is doubleclicked. It works once and stops working after a while.
Or, is there any alternate way to load EPUB files that will make it easier?from PySide6.QtWidgets import QApplication, QDialog, QVBoxLayout,QMessageBox,QLineEdit,QPushButton,QMainWindow,QSplashScreen,QFileDialog,QTreeView,QFileSystemModel,QTextBrowser,QTextEdit from PySide6.QtGui import QPixmap,QTextCharFormat,QFont,QTextCursor,QColor from PySide6.QtCore import Qt from PySide6.QtUiTools import QUiLoader import sys from ebooklib import epub from bs4 import BeautifulSoup import qdarktheme import hashlib import time scroll_positions = {} qss = """ QScrollBar::sub-page:horizontal { background: rgba(255, 255, 255, 0) } QScrollBar::add-page:horizontal { background: rgba(255, 255, 255, 0) } QScrollBar::sub-page:vertical { background: rgba(255, 255, 255, 0) } QScrollBar::add-page:vertical { background: rgba(255, 255, 255, 0) } QScrollBar::handle { background : rgba(138,124,171,1); min-height: 40px; } QScrollBar::handle:vertical { background : rgba(138,124,171,1); min-height: 40px; } QScrollBar::handle::pressed { background : rgba(138,124,171,1); } QScrollBar::handle::hover { background : rgba(138,124,171,1); } QScrollBar::add-line, QScrollBar::sub-line { width: 0; subcontrol-position: right; subcontrol-origin: margin; } """ def show_splash_screen(): splash_pix = QPixmap('assets\splash.jpg') splash_pix = splash_pix.scaled(550, 450, Qt.KeepAspectRatio,Qt.SmoothTransformation) splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) splash.setMask(splash_pix.mask()) splash.show() return splash def main(): app = QApplication(sys.argv) qdarktheme.setup_theme(additional_qss=qss,custom_colors={ "[dark]": { "primary": "#D0BCFF", "border": "#00000000", "treeSectionHeader.background":"#8a7cab" } }) # Create and show splash screen splash = show_splash_screen() main_window = Main() splash.close() main_window.children()[1].show() sys.exit(app.exec()) class Main(QMainWindow): def __init__(self): super().__init__() self.current_file_hash = None loader = QUiLoader() ui_file = "assets/main.ui" ui = loader.load(ui_file, self) self.directory = ui.findChild(QPushButton,"direct") self.directory.clicked.connect(self.dirpop) self.tree = ui.findChild(QTreeView,"tree") self.model = QFileSystemModel() self.model.setRootPath("/") self.tree.setModel(self.model) self.tree.setRootIndex(self.model.index("/")) self.tree.doubleClicked.connect(self.choose) self.text = ui.findChild(QTextEdit,'text') self.text.setReadOnly(True) self.scroll_bar = self.text.verticalScrollBar() def dirpop(self): options = QFileDialog.Options() directory = QFileDialog.getExistingDirectory(self, "Select Directory", "", options=options) if directory: self.tree.setRootIndex(self.model.index(directory)) def generate_file_hash(self, content): sha256 = hashlib.sha256() sha256.update(content.encode('utf-8')) return sha256.hexdigest() def choose(self, index): file_path = self.model.filePath(index) if ".epub" in file_path: # Save the current scroll position if self.current_file_hash: scroll_positions[self.current_file_hash] = self.text.verticalScrollBar().value() book = epub.read_epub(file_path) content = "" for item in book.items: if isinstance(item, epub.EpubHtml): content += item.content.decode('utf-8') styled_content = f""" <html> <head> <style> body {{ color: rgb(255, 255, 255); font-size: 16px; background-color: rgba(26, 26, 29, 1); }} </style> </head> <body> {content} </body> </html> """ self.text.setHtml(styled_content) # Generate a unique hash for the current file self.current_file_hash = self.generate_file_hash(content) # Restore the scroll position if available if self.current_file_hash in scroll_positions: self.text.verticalScrollBar().setValue(scroll_positions[self.current_file_hash]) print(scroll_positions) else: QMessageBox.information(self, "Invalid filetype","Please choose another file") if __name__ == "__main__": main()
-
@JonB The hash function is not the issue, as I checked the printed dictionary value. And for the files that does not work, the position gets shifted to around 1000 everytime
wrote on 16 Oct 2023, 21:35 last edited by@Rivridis said in Way to save QTextEdit scroll state?:
And for the files that does not work, the position gets shifted to around 1000 everytime
If it were me, I would try moving the
self.text.verticalScrollBar().setValue(scroll_positions[self.current_file_hash])
into a single shot
QTimer
with0
or small delay after you have done theself.text.setHtml(styled_content)
. -
Is there any way the scroll state of QTextEdit be saved to a local file or within code itself? I tried taking scrollbar position, but it gets reset while switching between files. I set up a QTextEdit to load a EPUB file's content when a element in QTreeview is doubleclicked. It works once and stops working after a while.
Or, is there any alternate way to load EPUB files that will make it easier?from PySide6.QtWidgets import QApplication, QDialog, QVBoxLayout,QMessageBox,QLineEdit,QPushButton,QMainWindow,QSplashScreen,QFileDialog,QTreeView,QFileSystemModel,QTextBrowser,QTextEdit from PySide6.QtGui import QPixmap,QTextCharFormat,QFont,QTextCursor,QColor from PySide6.QtCore import Qt from PySide6.QtUiTools import QUiLoader import sys from ebooklib import epub from bs4 import BeautifulSoup import qdarktheme import hashlib import time scroll_positions = {} qss = """ QScrollBar::sub-page:horizontal { background: rgba(255, 255, 255, 0) } QScrollBar::add-page:horizontal { background: rgba(255, 255, 255, 0) } QScrollBar::sub-page:vertical { background: rgba(255, 255, 255, 0) } QScrollBar::add-page:vertical { background: rgba(255, 255, 255, 0) } QScrollBar::handle { background : rgba(138,124,171,1); min-height: 40px; } QScrollBar::handle:vertical { background : rgba(138,124,171,1); min-height: 40px; } QScrollBar::handle::pressed { background : rgba(138,124,171,1); } QScrollBar::handle::hover { background : rgba(138,124,171,1); } QScrollBar::add-line, QScrollBar::sub-line { width: 0; subcontrol-position: right; subcontrol-origin: margin; } """ def show_splash_screen(): splash_pix = QPixmap('assets\splash.jpg') splash_pix = splash_pix.scaled(550, 450, Qt.KeepAspectRatio,Qt.SmoothTransformation) splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) splash.setMask(splash_pix.mask()) splash.show() return splash def main(): app = QApplication(sys.argv) qdarktheme.setup_theme(additional_qss=qss,custom_colors={ "[dark]": { "primary": "#D0BCFF", "border": "#00000000", "treeSectionHeader.background":"#8a7cab" } }) # Create and show splash screen splash = show_splash_screen() main_window = Main() splash.close() main_window.children()[1].show() sys.exit(app.exec()) class Main(QMainWindow): def __init__(self): super().__init__() self.current_file_hash = None loader = QUiLoader() ui_file = "assets/main.ui" ui = loader.load(ui_file, self) self.directory = ui.findChild(QPushButton,"direct") self.directory.clicked.connect(self.dirpop) self.tree = ui.findChild(QTreeView,"tree") self.model = QFileSystemModel() self.model.setRootPath("/") self.tree.setModel(self.model) self.tree.setRootIndex(self.model.index("/")) self.tree.doubleClicked.connect(self.choose) self.text = ui.findChild(QTextEdit,'text') self.text.setReadOnly(True) self.scroll_bar = self.text.verticalScrollBar() def dirpop(self): options = QFileDialog.Options() directory = QFileDialog.getExistingDirectory(self, "Select Directory", "", options=options) if directory: self.tree.setRootIndex(self.model.index(directory)) def generate_file_hash(self, content): sha256 = hashlib.sha256() sha256.update(content.encode('utf-8')) return sha256.hexdigest() def choose(self, index): file_path = self.model.filePath(index) if ".epub" in file_path: # Save the current scroll position if self.current_file_hash: scroll_positions[self.current_file_hash] = self.text.verticalScrollBar().value() book = epub.read_epub(file_path) content = "" for item in book.items: if isinstance(item, epub.EpubHtml): content += item.content.decode('utf-8') styled_content = f""" <html> <head> <style> body {{ color: rgb(255, 255, 255); font-size: 16px; background-color: rgba(26, 26, 29, 1); }} </style> </head> <body> {content} </body> </html> """ self.text.setHtml(styled_content) # Generate a unique hash for the current file self.current_file_hash = self.generate_file_hash(content) # Restore the scroll position if available if self.current_file_hash in scroll_positions: self.text.verticalScrollBar().setValue(scroll_positions[self.current_file_hash]) print(scroll_positions) else: QMessageBox.information(self, "Invalid filetype","Please choose another file") if __name__ == "__main__": main()
wrote on 16 Oct 2023, 17:26 last edited by@Rivridis said in Way to save QTextEdit scroll state?:
I tried taking scrollbar position, but it gets reset while switching between files.
Aren't you supposed to restore it after loading the file then?
-
@Rivridis said in Way to save QTextEdit scroll state?:
I tried taking scrollbar position, but it gets reset while switching between files.
Aren't you supposed to restore it after loading the file then?
-
@JonB That's what I did, as seen from the code, the thing is, it works for one fixed file and does not work for the others.
wrote on 16 Oct 2023, 18:05 last edited by@Rivridis
Then I would guess you might have some issue in your "hash lookup" of each file? Use a debugger or moreprint()
statements. For all the files where "it does not work", what is the saved scroll position, what are you restoring and where does to fail to work? -
@Rivridis
Then I would guess you might have some issue in your "hash lookup" of each file? Use a debugger or moreprint()
statements. For all the files where "it does not work", what is the saved scroll position, what are you restoring and where does to fail to work? -
S SGaist moved this topic from General and Desktop on 16 Oct 2023, 18:31
-
@JonB The hash function is not the issue, as I checked the printed dictionary value. And for the files that does not work, the position gets shifted to around 1000 everytime
Did you try to update the position in reaction to textChanged rather than directly after setting the new content ?
-
Did you try to update the position in reaction to textChanged rather than directly after setting the new content ?
-
@JonB The hash function is not the issue, as I checked the printed dictionary value. And for the files that does not work, the position gets shifted to around 1000 everytime
wrote on 16 Oct 2023, 21:35 last edited by@Rivridis said in Way to save QTextEdit scroll state?:
And for the files that does not work, the position gets shifted to around 1000 everytime
If it were me, I would try moving the
self.text.verticalScrollBar().setValue(scroll_positions[self.current_file_hash])
into a single shot
QTimer
with0
or small delay after you have done theself.text.setHtml(styled_content)
. -
@Rivridis said in Way to save QTextEdit scroll state?:
And for the files that does not work, the position gets shifted to around 1000 everytime
If it were me, I would try moving the
self.text.verticalScrollBar().setValue(scroll_positions[self.current_file_hash])
into a single shot
QTimer
with0
or small delay after you have done theself.text.setHtml(styled_content)
. -
-
@JonB Damn it works, thanks a lot. I had been trying to solve this for a day straight :/ Just needed 100 as time delay, small values did not work
1/10