Use qlitehtml from separate repository

qlitehtml moved into its own playground repository,
get it from there instead of carrying our copy around.

Change-Id: I0e267344e5ccf95f579e4fb239e6789d177d7b78
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Eike Ziller
2021-01-14 14:04:54 +01:00
parent b865fa5571
commit a0500f5b9a
18 changed files with 45 additions and 2892 deletions

6
.gitmodules vendored
View File

@ -6,9 +6,9 @@
path = src/tools/perfparser
url = ../perfparser.git
ignore = dirty
[submodule "litehtml"]
path = src/plugins/help/qlitehtml/litehtml
url = https://github.com/litehtml/litehtml.git
[submodule "googletest"]
path = tests/unit/unittest/3rdparty/googletest
url = https://github.com/google/googletest.git
[submodule "src/libs/qlitehtml"]
path = src/libs/qlitehtml
url = https://code.qt.io/playground/qlitehtml.git

View File

@ -18,3 +18,31 @@ add_subdirectory(clangsupport)
add_subdirectory(tracing)
add_subdirectory(qtcreatorcdbext)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qlitehtml/src/CMakeLists.txt)
option(BUILD_LIBRARY_QLITEHTML "Build library qlitehtml." ${BUILD_LIBRARIES_BY_DEFAULT})
set(QLITEHTML_VERSION_COMPAT ${IDE_VERSION_COMPAT} CACHE STRING "")
if(BUILD_LIBRARY_QLITEHTML)
set(QLITEHTML_BIN_PATH ${IDE_BIN_PATH})
set(QLITEHTML_LIBRARY_PATH ${IDE_LIBRARY_PATH})
set(QLITEHTML_EXPORT QtCreator)
set(QLITEHTML_DEVEL_COMPONENT Devel)
set(QLITEHTML_DEVEL_EXCLUDE_FROM_ALL ON)
set(QLITEHTML_HEADER_PATH "include/src/lib/qlitehtml")
add_subdirectory(qlitehtml/src)
endif()
if(TARGET qlitehtml)
target_compile_definitions(qlitehtml PRIVATE ${DEFAULT_DEFINES}) # for precompiled headers
enable_pch(qlitehtml)
#doesn't work: TARGET 'qlitehtml' was not created in this directory.
#qtc_enable_separate_debug_info(qlitehtml "${IDE_LIBRARY_PATH}")
qtc_output_binary_dir(_output_binary_dir)
set_target_properties(qlitehtml PROPERTIES
BUILD_RPATH "${_LIB_RPATH}"
INSTALL_RPATH "${_LIB_RPATH}"
RUNTIME_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_BIN_PATH}"
LIBRARY_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_PATH}"
ARCHIVE_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_PATH}"
)
endif()
endif()

View File

@ -1,7 +1,10 @@
import qbs
import qbs.File
Project {
name: "Libs"
property string qlitehtmlQbs: path + "/qlitehtml/src/qlitehtml.qbs"
property stringList qlitehtml: File.exists(qlitehtmlQbs) ? [qlitehtmlQbs] : []
references: [
"advanceddockingsystem/advanceddockingsystem.qbs",
"aggregation/aggregation.qbs",
@ -24,5 +27,5 @@ Project {
"utils/utils.qbs",
"3rdparty/syntax-highlighting/syntax-highlighting.qbs",
"3rdparty/yaml-cpp/yaml-cpp.qbs",
].concat(project.additionalLibs)
].concat(qlitehtml).concat(project.additionalLibs)
}

1
src/libs/qlitehtml Submodule

Submodule src/libs/qlitehtml added at 3bccbb86ee

View File

