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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fit-webview-bridge
3
- Version: 0.2.1a4
3
+ Version: 0.2.2a2
4
4
  Summary: Qt native WebView bridge with PySide6 bindings
5
5
  Author: FIT Project
6
6
  License: LGPL-3.0-or-later
@@ -7,6 +7,9 @@
7
7
  <object-type name="WKWebViewWidget">
8
8
  <include file-name="WKWebViewWidget.h" location="global"/>
9
9
  </object-type>
10
+ <object-type name="DownloadInfo">
11
+ <include file-name="DownloadInfo.h" location="global"/>
12
+ </object-type>
10
13
  </typesystem>
11
14
 
12
15
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fit-webview-bridge"
3
- version = "0.2.1a4"
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"]
@@ -28,6 +28,7 @@ file(CREATE_LINK "${QT_FRAMEWORKS_DIR}/QtWidgets.framework/Headers" "${QT_HDRSHI
28
28
  add_library(wkwebview STATIC
29
29
  WKWebViewWidget.mm
30
30
  WKWebViewWidget.h
31
+ DownloadInfo.h
31
32
  )
32
33
  target_compile_features(wkwebview PRIVATE cxx_std_17)
33
34
 
@@ -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(const QString& filePath);
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
- // ignora aggiornamenti dopo il completamento
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
- emit self.owner->downloadProgress(done, (total >= 0 ? total : -1));
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
- emit self.owner->downloadFinished(finalPath ? QString::fromUtf8(finalPath.UTF8String) : QString());
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
  // =======================