diff --git a/.agents/build-static-qt5.toml b/.agents/build-static-qt5.toml new file mode 100644 index 0000000..53d4232 --- /dev/null +++ b/.agents/build-static-qt5.toml @@ -0,0 +1,38 @@ +name = "build-static-qt5" +description = "Run and monitor the long static Qt 5 build, then report completion or failure." + +model = "gpt-5.4-mini" +model_reasoning_effort = "low" + +developer_instructions = """ +You are a narrow build runner for this repository. + +Your only job is to run the requested static Qt 5 helper flow. + +Allowed local commands are: +- ./build-qt5-static.sh --runtime docker --debug --clean +- ./build-qt5-static.sh --runtime docker --debug --qt-only --clean +- ./build-qt5-static.sh --runtime docker --debug --qtwebkit-only + +Use the full debug clean flow unless the caller explicitly asks for a scoped +Qt-only or QtWebKit-only build. Do not add release-build flags; release builds +are validated by CI. + +Monitor the command until it completes or fails. Do not edit files, refactor code, +inspect unrelated project state, or run unrelated commands. + +Use the repository's sanctioned helper-script flow only. Do not run host-local or +ad hoc qmake, make, cmake, ninja, compiler, or produced-binary commands. + +The clean debug Qt run is intentional when Qt patches changed: it avoids stale +generated Qt source trees. Do not combine --qtwebkit-only with --clean because +that scope requires an existing Qt install. + +When the build finishes, hand the result back to the top-level caller with: +- whether the build completed successfully or failed +- the exit status, if available +- the most relevant final output +- the first clear error message or failing step, if the build failed + +Keep the report concise and factual. +""" diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..0396b69 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,19 @@ +Checks: > + -*, + clang-analyzer-*, + bugprone-assignment-in-if-condition, + bugprone-branch-clone, + bugprone-copy-constructor-init, + bugprone-inaccurate-erase, + bugprone-macro-parentheses, + bugprone-sizeof-expression, + bugprone-string-constructor, + modernize-redundant-void-arg, + modernize-use-bool-literals, + modernize-use-nullptr, + readability-duplicate-include, + readability-misleading-indentation, + readability-redundant-control-flow, + readability-simplify-boolean-expr, + readability-static-accessed-through-instance +HeaderFilterRegex: '(^|.*/)src/.*' diff --git a/.github/workflows/qt5-static.yml b/.github/workflows/qt5-static.yml new file mode 100644 index 0000000..119bc16 --- /dev/null +++ b/.github/workflows/qt5-static.yml @@ -0,0 +1,258 @@ +name: Qt5 Static + +on: + push: + branches: + - "**" + tags: + - "**" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +env: + BUILD_TYPE: release + QT_VERSION: 5.15.17 + QTWEBKIT_VERSION: "2022-09-07" + TOOLCHAIN_PLATFORM: ubuntu-20.04-x86_64 + +jobs: + qt5: + name: Build Qt5 static + runs-on: ubuntu-24.04 + timeout-minutes: 720 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Check Qt version consistency + run: | + set -euo pipefail + + workflow_qt_version="${QT_VERSION}" + # shellcheck disable=SC1091 + source toolchains/qt5-static/common.sh + if [[ "${QT_VERSION}" != "${workflow_qt_version}" ]]; then + echo "error: workflow QT_VERSION=${workflow_qt_version} does not match common.sh QT_VERSION=${QT_VERSION}" >&2 + exit 1 + fi + + - name: Cache Qt5 build + id: qt5-cache + uses: actions/cache@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qt5-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch') }} + + - name: Cache source archives + if: steps.qt5-cache.outputs.cache-hit != 'true' + uses: actions/cache@v4 + with: + path: artifacts/src-cache + key: qt5-static-sources-${{ hashFiles('toolchains/qt5-static/sources.lock', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/sources-qtwebkit.lock') }} + + - name: Build static Qt5 + if: steps.qt5-cache.outputs.cache-hit != 'true' + run: ./build-qt5-static.sh --runtime docker --qt-only + + qtwebkit: + name: Build QtWebKit + runs-on: ubuntu-24.04 + needs: qt5 + timeout-minutes: 720 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Cache QtWebKit build + id: qtwebkit-cache + uses: actions/cache@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qtwebkit-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch', 'toolchains/qt5-static/sources-qtwebkit.lock', 'toolchains/qt5-static/patches/qtwebkit/*.patch') }} + + - name: Cache source archives + if: steps.qtwebkit-cache.outputs.cache-hit != 'true' + uses: actions/cache@v4 + with: + path: artifacts/src-cache + key: qt5-static-sources-${{ hashFiles('toolchains/qt5-static/sources.lock', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/sources-qtwebkit.lock') }} + + - name: Restore Qt5 build + if: steps.qtwebkit-cache.outputs.cache-hit != 'true' + uses: actions/cache/restore@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qt5-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch') }} + + - name: Build CI container image + run: docker build -f toolchains/qt5-static/Dockerfile -t qtweb-qt5-static:${QT_VERSION} . + + - name: Build static QtWebKit + if: steps.qtwebkit-cache.outputs.cache-hit != 'true' + run: ./build-qt5-static.sh --runtime docker --qtwebkit-only + + - name: Build QtWebKit smoke test + run: ./smoke-tests/qtwebkit-smoke/smoke-build-docker.sh + + # - name: Runtime test QtWebKit app + # run: ./run-smoke.sh --runtime-check about:blank + + - name: Check QtWebKit shared dependencies + run: ./run-smoke.sh --check + + qtweb: + name: Build QtWeb + runs-on: ubuntu-24.04 + needs: qtwebkit + timeout-minutes: 120 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Restore QtWebKit build + uses: actions/cache/restore@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qtwebkit-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch', 'toolchains/qt5-static/sources-qtwebkit.lock', 'toolchains/qt5-static/patches/qtwebkit/*.patch') }} + + - name: Build CI container image + run: docker build -f toolchains/qt5-static/Dockerfile -t qtweb-qt5-static:${QT_VERSION} . + + - name: Build QtWeb + run: ./build-browser-docker.sh + + # - name: Runtime test QtWeb + # run: ./run-browser.sh --runtime-check about:blank + + - name: Check QtWeb shared dependencies + run: ./run-browser.sh --check + + publish-qt-toolchain: + name: Publish Qt5 toolchain + runs-on: ubuntu-24.04 + needs: qt5 + permissions: + contents: write + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Restore Qt5 build + uses: actions/cache/restore@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qt5-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch') }} + + - name: Package Qt5 toolchain + run: | + set -euo pipefail + + toolchain_dir="artifacts/qt5-static-${QT_VERSION}-${BUILD_TYPE}" + asset="qt5-static-${QT_VERSION}-${BUILD_TYPE}-${TOOLCHAIN_PLATFORM}.tar.zst" + + test -d "${toolchain_dir}/install" + test -f "${toolchain_dir}/build-manifest.txt" + + tar --zstd -cf "${asset}" \ + -C "${toolchain_dir}" \ + install \ + build-manifest.txt + + - name: Upload workflow artifact + uses: actions/upload-artifact@v4 + with: + name: qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}-${{ env.TOOLCHAIN_PLATFORM }} + path: qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}-${{ env.TOOLCHAIN_PLATFORM }}.tar.zst + + - name: Upload release asset + if: startsWith(github.ref, 'refs/tags/') + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + asset="qt5-static-${QT_VERSION}-${BUILD_TYPE}-${TOOLCHAIN_PLATFORM}.tar.zst" + + if ! gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then + gh release create "${GITHUB_REF_NAME}" \ + --title "${GITHUB_REF_NAME}" \ + --notes "Static Qt5 and QtWebKit toolchains." + fi + + gh release upload "${GITHUB_REF_NAME}" "${asset}" --clobber + + publish-qtwebkit-toolchain: + name: Publish QtWebKit toolchain + runs-on: ubuntu-24.04 + needs: + - qtwebkit + - publish-qt-toolchain + permissions: + contents: write + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Restore QtWebKit build + uses: actions/cache/restore@v4 + with: + path: | + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/install + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/logs + artifacts/qt5-static-${{ env.QT_VERSION }}-${{ env.BUILD_TYPE }}/build-manifest.txt + key: qtwebkit-static-${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('toolchains/qt5-static/Dockerfile', 'toolchains/qt5-static/qt5-static-build-entrypoint.sh', 'toolchains/qt5-static/sources-qt.lock', 'toolchains/qt5-static/patches/qt/*.patch', 'toolchains/qt5-static/sources-qtwebkit.lock', 'toolchains/qt5-static/patches/qtwebkit/*.patch') }} + + - name: Package QtWebKit toolchain + run: | + set -euo pipefail + + toolchain_dir="artifacts/qt5-static-${QT_VERSION}-${BUILD_TYPE}" + asset="qt5-static-${QT_VERSION}-qtwebkit-${QTWEBKIT_VERSION}-${BUILD_TYPE}-${TOOLCHAIN_PLATFORM}.tar.zst" + + test -d "${toolchain_dir}/install" + test -f "${toolchain_dir}/build-manifest.txt" + + tar --zstd -cf "${asset}" \ + -C "${toolchain_dir}" \ + install \ + build-manifest.txt + + - name: Upload workflow artifact + uses: actions/upload-artifact@v4 + with: + name: qt5-static-${{ env.QT_VERSION }}-qtwebkit-${{ env.QTWEBKIT_VERSION }}-${{ env.BUILD_TYPE }}-${{ env.TOOLCHAIN_PLATFORM }} + path: qt5-static-${{ env.QT_VERSION }}-qtwebkit-${{ env.QTWEBKIT_VERSION }}-${{ env.BUILD_TYPE }}-${{ env.TOOLCHAIN_PLATFORM }}.tar.zst + + - name: Upload release asset + if: startsWith(github.ref, 'refs/tags/') + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + asset="qt5-static-${QT_VERSION}-qtwebkit-${QTWEBKIT_VERSION}-${BUILD_TYPE}-${TOOLCHAIN_PLATFORM}.tar.zst" + + gh release upload "${GITHUB_REF_NAME}" "${asset}" --clobber diff --git a/.gitignore b/.gitignore index bee15bb..052d04a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ src/qt/.* temp-src build artifacts +.codex # C++ objects and libs @@ -26,4 +27,4 @@ Makefile* build-* !build-browser-docker.sh !build-qt5-static.sh -!toolchains/qt5-static/build-inside-container.sh +!.agents/build-static-qt5.toml diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..688424f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "files.watcherExclude": { + "**/artifacts/**": true, + "**/build-*/**": true, + "**/src/qt/**": true + }, + "search.exclude": { + "**/artifacts/**": true, + "**/build-*/**": true, + "**/src/qt/**": true + } +} diff --git a/AGENTS.md b/AGENTS.md index 864469e..430de37 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,10 +1,37 @@ # AGENTS.md +## Code Style +- Do not introduce one-off variables for simple values or small argument groups. Keep values inline at the use site unless a variable removes real duplication, clarifies non-obvious logic, or matches nearby style. +- When individual shell command arguments need comments, prefer a single argument array with comments beside the relevant entries instead of separate helper variables for small flag groups. +- In shell scripts, do not build command strings or use `eval`; use direct command calls or argument arrays so quoting and word splitting stay explicit. +- Do not pass long inline shell programs to Docker with `bash -c`/`bash -lc`; put the container-side logic in a checked-in script and execute that script. +- Do not add helper functions that are only called once unless they isolate a meaningful phase, cleanup/error boundary, or repeated validation pattern. +- Treat `build.sh` as a legacy script: do not apply cleanup/style rewrites there unless the user explicitly asks to modernize that script. + ## Build And Validation Policy - Do not run host-local or ad hoc builds in this repository. - Do not invoke `qmake`, `make`, `cmake`, `ninja`, or compiler commands directly on the host for validation or debugging. -- Use the repository's sanctioned helper-script flows instead, such as `build-browser-docker.sh`, `build-qt5-static.sh`, and `smoke-run.sh`, when a build or runtime validation is explicitly required. +- Use the repository's sanctioned helper-script flows instead, such as `build-browser-docker.sh`, `build-qt5-static.sh`, and `run-smoke.sh`, when a build or runtime validation is explicitly required. +- For any `build-qt5-static.sh` request, including short requests like "clean rebuild", use the `.agents/build-static-qt5.toml` subagent instead of running the long build directly in the main agent. - If that sanctioned path is unavailable, blocked, or out of scope for the task, state that validation could not be run. Do not fall back to a local build. - Do not launch the built `QtWeb` binary or other produced executables as an agent. -- Do not run `smoke-run.sh` or start GUI/runtime validation on the user's behalf unless the user explicitly asks for that exact execution. +- Do not run `run-smoke.sh` or start GUI/runtime validation on the user's behalf unless the user explicitly asks for that exact execution. +- Use `./run-smoke.sh --check` and `./run-browser.sh --check` to check existing Docker-built binaries for remaining shared dependencies. - When a build succeeds, report the output path or the command the user can run; leave execution to the user unless explicitly requested. + +## QtWeb Static Build Notes +- Shared Qt build defaults live in `toolchains/qt5-static/common.sh`: Qt `5.15.17`, image tag `qtweb-qt5-static:5.15.17`. +- Static-linking fixes must be applied in the Qt or QtWebKit build itself, such as configure inputs, source patches, or checked-in container-side build scripts. This keeps future Qt/QtWebKit upgrades honest: patches should fail early and be rebased deliberately instead of relying on post-build metadata rewrites or other broken hacks. +- For local validation, check only debug builds to save time; release builds are validated by CI. +- Use the `.agents/build-static-qt5.toml` subagent when running full or scoped `./build-qt5-static.sh` flows so long builds are monitored without unrelated edits or commands. The default clean rebuild command is `./build-qt5-static.sh --runtime docker --debug --clean`. +- Use `./build-qt5-static.sh --runtime docker --qt-only` for the static Qt stage and `./build-qt5-static.sh --runtime docker --qtwebkit-only` for the QtWebKit stage. +- Use `./build-browser-docker.sh` for the QtWeb browser stage; add `--analyze` only when clang-tidy analysis is explicitly requested. +- Use `./smoke-tests/qtwebkit-smoke/smoke-build-docker.sh` for the QtWebKit smoke-test build. +- Runtime checks are host-side wrappers and must only be run on explicit request: `./run-smoke.sh --runtime-check about:blank` or `./run-browser.sh --runtime-check about:blank`. +- The CI workflow is `.github/workflows/qt5-static.yml`; its main order is `qt5` -> `qtwebkit` -> `qtweb`, followed by publish jobs. +- For build failures, classify the first real error as configure-time, compile-time, link-time, runtime/smoke-test, CI resource exhaustion, or missing static dependency before editing scripts. + +## Documentation Policy +- Keep `docs/migration-status.md` limited to behavior that is implemented in the repository. +- Keep `docs/plan.md` limited to planned or pending work. +- When implementing a planned change, update both docs in the same change: move completed points from `docs/plan.md` to `docs/migration-status.md` and remove stale planned items. diff --git a/README.md b/README.md index e4d8b82..43d8be1 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ QtWeb QtWeb Internet Browser -Build policy: do not use host-local or ad hoc builds for this repository. Use the repository helper scripts and containerized flows for build or validation work; if that path is unavailable, report validation as not run instead of falling back to local `qmake`/`make` commands. Agents should not launch the built `QtWeb` binary or other produced executables unless explicitly asked; they should report the path or command for the user to run instead. +Build policy: do not use host-local or ad hoc builds for this repository. Use the repository helper scripts and containerized flows for build or validation work; if that path is unavailable, report validation as not run instead of falling back to local `qmake`/`make` commands. `./run-smoke.sh --check` and `./run-browser.sh --check` validate shared dependencies for existing Docker-built binaries. `./run-smoke.sh --runtime-check about:blank` and `./run-browser.sh --runtime-check about:blank` are the host-side runtime checks. Agents may only use `run-smoke.sh` and `run-browser.sh` for runtime checks; directly launching the built `QtWeb` binary or other produced executables is prohibited. diff --git a/build-browser-docker.sh b/build-browser-docker.sh index a197fee..e64dd22 100755 --- a/build-browser-docker.sh +++ b/build-browser-docker.sh @@ -9,9 +9,41 @@ fail() { exit 1 } -IMAGE_TAG="${IMAGE_TAG:-qtweb-qt5-static-poc:5.5.1}" +# shellcheck disable=SC1090 +source "${REPO_ROOT}/toolchains/qt5-static/common.sh" + +SCRIPT_NAME="$(basename "$0")" + +report_run_duration() { + local exit_code="$1" + local outcome="failed" + + if [[ "$exit_code" -eq 0 ]]; then + outcome="completed" + fi + + echo "${SCRIPT_NAME} ${outcome} in $(format_duration "${SECONDS}")" +} + +usage() { + cat <<'EOF' +Usage: ./build-browser-docker.sh [options] + +Options: + --debug Build the debug browser variant + --analyze Build inside Docker and run clang-tidy + --analyze-only Alias for --analyze + --export-fixes Export YAML fix suggestions for clang-tidy + --help Show this help message +EOF +} + +IMAGE_TAG="${IMAGE_TAG:-$QT5_STATIC_IMAGE_TAG}" JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}" BUILD_TYPE="release" +RUN_ANALYSIS=0 +EXPORT_FIXES=0 +BUILD_DIR="" while [[ $# -gt 0 ]]; do case "$1" in @@ -19,21 +51,32 @@ while [[ $# -gt 0 ]]; do BUILD_TYPE="debug" shift ;; + --analyze|--analyze-only) + RUN_ANALYSIS=1 + shift + ;; + --export-fixes) + RUN_ANALYSIS=1 + EXPORT_FIXES=1 + shift + ;; + --help) + usage + exit 0 + ;; *) fail "unknown argument: $1" ;; esac done +SECONDS=0 +trap 'report_run_duration "$?"' EXIT + case "$BUILD_TYPE" in release|debug) - QT_PREFIX_IN_CONTAINER="/workspace/artifacts/qt5-static-5.5.1-${BUILD_TYPE}/install" - BUILD_DIR_IN_CONTAINER="build-docker-${BUILD_TYPE}" - if [[ "$BUILD_TYPE" == "release" ]]; then - QMAKE_CONFIG_ARGS="CONFIG+=release CONFIG-=debug" - else - QMAKE_CONFIG_ARGS="CONFIG+=debug CONFIG-=release" - fi + QT_PREFIX_IN_CONTAINER="${REPO_ROOT}/artifacts/qt5-static-${QT_VERSION}-${BUILD_TYPE}/install" + BUILD_DIR="${REPO_ROOT}/build-docker-${BUILD_TYPE}" ;; *) fail "BUILD_TYPE must be release or debug, got: ${BUILD_TYPE}" @@ -43,19 +86,13 @@ esac docker run --rm \ -u "$(id -u):$(id -g)" \ -e JOBS="${JOBS}" \ + -e REPO_ROOT="${REPO_ROOT}" \ -e QT_PREFIX_IN_CONTAINER="${QT_PREFIX_IN_CONTAINER}" \ - -e BUILD_DIR_IN_CONTAINER="${BUILD_DIR_IN_CONTAINER}" \ - -e QMAKE_CONFIG_ARGS="${QMAKE_CONFIG_ARGS}" \ - -v "${REPO_ROOT}:/workspace" \ + -e BUILD_DIR_IN_CONTAINER="${BUILD_DIR}" \ + -e BUILD_TYPE="${BUILD_TYPE}" \ + -e EXPORT_FIXES="${EXPORT_FIXES}" \ -v "${REPO_ROOT}:${REPO_ROOT}" \ - -w /workspace \ + -e RUN_ANALYSIS="${RUN_ANALYSIS}" \ + -w "${REPO_ROOT}" \ "${IMAGE_TAG}" \ - /bin/bash -lc ' - set -euo pipefail - rm -rf "${BUILD_DIR_IN_CONTAINER}" - mkdir -p "${BUILD_DIR_IN_CONTAINER}" - cd "${BUILD_DIR_IN_CONTAINER}" - "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../src/QtWeb.pro ${QMAKE_CONFIG_ARGS} - make -j"${JOBS}" - echo "built: /workspace/${BUILD_DIR_IN_CONTAINER}/QtWeb" - ' + "${REPO_ROOT}/toolchains/qt5-static/browser-build-entrypoint.sh" diff --git a/build-qt5-static.sh b/build-qt5-static.sh index 3dc97e6..33b5226 100755 --- a/build-qt5-static.sh +++ b/build-qt5-static.sh @@ -1,41 +1,47 @@ #!/usr/bin/env bash set -euo pipefail -QT_VERSION="5.5.1" -DEFAULT_JOBS="$(nproc 2>/dev/null || echo 8)" -JOBS="${COMPILE_JOBS:-$DEFAULT_JOBS}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$SCRIPT_DIR" +LOCK_FILE="${REPO_ROOT}/toolchains/qt5-static/sources.lock" +DOCKERFILE="${REPO_ROOT}/toolchains/qt5-static/Dockerfile" +INNER_SCRIPT="/workspace/toolchains/qt5-static/qt5-static-build-entrypoint.sh" + +# shellcheck disable=SC1090 +source "${REPO_ROOT}/toolchains/qt5-static/common.sh" + +SCRIPT_NAME="$(basename "$0")" + +JOBS="${COMPILE_JOBS:-$(nproc 2>/dev/null || echo 8)}" OUTPUT_DIR="" RUNTIME="auto" CLEAN=false BUILD_TYPE="release" -IMAGE_TAG="qtweb-qt5-static-poc:${QT_VERSION}" +IMAGE_TAG="${IMAGE_TAG:-$QT5_STATIC_IMAGE_TAG}" -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$SCRIPT_DIR" -LOCK_FILE="${REPO_ROOT}/toolchains/qt5-static/sources.lock" -DOCKERFILE="${REPO_ROOT}/toolchains/qt5-static/Dockerfile" -INNER_SCRIPT="/workspace/toolchains/qt5-static/build-inside-container.sh" +BUILD_SCOPE="${BUILD_SCOPE:-all}" usage() { - cat <<'EOF' + cat < Parallel build jobs (default: nproc) - --output-dir Output directory inside repo (default: artifacts/qt5-static-5.5.1-) + --output-dir Output directory inside repo (default: artifacts/qt5-static-${QT_VERSION}-) --runtime Container runtime selector (default: auto) --debug Build debug Qt libraries + --qt-only Build only the static Qt toolchain + --qtwebkit-only Build only QtWebKit against an existing Qt install --clean Remove output directory before running --help Show this help message Environment overrides: + IMAGE_TAG QT5_SRC_URL QT5_SRC_SHA256 QT5_WEBKIT_SRC_URL QT5_WEBKIT_SHA256 - ICU_SRC_URL - ICU_SRC_SHA256 EOF } @@ -44,13 +50,6 @@ fail() { exit 1 } -abs_path() { - case "$1" in - /*) printf '%s\n' "$1" ;; - *) printf '%s\n' "${REPO_ROOT}/$1" ;; - esac -} - basename_from_url() { local url="$1" url="${url%%\?*}" @@ -107,6 +106,33 @@ pick_runtime() { echo "$RUNTIME" } +RUN_CONTAINER_NAME="" + +cleanup_run_container() { + if [[ -n "${RUN_CONTAINER_NAME:-}" && -n "${CONTAINER_RUNTIME:-}" ]]; then + echo "cleaning up interrupted build container: $RUN_CONTAINER_NAME" + "$CONTAINER_RUNTIME" rm -f "$RUN_CONTAINER_NAME" >/dev/null 2>&1 || true + fi +} + +report_run_duration() { + local exit_code="$1" + local outcome="failed" + + if [[ "$exit_code" -eq 0 ]]; then + outcome="completed" + fi + + echo "${SCRIPT_NAME} ${outcome} in $(format_duration "${SECONDS}")" +} + +cleanup_and_report() { + local exit_code="$1" + + cleanup_run_container + report_run_duration "$exit_code" +} + download_file() { local url="$1" local dst="$2" @@ -179,6 +205,14 @@ while [[ $# -gt 0 ]]; do BUILD_TYPE="debug" shift ;; + --qt-only) + BUILD_SCOPE="qt" + shift + ;; + --qtwebkit-only) + BUILD_SCOPE="qtwebkit" + shift + ;; --clean) CLEAN=true shift @@ -197,6 +231,17 @@ if [[ "$BUILD_TYPE" != "release" && "$BUILD_TYPE" != "debug" ]]; then fail "unsupported build type: $BUILD_TYPE" fi +if [[ "$BUILD_SCOPE" != "all" && "$BUILD_SCOPE" != "qt" && "$BUILD_SCOPE" != "qtwebkit" ]]; then + fail "unsupported build scope: $BUILD_SCOPE" +fi + +SECONDS=0 +trap 'cleanup_and_report "$?"' EXIT + +if [[ "$BUILD_SCOPE" == "qtwebkit" && "$CLEAN" == true ]]; then + fail "--qtwebkit-only cannot be combined with --clean because it requires an existing Qt install in the output directory" +fi + if [[ -z "$OUTPUT_DIR" ]]; then OUTPUT_DIR="artifacts/qt5-static-${QT_VERSION}-${BUILD_TYPE}" fi @@ -215,20 +260,15 @@ QT5_WEBKIT_SRC_URL="${QT5_WEBKIT_SRC_URL:-${LOCK_QT5_WEBKIT_SRC_URL}}" QT5_WEBKIT_SHA256="${QT5_WEBKIT_SHA256:-${LOCK_QT5_WEBKIT_SHA256:-}}" QT5_WEBKIT_MD5="${LOCK_QT5_WEBKIT_MD5:-}" -ICU_SRC_URL="${ICU_SRC_URL:-${LOCK_ICU_SRC_URL}}" -ICU_SRC_SHA256="${ICU_SRC_SHA256:-${LOCK_ICU_SRC_SHA256:-}}" -ICU_SRC_MD5="${LOCK_ICU_SRC_MD5:-}" - -if [[ -z "$QT5_SRC_URL" || -z "$QT5_WEBKIT_SRC_URL" || -z "$ICU_SRC_URL" ]]; then +if [[ -z "$QT5_SRC_URL" || -z "$QT5_WEBKIT_SRC_URL" ]]; then fail "source URLs are empty in lock file" fi QT5_SRC_FILE="$(source_file_name "$QT5_SRC_URL" "$LOCK_QT5_SRC_URL" "${LOCK_QT5_SRC_FILE:-}")" QT5_WEBKIT_FILE="$(source_file_name "$QT5_WEBKIT_SRC_URL" "$LOCK_QT5_WEBKIT_SRC_URL" "${LOCK_QT5_WEBKIT_FILE:-}")" -ICU_SRC_FILE="$(source_file_name "$ICU_SRC_URL" "$LOCK_ICU_SRC_URL" "${LOCK_ICU_SRC_FILE:-}")" REPO_ABS="$(cd "$REPO_ROOT" && pwd -P)" -OUTPUT_RAW="$(abs_path "$OUTPUT_DIR")" +OUTPUT_RAW="$(cd "$REPO_ROOT" && realpath -m -- "$OUTPUT_DIR")" [[ "$JOBS" =~ ^[1-9][0-9]*$ ]] || fail "--jobs must be a positive integer" @@ -238,7 +278,6 @@ if $CLEAN && [[ -d "$OUTPUT_RAW" ]]; then rm -rf \ "${OUTPUT_RAW}/build" \ "${OUTPUT_RAW}/install" \ - "${OUTPUT_RAW}/icu-static" \ "${OUTPUT_RAW}/xkb-config-root" \ "${OUTPUT_RAW}/logs" \ "${OUTPUT_RAW}/build-manifest.txt" @@ -249,12 +288,12 @@ OUTPUT_ABS="$(cd "$OUTPUT_RAW" && pwd -P)" ensure_output_in_repo "$OUTPUT_ABS" "--output-dir resolves outside repo: $OUTPUT_ABS" -SRC_CACHE_DIR="${OUTPUT_ABS}/src-cache" +SRC_CACHE_DIR="${REPO_ABS}/artifacts/src-cache" +ensure_output_in_repo "$SRC_CACHE_DIR" "source cache resolves outside repo: $SRC_CACHE_DIR" mkdir -p "$SRC_CACHE_DIR" "${OUTPUT_ABS}/logs" "${OUTPUT_ABS}/build" QT5_SRC_ARCHIVE="${SRC_CACHE_DIR}/${QT5_SRC_FILE}" QT5_WEBKIT_ARCHIVE="${SRC_CACHE_DIR}/${QT5_WEBKIT_FILE}" -ICU_SRC_ARCHIVE="${SRC_CACHE_DIR}/${ICU_SRC_FILE}" download_file "$QT5_SRC_URL" "$QT5_SRC_ARCHIVE" verify_checksum "$QT5_SRC_ARCHIVE" "$QT5_SRC_SHA256" "$QT5_SRC_MD5" "$QT5_SRC_FILE" @@ -262,37 +301,48 @@ verify_checksum "$QT5_SRC_ARCHIVE" "$QT5_SRC_SHA256" "$QT5_SRC_MD5" "$QT5_SRC_FI download_file "$QT5_WEBKIT_SRC_URL" "$QT5_WEBKIT_ARCHIVE" verify_checksum "$QT5_WEBKIT_ARCHIVE" "$QT5_WEBKIT_SHA256" "$QT5_WEBKIT_MD5" "$QT5_WEBKIT_FILE" -download_file "$ICU_SRC_URL" "$ICU_SRC_ARCHIVE" -verify_checksum "$ICU_SRC_ARCHIVE" "$ICU_SRC_SHA256" "$ICU_SRC_MD5" "$ICU_SRC_FILE" - CONTAINER_RUNTIME="$(pick_runtime)" echo "using container runtime: $CONTAINER_RUNTIME" "$CONTAINER_RUNTIME" build -f "$DOCKERFILE" -t "$IMAGE_TAG" "$REPO_ROOT" +RUN_CONTAINER_NAME="qt5-static-build-$$-$(date +%s)" +trap cleanup_run_container INT TERM HUP + "$CONTAINER_RUNTIME" run --rm \ + --name "$RUN_CONTAINER_NAME" \ --user "$(id -u):$(id -g)" \ -e JOBS="$JOBS" \ -e CLEAN="$CLEAN" \ -e BUILD_TYPE="$BUILD_TYPE" \ + -e BUILD_SCOPE="$BUILD_SCOPE" \ -e QT_VERSION="$QT_VERSION" \ -e OUTPUT_DIR="${OUTPUT_ABS}" \ -e QT_SRC_ARCHIVE="${QT5_SRC_ARCHIVE}" \ -e QTWEBKIT_ARCHIVE="${QT5_WEBKIT_ARCHIVE}" \ - -e ICU_SRC_ARCHIVE="${ICU_SRC_ARCHIVE}" \ -e QT_SRC_URL="$QT5_SRC_URL" \ -e QTWEBKIT_URL="$QT5_WEBKIT_SRC_URL" \ - -e ICU_SRC_URL="$ICU_SRC_URL" \ -e QT_SRC_SHA256="$QT5_SRC_SHA256" \ -e QTWEBKIT_SHA256="$QT5_WEBKIT_SHA256" \ - -e ICU_SRC_SHA256="$ICU_SRC_SHA256" \ -e QT_SRC_MD5="$QT5_SRC_MD5" \ -e QTWEBKIT_MD5="$QT5_WEBKIT_MD5" \ - -e ICU_SRC_MD5="$ICU_SRC_MD5" \ -v "${REPO_ROOT}:/workspace" \ -v "${REPO_ROOT}:${REPO_ROOT}" \ -w /workspace \ "$IMAGE_TAG" \ "$INNER_SCRIPT" -echo "static Qt5 POC completed: ${OUTPUT_ABS}" +RUN_CONTAINER_NAME="" +trap - INT TERM HUP + +case "$BUILD_SCOPE" in + all) + echo "static Qt5 toolchain completed: ${OUTPUT_ABS}" + ;; + qt) + echo "static Qt build completed: ${OUTPUT_ABS}" + ;; + qtwebkit) + echo "static QtWebKit build completed: ${OUTPUT_ABS}" + ;; +esac diff --git a/docs/migration-status.md b/docs/migration-status.md new file mode 100644 index 0000000..2e33547 --- /dev/null +++ b/docs/migration-status.md @@ -0,0 +1,15 @@ +# QtWeb Migration Status + +- Qt `5.15.17` is the active Qt5 migration baseline. +- QtWebKit is pinned to the Movable Ink `2022-09-07` source archive. +- Static Qt5 release and debug toolchain builds are supported. +- Standalone QtWebKit builds against the static Qt5 toolchain are supported. +- Static Qt, QtWebKit, ICU, and OpenSSL library verification is implemented. +- QtWebKit smoke build validation is implemented. +- Docker browser builds against the static Qt5 toolchain are implemented. +- Host-side browser runtime checking through the repository helper is implemented. +- Docker-backed `clang-tidy` analysis is implemented. +- Analyzer fix export is implemented for `clang-tidy`. +- Generated build manifests and build logs are implemented. +- The browser remains on QtWebKit Widgets; no Qt WebEngine migration has been implemented. +- Existing Qt4 build flow remains untouched. diff --git a/docs/migration.md b/docs/migration.md deleted file mode 100644 index db46165..0000000 --- a/docs/migration.md +++ /dev/null @@ -1,69 +0,0 @@ -# Qt5 Browser Port Implementation Plan - -## Summary -Port QtWeb to the existing static Qt `5.5.1` toolchain on Linux while keeping the legacy Qt4 flow intact. The implementation base stays on `qt5-migration`, and the existing `qt5` branch is used as the donor for already-solved Qt5 application changes. The first source mutation is the automated Qt4-to-Qt5 header rewrite, followed by targeted manual integration until the full browser builds and runs with torrent and FTP support preserved. All Qt5 browser validation builds must run inside Docker against the repository's containerized toolchain environment rather than on the host, and they must be invoked through the repository helper scripts rather than direct `docker` or ad hoc build commands. Host-local `qmake`/`make`/compiler validation runs are explicitly out of policy for this repository. - -## Decisions -- Delivery branch: `qt5-migration` -- Donor branch for application porting work: `qt5` -- Target runtime/build baseline: Qt `5.5.1` static Linux `x86_64` -- Required build environment for Qt5 validation: Docker container using the repository image/toolchain -- Required invocation path for Qt5 validation: repository helper scripts such as `build-browser-docker.sh` and `run-broswer.sh`, not direct `docker` commands -- Keep the existing Qt4 `build.sh` path unchanged -- Preserve torrent support in the first Qt5 browser milestone -- Preserve FTP browsing and FTP downloads in the first Qt5 browser milestone - -## Implementation Order -1. Update this document with the concrete execution plan. -2. Run `/home/magist3r/code/qtbase/bin/fixqt4headers.pl` against `src/` and review the generated include rewrites. -3. Bring the qmake project files up to Qt5.5.1: -- `src/QtWeb.pro` must use `widgets`, `webkitwidgets`, and `printsupport` -- `src/torrent/torrent.pro` must stay compatible with Qt `5.5.1` qmake and must not depend on `requires(qtConfig(filedialog))` -4. Replay the relevant Qt5 source-port work from `qt5`: -- Qt5 include/module split across browser UI, WebKit, and print code -- `QStandardPaths` for storage paths -- `QUrlQuery` for query parsing -- Torrent networking migration from `QHttp` to `QNetworkAccessManager` -5. Adapt donor-branch code back down to Qt `5.5.1` where it assumes newer Qt: -- replace `QDateTime::currentSecsSinceEpoch()` -- replace `QRandomGenerator` -- replace `QOverload` connect syntax -6. Restore and keep both legacy feature areas: -- torrent remains built into the application -- FTP remains supported in `webview` for directory listing and file download -7. Validate the main browser inside Docker on top of the existing smoke-test/toolchain work, using the repository helper scripts instead of direct container or compiler invocations. - -## Public and Internal Interfaces -- No new user-facing CLI or configuration layer is added. -- Internal build interfaces change to Qt5-aware qmake module usage in: -- `src/QtWeb.pro` -- `src/torrent/torrent.pro` -- Torrent internal types move from `QHttp`-based APIs to `QNetworkAccessManager` / `QNetworkReply`. -- Storage path handling moves to `QStandardPaths`. -- Query parsing moves from deprecated Qt4 APIs to `QUrlQuery`. - -## Required Behavior -- The browser must launch and render pages under Qt5. -- Tabs, windows, and navigation behavior must remain functional. -- Downloads must continue to work. -- Torrent support must build and reach tracker communication under Qt5. -- `ftp://` directory browsing must still work. -- FTP file downloads must still work. -- Portable and non-portable settings/data paths must continue to resolve correctly. - -## Validation -- Documentation reflects the chosen implementation path and constraints. -- qmake generation succeeds inside Docker when invoked through `build-browser-docker.sh`. -- A clean out-of-tree browser build succeeds inside Docker through the helper scripts, with outputs kept in repository-local `build-docker-*` directories. -- Validate changed Bash / POSIX shell scripts with `shellcheck` when script changes are part of the work. -- Browser smoke validation covers page loading, tabs, windows, downloads, and print-related actions. -- Torrent validation covers successful build and tracker communication after the networking port. -- FTP validation covers directory listing and file download. -- Regression checks cover settings/data paths and autocomplete/password/query parsing after API replacements. - -## Known Risks -- The `qt5` donor branch was written against newer Qt and contains incompatible APIs for `5.5.1`. -- FTP was partially disabled in the donor branch and must be reintroduced without regressing navigation behavior. -- Settings-path or key drift can create silent compatibility regressions. -- Static-build constraints may surface additional link/runtime issues after compilation succeeds. -- Host-native builds can hide or invent problems relative to the intended toolchain, so the Docker helper-script path is the source of truth for Qt5 validation. diff --git a/docs/plan.md b/docs/plan.md new file mode 100644 index 0000000..846564b --- /dev/null +++ b/docs/plan.md @@ -0,0 +1,16 @@ +# QtWeb Implementation Plan + +- Docker-backed `clazy` analysis is planned. +- `clazy` report generation is planned. +- `clazy` validation alongside the existing `clang-tidy` analysis is planned. +- Analyzer cleanup for clear Qt API misuse is planned. +- Analyzer cleanup for unused locals, dead includes, redundant conditionals, and trivial temporary/container inefficiencies is planned. +- Removal of deprecated Qt API usage is planned, including `QRegExp`, `QString::SkipEmptyParts`, `QDesktopWidget`/`QApplication::desktop()`, `qrand()`/`qsrand()`, `Q_ENUMS`, `Q_FOREACH`/`foreach`, and legacy string-based `SIGNAL`/`SLOT` connections. +- Review of `QTextCodec`-based page/source encoding paths is planned before Qt6 migration work. +- Removal or replacement of the remaining `QFtp` download path is planned. +- Qt6 migration planning is constrained to a QtWebKit-preserving path; no QtWebKit code removal or Qt WebEngine replacement is planned. +- QtWebKit compatibility review is planned for the browser surface that currently depends on `QWebView`, `QWebPage`, `QWebFrame`, `QWebSettings`, `QWebHistoryInterface`, `QWebHitTestResult`, and `QWebHistory`. +- Docker base image digest pinning is planned. +- Additional dependency reduction checks for TLS, certificate handling, and module detection are planned before removing more runtime dependencies. +- Normal Docker browser build validation after analyzer cleanup is planned. +- Documentation updates must move completed points from this file to `docs/migration-status.md`. diff --git a/docs/qt5-static-poc.md b/docs/qt5-static-poc.md deleted file mode 100644 index 6329169..0000000 --- a/docs/qt5-static-poc.md +++ /dev/null @@ -1,112 +0,0 @@ -# Qt5 Static Build POC - -## Objective -Build a reproducible static Qt5 toolchain for QtWeb migration on Linux `x86_64`. - -Target versions: -- Qt `5.5.1` -- QtWebKit `5.5.1` - -This POC validates the toolchain pipeline only (not the QtWeb app build). -Primary portability target: static linking plus minimal runtime dependencies. - -## Non-Goals -- Migrating QtWeb application sources. -- Windows/macOS support. -- Modifying legacy Qt4 flow in `build.sh`. - -## Fixed Baseline -- Qt version is locked to `5.5.1`. -- Containerized build is required (`podman` or `docker`). -- ICU support is required for Qt5 + QtWebKit in this path. -- Outputs stay inside the repository (default: `artifacts/qt5-static-5.5.1`). - -## Inputs -- Wrapper script: `build-qt5-static.sh` -- In-container script: `toolchains/qt5-static/build-inside-container.sh` -- Container definition: `toolchains/qt5-static/Dockerfile` -- Source lock and checksums: `toolchains/qt5-static/sources.lock` -- Optional patch hook: `toolchains/qt5-static/patches/*.patch` - -Supported source override env vars: -- `QT5_SRC_URL` -- `QT5_SRC_SHA256` -- `QT5_WEBKIT_SRC_URL` -- `QT5_WEBKIT_SHA256` -- `ICU_SRC_URL` -- `ICU_SRC_SHA256` - -Checksum policy: -1. Prefer `sha256`. -2. Allow `md5` fallback only when `sha256` is unavailable in legacy metadata. -3. Abort immediately on mismatch. - -## Output Layout -Default root: `artifacts/qt5-static-5.5.1` - -- `src-cache/`: downloaded archives -- `build/`: extracted/build tree -- `install/`: static Qt install prefix -- `icu-static/`: static ICU install prefix -- `logs/`: `icu-configure.log`, `icu-build.log`, `icu-install.log`, `configure.log`, `build.log`, `install.log`, `verify.log` -- `build-manifest.txt`: runtime, source URLs/checksums, configure flags, verification summary - -## Verification Gates -A successful run must satisfy: -1. `qmake -query QT_VERSION` is `5.5.1`. -2. Install is static (`QT_CONFIG` contains `static` or static libs prove it). -3. Required static libs exist in `install/lib`: - - `libQt5Core.a` - - `libQt5Gui.a` - - `libQt5Widgets.a` - - `libQt5Network.a` - - `libQt5Xml.a` - - `libQt5PrintSupport.a` - - `libQt5WebKit.a` - - `libQt5WebKitWidgets.a` -4. Verification log ends with `verification passed`. -5. Required static ICU libs exist in `icu-static/lib`: - - `libicuuc.a` - - `libicui18n.a` - - `libicudata.a` - -## Current Status vs Planned Gates -Implemented now: -- Containerized build pipeline. -- Source lock + checksum verification. -- In-container static ICU build from locked source archive. -- Static Qt + QtWebKit library verification. -- Static ICU library verification. -- Manifest/log generation. - -Planned (not yet enforced by scripts): -- QtWebKit smoke test binary compile/link gate against produced toolchain. -- Digest-pinned container base image (currently tag-pinned `ubuntu:16.04`). - -## Run Examples -Default run: -```bash -./build-qt5-static.sh -``` - -Clean rebuild with explicit runtime and jobs: -```bash -./build-qt5-static.sh --clean --runtime podman --jobs 8 -``` - -Custom output directory inside repo: -```bash -./build-qt5-static.sh --output-dir artifacts/qt5-static-poc-run1 -``` - -## Risks -- Legacy Qt/QtWebKit code may fail under newer host toolchains. -- Static WebKit can still be rejected by configure constraints. -- Archive URLs may become unavailable over time. -- Over-aggressive dependency reduction can break TLS/cert/platform behavior. - -## Next POC Tasks -1. Add and enforce the QtWebKit smoke-test build gate. -2. Add SSL/TLS support in the Qt5 static build and validate it with an HTTPS smoke test. -3. Move Docker base image from tag pinning to digest pinning. -4. Define explicit dependency-audit output for produced artifacts (for example `ldd` policy and exceptions). diff --git a/run-broswer.sh b/run-broswer.sh deleted file mode 100755 index 8efe378..0000000 --- a/run-broswer.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -BUILD_SCRIPT="${SCRIPT_DIR}/build-browser-docker.sh" - -BUILD_TYPE="release" -RUN_WITH_GDB=0 -RUN_BUILD=0 -while [[ $# -gt 0 ]]; do - case "$1" in - --rebuild) - RUN_BUILD=1 - shift - ;; - --debug) - BUILD_TYPE="debug" - shift - ;; - --gdb) - RUN_WITH_GDB=1 - BUILD_TYPE="debug" - shift - ;; - --) - shift - break - ;; - *) - break - ;; - esac -done - -case "${BUILD_TYPE}" in - release|debug) ;; - *) - echo "error: BUILD_TYPE must be release or debug, got: ${BUILD_TYPE}" >&2 - exit 1 - ;; -esac - -BINARY="${SCRIPT_DIR}/build-docker-${BUILD_TYPE}/QtWeb" -if [[ "${RUN_BUILD}" -eq 1 ]]; then - BUILD_ARGS=() - if [[ "${BUILD_TYPE}" == "debug" ]]; then - BUILD_ARGS+=(--debug) - fi - "${BUILD_SCRIPT}" "${BUILD_ARGS[@]}" -elif [[ ! -x "${BINARY}" ]]; then - echo "error: browser binary not found: ${BINARY}" >&2 - echo "hint: rerun with --rebuild" >&2 - exit 1 -fi - -RUN_BINARY="${BINARY}" -if [[ "${RUN_WITH_GDB}" -eq 1 ]]; then - CMD=(gdb -ex run --args "${RUN_BINARY}") -else - CMD=("${RUN_BINARY}") -fi - -exec "${CMD[@]}" "$@" diff --git a/run-browser.sh b/run-browser.sh new file mode 100755 index 0000000..73610f6 --- /dev/null +++ b/run-browser.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="${SCRIPT_DIR}" + +APP_LABEL="browser" +BUILD_SCRIPT="${REPO_ROOT}/build-browser-docker.sh" +BINARY_ROOT="${REPO_ROOT}" +BINARY_NAME="QtWeb" + +# shellcheck disable=SC1090 +source "${REPO_ROOT}/toolchains/qt5-static/run-common.sh" diff --git a/run-smoke.sh b/run-smoke.sh new file mode 100755 index 0000000..269c044 --- /dev/null +++ b/run-smoke.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="${SCRIPT_DIR}" +SMOKE_DIR="${REPO_ROOT}/smoke-tests/qtwebkit-smoke" + +APP_LABEL="smoke" +BUILD_SCRIPT="${SMOKE_DIR}/smoke-build-docker.sh" +BINARY_ROOT="${SMOKE_DIR}" +BINARY_NAME="qtwebkit-smoke" + +# shellcheck disable=SC1090 +source "${REPO_ROOT}/toolchains/qt5-static/run-common.sh" diff --git a/smoke-run.sh b/smoke-run.sh deleted file mode 100755 index dfe5f92..0000000 --- a/smoke-run.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SMOKE_DIR="${SCRIPT_DIR}/smoke-tests/qtwebkit-smoke" -BUILD_SCRIPT="${SMOKE_DIR}/smoke-build-docker.sh" - -BUILD_TYPE="release" -RUN_WITH_GDB=0 -RUN_BUILD=0 -while [[ $# -gt 0 ]]; do - case "$1" in - --rebuild) - RUN_BUILD=1 - shift - ;; - --debug) - BUILD_TYPE="debug" - shift - ;; - --gdb) - RUN_WITH_GDB=1 - BUILD_TYPE="debug" - shift - ;; - --) - shift - break - ;; - *) - break - ;; - esac -done - -case "${BUILD_TYPE}" in - release|debug) ;; - *) - echo "error: BUILD_TYPE must be release or debug, got: ${BUILD_TYPE}" >&2 - exit 1 - ;; -esac - -BINARY="${SMOKE_DIR}/build-docker-${BUILD_TYPE}/qtwebkit-smoke" -if [[ "${RUN_BUILD}" -eq 1 ]]; then - BUILD_ARGS=() - if [[ "${BUILD_TYPE}" == "debug" ]]; then - BUILD_ARGS+=(--debug) - fi - "${BUILD_SCRIPT}" "${BUILD_ARGS[@]}" -elif [[ ! -x "${BINARY}" ]]; then - echo "error: smoke binary not found: ${BINARY}" >&2 - echo "hint: rerun with --build" >&2 - exit 1 -fi - -RUN_BINARY="${BINARY}" -if [[ "${RUN_WITH_GDB}" -eq 1 ]]; then - CMD=(gdb -ex run --args "${RUN_BINARY}") -else - CMD=("${RUN_BINARY}") -fi - -exec "${CMD[@]}" "$@" diff --git a/smoke-tests/qtwebkit-smoke/README.md b/smoke-tests/qtwebkit-smoke/README.md index 8678732..d3b0296 100644 --- a/smoke-tests/qtwebkit-smoke/README.md +++ b/smoke-tests/qtwebkit-smoke/README.md @@ -1,6 +1,6 @@ # QtWebKit Smoke Test -Minimal Qt 5.5.1 QtWebKitWidgets app used to verify that the custom Qt build +Minimal Qt 5.15.17 QtWebKitWidgets app used to verify that the custom Qt build can compile and link a `QWebView` application. ## Files @@ -33,6 +33,19 @@ Debug output binary: `smoke-tests/qtwebkit-smoke/build-docker-debug/qtwebkit-smoke` +## Host Check + +After the Docker build has produced the smoke binary, run the headless check +from the repository root on the host: + +```bash +./run-smoke.sh --runtime-check about:blank +``` + +This uses `xvfb-run` on the host. It does not build inside the host +environment. To check the binary for unexpected shared dependencies instead, +run `./run-smoke.sh --check`. + ## Notes - Docker build is required because the smoke app must link against the SSL diff --git a/smoke-tests/qtwebkit-smoke/qtwebkit-smoke.pro b/smoke-tests/qtwebkit-smoke/qtwebkit-smoke.pro index 0234f86..b3a3aef 100644 --- a/smoke-tests/qtwebkit-smoke/qtwebkit-smoke.pro +++ b/smoke-tests/qtwebkit-smoke/qtwebkit-smoke.pro @@ -6,3 +6,5 @@ QT += core gui widgets network webkit webkitwidgets CONFIG += c++11 SOURCES += main.cpp + +include(../../src/staticplugins.pri) diff --git a/smoke-tests/qtwebkit-smoke/smoke-build-docker.sh b/smoke-tests/qtwebkit-smoke/smoke-build-docker.sh index 98efa61..ad284b2 100755 --- a/smoke-tests/qtwebkit-smoke/smoke-build-docker.sh +++ b/smoke-tests/qtwebkit-smoke/smoke-build-docker.sh @@ -9,7 +9,10 @@ fail() { exit 1 } -IMAGE_TAG="${IMAGE_TAG:-qtweb-qt5-static-poc:5.5.1}" +# shellcheck disable=SC1090 +source "${REPO_ROOT}/toolchains/qt5-static/common.sh" + +IMAGE_TAG="${IMAGE_TAG:-$QT5_STATIC_IMAGE_TAG}" JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}" BUILD_TYPE="release" @@ -27,13 +30,8 @@ done case "$BUILD_TYPE" in release|debug) - QT_PREFIX_IN_CONTAINER="/workspace/artifacts/qt5-static-5.5.1-${BUILD_TYPE}/install" + QT_PREFIX_IN_CONTAINER="/workspace/artifacts/qt5-static-${QT_VERSION}-${BUILD_TYPE}/install" BUILD_DIR_IN_CONTAINER="smoke-tests/qtwebkit-smoke/build-docker-${BUILD_TYPE}" - if [[ "$BUILD_TYPE" == "release" ]]; then - QMAKE_CONFIG_ARGS="CONFIG+=release CONFIG-=debug" - else - QMAKE_CONFIG_ARGS="CONFIG+=debug CONFIG-=release" - fi ;; *) fail "BUILD_TYPE must be release or debug, got: ${BUILD_TYPE}" @@ -45,18 +43,9 @@ docker run --rm \ -e JOBS="${JOBS}" \ -e QT_PREFIX_IN_CONTAINER="${QT_PREFIX_IN_CONTAINER}" \ -e BUILD_DIR_IN_CONTAINER="${BUILD_DIR_IN_CONTAINER}" \ - -e QMAKE_CONFIG_ARGS="${QMAKE_CONFIG_ARGS}" \ + -e BUILD_TYPE="${BUILD_TYPE}" \ -v "${REPO_ROOT}:/workspace" \ -v "${REPO_ROOT}:${REPO_ROOT}" \ -w /workspace \ "${IMAGE_TAG}" \ - /bin/bash -lc ' - set -euo pipefail - rm -rf "${BUILD_DIR_IN_CONTAINER}" - mkdir -p "${BUILD_DIR_IN_CONTAINER}" - cd "${BUILD_DIR_IN_CONTAINER}" - "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../qtwebkit-smoke.pro ${QMAKE_CONFIG_ARGS} - make -j"${JOBS}" - cp /etc/ssl/certs/ca-certificates.crt ./ca-certificates.crt - echo "built: /workspace/${BUILD_DIR_IN_CONTAINER}/qtwebkit-smoke" - ' + /workspace/smoke-tests/qtwebkit-smoke/smoke-build-entrypoint.sh diff --git a/smoke-tests/qtwebkit-smoke/smoke-build-entrypoint.sh b/smoke-tests/qtwebkit-smoke/smoke-build-entrypoint.sh new file mode 100755 index 0000000..3795361 --- /dev/null +++ b/smoke-tests/qtwebkit-smoke/smoke-build-entrypoint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +rm -rf "$BUILD_DIR_IN_CONTAINER" +mkdir -p "$BUILD_DIR_IN_CONTAINER" +cd "$BUILD_DIR_IN_CONTAINER" + +if [[ "$BUILD_TYPE" == "release" ]]; then + "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../qtwebkit-smoke.pro CONFIG+=release CONFIG-=debug +else + "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../qtwebkit-smoke.pro CONFIG+=debug CONFIG-=release +fi + +make -j"$JOBS" +cp /etc/ssl/certs/ca-certificates.crt ./ca-certificates.crt +echo "built: /workspace/${BUILD_DIR_IN_CONTAINER}/qtwebkit-smoke" diff --git a/src/QtWeb.pro b/src/QtWeb.pro index aaf4a9a..ff5b383 100644 --- a/src/QtWeb.pro +++ b/src/QtWeb.pro @@ -1,16 +1,16 @@ TEMPLATE = app TARGET = QtWeb -QT += network xml webkitwidgets widgets printsupport -CONFIG += static c++11 +QT += network network-private xml webkitwidgets widgets printsupport +CONFIG += c++11 DEFINES += QT_NO_UITOOLS +include(staticplugins.pri) + INCLUDEPATH += moc \ rcc \ uic \ . -INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtNetwork/$$QT_VERSION/QtNetwork - MOC_DIR = moc/ OBJECTS_DIR = obj/ UI_DIR = uic/ diff --git a/src/aboutdialog.h b/src/aboutdialog.h index 504cb94..260480f 100644 --- a/src/aboutdialog.h +++ b/src/aboutdialog.h @@ -54,7 +54,7 @@ class AboutDialog : public QDialog, private Ui_AboutDialog Q_OBJECT public: - AboutDialog(QWidget *parent = 0); + AboutDialog(QWidget *parent = nullptr); protected slots: void credits(); diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index 235f032..a473dee 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -307,10 +307,10 @@ bool AutoComplete::complete( QWebFrame * frame) return false; started = true; - QString pwd = QInputDialog::getText( 0, tr("Master Password"), tr("Type a master password:"), QLineEdit::Password); + QString pwd = QInputDialog::getText( nullptr, tr("Master Password"), tr("Type a master password:"), QLineEdit::Password); if ( pwd != DecryptPassword(master)) { - QMessageBox::warning(0, tr("Warning"), tr("Invalid password")); + QMessageBox::warning(nullptr, tr("Warning"), tr("Invalid password")); started = false; return false; } diff --git a/src/bookmarks.cpp b/src/bookmarks.cpp index 0eab162..81af3f7 100644 --- a/src/bookmarks.cpp +++ b/src/bookmarks.cpp @@ -68,8 +68,8 @@ BookmarksManager::BookmarksManager(QObject *parent) : QObject(parent) , m_loaded(false) , m_saveTimer(new AutoSaver(this)) - , m_bookmarkRootNode(0) - , m_bookmarkModel(0) + , m_bookmarkRootNode(nullptr) + , m_bookmarkModel(nullptr) { connect(this, SIGNAL(entryAdded(BookmarkNode *)), m_saveTimer, SLOT(changeOccurred())); @@ -107,13 +107,13 @@ void BookmarksManager::load() XbelReader reader; m_bookmarkRootNode = reader.read(bookmarkFile); if (reader.error() != QXmlStreamReader::NoError) { - QMessageBox::warning(0, tr("Loading Bookmark"), + QMessageBox::warning(nullptr, tr("Loading Bookmark"), tr("Error when loading bookmarks on line %1, column %2:\n" "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); } - BookmarkNode *toolbar = 0; - BookmarkNode *menu = 0; + BookmarkNode *toolbar = nullptr; + BookmarkNode *menu = nullptr; QList others; for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { @@ -268,7 +268,7 @@ BookmarkNode *BookmarksManager::menu() return node; } Q_ASSERT(false); - return 0; + return nullptr; } BookmarkNode *BookmarksManager::toolbar() @@ -282,7 +282,7 @@ BookmarkNode *BookmarksManager::toolbar() return node; } Q_ASSERT(false); - return 0; + return nullptr; } QStringList BookmarksManager::find_tag_urls(BookmarkNode *start_node, const QString& tag) { @@ -339,7 +339,7 @@ BookmarkNode *BookmarksManager::find_folder(BookmarkNode *start_node,const QStri return found_node; } } - return 0; + return nullptr; } BookmarksModel *BookmarksManager::bookmarksModel() @@ -357,7 +357,7 @@ void BookmarksManager::importFromIE() importRootNode->setType(BookmarkNode::Folder); importRootNode->title = (tr("Imported %1 from Internet Explorer").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); addBookmark(menu(), importRootNode); - QMessageBox::information(0, tr("Importing Bookmarks"), + QMessageBox::information(nullptr, tr("Importing Bookmarks"), tr("Successfully imported Microsoft Internet Explorer favorites.")); } } @@ -367,7 +367,7 @@ void BookmarksManager::importFromMozilla() QString path = BookmarksImport::mozillaPath(); if (path.isEmpty()) { - QMessageBox::warning(0, tr("Importing Bookmarks"), + QMessageBox::warning(nullptr, tr("Importing Bookmarks"), tr("Mozilla FireFox local profile location is not found.
Please find and import BOOKMARKS.HTML file manually.")); return; } @@ -377,14 +377,14 @@ void BookmarksManager::importFromMozilla() importRootNode->setType(BookmarkNode::Folder); importRootNode->title = (tr("Imported %1 from Mozilla FireFox").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); addBookmark(menu(), importRootNode); - QMessageBox::information(0, tr("Importing Bookmarks"), + QMessageBox::information(nullptr, tr("Importing Bookmarks"), tr("Successfully imported Mozilla FireFox bookmarks.")); } } void BookmarksManager::importFromHTML() { - QString fileName = QFileDialog::getOpenFileName(0, tr("Open File"), + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), QString(), tr("Netscape HTML Bookmarks (*.html;*.htm)")); if (fileName.isEmpty()) @@ -397,14 +397,14 @@ void BookmarksManager::importFromHTML() importRootNode->setType(BookmarkNode::Folder); importRootNode->title = (tr("Imported %1 from HTML").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); addBookmark(menu(), importRootNode); - QMessageBox::information(0, tr("Importing Bookmarks"), + QMessageBox::information(nullptr, tr("Importing Bookmarks"), tr("Successfully imported bookmarks from Netscape defined HTML file.")); } } void BookmarksManager::importBookmarks() { - QString fileName = QFileDialog::getOpenFileName(0, tr("Open File"), + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), QString(), tr("XBEL (*.xbel *.xml)")); if (fileName.isEmpty()) @@ -413,7 +413,7 @@ void BookmarksManager::importBookmarks() XbelReader reader; BookmarkNode *importRootNode = reader.read(fileName); if (reader.error() != QXmlStreamReader::NoError) { - QMessageBox::warning(0, tr("Loading Bookmark"), + QMessageBox::warning(nullptr, tr("Loading Bookmark"), tr("Error when loading bookmarks on line %1, column %2:\n" "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); } @@ -425,7 +425,7 @@ void BookmarksManager::importBookmarks() void BookmarksManager::exportBookmarks() { - QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"), + QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save File"), QString("%1 Bookmarks.xbel").arg(QCoreApplication::applicationName()), QString("XBEL (*.xbel *.xml)")); if (fileName.isEmpty()) @@ -433,7 +433,7 @@ void BookmarksManager::exportBookmarks() XbelWriter writer; if (!writer.write(fileName, m_bookmarkRootNode)) - QMessageBox::critical(0, tr("Export error"), tr("error saving bookmarks")); + QMessageBox::critical(nullptr, tr("Export error"), tr("error saving bookmarks")); } RemoveBookmarksCommand::RemoveBookmarksCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *parent, int row) @@ -656,14 +656,16 @@ int BookmarksModel::columnCount(const QModelIndex &parent) const int BookmarksModel::rowCount(const QModelIndex &parent) const { + BookmarkNode *bookmarksRoot = m_bookmarksManager ? m_bookmarksManager->bookmarks() : nullptr; + if (parent.column() > 0) return 0; if (!parent.isValid()) - return m_bookmarksManager->bookmarks()->children().count(); + return bookmarksRoot ? bookmarksRoot->children().count() : 0; const BookmarkNode *item = static_cast(parent.internalPointer()); - return item->children().count(); + return item ? item->children().count() : 0; } QModelIndex BookmarksModel::index(int row, int column, const QModelIndex &parent) const @@ -682,7 +684,7 @@ QModelIndex BookmarksModel::parent(const QModelIndex &index) const return QModelIndex(); BookmarkNode *itemNode = node(index); - BookmarkNode *parentNode = (itemNode ? itemNode->parent() : 0); + BookmarkNode *parentNode = (itemNode ? itemNode->parent() : nullptr); if (!parentNode || parentNode == m_bookmarksManager->bookmarks()) return QModelIndex(); @@ -836,7 +838,7 @@ BookmarkNode *BookmarksModel::node(const QModelIndex &index) const { BookmarkNode *itemNode = static_cast(index.internalPointer()); if (!itemNode) - return m_bookmarksManager->bookmarks(); + return m_bookmarksManager ? m_bookmarksManager->bookmarks() : nullptr; return itemNode; } @@ -887,7 +889,7 @@ AddBookmarkDialog::AddBookmarkDialog(const QString &url, const QString &title, c settings.beginGroup(QLatin1String("websettings")); if (!m_default_folder.isEmpty()) { - BookmarkNode* folder = m_bookmarksManager->find_folder(NULL, m_default_folder); + BookmarkNode* folder = m_bookmarksManager->find_folder(nullptr, m_default_folder); if (folder) { QModelIndex ix = m_proxyModel->mapFromSource(model->index(folder)); @@ -948,7 +950,7 @@ void AddBookmarkDialog::acceptDefaultLocation() BookmarksMenu::BookmarksMenu(QWidget *parent) : ModelMenu(parent) - , m_bookmarksManager(0) + , m_bookmarksManager(nullptr) { connect(this, SIGNAL(activated(const QModelIndex &)), this, SLOT(activated(const QModelIndex &))); @@ -1152,7 +1154,7 @@ void BookmarksToolBar::dropEvent(QDropEvent *event) { QList urls = mimeData->urls(); int row = -1; - BookmarkNode * del_node = NULL; + BookmarkNode * del_node = nullptr; QModelIndex parentIndex = m_root; if( mimeData->hasText()) { @@ -1261,6 +1263,8 @@ void BookmarksToolBar::build() void BookmarksToolBar::deleteBookmark(const QUrl &url, const QString &title) { + Q_UNUSED(url); + for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); @@ -1280,6 +1284,8 @@ void BookmarksToolBar::deleteBookmark(const QUrl &url, const QString &title) void BookmarksToolBar::renameBookmark(const QUrl &url, const QString &title, const QString &new_title) { + Q_UNUSED(url); + for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); @@ -1378,7 +1384,7 @@ void BookmarkToolButton::mouseMoveEvent(QMouseEvent *event) mimeData->setProperty( "move", QVariant(true)); drag->setMimeData(mimeData); - Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); + drag->exec(Qt::CopyAction | Qt::MoveAction); QToolButton::mousePressEvent(event); } @@ -1406,6 +1412,8 @@ QUrl BookmarkToolButton::url() const void BookmarkToolButton::contextMenuRequested(const QPoint &pt) { + Q_UNUSED(pt); + QMenu menu; menu.addAction(tr("Open"), this, SLOT(openBookmark())); menu.addAction(tr("Open New Tab"), this, SLOT(openBookmarkNewTab())); diff --git a/src/bookmarks.h b/src/bookmarks.h index 95568ff..9b01092 100644 --- a/src/bookmarks.h +++ b/src/bookmarks.h @@ -45,7 +45,7 @@ class BookmarksManager : public QObject void entryChanged(BookmarkNode *item); public: - BookmarksManager(QObject *parent = 0); + BookmarksManager(QObject *parent = nullptr); ~BookmarksManager(); void addBookmark(BookmarkNode *parent, BookmarkNode *node, int row = -1); @@ -159,7 +159,7 @@ public slots: SeparatorRole = Qt::UserRole + 4 }; - BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent = 0); + BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent = nullptr); inline BookmarksManager *bookmarksManager() const { return m_bookmarksManager; } QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; @@ -180,7 +180,7 @@ public slots: BookmarkNode *node(const QModelIndex &index) const; QModelIndex index(BookmarkNode *node) const; - void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ) {;} + void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ) { Q_UNUSED(column); Q_UNUSED(order); } private: @@ -198,7 +198,7 @@ class BookmarksMenu : public ModelMenu void openUrl(const QUrl &url); public: - BookmarksMenu(QWidget *parent = 0); + BookmarksMenu(QWidget *parent = nullptr); void setInitialActions(QList actions); protected: @@ -221,7 +221,7 @@ class AddBookmarkProxyModel : public QSortFilterProxyModel { Q_OBJECT public: - AddBookmarkProxyModel(QObject * parent = 0); + AddBookmarkProxyModel(QObject * parent = nullptr); int columnCount(const QModelIndex & parent = QModelIndex()) const; protected: @@ -237,7 +237,7 @@ class AddBookmarkDialog : public QDialog, public Ui_AddBookmarkDialog Q_OBJECT public: - AddBookmarkDialog(const QString &url, const QString &title, const QString& default_folder, QWidget *parent = 0, BookmarksManager *bookmarkManager = 0); + AddBookmarkDialog(const QString &url, const QString &title, const QString& default_folder, QWidget *parent = nullptr, BookmarksManager *bookmarkManager = nullptr); void acceptDefaultLocation(); private slots: @@ -260,7 +260,7 @@ class BookmarksDialog : public QDialog, public Ui_BookmarksDialog void openUrl(const QUrl &url); public: - BookmarksDialog(QWidget *parent = 0, BookmarksManager *manager = 0); + BookmarksDialog(QWidget *parent = nullptr, BookmarksManager *manager = nullptr); ~BookmarksDialog(); private slots: @@ -290,7 +290,7 @@ class BookmarksToolBar : public QToolBar void openUrl(const QUrl &url); public: - BookmarksToolBar(BookmarksModel *model, QWidget *parent = 0); + BookmarksToolBar(BookmarksModel *model, QWidget *parent = nullptr); void setRootIndex(const QModelIndex &index); QModelIndex rootIndex() const; @@ -333,7 +333,7 @@ public slots: void addFolder(); public: - BookmarkToolButton(QUrl url, QWidget *parent = 0); + BookmarkToolButton(QUrl url, QWidget *parent = nullptr); QUrl url() const; protected: diff --git a/src/bookmarksimport.cpp b/src/bookmarksimport.cpp index a90d18f..7fdd966 100644 --- a/src/bookmarksimport.cpp +++ b/src/bookmarksimport.cpp @@ -134,7 +134,7 @@ BookmarkNode *BookmarksImport::importFromIE() { QString path = ieFavoritesPath(); if (path.isEmpty()) - return NULL; + return nullptr; BookmarkNode* root = new BookmarkNode(); @@ -258,12 +258,9 @@ void ParseHtmlBookmarks( QString& books , BookmarkNode* root) BookmarkNode *BookmarksImport::importFromHtml( QString path ) { - BookmarkNode* root = new BookmarkNode(); - - QFile f(path); if (!f.open(QIODevice::ReadOnly | QIODevice::Text) ) - return NULL; + return nullptr; bool bIsNetscape = false; // check format @@ -283,11 +280,12 @@ BookmarkNode *BookmarksImport::importFromHtml( QString path ) { // Format not supported f.close(); - QMessageBox::warning(0, QObject::tr("Importing Bookmarks"), + QMessageBox::warning(nullptr, QObject::tr("Importing Bookmarks"), QObject::tr("HTML format is not supported.
Please make sure that HTML file type is NETSCAPE-Bookmark-file-1.")); - return NULL; + return nullptr; } + BookmarkNode* root = new BookmarkNode(); QString books; QByteArray ba; bool bUtf8 = false; @@ -328,4 +326,3 @@ BookmarkNode *BookmarksImport::importFromHtml( QString path ) return root; } - diff --git a/src/browserapplication.cpp b/src/browserapplication.cpp index 07583d0..c9217a4 100644 --- a/src/browserapplication.cpp +++ b/src/browserapplication.cpp @@ -80,14 +80,14 @@ #include "torrent/torrentwindow.h" -DownloadManager *BrowserApplication::s_downloadManager = 0; -TorrentWindow *BrowserApplication::s_torrents = 0; -HistoryManager *BrowserApplication::s_historyManager = 0; -NetworkAccessManager *BrowserApplication::s_networkAccessManager = 0; -BookmarksManager *BrowserApplication::s_bookmarksManager = 0; +DownloadManager *BrowserApplication::s_downloadManager = nullptr; +TorrentWindow *BrowserApplication::s_torrents = nullptr; +HistoryManager *BrowserApplication::s_historyManager = nullptr; +NetworkAccessManager *BrowserApplication::s_networkAccessManager = nullptr; +BookmarksManager *BrowserApplication::s_bookmarksManager = nullptr; QMap BrowserApplication::s_hostIcons; bool BrowserApplication::s_resetOnQuit = false; -AutoComplete* BrowserApplication::s_autoCompleter = 0; +AutoComplete* BrowserApplication::s_autoCompleter = nullptr; bool BrowserApplication::s_portableRunMode = false; bool BrowserApplication::s_startResizeOnMouseweelClick = true; QReadWriteLock lockIcons; @@ -99,7 +99,7 @@ int BrowserApplication::getApplicationBuild() BrowserApplication::BrowserApplication(int &argc, char **argv) : QApplication(argc, argv) - , m_localServer(0) + , m_localServer(nullptr) , quiting(false) { QCoreApplication::setOrganizationName(QLatin1String("QtWeb.NET")); @@ -195,7 +195,7 @@ void BrowserApplication::CheckSetTranslator() bool removeDir(const QString &dirName) { - bool result; + bool result = true; QDir dir(dirName); if (dir.exists()) { @@ -241,9 +241,10 @@ void BrowserApplication::definePortableRunMode() { // Copy settings from base template to temporary storage QDir temp_dir(QDir::temp()); - bool res = temp_dir.mkdir(settings.organizationName()); - res = temp_dir.cd(settings.organizationName()); - res = QFile::copy( settings.fileName(), temp_dir.absolutePath() + QDir::separator() + settings.applicationName() + ".ini" ); + temp_dir.mkdir(settings.organizationName()); + temp_dir.cd(settings.organizationName()); + QFile::copy(settings.fileName(), + temp_dir.absolutePath() + QDir::separator() + settings.applicationName() + ".ini"); // Change path to settings to the temp storage QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, QDir::temp().tempPath()); } @@ -418,7 +419,6 @@ void BrowserApplication::loadSettings() defaultSettings->setAttribute(QWebSettings::ZoomTextOnly, zoom_text_only); defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, settings.value(QLatin1String("enableJavascript"), true).toBool()); - defaultSettings->setAttribute(QWebSettings::PluginsEnabled, settings.value(QLatin1String("enablePlugins"), true).toBool()); defaultSettings->setAttribute(QWebSettings::AutoLoadImages, settings.value(QLatin1String("autoLoadImages"), true).toBool()); defaultSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, ! (settings.value(QLatin1String("blockPopups"), true).toBool())); @@ -523,7 +523,7 @@ void BrowserApplication::restoreLastSession() settings.beginGroup(QLatin1String("MainWindow")); if (settings.value(QLatin1String("restoring"), false).toBool()) { - QMessageBox::information(0, tr("Session restore failed"), + QMessageBox::information(nullptr, tr("Session restore failed"), tr("The saved session will not be restored because QtWeb crashed before while trying to restore this session.")); return; } @@ -553,7 +553,7 @@ void BrowserApplication::restoreLastSession() windows.append(windowState); } for (int i = 0; i < windows.count(); ++i) { - BrowserMainWindow *newWindow = 0; + BrowserMainWindow *newWindow = nullptr; if (i == 0 && m_mainWindows.count() >= 1) { newWindow = mainWindow(); } else { @@ -565,7 +565,7 @@ void BrowserApplication::restoreLastSession() bool BrowserApplication::isTheOnlyBrowser() const { - return (m_localServer != 0); + return (m_localServer != nullptr); } void BrowserApplication::installTranslator(const QString &name) diff --git a/src/browserapplication.h b/src/browserapplication.h index a93ee79..6bbf74e 100644 --- a/src/browserapplication.h +++ b/src/browserapplication.h @@ -82,7 +82,7 @@ class BrowserApplication : public QApplication bool isTheOnlyBrowser() const; BrowserMainWindow *mainWindow(); QList mainWindows(); - QIcon icon(const QUrl &url, const WebView *webView = 0) const; + QIcon icon(const QUrl &url, const WebView *webView = nullptr) const; void CheckSetTranslator(); @@ -115,7 +115,7 @@ class BrowserApplication : public QApplication static void resetSettings( bool reload); static QString dataLocation(); static QString downloadsLocation(bool create_dir); - static bool existDownloadManager() {return s_downloadManager != NULL;} + static bool existDownloadManager() {return s_downloadManager != nullptr;} public slots: BrowserMainWindow *newMainWindow(); void restoreLastSession(); diff --git a/src/browsermainwindow.cpp b/src/browsermainwindow.cpp index 04268f8..4f43232 100644 --- a/src/browsermainwindow.cpp +++ b/src/browsermainwindow.cpp @@ -88,51 +88,50 @@ extern bool ShellExec(QString path); BrowserMainWindow::BrowserMainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) + , findWidget(nullptr) + , m_showMenuIcons(false) + , m_buttonsBar(nullptr) , m_tabWidget(new TabWidget(this)) - , findWidget(0) - , m_navSplit(0) - , m_buttonsBar(0) - , m_historyBack(0) - , m_historyForward(0) - , m_stop(0) - , m_reload(0) - , m_stylesMenu(0) - , m_encodingMenu(0) - , m_styles(0) - , m_emptyDiskCache(0) - , m_viewZoomTextOnly(0) , m_positionRestored(0) - , m_goBackAction(0) - , m_goForwardAction(0) - , m_addBookmarkAction(0) - , m_homeAction(0) - , m_prefsAction(0) - , m_imagesAction(0) - , m_proxyAction(0) - , m_restoreTabAction(0) - , m_resetAction(0) - , m_enableInspector(0) - , m_inspectElement(0) , m_dumpActionQuit(false) - , m_showMenuIcons(false) - , m_inspectAction(0) - , m_keyboardAction(0) - , m_textSizeAction(0) - , m_bookmarksAction(0) - , m_sizesMenu(0) - , m_textSizeLarger(0) - , m_textSizeNormal(0) - , m_textSizeSmaller(0) - , m_compMenu(0) -// , m_compatMenu(0) - , m_compatAction(0) - , m_compIE(0) - , m_compMozilla(0) - , m_compQtWeb(0) - , m_compOpera(0) - , m_compSafari(0) - , m_compChrome(0) - , m_compCustom(0) + , m_navSplit(nullptr) + , m_historyBack(nullptr) + , m_historyForward(nullptr) + , m_styles(nullptr) + , m_stylesMenu(nullptr) + , m_encodingMenu(nullptr) + , m_sizesMenu(nullptr) + , m_compMenu(nullptr) + , m_stop(nullptr) + , m_reload(nullptr) + , m_viewZoomTextOnly(nullptr) + , m_emptyDiskCache(nullptr) + , m_goBackAction(nullptr) + , m_goForwardAction(nullptr) + , m_addBookmarkAction(nullptr) + , m_homeAction(nullptr) + , m_prefsAction(nullptr) + , m_imagesAction(nullptr) + , m_proxyAction(nullptr) + , m_restoreTabAction(nullptr) + , m_resetAction(nullptr) + , m_enableInspector(nullptr) + , m_inspectElement(nullptr) + , m_inspectAction(nullptr) + , m_keyboardAction(nullptr) + , m_textSizeAction(nullptr) + , m_bookmarksAction(nullptr) + , m_compatAction(nullptr) + , m_compIE(nullptr) + , m_compMozilla(nullptr) + , m_compOpera(nullptr) + , m_compSafari(nullptr) + , m_compQtWeb(nullptr) + , m_compChrome(nullptr) + , m_compCustom(nullptr) + , m_textSizeLarger(nullptr) + , m_textSizeNormal(nullptr) + , m_textSizeSmaller(nullptr) { setAttribute(Qt::WA_DeleteOnClose, true); statusBar()->setSizeGripEnabled(true); @@ -314,8 +313,6 @@ bool BrowserMainWindow::restoreState(const QByteArray &state) bool showStatusbar; bool showTabBarWhenOneTab; QByteArray splitterState1;//, splitterState2; - bool bMenu = true; - stream >> tabState; stream >> showTabBarWhenOneTab; @@ -851,14 +848,6 @@ void BrowserMainWindow::setupMenu() this->addAction(m_disableCookies); m_disableCookies->setCheckable(true); - // Disable Plug-Ins - m_disablePlugIns = new QAction( cmds.PlugInsTitle(), this); - m_disablePlugIns->setShortcuts(cmds.PlugInsShortcuts()); - connect(m_disablePlugIns, SIGNAL(triggered()), this, SLOT(slotDisablePlugIns())); - privacyMenu->addAction(m_disablePlugIns); - this->addAction(m_disablePlugIns); - m_disablePlugIns->setCheckable(true); - // Disable UserAgent m_disableUserAgent = new QAction( cmds.AgentTitle(), this); m_disableUserAgent->setShortcuts(cmds.AgentShortcuts()); @@ -2113,7 +2102,7 @@ void BrowserMainWindow::loadPage(const QString &page) if (bm) { // if tags are detected - load all urls, and return - QStringList urls = bm->find_tag_urls(NULL, page); + QStringList urls = bm->find_tag_urls(nullptr, page); if (!urls.isEmpty()) { for(int i = 0; i < urls.size(); i++) @@ -2209,7 +2198,7 @@ void BrowserMainWindow::slotAboutToShowForwardMenu() void BrowserMainWindow::slotAboutToShowWindowMenu() { - static QAction *downs = NULL, *tors = NULL; + static QAction *downs = nullptr, *tors = nullptr; bool empty = m_windowMenu->isEmpty(); if (!empty) { @@ -2413,7 +2402,6 @@ void BrowserMainWindow::slotAboutToShowPrivacyMenu() QWebSettings* defaultSettings = QWebSettings::globalSettings(); m_disableJavaScript->setChecked(!defaultSettings->testAttribute(QWebSettings::JavascriptEnabled)); m_disableImages->setChecked(!defaultSettings->testAttribute(QWebSettings::AutoLoadImages)); - m_disablePlugIns->setChecked(!defaultSettings->testAttribute(QWebSettings::PluginsEnabled)); m_disablePopUps->setChecked(!defaultSettings->testAttribute(QWebSettings::JavascriptCanOpenWindows)); @@ -2454,16 +2442,6 @@ void BrowserMainWindow::slotDisableImages() checkToolBarButtons(); } -void BrowserMainWindow::slotDisablePlugIns() -{ - bool enabled = !m_disablePlugIns->isChecked(); - QWebSettings* defaultSettings = QWebSettings::globalSettings(); - defaultSettings->setAttribute(QWebSettings::PluginsEnabled, enabled); - QSettings settings; - settings.beginGroup(QLatin1String("websettings")); - settings.setValue(QLatin1String("enablePlugins"), enabled); -} - void BrowserMainWindow::slotDisableCookies() { bool enabled = !m_disableCookies->isChecked(); diff --git a/src/browsermainwindow.h b/src/browsermainwindow.h index 8092e3a..8e13064 100644 --- a/src/browsermainwindow.h +++ b/src/browsermainwindow.h @@ -64,7 +64,7 @@ class BrowserMainWindow : public QMainWindow { Q_OBJECT public: - BrowserMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + BrowserMainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = nullptr); ~BrowserMainWindow(); QSize sizeHint() const; @@ -134,7 +134,6 @@ private slots: void slotDisableJavaScript(); void slotDisableImages(); void slotDisableCookies(); - void slotDisablePlugIns(); void slotDisableUserAgent(); void slotEnableProxy(); void slotDisablePopUps(); @@ -240,7 +239,6 @@ private slots: QAction *m_disableJavaScript; QAction *m_disableImages; QAction *m_disableCookies; - QAction *m_disablePlugIns; QAction *m_disableUserAgent; QAction *m_enableProxy; QAction *m_disablePopUps; diff --git a/src/certificateinfo.h b/src/certificateinfo.h index 072f46e..d6320ca 100644 --- a/src/certificateinfo.h +++ b/src/certificateinfo.h @@ -34,7 +34,7 @@ class CertificateInfo : public QDialog { Q_OBJECT public: - CertificateInfo(QString host, QWidget *parent = 0); + CertificateInfo(QString host, QWidget *parent = nullptr); ~CertificateInfo(); void setCertificateChain(const QList &chain); diff --git a/src/chasewidget.h b/src/chasewidget.h index 2eb20b0..76dbc68 100644 --- a/src/chasewidget.h +++ b/src/chasewidget.h @@ -58,7 +58,7 @@ class ChaseWidget : public QWidget { Q_OBJECT public: - ChaseWidget(QWidget *parent = 0, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false); + ChaseWidget(QWidget *parent = nullptr, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false); void setAnimated(bool value); void setPixmapEnabled(bool enable); diff --git a/src/closeapp.h b/src/closeapp.h index a39d2e9..ec6a058 100644 --- a/src/closeapp.h +++ b/src/closeapp.h @@ -27,7 +27,7 @@ class CloseApp : public QDialog Q_OBJECT public: - CloseApp(QWidget *parent = 0); + CloseApp(QWidget *parent = nullptr); ~CloseApp(); private: diff --git a/src/commands.cpp b/src/commands.cpp index 190b31d..37a661a 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -21,17 +21,17 @@ #include -MenuCommands::MenuCommands(void) +MenuCommands::MenuCommands() { m_data.beginGroup(QLatin1String("MenuCommands")); } -MenuCommands::~MenuCommands(void) +MenuCommands::~MenuCommands() { m_data.endGroup(); } -#define MAX_COMMANDS 91 +#define MAX_COMMANDS 90 int MenuCommands::GetCommandsCount() const { @@ -221,9 +221,6 @@ QString MenuCommands::Get(int ind, What w) const if (cur++ == ind) return (w == Key ? CookiesKey() : (w == Title? CookiesTitle() : GetStr(CookiesShortcuts()))); - if (cur++ == ind) - return (w == Key ? PlugInsKey() : (w == Title? PlugInsTitle() : GetStr(PlugInsShortcuts()))); - if (cur++ == ind) return (w == Key ? AgentKey() : (w == Title? AgentTitle() : GetStr(AgentShortcuts()))); diff --git a/src/commands.h b/src/commands.h index d7297f6..f85fbda 100644 --- a/src/commands.h +++ b/src/commands.h @@ -291,10 +291,6 @@ class MenuCommands : public QObject QString CookiesTitle() const { return m_data.value( CookiesKey() , tr("Disable &Cookies")).toString(); } QList CookiesShortcuts() const { return loadShortcuts( CookiesKey(), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_C) ); } - QString PlugInsKey() const { return QLatin1String("PlugIns"); } - QString PlugInsTitle() const { return m_data.value( PlugInsKey() , tr("Disable Plu&g-Ins")).toString(); } - QList PlugInsShortcuts() const { return loadShortcuts( PlugInsKey(), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_G) ); } - QString AgentKey() const { return QLatin1String("UserAgent"); } QString AgentTitle() const { return m_data.value( AgentKey() , tr("Disable User&Agent")).toString(); } QList AgentShortcuts() const { return loadShortcuts( AgentKey(), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_A) ); } @@ -425,4 +421,4 @@ class MenuCommands : public QObject QSettings m_data; }; -#endif // MENUCOMMANDS_H \ No newline at end of file +#endif // MENUCOMMANDS_H diff --git a/src/cookiejar.h b/src/cookiejar.h index 864893d..0a04379 100644 --- a/src/cookiejar.h +++ b/src/cookiejar.h @@ -82,7 +82,7 @@ class CookieJar : public QNetworkCookieJar KeepUntilTimeLimit }; - CookieJar(QObject *parent = 0); + CookieJar(QObject *parent = nullptr); ~CookieJar(); QList cookiesForUrl(const QUrl &url) const; @@ -128,7 +128,7 @@ class CookieModel : public QAbstractTableModel Q_OBJECT public: - CookieModel(CookieJar *jar, QObject *parent = 0); + CookieModel(CookieJar *jar, QObject *parent = nullptr); QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; @@ -150,7 +150,7 @@ class CookiesDialog : public QDialog, public Ui_CookiesDialog Q_OBJECT public: - CookiesDialog(CookieJar *cookieJar, QWidget *parent = 0); + CookiesDialog(CookieJar *cookieJar, QWidget *parent = nullptr); private: QSortFilterProxyModel *m_proxyModel; @@ -162,7 +162,7 @@ class CookieExceptionsModel : public QAbstractTableModel friend class CookiesExceptionsDialog; public: - CookieExceptionsModel(CookieJar *cookieJar, QObject *parent = 0); + CookieExceptionsModel(CookieJar *cookieJar, QObject *parent = nullptr); void reload(); QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; @@ -184,7 +184,7 @@ class CookiesExceptionsDialog : public QDialog, public Ui_CookiesExceptionsDialo Q_OBJECT public: - CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent = 0); + CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent = nullptr); private slots: void block(); diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 8acfc8d..6e6d3b2 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -87,9 +87,9 @@ QString DefaultDownloadPath(bool create_dir) DownloadItem::DownloadItem(QNetworkReply *reply, bool requestFileName, QWidget *parent) : QWidget(parent) , m_reply(reply) + , m_to_delete(false) , m_requestFileName(requestFileName) , m_bytesReceived(0) - , m_to_delete(false) , m_finished(false) { setupUi(this); @@ -246,6 +246,7 @@ void DownloadItem::stop() void DownloadItem::mouseDoubleClickEvent ( QMouseEvent * event ) { + Q_UNUSED(event); open(); } @@ -465,7 +466,7 @@ bool DownloadItem::checkAddTorrent() DownloadManager::DownloadManager(QWidget *parent) : QDialog(parent, Qt::Window) , m_manager(BrowserApplication::networkAccessManager()) - , m_iconProvider(0) + , m_iconProvider(nullptr) , m_removePolicy(Never) { setupUi(this); @@ -502,6 +503,7 @@ DownloadManager::~DownloadManager() void DownloadManager::openItem(const QModelIndex& index) { + Q_UNUSED(index); } int DownloadManager::activeDownloads() const @@ -633,7 +635,7 @@ void DownloadManager::save() const void DownloadManager::addItem(const QUrl& url, QString filename, bool done) { - DownloadItem *item = new DownloadItem(0, false, this); + DownloadItem *item = new DownloadItem(nullptr, false, this); item->m_output.setFileName(filename); item->setOutputTitle(); @@ -736,7 +738,7 @@ void DownloadManager::cleanup_list() updateItemCount(); if (m_downloads.isEmpty() && m_iconProvider) { delete m_iconProvider; - m_iconProvider = 0; + m_iconProvider = nullptr; } save(); } @@ -781,7 +783,7 @@ void DownloadManager::cleanup_full() updateItemCount(); if (m_downloads.isEmpty() && m_iconProvider) { delete m_iconProvider; - m_iconProvider = 0; + m_iconProvider = nullptr; } save(); } @@ -824,8 +826,13 @@ bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent) || m_downloadManager->m_downloads.at(i)->tryAgainButton->isEnabled()) { beginRemoveRows(parent, i, i); DownloadItem* item = m_downloadManager->m_downloads.takeAt(i); - - if (item && item->m_output.exists()) + + if (!item) { + endRemoveRows(); + continue; + } + + if (item->m_output.exists()) { if (item->m_must_be_deleted) item->m_output.remove(); @@ -838,4 +845,3 @@ bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent) m_downloadManager->save(); return true; } - diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 1dff290..15f9113 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -57,7 +57,7 @@ class DownloadItem : public QWidget, public Ui_DownloadItem void statusChanged(); public: - DownloadItem(QNetworkReply *reply = 0, bool requestFileName = false, QWidget *parent = 0); + DownloadItem(QNetworkReply *reply = nullptr, bool requestFileName = false, QWidget *parent = nullptr); ~DownloadItem(); bool downloading() const; bool downloadedSuccessfully() const; @@ -124,7 +124,7 @@ class DownloadManager : public QDialog, public Ui_DownloadDialog SuccessFullDownload }; - DownloadManager(QWidget *parent = 0); + DownloadManager(QWidget *parent = nullptr); ~DownloadManager(); int activeDownloads() const; void load(); @@ -165,7 +165,7 @@ class DownloadModel : public QAbstractListModel Q_OBJECT public: - DownloadModel(DownloadManager *downloadManager, QObject *parent = 0); + DownloadModel(DownloadManager *downloadManager, QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); diff --git a/src/edittableview.h b/src/edittableview.h index fe42c46..913d8c0 100644 --- a/src/edittableview.h +++ b/src/edittableview.h @@ -48,7 +48,7 @@ class EditTableView : public QTableView Q_OBJECT public: - EditTableView(QWidget *parent = 0); + EditTableView(QWidget *parent = nullptr); void keyPressEvent(QKeyEvent *event); public slots: diff --git a/src/edittreeview.h b/src/edittreeview.h index 6cbee58..e6eb527 100644 --- a/src/edittreeview.h +++ b/src/edittreeview.h @@ -48,7 +48,7 @@ class EditTreeView : public QTreeView Q_OBJECT public: - EditTreeView(QWidget *parent = 0); + EditTreeView(QWidget *parent = nullptr); void keyPressEvent(QKeyEvent *event); public slots: diff --git a/src/exlineedit.cpp b/src/exlineedit.cpp index afcc4e0..26de917 100644 --- a/src/exlineedit.cpp +++ b/src/exlineedit.cpp @@ -79,7 +79,6 @@ void ClearButton::paintEvent(QPaintEvent *event) int height = this->height(); painter.setRenderHint(QPainter::Antialiasing, true); - QColor color = palette().color(QPalette::Midlight); painter.setBrush(isDown() ? palette().color(QPalette::Mid) : palette().color(QPalette::Midlight)); @@ -172,9 +171,9 @@ void LineEdit::keyPressEvent ( QKeyEvent * event ) //////////////////////////////////////// ExLineEdit::ExLineEdit(QWidget *parent, bool fix_url) : QWidget(parent) - , m_leftWidget(0) + , m_leftWidget(nullptr) , m_lineEdit(new LineEdit(this, fix_url)) - , m_clearButton(0) + , m_clearButton(nullptr) { setFocusPolicy(m_lineEdit->focusPolicy()); setAttribute(Qt::WA_InputMethodEnabled); @@ -328,4 +327,3 @@ void ExLineEdit::paintEvent(QPaintEvent *) style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); } - diff --git a/src/exlineedit.h b/src/exlineedit.h index 61ac742..f47886b 100644 --- a/src/exlineedit.h +++ b/src/exlineedit.h @@ -54,7 +54,7 @@ class ClearButton : public QAbstractButton Q_OBJECT public: - ClearButton(QWidget *parent = 0); + ClearButton(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); public slots: @@ -71,7 +71,7 @@ class LineEdit : public QLineEdit public: - LineEdit(QWidget *parent = 0, bool fix_url = false); + LineEdit(QWidget *parent = nullptr, bool fix_url = false); protected: void focusInEvent(QFocusEvent *); @@ -91,7 +91,7 @@ class ExLineEdit : public QWidget Q_OBJECT public: - ExLineEdit(QWidget *parent = 0, bool fix_url = false); + ExLineEdit(QWidget *parent = nullptr, bool fix_url = false); inline QLineEdit *lineEdit() const { return m_lineEdit; } diff --git a/src/findwidget.h b/src/findwidget.h index cc0bcb7..3dc8e10 100644 --- a/src/findwidget.h +++ b/src/findwidget.h @@ -55,7 +55,7 @@ class FindWidget : public QWidget { Q_OBJECT public: - FindWidget(QWidget *parent = 0); + FindWidget(QWidget *parent = nullptr); ~FindWidget(); void show(); diff --git a/src/googlesuggest.cpp b/src/googlesuggest.cpp index d68cce0..952d235 100644 --- a/src/googlesuggest.cpp +++ b/src/googlesuggest.cpp @@ -152,19 +152,17 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) } if (ev->type() == QEvent::KeyPress) { - - bool consumed = false; int key = static_cast(ev)->key(); switch (key) { case Qt::Key_Enter: case Qt::Key_Return: doneCompletion(); - consumed = true; + return true; case Qt::Key_Escape: editor->setFocus(); popup->hide(); - consumed = true; + return true; case Qt::Key_Up: case Qt::Key_Down: @@ -181,7 +179,7 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) break; } - return consumed; + return false; } return false; diff --git a/src/googlesuggest.h b/src/googlesuggest.h index b52eaad..60e1880 100644 --- a/src/googlesuggest.h +++ b/src/googlesuggest.h @@ -57,7 +57,7 @@ class GSuggestCompletion : public QObject Q_OBJECT public: - GSuggestCompletion(QLineEdit *parent = 0); + GSuggestCompletion(QLineEdit *parent = nullptr); ~GSuggestCompletion(); bool eventFilter(QObject *obj, QEvent *ev); void showCompletion(const QStringList &choices, const QStringList &hits); diff --git a/src/history.cpp b/src/history.cpp index f35f0ad..cb9faa0 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -69,10 +69,10 @@ HistoryManager::HistoryManager(QObject *parent) : QWebHistoryInterface(parent) , m_saveTimer(new AutoSaver(this)) , m_historyLimit(7) - , m_historyModel(0) - , m_historyFilterModel(0) - , m_historyTreeModel(0) , m_historyCleaned(false) + , m_historyModel(nullptr) + , m_historyFilterModel(nullptr) + , m_historyTreeModel(nullptr) { m_expiredTimer.setSingleShot(true); connect(&m_expiredTimer, SIGNAL(timeout()), @@ -534,7 +534,7 @@ int HistoryMenuModel::rowCount(const QModelIndex &parent) const return bumpedItems + folders; } - if (parent.internalId() == -1) { + if (parent.internalId() == quintptr(-1)) { if (parent.row() < bumpedRows()) return 0; } @@ -559,7 +559,7 @@ QModelIndex HistoryMenuModel::mapToSource(const QModelIndex &proxyIndex) const if (!proxyIndex.isValid()) return QModelIndex(); - if (proxyIndex.internalId() == -1) { + if (proxyIndex.internalId() == quintptr(-1)) { int bumpedItems = bumpedRows(); if (proxyIndex.row() < bumpedItems) return m_treeModel->index(proxyIndex.row(), proxyIndex.column(), m_treeModel->index(0, 0)); @@ -615,7 +615,7 @@ QModelIndex HistoryMenuModel::parent(const QModelIndex &index) const HistoryMenu::HistoryMenu(QWidget *parent) : ModelMenu(parent) - , m_history(0) + , m_history(nullptr) { connect(this, SIGNAL(activated(const QModelIndex &)), this, SLOT(activated(const QModelIndex &))); @@ -1174,9 +1174,7 @@ QModelIndex HistoryTreeModel::parent(const QModelIndex &index) const bool HistoryTreeModel::hasChildren(const QModelIndex &parent) const { QModelIndex grandparent = parent.parent(); - if (!grandparent.isValid()) - return true; - return false; + return !grandparent.isValid(); } Qt::ItemFlags HistoryTreeModel::flags(const QModelIndex &index) const diff --git a/src/history.h b/src/history.h index 701ee3b..2cfb7a1 100644 --- a/src/history.h +++ b/src/history.h @@ -90,7 +90,7 @@ class HistoryManager : public QWebHistoryInterface void entryUpdated(int offset); public: - HistoryManager(QObject *parent = 0); + HistoryManager(QObject *parent = nullptr); ~HistoryManager(); bool historyContains(const QString &url) const; @@ -152,7 +152,7 @@ public slots: UrlStringRole = Qt::UserRole + 4 }; - HistoryModel(HistoryManager *history, QObject *parent = 0); + HistoryModel(HistoryManager *history, QObject *parent = nullptr); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; @@ -173,7 +173,7 @@ class HistoryFilterModel : public QAbstractProxyModel Q_OBJECT public: - HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = 0); + HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = nullptr); inline bool historyContains(const QString &url) const { load(); return m_historyHash.contains(url); } @@ -217,7 +217,7 @@ class HistoryMenuModel : public QAbstractProxyModel Q_OBJECT public: - HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = 0); + HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = nullptr); int columnCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; QModelIndex mapFromSource(const QModelIndex & sourceIndex) const; @@ -240,7 +240,7 @@ class HistoryMenu : public ModelMenu void openUrl(const QUrl &url); public: - HistoryMenu(QWidget *parent = 0); + HistoryMenu(QWidget *parent = nullptr); void setInitialActions(QList actions); protected: @@ -264,7 +264,7 @@ class HistoryCompletionModel : public QAbstractProxyModel Q_OBJECT public: - HistoryCompletionModel(QObject *parent = 0); + HistoryCompletionModel(QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; @@ -287,7 +287,7 @@ class HistoryTreeModel : public QAbstractProxyModel Q_OBJECT public: - HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = 0); + HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int columnCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; @@ -321,7 +321,7 @@ class TreeProxyModel : public QSortFilterProxyModel Q_OBJECT public: - TreeProxyModel(QObject *parent = 0); + TreeProxyModel(QObject *parent = nullptr); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; @@ -337,7 +337,7 @@ class HistoryDialog : public QDialog, public Ui_HistoryDialog void openUrl(const QUrl &url); public: - HistoryDialog(QWidget *parent = 0, HistoryManager *history = 0); + HistoryDialog(QWidget *parent = nullptr, HistoryManager *history = nullptr); private slots: void customContextMenuRequested(const QPoint &pos); diff --git a/src/htmls/Welcome.html b/src/htmls/Welcome.html index cee86d2..6b7e468 100644 --- a/src/htmls/Welcome.html +++ b/src/htmls/Welcome.html @@ -241,7 +241,6 @@

Welcome to QtWeb Internet Browser

  • Supported FTP browsing and downloading
  • AutoFill option - stores and pre-populates user names and passwords for the sites you visit most
  • -
  • With Qt 4.6 supported Netscape plugins, like Adobe Flash Player, QuickTime or MediaPlayer
  • Use Scenarios diff --git a/src/main.cpp b/src/main.cpp index 80346e4..99d65fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,13 +46,7 @@ int main(int argc, char **argv) #ifndef QT_SHARED Q_INIT_RESOURCE(WebCore); - Q_INIT_RESOURCE(WebKit); - -# if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - Q_INIT_RESOURCE(InspectorBackendCommands); -# else - Q_INIT_RESOURCE(InspectorBackendStub); -# endif + Q_INIT_RESOURCE(WebInspector); #endif BrowserApplication application(argc, argv); diff --git a/src/modelmenu.cpp b/src/modelmenu.cpp index 5bff437..f7a2499 100644 --- a/src/modelmenu.cpp +++ b/src/modelmenu.cpp @@ -50,7 +50,7 @@ ModelMenu::ModelMenu(QWidget * parent) , m_maxWidth(-1) , m_hoverRole(0) , m_separatorRole(0) - , m_model(0) + , m_model(nullptr) { connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); } diff --git a/src/modelmenu.h b/src/modelmenu.h index c457768..c8c7d7c 100644 --- a/src/modelmenu.h +++ b/src/modelmenu.h @@ -54,7 +54,7 @@ class ModelMenu : public QMenu void hovered(const QString &text); public: - ModelMenu(QWidget *parent = 0); + ModelMenu(QWidget *parent = nullptr); void setModel(QAbstractItemModel *model); QAbstractItemModel *model() const; @@ -82,7 +82,7 @@ class ModelMenu : public QMenu // add any actions after the tree virtual void postPopulated(); // put all of the children of parent into menu up to max - void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = 0, QMenu *menu = 0); + void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = nullptr, QMenu *menu = nullptr); private slots: void aboutToShow(); diff --git a/src/networkaccessmanager.cpp b/src/networkaccessmanager.cpp index 16a7eb4..e95cef6 100644 --- a/src/networkaccessmanager.cpp +++ b/src/networkaccessmanager.cpp @@ -74,9 +74,9 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent) : QNetworkAccessManager(parent) , m_useProxy(false) - , m_proxyExceptions(0) - , m_adBlockEx(0) - , m_adBlock(0) + , m_proxyExceptions(nullptr) + , m_adBlock(nullptr) + , m_adBlockEx(nullptr) { connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); @@ -108,7 +108,7 @@ void NetworkAccessManager::loadSettings() if (m_proxyExceptions) { delete m_proxyExceptions; - m_proxyExceptions = 0; + m_proxyExceptions = nullptr; } QSettings settings; @@ -189,13 +189,13 @@ void NetworkAccessManager::loadSettings() if (m_adBlock) { delete m_adBlock; - m_adBlock = 0; + m_adBlock = nullptr; } if (m_adBlockEx) { delete m_adBlockEx; - m_adBlockEx = 0; + m_adBlockEx = nullptr; } settings.beginGroup(QLatin1String("AdBlock")); @@ -231,7 +231,7 @@ void NetworkAccessManager::loadSettings() if (!settings.value(QLatin1String("enableDiskCache"), false).toBool() && cache()) { cache()->clear(); - setCache(0); + setCache(nullptr); } } @@ -246,7 +246,7 @@ void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthent passwordDialog.setupUi(&dialog); passwordDialog.iconLabel->setText(QString()); - passwordDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); + passwordDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mainWindow).pixmap(32, 32)); QString introMessage = tr("Enter username and password for \"%1\" at %2"); introMessage = introMessage.arg(reply->url().toString().toHtmlEscaped()).arg(reply->url().toString().toHtmlEscaped()); @@ -270,7 +270,7 @@ void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &prox proxyDialog.setupUi(&dialog); proxyDialog.iconLabel->setText(QString()); - proxyDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); + proxyDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mainWindow).pixmap(32, 32)); QString introMessage = tr("Connect to proxy \"%1\" using:"); introMessage = introMessage.arg(proxy.hostName().toHtmlEscaped()); @@ -424,4 +424,4 @@ bool NetworkAccessManager::isUrlProxyException(const QUrl& url) return false; } -//HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ +// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings diff --git a/src/networkaccessmanager.h b/src/networkaccessmanager.h index 5da0ee9..5cb9562 100644 --- a/src/networkaccessmanager.h +++ b/src/networkaccessmanager.h @@ -51,12 +51,12 @@ class NetworkAccessManager : public QNetworkAccessManager Q_OBJECT public: - NetworkAccessManager(QObject *parent = 0); + NetworkAccessManager(QObject *parent = nullptr); ~NetworkAccessManager(); void blockAd(QString ad); protected: - QNetworkReply * createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 ); + QNetworkReply * createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = nullptr ); bool useProxy() {return m_useProxy; } bool isUrlProxyException(const QUrl&); diff --git a/src/passwords.h b/src/passwords.h index ecbd6c7..d55f6bb 100644 --- a/src/passwords.h +++ b/src/passwords.h @@ -35,7 +35,7 @@ class PasswordsModel : public QAbstractTableModel Q_OBJECT public: - PasswordsModel(QObject *parent = 0); + PasswordsModel(QObject *parent = nullptr); ~PasswordsModel(); QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; diff --git a/src/resetsettings.h b/src/resetsettings.h index 0f10307..e7c2cf5 100644 --- a/src/resetsettings.h +++ b/src/resetsettings.h @@ -32,7 +32,7 @@ class ResetSettings : public QDialog, public Ui_ResetSettings ToolbarSearch* m_toolbarSearch; public: - ResetSettings(ToolbarSearch*, QWidget *parent = 0); + ResetSettings(ToolbarSearch*, QWidget *parent = nullptr); ~ResetSettings(); public slots: diff --git a/src/savepdf.h b/src/savepdf.h index 2bff416..df6978e 100644 --- a/src/savepdf.h +++ b/src/savepdf.h @@ -11,7 +11,7 @@ class SavePDF : public QDialog Q_OBJECT public: - SavePDF(const QString& title, QWebFrame* frame, QWidget *parent = 0); + SavePDF(const QString& title, QWebFrame* frame, QWidget *parent = nullptr); ~SavePDF(); protected slots: diff --git a/src/searchlineedit.cpp b/src/searchlineedit.cpp index 22dc636..9bd3d02 100644 --- a/src/searchlineedit.cpp +++ b/src/searchlineedit.cpp @@ -53,7 +53,7 @@ */ class SearchButton : public QAbstractButton { public: - SearchButton(QWidget *parent = 0); + SearchButton(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); QMenu *m_menu; @@ -63,7 +63,7 @@ class SearchButton : public QAbstractButton { SearchButton::SearchButton(QWidget *parent) : QAbstractButton(parent), - m_menu(0) + m_menu(nullptr) { setObjectName(QLatin1String("SearchButton")); setCursor(Qt::ArrowCursor); diff --git a/src/searchlineedit.h b/src/searchlineedit.h index 99aeade..96bf9b1 100644 --- a/src/searchlineedit.h +++ b/src/searchlineedit.h @@ -60,7 +60,7 @@ class SearchLineEdit : public ExLineEdit void textChanged(const QString &text); public: - SearchLineEdit(QWidget *parent = 0); + SearchLineEdit(QWidget *parent = nullptr); QString inactiveText() const; void setInactiveText(const QString &text); diff --git a/src/settings.cpp b/src/settings.cpp index efbfc08..4ed948b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -170,7 +170,6 @@ void SettingsDialog::loadDefaults() downloadsLocation->setText( DefaultDownloadPath( false ) ); enableJavascript->setChecked(defaultSettings->testAttribute(QWebSettings::JavascriptEnabled)); - enablePlugins->setChecked(defaultSettings->testAttribute(QWebSettings::PluginsEnabled)); blockPopups->setChecked( ! (defaultSettings->testAttribute(QWebSettings::JavascriptCanOpenWindows)) ); autoLoadImages->setChecked(defaultSettings->testAttribute(QWebSettings::AutoLoadImages)); @@ -326,7 +325,6 @@ void SettingsDialog::loadFromSettings() fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); enableJavascript->setChecked(settings.value(QLatin1String("enableJavascript"), enableJavascript->isChecked()).toBool()); - enablePlugins->setChecked(settings.value(QLatin1String("enablePlugins"), enablePlugins->isChecked()).toBool()); autoLoadImages->setChecked(settings.value(QLatin1String("autoLoadImages"), autoLoadImages->isChecked()).toBool()); blockPopups->setChecked(settings.value(QLatin1String("blockPopups"), blockPopups->isChecked()).toBool()); @@ -521,7 +519,6 @@ void SettingsDialog::saveToSettings() settings.setValue(QLatin1String("fixedFont"), fixedFont); settings.setValue(QLatin1String("standardFont"), standardFont); settings.setValue(QLatin1String("enableJavascript"), enableJavascript->isChecked()); - settings.setValue(QLatin1String("enablePlugins"), enablePlugins->isChecked()); settings.setValue(QLatin1String("autoLoadImages"), autoLoadImages->isChecked()); settings.setValue(QLatin1String("blockPopups"), blockPopups->isChecked()); settings.setValue(QLatin1String("savePasswords"), chkSavePasswords->isChecked()); @@ -729,6 +726,8 @@ void SettingsDialog::warnLangChange(int) void SettingsDialog::setAppStyle(int index) { + Q_UNUSED(index); + QString style = comboBoxStyle->currentText(); QApplication::setStyle(QStyleFactory::create(style)); } @@ -869,7 +868,9 @@ void SettingsDialog::removeBlockAdEx() void SettingsDialog::addBlockItems(const QLatin1String& filename, QListWidget* listview) { QFile file(filename); - bool isOpened = file.open(QIODevice::ReadOnly | QIODevice::Text); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + QString all = QString(QLatin1String(file.readAll())); file.close(); QStringList lst = all.split("\n"); diff --git a/src/settings.h b/src/settings.h index 4d1c4d9..523df6f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -49,7 +49,7 @@ class SettingsDialog : public QDialog, public Ui_Settings Q_OBJECT public: - SettingsDialog(QWidget *parent = 0); + SettingsDialog(QWidget *parent = nullptr); void accept(); void reject(); diff --git a/src/settings.ui b/src/settings.ui index 7601aac..7fcec6a 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -1044,22 +1044,6 @@ true - - - - 11 - 90 - 289 - 19 - - - - Enable Plug-Ins - - - true - - @@ -1883,7 +1867,6 @@ enableJavascript autoLoadImages blockPopups - enablePlugins enableDiskCache checkBoxDeleteDownloads chkSavePasswords diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index f245ea6..d955328 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -98,7 +98,7 @@ bool Shortcuts::save() { if (!m_data.SetShortcuts(i, shorts->text().trimmed())) { - QMessageBox::warning(0, tr("Invalid shortcut assigned"), + QMessageBox::warning(nullptr, tr("Invalid shortcut assigned"), tr("Error assigning shortcut(s) for the menu command: %1.\n\nPlease check the shortcut(s): %2" ).arg(menu->text()).arg(shorts->text().trimmed())); return false; diff --git a/src/squeezelabel.h b/src/squeezelabel.h index 818f5a5..3e0d3d8 100644 --- a/src/squeezelabel.h +++ b/src/squeezelabel.h @@ -48,7 +48,7 @@ class SqueezeLabel : public QLabel Q_OBJECT public: - SqueezeLabel(QWidget *parent = 0); + SqueezeLabel(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *event); diff --git a/src/staticplugins.cpp b/src/staticplugins.cpp new file mode 100644 index 0000000..0b06f54 --- /dev/null +++ b/src/staticplugins.cpp @@ -0,0 +1,14 @@ +#include + +Q_IMPORT_PLUGIN(QXcbIntegrationPlugin) +Q_IMPORT_PLUGIN(QXcbEglIntegrationPlugin) +Q_IMPORT_PLUGIN(QXcbGlxIntegrationPlugin) +Q_IMPORT_PLUGIN(QGifPlugin) +Q_IMPORT_PLUGIN(QICNSPlugin) +Q_IMPORT_PLUGIN(QICOPlugin) +Q_IMPORT_PLUGIN(QJpegPlugin) +Q_IMPORT_PLUGIN(QTgaPlugin) +Q_IMPORT_PLUGIN(QTiffPlugin) +Q_IMPORT_PLUGIN(QWbmpPlugin) +Q_IMPORT_PLUGIN(QWebpPlugin) +Q_IMPORT_PLUGIN(QGenericEnginePlugin) diff --git a/src/staticplugins.pri b/src/staticplugins.pri new file mode 100644 index 0000000..9e9daa1 --- /dev/null +++ b/src/staticplugins.pri @@ -0,0 +1,16 @@ +static:unix { + CONFIG -= import_plugins + QTPLUGIN += qxcb \ + qxcb-egl-integration \ + qxcb-glx-integration \ + qgif \ + qicns \ + qico \ + qjpeg \ + qtga \ + qtiff \ + qwbmp \ + qwebp \ + qgenericbearer + SOURCES += $$PWD/staticplugins.cpp +} diff --git a/src/tabbar.cpp b/src/tabbar.cpp index 9d2813a..73f9797 100644 --- a/src/tabbar.cpp +++ b/src/tabbar.cpp @@ -76,7 +76,7 @@ int TabShortcut::tab() } TabBar::TabBar(QWidget *parent) : QTabBar(parent) - , m_viewTabBarAction(0) + , m_viewTabBarAction(nullptr) , m_showTabBarWhenOneTab(true) { setElideMode(Qt::ElideRight); @@ -122,7 +122,7 @@ void TabBar::setShowTabBarWhenOneTab(bool enabled) QTabBar::ButtonPosition TabBar::freeSide() { - QTabBar::ButtonPosition side = (QTabBar::ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, this); + QTabBar::ButtonPosition side = (QTabBar::ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, this); side = (side == QTabBar::LeftSide) ? QTabBar::RightSide : QTabBar::LeftSide; return side; } @@ -328,7 +328,7 @@ QSize TabBar::tabSizeHint(int index) const WebActionMapper::WebActionMapper(QAction *root, QWebPage::WebAction webAction, QObject *parent) : QObject(parent) - , m_currentParent(0) + , m_currentParent(nullptr) , m_root(root) , m_webAction(webAction) { @@ -341,12 +341,12 @@ WebActionMapper::WebActionMapper(QAction *root, QWebPage::WebAction webAction, Q void WebActionMapper::rootDestroyed() { - m_root = 0; + m_root = nullptr; } void WebActionMapper::currentDestroyed() { - updateCurrent(0); + updateCurrent(nullptr); } void WebActionMapper::addChild(QAction *action) diff --git a/src/tabbar.h b/src/tabbar.h index 13c5165..a337ed1 100644 --- a/src/tabbar.h +++ b/src/tabbar.h @@ -66,7 +66,7 @@ class TabBar : public QTabBar void loadUrl(const QUrl &url); public: - TabBar(QWidget *parent = 0); + TabBar(QWidget *parent = nullptr); bool showTabBarWhenOneTab() const; void setShowTabBarWhenOneTab(bool enabled); diff --git a/src/tabwidget.cpp b/src/tabwidget.cpp index 8298de4..2b7a537 100644 --- a/src/tabwidget.cpp +++ b/src/tabwidget.cpp @@ -68,15 +68,15 @@ TabWidget::TabWidget(QWidget *parent) : QTabWidget(parent) - , m_recentlyClosedTabsAction(0) - , m_newTabAction(0) - , m_closeTabAction(0) - , m_nextTabAction(0) - , m_previousTabAction(0) - , m_recentlyClosedTabsMenu(0) - , m_lineEdits(0) + , m_recentlyClosedTabsAction(nullptr) + , m_newTabAction(nullptr) + , m_closeTabAction(nullptr) + , m_nextTabAction(nullptr) + , m_previousTabAction(nullptr) + , m_recentlyClosedTabsMenu(nullptr) , m_prevSelectedTab(-1) , m_prevSelectedTabMark(-1) + , m_lineEdits(nullptr) , m_tabBar(new TabBar(this)) { setElideMode(Qt::ElideRight); @@ -305,7 +305,7 @@ QLineEdit *TabWidget::lineEdit(int index) const UrlLineEdit *urlLineEdit = qobject_cast(m_lineEdits->widget(index)); if (urlLineEdit) return urlLineEdit->lineEdit(); - return 0; + return nullptr; } WebView *TabWidget::webView(int index) const @@ -343,7 +343,7 @@ WebView *TabWidget::webView(int index) const return currentWebView(); } } - return 0; + return nullptr; } int TabWidget::webViewIndex(WebView *webView) const @@ -390,7 +390,7 @@ WebView *TabWidget::newTab(bool makeCurrent, bool empty) addTab(emptyWidget, tr("Blank Tab")); connect(this, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int))); - return 0; + return nullptr; } // webview @@ -446,8 +446,10 @@ WebView *TabWidget::newTab(bool makeCurrent, bool empty) case 0: // welcome page { QFile file(QLatin1String(":/Welcome.html")); - bool isOpened = file.open(QIODevice::ReadOnly | QIODevice::Text); - Q_ASSERT(isOpened); + const bool opened = file.open(QIODevice::ReadOnly | QIODevice::Text); + Q_ASSERT(opened); + if (!opened) + break; QString html = QString(QLatin1String(file.readAll())); QPixmap pix= style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(32,32); @@ -598,7 +600,7 @@ void TabWidget::closeTab(int index) QLabel *TabWidget::animationLabel(int index, bool addMovie) { if (-1 == index) - return 0; + return nullptr; QTabBar::ButtonPosition side = m_tabBar->freeSide(); QLabel *loadingAnimation = qobject_cast(m_tabBar->tabButton(index, side)); if (!loadingAnimation) { @@ -609,7 +611,7 @@ QLabel *TabWidget::animationLabel(int index, bool addMovie) loadingAnimation->setMovie(movie); movie->start(); } - m_tabBar->setTabButton(index, side, 0); + m_tabBar->setTabButton(index, side, nullptr); m_tabBar->setTabButton(index, side, loadingAnimation); return loadingAnimation; } @@ -635,7 +637,7 @@ void TabWidget::webViewIconChanged() QLabel *label = animationLabel(index, false); QMovie *movie = label->movie(); delete movie; - label->setMovie(0); + label->setMovie(nullptr); label->setPixmap(icon.pixmap(16, 16)); setElideMode(Qt::ElideRight); } @@ -644,6 +646,8 @@ void TabWidget::webViewIconChanged() void TabWidget::webViewLoadFinished(bool ok) { + Q_UNUSED(ok); + WebView *webView = qobject_cast(sender()); int index = webViewIndex(webView); if (-1 != index) diff --git a/src/tabwidget.h b/src/tabwidget.h index abf0ab2..1aa2c42 100644 --- a/src/tabwidget.h +++ b/src/tabwidget.h @@ -83,7 +83,7 @@ class TabWidget : public QTabWidget NewTab }; - TabWidget(QWidget *parent = 0); + TabWidget(QWidget *parent = nullptr); TabBar *tabBar() { return m_tabBar; } void clear(); void addWebAction(QAction *action, QWebPage::WebAction webAction); diff --git a/src/toolbarsearch.cpp b/src/toolbarsearch.cpp index 8fdbb13..d6b843b 100644 --- a/src/toolbarsearch.cpp +++ b/src/toolbarsearch.cpp @@ -59,7 +59,7 @@ ToolbarSearch::ToolbarSearch(QWidget *parent) : SearchLineEdit(parent) , m_maxSavedSearches(10) , m_stringListModel(new QStringListModel(this)) - , m_completer(0) + , m_completer(nullptr) { QMenu *m = menu(); connect(m, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); @@ -236,7 +236,7 @@ void ToolbarSearch::checkGoogleSuggest(bool show_google) else { delete m_completer; - m_completer = NULL; + m_completer = nullptr; } } @@ -360,7 +360,7 @@ void ToolbarSearch::addSearches() settings.endGroup(); } - QAction* searches = m->addAction(tr("Add..."), this, SLOT(addSearch())); + m->addAction(tr("Add..."), this, SLOT(addSearch())); } void ToolbarSearch::addSearch() @@ -411,4 +411,3 @@ void ToolbarSearch::clear() m_stringListModel->setStringList(QStringList()); save(); } - diff --git a/src/toolbarsearch.h b/src/toolbarsearch.h index 01dd8d6..58bfece 100644 --- a/src/toolbarsearch.h +++ b/src/toolbarsearch.h @@ -59,7 +59,7 @@ class ToolbarSearch : public SearchLineEdit void search(const QUrl &url); public: - ToolbarSearch(QWidget *parent = 0); + ToolbarSearch(QWidget *parent = nullptr); ~ToolbarSearch(); public slots: diff --git a/src/torrent/torrentclient.cpp b/src/torrent/torrentclient.cpp index 4ac8166..3776172 100644 --- a/src/torrent/torrentclient.cpp +++ b/src/torrent/torrentclient.cpp @@ -583,7 +583,8 @@ void TorrentClient::sendToPeer(int readId, int pieceIndex, int begin, const QByt // Send the requested block to the peer if the client connection // still exists; otherwise do nothing. This slot is called by the // file manager after it has read a block of data. - PeerWireClient *client = d->readIds.value(readId); + QMap::const_iterator it = d->readIds.constFind(readId); + PeerWireClient *client = (it != d->readIds.constEnd()) ? it.value() : nullptr; if (client) { if ((client->peerWireState() & PeerWireClient::ChokingPeer) == 0) client->sendBlock(pieceIndex, begin, data); @@ -638,7 +639,8 @@ void TorrentClient::fullVerificationDone() void TorrentClient::pieceVerified(int pieceIndex, bool ok) { - TorrentPiece *piece = d->pendingPieces.value(pieceIndex); + QMap::const_iterator pieceIt = d->pendingPieces.constFind(pieceIndex); + TorrentPiece *piece = (pieceIt != d->pendingPieces.constEnd()) ? pieceIt.value() : nullptr; // Remove this piece from all payloads QMultiMap::Iterator it = d->payloads.begin(); diff --git a/src/torrent/torrentserver.cpp b/src/torrent/torrentserver.cpp index 6517643..dec4cbf 100644 --- a/src/torrent/torrentserver.cpp +++ b/src/torrent/torrentserver.cpp @@ -112,7 +112,7 @@ void TorrentServer::processInfoHash(const QByteArray &infoHash) PeerWireClient *peer = qobject_cast(sender()); for (TorrentClient *client : qAsConst(clients)) { if (client->state() >= TorrentClient::Searching && client->infoHash() == infoHash) { - disconnect(peer, 0, this, 0); + disconnect(peer, nullptr, this, nullptr); client->setupIncomingConnection(peer); return; } diff --git a/src/urllineedit.cpp b/src/urllineedit.cpp index 4941bed..cec77f2 100644 --- a/src/urllineedit.cpp +++ b/src/urllineedit.cpp @@ -66,7 +66,7 @@ UrlIconLabel::UrlIconLabel(QWidget *parent) : QLabel(parent) - , m_webView(0) + , m_webView(nullptr) { setMinimumWidth(16); setMinimumHeight(16); @@ -133,8 +133,8 @@ void UrlIconLabel::mouseMoveEvent(QMouseEvent *event) UrlLineEdit::UrlLineEdit(QWidget *parent) : ExLineEdit(parent, true) - , m_webView(0) - , m_iconLabel(0) + , m_webView(nullptr) + , m_iconLabel(nullptr) { // icon m_iconLabel = new UrlIconLabel(this); diff --git a/src/urllineedit.h b/src/urllineedit.h index 1c95d98..ab4b8a8 100644 --- a/src/urllineedit.h +++ b/src/urllineedit.h @@ -75,7 +75,7 @@ class UrlLineEdit : public ExLineEdit Q_OBJECT public: - UrlLineEdit(QWidget *parent = 0); + UrlLineEdit(QWidget *parent = nullptr); void setWebView(WebView *webView); protected: diff --git a/src/webpage.cpp b/src/webpage.cpp index c481baf..8f19368 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -57,7 +57,6 @@ #include #include #include -//#include #include #include @@ -219,7 +218,7 @@ bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &r return false; } - if (frame == NULL && type == QWebPage::NavigationTypeLinkClicked) // Check for open links in tabs + if (frame == nullptr && type == QWebPage::NavigationTypeLinkClicked) // Check for open links in tabs { QSettings settings; settings.beginGroup(QLatin1String("general")); @@ -275,7 +274,7 @@ bool WebPage::extension(QWebPage::Extension extension, const QWebPage::Extension QBuffer imageBuffer; imageBuffer.open(QBuffer::ReadWrite); - QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, view()); + QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, view()); QPixmap pixmap = icon.pixmap(QSize(32,32)); if (pixmap.save(&imageBuffer, "PNG")) { html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"), @@ -314,17 +313,6 @@ QWebPage *WebPage::createWindow(QWebPage::WebWindowType type) return mainWindow->currentTab()->page(); } -#if !defined(QT_NO_UITOOLS) -QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) -{ - Q_UNUSED(url); - Q_UNUSED(paramNames); - Q_UNUSED(paramValues); - QUiLoader loader; - return loader.createWidget(classId, view()); -} -#endif // !defined(QT_NO_UITOOLS) - void WebPage::handleUnsupportedContent(QNetworkReply *reply) { if (reply->error() == QNetworkReply::NoError) @@ -340,4 +328,3 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) return; } } - diff --git a/src/webpage.cpp.bak b/src/webpage.cpp.bak deleted file mode 100644 index 636f534..0000000 --- a/src/webpage.cpp.bak +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (C) 2008-2009 Alexei Chaloupov - * Copyright (C) 2007-2008 Benjamin C. Meyer - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ -/**************************************************************************** -** -** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** Licensees holding a valid Qt License Agreement may use this file in -** accordance with the rights, responsibilities and obligations -** contained therein. Please consult your licensing agreement or -** contact sales@trolltech.com if any conditions of this licensing -** agreement are not clear to you. -** -** Further information about Qt licensing is available at: -** http://www.trolltech.com/products/qt/licensing.html or by -** contacting info@trolltech.com. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "downloadmanager.h" -#include "networkaccessmanager.h" -#include "tabwidget.h" -#include "webpage.h" -#include "webview.h" -#include "autocomplete.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -WebPage::WebPage(QObject *parent) - : QWebPage(parent) - , m_keyboardModifiers(Qt::NoModifier) - , m_pressedButtons(Qt::NoButton) - , m_openAction(OpenDefault) -{ - setNetworkAccessManager(BrowserApplication::networkAccessManager()); - connect(this, SIGNAL(unsupportedContent(QNetworkReply *)), - this, SLOT(handleUnsupportedContent(QNetworkReply *))); - -} - -BrowserMainWindow *WebPage::mainWindow() -{ - QObject *w = this->parent(); - while (w) { - if (BrowserMainWindow *mw = qobject_cast(w)) - return mw; - w = w->parent(); - } - return BrowserApplication::instance()->mainWindow(); -} - -QString WebPage::m_userAgent; - -void WebPage::setUserAgent(QString agent) -{ - m_userAgent = agent; -} - -void WebPage::setDefaultAgent( ) -{ - QString ver; -#ifdef Q_WS_WIN - switch(QSysInfo::WindowsVersion) - { - case QSysInfo::WV_32s: - ver = "Windows 3.1"; - break; - case QSysInfo::WV_95: - ver = "Windows 95"; - break; - case QSysInfo::WV_98: - ver = "Windows 98"; - break; - case QSysInfo::WV_Me: - ver = "Windows 98; Win 9x 4.90"; - break; - case QSysInfo::WV_NT: - ver = "WinNT4.0"; - break; - case QSysInfo::WV_2000: - ver = "Windows NT 5.0"; - break; - case QSysInfo::WV_XP: - ver = "Windows NT 5.1"; - break; - case QSysInfo::WV_2003: - ver = "Windows NT 5.2"; - break; - case QSysInfo::WV_VISTA: - ver = "Windows NT 6.0"; - break; - case QSysInfo::WV_CE: - ver = "Windows CE"; - break; - case QSysInfo::WV_CENET: - ver = "Windows CE .NET"; - break; - case QSysInfo::WV_CE_5: - ver = "Windows CE 5.x"; - break; - case QSysInfo::WV_CE_6: - ver = "Windows CE 6.x"; - break; - default: - ver = "Windows NT based"; - } -#else - - #ifdef Q_WS_MAC - switch(QSysInfo::MacintoshVersion) - { - case QSysInfo::MV_10_3: - ver = "Intel MacOS X 10.3"; - break; - case QSysInfo::MV_10_4: - ver = "Intel MacOS X 10.4"; - break; - case QSysInfo::MV_10_5: - ver = "Intel MacOS X 10.5"; - break; - case QSysInfo::MV_10_6: - ver = "Intel MacOS X 10.6"; - break; - default: - ver = "MacOS X"; - } - #else - ver = "Linux/Unix"; - #endif -#endif - // language - QString name = QLocale::system().name(); - name[2] = QLatin1Char('-'); - - QSettings settings; - settings.beginGroup(QLatin1String("websettings")); - bool bUseCustomAgent = settings.value(QLatin1String("customUserAgent"), false).toBool(); - if (bUseCustomAgent) - { - m_userAgent = settings.value(QLatin1String("UserAgent"), "").toString(); - if (m_userAgent == "Internet Explorer") - m_userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; %W; Trident/4.0)"; - else if (m_userAgent == "Firefox") - m_userAgent = "Mozilla/5.0 (Windows; U; %W; %L; rv:1.9.0.5) Gecko/2008120121 Firefox/3.0.5"; - else if (m_userAgent == "Opera") - m_userAgent = "Opera/9.63 (%W; U; en) Presto/2.1.1"; - else if (m_userAgent == "Safari") - m_userAgent = "Mozilla/5.0 (Windows; U; %W; %L) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Safari/528.17"; - else if (m_userAgent == "Chrome") - m_userAgent = "Mozilla/5.0 (Windows; U; %W; %L) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"; - - m_userAgent = m_userAgent.replace("%W", ver); - m_userAgent = m_userAgent.replace("%L", name); - return; - } - -#ifdef Q_WS_MAC - QString ua = QLatin1String("Mozilla/5.0 (Macintosh; %1; %2; "); -#else - QString ua = QLatin1String("Mozilla/5.0 (Windows; %1; %2; "); -#endif - - QChar securityStrength(QLatin1Char('N')); - if (QSslSocket::supportsSsl()) - securityStrength = QLatin1Char('U'); - ua = ua.arg(securityStrength); - - ua = QString(ua).arg(ver); - - // Language - ua.append(name); - ua.append(QLatin1String(") ")); - - // webkit/qt version - ua.append(QLatin1String("AppleWebKit/533.3 (KHTML, like Gecko) ")); - - // Application name/version - QString appName = QCoreApplication::applicationName(); - if (!appName.isEmpty()) { - ua.append(QLatin1Char(' ') + appName); - QString appVer = QCoreApplication::applicationVersion(); - if (!appVer.isEmpty()) - ua.append(QLatin1Char('/') + appVer); - ua.append(QLatin1String(" http://www.QtWeb.net")); - } - - m_userAgent = ua; -} - -const QString& WebPage::getUserAgent() -{ - return m_userAgent; -} - -QString WebPage::userAgentForUrl(const QUrl& url) const -{ - return getUserAgent(); -} - - -extern bool ShellOpenApp(QString app, QString cmd); - -bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type) -{ - if (!request.url().isEmpty()) - { - QString scheme = request.url().scheme(); - QString url = request.url().toString().toLower(); - if ( scheme == "mms" || scheme == QLatin1String("mailto") || - url.indexOf(".wmv") == url.length() - 4 || url.indexOf(".wma") == url.length() - 4) - { - if (QDesktopServices::openUrl(request.url())) - return false; - } - - /* AC: v .3.3.45 - PDF PlugIn is handled properly now in Qt 4.6.1++ - if( url.indexOf(".pdf") == url.length() - 4 ) - { - if (BrowserApplication::downloadManager()) - BrowserApplication::downloadManager()->download(request.url(), false); - return false; - }*/ - - } - - if (frame && (type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted)) - { - QSettings settings; - settings.beginGroup(QLatin1String("websettings")); - if ( settings.value(QLatin1String("savePasswords"), false).toBool()) - { - QUrl u = request.url(); - if (!request.rawHeader("Referer").isEmpty()) - u = QUrl(request.rawHeader("Referer")); - - BrowserApplication::autoCompleter()->setFormHtml( u, frame->toHtml() ); - } - } - - // ctrl open in new tab - // ctrl-shift open in new tab and select - // ctrl-alt open in new window - if (type == QWebPage::NavigationTypeLinkClicked && (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)) - { - QSettings settings; - settings.beginGroup(QLatin1String("general")); - int openLinksIn = settings.value(QLatin1String("openLinksIn"), 0).toInt(); - - bool newWindow = (m_keyboardModifiers & Qt::AltModifier); - WebView* webView; - if (newWindow || (openLinksIn == 1)) - { - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *newMainWindow = BrowserApplication::instance()->mainWindow(); - webView = newMainWindow->currentTab(); - newMainWindow->raise(); - newMainWindow->activateWindow(); - webView->setFocus(); - } - else - { - bool selectNewTab = (m_keyboardModifiers & Qt::ShiftModifier); - webView = mainWindow()->tabWidget()->newTab(selectNewTab); - } - webView->load(request); - m_keyboardModifiers = Qt::NoModifier; - m_pressedButtons = Qt::NoButton; - DefineHostIcon(request.url()); - return false; - } - - if (frame == NULL && type == QWebPage::NavigationTypeLinkClicked) // Check for open links in tabs - { - QSettings settings; - settings.beginGroup(QLatin1String("general")); - int openLinksIn = settings.value(QLatin1String("openLinksIn"), 0).toInt(); - if (openLinksIn == 0 && !(m_keyboardModifiers & Qt::AltModifier)) - { - WebView* webView = mainWindow()->tabWidget()->newTab(true); - webView->load(request); - //DefineHostIcon(request.url()); - return false; - } - } - - if (frame == mainFrame()) - { - if ( !request.url().isEmpty() ) - { - if (request.url().scheme() != "ftp") - { - m_loadingUrl = request.url(); - //emit loadingUrl(m_loadingUrl); // ??? to avoid unnecessary LineURL change - DefineHostIcon(request.url()); - return true; - } - else - { - m_loadingUrl = request.url(); - WebView* view = (WebView* )parent(); - if (!view->isLoading()) - { - view->loadUrl( request.url() ); - return false; - } - return true; - } - } - } - - return QWebPage::acceptNavigationRequest(frame, request, type); -} - -void WebPage::DefineHostIcon(const QUrl& url) -{ - BrowserApplication::instance()->CheckIcon(url); -} - -QWebPage *WebPage::createWindow(QWebPage::WebWindowType type) -{ - Q_UNUSED(type); - - if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton) - m_openAction = WebPage::OpenNewTab; - - if (m_openAction == WebPage::OpenNewTab ) - { - m_openAction = WebPage::OpenDefault; - return mainWindow()->tabWidget()->newTab()->page(); - } - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - return mainWindow->currentTab()->page(); -} - -#if !defined(QT_NO_UITOOLS) -QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) -{ - Q_UNUSED(url); - Q_UNUSED(paramNames); - Q_UNUSED(paramValues); - QUiLoader loader; - return loader.createWidget(classId, view()); -} -#endif // !defined(QT_NO_UITOOLS) - -void WebPage::handleUnsupportedContent(QNetworkReply *reply) -{ - if (reply->error() == QNetworkReply::NoError) - { - QVariant content = reply->header(QNetworkRequest::ContentTypeHeader); - QString c = content.toString(); - - if ( content.isValid() && !BrowserApplication::handleMIME( c, reply->url() ) ) - { - BrowserApplication::downloadManager()->handleUnsupportedContent(reply); - - } - return; - } - - QFile file(QLatin1String(":/notfound.html")); - bool isOpened = file.open(QIODevice::ReadOnly); - Q_ASSERT(isOpened); - QString title = tr("Loading error: %1").arg(reply->url().toString()); - QString html = QString(QLatin1String(file.readAll())) - .arg(title) - .arg(reply->errorString()) - .arg(reply->url().toString()); - - QBuffer imageBuffer; - imageBuffer.open(QBuffer::ReadWrite); - QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, view()); - QPixmap pixmap = icon.pixmap(QSize(32,32)); - if (pixmap.save(&imageBuffer, "PNG")) { - html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"), - QString(QLatin1String(imageBuffer.buffer().toBase64()))); - } - - QList frames; - frames.append(mainFrame()); - while (!frames.isEmpty()) { - QWebFrame *frame = frames.takeFirst(); - if (frame->url() == reply->url()) { - frame->setHtml(html, reply->url()); - return; - } - QList children = frame->childFrames(); - foreach(QWebFrame *frame, children) - frames.append(frame); - } - if (m_loadingUrl == reply->url()) { - mainFrame()->setHtml(html, reply->url()); - } -} - diff --git a/src/webpage.h b/src/webpage.h index 5340d77..5f95de8 100644 --- a/src/webpage.h +++ b/src/webpage.h @@ -66,7 +66,7 @@ class WebPage : public QWebPage { void errorLoadingUrl(); public: - WebPage(QObject *parent = 0); + WebPage(QObject *parent = nullptr); BrowserMainWindow *mainWindow(); static void setUserAgent(QString agent = "default"); @@ -84,10 +84,6 @@ class WebPage : public QWebPage { bool extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output); bool supportsExtension(Extension extension) const; -#if !defined(QT_NO_UITOOLS) - QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); -#endif - private slots: void handleUnsupportedContent(QNetworkReply *reply); diff --git a/src/webview.cpp b/src/webview.cpp index e205fce..8a8441b 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -57,7 +57,6 @@ #include #include #include -//#include #include #include @@ -66,10 +65,10 @@ WebView::WebView(QWidget* parent) : QWebView(parent) , m_progress(0) - , m_page(new WebPage(this)) - , m_font_resizing(false) , m_is_loading(false) , m_gestureStarted(false) + , m_page(new WebPage(this)) + , m_font_resizing(false) , m_encoding_in_progress(false) , m_ssl_errors_detected(false) , m_linkUnderCursor(false) @@ -522,16 +521,16 @@ void WebView::mouseReleaseEvent(QMouseEvent *event) if (difY > 0 && (difX == 0 || abs(difY / difX) >= 2)) down = true; else - if (difX < 0 && difY < 0 && abs(difX / difY) < 2 && abs((float)difX / (float)difY) > 0.5) + if (difX < 0 && difY < 0 && abs(difX / difY) < 2 && qAbs((float)difX / (float)difY) > 0.5) upper_left = true; else - if (difX > 0 && difY < 0 && abs(difX / difY) < 2 && abs((float)difX / (float)difY) > 0.5) + if (difX > 0 && difY < 0 && abs(difX / difY) < 2 && qAbs((float)difX / (float)difY) > 0.5) upper_right = true; else - if (difX > 0 && difY > 0 && abs(difX / difY) < 2 && abs((float)difX / (float)difY) > 0.5) + if (difX > 0 && difY > 0 && abs(difX / difY) < 2 && qAbs((float)difX / (float)difY) > 0.5) down_right = true; else - if (difX < 0 && difY > 0 && abs(difX / difY) < 2 && abs((float)difX / (float)difY) > 0.5) + if (difX < 0 && difY > 0 && abs(difX / difY) < 2 && qAbs((float)difX / (float)difY) > 0.5) down_left = true; if (left) @@ -748,6 +747,8 @@ void WebView::loadFtpUrl(const QUrl &url) void WebView::ftpDownloadFile(const QUrl &url, QString fileName ) { + Q_UNUSED(url); + if (!m_ftp) return; @@ -847,19 +848,26 @@ void WebView::ftpCommandFinished(int res, bool error) if (m_ftp->currentCommand() == QFtp::Get) { + if (!m_ftpFile) { + m_ftpProgressDialog->hide(); + urlChanged(m_initialUrl); + return; + } + + const QString ftpFileName = m_ftpFile->fileName(); if (error) { - setStatusBarText(tr("Canceled download of %1").arg(m_ftpFile->fileName())); + setStatusBarText(tr("Canceled download of %1").arg(ftpFileName)); m_ftpFile->close(); m_ftpFile->remove(); } else { DownloadManager* dm = BrowserApplication::downloadManager(); - setStatusBarText(tr("Successfully downloaded file %1").arg(m_ftpFile->fileName())); + setStatusBarText(tr("Successfully downloaded file %1").arg(ftpFileName)); m_ftpFile->close(); - dm->addItem(m_initialUrl, m_ftpFile->fileName(), true ); + dm->addItem(m_initialUrl, ftpFileName, true ); } delete m_ftpFile; m_ftpFile = nullptr; diff --git a/src/webview.h b/src/webview.h index 1201669..f61a7d6 100644 --- a/src/webview.h +++ b/src/webview.h @@ -57,7 +57,7 @@ class WebView : public QWebView { Q_OBJECT public: - WebView(QWidget *parent = 0); + WebView(QWidget *parent = nullptr); WebPage *webPage() const { return m_page; } void loadUrl(const QUrl &url, const QString &title = QString()); diff --git a/src/xbel.cpp b/src/xbel.cpp index 87c607a..86795c7 100644 --- a/src/xbel.cpp +++ b/src/xbel.cpp @@ -56,7 +56,7 @@ BookmarkNode::~BookmarkNode() if (m_parent) m_parent->remove(this); qDeleteAll(m_children); - m_parent = 0; + m_parent = nullptr; m_type = BookmarkNode::Root; } @@ -111,7 +111,7 @@ void BookmarkNode::add(BookmarkNode *child, int offset) void BookmarkNode::remove(BookmarkNode *child) { - child->m_parent = 0; + child->m_parent = nullptr; m_children.removeAll(child); } diff --git a/src/xbel.h b/src/xbel.h index 74be9f6..137b44d 100644 --- a/src/xbel.h +++ b/src/xbel.h @@ -54,7 +54,7 @@ class BookmarkNode Separator }; - BookmarkNode(Type type = Root, BookmarkNode *parent = 0); + BookmarkNode(Type type = Root, BookmarkNode *parent = nullptr); ~BookmarkNode(); bool operator==(const BookmarkNode &other); diff --git a/toolchains/qt5-static/Dockerfile b/toolchains/qt5-static/Dockerfile index adc8f24..531dc09 100644 --- a/toolchains/qt5-static/Dockerfile +++ b/toolchains/qt5-static/Dockerfile @@ -1,21 +1,38 @@ # Base image is version-tagged; switch to a digest-pinned reference when refreshed online. -FROM ubuntu:16.04 +FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 RUN apt-get update && apt-get install -y --no-install-recommends \ + bear \ bison \ build-essential \ ca-certificates \ + clang \ + clang-tidy \ + cmake \ curl \ file \ flex \ + fonts-dejavu-core \ + git \ gperf \ - # libdbus-1-dev \ + libdbus-1-dev \ + libegl1-mesa-dev \ + libfontconfig1-dev \ + libfreetype6-dev \ libglib2.0-dev \ - # libsqlite3-dev \ + libgl1-mesa-dev \ + libgles2-mesa-dev \ + libharfbuzz-dev \ + libhyphen-dev \ + libicu-dev \ + libjpeg-dev \ + liblzma-dev \ + libpng-dev \ + libsqlite3-dev \ libssl-dev \ libx11-dev \ libx11-xcb-dev \ @@ -25,15 +42,30 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libxext-dev \ libxfixes-dev \ libxi-dev \ - # libxml2-dev \ + libxml2-dev \ + libwebp-dev \ libxrandr-dev \ libxrender-dev \ - # libxslt1-dev \ libxcb1-dev \ + libxcb-icccm4-dev \ + libxcb-image0-dev \ + libxcb-keysyms1-dev \ + libxcb-randr0-dev \ + libxcb-render-util0-dev \ + libxcb-shape0-dev \ + libxcb-shm0-dev \ + libxcb-sync-dev \ + libxcb-util-dev \ + libxcb-xfixes0-dev \ + libxcb-xinerama0-dev \ + libxkbcommon-dev \ + libxkbcommon-x11-dev \ + ninja-build \ patch \ perl \ pkg-config \ - python \ + python3 \ + python-is-python3 \ ruby \ && rm -rf /var/lib/apt/lists/* diff --git a/toolchains/qt5-static/browser-build-entrypoint.sh b/toolchains/qt5-static/browser-build-entrypoint.sh new file mode 100755 index 0000000..b0d28df --- /dev/null +++ b/toolchains/qt5-static/browser-build-entrypoint.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +set -euo pipefail + +fail() { + echo "error: $*" >&2 + exit 1 +} + +require_tool() { + command -v "$1" >/dev/null 2>&1 || fail "missing tool in image: $1" +} + +collect_gcc_warnings() { + local build_log="$1" + local warnings_report="$2" + grep -F "warning:" "$build_log" > "$warnings_report" || : +} + +rm -rf "$BUILD_DIR_IN_CONTAINER" +mkdir -p "$BUILD_DIR_IN_CONTAINER" +cd "$BUILD_DIR_IN_CONTAINER" + +if [[ "$BUILD_TYPE" == "release" ]]; then + "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../src/QtWeb.pro CONFIG+=release CONFIG-=debug +else + "${QT_PREFIX_IN_CONTAINER}/bin/qmake" ../src/QtWeb.pro CONFIG+=debug CONFIG-=release +fi + +build_log="${BUILD_DIR_IN_CONTAINER}/build.log" +gcc_warnings_report="${BUILD_DIR_IN_CONTAINER}/gcc-warnings.txt" + +if [[ "$RUN_ANALYSIS" == "1" ]]; then + require_tool bear + require_tool clang-tidy + clang_tidy_fixes="${BUILD_DIR_IN_CONTAINER}/clang-tidy-fixes.yaml" + clang_tidy_extra_args=() + + bear make -j"$JOBS" 2>&1 | tee "$build_log" + collect_gcc_warnings "$build_log" "$gcc_warnings_report" + + mapfile -t ANALYSIS_SOURCES < <(find "${REPO_ROOT}/src" -path "${REPO_ROOT}/src/qt" -prune -o -type f -name "*.cpp" -print | sort) + [[ "${#ANALYSIS_SOURCES[@]}" -gt 0 ]] || fail "no analysis sources found under ${REPO_ROOT}/src" + + if [[ "$EXPORT_FIXES" == "1" ]]; then + rm -f "$clang_tidy_fixes" + clang_tidy_extra_args+=(-export-fixes="$clang_tidy_fixes") + fi + + clang-tidy \ + -p "$BUILD_DIR_IN_CONTAINER" \ + --header-filter="(^|.*/)src/.*" \ + "${clang_tidy_extra_args[@]}" \ + "${ANALYSIS_SOURCES[@]}" \ + > "${BUILD_DIR_IN_CONTAINER}/clang-tidy.txt" 2>&1 + + echo "built: ${BUILD_DIR_IN_CONTAINER}/QtWeb" + echo "compile_commands: ${BUILD_DIR_IN_CONTAINER}/compile_commands.json" + echo "build log: ${build_log}" + echo "gcc warnings: ${gcc_warnings_report}" + echo "clang-tidy report: ${BUILD_DIR_IN_CONTAINER}/clang-tidy.txt" + if [[ "$EXPORT_FIXES" == "1" ]]; then + echo "clang-tidy fixes: ${clang_tidy_fixes}" + fi +else + make -j"$JOBS" 2>&1 | tee "$build_log" + collect_gcc_warnings "$build_log" "$gcc_warnings_report" + echo "built: ${BUILD_DIR_IN_CONTAINER}/QtWeb" + echo "build log: ${build_log}" + echo "gcc warnings: ${gcc_warnings_report}" +fi diff --git a/toolchains/qt5-static/build-inside-container.sh b/toolchains/qt5-static/build-inside-container.sh deleted file mode 100755 index d8df5b9..0000000 --- a/toolchains/qt5-static/build-inside-container.sh +++ /dev/null @@ -1,345 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -: "${QT_VERSION:?QT_VERSION is required}" -: "${OUTPUT_DIR:?OUTPUT_DIR is required}" -: "${QT_SRC_ARCHIVE:?QT_SRC_ARCHIVE is required}" -: "${QTWEBKIT_ARCHIVE:?QTWEBKIT_ARCHIVE is required}" -: "${ICU_SRC_ARCHIVE:?ICU_SRC_ARCHIVE is required}" - -JOBS="${JOBS:-8}" -CLEAN="${CLEAN:-false}" -BUILD_TYPE="${BUILD_TYPE:-release}" -WORK_DIR="${OUTPUT_DIR}/build" -LOG_DIR="${OUTPUT_DIR}/logs" -INSTALL_DIR="${OUTPUT_DIR}/install" -ICU_INSTALL_DIR="${OUTPUT_DIR}/icu-static" -OPENSSL_INCLUDE_DIR="/usr/include" -OPENSSL_LIB_DIR="/usr/lib/x86_64-linux-gnu" -MANIFEST_FILE="${OUTPUT_DIR}/build-manifest.txt" -QT_SRC_DIR="${WORK_DIR}/qt-everywhere-opensource-src-${QT_VERSION}" -PATCH_DIR="/workspace/toolchains/qt5-static/patches" - -fail() { - echo "error: $*" >&2 - exit 1 -} - -MIN_DEP_CONFIGURE_FLAGS=( - -no-dbus - -no-gtkstyle - -no-fontconfig - -xkb-config-root /usr/share/X11/xkb - -icu - -qt-pcre - -qt-freetype - -qt-xcb - -qt-xkbcommon-x11 -) -case "$BUILD_TYPE" in - release) - BUILD_CONFIGURE_FLAG="-release" - ;; - debug) - BUILD_CONFIGURE_FLAG="-debug" - ;; - *) - fail "BUILD_TYPE must be release or debug, got: $BUILD_TYPE" - ;; -esac - -CONFIGURE_FLAGS=( - -opensource - -confirm-license - "$BUILD_CONFIGURE_FLAG" - -static - -prefix "$INSTALL_DIR" - -nomake tests - -nomake examples - -nomake tools - -qt-zlib - -qt-libpng - -qt-libjpeg - -I "${ICU_INSTALL_DIR}/include" - -L "${ICU_INSTALL_DIR}/lib" - -L "${OPENSSL_LIB_DIR}" - -openssl-linked - "${MIN_DEP_CONFIGURE_FLAGS[@]}" -) - -require_file() { - local path="$1" - [[ -f "$path" ]] || fail "missing file: $path" -} - -require_dir() { - local path="$1" - [[ -d "$path" ]] || fail "missing directory: $path" -} - -log_verify() { - local message="$1" - echo "$message" - echo "$message" >> "${LOG_DIR}/verify.log" -} - -apply_patches() { - local patch_files=() - local patch_file - - if [[ ! -d "$PATCH_DIR" ]]; then - return 0 - fi - - mapfile -t patch_files < <(find "$PATCH_DIR" -maxdepth 1 -type f -name '*.patch' | sort) - if [[ "${#patch_files[@]}" -eq 0 ]]; then - return 0 - fi - - for patch_file in "${patch_files[@]}"; do - if patch --dry-run -p1 < "$patch_file" >/dev/null 2>&1; then - patch -p1 < "$patch_file" - elif patch --dry-run -R -p1 < "$patch_file" >/dev/null 2>&1; then - echo "==> patch already applied: $(basename "$patch_file")" - else - fail "could not apply patch: $patch_file" - fi - done -} - -configure_qt() { - local log_file="$1" - echo "==> configure Qt" - ./configure -v "${CONFIGURE_FLAGS[@]}" >"$log_file" 2>&1 -} - -webkit_disabled_by_static_notice() { - local log_file="$1" - grep -q "Using static linking will disable the WebKit module." "$log_file" -} - -build_static_icu() { - local extract_dir icu_top_dir icu_source_dir - - require_file "$ICU_SRC_ARCHIVE" - - if [[ -f "${ICU_INSTALL_DIR}/lib/libicuuc.a" && -f "${ICU_INSTALL_DIR}/lib/libicui18n.a" && -f "${ICU_INSTALL_DIR}/lib/libicudata.a" ]]; then - echo "==> reusing static ICU install: ${ICU_INSTALL_DIR}" - return - fi - - echo "==> build static ICU" - extract_dir="${WORK_DIR}/_icu_extract" - rm -rf "$extract_dir" - mkdir -p "$extract_dir" - tar -xf "$ICU_SRC_ARCHIVE" -C "$extract_dir" - - icu_top_dir="$(find "$extract_dir" -mindepth 1 -maxdepth 1 -type d | head -n 1)" - [[ -n "$icu_top_dir" ]] || fail "could not identify extracted ICU source root" - - if [[ -f "${icu_top_dir}/source/configure" ]]; then - icu_source_dir="${icu_top_dir}/source" - elif [[ -f "${icu_top_dir}/icu/source/configure" ]]; then - icu_source_dir="${icu_top_dir}/icu/source" - else - fail "could not find ICU configure script in extracted archive" - fi - - rm -rf "$ICU_INSTALL_DIR" - pushd "$icu_source_dir" >/dev/null - ./configure \ - --prefix="$ICU_INSTALL_DIR" \ - --disable-shared \ - --enable-static \ - --disable-dyload \ - --with-data-packaging=static \ - CFLAGS="-fPIC" \ - CXXFLAGS="-fPIC" >"${LOG_DIR}/icu-configure.log" 2>&1 - make -j"$JOBS" >"${LOG_DIR}/icu-build.log" 2>&1 - make install >"${LOG_DIR}/icu-install.log" 2>&1 - popd >/dev/null - - rm -rf "$extract_dir" -} - -configure_build_env_for_qt() { - require_dir "$ICU_INSTALL_DIR" - echo "==> verify system OpenSSL static archives" - require_file "${OPENSSL_INCLUDE_DIR}/openssl/ssl.h" - require_file "${OPENSSL_LIB_DIR}/libssl.a" - require_file "${OPENSSL_LIB_DIR}/libcrypto.a" - export PKG_CONFIG_PATH="${ICU_INSTALL_DIR}/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}" - export CPPFLAGS="-I${ICU_INSTALL_DIR}/include${CPPFLAGS:+ ${CPPFLAGS}}" - export LDFLAGS="-L${OPENSSL_LIB_DIR} -L${ICU_INSTALL_DIR}/lib${LDFLAGS:+ ${LDFLAGS}}" - export OPENSSL_LIBS="-Wl,-Bstatic ${OPENSSL_LIB_DIR}/libssl.a ${OPENSSL_LIB_DIR}/libcrypto.a -Wl,-Bdynamic -ldl -lpthread -lz" -} - -sync_installed_qmake_metadata() { - local qtbase_build_dir="${QT_SRC_DIR}/qtbase" - local build_qconfig="${qtbase_build_dir}/mkspecs/qconfig.pri" - local build_qmodule="${qtbase_build_dir}/mkspecs/qmodule.pri" - local build_network_prl="${qtbase_build_dir}/lib/libQt5Network.prl" - local install_qconfig="${INSTALL_DIR}/mkspecs/qconfig.pri" - local install_qmodule="${INSTALL_DIR}/mkspecs/qmodule.pri" - local install_network_prl="${INSTALL_DIR}/lib/libQt5Network.prl" - local install_lib_expr='$$[QT_INSTALL_LIBS]' - - require_file "$build_qconfig" - require_file "$build_qmodule" - require_file "$build_network_prl" - require_dir "${INSTALL_DIR}/mkspecs" - require_dir "${INSTALL_DIR}/lib" - - cp "$build_qconfig" "$install_qconfig" - cp "$build_qmodule" "$install_qmodule" - sed "s|${qtbase_build_dir}/lib|${install_lib_expr}|g" "$build_network_prl" > "$install_network_prl" -} - -mkdir -p "$WORK_DIR" "$LOG_DIR" -require_file "$QT_SRC_ARCHIVE" -require_file "$QTWEBKIT_ARCHIVE" -require_file "$ICU_SRC_ARCHIVE" - -case "${CLEAN,,}" in - 1|true|yes|on) - rm -rf "$QT_SRC_DIR" "$INSTALL_DIR" "$ICU_INSTALL_DIR" - ;; -esac - -build_static_icu -configure_build_env_for_qt - -if [[ ! -d "$QT_SRC_DIR" ]]; then - tar -xf "$QT_SRC_ARCHIVE" -C "$WORK_DIR" -fi -[[ -d "$QT_SRC_DIR" ]] || fail "expected source directory not found: $QT_SRC_DIR" - -if [[ ! -d "${QT_SRC_DIR}/qtwebkit" ]]; then - EXTRACT_DIR="${WORK_DIR}/_qtwebkit_extract" - rm -rf "$EXTRACT_DIR" - mkdir -p "$EXTRACT_DIR" - tar -xf "$QTWEBKIT_ARCHIVE" -C "$EXTRACT_DIR" - - QTWEBKIT_SRC_DIR="$(find "$EXTRACT_DIR" -mindepth 1 -maxdepth 1 -type d | head -n 1)" - [[ -n "$QTWEBKIT_SRC_DIR" ]] || fail "could not identify extracted QtWebKit source directory" - - mv "$QTWEBKIT_SRC_DIR" "${QT_SRC_DIR}/qtwebkit" - rm -rf "$EXTRACT_DIR" -fi - -pushd "$QT_SRC_DIR" >/dev/null -log_verify "configure minimal-deps flags: ${MIN_DEP_CONFIGURE_FLAGS[*]}" -apply_patches -configure_qt "${LOG_DIR}/configure.log" - -if webkit_disabled_by_static_notice "${LOG_DIR}/configure.log"; then - log_verify "warning: configure still reports static WebKit disable notice; continuing to build and validating via installed libraries" -fi - -echo "==> build Qt (make -j${JOBS})" -make -j"$JOBS" >"${LOG_DIR}/build.log" 2>&1 -echo "==> install Qt" -make install >"${LOG_DIR}/install.log" 2>&1 -sync_installed_qmake_metadata -popd >/dev/null - -QMAKE_BIN="${INSTALL_DIR}/bin/qmake" -require_file "$QMAKE_BIN" - -QT_INSTALLED_VERSION="$("$QMAKE_BIN" -query QT_VERSION)" -QT_CONFIG="" -if ! QT_CONFIG="$("$QMAKE_BIN" -query QT_CONFIG 2>/dev/null)"; then - if [[ -f "${INSTALL_DIR}/mkspecs/qconfig.pri" ]]; then - QT_CONFIG="$(sed -n 's/^QT_CONFIG += *//p' "${INSTALL_DIR}/mkspecs/qconfig.pri" | tr '\n' ' ')" - fi -fi - -if [[ "$QT_INSTALLED_VERSION" != "$QT_VERSION" ]]; then - fail "unexpected Qt version in install: $QT_INSTALLED_VERSION" -fi - -if ! echo "$QT_CONFIG" | grep -qw static; then - [[ -f "${INSTALL_DIR}/lib/libQt5Core.a" ]] || fail "installed Qt is not static" -fi - -required_libs=( - "libQt5Core.a" - "libQt5Gui.a" - "libQt5Widgets.a" - "libQt5Network.a" - "libQt5Xml.a" - "libQt5PrintSupport.a" - "libQt5WebKit.a" - "libQt5WebKitWidgets.a" -) - -required_icu_libs=( - "libicuuc.a" - "libicui18n.a" - "libicudata.a" -) -required_ssl_libs=( - "libssl.a" - "libcrypto.a" -) - -missing=0 -for lib in "${required_libs[@]}"; do - if [[ ! -f "${INSTALL_DIR}/lib/${lib}" ]]; then - log_verify "missing: ${INSTALL_DIR}/lib/${lib}" - missing=1 - fi -done - -for lib in "${required_icu_libs[@]}"; do - if [[ ! -f "${ICU_INSTALL_DIR}/lib/${lib}" ]]; then - log_verify "missing: ${ICU_INSTALL_DIR}/lib/${lib}" - missing=1 - fi -done -for lib in "${required_ssl_libs[@]}"; do - if [[ ! -f "${OPENSSL_LIB_DIR}/${lib}" ]]; then - log_verify "missing: ${OPENSSL_LIB_DIR}/${lib}" - missing=1 - fi -done -if ! grep -q 'openssl-linked' "${INSTALL_DIR}/mkspecs/qconfig.pri"; then - log_verify "missing openssl-linked in: ${INSTALL_DIR}/mkspecs/qconfig.pri" - missing=1 -fi -if ! grep -q 'libssl\.a' "${INSTALL_DIR}/lib/libQt5Network.prl" \ - || ! grep -q 'libcrypto\.a' "${INSTALL_DIR}/lib/libQt5Network.prl"; then - log_verify "missing static OpenSSL archives in: ${INSTALL_DIR}/lib/libQt5Network.prl" - missing=1 -fi -[[ "$missing" -eq 0 ]] || fail "verification failed: required static libraries are missing" - -{ - echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" - echo "qt_version=${QT_INSTALLED_VERSION}" - echo "qt_config=${QT_CONFIG}" - echo "jobs=${JOBS}" - echo "clean=${CLEAN}" - echo "build_type=${BUILD_TYPE}" - echo "minimal_dep_configure_flags=${MIN_DEP_CONFIGURE_FLAGS[*]}" - echo "qt_src_archive=${QT_SRC_ARCHIVE}" - echo "qtwebkit_archive=${QTWEBKIT_ARCHIVE}" - echo "icu_src_archive=${ICU_SRC_ARCHIVE}" - echo "qt_src_url=${QT_SRC_URL:-}" - echo "qtwebkit_url=${QTWEBKIT_URL:-}" - echo "icu_src_url=${ICU_SRC_URL:-}" - echo "qt_src_sha256=${QT_SRC_SHA256:-}" - echo "qtwebkit_sha256=${QTWEBKIT_SHA256:-}" - echo "icu_src_sha256=${ICU_SRC_SHA256:-}" - echo "qt_src_md5=${QT_SRC_MD5:-}" - echo "qtwebkit_md5=${QTWEBKIT_MD5:-}" - echo "icu_src_md5=${ICU_SRC_MD5:-}" - echo "openssl_source=system-package" - echo "openssl_include_dir=${OPENSSL_INCLUDE_DIR}" - echo "openssl_lib_dir=${OPENSSL_LIB_DIR}" - echo "verified_libs=${required_libs[*]}" - echo "verified_icu_libs=${required_icu_libs[*]}" - echo "verified_ssl_libs=${required_ssl_libs[*]}" -} > "$MANIFEST_FILE" - -log_verify "verification passed" diff --git a/toolchains/qt5-static/check-shared-deps.py b/toolchains/qt5-static/check-shared-deps.py new file mode 100755 index 0000000..8c066bc --- /dev/null +++ b/toolchains/qt5-static/check-shared-deps.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +import sys + +sys.dont_write_bytecode = True + +import os +import re +import subprocess + + +ALLOWED_LIBRARIES = { + "ld-linux-x86-64.so.2", + "libatomic.so.1", + "libbsd.so.0", + "libc.so.6", + "libdl.so.2", + "libEGL.so.1", + "libbrotlicommon.so.1", + "libbrotlidec.so.1", + "libbz2.so.1", + "libfreetype.so.6", + "libgcc_s.so.1", + "libglib-2.0.so.0", + "libGL.so.1", + "libGLdispatch.so.0", + "libGLX.so.0", + "libgraphite2.so.3", + "libharfbuzz.so.0", + "libgthread-2.0.so.0", + "libICE.so.6", + "libm.so.6", + "libmd.so.0", + "libpcre.so.3", + "libpcre2-8.so.0", + "libpthread.so.0", + "libpng16.so.16", + "librt.so.1", + "libSM.so.6", + "libstdc++.so.6", + "libX11.so.6", + "libX11-xcb.so.1", + "libXau.so.6", + "libxcb.so.1", + "libxcb-icccm.so.4", + "libxcb-image.so.0", + "libxcb-keysyms.so.1", + "libxcb-randr.so.0", + "libxcb-render.so.0", + "libxcb-render-util.so.0", + "libxcb-shape.so.0", + "libxcb-shm.so.0", + "libxcb-sync.so.1", + "libxcb-util.so.1", + "libxcb-xfixes.so.0", + "libxcb-xinerama.so.0", + "libxcb-xkb.so.1", + "libXcomposite.so.1", + "libXcursor.so.1", + "libXdamage.so.1", + "libXdmcp.so.6", + "libXext.so.6", + "libXfixes.so.3", + "libXi.so.6", + "libxkbcommon.so.0", + "libxkbcommon-x11.so.0", + "libXrandr.so.2", + "libXrender.so.1", + "libz.so.1", + "linux-vdso.so.1", +} + + +LDD_ARROW_LINE_RE = re.compile(r"^\s*(\S+)\s+=>") +LDD_LOADER_LINE_RE = re.compile(r"^\s*/\S*/([^/\s]+)\s+\(") +LDD_DIRECT_LINE_RE = re.compile(r"^\s*(\S+)\s+\(") + + +def fail(message: str) -> None: + print(f"error: {message}", file=sys.stderr) + sys.exit(1) + + +def parse_library(line: str) -> str: + if "not found" in line: + return line.split(None, 1)[0] + + for pattern in (LDD_ARROW_LINE_RE, LDD_LOADER_LINE_RE, LDD_DIRECT_LINE_RE): + match = pattern.match(line) + if match: + return match.group(1) + + fail(f"could not parse ldd line: {line}") + + +def main() -> int: + if len(sys.argv) != 2: + fail(f"usage: {sys.argv[0]} ") + + binary = sys.argv[1] + if not os.path.isfile(binary) or not os.access(binary, os.X_OK): + fail(f"binary not found or not executable: {binary}") + + result = subprocess.run( + ["ldd", binary], + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + print(f"==> ldd output: {binary}") + print(result.stdout, end="") + print() + print(f"==> dependency check: {binary}") + + missing_allowed_libraries = [] + missing_unexpected_libraries = [] + unexpected_libraries = [] + matched_allowed_libraries = set() + for line in result.stdout.splitlines(): + library = parse_library(line) + matching_allowed_libraries = { + allowed_library + for allowed_library in ALLOWED_LIBRARIES + if library.startswith(allowed_library) + } + matched_allowed_libraries.update(matching_allowed_libraries) + if "not found" in line: + if matching_allowed_libraries: + missing_allowed_libraries.append(library) + else: + missing_unexpected_libraries.append(library) + elif not matching_allowed_libraries: + unexpected_libraries.append(library) + + failed = False + if missing_unexpected_libraries: + print(f"error: missing shared dependencies for {binary}:") + for library in sorted(set(missing_unexpected_libraries)): + print(f" {library}") + failed = True + + if unexpected_libraries: + print(f"error: unexpected shared dependencies for {binary}:") + for library in sorted(set(unexpected_libraries)): + print(f" {library}") + failed = True + + if failed: + return 1 + + if missing_allowed_libraries: + print(f"warning: allowed shared dependencies not installed on check host for {binary}:") + for library in sorted(set(missing_allowed_libraries)): + print(f" {library}") + + unused_allowed_libraries = sorted(ALLOWED_LIBRARIES - matched_allowed_libraries) + if unused_allowed_libraries: + print(f"warning: allowed libraries not linked by {binary}:") + for library in unused_allowed_libraries: + print(f" {library}") + + print(f"shared dependencies allowed: {binary}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/toolchains/qt5-static/common.sh b/toolchains/qt5-static/common.sh new file mode 100644 index 0000000..045bbd5 --- /dev/null +++ b/toolchains/qt5-static/common.sh @@ -0,0 +1,27 @@ +QT_VERSION="5.15.17" +QT5_STATIC_IMAGE_TAG="qtweb-qt5-static:${QT_VERSION}" + +format_duration() { + local total_seconds="$1" + local hours minutes seconds + + if (( total_seconds < 0 )); then + total_seconds=0 + fi + + hours=$((total_seconds / 3600)) + minutes=$(((total_seconds % 3600) / 60)) + seconds=$((total_seconds % 60)) + + if (( hours > 0 )); then + printf '%dh %02dm %02ds' "$hours" "$minutes" "$seconds" + return + fi + + if (( minutes > 0 )); then + printf '%dm %02ds' "$minutes" "$seconds" + return + fi + + printf '%ds' "$seconds" +} diff --git a/toolchains/qt5-static/patches/0001-enable-static-webkit.patch b/toolchains/qt5-static/patches/0001-enable-static-webkit.patch deleted file mode 100644 index 57ca328..0000000 --- a/toolchains/qt5-static/patches/0001-enable-static-webkit.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/qtbase/configure -+++ b/qtbase/configure -@@ -6439,12 +6439,6 @@ - canBuildWebKit="no" - fi - --if [ "$CFG_SHARED" = "no" ]; then -- echo -- echo "WARNING: Using static linking will disable the WebKit module." -- echo -- canBuildWebKit="no" --fi - - CFG_CONCURRENT="yes" - if [ "$canBuildQtConcurrent" = "no" ]; then diff --git a/toolchains/qt5-static/patches/0002-javascriptcore-jschar-uchar-casts.patch b/toolchains/qt5-static/patches/0002-javascriptcore-jschar-uchar-casts.patch deleted file mode 100644 index 598a507..0000000 --- a/toolchains/qt5-static/patches/0002-javascriptcore-jschar-uchar-casts.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/qtwebkit/Source/JavaScriptCore/API/JSStringRef.cpp -+++ b/qtwebkit/Source/JavaScriptCore/API/JSStringRef.cpp -@@ -37,7 +37,7 @@ - JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars) - { - initializeThreading(); -- return OpaqueJSString::create(chars, numChars).leakRef(); -+ return OpaqueJSString::create(reinterpret_cast(chars), numChars).leakRef(); - } - - JSStringRef JSStringCreateWithUTF8CString(const char* string) -@@ -62,7 +62,7 @@ - JSStringRef JSStringCreateWithCharactersNoCopy(const JSChar* chars, size_t numChars) - { - initializeThreading(); -- return OpaqueJSString::create(StringImpl::createWithoutCopying(chars, numChars, WTF::DoesNotHaveTerminatingNullCharacter)).leakRef(); -+ return OpaqueJSString::create(StringImpl::createWithoutCopying(reinterpret_cast(chars), numChars, WTF::DoesNotHaveTerminatingNullCharacter)).leakRef(); - } - - JSStringRef JSStringRetain(JSStringRef string) -@@ -83,7 +83,7 @@ - - const JSChar* JSStringGetCharactersPtr(JSStringRef string) - { -- return string->characters(); -+ return reinterpret_cast(string->characters()); - } - - size_t JSStringGetMaximumUTF8CStringSize(JSStringRef string) diff --git a/toolchains/qt5-static/patches/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch b/toolchains/qt5-static/patches/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch deleted file mode 100644 index 55bcca7..0000000 --- a/toolchains/qt5-static/patches/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/qtbase/qmake/generators/unix/unixmake2.cpp b/qtbase/qmake/generators/unix/unixmake2.cpp -index 3e2b4f2..a11f44e 100644 ---- a/qtbase/qmake/generators/unix/unixmake2.cpp -+++ b/qtbase/qmake/generators/unix/unixmake2.cpp -@@ -188,8 +188,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) - if(!project->isActiveConfig("staticlib")) { - t << "LINK = " << var("QMAKE_LINK") << endl; - t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; -- t << "LIBS = $(SUBLIBS) " << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' -- << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl; -+ t << "LIBS = -Wl,--start-group " -+ << "$(SUBLIBS) " << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' -+ << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') -+ << " -Wl,--end-group" << endl; - } diff --git a/toolchains/qt5-static/patches/README.md b/toolchains/qt5-static/patches/README.md index 8ca628c..10fdbbf 100644 --- a/toolchains/qt5-static/patches/README.md +++ b/toolchains/qt5-static/patches/README.md @@ -1,8 +1,12 @@ # Optional Patch Hook -Drop Qt source patches (`*.patch`) in this directory to support legacy build fixes. +Store source patches (`*.patch`) under the tree-specific subdirectories: -Behavior in `build-inside-container.sh`: -1. Run `configure` once. -2. If `Qt WebKit` is not enabled, apply all patches in lexicographic order. -3. Run `configure` again and continue only if WebKit is enabled. +- `qt/` for Qt source patches +- `qtwebkit/` for QtWebKit source patches + +Behavior in `qt5-static-build-entrypoint.sh`: +1. Apply patches from `patches/qt/` only to the Qt tree. +2. Apply patches from `patches/qtwebkit/` only to the QtWebKit tree. +3. Process patches in lexicographic order within that tree. +4. Fail the build if a patch for that tree is neither applicable nor already applied. diff --git a/toolchains/qt5-static/patches/qt/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch b/toolchains/qt5-static/patches/qt/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch new file mode 100644 index 0000000..41cd607 --- /dev/null +++ b/toolchains/qt5-static/patches/qt/0003-unixmake2-wrap-qmake-libs-in-start-end-group.patch @@ -0,0 +1,17 @@ +--- a/qtbase/qmake/generators/unix/unixmake2.cpp ++++ b/qtbase/qmake/generators/unix/unixmake2.cpp +@@ -219,10 +219,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) + if(!project->isActiveConfig("staticlib")) { + t << "LINK = " << var("QMAKE_LINK") << Qt::endl; + t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl; +- t << "LIBS = $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' ' +- << fixLibFlags("LIBS_PRIVATE").join(' ') << ' ' +- << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' +- << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl; ++ t << "LIBS = -Wl,--start-group $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' ' ++ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' ' ++ << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' ++ << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << " -Wl,--end-group" << Qt::endl; + } + + t << "AR = " << var("QMAKE_AR") << Qt::endl; diff --git a/toolchains/qt5-static/patches/0004-qt_parts-honor-no-make-tools.patch b/toolchains/qt5-static/patches/qt/0004-qt_parts-honor-no-make-tools.patch similarity index 100% rename from toolchains/qt5-static/patches/0004-qt_parts-honor-no-make-tools.patch rename to toolchains/qt5-static/patches/qt/0004-qt_parts-honor-no-make-tools.patch diff --git a/toolchains/qt5-static/patches/qt/0005-imageformats-honor-webp-libs-override.patch b/toolchains/qt5-static/patches/qt/0005-imageformats-honor-webp-libs-override.patch new file mode 100644 index 0000000..13f0aae --- /dev/null +++ b/toolchains/qt5-static/patches/qt/0005-imageformats-honor-webp-libs-override.patch @@ -0,0 +1,13 @@ +diff --git a/qtimageformats/src/imageformats/configure.json b/qtimageformats/src/imageformats/configure.json +index 2a359305..e2c8b2fb 100644 +--- a/qtimageformats/src/imageformats/configure.json ++++ b/qtimageformats/src/imageformats/configure.json +@@ -115,7 +115,7 @@ + ] + }, + "sources": [ +- { "type": "pkgConfig", "args": "libwebp libwebpmux libwebpdemux" }, ++ { "type": "pkgConfig", "condition": "input.webp.libs == ''", "args": "libwebp libwebpmux libwebpdemux" }, + { "libs": "-lwebp -lwebpdemux -lwebpmux" } + ] + } diff --git a/toolchains/qt5-static/patches/qtwebkit/0005-javascriptcore-skip-shell-for-static-qt.patch b/toolchains/qt5-static/patches/qtwebkit/0005-javascriptcore-skip-shell-for-static-qt.patch new file mode 100644 index 0000000..1efddd7 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0005-javascriptcore-skip-shell-for-static-qt.patch @@ -0,0 +1,11 @@ +diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt +--- a/Source/JavaScriptCore/CMakeLists.txt ++++ b/Source/JavaScriptCore/CMakeLists.txt +@@ -1567,4 +1567,6 @@ if (USE_VERSION_STAMPER) + VERBATIM) + endif () + +-add_subdirectory(shell) ++if (NOT QT_STATIC_BUILD) ++ add_subdirectory(shell) ++endif () diff --git a/toolchains/qt5-static/patches/qtwebkit/0006-optionsqt-skip-missing-target-export.patch b/toolchains/qt5-static/patches/qtwebkit/0006-optionsqt-skip-missing-target-export.patch new file mode 100644 index 0000000..9f97e79 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0006-optionsqt-skip-missing-target-export.patch @@ -0,0 +1,11 @@ +diff --git a/Source/cmake/OptionsQt.cmake b/Source/cmake/OptionsQt.cmake +--- a/Source/cmake/OptionsQt.cmake ++++ b/Source/cmake/OptionsQt.cmake +@@ -96,7 +96,7 @@ endmacro() + + macro(QT_ADD_EXTRA_WEBKIT_TARGET_EXPORT target) +- if (QT_STATIC_BUILD OR SHARED_CORE) ++ if ((QT_STATIC_BUILD OR SHARED_CORE) AND TARGET ${target}) + install(TARGETS ${target} EXPORT WebKitTargets + DESTINATION "${LIB_INSTALL_DIR}") + endif () diff --git a/toolchains/qt5-static/patches/qtwebkit/0007-platformqt-skip-cmake-package-install-for-static-build.patch b/toolchains/qt5-static/patches/qtwebkit/0007-platformqt-skip-cmake-package-install-for-static-build.patch new file mode 100644 index 0000000..77e256b --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0007-platformqt-skip-cmake-package-install-for-static-build.patch @@ -0,0 +1,16 @@ +diff --git a/Source/PlatformQt.cmake b/Source/PlatformQt.cmake +--- a/Source/PlatformQt.cmake ++++ b/Source/PlatformQt.cmake +@@ -192,6 +192,7 @@ write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/Qt5WebKitConfigVer + write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/Qt5WebKitWidgetsConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion) ++if (NOT QT_STATIC_BUILD) + + install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/Qt5WebKitConfig.cmake" +@@ -217,3 +218,4 @@ install(EXPORT Qt5WebKitWidgetsTargets + DESTINATION "${KDE_INSTALL_CMAKEPACKAGEDIR}/Qt5WebKitWidgets" + COMPONENT Code + ) ++endif () diff --git a/toolchains/qt5-static/patches/qtwebkit/0008-publicsuffixqt-fix-localhost-compare.patch b/toolchains/qt5-static/patches/qtwebkit/0008-publicsuffixqt-fix-localhost-compare.patch new file mode 100644 index 0000000..df75220 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0008-publicsuffixqt-fix-localhost-compare.patch @@ -0,0 +1,12 @@ +diff --git a/Source/WebCore/platform/network/qt/PublicSuffixQt.cpp b/Source/WebCore/platform/network/qt/PublicSuffixQt.cpp +--- a/Source/WebCore/platform/network/qt/PublicSuffixQt.cpp ++++ b/Source/WebCore/platform/network/qt/PublicSuffixQt.cpp +@@ -64,7 +64,7 @@ String topPrivatelyControlledDomain(const String& domain) + return domain; + + String lowercaseDomain = domain.convertToASCIILowercase(); +- if (lowercaseDomain == QLatin1String("localhost")) ++ if (lowercaseDomain == "localhost"_s) + return lowercaseDomain; + + QString qLowercaseDomain = lowercaseDomain; diff --git a/toolchains/qt5-static/patches/qtwebkit/0009-compressionstream-contain-qtzlib-macros.patch b/toolchains/qt5-static/patches/qtwebkit/0009-compressionstream-contain-qtzlib-macros.patch new file mode 100644 index 0000000..01fa401 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0009-compressionstream-contain-qtzlib-macros.patch @@ -0,0 +1,122 @@ +diff --git a/Source/WebCore/Modules/compression/CompressionStreamEncoder.h b/Source/WebCore/Modules/compression/CompressionStreamEncoder.h +--- a/Source/WebCore/Modules/compression/CompressionStreamEncoder.h ++++ b/Source/WebCore/Modules/compression/CompressionStreamEncoder.h +@@ -33,6 +33,19 @@ + #include + #include + ++// Qt's static zlib build prefixes its API via preprocessor macros such as ++// inflate -> z_inflate. Keep those macros from leaking into the rest of the ++// unified WebCore translation unit. ++#ifdef deflate ++#undef deflate ++#endif ++#ifdef deflateEnd ++#undef deflateEnd ++#endif ++#ifdef deflateInit2 ++#undef deflateInit2 ++#endif ++ + namespace WebCore { + + class CompressionStreamEncoder : public RefCounted { +@@ -48,7 +61,7 @@ + ~CompressionStreamEncoder() + { + if (m_initialized) +- deflateEnd(&m_zstream); ++ z_deflateEnd(&m_zstream); + } + + private: +diff --git a/Source/WebCore/Modules/compression/CompressionStreamEncoder.cpp b/Source/WebCore/Modules/compression/CompressionStreamEncoder.cpp +--- a/Source/WebCore/Modules/compression/CompressionStreamEncoder.cpp ++++ b/Source/WebCore/Modules/compression/CompressionStreamEncoder.cpp +@@ -76,13 +76,13 @@ + // Values chosen here are based off + // https://developer.apple.com/documentation/compression/compression_algorithm/compression_zlib?language=objc + case Formats::CompressionFormat::Deflate: +- result = deflateInit2(&m_zstream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); ++ result = z_deflateInit2(&m_zstream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + break; + case Formats::CompressionFormat::Zlib: +- result = deflateInit2(&m_zstream, 5, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY); ++ result = z_deflateInit2(&m_zstream, 5, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY); + break; + case Formats::CompressionFormat::Gzip: +- result = deflateInit2(&m_zstream, 5, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); ++ result = z_deflateInit2(&m_zstream, 5, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); +@@ -129,7 +129,7 @@ + m_zstream.next_out = output.data(); + m_zstream.avail_out = output.size(); + +- result = deflate(&m_zstream, (m_finish) ? Z_FINISH : Z_NO_FLUSH); ++ result = z_deflate(&m_zstream, (m_finish) ? Z_FINISH : Z_NO_FLUSH); + if (result != Z_OK && result != Z_STREAM_END && result != Z_BUF_ERROR) + return Exception { TypeError, "Failed to compress data."_s }; + +diff --git a/Source/WebCore/Modules/compression/DecompressionStreamDecoder.h b/Source/WebCore/Modules/compression/DecompressionStreamDecoder.h +--- a/Source/WebCore/Modules/compression/DecompressionStreamDecoder.h ++++ b/Source/WebCore/Modules/compression/DecompressionStreamDecoder.h +@@ -38,6 +38,19 @@ + #include + #include + ++// Qt's static zlib build prefixes its API via preprocessor macros such as ++// inflate -> z_inflate. Keep those macros from leaking into the rest of the ++// unified WebCore translation unit. ++#ifdef inflate ++#undef inflate ++#endif ++#ifdef inflateEnd ++#undef inflateEnd ++#endif ++#ifdef inflateInit2 ++#undef inflateInit2 ++#endif ++ + namespace WebCore { + + class DecompressionStreamDecoder : public RefCounted { +@@ -58,7 +71,7 @@ + compression_stream_destroy(&m_stream); + #endif + } else +- deflateEnd(&m_zstream); ++ z_inflateEnd(&m_zstream); + } + } + +diff --git a/Source/WebCore/Modules/compression/DecompressionStreamDecoder.cpp b/Source/WebCore/Modules/compression/DecompressionStreamDecoder.cpp +--- a/Source/WebCore/Modules/compression/DecompressionStreamDecoder.cpp ++++ b/Source/WebCore/Modules/compression/DecompressionStreamDecoder.cpp +@@ -81,13 +81,13 @@ + + switch (m_format) { + case Formats::CompressionFormat::Deflate: +- result = inflateInit2(&m_zstream, -15); ++ result = z_inflateInit2(&m_zstream, -15); + break; + case Formats::CompressionFormat::Zlib: +- result = inflateInit2(&m_zstream, 15); ++ result = z_inflateInit2(&m_zstream, 15); + break; + case Formats::CompressionFormat::Gzip: +- result = inflateInit2(&m_zstream, 15 + 16); ++ result = z_inflateInit2(&m_zstream, 15 + 16); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); +@@ -133,7 +133,7 @@ + m_zstream.next_out = output.data(); + m_zstream.avail_out = output.size(); + +- result = inflate(&m_zstream, (m_finish) ? Z_FINISH : Z_NO_FLUSH); ++ result = z_inflate(&m_zstream, (m_finish) ? Z_FINISH : Z_NO_FLUSH); + + if (result != Z_OK && result != Z_STREAM_END && result != Z_BUF_ERROR) + return Exception { TypeError, "Failed to Decode Data."_s }; diff --git a/toolchains/qt5-static/patches/qtwebkit/0010-platformqt-build-widgets-only.patch b/toolchains/qt5-static/patches/qtwebkit/0010-platformqt-build-widgets-only.patch new file mode 100644 index 0000000..1828d41 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0010-platformqt-build-widgets-only.patch @@ -0,0 +1,65 @@ +diff --git a/Source/WebKit/PlatformQt.cmake b/Source/WebKit/PlatformQt.cmake +--- a/Source/WebKit/PlatformQt.cmake ++++ b/Source/WebKit/PlatformQt.cmake +@@ -106,25 +106,6 @@ + + UIProcess/API/cpp/qt/WKStringQt.cpp + UIProcess/API/cpp/qt/WKURLQt.cpp +- +- UIProcess/API/qt/qquicknetworkreply.cpp +- UIProcess/API/qt/qquicknetworkrequest.cpp +- UIProcess/API/qt/qquickurlschemedelegate.cpp +- UIProcess/API/qt/qquickwebpage.cpp +- UIProcess/API/qt/qquickwebview.cpp +- UIProcess/API/qt/qtwebsecurityorigin.cpp +- UIProcess/API/qt/qwebchannelwebkittransport.cpp +- UIProcess/API/qt/qwebdownloaditem.cpp +- UIProcess/API/qt/qwebdownloaditem_p.h +- UIProcess/API/qt/qwebdownloaditem_p_p.h +- UIProcess/API/qt/qwebiconimageprovider.cpp +- UIProcess/API/qt/qwebkittest.cpp +- UIProcess/API/qt/qwebloadrequest.cpp +- UIProcess/API/qt/qwebnavigationhistory.cpp +- UIProcess/API/qt/qwebnavigationrequest.cpp +- UIProcess/API/qt/qwebpermissionrequest.cpp +- UIProcess/API/qt/qwebpreferences.cpp +- + UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp + + UIProcess/Launcher/qt/ProcessLauncherQt.cpp +@@ -192,19 +173,6 @@ + WebProcess/qt/WebProcessQt.cpp + ) + +-if (COMPILER_IS_GCC_OR_CLANG) +- set_source_files_properties( +- UIProcess/API/qt/qquicknetworkreply.cpp +- UIProcess/API/qt/qquicknetworkrequest.cpp +- UIProcess/API/qt/qquickurlschemedelegate.cpp +- UIProcess/API/qt/qquickwebpage.cpp +- UIProcess/API/qt/qquickwebview.cpp +- UIProcess/API/qt/qwebiconimageprovider.cpp +- PROPERTIES +- COMPILE_FLAGS -frtti +- ) +-endif () +- + if (USE_MACH_PORTS) + list(APPEND WebKit_INCLUDE_DIRECTORIES + "${WEBKIT_DIR}/Platform/IPC/cocoa" +@@ -251,15 +219,11 @@ + list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES + ${GLIB_INCLUDE_DIRS} + ${GSTREAMER_INCLUDE_DIRS} +- ${Qt5Quick_INCLUDE_DIRS} +- ${Qt5Quick_PRIVATE_INCLUDE_DIRS} + ${SQLITE_INCLUDE_DIR} + ) + + list(APPEND WebKit_LIBRARIES + ${Qt5Positioning_LIBRARIES} +- ${Qt5Quick_LIBRARIES} +- ${Qt5WebChannel_LIBRARIES} + ${X11_X11_LIB} + ) + diff --git a/toolchains/qt5-static/patches/qtwebkit/0011-qwebsettings-guard-media-setting-with-video.patch b/toolchains/qt5-static/patches/qtwebkit/0011-qwebsettings-guard-media-setting-with-video.patch new file mode 100644 index 0000000..a96fdb7 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0011-qwebsettings-guard-media-setting-with-video.patch @@ -0,0 +1,14 @@ +diff --git a/Source/WebKitLegacy/qt/Api/qwebsettings.cpp b/Source/WebKitLegacy/qt/Api/qwebsettings.cpp +--- a/Source/WebKitLegacy/qt/Api/qwebsettings.cpp ++++ b/Source/WebKitLegacy/qt/Api/qwebsettings.cpp +@@ -175,8 +175,10 @@ void QWebSettingsPrivate::apply() + settings->setMediaSourceEnabled(value); + #endif + ++#if ENABLE(VIDEO) + value = attributes.value(QWebSettings::MediaEnabled, global->attributes.value(QWebSettings::MediaEnabled)); + settings->setMediaEnabled(value); ++#endif + + value = attributes.value(QWebSettings::HyperlinkAuditingEnabled, + global->attributes.value(QWebSettings::HyperlinkAuditingEnabled)); diff --git a/toolchains/qt5-static/patches/qtwebkit/0012-webkitlegacy-static-for-static-qt.patch b/toolchains/qt5-static/patches/qtwebkit/0012-webkitlegacy-static-for-static-qt.patch new file mode 100644 index 0000000..a429744 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0012-webkitlegacy-static-for-static-qt.patch @@ -0,0 +1,14 @@ +diff --git a/Source/WebKitLegacy/CMakeLists.txt b/Source/WebKitLegacy/CMakeLists.txt +--- a/Source/WebKitLegacy/CMakeLists.txt ++++ b/Source/WebKitLegacy/CMakeLists.txt +@@ -34,6 +34,10 @@ set(WebKitLegacy_PRIVATE_LIBRARIES + WebKit::WebCore + ) + ++if (${PORT} STREQUAL "Qt" AND QT_STATIC_BUILD) ++ set(WebKitLegacy_LIBRARY_TYPE STATIC) ++endif () ++ + WEBKIT_FRAMEWORK_DECLARE(WebKitLegacy) + WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() + diff --git a/toolchains/qt5-static/patches/qtwebkit/0013-platformqt-generate-static-pri-libs.patch b/toolchains/qt5-static/patches/qtwebkit/0013-platformqt-generate-static-pri-libs.patch new file mode 100644 index 0000000..761ca37 --- /dev/null +++ b/toolchains/qt5-static/patches/qtwebkit/0013-platformqt-generate-static-pri-libs.patch @@ -0,0 +1,24 @@ +diff --git a/Source/WebKitLegacy/PlatformQt.cmake b/Source/WebKitLegacy/PlatformQt.cmake +--- a/Source/WebKitLegacy/PlatformQt.cmake ++++ b/Source/WebKitLegacy/PlatformQt.cmake +@@ -357,6 +357,9 @@ if (QT_STATIC_BUILD) + set(WEBKIT_PKGCONFIG_DEPS "${WEBKIT_PKGCONFIG_DEPS} ${LIB_PREFIX}${LIB_NAME}") + set(WEBKIT_PRI_EXTRA_LIBS "${WEBKIT_PRI_EXTRA_LIBS} -l${LIB_PREFIX}${LIB_NAME}") + endforeach () ++ if (QTWEBKIT_SYSTEM_LIB_DIR) ++ set(WEBKIT_PRI_EXTRA_LIBS "-L\$\$QT_MODULE_LIB_BASE -lWebCore -lPAL -lJavaScriptCore -lWTF ${QTWEBKIT_SYSTEM_LIB_DIR}/libxml2.a ${QTWEBKIT_SYSTEM_LIB_DIR}/liblzma.a ${QTWEBKIT_SYSTEM_LIB_DIR}/libharfbuzz-icu.a ${QTWEBKIT_SYSTEM_LIB_DIR}/libicui18n.a ${QTWEBKIT_SYSTEM_LIB_DIR}/libicuuc.a ${QTWEBKIT_SYSTEM_LIB_DIR}/libicudata.a ${QTWEBKIT_SYSTEM_LIB_DIR}/libsqlite3.a -lz -lbmalloc ${QTWEBKIT_SYSTEM_LIB_DIR}/libhyphen.a -latomic") ++ endif () + endif () + + if (NOT MACOS_BUILD_FRAMEWORKS) +@@ -687,6 +690,10 @@ else () + endif () + endif () + ++if (QT_STATIC_BUILD) ++ list(APPEND WebKitWidgets_PRI_ARGUMENTS MODULE_CONFIG "staticlib") ++endif () ++ + list(APPEND WebKitWidgets_Private_PRI_ARGUMENTS MODULE_CONFIG "internal_module no_link") + + if (MACOS_BUILD_FRAMEWORKS) diff --git a/toolchains/qt5-static/qt5-static-build-entrypoint.sh b/toolchains/qt5-static/qt5-static-build-entrypoint.sh new file mode 100755 index 0000000..8b7ded6 --- /dev/null +++ b/toolchains/qt5-static/qt5-static-build-entrypoint.sh @@ -0,0 +1,364 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${QT_VERSION:?QT_VERSION is required}" +: "${OUTPUT_DIR:?OUTPUT_DIR is required}" +: "${QT_SRC_ARCHIVE:?QT_SRC_ARCHIVE is required}" +: "${QTWEBKIT_ARCHIVE:?QTWEBKIT_ARCHIVE is required}" + +JOBS="${JOBS:-$(nproc 2>/dev/null || echo 8)}" +QTWEBKIT_JOBS="$JOBS" +if (( QTWEBKIT_JOBS > 12 )); then + QTWEBKIT_JOBS=12 +fi +CLEAN="${CLEAN:-false}" +BUILD_TYPE="${BUILD_TYPE:-release}" +BUILD_SCOPE="${BUILD_SCOPE:-all}" +WORK_DIR="${OUTPUT_DIR}/build" +LOG_DIR="${OUTPUT_DIR}/logs" +INSTALL_DIR="${OUTPUT_DIR}/install" +SYSTEM_LIB_DIR="/usr/lib/x86_64-linux-gnu" +DEJAVU_FONT_DIR="/usr/share/fonts/truetype/dejavu" +MANIFEST_FILE="${OUTPUT_DIR}/build-manifest.txt" +PATCH_DIR="/workspace/toolchains/qt5-static/patches" +QT_SRC_DIR="" +QTWEBKIT_SOURCE_DIR="" +QTWEBKIT_BUILD_DIR="${WORK_DIR}/qtwebkit-build-${BUILD_TYPE}" +SMOKE_DIR="/workspace/smoke-tests/qtwebkit-smoke" +SMOKE_BUILD_DIR="${SMOKE_DIR}/build-docker-${BUILD_TYPE}" + +fail() { + echo "error: $*" >&2 + exit 1 +} + +case "$BUILD_TYPE" in + release) + BUILD_CONFIGURE_FLAG="-release" + CMAKE_BUILD_TYPE="Release" + ;; + debug) + BUILD_CONFIGURE_FLAG="-debug" + CMAKE_BUILD_TYPE="Debug" + ;; + *) + fail "BUILD_TYPE must be release or debug, got: $BUILD_TYPE" + ;; +esac + +case "$BUILD_SCOPE" in + all|qt|qtwebkit) ;; + *) + fail "BUILD_SCOPE must be all, qt, or qtwebkit; got: $BUILD_SCOPE" + ;; +esac + +CONFIGURE_FLAGS=( + -opensource + -confirm-license + "$BUILD_CONFIGURE_FLAG" + -static + -prefix "$INSTALL_DIR" + -skip qtdeclarative + -skip qtwebengine + -nomake tests + -nomake examples + -nomake tools + -no-dbus + -no-gtk + -no-fontconfig + -qt-pcre + -qt-freetype + -qt-zlib + -qt-libpng + -qt-libjpeg + -icu + "ICU_LIBS=${SYSTEM_LIB_DIR}/libicui18n.a ${SYSTEM_LIB_DIR}/libicuuc.a ${SYSTEM_LIB_DIR}/libicudata.a" + "WEBP_LIBS=${SYSTEM_LIB_DIR}/libwebpmux.a ${SYSTEM_LIB_DIR}/libwebpdemux.a ${SYSTEM_LIB_DIR}/libwebp.a -lpthread" + -openssl-linked +) + +require_file() { + local path="$1" + [[ -f "$path" ]] || fail "missing file: $path" +} + +require_dir() { + local path="$1" + [[ -d "$path" ]] || fail "missing directory: $path" +} + +is_thin_archive() { + local path="$1" + file "$path" 2>/dev/null | grep -q 'thin archive' +} + +log_verify() { + local message="$1" + echo "$message" + echo "$message" >> "${LOG_DIR}/verify.log" +} + +locate_qt_source_dir() { + find "$WORK_DIR" -maxdepth 1 -mindepth 1 -type d -name "qt-everywhere*-${QT_VERSION}" | head -n 1 +} + +apply_matching_patches() { + local tree_name="$1" + local tree_patch_dir="${PATCH_DIR}/${tree_name}" + local patch_files=() + local patch_file + + if [[ ! -d "$tree_patch_dir" ]]; then + return 0 + fi + + mapfile -t patch_files < <(find "$tree_patch_dir" -maxdepth 1 -type f -name '*.patch' | sort) + if [[ "${#patch_files[@]}" -eq 0 ]]; then + return 0 + fi + + for patch_file in "${patch_files[@]}"; do + if patch --dry-run -p1 < "$patch_file" >/dev/null 2>&1; then + echo "==> apply ${tree_name} patch: $(basename "$patch_file")" + patch -p1 < "$patch_file" + elif patch --dry-run -R -p1 < "$patch_file" >/dev/null 2>&1; then + echo "==> ${tree_name} patch already applied: $(basename "$patch_file")" + else + fail "${tree_name} patch does not apply cleanly: $(basename "$patch_file")" + fi + done +} + +configure_build_env_for_qt() { + echo "==> verify system ICU static archives" + require_file "${SYSTEM_LIB_DIR}/libicuuc.a" + require_file "${SYSTEM_LIB_DIR}/libicui18n.a" + require_file "${SYSTEM_LIB_DIR}/libicudata.a" + echo "==> verify system OpenSSL static archives" + require_file "${SYSTEM_LIB_DIR}/libssl.a" + require_file "${SYSTEM_LIB_DIR}/libcrypto.a" + export OPENSSL_LIBS="-Wl,-Bstatic ${SYSTEM_LIB_DIR}/libssl.a ${SYSTEM_LIB_DIR}/libcrypto.a -Wl,-Bdynamic -ldl -lpthread -lz" +} + +configure_qt() { + echo "==> configure Qt" + ./configure -v "${CONFIGURE_FLAGS[@]}" >"${LOG_DIR}/configure.log" 2>&1 +} + +install_qt_runtime_fonts() { + local font_dir="${INSTALL_DIR}/lib/fonts" + local font_files=("${DEJAVU_FONT_DIR}"/*.ttf) + + require_dir "${INSTALL_DIR}/lib" + require_dir "$DEJAVU_FONT_DIR" + [[ -e "${font_files[0]}" ]] || fail "no DejaVu TTF fonts found in ${DEJAVU_FONT_DIR}" + + mkdir -p "$font_dir" + cp -f "${font_files[@]}" "$font_dir"/ +} + +build_qtwebkit() { + local extract_dir source_root + local top_level_entries=() + + if [[ -f "${INSTALL_DIR}/lib/libQt5WebKit.a" && -f "${INSTALL_DIR}/lib/libQt5WebKitWidgets.a" ]]; then + if is_thin_archive "${INSTALL_DIR}/lib/libQt5WebKit.a" || is_thin_archive "${INSTALL_DIR}/lib/libQt5WebKitWidgets.a"; then + fail "installed QtWebKit archives are thin; remove the installed QtWebKit artifacts and rerun so they can be rebuilt as normal archives" + fi + echo "==> reusing installed QtWebKit from ${INSTALL_DIR}" + return + fi + + echo "==> extract QtWebKit" + extract_dir="${WORK_DIR}/_qtwebkit_extract" + rm -rf "$extract_dir" "$QTWEBKIT_BUILD_DIR" + mkdir -p "$extract_dir" "$QTWEBKIT_BUILD_DIR" + tar -xf "$QTWEBKIT_ARCHIVE" -C "$extract_dir" + + mapfile -t top_level_entries < <(find "$extract_dir" -mindepth 1 -maxdepth 1 | sort) + if [[ "${#top_level_entries[@]}" -eq 1 && -d "${top_level_entries[0]}" ]]; then + source_root="${top_level_entries[0]}" + QTWEBKIT_SOURCE_DIR="${WORK_DIR}/$(basename "$source_root")" + else + require_file "${extract_dir}/CMakeLists.txt" + require_dir "${extract_dir}/Source" + source_root="$extract_dir" + QTWEBKIT_SOURCE_DIR="${WORK_DIR}/qtwebkit-source" + fi + + rm -rf "$QTWEBKIT_SOURCE_DIR" + mv "$source_root" "$QTWEBKIT_SOURCE_DIR" + if [[ "$source_root" != "$extract_dir" ]]; then + rm -rf "$extract_dir" + fi + + pushd "$QTWEBKIT_SOURCE_DIR" >/dev/null + apply_matching_patches "qtwebkit" + popd >/dev/null + + pushd "$QTWEBKIT_BUILD_DIR" >/dev/null + echo "==> configure QtWebKit" + local cmake_args=( + -DPORT=Qt + -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" + -DCMAKE_PREFIX_PATH="${INSTALL_DIR}" + -DQt5_DIR="${INSTALL_DIR}/lib/cmake/Qt5" + -DICU_UC_LIBRARY="${SYSTEM_LIB_DIR}/libicuuc.a" + -DICU_I18N_LIBRARY="${SYSTEM_LIB_DIR}/libicui18n.a" + -DICU_DATA_LIBRARY="${SYSTEM_LIB_DIR}/libicudata.a" + -DQTWEBKIT_SYSTEM_LIB_DIR="${SYSTEM_LIB_DIR}" + -DENABLE_API_TESTS=OFF + -DENABLE_TOOLS=OFF + -DENABLE_GEOLOCATION=OFF + -DENABLE_PRINT_SUPPORT=ON + -DENABLE_VIDEO=OFF + -DENABLE_WEBKIT=OFF + -DENABLE_WEBKIT2=OFF + -DUSE_THIN_ARCHIVES=OFF + -DUSE_GSTREAMER=OFF + -DUSE_LD_GOLD=OFF + -DUSE_WOFF2=OFF # Avoid WOFF2/Brotli runtime deps; pages fall back to other fonts when available. + -DENABLE_WEB_CRYPTO=OFF # Avoid libgcrypt/libtasn1 deps; HTTPS still works, but window.crypto.subtle is unavailable. + -DENABLE_XSLT=OFF # Avoid libxslt dependency; legacy XML+XSLT pages will not transform client-side. + "${QTWEBKIT_SOURCE_DIR}" + ) + cmake -G Ninja "${cmake_args[@]}" >"${LOG_DIR}/qtwebkit-configure.log" 2>&1 + echo "==> build QtWebKit" + ninja -j"$QTWEBKIT_JOBS" >"${LOG_DIR}/qtwebkit-build.log" 2>&1 + echo "==> install QtWebKit" + ninja install >"${LOG_DIR}/qtwebkit-install.log" 2>&1 + popd >/dev/null +} + +mkdir -p "$WORK_DIR" "$LOG_DIR" +require_file "$QT_SRC_ARCHIVE" +require_file "$QTWEBKIT_ARCHIVE" + +case "${CLEAN,,}" in + 1|true|yes|on) + find "$WORK_DIR" -maxdepth 1 -mindepth 1 -type d -name "qt-everywhere*-${QT_VERSION}" -exec rm -rf {} + + rm -rf "$QTWEBKIT_BUILD_DIR" "$INSTALL_DIR" + ;; +esac + +if [[ "$BUILD_SCOPE" == "all" || "$BUILD_SCOPE" == "qt" ]]; then + configure_build_env_for_qt + + if [[ ! -x "${INSTALL_DIR}/bin/qmake" ]]; then + find "$WORK_DIR" -maxdepth 1 -mindepth 1 -type d -name "qt-everywhere*-${QT_VERSION}" -exec rm -rf {} + + fi + + QT_SRC_DIR="$(locate_qt_source_dir)" + if [[ -z "$QT_SRC_DIR" ]]; then + tar -xf "$QT_SRC_ARCHIVE" -C "$WORK_DIR" + fi + QT_SRC_DIR="$(locate_qt_source_dir)" + [[ -d "$QT_SRC_DIR" ]] || fail "expected source directory not found: $QT_SRC_DIR" + + pushd "$QT_SRC_DIR" >/dev/null + apply_matching_patches "qt" + configure_qt + echo "==> build Qt (make -j${JOBS})" + make -j"$JOBS" >"${LOG_DIR}/build.log" 2>&1 + echo "==> install Qt" + make install >"${LOG_DIR}/install.log" 2>&1 + install_qt_runtime_fonts + popd >/dev/null +fi + +if [[ "$BUILD_SCOPE" == "all" || "$BUILD_SCOPE" == "qtwebkit" ]]; then + configure_build_env_for_qt + require_file "${INSTALL_DIR}/bin/qmake" + install_qt_runtime_fonts + build_qtwebkit + echo "==> build QtWebKit smoke test" + require_file "${SMOKE_DIR}/smoke-build-entrypoint.sh" + JOBS="$JOBS" \ + QT_PREFIX_IN_CONTAINER="$INSTALL_DIR" \ + BUILD_DIR_IN_CONTAINER="${SMOKE_BUILD_DIR#/workspace/}" \ + BUILD_TYPE="$BUILD_TYPE" \ + "${SMOKE_DIR}/smoke-build-entrypoint.sh" >"${LOG_DIR}/smoke-build.log" 2>&1 + require_file "${SMOKE_BUILD_DIR}/qtwebkit-smoke" +fi + +QMAKE_BIN="${INSTALL_DIR}/bin/qmake" +require_file "$QMAKE_BIN" + +QT_INSTALLED_VERSION="$("$QMAKE_BIN" -query QT_VERSION)" +QT_CONFIG="" +if ! QT_CONFIG="$("$QMAKE_BIN" -query QT_CONFIG 2>/dev/null)"; then + if [[ -f "${INSTALL_DIR}/mkspecs/qconfig.pri" ]]; then + QT_CONFIG="$(sed -n 's/^QT_CONFIG += *//p' "${INSTALL_DIR}/mkspecs/qconfig.pri" | tr '\n' ' ')" + fi +fi + +if [[ "$QT_INSTALLED_VERSION" != "$QT_VERSION" ]]; then + fail "unexpected Qt version in install: $QT_INSTALLED_VERSION" +fi + +if ! echo "$QT_CONFIG" | grep -qw static; then + [[ -f "${INSTALL_DIR}/lib/libQt5Core.a" ]] || fail "installed Qt is not static" +fi + +required_libs=( + "libQt5Core.a" + "libQt5Gui.a" + "libQt5Widgets.a" + "libQt5Network.a" + "libQt5Xml.a" +) + +if [[ "$BUILD_SCOPE" == "all" || "$BUILD_SCOPE" == "qtwebkit" ]]; then + required_libs+=( + "libQt5PrintSupport.a" + "libQt5WebKit.a" + "libQt5WebKitWidgets.a" + ) +fi + +missing=0 +for lib in "${required_libs[@]}"; do + if [[ ! -f "${INSTALL_DIR}/lib/${lib}" ]]; then + log_verify "missing: ${INSTALL_DIR}/lib/${lib}" + missing=1 + fi +done + +if ! grep -q 'openssl-linked' "${INSTALL_DIR}/mkspecs/modules/qt_lib_network_private.pri"; then + log_verify "missing openssl-linked in: ${INSTALL_DIR}/mkspecs/modules/qt_lib_network_private.pri" + missing=1 +fi +if ! grep -q 'libssl\.a' "${INSTALL_DIR}/lib/libQt5Network.prl" \ + || ! grep -q 'libcrypto\.a' "${INSTALL_DIR}/lib/libQt5Network.prl"; then + log_verify "missing static OpenSSL archives in: ${INSTALL_DIR}/lib/libQt5Network.prl" + missing=1 +fi +[[ "$missing" -eq 0 ]] || fail "verification failed: required static libraries are missing" + +{ + echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "qt_version=${QT_INSTALLED_VERSION}" + echo "qt_config=${QT_CONFIG}" + echo "jobs=${JOBS}" + echo "clean=${CLEAN}" + echo "build_type=${BUILD_TYPE}" + echo "build_scope=${BUILD_SCOPE}" + echo "qt_src_archive=${QT_SRC_ARCHIVE}" + echo "qtwebkit_archive=${QTWEBKIT_ARCHIVE}" + echo "qt_src_url=${QT_SRC_URL:-}" + echo "qtwebkit_url=${QTWEBKIT_URL:-}" + echo "qt_src_sha256=${QT_SRC_SHA256:-}" + echo "qtwebkit_sha256=${QTWEBKIT_SHA256:-}" + echo "qt_src_md5=${QT_SRC_MD5:-}" + echo "qtwebkit_md5=${QTWEBKIT_MD5:-}" + echo "icu_source=system-package" + echo "openssl_source=system-package" + echo "verified_libs=${required_libs[*]}" + if [[ "$BUILD_SCOPE" == "all" || "$BUILD_SCOPE" == "qtwebkit" ]]; then + echo "smoke_binary=${SMOKE_BUILD_DIR}/qtwebkit-smoke" + fi +} > "$MANIFEST_FILE" + +log_verify "verification passed" diff --git a/toolchains/qt5-static/run-common.sh b/toolchains/qt5-static/run-common.sh new file mode 100644 index 0000000..ca343eb --- /dev/null +++ b/toolchains/qt5-static/run-common.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +BUILD_TYPE="release" +RUN_WITH_GDB=0 +RUN_BUILD=0 +RUN_CHECK=0 +RUN_RUNTIME_CHECK=0 +while [[ $# -gt 0 ]]; do + case "$1" in + --rebuild) + RUN_BUILD=1 + shift + ;; + --debug) + BUILD_TYPE="debug" + shift + ;; + --gdb) + RUN_WITH_GDB=1 + BUILD_TYPE="debug" + shift + ;; + --check) + RUN_CHECK=1 + shift + ;; + --runtime-check) + RUN_RUNTIME_CHECK=1 + shift + ;; + --) + shift + break + ;; + *) + break + ;; + esac +done + +case "${BUILD_TYPE}" in + release|debug) ;; + *) + echo "error: BUILD_TYPE must be release or debug, got: ${BUILD_TYPE}" >&2 + exit 1 + ;; +esac + +if [[ "${RUN_WITH_GDB}" -eq 1 && ( "${RUN_CHECK}" -eq 1 || "${RUN_RUNTIME_CHECK}" -eq 1 ) ]]; then + echo "error: --gdb cannot be used with --check or --runtime-check" >&2 + exit 1 +fi + +if [[ "${RUN_CHECK}" -eq 1 && "${RUN_RUNTIME_CHECK}" -eq 1 ]]; then + echo "error: --check cannot be used with --runtime-check" >&2 + exit 1 +fi + +BINARY="${BINARY_ROOT}/build-docker-${BUILD_TYPE}/${BINARY_NAME}" +if [[ "${RUN_BUILD}" -eq 1 ]]; then + if [[ "${BUILD_TYPE}" == "debug" ]]; then + "${BUILD_SCRIPT}" --debug + else + "${BUILD_SCRIPT}" + fi +elif [[ ! -x "${BINARY}" ]]; then + echo "error: ${APP_LABEL} binary not found: ${BINARY}" >&2 + echo "hint: rerun with --rebuild" >&2 + exit 1 +fi + +if [[ "${RUN_CHECK}" -eq 1 ]]; then + "${REPO_ROOT}/toolchains/qt5-static/check-shared-deps.py" "${BINARY}" +elif [[ "${RUN_RUNTIME_CHECK}" -eq 1 ]]; then + set +e + xvfb-run -a -s "-screen 0 1280x1024x24" timeout 20s "${BINARY}" "$@" + status="$?" + set -e + if [[ "${status}" -ne 0 && "${status}" -ne 124 ]]; then + exit "${status}" + fi +elif [[ "${RUN_WITH_GDB}" -eq 1 ]]; then + exec gdb -ex run --args "${BINARY}" "$@" +else + exec "${BINARY}" "$@" +fi diff --git a/toolchains/qt5-static/sources-qt.lock b/toolchains/qt5-static/sources-qt.lock new file mode 100644 index 0000000..55fb227 --- /dev/null +++ b/toolchains/qt5-static/sources-qt.lock @@ -0,0 +1,8 @@ +# shellcheck disable=SC2034 + +LOCK_QT_VERSION="5.15.17" + +LOCK_QT5_SRC_FILE="qt-everywhere-opensource-src-5.15.17.tar.xz" +LOCK_QT5_SRC_URL="https://download.qt.io/archive/qt/5.15/5.15.17/single/qt-everywhere-opensource-src-5.15.17.tar.xz" +LOCK_QT5_SRC_SHA256="85eb566333d6ba59be3a97c9445a6e52f2af1b52fc3c54b8a2e7f9ea040a7de4" +LOCK_QT5_SRC_MD5="5f212232bbc41f2eabbdee4fcbc4040e" diff --git a/toolchains/qt5-static/sources-qtwebkit.lock b/toolchains/qt5-static/sources-qtwebkit.lock new file mode 100644 index 0000000..5dcb613 --- /dev/null +++ b/toolchains/qt5-static/sources-qtwebkit.lock @@ -0,0 +1,6 @@ +# shellcheck disable=SC2034 + +LOCK_QT5_WEBKIT_FILE="qtwebkit-2022-09-07-src.tar.xz" +LOCK_QT5_WEBKIT_SRC_URL="https://github.com/movableink/webkit/releases/download/2022-09-07/qtwebkit-2022-09-07-src.tar.xz" +LOCK_QT5_WEBKIT_SHA256="1a9f77c3f11a44d147cab6db0fd34aea803f149242e2c217683392aa2f572060" +LOCK_QT5_WEBKIT_MD5="" diff --git a/toolchains/qt5-static/sources.lock b/toolchains/qt5-static/sources.lock index 77716ca..039b585 100644 --- a/toolchains/qt5-static/sources.lock +++ b/toolchains/qt5-static/sources.lock @@ -1,21 +1,11 @@ -# shellcheck disable=SC2034 - # This lock file is sourced by build-qt5-static.sh. # Every source must have at least one checksum (sha256 preferred, md5 fallback). -LOCK_QT_VERSION="5.5.1" - -LOCK_QT5_SRC_FILE="qt-everywhere-opensource-src-5.5.1.tar.gz" -LOCK_QT5_SRC_URL="https://download.qt.io/new_archive/qt/5.5/5.5.1/single/qt-everywhere-opensource-src-5.5.1.tar.gz" -LOCK_QT5_SRC_SHA256="c7fad41a009af1996b62ec494e438aedcb072b3234b2ad3eeea6e6b1f64be3b3" -LOCK_QT5_SRC_MD5="59f0216819152b77536cf660b015d784" +LOCK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -LOCK_QT5_WEBKIT_FILE="qtwebkit-opensource-src-5.5.1.tar.gz" -LOCK_QT5_WEBKIT_SRC_URL="https://download.qt.io/new_archive/qt/5.5/5.5.1/submodules/qtwebkit-opensource-src-5.5.1.tar.gz" -LOCK_QT5_WEBKIT_SHA256="d7776b4f76aae5a495cf16879fed5fd8370342a33116d8f41c30ab4ffd0b9ffd" -LOCK_QT5_WEBKIT_MD5="67ebccfbcd2bbb7eb24c8af6467a55dd" +# shellcheck disable=SC1091 +source "${LOCK_DIR}/sources-qt.lock" +# shellcheck disable=SC1091 +source "${LOCK_DIR}/sources-qtwebkit.lock" -LOCK_ICU_SRC_FILE="icu4c-52_1-src.tgz" -LOCK_ICU_SRC_URL="https://download.qt.io/development_releases/prebuilt/icu/src/icu4c-52_1-src.tgz" -LOCK_ICU_SRC_SHA256="2f4d5e68d4698e87759dbdc1a586d053d96935787f79961d192c477b029d8092" -LOCK_ICU_SRC_MD5="9e96ed4c1d99c0d14ac03c140f9f346c" +unset LOCK_DIR