Search code examples
qtwebkitqtwebkit

Program crashes with WebKit Previewer example with on_textEdit_textChanged()


I recreated the example of a webkit that displays the content of a textEdit containing HTML: http://qt-project.org/doc/qt-4.8/webkit-previewer.html

I changed it so rather than the webkit HTML being changed upon clicking the button, it's changed upon the text in the textEdit being changed:

// changed when button is click. Works fine.
void Previewer::on_previewButton_clicked()
{
    // Update the contents in web viewer
    QString text = htmlTextEdit->toPlainText();
    webView->setHtml(text);
}

// change when text is changed. Crashes.
void Previewer::on_htmlTextEdit_textChanged()
{
    // Update the contents in web viewer
    QString text = "<html><body><h1>No crash!</h1></body></html>";
    webView->setHtml(text);
}

This causes the program to crash as soon as it starts. I altered the program to run the function only a bit later (I thought maybe something needed to be initialized) but it still crashed once it reached the textChanged function. Why is it crashing? How can I fix this?


Solution

  • Your program is entering an infinite loop because, in the example, there's a connection between the webView's loadFinished(bool) signal and the text/html editor's updateTextEdit() slot.

    Basically, editing the HTML causes the page to load again, which causes an update to the editor, which causes the page to load again, so on and so forth.

    A quick way I solved this was to add a static bool flag to the updateTextEdit SLOT/function that only allows it to run once.

     void MainWindow::updateTextEdit()
     {
         static bool once = false;
    
         if (once) {
             return;
         }
    
         once = true;
    
         QWebFrame *mainFrame = centralWidget->webView->page()->mainFrame();
         QString frameText = mainFrame->toHtml();
         centralWidget->plainTextEdit->setPlainText(frameText);
     }
    

    Doing this worked for me, but your version might work differently than mine. I followed the example closely, but added an htmlchanged() slot to the previewer class, and made the connection like so:

    connect(centralWidget->plainTextEdit, SIGNAL(textChanged()), centralWidget, SLOT(html_changed()));
    

    Also, I'm no expert, but I'm pretty sure this is not the best way to get around this, and I assume that updateTextEdit() needs to run more than once. It'll work for the time being, though.