From 977b6cd8f3d7e9fdacefa1ff0927e58aa658ebcb Mon Sep 17 00:00:00 2001 From: qu1ck Date: Sun, 28 Aug 2022 04:40:06 -0700 Subject: [PATCH] PCM: add ability to pin packages Pinned packages don't affect available update notification and will not be updated with "Update All" button. Manual update is still possible but will trigger a confirmation dialog. --- common/widgets/split_button.cpp | 7 ++ include/widgets/split_button.h | 1 + kicad/pcm/dialogs/dialog_pcm.cpp | 78 +++++++++++++++-------- kicad/pcm/dialogs/dialog_pcm.h | 6 +- kicad/pcm/dialogs/panel_package.cpp | 68 ++++++++++++++++---- kicad/pcm/dialogs/panel_package.h | 17 ++++- kicad/pcm/dialogs/panel_packages_view.cpp | 23 ++++--- kicad/pcm/dialogs/panel_packages_view.h | 13 ++-- kicad/pcm/pcm.cpp | 28 ++++++-- kicad/pcm/pcm.h | 19 ++++++ kicad/pcm/pcm_data.cpp | 25 ++++++++ kicad/pcm/pcm_data.h | 7 +- 12 files changed, 226 insertions(+), 66 deletions(-) diff --git a/common/widgets/split_button.cpp b/common/widgets/split_button.cpp index d00019d9b5..399865a158 100644 --- a/common/widgets/split_button.cpp +++ b/common/widgets/split_button.cpp @@ -88,6 +88,13 @@ void SPLIT_BUTTON::SetBitmap( const wxBitmap& aBmp ) } +void SPLIT_BUTTON::SetLabel( const wxString& aLabel ) +{ + m_label = aLabel; + Refresh(); +} + + wxMenu* SPLIT_BUTTON::GetSplitButtonMenu() { return m_pMenu; diff --git a/include/widgets/split_button.h b/include/widgets/split_button.h index 3d612bc9fa..be8d98f565 100644 --- a/include/widgets/split_button.h +++ b/include/widgets/split_button.h @@ -43,6 +43,7 @@ public: void SetBitmap( const wxBitmap& aBmp ); void SetMinSize( const wxSize& aSize ) override; void SetWidthPadding( int aPadding ); + void SetLabel( const wxString& aLabel ) override; protected: void OnKillFocus( wxFocusEvent& aEvent ); diff --git a/kicad/pcm/dialogs/dialog_pcm.cpp b/kicad/pcm/dialogs/dialog_pcm.cpp index 1a9db5d584..7ce13b7fbc 100644 --- a/kicad/pcm/dialogs/dialog_pcm.cpp +++ b/kicad/pcm/dialogs/dialog_pcm.cpp @@ -66,23 +66,19 @@ DIALOG_PCM::DIALOG_PCM( wxWindow* parent, std::shared_ptrSetBitmap( KiBitmap( BITMAPS::small_trash ) ); m_panelPending->Layout(); - m_installedPanel = new PANEL_PACKAGES_VIEW( m_panelInstalledHolder, m_pcm ); - m_panelInstalledHolder->GetSizer()->Add( m_installedPanel, 1, wxEXPAND ); - m_panelInstalledHolder->Layout(); - - for( const std::pair& entry : PACKAGE_TYPE_LIST ) + m_actionCallback = [this]( const PACKAGE_VIEW_DATA& aData, PCM_PACKAGE_ACTION aAction, + const wxString& aVersion ) { - PANEL_PACKAGES_VIEW* panel = new PANEL_PACKAGES_VIEW( m_contentNotebook, m_pcm ); - wxString label = wxGetTranslation( entry.second ); - m_contentNotebook->AddPage( panel, wxString::Format( label, 0 ) ); - m_repositoryContentPanels.insert( { entry.first, panel } ); - } + if( aAction == PPA_UPDATE && m_pcm->IsPackagePinned( aData.package.identifier ) ) + { + if( wxMessageBox( wxString::Format( _( "Are you sure you want to update pinned package " + "from version %s to %s?" ), + aData.current_version, aVersion ), + _( "Confirm update" ), wxICON_QUESTION | wxYES_NO, this ) + == wxNO ) + return; + } - m_dialogNotebook->SetPageText( 0, wxString::Format( _( "Repository (%d)" ), 0 ) ); - - m_callback = [this]( const PACKAGE_VIEW_DATA& aData, PCM_PACKAGE_ACTION aAction, - const wxString& aVersion ) - { m_gridPendingActions->Freeze(); PCM_PACKAGE_STATE new_state; @@ -125,12 +121,33 @@ DIALOG_PCM::DIALOG_PCM( wxWindow* parent, std::shared_ptrSetPackageState( aData.package.identifier, new_state ); - - for( const auto& entry : m_repositoryContentPanels ) - entry.second->SetPackageState( aData.package.identifier, new_state ); + updatePackageState( aData.package.identifier, new_state ); }; + m_pinCallback = + [this]( const wxString& aPackageId, const PCM_PACKAGE_STATE aState, const bool aPinned ) + { + m_pcm->SetPinned( aPackageId, aPinned ); + + updatePackageState( aPackageId, aState ); + }; + + m_installedPanel = new PANEL_PACKAGES_VIEW( m_panelInstalledHolder, m_pcm, m_actionCallback, + m_pinCallback ); + m_panelInstalledHolder->GetSizer()->Add( m_installedPanel, 1, wxEXPAND ); + m_panelInstalledHolder->Layout(); + + for( const std::pair& entry : PACKAGE_TYPE_LIST ) + { + PANEL_PACKAGES_VIEW* panel = new PANEL_PACKAGES_VIEW( m_contentNotebook, m_pcm, + m_actionCallback, m_pinCallback ); + wxString label = wxGetTranslation( entry.second ); + m_contentNotebook->AddPage( panel, wxString::Format( label, 0 ) ); + m_repositoryContentPanels.insert( { entry.first, panel } ); + } + + m_dialogNotebook->SetPageText( 0, wxString::Format( _( "Repository (%d)" ), 0 ) ); + setInstalledPackages(); updatePendingActionsTab(); @@ -312,7 +329,10 @@ void DIALOG_PCM::setRepositoryData( const wxString& aRepositoryId ) package_data.state = m_pcm->GetPackageState( aRepositoryId, pkg.identifier ); if( package_data.state == PPS_INSTALLED || package_data.state == PPS_UPDATE_AVAILABLE ) + { package_data.current_version = m_pcm->GetInstalledPackageVersion( pkg.identifier ); + package_data.pinned = m_pcm->IsPackagePinned( pkg.identifier ); + } if( package_data.state == PPS_UPDATE_AVAILABLE ) package_data.update_version = m_pcm->GetPackageUpdateVersion( pkg ); @@ -343,7 +363,7 @@ void DIALOG_PCM::setRepositoryData( const wxString& aRepositoryId ) { PCM_PACKAGE_TYPE type = PACKAGE_TYPE_LIST[i].first; const wxString& label = PACKAGE_TYPE_LIST[i].second; - m_repositoryContentPanels[type]->SetData( data[type], m_callback ); + m_repositoryContentPanels[type]->SetData( data[type] ); m_contentNotebook->SetPageText( i, wxString::Format( wxGetTranslation( label ), (int) data[type].size() ) ); } @@ -401,7 +421,7 @@ void DIALOG_PCM::setInstalledPackages() package_list.emplace_back( package_data ); } - m_installedPanel->SetData( package_list, m_callback ); + m_installedPanel->SetData( package_list ); m_dialogNotebook->SetPageText( 1, wxString::Format( _( "Installed (%d)" ), (int) package_list.size() ) ); @@ -489,15 +509,23 @@ void DIALOG_PCM::discardAction( int aIndex ) PCM_PACKAGE_STATE state = m_pcm->GetPackageState( action.repository_id, action.package.identifier ); - m_installedPanel->SetPackageState( action.package.identifier, state ); - - for( const auto& entry : m_repositoryContentPanels ) - entry.second->SetPackageState( action.package.identifier, state ); + updatePackageState( action.package.identifier, state ); m_pendingActions.erase( m_pendingActions.begin() + aIndex ); } +void DIALOG_PCM::updatePackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState ) +{ + bool pinned = m_pcm->IsPackagePinned( aPackageId ); + + m_installedPanel->SetPackageState( aPackageId, aState, pinned ); + + for( const auto& entry : m_repositoryContentPanels ) + entry.second->SetPackageState( aPackageId, aState, pinned ); +} + + void DIALOG_PCM::OnOpenPackageDirClicked( wxCommandEvent& event ) { LaunchExternal( m_pcm->Get3rdPartyPath() ); diff --git a/kicad/pcm/dialogs/dialog_pcm.h b/kicad/pcm/dialogs/dialog_pcm.h index f652e04778..79cb0329e4 100644 --- a/kicad/pcm/dialogs/dialog_pcm.h +++ b/kicad/pcm/dialogs/dialog_pcm.h @@ -90,11 +90,15 @@ private: ///< Gets installed packages list from PCM and displays it on installed tab void setInstalledPackages(); + ///< Reflects new state of the package in all panels where it is displayed + void updatePackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState ); + ///< Discards specified pending action void discardAction( int aIndex ); std::shared_ptr m_pcm; - ActionCallback m_callback; + ActionCallback m_actionCallback; + PinCallback m_pinCallback; PANEL_PACKAGES_VIEW* m_installedPanel; std::unordered_map m_repositoryContentPanels; wxString m_selectedRepositoryId; diff --git a/kicad/pcm/dialogs/panel_package.cpp b/kicad/pcm/dialogs/panel_package.cpp index f65df74f28..b40f904863 100644 --- a/kicad/pcm/dialogs/panel_package.cpp +++ b/kicad/pcm/dialogs/panel_package.cpp @@ -24,9 +24,9 @@ #include "panel_package.h" PANEL_PACKAGE::PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback, - const PACKAGE_VIEW_DATA& aData ) : + const PinCallback& aPinCallback, const PACKAGE_VIEW_DATA& aData ) : PANEL_PACKAGE_BASE( parent ), - m_actionCallback( aCallback ), m_data( aData ) + m_actionCallback( aCallback ), m_pinCallback( aPinCallback ), m_data( aData ) { // Propagate clicks on static elements to the panel handler. m_name->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this ); @@ -60,13 +60,18 @@ PANEL_PACKAGE::PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback, m_splitButton->SetLabel( _( "Update" ) ); m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this ); - wxMenu* splitMenu = m_splitButton->GetSplitButtonMenu(); - wxMenuItem* menuItem = splitMenu->Append( wxID_ANY, _( "Uninstall" ) ); + wxMenu* splitMenu = m_splitButton->GetSplitButtonMenu(); + m_pinVersionMenuItem = + splitMenu->Append( wxID_ANY, _( "Pin package" ), + _( "Pinned packages don't affect available update notification and " + "will not be updated with \"Update All\" button." ), + wxITEM_CHECK ); + splitMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_PACKAGE::OnPinVersionClick, this, + m_pinVersionMenuItem->GetId() ); - splitMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_PACKAGE::OnUninstallClick, this, - menuItem->GetId() ); + m_actionMenuItem = splitMenu->Append( wxID_ANY, _( "Uninstall" ) ); - SetState( m_data.state ); + SetState( m_data.state, m_data.pinned ); } @@ -76,9 +81,11 @@ void PANEL_PACKAGE::OnSize( wxSizeEvent& event ) } -void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState ) +void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState, bool aPinned ) { m_data.state = aState; + m_data.pinned = aPinned; + m_splitButton->GetSplitButtonMenu()->Check( m_pinVersionMenuItem->GetId(), aPinned ); switch( aState ) { @@ -95,10 +102,15 @@ void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState ) m_button->Disable(); break; case PCM_PACKAGE_STATE::PPS_INSTALLED: - m_splitButton->Hide(); - m_button->Show(); - m_button->SetLabel( _( "Uninstall" ) ); - m_button->Enable(); + m_button->Hide(); + m_splitButton->Show(); + + m_splitButton->SetLabel( _( "Uninstall" ) ); + m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this ); + + m_actionMenuItem->SetItemLabel( _( "Update" ) ); + m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), false ); + break; case PCM_PACKAGE_STATE::PPS_PENDING_INSTALL: m_splitButton->Hide(); @@ -113,9 +125,31 @@ void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState ) m_button->Disable(); break; case PCM_PACKAGE_STATE::PPS_UPDATE_AVAILABLE: - // The only state where the split button is shown instead of the normal one m_button->Hide(); m_splitButton->Show(); + + if( aPinned ) + { + m_splitButton->SetLabel( _( "Uninstall" ) ); + m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnUninstallClick, this ); + + m_actionMenuItem->SetItemLabel( _( "Update" ) ); + m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true ); + m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED, + &PANEL_PACKAGE::OnButtonClicked, this, + m_actionMenuItem->GetId() ); + } + else + { + m_splitButton->SetLabel( _( "Update" ) ); + m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this ); + + m_actionMenuItem->SetItemLabel( _( "Uninstall" ) ); + m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true ); + m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED, + &PANEL_PACKAGE::OnUninstallClick, this, + m_actionMenuItem->GetId() ); + } break; case PCM_PACKAGE_STATE::PPS_PENDING_UPDATE: m_splitButton->Hide(); @@ -152,6 +186,14 @@ void PANEL_PACKAGE::OnButtonClicked( wxCommandEvent& event ) } +void PANEL_PACKAGE::OnPinVersionClick( wxCommandEvent& event ) +{ + m_data.pinned = event.IsChecked(); + + m_pinCallback( m_data.package.identifier, m_data.state, m_data.pinned ); +} + + void PANEL_PACKAGE::OnUninstallClick( wxCommandEvent& event ) { if( m_data.state == PPS_UPDATE_AVAILABLE ) diff --git a/kicad/pcm/dialogs/panel_package.h b/kicad/pcm/dialogs/panel_package.h index b4274e9232..5e19f19203 100644 --- a/kicad/pcm/dialogs/panel_package.h +++ b/kicad/pcm/dialogs/panel_package.h @@ -32,12 +32,14 @@ struct PACKAGE_VIEW_DATA const PCM_PACKAGE package; wxBitmap* bitmap; PCM_PACKAGE_STATE state; + bool pinned; wxString repository_id; wxString repository_name; wxString current_version; wxString update_version; PACKAGE_VIEW_DATA( const PCM_PACKAGE aPackage ) : - package( std::move( aPackage ) ), bitmap( nullptr ), state( PPS_INSTALLED ){}; + package( std::move( aPackage ) ), bitmap( nullptr ), state( PPS_INSTALLED ), + pinned( false ){}; PACKAGE_VIEW_DATA( const PCM_INSTALLATION_ENTRY& aEntry ) : package( std::move( aEntry.package ) ), bitmap( nullptr ) { @@ -45,6 +47,7 @@ struct PACKAGE_VIEW_DATA repository_id = aEntry.repository_id; repository_name = aEntry.repository_name; current_version = aEntry.current_version; + pinned = aEntry.pinned; } }; @@ -53,12 +56,15 @@ struct PACKAGE_VIEW_DATA using ActionCallback = std::function; +using PinCallback = std::function; + class PANEL_PACKAGE : public PANEL_PACKAGE_BASE { public: PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback, - const PACKAGE_VIEW_DATA& aData ); + const PinCallback& aPinCallback, const PACKAGE_VIEW_DATA& aData ); ///< Sets callback for OnClick action void SetSelectCallback( const std::function& aCallback ); @@ -69,13 +75,15 @@ public: void OnButtonClicked( wxCommandEvent& event ) override; ///< Changes state of the (un)install button - void SetState( PCM_PACKAGE_STATE aState ); + void SetState( PCM_PACKAGE_STATE aState, bool aPinned ); ///< Called when anywhere on the panel is clicked (except install button) void OnClick( wxMouseEvent& event ) override; void OnUninstallClick( wxCommandEvent& event ); + void OnPinVersionClick( wxCommandEvent& event ); + void OnSize( wxSizeEvent& event ) override; ///< Get preferred version. If criteria are not met, return wxEmptyString @@ -87,9 +95,12 @@ private: void OnPaint( wxPaintEvent& event ) override; private: + wxMenuItem* m_pinVersionMenuItem; + wxMenuItem* m_actionMenuItem; std::function m_selectCallback; bool m_selected = false; const ActionCallback& m_actionCallback; + const PinCallback& m_pinCallback; PACKAGE_VIEW_DATA m_data; int m_minHeight; }; diff --git a/kicad/pcm/dialogs/panel_packages_view.cpp b/kicad/pcm/dialogs/panel_packages_view.cpp index b7483bdcfe..90f5cb0082 100644 --- a/kicad/pcm/dialogs/panel_packages_view.cpp +++ b/kicad/pcm/dialogs/panel_packages_view.cpp @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -49,9 +49,11 @@ std::unordered_map PANEL_PACKAGES_VIEW::ST PANEL_PACKAGES_VIEW::PANEL_PACKAGES_VIEW( wxWindow* parent, - std::shared_ptr aPcm ) : + std::shared_ptr aPcm, + const ActionCallback& aActionCallback, + const PinCallback& aPinCallback ) : PANEL_PACKAGES_VIEW_BASE( parent ), - m_pcm( aPcm ) + m_pcm( aPcm ), m_actionCallback( aActionCallback ), m_pinCallback( aPinCallback ) { // Replace wxFormBuilder's sash initializer with one which will respect m_initialSashPos. m_splitter1->Disconnect( wxEVT_IDLE, @@ -121,17 +123,14 @@ void PANEL_PACKAGES_VIEW::ClearData() } -void PANEL_PACKAGES_VIEW::SetData( const std::vector& aPackageData, - ActionCallback aCallback ) +void PANEL_PACKAGES_VIEW::SetData( const std::vector& aPackageData ) { - m_actionCallback = aCallback; - ClearData(); for( const PACKAGE_VIEW_DATA& data : aPackageData ) { PANEL_PACKAGE* package_panel = - new PANEL_PACKAGE( m_packageListWindow, m_actionCallback, data ); + new PANEL_PACKAGE( m_packageListWindow, m_actionCallback, m_pinCallback, data ); package_panel->SetSelectCallback( [package_panel, this]() @@ -149,7 +148,7 @@ void PANEL_PACKAGES_VIEW::SetData( const std::vector& aPackag m_packagePanels.insert( { data.package.identifier, package_panel } ); m_packageInitialOrder.push_back( data.package.identifier ); - if( data.state == PPS_UPDATE_AVAILABLE ) + if( data.state == PPS_UPDATE_AVAILABLE && !data.pinned ) m_updateablePackages.insert( data.package.identifier ); } @@ -429,13 +428,13 @@ bool PANEL_PACKAGES_VIEW::canRunAction() const void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId, - const PCM_PACKAGE_STATE aState ) + const PCM_PACKAGE_STATE aState, const bool aPinned ) { auto it = m_packagePanels.find( aPackageId ); if( it != m_packagePanels.end() ) { - it->second->SetState( aState ); + it->second->SetState( aState, aPinned ); if( m_currentSelected && m_currentSelected == it->second ) { @@ -443,7 +442,7 @@ void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId, m_currentSelected->OnClick( dummy ); } - if( aState == PPS_UPDATE_AVAILABLE ) + if( aState == PPS_UPDATE_AVAILABLE && !aPinned ) { m_updateablePackages.insert( aPackageId ); } diff --git a/kicad/pcm/dialogs/panel_packages_view.h b/kicad/pcm/dialogs/panel_packages_view.h index f3d082f22c..51afd986c8 100644 --- a/kicad/pcm/dialogs/panel_packages_view.h +++ b/kicad/pcm/dialogs/panel_packages_view.h @@ -35,24 +35,26 @@ class PANEL_PACKAGES_VIEW : public PANEL_PACKAGES_VIEW_BASE { public: - PANEL_PACKAGES_VIEW( wxWindow* parent, std::shared_ptr aPcm ); + PANEL_PACKAGES_VIEW( wxWindow* parent, std::shared_ptr aPcm, + const ActionCallback& aCallback, const PinCallback& aPinCallback ); ~PANEL_PACKAGES_VIEW(); /** * @brief Recreates package panels and displays data * * @param aPackageData list of package view data - * @param aCallback (un)install button callback */ - void SetData( const std::vector& aPackageData, ActionCallback aCallback ); + void SetData( const std::vector& aPackageData ); /** * @brief Set the state of package * * @param aPackageId id of the package * @param aState new state + * @param aPinned indicates pinned version */ - void SetPackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState ); + void SetPackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState, + const bool aPinned ); ///< Destroys package panels void ClearData(); @@ -115,7 +117,8 @@ private: PCM_PACKAGE_ACTION getAction() const; private: - ActionCallback m_actionCallback; + const ActionCallback& m_actionCallback; + const PinCallback& m_pinCallback; std::unordered_map m_packagePanels; std::vector m_packageInitialOrder; PANEL_PACKAGE* m_currentSelected; diff --git a/kicad/pcm/pcm.cpp b/kicad/pcm/pcm.cpp index 6ffcc6b2e5..f1dabb9912 100644 --- a/kicad/pcm/pcm.cpp +++ b/kicad/pcm/pcm.cpp @@ -813,7 +813,6 @@ PCM_PACKAGE_STATE PLUGIN_CONTENT_MANAGER::GetPackageState( const wxString& aRepo try { repo = &getCachedRepository( aRepositoryId ); - } catch( ... ) { @@ -938,6 +937,24 @@ PLUGIN_CONTENT_MANAGER::GetInstalledPackageVersion( const wxString& aPackageId ) } +bool PLUGIN_CONTENT_MANAGER::IsPackagePinned( const wxString& aPackageId ) const +{ + if( m_installed.find( aPackageId ) == m_installed.end() ) + return false; + + return m_installed.at( aPackageId ).pinned; +} + + +void PLUGIN_CONTENT_MANAGER::SetPinned( const wxString& aPackageId, const bool aPinned ) +{ + if( m_installed.find( aPackageId ) == m_installed.end() ) + return; + + m_installed.at( aPackageId ).pinned = aPinned; +} + + int PLUGIN_CONTENT_MANAGER::GetPackageSearchRank( const PCM_PACKAGE& aPackage, const wxString& aSearchTerm ) { @@ -1096,11 +1113,14 @@ void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate() if( m_installed.size() == 0 ) return; - // Only fetch repositories that have installed packages + // Only fetch repositories that have installed not pinned packages std::unordered_set repo_ids; for( auto& entry : m_installed ) - repo_ids.insert( entry.second.repository_id ); + { + if( !entry.second.pinned ) + repo_ids.insert( entry.second.repository_id ); + } for( const auto& entry : m_repository_list ) { @@ -1132,7 +1152,7 @@ void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate() GetPackageState( installed_package.repository_id, installed_package.package.identifier ); - if( state == PPS_UPDATE_AVAILABLE ) + if( state == PPS_UPDATE_AVAILABLE && !installed_package.pinned ) availableUpdateCount++; } diff --git a/kicad/pcm/pcm.h b/kicad/pcm/pcm.h index ac6e343af2..85e452b8e7 100644 --- a/kicad/pcm/pcm.h +++ b/kicad/pcm/pcm.h @@ -240,6 +240,25 @@ public: */ PCM_PACKAGE_STATE GetPackageState( const wxString& aRepositoryId, const wxString& aPackageId ); + /** + * @brief Returns pinned status of a package + * + * @param aPackageId package id + * @return true if package is installed and is pinned + * @return false if package is not installed or not pinned + */ + bool IsPackagePinned( const wxString& aPackageId ) const; + + /** + * @brief Set the pinned status of a package + * + * no-op for not installed packages + * + * @param aPackageId package id + * @param aPinned pinned status + */ + void SetPinned( const wxString& aPackageId, const bool aPinned ); + /** * @brief Get the preferred package update version or empty string if there is none * diff --git a/kicad/pcm/pcm_data.cpp b/kicad/pcm/pcm_data.cpp index a9b02704ec..01eed268b4 100644 --- a/kicad/pcm/pcm_data.cpp +++ b/kicad/pcm/pcm_data.cpp @@ -173,3 +173,28 @@ void from_json( const json& j, PCM_REPOSITORY& r ) to_optional( j, "manifests", r.manifests ); to_optional( j, "maintainer", r.maintainer ); } + + +void to_json( json& j, const PCM_INSTALLATION_ENTRY& e ) +{ + j = json{ { "package", e.package }, + { "current_version", e.current_version }, + { "repository_id", e.repository_id }, + { "repository_name", e.repository_name }, + { "install_timestamp", e.install_timestamp }, + { "pinned", e.pinned } }; +} + + +void from_json( const json& j, PCM_INSTALLATION_ENTRY& e ) +{ + j.at( "package" ).get_to( e.package ); + j.at( "current_version" ).get_to( e.current_version ); + j.at( "repository_id" ).get_to( e.repository_id ); + j.at( "repository_name" ).get_to( e.repository_name ); + j.at( "install_timestamp" ).get_to( e.install_timestamp ); + + e.pinned = false; + if( j.contains( "pinned" ) ) + j.at( "pinned" ).get_to( e.pinned ); +} diff --git a/kicad/pcm/pcm_data.h b/kicad/pcm/pcm_data.h index 3e64d76984..6946f34714 100644 --- a/kicad/pcm/pcm_data.h +++ b/kicad/pcm/pcm_data.h @@ -23,9 +23,9 @@ #include "core/wx_stl_compat.h" -#include #include #include +#include #include #include #include @@ -141,6 +141,7 @@ struct PCM_INSTALLATION_ENTRY wxString repository_id; wxString repository_name; uint64_t install_timestamp; + bool pinned; // Not serialized fields bool update_available; @@ -203,8 +204,8 @@ void to_json( json& j, const PCM_REPOSITORY& r ); void from_json( const json& j, PCM_REPOSITORY& r ); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( PCM_INSTALLATION_ENTRY, package, current_version, repository_id, - repository_name, install_timestamp ); +void to_json( json& j, const PCM_INSTALLATION_ENTRY& e ); +void from_json( const json& j, PCM_INSTALLATION_ENTRY& e ); #endif // PCM_DATA_H_