diff --git a/cura/CuraActions.py b/cura/CuraActions.py index 835c46bba81..e5615ba6cbb 100644 --- a/cura/CuraActions.py +++ b/cura/CuraActions.py @@ -31,6 +31,10 @@ from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode +from UM.Resources import Resources +import os +import re +import shutil class CuraActions(QObject): def __init__(self, parent: QObject = None) -> None: @@ -280,3 +284,62 @@ def paste(self) -> None: def _openUrl(self, url: QUrl) -> None: QDesktopServices.openUrl(url) + + @pyqtSlot(bool) + def clearConfigurationCache(self, clear_all_versions: bool = False) -> None: + """Clear the configuration cache folder. + + :param clear_all_versions: If True, also clear cache from previous Cura versions. + """ + from UM.Message import Message + from UM.i18n import i18nCatalog + catalog = i18nCatalog("cura") + + try: + # Get the current version's data storage path + current_data_path = Resources.getDataStoragePath() + cache_path = os.path.join(current_data_path, "cache") + + # Clear current version's cache + if os.path.exists(cache_path): + shutil.rmtree(cache_path) + Logger.log("i", "Cleared cache at: %s", cache_path) + + # Clear previous versions' caches if requested + if clear_all_versions: + # Get the parent directory containing all version folders + data_storage_root = os.path.dirname(current_data_path) + if os.path.exists(data_storage_root): + # Iterate through all directories in the data storage root + version_pattern = re.compile(r'^\d+\.\d+$') # Pattern to match version folders like "5.0", "5.1" + + for folder_name in os.listdir(data_storage_root): + # Only process folders that look like version numbers + if not version_pattern.match(folder_name): + continue + + folder_path = os.path.join(data_storage_root, folder_name) + # Skip if it's not a directory or if it's the current version + if not os.path.isdir(folder_path) or folder_path == current_data_path: + continue + # Check if it looks like a version folder (has a cache subdirectory) + version_cache_path = os.path.join(folder_path, "cache") + if os.path.exists(version_cache_path): + shutil.rmtree(version_cache_path) + Logger.log("i", "Cleared cache at: %s", version_cache_path) + + # Show success message + message_text = catalog.i18nc("@info:status", "Configuration cache cleared successfully.") + if clear_all_versions: + message_text = catalog.i18nc("@info:status", "Configuration cache cleared successfully for all versions.") + message = Message(message_text, lifetime=5, title=catalog.i18nc("@info:title", "Cache Cleared")) + message.show() + + except Exception as e: + Logger.log("e", "Failed to clear configuration cache: %s", str(e)) + error_message = Message( + catalog.i18nc("@info:status", "Failed to clear configuration cache: {0}").format(str(e)), + lifetime=0, + title=catalog.i18nc("@info:title", "Error") + ) + error_message.show() diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index b12699a100e..84c1686e344 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -62,6 +62,7 @@ Item property alias showProfileFolder: showProfileFolderAction property alias openCuraLogFile: openCuraLogFileAction + property alias clearConfigurationCache: clearConfigurationCacheAction property alias documentation: documentationAction property alias openSponsershipPage: openSponsershipPageAction property alias reportBug: reportBugAction @@ -543,6 +544,12 @@ Item text: catalog.i18nc("@action:inmenu menubar:help","Open Cura Log File") } + Action + { + id: clearConfigurationCacheAction + text: catalog.i18nc("@action:inmenu menubar:help", "Clear Configuration Cache...") + } + Action { diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index bb3e56eafa9..02fe5448d12 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -807,6 +807,75 @@ UM.MainWindow } } + UM.Dialog + { + id: clearConfigurationCacheDialog + + title: catalog.i18nc("@title:window", "Clear Configuration Cache") + width: UM.Theme.getSize("small_popup_dialog").width + height: UM.Theme.getSize("small_popup_dialog").height + backgroundColor: UM.Theme.getColor("main_background") + + maximumHeight: height + maximumWidth: width + minimumHeight: maximumHeight + minimumWidth: maximumWidth + + modality: Qt.ApplicationModal + + Column + { + anchors.fill: parent + spacing: UM.Theme.getSize("default_margin").height + + UM.Label + { + width: parent.width + text: catalog.i18nc("@info:question", "Are you sure you want to clear the configuration cache? This will remove cached data and may improve performance if you're experiencing issues.") + wrapMode: Text.WordWrap + } + + UM.CheckBox + { + id: clearAllVersionsCheckBox + text: catalog.i18nc("@option:check", "Also clear cache from previous Cura versions") + } + } + + rightButtons: + [ + Cura.SecondaryButton + { + text: catalog.i18nc("@action:button", "Cancel") + onClicked: clearConfigurationCacheDialog.reject() + }, + Cura.PrimaryButton + { + text: catalog.i18nc("@action:button", "Clear Cache") + onClicked: clearConfigurationCacheDialog.accept() + } + ] + + onAccepted: + { + CuraActions.clearConfigurationCache(clearAllVersionsCheckBox.checked) + clearConfigurationCacheDialog.hide() + } + onRejected: + { + clearConfigurationCacheDialog.hide() + } + } + + Connections + { + target: Cura.Actions.clearConfigurationCache + function onTriggered() + { + clearConfigurationCacheDialog.visible = true + } + } + Component { id: discardOrKeepProfileChangesDialogComponent diff --git a/resources/qml/Menus/HelpMenu.qml b/resources/qml/Menus/HelpMenu.qml index db189a9ddd0..ca609d892f4 100644 --- a/resources/qml/Menus/HelpMenu.qml +++ b/resources/qml/Menus/HelpMenu.qml @@ -15,6 +15,7 @@ Cura.Menu Cura.MenuItem { action: Cura.Actions.showProfileFolder } Cura.MenuItem { action: Cura.Actions.openCuraLogFile } + Cura.MenuItem { action: Cura.Actions.clearConfigurationCache } Cura.MenuSeparator { } Cura.MenuItem { action: Cura.Actions.documentation } Cura.MenuItem { action: Cura.Actions.reportBug }