diff --git a/CMakeLists.txt b/CMakeLists.txt index 96d6befb38178083ec9930d531c11fc9923998d6..5ed494eb3064e211f8176f23b0465f6ea77045d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ if(ZERO_TOLERANCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wfatal-errors") endif() if(BORNAGAIN_GUI) + include(SearchQt) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_MESSAGELOGCONTEXT=ON") endif() include(BornAgainConfiguration) @@ -108,7 +109,6 @@ add_subdirectory(Tests/UnitTests/Numeric) add_subdirectory(Tests/Performance/Core) if(BORNAGAIN_GUI) - include(SearchQt) add_subdirectory(ThirdParty/GUI) add_subdirectory(GUI) add_subdirectory(Tests/UnitTests/GUI) diff --git a/Core/Basics/Assert.h b/Core/Basics/Assert.h index b9a2d457f1d8484fc83186190020c828ada6f557..fd0e15b53c4bf2ece482c2717e6d6e23ee980a6e 100644 --- a/Core/Basics/Assert.h +++ b/Core/Basics/Assert.h @@ -15,22 +15,19 @@ #ifndef BORNAGAIN_CORE_BASICS_ASSERT_H #define BORNAGAIN_CORE_BASICS_ASSERT_H -#ifdef BORNAGAIN_GUI +// ASSERT must be declared as a macro, not a function, in order for the error +// message to correctly report the source line where the assertion failed. + +#ifdef QT_MESSAGELOGCONTEXT #include <QtGlobal> -#define ASSERT(condition) \ - if (!(condition)) \ - qFatal("assertion failed"); +#define ASSERT(condition) if (!(condition)) qFatal("Assertion failed") -#else // The non-GUI case is used by our test suite +#else // QT_MESSAGELOGCONTEXT undefined -#include <iostream> -#define ASSERT(condition) \ - if (!(condition)) { \ - std::cerr << "assertion failed" << std::endl; \ - exit(1); \ - } +#include <cassert> +#define ASSERT(condition) assert(condition) -#endif // BORNAGAIN_GUI +#endif // QT_MESSAGELOGCONTEXT #endif // BORNAGAIN_CORE_BASICS_ASSERT_H diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 505ae524815f6f08c9b554b339b7b08524eff5ee..546a2dfae3976c34d95d8ca600cdb0a866ca6a07 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -154,6 +154,10 @@ target_include_directories(${library_name} ${CMAKE_SOURCE_DIR}/ThirdParty/Core/cerf_wrapper # TEMPORARY SYSTEM PUBLIC ${EIGEN3_INCLUDE_DIRS} ) +if(BORNAGAIN_GUI) + target_include_directories(${library_name} PUBLIC ${Qt5Core_INCLUDE_DIRS}) +endif() + target_link_libraries(${library_name} ${Boost_LIBRARIES} ${FFTW3_LIBRARIES} ${GSL_LIBRARIES} ${tspectrum_LIBRARY} ${Cerf_LIBRARIES}) diff --git a/GUI/main/CMakeLists.txt b/GUI/main/CMakeLists.txt index 3e2450a18dbb442a395f22a26a119a91cbc82d52..2acb75efd7c7b4b77a81ac0dae6f796e977b385b 100644 --- a/GUI/main/CMakeLists.txt +++ b/GUI/main/CMakeLists.txt @@ -3,8 +3,8 @@ ############################################################################### set(executable_name BornAgain) -set(source_files main.cpp appoptions.cpp) -set(include_files appoptions.h) +set(source_files main.cpp appoptions.cpp MessageHandler.cpp) +set(include_files appoptions.h MessageHandler.h ) # ----------------------------------------------------------------------------- # Qt configuration diff --git a/GUI/main/MessageHandler.cpp b/GUI/main/MessageHandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db6b72c797c06468911662294c24981f30bcd163 --- /dev/null +++ b/GUI/main/MessageHandler.cpp @@ -0,0 +1,62 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file GUI/main/MessageHandler.cpp +//! @brief Implements function MessageHandler +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2018 +//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) +// +// ************************************************************************** // + +#include "GUI/main/MessageHandler.h" +#include <iostream> +#include <QMessageBox> + +#ifndef QT_NO_DEBUG +#define context(ctx) " [" << ctx.function << "]" +#else +#define context(ctx) "" +#endif + +//! This is set by main to be the message handler of our GUI. +void MessageHandler(QtMsgType type, const QMessageLogContext& ctx, const QString& msg) +{ + switch (type) { + case QtDebugMsg: + if (!msg.size()) // KDE will pass a zero-length msg qstring + break; + std::cerr << "DEBUG: " << msg.toStdString() << std::endl; + break; + case QtInfoMsg: + std::cerr << "INFO: " << msg.toStdString() << context(ctx) << std::endl; + break; + case QtWarningMsg: + default: + if (msg.left(4) == "QXcb") + return; + std::cerr << "WARNING: " << msg.toStdString() << " [" << ctx.function << "]" + << std::endl; + QMessageBox::warning(QApplication::activeWindow(), qAppName(), msg); + break; + case QtFatalMsg: + std::cerr << "FATAL: " << msg.toStdString() << " [" << ctx.function << "]" << std::endl; + qApp->restoreOverrideCursor(); + QMessageBox::critical( + QApplication::activeWindow(), qAppName(), + "Sorry, you encountered a fatal bug.\n" + "The application will terminate.\n" + "Please note the following and inform the maintainers.\n\n" + "Error:\n" + + msg + + "\n" + "Context:\n" + + ctx.function + "\n" + ); + qApp->quit(); + exit(1); + } +} diff --git a/GUI/main/MessageHandler.h b/GUI/main/MessageHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..961d4248d016ed759561e554fa5ffe8fa58e840d --- /dev/null +++ b/GUI/main/MessageHandler.h @@ -0,0 +1,17 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file GUI/main/MessageHandler.cpp +//! @brief Declares function MessageHandler +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2018 +//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) +// +// ************************************************************************** // + +#include <QApplication> + +void MessageHandler(QtMsgType type, const QMessageLogContext& ctx, const QString& msg); diff --git a/GUI/main/main.cpp b/GUI/main/main.cpp index 9b6d77f59c35ed85e33f5afd4803cd1dcc769b19..e997a45ba594f2ea75bdf402835b5c512ef67fa9 100644 --- a/GUI/main/main.cpp +++ b/GUI/main/main.cpp @@ -17,7 +17,7 @@ #include "GUI/coregui/mainwindow/mainwindow.h" #include "GUI/coregui/utils/hostosinfo.h" #include "GUI/main/appoptions.h" -#include <QApplication> +#include "GUI/main/MessageHandler.h" #include <QLocale> #include <QMetaType> @@ -37,8 +37,7 @@ int main(int argc, char* argv[]) QApplication app(argc, argv); - if (!options.find("with-debug")) - qInstallMessageHandler(messageHandler); + qInstallMessageHandler(MessageHandler); std::unique_ptr<SplashScreen> splash; if (!options.find("no-splash")) { diff --git a/Tests/UnitTests/Core/Basics/TestAssert.cpp b/Tests/UnitTests/Core/Basics/TestAssert.cpp index e52a734c12d74501563bae4c015bb98dc5463ece..06ef68b29c7e3dc61591e3aebcc96c5f8399a92b 100644 --- a/Tests/UnitTests/Core/Basics/TestAssert.cpp +++ b/Tests/UnitTests/Core/Basics/TestAssert.cpp @@ -8,5 +8,9 @@ class TestAssert : public ::testing::Test TEST_F(TestAssert, Assert) { EXPECT_NO_THROW(ASSERT(1)); - EXPECT_EXIT(ASSERT(0), ::testing::ExitedWithCode(1), "assertion failed"); +#ifdef QT_MESSAGELOGCONTEXT + EXPECT_EXIT(ASSERT(0), ::testing::KilledBySignal(6), "Assertion failed"); +#else + EXPECT_EXIT(ASSERT(0), ::testing::KilledBySignal(6), "Assertion .* failed"); +#endif } diff --git a/Tests/UnitTests/Core/CMakeLists.txt b/Tests/UnitTests/Core/CMakeLists.txt index 294b8fcd3ee424fdf4e604845524abe0dc4306b0..6e312354ee6fc1717a8801e7c715444c76610e98 100644 --- a/Tests/UnitTests/Core/CMakeLists.txt +++ b/Tests/UnitTests/Core/CMakeLists.txt @@ -2,11 +2,14 @@ include(GoogleTest) # provides gtest_discover_tests set(test UnitTestCore) -include_directories(${CMAKE_SOURCE_DIR}/Tests/UnitTests/utilities) - file(GLOB source_files "*/*.cpp" ${CMAKE_SOURCE_DIR}/Tests/GTestWrapper/TestAll.cpp) add_executable(${test} ${source_files}) +target_include_directories(${test} PUBLIC ${CMAKE_SOURCE_DIR}/Tests/UnitTests/utilities) target_link_libraries(${test} ${BornAgainCore_LIBRARY} gtest) +if(BORNAGAIN_GUI) + target_include_directories(${test} PUBLIC ${Qt5Core_INCLUDE_DIRS}) + target_link_libraries(${test} ${Qt5Core_LIBRARIES}) +endif() gtest_discover_tests(${test} TEST_PREFIX Core.Unit.)