diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f6f4ae6b07ffbefbd25f90d4d9ec1a033af4859..3ae6e07d81e89069e2ff23ed7bd11daedeb6cd3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,9 @@ if (WIN32) option(USE_BREAKPAD "Build the crash handler for Krita (only on windows)" OFF) endif () +option(HIDE_SAFE_ASSERTS "Don't show message box for \"safe\" asserts, just ignore them automatically and dump a message to the terminal." ON) +configure_file(config-hide-safe-asserts.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hide-safe-asserts.h) + ####################### ######################## ## Productset setting ## @@ -698,4 +701,3 @@ configure_file(config-ocio.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ocio.h ) check_function_exists(powf HAVE_POWF) configure_file(config-powf.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-powf.h) - diff --git a/config-hide-safe-asserts.h.cmake b/config-hide-safe-asserts.h.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e9fe991a4693f810d40c2b09e12ba874d57c19bc --- /dev/null +++ b/config-hide-safe-asserts.h.cmake @@ -0,0 +1,7 @@ +/* config-hide-safe-asserts.h. Generated by cmake from config-hide-safe-asserts.h.cmake */ + +/* Define if you have ocio, the OpenColorIO Library */ +#cmakedefine HIDE_SAFE_ASSERTS 1 + + + diff --git a/libs/global/kis_assert.cpp b/libs/global/kis_assert.cpp index df39fc7f1bb6b77884b5c8c4967a61b099101c65..3b3c72fdab33d728839799a445e2e74cae171469 100644 --- a/libs/global/kis_assert.cpp +++ b/libs/global/kis_assert.cpp @@ -26,6 +26,7 @@ #include #include #include +#include "config-hide-safe-asserts.h" /** * TODO: Add automatic saving of the documents @@ -40,13 +41,14 @@ * lead to an infinite loop. */ -void kis_assert_common(const char *assertion, const char *file, int line, bool throwException) +void kis_assert_common(const char *assertion, const char *file, int line, bool throwException, bool isIgnorable) { QString shortMessage = - QString("ASSERT (krita): \"%1\" in file %2, line %3") + QString("%4ASSERT (krita): \"%1\" in file %2, line %3") .arg(assertion) .arg(file) - .arg(line); + .arg(line) + .arg(isIgnorable ? "SAFE " : ""); QString longMessage = QString( @@ -65,7 +67,16 @@ void kis_assert_common(const char *assertion, const char *file, int line, bool t disableAssertMsg = true; } - QMessageBox::StandardButton button = QMessageBox::Abort; +#ifdef HIDE_SAFE_ASSERTS + const bool shouldIgnoreAsserts = HIDE_SAFE_ASSERTS; +#else + const bool shouldIgnoreAsserts = false; +#endif + + disableAssertMsg |= shouldIgnoreAsserts; + + QMessageBox::StandardButton button = + isIgnorable ? QMessageBox::Ignore : QMessageBox::Abort; if (!disableAssertMsg) { button = @@ -77,6 +88,10 @@ void kis_assert_common(const char *assertion, const char *file, int line, bool t if (button == QMessageBox::Abort) { qFatal("%s", shortMessage.toLatin1().data()); + } else if (isIgnorable) { + // Assert is a bug! Please don't change this line to warnKrita, + // the user must see it! + qWarning("%s", shortMessage.toLatin1().data()); } else if (throwException) { throw KisAssertException(shortMessage.toLatin1().data()); } @@ -85,12 +100,17 @@ void kis_assert_common(const char *assertion, const char *file, int line, bool t void kis_assert_recoverable(const char *assertion, const char *file, int line) { - kis_assert_common(assertion, file, line, false); + kis_assert_common(assertion, file, line, false, false); +} + +void kis_safe_assert_recoverable(const char *assertion, const char *file, int line) +{ + kis_assert_common(assertion, file, line, false, true); } void kis_assert_exception(const char *assertion, const char *file, int line) { - kis_assert_common(assertion, file, line, true); + kis_assert_common(assertion, file, line, true, false); } void kis_assert_x_exception(const char *assertion, @@ -104,5 +124,5 @@ void kis_assert_x_exception(const char *assertion, .arg(what) .arg(assertion); - kis_assert_common(res.toLatin1().data(), file, line, true); + kis_assert_common(res.toLatin1().data(), file, line, true, false); } diff --git a/libs/global/kis_assert.h b/libs/global/kis_assert.h index f7e9ba54797ce9699fad28b90ddc99a04cbbf7f3..d0e4900a01b3192a9e500e9543b9acf8ded4ce18 100644 --- a/libs/global/kis_assert.h +++ b/libs/global/kis_assert.h @@ -26,6 +26,8 @@ KRITAGLOBAL_EXPORT void kis_assert_exception(const char *assertion, const char * KRITAGLOBAL_EXPORT void kis_assert_recoverable(const char *assertion, const char *file, int line); KRITAGLOBAL_EXPORT void kis_assert_x_exception(const char *assertion, const char *where, const char *what, const char *file, int line); +KRITAGLOBAL_EXPORT void kis_safe_assert_recoverable(const char *assertion, const char *file, int line); + /** * KIS_ASSERT family of macros allows the user to choose whether to @@ -105,4 +107,37 @@ KRITAGLOBAL_EXPORT void kis_assert_x_exception(const char *assertion, const char */ #define KIS_ASSERT_RECOVER_NOOP(cond) KIS_ASSERT_RECOVER(cond) { qt_noop(); } + +/** + * This set of macros work in exactly the same way as their non-safe + * counterparts, but they are automatically converted into console + * warnings in release builds. That is the user will not see any + * message box, just a warning message wil be printed in a terminal + * and a recovery branch will be taken automatically. + * + * Rules when to use "safe" asserts. Use them if the following + * conditions are met: + * + * 1) The condition in the assert shows that a real *bug* has + * happened. It is not just a warning. It is a bug that should be + * fixed. + * + * 2) The recovery branch will *workaround* the bug and the user will + * be able to continue his work *as if nothing has + * happened*. Again, please mark the assert "safe" if and only if + * you are 100% sure Krita will not crash in a minute after you + * faced that bug. The user is not notified about this bug, so he + * is not going to take any emergency steps like saving his work + * and restarting Krita! + * + * 3) If you think that Krita should be better restarted after this + * bug, please use a usual KIS_ASSRT_RECOVER. + */ + +#define KIS_SAFE_ASSERT_RECOVER(cond) if (!(cond) && (kis_safe_assert_recoverable(#cond,__FILE__,__LINE__), true)) +#define KIS_SAFE_ASSERT_RECOVER_BREAK(cond) KIS_SAFE_ASSERT_RECOVER(cond) { break; } +#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond) KIS_SAFE_ASSERT_RECOVER(cond) { return; } +#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val) KIS_SAFE_ASSERT_RECOVER(cond) { return (val); } +#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond) KIS_SAFE_ASSERT_RECOVER(cond) { qt_noop(); } + #endif /* __KIS_ASSERT_H */ diff --git a/plugins/impex/bmp/kis_bmp_export.cpp b/plugins/impex/bmp/kis_bmp_export.cpp index 1b88903db7ff2068d893ec9800fbab76ffd3b211..6202f399fb25a7cecb9fb5ccc4f86da0db43e02b 100644 --- a/plugins/impex/bmp/kis_bmp_export.cpp +++ b/plugins/impex/bmp/kis_bmp_export.cpp @@ -60,7 +60,7 @@ KisImportExportFilter::ConversionStatus KisBMPExport::convert(const QByteArray& QRect rc = input->image()->bounds(); // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); image.save(filename); return KisImportExportFilter::OK; diff --git a/plugins/impex/brush/kis_brush_export.cpp b/plugins/impex/brush/kis_brush_export.cpp index a5652fde8732d70ae786237fe869079f3c77cfe9..af895c4faee67d25bb614d505f712d532671633e 100644 --- a/plugins/impex/brush/kis_brush_export.cpp +++ b/plugins/impex/brush/kis_brush_export.cpp @@ -142,7 +142,7 @@ KisImportExportFilter::ConversionStatus KisBrushExport::convert(const QByteArray } // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); QRect rc = input->image()->bounds(); diff --git a/plugins/impex/exr/exr_export.cc b/plugins/impex/exr/exr_export.cc index 79468d7c3bcd01a8a527a85e01ce1d21087961f1..1b196f54a09c6ec045b391c641809a62bea8d0d0 100644 --- a/plugins/impex/exr/exr_export.cc +++ b/plugins/impex/exr/exr_export.cc @@ -102,7 +102,7 @@ KisImportExportFilter::ConversionStatus exrExport::convert(const QByteArray& fro if (widget.flatten->isChecked()) { // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); @@ -111,7 +111,7 @@ KisImportExportFilter::ConversionStatus exrExport::convert(const QByteArray& fro } else { // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); res = kpc.buildFile(filename, image->rootLayer()); } diff --git a/plugins/impex/heightmap/kis_heightmap_export.cpp b/plugins/impex/heightmap/kis_heightmap_export.cpp index 12305f22b4bf840c607b892d6c79e9095d8eff6d..eeeb4baf60fcbc5149c3115b21562c37f15ade89 100644 --- a/plugins/impex/heightmap/kis_heightmap_export.cpp +++ b/plugins/impex/heightmap/kis_heightmap_export.cpp @@ -139,7 +139,7 @@ KisImportExportFilter::ConversionStatus KisHeightMapExport::convert(const QByteA // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(image->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); QFile f(filename); diff --git a/plugins/impex/jp2/jp2_export.cc b/plugins/impex/jp2/jp2_export.cc index 06981907e021692e4901ff789419dd8e0c37f7ce..a7f92b35a2f1f26bdf1277c397aef004a8ca75ba 100644 --- a/plugins/impex/jp2/jp2_export.cc +++ b/plugins/impex/jp2/jp2_export.cc @@ -106,7 +106,7 @@ KisImportExportFilter::ConversionStatus jp2Export::convert(const QByteArray& fro // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); jp2Converter kpc(input); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); diff --git a/plugins/impex/jpeg/kis_jpeg_export.cc b/plugins/impex/jpeg/kis_jpeg_export.cc index 4a35cfbe23eff210f9cc32135677432dd0eb8769..8169266783538551b87cc465d22730448d11ae3b 100644 --- a/plugins/impex/jpeg/kis_jpeg_export.cc +++ b/plugins/impex/jpeg/kis_jpeg_export.cc @@ -192,7 +192,7 @@ KisImportExportFilter::ConversionStatus KisJPEGExport::convert(const QByteArray& if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisJPEGConverter kpc(input, getBatchMode()); diff --git a/plugins/impex/png/kis_png_export.cc b/plugins/impex/png/kis_png_export.cc index 7dc2cf2c0b368b7deeac35ef7ac578c459902086..13151a79f706f115fb69e48181322f6c7e7ccdaf 100644 --- a/plugins/impex/png/kis_png_export.cc +++ b/plugins/impex/png/kis_png_export.cc @@ -94,7 +94,7 @@ KisImportExportFilter::ConversionStatus KisPNGExport::convert(const QByteArray& KisImageWSP image = input->image(); // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(image->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd; pd = new KisPaintDevice(*image->projection()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); diff --git a/plugins/impex/ppm/kis_ppm_export.cpp b/plugins/impex/ppm/kis_ppm_export.cpp index b908defbb7533d602ab084c7dde0be00c3fe1610..1859cf35333b2729560a5851211a37f41d9f5b68 100644 --- a/plugins/impex/ppm/kis_ppm_export.cpp +++ b/plugins/impex/ppm/kis_ppm_export.cpp @@ -185,7 +185,7 @@ KisImportExportFilter::ConversionStatus KisPPMExport::convert(const QByteArray& KisImageWSP image = input->image(); Q_CHECK_PTR(image); // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); // Test color space diff --git a/plugins/impex/psd/psd_loader.cpp b/plugins/impex/psd/psd_loader.cpp index 0e1ef02bea73e91d35412e17cc7596856e2fb0be..12f7761b581d226856680cd14770a74bf3004742 100644 --- a/plugins/impex/psd/psd_loader.cpp +++ b/plugins/impex/psd/psd_loader.cpp @@ -344,10 +344,10 @@ KisImageBuilder_Result PSDLoader::decode(const QString &filename) new KisPSDLayerStyleCollectionResource("Embedded PSD Styles.asl"); collection->setName(i18nc("Auto-generated layer style collection name for embedded styles (collection)", "<%1> (embedded)", m_image->objectName())); - KIS_ASSERT_RECOVER_NOOP(!collection->valid()); + KIS_SAFE_ASSERT_RECOVER_NOOP(!collection->valid()); collection->setLayerStyles(allStylesForServer); - KIS_ASSERT_RECOVER_NOOP(collection->valid()); + KIS_SAFE_ASSERT_RECOVER_NOOP(collection->valid()); KoResourceServer *server = KisResourceServerProvider::instance()->layerStyleCollectionServer(); server->addResource(collection, false); diff --git a/plugins/impex/tga/kis_tga_export.cpp b/plugins/impex/tga/kis_tga_export.cpp index 9d0fe008b0827029e093a79ba16510768e476ba1..c895d95b9a42a8d24a4c3cd66f2c84ac406d7fcc 100644 --- a/plugins/impex/tga/kis_tga_export.cpp +++ b/plugins/impex/tga/kis_tga_export.cpp @@ -62,7 +62,7 @@ KisImportExportFilter::ConversionStatus KisTGAExport::convert(const QByteArray& return KisImportExportFilter::NotImplemented; // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); QRect rc = input->image()->bounds(); QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); diff --git a/plugins/impex/tiff/kis_tiff_export.cc b/plugins/impex/tiff/kis_tiff_export.cc index 660333c4b6264a7eb25ba640a39f8172d9473abb..f9c245381a9382198d9ba7aa72f31643e95a7341 100644 --- a/plugins/impex/tiff/kis_tiff_export.cc +++ b/plugins/impex/tiff/kis_tiff_export.cc @@ -110,7 +110,7 @@ KisImportExportFilter::ConversionStatus KisTIFFExport::convert(const QByteArray& } // the image must be locked at the higher levels - KIS_ASSERT_RECOVER_NOOP(input->image()->locked()); + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisTIFFConverter ktc(input); KisImageBuilder_Result res;