KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 <widgets/html_window.h>
24#include <pgm_base.h>
25#include <kiplatform/ui.h>
29#include <string_utils.h>
30#include <widgets/wx_panel.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
43std::unordered_map<PCM_PACKAGE_VERSION_STATUS, wxString> PANEL_PACKAGES_VIEW::STATUS_ENUM_TO_STR = {
44 { PVS_INVALID, wxS( "invalid" ) },
45 { PVS_STABLE, wxS( "stable" ) },
46 { PVS_TESTING, wxS( "testing" ) },
47 { PVS_DEVELOPMENT, wxS( "development" ) },
48 { PVS_DEPRECATED, wxS( "deprecated" ) }
49};
50
51
53 std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm,
54 const ActionCallback& aActionCallback,
55 const PinCallback& aPinCallback ) :
57 m_actionCallback( aActionCallback ),
58 m_pinCallback( aPinCallback ),
59 m_pcm( aPcm )
60{
61 // Replace wxFormBuilder's sash initializer with one which will respect m_initialSashPos.
62 m_splitter1->Disconnect( wxEVT_IDLE,
64 NULL, this );
65 m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW::SetSashOnIdle ),
66 NULL, this );
67
68 m_splitter1->SetPaneMinimums( 350, 450 );
69
70#ifdef __WXGTK__
71 // wxSearchCtrl vertical height is not calculated correctly on some GTK setups
72 // See https://gitlab.com/kicad/code/kicad/-/issues/9019
73 m_searchCtrl->SetMinSize( wxSize( -1, GetTextExtent( wxT( "qb" ) ).y + 10 ) );
74#endif
75
77 m_searchCtrl->SetDescriptiveText( _( "Filter" ) );
78
79 m_panelList->SetBorders( false, true, false, false );
80
81 m_gridVersions->PushEventHandler( new GRID_TRICKS( m_gridVersions ) );
82
83 for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
84 {
85 const wxString& heading = m_gridVersions->GetColLabelValue( col );
86 int headingWidth = GetTextExtent( heading ).x + 2 * GRID_CELL_MARGIN;
87
88 // Set the minimal width to the column label size.
89 m_gridVersions->SetColMinimalWidth( col, headingWidth );
90 m_gridVersions->SetColSize( col, m_gridVersions->GetVisibleWidth( col ) );
91 }
92
93 // Most likely should be changed to wxGridSelectNone once WxWidgets>=3.1.5 is mandatory.
94 m_gridVersions->SetSelectionMode( WX_GRID::wxGridSelectRows );
95
96 wxColor background = wxStaticText::GetClassDefaultAttributes().colBg;
97 m_panelList->SetBackgroundColour( background );
98 m_packageListWindow->SetBackgroundColour( background );
99 m_infoScrollWindow->SetBackgroundColour( background );
100 m_infoScrollWindow->EnableScrolling( false, true );
101
102 ClearData();
103}
104
105
107{
108 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
109 cfg->m_PackageManager.sash_pos = m_splitter1->GetSashPosition();
110
111 m_gridVersions->PopEventHandler( true );
112}
113
114
116{
118
119 m_currentSelected = nullptr;
120 m_updateablePackages.clear();
121 m_packagePanels.clear();
122 m_packageInitialOrder.clear();
123 m_packageListWindow->GetSizer()->Clear( true ); // Delete panels
124 m_packageListWindow->GetSizer()->FitInside( m_packageListWindow );
125 m_packageListWindow->Layout();
126}
127
128
129void PANEL_PACKAGES_VIEW::SetData( const std::vector<PACKAGE_VIEW_DATA>& aPackageData )
130{
131 ClearData();
132
133 for( const PACKAGE_VIEW_DATA& data : aPackageData )
134 {
136 m_pinCallback, data );
137
138 package_panel->SetSelectCallback(
139 [package_panel, this] ()
140 {
141 if( m_currentSelected && m_currentSelected != package_panel )
143
144 package_panel->SetSelected( true );
145 m_currentSelected = package_panel;
146 setPackageDetails( package_panel->GetPackageData() );
147
148 Layout();
149 } );
150
151 m_packagePanels.insert( { data.package.identifier, package_panel } );
152 m_packageInitialOrder.push_back( data.package.identifier );
153
154 if( data.state == PPS_UPDATE_AVAILABLE && !data.pinned )
155 m_updateablePackages.insert( data.package.identifier );
156 }
157
160}
161
162
164{
165 const PCM_PACKAGE& package = aPackageData.package;
166
167 // Details
168 wxString details;
169
170 details << wxT( "<h5>" ) + package.name + wxT( "</h5>" );
171
172 auto format_desc =
173 []( const wxString& text ) -> wxString
174 {
175 wxString result;
176 bool inURL = false;
177 wxString url;
178
179 for( unsigned i = 0; i < text.length(); ++i )
180 {
181 wxUniChar c = text[i];
182
183 if( inURL )
184 {
185 if( c == ' ' || c == '\n')
186 {
187 result += wxString::Format( wxT( "<a href='%s'>%s</a>" ), url, url );
188 inURL = false;
189
190 if( c == '\n' )
191 result += wxT( "</p><p>" );
192 else
193 result += c;
194 }
195 else
196 {
197 url += c;
198 }
199 }
200 else if( text.Mid( i, 5 ) == wxT( "http:" )
201 || text.Mid( i, 6 ) == wxT( "https:" ) )
202 {
203 url = c;
204 inURL = true;
205 }
206 else if( c == '\n' )
207 {
208 result += wxT( "</p><p>" );
209 }
210 else
211 {
212 result += c;
213 }
214 }
215
216 if( inURL )
217 result += wxString::Format( wxT( "<a href='%s'>%s</a>" ), url, url );
218
219 return result;
220 };
221
222 wxString desc = package.description_full;
223 details << wxT( "<p>" ) + format_desc( desc ) + wxT( "</p>" );
224
225 details << wxT( "<p><b>" ) + _( "Metadata" ) + wxT( "</b></p>" );
226 details << wxT( "<ul>" );
227 details << wxT( "<li>" ) + _( "Package identifier: " ) + package.identifier + wxT( "</li>" );
228 details << wxT( "<li>" ) + _( "License: " ) + package.license + wxT( "</li>" );
229
230 if( package.tags.size() > 0 )
231 {
232 wxString tags_str;
233
234 for( const std::string& tag : package.tags )
235 {
236 if( !tags_str.IsEmpty() )
237 tags_str += ", ";
238
239 tags_str += tag;
240 }
241
242 details << wxT( "<li>" ) + _( "Tags: " ) + tags_str + wxT( "</li>" );
243 }
244
245 auto format_entry =
246 []( const std::pair<const std::string, wxString>& entry ) -> wxString
247 {
248 wxString name = entry.first;
249 wxString url = EscapeHTML( entry.second );
250
251 if( name == wxT( "email" ) )
252 return wxString::Format( wxT( "<a href='mailto:%s'>%s</a>" ), url, url );
253 else if( url.StartsWith( wxT( "http:" ) ) || url.StartsWith( wxT( "https:" ) ) )
254 return wxString::Format( wxT( "<a href='%s'>%s</a>" ), url, url );
255 else
256 return entry.second;
257 };
258
259 auto write_contact =
260 [&]( const wxString& type, const PCM_CONTACT& contact )
261 {
262 details << wxT( "<li>" ) + type + wxT( ": " ) + contact.name + wxT( "<ul>" );
263
264 for( const std::pair<const std::string, wxString>& entry : contact.contact )
265 {
266 details << wxT( "<li>" );
267 details << entry.first + wxT( ": " ) + format_entry( entry );
268 details << wxT( "</li>" );
269 }
270
271 details << wxT( "</ul>" );
272 };
273
274 write_contact( _( "Author" ), package.author );
275
276 if( package.maintainer )
277 write_contact( _( "Maintainer" ), *package.maintainer );
278
279 if( package.resources.size() > 0 )
280 {
281 details << wxT( "<li>" ) + _( "Resources" ) + wxT( "<ul>" );
282
283 for( const std::pair<const std::string, wxString>& entry : package.resources )
284 {
285 details << wxT( "<li>" );
286 details << entry.first + wxT( ": " );
287 details << format_entry( entry ) + wxT( "</li>" );
288 }
289
290 details << wxT( "</ul>" );
291 }
292
293 details << wxT( "</ul>" );
294
295 m_infoText->SetPage( details );
296
297 wxSizeEvent dummy;
298 OnSizeInfoBox( dummy );
299
300 // Versions table
301 m_gridVersions->Freeze();
302
303 if( m_gridVersions->GetNumberRows() != 0 )
304 m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
305
306 int row = 0;
307 wxString current_version;
308
309 if( aPackageData.state == PPS_INSTALLED || aPackageData.state == PPS_UPDATE_AVAILABLE )
310 current_version = m_pcm->GetInstalledPackageVersion( package.identifier );
311
312 wxFont bold_font = m_gridVersions->GetDefaultCellFont().Bold();
313
314 for( const PACKAGE_VERSION& version : package.versions )
315 {
316 if( !version.compatible && !m_showAllVersions->IsChecked() )
317 continue;
318
319 m_gridVersions->InsertRows( row );
320
321 m_gridVersions->SetCellValue( row, COL_VERSION, version.version );
322 m_gridVersions->SetCellValue( row, COL_DOWNLOAD_SIZE,
323 toHumanReadableSize( version.download_size ) );
324 m_gridVersions->SetCellValue( row, COL_INSTALL_SIZE,
325 toHumanReadableSize( version.install_size ) );
326 m_gridVersions->SetCellValue( row, COL_COMPATIBILITY,
327 version.compatible ? wxT( "\u2714" ) : wxEmptyString );
328 m_gridVersions->SetCellValue( row, COL_STATUS, STATUS_ENUM_TO_STR.at( version.status ) );
329
330 m_gridVersions->SetCellAlignment( row, COL_COMPATIBILITY, wxALIGN_CENTER, wxALIGN_CENTER );
331
332 if( current_version == version.version )
333 {
334 for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
335 m_gridVersions->SetCellFont( row, col, bold_font );
336 }
337
338 row++;
339 }
340
341 for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
342 {
343 // Set the width to see the full contents
344 m_gridVersions->SetColSize( col, m_gridVersions->GetVisibleWidth( col ) );
345 }
346
347 // Autoselect preferred or installed version
348 if( m_gridVersions->GetNumberRows() >= 1 )
349 {
350 wxString version = m_currentSelected->GetPackageData().current_version;
351
352 if( version.IsEmpty() )
353 version = m_currentSelected->GetPreferredVersion();
354
355 if( !version.IsEmpty() )
356 {
357 for( int i = 0; i < m_gridVersions->GetNumberRows(); i++ )
358 {
359 if( m_gridVersions->GetCellValue( i, COL_VERSION ) == version )
360 {
361 m_gridVersions->SelectRow( i );
362 m_gridVersions->SetGridCursor( i, COL_VERSION );
363 break;
364 }
365 }
366 }
367 else
368 {
369 // Fall back to first row.
370 m_gridVersions->SelectRow( 0 );
371 }
372 }
373
374 m_gridVersions->Thaw();
375
376 updateDetailsButtons();
377
378 m_infoText->Show( true );
379 m_sizerVersions->Show( true );
380 m_sizerVersions->Layout();
381
382 wxSize size = m_infoScrollWindow->GetTargetWindow()->GetBestVirtualSize();
383 m_infoScrollWindow->SetVirtualSize( size );
384}
385
386
388{
389 m_infoText->SetPage( wxEmptyString );
390 m_infoText->Show( false );
391 m_sizerVersions->Show( false );
392
393 wxSize size = m_infoScrollWindow->GetTargetWindow()->GetBestVirtualSize();
394 m_infoScrollWindow->SetVirtualSize( size );
395
396 // Clean up grid just so we don't keep stale info around (it's already been hidden).
397 m_gridVersions->Freeze();
398
399 if( m_gridVersions->GetNumberRows() > 0 )
400 m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
401
402 m_gridVersions->Thaw();
403}
404
405
406wxString PANEL_PACKAGES_VIEW::toHumanReadableSize( const std::optional<uint64_t> size ) const
407{
408 if( !size )
409 return wxT( "-" );
410
411 uint64_t b = *size;
412
413 if( b >= 1024 * 1024 )
414 return wxString::Format( wxT( "%.1f MB" ), b / 1000.0 / 1000.0 );
415
416 if( b >= 1024 )
417 return wxString::Format( wxT( "%lld kB" ), b / 1000 );
418
419 return wxString::Format( wxT( "%lld B" ), b );
420}
421
422
424{
425 if( !m_currentSelected )
426 return false;
427
428 return m_gridVersions->GetNumberRows() == 1 || m_gridVersions->GetSelectedRows().size() == 1;
429}
430
431
433{
434 if( !m_currentSelected )
435 return false;
436
437 const PACKAGE_VIEW_DATA& packageData = m_currentSelected->GetPackageData();
438
439 switch( packageData.state )
440 {
443 case PPS_PENDING_UPDATE: return false;
444 default: break;
445 }
446
447 return m_gridVersions->GetNumberRows() == 1 || m_gridVersions->GetSelectedRows().size() == 1;
448}
449
450
451void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId,
452 const PCM_PACKAGE_STATE aState, const bool aPinned )
453{
454 auto it = m_packagePanels.find( aPackageId );
455
456 if( it != m_packagePanels.end() )
457 {
458 it->second->SetState( aState, aPinned );
459
460 if( m_currentSelected && m_currentSelected == it->second )
461 {
462 wxMouseEvent dummy;
464 }
465
466 if( aState == PPS_UPDATE_AVAILABLE && !aPinned )
467 {
468 m_updateablePackages.insert( aPackageId );
469 }
470 else
471 {
472 m_updateablePackages.erase( aPackageId );
473 }
474
476 }
477}
478
479
481{
482 m_gridVersions->ClearSelection();
483 m_gridVersions->SelectRow( event.GetRow() );
484
486}
487
488
490{
491 if( !canDownload() )
492 {
493 wxBell();
494 return;
495 }
496
497 if( m_gridVersions->GetNumberRows() == 1 )
498 m_gridVersions->SelectRow( 0 );
499
500 const wxArrayInt selectedRows = m_gridVersions->GetSelectedRows();
501
502 wxString version = m_gridVersions->GetCellValue( selectedRows[0], COL_VERSION );
503 const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
504
505 auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
506 [&]( const PACKAGE_VERSION& ver )
507 {
508 return ver.version == version;
509 } );
510
511 wxASSERT_MSG( ver_it != package.versions.end(), "Could not find package version" );
512
513 if( !ver_it->download_url )
514 {
515 wxMessageBox( _( "Package download url is not specified" ),
516 _( "Error downloading package" ), wxICON_INFORMATION | wxOK, this );
517 return;
518 }
519
520 const wxString& url = *ver_it->download_url;
521
522 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
523 KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
524
525 wxFileDialog dialog( this, _( "Save package" ), app_settings->m_PcmLastDownloadDir,
526 wxString::Format( wxT( "%s_v%s.zip" ), package.identifier, version ),
527 wxT( "ZIP files (*.zip)|*.zip" ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
528
529 if( dialog.ShowModal() == wxID_CANCEL )
530 return;
531
532 wxString path = dialog.GetPath();
533 app_settings->m_PcmLastDownloadDir = wxPathOnly( path );
534
535 std::ofstream output( path.ToUTF8(), std::ios_base::binary );
536
537 std::unique_ptr<WX_PROGRESS_REPORTER> reporter =
538 std::make_unique<WX_PROGRESS_REPORTER>( this, _( "Downloading package" ), 1 );
539
540 bool success = m_pcm->DownloadToStream( url, &output, reporter.get(), 0 );
541
542 output.close();
543
544 if( success )
545 {
546 if( ver_it->download_sha256 )
547 {
548 std::ifstream stream( path.ToUTF8(), std::ios_base::binary );
549
550 bool matches = m_pcm->VerifyHash( stream, *ver_it->download_sha256 );
551
552 stream.close();
553
554 if( !matches
555 && wxMessageBox(
556 _( "Integrity of the downloaded package could not be verified, hash "
557 "does not match. Are you sure you want to keep this file?" ),
558 _( "Keep downloaded file" ), wxICON_EXCLAMATION | wxYES_NO, this )
559 == wxNO )
560 {
561 wxRemoveFile( path );
562 }
563 }
564 }
565 else
566 {
567 if( wxFileExists( path ) )
568 wxRemoveFile( path );
569 }
570}
571
572
574{
575 if( !canRunAction() )
576 {
577 wxBell();
578 return;
579 }
580
581 PCM_PACKAGE_ACTION action = getAction();
582
583 if( action == PPA_UNINSTALL )
584 {
587 return;
588 }
589
590 if( m_gridVersions->GetNumberRows() == 1 )
591 m_gridVersions->SelectRow( 0 );
592
593 const wxArrayInt selectedRows = m_gridVersions->GetSelectedRows();
594
595 wxString version = m_gridVersions->GetCellValue( selectedRows[0], COL_VERSION );
596 const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
597
598 auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
599 [&]( const PACKAGE_VERSION& ver )
600 {
601 return ver.version == version;
602 } );
603
604 wxCHECK_RET( ver_it != package.versions.end(), "Could not find package version" );
605
606 if( !ver_it->compatible
607 && wxMessageBox( _( "This package version is incompatible with your kicad version or "
608 "platform. Are you sure you want to install it anyway?" ),
609 _( "Install package" ), wxICON_EXCLAMATION | wxYES_NO, this )
610 == wxNO )
611 {
612 return;
613 }
614
615 m_actionCallback( m_currentSelected->GetPackageData(), action, version );
616}
617
618
620{
622 {
623 wxMouseEvent dummy;
625 }
626
628}
629
630
631void PANEL_PACKAGES_VIEW::OnSearchTextChanged( wxCommandEvent& event )
632{
634
637
638 m_currentSelected = nullptr;
639
641}
642
643
645{
646 // Sort by descending rank, ascending index
647 std::vector<std::pair<int, int>> package_ranks;
648
649 const wxString search_term = m_searchCtrl->GetValue().Trim();
650
651 for( size_t index = 0; index < m_packageInitialOrder.size(); index++ )
652 {
653 int rank = 1;
654 const PCM_PACKAGE& pkg =
655 m_packagePanels[m_packageInitialOrder[index]]->GetPackageData().package;
656
657 if( search_term.size() > 2 )
658 rank = m_pcm->GetPackageSearchRank( pkg, search_term );
659
660 // Packages with no versions are delisted and should not be shown
661 if( pkg.versions.size() == 0 )
662 rank = 0;
663
664 package_ranks.emplace_back( rank, index );
665 }
666
667 std::sort( package_ranks.begin(), package_ranks.end(),
668 []( const std::pair<int, int>& a, const std::pair<int, int>& b )
669 {
670 return a.first > b.first || ( a.first == b.first && a.second < b.second );
671 } );
672
673 // Rearrange panels, hide ones with 0 rank
674 wxSizer* sizer = m_packageListWindow->GetSizer();
675 sizer->Clear( false ); // Don't delete panels
676
677 for( const std::pair<int, int>& pair : package_ranks )
678 {
680
681 if( pair.first > 0 )
682 {
683 sizer->Add( panel, 0, wxEXPAND );
684 panel->Show();
685 }
686 else
687 {
688 panel->Hide();
689 }
690 }
691
692 m_packageListWindow->FitInside();
693 m_packageListWindow->SetScrollRate( 0, 15 );
694 m_packageListWindow->SendSizeEvent( wxSEND_EVENT_POST );
695}
696
697
699{
700 m_buttonDownload->Enable( canDownload() );
701
702 if( canRunAction() )
703 {
704 m_buttonAction->Enable();
705
706 PCM_PACKAGE_ACTION action = getAction();
707
708 switch( action )
709 {
710 case PPA_INSTALL: m_buttonAction->SetLabel( _( "Install" ) ); break;
711 case PPA_UNINSTALL: m_buttonAction->SetLabel( _( "Uninstall" ) ); break;
712 case PPA_UPDATE: m_buttonAction->SetLabel( _( "Update" ) ); break;
713 }
714 }
715 else
716 {
717 m_buttonAction->Disable();
718 m_buttonAction->SetLabel( _( "Pending" ) );
719 }
720}
721
722
724{
725 wxASSERT_MSG( m_gridVersions->GetNumberRows() == 1
726 || m_gridVersions->GetSelectedRows().size() == 1,
727 wxT( "getAction() called with ambiguous version selection" ) );
728
729 int selected_row = 0;
730
731 if( m_gridVersions->GetSelectedRows().size() == 1 )
732 selected_row = m_gridVersions->GetSelectedRows()[0];
733
734 wxString version = m_gridVersions->GetCellValue( selected_row, COL_VERSION );
735 const PACKAGE_VIEW_DATA& package = m_currentSelected->GetPackageData();
736
737 switch( package.state )
738 {
739 case PPS_AVAILABLE:
740 case PPS_UNAVAILABLE:
741 return PPA_INSTALL; // Only action for not installed package is to install it
742 case PPS_INSTALLED:
744 if( version == package.current_version )
745 return PPA_UNINSTALL;
746 else
747 return PPA_UPDATE;
748 default:
749 return PPA_INSTALL; // For pending states return value does not matter as button will be disabled
750 }
751}
752
753
754void PANEL_PACKAGES_VIEW::OnSizeInfoBox( wxSizeEvent& aEvent )
755{
756 wxSize infoSize = KIPLATFORM::UI::GetUnobscuredSize( m_infoText->GetParent() );
757 infoSize.x -= 10;
758 m_infoText->SetMinSize( infoSize );
759 m_infoText->SetMaxSize( infoSize );
760 m_infoText->SetSize( infoSize );
761 m_infoText->Layout();
762
763 infoSize.y = m_infoText->GetInternalRepresentation()->GetHeight() + 12;
764 m_infoText->SetMinSize( infoSize );
765 m_infoText->SetMaxSize( infoSize );
766 m_infoText->SetSize( infoSize );
767 m_infoText->Layout();
768
769 Refresh();
770}
771
772
773void PANEL_PACKAGES_VIEW::OnURLClicked( wxHtmlLinkEvent& aEvent )
774{
775 const wxHtmlLinkInfo& info = aEvent.GetLinkInfo();
776 ::wxLaunchDefaultBrowser( info.GetHref() );
777}
778
779
780void PANEL_PACKAGES_VIEW::OnInfoMouseWheel( wxMouseEvent& event )
781{
782 // Transfer scrolling from the info window to its parent scroll window
783 m_infoScrollWindow->HandleOnMouseWheel( event );
784}
785
786
787void PANEL_PACKAGES_VIEW::SetSashOnIdle( wxIdleEvent& aEvent )
788{
789 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
790 m_splitter1->SetSashPosition( cfg->m_PackageManager.sash_pos );
791
792 m_packageListWindow->FitInside();
793
794 m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW::SetSashOnIdle ),
795 NULL, this );
796}
797
798
800{
801 m_buttonUpdateAll->Enable( m_updateablePackages.size() > 0 );
802}
803
804
805void PANEL_PACKAGES_VIEW::OnUpdateAllClicked( wxCommandEvent& event )
806{
807 // The map will be modified by the callback so we copy the list here
808 std::vector<wxString> packages;
809
810 std::copy( m_updateablePackages.begin(), m_updateablePackages.end(),
811 std::back_inserter( packages ) );
812
813 for( const wxString& pkg_id : packages )
814 {
815 auto it = m_packagePanels.find( pkg_id );
816
817 if( it != m_packagePanels.end() )
818 {
819 const PACKAGE_VIEW_DATA& data = it->second->GetPackageData();
820
822 }
823 }
824}
const char * name
Definition: DXF_plotter.cpp:57
PACKAGE_MANAGER m_PackageManager
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
bool SetPage(const wxString &aSource) override
Definition: html_window.cpp:38
wxString m_PcmLastDownloadDir
Class PANEL_PACKAGES_VIEW_BASE.
WX_SPLITTER_WINDOW * m_splitter1
wxScrolledWindow * m_packageListWindow
void m_splitter1OnIdle(wxIdleEvent &)
wxScrolledWindow * m_infoScrollWindow
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
Definition: panel_package.h:92
void SetSelected(bool aSelected)
void SetSelectCallback(const std::function< void()> &aCallback)
Marks panel as selected.
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=true, bool aKeep=false)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:546
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition: wx_panel.h:39
void SetPaneMinimums(int aFirst, int aSecond)
#define GRID_CELL_MARGIN
#define _(s)
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: gtk/ui.cpp:195
std::function< void(const wxString &aPackageId, const PCM_PACKAGE_STATE aState, const bool aPinned)> PinCallback
Definition: panel_package.h:60
std::function< void(const PACKAGE_VIEW_DATA &aData, PCM_PACKAGE_ACTION aAction, const wxString &aVersion)> ActionCallback
Definition: panel_package.h:57
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
PCM_PACKAGE_STATE
Definition: pcm.h:57
@ PPS_INSTALLED
Definition: pcm.h:60
@ PPS_PENDING_UPDATE
Definition: pcm.h:64
@ PPS_UNAVAILABLE
Definition: pcm.h:59
@ PPS_UPDATE_AVAILABLE
Definition: pcm.h:63
@ PPS_PENDING_UNINSTALL
Definition: pcm.h:62
@ PPS_PENDING_INSTALL
Definition: pcm.h:61
@ PPS_AVAILABLE
Definition: pcm.h:58
PCM_PACKAGE_ACTION
Definition: pcm.h:70
@ PPA_UNINSTALL
Definition: pcm.h:72
@ PPA_UPDATE
Definition: pcm.h:73
@ PPA_INSTALL
Definition: pcm.h:71
@ PVS_INVALID
Definition: pcm_data.h:53
@ PVS_DEVELOPMENT
Definition: pcm_data.h:56
@ PVS_STABLE
Definition: pcm_data.h:54
@ PVS_TESTING
Definition: pcm_data.h:55
@ PVS_DEPRECATED
Definition: pcm_data.h:57
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
< Package version metadata Package metadata
Definition: pcm_data.h:75
std::optional< uint64_t > download_size
Definition: pcm_data.h:80
bool compatible
Definition: pcm_data.h:90
std::optional< uint64_t > install_size
Definition: pcm_data.h:81
wxString version
Definition: pcm_data.h:76
PCM_PACKAGE_VERSION_STATUS status
Definition: pcm_data.h:82
< Collection of data relevant to the package display panel Callback for (un)install button
Definition: panel_package.h:31
wxString update_version
Definition: panel_package.h:39
wxString current_version
Definition: panel_package.h:38
PCM_PACKAGE_STATE state
Definition: panel_package.h:34
Repository reference to a resource.
Definition: pcm_data.h:96
wxString name
Definition: pcm_data.h:97
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:108