Sync from development - prepare for v0.1.0.1

This commit is contained in:
Omni
2025-09-14 20:18:33 +01:00
parent c2803e854e
commit 2e4cdc2854
51 changed files with 378 additions and 314 deletions

View File

@@ -1,5 +1,30 @@
# Jackify Changelog
## v0.1.0.1 - Engine Update and Stability Improvements
**Release Date:** September 14, 2025
### Engine Updates
- **jackify-engine v0.3.13**: Major stability and resource management improvements
- **Wine Prefix Cleanup**: Automatic cleanup of ~281MB Wine prefix directories after each modlist installation
- **Manual Download Handling**: Fixed installation crashes when manual downloads are required
- **Enhanced Error Messaging**: Detailed mod information for failed downloads (Nexus ModID/FileID, Google Drive, HTTP sources)
- **Resource Settings Compliance**: Fixed resource settings not being respected during VFS and Installer operations
- **VFS Crash Prevention**: Fixed KeyNotFoundException crashes during "Priming VFS" phase with missing archives
- **Creation Club File Handling**: Fixed incorrect re-download attempts for Creation Club files
- **BSA Extraction Fix**: Fixed DirectoryNotFoundException during BSA building operations
### Improvements
- **Disk Space Management**: No more accumulation of Wine prefix directories consuming hundreds of MB per installation
- **Clean Error Handling**: Manual download requirements now show clear summary instead of stack traces
- **Better Resource Control**: Users can now properly control CPU usage during installation via resource_settings.json
### Bug Fixes
- **Download System**: Fixed GoogleDrive and MEGA download regressions
- **Configuration Integration**: MEGA tokens properly stored in Jackify's config directory structure
- **Installation Reliability**: Enhanced error handling prevents crashes with missing or corrupted archives
---
## v0.1.0 - First Public Release
**Release Date:** September 11, 2025

View File

