fit-webview-bridge 0.2.3a1__tar.gz → 0.2.4a1__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.4a1}/PKG-INFO +1 -1
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/examples/macos/wkwebview_demo.py +26 -5
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/pyproject.toml +1 -1
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/src/macos/WKWebViewWidget.h +2 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/src/macos/WKWebViewWidget.mm +218 -6
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/.github/workflows/wheels-macos.yml +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/.gitignore +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/.vscode/settings.json +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/README.md +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/bindings/pyside6/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/bindings/pyside6/macos/typesystem_wkwebview.xml +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/fit_webview_bridge/__init__.py +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/src/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/src/macos/DownloadInfo.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.4a1"
|
|
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"]
|
|
@@ -26,6 +26,7 @@ public:
|
|
|
26
26
|
|
|
27
27
|
Q_INVOKABLE void setDownloadDirectory(const QString& dirPath);
|
|
28
28
|
Q_INVOKABLE QString downloadDirectory() const;
|
|
29
|
+
void renderErrorPage(const QUrl& url, const QString& reason, int httpStatus);
|
|
29
30
|
|
|
30
31
|
signals:
|
|
31
32
|
void loadFinished(bool ok);
|
|
@@ -34,6 +35,7 @@ signals:
|
|
|
34
35
|
void loadProgress(int percent);
|
|
35
36
|
void canGoBackChanged(bool);
|
|
36
37
|
void canGoForwardChanged(bool);
|
|
38
|
+
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
void downloadStarted(const QString& suggestedFilename, const QString& destinationPath);
|
|
@@ -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"
|
|
@@ -90,6 +92,10 @@ static NSString* FIT_T(NSString* key) {
|
|
|
90
92
|
@"menu.openImage": @"Open image",
|
|
91
93
|
@"menu.copyImageURL": @"Copy image URL",
|
|
92
94
|
@"menu.downloadImage":@"Download image…",
|
|
95
|
+
@"error.title": @"Can’t load this page",
|
|
96
|
+
@"error.reason": @"The site may not exist or be temporarily unreachable.",
|
|
97
|
+
@"error.retry": @"Retry",
|
|
98
|
+
@"error.close": @"Close",
|
|
93
99
|
};
|
|
94
100
|
it = @{
|
|
95
101
|
@"menu.openLink": @"Apri link",
|
|
@@ -97,6 +103,10 @@ static NSString* FIT_T(NSString* key) {
|
|
|
97
103
|
@"menu.openImage": @"Apri immagine",
|
|
98
104
|
@"menu.copyImageURL": @"Copia URL immagine",
|
|
99
105
|
@"menu.downloadImage":@"Scarica immagine…",
|
|
106
|
+
@"error.title": @"Impossibile caricare la pagina",
|
|
107
|
+
@"error.reason": @"Il sito potrebbe essere inesistente o momentaneamente non raggiungibile.",
|
|
108
|
+
@"error.retry": @"Riprova",
|
|
109
|
+
@"error.close": @"Chiudi",
|
|
100
110
|
};
|
|
101
111
|
});
|
|
102
112
|
NSString *lang = FIT_CurrentLang();
|
|
@@ -299,6 +309,9 @@ static NSString* fit_uniquePath(NSString* baseDir, NSString* filename) {
|
|
|
299
309
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSNumber*>* expectedTotals; // weak->strong
|
|
300
310
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSURL*>* sourceURLs; // weak->strong
|
|
301
311
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* suggestedNames; // weak->strong
|
|
312
|
+
@property(nonatomic, strong) NSURL* pendingPopupParentURL;
|
|
313
|
+
@property(nonatomic, strong) NSURL* pendingPopupChildURL;
|
|
314
|
+
@property(nonatomic, assign) WKWebView* webView;
|
|
302
315
|
@end
|
|
303
316
|
|
|
304
317
|
@implementation WKNavDelegate
|
|
@@ -316,17 +329,15 @@ static NSString* fit_uniquePath(NSString* baseDir, NSString* filename) {
|
|
|
316
329
|
}
|
|
317
330
|
|
|
318
331
|
#pragma mark - Navigazione
|
|
319
|
-
|
|
320
|
-
|
|
321
332
|
// 1a) Navigation: intercetta click con targetFrame == nil (tipico di _blank)
|
|
322
333
|
- (void)webView:(WKWebView *)webView
|
|
323
334
|
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
|
|
324
335
|
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
|
|
325
336
|
{
|
|
326
|
-
// Se è un _blank, no-op qui: ci pensa createWebView... (sopra)
|
|
327
337
|
decisionHandler(WKNavigationActionPolicyAllow);
|
|
328
338
|
}
|
|
329
339
|
|
|
340
|
+
|
|
330
341
|
// 1b) UI: invocato quando la pagina chiede esplicitamente una nuova webview
|
|
331
342
|
- (WKWebView *)webView:(WKWebView *)webView
|
|
332
343
|
createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
@@ -334,12 +345,42 @@ createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
|
334
345
|
windowFeatures:(WKWindowFeatures *)windowFeatures
|
|
335
346
|
{
|
|
336
347
|
if (navigationAction.targetFrame == nil || !navigationAction.targetFrame.isMainFrame) {
|
|
337
|
-
|
|
348
|
+
NSURL *parent = webView.URL;
|
|
349
|
+
NSURL *child = navigationAction.request.URL;
|
|
350
|
+
|
|
351
|
+
// salva coppia padre/figlio per il “ritorno” post-download
|
|
352
|
+
self.pendingPopupParentURL = parent;
|
|
353
|
+
self.pendingPopupChildURL = child;
|
|
354
|
+
|
|
355
|
+
if (child) {
|
|
356
|
+
[webView loadRequest:navigationAction.request]; // apri nella stessa webview
|
|
357
|
+
}
|
|
338
358
|
}
|
|
359
|
+
|
|
339
360
|
return nil; // restituisci nil per NON creare una nuova finestra
|
|
340
361
|
}
|
|
341
362
|
|
|
342
363
|
|
|
364
|
+
- (void)webView:(WKWebView *)webView
|
|
365
|
+
didFailProvisionalNavigation:(WKNavigation *)navigation
|
|
366
|
+
withError:(NSError *)error
|
|
367
|
+
{
|
|
368
|
+
if (!self.owner) return;
|
|
369
|
+
emit self.owner->loadFinished(false);
|
|
370
|
+
emit self.owner->loadProgress(0);
|
|
371
|
+
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
372
|
+
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
373
|
+
|
|
374
|
+
QUrl qurl = webView.URL
|
|
375
|
+
? QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String))
|
|
376
|
+
: QUrl();
|
|
377
|
+
self.owner->renderErrorPage(qurl,
|
|
378
|
+
QString::fromUtf8(error.localizedDescription.UTF8String),
|
|
379
|
+
/*httpStatus*/ 0);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
343
384
|
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
|
|
344
385
|
if (!self.owner) return;
|
|
345
386
|
if (webView.URL)
|
|
@@ -382,6 +423,13 @@ createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
|
382
423
|
emit self.owner->loadProgress(0);
|
|
383
424
|
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
384
425
|
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
426
|
+
// Mostra pagina d'errore interna
|
|
427
|
+
QUrl qurl = webView.URL
|
|
428
|
+
? QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String))
|
|
429
|
+
: QUrl();
|
|
430
|
+
self.owner->renderErrorPage(qurl,
|
|
431
|
+
QString::fromUtf8(error.localizedDescription.UTF8String),
|
|
432
|
+
/*httpStatus*/ 0);
|
|
385
433
|
}
|
|
386
434
|
|
|
387
435
|
#pragma mark - Decide download vs render
|
|
@@ -390,10 +438,36 @@ createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
|
|
390
438
|
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
|
|
391
439
|
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
|
|
392
440
|
{
|
|
441
|
+
NSURLResponse *resp = navigationResponse.response;
|
|
442
|
+
NSURL *url = resp.URL;
|
|
443
|
+
|
|
444
|
+
BOOL isAttachment = NO;
|
|
445
|
+
if ([resp isKindOfClass:NSHTTPURLResponse.class]) {
|
|
446
|
+
NSHTTPURLResponse *http = (NSHTTPURLResponse *)resp;
|
|
447
|
+
NSString *cd = http.allHeaderFields[@"Content-Disposition"];
|
|
448
|
+
if (cd && [[cd lowercaseString] containsString:@"attachment"]) {
|
|
449
|
+
isAttachment = YES;
|
|
450
|
+
}
|
|
451
|
+
// 🔎 Se è main frame e status HTTP >= 400, mostra pagina d'errore custom
|
|
452
|
+
if (navigationResponse.isForMainFrame && http.statusCode >= 400 && self.owner) {
|
|
453
|
+
QUrl qurl = QUrl::fromEncoded(QByteArray(url.absoluteString.UTF8String));
|
|
454
|
+
self.owner->renderErrorPage(qurl,
|
|
455
|
+
QStringLiteral(""), // reason generica localizzata dal template
|
|
456
|
+
(int)http.statusCode);
|
|
457
|
+
decisionHandler(WKNavigationResponsePolicyCancel);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (isAttachment) {
|
|
463
|
+
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
393
467
|
if (navigationResponse.canShowMIMEType) {
|
|
394
468
|
decisionHandler(WKNavigationResponsePolicyAllow);
|
|
395
469
|
} else {
|
|
396
|
-
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
470
|
+
decisionHandler(WKNavigationResponsePolicyDownload);
|
|
397
471
|
}
|
|
398
472
|
}
|
|
399
473
|
|
|
@@ -582,6 +656,42 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
582
656
|
DownloadInfo* info = new DownloadInfo(qFileName, qDir, qUrl, self.owner);
|
|
583
657
|
emit self.owner->downloadFinished(info);
|
|
584
658
|
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
WKWebView *webView = self.webView;
|
|
662
|
+
NSURL *srcURL = [self.sourceURLs objectForKey:download];
|
|
663
|
+
|
|
664
|
+
if (webView && self.pendingPopupChildURL && srcURL &&
|
|
665
|
+
[srcURL isEqual:self.pendingPopupChildURL]) {
|
|
666
|
+
|
|
667
|
+
WKBackForwardList *bf = webView.backForwardList;
|
|
668
|
+
NSURL *current = webView.URL;
|
|
669
|
+
NSURL *backURL = bf.backItem.URL;
|
|
670
|
+
|
|
671
|
+
// CASI:
|
|
672
|
+
// A) Sei sul FIGLIO → torna indietro alla PARENT
|
|
673
|
+
if (current && [current isEqual:self.pendingPopupChildURL]) {
|
|
674
|
+
[webView goBack];
|
|
675
|
+
}
|
|
676
|
+
// B) Sei già sulla PARENT → non fare nulla
|
|
677
|
+
else if (current && [current isEqual:self.pendingPopupParentURL]) {
|
|
678
|
+
// niente
|
|
679
|
+
}
|
|
680
|
+
// C) Non sei sul child, ma l’item precedente è la PARENT → goBack
|
|
681
|
+
else if (backURL && [backURL isEqual:self.pendingPopupParentURL]) {
|
|
682
|
+
[webView goBack];
|
|
683
|
+
}
|
|
684
|
+
// D) Fallback: carica esplicitamente la PARENT
|
|
685
|
+
else if (self.pendingPopupParentURL) {
|
|
686
|
+
[webView loadRequest:[NSURLRequest requestWithURL:self.pendingPopupParentURL]];
|
|
687
|
+
} else {
|
|
688
|
+
//Niente
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// pulizia stato
|
|
692
|
+
self.pendingPopupChildURL = nil;
|
|
693
|
+
self.pendingPopupParentURL = nil;
|
|
694
|
+
}
|
|
585
695
|
// 5) cleanup mappe
|
|
586
696
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
587
697
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
@@ -609,6 +719,20 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
609
719
|
QString::fromUtf8(error.localizedDescription.UTF8String)
|
|
610
720
|
);
|
|
611
721
|
|
|
722
|
+
// 🔙 Se il download proviene dal "figlio", torna alla "pagina padre"
|
|
723
|
+
WKWebView *webView = self.webView;
|
|
724
|
+
NSURL *src = [self.sourceURLs objectForKey:download];
|
|
725
|
+
if (webView && self.pendingPopupChildURL && src && [src isEqual:self.pendingPopupChildURL]) {
|
|
726
|
+
if (webView.canGoBack) {
|
|
727
|
+
[webView goBack];
|
|
728
|
+
} else if (self.pendingPopupParentURL) {
|
|
729
|
+
[webView loadRequest:[NSURLRequest requestWithURL:self.pendingPopupParentURL]];
|
|
730
|
+
}
|
|
731
|
+
// ripulisci lo stato
|
|
732
|
+
self.pendingPopupChildURL = nil;
|
|
733
|
+
self.pendingPopupParentURL = nil;
|
|
734
|
+
}
|
|
735
|
+
|
|
612
736
|
// cleanup mappe
|
|
613
737
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
614
738
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
@@ -656,6 +780,11 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
656
780
|
cfg.defaultWebpagePreferences.allowsContentJavaScript = YES;
|
|
657
781
|
}
|
|
658
782
|
|
|
783
|
+
// ✅ Consenti window.open() senza creare una nuova finestra UI
|
|
784
|
+
@try {
|
|
785
|
+
cfg.preferences.javaScriptCanOpenWindowsAutomatically = YES;
|
|
786
|
+
} @catch (...) {}
|
|
787
|
+
|
|
659
788
|
// --- Fullscreen HTML5 (via KVC tollerante) ---
|
|
660
789
|
@try {
|
|
661
790
|
[cfg.preferences setValue:@YES forKey:@"fullScreenEnabled"];
|
|
@@ -722,8 +851,8 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
722
851
|
|
|
723
852
|
d->delegate = [WKNavDelegate new];
|
|
724
853
|
d->delegate.owner = this;
|
|
854
|
+
d->delegate.webView = d->wk;
|
|
725
855
|
[d->wk setNavigationDelegate:d->delegate];
|
|
726
|
-
|
|
727
856
|
[d->wk setUIDelegate:d->delegate];
|
|
728
857
|
}
|
|
729
858
|
|
|
@@ -789,4 +918,87 @@ void WKWebViewWidget::setDownloadDirectory(const QString& dirPath) {
|
|
|
789
918
|
if (p.isEmpty()) return;
|
|
790
919
|
QDir().mkpath(p);
|
|
791
920
|
d->downloadDir = p;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
void WKWebViewWidget::renderErrorPage(const QUrl& url,
|
|
924
|
+
const QString& reason,
|
|
925
|
+
int httpStatus)
|
|
926
|
+
{
|
|
927
|
+
if (!(d && d->wk)) return;
|
|
928
|
+
|
|
929
|
+
// Template HTML minimale, con testo bilingue (IT/EN tramite FIT_T).
|
|
930
|
+
// Segnaposti: {url}, {reason}, {status}, {title}, {retry}, {close}
|
|
931
|
+
QString html = QString::fromUtf8(
|
|
932
|
+
R"FWB(<!doctype html><html lang="it"><meta charset="utf-8">
|
|
933
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
934
|
+
<title>{title}</title>
|
|
935
|
+
<style>
|
|
936
|
+
:root { color-scheme: light dark; }
|
|
937
|
+
html,body{height:100%}
|
|
938
|
+
body{
|
|
939
|
+
font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial;
|
|
940
|
+
margin:0;background:#fff;color:#000
|
|
941
|
+
}
|
|
942
|
+
@media (prefers-color-scheme: dark){
|
|
943
|
+
body{background:#000;color:#fff}
|
|
944
|
+
}
|
|
945
|
+
.card{
|
|
946
|
+
max-width:720px;margin:8vh auto;padding:28px;border-radius:16px;
|
|
947
|
+
background:#fff;color:#000;box-shadow:0 6px 24px rgba(0,0,0,.18)
|
|
948
|
+
}
|
|
949
|
+
@media (prefers-color-scheme: dark){
|
|
950
|
+
.card{background:#111;color:#eee;box-shadow:0 6px 24px rgba(255,255,255,.05)}
|
|
951
|
+
}
|
|
952
|
+
h1{font-size:22px;margin:0 0 6px}
|
|
953
|
+
p{line-height:1.5}
|
|
954
|
+
code{
|
|
955
|
+
background:#eee;color:#000;padding:2px 6px;border-radius:6px
|
|
956
|
+
}
|
|
957
|
+
@media (prefers-color-scheme: dark){
|
|
958
|
+
code{background:#222;color:#fff}
|
|
959
|
+
}
|
|
960
|
+
.actions{margin-top:18px;display:flex;gap:10px;flex-wrap:wrap}
|
|
961
|
+
button,a{
|
|
962
|
+
padding:10px 14px;border-radius:10px;border:1px solid currentColor;
|
|
963
|
+
cursor:pointer;text-decoration:none;background:transparent;color:inherit
|
|
964
|
+
}
|
|
965
|
+
button.primary{
|
|
966
|
+
background:#000;color:#fff;border-color:#000
|
|
967
|
+
}
|
|
968
|
+
@media (prefers-color-scheme: dark){
|
|
969
|
+
button.primary{background:#fff;color:#000;border-color:#fff}
|
|
970
|
+
}
|
|
971
|
+
small{opacity:.7}
|
|
972
|
+
</style>
|
|
973
|
+
<div class="card">
|
|
974
|
+
<h1>{title}</h1>
|
|
975
|
+
<p>URL: <code>{url}</code></p>
|
|
976
|
+
<p>{reason} <small>{status}</small></p>
|
|
977
|
+
<div class="actions">
|
|
978
|
+
<button class="primary" onclick="location.reload()">{retry}</button>
|
|
979
|
+
<a class="ghost" href="about:blank">{close}</a>
|
|
980
|
+
</div>
|
|
981
|
+
</div>)FWB"
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
// Localizza con FIT_T
|
|
987
|
+
QString title = QString::fromUtf8([FIT_T(@"error.title") UTF8String]);
|
|
988
|
+
QString reasonText = reason.isEmpty()
|
|
989
|
+
? QString::fromUtf8([FIT_T(@"error.reason") UTF8String])
|
|
990
|
+
: reason;
|
|
991
|
+
QString retry = QString::fromUtf8([FIT_T(@"error.retry") UTF8String]);
|
|
992
|
+
QString close = QString::fromUtf8([FIT_T(@"error.close") UTF8String]);
|
|
993
|
+
|
|
994
|
+
html.replace("{title}", title);
|
|
995
|
+
html.replace("{url}", url.toString());
|
|
996
|
+
html.replace("{reason}", reasonText);
|
|
997
|
+
html.replace("{status}", httpStatus > 0 ? QString("HTTP %1").arg(httpStatus) : QString());
|
|
998
|
+
html.replace("{retry}", retry);
|
|
999
|
+
html.replace("{close}", close);
|
|
1000
|
+
|
|
1001
|
+
// Carica l'HTML direttamente nella webview
|
|
1002
|
+
[d->wk loadHTMLString:[NSString stringWithUTF8String:html.toUtf8().constData()]
|
|
1003
|
+
baseURL:[NSURL URLWithString:@"about:blank"]];
|
|
792
1004
|
}
|
{fit_webview_bridge-0.2.3a1 → fit_webview_bridge-0.2.4a1}/.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.4a1}/bindings/pyside6/macos/CMakeLists.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|