fit-webview-bridge 0.2.1a4__tar.gz → 0.2.2a2__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.1a4 → fit_webview_bridge-0.2.2a2}/PKG-INFO +1 -1
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/bindings/pyside6/macos/typesystem_wkwebview.xml +3 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/pyproject.toml +1 -1
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/src/macos/CMakeLists.txt +1 -0
- fit_webview_bridge-0.2.2a2/src/macos/DownloadInfo.h +26 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/src/macos/WKWebViewWidget.h +3 -1
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/src/macos/WKWebViewWidget.mm +80 -6
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/.github/workflows/wheels-macos.yml +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/.gitignore +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/.vscode/settings.json +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/README.md +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/bindings/pyside6/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/examples/macos/wkwebview_demo.py +0 -0
- {fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/fit_webview_bridge/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fit-webview-bridge"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2a2"
|
|
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"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <QObject>
|
|
3
|
+
#include <QString>
|
|
4
|
+
#include <QUrl>
|
|
5
|
+
|
|
6
|
+
class DownloadInfo : public QObject {
|
|
7
|
+
Q_OBJECT
|
|
8
|
+
Q_PROPERTY(QString downloadFileName READ downloadFileName CONSTANT)
|
|
9
|
+
Q_PROPERTY(QString downloadDirectory READ downloadDirectory CONSTANT)
|
|
10
|
+
Q_PROPERTY(QUrl downloadUrl READ downloadUrl CONSTANT)
|
|
11
|
+
public:
|
|
12
|
+
explicit DownloadInfo(const QString& fileName,
|
|
13
|
+
const QString& directory,
|
|
14
|
+
const QUrl& url,
|
|
15
|
+
QObject* parent=nullptr)
|
|
16
|
+
: QObject(parent), m_fileName(fileName), m_directory(directory), m_url(url) {}
|
|
17
|
+
|
|
18
|
+
QString downloadFileName() const { return m_fileName; }
|
|
19
|
+
QString downloadDirectory() const { return m_directory; }
|
|
20
|
+
QUrl downloadUrl() const { return m_url; }
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
QString m_fileName;
|
|
24
|
+
QString m_directory;
|
|
25
|
+
QUrl m_url;
|
|
26
|
+
};
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
#include <QObject>
|
|
4
4
|
#include <QUrl>
|
|
5
5
|
|
|
6
|
+
#include "DownloadInfo.h"
|
|
7
|
+
|
|
6
8
|
class QString; class QShowEvent; class QResizeEvent;
|
|
7
9
|
|
|
8
10
|
class WKWebViewWidget : public QWidget {
|
|
@@ -36,7 +38,7 @@ signals:
|
|
|
36
38
|
|
|
37
39
|
void downloadStarted(const QString& suggestedFilename, const QString& destinationPath);
|
|
38
40
|
void downloadProgress(qint64 bytesReceived, qint64 totalBytes);
|
|
39
|
-
void downloadFinished(
|
|
41
|
+
void downloadFinished(DownloadInfo* info);
|
|
40
42
|
void downloadFailed(const QString& filePath, const QString& error);
|
|
41
43
|
|
|
42
44
|
protected:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import <WebKit/WebKit.h>
|
|
3
3
|
|
|
4
4
|
#include "WKWebViewWidget.h"
|
|
5
|
+
#include "DownloadInfo.h"
|
|
5
6
|
|
|
6
7
|
#include <QtWidgets>
|
|
7
8
|
#include <QString>
|
|
@@ -52,6 +53,9 @@ static NSURL* toNSURL(QUrl u);
|
|
|
52
53
|
@property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* downloadPaths; // weak key -> strong value
|
|
53
54
|
@property(nonatomic, strong) NSMapTable<NSProgress*, WKDownload*>* progressToDownload; // weak->weak
|
|
54
55
|
@property(nonatomic, strong) NSHashTable<NSProgress*>* completedProgresses; // weak set
|
|
56
|
+
@property(nonatomic, strong) NSMapTable<WKDownload*, NSNumber*>* expectedTotals; // weak->strong
|
|
57
|
+
@property(nonatomic, strong) NSMapTable<WKDownload*, NSURL*>* sourceURLs; // weak->strong
|
|
58
|
+
@property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* suggestedNames; // weak->strong
|
|
55
59
|
@end
|
|
56
60
|
|
|
57
61
|
@implementation WKNavDelegate
|
|
@@ -61,6 +65,9 @@ static NSURL* toNSURL(QUrl u);
|
|
|
61
65
|
_downloadPaths = [NSMapTable weakToStrongObjectsMapTable];
|
|
62
66
|
_progressToDownload = [NSMapTable weakToWeakObjectsMapTable];
|
|
63
67
|
_completedProgresses = [NSHashTable weakObjectsHashTable];
|
|
68
|
+
_expectedTotals = [NSMapTable weakToStrongObjectsMapTable];
|
|
69
|
+
_sourceURLs = [NSMapTable weakToStrongObjectsMapTable];
|
|
70
|
+
_suggestedNames = [NSMapTable weakToStrongObjectsMapTable];
|
|
64
71
|
}
|
|
65
72
|
return self;
|
|
66
73
|
}
|
|
@@ -131,6 +138,12 @@ navigationAction:(WKNavigationAction *)navigationAction
|
|
|
131
138
|
didBecomeDownload:(WKDownload *)download
|
|
132
139
|
{
|
|
133
140
|
download.delegate = self;
|
|
141
|
+
|
|
142
|
+
// URL sorgente (request dell’azione)
|
|
143
|
+
if (navigationAction.request.URL) {
|
|
144
|
+
[self.sourceURLs setObject:navigationAction.request.URL forKey:download];
|
|
145
|
+
}
|
|
146
|
+
|
|
134
147
|
if (self.owner) emit self.owner->downloadStarted(QString(), QString());
|
|
135
148
|
|
|
136
149
|
// KVO su NSProgress (3 keyPath, con INITIAL)
|
|
@@ -153,6 +166,10 @@ didBecomeDownload:(WKDownload *)download
|
|
|
153
166
|
{
|
|
154
167
|
download.delegate = self;
|
|
155
168
|
|
|
169
|
+
if (navigationResponse.response.URL) {
|
|
170
|
+
[self.sourceURLs setObject:navigationResponse.response.URL forKey:download];
|
|
171
|
+
}
|
|
172
|
+
|
|
156
173
|
NSString* suggested = navigationResponse.response.suggestedFilename ?: @"download";
|
|
157
174
|
if (self.owner) {
|
|
158
175
|
QString dir = self.owner->downloadDirectory();
|
|
@@ -216,6 +233,22 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
216
233
|
QString::fromUtf8(finalPath.UTF8String)
|
|
217
234
|
);
|
|
218
235
|
|
|
236
|
+
// Leggi il Content-Length se disponibile e salvalo
|
|
237
|
+
long long expected = response.expectedContentLength; // -1 se sconosciuto
|
|
238
|
+
if (expected >= 0) {
|
|
239
|
+
[self.expectedTotals setObject:@(expected) forKey:download];
|
|
240
|
+
if (self.owner) {
|
|
241
|
+
// progress iniziale (0 di total)
|
|
242
|
+
emit self.owner->downloadProgress(0, expected);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (suggestedFilename) {
|
|
247
|
+
[self.suggestedNames setObject:suggestedFilename forKey:download];
|
|
248
|
+
} else if (![self.suggestedNames objectForKey:download]) {
|
|
249
|
+
[self.suggestedNames setObject:@"download" forKey:download];
|
|
250
|
+
}
|
|
251
|
+
|
|
219
252
|
completionHandler([NSURL fileURLWithPath:finalPath]);
|
|
220
253
|
}
|
|
221
254
|
|
|
@@ -230,54 +263,95 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
|
|
|
230
263
|
}
|
|
231
264
|
NSProgress* prog = (NSProgress*)obj;
|
|
232
265
|
|
|
233
|
-
//
|
|
234
|
-
if ([self.completedProgresses containsObject:prog]) return;
|
|
235
|
-
|
|
266
|
+
// Calcolo grezzo fuori dal main
|
|
236
267
|
int64_t total = prog.totalUnitCount; // -1 se sconosciuto
|
|
237
268
|
int64_t done = prog.completedUnitCount;
|
|
238
269
|
|
|
270
|
+
// Dispatch su main, ma **ricontrolla** lo stato "completed" dentro al blocco
|
|
271
|
+
// DOPO (compatibile MRC)
|
|
272
|
+
__unsafe_unretained WKNavDelegate* weakSelf = self;
|
|
239
273
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
240
|
-
|
|
274
|
+
WKNavDelegate* strongSelf = weakSelf;
|
|
275
|
+
if (!strongSelf || !strongSelf.owner) return;
|
|
276
|
+
|
|
277
|
+
// blocca update tardivi dopo finished/failed
|
|
278
|
+
if ([strongSelf.completedProgresses containsObject:prog]) return;
|
|
279
|
+
|
|
280
|
+
WKDownload* dl = [strongSelf.progressToDownload objectForKey:prog];
|
|
281
|
+
NSNumber* exp = dl ? [strongSelf.expectedTotals objectForKey:dl] : nil;
|
|
282
|
+
|
|
283
|
+
int64_t totalEff = (total >= 0 ? total : (exp ? exp.longLongValue : -1));
|
|
284
|
+
emit strongSelf.owner->downloadProgress(done, totalEff);
|
|
241
285
|
});
|
|
286
|
+
|
|
287
|
+
|
|
242
288
|
}
|
|
243
289
|
|
|
244
290
|
- (void)downloadDidFinish:(WKDownload *)download {
|
|
245
291
|
if (!self.owner) return;
|
|
246
292
|
|
|
293
|
+
// 1) stop KVO
|
|
247
294
|
@try {
|
|
248
295
|
[download.progress removeObserver:self forKeyPath:@"fractionCompleted"];
|
|
249
296
|
[download.progress removeObserver:self forKeyPath:@"completedUnitCount"];
|
|
250
297
|
[download.progress removeObserver:self forKeyPath:@"totalUnitCount"];
|
|
251
298
|
} @catch (...) {}
|
|
252
299
|
|
|
300
|
+
// 2) marca come completato per filtrare update tardivi
|
|
253
301
|
[self.completedProgresses addObject:download.progress];
|
|
254
302
|
|
|
303
|
+
// 3) raccogli dati
|
|
255
304
|
NSString* finalPath = [self.downloadPaths objectForKey:download];
|
|
256
|
-
|
|
305
|
+
NSString* fname = [self.suggestedNames objectForKey:download];
|
|
306
|
+
if (!fname && finalPath) fname = [finalPath lastPathComponent];
|
|
307
|
+
NSString* dir = finalPath ? [finalPath stringByDeletingLastPathComponent] : nil;
|
|
308
|
+
NSURL* src = [self.sourceURLs objectForKey:download];
|
|
309
|
+
|
|
310
|
+
// 4) crea DownloadInfo* e emetti
|
|
311
|
+
QString qFileName = fname ? QString::fromUtf8(fname.UTF8String) : QString();
|
|
312
|
+
QString qDir = dir ? QString::fromUtf8(dir.UTF8String) : QString();
|
|
313
|
+
QUrl qUrl = src ? QUrl::fromEncoded(QByteArray(src.absoluteString.UTF8String))
|
|
314
|
+
: QUrl();
|
|
315
|
+
|
|
316
|
+
DownloadInfo* info = new DownloadInfo(qFileName, qDir, qUrl, self.owner);
|
|
317
|
+
emit self.owner->downloadFinished(info);
|
|
318
|
+
|
|
319
|
+
// 5) cleanup mappe
|
|
257
320
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
258
321
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
322
|
+
[self.expectedTotals removeObjectForKey:download];
|
|
323
|
+
[self.sourceURLs removeObjectForKey:download];
|
|
324
|
+
[self.suggestedNames removeObjectForKey:download];
|
|
259
325
|
}
|
|
260
326
|
|
|
327
|
+
|
|
261
328
|
- (void)download:(WKDownload *)download didFailWithError:(NSError *)error resumeData:(NSData *)resumeData {
|
|
262
329
|
if (!self.owner) return;
|
|
263
330
|
|
|
331
|
+
// stop KVO
|
|
264
332
|
@try {
|
|
265
333
|
[download.progress removeObserver:self forKeyPath:@"fractionCompleted"];
|
|
266
334
|
[download.progress removeObserver:self forKeyPath:@"completedUnitCount"];
|
|
267
335
|
[download.progress removeObserver:self forKeyPath:@"totalUnitCount"];
|
|
268
336
|
} @catch (...) {}
|
|
269
|
-
|
|
270
337
|
[self.completedProgresses addObject:download.progress];
|
|
271
338
|
|
|
339
|
+
// path (se già deciso)
|
|
272
340
|
NSString* finalPath = [self.downloadPaths objectForKey:download];
|
|
273
341
|
emit self.owner->downloadFailed(
|
|
274
342
|
finalPath ? QString::fromUtf8(finalPath.UTF8String) : QString(),
|
|
275
343
|
QString::fromUtf8(error.localizedDescription.UTF8String)
|
|
276
344
|
);
|
|
345
|
+
|
|
346
|
+
// cleanup mappe
|
|
277
347
|
if (finalPath) [self.downloadPaths removeObjectForKey:download];
|
|
278
348
|
[self.progressToDownload removeObjectForKey:download.progress];
|
|
349
|
+
[self.expectedTotals removeObjectForKey:download];
|
|
350
|
+
[self.sourceURLs removeObjectForKey:download];
|
|
351
|
+
[self.suggestedNames removeObjectForKey:download];
|
|
279
352
|
}
|
|
280
353
|
|
|
354
|
+
|
|
281
355
|
@end
|
|
282
356
|
|
|
283
357
|
// =======================
|
{fit_webview_bridge-0.2.1a4 → fit_webview_bridge-0.2.2a2}/.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.1a4 → fit_webview_bridge-0.2.2a2}/bindings/pyside6/macos/CMakeLists.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|