KiCad PCB EDA Suite
panel_packages_view.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
5  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "panel_packages_view.h"
22 #include <grid_tricks.h>
23 #include <kicad_settings.h>
24 #include <pgm_base.h>
28 #include <widgets/wx_panel.h>
29 #include <string_utils.h>
30 #include <html_window.h>
32 
33 #include <cmath>
34 #include <fstream>
35 #include <wx/filedlg.h>
36 #include <wx/font.h>
37 #include <wx/tokenzr.h>
38 
39 
40 #define GRID_CELL_MARGIN 4
41 
42 
43 std::unordered_map<PCM_PACKAGE_VERSION_STATUS, wxString> PANEL_PACKAGES_VIEW::STATUS_ENUM_TO_STR = {
44  { PVS_INVALID, wxT( "invalid" ) },
45  { PVS_STABLE, wxT( "stable" ) },
46  { PVS_TESTING, wxT( "testing" ) },
47  { PVS_DEVELOPMENT, wxT( "development" ) },
48  { PVS_DEPRECATED, wxT( "deprecated" ) }
49 };
50 
51 
53  std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm ) :
54  PANEL_PACKAGES_VIEW_BASE( parent ),
55  m_pcm( aPcm )
56 {
57  // Replace wxFormBuilder's sash initializer with one which will respect m_initialSashPos.
58  m_splitter1->Disconnect( wxEVT_IDLE,
59  wxIdleEventHandler( PANEL_PACKAGES_VIEW_BASE::m_splitter1OnIdle ),
60  NULL, this );
61  m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW::SetSashOnIdle ),
62  NULL, this );
63 
64  m_splitter1->SetPaneMinimums( 350, 450 );
65 
66 #ifdef __WXGTK__
67  // wxSearchCtrl vertical height is not calculated correctly on some GTK setups
68  // See https://gitlab.com/kicad/code/kicad/-/issues/9019
69  m_searchCtrl->SetMinSize( wxSize( -1, GetTextExtent( wxT( "qb" ) ).y + 10 ) );
70 #endif
71 
72  m_searchCtrl->Bind( wxEVT_TEXT, &PANEL_PACKAGES_VIEW::OnSearchTextChanged, this );
73  m_searchCtrl->SetDescriptiveText( _( "Filter" ) );
74 
75  m_panelList->SetBorders( false, true, false, false );
76 
77  m_gridVersions->PushEventHandler( new GRID_TRICKS( m_gridVersions ) );
78 
79  for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
80  {
81  const wxString& heading = m_gridVersions->GetColLabelValue( col );
82  int headingWidth = GetTextExtent( heading ).x + 2 * GRID_CELL_MARGIN;
83 
84  // Set the minimal width to the column label size.
85  m_gridVersions->SetColMinimalWidth( col, headingWidth );
86  m_gridVersions->SetColSize( col, m_gridVersions->GetVisibleWidth( col, true, true,
87  false ) );
88  }
89 
90  // Most likely should be changed to wxGridSelectNone once WxWidgets>=3.1.5 is mandatory.
91  m_gridVersions->SetSelectionMode( WX_GRID::wxGridSelectRows );
92 
93  wxColor background = wxStaticText::GetClassDefaultAttributes().colBg;
94  m_panelList->SetBackgroundColour( background );
95  m_packageListWindow->SetBackgroundColour( background );
96  m_infoScrollWindow->SetBackgroundColour( background );
97  m_infoScrollWindow->EnableScrolling( false, true );
98 
99  ClearData();
100 }
101 
102 
104 {
105  COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
106  cfg->m_PackageManager.sash_pos = m_splitter1->GetSashPosition();
107 
108  m_gridVersions->PopEventHandler( true );
109 }
110 
111 
113 {
115 
116  m_currentSelected = nullptr;
117  m_packagePanels.clear();
118  m_packageInitialOrder.clear();
119  m_packageListWindow->GetSizer()->Clear( true ); // Delete panels
120  m_packageListWindow->GetSizer()->FitInside( m_packageListWindow );
121  m_packageListWindow->Layout();
122 }
123 
124 
125 void PANEL_PACKAGES_VIEW::SetData( const std::vector<PACKAGE_VIEW_DATA>& aPackageData,
126  ActionCallback aCallback )
127 {
128  m_actionCallback = aCallback;
129 
130  ClearData();
131 
132  for( const PACKAGE_VIEW_DATA& data : aPackageData )
133  {
134  PANEL_PACKAGE* package_panel =
136 
137  package_panel->SetSelectCallback(
138  [package_panel, this]()
139  {
140  if( m_currentSelected && m_currentSelected != package_panel )
141  m_currentSelected->SetSelected( false );
142 
143  package_panel->SetSelected( true );
144  m_currentSelected = package_panel;
145  setPackageDetails( package_panel->GetPackageData() );
146 
147  Layout();
148  } );
149 
150  m_packagePanels.insert( { data.package.identifier, package_panel } );
151  m_packageInitialOrder.push_back( data.package.identifier );
152  }
153 
155 }
156 
157 
159 {
160  const PCM_PACKAGE& package = aPackageData.package;
161 
162  // Details
163  wxString details;
164 
165  details << wxT( "<h5>" ) + package.name + wxT( "</h5>" );
166 
167  auto format_desc =
168  []( const wxString& text ) -> wxString
169  {
170  wxString result;
171  bool inURL = false;
172  wxString url;
173 
174  for( unsigned i = 0; i < text.length(); ++i )
175  {
176  wxUniChar c = text[i];
177 
178  if( inURL )
179  {
180  if( c == ' ' )
181  {
182  result += wxString::Format( wxT( "<a href='%s'>%s</a>" ), url, url );
183  inURL = false;
184 
185  result += c;
186  }
187  else
188  {
189  url += c;
190  }
191  }
192  else if( text.Mid( i, 5 ) == wxT( "http:" ) || text.Mid( i, 6 ) == wxT( "https:" ) )
193  {
194  url = c;
195  inURL = true;
196  }
197  else if( c == '\n' )
198  {
199  result += wxT( "</p><p>" );
200  }
201  else
202  {
203  result += c;
204  }
205  }
206 
207  return result;
208  };
209 
210  wxString desc = package.description_full;
211  details << wxT( "<p>" ) + format_desc( desc ) + wxT( "</p>" );
212 
213  details << wxT( "<p><b>" ) + _( "Metadata" ) + wxT( "</b></p>" );
214  details << wxT( "<ul>" );
215  details << wxT( "<li>" ) + _( "Package identifier: " ) + package.identifier + wxT( "</li>" );
216  details << wxT( "<li>" ) + _( "License: " ) + package.license + wxT( "</li>" );
217 
218  if( package.tags.size() > 0 )
219  {
220  wxString tags_str;
221 
222  for( const std::string& tag : package.tags )
223  {
224  if( !tags_str.IsEmpty() )
225  tags_str += wxT( ", " );
226 
227  tags_str += tag;
228  }
229 
230  details << wxT( "<li>" ) + _( "Tags: " ) + tags_str + wxT( "</li>" );
231  }
232 
233  auto format_entry =
234  []( const std::pair<const std::string, wxString>& entry ) -> wxString
235  {
236  wxString name = entry.first;
237  wxString url = EscapeHTML( entry.second );
238 
239  if( name == wxT( "email" ) )
240  return wxString::Format( wxT( "<a href='mailto:%s'>%s</a>" ), url, url );
241  else if( url.StartsWith( wxT( "http:" ) ) || url.StartsWith( wxT( "https:" ) ) )
242  return wxString::Format( wxT( "<a href='%s'>%s</a>" ), url, url );
243  else
244  return entry.second;
245  };
246 
247  auto write_contact =
248  [&]( const wxString& type, const PCM_CONTACT& contact )
249  {
250  details << wxT( "<li>" ) + type + wxT( ": " ) + contact.name + wxT( "<ul>" );
251 
252  for( const std::pair<const std::string, wxString>& entry : contact.contact )
253  details << wxT( "<li>" ) + entry.first + wxT( ": " ) + format_entry( entry ) + wxT( "</li>" );
254 
255  details << wxT( "</ul>" );
256  };
257 
258  write_contact( _( "Author" ), package.author );
259 
260  if( package.maintainer )
261  write_contact( _( "Maintainer" ), package.maintainer.get() );
262 
263  if( package.resources.size() > 0 )
264  {
265  details << wxT( "<li>" ) + _( "Resources" ) + wxT( "<ul>" );
266 
267  for( const std::pair<const std::string, wxString>& entry : package.resources )
268  details << wxT( "<li>" ) + entry.first + wxS( ": " ) + format_entry( entry ) + wxT( "</li>" );
269 
270  details << wxT( "</ul>" );
271  }
272 
273  details << wxT( "</ul>" );
274 
275  m_infoText->SetPage( details );
276 
277  wxSizeEvent dummy;
278  OnSizeInfoBox( dummy );
279 
280  // Versions table
281  m_gridVersions->Freeze();
282 
283  if( m_gridVersions->GetNumberRows() != 0 )
284  m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
285 
286  int row = 0;
287  wxString current_version;
288 
289  if( aPackageData.state == PPS_INSTALLED )
290  current_version = m_pcm->GetInstalledPackageVersion( package.identifier );
291 
292  wxFont bold_font = m_gridVersions->GetDefaultCellFont().Bold();
293 
294  for( const PACKAGE_VERSION& version : package.versions )
295  {
296  if( !version.compatible && !m_showAllVersions->IsChecked() )
297  continue;
298 
299  m_gridVersions->InsertRows( row );
300 
301  m_gridVersions->SetCellValue( row, COL_VERSION, version.version );
302  m_gridVersions->SetCellValue( row, COL_DOWNLOAD_SIZE,
303  toHumanReadableSize( version.download_size ) );
304  m_gridVersions->SetCellValue( row, COL_INSTALL_SIZE,
305  toHumanReadableSize( version.install_size ) );
306  m_gridVersions->SetCellValue( row, COL_COMPATIBILITY,
307  version.compatible ? wxT( "\u2714" ) : wxEmptyString );
308  m_gridVersions->SetCellValue( row, COL_STATUS, STATUS_ENUM_TO_STR.at( version.status ) );
309 
310  m_gridVersions->SetCellAlignment( row, COL_COMPATIBILITY, wxALIGN_CENTER, wxALIGN_CENTER );
311 
312  if( current_version == version.version )
313  {
314  for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
315  m_gridVersions->SetCellFont( row, col, bold_font );
316  }
317 
318  row++;
319  }
320 
321  for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
322  {
323  // Set the width to see the full contents
324  m_gridVersions->SetColSize( col, m_gridVersions->GetVisibleWidth( col, true, true,
325  false ) );
326  }
327 
328  if( m_gridVersions->GetNumberRows() >= 1 )
329  {
330  wxString version = m_currentSelected->GetPreferredVersion();
331 
332  if( !version.IsEmpty() )
333  {
334  for( int i = 0; i < m_gridVersions->GetNumberRows(); i++ )
335  {
336  if( m_gridVersions->GetCellValue( i, COL_VERSION ) == version )
337  {
338  m_gridVersions->SelectRow( i );
339  break;
340  }
341  }
342  }
343  else
344  {
345  // Fall back to first row.
346  m_gridVersions->SelectRow( 0 );
347  }
348  }
349 
350  m_gridVersions->Thaw();
351 
353 
354  m_infoText->Show( true );
355  m_sizerVersions->Show( true );
356  m_sizerVersions->Layout();
357 
358  wxSize size = m_infoScrollWindow->GetTargetWindow()->GetBestVirtualSize();
359  m_infoScrollWindow->SetVirtualSize( size );
360 }
361 
362 
364 {
365  m_infoText->SetPage( wxEmptyString );
366  m_infoText->Show( false );
367  m_sizerVersions->Show( false );
368 
369  wxSize size = m_infoScrollWindow->GetTargetWindow()->GetBestVirtualSize();
370  m_infoScrollWindow->SetVirtualSize( size );
371 
372  // Clean up grid just so we don't keep stale info around (it's already been hidden).
373  m_gridVersions->Freeze();
374 
375  if( m_gridVersions->GetNumberRows() > 0 )
376  m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
377 
378  m_gridVersions->Thaw();
379 }
380 
381 
382 wxString PANEL_PACKAGES_VIEW::toHumanReadableSize( const boost::optional<uint64_t> size ) const
383 {
384  if( !size )
385  return wxT( "-" );
386 
387  uint64_t b = size.get();
388 
389  if( b >= 1024 * 1024 )
390  return wxString::Format( wxT( "%.1f Mb" ), b / 1024.0 / 1024.0 );
391 
392  if( b >= 1024 )
393  return wxString::Format( wxT( "%lld Kb" ), b / 1024 );
394 
395  return wxString::Format( wxT( "%lld b" ), b );
396 }
397 
398 
400 {
401  if( !m_currentSelected )
402  return false;
403 
404  return m_gridVersions->GetNumberRows() == 1 || m_gridVersions->GetSelectedRows().size() == 1;
405 }
406 
407 
409 {
410  if( !m_currentSelected )
411  return false;
412 
413  const PACKAGE_VIEW_DATA& packageData = m_currentSelected->GetPackageData();
414 
415  if( packageData.state != PPS_AVAILABLE && packageData.state != PPS_UNAVAILABLE )
416  return false;
417 
418  return m_gridVersions->GetNumberRows() == 1 || m_gridVersions->GetSelectedRows().size() == 1;
419 }
420 
421 
422 void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId,
423  const PCM_PACKAGE_STATE aState ) const
424 {
425  auto it = m_packagePanels.find( aPackageId );
426 
427  if( it != m_packagePanels.end() )
428  {
429  it->second->SetState( aState );
430 
431  if( m_currentSelected && m_currentSelected == it->second )
432  {
433  wxMouseEvent dummy;
435  }
436  }
437 }
438 
439 
441 {
442  m_gridVersions->ClearSelection();
443  m_gridVersions->SelectRow( event.GetRow() );
444 
446 }
447 
448 
450 {
451  if( !canDownload() )
452  {
453  wxBell();
454  return;
455  }
456 
457  if( m_gridVersions->GetNumberRows() == 1 )
458  m_gridVersions->SelectRow( 0 );
459 
460  const wxArrayInt selectedRows = m_gridVersions->GetSelectedRows();
461 
462  wxString version = m_gridVersions->GetCellValue( selectedRows[0], COL_VERSION );
463  const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
464 
465  auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
466  [&]( const PACKAGE_VERSION& ver )
467  {
468  return ver.version == version;
469  } );
470 
471  wxASSERT_MSG( ver_it != package.versions.end(), wxT( "Could not find package version" ) );
472 
473  if( !ver_it->download_url )
474  {
475  wxMessageBox( _( "Package download url is not specified" ),
476  _( "Error downloading package" ), wxICON_INFORMATION | wxOK, this );
477  return;
478  }
479 
480  const wxString& url = ver_it->download_url.get();
481 
482  SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
483  KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
484 
485  wxFileDialog dialog( this, _( "Save package" ), app_settings->m_PcmLastDownloadDir,
486  wxString::Format( wxT( "%s_v%s.zip" ), package.identifier, version ),
487  ZipFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
488 
489  if( dialog.ShowModal() == wxID_CANCEL )
490  return;
491 
492  wxString path = dialog.GetPath();
493  app_settings->m_PcmLastDownloadDir = wxPathOnly( path );
494 
495  std::ofstream output( path.ToUTF8(), std::ios_base::binary );
496 
497  std::unique_ptr<WX_PROGRESS_REPORTER> reporter(
498  new WX_PROGRESS_REPORTER( this, _( "Downloading package" ), 1 ) );
499 
500  bool success = m_pcm->DownloadToStream( url, &output, reporter.get(), 0 );
501 
502  output.close();
503 
504  if( success )
505  {
506  if( ver_it->download_sha256 )
507  {
508  std::ifstream stream( path.ToUTF8(), std::ios_base::binary );
509 
510  bool matches = m_pcm->VerifyHash( stream, ver_it->download_sha256.get() );
511 
512  stream.close();
513 
514  if( !matches
515  && wxMessageBox(
516  _( "Integrity of the downloaded package could not be verified, hash "
517  "does not match. Are you sure you want to keep this file?" ),
518  _( "Keep downloaded file" ), wxICON_EXCLAMATION | wxYES_NO, this )
519  == wxNO )
520  {
521  wxRemoveFile( path );
522  }
523  }
524  }
525  else
526  {
527  if( wxFileExists( path ) )
528  wxRemoveFile( path );
529  }
530 }
531 
532 
533 void PANEL_PACKAGES_VIEW::OnInstallVersionClicked( wxCommandEvent& event )
534 {
535  if( !canInstall() )
536  {
537  wxBell();
538  return;
539  }
540 
541  if( m_gridVersions->GetNumberRows() == 1 )
542  m_gridVersions->SelectRow( 0 );
543 
544  const wxArrayInt selectedRows = m_gridVersions->GetSelectedRows();
545 
546  wxString version = m_gridVersions->GetCellValue( selectedRows[0], COL_VERSION );
547  const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
548 
549  auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
550  [&]( const PACKAGE_VERSION& ver )
551  {
552  return ver.version == version;
553  } );
554 
555  wxASSERT_MSG( ver_it != package.versions.end(), wxT( "Could not find package version" ) );
556 
557  if( !ver_it->compatible
558  && wxMessageBox( _( "This package version is incompatible with your kicad version or "
559  "platform. Are you sure you want to install it anyway?" ),
560  _( "Install package" ), wxICON_EXCLAMATION | wxYES_NO, this )
561  == wxNO )
562  {
563  return;
564  }
565 
567 }
568 
569 
571 {
572  if( m_currentSelected )
573  {
574  wxMouseEvent dummy;
576  }
577 
579 }
580 
581 
582 void PANEL_PACKAGES_VIEW::OnSearchTextChanged( wxCommandEvent& event )
583 {
585 
586  if( m_currentSelected )
587  m_currentSelected->SetSelected( false );
588 
589  m_currentSelected = nullptr;
590 
592 }
593 
594 
596 {
597  // Sort by descending rank, ascending index
598  std::vector<std::pair<int, int>> package_ranks;
599 
600  const wxString search_term = m_searchCtrl->GetValue().Trim();
601 
602  for( size_t index = 0; index < m_packageInitialOrder.size(); index++ )
603  {
604  int rank = 1;
605  const PCM_PACKAGE& pkg =
606  m_packagePanels[m_packageInitialOrder[index]]->GetPackageData().package;
607 
608  if( search_term.size() > 2 )
609  rank = m_pcm->GetPackageSearchRank( pkg, search_term );
610 
611  // Packages with no versions are delisted and should not be shown
612  if( pkg.versions.size() == 0 )
613  rank = 0;
614 
615  package_ranks.emplace_back( rank, index );
616  }
617 
618  std::sort( package_ranks.begin(), package_ranks.end(),
619  []( const std::pair<int, int>& a, const std::pair<int, int>& b )
620  {
621  return a.first > b.first || ( a.first == b.first && a.second < b.second );
622  } );
623 
624  // Rearrange panels, hide ones with 0 rank
625  wxSizer* sizer = m_packageListWindow->GetSizer();
626  sizer->Clear( false ); // Don't delete panels
627 
628  for( const std::pair<int, int>& pair : package_ranks )
629  {
630  PANEL_PACKAGE* panel = m_packagePanels[m_packageInitialOrder[pair.second]];
631 
632  if( pair.first > 0 )
633  {
634  sizer->Add( panel, 0, wxEXPAND );
635  panel->Show();
636  }
637  else
638  {
639  panel->Hide();
640  }
641  }
642 
643  m_packageListWindow->FitInside();
644  m_packageListWindow->SetScrollRate( 0, 15 );
645  m_packageListWindow->SendSizeEvent( wxSEND_EVENT_POST );
646 }
647 
648 
650 {
651  m_buttonDownload->Enable( canDownload() );
652  m_buttonInstall->Enable( canInstall() );
653 }
654 
655 
656 void PANEL_PACKAGES_VIEW::OnSizeInfoBox( wxSizeEvent& aEvent )
657 {
658  wxSize infoSize = m_infoText->GetParent()->GetClientSize();
659  infoSize.x -= 8;
660  m_infoText->SetMinSize( infoSize );
661  m_infoText->SetMaxSize( infoSize );
662  m_infoText->SetSize( infoSize );
663  m_infoText->Layout();
664 
665  infoSize.y = m_infoText->GetInternalRepresentation()->GetHeight() + 12;
666  m_infoText->SetMinSize( infoSize );
667  m_infoText->SetMaxSize( infoSize );
668  m_infoText->SetSize( infoSize );
669  m_infoText->Layout();
670 
671  Refresh();
672 }
673 
674 
675 void PANEL_PACKAGES_VIEW::OnURLClicked( wxHtmlLinkEvent& aEvent )
676 {
677  const wxHtmlLinkInfo& info = aEvent.GetLinkInfo();
678  ::wxLaunchDefaultBrowser( info.GetHref() );
679 }
680 
681 
682 void PANEL_PACKAGES_VIEW::OnInfoMouseWheel( wxMouseEvent& event )
683 {
684  // Transfer scrolling from the info window to its parent scroll window
685  m_infoScrollWindow->HandleOnMouseWheel( event );
686 }
687 
688 
689 void PANEL_PACKAGES_VIEW::SetSashOnIdle( wxIdleEvent& aEvent )
690 {
691  COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
692  m_splitter1->SetSashPosition( cfg->m_PackageManager.sash_pos );
693 
694  m_packageListWindow->FitInside();
695 
696  m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW::SetSashOnIdle ),
697  NULL, this );
698 }
< Package version metadata Package metadata
Definition: pcm_data.h:73
void SetData(const std::vector< PACKAGE_VIEW_DATA > &aPackageData, ActionCallback aCallback)
Recreates package panels and displays data.
void OnURLClicked(wxHtmlLinkEvent &event) override
Respond to scrolling over the window.
std::shared_ptr< PLUGIN_CONTENT_MANAGER > m_pcm
PCM_PACKAGE_VERSION_STATUS status
Definition: pcm_data.h:81
wxString toHumanReadableSize(const boost::optional< uint64_t > size) const
Returns true if it the download operation can be performed.
void OnSizeInfoBox(wxSizeEvent &aEvent) override
Respond to a URL in the info window.
boost::optional< uint64_t > download_size
Definition: pcm_data.h:79
boost::optional< uint64_t > install_size
Definition: pcm_data.h:80
bool canDownload() const
Returns true if the install operation can be performed.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:55
wxString ZipFileWildcard()
std::vector< wxString > m_packageInitialOrder
void ClearData()
Selects full row of the clicked cell.
void unsetPackageDetails()
Bytes to Kb/Mb/Gb string or "-" if absent.
void OnInstallVersionClicked(wxCommandEvent &event) override
Shows all versions including incompatible ones.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
wxScrolledWindow * m_infoScrollWindow
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=false, bool aKeep=true)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:282
void updateDetailsButtons()
Updates details panel.
< Collection of data relevant to the package display panel Callback for (un)install button
Definition: panel_package.h:30
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
static std::unordered_map< PCM_PACKAGE_VERSION_STATUS, wxString > STATUS_ENUM_TO_STR
void SetPackageState(const wxString &aPackageId, const PCM_PACKAGE_STATE aState) const
Set the state of package.
bool compatible
Definition: pcm_data.h:88
void OnShowAllVersionsClicked(wxCommandEvent &event) override
Ranks packages for entered search term and rearranges/hides panels according to their rank.
void m_splitter1OnIdle(wxIdleEvent &)
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition: wx_panel.h:38
void SetSelected(bool aSelected)
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
Class PANEL_PACKAGES_VIEW_BASE.
Repository reference to a resource.
Definition: pcm_data.h:93
void OnDownloadVersionClicked(wxCommandEvent &event) override
Schedules installation of selected package version.
T * GetAppSettings(bool aLoadNow=true)
Returns a handle to the a given settings by type If the settings have already been loaded,...
Definition of file extensions used in Kicad.
bool SetPage(const wxString &aSource) override
Definition: html_window.cpp:38
#define _(s)
void SetSashOnIdle(wxIdleEvent &)
wxString name
Definition: pcm_data.h:95
WX_SPLITTER_WINDOW * m_splitter1
wxScrolledWindow * m_packageListWindow
void OnClick(wxMouseEvent &event) override
void SetSelectCallback(const std::function< void()> &aCallback)
Marks panel as selected.
void OnInfoMouseWheel(wxMouseEvent &event) override
Replacement of wxFormBuilder's ill-advised m_splitter1OnIdle.
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:105
void OnSearchTextChanged(wxCommandEvent &event)
void OnVersionsCellClicked(wxGridEvent &event) override
Opens file chooser dialog and downloads selected package version archive.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
PCM_PACKAGE_STATE
Definition: pcm.h:52
PACKAGE_MANAGER m_PackageManager
PCM_PACKAGE_STATE state
Definition: panel_package.h:34
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
void setPackageDetails(const PACKAGE_VIEW_DATA &aPackageData)
Clears details panel.
see class PGM_BASE
const PACKAGE_VIEW_DATA & GetPackageData() const
Definition: panel_package.h:81
const char * name
Definition: DXF_plotter.cpp:56
PANEL_PACKAGE * m_currentSelected
void updatePackageList()
< Updates package listing according to search term
std::unordered_map< wxString, PANEL_PACKAGE * > m_packagePanels
std::function< void(const PACKAGE_VIEW_DATA &aData, PCM_PACKAGE_ACTION aAction, const wxString &aVersion)> ActionCallback
Definition: panel_package.h:53
PANEL_PACKAGES_VIEW(wxWindow *parent, std::shared_ptr< PLUGIN_CONTENT_MANAGER > aPcm)
ActionCallback m_actionCallback
wxString GetPreferredVersion() const
wxString version
Definition: pcm_data.h:75
#define GRID_CELL_MARGIN
void SetPaneMinimums(int aFirst, int aSecond)