I want to get the HTML code of a web page opened in QWebEngineView I use toHtml() function in QWebEnginePage Class like this
QWebEnginePage *page = ui->widget->page();
QString HTML = "";
page->toHtml([&HTML](QString html){qDebug() << "code \n\n\n" << html;});
the HTML code of html page appeared in qDebug good without problem the problem here is when I want to use HTML string outside the function when I show the size of the HTML varible it is equal to zero and empty so I tried this
QWebEnginePage *page = ui->widget->page();
QString HTML = "";
page->toHtml([&HTML](QString html){HTML = html;}); // crash
qDebug() << "i want to use HTML here outside the function = " << HTML;
but the app crash show so what should I do so I put the HTML data in the HTML variable so I can use it outside the function
Thanks in advance
Your problem is caused by the fact that the lambda is run asynchronously. So it is really called after you have exited the method in which you call toHtml
method and that also explains the crash - HTML
is a local variable within the method which has already exited so the lambda just randomly corrupts the memory used to be occupied by HTML
variable.
What you want to do here is to synchronize things i.e. block your method until the lambda is executed. It can be done with QEventLoop
but that would need to involve sending a special signal from the lambda to indicate the fact that the lambda finished executing. So it would look somewhat like this (non-tested):
class MyClass: public QObject
{
Q_OBJECT
public:
MyClass(QWebEnginePage & page, QObject * parent = 0);
void notifyHtmlReceived();
QString getHtml();
void setHtml(const QString & html) { m_html = html; }
Q_SIGNALS:
void htmlReceived();
private Q_SLOTS:
void requestHtmlFromPage();
private:
QWebEnginePage & m_page;
QString m_html;
};
MyClass::MyClass(QWebEnginePage & page, QObject * parent) :
QObject(parent),
m_page(page)
{}
void MyClass::notifyHtmlReceived()
{
emit htmlReceived();
}
QString MyClass::getHtml()
{
QEventLoop loop;
QObject::connect(this, SIGNAL(htmlReceived()), &loop, SLOT(quit()));
// Schedule the slot to run in 0 seconds but not right now
QTimer::singleShot(0, this, SLOT(requestHtmlFromPage()));
// The event loop would block until the lambda receiving the HTML is executed
loop.exec();
// If we got here, the html has been received and the result was saved in m_html
return m_html;
}
void MyClass::requestHtmlFromPage()
{
m_page.toHtml([this](QString html)
{
this->setHtml(html);
this->notifyHtmlReceived();
});
}