Package: release.debian.org User: release.debian....@packages.debian.org Usertags: unblock
Dear RT, I've just uploaded a sigil/0.9.13-1, with the latest upstream release. It's a mostly bugfix release, that once stripped of the doc changes and translation updates boils down to 57 files changed, 643 insertions(+), 883 deletions(-) According to upstream, 0.9.12 (released in February) is "very buggy" (https://github.com/Sigil-Ebook/Sigil/wiki#versions-0911-and-0912-of-sigil-are-very-buggy) and are not quite fit for usage. Also, there is finally built-in support for system-wide mathjs, so we are not patch-free, which is a great thing by itself for me :) Please find attached the stripped down debdiff created with /usr/bin/debdiff sigil_0.9.12+dfsg-1.dsc sigil_0.9.13+dfsg-1.dsc | filterdiff -x '*/ts/*' | filterdiff -x '*/docs/*' Thanks for considering. -- regards, Mattia Rizzolo GPG Key: 66AE 2B4A FCCF 3F52 DA18 4D18 4B04 3FCD B944 4540 .''`. more about me: https://mapreri.org : :' : Launchpad user: https://launchpad.net/~mapreri `. `'` Debian QA page: https://qa.debian.org/developer.php?login=mattia `-
diffstat for sigil-0.9.12+dfsg sigil-0.9.13+dfsg CMakeLists.txt | 2 ChangeLog.txt | 23 README.md | 2 appveyor.yml | 13 debian/changelog | 11 debian/control | 2 debian/copyright | 8 debian/patches/mathajx | 50 - debian/patches/series | 1 debian/rules | 3 debian/sigil-data.install | 1 internal/gumbo/tokenizer.c | 6 src/CMakeLists.txt | 40 src/Dialogs/ClipEditor.cpp | 22 src/Dialogs/ClipboardHistorySelector.cpp | 3 src/Dialogs/Reports.cpp | 1 src/Dialogs/ReportsWidgets/AllFilesWidget.cpp | 7 src/Dialogs/ReportsWidgets/AllFilesWidget.h | 2 src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp | 7 src/Dialogs/ReportsWidgets/CSSFilesWidget.h | 2 src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp | 6 src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h | 2 src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp | 6 src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h | 2 src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp | 7 src/Dialogs/ReportsWidgets/HTMLFilesWidget.h | 2 src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp | 7 src/Dialogs/ReportsWidgets/ImageFilesWidget.h | 2 src/Dialogs/ReportsWidgets/LinksWidget.cpp | 6 src/Dialogs/ReportsWidgets/LinksWidget.h | 2 src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp | 6 src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h | 2 src/Dialogs/SearchEditor.cpp | 15 src/MainUI/FindReplace.cpp | 5 src/MainUI/FindReplace.h | 1 src/MainUI/MainWindow.cpp | 60 + src/MainUI/MainWindow.h | 1 src/MainUI/PreviewWindow.cpp | 22 src/Misc/CSSInfo.cpp | 24 src/Misc/CSSInfo.h | 3 src/Misc/EmbeddedPythonPkg.cpp | 617 ------------- src/Misc/FilenameDelegate.cpp | 13 src/Misc/SettingsStore.cpp | 10 src/MiscEditors/ClipEditorModel.cpp | 99 +- src/MiscEditors/ClipEditorModel.h | 1 src/MiscEditors/IndexEditorModel.cpp | 103 +- src/MiscEditors/SearchEditorModel.cpp | 106 +- src/Resource_Files/plugin_launchers/python/wrapper.py | 2 src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js | 23 src/Resource_Files/windows/version.rc.in | 2 src/SourceUpdates/PerformCSSUpdates.cpp | 2 src/Tabs/TabManager.cpp | 33 src/ViewEditors/BookViewPreview.cpp | 17 src/ViewEditors/CodeViewEditor.cpp | 9 src/main.cpp | 100 +- src/sigil_constants.cpp | 1 src/sigil_constants.h | 1 57 files changed, 643 insertions(+), 883 deletions(-) diff -Nru sigil-0.9.12+dfsg/appveyor.yml sigil-0.9.13+dfsg/appveyor.yml --- sigil-0.9.12+dfsg/appveyor.yml 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/appveyor.yml 2019-03-20 01:01:44.000000000 +0100 @@ -1,4 +1,4 @@ -version: '0.9.10-{build}' +version: '0.9.13-{build}' branches: only: @@ -13,7 +13,6 @@ configuration: Release platform: -- x86 - x64 clone_script: @@ -34,19 +33,19 @@ global: INNO: C:\Program Files (x86)\Inno Setup 5 REDIST: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\1033\vcredist_%PLATFORM%.exe - DOWNLOAD: https://github.com/dougmassay/win-qtwebkit-5.212/releases/download/v5.212-1/qt5.11-custom-webkit-%PLATFORM%.zip + DOWNLOAD: https://github.com/dougmassay/win-qtwebkit-5.212/releases/download/v5.212-1/qt5.12-custom-webkit-%PLATFORM%.zip matrix: - PYTHON: C:\Python37 - QT: C:\Qt\5.11\msvc2015 + QT: C:\Qt\5.12\msvc2015 CMAKE64BIT: - PYTHON: C:\Python37-x64 - QT: C:\Qt\5.11\msvc2015_64 + QT: C:\Qt\5.12\msvc2015_64 CMAKE64BIT: -DWIN_INSTALLER_USE_64BIT_CRT=1 matrix: exclude: - platform: x86 - PYTHON: C:\Python37-x64 + PYTHON: C:\Python37 - platform: x64 PYTHON: C:\Python37 fast_finish: true @@ -81,7 +80,7 @@ pip3.7 install cssselect==1.0.3 pip3.7 install chardet==3.0.4 pip3.7 install pillow==5.4.1 - pip3.7 install PyQt5==5.11.3 + pip3.7 install PyQt5==5.12 pip3.7 install lxml==4.2.6 cd project\sigil\build call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM% diff -Nru sigil-0.9.12+dfsg/ChangeLog.txt sigil-0.9.13+dfsg/ChangeLog.txt --- sigil-0.9.12+dfsg/ChangeLog.txt 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/ChangeLog.txt 2019-03-20 01:01:44.000000000 +0100 @@ -1,3 +1,26 @@ +Sigil-0.9.13 + Bug Fixes + - Revert change of INI encoding to utf-8 as QSettings very broken under utf-8 (commit 5484463) + - Ensure all url attributes in shape-outside properties in CSS stylesheets get updated (commit de7b09f) + - Workaround for lost cursor in qlineedit Qt bug (issue #398) (commit a8acab7) + - Workaround missing File New, Open, Quit menus in Mac menubar if windows closed (commit 660a8aa) + - Remove Icon from Tab for macOS only to workaround Qt bug (commit 5c91924) + - Plug some memory leaks (commits: 85f78d7, cb9b833, 614d601, bf2f2f4, ebfb613, 4qa8f33) + - Backport Qt 5.12alpha fix to prevent heap corruption due to qwidget next focus pointers (commit f5c7284) + - Plug macOS memory leaks when closing a main window (commit fbf9015) + - Put back quote in tag name bug fix lost in recent changes (commit ebd8c7c) + - Disable Netscape Plugins being used in BookView and Preview Window (commit 79314ea) + - Use custom version of qtwebkit with Qt 5.5 memory leak fix added back and no load plugins if disabled + (see commits 94a28d7, 9f7ebba, and 4b968a9) + + New Features + - Add filename to tab tooltip (commit 27f8db7) + - Clear memory caches when Preview changes to keep memory footprint smaller (commit 87b9247) + - Update to MathJax 2.75, adds support for mathml mlongdiv, mstack, mcarries (commit 568aba5) + - Reduce memory footprint by letting worker threads expire (commit c1ee7ca) + - Reduce memory footprint by properly setting web page caches (commit 9f07cbe) + + Sigil-0.9.12 Bug Fixes - fix typo in cssreformatter that caused errors with @fontface (issue #394) diff -Nru sigil-0.9.12+dfsg/CMakeLists.txt sigil-0.9.13+dfsg/CMakeLists.txt --- sigil-0.9.12+dfsg/CMakeLists.txt 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/CMakeLists.txt 2019-03-20 01:01:44.000000000 +0100 @@ -29,7 +29,7 @@ set( SIGIL_MAJOR_VERSION 0 ) set( SIGIL_MINOR_VERSION 9 ) -set( SIGIL_REVISION_VERSION 12 ) +set( SIGIL_REVISION_VERSION 13 ) set( SIGIL_FULL_VERSION ${SIGIL_MAJOR_VERSION}.${SIGIL_MINOR_VERSION}.${SIGIL_REVISION_VERSION} ) if( UNIX AND NOT APPLE ) diff -Nru sigil-0.9.12+dfsg/debian/changelog sigil-0.9.13+dfsg/debian/changelog --- sigil-0.9.12+dfsg/debian/changelog 2019-02-19 13:50:47.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/changelog 2019-03-21 13:02:08.000000000 +0100 @@ -1,3 +1,14 @@ +sigil (0.9.13+dfsg-1) unstable; urgency=medium + + * New upstream version 0.9.13+dfsg. + * d/copyright: + + Update the Files-Excluded pattern. + + Update. + * Sigil now has native support for system-wide mathjx, leverage it, + and drop the local patch. + + -- Mattia Rizzolo <mat...@debian.org> Thu, 21 Mar 2019 13:02:08 +0100 + sigil (0.9.12+dfsg-1) unstable; urgency=medium * New upstream version 0.9.12+dfsg. diff -Nru sigil-0.9.12+dfsg/debian/control sigil-0.9.13+dfsg/debian/control --- sigil-0.9.12+dfsg/debian/control 2019-02-16 20:52:45.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/control 2019-03-21 12:39:01.000000000 +0100 @@ -31,7 +31,7 @@ Depends: libhunspell-dev, libjs-jquery-scrollto, - libjs-mathjax, + libjs-mathjax (>= 2.7.0), python3-lxml, sigil-data (= ${source:Version}), ${misc:Depends}, diff -Nru sigil-0.9.12+dfsg/debian/copyright sigil-0.9.13+dfsg/debian/copyright --- sigil-0.9.12+dfsg/debian/copyright 2019-02-16 20:43:41.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/copyright 2019-03-21 12:42:32.000000000 +0100 @@ -10,7 +10,9 @@ src/Resource_Files/dictionaries src/Resource_Files/javascript/jquery-* src/Resource_Files/javascript/jquery.scrollTo-* - src/Resource_Files/polyfills + src/Resource_Files/polyfills/MathJax_License.txt + src/Resource_Files/polyfills/MathJax_README.md + src/Resource_Files/polyfills/ML.zip Files: * Copyright: 2009-2011 Strahinja Markovic <strahinja.marko...@gmail.com> @@ -89,6 +91,10 @@ Copyright: 2004-2013 Christof Hoeke License: LGPL-3+ +Files: src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js +Copyright: 2010-2018 The MathJax Consortium +License: Apache-2.0 + Files: src/Resource_Files/python3lib/cssreformatter.py Copyright: 2016 Francesco Martini License: GPL-3+ diff -Nru sigil-0.9.12+dfsg/debian/patches/mathajx sigil-0.9.13+dfsg/debian/patches/mathajx --- sigil-0.9.12+dfsg/debian/patches/mathajx 2018-07-29 18:23:23.000000000 +0200 +++ sigil-0.9.13+dfsg/debian/patches/mathajx 1970-01-01 01:00:00.000000000 +0100 @@ -1,50 +0,0 @@ -Description: use system installation of MathJax instead of the bundled one - This drops support for SIGIL_EXTRA_ROOT variable here, and given that common - installation of MathJax are not single-file-built we need to configure the - loader to load our the extensions we need. - Thanks to Dmitry Shachnev <mity...@debian.org> for helping out with the MathJax - configuration. -Author: Mattia Rizzolo <mat...@debian.org> -Forwarded: no -Last-Update: 2016-06-13 - ---- a/src/MainUI/PreviewWindow.cpp -+++ b/src/MainUI/PreviewWindow.cpp -@@ -211,18 +211,21 @@ - mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MathJax.js"; - #else - // all flavours of linux / unix -- // user supplied environment variable to 'share/sigil' directory will overrides everything -- if (!sigil_extra_root.isEmpty()) { -- mathjaxurl = sigil_extra_root + "/polyfills/MathJax.js"; -- } else { -- mathjaxurl = sigil_share_root + "/polyfills/MathJax.js"; -- } -+ mathjaxurl = "/usr/share/javascript/mathjax/MathJax.js"; - #endif - - mathjaxurl = "file://" + Utility::URLEncodePath(mathjaxurl); - int endheadpos = text.indexOf("</head>"); - if (endheadpos > 1) { - QString inject_mathjax = -+ "<script type=\"text/x-mathjax-config\">" -+ " MathJax.Hub.Config({" -+ " config: [\"MML_SVG.js\"]," -+ " extensions: [\"MatchWebFonts.js\"]," -+ " MathML: { extensions: [\"mml3.js\"] }," -+ " SVG: { blacker: 1 }," -+ " });" -+ "</script>" - "<script type=\"text/javascript\" " - "src=\"" + mathjaxurl + "\"></script>"; - text.insert(endheadpos, inject_mathjax); ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -997,7 +997,6 @@ - if ( INSTALL_BUNDLED_DICTS ) - install( FILES ${DIC_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/hunspell_dictionaries/ ) - endif() -- install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax.js DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/ ) - install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/plugin_launchers/python/ DESTINATION ${SIGIL_SHARE_ROOT}/plugin_launchers/python ) - install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/python3lib/ DESTINATION ${SIGIL_SHARE_ROOT}/python3lib ) - install( FILES ${EXAMPLE_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/examples/ ) diff -Nru sigil-0.9.12+dfsg/debian/patches/series sigil-0.9.13+dfsg/debian/patches/series --- sigil-0.9.12+dfsg/debian/patches/series 2017-03-22 10:26:53.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -mathajx diff -Nru sigil-0.9.12+dfsg/debian/rules sigil-0.9.13+dfsg/debian/rules --- sigil-0.9.12+dfsg/debian/rules 2019-02-16 20:49:44.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/rules 2019-03-21 12:39:01.000000000 +0100 @@ -13,7 +13,8 @@ dh_auto_configure -- \ -DUSE_SYSTEM_LIBS=1 \ -DSYSTEM_LIBS_REQUIRED=1 \ - -DINSTALL_BUNDLED_DICTS=0 + -DINSTALL_BUNDLED_DICTS=0 \ + -DMATHJAX_DIR=/usr/share/javascript/mathjax/ \ override_dh_install: rm -v $(CURDIR)/debian/tmp/usr/share/sigil/plugin_launchers/python/sigil_bs4/COPYING.txt diff -Nru sigil-0.9.12+dfsg/debian/sigil-data.install sigil-0.9.13+dfsg/debian/sigil-data.install --- sigil-0.9.12+dfsg/debian/sigil-data.install 2017-03-22 10:37:37.000000000 +0100 +++ sigil-0.9.13+dfsg/debian/sigil-data.install 2019-03-21 12:40:27.000000000 +0100 @@ -1,2 +1,3 @@ +usr/share/javascript/mathjax/config/local/SIGIL_EBOOK_MML_SVG.js usr/share/pixmaps usr/share/sigil diff -Nru sigil-0.9.12+dfsg/internal/gumbo/tokenizer.c sigil-0.9.13+dfsg/internal/gumbo/tokenizer.c --- sigil-0.9.12+dfsg/internal/gumbo/tokenizer.c 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/internal/gumbo/tokenizer.c 2019-03-20 01:01:44.000000000 +0100 @@ -1088,6 +1088,12 @@ abandon_current_tag(parser); gumbo_tokenizer_set_state(parser, GUMBO_LEX_DATA); return NEXT_CHAR; + // xml parsing rules do not allow single or double quotes in tag names + case '"': + case '\'': + tokenizer_add_parse_error(parser, GUMBO_ERR_TAG_INVALID); + append_char_to_tag_buffer(parser, '_', false); + return NEXT_CHAR; default: append_char_to_tag_buffer(parser, gumbo_tolower(c), true); return NEXT_CHAR; diff -Nru sigil-0.9.12+dfsg/README.md sigil-0.9.13+dfsg/README.md --- sigil-0.9.12+dfsg/README.md 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/README.md 2019-03-20 01:01:44.000000000 +0100 @@ -101,7 +101,7 @@ * ZLib Data Compression Library (zlib 1.2.8) * jQuery-2.2.4 (src/Resource_Files/javascript/jquery-2.2.4.min.js) * jQuery.ScrollTo-2.1.2 (src/Resource_Files/javascript/jquery.scrollTo-2.1.2.min.js) -* MathJax.js single file version: (src/Resource_Files/polyfills) +* MathJax.js Version 2.75: (src/Resource_Files/polyfills) In addtion, Sigil uses the following other packages that have been specifically modified for use inside Sigil: diff -Nru sigil-0.9.12+dfsg/src/CMakeLists.txt sigil-0.9.13+dfsg/src/CMakeLists.txt --- sigil-0.9.12+dfsg/src/CMakeLists.txt 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/CMakeLists.txt 2019-03-20 01:01:44.000000000 +0100 @@ -585,7 +585,12 @@ set( ALL_SOURCES ${RAW_SOURCES} ${UI_FILES_H} ${QRC_FILES_CPP} ${QM_FILES} ) +# Location of the MathJax zip archive for all platforms +set( MATHJAX_ZIP "${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/ML.zip" ) + # Adding resource (RC) files for Windows +# Grab the current year so copyright notice is updated on Windows file properties +string( TIMESTAMP SIGIL_BUILD_YEAR "%Y" ) if ( WIN32 ) configure_file( Resource_files/windows/version.rc.in ${PROJECT_BINARY_DIR}/version.rc ) set( WINDOWS_RC_FILES @@ -606,7 +611,7 @@ if( CMAKE_GENERATOR STREQUAL Xcode ) exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources") exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills") - exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/polyfills/MathJax.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills") + exec_program("unzip ${MATHJAX_ZIP} -d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/Sigil.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/sgf.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/epub.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources") @@ -621,7 +626,7 @@ else() exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources") exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills") - exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/polyfills/MathJax.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills") + exec_program("unzip ${MATHJAX_ZIP} -d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/Sigil.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/sgf.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources") exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/epub.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources") @@ -812,7 +817,7 @@ # windeployqt add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND - windeployqt.exe --release --no-webkit2 --no-opengl-sw --no-translations --no-compiler-runtime --dir ${MAIN_PACKAGE_DIR} --libdir ${MAIN_PACKAGE_DIR} ${MAIN_PACKAGE_DIR}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) + windeployqt.exe --release --no-webkit2 --no-translations --no-compiler-runtime --dir ${MAIN_PACKAGE_DIR} --libdir ${MAIN_PACKAGE_DIR} ${MAIN_PACKAGE_DIR}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) set( LIBXML2 ${QT_INSTALL_BINS}/libxml2.dll ) if ( EXISTS ${LIBXML2} ) @@ -841,10 +846,10 @@ endif() endforeach( QM ) - # Copy the MathJax polyfill - set( MATHJAX_FILE ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax_win.js ) - add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MAIN_PACKAGE_DIR}/polyfills/ ) - add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND cmake -E copy ${MATHJAX_FILE} ${MAIN_PACKAGE_DIR}/polyfills/MathJax.js ) + # Extract the MathJax polyfill archive into the package directory + set( MATHJAX_UNZIP_DEST ${MAIN_PACKAGE_DIR}/polyfills ) + add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MATHJAX_UNZIP_DEST} ) + add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND cmake -E tar xzf ${MATHJAX_ZIP} WORKING_DIRECTORY ${MATHJAX_UNZIP_DEST} ) # Copy the dictionary files add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MAIN_PACKAGE_DIR}/hunspell_dictionaries/ ) @@ -958,12 +963,25 @@ set_property ( SOURCE sigil_constants.cpp PROPERTY COMPILE_DEFINITIONS - SIGIL_SHARE_ROOT="${SIGIL_SHARE_ROOT}" DICTS_ARE_BUNDLED=${INSTALL_BUNDLED_DICTS} EXTRA_DICT_DIRS="${EXTRA_DICT_DIRS}" + SIGIL_SHARE_ROOT="${SIGIL_SHARE_ROOT}" DICTS_ARE_BUNDLED=${INSTALL_BUNDLED_DICTS} + EXTRA_DICT_DIRS="${EXTRA_DICT_DIRS}" MATHJAX_DIR="${MATHJAX_DIR}" ) # Launch script for sigil set( LINUX_LAUNCH_INSTALL_SCRIPT_CONFIGURED ${CMAKE_BINARY_DIR}/sigil-sh_install_configured ) set( SIGIL_EXECUTABLE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) + + # Destination directory for unzipped MathJax archive + set( MATHJAX_UNZIP_DEST "${CMAKE_BINARY_DIR}/polyfills" ) + # Remove previous directories + if ( EXISTS ${MATHJAX_UNZIP_DEST} ) + file( REMOVE_RECURSE ${MATHJAX_UNZIP_DEST} ) + endif() + # Create the polyfills dir and extract the MathJax archive to it + if ( NOT DEFINED MATHJAX_DIR ) + file( MAKE_DIRECTORY ${MATHJAX_UNZIP_DEST} ) + execute_process( COMMAND cmake -E tar xvzf ${MATHJAX_ZIP} WORKING_DIRECTORY ${MATHJAX_UNZIP_DEST} ) + endif() # Configure Linux launch script configure_file( ${LINUX_LAUNCH_INSTALL_SCRIPT} ${LINUX_LAUNCH_INSTALL_SCRIPT_CONFIGURED} ) @@ -997,7 +1015,11 @@ if ( INSTALL_BUNDLED_DICTS ) install( FILES ${DIC_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/hunspell_dictionaries/ ) endif() - install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax.js DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/ ) + if ( MATHJAX_DIR ) + install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js DESTINATION ${MATHJAX_DIR}/config/local/ ) + else() + install( DIRECTORY ${MATHJAX_UNZIP_DEST}/MJ/ DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/MJ ) + endif() install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/plugin_launchers/python/ DESTINATION ${SIGIL_SHARE_ROOT}/plugin_launchers/python ) install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/python3lib/ DESTINATION ${SIGIL_SHARE_ROOT}/python3lib ) install( FILES ${EXAMPLE_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/examples/ ) diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ClipboardHistorySelector.cpp sigil-0.9.13+dfsg/src/Dialogs/ClipboardHistorySelector.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ClipboardHistorySelector.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ClipboardHistorySelector.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -65,8 +65,7 @@ void ClipboardHistorySelector::ApplicationActivated() { - // Turned on when Sigil is activated, put the latest text if any at the top of the history - ClipboardChanged(); + // Turned on when Sigil is activated connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(ClipboardChanged())); // If we are currently showing this dialog, refresh the display diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ClipEditor.cpp sigil-0.9.13+dfsg/src/Dialogs/ClipEditor.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ClipEditor.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ClipEditor.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -95,6 +96,8 @@ void ClipEditor::PasteIntoDocument() { + // GetSelectedEntries creates each clipEntry with new + // and so they will need to be deleted to prevent memory leaks emit PasteSelectedClipRequest(GetSelectedEntries()); } @@ -151,6 +154,10 @@ return count; } + +// Note this routine invokes ClipEditorModel GetEntries or GetEntry +// which creates the clipEntry structs using new so we will need +// to clean up after we are done to prevent memory leaks QList<ClipEditorModel::clipEntry *> ClipEditor::GetSelectedEntries() { QList<ClipEditorModel::clipEntry *> selected_entries; @@ -254,10 +261,15 @@ } while (m_SavedClipEntries.count()) { + // these were previously generated with new + ClipEditorModel::clipEntry * p = m_SavedClipEntries.at(0); + delete p; m_SavedClipEntries.removeAt(0); } + // we will need to clean up the entries below to prevent memory leaks QList<ClipEditorModel::clipEntry *> entries = GetSelectedEntries(); + if (!entries.count()) { return false; @@ -268,16 +280,22 @@ if (entry->is_group) { Utility::DisplayStdErrorDialog(tr("You cannot Copy or Cut groups - use drag-and-drop.")) ; + delete entry; return false; } + delete entry; } foreach(ClipEditorModel::clipEntry * entry, entries) { + // need to clean up m_SavedClipEntries when done to prevent memory leak ClipEditorModel::clipEntry *save_entry = new ClipEditorModel::clipEntry(); save_entry->name = entry->name; save_entry->is_group = entry->is_group; save_entry->text = entry->text; m_SavedClipEntries.append(save_entry); } + // to prevent memory leaks + qDeleteAll(entries); + entries.clear(); return true; } @@ -410,6 +428,7 @@ parent_path = m_ClipEditorModel->GetFullName(item->parent()); } + // Note GetEntry creates the clipEntry with new and it is just a struct foreach(QStandardItem * item, sub_items) { ClipEditorModel::clipEntry *entry = m_ClipEditorModel->GetEntry(item); // Remove the top level paths since we're exporting a subset @@ -443,6 +462,9 @@ m_LastFolderOpen = QFileInfo(filename).absolutePath(); WriteSettings(); } + // need to delete the entries to prevent a leak + qDeleteAll(entries); + entries.clear(); } void ClipEditor::CollapseAll() diff -Nru sigil-0.9.12+dfsg/src/Dialogs/Reports.cpp sigil-0.9.13+dfsg/src/Dialogs/Reports.cpp --- sigil-0.9.12+dfsg/src/Dialogs/Reports.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/Reports.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2011 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2017, 2018 Kevin B. Hendricks, Stratford, Ontario +** Copyright (C) 2017, 2018, 2019 Kevin B. Hendricks, Stratford, Ontario ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012, 2013 Dave Heiland ** @@ -52,6 +52,11 @@ connectSignalsSlots(); } +AllFilesWidget::~AllFilesWidget() +{ + delete m_ItemModel; +} + void AllFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -47,6 +48,7 @@ public: AllFilesWidget(); + ~AllFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -54,6 +55,11 @@ connectSignalsSlots(); } +CharactersInHTMLFilesWidget::~CharactersInHTMLFilesWidget() +{ + delete m_ItemModel; +} + void CharactersInHTMLFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -44,6 +45,7 @@ public: CharactersInHTMLFilesWidget(); + ~CharactersInHTMLFilesWidget(); void CreateReport(QSharedPointer<Book> m_Book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -51,6 +52,11 @@ connectSignalsSlots(); } +ClassesInHTMLFilesWidget::~ClassesInHTMLFilesWidget() +{ + delete m_ItemModel; +} + void ClassesInHTMLFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -44,6 +45,7 @@ public: ClassesInHTMLFilesWidget(); + ~ClassesInHTMLFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2018 Kevin B. Hendricks, Stratford, ON +** Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, ON ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** @@ -54,6 +54,11 @@ connectSignalsSlots(); } +CSSFilesWidget::~CSSFilesWidget() { + delete m_ItemModel; +} + + void CSSFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** @@ -46,6 +47,7 @@ public: CSSFilesWidget(); + ~CSSFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2018 Kevin B. Hendricks, Stratford, ON +** Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, ON ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -54,6 +54,11 @@ connectSignalsSlots(); } +HTMLFilesWidget::~HTMLFilesWidget() +{ + delete m_ItemModel; +} + void HTMLFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -47,6 +48,7 @@ public: HTMLFilesWidget(); + ~HTMLFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2018 Kevin Hendricks, Statford, ON +** Copyright (C) 2018, 2019 Kevin Hendricks, Statford, ON ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** @@ -57,6 +57,11 @@ ReadSettings(); } +ImageFilesWidget::~ImageFilesWidget() +{ + delete m_ItemModel; +} + void ImageFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** @@ -46,6 +47,7 @@ public: ImageFilesWidget(); + ~ImageFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2013 John Schember <j...@nachtimwald.com> ** Copyright (C) 2013 Dave Heiland ** @@ -50,6 +51,11 @@ connectSignalsSlots(); } +LinksWidget::~LinksWidget() +{ + delete m_ItemModel; +} + void LinksWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2013 John Schember <j...@nachtimwald.com> ** Copyright (C) 2013 Dave Heiland ** @@ -47,6 +48,7 @@ public: LinksWidget(); + ~LinksWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -52,6 +53,11 @@ connectSignalsSlots(); } +StylesInCSSFilesWidget::~StylesInCSSFilesWidget() +{ + delete m_ItemModel; +} + void StylesInCSSFilesWidget::CreateReport(QSharedPointer<Book> book) { m_Book = book; diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h --- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -47,6 +48,7 @@ public: StylesInCSSFilesWidget(); + ~StylesInCSSFilesWidget(); void CreateReport(QSharedPointer<Book> book); diff -Nru sigil-0.9.12+dfsg/src/Dialogs/SearchEditor.cpp sigil-0.9.13+dfsg/src/Dialogs/SearchEditor.cpp --- sigil-0.9.12+dfsg/src/Dialogs/SearchEditor.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Dialogs/SearchEditor.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -94,31 +95,37 @@ void SearchEditor::LoadFindReplace() { + // destination needs to delete each searchEntry when done emit LoadSelectedSearchRequest(GetSelectedEntry(false)); } void SearchEditor::Find() { + // destination needs to delete each searchEntry when done emit FindSelectedSearchRequest(GetSelectedEntries()); } void SearchEditor::ReplaceCurrent() { + // destination needs to delete each searchEntry when done emit ReplaceCurrentSelectedSearchRequest(GetSelectedEntries()); } void SearchEditor::Replace() { + // destination needs to delete each searchEntry when done emit ReplaceSelectedSearchRequest(GetSelectedEntries()); } void SearchEditor::CountAll() { + // destination needs to delete each searchEntry when done emit CountAllSelectedSearchRequest(GetSelectedEntries()); } void SearchEditor::ReplaceAll() { + // destination needs to delete each searchEntry when done emit ReplaceAllSelectedSearchRequest(GetSelectedEntries()); } @@ -183,6 +190,10 @@ SearchEditorModel::searchEntry *SearchEditor::GetSelectedEntry(bool show_warning) { + // Note: a SeachEditorModel::searchEntry is a simple struct that is created + // by new in SearchEditorModel GetEntry() and GetEntries() + // These must be manually deleted when done to prevent memory leaks + SearchEditorModel::searchEntry *entry = NULL; if (ui.SearchEditorTree->selectionModel()->hasSelection()) { @@ -210,6 +221,10 @@ QList<SearchEditorModel::searchEntry *> SearchEditor::GetSelectedEntries() { + // Note: a SeachEditorModel::searchEntry is a simple struct that is created + // by new in SearchEditorModel GetEntry() and GetEntries() + // These must be manually deleted when done to prevent memory leaks + QList<SearchEditorModel::searchEntry *> selected_entries; if (ui.SearchEditorTree->selectionModel()->hasSelection()) { diff -Nru sigil-0.9.12+dfsg/src/main.cpp sigil-0.9.13+dfsg/src/main.cpp --- sigil-0.9.12+dfsg/src/main.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/main.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.marko...@gmail.com> ** ** This file is part of Sigil. @@ -32,6 +33,7 @@ #include <QtWidgets/QMessageBox> #include <QXmlStreamReader> #include <QFileInfo> +#include <QDebug> #include "Misc/PluginDB.h" #include "Misc/UILanguage.h" @@ -65,14 +67,12 @@ // on command line arguments static MainWindow *GetMainWindow(const QStringList &arguments) { - // We use the first argument - // as the file to load after starting - if (arguments.size() > 1 && - Utility::IsFileReadable(arguments.at(1))) { - return new MainWindow(arguments.at(1)); - } else { - return new MainWindow(); + // We use the first argument as the file to load after starting + QString filepath; + if (arguments.size() > 1 && Utility::IsFileReadable(arguments.at(1))) { + filepath = arguments.at(1); } + return new MainWindow(filepath); } #ifdef Q_OS_MAC @@ -226,33 +226,46 @@ #ifndef QT_DEBUG qInstallMessageHandler(MessageHandler); #endif + + // Set application information for easier use of QSettings classes + QCoreApplication::setOrganizationName("sigil-ebook"); + QCoreApplication::setOrganizationDomain("sigil-ebook.com"); + QCoreApplication::setApplicationName("sigil"); + QCoreApplication::setApplicationVersion(SIGIL_VERSION); + + // many qtbugs related to mixing 32 and 64 bit qt apps when shader disk cache is used + QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache); + + +#if 0 // On recent processors with multiple cores this leads to over 40 threads at times + // We prevent Qt from constantly creating and deleting threads. + // Using a negative number forces the threads to stay around; + // that way, we always have a steady number of threads ready to do work. + QThreadPool::globalInstance()->setExpiryTimeout(-1); +#endif + MainApplication app(argc, argv); + // drag and drop in main tab bar is too touchy and that can cause problems. + // default drag distance limit is much too small especially for hpi displays + // startDragDistance default is just 10 pixels + if (app.startDragDistance() < 50) app.setStartDragDistance(50); + // Set up embedded python integration first thing EmbeddedPython* epython = EmbeddedPython::instance(); epython->addToPythonSysPath(epython->embeddedRoot()); epython->addToPythonSysPath(PluginDB::launcherRoot() + "/python"); try { - // We prevent Qt from constantly creating and deleting threads. - // Using a negative number forces the threads to stay around; - // that way, we always have a steady number of threads ready to do work. - QThreadPool::globalInstance()->setExpiryTimeout(-1); + // Specify the plugin folders // (language codecs and image loaders) app.addLibraryPath("codecs"); app.addLibraryPath("iconengines"); app.addLibraryPath("imageformats"); - // Set application information for - // easier use of QSettings classes - QCoreApplication::setOrganizationName("sigil-ebook"); - QCoreApplication::setOrganizationDomain("sigil-ebook.com"); - QCoreApplication::setApplicationName("sigil"); - QCoreApplication::setApplicationVersion(SIGIL_VERSION); QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf8")); SettingsStore settings; - // Setup the qtbase_ translator and load the translation for the selected language QTranslator qtbaseTranslator; const QString qm_name_qtbase = QString("qtbase_%1").arg(settings.uiLanguage()); @@ -321,26 +334,51 @@ } else { // Normal startup #ifdef Q_OS_MAC + // Work around QTBUG-62193 and QTBUG-65245 and others where menubar + // menu items are lost under File and Sigil menus and where + // Quit menu gets lost when deleting other windows first + + // Now we Create and show a frameless translucent QMainWindow to hold + // the menubar. Note: macOS has a single menubar attached at + // the top of the screen that all mainwindows share. + app.setQuitOnLastWindowClosed(false); + Qt::WindowFlags flags = Qt::Window | Qt::FramelessWindowHint; + QMainWindow * basemw = new QMainWindow(NULL, flags); + basemw->setAttribute(Qt::WA_TranslucentBackground, true); + QMenuBar *mac_menu = new QMenuBar(0); QMenu *file_menu = new QMenu("File"); - QAction *action; - // New - action = file_menu->addAction("New"); - action->setShortcut(QKeySequence("Ctrl+N")); - QObject::connect(action, &QAction::triggered, file_new); + + // New + QAction * new_action = new QAction("New"); + new_action->setShortcut(QKeySequence("Ctrl+N")); + QObject::connect(new_action, &QAction::triggered, file_new); + file_menu ->addAction(new_action); + // Open - action = file_menu->addAction("Open"); - action->setShortcut(QKeySequence("Ctrl+O")); - QObject::connect(action, &QAction::triggered, file_open); - // Quit - action = file_menu->addAction("Quit"); - action->setShortcut(QKeySequence("Ctrl+Q")); - QObject::connect(action, &QAction::triggered, qApp->quit); + QAction* open_action = new QAction("Open"); + open_action->setShortcut(QKeySequence("Ctrl+O")); + QObject::connect(open_action, &QAction::triggered, file_open); + file_menu ->addAction(open_action); + + // Quit - force add of a secondary quit menu to the file menu + QAction* quit_action = new QAction("Quit"); + quit_action->setMenuRole(QAction::NoRole); + quit_action->setShortcut(QKeySequence("Ctrl+Q")); + QObject::connect(quit_action, &QAction::triggered, qApp->quit); + file_menu ->addAction(quit_action); mac_menu->addMenu(file_menu); - mac_menu->show(); + + // Application specific quit menu + // according to Qt docs this is the right way to add an application + // quit menu - but it does not work and will still sometimes get lost + mac_menu->addAction("quit"); + + basemw->setMenuBar(mac_menu); + basemw->show(); #endif VerifyPlugins(); MainWindow *widget = GetMainWindow(arguments); diff -Nru sigil-0.9.12+dfsg/src/MainUI/FindReplace.cpp sigil-0.9.13+dfsg/src/MainUI/FindReplace.cpp --- sigil-0.9.12+dfsg/src/MainUI/FindReplace.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MainUI/FindReplace.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2011, 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.marko...@gmail.com> @@ -1170,6 +1171,10 @@ message = QString("%1: %2 ").arg(tr("Loaded")).arg(search_entry->name.replace('<', "<").replace('>', ">").left(50)); } + // prevent memory leak in FindSearch, ReplaceCurrentSearch, ReplaceSearch, + // CountAllSearch, and ReplaceAllSearch + delete search_entry; + ShowMessage(message); } diff -Nru sigil-0.9.12+dfsg/src/MainUI/FindReplace.h sigil-0.9.13+dfsg/src/MainUI/FindReplace.h --- sigil-0.9.12+dfsg/src/MainUI/FindReplace.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MainUI/FindReplace.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2011, 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.marko...@gmail.com> diff -Nru sigil-0.9.12+dfsg/src/MainUI/MainWindow.cpp sigil-0.9.13+dfsg/src/MainUI/MainWindow.cpp --- sigil-0.9.12+dfsg/src/MainUI/MainWindow.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MainUI/MainWindow.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2016 Kevin B. Hendricks, Stratford, Ontario Canada +** Copyright (C) 2016, 2017, 2018, 2019 Kevin B. Hendricks, Stratford, Ontario Canada ** Copyright (C) 2012-2015 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012-2013 Dave Heiland ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.marko...@gmail.com> @@ -222,6 +222,31 @@ m_ViewImage->close(); m_ViewImage = NULL; } + +#ifdef Q_OS_MAC + if (m_ClipboardHistorySelector) delete m_ClipboardHistorySelector; + if (m_LinkOrStyleBookmark) delete m_LinkOrStyleBookmark; + if (m_Reports) delete m_Reports; + if (m_ViewImage) delete m_ViewImage; + if (m_SelectCharacter) delete m_SelectCharacter; + if (m_SpellcheckEditor) delete m_SpellcheckEditor; + if (m_IndexEditor) delete m_IndexEditor; + if (m_ClipEditor) delete m_ClipEditor; + if (m_SearchEditor) delete m_SearchEditor; + if (m_pluginMapper) delete m_pluginMapper; + if (m_casingChangeMapper) delete m_casingChangeMapper; + if (m_headingMapper) delete m_headingMapper; + if (m_lbZoomLabel) delete m_lbZoomLabel; + if (m_slZoomSlider) delete m_slZoomSlider; + if (m_ValidationResultsView) delete m_ValidationResultsView; + if (m_TableOfContents) delete m_TableOfContents; + if (m_FindReplace) delete m_FindReplace; + if (m_Clips) delete m_Clips; + if (m_BookBrowser) delete m_BookBrowser; + if (m_TabManager) delete m_TabManager; + if (m_PreviewWindow) delete m_PreviewWindow; +#endif + } @@ -1084,15 +1109,15 @@ void MainWindow::clearMemoryCaches() { - // See https://bugreports.qt-project.org/browse/QTBUG-4350 - // QWebSettinbgs::clearMemoryCaches(); + // See https://bugreports.qt-project.org/browse/QTBUG-43504 + // QWebSettings::clearMemoryCaches(); // replace the above with a similar sequence // that does not invalidate the fontCache // toggle memory caches to disable and then re-enable QWebSettings::setObjectCacheCapacities(0,0,0); - QWebSettings::setObjectCacheCapacities(0, 0, 100 * 1024 * 1024); + QWebSettings::setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024); // do the same to flush the page cache int numpages = QWebSettings::maximumPagesInCache(); @@ -1228,7 +1253,7 @@ m_BookBrowser->Refresh(); m_Book->SetModified(); - clearMemoryCaches(); + MainWindow::clearMemoryCaches(); OpenResourceAndWaitUntilLoaded(html_cover_resource); // Reload the tab to ensure it reflects updated image. FlowTab *flow_tab = GetCurrentFlowTab(); @@ -1749,7 +1774,7 @@ QStringList filenames = m_BookBrowser->AddExisting(true); connect(m_BookBrowser, SIGNAL(ResourcesAdded()), this, SLOT(ResourcesAddedOrDeleted())); // Since we disconnected the signal we will have missed forced clearing of cache - clearMemoryCaches(); + MainWindow::clearMemoryCaches(); QStringList internal_filenames; foreach(QString filename, filenames) { QString internal_filename = filename.right(filename.length() - filename.lastIndexOf("/") - 1); @@ -2042,10 +2067,17 @@ PasteClipIntoCurrentTarget(20); } +// How to deal with this as each clipEntry struct created with new and passed via +// emit signal to here? Where and show should their memory be freed. +// Perhaps we need to make clipEntry a QObject instead of just a struct or use +// smart pointers void MainWindow::PasteClipEntriesIntoCurrentTarget(const QList<ClipEditorModel::clipEntry *> &clips) { if (m_LastPasteTarget == NULL) { ShowMessageOnStatusBar(tr("Select the destination to paste into first.")); + foreach(ClipEditorModel::clipEntry * entry, clips) { + if (entry) delete entry; + } return; } @@ -2055,6 +2087,11 @@ // Clear the statusbar afterwards but only if entries were pasted. ShowMessageOnStatusBar(); } + + foreach(ClipEditorModel::clipEntry * entry, clips) { + if (entry) delete entry; + } + } void MainWindow::PasteClipEntriesIntoPreviousTarget(const QList<ClipEditorModel::clipEntry *> &clips) @@ -3317,6 +3354,8 @@ html_resource = qobject_cast<HTMLResource *>(tab->GetLoadedResource()); + // handle any memory cache clearing inside BookViewPreview + // handles all cases of non-html resource in front tab if (!html_resource) { // note: must handle case of m_PreviousHTMLResource being deleted by user @@ -3644,6 +3683,9 @@ web_settings->setFontFamily(QWebSettings::StandardFont, bookViewAppearance.font_family_standard); web_settings->setFontFamily(QWebSettings::SerifFont, bookViewAppearance.font_family_serif); web_settings->setFontFamily(QWebSettings::SansSerifFont, bookViewAppearance.font_family_sans_serif); + web_settings->setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024); + web_settings->setMaximumPagesInCache(2); + // Check for existing custom Preview/Book View stylesheet in Prefs dir and load it if present QFileInfo CustomPreviewStylesheetInfo(QDir(Utility::DefinePrefsDir()).filePath(CUSTOM_PREVIEW_STYLE_FILENAME)); if (CustomPreviewStylesheetInfo.exists() && CustomPreviewStylesheetInfo.isFile() && CustomPreviewStylesheetInfo.isReadable()) { @@ -3730,7 +3772,7 @@ void MainWindow::ResourcesAddedOrDeleted() { - clearMemoryCaches(); + MainWindow::clearMemoryCaches(); // Make sure currently visible tab is updated immediately FlowTab *flow_tab = GetCurrentFlowTab(); @@ -4521,6 +4563,8 @@ void MainWindow::UpdateClipButton(int clip_number, QAction *ui_action) { + // clipEntry is a simple struct created by GetEntry with new, + // no reference counting or smart pointers so they must be cleaned up appropriately ClipEditorModel::clipEntry *clip_entry = ClipEditorModel::instance()->GetEntryFromNumber(clip_number); if (clip_entry) { @@ -4529,6 +4573,8 @@ clip_text.replace('&', "&").replace('<', "<").replace('>', ">"); ui_action->setToolTip(clip_text); ui_action->setVisible(true); + // prevent memory leak + delete clip_entry; } else { ui_action->setText(""); ui_action->setToolTip(""); diff -Nru sigil-0.9.12+dfsg/src/MainUI/MainWindow.h sigil-0.9.13+dfsg/src/MainUI/MainWindow.h --- sigil-0.9.12+dfsg/src/MainUI/MainWindow.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MainUI/MainWindow.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2016-2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012-2015 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.marko...@gmail.com> diff -Nru sigil-0.9.12+dfsg/src/MainUI/PreviewWindow.cpp sigil-0.9.13+dfsg/src/MainUI/PreviewWindow.cpp --- sigil-0.9.12+dfsg/src/MainUI/PreviewWindow.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MainUI/PreviewWindow.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin Hendricks, Doug Massay ** Copyright (C) 2012 Dave Heiland, John Schember ** ** This file is part of Sigil. @@ -206,24 +207,31 @@ // On Mac OS X QCoreApplication::applicationDirPath() points to Sigil.app/Contents/MacOS/ QDir execdir(QCoreApplication::applicationDirPath()); execdir.cdUp(); - mathjaxurl = execdir.absolutePath() + "/polyfills/MathJax.js"; + mathjaxurl = execdir.absolutePath() + "/polyfills/MJ/MathJax.js"; #elif defined(Q_OS_WIN32) - mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MathJax.js"; + mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MJ/MathJax.js"; #else // all flavours of linux / unix - // user supplied environment variable to 'share/sigil' directory will overrides everything - if (!sigil_extra_root.isEmpty()) { - mathjaxurl = sigil_extra_root + "/polyfills/MathJax.js"; + // First check if system MathJax was configured to be used at compile time + if (!mathjax_dir.isEmpty()) { + mathjaxurl = mathjax_dir + "/MathJax.js"; } else { - mathjaxurl = sigil_share_root + "/polyfills/MathJax.js"; + // otherwise user supplied environment variable to 'share/sigil' + // takes precedence over Sigil's usual share location. + if (!sigil_extra_root.isEmpty()) { + mathjaxurl = sigil_extra_root + "/polyfills/MJ/MathJax.js"; + } else { + mathjaxurl = sigil_share_root + "/polyfills/MJ/MathJax.js"; + } } #endif mathjaxurl = "file://" + Utility::URLEncodePath(mathjaxurl); + mathjaxurl = mathjaxurl + "?config=local/SIGIL_EBOOK_MML_SVG"; int endheadpos = text.indexOf("</head>"); if (endheadpos > 1) { QString inject_mathjax = - "<script type=\"text/javascript\" " + "<script type=\"text/javascript\" async=\"async\" " "src=\"" + mathjaxurl + "\"></script>"; text.insert(endheadpos, inject_mathjax); } diff -Nru sigil-0.9.12+dfsg/src/Misc/CSSInfo.cpp sigil-0.9.13+dfsg/src/Misc/CSSInfo.cpp --- sigil-0.9.12+dfsg/src/Misc/CSSInfo.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Misc/CSSInfo.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2016 Kevin B. Hendricks, Stratford, ON Canada +** Copyright (C) 2016, 2017, 2018, 2019 Kevin B. Hendricks, Stratford, ON Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -32,6 +32,11 @@ const QString LINE_MARKER("[SIGIL_NEWLINE]"); static const QString DELIMITERS = "}{;"; + +// Note: CSSProperties and CSSSelectors are simple struct that this code +// created with new and so need to be manually cleaned up to prevent +// large memory leaks + CSSInfo::CSSInfo(const QString &text, bool isCSSFile) : m_OriginalText(text), m_IsCSSFile(isCSSFile) @@ -52,6 +57,15 @@ } } +// Need to manually clean up the Selector List +CSSInfo::~CSSInfo() +{ + foreach(CSSSelector * sp, m_CSSSelectors) { + if (sp) delete sp; + } +} + + QList<CSSInfo::CSSSelector *> CSSInfo::getClassSelectors(const QString filterClassName) { QList<CSSInfo::CSSSelector *> selectors; @@ -156,6 +170,7 @@ if (property.isEmpty() || p->name == property) { property_values.append(p->value); } + delete p; } } @@ -233,6 +248,10 @@ QList<CSSInfo::CSSProperty *> new_properties = getCSSProperties(m_OriginalText, cssSelector->openingBracePos + 1, cssSelector->closingBracePos); const QString &new_properties_text = formatCSSProperties(new_properties, multipleLineFormat, selector_indent); new_text.replace(cssSelector->openingBracePos + 1, cssSelector->closingBracePos - cssSelector->openingBracePos - 1, new_properties_text); + // clear up new_properties as they were created with new + foreach(CSSInfo::CSSProperty* p, new_properties) { + if (p) delete p; + } // Reformat the selector text itself - whitespace only since incomplete parsing. // Will ensure the braces are placed on the same line as the selector name, // comma separated groups are spaced apart and double spaces are removed. @@ -444,7 +463,8 @@ { QRegularExpression strip_attributes_regex("\\[[^\\]]*\\]"); QRegularExpression strip_ids_regex("#[^\\s\\.]+"); - QRegularExpression strip_non_name_chars_regex("[^A-Za-z0-9_\\-\\.:]+"); + // QRegularExpression strip_non_name_chars_regex("[^A-Za-z0-9_\\-\\.:]+"); + QRegularExpression strip_non_name_chars_regex("[^\\w_\\-\\.:]+", QRegularExpression::UseUnicodePropertiesOption); QString search_text = replaceBlockComments(text); // CSS selectors can be in a myriad of formats... the class based selectors could be: // .c1 / e1.c1 / e1.c1.c2 / e1[class~=c1] / e1#id1.c1 / e1.c1#id1 / .c1, .c2 / ... diff -Nru sigil-0.9.12+dfsg/src/Misc/CSSInfo.h sigil-0.9.13+dfsg/src/Misc/CSSInfo.h --- sigil-0.9.12+dfsg/src/Misc/CSSInfo.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Misc/CSSInfo.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, ON, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -41,6 +42,8 @@ */ CSSInfo(const QString &text, bool isCSSFile = true); + ~CSSInfo(); + struct CSSSelector { QString originalText; /* The original text of the complete selector */ bool isGroup; /* Whether selector was declared in a comma separated group */ diff -Nru sigil-0.9.12+dfsg/src/Misc/EmbeddedPythonPkg.cpp sigil-0.9.13+dfsg/src/Misc/EmbeddedPythonPkg.cpp --- sigil-0.9.12+dfsg/src/Misc/EmbeddedPythonPkg.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Misc/EmbeddedPythonPkg.cpp 1970-01-01 01:00:00.000000000 +0100 @@ -1,617 +0,0 @@ -/************************************************************************ -** -** Copyright (C) 2015 Kevin Hendricks -** Copyright (C) 2015 John Schember <j...@nachtimwald.com> -** -** This file is part of Sigil. -** -** Sigil is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** Sigil is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with Sigil. If not, see <http://www.gnu.org/licenses/>. -** -*************************************************************************/ - -#include "Misc/EmbeddedPython.h" -#include <QString> -#include <QByteArray> -#include <QList> -#include <QStringList> -#include <QVariant> -#include <QMetaType> -#include <QStandardPaths> -#include <QDir> -#include "Misc/Utility.h" -#include "sigil_constants.h" - -/** - * Possibly Useful QMetaTypes::Type types - * - * QMetaType::Bool 1 bool - * QMetaType::Int 2 int - * QMetaType::UInt 3 unsigned int - * QMetaType::Double 6 double - * QMetaType::QChar 7 QChar - * QMetaType::QString 10 QString - * QMetaType::QByteArray 12 QByteArray - * QMetaType::Long 32 long - * QMetaType::LongLong 4 LongLong - * QMetaType::Short 33 short - * QMetaType::Char 34 char - * QMetaType::ULong 35 unsigned long - * QMetaType::ULongLong 5 ULongLong - * QMetaType::UShort 36 unsigned short - * QMetaType::SChar 40 signed char - * QMetaType::UChar 37 unsigned char - * QMetaType::Float 38 float - * QMetaType::QVariant 41 QVariant - * QMetaType::QVariantList 9 QVariantList - * QMetaType::QStringList 11 QStringList - * QMetaType::QVariantMap 8 QVariantMap - * QMetaType::QVariantHash 28 QVariantHash - * QMetaType::User 1024 Base value for User registered Type - * QMetaType::UnknownType 0 This is an invalid type id. It is returned from QMetaType for types that are not registered - */ - - -/** - * // example of how to run a python function inside a specific module - * - * void EmbeddedPython::multiply_pushed(int val1, int val2) - * { - * int rv = 0; - * QString error_traceback; - * QList<QVariant> args; - * args.append(QVariant(val1)); - * args.append(QVariant(val2)); - * QVariant res = runInPython(QString("multiply"), - * QString("multiply"), - * args, - * &rv, - * error_traceback); - * if (rv == 0) { - * // no errors - * } else { - * // error occured - * } - * } - * - * // Where multiply.py is: - * - * #!/usr/bin/env python3 - * - * def multiply(a,b): - * print("Will compute", a, "times", b) - * c = a * b - * return c - */ - -/** - * // example of how to use the callPyObjMethod - * - * // First invoke module function to get the Python object - * - * PyObjectPtr MyClass::get_object() - * { - * int rv = 0; - * QString traceback; - * QString v1 = QString("Hello"); - * QList<QVariant> args; - * args.append(QVariant(v1)); - * - * QVariant res = m_epp->runInPython( QString("multiply"), - * QString("get_object"), - * args, - * &rv, - * traceback, - * true); - * if (rv == 0) { - * return PyObjectPtr(res); - * } else { - * return PyObjectPtr(); - * } - * } - * - * // Now invoke its "get_len" method - * - * QString MyClass:use_object(PyObjectPtr v) - * { - * int rv = 0; - * QString traceback; - * QList<QVariant> args; - * QVariant res = m_epp->callPyObjMethod(v, - * QString("get_len"), - * args, - * &rv, - * traceback); - * if (rv == 0) { - * return res.toString(); - * } else { - * return QString("Error: ") + QString::number(rv); - * } - * } - * - * - * # With the following python code inside of multiply.py - * - * class TestMe: - * def __init__(self, storeme): - * self.storeme = storeme - * self.mylen = len(self.storeme) - * - * def get_me(self): - * return self.storeme - * - * def get_len(self): - * return self.mylen - * - * def get_object(v1): - * tme = TestMe(v1) - * return tme - */ - -QMutex EmbeddedPython::m_mutex; - -EmbeddedPython* EmbeddedPython::m_instance = 0; -int EmbeddedPython::m_pyobjmetaid = 0; -PyThreadState * EmbeddedPython::m_threadstate = NULL; - -EmbeddedPython* EmbeddedPython::instance() -{ - if (m_instance == 0) { - m_instance = new EmbeddedPython(); - } - return m_instance; -} - -EmbeddedPython::EmbeddedPython() -{ - // Build string list of paths that will - // comprise the embedded Python's sys.path. -#if defined(__APPLE__) - // On Mac OS X QCoreApplication::applicationDirPath() points to - // whereever Sigil.app/Contents/MacOS/ is located - // but the python3 dir is in Contents - QDir execdir(QCoreApplication::applicationDirPath()); - execdir.cdUp(); - QString pyhomepath = execdir.absolutePath(); -#else - QString pyhomepath = QCoreApplication::applicationDirPath(); -#endif - wchar_t *hpath = new wchar_t[pyhomepath.size()+1]; - pyhomepath.toWCharArray(hpath); - hpath[pyhomepath.size()]=L'\0'; - - QString pysyspath = pyhomepath + PYTHON_MAIN_PATH; - foreach (const QString &src_path, PYTHON_SYS_PATHS) { - pysyspath = pysyspath + PATH_LIST_DELIM + pyhomepath + PYTHON_MAIN_PATH + src_path; - } - wchar_t *mpath = new wchar_t[pysyspath.size()+1]; - pysyspath.toWCharArray(mpath); - mpath[pysyspath.size()]=L'\0'; - delete[] hpath; - - Py_OptimizeFlag = 2; - Py_NoSiteFlag = 1; - Py_DontWriteBytecodeFlag = 1; - Py_IgnoreEnvironmentFlag = 1; - Py_NoUserSiteDirectory = 1; - /*Py_DebugFlag = 0; - Py_VerboseFlag = 0; - Py_SetProgramName(progname); - delete[] progname; - Py_SetPythonHome(hpath); - delete[] hpath;*/ - - // Set before Py_Initialize to ensure isolation from system python - Py_SetPath(mpath); - delete[] mpath; - - Py_Initialize(); - PyEval_InitThreads(); - m_threadstate = PyEval_SaveThread(); - m_pyobjmetaid = qMetaTypeId<PyObjectPtr>(); -} - - -EmbeddedPython::~EmbeddedPython() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } - m_pyobjmetaid = 0; - PyEval_RestoreThread(m_threadstate); - Py_Finalize(); -} - -QString EmbeddedPython::embeddedRoot() -{ - QString embedded_root; - QStringList embedded_roots; - QDir d; - -#ifdef Q_OS_MAC - embedded_roots.append(QCoreApplication::applicationDirPath() + "/../python3lib/"); -#elif defined(Q_OS_WIN32) - embedded_roots.append(QCoreApplication::applicationDirPath() + "/python3lib/"); -#elif !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) - // all flavours of linux / unix - if (!sigil_extra_root.isEmpty()) { - embedded_roots.append(sigil_extra_root + "/python3lib/"); - } else { - embedded_roots.append(sigil_share_root + "/python3lib/"); - } -#endif - - Q_FOREACH (QString s, embedded_roots) { - if (d.exists(s)) { - embedded_root = s; - break; - } - } - - QDir base(embedded_root); - return base.absolutePath(); -} - -bool EmbeddedPython::addToPythonSysPath(const QString &mpath) -{ - EmbeddedPython::m_mutex.lock(); - PyGILState_STATE gstate = PyGILState_Ensure(); - - PyObject* sysPath = NULL; - PyObject* aPath = NULL; - bool success = false; - - // PySys_GetObject borrows a reference */ - sysPath = PySys_GetObject((char*)"path"); - if (sysPath != NULL) { - aPath = PyUnicode_FromString(mpath.toUtf8().constData()); - if (aPath != NULL) { - PyList_Append(sysPath, aPath); - success = true; - } - } - Py_XDECREF(aPath); - PyGILState_Release(gstate); - EmbeddedPython::m_mutex.unlock(); - return success; -} - -// run interpreter without initiating/locking/unlocking GIL -// in a single thread at a time -QVariant EmbeddedPython::runInPython(const QString &mname, - const QString &fname, - const QVariantList &args, - int *rv, - QString &tb, - bool ret_python_object) -{ - EmbeddedPython::m_mutex.lock(); - PyGILState_STATE gstate = PyGILState_Ensure(); - - QVariant res = QVariant(QString()); - PyObject *moduleName = NULL; - PyObject *module = NULL; - PyObject *func = NULL; - PyObject *pyargs = NULL; - PyObject *pyres = NULL; - int idx = 0; - - moduleName = PyUnicode_FromString(mname.toUtf8().constData()); - if (moduleName == NULL) { - *rv = -1; - goto cleanup; - } - - module = PyImport_Import(moduleName); - if (module == NULL) { - *rv = -2; - goto cleanup; - } - - func = PyObject_GetAttrString(module,fname.toUtf8().constData()); - if (func == NULL) { - *rv = -3; - goto cleanup; - } - - if (!PyCallable_Check(func)) { - *rv = -4; - goto cleanup; - } - - // Build up Python argument List from args - pyargs = PyTuple_New(args.size()); - idx = 0; - foreach(QVariant arg, args) { - PyTuple_SetItem(pyargs, idx, QVariantToPyObject(arg)); - idx++; - } - - pyres = PyObject_CallObject(func, pyargs); - if (pyres == NULL) { - *rv = -5; - goto cleanup; - } - - *rv = 0; - - res = PyObjectToQVariant(pyres, ret_python_object); - -cleanup: - if (PyErr_Occurred() != NULL) { - tb = getPythonErrorTraceback(); - } - Py_XDECREF(pyres); - Py_XDECREF(pyargs); - Py_XDECREF(func); - Py_XDECREF(module); - Py_XDECREF(moduleName); - - PyGILState_Release(gstate); - EmbeddedPython::m_mutex.unlock(); - return res; -} - - -// given an existing python object instance, invoke one of its methods -// grabs mutex to prevent need for Python GIL -QVariant EmbeddedPython::callPyObjMethod(PyObjectPtr &pyobj, - const QString &methname, - const QVariantList &args, - int *rv, - QString &tb, - bool ret_python_object) -{ - EmbeddedPython::m_mutex.lock(); - PyGILState_STATE gstate = PyGILState_Ensure(); - - QVariant res = QVariant(QString()); - PyObject* obj = pyobj.object(); - PyObject* func = NULL; - PyObject* pyargs = NULL; - PyObject* pyres = NULL; - int idx = 0; - - func = PyObject_GetAttrString(obj,methname.toUtf8().constData()); - if (func == NULL) { - *rv = -1; - goto cleanup; - } - - if (!PyCallable_Check(func)) { - *rv = -2; - goto cleanup; - } - - // Build up Python argument List from args - pyargs = PyTuple_New(args.size()); - idx = 0; - foreach(QVariant arg, args) { - PyTuple_SetItem(pyargs, idx, QVariantToPyObject(arg)); - idx++; - } - - pyres = PyObject_CallObject(func, pyargs); - if (pyres == NULL) { - *rv = -3; - goto cleanup; - } - - *rv = 0; - - res = PyObjectToQVariant(pyres, ret_python_object); - - cleanup: - if (PyErr_Occurred() != NULL) { - tb = getPythonErrorTraceback(); - } - Py_XDECREF(pyres); - Py_XDECREF(pyargs); - Py_XDECREF(func); - - PyGILState_Release(gstate); - EmbeddedPython::m_mutex.unlock(); - return res; -} - - -// *** below here all routines are private and only invoked -// *** from runInPython and callPyObjMethod with lock held - - -// Convert PyObject types to their QVariant equivalents -// call recursively to allow populating QVariant lists and lists of lists -QVariant EmbeddedPython::PyObjectToQVariant(PyObject *po, bool ret_python_object) -{ - QVariant res = QVariant(QString()); - - if ((po) == NULL) - return res; - - if (PyLong_Check(po)) { - res = QVariant(PyLong_AsLongLong(po)); - - } else if (PyFloat_Check(po)) { - res = QVariant(PyFloat_AsDouble(po)); - - } else if (PyBytes_Check(po)) { - res = QVariant(QByteArray(PyBytes_AsString(po))); - - } else if (PyUnicode_Check(po)) { - - int kind = PyUnicode_KIND(po); - - if (PyUnicode_READY(po) != 0) - return res; - - if (kind == PyUnicode_1BYTE_KIND) { - // latin 1 according to PEP 393 - res = QVariant(QString::fromLatin1(reinterpret_cast<const char *>PyUnicode_1BYTE_DATA(po), -1)); - - } else if (kind == PyUnicode_2BYTE_KIND) { - res = QVariant(QString::fromUtf16(PyUnicode_2BYTE_DATA(po), -1)); - - } else if (kind == PyUnicode_4BYTE_KIND) { - // PyUnicode_4BYTE_KIND - res = QVariant(QString::fromUcs4(PyUnicode_4BYTE_DATA(po), -1)); - - } else { - // convert to utf8 since not a known - res = QVariant(QString::fromUtf8(PyUnicode_AsUTF8(po),-1)); - } - - } else if (PyTuple_Check(po)) { - QVariantList vlist; - int n = PyTuple_Size(po); - for (int i=0; i< n; i++) { - vlist.append(PyObjectToQVariant(PyTuple_GetItem(po,i))); - } - res = QVariant(vlist); - - } else if (PyList_Check(po)) { - QVariantList vlist; - int n = PyList_Size(po); - for (int i=0; i< n; i++) { - vlist.append(PyObjectToQVariant(PyList_GetItem(po,i))); - } - res = QVariant(vlist); - - } else if (ret_python_object) { - QVariant var; - var.setValue(PyObjectPtr(po)); - res = var; - } else { - // do nothing here to return null value - } - return res; -} - -// Convert QVariant to a Python Equivalent Type -// call recursively to allow populating tuples/lists and lists of lists -PyObject* EmbeddedPython::QVariantToPyObject(const QVariant &v) -{ - PyObject* value = NULL; - bool ok; - switch ((QMetaType::Type)v.type()) { - case QMetaType::Double: - value = Py_BuildValue("d", v.toDouble(&ok)); - break; - case QMetaType::Float: - value = Py_BuildValue("f", v.toFloat(&ok)); - break; - case QMetaType::Int: - value = Py_BuildValue("i", v.toInt(&ok)); - break; - case QMetaType::UInt: - value = Py_BuildValue("I", v.toUInt(&ok)); - break; - case QMetaType::LongLong: - value = Py_BuildValue("L", v.toLongLong(&ok)); - break; - case QMetaType::ULongLong: - value = Py_BuildValue("K", v.toULongLong(&ok)); - break; - case QMetaType::QString: - value = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, v.toString().utf16(), v.toString().size()); - // value = Py_BuildValue("s", v.toString().toUtf8().constData()); - break; - case QMetaType::QByteArray: - value = Py_BuildValue("y", v.toByteArray().constData()); - break; - case QMetaType::QStringList: - { - QStringList vlist = v.toStringList(); - value = PyList_New(vlist.size()); - int pos = 0; - foreach(QString av, vlist) { - PyObject* strval = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, av.utf16(), av.size()); - PyList_SetItem(value, pos, strval); - pos++; - } - } - break; - case QMetaType::QVariantList: - { - QVariantList vlist = v.toList(); - value = PyList_New(vlist.size()); - int pos = 0; - foreach(QVariant av, vlist) { - PyList_SetItem(value, pos, QVariantToPyObject(av)); - pos++; - } - } - break; - default: - { - if ((QMetaType::Type)v.type() >= QMetaType::User && (v.userType() == m_pyobjmetaid)) - { - - PyObjectPtr op = v.value<PyObjectPtr>(); - value = op.object(); - // Need to increment object count otherwise will go away when Py_XDECREF used on pyargs - Py_XINCREF(value); - - } else { - - // Ensure we don't have any holes. - value = Py_BuildValue("u", ""); - } - } - break; - } - return value; -} - - -// get traceback from inside interpreter upon error -QString EmbeddedPython::getPythonErrorTraceback(bool useMsgBox) -{ - PyObject *etype = NULL; - PyObject *evalue = NULL; - PyObject *etraceback = NULL; - PyObject *mod = NULL; - PyObject *elist = NULL; - QStringList tblist; - - PyErr_Fetch(&etype, &evalue, &etraceback); - PyErr_NormalizeException(&etype, &evalue, &etraceback); - - mod = PyImport_ImportModule("traceback"); - - if (mod) { - elist = PyObject_CallMethod(mod, "format_exception", "OOO", etype, evalue, etraceback); - if (elist != NULL) { - tblist = PyObjectToQVariant(elist).toStringList(); - } else { - tblist.append(QString("Error: traceback report is missing")); - } - } else { - tblist.append(QString("Error: traceback module failed to load")); - } - - Py_XDECREF(elist); - Py_XDECREF(mod); - Py_XDECREF(etraceback); - Py_XDECREF(evalue); - Py_XDECREF(etype); - - PyErr_Clear(); - - QString tb = tblist.join(QString("\n")); - if (useMsgBox) { - QString message = QString(tr("Embedded Python Error")); - Utility::DisplayStdErrorDialog(message, tb); - } - return tb; -} diff -Nru sigil-0.9.12+dfsg/src/Misc/FilenameDelegate.cpp sigil-0.9.13+dfsg/src/Misc/FilenameDelegate.cpp --- sigil-0.9.12+dfsg/src/Misc/FilenameDelegate.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Misc/FilenameDelegate.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -20,7 +20,9 @@ *************************************************************************/ #include <QtCore/QEvent> +#include <QKeyEvent> #include <QtWidgets/QLineEdit> +#include <QApplication> #include "Misc/FilenameDelegate.h" @@ -41,6 +43,17 @@ } edit->setSelection(0, pos); + + // Due to bug introduced into Qt sometime after version 5.6 + // the cursor is made not visibile whenever a qlinedit + // has a selection when first focused/selected. + // No mouse click will cause the cursor to appear, only a key release event + // for some insane reason. So create a fake shift key press/release event that + // will not change the cursor position but will make the cursor visible after a + // mouse event deselects things. + QApplication::postEvent(edit, new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier)); + QApplication::postEvent(edit, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier)); + QApplication::processEvents(); event->accept(); return true; } diff -Nru sigil-0.9.12+dfsg/src/Misc/SettingsStore.cpp sigil-0.9.13+dfsg/src/Misc/SettingsStore.cpp --- sigil-0.9.12+dfsg/src/Misc/SettingsStore.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Misc/SettingsStore.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2016, 2017, 2018 Kevin B. Hendricks, Stratford, ON +** Copyright (C) 2019 - 2016 Kevin B. Hendricks, Stratford, ON ** Copyright (C) 2011, 2012, 2013 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012, 2013 Dave Heiland ** @@ -100,14 +100,16 @@ SettingsStore::SettingsStore() : QSettings(Utility::DefinePrefsDir() + "/sigil.ini", QSettings::IniFormat) -{ - setIniCodec("UTF-8"); +{ + // See QTBUG-40796 and QTBUG-54510 as using UTF-8 as a codec for ini files is very broken + // setIniCodec("UTF-8"); } SettingsStore::SettingsStore(QString filename) : QSettings(filename, QSettings::IniFormat) { - setIniCodec("UTF-8"); + // See QTBUG-40796 and QTBUG-54510 as using UTF-8 as a codec for ini files is very broken + // setIniCodec("UTF-8"); } QString SettingsStore::uiLanguage() diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.cpp --- sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2018 Kevin B. Hendricks, Stratford, Ontario +** Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, Ontario ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -263,6 +263,7 @@ return item->data(FULLNAME_ROLE).toString(); } +// potential memory leak here too from GetEntry ClipEditorModel::clipEntry *ClipEditorModel::GetEntryFromNumber(int clip_number) { return GetEntry(GetItemFromNumber(clip_number)); @@ -345,32 +346,29 @@ void ClipEditorModel::LoadData(const QString &filename, QStandardItem *item) { - SettingsStore *settings; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } + SettingsStore ss(settings_path); - int size = settings->beginReadArray(SETTINGS_GROUP); + int size = ss.beginReadArray(SETTINGS_GROUP); // Add one entry at a time to the list for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); + ss.setArrayIndex(i); ClipEditorModel::clipEntry *entry = new ClipEditorModel::clipEntry(); - QString fullname = settings->value(ENTRY_NAME).toString(); + QString fullname = ss.value(ENTRY_NAME).toString(); fullname.replace(QRegularExpression("\\s*/+\\s*"), "/"); fullname.replace(QRegularExpression("^/"), ""); entry->is_group = fullname.endsWith("/"); // Name is set to fullname only while looping through parent groups when adding entry->name = fullname; entry->fullname = fullname; - entry->text = settings->value(ENTRY_TEXT).toString(); + entry->text = ss.value(ENTRY_TEXT).toString(); AddFullNameEntry(entry, item); + delete entry; } - - settings->endArray(); + ss.endArray(); } void ClipEditorModel::AddFullNameEntry(ClipEditorModel::clipEntry *entry, QStandardItem *parent_item, int row) @@ -414,6 +412,8 @@ new_entry->is_group = true; new_entry->name = group_name; parent_item = AddEntryToModel(new_entry, new_entry->is_group, parent_item, parent_item->rowCount()); + // fix memory leak + delete new_entry; } } row = parent_item->rowCount(); @@ -652,56 +652,71 @@ QString ClipEditorModel::SaveData(QList<ClipEditorModel::clipEntry *> entries, const QString &filename) { QString message = ""; + bool clean_up_needed = false; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; // Save everything if no entries selected if (entries.isEmpty()) { QList<QStandardItem *> items = GetNonParentItems(invisibleRootItem()); if (!items.isEmpty()) { + // GetEntries calls GetEntry which creates each entry with new entries = GetEntries(items); + clean_up_needed = true; } } // Stop watching the file while we save it - if (m_FSWatcher->files().contains(m_SettingsPath)) { - m_FSWatcher->removePath(m_SettingsPath); + if (m_FSWatcher->files().contains(settings_path)) { + m_FSWatcher->removePath(settings_path); } // Open the default file for save, or specific file for export - SettingsStore *settings; + { + SettingsStore ss(settings_path); - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } + if (!ss.isWritable()) { + message = tr("Unable to create file %1").arg(filename); + // Watch the file again + m_FSWatcher->addPath(settings_path); + + // delete each entry if we created them above + if (clean_up_needed) { + foreach(ClipEditorModel::clipEntry* entry, entries) { + delete entry; + } + } + return message; + } - settings->sync(); + // Remove the old values to account for deletions + ss.remove(SETTINGS_GROUP); + ss.beginWriteArray(SETTINGS_GROUP); + int i = 0; + foreach(ClipEditorModel::clipEntry * entry, entries) { + ss.setArrayIndex(i++); + ss.setValue(ENTRY_NAME, entry->fullname); - if (!settings->isWritable()) { - message = tr("Unable to create file %1").arg(filename); - // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); - return message; + if (!entry->is_group) { + ss.setValue(ENTRY_TEXT, entry->text); + } + } + // delete each entry if we created them above + if (clean_up_needed) { + foreach(ClipEditorModel::clipEntry* entry, entries) { + delete entry; + } + } + ss.endArray(); + + // Make sure file is created/updated so it can be checked + ss.sync(); } - // Remove the old values to account for deletions - settings->remove(SETTINGS_GROUP); - settings->beginWriteArray(SETTINGS_GROUP); - int i = 0; - foreach(ClipEditorModel::clipEntry * entry, entries) { - settings->setArrayIndex(i++); - settings->setValue(ENTRY_NAME, entry->fullname); - if (!entry->is_group) { - settings->setValue(ENTRY_TEXT, entry->text); - } - } - settings->endArray(); - // Make sure file is created/updated so it can be checked - settings->sync(); // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); + m_FSWatcher->addPath(settings_path); SetDataModified(false); return message; } diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.h sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.h --- sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.h 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/IndexEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/IndexEditorModel.cpp --- sigil-0.9.12+dfsg/src/MiscEditors/IndexEditorModel.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MiscEditors/IndexEditorModel.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** @@ -189,34 +190,33 @@ entry->pattern = line; } AddFullNameEntry(entry, item); + delete entry; } return; } // Read standard ini files - SettingsStore *settings; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } + SettingsStore ss(settings_path); - int size = settings->beginReadArray(SETTINGS_GROUP); + int size = ss.beginReadArray(SETTINGS_GROUP); // Add one entry at a time to the list for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); + ss.setArrayIndex(i); IndexEditorModel::indexEntry *entry = new IndexEditorModel::indexEntry(); - entry->pattern = settings->value(ENTRY_PATTERN).toString(); - entry->index_entry = settings->value(ENTRY_INDEX_ENTRY).toString(); + entry->pattern = ss.value(ENTRY_PATTERN).toString(); + entry->index_entry = ss.value(ENTRY_INDEX_ENTRY).toString(); if (!entry->pattern.isEmpty() || !entry->index_entry.isEmpty()) { AddFullNameEntry(entry, item); } + delete entry; } - settings->endArray(); + ss.endArray(); } QStandardItem *IndexEditorModel::AddFullNameEntry(IndexEditorModel::indexEntry *entry, QStandardItem *parent_item, int row) @@ -239,6 +239,8 @@ QStandardItem *IndexEditorModel::AddEntryToModel(IndexEditorModel::indexEntry *entry, QStandardItem *parent_item, int row) { + bool clean_up = false; + // parent_item must be a group item if (!parent_item) { parent_item = invisibleRootItem(); @@ -249,6 +251,7 @@ entry = new IndexEditorModel::indexEntry(); entry->pattern = ""; entry->index_entry = ""; + clean_up = true; } QList<QStandardItem *> rowItems; @@ -266,6 +269,8 @@ } SetDataModified(true); + if (clean_up) delete entry; + return new_item; } @@ -312,59 +317,75 @@ QString IndexEditorModel::SaveData(QList<IndexEditorModel::indexEntry *> entries, const QString &filename) { QString message = ""; + bool clean_up_needed = false; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; // Save everything if no entries selected if (entries.isEmpty()) { QList<QStandardItem *> items = GetItems(); if (!items.isEmpty()) { + // GetEntries calls GetEntry which creates each entry with new entries = GetEntries(items); + clean_up_needed = true; } } // Stop watching the file while we save it - if (m_FSWatcher->files().contains(m_SettingsPath)) { - m_FSWatcher->removePath(m_SettingsPath); + if (m_FSWatcher->files().contains(settings_path)) { + m_FSWatcher->removePath(settings_path); } // Open the default file for save, or specific file for export - SettingsStore *settings; + { + SettingsStore ss(settings_path); - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } + // ss.sync(); - settings->sync(); + if (!ss.isWritable()) { + message = tr("Unable to create file %1").arg(filename); + // Watch the file again + m_FSWatcher->addPath(settings_path); + + // delete each entry if we created them above + if (clean_up_needed) { + foreach(IndexEditorModel::indexEntry* entry, entries) { + delete entry; + } + } + return message; + } - if (!settings->isWritable()) { - message = tr("Unable to create file %1").arg(filename); - // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); - return message; - } + // Remove the old values to account for deletions + ss.remove(SETTINGS_GROUP); + ss.beginWriteArray(SETTINGS_GROUP); + int i = 0; + foreach(IndexEditorModel::indexEntry * entry, entries) { + if (entry->pattern.isEmpty() && entry->index_entry.isEmpty()) { + continue; + } - // Remove the old values to account for deletions - settings->remove(SETTINGS_GROUP); - settings->beginWriteArray(SETTINGS_GROUP); - int i = 0; - foreach(IndexEditorModel::indexEntry * entry, entries) { - if (entry->pattern.isEmpty() && entry->index_entry.isEmpty()) { - continue; + foreach(QString pattern, entry->pattern.split("\n")) { + ss.setArrayIndex(i++); + ss.setValue(ENTRY_PATTERN, pattern); + ss.setValue(ENTRY_INDEX_ENTRY, entry->index_entry); + } } - foreach(QString pattern, entry->pattern.split("\n")) { - settings->setArrayIndex(i++); - settings->setValue(ENTRY_PATTERN, pattern); - settings->setValue(ENTRY_INDEX_ENTRY, entry->index_entry); + // delete each entry if we created them above + if (clean_up_needed) { + foreach(IndexEditorModel::indexEntry* entry, entries) { + delete entry; + } } + ss.endArray(); + // Make sure file is created/updated so it can be checked + ss.sync(); } - settings->endArray(); - // Make sure file is created/updated so it can be checked - settings->sync(); + // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); + m_FSWatcher->addPath(settings_path); SetDataModified(false); return message; } diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/SearchEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/SearchEditorModel.cpp --- sigil-0.9.12+dfsg/src/MiscEditors/SearchEditorModel.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/MiscEditors/SearchEditorModel.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2018 Kevin B. Hendricks, Stratford, Ontario, Canada +** Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, Ontario, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2012 Grant Drake @@ -293,33 +293,31 @@ void SearchEditorModel::LoadData(const QString &filename, QStandardItem *item) { - SettingsStore *settings; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } + SettingsStore ss(settings_path); - int size = settings->beginReadArray(SETTINGS_GROUP); + int size = ss.beginReadArray(SETTINGS_GROUP); // Add one entry at a time to the list for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); + ss.setArrayIndex(i); SearchEditorModel::searchEntry *entry = new SearchEditorModel::searchEntry(); - QString fullname = settings->value(ENTRY_NAME).toString(); + QString fullname = ss.value(ENTRY_NAME).toString(); fullname.replace(QRegularExpression("\\s*/+\\s*"), "/"); fullname.replace(QRegularExpression("^/"), ""); entry->is_group = fullname.endsWith("/"); // Name is set to fullname only while looping through parent groups when adding entry->name = fullname; entry->fullname = fullname; - entry->find = settings->value(ENTRY_FIND).toString(); - entry->replace = settings->value(ENTRY_REPLACE).toString(); + entry->find = ss.value(ENTRY_FIND).toString(); + entry->replace = ss.value(ENTRY_REPLACE).toString(); AddFullNameEntry(entry, item); + // done with the temporary entry so remove it + delete entry; } - - settings->endArray(); + ss.endArray(); } void SearchEditorModel::AddFullNameEntry(SearchEditorModel::searchEntry *entry, QStandardItem *parent_item, int row) @@ -363,6 +361,7 @@ new_entry->is_group = true; new_entry->name = group_name; parent_item = AddEntryToModel(new_entry, new_entry->is_group, parent_item, parent_item->rowCount()); + delete new_entry; } } row = parent_item->rowCount(); @@ -575,57 +574,74 @@ QString SearchEditorModel::SaveData(QList<SearchEditorModel::searchEntry *> entries, const QString &filename) { QString message = ""; + bool clean_up_needed = false; + QString settings_path = filename; + if (settings_path.isEmpty()) settings_path = m_SettingsPath; // Save everything if no entries selected if (entries.isEmpty()) { QList<QStandardItem *> items = GetNonParentItems(invisibleRootItem()); if (!items.isEmpty()) { + // GetEntries calls GetEntry which creates each entry with new entries = GetEntries(items); + clean_up_needed = true; } } // Stop watching the file while we save it - if (m_FSWatcher->files().contains(m_SettingsPath)) { - m_FSWatcher->removePath(m_SettingsPath); + if (m_FSWatcher->files().contains(settings_path)) { + m_FSWatcher->removePath(settings_path); } // Open the default file for save, or specific file for export - SettingsStore *settings; + { + SettingsStore ss(settings_path); - if (filename.isEmpty()) { - settings = new SettingsStore(m_SettingsPath); - } else { - settings = new SettingsStore(filename); - } - - settings->sync(); + // ss.sync(); - if (!settings->isWritable()) { - message = tr("Unable to create file %1").arg(filename); - // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); - return message; - } + if (!ss.isWritable()) { + message = tr("Unable to create file %1").arg(filename); + // Watch the file again + m_FSWatcher->addPath(settings_path); + // delete each entry if we created them above + if (clean_up_needed) { + foreach(SearchEditorModel::searchEntry* entry, entries) { + delete entry; + } + } + return message; + } + + // Remove the old values to account for deletions + ss.remove(SETTINGS_GROUP); + ss.beginWriteArray(SETTINGS_GROUP); + int i = 0; + foreach(SearchEditorModel::searchEntry * entry, entries) { + ss.setArrayIndex(i++); + ss.setValue(ENTRY_NAME, entry->fullname); + + if (!entry->is_group) { + ss.setValue(ENTRY_FIND, entry->find); + ss.setValue(ENTRY_REPLACE, entry->replace); + } + } + + // delete each entry if we created them above + if (clean_up_needed) { + foreach(SearchEditorModel::searchEntry* entry, entries) { + delete entry; + } + } - // Remove the old values to account for deletions - settings->remove(SETTINGS_GROUP); - settings->beginWriteArray(SETTINGS_GROUP); - int i = 0; - foreach(SearchEditorModel::searchEntry * entry, entries) { - settings->setArrayIndex(i++); - settings->setValue(ENTRY_NAME, entry->fullname); + ss.endArray(); - if (!entry->is_group) { - settings->setValue(ENTRY_FIND, entry->find); - settings->setValue(ENTRY_REPLACE, entry->replace); - } + // Make sure file is created/updated so it can be checked + ss.sync(); } - settings->endArray(); - // Make sure file is created/updated so it can be checked - settings->sync(); + // Watch the file again - m_FSWatcher->addPath(m_SettingsPath); + m_FSWatcher->addPath(settings_path); SetDataModified(false); return message; } diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py sigil-0.9.13+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py --- sigil-0.9.12+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py 2019-03-20 01:01:44.000000000 +0100 @@ -35,7 +35,7 @@ from unipath import pathof import unicodedata -_launcher_version=20190218 +_launcher_version=20190309 _PKG_VER = re.compile(r'''<\s*package[^>]*version\s*=\s*["']([^'"]*)['"][^>]*>''',re.IGNORECASE) diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js sigil-0.9.13+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js --- sigil-0.9.12+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js 1970-01-01 01:00:00.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js 2019-03-20 01:01:44.000000000 +0100 @@ -0,0 +1,23 @@ +/************************************************************* + * + * Modified Version of MathJax/unpacked/config/MML_SVG.js + * Specifically for Sigil-EBook's PreviewWindow + * + * Copyright (c) 2010-2018 The MathJax Consortium + * + * Part of the MathJax library. + * See http://www.mathjax.org for details. + * + * Licensed under the Apache License, Version 2.0; + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +MathJax.Hub.Config({ + extensions: ["mml2jax.js","MathML/mml3.js","MathEvents.js","fast-preview.js","AssistiveMML.js"], + jax: ["input/MathML","output/SVG","output/PreviewHTML"], + messageStyle: "none" +}); + +MathJax.Ajax.loadComplete("[MathJax]/config/local/SIGIL_EBOOK_MML_SVG.js"); diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/windows/version.rc.in sigil-0.9.13+dfsg/src/Resource_Files/windows/version.rc.in --- sigil-0.9.12+dfsg/src/Resource_Files/windows/version.rc.in 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Resource_Files/windows/version.rc.in 2019-03-20 01:01:44.000000000 +0100 @@ -14,7 +14,7 @@ VALUE "FileDescription", "Sigil is a multi-platform EPUB ebook editor" VALUE "FileVersion", "${SIGIL_FULL_VERSION}.0" VALUE "InternalName", "Sigil" - VALUE "LegalCopyright", "Copyright (c) 2010-2014 Sigil Authors" + VALUE "LegalCopyright", "Copyright (c) 2010-${SIGIL_BUILD_YEAR} Sigil Authors" VALUE "LegalTrademarks1", "All Rights Reserved" VALUE "LegalTrademarks2", "All Rights Reserved" VALUE "OriginalFilename", "Sigil.exe" diff -Nru sigil-0.9.12+dfsg/src/sigil_constants.cpp sigil-0.9.13+dfsg/src/sigil_constants.cpp --- sigil-0.9.12+dfsg/src/sigil_constants.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/sigil_constants.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -33,6 +33,7 @@ const QString sigil_share_root = QString(SIGIL_SHARE_ROOT); const bool dicts_are_bundled = DICTS_ARE_BUNDLED; const QString extra_dict_dirs = QString(EXTRA_DICT_DIRS); +const QString mathjax_dir = QString(MATHJAX_DIR); const QString PYTHON_MAIN_PATH = "/python3/lib/python3.5"; #if __x86_64__ || __ppc64__ const QStringList PYTHON_SYS_PATHS = QStringList () << "/plat-x86_64-linux-gnu" << "/plat-linux" << "/lib-dynload" << "/site-packages"; diff -Nru sigil-0.9.12+dfsg/src/sigil_constants.h sigil-0.9.13+dfsg/src/sigil_constants.h --- sigil-0.9.12+dfsg/src/sigil_constants.h 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/sigil_constants.h 2019-03-20 01:01:44.000000000 +0100 @@ -131,6 +131,7 @@ extern const QString sigil_share_root; extern const bool dicts_are_bundled; extern const QString extra_dict_dirs; +extern const QString mathjax_dir; #endif #endif // SG_CONSTANTS_H diff -Nru sigil-0.9.12+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp sigil-0.9.13+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp --- sigil-0.9.12+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -50,7 +50,7 @@ // Now parse the text once looking for keys and replacing them where needed QRegularExpression reference( - "(?:(?:src|background|background-image|list-style|list-style-image|border-image|border-image-source|content)\\s*:|@import)\\s*" + "(?:(?:src|background|background-image|list-style|list-style-image|border-image|border-image-source|content|(?:-webkit-)?shape-outside)\\s*:|@import)\\s*" "(" "[^;\\}]*" ")" diff -Nru sigil-0.9.12+dfsg/src/Tabs/TabManager.cpp sigil-0.9.13+dfsg/src/Tabs/TabManager.cpp --- sigil-0.9.12+dfsg/src/Tabs/TabManager.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/Tabs/TabManager.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -53,8 +53,18 @@ connect(this, SIGNAL(currentChanged(int)), this, SLOT(EmitTabChanged())); connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(CloseTab(int))); setDocumentMode(true); - setMovable(true); + // QTabBar has a bug when a user "presses and flicks" on a non current tab it will cause it + // to setCurrentIndex() but during EmitTabChanged() it then may allows the resulting mouseMoveEvent + // be processed on the same index that is being set in setCurrentIndex which causes a crash. + // This bug makes it dangerous to enable dragging and dropping to move tabs in the QTabBar + // So default to non-movable but let a environment variable override this decision + if (qEnvironmentVariableIsSet("SIGIL_ALLOW_TAB_MOVEMENT")) { + setMovable(true); + } else { + setMovable(false); + } setTabsClosable(true); + // setElideMode(Qt::ElideRight); this is the default after qt-5.6 setUsesScrollButtons(true); } @@ -536,14 +546,29 @@ if (new_tab == NULL) { return false; } - + int idx = -1; if (!precede_current_tab) { - addTab(new_tab, new_tab->GetIcon(), new_tab->GetFilename()); + +#ifdef Q_OS_MAC + // drop use of icons to workaround Qt Bugs: QTBUG-61235, QTBUG-61742, QTBUG-63445, QTBUG-64630 + idx = addTab(new_tab, new_tab->GetFilename()); +#else + idx = addTab(new_tab, new_tab->GetIcon(), new_tab->GetFilename()); +#endif + setCurrentWidget(new_tab); new_tab->setFocus(); } else { - insertTab(currentIndex(), new_tab, new_tab->GetIcon(), new_tab->GetFilename()); + +#ifdef Q_OS_MAC + // drop use of icons to workaround Qt Bugs: QTBUG-61235, QTBUG-61742, QTBUG-63445, QTBUG-64630 + idx = insertTab(currentIndex(), new_tab, new_tab->GetFilename()); +#else + idx = insertTab(currentIndex(), new_tab, new_tab->GetIcon(), new_tab->GetFilename()); +#endif + } + setTabToolTip(idx, new_tab->GetFilename()); connect(new_tab, SIGNAL(DeleteMe(ContentTab *)), this, SLOT(DeleteTab(ContentTab *))); connect(new_tab, SIGNAL(TabRenamed(ContentTab *)), this, SLOT(UpdateTabName(ContentTab *))); diff -Nru sigil-0.9.12+dfsg/src/ViewEditors/BookViewPreview.cpp sigil-0.9.13+dfsg/src/ViewEditors/BookViewPreview.cpp --- sigil-0.9.12+dfsg/src/ViewEditors/BookViewPreview.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/ViewEditors/BookViewPreview.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,6 +1,6 @@ /************************************************************************ ** -** Copyright (C) 2015 Kevin B. Hendricks Stratford, ON, Canada +** Copyright (C) 2019, 2018, 2017, 2016, 2015 Kevin B. Hendricks Stratford, ON, Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** ** This file is part of Sigil. @@ -73,7 +73,7 @@ // Enable our link filter. page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); - page()->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + // page()->settings()->setAttribute(QWebSettings::PluginsEnabled, false); // Allow epubs to access remote resources via the net page()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, (settings.remoteOn() == 1)); // Enable local-storage for epub3 @@ -152,6 +152,19 @@ // If this is not the very first load of this document, store the caret location if (!url().isEmpty()) { StoreCurrentCaretLocation(); + // to help keep memory footprint small clear any memory caches when a new page loads + if (url().path() != path) { + settings()->clearMemoryCaches(); +#if 0 + // An attempt to flush caches but not the font caches + // These need to be kept in sync with MainWindow::clearMemoryCaches() + // settings()->setObjectCacheCapacities(0,0,0); + // settings()->setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024); + // int n = settings()->maximumPagesInCache(); + // settings()->setMaximumPagesInCache(0); + // settings()->setMaximumPagesInCache(n); +#endif + } } m_isLoadFinished = false; diff -Nru sigil-0.9.12+dfsg/src/ViewEditors/CodeViewEditor.cpp sigil-0.9.13+dfsg/src/ViewEditors/CodeViewEditor.cpp --- sigil-0.9.12+dfsg/src/ViewEditors/CodeViewEditor.cpp 2019-02-18 22:53:28.000000000 +0100 +++ sigil-0.9.13+dfsg/src/ViewEditors/CodeViewEditor.cpp 2019-03-20 01:01:44.000000000 +0100 @@ -1,5 +1,6 @@ /************************************************************************ ** +** Copyright (C) 2019 Doug Massay ** Copyright (C) 2015 Kevin B. Hendricks Stratford, ON Canada ** Copyright (C) 2012 John Schember <j...@nachtimwald.com> ** Copyright (C) 2012, 2013 Dave Heiland @@ -2103,6 +2104,11 @@ { if (m_DelayedCursorScreenCenteringRequired) { centerCursor(); +#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) + // The Code View viewport stopped updating on Linux somewhere + // around Qt5.12.0 in this delayed call to center the cursor. + viewport()->update(); +#endif m_DelayedCursorScreenCenteringRequired = false; } } @@ -3193,6 +3199,9 @@ } else { property_values.append(QString("%1: %2").arg(css_property->name).arg(css_property->value)); } + // CSSInfo.getCSSProperties creates each CSSProperty pointer with new + // and it must be cleaned by caller to prevent memory leak + if (css_property) delete css_property; } style_attribute_value = QString("%1;").arg(property_values.join("; ")); }
signature.asc
Description: PGP signature