@ -60,11 +60,8 @@ extend_qtc_plugin(Help
webenginehelpviewer.h
)
find_package(litehtml QUIET)
add_subdirectory(qlitehtml)
extend_qtc_plugin(Help
CONDITION TARGET litehtml AND TARGET qlitehtml
CONDITION TARGET qlitehtml
FEATURE_INFO "litehtml help viewer"
DEPENDS qlitehtml
DEFINES QTC_LITEHTML_HELPVIEWER

View File

@ -75,11 +75,14 @@ osx {
}
}
exists($$PWD/qlitehtml/litehtml/CMakeLists.txt)|!isEmpty(LITEHTML_INSTALL_DIR) {
include(qlitehtml/qlitehtml.pri)
HEADERS += litehtmlhelpviewer.h
SOURCES += litehtmlhelpviewer.cpp
DEFINES += QTC_LITEHTML_HELPVIEWER
QLITEHTML_DIR = $$PWD/../../libs/qlitehtml
exists($$QLITEHTML_DIR/src/qlitehtml.pri) {
exists($$QLITEHTML_DIR/src/3rdparty/litehtml/CMakeLists.txt)|!isEmpty(LITEHTML_INSTALL_DIR) {
include($$QLITEHTML_DIR/src/qlitehtml.pri)
HEADERS += litehtmlhelpviewer.h
SOURCES += litehtmlhelpviewer.cpp
DEFINES += QTC_LITEHTML_HELPVIEWER
}
}
RESOURCES += help.qrc

View File

@ -3,8 +3,6 @@ import qbs.Utilities
Project {
name: "Help"
references: "qlitehtml"
QtcPlugin {
name: "Help"

View File

@ -1,32 +0,0 @@
find_package(litehtml QUIET)
if(NOT TARGET litehtml AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/litehtml/CMakeLists.txt)
set(ORIG_FPIC ${CMAKE_POSITION_INDEPENDENT_CODE})
if (WIN32)
set(LITEHTML_UTF8 ON CACHE BOOL "")
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(litehtml EXCLUDE_FROM_ALL)
set(CMAKE_POSITION_INDEPENDENT_CODE "${ORIG_FPIC}")
# force optimized litehtml even in debug
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
# except for windows
if (NOT WIN32)
target_compile_options(gumbo PRIVATE -O2)
target_compile_options(litehtml PRIVATE -O2)
endif()
endif()
endif()
add_qtc_library(qlitehtml
CONDITION TARGET litehtml
PUBLIC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS Qt5::Widgets litehtml
PROPERTIES
POSITION_INDEPENDENT_CODE ON
SOURCES
container_qpainter.cpp container_qpainter.h container_qpainter_p.h
qlitehtml_global.h
qlitehtmlwidget.cpp qlitehtmlwidget.h
)

View File

@ -1,24 +0,0 @@
# Qt backend for litehtml
Provides
* A QPainter based rendering backend for the light-weight HTML/CSS rendering engine [litehtml].
* A QWidget that uses the QPainter based backend and provides API for simply setting the HTML text
and a base URL plus hook that are used for requesting referenced resources.
## How to build
Build and install [litehtml]. It is recommended to build [litehtml] in release mode
```
cd litehtml
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$PWD/../install" -DCMAKE_BUILD_TYPE=Release -G Ninja ..
cmake --build .
cmake --install .
```
Add the [litehtml] installation path to the `CMAKE_PREFIX_PATH` when building the Qt backend
[litehtml]: https://github.com/litehtml/litehtml

File diff suppressed because it is too large Load Diff

View File

@ -1,124 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of QLiteHtml.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "qlitehtml_global.h"
#include <QByteArray>
#include <QPaintDevice>
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QString>
#include <QTextDocument>
#include <QUrl>
#include <QVector>
#include <functional>
#include <memory>
class DocumentContainerPrivate;
class DocumentContainerContextPrivate;
class QLITEHTML_EXPORT DocumentContainerContext
{
public:
DocumentContainerContext();
~DocumentContainerContext();
void setMasterStyleSheet(const QString &css);
private:
std::unique_ptr<DocumentContainerContextPrivate> d;
friend class DocumentContainer;
friend class DocumentContainerPrivate;
};
class QLITEHTML_EXPORT DocumentContainer
{
public:
DocumentContainer();
virtual ~DocumentContainer();
public: // outside API
void setPaintDevice(QPaintDevice *paintDevice);
void setDocument(const QByteArray &data, DocumentContainerContext *context);
bool hasDocument() const;
void setBaseUrl(const QString &url);
void setScrollPosition(const QPoint &pos);
void render(int width, int height);
void draw(QPainter *painter, const QRect &clip);
int documentWidth() const;
int documentHeight() const;
int anchorY(const QString &anchorName) const;
// these return areas to redraw in document space
QVector<QRect> mousePressEvent(const QPoint &documentPos,
const QPoint &viewportPos,
Qt::MouseButton button);
QVector<QRect> mouseMoveEvent(const QPoint &documentPos, const QPoint &viewportPos);
QVector<QRect> mouseReleaseEvent(const QPoint &documentPos,
const QPoint &viewportPos,
Qt::MouseButton button);
QVector<QRect> mouseDoubleClickEvent(const QPoint &documentPos,
const QPoint &viewportPos,
Qt::MouseButton button);
QVector<QRect> leaveEvent();
QUrl linkAt(const QPoint &documentPos, const QPoint &viewportPos);
QString caption() const;
QString selectedText() const;
void findText(const QString &text,
QTextDocument::FindFlags flags,
bool incremental,
bool *wrapped,
bool *success,
QVector<QRect> *oldSelection,
QVector<QRect> *newSelection);
void setDefaultFont(const QFont &font);
QFont defaultFont() const;
using DataCallback = std::function<QByteArray(QUrl)>;
void setDataCallback(const DataCallback &callback);
using CursorCallback = std::function<void(QCursor)>;
void setCursorCallback(const CursorCallback &callback);
using LinkCallback = std::function<void(QUrl)>;
void setLinkCallback(const LinkCallback &callback);
using PaletteCallback = std::function<QPalette()>;
void setPaletteCallback(const PaletteCallback &callback);
int withFixedElementPosition(int y, const std::function<void()> &action);
private:
std::unique_ptr<DocumentContainerPrivate> d;
};

View File

@ -1,163 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of QLiteHtml.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "container_qpainter.h"
#include <litehtml.h>
#include <QPaintDevice>
#include <QPixmap>
#include <QPoint>
#include <QRect>
#include <QString>
#include <QVector>
#include <unordered_map>
class Selection
{
public:
struct Element
{
litehtml::element::ptr element;
int index = -1;
int x = -1;
};
enum class Mode { Free, Word };
bool isValid() const;
void update();
QRect boundingRect() const;
Element startElem;
Element endElem;
QVector<QRect> selection;
QString text;
QPoint selectionStartDocumentPos;
Mode mode = Mode::Free;
bool isSelecting = false;
};
struct Index
{
QString text;
// only contains leaf elements
std::unordered_map<litehtml::element::ptr, int> elementToIndex;
using Entry = std::pair<int, litehtml::element::ptr>;
std::vector<Entry> indexToElement;
Entry findElement(int index) const;
};
class DocumentContainerPrivate : public litehtml::document_container
{
public: // document_container API
litehtml::uint_ptr create_font(const litehtml::tchar_t *faceName,
int size,
int weight,
litehtml::font_style italic,
unsigned int decoration,
litehtml::font_metrics *fm) override;
void delete_font(litehtml::uint_ptr hFont) override;
int text_width(const litehtml::tchar_t *text, litehtml::uint_ptr hFont) override;
void draw_text(litehtml::uint_ptr hdc,
const litehtml::tchar_t *text,
litehtml::uint_ptr hFont,
litehtml::web_color color,
const litehtml::position &pos) override;
int pt_to_px(int pt) override;
int get_default_font_size() const override;
const litehtml::tchar_t *get_default_font_name() const override;
void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker &marker) override;
void load_image(const litehtml::tchar_t *src,
const litehtml::tchar_t *baseurl,
bool redraw_on_ready) override;
void get_image_size(const litehtml::tchar_t *src,
const litehtml::tchar_t *baseurl,
litehtml::size &sz) override;
void draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint &bg) override;
void draw_borders(litehtml::uint_ptr hdc,
const litehtml::borders &borders,
const litehtml::position &draw_pos,
bool root) override;
void set_caption(const litehtml::tchar_t *caption) override;
void set_base_url(const litehtml::tchar_t *base_url) override;
void link(const std::shared_ptr<litehtml::document> &doc,
const litehtml::element::ptr &el) override;
void on_anchor_click(const litehtml::tchar_t *url, const litehtml::element::ptr &el) override;
void set_cursor(const litehtml::tchar_t *cursor) override;
void transform_text(litehtml::tstring &text, litehtml::text_transform tt) override;
void import_css(litehtml::tstring &text,
const litehtml::tstring &url,
litehtml::tstring &baseurl) override;
void set_clip(const litehtml::position &pos,
const litehtml::border_radiuses &bdr_radius,
bool valid_x,
bool valid_y) override;
void del_clip() override;
void get_client_rect(litehtml::position &client) const override;
std::shared_ptr<litehtml::element> create_element(const litehtml::tchar_t *tag_name,
const litehtml::string_map &attributes,
const std::shared_ptr<litehtml::document> &doc) override;
void get_media_features(litehtml::media_features &media) const override;
void get_language(litehtml::tstring &language, litehtml::tstring &culture) const override;
QPixmap getPixmap(const QString &imageUrl, const QString &baseUrl);
QString serifFont() const;
QString sansSerifFont() const;
QString monospaceFont() const;
QUrl resolveUrl(const QString &url, const QString &baseUrl) const;
void drawSelection(QPainter *painter, const QRect &clip) const;
void buildIndex();
QPaintDevice *m_paintDevice = nullptr;
litehtml::document::ptr m_document;
Index m_index;
QString m_baseUrl;
QRect m_clientRect;
QPoint m_scrollPosition;
QString m_caption;
QFont m_defaultFont = QFont(sansSerifFont(), 16);
QByteArray m_defaultFontFamilyName = m_defaultFont.family().toUtf8();
QHash<QUrl, QPixmap> m_pixmaps;
Selection m_selection;
DocumentContainer::DataCallback m_dataCallback;
DocumentContainer::CursorCallback m_cursorCallback;
DocumentContainer::LinkCallback m_linkCallback;
DocumentContainer::PaletteCallback m_paletteCallback;
bool m_blockLinks = false;
};
class DocumentContainerContextPrivate
{
public:
litehtml::context context;
};

View File

@ -1,164 +0,0 @@
exists($$PWD/litehtml/CMakeLists.txt) {
LH_SRC = $$PWD/litehtml
LH_HDR = $$LH_SRC/include/litehtml
GB_SRC = $$PWD/litehtml/src/gumbo
GB_HDR = $$GB_SRC/include/gumbo
# gumbo
SOURCES += \
$$GB_SRC/attribute.c \
$$GB_SRC/char_ref.c \
$$GB_SRC/error.c \
$$GB_SRC/parser.c \
$$GB_SRC/string_buffer.c \
$$GB_SRC/string_piece.c \
$$GB_SRC/tag.c \
$$GB_SRC/tokenizer.c \
$$GB_SRC/utf8.c \
$$GB_SRC/util.c \
$$GB_SRC/vector.c
HEADERS += \
$$GB_SRC/include//gumbo.h \
$$GB_HDR/attribute.h \
$$GB_HDR/char_ref.h \
$$GB_HDR/error.h \
$$GB_HDR/insertion_mode.h \
$$GB_HDR/parser.h \
$$GB_HDR/string_buffer.h \
$$GB_HDR/string_piece.h \
$$GB_HDR/tag_enum.h \
$$GB_HDR/tag_gperf.h \
$$GB_HDR/tag_sizes.h \
$$GB_HDR/tag_strings.h \
$$GB_HDR/token_type.h \
$$GB_HDR/tokenizer.h \
$$GB_HDR/tokenizer_states.h \
$$GB_HDR/utf8.h \
$$GB_HDR/util.h \
$$GB_HDR/vector.h
INCLUDEPATH *= $$GB_SRC/include $$GB_HDR
win32 {
HEADERS += \
$$GB_SRC/visualc/include/strings.h
INCLUDEPATH *= $$GB_SRC/visualc/include
}
# litehtml
SOURCES += \
$$LH_SRC/src/background.cpp \
$$LH_SRC/src/box.cpp \
$$LH_SRC/src/context.cpp \
$$LH_SRC/src/css_length.cpp \
$$LH_SRC/src/css_selector.cpp \
$$LH_SRC/src/document.cpp \
$$LH_SRC/src/el_anchor.cpp \
$$LH_SRC/src/el_base.cpp \
$$LH_SRC/src/el_before_after.cpp \
$$LH_SRC/src/el_body.cpp \
$$LH_SRC/src/el_break.cpp \
$$LH_SRC/src/el_cdata.cpp \
$$LH_SRC/src/el_comment.cpp \
$$LH_SRC/src/el_div.cpp \
$$LH_SRC/src/element.cpp \
$$LH_SRC/src/el_font.cpp \
$$LH_SRC/src/el_image.cpp \
$$LH_SRC/src/el_li.cpp \
$$LH_SRC/src/el_link.cpp \
$$LH_SRC/src/el_para.cpp \
$$LH_SRC/src/el_script.cpp \
$$LH_SRC/src/el_space.cpp \
$$LH_SRC/src/el_style.cpp \
$$LH_SRC/src/el_table.cpp \
$$LH_SRC/src/el_td.cpp \
$$LH_SRC/src/el_text.cpp \
$$LH_SRC/src/el_title.cpp \
$$LH_SRC/src/el_tr.cpp \
$$LH_SRC/src/html.cpp \
$$LH_SRC/src/html_tag.cpp \
$$LH_SRC/src/iterators.cpp \
$$LH_SRC/src/media_query.cpp \
$$LH_SRC/src/num_cvt.cpp \
$$LH_SRC/src/style.cpp \
$$LH_SRC/src/stylesheet.cpp \
$$LH_SRC/src/table.cpp \
$$LH_SRC/src/utf8_strings.cpp \
$$LH_SRC/src/web_color.cpp
HEADERS += \
$$LH_SRC/include/litehtml.h \
$$LH_HDR/attributes.h \
$$LH_HDR/background.h \
$$LH_HDR/borders.h \
$$LH_HDR/box.h \
$$LH_HDR/context.h \
$$LH_HDR/css_length.h \
$$LH_HDR/css_margins.h \
$$LH_HDR/css_offsets.h \
$$LH_HDR/css_position.h \
$$LH_HDR/css_selector.h \
$$LH_HDR/document.h \
$$LH_HDR/el_anchor.h \
$$LH_HDR/el_base.h \
$$LH_HDR/el_before_after.h \
$$LH_HDR/el_body.h \
$$LH_HDR/el_break.h \
$$LH_HDR/el_cdata.h \
$$LH_HDR/el_comment.h \
$$LH_HDR/el_div.h \
$$LH_HDR/el_font.h \
$$LH_HDR/el_image.h \
$$LH_HDR/el_li.h \
$$LH_HDR/el_link.h \
$$LH_HDR/el_para.h \
$$LH_HDR/el_script.h \
$$LH_HDR/el_space.h \
$$LH_HDR/el_style.h \
$$LH_HDR/el_table.h \
$$LH_HDR/el_td.h \
$$LH_HDR/el_text.h \
$$LH_HDR/el_title.h \
$$LH_HDR/el_tr.h \
$$LH_HDR/element.h \
$$LH_HDR/html.h \
$$LH_HDR/html_tag.h \
$$LH_HDR/iterators.h \
$$LH_HDR/media_query.h \
$$LH_HDR/num_cvt.h \
$$LH_HDR/os_types.h \
$$LH_HDR/style.h \
$$LH_HDR/stylesheet.h \
$$LH_HDR/table.h \
$$LH_HDR/types.h \
$$LH_HDR/utf8_strings.h \
$$LH_HDR/web_color.h
INCLUDEPATH *= $$LH_SRC/include $$LH_HDR
# litehtml without optimization is not fun
QMAKE_CFLAGS_DEBUG += -O2
QMAKE_CXXFLAGS_DEBUG += -O2
} else {
INCLUDEPATH *= $$LITEHTML_INSTALL_DIR/include $$LITEHTML_INSTALL_DIR/include/litehtml
LITEHTML_LIB_DIR = $$LITEHTML_INSTALL_DIR/lib
LIBS += -L$$LITEHTML_LIB_DIR -llitehtml -lgumbo
win32: PRE_TARGETDEPS += $$LITEHTML_LIB_DIR/litehtml.lib $$LITEHTML_LIB_DIR/gumbo.lib
else:unix: PRE_TARGETDEPS += $$LITEHTML_LIB_DIR/liblitehtml.a $$LITEHTML_LIB_DIR/libgumbo.a
}
HEADERS += \
$$PWD/container_qpainter.h \
$$PWD/container_qpainter_p.h \
$$PWD/qlitehtmlwidget.h
SOURCES += \
$$PWD/container_qpainter.cpp \
$$PWD/qlitehtmlwidget.cpp
INCLUDEPATH *= $$PWD
win32: DEFINES += LITEHTML_UTF8
DEFINES *= QLITEHTML_STATIC_LIBRARY

View File

@ -1,216 +0,0 @@
import qbs.File
import qbs.FileInfo
Product {
type: buildLib ? ["staticlibrary"] : undefined
Depends { name: "cpp" }
Depends { name: "qtc" }
property bool useExternalLib: qtc.litehtmlInstallDir
property bool buildLib: !useExternalLib && File.exists(path + "/litehtml/CMakeLists.txt")
condition: useExternalLib || buildLib
property string gumboSrcDir: path + "/litehtml/src/gumbo"
property string gumboHeaderDir: gumboSrcDir + "/include/gumbo"
property string litehtmlHeaderDir: path + "/litehtml/include/litehtml"
property string mainHeaderDir: litehtmlHeaderDir + '/..'
property stringList sharedDefines: {
var defines = ["QLITEHTML_STATIC_LIBRARY"];
if (qbs.targetOS.contains("windows"))
defines.push("LITEHTML_UTF8");
return defines;
}
cpp.defines: sharedDefines
cpp.includePaths: {
var paths = [gumboHeaderDir, gumboHeaderDir + '/..', litehtmlHeaderDir, mainHeaderDir];
if (qbs.targetOS.contains("windows"))
paths.push(gumboSrcDir + "/visualc/include");
return paths;
}
cpp.optimization: "fast"
cpp.warningLevel: "none"
cpp.cxxLanguageVersion: "c++14"
Export {
Depends { name: "cpp" }
Group {
name: "litehtml/Qt glue"
cpp.warningLevel: "none"
files: [
"container_qpainter.cpp",
"container_qpainter.h",
"container_qpainter_p.h",
"qlitehtmlwidget.cpp",
"qlitehtmlwidget.h",
]
}
Properties {
condition: product.useExternalLib
cpp.dynamicLibraries: ["litehtml", "gumbo"]
cpp.includePaths: [
FileInfo.joinPaths(qtc.litehtmlInstallDir, "include"),
FileInfo.joinPaths(qtc.litehtmlInstallDir, "include", "litehtml"),
]
cpp.libraryPaths: FileInfo.joinPaths(qtc.litehtmlInstallDir, "lib")
}
Properties {
condition: product.buildLib
cpp.defines: product.sharedDefines
cpp.includePaths: [product.mainHeaderDir, path]
}
}
Group {
condition: buildLib
name: "gumbo sources"
prefix: gumboSrcDir + '/'
files: [
"attribute.c",
"char_ref.c",
"error.c",
"parser.c",
"string_buffer.c",
"string_piece.c",
"tag.c",
"tokenizer.c",
"utf8.c",
"util.c",
"vector.c",
]
}
Group {
condition: buildLib
name: "gumbo headers"
prefix: gumboHeaderDir + '/'
files: [
"../gumbo.h",
"attribute.h",
"char_ref.h",
"error.h",
"insertion_mode.h",
"parser.h",
"string_buffer.h",
"string_piece.h",
"tag_enum.h",
"tag_gperf.h",
"tag_sizes.h",
"tag_strings.h",
"token_type.h",
"tokenizer.h",
"tokenizer_states.h",
"utf8.h",
"util.h",
"vector.h",
]
Group {
name: "gumbo Windows headers"
condition: qbs.targetOS.contains("windows")
files: "../../visualc/include/strings.h"
}
}
Group {
condition: buildLib
name: "litehtml sources"
prefix: "litehtml/src/"
files: [
"background.cpp",
"box.cpp",
"context.cpp",
"css_length.cpp",
"css_selector.cpp",
"document.cpp",
"el_anchor.cpp",
"el_base.cpp",
"el_before_after.cpp",
"el_body.cpp",
"el_break.cpp",
"el_cdata.cpp",
"el_comment.cpp",
"el_div.cpp",
"element.cpp",
"el_font.cpp",
"el_image.cpp",
"el_li.cpp",
"el_link.cpp",
"el_para.cpp",
"el_script.cpp",
"el_space.cpp",
"el_style.cpp",
"el_table.cpp",
"el_td.cpp",
"el_text.cpp",
"el_title.cpp",
"el_tr.cpp",
"html.cpp",
"html_tag.cpp",
"iterators.cpp",
"media_query.cpp",
"num_cvt.cpp",
"style.cpp",
"stylesheet.cpp",
"table.cpp",
"utf8_strings.cpp",
"web_color.cpp",
]
}
Group {
condition: buildLib
name: "litehtml headers"
prefix: litehtmlHeaderDir + '/'
files: [
"../litehtml.h",
"attributes.h",
"background.h",
"borders.h",
"box.h",
"context.h",
"css_length.h",
"css_margins.h",
"css_offsets.h",
"css_position.h",
"css_selector.h",
"document.h",
"el_anchor.h",
"el_base.h",
"el_before_after.h",
"el_body.h",
"el_break.h",
"el_cdata.h",
"el_comment.h",
"el_div.h",
"el_font.h",
"el_image.h",
"el_li.h",
"el_link.h",
"el_para.h",
"el_script.h",
"el_space.h",
"el_style.h",
"el_table.h",
"el_td.h",
"el_text.h",
"el_title.h",
"el_tr.h",
"element.h",
"html.h",
"html_tag.h",
"iterators.h",
"media_query.h",
"num_cvt.h",
"os_types.h",
"style.h",
"stylesheet.h",
"table.h",
"types.h",
"utf8_strings.h",
"web_color.h",
]
}
}

View File

@ -1,36 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <qglobal.h>
#if defined(QLITEHTML_LIBRARY)
# define QLITEHTML_EXPORT Q_DECL_EXPORT
#elif defined(QLITEHTML_STATIC_LIBRARY) // Abuse single files for manual tests
# define QLITEHTML_EXPORT
#else
# define QLITEHTML_EXPORT Q_DECL_IMPORT
#endif

View File

@ -1,656 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of QLiteHtml.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qlitehtmlwidget.h"
#include "container_qpainter.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QScrollBar>
#include <QStyle>
#include <QTimer>
const int kScrollBarStep = 40;
// TODO copied from litehtml/include/master.css
const char mastercss[] = R"RAW(
html {
display: block;
height:100%;
width:100%;
position: relative;
}
head {
display: none
}
meta {
display: none
}
title {
display: none
}
link {
display: none
}
style {
display: none
}
script {
display: none
}
body {
display:block;
margin:8px;
height:100%;
width:100%;
}
p {
display:block;
margin-top:1em;
margin-bottom:1em;
}
b, strong {
display:inline;
font-weight:bold;
}
i, em {
display:inline;
font-style:italic;
}
center
{
text-align:center;
display:block;
}
a:link
{
text-decoration: underline;
color: #00f;
cursor: pointer;
}
h1, h2, h3, h4, h5, h6, div {
display:block;
}
h1 {
font-weight:bold;
margin-top:0.67em;
margin-bottom:0.67em;
font-size: 2em;
}
h2 {
font-weight:bold;
margin-top:0.83em;
margin-bottom:0.83em;
font-size: 1.5em;
}
h3 {
font-weight:bold;
margin-top:1em;
margin-bottom:1em;
font-size:1.17em;
}
h4 {
font-weight:bold;
margin-top:1.33em;
margin-bottom:1.33em
}
h5 {
font-weight:bold;
margin-top:1.67em;
margin-bottom:1.67em;
font-size:.83em;
}
h6 {
font-weight:bold;
margin-top:2.33em;
margin-bottom:2.33em;
font-size:.67em;
}
br {
display:inline-block;
}
br[clear="all"]
{
clear:both;
}
br[clear="left"]
{
clear:left;
}
br[clear="right"]
{
clear:right;
}
span {
display:inline
}
img {
display: inline-block;
}
img[align="right"]
{
float: right;
}
img[align="left"]
{
float: left;
}
hr {
display: block;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: auto;
margin-right: auto;
border-style: inset;
border-width: 1px
}
/***************** TABLES ********************/
table {
display: table;
border-collapse: separate;
border-spacing: 2px;
border-top-color:gray;
border-left-color:gray;
border-bottom-color:black;
border-right-color:black;
}
tbody, tfoot, thead {
display:table-row-group;
vertical-align:middle;
}
tr {
display: table-row;
vertical-align: inherit;
border-color: inherit;
}
td, th {
display: table-cell;
vertical-align: inherit;
border-width:1px;
padding:1px;
}
th {
font-weight: bold;
}
table[border] {
border-style:solid;
}
table[border|=0] {
border-style:none;
}
table[border] td, table[border] th {
border-style:solid;
border-top-color:black;
border-left-color:black;
border-bottom-color:gray;
border-right-color:gray;
}
table[border|=0] td, table[border|=0] th {
border-style:none;
}
caption {
display: table-caption;
}
td[nowrap], th[nowrap] {
white-space:nowrap;
}
tt, code, kbd, samp {
font-family: monospace
}
pre, xmp, plaintext, listing {
display: block;
font-family: monospace;
white-space: pre;
margin: 1em 0
}
/***************** LISTS ********************/
ul, menu, dir {
display: block;
list-style-type: disc;
margin-top: 1em;
margin-bottom: 1em;
margin-left: 0;
margin-right: 0;
padding-left: 40px
}
ol {
display: block;
list-style-type: decimal;
margin-top: 1em;
margin-bottom: 1em;
margin-left: 0;
margin-right: 0;
padding-left: 40px
}
li {
display: list-item;
}
ul ul, ol ul {
list-style-type: circle;
}
ol ol ul, ol ul ul, ul ol ul, ul ul ul {
list-style-type: square;
}
dd {
display: block;
margin-left: 40px;
}
dl {
display: block;
margin-top: 1em;
margin-bottom: 1em;
margin-left: 0;
margin-right: 0;
}
dt {
display: block;
}
ol ul, ul ol, ul ul, ol ol {
margin-top: 0;
margin-bottom: 0
}
blockquote {
display: block;
margin-top: 1em;
margin-bottom: 1em;
margin-left: 40px;
margin-left: 40px;
}
/*********** FORM ELEMENTS ************/
form {
display: block;
margin-top: 0em;
}
option {
display: none;
}
input, textarea, keygen, select, button, isindex {
margin: 0em;
color: initial;
line-height: normal;
text-transform: none;
text-indent: 0;
text-shadow: none;
display: inline-block;
}
input[type="hidden"] {
display: none;
}
article, aside, footer, header, hgroup, nav, section
{
display: block;
}
)RAW";
class QLiteHtmlWidgetPrivate
{
public:
QString html;
DocumentContainerContext context;
QUrl url;
DocumentContainer documentContainer;
qreal zoomFactor = 1;
};
QLiteHtmlWidget::QLiteHtmlWidget(QWidget *parent)
: QAbstractScrollArea(parent)
, d(new QLiteHtmlWidgetPrivate)
{
setMouseTracking(true);
horizontalScrollBar()->setSingleStep(kScrollBarStep);
verticalScrollBar()->setSingleStep(kScrollBarStep);
d->documentContainer.setCursorCallback([this](const QCursor &c) { viewport()->setCursor(c); });
d->documentContainer.setPaletteCallback([this] { return palette(); });
d->documentContainer.setLinkCallback([this](const QUrl &url) {
QUrl fullUrl = url;
if (url.isRelative() && url.path(QUrl::FullyEncoded).isEmpty()) { // fragment/anchor only
fullUrl = d->url;
fullUrl.setFragment(url.fragment(QUrl::FullyEncoded));
}
// delay because document may not be changed directly during this callback
QTimer::singleShot(0, this, [this, fullUrl] { emit linkClicked(fullUrl); });
});
// TODO adapt mastercss to palette (default text & background color)
d->context.setMasterStyleSheet(mastercss);
}
QLiteHtmlWidget::~QLiteHtmlWidget()
{
delete d;
}
void QLiteHtmlWidget::setUrl(const QUrl &url)
{
d->url = url;
QUrl urlWithoutAnchor = url;
urlWithoutAnchor.setFragment({});
const QString urlString = urlWithoutAnchor.toString(QUrl::None);
const int lastSlash = urlString.lastIndexOf('/');
const QString baseUrl = lastSlash >= 0 ? urlString.left(lastSlash) : urlString;
d->documentContainer.setBaseUrl(baseUrl);
}
QUrl QLiteHtmlWidget::url() const
{
return d->url;
}
void QLiteHtmlWidget::setHtml(const QString &content)
{
d->html = content;
d->documentContainer.setPaintDevice(viewport());
d->documentContainer.setDocument(content.toUtf8(), &d->context);
verticalScrollBar()->setValue(0);
horizontalScrollBar()->setValue(0);
render();
}
QString QLiteHtmlWidget::html() const
{
return d->html;
}
QString QLiteHtmlWidget::title() const
{
return d->documentContainer.caption();
}
void QLiteHtmlWidget::setZoomFactor(qreal scale)
{
Q_ASSERT(scale != 0);
d->zoomFactor = scale;
withFixedTextPosition([this] { render(); });
}
qreal QLiteHtmlWidget::zoomFactor() const
{
return d->zoomFactor;
}
bool QLiteHtmlWidget::findText(const QString &text,
QTextDocument::FindFlags flags,
bool incremental,
bool *wrapped)
{
bool success = false;
QVector<QRect> oldSelection;
QVector<QRect> newSelection;
d->documentContainer
.findText(text, flags, incremental, wrapped, &success, &oldSelection, &newSelection);
// scroll to search result position and/or redraw as necessary
QRect newSelectionCombined;
for (const QRect &r : qAsConst(newSelection))
newSelectionCombined = newSelectionCombined.united(r);
QScrollBar *vBar = verticalScrollBar();
const int top = newSelectionCombined.top();
const int bottom = newSelectionCombined.bottom() - toVirtual(viewport()->size()).height();
if (success && top < vBar->value() && vBar->minimum() <= top) {
vBar->setValue(top);
} else if (success && vBar->value() < bottom && bottom <= vBar->maximum()) {
vBar->setValue(bottom);
} else {
viewport()->update(fromVirtual(newSelectionCombined.translated(-scrollPosition())));
for (const QRect &r : qAsConst(oldSelection))
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
return success;
}
void QLiteHtmlWidget::setDefaultFont(const QFont &font)
{
withFixedTextPosition([this, &font] {
d->documentContainer.setDefaultFont(font);
render();
});
}
QFont QLiteHtmlWidget::defaultFont() const
{
return d->documentContainer.defaultFont();
}
void QLiteHtmlWidget::scrollToAnchor(const QString &name)
{
if (!d->documentContainer.hasDocument())
return;
horizontalScrollBar()->setValue(0);
if (name.isEmpty()) {
verticalScrollBar()->setValue(0);
return;
}
const int y = d->documentContainer.anchorY(name);
if (y >= 0)
verticalScrollBar()->setValue(std::min(y, verticalScrollBar()->maximum()));
}
void QLiteHtmlWidget::setResourceHandler(const QLiteHtmlWidget::ResourceHandler &handler)
{
d->documentContainer.setDataCallback(handler);
}
QString QLiteHtmlWidget::selectedText() const
{
return d->documentContainer.selectedText();
}
void QLiteHtmlWidget::paintEvent(QPaintEvent *event)
{
if (!d->documentContainer.hasDocument())
return;
d->documentContainer.setScrollPosition(scrollPosition());
QPainter p(viewport());
p.setWorldTransform(QTransform().scale(d->zoomFactor, d->zoomFactor));
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
p.setRenderHint(QPainter::Antialiasing, true);
d->documentContainer.draw(&p, toVirtual(event->rect()));
}
void QLiteHtmlWidget::resizeEvent(QResizeEvent *event)
{
withFixedTextPosition([this, event] {
QAbstractScrollArea::resizeEvent(event);
render();
});
}
void QLiteHtmlWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint viewportPos;
QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mouseMoveEvent(pos, viewportPos))
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
void QLiteHtmlWidget::mousePressEvent(QMouseEvent *event)
{
QPoint viewportPos;
QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mousePressEvent(pos, viewportPos, event->button()))
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
void QLiteHtmlWidget::mouseReleaseEvent(QMouseEvent *event)
{
QPoint viewportPos;
QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mouseReleaseEvent(pos, viewportPos, event->button()))
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
void QLiteHtmlWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QPoint viewportPos;
QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r :
d->documentContainer.mouseDoubleClickEvent(pos, viewportPos, event->button())) {
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
}
void QLiteHtmlWidget::leaveEvent(QEvent *event)
{
Q_UNUSED(event)
for (const QRect &r : d->documentContainer.leaveEvent())
viewport()->update(fromVirtual(r.translated(-scrollPosition())));
}
void QLiteHtmlWidget::contextMenuEvent(QContextMenuEvent *event)
{
QPoint viewportPos;
QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos);
emit contextMenuRequested(event->pos(), d->documentContainer.linkAt(pos, viewportPos));
}
void QLiteHtmlWidget::withFixedTextPosition(const std::function<void()> &action)
{
// remember element to which to scroll after re-rendering
QPoint viewportPos;
QPoint pos;
htmlPos({}, &viewportPos, &pos); // top-left
const int y = d->documentContainer.withFixedElementPosition(pos.y(), action);
if (y >= 0)
verticalScrollBar()->setValue(std::min(y, verticalScrollBar()->maximum()));
}
void QLiteHtmlWidget::render()
{
if (!d->documentContainer.hasDocument())
return;
const int fullWidth = width() / d->zoomFactor;
const QSize vViewportSize = toVirtual(viewport()->size());
const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, this);
const int w = fullWidth - scrollbarWidth - 2;
d->documentContainer.render(w, vViewportSize.height());
// scroll bars reflect virtual/scaled size of html document
horizontalScrollBar()->setPageStep(vViewportSize.width());
horizontalScrollBar()->setRange(0, std::max(0, d->documentContainer.documentWidth() - w));
verticalScrollBar()->setPageStep(vViewportSize.height());
verticalScrollBar()
->setRange(0, std::max(0, d->documentContainer.documentHeight() - vViewportSize.height()));
viewport()->update();
}
QPoint QLiteHtmlWidget::scrollPosition() const
{
return {horizontalScrollBar()->value(), verticalScrollBar()->value()};
}
void QLiteHtmlWidget::htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const
{
*viewportPos = toVirtual(viewport()->mapFromParent(pos));
*htmlPos = *viewportPos + scrollPosition();
}
QPoint QLiteHtmlWidget::toVirtual(const QPoint &p) const
{
return {int(p.x() / d->zoomFactor), int(p.y() / d->zoomFactor)};
}
QSize QLiteHtmlWidget::toVirtual(const QSize &s) const
{
return {int(s.width() / d->zoomFactor), int(s.height() / d->zoomFactor)};
}
QRect QLiteHtmlWidget::toVirtual(const QRect &r) const
{
return {toVirtual(r.topLeft()), toVirtual(r.size())};
}
QRect QLiteHtmlWidget::fromVirtual(const QRect &r) const
{
const QPoint tl{int(r.x() * d->zoomFactor), int(r.y() * d->zoomFactor)};
// round size up, and add one since the topleft point was rounded down
const QSize s{int(r.width() * d->zoomFactor + 0.5) + 1,
int(r.height() * d->zoomFactor + 0.5) + 1};
return {tl, s};
}

