35#include <wx/filedlg.h>
37#include <wx/tokenzr.h>
40#define GRID_CELL_MARGIN 4
53 std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm,
68 m_splitter1->SetPaneMinimums( FromDIP( 350 ), FromDIP( 450 ) );
73 m_searchCtrl->SetMinSize( wxSize( -1, GetTextExtent( wxT(
"qb" ) ).y + 10 ) );
79 m_panelList->SetBorders(
false,
true,
false,
false );
96 wxColor background = wxStaticText::GetClassDefaultAttributes().colBg;
142 [package_panel,
this] ()
173 details << wxT(
"<h5>" ) + package.
name + wxT(
"</h5>" );
176 [](
const wxString&
text ) -> wxString
182 for(
unsigned i = 0; i <
text.length(); ++i )
184 wxUniChar c =
text[i];
188 if( c ==
' ' || c ==
'\n')
190 result += wxString::Format( wxT(
"<a href='%s'>%s</a>" ), url, url );
194 result += wxT(
"</p><p>" );
203 else if(
text.Mid( i, 5 ) == wxT(
"http:" )
204 ||
text.Mid( i, 6 ) == wxT(
"https:" ) )
211 result += wxT(
"</p><p>" );
220 result += wxString::Format( wxT(
"<a href='%s'>%s</a>" ), url, url );
225 wxString desc = package.description_full;
226 details << wxT(
"<p>" ) + format_desc( desc ) + wxT(
"</p>" );
228 details << wxT(
"<p><b>" ) +
_(
"Metadata" ) + wxT(
"</b></p>" );
229 details << wxT(
"<ul>" );
230 details << wxT(
"<li>" ) +
_(
"Package identifier: " ) + package.identifier + wxT(
"</li>" );
231 details << wxT(
"<li>" ) +
_(
"License: " ) + package.license + wxT(
"</li>" );
233 if( package.tags.size() > 0 )
237 for(
const std::string& tag : package.tags )
239 if( !tags_str.IsEmpty() )
245 details << wxT(
"<li>" ) +
_(
"Tags: " ) + tags_str + wxT(
"</li>" );
249 [](
const std::pair<const std::string, wxString>& entry ) -> wxString
251 wxString
name = entry.first;
254 if(
name == wxT(
"email" ) )
255 return wxString::Format( wxT(
"<a href='mailto:%s'>%s</a>" ), url, url );
256 else if( url.StartsWith( wxT(
"http:" ) ) || url.StartsWith( wxT(
"https:" ) ) )
257 return wxString::Format( wxT(
"<a href='%s'>%s</a>" ), url, url );
263 [&](
const wxString& type,
const PCM_CONTACT& contact )
265 details << wxT(
"<li>" ) + type + wxT(
": " ) + contact.name + wxT(
"<ul>" );
267 for(
const std::pair<const std::string, wxString>& entry : contact.contact )
269 details << wxT(
"<li>" );
270 details << entry.first << wxT(
": " ) + format_entry( entry );
271 details << wxT(
"</li>" );
274 details << wxT(
"</ul>" );
277 write_contact(
_(
"Author" ), package.author );
279 if( package.maintainer )
280 write_contact(
_(
"Maintainer" ), *package.maintainer );
282 if( package.resources.size() > 0 )
284 details << wxT(
"<li>" ) +
_(
"Resources" ) + wxT(
"<ul>" );
286 for(
const std::pair<const std::string, wxString>& entry : package.resources )
288 details << wxT(
"<li>" );
289 details << entry.first << wxT(
": " );
290 details << format_entry( entry ) + wxT(
"</li>" );
293 details << wxT(
"</ul>" );
296 details << wxT(
"</ul>" );
308 wxString current_version;
311 current_version =
m_pcm->GetInstalledPackageVersion( package.identifier );
330 if( current_version == version.
version )
350 if( version.IsEmpty() )
353 if( !version.IsEmpty() )
408 if( b >= 1024 * 1024 )
409 return wxString::Format( wxT(
"%.1f MB" ), b / 1000.0 / 1000.0 );
412 return wxString::Format( wxT(
"%lld kB" ), b / 1000 );
414 return wxString::Format( wxT(
"%lld B" ), b );
434 switch( packageData.
state )
453 it->second->SetState( aState, aPinned );
491 const wxArrayInt selectedRows =
m_gridVersions->GetSelectedRows();
494 const PCM_PACKAGE&
package = m_currentSelected->GetPackageData().package;
496 auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
499 return ver.version == version;
502 wxASSERT_MSG( ver_it != package.
versions.end(),
"Could not find package version" );
504 if( !ver_it->download_url )
506 wxMessageBox(
_(
"Package download url is not specified" ),
_(
"Error downloading package" ),
507 wxICON_INFORMATION | wxOK, wxGetTopLevelParent(
this ) );
511 const wxString& url = *ver_it->download_url;
514 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
516 wxString::Format( wxT(
"%s_v%s.zip" ), package.identifier, version ),
517 wxT(
"ZIP files (*.zip)|*.zip" ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
519 if( dialog.ShowModal() == wxID_CANCEL )
522 wxString
path = dialog.GetPath();
525 std::ofstream output(
path.ToUTF8(), std::ios_base::binary );
529 bool success =
m_pcm->DownloadToStream( url, &output, &reporter, 0 );
535 if( ver_it->download_sha256 )
537 std::ifstream stream(
path.ToUTF8(), std::ios_base::binary );
539 bool matches =
m_pcm->VerifyHash( stream, *ver_it->download_sha256 );
543 if( !matches && wxMessageBox(
_(
"Integrity of the downloaded package could not be verified, hash "
544 "does not match. Are you sure you want to keep this file?" ),
545 _(
"Keep downloaded file" ), wxICON_EXCLAMATION | wxYES_NO,
546 wxGetTopLevelParent(
this ) )
549 wxRemoveFile(
path );
555 if( wxFileExists(
path ) )
556 wxRemoveFile(
path );
581 const wxArrayInt selectedRows =
m_gridVersions->GetSelectedRows();
584 const PCM_PACKAGE&
package = m_currentSelected->GetPackageData().package;
586 auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
589 return ver.version == version;
592 wxCHECK_RET( ver_it != package.
versions.end(),
"Could not find package version" );
594 if( !ver_it->compatible && wxMessageBox(
_(
"This package version is incompatible with your KiCad version or "
595 "platform. Are you sure you want to install it anyway?" ),
596 _(
"Install package" ), wxICON_EXCLAMATION | wxYES_NO,
597 wxGetTopLevelParent(
this ) )
635 std::vector<std::pair<int, int>> package_ranks;
637 const wxString search_term =
m_searchCtrl->GetValue().Trim();
644 if( search_term.size() > 2 )
645 rank =
m_pcm->GetPackageSearchRank( pkg, search_term );
651 package_ranks.emplace_back( rank, index );
654 std::sort( package_ranks.begin(), package_ranks.end(),
655 [](
const std::pair<int, int>& a,
const std::pair<int, int>& b )
657 return a.first > b.first || ( a.first == b.first && a.second < b.second );
662 sizer->Clear(
false );
664 for(
const std::pair<int, int>& pair : package_ranks )
670 sizer->Add( panel, 0, wxEXPAND );
719 wxT(
"getAction() called with ambiguous version selection" ) );
721 int selected_row = 0;
729 switch( package.state )
732 case PPS_UNAVAILABLE:
735 case PPS_UPDATE_AVAILABLE:
736 if( version == package.current_version )
737 return PPA_UNINSTALL;
755 infoSize.y =
m_infoText->GetInternalRepresentation()->GetHeight() + 12;
767 const wxHtmlLinkInfo&
info = aEvent.GetLinkInfo();
768 ::wxLaunchDefaultBrowser(
info.GetHref() );
799 std::vector<wxString> packages;
803 for(
const wxString& pkg_id : packages )
PACKAGE_MANAGER m_PackageManager
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
wxString m_PcmLastDownloadDir
WX_SPLITTER_WINDOW * m_splitter1
wxScrolledWindow * m_packageListWindow
void m_splitter1OnIdle(wxIdleEvent &)
PANEL_PACKAGES_VIEW_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxButton * m_buttonAction
wxButton * m_buttonUpdateAll
wxButton * m_buttonDownload
wxBoxSizer * m_sizerVersions
wxCheckBox * m_showAllVersions
wxScrolledWindow * m_infoScrollWindow
wxSearchCtrl * m_searchCtrl
void OnInfoMouseWheel(wxMouseEvent &event) override
Replacement of wxFormBuilder's ill-advised m_splitter1OnIdle.
std::unordered_set< wxString > m_updateablePackages
void OnUpdateAllClicked(wxCommandEvent &event) override
void ClearData()
Selects full row of the clicked cell.
void updateDetailsButtons()
Called when package state changes, currently used to calculate Update All button state.
void OnVersionActionClicked(wxCommandEvent &event) override
Shows all versions including incompatible ones.
void OnSizeInfoBox(wxSizeEvent &aEvent) override
Respond to a URL in the info window.
bool canDownload() const
Returns true if the package action can be performed.
void OnDownloadVersionClicked(wxCommandEvent &event) override
Schedules relevant action for selected package version.
wxString toHumanReadableSize(const std::optional< uint64_t > size) const
Returns true if it the download operation can be performed.
void OnSearchTextChanged(wxCommandEvent &event)
void updateCommonState()
Updates details panel.
void updatePackageList()
< Updates package listing according to search term
const ActionCallback & m_actionCallback
std::unordered_map< wxString, PANEL_PACKAGE * > m_packagePanels
void setPackageDetails(const PACKAGE_VIEW_DATA &aPackageData)
Clears details panel.
const PinCallback & m_pinCallback
std::shared_ptr< PLUGIN_CONTENT_MANAGER > m_pcm
PCM_PACKAGE_ACTION getAction() const
bool canRunAction() const
Returns implied action for the action button.
PANEL_PACKAGE * m_currentSelected
void unsetPackageDetails()
Bytes to Kb/Mb/Gb string or "-" if absent.
void SetData(const std::vector< PACKAGE_VIEW_DATA > &aPackageData)
Recreates package panels and displays data.
void OnVersionsCellClicked(wxGridEvent &event) override
Opens file chooser dialog and downloads selected package version archive.
void OnURLClicked(wxHtmlLinkEvent &event) override
Respond to scrolling over the window.
void SetSashOnIdle(wxIdleEvent &)
Enqueues all available package updates.
static std::unordered_map< PCM_PACKAGE_VERSION_STATUS, wxString > STATUS_ENUM_TO_STR
void SetPackageState(const wxString &aPackageId, const PCM_PACKAGE_STATE aState, const bool aPinned)
Set the state of package.
std::vector< wxString > m_packageInitialOrder
PANEL_PACKAGES_VIEW(wxWindow *parent, std::shared_ptr< PLUGIN_CONTENT_MANAGER > aPcm, const ActionCallback &aCallback, const PinCallback &aPinCallback)
void OnShowAllVersionsClicked(wxCommandEvent &event) override
Ranks packages for entered search term and rearranges/hides panels according to their rank.
void OnClick(wxMouseEvent &event) override
const PACKAGE_VIEW_DATA & GetPackageData() const
void SetSelected(bool aSelected)
void SetSelectCallback(const std::function< void()> &aCallback)
Marks panel as selected.
virtual COMMON_SETTINGS * GetCommonSettings() const
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
std::function< void(const wxString &aPackageId, const PCM_PACKAGE_STATE aState, const bool aPinned)> PinCallback
std::function< void(const PACKAGE_VIEW_DATA &aData, PCM_PACKAGE_ACTION aAction, const wxString &aVersion)> ActionCallback
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
PGM_BASE & Pgm()
The global program "get" accessor.
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
< Package version metadataPackage metadata
std::optional< uint64_t > download_size
std::optional< uint64_t > install_size
PCM_PACKAGE_VERSION_STATUS status
< Collection of data relevant to the package display panelCallback for (un)install button
Repository reference to a resource.
std::vector< PACKAGE_VERSION > versions
wxString result
Test unit parsing edge cases and error handling.