Преглед изворни кода

This commit enables Qt5 support for the CTK Core library, issue #277.

There is still a Qt5Widgets dependency, see issue #278. The tests
pass (on my Ubuntu 12.04 development machine) with both Qt4 and Qt5.
Sascha Zelzer пре 12 година
родитељ
комит
588b1b7f57

+ 9 - 0
Libs/Core/CMakeLists.txt

@@ -97,6 +97,7 @@ set(KIT_MOC_SRCS
   ctkLogger.h
   ctkHistogram.h
   ctkModelTester.h
+  ctkErrorLogQtMessageHandler.h
   ctkTransferFunction.h
   ctkTransferFunctionRepresentation.h
   ctkWorkflow.h
@@ -119,6 +120,13 @@ set(KIT_target_libraries)
 
 ctkFunctionGetTargetLibraries(KIT_target_libraries)
 
+if(CTK_USE_QT5)
+  # This line below should actually be
+  # set(qt5_modules Qt5Core)
+  # see https://github.com/commontk/CTK/issues/278
+  set(qt5_modules Qt5Widgets)
+endif()
+
 ctkMacroBuildLib(
   NAME ${PROJECT_NAME}
   EXPORT_DIRECTIVE ${KIT_export_directive}
@@ -128,6 +136,7 @@ ctkMacroBuildLib(
   TARGET_LIBRARIES ${KIT_target_libraries}
   RESOURCES ${KIT_resources}
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  QT5_MODULES ${qt5_modules}
   )
 
 # Needed for ctkBackTrace

+ 14 - 3
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -100,12 +100,19 @@ set(Tests_Helpers_MOC_SRCS
   ctkExampleWorkflowStepUsingSignalsAndSlots.h
   )
 
-set(Tests_Helpers_MOC_CPP)
-QT4_WRAP_CPP(Tests_Helpers_MOC_CPP ${Tests_Helpers_MOC_SRCS})
-QT4_GENERATE_MOCS(
+set(Tests_Helpers_MOC_CPPS
   ctkBooleanMapperTest.cpp
   )
 
+set(Tests_Helpers_MOC_CPP)
+if(CTK_USE_QT5)
+  qt5_wrap_cpp(Tests_Helpers_MOC_CPP ${Tests_Helpers_MOC_SRCS})
+  qt5_generate_mocs(${Tests_Helpers_MOC_CPPS})
+else()
+  QT4_WRAP_CPP(Tests_Helpers_MOC_CPP ${Tests_Helpers_MOC_SRCS})
+  QT4_GENERATE_MOCS(${Tests_Helpers_MOC_CPPS})
+endif()
+
 if(HAVE_BFD)
   add_executable(ctkBinaryFileDescriptorTestHelper ctkBinaryFileDescriptorTestHelper.cpp)
 endif()
@@ -120,6 +127,10 @@ endif()
 add_executable(${KIT}CppTests ${Tests} ${Tests_Helpers_SRCS} ${Tests_Helpers_MOC_CPP})
 target_link_libraries(${KIT}CppTests ${LIBRARY_NAME} ${CTK_BASE_LIBRARIES} CTKDummyPlugin)
 
+if(CTK_USE_QT5)
+  qt5_use_modules(${KIT}CppTests Test Widgets)
+endif()
+
 #
 # Add Tests
 #

+ 1 - 1
Libs/Core/Testing/Cpp/ctkAbstractLibraryFactoryTest1.cpp

@@ -45,7 +45,7 @@ protected:
     QScopedPointer<ctkDummyLibrary> module(new ctkDummyLibrary());
     foreach(QString symbol, this->Symbols)
       {
-      void* res = this->symbolAddress(symbol);
+      SymbolAdressType res = this->symbolAddress(symbol);
       if (!res)
         {
         }

+ 4 - 2
Libs/Core/Testing/Cpp/ctkDummyPlugin.cpp

@@ -25,8 +25,6 @@
 // CTK includes
 #include "ctkDummyPlugin.h"
 
-Q_EXPORT_PLUGIN2( ctkDummyPlugin , ctkDummyPlugin)
-
 //-----------------------------------------------------------------------------
 ctkDummyPlugin::ctkDummyPlugin(QObject* parent)
   :QObject(parent)
@@ -45,3 +43,7 @@ void ctkDummyPlugin::dummyInterface()
 {
   qDebug() << "dummyInterface()";
 }
+
+#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+Q_EXPORT_PLUGIN2( ctkDummyPlugin , ctkDummyPlugin)
+#endif

+ 3 - 0
Libs/Core/Testing/Cpp/ctkDummyPlugin.h

@@ -34,6 +34,9 @@ class CTK_DUMMY_EXPORT ctkDummyPlugin: public QObject//, public ctkDummyInterfac
 {
   Q_OBJECT
 //  Q_INTERFACES(ctkDummyInterface)
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+  Q_PLUGIN_METADATA(IID "org.commontk.DummyPlugin")
+#endif
 public:
   ctkDummyPlugin(QObject* parent = 0);
   ~ctkDummyPlugin();

+ 13 - 4
Libs/Core/ctkAbstractLibraryFactory.h

@@ -34,9 +34,18 @@
 template<typename BaseClassType>
 class ctkFactoryLibraryItem : public ctkAbstractFactoryFileBasedItem<BaseClassType>
 {
+
+public:
+
+#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+  typedef void* SymbolAdressType;
+#else
+  typedef QFunctionPointer SymbolAdressType;
+#endif
+
 protected:
-  typedef typename QHash<QString, void*>::const_iterator ConstIterator;
-  typedef typename QHash<QString, void*>::iterator       Iterator;
+  typedef typename QHash<QString, SymbolAdressType>::const_iterator ConstIterator;
+  typedef typename QHash<QString, SymbolAdressType>::iterator       Iterator;
 
 public:
   //explicit ctkFactoryLibraryItem(const QString& path);
@@ -55,11 +64,11 @@ public:
   
   /// 
   /// Get symbol address
-  void* symbolAddress(const QString& symbol)const;
+  SymbolAdressType symbolAddress(const QString& symbol)const;
 
 protected:
   mutable QLibrary      Library;
-  QHash<QString, void*> ResolvedSymbols;
+  QHash<QString, SymbolAdressType> ResolvedSymbols;
   QStringList           Symbols;
 };
 

+ 3 - 2
Libs/Core/ctkAbstractLibraryFactory.tpp

@@ -83,7 +83,7 @@ bool ctkFactoryLibraryItem<BaseClassType>::resolve()
       continue;
       }
 
-    void * resolvedSymbol = this->Library.resolve(symbol.toLatin1());
+    SymbolAdressType resolvedSymbol = this->Library.resolve(symbol.toLatin1());
     if (!resolvedSymbol)
       {
       this->appendLoadErrorString(QString("Failed to resolve mandatory symbol '%1'").arg(symbol));
@@ -96,7 +96,8 @@ bool ctkFactoryLibraryItem<BaseClassType>::resolve()
 
 //-----------------------------------------------------------------------------
 template<typename BaseClassType>
-void* ctkFactoryLibraryItem<BaseClassType>::symbolAddress(const QString& symbol)const
+typename ctkFactoryLibraryItem<BaseClassType>::SymbolAdressType
+ctkFactoryLibraryItem<BaseClassType>::symbolAddress(const QString& symbol)const
 {
   ConstIterator iter = this->ResolvedSymbols.find(symbol);
   if ( iter == this->ResolvedSymbols.constEnd())

+ 2 - 3
Libs/Core/ctkCheckableModelHelper.cpp

@@ -20,10 +20,9 @@
 
 // Qt includes
 #include <QAbstractItemModel>
-#include <QApplication>
 #include <QDebug>
 #include <QStandardItemModel>
-#include <QWeakPointer>
+#include <QPointer>
 
 // CTK includes
 #include "ctkCheckableModelHelper.h"
@@ -56,7 +55,7 @@ public:
 
   void forceCheckability(const QModelIndex& index);
 
-  QWeakPointer<QAbstractItemModel> Model;
+  QPointer<QAbstractItemModel> Model;
   QModelIndex         RootIndex;
   Qt::Orientation     Orientation;
   bool                HeaderIsUpdating;

+ 0 - 3
Libs/Core/ctkErrorLogModel.cpp

@@ -19,17 +19,14 @@
 =========================================================================*/
 
 // Qt includes
-#include <QApplication>
 #include <QDateTime>
 #include <QDebug>
 #include <QFile>
-#include <QMainWindow>
 #include <QMetaEnum>
 #include <QMetaType>
 #include <QMutexLocker>
 #include <QPointer>
 #include <QStandardItem>
-#include <QStatusBar>
 
 // CTK includes
 #include "ctkErrorLogModel.h"

+ 0 - 1
Libs/Core/ctkErrorLogModel.h

@@ -22,7 +22,6 @@
 #define __ctkErrorLogModel_h
 
 // Qt includes
-#include <QPointer>
 #include <QSortFilterProxyModel>
 
 // CTK includes

+ 55 - 0
Libs/Core/ctkErrorLogQtMessageHandler.cpp

@@ -53,6 +53,52 @@ ctkErrorLogQtMessageHandler::ctkErrorLogQtMessageHandler() : Superclass()
 namespace
 {
 //------------------------------------------------------------------------------
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+void ctkErrorLogModelQtMessageOutput(QtMsgType type, const QMessageLogContext& context,
+                                     const QString& msg)
+{
+  //TODO: use context in the log message
+  Q_UNUSED(context)
+  // Warning: To avoid inifinite loop, do not use Q_ASSERT in this function.
+  if (msg.isEmpty())
+    {
+    return;
+    }
+  ctkErrorLogLevel::LogLevel level = ctkErrorLogLevel::Unknown;
+  if (type == QtDebugMsg)
+    {
+    level = ctkErrorLogLevel::Debug;
+    }
+  else if (type == QtWarningMsg)
+    {
+    level = ctkErrorLogLevel::Warning;
+    }
+  else if (type == QtCriticalMsg)
+    {
+    level = ctkErrorLogLevel::Critical;
+    }
+  else if (type == QtFatalMsg)
+    {
+    level = ctkErrorLogLevel::Fatal;
+    }
+
+  QCoreApplication * coreApp = QCoreApplication::instance();
+  QList<QVariant> handlers = coreApp->property("ctkErrorLogQtMessageHandlers").toList();
+  foreach(QVariant v, handlers)
+    {
+    ctkErrorLogQtMessageHandler* handler = v.value<ctkErrorLogQtMessageHandler*>();
+    Q_ASSERT(handler);
+//    //QPointer<ctkErrorLogQtMessageHandler> handler = v.value<QPointer<ctkErrorLogQtMessageHandler> >();
+//    //if(handler.isNull())
+//    //  {
+//    //  continue;
+//    //  }
+    handler->handleMessage(
+          ctk::qtHandleToString(QThread::currentThreadId()),
+          level, handler->handlerPrettyName(), msg);
+    }
+}
+#else
 void ctkErrorLogModelQtMessageOutput(QtMsgType type, const char *msg)
 {
   // Warning: To avoid inifinite loop, do not use Q_ASSERT in this function.
@@ -94,6 +140,7 @@ void ctkErrorLogModelQtMessageOutput(QtMsgType type, const char *msg)
           level, handler->handlerPrettyName(), msg);
     }
 }
+#endif
 }
 
 // --------------------------------------------------------------------------
@@ -107,10 +154,18 @@ void ctkErrorLogQtMessageHandler::setEnabledInternal(bool value)
 {
   if (value)
     {
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+    this->SavedQtMessageHandler = qInstallMessageHandler(ctkErrorLogModelQtMessageOutput);
+#else
     this->SavedQtMessageHandler = qInstallMsgHandler(ctkErrorLogModelQtMessageOutput);
+#endif
     }
   else
     {
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+    qInstallMessageHandler(this->SavedQtMessageHandler);
+#else
     qInstallMsgHandler(this->SavedQtMessageHandler);
+#endif
     }
 }

+ 11 - 0
Libs/Core/ctkErrorLogQtMessageHandler.h

@@ -25,10 +25,17 @@
 #include <ctkErrorLogModel.h>
 #include "ctkCoreExport.h"
 
+// Qt includes
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+#include <QtMessageHandler>
+#endif
+
 //------------------------------------------------------------------------------
 /// \ingroup Core
 class CTK_CORE_EXPORT ctkErrorLogQtMessageHandler : public ctkErrorLogAbstractMessageHandler
 {
+  Q_OBJECT
+
 public:
   typedef ctkErrorLogAbstractMessageHandler Superclass;
 
@@ -39,7 +46,11 @@ public:
   virtual QString handlerName()const;
   virtual void setEnabledInternal(bool value);
 
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+  QtMessageHandler SavedQtMessageHandler;
+#else
   QtMsgHandler SavedQtMessageHandler;
+#endif
 };
 
 #endif

+ 1 - 1
Libs/Testing/ctkTest.h

@@ -87,7 +87,7 @@ static void mouseEvent(QTest::MouseAction action, QWidget *widget, Qt::MouseButt
     static const char *mouseActionNames[] =
         { "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" };
     QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget");
-    QTest::qWarn(warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])).toAscii().data());
+    QTest::qWarn(qPrintable(warning.arg(mouseActionNames[static_cast<int>(action)])));
     }
 }