App-Devel-MAT-Explorer-GTK
view release on metacpan or search on metacpan
bin/pmat-explore-gtk view on Meta::CPAN
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use Glib qw( TRUE FALSE );
use Gtk2 -init;
use Gtk2::SimpleList;
use Devel::MAT;
use List::Util qw( pairs );
use List::UtilsBy qw( sort_by );
use App::Devel::MAT::Explorer::GTK::Resources qw( get_icon );
use App::Devel::MAT::Explorer::GTK::Shell;
use App::Devel::MAT::Explorer::GTK::SVDetail;
use App::Devel::MAT::Explorer::GTK::Utils qw( bytes2size );
use App::Devel::MAT::Explorer::GTK::Widgets qw( framed vscrollable );
my $pmat;
my $df;
my $win = Gtk2::Window->new( "toplevel" );
$win->signal_connect( destroy => sub { Gtk2->main_quit } );
$win->resize( 1000, 600 );
my $winbox = Gtk2::VBox->new( 0, 0 );
$win->add( $winbox );
my $menu = Gtk2::MenuBar->new;
$winbox->pack_start( $menu, FALSE, TRUE, 0 );
my $filemenu = add_submenu( $menu, "File" );
add_menuitem( $filemenu, "Quit" => sub { Gtk2->main_quit } );
my $navmenu = add_submenu( $menu, "Navigate" );
my $toolbar = Gtk2::Toolbar->new;
$toolbar->set_style( 'both' );
$winbox->pack_start( $toolbar, FALSE, TRUE, 0 );
my $backbtn = $toolbar->append_item( "Back", "Go back to the previous SV", "",
Gtk2::Image->new_from_stock("gtk-go-back", "small-toolbar"), \&history_back );
my $forwardbtn = $toolbar->append_item( "Forward", "Go forward to the next SV", "",
Gtk2::Image->new_from_stock("gtk-go-forward", "small-toolbar"), \&history_forward );
my $svs_loaded;
my $outrefs_mth = "outrefs";
my $inrefs_mth = "inrefs";
{
my %mode_buttons;
my %mode_tooltip = (
All => "Display and count every kind of inref and outref",
Direct => "Display and count only direct inrefs and outrefs",
Strong => "Display and count only strong direct inrefs and outrefs",
);
Devel::MAT::UI->provides_radiobutton_set(
map {
my $filter = $_ eq "All" ? "" : "_\L$_";
Devel::MAT::UI->register_icon(
name => "refs-$_",
svg => "icons/refs-$_.svg"
);
{
text => $_,
icon => "refs-$_",
tooltip => $mode_tooltip{$_},
code => sub {
$outrefs_mth = "outrefs$filter";
$inrefs_mth = "inrefs$filter";
reset_svlist_refs() if $svs_loaded;
redisplay_sv();
},
bin/pmat-explore-gtk view on Meta::CPAN
}
sub Devel::MAT::UI::current_sv
{
return $current_sv;
}
}
add_menuitem( $navmenu, "Back" => \&history_back );
add_menuitem( $navmenu, "Forward" => \&history_forward );
add_menuitem( $navmenu, "By address..." => sub {
defined( my $addr = entry_dialog( "Enter SV address" ) ) or return;
$addr = hex $addr;
if( my $sv = $df->sv_at( $addr ) ) {
history_nav( $sv );
}
else {
progress( sprintf "Cannot navigate by address: no such SV at 0x%x", $addr );
}
});
add_menuitem( $navmenu, "By symbol..." => sub {
defined( my $symb = entry_dialog( "Enter symbol name" ) ) or return;
if( my $sv = eval { $pmat->find_symbol( $symb ) } ) {
history_nav( $sv );
}
else {
chomp( my $e = $@ );
progress( "Cannot navigate by symbol: $e" );
}
});
my $rootmenu = add_submenu( $menu, "Roots" );
my $toolmenu;
foreach my $tool ( sort Devel::MAT->available_tools ) {
my $tool_class = "Devel::MAT::Tool::$tool";
next unless $tool_class->can( "FOR_UI" ) and $tool_class->FOR_UI;
$toolmenu ||= add_submenu( $menu, "Tools" );
add_menuitem( $toolmenu, $tool, sub {
my ( $mi ) = @_;
$mi->set_sensitive( FALSE );
my $tool = $pmat->load_tool( $tool, progress => \&progress );
$tool->init_ui( "Devel::MAT::UI" );
progress();
});
}
$winbox->add( my $vpane = Gtk2::VPaned->new );
$vpane->pack1( my $hpane = Gtk2::HPaned->new, TRUE, TRUE );
my $statusbar = Gtk2::Statusbar->new;
$winbox->pack_end( $statusbar, FALSE, TRUE, 0 );
$statusbar->pack_start( framed( my $perlver_label = Gtk2::Label->new( "" ) ), FALSE, FALSE, 0 );
$statusbar->pack_start( framed( my $svcount_label = Gtk2::Label->new( "" ) ), FALSE, FALSE, 0 );
$statusbar->pack_start( framed( my $bytetotal_label = Gtk2::Label->new( "" ) ), FALSE, FALSE, 0 );
$win->show_all;
{
my $id = $statusbar->get_context_id( "progress" );
sub progress
{
$statusbar->pop( $id );
$statusbar->push( $id, "Progress: $_[0]" ) if defined $_[0];
Gtk2->main_iteration_do( FALSE ) while Gtk2->events_pending;
}
}
my $filename = $ARGV[0] or die "Need dumpfile\n";
$win->set_title( "$filename - pmat-explore-gtk" );
$pmat = Devel::MAT->load( $filename, progress => \&progress );
$df = $pmat->dumpfile;
$perlver_label->set_text( join " ", "Perl",
$df->perlversion,
( $df->ithreads ? "thread" : () ),
( $df->ptr_len * 8 ) . "bit",
);
$svcount_label->set_text( scalar($df->heap) . " SVs" );
# We're going to be using Inrefs
$pmat->load_tool( "Inrefs", progress => \&progress );
foreach ( pairs $df->roots ) {
my ( $desc, $sv ) = @$_;
add_menuitem( $rootmenu, $desc, sub { history_nav( $sv ) } ) if $sv;
}
my $svlist_model = Gtk2::ListStore->new(
"Glib::String",
( $df->ptr_len > 4 ? "Glib::Long" : "Glib::Int" ),
"Glib::String",
"Glib::Int",
"Glib::String",
"Glib::Int",
"Glib::Int",
);
# UI column constants
sub Devel::MAT::UI::COLUMN_TYPE () { 0 }
sub Devel::MAT::UI::COLUMN_ADDR () { 1 }
sub Devel::MAT::UI::COLUMN_DESC () { 2 }
sub Devel::MAT::UI::COLUMN_SIZE () { 3 }
sub Devel::MAT::UI::COLUMN_BLESSED() { 4 }
sub Devel::MAT::UI::COLUMN_OUTREFS() { 5 }
sub Devel::MAT::UI::COLUMN_INREFS () { 6 }
my $svlist_view = Gtk2::TreeView->new;
$svlist_view->set_model( $svlist_model );
sub add_svlist_column
{
( run in 0.501 second using v1.01-cache-2.11-cpan-e1769b4cff6 )