Transition from Qt 4.x to Qt5: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
m (smplify)
 
(14 intermediate revisions by 13 users not shown)
Line 1: Line 1:
[[Category:Developing_with_Qt]]<br />[[Category:Developing_Qt]]
{{LangSwitch}}


[toc align_right="yes" depth="2"]
[[Category:Developing_with_Qt]]
[[Category:Developing_Qt]]


= The Transition from Qt 4.x to Qt 5 =
The transition from Qt 4.x to Qt 5 is not expected to be significant. However, the "modularization" of the Qt code base requires some amount of changes to project configuration, such as use of "headers", and configuration of project build settings (such as changes to the *.pro files).


The transition from Qt 4.x to Qt 5 is not expected to be significant. However, the "modularization" of the Qt code base requires some amount of changes to project configuration, such as use of "headers", and configuration of project build settings (such as changes to the '''.pro files).
== QtWidgets as a Separate Module ==
<br />Qt Creator (master) is compiled using Qt 4 and Qt 5; you can refer to its sources to get an overview of what is required to port an application and keep the sources backwards compatible to Qt 4.
<br />h2. QtWidgets as a Separate Module
<br />h3. example compile time errors<br /><code><br />error: QMainWindow: No such file or directory<br />error: QToolButton: No such file or directory<br />error: QWidget: No such file or directory<br /></code>
<br />h3. Solution
<br />Add this in your'''.pro file:


<code><br />QT ''= widgets<br /></code>
=== example compile time errors ===
<br />Change all instances of
<code>
<br /><code><br />#include <QtGui><br /></code>
error: QMainWindow: No such file or directory
<br />to
error: QToolButton: No such file or directory
<br /><code><br />#include <QtWidgets><br /></code>
error: QWidget: No such file or directory
<br />The code should work now, though sometimes you may require to be more explicit:
</code>
<br /><code><br />#include <QtWidgets/QToolButton><br /></code>
<br />h2. QtWebKitWidgets is also a separate module:
<br />h3. example compile time errors<br /><code><br />error: invalid use of incomplete type 'class QWebFrame'<br />error: forward declaration of 'class QWebFrame'<br /></code>
<br />h3. Solution
<br />Add this in your *.pro file:
<br /><code><br />QT''= webkitwidgets<br /></code>


'''Note''': when you have QT ''= webkitwidgets you don't need QT''= widgets
=== Solution ===
 
Add this in ''every'' *.pro file in your project:
 
<code>
QT += widgets
</code>
 
Change all instances of
 
<code>
#include <QtGui>
</code>
 
to
 
<code>
#include <QtWidgets>
</code>
 
The code should work now, though sometimes you may require to be more explicit:
 
<code>
#include <QtWidgets/QToolButton>
</code>
 
==QtWebKitWidgets is also a separate module:==
 
===example compile time errors===
<code>
error: invalid use of incomplete type 'class QWebFrame'
error: forward declaration of 'class QWebFrame'
</code>
 
=== Solution===
 
Add this in your *.pro file:
 
<code>
QT += webkitwidgets
</code>
 
'''Note''': when you have QT += webkitwidgets you don't need QT += widgets


In addition, replace all instances of
In addition, replace all instances of


<code><br />#include <QtWebKit><br /></code>
<code>
#include <QtWebKit>
</code>


to
to


<code><br />#include <QtWebKitWidgets><br /></code>
<code>
#include <QtWebKitWidgets>
</code>


You can try this by porting a "WYSISWYG html editor":http://qt.gitorious.org/qt-labs/graphics-dojo/trees/c8d0c381b994d7417863832929cc4c3f710f2db5/htmleditor from Qt 4 to Qt 5.
You can try this by porting a [http://qt.gitorious.org/qt-labs/graphics-dojo/trees/c8d0c381b994d7417863832929cc4c3f710f2db5/htmleditor WYSISWYG html editor] from Qt 4 to Qt 5.


== QPrinter Doesn't Work ==
==QPrinter Doesn't Work==


If your code has the following lines:
If your code has the following lines:


<code><br />#include <QPrinter><br />#include <QPrintDialog><br /></code>
<code>
#include <QPrinter>
#include <QPrintDialog>
</code>


add the following to your project file:
add the following to your project file:


<code><br />QT ''= printsupport<br /></code>
<code>
<br />Again, sometimes it may not work and you would need to be explicit:
QT += printsupport
<br /><code><br />#include <QtPrintSupport/QPrinter><br />#include <QtPrintSupport/QPrintDialog><br /></code>
</code>
<br />h2. toAscii() and fromAscii() Methods are deprecated
 
<br />Replace all instances of  
Again, sometimes it may not work and you would need to be explicit:
<br /><code><br />fromAscii()<br />toAscii()<br /></code>
 
<br />to<br /><code><br />fromLatin1()<br />toLatin1()<br /></code>
<code>
<br />For example, given the Qt 4 code<br /><code><br />QByteArray configfileti = TMP_Config.toAscii();<br /></code>
#include <QtPrintSupport/QPrinter>
<br />you would change to<br /><code><br />QByteArray configfileti = TMP_Config.toLatin1();<br /></code>
#include <QtPrintSupport/QPrintDialog>
<br />h2. QCoreApplication::UnicodeUTF8 is deprecated
</code>
<br />This enum type used to define the 8-bit encoding of character string arguments to translate(). This enum is now obsolete and UTF-8 will be used in all cases. So remove all instances of QCoreApplication::UnicodeUTF8. For example:
 
<br /><code><br />Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0, QApplication::UnicodeUTF8));<br />label->setText(QApplication::translate("Href_Gui", "Text:", 0, QApplication::UnicodeUTF8));<br />label_2->setText(QApplication::translate("Href_Gui", "Url:", 0, QApplication::UnicodeUTF8));<br />label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0, QApplication::UnicodeUTF8));<br /></code>
==toAscii() and fromAscii() Methods are deprecated ==
<br />to
 
