|
@@ -31,12 +31,12 @@ class Backend(QObject):
|
|
|
"Never": 0 # 0 means never timeout
|
|
"Never": 0 # 0 means never timeout
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- # Predefined speed options
|
|
|
|
|
|
|
+ # Predefined speed options
|
|
|
SPEED_OPTIONS = {
|
|
SPEED_OPTIONS = {
|
|
|
"50": 50,
|
|
"50": 50,
|
|
|
"100": 100,
|
|
"100": 100,
|
|
|
|
|
+ "150": 150,
|
|
|
"200": 200,
|
|
"200": 200,
|
|
|
- "300": 300,
|
|
|
|
|
"500": 500
|
|
"500": 500
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -70,22 +70,9 @@ class Backend(QObject):
|
|
|
backendConnectionChanged = Signal(bool) # True = backend reachable, False = unreachable
|
|
backendConnectionChanged = Signal(bool) # True = backend reachable, False = unreachable
|
|
|
reconnectStatusChanged = Signal(str) # Current reconnection status message
|
|
reconnectStatusChanged = Signal(str) # Current reconnection status message
|
|
|
|
|
|
|
|
- # Cache generation signals
|
|
|
|
|
- cacheProgressChanged = Signal(dict) # Emits cache progress data
|
|
|
|
|
-
|
|
|
|
|
def __init__(self):
|
|
def __init__(self):
|
|
|
super().__init__()
|
|
super().__init__()
|
|
|
self.base_url = "http://localhost:8080"
|
|
self.base_url = "http://localhost:8080"
|
|
|
-
|
|
|
|
|
- # Cache progress tracking
|
|
|
|
|
- self._cache_in_progress = False
|
|
|
|
|
- self._cache_progress = {
|
|
|
|
|
- 'in_progress': False,
|
|
|
|
|
- 'current': 0,
|
|
|
|
|
- 'total': 0,
|
|
|
|
|
- 'current_file': '',
|
|
|
|
|
- 'percentage': 0
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
# Initialize all status properties first
|
|
# Initialize all status properties first
|
|
|
self._current_file = ""
|
|
self._current_file = ""
|
|
@@ -138,15 +125,10 @@ class Backend(QObject):
|
|
|
|
|
|
|
|
# Use QTimer to defer session initialization until event loop is running
|
|
# Use QTimer to defer session initialization until event loop is running
|
|
|
QTimer.singleShot(100, self._delayed_init)
|
|
QTimer.singleShot(100, self._delayed_init)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
# Start initial WebSocket connection (after all attributes are initialized)
|
|
# Start initial WebSocket connection (after all attributes are initialized)
|
|
|
# Use QTimer to ensure it happens after constructor completes
|
|
# Use QTimer to ensure it happens after constructor completes
|
|
|
QTimer.singleShot(200, self._attempt_ws_reconnect)
|
|
QTimer.singleShot(200, self._attempt_ws_reconnect)
|
|
|
-
|
|
|
|
|
- # Start cache progress monitoring
|
|
|
|
|
- self._cache_progress_timer = QTimer()
|
|
|
|
|
- self._cache_progress_timer.timeout.connect(self._check_cache_progress)
|
|
|
|
|
- QTimer.singleShot(1000, lambda: self._cache_progress_timer.start(2000)) # Check every 2 seconds
|
|
|
|
|
|
|
|
|
|
@Slot()
|
|
@Slot()
|
|
|
def _delayed_init(self):
|
|
def _delayed_init(self):
|
|
@@ -216,59 +198,6 @@ class Backend(QObject):
|
|
|
def reconnectStatus(self):
|
|
def reconnectStatus(self):
|
|
|
return self._reconnect_status
|
|
return self._reconnect_status
|
|
|
|
|
|
|
|
- @Property(bool, notify=cacheProgressChanged)
|
|
|
|
|
- def cacheInProgress(self):
|
|
|
|
|
- return self._cache_in_progress
|
|
|
|
|
-
|
|
|
|
|
- @Property(dict, notify=cacheProgressChanged)
|
|
|
|
|
- def cacheProgress(self):
|
|
|
|
|
- return self._cache_progress
|
|
|
|
|
-
|
|
|
|
|
- # Cache progress checking
|
|
|
|
|
- @Slot()
|
|
|
|
|
- def _check_cache_progress(self):
|
|
|
|
|
- """Poll the backend for cache generation progress"""
|
|
|
|
|
- if self.session and self._backend_connected:
|
|
|
|
|
- asyncio.create_task(self._fetch_cache_progress())
|
|
|
|
|
-
|
|
|
|
|
- async def _fetch_cache_progress(self):
|
|
|
|
|
- """Fetch cache progress from backend API"""
|
|
|
|
|
- try:
|
|
|
|
|
- async with self.session.get(f"{self.base_url}/cache-progress") as resp:
|
|
|
|
|
- if resp.status == 200:
|
|
|
|
|
- data = await resp.json()
|
|
|
|
|
- was_in_progress = self._cache_in_progress
|
|
|
|
|
- self._cache_in_progress = data.get('in_progress', False)
|
|
|
|
|
- self._cache_progress = {
|
|
|
|
|
- 'in_progress': data.get('in_progress', False),
|
|
|
|
|
- 'current': data.get('current', 0),
|
|
|
|
|
- 'total': data.get('total', 0),
|
|
|
|
|
- 'current_file': data.get('current_file', ''),
|
|
|
|
|
- 'percentage': data.get('percentage', 0)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- # Only emit if status changed or progress updated
|
|
|
|
|
- if was_in_progress != self._cache_in_progress or self._cache_in_progress:
|
|
|
|
|
- self.cacheProgressChanged.emit(self._cache_progress)
|
|
|
|
|
-
|
|
|
|
|
- # Log when cache generation starts/stops
|
|
|
|
|
- if self._cache_in_progress and not was_in_progress:
|
|
|
|
|
- print(f"🎨 Cache generation started: {self._cache_progress['total']} patterns")
|
|
|
|
|
- elif not self._cache_in_progress and was_in_progress:
|
|
|
|
|
- print(f"✅ Cache generation completed!")
|
|
|
|
|
- # Stop polling when cache generation completes
|
|
|
|
|
- if self._cache_progress_timer.isActive():
|
|
|
|
|
- self._cache_progress_timer.stop()
|
|
|
|
|
- print(f"🛑 Cache progress polling stopped")
|
|
|
|
|
-
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- # Silently fail - cache progress is non-critical
|
|
|
|
|
- # Stop polling on repeated errors to avoid log spam
|
|
|
|
|
- if self._cache_progress_timer.isActive():
|
|
|
|
|
- self._cache_progress_timer.stop()
|
|
|
|
|
- print(f"🛑 Cache progress polling stopped due to error")
|
|
|
|
|
- pass
|
|
|
|
|
-
|
|
|
|
|
# WebSocket handlers
|
|
# WebSocket handlers
|
|
|
@Slot()
|
|
@Slot()
|
|
|
def _on_ws_connected(self):
|
|
def _on_ws_connected(self):
|