Commit 12eff4a0 authored by jcfr's avatar jcfr

ENH: Add preliminary support for Qt5

Support configuration using either Qt4 or Qt5

Based on preliminary work from Steve Pieper <pieper@bwh.harvard.edu>

* vtkSlicerConfigure: Introduced Slicer_HAVE_QT5 and Slicer_HAVE_WEBKIT_SUPPORT.
  This was needed to workaround limitation of "moc" compiler preventing it
  from expanding macro like "QT_VERSION_CHECK.

* Explicitly set QT_PLUGINS_DIR and QT_BINARY_DIR variables when using Qt5

* Update extension build system to propagate Qt version

Tested with Qt 5.7 and Qt 5.9 on Ubuntu

Remaining tasks:
* Port extension manager
* Update install/packaging rules to support Qt5
* SlicerStyle (based on CommonStyle) is disabled (see Main.cxx). Application crashes on Linux.
* Fix runtime errors:
 * libpng warning: iCCP: known incorrect sRGB profile
 * QPixmap::grabWidget is deprecated, use QWidget::grab() instead
Co-authored-by: default avatarHina Shah <hina.shah@kitware.com>
Co-authored-by: Max Smolens's avatarMax Smolens <max.smolens@kitware.com>

COMP adding qt5 variables for extension testing

COMP Adding Qt5 build and plugin cmake variables

From: Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>