View File

@ -1,95 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of QLiteHtml.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "qlitehtml_global.h"
#include <QAbstractScrollArea>
#include <QTextDocument>
#include <functional>
class QLiteHtmlWidgetPrivate;
class QLITEHTML_EXPORT QLiteHtmlWidget : public QAbstractScrollArea
{
Q_OBJECT
public:
explicit QLiteHtmlWidget(QWidget *parent = nullptr);
~QLiteHtmlWidget() override;
// declaring the getters Q_INVOKABLE to make them Squish-testable
void setUrl(const QUrl &url);
Q_INVOKABLE QUrl url() const;
void setHtml(const QString &content);
Q_INVOKABLE QString html() const;
Q_INVOKABLE QString title() const;
void setZoomFactor(qreal scale);
qreal zoomFactor() const;
bool findText(const QString &text,
QTextDocument::FindFlags flags,
bool incremental,
bool *wrapped = nullptr);
void setDefaultFont(const QFont &font);
QFont defaultFont() const;
void scrollToAnchor(const QString &name);
using ResourceHandler = std::function<QByteArray(QUrl)>;
void setResourceHandler(const ResourceHandler &handler);
// declaring this Q_INVOKABLE to make it Squish-testable
Q_INVOKABLE QString selectedText() const;
signals:
void linkClicked(const QUrl &url);
void contextMenuRequested(const QPoint &pos, const QUrl &url);
protected:
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void leaveEvent(QEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private:
void withFixedTextPosition(const std::function<void()> &action);
void render();
QPoint scrollPosition() const;
void htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const;
QPoint toVirtual(const QPoint &p) const;
QSize toVirtual(const QSize &s) const;
QRect toVirtual(const QRect &r) const;
QRect fromVirtual(const QRect &r) const;
QLiteHtmlWidgetPrivate *d;
};