fit-webview-bridge 0.1.1a6__tar.gz → 0.2.0a2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fit-webview-bridge might be problematic. Click here for more details.
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/.gitignore +0 -2
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/CMakeLists.txt +0 -3
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/PKG-INFO +1 -3
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/README.md +0 -2
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/bindings/pyside6/macos/CMakeLists.txt +16 -28
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/examples/macos/wkwebview_demo.py +12 -6
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/pyproject.toml +1 -1
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/src/macos/CMakeLists.txt +2 -6
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/src/macos/WKWebViewWidget.h +7 -2
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/src/macos/WKWebViewWidget.mm +33 -11
- fit_webview_bridge-0.1.1a6/README.it.md +0 -139
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/.github/workflows/wheels-macos.yml +0 -0
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/.vscode/settings.json +0 -0
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/bindings/pyside6/macos/typesystem_wkwebview.xml +0 -0
- {fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/fit_webview_bridge/__init__.py +0 -0
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.24)
|
|
2
2
|
project(FITWebViewBridge LANGUAGES CXX)
|
|
3
3
|
|
|
4
|
-
# Standard C++
|
|
5
4
|
set(CMAKE_CXX_STANDARD 17)
|
|
6
5
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
6
|
|
|
8
|
-
# Opzione unica rimasta
|
|
9
7
|
option(BUILD_BINDINGS "Build Python bindings" ON)
|
|
10
8
|
|
|
11
|
-
# Dispatch per-OS: tutta la logica sta nelle sottodirectory
|
|
12
9
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
|
13
10
|
add_subdirectory(src/macos)
|
|
14
11
|
if(BUILD_BINDINGS)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fit-webview-bridge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0a2
|
|
4
4
|
Summary: Qt native WebView bridge with PySide6 bindings
|
|
5
5
|
Author: FIT Project
|
|
6
6
|
License: LGPL-3.0-or-later
|
|
@@ -13,8 +13,6 @@ Description-Content-Type: text/markdown
|
|
|
13
13
|
|
|
14
14
|
# FIT WebView Bridge
|
|
15
15
|
|
|
16
|
-
[🇬🇧 English](README.md) | [🇮🇹 Italiano](README.it.md)
|
|
17
|
-
|
|
18
16
|
### Description
|
|
19
17
|
|
|
20
18
|
**FIT WebView Bridge** is a cross‑platform Qt widget (C++/Objective‑C++) with **PySide6** bindings that wraps the OS‑native web engines:
|
{fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/bindings/pyside6/macos/CMakeLists.txt
RENAMED
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.21)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module)
|
|
5
5
|
find_program(SHIBOKEN6_GEN shiboken6 REQUIRED)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
# Passa -DQt6_DIR=/path/to/Qt/6.9.0/macos/lib/cmake/Qt6
|
|
7
|
+
|
|
9
8
|
find_package(Qt6 6.7 REQUIRED COMPONENTS Core Gui Widgets)
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
get_filename_component(
|
|
13
|
-
get_filename_component(QT_FRAMEWORKS_DIR "${_qt_cmake_dir}" DIRECTORY) # …/macos/lib
|
|
10
|
+
get_filename_component(_qt_cmake_dir "${Qt6_DIR}" DIRECTORY)
|
|
11
|
+
get_filename_component(QT_FRAMEWORKS_DIR "${_qt_cmake_dir}" DIRECTORY)
|
|
14
12
|
|
|
15
|
-
# Verifica headers Qt (SDK)
|
|
16
13
|
foreach(_mod QtCore QtGui QtWidgets)
|
|
17
14
|
if(NOT EXISTS "${QT_FRAMEWORKS_DIR}/${_mod}.framework/Headers")
|
|
18
15
|
message(FATAL_ERROR "Missing ${_mod}.framework/Headers under: ${QT_FRAMEWORKS_DIR}")
|
|
19
16
|
endif()
|
|
20
17
|
endforeach()
|
|
21
18
|
|
|
22
|
-
# Shim uniforme per includere QtCore/QtGui/QtWidgets
|
|
23
19
|
set(QT_HDRSHIM "${CMAKE_BINARY_DIR}/qt_hdrshim")
|
|
24
20
|
file(MAKE_DIRECTORY "${QT_HDRSHIM}")
|
|
25
21
|
file(CREATE_LINK "${QT_FRAMEWORKS_DIR}/QtCore.framework/Headers" "${QT_HDRSHIM}/QtCore" SYMBOLIC)
|
|
26
22
|
file(CREATE_LINK "${QT_FRAMEWORKS_DIR}/QtGui.framework/Headers" "${QT_HDRSHIM}/QtGui" SYMBOLIC)
|
|
27
23
|
file(CREATE_LINK "${QT_FRAMEWORKS_DIR}/QtWidgets.framework/Headers" "${QT_HDRSHIM}/QtWidgets" SYMBOLIC)
|
|
28
24
|
|
|
29
|
-
# =============== PySide6 runtime (da site-packages) ===============
|
|
30
|
-
# Dir dei frameworks Qt nel venv (PySide6/Qt/lib)
|
|
31
25
|
if(NOT DEFINED PYSIDE_QT_LIBDIR)
|
|
32
26
|
execute_process(
|
|
33
27
|
COMMAND ${Python3_EXECUTABLE} -c "import os, PySide6; print(os.path.join(os.path.dirname(PySide6.__file__), 'Qt', 'lib'))"
|
|
@@ -39,7 +33,6 @@ if(NOT EXISTS "${PYSIDE_QT_LIBDIR}")
|
|
|
39
33
|
message(FATAL_ERROR "PySide6 Qt frameworks not found: ${PYSIDE_QT_LIBDIR}")
|
|
40
34
|
endif()
|
|
41
35
|
|
|
42
|
-
# Binari framework da PySide6 (linker)
|
|
43
36
|
set(QTCORE_BIN "${PYSIDE_QT_LIBDIR}/QtCore.framework/Versions/A/QtCore")
|
|
44
37
|
set(QTGUI_BIN "${PYSIDE_QT_LIBDIR}/QtGui.framework/Versions/A/QtGui")
|
|
45
38
|
set(QTWIDGETS_BIN "${PYSIDE_QT_LIBDIR}/QtWidgets.framework/Versions/A/QtWidgets")
|
|
@@ -49,12 +42,12 @@ foreach(_f ${QTCORE_BIN} ${QTGUI_BIN} ${QTWIDGETS_BIN})
|
|
|
49
42
|
endif()
|
|
50
43
|
endforeach()
|
|
51
44
|
|
|
52
|
-
|
|
45
|
+
|
|
53
46
|
find_library(QTCORE_FW NAMES QtCore PATHS "${PYSIDE_QT_LIBDIR}" NO_DEFAULT_PATH REQUIRED)
|
|
54
47
|
find_library(QTGUI_FW NAMES QtGui PATHS "${PYSIDE_QT_LIBDIR}" NO_DEFAULT_PATH REQUIRED)
|
|
55
48
|
find_library(QTWIDGETS_FW NAMES QtWidgets PATHS "${PYSIDE_QT_LIBDIR}" NO_DEFAULT_PATH REQUIRED)
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
|
|
58
51
|
execute_process(
|
|
59
52
|
COMMAND ${Python3_EXECUTABLE} -c "import os,shiboken6;print(os.path.join(os.path.dirname(shiboken6.__file__),'typesystems'))"
|
|
60
53
|
OUTPUT_VARIABLE SHIBOKEN_TYPESYS
|
|
@@ -66,7 +59,6 @@ execute_process(
|
|
|
66
59
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
67
60
|
)
|
|
68
61
|
|
|
69
|
-
# Shiboken include (runtime, poi fallback al generator)
|
|
70
62
|
execute_process(
|
|
71
63
|
COMMAND ${Python3_EXECUTABLE} -c "import os,importlib; m=importlib.import_module('shiboken6'); print(os.path.join(os.path.dirname(m.__file__),'include'))"
|
|
72
64
|
OUTPUT_VARIABLE SHIBOKEN_INCLUDE_DIR
|
|
@@ -84,7 +76,7 @@ if(NOT EXISTS "${SHIBOKEN_INCLUDE_DIR}/shiboken.h")
|
|
|
84
76
|
endif()
|
|
85
77
|
message(STATUS "Shiboken include dir: ${SHIBOKEN_INCLUDE_DIR}")
|
|
86
78
|
|
|
87
|
-
|
|
79
|
+
|
|
88
80
|
execute_process(
|
|
89
81
|
COMMAND ${Python3_EXECUTABLE} -c "import os,glob,importlib; d=os.path.dirname(importlib.import_module('shiboken6').__file__); m=glob.glob(os.path.join(d,'libshiboken*.dylib')) or glob.glob(os.path.join(d,'libshiboken*.so*')); print(m[0] if m else '')"
|
|
90
82
|
OUTPUT_VARIABLE SHIBOKEN_LIBRARY
|
|
@@ -102,7 +94,7 @@ if(NOT SHIBOKEN_LIBRARY)
|
|
|
102
94
|
endif()
|
|
103
95
|
message(STATUS "Shiboken library: ${SHIBOKEN_LIBRARY}")
|
|
104
96
|
|
|
105
|
-
|
|
97
|
+
|
|
106
98
|
execute_process(
|
|
107
99
|
COMMAND ${Python3_EXECUTABLE} -c "import os, PySide6; print(os.path.join(os.path.dirname(PySide6.__file__), 'include'))"
|
|
108
100
|
OUTPUT_VARIABLE PYSIDE_INCLUDE_DIR
|
|
@@ -119,11 +111,11 @@ endif()
|
|
|
119
111
|
message(STATUS "PySide library : ${PYSIDE_LIBRARY}")
|
|
120
112
|
get_filename_component(PYSIDE_LIB_DIR "${PYSIDE_LIBRARY}" DIRECTORY)
|
|
121
113
|
|
|
122
|
-
|
|
114
|
+
|
|
123
115
|
set(SHIBOKEN_INCLUDE_LIST
|
|
124
|
-
"${QT_HDRSHIM}"
|
|
125
|
-
"${PROJECT_SOURCE_DIR}/src/macos"
|
|
126
|
-
"${SHIBOKEN_INCLUDE_DIR}"
|
|
116
|
+
"${QT_HDRSHIM}"
|
|
117
|
+
"${PROJECT_SOURCE_DIR}/src/macos"
|
|
118
|
+
"${SHIBOKEN_INCLUDE_DIR}"
|
|
127
119
|
"${QT_FRAMEWORKS_DIR}/QtCore.framework/Headers"
|
|
128
120
|
"${QT_FRAMEWORKS_DIR}/QtGui.framework/Headers"
|
|
129
121
|
"${QT_FRAMEWORKS_DIR}/QtWidgets.framework/Headers"
|
|
@@ -139,7 +131,7 @@ endif()
|
|
|
139
131
|
list(JOIN SHIBOKEN_INCLUDE_LIST ":" SHIBOKEN_INCLUDE_ARG)
|
|
140
132
|
message(STATUS "Shiboken include paths:\n ${SHIBOKEN_INCLUDE_ARG}")
|
|
141
133
|
|
|
142
|
-
|
|
134
|
+
|
|
143
135
|
set(GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/shiboken_out)
|
|
144
136
|
file(MAKE_DIRECTORY ${GEN_DIR})
|
|
145
137
|
|
|
@@ -173,24 +165,21 @@ if (SHIBOKEN_SRCS STREQUAL "")
|
|
|
173
165
|
message(FATAL_ERROR "No sources generated in ${GEN_DIR}")
|
|
174
166
|
endif()
|
|
175
167
|
|
|
176
|
-
|
|
168
|
+
|
|
177
169
|
add_library(_wkwebview MODULE ${SHIBOKEN_SRCS})
|
|
178
170
|
target_compile_features(_wkwebview PRIVATE cxx_std_17)
|
|
179
171
|
|
|
180
|
-
# Installa l’estensione nel pacchetto Python
|
|
181
172
|
install(TARGETS _wkwebview
|
|
182
173
|
LIBRARY DESTINATION fit_webview_bridge
|
|
183
174
|
RUNTIME DESTINATION fit_webview_bridge
|
|
184
175
|
)
|
|
185
176
|
|
|
186
|
-
# Suffisso Python (es. .cpython-311-darwin.so)
|
|
187
177
|
execute_process(
|
|
188
178
|
COMMAND ${Python3_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX') or '.so')"
|
|
189
179
|
OUTPUT_VARIABLE PY_EXT_SUFFIX
|
|
190
180
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
191
181
|
)
|
|
192
182
|
|
|
193
|
-
# Include & link
|
|
194
183
|
target_include_directories(_wkwebview PRIVATE
|
|
195
184
|
${GEN_DIR}
|
|
196
185
|
"${PROJECT_SOURCE_DIR}/src/macos"
|
|
@@ -207,10 +196,10 @@ if(EXISTS "${PYSIDE_INCLUDE_DIR}")
|
|
|
207
196
|
)
|
|
208
197
|
endif()
|
|
209
198
|
|
|
210
|
-
|
|
199
|
+
|
|
211
200
|
target_link_directories(_wkwebview PRIVATE "${PYSIDE_QT_LIBDIR}")
|
|
212
201
|
|
|
213
|
-
|
|
202
|
+
|
|
214
203
|
target_link_libraries(_wkwebview PRIVATE
|
|
215
204
|
"${QTCORE_BIN}"
|
|
216
205
|
"${QTGUI_BIN}"
|
|
@@ -221,7 +210,6 @@ target_link_libraries(_wkwebview PRIVATE
|
|
|
221
210
|
wkwebview
|
|
222
211
|
)
|
|
223
212
|
|
|
224
|
-
# =============== RPATH per runtime su macOS =======================
|
|
225
213
|
get_filename_component(SHIBOKEN_LIB_DIR "${SHIBOKEN_LIBRARY}" DIRECTORY)
|
|
226
214
|
option(FITWVB_VENDORIZE "Vendorize PySide/Qt lookup via @loader_path" ON)
|
|
227
215
|
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import os
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
2
4
|
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
3
|
-
sys.path[:0] = [
|
|
4
|
-
|
|
5
|
+
sys.path[:0] = [
|
|
6
|
+
os.path.join(ROOT, "build"),
|
|
7
|
+
os.path.join(ROOT, "build", "bindings", "shiboken_out"),
|
|
8
|
+
]
|
|
5
9
|
|
|
10
|
+
from PySide6.QtCore import QUrl
|
|
11
|
+
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
|
|
6
12
|
|
|
7
|
-
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
|
|
8
|
-
from fit_webview_bridge import SystemWebView
|
|
9
13
|
# tentativo 1: pacchetto generato da shiboken (wkwebview)
|
|
10
14
|
try:
|
|
11
15
|
import wkwebview
|
|
16
|
+
|
|
12
17
|
WKWebViewWidget = wkwebview.WKWebViewWidget # accesso via attributo
|
|
13
18
|
except Exception:
|
|
14
19
|
# tentativo 2: modulo nativo diretto
|
|
@@ -28,7 +33,8 @@ class Main(QMainWindow):
|
|
|
28
33
|
self.view.titleChanged.connect(self.setWindowTitle)
|
|
29
34
|
self.view.loadProgress.connect(lambda p: print("progress:", p))
|
|
30
35
|
|
|
31
|
-
self.view.
|
|
36
|
+
self.view.setUrl(QUrl("http://fit-project.org/"))
|
|
37
|
+
|
|
32
38
|
|
|
33
39
|
app = QApplication([])
|
|
34
40
|
m = Main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fit-webview-bridge"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0a2"
|
|
4
4
|
description = "Qt native WebView bridge with PySide6 bindings"
|
|
5
5
|
requires-python = ">=3.11,<3.14"
|
|
6
6
|
dependencies = ["PySide6==6.9.0", "shiboken6==6.9.0", "shiboken6-generator==6.9.0"]
|
|
@@ -6,22 +6,19 @@ set(CMAKE_OBJCXX_STANDARD 17)
|
|
|
6
6
|
set(CMAKE_OBJCXX_STANDARD_REQUIRED ON)
|
|
7
7
|
set(CMAKE_AUTOMOC ON)
|
|
8
8
|
|
|
9
|
-
# Qt da aqt: serve solo per moc + headers
|
|
10
|
-
# Passa -DQt6_DIR=/path/to/Qt/6.9.0/macos/lib/cmake/Qt6
|
|
11
9
|
find_package(Qt6 6.7 REQUIRED COMPONENTS Core Gui Widgets)
|
|
12
10
|
|
|
13
|
-
# Deriva la cartella dei frameworks (…/macos/lib) da Qt6_DIR
|
|
14
11
|
get_filename_component(_qt_cmake_dir "${Qt6_DIR}" DIRECTORY) # …/macos/lib/cmake
|
|
15
12
|
get_filename_component(QT_FRAMEWORKS_DIR "${_qt_cmake_dir}" DIRECTORY) # …/macos/lib
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
|
|
18
15
|
foreach(_m QtCore QtGui QtWidgets)
|
|
19
16
|
if(NOT EXISTS "${QT_FRAMEWORKS_DIR}/${_m}.framework/Headers")
|
|
20
17
|
message(FATAL_ERROR "Missing ${_m}.framework/Headers in: ${QT_FRAMEWORKS_DIR}")
|
|
21
18
|
endif()
|
|
22
19
|
endforeach()
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
|
|
25
22
|
set(QT_HDRSHIM "${CMAKE_BINARY_DIR}/qt_hdrshim")
|
|
26
23
|
file(MAKE_DIRECTORY "${QT_HDRSHIM}")
|
|
27
24
|
file(CREATE_LINK "${QT_FRAMEWORKS_DIR}/QtCore.framework/Headers" "${QT_HDRSHIM}/QtCore" SYMBOLIC)
|
|
@@ -42,7 +39,6 @@ target_include_directories(wkwebview PUBLIC
|
|
|
42
39
|
${QT_HDRSHIM}
|
|
43
40
|
)
|
|
44
41
|
|
|
45
|
-
# Link SOLO framework di sistema (Cocoa/WebKit). Niente Qt qui.
|
|
46
42
|
target_link_libraries(wkwebview PUBLIC
|
|
47
43
|
"-framework Cocoa"
|
|
48
44
|
"-framework WebKit"
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include <QWidget>
|
|
3
3
|
#include <QObject>
|
|
4
|
+
#include <QUrl>
|
|
4
5
|
|
|
5
|
-
class QString; class
|
|
6
|
+
class QString; class QShowEvent; class QResizeEvent;
|
|
6
7
|
|
|
7
8
|
class WKWebViewWidget : public QWidget {
|
|
8
9
|
Q_OBJECT
|
|
10
|
+
Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
|
|
11
|
+
|
|
9
12
|
public:
|
|
10
13
|
explicit WKWebViewWidget(QWidget* parent = nullptr);
|
|
11
14
|
~WKWebViewWidget() override;
|
|
12
15
|
|
|
13
|
-
Q_INVOKABLE
|
|
16
|
+
Q_INVOKABLE QUrl url() const;
|
|
17
|
+
Q_INVOKABLE void setUrl(const QUrl& url);
|
|
18
|
+
|
|
14
19
|
Q_INVOKABLE void back();
|
|
15
20
|
Q_INVOKABLE void forward();
|
|
16
21
|
Q_INVOKABLE void stop();
|
|
@@ -22,7 +22,7 @@ struct WKWebViewWidget::Impl {
|
|
|
22
22
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
|
23
23
|
if (!self.owner) return;
|
|
24
24
|
emit self.owner->loadFinished(true);
|
|
25
|
-
if (webView.URL) emit self.owner->urlChanged(QUrl
|
|
25
|
+
if (webView.URL) emit self.owner->urlChanged(QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String)));
|
|
26
26
|
if (webView.title) emit self.owner->titleChanged(QString::fromUtf8(webView.title.UTF8String));
|
|
27
27
|
emit self.owner->loadProgress(100);
|
|
28
28
|
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
@@ -43,12 +43,23 @@ struct WKWebViewWidget::Impl {
|
|
|
43
43
|
}
|
|
44
44
|
@end
|
|
45
45
|
|
|
46
|
-
static NSURL* toNSURL(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
static NSURL* toNSURL(QUrl u) {
|
|
47
|
+
if (!u.isValid()) return nil;
|
|
48
|
+
|
|
49
|
+
if (u.scheme().isEmpty())
|
|
50
|
+
u = QUrl::fromUserInput(u.toString());
|
|
51
|
+
|
|
52
|
+
if (u.scheme() == "http")
|
|
53
|
+
u.setScheme("https");
|
|
54
|
+
|
|
55
|
+
if (u.isLocalFile())
|
|
56
|
+
return [NSURL fileURLWithPath:[NSString stringWithUTF8String:u.toLocalFile().toUtf8().constData()]];
|
|
57
|
+
|
|
58
|
+
const QByteArray enc = u.toString(QUrl::FullyEncoded).toUtf8();
|
|
59
|
+
return [NSURL URLWithString:[NSString stringWithUTF8String:enc.constData()]];
|
|
50
60
|
}
|
|
51
61
|
|
|
62
|
+
|
|
52
63
|
WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
53
64
|
: QWidget(parent), d(new Impl) {
|
|
54
65
|
setAttribute(Qt::WA_NativeWindow, true);
|
|
@@ -66,8 +77,6 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
66
77
|
d->delegate = [WKNavDelegate new];
|
|
67
78
|
d->delegate.owner = this;
|
|
68
79
|
[d->wk setNavigationDelegate:d->delegate];
|
|
69
|
-
|
|
70
|
-
load(QStringLiteral("https://example.org"));
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
WKWebViewWidget::~WKWebViewWidget() {
|
|
@@ -77,12 +86,25 @@ WKWebViewWidget::~WKWebViewWidget() {
|
|
|
77
86
|
delete d; d = nullptr;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
void WKWebViewWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e);
|
|
81
|
-
void WKWebViewWidget::resizeEvent(QResizeEvent* e) { QWidget::resizeEvent(e);
|
|
89
|
+
void WKWebViewWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); }
|
|
90
|
+
void WKWebViewWidget::resizeEvent(QResizeEvent* e) { QWidget::resizeEvent(e); }
|
|
91
|
+
|
|
92
|
+
QUrl WKWebViewWidget::url() const {
|
|
93
|
+
if (!(d && d->wk)) return QUrl();
|
|
94
|
+
NSURL* nsurl = d->wk.URL;
|
|
95
|
+
if (!nsurl) return QUrl();
|
|
96
|
+
const char* utf8 = nsurl.absoluteString.UTF8String;
|
|
97
|
+
if (!utf8) return QUrl();
|
|
98
|
+
return QUrl::fromEncoded(QByteArray(utf8));
|
|
99
|
+
}
|
|
82
100
|
|
|
83
|
-
void WKWebViewWidget::
|
|
84
|
-
if (d && d->wk)
|
|
101
|
+
void WKWebViewWidget::setUrl(const QUrl& u) {
|
|
102
|
+
if (!(d && d->wk)) return;
|
|
103
|
+
NSURL* nsurl = toNSURL(u);
|
|
104
|
+
if (!nsurl) return;
|
|
105
|
+
[d->wk loadRequest:[NSURLRequest requestWithURL:nsurl]];
|
|
85
106
|
}
|
|
107
|
+
|
|
86
108
|
void WKWebViewWidget::back() { if (d && d->wk && d->wk.canGoBack) [d->wk goBack]; }
|
|
87
109
|
void WKWebViewWidget::forward() { if (d && d->wk && d->wk.canGoForward) [d->wk goForward]; }
|
|
88
110
|
void WKWebViewWidget::stop() { if (d && d->wk) [d->wk stopLoading:nil]; }
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# FIT WebView Bridge
|
|
2
|
-
|
|
3
|
-
[🇬🇧 English](README.md) | [🇮🇹 Italiano](README.it.md)
|
|
4
|
-
|
|
5
|
-
### Descrizione
|
|
6
|
-
|
|
7
|
-
**FIT WebView Bridge** è un widget Qt multipiattaforma (C++/Objective-C++) con binding **PySide6** che incapsula i motori web nativi del sistema:
|
|
8
|
-
- **Windows →** Edge WebView2
|
|
9
|
-
- **macOS →** WKWebView
|
|
10
|
-
- **Linux →** WebKitGTK (con **GStreamer** per i codec)
|
|
11
|
-
|
|
12
|
-
Espone una **API Python unificata** per controllare il browser ed abilita la **visualizzazione/acquisizione forense** di contenuti, inclusi quelli che richiedono codec proprietari (es. **H.264/AAC**), **senza** build personalizzate di QtWebEngine né oneri di redistribuzione dei codec (si usano quelli del sistema operativo). I **controlli** (UI e logica applicativa) sono **demandati alla finestra PySide**.
|
|
13
|
-
|
|
14
|
-
### Perché questo progetto
|
|
15
|
-
QtWebEngine (Chromium) di default **non abilita i codec proprietari** e la loro distribuzione richiede **licenza**. Le alternative considerate (compilare QtWebEngine con codec o usare QtWebView/QML) presentano limiti di portabilità/controllo. La via scelta è **incapsulare i motori di sistema**, ottenendo compatibilità con i codec e **massimo controllo** via API Python.
|
|
16
|
-
|
|
17
|
-
### Struttura del repository
|
|
18
|
-
```
|
|
19
|
-
fit-webview-bridge/
|
|
20
|
-
├─ CMakeLists.txt
|
|
21
|
-
├─ cmake/ # Find*.cmake, toolchain, helper
|
|
22
|
-
├─ include/fitwvb/ # Header pubblici (API)
|
|
23
|
-
├─ src/
|
|
24
|
-
│ ├─ core/ # Facade / interfacce comuni
|
|
25
|
-
│ ├─ win/ # Backend Edge WebView2 (C++)
|
|
26
|
-
│ ├─ macos/ # Backend WKWebView (Obj-C++)
|
|
27
|
-
│ └─ linux/ # Backend WebKitGTK (C++)
|
|
28
|
-
├─ bindings/pyside6/ # Shiboken6: typesystem e config
|
|
29
|
-
├─ tests/ # Unit / integration
|
|
30
|
-
└─ examples/ # Mini app PySide6 dimostrativa
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Interfaccia (metodi/slot + segnali)
|
|
34
|
-
**Metodi / slot**
|
|
35
|
-
- `load(url)`
|
|
36
|
-
- `back()`
|
|
37
|
-
- `forward()`
|
|
38
|
-
- `reload()`
|
|
39
|
-
- `stop()`
|
|
40
|
-
- `setHtml(html, baseUrl)`
|
|
41
|
-
- `evalJs(script, callback)`
|
|
42
|
-
|
|
43
|
-
**Segnali**
|
|
44
|
-
- `urlChanged(QUrl)`
|
|
45
|
-
- `titleChanged(QString)`
|
|
46
|
-
- `loadProgress(int)`
|
|
47
|
-
- `loadFinished(bool)`
|
|
48
|
-
- `consoleMessage(QString)`
|
|
49
|
-
|
|
50
|
-
> Nota: l’API è esposta in modo **uniforme** su tutti gli OS; l’implementazione delega al motore nativo.
|
|
51
|
-
|
|
52
|
-
### Prerequisiti
|
|
53
|
-
**Comuni**
|
|
54
|
-
- **CMake** (>= 3.24 consigliato)
|
|
55
|
-
- **Ninja** (generator)
|
|
56
|
-
- **Python** 3.9+
|
|
57
|
-
- **PySide6** e **Shiboken6** (per i binding Python)
|
|
58
|
-
- Strumenti di build della piattaforma
|
|
59
|
-
|
|
60
|
-
**Windows**
|
|
61
|
-
- **MSVC** (Visual Studio 2022 o Build Tools) e Windows SDK
|
|
62
|
-
- **Microsoft Edge WebView2 Runtime**
|
|
63
|
-
- **WebView2 SDK** (NuGet/vcpkg)
|
|
64
|
-
|
|
65
|
-
**macOS**
|
|
66
|
-
- **Xcode** + Command Line Tools
|
|
67
|
-
- Linguaggio **Objective-C++** abilitato (.mm)
|
|
68
|
-
- Framework: `WebKit`, `Cocoa`
|
|
69
|
-
|
|
70
|
-
**Linux**
|
|
71
|
-
- **GCC/Clang**, `pkg-config`
|
|
72
|
-
- **WebKitGTK** dev (es. `webkit2gtk-4.1` o equivalente della distro)
|
|
73
|
-
- **GStreamer** (base + plugin necessari per i codec)
|
|
74
|
-
|
|
75
|
-
### Compilazione (indicativa)
|
|
76
|
-
```bash
|
|
77
|
-
git clone https://github.com/fit-project/fit-webview-bridge.git
|
|
78
|
-
cd fit-webview-bridge
|
|
79
|
-
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_PYSIDE6_BINDINGS=ON
|
|
80
|
-
cmake --build build
|
|
81
|
-
# (opzionale) ctest --test-dir build
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Esempi
|
|
85
|
-
Gli esempi PySide6 si trovano in `examples/` e mostrano caricamento URL, iniezione JS e ascolto dei segnali.
|
|
86
|
-
|
|
87
|
-
### Considerazioni su codec e licenze
|
|
88
|
-
Il progetto **non** ridistribuisce codec proprietari: sfrutta i codec **già presenti nel sistema operativo**. L’uso finale dei contenuti è responsabilità dell’utente in base alle rispettive licenze/formati.
|
|
89
|
-
|
|
90
|
-
### Stato del progetto
|
|
91
|
-
Iniziale/alpha (API soggetta a modifiche).
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
Fit Web — Motivazioni del progetto e opzioni per i codec proprietari
|
|
96
|
-
|
|
97
|
-
**Fit Web** è il modulo *scraper* del progetto FIT pensato per **acquisire e cristallizzare, con modalità forensi, contenuti web**: <https://github.com/fit-project/fit-web>.
|
|
98
|
-
|
|
99
|
-
Come gli altri moduli, **Fit Web** si basa su **PySide** (Qt per Python). Attualmente utilizza **QtWebEngine**, che è un *wrapper* di **Chromium**.
|
|
100
|
-
|
|
101
|
-
## Il problema
|
|
102
|
-
Chromium, di default, **non abilita i codec audio/video proprietari**, in particolare **H.264** e **AAC**.
|
|
103
|
-
|
|
104
|
-
## Soluzioni considerate
|
|
105
|
-
|
|
106
|
-
### 1) Compilare QtWebEngine con codec proprietari
|
|
107
|
-
Abilitare l’opzione `-webengine-proprietary-codecs`.
|
|
108
|
-
Documentazione: <https://doc.qt.io/qt-6/qtwebengine-overview.html>
|
|
109
|
-
|
|
110
|
-
**Criticità**
|
|
111
|
-
- Va eseguito per **tutti i sistemi operativi** supportati.
|
|
112
|
-
- La compilazione richiede **macchine molto performanti** (es.: difficoltà su MacBook Air M2 con 16 GB di RAM).
|
|
113
|
-
- **Licenze**: la **distribuzione** di H.264 e AAC **richiede una licenza**.
|
|
114
|
-
|
|
115
|
-
### 2) Usare QtWebView
|
|
116
|
-
QtWebView utilizza **le API web native del sistema operativo**; per i contenuti con codec proprietari sfrutta **i codec del sistema**.
|
|
117
|
-
**Vantaggi**: niente compilazioni personalizzate, niente gestione diretta delle licenze.
|
|
118
|
-
**Limiti**: l’interfaccia è in **QML**, pensata per UI leggere (spesso mobile), e **non offre il controllo completo** sul browser rispetto a QtWebEngine.
|
|
119
|
-
|
|
120
|
-
Documentazione: <https://doc.qt.io/qt-6/qtwebview-index.html>
|
|
121
|
-
|
|
122
|
-
### 3) Scrivere un widget Qt nativo (C/C++) per ogni OS
|
|
123
|
-
Creare un widget Qt (usabile da **PySide6**) che *embedda* il motore web di sistema:
|
|
124
|
-
|
|
125
|
-
- **Windows →** Edge WebView2
|
|
126
|
-
- **macOS →** WKWebView
|
|
127
|
-
- **Linux →** WebKitGTK (con **GStreamer** per i codec)
|
|
128
|
-
|
|
129
|
-
**Vantaggi**
|
|
130
|
-
- **Nessuna licenza da redistribuire**: si usano i codec già forniti dal sistema.
|
|
131
|
-
- Possibilità di **un’API comune** da esporre a PySide6.
|
|
132
|
-
- **Maggiore controllo** rispetto a QtWebView, senza i limiti imposti da QML.
|
|
133
|
-
|
|
134
|
-
**Svantaggi**
|
|
135
|
-
- **Complessità medio‑alta** di implementazione.
|
|
136
|
-
- Richiede **C++** e, su macOS, anche **Objective‑C++**.
|
|
137
|
-
- Necessità di **CMake** ad hoc per includere librerie e collegamenti.
|
|
138
|
-
|
|
139
|
-
---
|
{fit_webview_bridge-0.1.1a6 → fit_webview_bridge-0.2.0a2}/.github/workflows/wheels-macos.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|