fit-webview-bridge 0.1.1a6__tar.gz → 0.2.0a1__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.

@@ -179,6 +179,4 @@ pyrightconfig.json
179
179
  *.db
180
180
  .DS_Store
181
181
  FIT/
182
- COMPILAZIONE.md
183
- TEST.md
184
182
  Qt/
@@ -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.1.1a6
3
+ Version: 0.2.0a1
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:
@@ -1,7 +1,5 @@
1
1
  # FIT WebView Bridge
2
2
 
3
- [🇬🇧 English](README.md) | [🇮🇹 Italiano](README.it.md)
4
-
5
3
  ### Description
6
4
 
7
5
  **FIT WebView Bridge** is a cross‑platform Qt widget (C++/Objective‑C++) with **PySide6** bindings that wraps the OS‑native web engines:
@@ -1,33 +1,27 @@
1
1
  cmake_minimum_required(VERSION 3.21)
2
2
 
3
- # Python + Shiboken6 + PySide6
3
+
4
4
  find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module)
5
5
  find_program(SHIBOKEN6_GEN shiboken6 REQUIRED)
6
6
 
7
- # =============== Qt headers (solo SDK, via aqt) ==================
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
- # Deriva la cartella frameworks (…/macos/lib) a partire da Qt6_DIR
12
- get_filename_component(_qt_cmake_dir "${Qt6_DIR}" DIRECTORY) # …/macos/lib/cmake
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
- # Trova anche i frameworks per completezza (stessa cartella)
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
- # =============== Typesystem & includes Shiboken/PySide6 ==========
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
- # Shiboken runtime library
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
- # PySide6 include & lib
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
- # Include per shiboken (SDK Qt + tuoi header + shiboken + PySide6)
114
+
123
115
  set(SHIBOKEN_INCLUDE_LIST
124
- "${QT_HDRSHIM}" # QtCore/QtGui/QtWidgets headers
125
- "${PROJECT_SOURCE_DIR}/src/macos" # tuoi header nativi
126
- "${SHIBOKEN_INCLUDE_DIR}" # shiboken.h
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
- # =============== Shiboken: codegen ================================
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
- # =============== Estensione Python ================================
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
- # CMake deve cercare nelle dir dei framework di PySide6
199
+
211
200
  target_link_directories(_wkwebview PRIVATE "${PYSIDE_QT_LIBDIR}")
212
201
 
213
- # Linka CONTRO i binari di PySide6 + shiboken + Python + lib nativa
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, sys
1
+ import os
2
+ import sys
3
+
2
4
  ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
3
- sys.path[:0] = [os.path.join(ROOT, "build"),
4
- os.path.join(ROOT, "build", "bindings", "shiboken_out")]
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.load("https://www.facebook.com/reel/574839388710756/")
36
+ self.view.setUrl(QUrl("https://www.facebook.com/reel/574839388710756/"))
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.1.1a6"
3
+ version = "0.2.0a1"
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
- # Verifica headers
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
- # Shim include uniforme
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 QUrl; class QShowEvent; class QResizeEvent;
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 void load(const QString& url);
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(QString::fromUtf8(webView.URL.absoluteString.UTF8String)));
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,10 +43,14 @@ struct WKWebViewWidget::Impl {
43
43
  }
44
44
  @end
45
45
 
46
- static NSURL* toNSURL(QString u) {
47
- u = u.trimmed();
48
- if (!u.startsWith("http://") && !u.startsWith("https://")) u = "https://" + u;
49
- return [NSURL URLWithString:[NSString stringWithUTF8String:u.toUtf8().constData()]];
46
+ static NSURL* toNSURL(QUrl u) {
47
+ if (!u.isValid()) return nil;
48
+ if (u.scheme().isEmpty())
49
+ u = QUrl::fromUserInput(u.toString());
50
+ if (u.isLocalFile())
51
+ return [NSURL fileURLWithPath:[NSString stringWithUTF8String:u.toLocalFile().toUtf8().constData()]];
52
+ const QByteArray enc = u.toString(QUrl::FullyEncoded).toUtf8();
53
+ return [NSURL URLWithString:[NSString stringWithUTF8String:enc.constData()]];
50
54
  }
51
55
 
52
56
  WKWebViewWidget::WKWebViewWidget(QWidget* parent)
@@ -66,8 +70,6 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
66
70
  d->delegate = [WKNavDelegate new];
67
71
  d->delegate.owner = this;
68
72
  [d->wk setNavigationDelegate:d->delegate];
69
-
70
- load(QStringLiteral("https://example.org"));
71
73
  }
72
74
 
73
75
  WKWebViewWidget::~WKWebViewWidget() {
@@ -77,12 +79,25 @@ WKWebViewWidget::~WKWebViewWidget() {
77
79
  delete d; d = nullptr;
78
80
  }
79
81
 
80
- void WKWebViewWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); /* opzionale */ }
81
- void WKWebViewWidget::resizeEvent(QResizeEvent* e) { QWidget::resizeEvent(e); /* opzionale */ }
82
+ void WKWebViewWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); }
83
+ void WKWebViewWidget::resizeEvent(QResizeEvent* e) { QWidget::resizeEvent(e); }
84
+
85
+ QUrl WKWebViewWidget::url() const {
86
+ if (!(d && d->wk)) return QUrl();
87
+ NSURL* nsurl = d->wk.URL;
88
+ if (!nsurl) return QUrl();
89
+ const char* utf8 = nsurl.absoluteString.UTF8String;
90
+ if (!utf8) return QUrl();
91
+ return QUrl::fromEncoded(QByteArray(utf8));
92
+ }
82
93
 
83
- void WKWebViewWidget::load(const QString& url) {
84
- if (d && d->wk) [d->wk loadRequest:[NSURLRequest requestWithURL:toNSURL(url)]];
94
+ void WKWebViewWidget::setUrl(const QUrl& u) {
95
+ if (!(d && d->wk)) return;
96
+ NSURL* nsurl = toNSURL(u);
97
+ if (!nsurl) return;
98
+ [d->wk loadRequest:[NSURLRequest requestWithURL:nsurl]];
85
99
  }
100
+
86
101
  void WKWebViewWidget::back() { if (d && d->wk && d->wk.canGoBack) [d->wk goBack]; }
87
102
  void WKWebViewWidget::forward() { if (d && d->wk && d->wk.canGoForward) [d->wk goForward]; }
88
103
  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
- ---