diff --git a/src/logger.py b/src/logger.py index 323f308..0165f70 100644 --- a/src/logger.py +++ b/src/logger.py @@ -17,6 +17,8 @@ def config_debug_level(): return logging.WARNING elif debug_level == "ERROR": return logging.ERROR + elif debug_level == "CRITICAL": + return logging.CRITICAL else: return logging.DEBUG diff --git a/src/main_window.py b/src/main_window.py index 65c3833..ddea68d 100644 --- a/src/main_window.py +++ b/src/main_window.py @@ -267,7 +267,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): sys.exit() elif close_question == QMessageBox.No: - logging.debug("[GUI] Keeping OneDriveGUI running.") + logging.info("[GUI] Keeping OneDriveGUI running.") def stop_onedrive_monitor(self, profile_name): if profile_name in workers: @@ -283,13 +283,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): try: if self.tray.isSystemTrayAvailable(): self.hide() - logging.info("[GUI] Minimizing main window to tray") + logging.debug("[GUI] Minimizing main window to tray") else: self.setWindowState(Qt.WindowMinimized) - logging.info("[GUI] Minimizing main window to taskbar/dock") + logging.debug("[GUI] Minimizing main window to taskbar/dock") except: self.setWindowState(Qt.WindowMinimized) - logging.info("[GUI] Minimizing main window to taskbar/dock") + logging.debug("[GUI] Minimizing main window to taskbar/dock") def show_setup_wizard(self): setup_wizard.show() @@ -342,7 +342,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): latest_client_version = get_latest_client_version() installed_client_version = get_installed_client_version() - logging.debug(f"[GUI] Client version check: Installed: {installed_client_version[0]} | Latest: {latest_client_version}") + logging.info(f"[GUI] Client version check: Installed: {installed_client_version[0]} | Latest: {latest_client_version}") if not installed_client_version: version_label_text = "OneDrive client not found!" @@ -418,7 +418,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): if not latest_gui_version: # Network issue or API error - don't show warning - logging.debug("[GUI] Unable to check for latest OneDriveGUI version") + logging.warning("[GUI] Unable to check for latest OneDriveGUI version") return # Parse versions for comparison @@ -429,14 +429,14 @@ class MainWindow(QMainWindow, Ui_MainWindow): logging.error("[GUI] Failed to parse GUI versions for comparison") return - logging.debug(f"[GUI] GUI version check: Installed: v{installed_gui_version} | Latest: {latest_gui_version}") + logging.info(f"[GUI] GUI version check: Installed: v{installed_gui_version} | Latest: {latest_gui_version}") # Compare versions if installed_version_tuple < latest_version_tuple: version_label_text = "OneDriveGUI is out of date!" version_tooltip_text = f"OneDriveGUI is out of date! \n Installed: v{installed_gui_version} \n Latest: {latest_gui_version}" else: - logging.debug("[GUI] OneDriveGUI is up to date") + logging.info("[GUI] OneDriveGUI is up to date") # Store results self.gui_version_status["label_text"] = version_label_text @@ -688,8 +688,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): def autostart_monitor(self): # Auto-start sync if compatible version of OneDrive client is installed. for profile_name in global_config: - logging.debug(f"[{profile_name}] Compatible client version found: {self.profile_status_pages[profile_name].pushButton_start.isEnabled()}") - logging.debug(f"[{profile_name}] Auto-sync enabled for profile: {global_config[profile_name]['auto_sync']}") + logging.info(f"[{profile_name}] Compatible client version found: {self.profile_status_pages[profile_name].pushButton_start.isEnabled()}") + logging.info(f"[{profile_name}] Auto-sync enabled for profile: {global_config[profile_name]['auto_sync']}") if self.profile_status_pages[profile_name].pushButton_start.isEnabled() and global_config[profile_name]["auto_sync"] == "True": self.start_onedrive_monitor(profile_name) @@ -703,7 +703,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): workers[profile_name] = WorkerThread(profile_name, options) workers[profile_name].start() else: - logging.info(f"Worker for profile {profile_name} is already running. Please stop it first.") + logging.warning(f"Worker for profile {profile_name} is already running. Please stop it first.") logging.info(f"Running workers: {workers}") if "True" not in gui_settings.get("QWebEngine_login"): @@ -724,7 +724,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): try: workers[profile_name].finished.connect(lambda: self.remove_worker(profile_name)) except KeyError: - logging.debug(f"[GUI] The worker for profile {profile_name} is already stopped.") + logging.info(f"[GUI] The worker for profile {profile_name} is already stopped.") def resync_auth_dialog(self, profile_name): resync_question = QMessageBox( @@ -822,7 +822,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): """ _sync_dir = os.path.expanduser(global_config[profile]["onedrive"]["sync_dir"].strip('"')) - logging.info(data) + logging.debug(data) file_path = f"{_sync_dir}" + "/" + data["file_path"] absolute_path = QFileInfo(file_path).absolutePath().replace(" ", "%20") relative_path_display = os.path.relpath(QFileInfo(file_path).absolutePath(), _sync_dir + os.path.sep) @@ -849,7 +849,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): if file_name == item_file_name and item_incomplete: # If current file is already in the list and progress bar is not complete, update the existing item. # Otherwise skip and create a new item. - logging.info("Updating list item") + logging.debug("Updating list item") item_widget.set_progress(int(progress)) # item_widget.set_icon(file_path) @@ -912,11 +912,11 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.profile_status_pages[profile].listWidget.setItemWidget(item, item_widget) new_list_item = False - logging.info(f"List item updated for file {item_file_name}") + logging.debug(f"List item updated for file {item_file_name}") break if new_list_item: - logging.info(f"Adding new list item for file {file_name}") + logging.debug(f"Adding new list item for file {file_name}") myQCustomQWidget = TaskList() myQCustomQWidget.set_file_name(file_name) myQCustomQWidget.set_progress(int(progress)) @@ -1093,10 +1093,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): def enable_login_button(self): # Enable 'Save' button only when valid URL with login response code is provided. if "nativeclient?code=" in self.lw2.lineEdit_response_url.text(): - logging.debug(f"[GUI] Valid login response code provided. Enabling Save button.") + logging.info(f"[GUI] Valid login response code provided. Enabling Save button.") self.lw2.pushButton_login.setEnabled(True) else: - logging.debug(f"[GUI] Invalid login response code provided. Disabling Save button.") + logging.info(f"[GUI] Invalid login response code provided. Disabling Save button.") self.lw2.pushButton_login.setEnabled(False) def get_response_url(self, response_url, profile): @@ -1209,7 +1209,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): index = self.comboBox.findText(old_name) if index >= 0: self.comboBox.setItemText(index, new_name) - logging.debug(f"[MAIN_WINDOW] Updated comboBox item at index {index} from '{old_name}' to '{new_name}'.") + logging.info(f"[MAIN_WINDOW] Updated comboBox item at index {index} from '{old_name}' to '{new_name}'.") else: logging.warning(f"[MAIN_WINDOW] Profile '{old_name}' not found in comboBox.") @@ -1218,7 +1218,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.profile_status_pages[new_name] = self.profile_status_pages.pop(old_name) # Also update the profile_name attribute within the ProfileStatusPage instance self.profile_status_pages[new_name].profile_name = new_name - logging.debug(f"[MAIN_WINDOW] Updated profile_status_pages key from '{old_name}' to '{new_name}'.") + logging.info(f"[MAIN_WINDOW] Updated profile_status_pages key from '{old_name}' to '{new_name}'.") else: logging.warning(f"[MAIN_WINDOW] Profile '{old_name}' not found in profile_status_pages.") @@ -1227,9 +1227,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): workers[new_name] = workers.pop(old_name) # Also update the profile_name attribute within the WorkerThread instance workers[new_name].profile_name = new_name - logging.debug(f"[MAIN_WINDOW] Updated workers key from '{old_name}' to '{new_name}'.") + logging.info(f"[MAIN_WINDOW] Updated workers key from '{old_name}' to '{new_name}'.") else: - logging.debug(f"[MAIN_WINDOW] No worker found for profile '{old_name}'.") + logging.info(f"[MAIN_WINDOW] No worker found for profile '{old_name}'.") # Force update the UI self.comboBox.update() diff --git a/src/workers.py b/src/workers.py index af56277..7656505 100644 --- a/src/workers.py +++ b/src/workers.py @@ -51,10 +51,10 @@ class WorkerThread(QThread): self.config_file = global_config[profile]["config_file"] self.config_dir = re.search(r"(.+)/.+$", self.config_file) - logging.debug(f"[GUI] OneDrive config file: {self.config_file}") - logging.debug(f"[GUI] OneDrive config dir: {self.config_dir}") + logging.info(f"[GUI] OneDrive config file: {self.config_file}") + logging.info(f"[GUI] OneDrive config dir: {self.config_dir}") self._command = f"exec {client_bin_path} --confdir='{self.config_dir.group(1)}' --monitor -v {options}" - logging.debug(f"[GUI] Monitoring command: '{self._command}'") + logging.info(f"[GUI] Monitoring command: '{self._command}'") self.profile_name = profile def stop_worker(self): @@ -102,6 +102,7 @@ class WorkerThread(QThread): self.failed_files_count = 0 self.collecting_failed_files = False # Flag to indicate we're collecting failed file lines + self.msg = "" self.profile_status["status_message"] = "OneDrive sync is starting..." self.update_profile_status.emit(self.profile_status, self.profile_name) @@ -195,7 +196,7 @@ class WorkerThread(QThread): def read_stdout(self): stdout = self.onedrive_process.stdout.readline().strip() if stdout != "": - logging.info(f"[{self.profile_name}] " + stdout) + logging.debug(f"[{self.profile_name}] " + stdout) # Check if we have a pending error from previous line that wasn't followed by "Error Message:" if self.pending_error and "Error Message:" not in stdout: @@ -210,21 +211,29 @@ class WorkerThread(QThread): self.collecting_failed_files = False if "Calling Function: testNetwork()" in stdout: - self.profile_status["status_message"] = "Cannot connect to Microsoft OneDrive Service" + self.msg = "Testing network connection to Microsoft OneDrive Service..." + logging.warning(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif "authorise this application by" in stdout.lower() or "--reauth and re-authorise this client" in stdout: self.onedrive_process.kill() - self.profile_status["status_message"] = "OneDrive login is required" + self.msg = "OneDrive login is required." + logging.warning(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) self.update_credentials.emit(self.profile_name) elif any(msg in stdout for msg in ["Sync with Microsoft OneDrive is complete", "Total number of local file(s) added or changed"]): - self.profile_status["status_message"] = "OneDrive sync is complete" + self.msg = "OneDrive sync is complete." + logging.info(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif "Sync with Microsoft OneDrive has completed, however there are items that failed to sync" in stdout: - self.profile_status["status_message"] = "Sync completed with errors. Check the log file." + self.msg = "OneDrive sync completed with errors." + logging.warning(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif "Remaining Free Space" in stdout: @@ -259,27 +268,35 @@ class WorkerThread(QThread): self.failed_files = [] self.failed_files_count = 0 self.collecting_failed_files = False - self.profile_status["status_message"] = "Initializing the OneDrive API" + self.msg = "Initializing the OneDrive API" + logging.info(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif "Processing:" in stdout or "Number of items to download from Microsoft OneDrive" in stdout or "OneDrive Client requested to create" in stdout: items_left = re.match(r"^Processing\s([0-9]+)\sOneDrive\sitems", stdout) if items_left != None: + if self.profile_status["status_message"].startswith(f"OneDrive is processing"): + logging.info(f"[{self.profile_name}] OneDrive is processing {items_left.group(1)} items...") self.profile_status["status_message"] = f"OneDrive is processing {items_left.group(1)} items..." else: + if self.profile_status["status_message"] != "OneDrive is processing items...": + logging.info(f"[{self.profile_name}] OneDrive is processing items...") self.profile_status["status_message"] = "OneDrive is processing items..." self.update_profile_status.emit(self.profile_status, self.profile_name) elif "--resync is required" in stdout or "before using --resync" in stdout: # Ask user for resync authorization and stop the worker. - logging.warning(f"[{self.profile_name}] {str(stdout)} - Asking for resync authorization.") + self.msg = "OneDrive resync authorization is required." + logging.warning(f"[{self.profile_name}] {stdout!s} - {self.msg}") self.trigger_resync.emit(self.profile_name) elif "To delete a large volume of data use" in stdout: # Ask user for big delete authorization and stop the worker. - logging.warning(f"[{self.profile_name}] {str(stdout)} - Asking for big delete authorization.") + self.msg = "OneDrive big delete authorization is required." + logging.warning(f"[{self.profile_name}] {stdout!s} - {self.msg}") self.update_profile_status.emit(self.profile_status, self.profile_name) - self.profile_status["status_message"] = "Sync stopped due to big delete detected." + self.profile_status["status_message"] = self.msg self.trigger_big_delete.emit(self.profile_name) elif any(_ in stdout for _ in self.tasks): @@ -306,7 +323,7 @@ class WorkerThread(QThread): } # Update file transfer list - logging.info(transfer_progress_new) + logging.debug(transfer_progress_new) self.update_progress_new.emit(transfer_progress_new, self.profile_name) # Update profile status message. @@ -314,6 +331,8 @@ class WorkerThread(QThread): pass # self.profile_status["status_message"] = "OneDrive sync is complete" else: + if self.profile_status["status_message"] != "OneDrive sync in progress...": + logging.info(f"[{self.profile_name}] OneDrive sync in progress...") self.profile_status["status_message"] = "OneDrive sync in progress..." elif "% " in stdout: @@ -339,13 +358,15 @@ class WorkerThread(QThread): "timestamp": datetime.now() if transfer_complete else None, } - logging.info(transfer_progress_new) + logging.debug(transfer_progress_new) self.update_progress_new.emit(transfer_progress_new, self.profile_name) if transfer_complete: pass # self.profile_status["status_message"] = "OneDrive sync is complete" else: + if self.profile_status["status_message"] != "OneDrive sync in progress...": + logging.info(f"[{self.profile_name}] OneDrive sync in progress...") self.profile_status["status_message"] = "OneDrive sync in progress..." self.update_profile_status.emit(self.profile_status, self.profile_name) @@ -370,22 +391,21 @@ class WorkerThread(QThread): # self.update_profile_status.emit(self.profile_status, self.profile_name) elif "command not found" in stdout: - logging.error( - """Onedrive does not seem to be installed. Please install it as per instruction at - https://github.com/abraunegg/onedrive/blob/master/docs/install.md """ - ) + self.msg = "Onedrive does not seem to be installed. Please install it as per instruction at https://github.com/abraunegg/onedrive/blob/master/docs/install.md" + logging.error(f"[{self.profile_name}] {self.msg}") - self.profile_status["status_message"] = ( - 'OneDrive Client not found! Please install it.' - ) + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif "/dlang/" in stdout: - self.profile_status["status_message"] = "OneDrive client crashed. Please check logs." + self.msg = "OneDrive client crashed. Please check logs." + logging.critical(f"[{self.profile_name}] {self.msg}") + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) elif " refresh_token " in stdout or "'refresh_token'" in stdout: - self.profile_status["status_message"] = "Logon details expired. Please re-authenticate." + self.msg = "Logon details expired. Please re-authenticate." + self.profile_status["status_message"] = self.msg self.update_profile_status.emit(self.profile_status, self.profile_name) self.update_credentials.emit(self.profile_name) @@ -400,6 +420,7 @@ class WorkerThread(QThread): else: full_error_message = self.pending_error self.pending_error = None # Clear pending error + logging.error(f"[{self.profile_name}] {full_error_message}") self._emit_error_status(full_error_message) elif "ERROR:" in stdout: @@ -438,6 +459,7 @@ class WorkerThread(QThread): error_message = f"Configuration error: Unknown key '{invalid_key}'. Please check your config file and remove invalid options." else: error_message = "Configuration error: Unknown key in config file. Please check your configuration." + logging.error(f"[{self.profile_name}] {error_message}") self._emit_error_status(error_message) else: @@ -465,14 +487,14 @@ class MaintenanceWorker(QThread): self.config_file = global_config[self.profile]["config_file"] self.config_dir = re.search(r"(.+)/.+$", self.config_file).group(1) - logging.debug(f"[GUI] OneDrive config file: {self.config_file}") - logging.debug(f"[GUI] OneDrive config dir: {self.config_dir}") + logging.info(f"[GUI] OneDrive config file: {self.config_file}") + logging.info(f"[GUI] OneDrive config dir: {self.config_dir}") self._command = f"exec {client_bin_path} --confdir='{self.config_dir}' {options}" - logging.debug(f"[GUI] Maintenance command: '{self._command}'") + logging.info(f"[GUI] Maintenance command: '{self._command}'") def run(self): - logging.debug(f"[GUI] Starting Maintenance Worker") + logging.info(f"[GUI] Starting Maintenance Worker") self.onedrive_maintainer = subprocess.Popen( self._command, stdout=subprocess.PIPE, @@ -483,7 +505,7 @@ class MaintenanceWorker(QThread): if "--auth-response" in self.options: # exec onedrive --confdir="{config_dir}" --auth-response "{response_url}" - logging.info(f"[GUI] Trying login...") + logging.debug(f"[GUI] Trying login...") self.login_response = "success" while self.onedrive_maintainer.poll() is None: @@ -585,7 +607,7 @@ class MaintenanceWorker(QThread): pass elif "Library Name:" in stdout: library_name = re.match(r"^.+\:\s+(.+)$", stdout).group(1) - logging.info(f"[MaintenanceWorker][{self.profile}] Library Name: {library_name}") + logging.debug(f"[MaintenanceWorker][{self.profile}] Library Name: {library_name}") self.library_ids_dict[library_name] = "" @@ -593,7 +615,7 @@ class MaintenanceWorker(QThread): last_key = list(self.library_ids_dict.keys())[-1] library_id = re.match(r"^.+\:\s+(.+)$", stdout).group(1) - logging.info(f"[MaintenanceWorker][{self.profile}] Library ID: {library_id}") + logging.debug(f"[MaintenanceWorker][{self.profile}] Library ID: {library_id}") self.library_ids_dict[last_key] = library_id @@ -614,9 +636,9 @@ class MaintenanceWorker(QThread): elif "Shared Folder:" in stdout: folder_name = re.match(r"^.+:\s+(.+)$", stdout).group(1) self.business_folder_list.append(folder_name) - logging.info(f"[MaintenanceWorker][{self.profile}] Retrieved Business Shared Folder: {folder_name}") + logging.debug(f"[MaintenanceWorker][{self.profile}] Retrieved Business Shared Folder: {folder_name}") else: - logging.info(f"[MaintenanceWorker][{self.profile}] " + stdout.strip()) + logging.debug(f"[MaintenanceWorker][{self.profile}] " + stdout.strip()) if self.onedrive_maintainer.stderr: stderr = self.onedrive_maintainer.stderr.readline() @@ -635,9 +657,9 @@ class MaintenanceWorker(QThread): elif " * " in stdout: site_name = re.match(r"^\s\*\s(.+)", stdout).group(1) self.sharepoint_site_list.append(site_name) - logging.info(f"[MaintenanceWorker][{self.profile}] Retrieved SharePoint Site: {site_name}") + logging.debug(f"[MaintenanceWorker][{self.profile}] Retrieved SharePoint Site: {site_name}") else: - logging.info(f"[MaintenanceWorker][{self.profile}] " + stdout.strip()) + logging.debug(f"[MaintenanceWorker][{self.profile}] " + stdout.strip()) if self.onedrive_maintainer.stderr: stderr = self.onedrive_maintainer.stderr.readline()