git-svn-id: http://svn.slicer.org/Slicer4/trunk@26251 3bd1e089-480b-0410-8dfb-8563597acbee
parent d4b5c756
......@@ -120,7 +120,9 @@ int SlicerAppMain(int argc, char* argv[])
QCoreApplication::setApplicationVersion(Slicer_VERSION_FULL);
//vtkObject::SetGlobalWarningDisplay(false);
QApplication::setDesktopSettingsAware(false);
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
QApplication::setStyle(new qSlicerStyle());
#endif
qSlicerApplication app(argc, argv);
if (app.returnCode() != -1)
......
......@@ -21,7 +21,6 @@ set(${KIT}_SRCS
# Headers that should run through moc
set(${KIT}_MOC_SRCS
qSlicerQTCLIAbstractPlugin.h
qSlicerQTCLIPlugins.h
qSlicerCLIProgressBarPlugin.h
)
......
......@@ -23,7 +23,7 @@
//-----------------------------------------------------------------------------
qSlicerCLIProgressBarPlugin::qSlicerCLIProgressBarPlugin(QObject* parent)
: qSlicerQTCLIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTCLIAbstractPlugin.h"
class Q_SLICER_BASE_QTCLI_PLUGINS_EXPORT qSlicerCLIProgressBarPlugin
: public qSlicerQTCLIAbstractPlugin
: public QObject,
public qSlicerQTCLIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -20,8 +20,7 @@
#include "qSlicerQTCLIAbstractPlugin.h"
qSlicerQTCLIAbstractPlugin::qSlicerQTCLIAbstractPlugin(QObject* parent)
: QObject(parent)
qSlicerQTCLIAbstractPlugin::qSlicerQTCLIAbstractPlugin()
{
}
......
......@@ -22,21 +22,26 @@
#define __qSlicerQTCLIAbstractPlugin_h
// QT includes
#include <QtGlobal>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QDesignerCustomWidgetInterface>
#include <QObject>
#else
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#endif
// QTCLI includes
#include "qSlicerBaseQTCLIPluginsExport.h"
class Q_SLICER_BASE_QTCLI_PLUGINS_EXPORT qSlicerQTCLIAbstractPlugin
: public QObject
, public QDesignerCustomWidgetInterface
: public QDesignerCustomWidgetInterface
{
Q_OBJECT
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
#endif
Q_INTERFACES(QDesignerCustomWidgetInterface);
public:
qSlicerQTCLIAbstractPlugin(QObject* parent = 0);
qSlicerQTCLIAbstractPlugin();
// Don't reimplement this method.
QString group() const;
// You can reimplement these methods
......
......@@ -20,6 +20,9 @@
#include "qSlicerQTCLIPlugins.h"
#include <QtPlugin>
#include <QtGlobal>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QtPlugin>
Q_EXPORT_PLUGIN2(customwidgetplugin, qSlicerQTCLIPlugins);
#endif
......@@ -21,8 +21,14 @@
#ifndef __qSlicerQTCLIPlugins_h
#define __qSlicerQTCLIPlugins_h
// QT includes
#include "vtkSlicerConfigure.h" // For Slicer_HAVE_QT5
// Qt includes
#ifdef Slicer_HAVE_QT5
#include <QtUiPlugin/QDesignerCustomWidgetCollectionInterface>
#else
#include <QDesignerCustomWidgetCollectionInterface>
#endif
// QtCLI includes
#include "qSlicerCLIProgressBarPlugin.h"
......@@ -33,6 +39,9 @@ class Q_SLICER_BASE_QTCLI_PLUGINS_EXPORT qSlicerQTCLIPlugins
, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
#ifdef Slicer_HAVE_QT5
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
#endif
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface);
public:
......
......@@ -206,8 +206,8 @@ bool qSlicerCLILoadableModuleFactoryItem::updateLogo(qSlicerCLILoadableModuleFac
int pixelSize = 0;
unsigned long bufferLength = 0;
void * resolvedGetModuleLogoSymbol = item->symbolAddress("GetModuleLogo");
void * resolvedModuleLogoImageSymbol = item->symbolAddress("ModuleLogoImage");
SymbolAddressType resolvedGetModuleLogoSymbol = item->symbolAddress("GetModuleLogo");
SymbolAddressType resolvedModuleLogoImageSymbol = item->symbolAddress("ModuleLogoImage");
if(resolvedGetModuleLogoSymbol)
{
......@@ -223,10 +223,10 @@ bool qSlicerCLILoadableModuleFactoryItem::updateLogo(qSlicerCLILoadableModuleFac
QStringList expectedSymbols;
expectedSymbols << "ModuleLogoWidth" << "ModuleLogoHeight"
<< "ModuleLogoPixelSize" << "ModuleLogoLength";
QList<void*> resolvedSymbols;
QList<SymbolAddressType> resolvedSymbols;
foreach(const QString& symbol, expectedSymbols)
{
void * resolvedSymbol = item->symbolAddress(symbol);
SymbolAddressType resolvedSymbol = item->symbolAddress(symbol);
if (resolvedSymbol)
{
resolvedSymbols << resolvedSymbol;
......
......@@ -34,30 +34,32 @@ if(BUILD_TESTING)
EXTRA_INCLUDE vtkMRMLDebugLeaksMacro.h
)
QT4_GENERATE_MOCS(
set(KIT_TEST_GENERATE_MOC_SRCS
qSlicerSslTest.cxx
)
if(Slicer_BUILD_EXTENSIONMANAGER_SUPPORT)
QT4_GENERATE_MOCS(
list(APPEND KIT_TEST_GENERATE_MOC_SRCS
qSlicerExtensionsManagerModelTest.cxx
qSlicerPersistentCookieJarTest.cxx
)
endif()
if(Slicer_USE_PYTHONQT)
QT4_GENERATE_MOCS(
list(APPEND KIT_TEST_GENERATE_MOC_SRCS
qSlicerCorePythonManagerWithoutApplicationTest.cxx
)
endif()
QT4_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
set(KIT_TEST_TARGET_LIBRARIES ${KIT})
if(CTK_QT_VERSION VERSION_GREATER "4")
list(APPEND KIT_TEST_TARGET_LIBRARIES Qt5::Test)
else()
if(CTK_QT_VERSION VERSION_LESS "5")
QT4_GENERATE_MOCS(${KIT_TEST_GENERATE_MOC_SRCS})
QT4_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
list(APPEND KIT_TEST_TARGET_LIBRARIES Qt4::QtTest)
else()
QT5_GENERATE_MOCS(${KIT_TEST_GENERATE_MOC_SRCS})
QT5_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
list(APPEND KIT_TEST_TARGET_LIBRARIES Qt5::Test)
endif()
if(Slicer_USE_PYTHONQT)
......
......@@ -23,7 +23,9 @@ private slots:
void testHttpsConnection_data();
};
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
Q_DECLARE_METATYPE(QNetworkReply::NetworkError)
#endif
// ----------------------------------------------------------------------------
void qSlicerSslTester::testSupportsSsl()
......
......@@ -23,7 +23,6 @@
// Qt includes
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QLocale>
#include <QMessageBox>
......@@ -33,6 +32,12 @@
#include <QSettings>
#include <QTranslator>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QDesktopServices>
#else
#include <QStandardPaths>
#endif
// For:
// - Slicer_QTLOADABLEMODULES_LIB_DIR
// - Slicer_CLIMODULES_BIN_DIR
......@@ -1026,7 +1031,14 @@ QString qSlicerCoreApplication::defaultScenePath() const
{
QSettings* appSettings = this->userSettings();
Q_ASSERT(appSettings);
QString defaultScenePath = appSettings->value("DefaultScenePath", QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).toString();
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
QString defaultScenePath = appSettings->value(
"DefaultScenePath", QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).toString();
#else
QString defaultScenePath = appSettings->value(
"DefaultScenePath", QStandardPaths::DocumentsLocation).toString();
#endif
return defaultScenePath;
}
......
......@@ -30,6 +30,9 @@
#include <QTemporaryFile>
#include <QTextStream>
#include <QUrl>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QUrlQuery>
#endif
// CTK includes
#include <ctkScopedCurrentDir.h>
......@@ -76,10 +79,18 @@ struct UpdateDownloadInformation
class QStandardItemModelWithRole : public QStandardItemModel
{
public:
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
void setRoleNames(const QHash<int,QByteArray> &roleNames)
{
this->QStandardItemModel::setRoleNames(roleNames);
}
#else
QHash<int, QByteArray> roleNames() const
{
return this->CustomRoleNames;
}
QHash<int,QByteArray> CustomRoleNames;
#endif
};
} // end of anonymous namespace
......@@ -281,7 +292,15 @@ void qSlicerExtensionsManagerModelPrivate::init()
roleNames[Qt::UserRole + 1 + columnIdx] = columnName.toLatin1();
++columnIdx;
}
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
//
// See QStandardItemModelWithRole::roleNames() for Qt5 implementation
//
this->Model.setRoleNames(roleNames);
#else
this->Model.CustomRoleNames = roleNames;
#endif
QObject::connect(q, SIGNAL(slicerRequirementsChanged(QString,QString,QString)),
q, SLOT(identifyIncompatibleExtensions()));
......@@ -1123,8 +1142,15 @@ qSlicerExtensionsManagerModelPrivate::downloadExtension(
this->debug(QString("Downloading extension [ itemId: %1]").arg(itemId));
QUrl downloadUrl(q->serverUrl());
downloadUrl.setPath(downloadUrl.path() + "/download");
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
downloadUrl.setQueryItems(
QList<QPair<QString, QString> >() << QPair<QString, QString>("items", itemId));
#else
QUrlQuery urlQuery;
urlQuery.setQueryItems(
QList<QPair<QString, QString> >() << QPair<QString, QString>("items", itemId));
downloadUrl.setQuery(urlQuery);
#endif
QNetworkReply* const reply =
this->NetworkManager.get(QNetworkRequest(downloadUrl));
......@@ -1170,7 +1196,11 @@ void qSlicerExtensionsManagerModel::onInstallDownloadFinished(
QNetworkReply* const reply = task->reply();
QUrl downloadUrl = reply->url();
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
Q_ASSERT(downloadUrl.hasQueryItem("items"));
#else
Q_ASSERT(QUrlQuery(downloadUrl).hasQueryItem("items"));
#endif
emit this->downloadFinished(reply);
......@@ -1580,7 +1610,11 @@ void qSlicerExtensionsManagerModel::onUpdateDownloadFinished(
// Get network reply
QNetworkReply* const reply = task->reply();
QUrl downloadUrl = reply->url();
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
Q_ASSERT(downloadUrl.hasQueryItem("items"));
#else
Q_ASSERT(QUrlQuery(downloadUrl).hasQueryItem("items"));
#endif
// Notify observers of event
emit this->downloadFinished(reply);
......
......@@ -22,6 +22,7 @@
#include <QDir>
#include <QFileInfo>
#include <QFileInfo>
#include <QNetworkCookie>
#include <QSettings>
#include <QStringList>
......
......@@ -31,7 +31,6 @@ set(${KIT}_SRCS
set(${KIT}_MOC_SRCS
qSlicerQTGUIPlugins.h
qSlicerQTGUIAbstractPlugin.h
qSlicerDirectoryListViewPlugin.h
qSlicerModulePanelPlugin.h
qSlicerModulesListViewPlugin.h
......
......@@ -22,7 +22,7 @@
#include "qSlicerDirectoryListView.h"
qSlicerDirectoryListViewPlugin::qSlicerDirectoryListViewPlugin(QObject* parent)
: qSlicerQTGUIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTGUIAbstractPlugin.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerDirectoryListViewPlugin
: public qSlicerQTGUIAbstractPlugin
: public QObject,
public qSlicerQTGUIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -22,7 +22,7 @@
#include "qSlicerModulePanel.h"
qSlicerModulePanelPlugin::qSlicerModulePanelPlugin(QObject* parent)
: qSlicerQTGUIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTGUIAbstractPlugin.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerModulePanelPlugin
: public qSlicerQTGUIAbstractPlugin
: public QObject,
public qSlicerQTGUIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -22,7 +22,7 @@
#include "qSlicerModulesListView.h"
qSlicerModulesListViewPlugin::qSlicerModulesListViewPlugin(QObject* parent)
: qSlicerQTGUIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTGUIAbstractPlugin.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerModulesListViewPlugin
: public qSlicerQTGUIAbstractPlugin
: public QObject,
public qSlicerQTGUIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -22,7 +22,7 @@
#include "qSlicerMouseModeToolBar.h"
qSlicerMouseModeToolBarPlugin::qSlicerMouseModeToolBarPlugin(QObject* parent)
: qSlicerQTGUIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTGUIAbstractPlugin.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerMouseModeToolBarPlugin
: public qSlicerQTGUIAbstractPlugin
: public QObject,
public qSlicerQTGUIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -20,8 +20,7 @@
#include "qSlicerQTGUIAbstractPlugin.h"
qSlicerQTGUIAbstractPlugin::qSlicerQTGUIAbstractPlugin(QObject* parent)
: QObject(parent)
qSlicerQTGUIAbstractPlugin::qSlicerQTGUIAbstractPlugin()
{
}
......
......@@ -22,21 +22,26 @@
#define __qSlicerQTGUIAbstractPlugin_h
// QT includes
#include <QtGlobal>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QDesignerCustomWidgetInterface>
#include <QObject>
#else
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#endif
// QTGUI includes
#include "qSlicerBaseQTGUIDesignerPluginsExport.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerQTGUIAbstractPlugin
: public QObject
, public QDesignerCustomWidgetInterface
: public QDesignerCustomWidgetInterface
{
Q_OBJECT
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
#endif
Q_INTERFACES(QDesignerCustomWidgetInterface);
public:
qSlicerQTGUIAbstractPlugin(QObject* parent = 0);
qSlicerQTGUIAbstractPlugin();
// Don't reimplement this method.
QString group() const;
// You can reimplement these methods
......
......@@ -20,6 +20,9 @@
#include "qSlicerQTGUIPlugins.h"
#include <QtPlugin>
#include <QtGlobal>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QtPlugin>
Q_EXPORT_PLUGIN2(customwidgetplugin, qSlicerQTGUIPlugins);
#endif
......@@ -21,8 +21,14 @@
#ifndef __qSlicerQTGUIPlugins_h
#define __qSlicerQTGUIPlugins_h
// QT includes
#include "vtkSlicerConfigure.h" // For Slicer_HAVE_QT5
// Qt includes
#ifdef Slicer_HAVE_QT5
#include <QtUiPlugin/QDesignerCustomWidgetCollectionInterface>
#else
#include <QDesignerCustomWidgetCollectionInterface>
#endif
// QtGUI includes
#include "qSlicerWidgetPlugin.h"
......@@ -37,6 +43,9 @@ class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerQTGUIPlugins
, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
#ifdef Slicer_HAVE_QT5
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
#endif
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface);
public:
......
......@@ -24,7 +24,7 @@
// --------------------------------------------------------------------------
qSlicerWidgetPlugin::qSlicerWidgetPlugin(QObject* parent)
: qSlicerQTGUIAbstractPlugin(parent)
: QObject(parent)
{
}
......
......@@ -24,7 +24,8 @@
#include "qSlicerQTGUIAbstractPlugin.h"
class Q_SLICER_DESIGNER_PLUGINS_EXPORT qSlicerWidgetPlugin
: public qSlicerQTGUIAbstractPlugin
: public QObject,
public qSlicerQTGUIAbstractPlugin
{
Q_OBJECT
public:
......
......@@ -47,15 +47,6 @@
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QWebView" name="WebView">
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
......@@ -76,11 +67,6 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKit/QWebView</header>
</customwidget>
<customwidget>
<class>ctkActionsWidget</class>
<extends>QWidget</extends>
......
......@@ -14,15 +14,6 @@
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QWebView" name="WebView">
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="ProgressBar">
<property name="value">
......@@ -32,13 +23,7 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKit/QWebView</header>
</customwidget>
</customwidgets>
<customwidgets/>
<resources/>
<connections/>
</ui>
......@@ -27,6 +27,12 @@
#include "qSlicerDarkStyle.h"
#include "qSlicerStylePlugin.h"
// --------------------------------------------------------------------------
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QtPlugin>
Q_EXPORT_PLUGIN2(qSlicerStylePlugin, qSlicerStylePlugin)
#endif
// --------------------------------------------------------------------------
// qSlicerStylePlugin methods
......@@ -60,4 +66,3 @@ QStringList qSlicerStylePlugin::keys() const
return QStringList() << "Slicer" <<"Dark Slicer";
}
Q_EXPORT_PLUGIN2(qSlicerStylePlugin, qSlicerStylePlugin)
......@@ -61,19 +61,28 @@ if(BUILD_TESTING)
EXTRA_INCLUDE ${EXTRA_INCLUDE}
)
set(KIT_TEST_MOC_SRCS
set(KIT_TEST_GENERATE_MOC_SRCS
)
if(Slicer_USE_PYTHONQT)
list(APPEND KIT_TEST_MOC_SRCS
list(APPEND KIT_TEST_GENERATE_MOC_SRCS
qSlicerLoadableModuleWithPythonTest.cxx
qSlicerPythonManagerWithoutApplicationTest.cxx
qSlicerScriptedLoadableModuleTest.cxx
qSlicerScriptedLoadableModuleWidgetTest.cxx
)
QT4_GENERATE_MOCS(${KIT_TEST_MOC_SRCS})
endif()
QT4_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
if(CTK_QT_VERSION VERSION_LESS "5")
if(KIT_TEST_GENERATE_MOC_SRCS)
QT4_GENERATE_MOCS(${KIT_TEST_GENERATE_MOC_SRCS})
endif()
QT4_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
else()
if(KIT_TEST_GENERATE_MOC_SRCS)
QT5_GENERATE_MOCS(${KIT_TEST_GENERATE_MOC_SRCS})
endif()
QT5_ADD_RESOURCES(Tests Resources/${KIT}Testing.qrc)
endif()
add_executable(${KIT}CxxTests ${Tests})
target_link_libraries(${KIT}CxxTests ${KIT})
......
......@@ -18,7 +18,11 @@
#include <QString>
#include <QTimer>
#include <QVBoxLayout>
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
#include <QWebView>
#else
#include <QWebEngineView>
#endif
// SlicerQt includes
#include "qSlicerWidget.h"
......@@ -166,7 +170,11 @@ int qSlicerWidgetTest2(int argc, char * argv[] )
vbox.addWidget(vtkWidget);
vtkWidget->GetRenderWindow()->Render();