diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b541df..504ec8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,120 +1,120 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.11.42") project(KPimTextEdit VERSION ${PIM_VERSION}) # ECM setup set(KF5_MIN_VERSION "5.58.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) if (POLICY CMP0053) cmake_policy(SET CMP0053 NEW) endif() include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMAddTests) include(ECMQtDeclareLoggingCategory) set(KPIMTEXTEDIT_LIB_VERSION ${PIM_VERSION}) ecm_setup_version(PROJECT VARIABLE_PREFIX KPIMTEXTEDIT VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpimtextedit_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfigVersion.cmake" SOVERSION 5 ) set(QT_REQUIRED_VERSION "5.10.0") find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Widgets) find_package(Grantlee5 "5.1" CONFIG REQUIRED) set_package_properties(Grantlee5 PROPERTIES DESCRIPTION "A plug-in based String Template system for Qt" - URL "http://github.com/steveire/grantlee" + URL "https://github.com/steveire/grantlee" PURPOSE "Required for the RichText composer" TYPE REQUIRED ) find_package(KF5DesignerPlugin ${KF5_MIN_VERSION} CONFIG) set_package_properties(KF5DesignerPlugin PROPERTIES DESCRIPTION "KF5 designer plugin" TYPE OPTIONAL) ########### Find packages ########### find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5CoreAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Emoticons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Sonnet ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5SyntaxHighlighting ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5DesignerPlugin ${KF5_MIN_VERSION} CONFIG) set_package_properties(KF5DesignerPlugin PROPERTIES DESCRIPTION "KF5 designer plugin" TYPE OPTIONAL) add_definitions(-DTRANSLATION_DOMAIN=\"libkpimtextedit\") add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_definitions(-DQT_NO_FOREACH) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS TextToSpeech) if(BUILD_TESTING) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Test) add_definitions(-DBUILD_TESTING) endif() ########### Targets ########### add_subdirectory(src) if(BUILD_TESTING) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) add_subdirectory(autotests) add_subdirectory(tests) endif() ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5PimTextEdit") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5PimTextEditConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5PimTextEditTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5PimTextEditTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kpimtextedit_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) install( FILES kpimtextedit.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/grantleebuilder/markupdirector.cpp b/src/grantleebuilder/markupdirector.cpp index fae6bb6..a801c3a 100644 --- a/src/grantleebuilder/markupdirector.cpp +++ b/src/grantleebuilder/markupdirector.cpp @@ -1,198 +1,198 @@ /* Copyright (c) 2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "markupdirector.h" #include using namespace KPIMTextEdit; MarkupDirector::MarkupDirector(Grantlee::AbstractMarkupBuilder *builder) : Grantlee::MarkupDirector(builder) { } MarkupDirector::~MarkupDirector() { } QTextFrame::iterator MarkupDirector::processBlockContents(QTextFrame::iterator frameIt, const QTextBlock &block) { //Same code as grantlee but interprete margin auto blockFormat = block.blockFormat(); auto blockAlignment = blockFormat.alignment(); // TODO: decide when to use

etc. if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { m_builder->insertHorizontalRule(); if (!frameIt.atEnd()) return ++frameIt; return frameIt; } auto it = block.begin(); // The beginning is the end. This is an empty block. Insert a newline and // move // on. if (it.atEnd()) { m_builder->addNewline(); if (!frameIt.atEnd()) return ++frameIt; return frameIt; } // Don't have p tags inside li tags. if (!block.textList()) { //Laurent : we need this margin as it's necessary to show blockquote // Don't instruct builders to use margins. The rich text widget doesn't // have // an action for them yet, // So users can't edit them. See bug - // http://bugs.kde.org/show_bug.cgi?id=160600 + // https://bugs.kde.org/show_bug.cgi?id=160600 m_builder->beginParagraph( blockAlignment, blockFormat.topMargin(), blockFormat.bottomMargin(), blockFormat.leftMargin(), blockFormat.rightMargin() ); } while (!it.atEnd()) { it = processFragment(it, it.fragment(), block.document()); } // Don't have p tags inside li tags. if (!block.textList()) { m_builder->endParagraph(); } if (!frameIt.atEnd()) return ++frameIt; return frameIt; } QTextBlock::iterator MarkupDirector::processFragment(QTextBlock::iterator it, const QTextFragment &fragment, QTextDocument const *doc) { //Same code as Grantlee + a fix ! // Q_D( MarkupDirector ); auto charFormat = fragment.charFormat(); if (charFormat.objectType() >= QTextFormat::UserObject) { processCustomFragment(fragment, doc); if (!it.atEnd()) return ++it; return it; } auto textObject = doc->objectForFormat(charFormat); if (textObject) return processCharTextObject(it, fragment, textObject); if (fragment.text().at(0).category() == QChar::Separator_Line) { m_builder->addNewline(); if (!it.atEnd()) return ++it; return it; } // The order of closing and opening tags can determine whether generated // html // is valid or not. // When processing a document with formatting which appears as // 'Some // formatted text', // the correct generated output will contain 'Some // formatted text'. // However, processing text which appears as 'Some formatted // text' might be incorrectly rendered // as 'Some formatted text' if tags which start at // the same fragment are // opened out of order. Here, tags are not nested properly, and the html // would // not be valid or render correctly by unforgiving parsers (like QTextEdit). // One solution is to make the order of opening tags dynamic. In the above // case, the em tag would // be opened before the strong tag 'Some formatted // text'. That would // require knowledge of which tag is going to close first. That might be // possible by examining // the 'next' QTextFragment while processing one. // // The other option is to do pessimistic closing of tags. // In the above case, this means that if a fragment has two or more formats // applied (bold and italic here), // and one of them is closed, then all tags should be closed first. They // will // of course be reopened // if necessary while processing the next fragment. // The above case would be rendered as 'Some // formatted text'. // // The first option is taken here, as the redundant opening and closing tags // in the second option // didn't appeal. // See testDoubleStartDifferentFinish, // testDoubleStartDifferentFinishReverseOrder processOpeningElements(it); // If a sequence such as '

' is imported into a document with // setHtml, LineSeparator // characters are inserted. Here I make sure to put them back. auto sl = fragment.text().split(QChar(QChar::LineSeparator)); QStringListIterator i(sl); auto paraClosed = false; while (i.hasNext()) { m_builder->appendLiteralText(i.next()); if (i.hasNext()) { if (i.peekNext().isEmpty()) { if (!paraClosed) { m_builder->endParagraph(); paraClosed = true; } m_builder->addNewline(); } else if (paraClosed) { m_builder->beginParagraph(/* blockAlignment */); paraClosed = false; } else { //Bug fixing : missing end line here m_builder->addNewline(); } } } if (!it.atEnd()) ++it; processClosingElements(it); return it; }