浏览代码

Add "terminalOutputEnabled" property to ctkErrorLogModel

Enabling this property allows to have both the message printed in the terminal
and added in the model.
Jean-Christophe Fillion-Robin 14 年之前
父节点
当前提交
ad5468b1e1

+ 4 - 0
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -28,6 +28,7 @@ SET(KITTests_SRCS
   ctkCommandLineParserTest1.cpp
   ctkErrorLogModelTest1.cpp
   ctkErrorLogModelTest2.cpp
+  ctkErrorLogModelTest3.cpp
   ctkModelTesterTest1.cpp
   ctkUtilsTest1.cpp
   ctkUtilsTest2.cpp
@@ -112,6 +113,9 @@ SIMPLE_TEST( ctkDependencyGraphTest1 )
 SIMPLE_TEST( ctkDependencyGraphTest2 )
 SIMPLE_TEST( ctkErrorLogModelTest1 )
 SIMPLE_TEST( ctkErrorLogModelTest2 )
+SIMPLE_TEST( ctkErrorLogModelTest3 )
+SET_TESTS_PROPERTIES(ctkErrorLogModelTest3 PROPERTIES PASS_REGULAR_EXPRESSION
+"This is a qDebug message\nThis is a qWarning message\nThis is a qCritical message\n")
 SIMPLE_TEST( ctkModelTesterTest1 )
 SIMPLE_TEST( ctkPimplTest1 )
 SIMPLE_TEST( ctkSingletonTest1 )

+ 186 - 0
Libs/Core/Testing/Cpp/ctkErrorLogModelTest3.cpp

@@ -0,0 +1,186 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QCoreApplication>
+#include <QDebug>
+#include <QStringList>
+
+// CTK includes
+#include "ctkErrorLogModel.h"
+#include "ctkErrorLogQtMessageHandler.h"
+#include "ctkModelTester.h"
+
+// STL includes
+#include <cstdlib>
+#include <iostream>
+
+namespace
+{
+//-----------------------------------------------------------------------------
+// Utility function
+
+//-----------------------------------------------------------------------------
+QString checkRowCount(int line, int currentRowCount, int expectedRowCount)
+{
+  if (currentRowCount != expectedRowCount)
+    {
+    QString errorMsg("Line %1 - Expected rowCount: %2 - Current rowCount: %3\n");
+    return errorMsg.arg(line).arg(expectedRowCount).arg(currentRowCount);
+    }
+  return QString();
+}
+
+//-----------------------------------------------------------------------------
+QString checkTextMessages(int line, const ctkErrorLogModel& model, const QStringList& expectedMessages)
+{
+  for(int i=0; i < expectedMessages.count(); ++i)
+    {
+    QModelIndex descriptionIndex = model.index(i, ctkErrorLogModel::DescriptionColumn);
+    QString currentMessage = descriptionIndex.data(ctkErrorLogModel::DescriptionTextRole).toString();
+    if (currentMessage.compare(expectedMessages.value(i)) != 0)
+      {
+      QString errorMsg("Line %1 - Problem with row%2 !\n"
+                       "\tExpected message [%3]\n"
+                       "\tCurrent message [%4]\n");
+      return errorMsg.arg(line).arg(i).arg(expectedMessages.value(i)).arg(currentMessage);
+      }
+    }
+  return QString();
+}
+
+//-----------------------------------------------------------------------------
+void printTextMessages(const ctkErrorLogModel& model)
+{
+  fprintf(stdout, "%s", "ErrorLogModel rows:\n");
+  QString text("\trow %1 => %2\n");
+  for (int i=0; i < model.rowCount(); ++i)
+    {
+    QString description =
+        model.index(0, ctkErrorLogModel::DescriptionColumn).data().toString();
+    fprintf(stdout, "%s", qPrintable(text.arg(i).arg(description)));
+    }
+  fflush(stdout);
+}
+
+//-----------------------------------------------------------------------------
+void printErrorMessage(const QString& errorMessage)
+{
+  fprintf(stderr, "%s", qPrintable(errorMessage));
+  fflush(stderr);
+}
+
+//-----------------------------------------------------------------------------
+QString checkBoolean(int line, const char* valueName, bool current, bool expected)
+{
+  if (current != expected)
+    {
+    QString errorMsg("Line %1 - Expected %2: %3 - Current %4: %5\n");
+    return errorMsg.arg(line).arg(valueName).
+        arg(static_cast<int>(expected)).arg(valueName).arg(static_cast<int>(current));
+    }
+  return QString();
+}
+
+} // end namespace
+
+//-----------------------------------------------------------------------------
+int ctkErrorLogModelTest3(int argc, char * argv [])
+{
+  QCoreApplication app(argc, argv);
+  Q_UNUSED(app);
+  QString errorMsg;
+    
+  ctkErrorLogModel model;
+  bool currentTerminalOutputEnabled = model.terminalOutputEnabled();
+  errorMsg = checkBoolean(__LINE__, "TerminalOutputEnabled", currentTerminalOutputEnabled, false);
+  if (!errorMsg.isEmpty())
+    {
+    model.disableAllMsgHandler();
+    printErrorMessage(errorMsg);
+    printTextMessages(model);
+    return EXIT_FAILURE;
+    }
+
+  model.setTerminalOutputEnabled(true);
+
+  currentTerminalOutputEnabled = model.terminalOutputEnabled();
+  errorMsg = checkBoolean(__LINE__, "TerminalOutputEnabled", currentTerminalOutputEnabled, true);
+  if (!errorMsg.isEmpty())
+    {
+    model.disableAllMsgHandler();
+    printErrorMessage(errorMsg);
+    printTextMessages(model);
+    return EXIT_FAILURE;
+    }
+
+  ctkModelTester modelTester;
+  modelTester.setVerbose(false);
+
+  try
+    {
+    modelTester.setModel(&model);
+
+    // --------------------------------------------------------------------------
+    // Monitor Qt messages
+    model.registerMsgHandler(new ctkErrorLogQtMessageHandler);
+    model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, true);
+
+    QString qtMessage0("This is a qDebug message");
+    qDebug().nospace() << qPrintable(qtMessage0);
+
+    QString qtMessage1("This is a qWarning message");
+    qWarning().nospace() << qPrintable(qtMessage1);
+
+    QString qtMessage2("This is a qCritical message");
+    qCritical().nospace() << qPrintable(qtMessage2);
+
+    QStringList expectedQtMessages;
+    expectedQtMessages << qtMessage0
+                       << qtMessage1
+                       << qtMessage2;
+
+    errorMsg = checkRowCount(__LINE__, model.rowCount(), /* expected = */ expectedQtMessages.count());
+    if (!errorMsg.isEmpty())
+      {
+      model.disableAllMsgHandler();
+      printErrorMessage(errorMsg);
+      printTextMessages(model);
+      return EXIT_FAILURE;
+      }
+
+    errorMsg = checkTextMessages(__LINE__, model, expectedQtMessages);
+    if (!errorMsg.isEmpty())
+      {
+      model.disableAllMsgHandler();
+      printErrorMessage(errorMsg);
+      return EXIT_FAILURE;
+      }
+
+    }
+  catch (const char* error)
+    {
+    model.disableAllMsgHandler();
+    std::cerr << error << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}

+ 32 - 0
Libs/Core/ctkErrorLogModel.cpp

@@ -108,6 +108,8 @@ public:
 
   bool LogEntryGrouping;
 
+  int TerminalOutputEnabled;
+
 };
 
 // --------------------------------------------------------------------------
