Skip to content

Commit 408ae93

Browse files
committed
update
1 parent c99b50c commit 408ae93

File tree

2 files changed

+145
-182
lines changed

2 files changed

+145
-182
lines changed

ui_main.py

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys, os
33
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QListWidget, QFileDialog, QProgressBar, QTextEdit, QMessageBox, QSizePolicy
44
from PyQt6.QtCore import QThread, pyqtSignal, Qt
5+
from PyQt6.QtGui import QTextCursor
56
from auth import list_accounts, acquire_token_interactive, remove_account
67
from uploader import upload_items
78
from Cocoa import NSOpenPanel
@@ -50,11 +51,13 @@ def progress_cb(uploaded_bytes, total_bytes, speed_bytes_per_sec=None, eta_secon
5051
should_stop=lambda: self._stop
5152
)
5253
self.finished.emit(True)
53-
except Exception as e:
54-
self.log.emit("ERROR: " + str(e))
54+
except Exception:
55+
import traceback
56+
self.log.emit("ERROR:\n" + traceback.format_exc())
5557
self.finished.emit(False)
5658

5759
class MainWindow(QWidget):
60+
MAX_LOG_LINES = 1000
5861
def __init__(self):
5962
super().__init__()
6063
self.setWindowTitle("OneDrive Uploader")
@@ -112,6 +115,35 @@ def __init__(self):
112115
# Connect the unified choose button
113116
self.btn_choose.clicked.connect(self.choose_files_and_folders)
114117

118+
def _append_log(self, message: str):
119+
"""Append formatted log efficiently and trim to last MAX_LOG_LINES lines."""
120+
# format any raw byte values first
121+
formatted = self._format_log_message(message)
122+
cursor = self.log.textCursor()
123+
cursor.movePosition(QTextCursor.MoveOperation.End)
124+
cursor.insertText(formatted + "\n")
125+
self.log.setTextCursor(cursor)
126+
self.log.ensureCursorVisible()
127+
# trim lines if too many
128+
doc = self.log.document()
129+
if doc.blockCount() > self.MAX_LOG_LINES:
130+
# remove earliest extra lines
131+
extra = doc.blockCount() - self.MAX_LOG_LINES
132+
b = doc.begin()
133+
rm = 0
134+
cur = self.log.textCursor()
135+
cur.beginEditBlock()
136+
while extra > 0 and b.isValid():
137+
nxt = b.next()
138+
cur.setPosition(b.position())
139+
cur.movePosition(QTextCursor.MoveOperation.EndOfBlock, QTextCursor.MoveMode.KeepAnchor)
140+
cur.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor) # include newline
141+
cur.removeSelectedText()
142+
rm += 1
143+
extra -= 1
144+
b = nxt
145+
cur.endEditBlock()
146+
115147
def refresh_accounts(self):
116148
self.acct_list.clear()
117149
accts = list_accounts()
@@ -203,7 +235,7 @@ def format_size(bytes_value):
203235
return f"{mb:.1f} MB"
204236
gb = mb / 1024
205237
return f"{gb:.2f} GB"
206-
self.log.append(f"Total upload size: {format_size(total_bytes)}")
238+
self._append_log(f"Total upload size: {format_size(total_bytes)}")
207239

208240
def update_folder_label(self):
209241
full_list = getattr(self, '_full_list', [])
@@ -255,7 +287,7 @@ def add_account(self):
255287
try:
256288
token, acc = acquire_token_interactive()
257289
QMessageBox.information(self, "Signed In", f"Signed in as {acc.get('username')}")
258-
self.log.append(f"Signed in: {acc.get('username')}")
290+
self._append_log(f"Signed in: {acc.get('username')}")
259291
self.refresh_accounts()
260292
except Exception as e:
261293
QMessageBox.critical(self, "Error", str(e))
@@ -270,7 +302,7 @@ def remove_selected_account(self):
270302
hid = text.split("[")[-1].split("]")[0]
271303
ok = remove_account(hid)
272304
if ok:
273-
self.log.append(f"Removed account {hid}")
305+
self._append_log(f"Removed account {hid}")
274306
self.refresh_accounts()
275307
else:
276308
QMessageBox.warning(self, "Remove", "Failed to remove account")
@@ -283,6 +315,10 @@ def start_upload(self):
283315
if row < 0:
284316
QMessageBox.warning(self, "No account", "Add and select an account")
285317
return
318+
# Thread lifecycle management: prevent multiple uploads
319+
if self.worker and self.worker.isRunning():
320+
QMessageBox.warning(self, "Busy", "An upload task is still running.")
321+
return
286322
text = self.acct_list.currentItem().text()
287323
hid = text.split("[")[-1].split("]")[0]
288324

@@ -292,16 +328,16 @@ def start_upload(self):
292328
# 传 selected_paths 和 base_dir 给上传线程
293329
self.worker = UploadWorker(self.selected_paths, self.base_dir, account_home_id=hid)
294330
self.worker.progress.connect(self.on_progress)
295-
self.worker.log.connect(lambda s: self.log.append(self._format_log_message(s)))
331+
self.worker.log.connect(self._append_log)
296332
self.worker.finished.connect(lambda ok: self.on_finished(ok))
297333
self.worker.start()
298-
self.log.append("Upload started")
334+
self._append_log("Upload started")
299335

300336
def stop_upload(self):
301337
if self.worker and self.worker.isRunning():
302338
# signal worker to stop gracefully
303339
self.worker.request_stop()
304-
self.log.append("Stopping... waiting for current chunk to finish")
340+
self._append_log("Stopping... waiting for current chunk to finish")
305341
self.btn_start.setEnabled(True)
306342
self.btn_stop.setEnabled(False)
307343

@@ -311,7 +347,8 @@ def on_progress(self, uploaded, _ignored_total, speed=0, eta=0):
311347
total = getattr(self, "total_bytes", _ignored_total) or 0
312348
if total > 0:
313349
pct = int(uploaded * 100 / total)
314-
self.progress.setValue(pct)
350+
if pct != self.progress.value():
351+
self.progress.setValue(pct)
315352

316353
# --- 单位换算(动态单位显示) ---
317354
def format_size(bytes_value):
@@ -342,7 +379,7 @@ def format_time(seconds):
342379
uploaded_str = format_size(uploaded)
343380
total_str = format_size(total)
344381
mbps = (speed or 0) / (1024 * 1024)
345-
eta_str = format_time(eta)
382+
eta_str = format_time(eta) if eta and eta > 0 else "\u221e"
346383

347384
# --- 界面更新(进度条和状态标签) ---
348385
self.lbl_status.setText(
@@ -355,8 +392,14 @@ def format_time(seconds):
355392
def on_finished(self, ok):
356393
self.btn_start.setEnabled(True)
357394
self.btn_stop.setEnabled(False)
358-
self.log.append("Upload finished" if ok else "Upload ended with errors")
395+
self._append_log("Upload finished" if ok else "Upload ended with errors")
359396
self.refresh_accounts()
397+
if self.worker:
398+
try:
399+
self.worker.deleteLater()
400+
except Exception:
401+
pass
402+
self.worker = None
360403
def _format_log_message(self, message: str) -> str:
361404
"""Convert raw byte values in uploader logs to human-readable units."""
362405
import re

0 commit comments

Comments
 (0)