Searene
Searene

Reputation: 27574

How to set the height of QWebView to just hold its contents?

HtmlEditor is meant to be empty, editable and display only one line at first. Its height is just enough to hold one line, no more bigger or smaller. The height of it will extend as the user inputs more lines of text.

But the problem is, the height of HtmlEditor is a little smaller at first. I guess it is because the height is set to be exactly the size of the font, but there are also margins around the font too, which isn't considered. After inputting a character in it, the height of HtmlEditor will soon get bigger, just enough to hold the text thanks to the sizeChange function. I wish I could set the MaximumHeight of HtmlEditor as self.page().mainFrame().contentsSize().height() at first too, because contentsSize().height() seems perfect to hold the text. But it seems impossible considering there is no contents at all at first, in which case contentsSize().height() is just a wrong number. How to do the trick, setting both MaximumHeight and MinimumHeight of HtmlEditor as the height of the contents to just hold it?

class HtmlEditor(QWebView):
    def __init__(self):
        super().__init__()
        self.page().setContentEditable(True)
        self.page().contentsChanged.connect(self.sizeChange)
        self.setUpFont(10)

    def setUpFont(self, fontSize):
        self.htmlEditorSettings = self.settings()
        self.htmlEditorSettings.setFontSize(QWebSettings.DefaultFontSize, fontSize)
        self.setMaximumHeight(fontSize)

    def sizeChange(self):
        docHeight = self.page().mainFrame().contentsSize().height()
        self.setMinimumHeight(docHeight)

Upvotes: 0

Views: 343

Answers (2)

Searene
Searene

Reputation: 27574

Thank @MichaelBlakeley, this is my final code:

class HtmlEditor(QWebView):
    def __init__(self):
        super().__init__()
        self.page().setContentEditable(True)
        self.page().contentsChanged.connect(self.sizeChange)
        self.setupFont(10)

    def setupFont(self, fontSize):
        self.htmlEditorSettings = self.settings()
        self.htmlEditorSettings.setFontSize(QWebSettings.DefaultFontSize, fontSize)
        margins = self.contentsMargins()
        self.setFixedHeight(fontsize + margins.top() + margins.bottom())

    def sizeChange(self):
        docHeight = self.page().mainFrame().contentsSize().height()
        self.setFixedHeight(docHeight)

Upvotes: 0

Michael Blakeley
Michael Blakeley

Reputation: 346

Here is a hackish solution using QFontMetrics. I'm considering it hackish since I had to implement the text leading manually. There's probably a good reason why QFontMetrics seems to be spitting out a bad value, but this should work for you in the mean time.

We take all of the sizing information for a line of text, figure out how many lines we're working with, and adjust the size of QWebView accordingly:

class HtmlEditor(QWebView):
    def __init__(self):
        super().__init__()
        self.page().setContentEditable(True)
        self.page().contentsChanged.connect(self.update_height)
        self.settings().setFontSize(QWebSettings.DefaultFontSize, 10)
        self.setContentsMargins(QMargins(10, 10, 10, 10))
        self.update_height()

    def update_height(self):
        num_lines = len(self.page().mainFrame().toPlainText().splitlines())
        if num_lines == 0:
            num_lines = 1
        margins = self.contentsMargins()
        metrics = self.fontMetrics()
        leading = 4  # You should be able to do metrics.leading() but it was giving me 0 for some reason
        line_height = metrics.height()  # For the above reason, we use height() here instead of metrics.lineSpacing() and add the leading manually
        self.setFixedHeight((line_height * num_lines) + (leading * (num_lines - 1)) + margins.top() + margins.bottom())

I would be greatly appreciative if somebody could chime in here with a reasoning for the strange behavior of QFontMetrics in this scenario.

Upvotes: 1

Related Questions