PDA

View Full Version : QWebView with two instances of QApplication



khilin
24th April 2013, 17:44
We are developing our own widget that inherits from QWebView; we are using TDD (Test Driven Development) to do this. For every test we run, we create a QApplication, run the test code and delete the QApplication, the idea behind this is to have tests that behave as much as possible as if they were completely independent from the rest of the tests.
The problem we are having is that after the first test (the tests run every time in a random order, so every test can be the first test) when we set a piece of HTML code to our QWebView class (using setHtml(QString)) the code is not interpreted, it is shown as plain text (but without the HTML tags).
To try this we made a test that creates an instance of our class, set the HTML code, shows the widget on screen (so we can see the results) and then deletes the instance it created. We create a duplicate of this test and run them in random order, no matter the order they run, always the one that runs first works, the second shows plain text.
We went even further and modify both tests so after showing the widget on screen and deleting it, they create a new instance, set a different piece of HTML code, show it on screen again and delete the new instance. The results are exactly the same, the first test that runs shows the correct, interpreted, web page (both times), the second shows only uninterpreted HTML code without tags (both times).
To isolate the problem, we created a main function using only QApplication and QWebView: we created an instance of a QApplication, an instance of QWebView, set a piece of HTML code, show it on screen, delete the QWebView, delete the QApplication and start over again. The results are exactly the same, the first time it is ok and the second shows only plain text. Here is the source code for this test, it only uses QApplication and QWebView, to see the result, after the first window is shown, just close it and the second one will appear.


#include <QApplication>
#include <QWebView>
int main (int argc, char **argv)
{
// Declare and create the QApplication
QApplication* theApplication;
theApplication = new QApplication(argc, argv);

// Declare and create the QWebView, set a minimun size so we can see it OK
QWebView* pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
theApplication->exec();

// Delete the QWebView
delete pkWebView;
pkWebView = NULL;

// Exit and delete the QApplication
qApp->exit(0);
delete qApp;

// Create a new QApplication
theApplication = new QApplication(argc, argv);

// Create a new QWebkit with the same size
pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the same HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
theApplication->exec();

// Delete the QWebkit
delete pkWebView;
pkWebView = NULL;
}

Another curious thing is that if we add create a second QWebView instance for each instance of QApplication we are using, the second theApplication->exec(); throws and exception, but if we comment this line the other 3 times that it is called it works OK, We really don't know if it is related or not, here is the code of this second test, with the line that generates the exception commented, uncomment it to see the exception:


#include <QApplication>
#include <QWebView>
int main (int argc, char **argv)
{
// Declare and create the QApplication
QApplication* theApplication;
theApplication = new QApplication(argc, argv);

// Declare and create the QWebView, set a minimun size so we can see it OK
QWebView* pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
theApplication->exec();

// Delete the QWebView
delete pkWebView;
pkWebView = NULL;

// Create the QWebView again within the same instance of QApplication
pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
//------------------------------------------------------------------
// UNCOMMENT THIS LINE TO SEE THE EXCEPTION
//theApplication->exec();
//------------------------------------------------------------------

// Delete the QWebView
delete pkWebView;
pkWebView = NULL;

// Exit and delete the QApplication
qApp->exit(0);
delete qApp;

// Create a new QApplication
theApplication = new QApplication(argc, argv);

// Create a new QWebkit with the same size
pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the same HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
theApplication->exec();

// Delete the QWebkit
delete pkWebView;
pkWebView = NULL;

// Create the QWebView again within the same instance of QApplication
pkWebView = new QWebView();
pkWebView->setMinimumSize(320,240);

// Set the HTML code
pkWebView->setHtml("<html>\
<head>\
<title></title>\
</head>\
<body>\
<!-- Put the body of your page below this line -->\
<p><b>This text is bold</b></p>\
<p><strong>This text is strong</strong></p>\
<p><em>This text is emphasized</em></p>\
<p><i>This text is italic</i></p>\
<p><small>This text is small</small></p>\
<p>This is<sub> subscript</sub> and <sup>superscript</sup></p>\
<!-- Put the body of your page above this line -->\
</body>\
</html>");

// Show it on screen
pkWebView->show();
theApplication->exec();

// Delete the QWebView
delete pkWebView;
pkWebView = NULL;
}

We tried this code with Qt 4.7.4 and 4.8.4 and the results were the same. We are using Visual Studio 2008 on Microsoft Windows 7 (64 bits).

Any hint that can point us in the right direction will be appretiated.

It would also help to know, if someone can try this on Mac or Unix, if this happens on another platfom/compiler combination.

Thank you very much for you time.

I also asking this on Stack Exchange (http://stackoverflow.com/questions/16197046/qt-qwebview-with-two-instances-of-qapplication) and QtForum.org (http://www.qtforum.org/article/39199/qwebview-with-two-instances-of-qapplication.html#post121585)

Daniel

Santosh Reddy
24th April 2013, 23:36
QApplication (QCoreApplication) is a singleton design, it is not intended to be created multiple times in an application. As a matter of fact even if you create multiple instance, user code will access a different instance (may be the second instance) and the Qt library code will still be using the first instance and if you deleted the first instance or has gone out of scope your system will be UNSTABLE.

You have to consider to change the test approach and base all you testing with one QApplication instance.

Even if some one were to find the reason behind the behavior (the obvious reason is that Qt lib internally uses the first instance), you will still have to live with single QApplication instance.


It would also help to know, if someone can try this on Mac or Unix, if this happens on another platfom/compiler combination.
I think it is clear that platform will not play any role in this, it is just that Qt is designed that way.

khilin
25th April 2013, 15:19
Santosh, thank you very much for your answer.

After we read your answer we are already working to change the test approach to use only one instance of QApplication. We have a question about it, is there any way to reset the state of the instance of QApplication, we want to be sure that the execution of one test does not affect the execution of the rest of the tests.

Again, thank you for your time.

Daniel

Santosh Reddy
25th April 2013, 16:41
We have a question about it, is there any way to reset the state of the instance of QApplication,
As such there is no direct way (API) to reset the QApplication. What you could do is individually reset the properties which are of your interest.


we want to be sure that the execution of one test does not affect the execution of the rest of the tests.
IMO, when it come to unit tests, each test is supposed to set up it's required settings with in the test itself, so the test case should pass what ever be the condition of QApplication, so I don't see any need to resetting QApplication state

wysota
26th April 2013, 08:37
What exactly would you want to reset in the application object? If you are not modifying the object yourself then there is nothing to reset. Webviews will not contaminate the application object in any way.

anda_skoa
26th April 2013, 12:15
I would suggest to look into Qt's unit test framework QTestLib.

It is trivial to use and you'll get a separate executable for all things you want to have separate.

Cheers,
_