@@ -117,6 +119,7 @@ public:
 ctkErrorLogModelPrivate::ctkErrorLogModelPrivate(ctkErrorLogModel& object)
   : q_ptr(&object)
 {
+  this->TerminalOutputEnabled = false;
 }
 
 // --------------------------------------------------------------------------
@@ -258,6 +261,20 @@ void ctkErrorLogModel::setAllMsgHandlerEnabled(bool enabled)
 }
 
 //------------------------------------------------------------------------------
+bool ctkErrorLogModel::terminalOutputEnabled()const
+{
+  Q_D(const ctkErrorLogModel);
+  return d->TerminalOutputEnabled;
+}
+
+//------------------------------------------------------------------------------
+void ctkErrorLogModel::setTerminalOutputEnabled(bool enabled)
+{
+  Q_D(ctkErrorLogModel);
+  d->TerminalOutputEnabled = enabled;
+}
+
+//------------------------------------------------------------------------------
 QString ctkErrorLogModel::logLevelAsString(LogLevel logLevel)const
 {
   QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
@@ -349,6 +366,21 @@ void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
       d->StandardItemModel.setData(lastRowDescriptionIndex, displayText.append("..."), Qt::DisplayRole);
       }
     }
+
+  if (d->TerminalOutputEnabled)
+    {
+    QStringList savedMsgHandlerEnabled = this->msgHandlerEnabled();
+    this->disableAllMsgHandler();
+    if (logLevel <= ctkErrorLogModel::Info)
+      {
+      std::cout << text << std::endl;
+      }
+    else
+      {
+      std::cerr << text << std::endl;
+      }
+    this->setMsgHandlerEnabled(savedMsgHandlerEnabled);
+    }
 }
 
 //------------------------------------------------------------------------------

+ 6 - 0
Libs/Core/ctkErrorLogModel.h

@@ -68,6 +68,7 @@ class CTK_CORE_EXPORT ctkErrorLogModel : public QSortFilterProxyModel
   Q_OBJECT
   Q_FLAGS(LogLevel)
   Q_PROPERTY(bool logEntryGrouping READ logEntryGrouping WRITE setLogEntryGrouping)
+  Q_PROPERTY(bool terminalOutputEnabled READ terminalOutputEnabled WRITE  setTerminalOutputEnabled)
 public:
   typedef QSortFilterProxyModel Superclass;
   typedef ctkErrorLogModel Self;
@@ -118,6 +119,11 @@ public:
   void disableAllMsgHandler();
   void setAllMsgHandlerEnabled(bool enabled);
 
+  /// Return True messages are both printed into the terminal and added to ctkErrorLogModel.
+  bool terminalOutputEnabled()const;
+
+  void setTerminalOutputEnabled(bool enabled);
+
   QString logLevelAsString(LogLevel logLevel)const;
 
   void addEntry(LogLevel logLevel, const QString& origin, const char* text);