File Coverage

blib/lib/CPANPLUS/Shell/Wx/ModulePanel.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package CPANPLUS::Shell::Wx::ModulePanel;
2 1     1   2351 use Wx qw[:everything];
  0            
  0            
3             use base qw(Wx::Panel);
4             use Wx::Event qw(EVT_CONTEXT_MENU EVT_WINDOW_CREATE EVT_BUTTON
5             EVT_TREE_SEL_CHANGED EVT_TREE_ITEM_ACTIVATED EVT_RIGHT_DOWN
6             EVT_TREE_ITEM_RIGHT_CLICK);
7             use Wx::ArtProvider qw/:artid :clientid/;
8              
9             #since we want to route calls from here to the module tree,
10             our $AUTOLOAD;
11              
12             use Data::Dumper;
13             use YAML qw/LoadFile Load/;
14             #use File::Spec;
15             #use File::Path;
16             use Storable;
17              
18             use threads;
19             use LWP::Simple;
20             use Wx::Locale gettext => '_T';
21              
22             use CPANPLUS::Shell::Wx::util;
23              
24             sub new{
25             my( $self, $parent, $id, $pos, $size, $style, $name ) = @_;
26             $parent = undef unless defined $parent;
27             $id = -1 unless defined $id;
28             $pos = wxDefaultPosition unless defined $pos;
29             $size = wxDefaultSize unless defined $size;
30             $name = "" unless defined $name;
31             $style = wxTAB_TRAVERSAL unless defined $style;
32              
33             $self = $self->SUPER::new( $parent, $id, $pos, $size, $style, $name );
34             print "New ModulePanel\n";
35             return $self;
36             }
37              
38             #initialize all the children. This was the OnWindowCreate Handler
39             sub Init {
40             my $self = shift;
41              
42             #get references so we can access them easier
43             $self->{parent}=$self->GetParent(); #Wx::Window::FindWindowByName('main_window');
44             $self->{mod_tree}=Wx::Window::FindWindowByName('tree_modules');
45             $self->{mod_tree}->Init();
46             #show info on what we are doing
47             Wx::LogMessage _T("Showing "),$self->{'show'},_T(" by "),$self->{'sort'};
48              
49             #populate tree with default values
50             #$self->{mod_tree}->Populate();
51              
52             #print Dumper $self->{mod_tree};
53             #for testing purposes, insert test values
54             my @testMods=qw/Alter CPAN Cache::BerkeleyDB CPANPLUS Module::NoExist Muck Acme::Time::Baby Wx/;
55             foreach $item (sort(@testMods)){
56             $self->{mod_tree}->AppendItem($self->{mod_tree}->GetRootItem(),$item,$self->{mod_tree}->_get_status_icon($item));
57             }
58              
59             $self->_setup_search();
60             $self->_setup_info_tabs();
61              
62             #my $cMenu=$self->{mod_tree}->GetContextMenu();
63             # $self->{mod_tree}->SetCPP(\&HandleContextInfo);
64             $self->{mod_tree}->SetInfoHandler(\&HandleContextInfo);
65             $self->{mod_tree}->SetClickHandler( sub{$self->HandleTreeClick(@_)});
66             #$self->{mod_tree}->SetDblClickHandler( sub{$self->ShowPODReader(@_)});
67              
68             _uShowErr;
69             }
70             #set up the search bar.
71             sub _setup_search{
72             $self=shift;
73             my $searchbox=Wx::Window::FindWindowByName('cb_main_search');
74             my $typebox=Wx::Window::FindWindowByName('cb_search_type');
75             EVT_TEXT_ENTER( $self,
76             Wx::XmlResource::GetXRCID('cb_main_search'),
77             sub{$self->{list}->search($typebox->GetValue,$searchbox->GetValue);} );
78              
79             my @items=();
80              
81             foreach $term (CPANPLUS::Module->accessors()){
82             $term=~s/^\_//;
83             push(@items,$term) unless grep(/$term/,@items) ;
84             }
85             foreach $term (CPANPLUS::Module::Author->accessors()){
86             $term=~s/^\_//;
87             push(@items,$term) unless grep(/$term/,@items) ;
88             }
89             $typebox->Append(ucfirst($_)) foreach (sort(@items));
90             #$typebox->SetValue(0);
91             }
92              
93              
94             sub _setup_info_tabs{
95             $self=shift;
96             #attach menu events
97             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_more_info'),sub{$self->_get_more_info()} );
98             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_readme'),sub{$self->_info_get_readme()} );
99             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_status'),sub{$self->_info_get_status()} );
100             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_prereqs'),sub{$self->_info_get_prereqs()} );
101             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_files'),sub{$self->_info_get_files()} );
102             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_versions'),sub{$self->_info_get_versions()} );
103             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_contents'),sub{$self->_info_get_contents()} );
104             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_report_this'),sub{$self->_info_get_report_this()} );
105             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_report_all'),sub{$self->_info_get_report_all()} );
106             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_get_validate'),sub{$self->_info_get_validate()} );
107              
108             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_fetch'),sub{$self->{mod_tree}->_fetch_module()} );
109             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_extract'),sub{$self->{mod_tree}->_extract_module()} );
110             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_prepare'),sub{$self->{mod_tree}->_prepare_module()} );
111             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_create'),sub{$self->{mod_tree}->_create_module()} );
112             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_test'),sub{$self->{mod_tree}->_test_module()} );
113             EVT_BUTTON( $self, Wx::XmlResource::GetXRCID('info_install'),sub{$self->{mod_tree}->_install_module()} );
114              
115             }
116             #update only info tab in the lower notebook and clear other items
117             sub HandleTreeClick{
118             my ($self,$tree,$event)=@_;
119              
120             #set global variable for CPANPLUS::Module object of what the user selected
121             $self->{thisName}=$tree->GetName;
122             $self->{thisMod}=$self->_get_mod($self->{thisName});
123              
124             #reset all info in Info pane
125             $self->_info_reset();
126              
127             #return if we can't get an object reference
128             return unless $self->{thisMod};
129              
130             #display info
131             $self->_info_get_info();
132             }
133              
134              
135             # Here, we reroute the calls to ModuleTree
136             sub AUTOLOAD{
137             my $self=shift;
138             my @ops=@_;
139             my $type = ref($self) or return undef;
140             my $func=$AUTOLOAD;
141             #print "$func (".ref($func).") not found in ModulePanel. Trying ModuleTree...\n";
142             $func =~ s/.*:://;
143             if ($self->{mod_tree}->can($func)){
144             @ops=map( ((defined($_))?$_:'undef'),@ops); #make sure undefs are kept undef
145             return $self->{mod_tree}->$func(@ops);
146             }elsif ($self->{mod_tree}->{$func}){
147             return $self->{mod_tree}->{$func};
148             }else{
149             Wx::LogError("$func does not exist!");
150             }
151              
152             }
153              
154             sub HandleContextInfo{
155             my ($self,$menu,$cmd_event,$modName)=@_;
156             my $modtree=Wx::Window::FindWindowByName('tree_modules');
157              
158             $modtree->_get_more_info($self->{cpan}->parse_tree(module=>$modName));
159             }
160              
161             #accessors (should be obvious)
162             sub SetStatusBar{$_[0]->{statusBar}=$_[1];$_[0]->{mod_tree}->SetStatusBar($_[1]);} #any widget that has SetStatusText($txt) method
163             sub GetStatusBar{return $_->{statusbar};}
164             sub SetPODReader{$_[0]->{PODReader}=$_[1];} #must be a CPANPLUS::Shell::Wx::PODReader
165             sub GetPODReader{return $_->{PODReader};}
166             sub SetImageList{ #must be a Wx::ImageList
167             my ($self,$imgList)=@_;
168             $self->{imageList}=$imgList;
169             $self->{mod_tree}->SetImageList($imgList);
170             print "Assigning imagelist....".$imgList->imageList."\n";
171             Wx::Window::FindWindowByName('info_prereqs')->AssignImageList($imgList->imageList);
172             }
173             sub GetImageList{return $_->{imageList};}
174             sub SetModuleTree{$_[0]->{mod_tree}=$_[1];} #must be a CPANPLUS::Shell::Wx::ModuleTree
175             sub GetModuleTree{return $_->{mod_tree};}
176             sub SetCPP{ #must be a CPANPLUS::Backend
177             my $self=shift;
178             my $cpp=shift;
179             $self->{cpan}=$cpp;
180             $self->{config}=$cpp->configure_object;
181             $self->{mod_tree}->{cpan}=$cpp if $self->{mod_tree};
182             $self->{mod_tree}->{config}=$cpp->configure_object if $self->{mod_tree};
183             }
184             sub GetCPP{return $_[0]->{cpan};}
185             sub SetConfig{$_[0]->{config}=$_[1];} #must be a CPANPLUS::Backend::Configure
186             sub GetConfig{return $_[0]->{config};}
187             #sub _get_mod{shift->{mod_tree}->_get_mod(@_)}
188             #sub _get_modname{shift->{mod_tree}->_get_modname(@_)}
189             #sub SetDblClickHandler{$_[0]->{mod_tree}->SetDblClickHandler($_[1]);}
190              
191             ##################################
192             ##### Moved from ModuleTree #####
193             ##################################
194              
195             #get prereqs and fills in Prereqs tab
196             sub _info_get_prereqs{
197             my $self=shift;
198             my $mod=shift||$self->{thisMod};
199             my $version=shift||'';
200              
201             return unless $mod;
202             #set up variables for retrieving and setting data
203             $self->{thisPrereq}=[];
204              
205             #get correct control and clear all items
206             my $preTree=Wx::Window::FindWindowByName('info_prereqs');
207             $preTree->DeleteAllItems();
208             my $root=$preTree->AddRoot('prereqs');
209              
210             #append all prerequisites to root item
211             $self->{mod_tree}->_append_prereq($self->_get_mod($mod,$version),$preTree,$root);
212              
213             #show any CPANPLUS errors in Log tab
214             _uShowErr;
215             }
216              
217             #clears all info fields. Optionally takes a tab name to clear only that tab's fields.
218             sub _info_reset{
219             my $self=shift;
220             my $context=shift;
221              
222             Wx::Window::FindWindowByName('info_tab_text')->SetValue('') unless $self->{thisName};
223             Wx::Window::FindWindowByName('info_tab_text')->SetValue($self->{thisName}._T(" may not exist!")) if (!$context || $context eq 'info');
224             Wx::Window::FindWindowByName('info_report')->DeleteAllItems() if (!$context || $context eq 'report');
225             Wx::Window::FindWindowByName('info_prereqs')->DeleteAllItems() if (!$context || $context eq 'prereqs');
226             Wx::Window::FindWindowByName('info_validate')->Clear() if (!$context || $context eq 'validate');
227             Wx::Window::FindWindowByName('info_files')->Clear() if (!$context || $context eq 'files');
228             Wx::Window::FindWindowByName('info_contents')->Clear() if (!$context || $context eq 'contents');
229             Wx::Window::FindWindowByName('info_readme')->Clear() if (!$context || $context eq 'readme');
230             Wx::Window::FindWindowByName('info_distributions')->Clear() if (!$context || $context eq 'readme');
231             if (!$context || $context eq 'status'){
232             Wx::Window::FindWindowByName('info_status_installed')->SetValue(0);
233             Wx::Window::FindWindowByName('info_status_uninstall')->SetValue(0);
234             Wx::Window::FindWindowByName('info_status_fetch')->SetValue('');
235             Wx::Window::FindWindowByName('info_status_signature')->SetValue(0);
236             Wx::Window::FindWindowByName('info_status_extract')->SetValue('');
237             Wx::Window::FindWindowByName('info_status_created')->SetValue(0);
238             Wx::Window::FindWindowByName('info_status_installer_type')->SetValue('');
239             Wx::Window::FindWindowByName('info_status_checksums')->SetValue('');
240             Wx::Window::FindWindowByName('info_status_checksum_value')->SetValue('');
241             Wx::Window::FindWindowByName('info_status_checksum_ok')->SetValue(0);
242             }
243             }
244              
245             sub _get_more_info{
246             my $self=shift;
247             my $mod=shift||$self->{thisMod};
248             return unless $mod;
249              
250             $self->{statusBar}->SetStatusText(_T("Getting Status for ").$mod->name."...");
251              
252             $progress=Wx::ProgressDialog->new(_T("Getting Extended Info..."),
253             _T("Updating List of Files..."),
254             8,$self,wxPD_APP_MODAL|wxPD_CAN_ABORT|wxPD_ESTIMATED_TIME|wxPD_REMAINING_TIME
255             );
256             $self->_info_get_versions($mod) if $progress->Update(4,_T("Getting Version Information..."));
257             $self->_info_get_files($mod) if $progress->Update(0);
258             $self->_info_get_readme($mod) if $progress->Update(1,_T("Getting README..."));
259             $self->_info_get_status($mod) if $progress->Update(2,_T("Getting Status for ").$self->{thisName}."...");
260             $self->_info_get_prereqs($mod) if $progress->Update(3,_T("Getting Prerequisites for ").$self->{thisName}."...");
261             $self->_info_get_contents($mod) if $progress->Update(5,_T("Getting Contents..."));
262             $self->_info_get_report_all($mod) if $progress->Update(6,_T("Getting Reports..."));
263             $self->_info_get_validate($mod) if $progress->Update(7,_T("Validating Module..."));
264              
265             $self->{statusBar}->SetStatusText('');
266             $progress->Destroy();
267             _uShowErr;
268              
269             }
270              
271             sub _info_get_files{
272             my $self=shift;
273             my $mod=shift||$self->{thisMod};
274             return unless $mod;
275              
276             $self->{statusBar}->SetStatusText(_T("Getting File Info..."));
277             my $info_files=Wx::Window::FindWindowByName('info_files');
278             $info_files->Clear();
279              
280             my @files=$mod->files();
281             my $text=$mod->name._T(" has ").(@files || _T('NO'))._T(" installed files:\n");
282             foreach $file (@files){
283             $text.="$file\n";
284             }
285             $text.=_T("There was a problem retrieving the file information for this module.\n").
286             ("Please see the log for more info.\n") unless @files;
287             $info_files->AppendText($text);
288             _uShowErr;
289             }
290             sub _info_get_info{
291             my $self=shift;
292             my $mod=shift||$self->{mod_tree}->GetMod();
293             #return unless $mod;
294              
295             my $info_ctrl=Wx::Window::FindWindowByName('info_tab_text');
296             $info_ctrl->Clear();
297             $self->{statusBar}->SetStatusText(_T("Getting Info for ").$mod->name."...");
298              
299             my $status_info_text='';
300             #update info panel
301             unless ($mod){
302             $info_ctrl->AppendText(_T("No Information Found!"));
303             }else{
304             my $info=$mod->details();
305             $status_info_text.=_T("\tAuthor\t\t\t\t").$info->{'Author'}."\n" if $info->{'Author'};
306             $status_info_text.=_T("\tDescription\t\t\t").$info->{'Description'}."\n" if $info->{'Description'};
307             $status_info_text.=_T("\tIs Perl Core?\t\t\t").($mod->package_is_perl_core()?_T('Yes'):_T('No'))."\n";
308             $status_info_text.=_T("\tDevelopment Stage\t").$info->{'Development Stage'}."\n" if $info->{'Development Stage'};
309             $status_info_text.=_T("\tInstalled File\t\t\t").$info->{'Installed File'}."\n" if $info->{'Installed File'};
310             $status_info_text.=_T("\tInterface Style\t\t").$info->{'Interface Style'}."\n" if $info->{'Interface Style'};
311             $status_info_text.=_T("\tLanguage Used\t\t").$info->{'Language Used'}."\n" if $info->{'Language Used'};
312             $status_info_text.=_T("\tPackage\t\t\t\t").$info->{'Package'}."\n" if $info->{'Package'};
313             $status_info_text.=_T("\tPublic License\t\t").$info->{'Public License'}."\n" if $info->{'Public License'};
314             $status_info_text.=_T("\tSupport Level\t\t").$info->{'Support Level'}."\n" if $info->{'Support Level'};
315             $status_info_text.=_T("\tVersion Installed\t\t").$info->{'Version Installed'}."\n" if $info->{'Version Installed'};
316             $status_info_text.=_T("\tVersion on CPAN\t\t").$info->{'Version on CPAN'}."\n" if $info->{'Version on CPAN'};
317             $status_info_text.=_T("\tComment\t\t\t").($mod->comment || 'N/A')."\n";
318             $status_info_text.=_T("\tPath On Mirror\t\t").($mod->path || 'N/A')."\n";
319             $status_info_text.=_T("\tdslip\t\t\t\t").($mod->dslip || 'N/A')."\n";
320             $status_info_text.=_T("\tIs Bundle?\t\t\t").($mod->is_bundle()?_T('Yes'):_T('No'))."\n";
321             #third-party information
322             $status_info_text.=_T("\tThird-Party?\t\t\t").($mod->is_third_party()?_T('Yes'):_T('No'))."\n";
323             if ($mod->is_third_party()) {
324             my $info = $self->{cpan}->module_information($mod->name);
325             $status_info_text.=
326             _T("\t\tIncluded In\t\t").$info->{name}."\n".
327             _T("\t\tModule URI\t").$info->{url}."\n".
328             _T("\t\tAuthor\t\t\t").$info->{author}."\n".
329             _T("\t\tAuthor URI\t").$info->{author_url}."\n";
330             }
331             $info_ctrl->AppendText($status_info_text);
332             $info_ctrl->ShowPosition(0);
333             }
334             $self->{statusBar}->SetStatusText('');
335             _uShowErr;
336              
337              
338             }
339             sub _info_get_versions{
340             my $self=shift;
341             my $mod=shift||$self->{thisMod};
342             return unless $mod;
343              
344             $self->{statusBar}->SetStatusText(_T("Getting Version Info for ").$mod->name."...");
345             my $versionList=Wx::Window::FindWindowByName('info_distributions');
346             $versionList->Clear();
347              
348             my @versions=();
349             foreach $m ($mod->distributions()){
350             my $v=($m->version || 0.0) if $m;
351             push(@versions,$v) unless (grep(/$v/,@versions));
352             }
353             @versions=sort(@versions);
354             my $numInList=@versions;
355             $versionList->Append($_) foreach (@versions);
356             $versionList->SetValue($versions[-1]);
357             #$versionList->SetFirstItem($numInList);
358              
359             _uShowErr;
360             }
361              
362             #get installer status info
363             #TODO Make this work! Store status info after build into file
364             #Update the status tab
365             sub _info_get_status{
366             my $self=shift;
367             my $mod=shift||$self->{thisMod};
368             return unless $mod;
369             Wx::LogMessage _T("Getting status for ").$mod->name."...";
370              
371             #get status from module
372             my $status=$mod->status();
373              
374             #if we haven't retrieved the file and the stored info exists
375             #then use the stored values
376             my $statFile=_uGetPath($self->{config},'cpp_stat_file');
377             if (!defined($status->fetch) && -e $statFile && (my $Allstatus=retrieve($statFile)) ){
378             $thisStat=$Allstatus->{$mod->name};
379             $status=$thisStat if $Allstatus->{$mod->name};
380             }
381             #print Dumper $status;
382             Wx::Window::FindWindowByName('info_status_installed')->SetValue($status->installed || 0);
383             Wx::Window::FindWindowByName('info_status_uninstall')->SetValue($status->uninstall || 0);
384             Wx::Window::FindWindowByName('info_status_fetch')->SetValue($status->fetch||'n/a');
385             Wx::Window::FindWindowByName('info_status_signature')->SetValue($status->signature||0);
386             Wx::Window::FindWindowByName('info_status_extract')->SetValue($status->extract||'n/a');
387             Wx::Window::FindWindowByName('info_status_created')->SetValue($status->created||0);
388             Wx::Window::FindWindowByName('info_status_installer_type')->SetValue($status->installer_type||'n/a');
389             Wx::Window::FindWindowByName('info_status_checksums')->SetValue($status->checksums || 'n/a');
390             Wx::Window::FindWindowByName('info_status_checksum_value')->SetValue($status->checksum_value||'n/a');
391             Wx::Window::FindWindowByName('info_status_checksum_ok')->SetValue($status->checksum_ok || 0);
392             _uShowErr;
393              
394             }
395              
396             #get the readme file
397             sub _info_get_readme{
398             my $self=shift;
399             my $mod=shift||$self->{thisMod};
400             return unless $mod;
401             my $info_readme=Wx::Window::FindWindowByName('info_readme');
402             $info_readme->Clear();
403             $info_readme->AppendText(($mod->readme || 'No README Found! Check Log for more information.'));
404             $info_readme->ShowPosition(0);
405             _uShowErr;
406             }
407              
408             sub _info_get_contents{
409             my $self=shift;
410             my $mod=shift||$self->{thisMod};
411             return unless $mod;
412             my $info_contents=Wx::Window::FindWindowByName('info_contents');
413             $info_contents->Clear();
414             my $txt='';
415             foreach $m (sort {lc($a->name) cmp lc($b->name)} $mod->contains() ){
416             $txt.=$m->name."\n";
417             }
418             $info_contents->AppendText($txt);
419             $info_contents->ShowPosition(0); #set visible position to beginning
420             _uShowErr;
421             }
422             sub _info_get_validate{
423             my $self=shift;
424             my $mod=shift||$self->{thisMod};
425             return unless $mod;
426             my $display=Wx::Window::FindWindowByName('info_validate');
427             $display->Clear();
428             my $txt='';
429             foreach $file (sort($mod->validate) ){
430             $txt.=$file."\n";
431             }
432             $display->AppendText( ($txt || _T("No Missing Files or No Information. See Log.")) );
433             $display->ShowPosition(0); #set visible position to beginning
434             _uShowErr;
435             }
436              
437              
438             sub _info_get_report_all{
439             my $self=shift;
440             my $mod=shift||$self->{thisMod};
441             return unless $mod;
442             my $info_report=Wx::Window::FindWindowByName('info_report');
443             $info_report->DeleteAllItems();
444              
445             #set up the listctrl
446             unless ($info_report->GetColumnCount == 3){
447             while ($info_report->GetColumnCount){
448             $info_report->DeleteColumn(0);
449             }
450             $info_report->InsertColumn( 0, _T('Distribution'));
451             $info_report->InsertColumn( 1, _T('Platform') );
452             $info_report->InsertColumn( 2, _T('Grade') );
453             }
454             my @versions=$mod->fetch_report(all_versions => 1, verbose => 1);
455             @versions=reverse(sort { lc($a->{platform}) cmp lc($b->{platform})} @versions);
456             # print Dumper $versions[0];
457             foreach $item (@versions ){
458             $info_report->InsertStringItem( 0, $item->{'dist'} );
459             $info_report->SetItem( 0, 1, $item->{'platform'} );
460             $info_report->SetItem( 0, 2, $item->{'grade'} );
461             }
462             $info_report->SetColumnWidth(0,wxLIST_AUTOSIZE);
463             $info_report->SetColumnWidth(1,wxLIST_AUTOSIZE);
464             $info_report->SetColumnWidth(2,wxLIST_AUTOSIZE);
465             _uShowErr;
466             }
467             sub _info_get_report_this{
468             my $self=shift;
469             my $mod=shift||$self->{thisMod};
470             return unless $mod;
471             my $info_report=Wx::Window::FindWindowByName('info_report');
472             $info_report->DeleteAllItems();
473              
474             #set up the listctrl
475             unless ($info_report->GetColumnCount == 3){
476             while ($info_report->GetColumnCount){
477             $info_report->DeleteColumn(0);
478             }
479             $info_report->InsertColumn( 0, _T('Distribution') );
480             $info_report->InsertColumn( 1, _T('Platform') );
481             $info_report->InsertColumn( 2, _T('Grade') );
482             }
483              
484             my @versions=$mod->fetch_report(all_versions => 0, verbose => 1);
485             @versions=reverse(sort { lc($a->{platform}) cmp lc($b->{platform})} @versions);
486             foreach $item (@versions ){
487             $info_report->InsertStringItem( 0, $item->{'dist'} );
488             $info_report->SetItem( 0, 1, $item->{'platform'} );
489             $info_report->SetItem( 0, 2, $item->{'grade'} );
490             }
491             $info_report->SetColumnWidth(0,wxLIST_AUTOSIZE);
492             $info_report->SetColumnWidth(1,wxLIST_AUTOSIZE);
493             $info_report->SetColumnWidth(2,wxLIST_AUTOSIZE);
494             _uShowErr;
495             }
496              
497             sub GetInfo{
498             my ($menu,$cmd_event,$modName)=@_;
499             my $modtree=$self->{mod_tree};
500              
501             $modtree->_get_more_info($modtree->_get_mod($modName));
502             }
503              
504             1;