<br /><code><br />Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0));<br />label->setText(QApplication::translate("Href_Gui", "Text:", 0));<br />label_2->setText(QApplication::translate("Href_Gui", "Url:", 0));<br />label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0));<br /></code>
Replace all instances of  
<br />h2. QWorkspace is deprecated
 
<br />This class is obsolete and was replaced by the QMdiArea class in Qt 4.3. In Qt 5 QWorkspace has been removed. The new class has a similar API to QWorkspace and porting it only involved changing the names of a few methods, signals, and slots.  
<code>
<br />replace
fromAscii()
<br /><code>#include <QWorkspace><br /></code>
toAscii()
<br />with
</code>
<br /><code>#include <QMdiArea><br /></code>
 
<br />h2. QDrag Problems
to
<br />Apps that has drop and drag functionality will need some tweaking. A line such as
<code>
<br /><code><br />QDrag '''drag = new QDrag(event->widget());<br /></code>
fromLatin1()
<br />in Qt 5 will generate the error
toLatin1()
<br /><code><br />error: no matching function for call to 'QDrag::QDrag(QWidget''')'<br /></code>
</code>
<br />To fix this add among the includes:
 
<br /><code><br />#include <QWidget><br /></code>
For example, given the Qt 4 code
<br />h2. qFindChildren is deprecated
<code>
<br />An error will pop of this fashion:<br /><code><br />error: 'qFindChildren' was not declared in this scope<br /></code>
QByteArray configfileti = TMP_Config.toAscii();
<br />To solve this you replace qFindChildren with findChildren, for example in
</code>
<br /><code><br />toString(const QObject* obj, int indentLevel) const {<br />[…]<br /> /* Query over QObjects */<br /> if (m_children) {<br /> QList<QObject'''> childlist = qFindChildren<QObject*>(obj, QString());<br />[]<br /></code>
 
<br />replace
you would change to
<br /><code><br />QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());<br /></code>
<code>
<br />with
QByteArray configfileti = TMP_Config.toLatin1();
<br /><code><br />QList<QObject*> childlist = obj->findChildren<QObject*>(QString());<br /></code>
</code>
 
==QCoreApplication::UnicodeUTF8 is deprecated==
 
This enum type used to define the 8-bit encoding of character string arguments to translate(). This enum is now obsolete and UTF-8 will be used in all cases. So remove all instances of QCoreApplication::UnicodeUTF8. For example:
 
<code>
Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0, QApplication::UnicodeUTF8));
label->setText(QApplication::translate("Href_Gui", "Text:", 0, QApplication::UnicodeUTF8));
label_2->setText(QApplication::translate("Href_Gui", "Url:", 0, QApplication::UnicodeUTF8));
label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0, QApplication::UnicodeUTF8));
</code>
 
to
 
<code>
Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0));
label->setText(QApplication::translate("Href_Gui", "Text:", 0));
label_2->setText(QApplication::translate("Href_Gui", "Url:", 0));
label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0));
</code>
 
==QWorkspace is deprecated ==
 
This class is obsolete and was replaced by the QMdiArea class in Qt 4.3. In Qt 5 QWorkspace has been removed. The new class has a similar API to QWorkspace and porting it only involved changing the names of a few methods, signals, and slots.  
 
replace
 
<code>#include <QWorkspace>
</code>
 
with
 
<code>#include <QMdiArea>
</code>
 
==QDrag Problems==
 
Apps that have drop and drag functionality will need some tweaking. A line such as
 
<code>
QDrag *drag = new QDrag(event->widget());
</code>
 
in Qt 5 will generate the error
 
<code>
error: no matching function for call to 'QDrag::QDrag(QWidget*)'
</code>
 
To fix this add among the includes:
 
<code>
#include <QWidget>
</code>
 
==qFindChildren is deprecated==
 
An error will pop of this fashion:
<code>
error: 'qFindChildren' was not declared in this scope
</code>
 
To solve this you replace qFindChildren with findChildren, for example in
 
<code>
toString(const QObject* obj, int indentLevel) const {
[…]
/* Query over QObjects */
if (m_children) {
QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());
[…]
</code>
 
replace
 
<code>
QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());
</code>
 
with
 
<code>
QList<QObject*> childlist = obj->findChildren<QObject*>(QString());
</code>
 
 
[https://bugs.webkit.org/attachment.cgi?id=82025&action=diff source]
 
==qInstallMsgHandler is deprecated==
 
The 4.8 function [http://doc.qt.io/archives/qt-4.8/qtglobal.html#qInstallMsgHandler qInstallMsgHandler] has been replaced with [http://doc.qt.io/qt-5/qtglobal.html#qInstallMessageHandler qInstallMessageHandler]. The functions are similar, but the function signature of the `handler` has also changed, adding a very useful [http://doc.qt.io/qt-5/qmessagelogcontext.html QMessageLogContext] and replacing the char array with a QString reference.
 
Your compiler will complain
 
<code>
error: 'qInstallMsgHandler': identifier not found
</code>
 
so replace
 
<code>
void myhandler(QtMsgType type, const char* msg) {
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %s\n", msg);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s\n", msg);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s\n", msg);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s\n", msg);
        abort();
    }
}
 
int main(int argc, char** argv) {
    qInstallMsgHandler(myhandler);
    QApplication app(argc, argv);
    //...
    return app.exec();
}
</code>
 
with
 
<code>
void myhandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) { //<-- new signature! added context!
    QByteArray localMsg(msg.toLocal8Bit());      //<-- not a char* any more!
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %s (%s:%u, %s)\n",    localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtInfoMsg:
        fprintf(stderr, "Info: %s (%s:%u, %s)\n",    localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s (%s:%u, %s)\n",  localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s (%s:%u, %s)\n",    localMsg.constData(), context.file, context.line, context.function);
        break;                                  //<-- Qt example doesn't abort() any more with fatal error
    }
}
 
int main(int argc, char** argv) {
    qInstallMessageHandler(myhandler);          //<-- new function
    QApplication app(argc, argv);
    //...
    return app.exec();
}
</code>
 
==qVariantValue is deprecated==
 
Your compiler will say
<code>
error: 'qVariantValue' was not declared in this scope
</code>
 
This function is equivalent to QVariant::value<T>(value). Therefore if given a QVariant val rewrite the line
<code>
QTime t = qVariantValue<QTime>(val);
</code>
 
to
 
<code>
QTime t = val.value<QTime>();
</code>
 
This QTime enclosed in the angled brackets lets the compiler know what QVariant will return. However, if the variable is not a QVariable the type enclosed in the angled brackets should not be used(doing so will result in a vague compile time error). So given that m_color is of type QColor you will rewrite
 
<code>
s.setValue("color/favorite", qVariantValue<QColor>(m_color));
</code>
 
to
 
<code>
s.setValue("color/favorite", m_color.value());
</code>
 
[http://stackoverflow.com/questions/14919867/qvariantvalue-is-qt-deprecated-what-is-the-replacement source]
 
==qVariantCanConvert is deprecated==
 
replace
 
<code>
Q_ASSERT(qVariantCanConvert<QString>(variant));
Q_ASSERT(qVariantCanConvert<QSize>(variant));
Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));
</code>
 
with
 
<code>
Q_ASSERT(variant.canConvert(QMetaType::QString));
Q_ASSERT(variant.canConvert(QMetaType::QSize));
Q_ASSERT(fontVariant.canConvert(QMetaType::QFont));
</code>
 
==Qt::escape is deprecated==
 
<code>
error: 'escape' is not a member of 'Qt'
</code>
 
So you would change the following block:
 
<code>
if (result == QString())
    result = Qt::escape(val.toString());
else
    result = Qt::escape(result);
return result;
</code>
 
to
 
<code>
if (result == QString())
    result = QString(val.toString()).toHtmlEscaped();
else
    result = QString(result).toHtmlEscaped();
return result;
</code>
 
this procedure can be automated by a [http://www.kdab.com/automated-porting-from-qt-4-to-qt-5/ porting tool] from KDAB.
 
==QDesktopServices::storageLocation deprecated==
 
<code>
error: 'storageLocation' is not a member of 'QDesktopServices'
error: 'DataLocation' is not a member of 'QDesktopServices'
</code>
 
Use QStandardPaths::StandardLocation:
 
<code>
QString path = s.value("db.path", QDesktopServices::storageLocation(QDesktopServices::DataLocation)).toString();
</code>
 
to
 
<code>
QString path = s.value("db.path", QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString();
</code>
 
[http://doc.qt.io/qt-5/QDesktopServices.html source]


<br />"source":https://bugs.webkit.org/attachment.cgi?id=82025&amp;amp;action=diff
== CONFIG+=qtestlib is deprecated ==
<br />h2. qVariantValue is deprecated
<br />Your compiler will say<br /><code><br />error: 'qVariantValue' was not declared in this scope<br /></code>
<br />This function is equivalent to QVariant::value<T>(value). Therefore if given a QVariant val rewrite the line<br /><code><br />QTime t = qVariantValue<QTime>(val);<br /></code>
<br />to
<br /><code><br />QTime t = val.value<QTime>();<br /></code>
<br />This QTime enclosed in the angled brackets lets the compiler know what QVariant will return. However, if the variable is not a QVariable the type enclosed in the angled brackets should not be used(doing so will result in a vague compile time error). So given that m_color is of type QColor you will rewrite
<br /><code><br />s.setValue("color/favorite", qVariantValue<QColor>(m_color));<br /></code>
<br />to
<br /><code><br />s.setValue("color/favorite", m_color.value());<br /></code>
<br />"source":http://stackoverflow.com/questions/14919867/qvariantvalue-is-qt-deprecated-what-is-the-replacement
<br />h2. qVariantCanConvert is deprecated
<br />replace
<br /><code><br />Q_ASSERT(qVariantCanConvert<QString>(variant));<br />Q_ASSERT(qVariantCanConvert<QSize>(variant));<br />Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));<br /></code>
<br />with
<br /><code><br />Q_ASSERT(variant.canConvert(QMetaType::QString));<br />Q_ASSERT(variant.canConvert(QMetaType::QSize));<br />Q_ASSERT(fontVariant.canConvert(QMetaType::QFont));<br /></code>
<br />h2. Qt::escape is deprecated
<br /><code><br />error: 'escape' is not a member of 'Qt'<br /></code>
<br />So you would change the following block:
<br /><code><br /> if (result == QString())<br /> result = Qt::escape(val.toString());<br /> else<br /> result = Qt::escape(result);<br /> return result;<br /></code>
<br />to
<br /><code><br /> if (result == QString())<br /> result = QString(val.toString()).toHtmlEscaped();<br /> else<br /> result = QString(result).toHtmlEscaped();<br /> return result;<br /></code>
<br />this procedure can be automated by a "porting tool":http://www.kdab.com/automated-porting-from-qt-4-to-qt-5/ from KDAB.
<br />h2. QDesktopServices::storageLocation deprecated
<br /><code><br />error: 'storageLocation' is not a member of 'QDesktopServices'<br />error: 'DataLocation' is not a member of 'QDesktopServices'<br /></code>
<br />Use QStandardPaths::StandardLocation:
<br /><code><br />QString path = s.value("db.path", QDesktopServices::storageLocation(QDesktopServices::DataLocation)).toString();<br /></code>
<br />to
<br /><code><br />QString path = s.value("db.path", QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString();<br /></code>
<br />"source":http://doc.qt.io/qt-5.0/qtgui/qdesktopservices-obsolete.html
<br />h2. CONFIG''=qtestlib is deprecated


If you have the above line in your project file the compiler will warn you in the compile window, nonetheless the code will still run as usual:
If you have the above line in your project file the compiler will warn you in the compile window, nonetheless the code will still run as usual:


<code><br />Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.<br /></code>
<code>
Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.
</code>


== QWeakPointer quirks ==
== QWeakPointer quirks==


A code block like
A code block like


<code><br />quint64 decodedPointer = line.toULongLong();<br />MetaData* md = reinterpret_cast&amp;amp;lt;MetaData*>(decodedPointer);<br />QWeakPointer&amp;amp;lt;MetaData&amp;amp;gt; wp(md);<br /></code>
<code>
quint64 decodedPointer = line.toULongLong();
MetaData* md = reinterpret_cast<MetaData*>(decodedPointer);
QWeakPointer<MetaData> wp(md);
</code>


results in
results in


<code><br />error: no matching function for call to 'QWeakPointer&amp;amp;lt;MetaData&amp;amp;gt;::QWeakPointer(MetaData*&amp;)'<br /></code>
<code>
error: no matching function for call to 'QWeakPointer<MetaData>::QWeakPointer(MetaData*&)'
</code>


To fix this add to the project file:
To fix this add to the project file:


<code><br />DEFINES ''= QT_DISABLE_DEPRECATED_BEFORE=0<br /></code>
<code>
<br />"source":http://forum.qt.io/viewthread/27510
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
<br />h2. QtConcurrent Library is Missing?
</code>
<br /><code><br />C:5.0.2\5.0.2\mingw47_32\include\QtConcurrent\qtconcurrentthreadengine.h:133: error: undefined reference to `_imp___ZN12QtConcurrent16ThreadEngineBaseD2Ev'<br /></code>
 
<br />In Qt 4, QtConcurrent was part of QtCore, so there was no need to include specific headers. This is no longer the case with Qt 5. If your source code have lines like
[http://forum.qt.io/viewthread/27510 source]
<br /><code><br />m_current = QtConcurrent::blockingMappedReduced(slices, functor, stitchReduce, QtConcurrent::UnorderedReduce );<br /></code>
 
<br />You will need to include the header:
==QtConcurrent Library is Missing?==
<br /><code><br />#include <QtConcurrent/QtConcurrent><br /></code>
 
<br />and add the following line to your project file:
<code>
<br /><code><br />QT''= concurrent<br /></code>
C:\Qt\5.0.2\5.0.2\mingw47_32\include\QtConcurrent\qtconcurrentthreadengine.h:133: error: undefined reference to  
`_imp___ZN12QtConcurrent16ThreadEngineBaseD2Ev'
</code>
 
In Qt 4, QtConcurrent was part of QtCore, so there was no need to include specific headers. This is no longer the case with Qt 5. If your source code has lines like
 
<code>
m_current = QtConcurrent::blockingMappedReduced(slices, functor, stitchReduce, QtConcurrent::UnorderedReduce );
</code>
 
You will need to include the header:
 
<code>
#include <QtConcurrent/QtConcurrent>
</code>
 
and add the following line to your project file:
 
<code>
QT+= concurrent
</code>


== Fixing #include<> Headers ==
==Fixing #include<> Headers==


A Perl script "fixqt4headers.pl" exists in qtbase/bin/. that should be run on source code using Qt that corrects the #include<> directives for Qt components to also consider the module name.
A Perl script "fixqt4headers.pl" exists in qtbase/bin/. that should be run on source code using Qt that corrects the #include<> directives for Qt components to also consider the module name.


== Plugin loading ==
==Plugin loading==


The Q_EXPORT_PLUGIN,Q_EXPORT_PLUGIN2 macros have been deprecated in favor of the new Q_PLUGIN_METADATA macro. The advantage of the new system is that it allows Qt to query the metadata for the plugin without actually dlopen'ing it. This greatly improves performance and reliability of the plugin system.
The Q_EXPORT_PLUGIN,Q_EXPORT_PLUGIN2 macros have been deprecated in favor of the new Q_PLUGIN_METADATA macro. The advantage of the new system is that it allows Qt to query the metadata for the plugin without actually dlopen'ing it. This greatly improves performance and reliability of the plugin system.
Line 150: Line 443:
The new Q_PLUGIN_METADATA macro is included next to the Q_OBJECT macro in the QObject derived class that is returned when loading the plugin. It contains the plugins IID and a filename pointing to a json file containing the metadata for the plugin. The json file is compiled into the plugin and does not need to be installed.
The new Q_PLUGIN_METADATA macro is included next to the Q_OBJECT macro in the QObject derived class that is returned when loading the plugin. It contains the plugins IID and a filename pointing to a json file containing the metadata for the plugin. The json file is compiled into the plugin and does not need to be installed.


An example on how to change your plugins can be found by looking at the patch that changes the Gif image format plugin, see http://qt.gitorious.org/qt/qtbase/commit/963b4c1647299fd023ddbe7c4a25ac404e303c5d .
An example on how to change your plugins can be found by looking at the patch that changes the Gif image format plugin, see http://code.qt.io/cgit/qt/qtbase.git/commit/?id=963b4c1647299fd023ddbe7c4a25ac404e303c5d
 
==Deploying to systems without C++11==
 
When Qt is built from source code on a system with C++11 installed, the Qt libraries/frameworks are linked against the system's C++11 library (libc). This means that the Qt libraries/frameworks are not deployable to systems without C++11 installed (such as out-of-the-box Mac OS X 10.6). To be able to deploy to systems that only support the older C++ standard (libstdc++), build Qt from source code with the -no-c++11 configure option.
 
==QTimer is no longer accurate to the millisecond by default==
 
QTimer has now 3 accuracy types, with a new default behaviour:
*The new default type is Qt::CoarseTimer which, to reduce power/CPU consumption, allow ''5% difference'' between requested time and actual one, and even ''allow the timer to fire before'' the requested time.
*The former one is Qt::PreciseTimer (to the millisecond, never before the requested time).
*A third one is Qt::VeryCoarseTimer and allow a 1 second difference
 
==QUrl addQueryItem moved to QUrlQuery==
 
If you have:
<code>
QUrl url;
// …
url.addQueryItem(key, value);
</code>
 
You will want to change it to
<code>
QUrl url;
QUrlQuery urlQuery(url);        //initialize with url to append to existing query, if present
// …
urlQuery.addQueryItem(key, value);
 
url.setQuery(urlQuery);
</code>
 
The same applies to the QUrl::getQueryItem() methods. They have been moved to QUrlQuery.
 
==QAbstractItemModel changes==
 
<code>
void reset()
void setRoleNames(const QHash<int, QByteArray> & roleNames)
</code>
both have changed and are now obsolete.
 
See [http://doc.qt.io/qt-5/qabstractitemmodel-obsolete.html Obsolete Members for QAbstractItemModel]
 
==QHeaderView changes==
 
Use <code>void QHeaderView::setSectionResizeMode(QHeaderView::ResizeMode mode)</code> instead of <code>void QHeaderView::setResizeMode(ResizeMode mode)</code> The latter has been removed.
 
==Recommended Reading==


== Deploying to systems without C+''11
*[http://doc.qt.io/qt-5/sourcebreaks.html C++ API Changes]
<br />When Qt is built from source code on a system with C11 installed, the Qt libraries/frameworks are linked against the system's C11 library (libc). This means that the Qt libraries/frameworks are not deployable to systems without C11 installed (such as out-of-the-box Mac OS X 10.6). To be able to deploy to systems that only support the older C''+ standard (libstdc+''), build Qt from source code with the -no-c11 configure option.
*[http://doc.qt.io/qt-5/portingguide.html The porting guide]
<br />h2. QTimer is no longer accurate to the millisecond by default
*[http://www.ics.com/blog/porting-desktop-applications-qt-4-qt-5 Porting Desktop Applications from Qt 4 to Qt 5]
<br />QTimer has now 3 accuracy types, with a new default behaviour:<br />* The new default type is Qt::CoarseTimer which, to reduce power/CPU consumption, allow ''5% difference'' between requested time and actual one, and even ''allow the timer to fire before'' the requested time.<br />* The former one is Qt::PreciseTimer (to the millisecond, never before the requested time).<br />* A third one is Qt::VeryCoarseTimer and allow a 1 second difference
*[http://www.kdab.com/porting-from-qt-4-to-qt-5/ Porting from Qt 4 to Qt 5]
<br />h2. QUrl addQueryItem moved to QUrlQuery
*[http://www.kdab.com/automated-porting-from-qt-4-to-qt-5/ Automated porting from Qt 4 to Qt 5]
<br />If you have:<br /><code><br />QUrl url;<br />// …<br />url.addQueryItem(key, value);<br /></code>
<br />You will want to change it to<br /><code><br />QUrl url;<br />QUrlQuery urlQuery;<br />// …<br />urlQuery.addQueryItem(key, value);
<br />url.setUrlQuery(urlQuery);<br /></code>
<br />h2. QAbstractItemModel changes
<br /><code><br />void reset()<br />void setRoleNames(const QHash<int, QByteArray> &amp; roleNames)<br /></code><br />both have changed and are now protected.
<br />See "Compatibility Members for QAbstractItemModel":http://doc.qt.io/qt-5/qabstractitemmodel-compat.html#reset
<br />h2. Recommended Reading
<br />* "C''+ API Changes":http://doc.qt.io/qt-5.0/qtdoc/sourcebreaks.html<br />* "The porting guide":http://doc.qt.io/qt-5.0/qtdoc/portingguide.html<br />* "Porting Desktop Applications from Qt 4 to Qt 5":http://blog.ics.com/2013/01/porting-desktop-applications-from-qt-4-to-qt-5.html#.UVDeLReGqSr<br />* "Porting from Qt 4 to Qt 5":http://www.kdab.com/porting-from-qt-4-to-qt-5/<br />* "Automated porting from Qt 4 to Qt 5":http://www.kdab.com/automated-porting-from-qt-4-to-qt-5/ ==

Latest revision as of 23:03, 27 April 2024

En Ar Bg De El Es Fa Fi Fr Hi Hu It Ja Kn Ko Ms Nl Pl Pt Ru Sq Th Tr Uk Zh

The transition from Qt 4.x to Qt 5 is not expected to be significant. However, the "modularization" of the Qt code base requires some amount of changes to project configuration, such as use of "headers", and configuration of project build settings (such as changes to the *.pro files).

QtWidgets as a Separate Module

example compile time errors

error: QMainWindow: No such file or directory
error: QToolButton: No such file or directory
error: QWidget: No such file or directory

Solution

Add this in every *.pro file in your project:

QT += widgets

Change all instances of

#include <QtGui>

to

#include <QtWidgets>

The code should work now, though sometimes you may require to be more explicit:

#include <QtWidgets/QToolButton>

QtWebKitWidgets is also a separate module:

example compile time errors

error: invalid use of incomplete type 'class QWebFrame'
error: forward declaration of 'class QWebFrame'

Solution

Add this in your *.pro file:

QT += webkitwidgets

Note: when you have QT += webkitwidgets you don't need QT += widgets

In addition, replace all instances of

#include <QtWebKit>

to

#include <QtWebKitWidgets>

You can try this by porting a WYSISWYG html editor from Qt 4 to Qt 5.

QPrinter Doesn't Work

If your code has the following lines:

#include <QPrinter>
#include <QPrintDialog>

add the following to your project file:

QT += printsupport

Again, sometimes it may not work and you would need to be explicit:

#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>

toAscii() and fromAscii() Methods are deprecated

Replace all instances of

fromAscii()
toAscii()

to

fromLatin1()
toLatin1()

For example, given the Qt 4 code

QByteArray configfileti = TMP_Config.toAscii();

you would change to

QByteArray configfileti = TMP_Config.toLatin1();

QCoreApplication::UnicodeUTF8 is deprecated

This enum type used to define the 8-bit encoding of character string arguments to translate(). This enum is now obsolete and UTF-8 will be used in all cases. So remove all instances of QCoreApplication::UnicodeUTF8. For example:

Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0, QApplication::UnicodeUTF8));
label->setText(QApplication::translate("Href_Gui", "Text:", 0, QApplication::UnicodeUTF8));
label_2->setText(QApplication::translate("Href_Gui", "Url:", 0, QApplication::UnicodeUTF8));
label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0, QApplication::UnicodeUTF8));

to

Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0));
label->setText(QApplication::translate("Href_Gui", "Text:", 0));
label_2->setText(QApplication::translate("Href_Gui", "Url:", 0));
label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0));

QWorkspace is deprecated

This class is obsolete and was replaced by the QMdiArea class in Qt 4.3. In Qt 5 QWorkspace has been removed. The new class has a similar API to QWorkspace and porting it only involved changing the names of a few methods, signals, and slots.

replace

#include <QWorkspace>

with

#include <QMdiArea>

QDrag Problems

Apps that have drop and drag functionality will need some tweaking. A line such as

QDrag *drag = new QDrag(event->widget());

in Qt 5 will generate the error

error: no matching function for call to 'QDrag::QDrag(QWidget*)'

To fix this add among the includes:

#include <QWidget>

qFindChildren is deprecated

An error will pop of this fashion:

error: 'qFindChildren' was not declared in this scope

To solve this you replace qFindChildren with findChildren, for example in

toString(const QObject* obj, int indentLevel) const {
[]
 /* Query over QObjects */
 if (m_children) {
 QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());
[]

replace

QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());

with

QList<QObject*> childlist = obj->findChildren<QObject*>(QString());


source

qInstallMsgHandler is deprecated

The 4.8 function qInstallMsgHandler has been replaced with qInstallMessageHandler. The functions are similar, but the function signature of the `handler` has also changed, adding a very useful QMessageLogContext and replacing the char array with a QString reference.

Your compiler will complain

error: 'qInstallMsgHandler': identifier not found

so replace

void myhandler(QtMsgType type, const char* msg) {
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %s\n", msg);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s\n", msg);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s\n", msg);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s\n", msg);
        abort();
    }
}

int main(int argc, char** argv) {
    qInstallMsgHandler(myhandler);
    QApplication app(argc, argv);
    //...
    return app.exec();
}

with

void myhandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) { //<-- new signature! added context!
    QByteArray localMsg(msg.toLocal8Bit());       //<-- not a char* any more!
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %s (%s:%u, %s)\n",    localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtInfoMsg:
        fprintf(stderr, "Info: %s (%s:%u, %s)\n",     localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s (%s:%u, %s)\n",  localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s (%s:%u, %s)\n",    localMsg.constData(), context.file, context.line, context.function);
        break;                                   //<-- Qt example doesn't abort() any more with fatal error
    }
}

int main(int argc, char** argv) {
    qInstallMessageHandler(myhandler);          //<-- new function
    QApplication app(argc, argv);
    //...
    return app.exec();
}

qVariantValue is deprecated

Your compiler will say

error: 'qVariantValue' was not declared in this scope

This function is equivalent to QVariant::value<T>(value). Therefore if given a QVariant val rewrite the line

QTime t = qVariantValue<QTime>(val);

to

QTime t = val.value<QTime>();

This QTime enclosed in the angled brackets lets the compiler know what QVariant will return. However, if the variable is not a QVariable the type enclosed in the angled brackets should not be used(doing so will result in a vague compile time error). So given that m_color is of type QColor you will rewrite

s.setValue("color/favorite", qVariantValue<QColor>(m_color));

to

s.setValue("color/favorite", m_color.value());

source

qVariantCanConvert is deprecated

replace

Q_ASSERT(qVariantCanConvert<QString>(variant));
Q_ASSERT(qVariantCanConvert<QSize>(variant));
Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));

with

Q_ASSERT(variant.canConvert(QMetaType::QString));
Q_ASSERT(variant.canConvert(QMetaType::QSize));
Q_ASSERT(fontVariant.canConvert(QMetaType::QFont));

Qt::escape is deprecated

error: 'escape' is not a member of 'Qt'

So you would change the following block:

if (result == QString())
    result = Qt::escape(val.toString());
else
    result = Qt::escape(result);
return result;

to

if (result == QString())
    result = QString(val.toString()).toHtmlEscaped();
else
    result = QString(result).toHtmlEscaped();
return result;

this procedure can be automated by a porting tool from KDAB.

QDesktopServices::storageLocation deprecated

error: 'storageLocation' is not a member of 'QDesktopServices'
error: 'DataLocation' is not a member of 'QDesktopServices'

Use QStandardPaths::StandardLocation:

QString path = s.value("db.path", QDesktopServices::storageLocation(QDesktopServices::DataLocation)).toString();

to

QString path = s.value("db.path", QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString();

source

CONFIG+=qtestlib is deprecated

If you have the above line in your project file the compiler will warn you in the compile window, nonetheless the code will still run as usual:

Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.

QWeakPointer quirks

A code block like

quint64 decodedPointer = line.toULongLong();
MetaData* md = reinterpret_cast<MetaData*>(decodedPointer);
QWeakPointer<MetaData> wp(md);

results in

error: no matching function for call to 'QWeakPointer<MetaData>::QWeakPointer(MetaData*&)'

To fix this add to the project file:

DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

source

QtConcurrent Library is Missing?

C:\Qt\5.0.2\5.0.2\mingw47_32\include\QtConcurrent\qtconcurrentthreadengine.h:133: error: undefined reference to 
`_imp___ZN12QtConcurrent16ThreadEngineBaseD2Ev'

In Qt 4, QtConcurrent was part of QtCore, so there was no need to include specific headers. This is no longer the case with Qt 5. If your source code has lines like

m_current = QtConcurrent::blockingMappedReduced(slices, functor, stitchReduce, QtConcurrent::UnorderedReduce );

You will need to include the header:

#include <QtConcurrent/QtConcurrent>

and add the following line to your project file:

QT+= concurrent

Fixing #include<> Headers

A Perl script "fixqt4headers.pl" exists in qtbase/bin/. that should be run on source code using Qt that corrects the #include<> directives for Qt components to also consider the module name.

Plugin loading

The Q_EXPORT_PLUGIN,Q_EXPORT_PLUGIN2 macros have been deprecated in favor of the new Q_PLUGIN_METADATA macro. The advantage of the new system is that it allows Qt to query the metadata for the plugin without actually dlopen'ing it. This greatly improves performance and reliability of the plugin system.

The new Q_PLUGIN_METADATA macro is included next to the Q_OBJECT macro in the QObject derived class that is returned when loading the plugin. It contains the plugins IID and a filename pointing to a json file containing the metadata for the plugin. The json file is compiled into the plugin and does not need to be installed.

An example on how to change your plugins can be found by looking at the patch that changes the Gif image format plugin, see http://code.qt.io/cgit/qt/qtbase.git/commit/?id=963b4c1647299fd023ddbe7c4a25ac404e303c5d

Deploying to systems without C++11

When Qt is built from source code on a system with C++11 installed, the Qt libraries/frameworks are linked against the system's C++11 library (libc). This means that the Qt libraries/frameworks are not deployable to systems without C++11 installed (such as out-of-the-box Mac OS X 10.6). To be able to deploy to systems that only support the older C++ standard (libstdc++), build Qt from source code with the -no-c++11 configure option.

QTimer is no longer accurate to the millisecond by default

QTimer has now 3 accuracy types, with a new default behaviour:

  • The new default type is Qt::CoarseTimer which, to reduce power/CPU consumption, allow 5% difference between requested time and actual one, and even allow the timer to fire before the requested time.
  • The former one is Qt::PreciseTimer (to the millisecond, never before the requested time).
  • A third one is Qt::VeryCoarseTimer and allow a 1 second difference

QUrl addQueryItem moved to QUrlQuery

If you have:

QUrl url;
// …
url.addQueryItem(key, value);

You will want to change it to

QUrl url;
QUrlQuery urlQuery(url);        //initialize with url to append to existing query, if present
// …
urlQuery.addQueryItem(key, value);

url.setQuery(urlQuery);

The same applies to the QUrl::getQueryItem() methods. They have been moved to QUrlQuery.

QAbstractItemModel changes

void reset()
void setRoleNames(const QHash<int, QByteArray> & roleNames)

both have changed and are now obsolete.

See Obsolete Members for QAbstractItemModel

QHeaderView changes

Use

void QHeaderView::setSectionResizeMode(QHeaderView::ResizeMode mode)

instead of

void QHeaderView::setResizeMode(ResizeMode mode)

The latter has been removed.

Recommended Reading