Your message dated Tue, 02 Apr 2019 18:12:00 +0000 with message-id <e4de057a-9400-4e95-102c-7dff2611d16d@thykier.net> and subject line Re: Bug#925219: unblock: sigil/0.9.13-1 has caused the Debian Bug report #925219, regarding unblock: sigil/0.9.13-1 to be marked as done. This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact owner@bugs.debian.org immediately.) -- 925219: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925219 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
--- Begin Message ---
- To: submit@bugs.debian.org
- Subject: unblock: sigil/0.9.13-1
- From: Mattia Rizzolo <mattia@debian.org>
- Date: Thu, 21 Mar 2019 13:16:11 +0100
- Message-id: <20190321121609.GB15362@mapreri.org>
Package: release.debian.org User: release.debian.org@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 <mattia@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.markovic@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 <mitya57@debian.org> for helping out with the MathJax - configuration. -Author: Mattia Rizzolo <mattia@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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.markovic@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 <john@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.markovic@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 <john@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.markovic@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 <john@nachtimwald.com> ** Copyright (C) 2012-2013 Dave Heiland ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.markovic@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 <john@nachtimwald.com> ** Copyright (C) 2012 Dave Heiland ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.markovic@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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 <john@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("; ")); }Attachment: signature.asc
Description: PGP signature
--- End Message ---
--- Begin Message ---
- To: Mattia Rizzolo <mattia@debian.org>, 925219-done@bugs.debian.org
- Subject: Re: Bug#925219: unblock: sigil/0.9.13-1
- From: Niels Thykier <niels@thykier.net>
- Date: Tue, 02 Apr 2019 18:12:00 +0000
- Message-id: <e4de057a-9400-4e95-102c-7dff2611d16d@thykier.net>
- In-reply-to: <20190321121609.GB15362@mapreri.org>
- References: <20190321121609.GB15362@mapreri.org>
Mattia Rizzolo: > Package: release.debian.org > User: release.debian.org@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. > Unblocked, thanks. ~Niels
--- End Message ---