fit-webview-bridge 0.2.3a1__tar.gz → 0.2.3a2__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.2.3a1 → fit_webview_bridge-0.2.3a2}/PKG-INFO +1 -1
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/examples/macos/wkwebview_demo.py +26 -5
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/pyproject.toml +1 -1
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/src/macos/WKWebViewWidget.mm +91 -6
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/.github/workflows/wheels-macos.yml +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/.gitignore +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/.vscode/settings.json +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/README.md +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/bindings/pyside6/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/bindings/pyside6/macos/typesystem_wkwebview.xml +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/fit_webview_bridge/__init__.py +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/src/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/src/macos/DownloadInfo.h +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/src/macos/WKWebViewWidget.h +0 -0
|
@@ -11,6 +11,7 @@ from PySide6.QtCore import QUrl
|
|
|
11
11
|
from PySide6.QtWidgets import (
|
|
12
12
|
QApplication,
|
|
13
13
|
QHBoxLayout,
|
|
14
|
+
QLineEdit,
|
|
14
15
|
QMainWindow,
|
|
15
16
|
QPushButton,
|
|
16
17
|
QVBoxLayout,
|
|
@@ -27,7 +28,7 @@ except Exception:
|
|
|
27
28
|
from _wkwebview import WKWebViewWidget
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
HOME_URL = "https://
|
|
31
|
+
HOME_URL = "https://github.com/fit-project"
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class Main(QMainWindow):
|
|
@@ -38,15 +39,21 @@ class Main(QMainWindow):
|
|
|
38
39
|
root = QVBoxLayout(central)
|
|
39
40
|
self.setCentralWidget(central)
|
|
40
41
|
|
|
41
|
-
# --- toolbar
|
|
42
|
+
# --- toolbar: back/forward/home + address bar + go ---
|
|
42
43
|
bar = QHBoxLayout()
|
|
43
44
|
self.btnBack = QPushButton("◀︎ Back")
|
|
44
45
|
self.btnFwd = QPushButton("Forward ▶︎")
|
|
45
46
|
self.btnHome = QPushButton("🏠 Home")
|
|
47
|
+
|
|
48
|
+
self.address = QLineEdit() # ← barra indirizzi
|
|
49
|
+
self.address.setPlaceholderText("Digita un URL o una ricerca…")
|
|
50
|
+
self.btnGo = QPushButton("Go")
|
|
51
|
+
|
|
46
52
|
bar.addWidget(self.btnBack)
|
|
47
53
|
bar.addWidget(self.btnFwd)
|
|
48
54
|
bar.addWidget(self.btnHome)
|
|
49
|
-
bar.
|
|
55
|
+
bar.addWidget(self.address, 1) # ← occupa spazio elastico
|
|
56
|
+
bar.addWidget(self.btnGo)
|
|
50
57
|
root.addLayout(bar)
|
|
51
58
|
|
|
52
59
|
# --- webview ---
|
|
@@ -68,6 +75,20 @@ class Main(QMainWindow):
|
|
|
68
75
|
self.btnFwd.clicked.connect(self.view.forward)
|
|
69
76
|
self.btnHome.clicked.connect(lambda: self.view.setUrl(QUrl(HOME_URL)))
|
|
70
77
|
|
|
78
|
+
# --- address bar: invio / bottone Go ---
|
|
79
|
+
def navigate_from_address():
|
|
80
|
+
text = (self.address.text() or "").strip()
|
|
81
|
+
if not text:
|
|
82
|
+
return
|
|
83
|
+
url = QUrl.fromUserInput(text) # gestisce http/https, domini, file, ecc.
|
|
84
|
+
self.view.setUrl(url)
|
|
85
|
+
|
|
86
|
+
self.address.returnPressed.connect(navigate_from_address)
|
|
87
|
+
self.btnGo.clicked.connect(navigate_from_address)
|
|
88
|
+
|
|
89
|
+
# mantieni sincronizzata la barra con la URL corrente
|
|
90
|
+
self.view.urlChanged.connect(lambda u: self.address.setText(u.toString()))
|
|
91
|
+
|
|
71
92
|
# --- eventi download: print semplici ---
|
|
72
93
|
self.view.downloadStarted.connect(
|
|
73
94
|
lambda name, path: print(f"[download] started: name='{name}' path='{path}'")
|
|
@@ -82,7 +103,6 @@ class Main(QMainWindow):
|
|
|
82
103
|
)
|
|
83
104
|
|
|
84
105
|
def on_finished(info):
|
|
85
|
-
# Proviamo a leggere i getter se disponibili; fallback a repr
|
|
86
106
|
try:
|
|
87
107
|
fname = info.fileName() if hasattr(info, "fileName") else None
|
|
88
108
|
directory = info.directory() if hasattr(info, "directory") else None
|
|
@@ -98,8 +118,9 @@ class Main(QMainWindow):
|
|
|
98
118
|
|
|
99
119
|
self.view.downloadFinished.connect(on_finished)
|
|
100
120
|
|
|
101
|
-
# carica home
|
|
121
|
+
# carica home e imposta barra
|
|
102
122
|
self.view.setUrl(QUrl(HOME_URL))
|
|
123
|
+
self.address.setText(HOME_URL)
|
|
103
124
|
|
|
104
125
|
|
|
105
126
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fit-webview-bridge"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.3a2"
|
|
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"]
|
|
@@ -73,6 +73,8 @@ static NSURL* toNSURL(QUrl u);
|
|
|
73
73
|
@end
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
static inline NSString* FITURLStr(NSURL *u) { return u ? u.absoluteString : @"(nil)"; }
|
|
77
|
+
|
|
76
78
|
static NSString* FIT_CurrentLang(void) {
|
|
77
79
|
NSString *lang = NSLocale.preferredLanguages.firstObject ?: @"en";
|
|
78
80
|
// normalizza es. "it-IT" -> "it"
|
|
@@ -299,6 +301,9 @@ static NSString* fit_uniquePath(NSString* baseDir, NSString* filename) {
|
|
|
299
301
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSNumber*>* expectedTotals; // weak->strong
|
|
300
302
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSURL*>* sourceURLs; // weak->strong
|
|
301
303
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* suggestedNames; // weak->strong
|
|
304
|
+
@property(nonatomic, strong) NSURL* pendingPopupParentURL;
|
|
305
|
+
@property(nonatomic, strong) NSURL* pendingPopupChildURL;
|
|
306
|
+
@property(nonatomic, assign) WKWebView* webView;
|
|
302
307
|
@end
|
|
303
308
|
|
|
304
309
|
@implementation WKNavDelegate
|
|
@@ -316,17 +321,15 @@ static NSString* fit_uniquePath(NSString* baseDir, NSString* filename) {
|
|
|
316
321
|
}
|
|
317
322
|
|
|
318
323
|
#pragma mark - Navigazione
|
|
319
|
-
|
|
320
|
-
|
|
321
324
|
// 1a) Navigation: intercetta click con targetFrame == nil (tipico di _blank)
|
|
322
325
|
- (void)webView:(WKWebView *)webView
|
|
323
326
|
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
|
|
324
327
|
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
|
|
325
328
|
{
|
|
326
|
-
// Se è un _blank, no-op qui: ci pensa createWebView... (sopra)
|
|
327
329
|
decisionHandler(WKNavigationActionPolicyAllow);
|
|
328
330
|
}
|
|
329
331
|
|
|
332
|
+
|
|
330
333
|
// 1b) UI: invocato quando la pagina chiede esplicitamente una nuova webview
|
|
331
334
|
- (WKWebView *)webView:(WKWebView *)webView
|
|
332
335
|
createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
@@ -334,8 +337,18 @@ createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
|
334
337
|
windowFeatures:(WKWindowFeatures *)windowFeatures
|
|
335
338
|
{
|
|
336
339
|
if (navigationAction.targetFrame == nil || !navigationAction.targetFrame.isMainFrame) {
|
|
337
|
-
|
|
340
|
+
NSURL *parent = webView.URL;
|
|
341
|
+
NSURL *child = navigationAction.request.URL;
|
|
342
|
+
|
|
343
|
+
// salva coppia padre/figlio per il “ritorno” post-download
|
|
344
|
+
self.pendingPopupParentURL = parent;
|
|
345
|
+
self.pendingPopupChildURL = child;
|
|
346
|
+
|
|
347
|
+
if (child) {
|
|
348
|
+
[webView loadRequest:navigationAction.request]; // apri nella stessa webview
|
|
349
|
+
}
|
|
338
350
|
}
|
|
351
|
+
|
|
339
352
|
return nil; // restituisci nil per NON creare una nuova finestra
|
|
340
353
|
}
|
|
341
354
|
|
|
@@ -390,10 +403,27 @@ createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
|
390
403
|
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
|
|
391
404
|
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
|
|
392
405
|
{
|
|
406
|
+
NSURLResponse *resp = navigationResponse.response;
|
|
407
|
+
NSURL *url = resp.URL;
|
|
408
|
+
|
|
409
|
+
BOOL isAttachment = NO;
|
|
410
|
+
if ([resp isKindOfClass:NSHTTPURLResponse.class]) {
|
|
411
|
+
NSHTTPURLResponse *http = (NSHTTPURLResponse *)resp;
|
|
412
|
+
NSString *cd = http.allHeaderFields[@"Content-Disposition"];
|
|
413
|
+
if (cd && [[cd lowercaseString] containsString:@"attachment"]) {
|
|
414
|
+
isAttachment = YES;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (isAttachment) {
|
|
419
|
+
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
393
423
|
if (navigationResponse.canShowMIMEType) {
|
|
394
424
|
decisionHandler(WKNavigationResponsePolicyAllow);
|
|
395
425
|
} else {
|
|
396
|
-
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
426
|
+
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
397
427
|
}
|
|
398
428
|
}
|
|
399
429
|
|
|
@@ -582,6 +612,42 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
582
612
|
DownloadInfo* info = new DownloadInfo(qFileName, qDir, qUrl, self.owner);
|
|
583
613
|
emit self.owner->downloadFinished(info);
|
|
584
614
|
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
WKWebView *webView = self.webView;
|
|
618
|
+
NSURL *srcURL = [self.sourceURLs objectForKey:download];
|
|
619
|
+
|
|
620
|
+
if (webView && self.pendingPopupChildURL && srcURL &&
|
|
621
|
+
[srcURL isEqual:self.pendingPopupChildURL]) {
|
|
622
|
+
|
|
623
|
+
WKBackForwardList *bf = webView.backForwardList;
|
|
624
|
+
NSURL *current = webView.URL;
|
|
625
|
+
NSURL *backURL = bf.backItem.URL;
|
|
626
|
+
|
|
627
|
+
// CASI:
|
|
628
|
+
// A) Sei sul FIGLIO → torna indietro alla PARENT
|
|
629
|
+
if (current && [current isEqual:self.pendingPopupChildURL]) {
|
|
630
|
+
[webView goBack];
|
|
631
|
+
}
|
|
632
|
+
// B) Sei già sulla PARENT → non fare nulla
|
|
633
|
+
else if (current && [current isEqual:self.pendingPopupParentURL]) {
|
|
634
|
+
// niente
|
|
635
|
+
}
|
|
636
|
+
// C) Non sei sul child, ma l’item precedente è la PARENT → goBack
|
|
637
|
+
else if (backURL && [backURL isEqual:self.pendingPopupParentURL]) {
|
|
638
|
+
[webView goBack];
|
|
639
|
+
}
|
|
640
|
+
// D) Fallback: carica esplicitamente la PARENT
|
|
641
|
+
else if (self.pendingPopupParentURL) {
|
|
642
|
+
[webView loadRequest:[NSURLRequest requestWithURL:self.pendingPopupParentURL]];
|
|
643
|
+
} else {
|
|
644
|
+
//Niente
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// pulizia stato
|
|
648
|
+
self.pendingPopupChildURL = nil;
|
|
649
|
+
self.pendingPopupParentURL = nil;
|
|
650
|
+
}
|
|
585
651
|
// 5) cleanup mappe
|
|
586
652
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
587
653
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
@@ -609,6 +675,20 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
609
675
|
QString::fromUtf8(error.localizedDescription.UTF8String)
|
|
610
676
|
);
|
|
611
677
|
|
|
678
|
+
// 🔙 Se il download proviene dal "figlio", torna alla "pagina padre"
|
|
679
|
+
WKWebView *webView = self.webView;
|
|
680
|
+
NSURL *src = [self.sourceURLs objectForKey:download];
|
|
681
|
+
if (webView && self.pendingPopupChildURL && src && [src isEqual:self.pendingPopupChildURL]) {
|
|
682
|
+
if (webView.canGoBack) {
|
|
683
|
+
[webView goBack];
|
|
684
|
+
} else if (self.pendingPopupParentURL) {
|
|
685
|
+
[webView loadRequest:[NSURLRequest requestWithURL:self.pendingPopupParentURL]];
|
|
686
|
+
}
|
|
687
|
+
// ripulisci lo stato
|
|
688
|
+
self.pendingPopupChildURL = nil;
|
|
689
|
+
self.pendingPopupParentURL = nil;
|
|
690
|
+
}
|
|
691
|
+
|
|
612
692
|
// cleanup mappe
|
|
613
693
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
614
694
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
@@ -656,6 +736,11 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
656
736
|
cfg.defaultWebpagePreferences.allowsContentJavaScript = YES;
|
|
657
737
|
}
|
|
658
738
|
|
|
739
|
+
// ✅ Consenti window.open() senza creare una nuova finestra UI
|
|
740
|
+
@try {
|
|
741
|
+
cfg.preferences.javaScriptCanOpenWindowsAutomatically = YES;
|
|
742
|
+
} @catch (...) {}
|
|
743
|
+
|
|
659
744
|
// --- Fullscreen HTML5 (via KVC tollerante) ---
|
|
660
745
|
@try {
|
|
661
746
|
[cfg.preferences setValue:@YES forKey:@"fullScreenEnabled"];
|
|
@@ -722,8 +807,8 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
722
807
|
|
|
723
808
|
d->delegate = [WKNavDelegate new];
|
|
724
809
|
d->delegate.owner = this;
|
|
810
|
+
d->delegate.webView = d->wk;
|
|
725
811
|
[d->wk setNavigationDelegate:d->delegate];
|
|
726
|
-
|
|
727
812
|
[d->wk setUIDelegate:d->delegate];
|
|
728
813
|
}
|
|
729
814
|
|
{fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/.github/workflows/wheels-macos.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.3a2}/bindings/pyside6/macos/CMakeLists.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|