From 6767ab5ae03ec70d1dadc87b09ce802fdf23fab2 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Fri, 17 Jul 2026 16:25:10 +0800 Subject: [PATCH] Make the Latest and installed version labels dynamic --- src/slic3r/GUI/NetworkPluginDialog.cpp | 11 ++++++--- src/slic3r/GUI/Preferences.cpp | 6 +++-- src/slic3r/Utils/BBLNetworkPlugin.cpp | 18 ++++++++++++++ src/slic3r/Utils/bambu_networking.hpp | 2 ++ tests/slic3rutils/test_network_versions.cpp | 26 ++++++++++++++++++--- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/NetworkPluginDialog.cpp b/src/slic3r/GUI/NetworkPluginDialog.cpp index eeccd88006..133ae4f2de 100644 --- a/src/slic3r/GUI/NetworkPluginDialog.cpp +++ b/src/slic3r/GUI/NetworkPluginDialog.cpp @@ -219,9 +219,14 @@ void NetworkPluginDownloadDialog::setup_version_selector() label = wxString::FromUTF8("\xE2\x94\x94 ") + wxString::FromUTF8(ver.display_name); } else { label = wxString::FromUTF8(ver.display_name); - if (ver.is_latest) { - label += wxString(" ") + _L("(Latest)"); - } + } + // Same labeling as the Preferences selector: "(Latest)" = highest listed + // version, "(installed)" = library already on disk; both can apply. + if (ver.is_latest) { + label += wxString(" ") + _L("(Latest)"); + } + if (ver.is_installed) { + label += wxString(" ") + _L("(installed)"); } m_version_combo->Append(label); } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 51c0d6629c..c8d520f2f2 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1270,10 +1270,12 @@ wxBoxSizer *PreferencesDialog::create_item_network_plugin_version(wxString title label = wxString::FromUTF8(ver.display_name); } + // "(Latest)" marks the highest listed version; "(installed)" marks versions + // whose library is already on disk. One entry can carry both. if (ver.is_latest) { label += " " + _L("(Latest)"); - } else if (ver.is_discovered && ver.suffix.empty()) { - // A same-series build found on disk (usually installed by the OTA update). + } + if (ver.is_installed) { label += " " + _L("(installed)"); } m_network_version_combo->Append(label); diff --git a/src/slic3r/Utils/BBLNetworkPlugin.cpp b/src/slic3r/Utils/BBLNetworkPlugin.cpp index cf8c00ccdb..d4b77851df 100644 --- a/src/slic3r/Utils/BBLNetworkPlugin.cpp +++ b/src/slic3r/Utils/BBLNetworkPlugin.cpp @@ -885,6 +885,24 @@ std::vector get_all_available_versions() NetworkLibraryVersionInfo::from_discovered(full, full, "")); } + // Final pass: record what is actually present on disk, and put the "(Latest)" + // label on the truly highest full version in the list - an OTA-installed build + // can be newer than the newest whitelisted entry. get_latest_network_version() + // intentionally keeps returning the static whitelist default, which drives the + // download and update-check decisions. + size_t highest = result.size(); + for (size_t i = 0; i < result.size(); ++i) { + auto& info = result[i]; + info.is_installed = info.is_discovered || + BBLNetworkPlugin::versioned_library_exists(info.version); + info.is_latest = false; + if (info.suffix.empty() && + (highest == result.size() || info.version > result[highest].version)) + highest = i; + } + if (highest < result.size()) + result[highest].is_latest = true; + return result; } diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index 7ae94841ab..a7d40f171f 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -386,6 +386,8 @@ struct NetworkLibraryVersionInfo { bool is_latest; std::string warning; bool is_discovered; + // Whether the versioned library file for this entry is present on disk. + bool is_installed = false; static NetworkLibraryVersionInfo from_static(const NetworkLibraryVersion& v) { return { diff --git a/tests/slic3rutils/test_network_versions.cpp b/tests/slic3rutils/test_network_versions.cpp index 7df2a98864..781214cba3 100644 --- a/tests/slic3rutils/test_network_versions.cpp +++ b/tests/slic3rutils/test_network_versions.cpp @@ -90,10 +90,21 @@ TEST_CASE_METHOD(PluginFolderFixture, "Same-series OTA plugin versions are surfa const auto& ota = versions[ota_pos]; REQUIRE(ota.is_discovered); REQUIRE(ota.suffix.empty()); - REQUIRE_FALSE(ota.is_latest); - // The static whitelist entry keeps its "latest" role. - REQUIRE(versions[latest_pos].is_latest); + // "(Latest)" is dynamic: the OTA build is the highest listed version, so it takes + // the label from the static whitelist entry - and it is also marked installed. + REQUIRE(ota.is_latest); + REQUIRE(ota.is_installed); + REQUIRE_FALSE(versions[latest_pos].is_latest); + REQUIRE_FALSE(versions[latest_pos].is_installed); + + // A whitelisted version whose library exists on disk is marked installed. + for (const auto& info : versions) { + if (info.version == "02.03.00.62") + REQUIRE(info.is_installed); + } + + // The static default used for download and update-check decisions is unchanged. REQUIRE(std::string(get_latest_network_version()) == "02.08.01.52"); } @@ -109,4 +120,13 @@ TEST_CASE_METHOD(PluginFolderFixture, "Legacy series never adopts discovered bui REQUIRE(count_version(versions, legacy_sibling) == 0); REQUIRE(count_version(versions, legacy) == 1); + + // With nothing else on disk, the highest whitelisted version holds "(Latest)" + // even though its library is not installed. + for (const auto& info : versions) { + if (info.version == "02.08.01.52") { + REQUIRE(info.is_latest); + REQUIRE_FALSE(info.is_installed); + } + } }