@@ -5,4 +5,4 @@ This package provides both CLI and GUI interfaces for managing
Wabbajack modlists natively on Linux systems.
"""
__version__ = "0.1.0"
__version__ = "0.1.0.1"

View File

@@ -1400,8 +1400,9 @@ class ModlistInstallCLI:
# Remove status indicators to get clean line
clean_line = line.replace('[DOWN]', '').replace('[NSFW]', '').strip()
# Split on ' - ' to get: [Modlist Name, Game, Sizes, MachineURL]
parts = clean_line.split(' - ')
# Split from right to handle modlist names with dashes
# Format: "NAME - GAME - SIZES - MACHINE_URL"
parts = clean_line.rsplit(' - ', 3) # Split from right, max 3 splits = 4 parts
if len(parts) != 4:
continue # Skip malformed lines

View File

@@ -213,11 +213,14 @@ class ConfigHandler:
def get_api_key(self):
"""
Retrieve and decode the saved Nexus API key
Always reads fresh from disk to pick up changes from other instances
Returns:
str: Decoded API key or None if not saved
"""
try:
# Reload config from disk to pick up changes from Settings dialog
self._load_config()
encoded_key = self.settings.get("nexus_api_key")
if encoded_key:
# Decode the base64 encoded key
@@ -231,10 +234,13 @@ class ConfigHandler:
def has_saved_api_key(self):
"""
Check if an API key is saved in configuration
Always reads fresh from disk to pick up changes from other instances
Returns:
bool: True if API key exists, False otherwise
"""
# Reload config from disk to pick up changes from Settings dialog
self._load_config()
return self.settings.get("nexus_api_key") is not None
def clear_api_key(self):

View File

@@ -1117,6 +1117,7 @@ class ModlistHandler:
("grid-hero.png", f"{appid}_hero.png"),
("grid-logo.png", f"{appid}_logo.png"),
("grid-tall.png", f"{appid}.png"),
("grid-tall.png", f"{appid}p.png"),
]
for src_name, dest_name in images:

View File

@@ -1020,8 +1020,9 @@ class ModlistInstallCLI:
# Remove status indicators to get clean line
clean_line = line.replace('[DOWN]', '').replace('[NSFW]', '').strip()
# Split on ' - ' to get: [Modlist Name, Game, Sizes, MachineURL]
parts = clean_line.split(' - ')
# Split from right to handle modlist names with dashes
# Format: "NAME - GAME - SIZES - MACHINE_URL"
parts = clean_line.rsplit(' - ', 3) # Split from right, max 3 splits = 4 parts
if len(parts) != 4:
continue # Skip malformed lines

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,7 +7,7 @@
"targets": {
".NETCoreApp,Version=v8.0": {},
".NETCoreApp,Version=v8.0/linux-x64": {
"jackify-engine/0.3.12": {
"jackify-engine/0.3.13": {
"dependencies": {
"Markdig": "0.40.0",
"Microsoft.Extensions.Configuration.Json": "9.0.1",
@@ -22,16 +22,16 @@
"SixLabors.ImageSharp": "3.1.6",
"System.CommandLine": "2.0.0-beta4.22272.1",
"System.CommandLine.NamingConventionBinder": "2.0.0-beta4.22272.1",
"Wabbajack.CLI.Builder": "0.3.12",
"Wabbajack.Downloaders.Bethesda": "0.3.12",
"Wabbajack.Downloaders.Dispatcher": "0.3.12",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Networking.Discord": "0.3.12",
"Wabbajack.Networking.GitHub": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12",
"Wabbajack.Server.Lib": "0.3.12",
"Wabbajack.Services.OSIntegrated": "0.3.12",
"Wabbajack.VFS": "0.3.12",
"Wabbajack.CLI.Builder": "0.3.13",
"Wabbajack.Downloaders.Bethesda": "0.3.13",
"Wabbajack.Downloaders.Dispatcher": "0.3.13",
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Networking.Discord": "0.3.13",
"Wabbajack.Networking.GitHub": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13",
"Wabbajack.Server.Lib": "0.3.13",
"Wabbajack.Services.OSIntegrated": "0.3.13",
"Wabbajack.VFS": "0.3.13",
"MegaApiClient": "1.0.0.0",
"runtimepack.Microsoft.NETCore.App.Runtime.linux-x64": "8.0.19"
},
@@ -1781,7 +1781,7 @@
}
}
},
"Wabbajack.CLI.Builder/0.3.12": {
"Wabbajack.CLI.Builder/0.3.13": {
"dependencies": {
"Microsoft.Extensions.Configuration.Json": "9.0.1",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
@@ -1791,109 +1791,109 @@
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"System.CommandLine": "2.0.0-beta4.22272.1",
"System.CommandLine.NamingConventionBinder": "2.0.0-beta4.22272.1",
"Wabbajack.Paths": "0.3.12"
"Wabbajack.Paths": "0.3.13"
},
"runtime": {
"Wabbajack.CLI.Builder.dll": {}
}
},
"Wabbajack.Common/0.3.12": {
"Wabbajack.Common/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"System.Reactive": "6.0.1",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Common.dll": {}
}
},
"Wabbajack.Compiler/0.3.12": {
"Wabbajack.Compiler/0.3.13": {
"dependencies": {
"F23.StringSimilarity": "6.0.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Downloaders.Dispatcher": "0.3.12",
"Wabbajack.Installer": "0.3.12",
"Wabbajack.VFS": "0.3.12",
"Wabbajack.Downloaders.Dispatcher": "0.3.13",
"Wabbajack.Installer": "0.3.13",
"Wabbajack.VFS": "0.3.13",
"ini-parser-netstandard": "2.5.2"
},
"runtime": {
"Wabbajack.Compiler.dll": {}
}
},
"Wabbajack.Compression.BSA/0.3.12": {
"Wabbajack.Compression.BSA/0.3.13": {
"dependencies": {
"K4os.Compression.LZ4.Streams": "1.3.8",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"SharpZipLib": "1.4.2",
"Wabbajack.Common": "0.3.12",
"Wabbajack.DTOs": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.DTOs": "0.3.13"
},
"runtime": {
"Wabbajack.Compression.BSA.dll": {}
}
},
"Wabbajack.Compression.Zip/0.3.12": {
"Wabbajack.Compression.Zip/0.3.13": {
"dependencies": {
"Wabbajack.IO.Async": "0.3.12"
"Wabbajack.IO.Async": "0.3.13"
},
"runtime": {
"Wabbajack.Compression.Zip.dll": {}
}
},
"Wabbajack.Configuration/0.3.12": {
"Wabbajack.Configuration/0.3.13": {
"runtime": {
"Wabbajack.Configuration.dll": {}
}
},
"Wabbajack.Downloaders.Bethesda/0.3.12": {
"Wabbajack.Downloaders.Bethesda/0.3.13": {
"dependencies": {
"LibAES-CTR": "1.1.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"SharpZipLib": "1.4.2",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.BethesdaNet": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.BethesdaNet": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Bethesda.dll": {}
}
},
"Wabbajack.Downloaders.Dispatcher/0.3.12": {
"Wabbajack.Downloaders.Dispatcher/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Downloaders.Bethesda": "0.3.12",
"Wabbajack.Downloaders.GameFile": "0.3.12",
"Wabbajack.Downloaders.GoogleDrive": "0.3.12",
"Wabbajack.Downloaders.Http": "0.3.12",
"Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Downloaders.Manual": "0.3.12",
"Wabbajack.Downloaders.MediaFire": "0.3.12",
"Wabbajack.Downloaders.Mega": "0.3.12",
"Wabbajack.Downloaders.ModDB": "0.3.12",
"Wabbajack.Downloaders.Nexus": "0.3.12",
"Wabbajack.Downloaders.VerificationCache": "0.3.12",
"Wabbajack.Downloaders.WabbajackCDN": "0.3.12",
"Wabbajack.Networking.WabbajackClientApi": "0.3.12"
"Wabbajack.Downloaders.Bethesda": "0.3.13",
"Wabbajack.Downloaders.GameFile": "0.3.13",
"Wabbajack.Downloaders.GoogleDrive": "0.3.13",
"Wabbajack.Downloaders.Http": "0.3.13",
"Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Downloaders.Manual": "0.3.13",
"Wabbajack.Downloaders.MediaFire": "0.3.13",
"Wabbajack.Downloaders.Mega": "0.3.13",
"Wabbajack.Downloaders.ModDB": "0.3.13",
"Wabbajack.Downloaders.Nexus": "0.3.13",
"Wabbajack.Downloaders.VerificationCache": "0.3.13",
"Wabbajack.Downloaders.WabbajackCDN": "0.3.13",
"Wabbajack.Networking.WabbajackClientApi": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Dispatcher.dll": {}
}
},
"Wabbajack.Downloaders.GameFile/0.3.12": {
"Wabbajack.Downloaders.GameFile/0.3.13": {
"dependencies": {
"GameFinder.StoreHandlers.EADesktop": "4.5.0",
"GameFinder.StoreHandlers.EGS": "4.5.0",
@@ -1903,360 +1903,360 @@
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.VFS": "0.3.12"
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.VFS": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.GameFile.dll": {}
}
},
"Wabbajack.Downloaders.GoogleDrive/0.3.12": {
"Wabbajack.Downloaders.GoogleDrive/0.3.13": {
"dependencies": {
"HtmlAgilityPack": "1.11.72",
"Microsoft.AspNetCore.Http.Extensions": "2.3.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.GoogleDrive.dll": {}
}
},
"Wabbajack.Downloaders.Http/0.3.12": {
"Wabbajack.Downloaders.Http/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.BethesdaNet": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.BethesdaNet": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Http.dll": {}
}
},
"Wabbajack.Downloaders.Interfaces/0.3.12": {
"Wabbajack.Downloaders.Interfaces/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Wabbajack.Compression.Zip": "0.3.12",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.Compression.Zip": "0.3.13",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Interfaces.dll": {}
}
},
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.12": {
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.13": {
"dependencies": {
"F23.StringSimilarity": "6.0.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.IPS4OAuth2Downloader.dll": {}
}
},
"Wabbajack.Downloaders.Manual/0.3.12": {
"Wabbajack.Downloaders.Manual/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Manual.dll": {}
}
},
"Wabbajack.Downloaders.MediaFire/0.3.12": {
"Wabbajack.Downloaders.MediaFire/0.3.13": {
"dependencies": {
"HtmlAgilityPack": "1.11.72",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.MediaFire.dll": {}
}
},
"Wabbajack.Downloaders.Mega/0.3.12": {
"Wabbajack.Downloaders.Mega/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Mega.dll": {}
}
},
"Wabbajack.Downloaders.ModDB/0.3.12": {
"Wabbajack.Downloaders.ModDB/0.3.13": {
"dependencies": {
"HtmlAgilityPack": "1.11.72",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.ModDB.dll": {}
}
},
"Wabbajack.Downloaders.Nexus/0.3.12": {
"Wabbajack.Downloaders.Nexus/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12",
"Wabbajack.Networking.NexusApi": "0.3.12",
"Wabbajack.Paths": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13",
"Wabbajack.Networking.NexusApi": "0.3.13",
"Wabbajack.Paths": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.Nexus.dll": {}
}
},
"Wabbajack.Downloaders.VerificationCache/0.3.12": {
"Wabbajack.Downloaders.VerificationCache/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Stub.System.Data.SQLite.Core.NetStandard": "1.0.119",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.VerificationCache.dll": {}
}
},
"Wabbajack.Downloaders.WabbajackCDN/0.3.12": {
"Wabbajack.Downloaders.WabbajackCDN/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Microsoft.Toolkit.HighPerformance": "7.1.2",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.RateLimiter": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.RateLimiter": "0.3.13"
},
"runtime": {
"Wabbajack.Downloaders.WabbajackCDN.dll": {}
}
},
"Wabbajack.DTOs/0.3.12": {
"Wabbajack.DTOs/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Paths": "0.3.12"
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Paths": "0.3.13"
},
"runtime": {
"Wabbajack.DTOs.dll": {}
}
},
"Wabbajack.FileExtractor/0.3.12": {
"Wabbajack.FileExtractor/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"OMODFramework": "3.0.1",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Compression.BSA": "0.3.12",
"Wabbajack.Hashing.PHash": "0.3.12",
"Wabbajack.Paths": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Compression.BSA": "0.3.13",
"Wabbajack.Hashing.PHash": "0.3.13",
"Wabbajack.Paths": "0.3.13"
},
"runtime": {
"Wabbajack.FileExtractor.dll": {}
}
},
"Wabbajack.Hashing.PHash/0.3.12": {
"Wabbajack.Hashing.PHash/0.3.13": {
"dependencies": {
"BCnEncoder.Net.ImageSharp": "1.1.1",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Shipwreck.Phash": "0.5.0",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Common": "0.3.12",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Paths": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Paths": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Hashing.PHash.dll": {}
}
},
"Wabbajack.Hashing.xxHash64/0.3.12": {
"Wabbajack.Hashing.xxHash64/0.3.13": {
"dependencies": {
"Wabbajack.Paths": "0.3.12",
"Wabbajack.RateLimiter": "0.3.12"
"Wabbajack.Paths": "0.3.13",
"Wabbajack.RateLimiter": "0.3.13"
},
"runtime": {
"Wabbajack.Hashing.xxHash64.dll": {}
}
},
"Wabbajack.Installer/0.3.12": {
"Wabbajack.Installer/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"Octopus.Octodiff": "2.0.548",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Downloaders.Dispatcher": "0.3.12",
"Wabbajack.Downloaders.GameFile": "0.3.12",
"Wabbajack.FileExtractor": "0.3.12",
"Wabbajack.Networking.WabbajackClientApi": "0.3.12",
"Wabbajack.Paths": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12",
"Wabbajack.VFS": "0.3.12",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Downloaders.Dispatcher": "0.3.13",
"Wabbajack.Downloaders.GameFile": "0.3.13",
"Wabbajack.FileExtractor": "0.3.13",
"Wabbajack.Networking.WabbajackClientApi": "0.3.13",
"Wabbajack.Paths": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13",
"Wabbajack.VFS": "0.3.13",
"ini-parser-netstandard": "2.5.2"
},
"runtime": {
"Wabbajack.Installer.dll": {}
}
},
"Wabbajack.IO.Async/0.3.12": {
"Wabbajack.IO.Async/0.3.13": {
"runtime": {
"Wabbajack.IO.Async.dll": {}
}
},
"Wabbajack.Networking.BethesdaNet/0.3.12": {
"Wabbajack.Networking.BethesdaNet/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.BethesdaNet.dll": {}
}
},
"Wabbajack.Networking.Discord/0.3.12": {
"Wabbajack.Networking.Discord/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.Discord.dll": {}
}
},
"Wabbajack.Networking.GitHub/0.3.12": {
"Wabbajack.Networking.GitHub/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Octokit": "14.0.0",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.GitHub.dll": {}
}
},
"Wabbajack.Networking.Http/0.3.12": {
"Wabbajack.Networking.Http/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Http": "9.0.1",
"Microsoft.Extensions.Logging": "9.0.1",
"Wabbajack.Configuration": "0.3.12",
"Wabbajack.Downloaders.Interfaces": "0.3.12",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12",
"Wabbajack.Paths": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12"
"Wabbajack.Configuration": "0.3.13",
"Wabbajack.Downloaders.Interfaces": "0.3.13",
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13",
"Wabbajack.Paths": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.Http.dll": {}
}
},
"Wabbajack.Networking.Http.Interfaces/0.3.12": {
"Wabbajack.Networking.Http.Interfaces/0.3.13": {
"dependencies": {
"Wabbajack.Hashing.xxHash64": "0.3.12"
"Wabbajack.Hashing.xxHash64": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.Http.Interfaces.dll": {}
}
},
"Wabbajack.Networking.NexusApi/0.3.12": {
"Wabbajack.Networking.NexusApi/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Networking.Http": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12",
"Wabbajack.Networking.WabbajackClientApi": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Networking.Http": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13",
"Wabbajack.Networking.WabbajackClientApi": "0.3.13"
},
"runtime": {
"Wabbajack.Networking.NexusApi.dll": {}
}
},
"Wabbajack.Networking.WabbajackClientApi/0.3.12": {
"Wabbajack.Networking.WabbajackClientApi/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"Octokit": "14.0.0",
"Wabbajack.Common": "0.3.12",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12",
"Wabbajack.VFS.Interfaces": "0.3.12",
"Wabbajack.Common": "0.3.13",
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13",
"Wabbajack.VFS.Interfaces": "0.3.13",
"YamlDotNet": "16.3.0"
},
"runtime": {
"Wabbajack.Networking.WabbajackClientApi.dll": {}
}
},
"Wabbajack.Paths/0.3.12": {
"Wabbajack.Paths/0.3.13": {
"runtime": {
"Wabbajack.Paths.dll": {}
}
},
"Wabbajack.Paths.IO/0.3.12": {
"Wabbajack.Paths.IO/0.3.13": {
"dependencies": {
"Wabbajack.Paths": "0.3.12",
"Wabbajack.Paths": "0.3.13",
"shortid": "4.0.0"
},
"runtime": {
"Wabbajack.Paths.IO.dll": {}
}
},
"Wabbajack.RateLimiter/0.3.12": {
"Wabbajack.RateLimiter/0.3.13": {
"runtime": {
"Wabbajack.RateLimiter.dll": {}
}
},
"Wabbajack.Server.Lib/0.3.12": {
"Wabbajack.Server.Lib/0.3.13": {
"dependencies": {
"FluentFTP": "52.0.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
@@ -2264,58 +2264,58 @@
"Nettle": "3.0.0",
"Newtonsoft.Json": "13.0.3",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Common": "0.3.12",
"Wabbajack.Networking.Http.Interfaces": "0.3.12",
"Wabbajack.Services.OSIntegrated": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.Networking.Http.Interfaces": "0.3.13",
"Wabbajack.Services.OSIntegrated": "0.3.13"
},
"runtime": {
"Wabbajack.Server.Lib.dll": {}
}
},
"Wabbajack.Services.OSIntegrated/0.3.12": {
"Wabbajack.Services.OSIntegrated/0.3.13": {
"dependencies": {
"DeviceId": "6.8.0",
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Newtonsoft.Json": "13.0.3",
"SixLabors.ImageSharp": "3.1.6",
"Wabbajack.Compiler": "0.3.12",
"Wabbajack.Downloaders.Dispatcher": "0.3.12",
"Wabbajack.Installer": "0.3.12",
"Wabbajack.Networking.BethesdaNet": "0.3.12",
"Wabbajack.Networking.Discord": "0.3.12",
"Wabbajack.VFS": "0.3.12"
"Wabbajack.Compiler": "0.3.13",
"Wabbajack.Downloaders.Dispatcher": "0.3.13",
"Wabbajack.Installer": "0.3.13",
"Wabbajack.Networking.BethesdaNet": "0.3.13",
"Wabbajack.Networking.Discord": "0.3.13",
"Wabbajack.VFS": "0.3.13"
},
"runtime": {
"Wabbajack.Services.OSIntegrated.dll": {}
}
},
"Wabbajack.VFS/0.3.12": {
"Wabbajack.VFS/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
"SixLabors.ImageSharp": "3.1.6",
"System.Data.SQLite.Core": "1.0.119",
"Wabbajack.Common": "0.3.12",
"Wabbajack.FileExtractor": "0.3.12",
"Wabbajack.Hashing.PHash": "0.3.12",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Paths": "0.3.12",
"Wabbajack.Paths.IO": "0.3.12",
"Wabbajack.VFS.Interfaces": "0.3.12"
"Wabbajack.Common": "0.3.13",
"Wabbajack.FileExtractor": "0.3.13",
"Wabbajack.Hashing.PHash": "0.3.13",
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Paths": "0.3.13",
"Wabbajack.Paths.IO": "0.3.13",
"Wabbajack.VFS.Interfaces": "0.3.13"
},
"runtime": {
"Wabbajack.VFS.dll": {}
}
},
"Wabbajack.VFS.Interfaces/0.3.12": {
"Wabbajack.VFS.Interfaces/0.3.13": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.1",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
"Wabbajack.DTOs": "0.3.12",
"Wabbajack.Hashing.xxHash64": "0.3.12",
"Wabbajack.Paths": "0.3.12"
"Wabbajack.DTOs": "0.3.13",
"Wabbajack.Hashing.xxHash64": "0.3.13",
"Wabbajack.Paths": "0.3.13"
},
"runtime": {
"Wabbajack.VFS.Interfaces.dll": {}
@@ -2332,7 +2332,7 @@
}
},
"libraries": {
"jackify-engine/0.3.12": {
"jackify-engine/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
@@ -3021,202 +3021,202 @@
"path": "yamldotnet/16.3.0",
"hashPath": "yamldotnet.16.3.0.nupkg.sha512"
},
"Wabbajack.CLI.Builder/0.3.12": {
"Wabbajack.CLI.Builder/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Common/0.3.12": {
"Wabbajack.Common/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Compiler/0.3.12": {
"Wabbajack.Compiler/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Compression.BSA/0.3.12": {
"Wabbajack.Compression.BSA/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Compression.Zip/0.3.12": {
"Wabbajack.Compression.Zip/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Configuration/0.3.12": {
"Wabbajack.Configuration/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Bethesda/0.3.12": {
"Wabbajack.Downloaders.Bethesda/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Dispatcher/0.3.12": {
"Wabbajack.Downloaders.Dispatcher/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.GameFile/0.3.12": {
"Wabbajack.Downloaders.GameFile/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.GoogleDrive/0.3.12": {
"Wabbajack.Downloaders.GoogleDrive/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Http/0.3.12": {
"Wabbajack.Downloaders.Http/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Interfaces/0.3.12": {
"Wabbajack.Downloaders.Interfaces/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.12": {
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Manual/0.3.12": {
"Wabbajack.Downloaders.Manual/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.MediaFire/0.3.12": {
"Wabbajack.Downloaders.MediaFire/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Mega/0.3.12": {
"Wabbajack.Downloaders.Mega/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.ModDB/0.3.12": {
"Wabbajack.Downloaders.ModDB/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.Nexus/0.3.12": {
"Wabbajack.Downloaders.Nexus/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.VerificationCache/0.3.12": {
"Wabbajack.Downloaders.VerificationCache/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Downloaders.WabbajackCDN/0.3.12": {
"Wabbajack.Downloaders.WabbajackCDN/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.DTOs/0.3.12": {
"Wabbajack.DTOs/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.FileExtractor/0.3.12": {
"Wabbajack.FileExtractor/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Hashing.PHash/0.3.12": {
"Wabbajack.Hashing.PHash/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Hashing.xxHash64/0.3.12": {
"Wabbajack.Hashing.xxHash64/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Installer/0.3.12": {
"Wabbajack.Installer/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.IO.Async/0.3.12": {
"Wabbajack.IO.Async/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.BethesdaNet/0.3.12": {
"Wabbajack.Networking.BethesdaNet/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.Discord/0.3.12": {
"Wabbajack.Networking.Discord/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.GitHub/0.3.12": {
"Wabbajack.Networking.GitHub/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.Http/0.3.12": {
"Wabbajack.Networking.Http/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.Http.Interfaces/0.3.12": {
"Wabbajack.Networking.Http.Interfaces/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.NexusApi/0.3.12": {
"Wabbajack.Networking.NexusApi/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Networking.WabbajackClientApi/0.3.12": {
"Wabbajack.Networking.WabbajackClientApi/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Paths/0.3.12": {
"Wabbajack.Paths/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Paths.IO/0.3.12": {
"Wabbajack.Paths.IO/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.RateLimiter/0.3.12": {
"Wabbajack.RateLimiter/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Server.Lib/0.3.12": {
"Wabbajack.Server.Lib/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.Services.OSIntegrated/0.3.12": {
"Wabbajack.Services.OSIntegrated/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.VFS/0.3.12": {
"Wabbajack.VFS/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Wabbajack.VFS.Interfaces/0.3.12": {
"Wabbajack.VFS.Interfaces/0.3.13": {
"type": "project",
"serviceable": false,
"sha512": ""

Binary file not shown.

View File

@@ -181,59 +181,76 @@ class SettingsDialog(QDialog):
self.resource_edits = {}
resource_row_index = 0
for resource_row_index, (k, v) in enumerate(self.resource_settings.items(), start=1):
# Create resource label with optional inline checkbox for File Extractor
if k == "File Extractor":
# Create horizontal layout for File Extractor with inline checkbox
resource_row = QHBoxLayout()
resource_label = QLabel(f"{k}:", parent=self)
resource_row.addWidget(resource_label)
resource_row.addSpacing(10) # Add some spacing
try:
# Create resource label with optional inline checkbox for File Extractor
if k == "File Extractor":
# Create horizontal layout for File Extractor with inline checkbox
resource_row = QHBoxLayout()
resource_label = QLabel(f"{k}:", parent=self)
resource_row.addWidget(resource_label)
resource_row.addSpacing(10) # Add some spacing
multithreading_checkbox = QCheckBox("Multithreading (Experimental)")
multithreading_checkbox.setChecked(v.get('_7zzMultiThread', 'off') == 'on')
multithreading_checkbox.setToolTip("Enables multithreaded file extraction using 7-Zip. May improve extraction speed on multi-core systems but could be less stable.")
multithreading_checkbox.setStyleSheet("color: #fff;")
resource_row.addWidget(multithreading_checkbox)
resource_row.addStretch() # Push checkbox to the left
# Add the horizontal layout to the grid
resource_layout.addLayout(resource_row, resource_row_index, 0)
else:
resource_layout.addWidget(QLabel(f"{k}:", parent=self), resource_row_index, 0, 1, 1, Qt.AlignLeft)
multithreading_checkbox = QCheckBox("Multithreading (Experimental)")
multithreading_checkbox.setChecked(v.get('_7zzMultiThread', 'off') == 'on')
multithreading_checkbox.setToolTip("Enables multithreaded file extraction using 7-Zip. May improve extraction speed on multi-core systems but could be less stable.")
multithreading_checkbox.setStyleSheet("color: #fff;")
resource_row.addWidget(multithreading_checkbox)
resource_row.addStretch() # Push checkbox to the left
max_tasks_spin = QSpinBox()
max_tasks_spin.setMinimum(1)
max_tasks_spin.setMaximum(128)
max_tasks_spin.setValue(v.get('MaxTasks', 16))
max_tasks_spin.setToolTip("Maximum number of concurrent tasks for this resource.")
max_tasks_spin.setFixedWidth(160)
resource_layout.addWidget(max_tasks_spin, resource_row_index, 1)
# Add the horizontal layout to the grid
resource_layout.addLayout(resource_row, resource_row_index, 0)
else:
resource_layout.addWidget(QLabel(f"{k}:", parent=self), resource_row_index, 0, 1, 1, Qt.AlignLeft)
max_tasks_spin = QSpinBox()
max_tasks_spin.setMinimum(1)
max_tasks_spin.setMaximum(128)
max_tasks_spin.setValue(v.get('MaxTasks', 16))
max_tasks_spin.setToolTip("Maximum number of concurrent tasks for this resource.")
max_tasks_spin.setFixedWidth(160)
resource_layout.addWidget(max_tasks_spin, resource_row_index, 1)
# Store the widgets (checkbox for File Extractor, None for others)
if k == "File Extractor":
self.resource_edits[k] = (multithreading_checkbox, max_tasks_spin)
else:
self.resource_edits[k] = (None, max_tasks_spin)
# Bandwidth limiter row
self.app_settings_path = os.path.expanduser("~/.config/jackify/app_settings.json")
self.app_settings = self._load_json(self.app_settings_path)
self.bandwidth_spin = QSpinBox()
self.bandwidth_spin.setMinimum(0)
self.bandwidth_spin.setMaximum(1000000)
self.bandwidth_spin.setValue(self.app_settings.get("MaxDownloadSpeedKBps", 0))
self.bandwidth_spin.setSuffix(" KB/s")
self.bandwidth_spin.setFixedWidth(160)
self.bandwidth_spin.setToolTip("Set the maximum download speed for modlist downloads. 0 = unlimited.")
bandwidth_note = QLabel("(0 = unlimited)")
bandwidth_note.setStyleSheet("color: #aaa; font-size: 10pt;")
# Create horizontal layout for bandwidth row
bandwidth_row = QHBoxLayout()
bandwidth_row.addWidget(self.bandwidth_spin)
bandwidth_row.addWidget(bandwidth_note)
bandwidth_row.addStretch() # Push to the left
# Store the widgets (checkbox for File Extractor, None for others)
if k == "File Extractor":
self.resource_edits[k] = (multithreading_checkbox, max_tasks_spin)
else:
self.resource_edits[k] = (None, max_tasks_spin)
except Exception as e:
print(f"[ERROR] Failed to create widgets for resource '{k}': {e}")
continue
resource_layout.addWidget(QLabel("Bandwidth Limit:", parent=self), resource_row_index+1, 0, 1, 1, Qt.AlignLeft)
resource_layout.addLayout(bandwidth_row, resource_row_index+1, 1)
# If no resources exist, show helpful message
if not self.resource_edits:
info_label = QLabel("Resource Limit settings will be generated once a modlist install action is performed")
info_label.setStyleSheet("color: #aaa; font-style: italic; padding: 20px; font-size: 11pt;")
info_label.setWordWrap(True)
info_label.setAlignment(Qt.AlignCenter)
info_label.setMinimumHeight(60) # Ensure enough height to prevent cutoff
resource_layout.addWidget(info_label, 1, 0, 3, 2) # Span more rows for better space
# Bandwidth limiter row (only show if Downloads resource exists)
if "Downloads" in self.resource_settings:
downloads_throughput = self.resource_settings["Downloads"].get("MaxThroughput", 0)
self.bandwidth_spin = QSpinBox()
self.bandwidth_spin.setMinimum(0)
self.bandwidth_spin.setMaximum(1000000)
self.bandwidth_spin.setValue(downloads_throughput)
self.bandwidth_spin.setSuffix(" KB/s")
self.bandwidth_spin.setFixedWidth(160)
self.bandwidth_spin.setToolTip("Set the maximum download speed for modlist downloads. 0 = unlimited.")
bandwidth_note = QLabel("(0 = unlimited)")
bandwidth_note.setStyleSheet("color: #aaa; font-size: 10pt;")
# Create horizontal layout for bandwidth row
bandwidth_row = QHBoxLayout()
bandwidth_row.addWidget(self.bandwidth_spin)
bandwidth_row.addWidget(bandwidth_note)
bandwidth_row.addStretch() # Push to the left
resource_layout.addWidget(QLabel("Bandwidth Limit:", parent=self), resource_row_index+1, 0, 1, 1, Qt.AlignLeft)
resource_layout.addLayout(bandwidth_row, resource_row_index+1, 1)
else:
self.bandwidth_spin = None # No bandwidth UI if Downloads resource doesn't exist
main_layout.addWidget(resource_group)
main_layout.addSpacing(12)
@@ -328,12 +345,13 @@ class SettingsDialog(QDialog):
main_layout.addLayout(btn_layout)
# Set tab order for accessibility
# Get the first resource's widgets
first_resource_key = list(self.resource_edits.keys())[0]
first_multithreading, first_max_tasks = self.resource_edits[first_resource_key]
# Set tab order starting with the first max tasks spinner
self.setTabOrder(first_max_tasks, self.bandwidth_spin)
# Get the first resource's widgets if any exist
if self.resource_edits:
first_resource_key = list(self.resource_edits.keys())[0]
first_multithreading, first_max_tasks = self.resource_edits[first_resource_key]
# Set tab order starting with the first max tasks spinner
self.setTabOrder(first_max_tasks, self.bandwidth_spin)
# Continue with bandwidth spinner regardless of resources
self.setTabOrder(self.bandwidth_spin, self.debug_checkbox)
self.setTabOrder(self.debug_checkbox, self.api_key_edit)
self.setTabOrder(self.api_key_edit, self.api_show_btn)
@@ -412,7 +430,7 @@ class SettingsDialog(QDialog):
if max_tasks_spin.value() > 128:
self.error_label.setText(f"Invalid value for {k}: Max Tasks must be <= 128.")
return
if self.bandwidth_spin.value() > 1000000:
if self.bandwidth_spin and self.bandwidth_spin.value() > 1000000:
self.error_label.setText("Bandwidth limit must be <= 1,000,000 KB/s.")
return
self.error_label.setText("")
@@ -428,12 +446,18 @@ class SettingsDialog(QDialog):
# Remove the setting if unchecked (don't add 'off')
resource_data.pop('_7zzMultiThread', None)
self.resource_settings[k] = resource_data
# Save bandwidth limit to Downloads resource MaxThroughput (only if bandwidth UI exists)
if self.bandwidth_spin:
if "Downloads" not in self.resource_settings:
self.resource_settings["Downloads"] = {"MaxTasks": 16} # Provide default MaxTasks
self.resource_settings["Downloads"]["MaxThroughput"] = self.bandwidth_spin.value()
# Save all resource settings (including bandwidth) in one operation
self._save_json(self.resource_settings_path, self.resource_settings)
# Save debug mode to config
self.config_handler.set('debug_mode', self.debug_checkbox.isChecked())
# Save bandwidth limit
self.app_settings["MaxDownloadSpeedKBps"] = self.bandwidth_spin.value()
self._save_json(self.app_settings_path, self.app_settings)
# Save API key
api_key = self.api_key_edit.text().strip()
self.config_handler.save_api_key(api_key)

View File

@@ -745,19 +745,22 @@ class InstallModlistScreen(QWidget):
self.console.setMinimumHeight(50) # Keep minimum height for usability
def showEvent(self, event):
"""Called when the widget becomes visible - reload saved API key only"""
"""Called when the widget becomes visible - always reload saved API key"""
super().showEvent(event)
# Reload saved API key if available and field is empty
if not self.api_key_edit.text().strip() or (self.api_key_is_obfuscated and not self.api_key_original_text.strip()):
saved_key = self.api_key_service.get_saved_api_key()
if saved_key:
self.api_key_original_text = saved_key
self.api_key_edit.setText(saved_key)
self.api_key_is_obfuscated = False # Start unobfuscated
# Set checkbox state
self.save_api_key_checkbox.setChecked(True)
# Start obfuscation timer
self.api_key_obfuscation_timer.start(3000)
# Always reload saved API key to pick up changes from Settings dialog
saved_key = self.api_key_service.get_saved_api_key()
if saved_key:
self.api_key_original_text = saved_key
self.api_key_edit.setText(saved_key)
self.api_key_is_obfuscated = False # Start unobfuscated
# Set checkbox state
self.save_api_key_checkbox.setChecked(True)
# Immediately obfuscate saved keys (don't wait 3 seconds)
self._obfuscate_api_key()
elif not self.api_key_edit.text().strip():
# Only clear if no saved key and field is empty
self.api_key_original_text = ""
self.save_api_key_checkbox.setChecked(False)
# Do NOT load saved parent directories
def _load_saved_parent_directories(self):

View File

@@ -461,19 +461,22 @@ class TuxbornInstallerScreen(QWidget):
self.console.setMinimumHeight(50) # Keep minimum height for usability
def showEvent(self, event):
"""Called when the widget becomes visible - reload saved API key and parent directories"""
"""Called when the widget becomes visible - always reload saved API key and parent directories"""
super().showEvent(event)
# Reload saved API key if available and field is empty
if not self.api_key_edit.text().strip() or (self.api_key_is_obfuscated and not self.api_key_original_text.strip()):
saved_key = self.api_key_service.get_saved_api_key()
if saved_key:
self.api_key_original_text = saved_key
self.api_key_edit.setText(saved_key)
self.api_key_is_obfuscated = False # Start unobfuscated
# Set checkbox state
self.save_api_key_checkbox.setChecked(True)
# Start obfuscation timer
self.api_key_obfuscation_timer.start(3000)
# Always reload saved API key to pick up changes from Settings dialog
saved_key = self.api_key_service.get_saved_api_key()
if saved_key:
self.api_key_original_text = saved_key
self.api_key_edit.setText(saved_key)
self.api_key_is_obfuscated = False # Start unobfuscated
# Set checkbox state
self.save_api_key_checkbox.setChecked(True)
# Immediately obfuscate saved keys (don't wait 3 seconds)
self._obfuscate_api_key()
elif not self.api_key_edit.text().strip():
# Only clear if no saved key and field is empty
self.api_key_original_text = ""
self.save_api_key_checkbox.setChecked(False)
# Load saved parent directories and pre-populate fields
self._load_saved_parent_directories()