view release on metacpan or search on metacpan
Version 10, June 2011
- tests more diagnostics on the Test::Weaken checks
Version 9, October 2010
- don't raise on every error, too instrusive
Version 8, September 2010
- test manifest only as an author test
Version 7, August 2010
- oops, fix popup out of exception_handler()
Version 6, August 2010
- new "Popup on Error" check button
Version 5, December 2009
- new max-chars property limiting textbuf size
- new action signals for clear and popup-save-dialog
- protect against repeated errors from idle handler itself
Version 4, October 2009
- support messages during perl "compile error" by using a Glib
idle to defer dialog loading
Version 3, March 2009
- during "global destruction" only print to STDERR
Version 2, March 2009
devel/Action.pm view on Meta::CPAN
$dialog->present;
}
1;
__END__
=for stopwords
=head1 NAME
Gtk2::Ex::ErrorTextDialog::Action -- Gtk2::Action to popup the errors dialog
=for test_synopsis my ($actiongroup)
=head1 SYNOPSIS
use Gtk2::Ex::ErrorTextDialog::Action;
my $action = Gtk2::Ex::ErrorTextDialog::Action->new;
$actiongroup->add_action_with_accel ($action, '<Ctrl><Shift>E');
=head1 OBJECT HIERARCHY
devel/Action.pm view on Meta::CPAN
Gtk2::Action
Gtk2::Ex::ErrorTextDialog::Action
=head1 DESCRIPTION
C<Gtk2::Ex::ErrorTextDialog::Action> invokes either C<back> or C<forward> on
a given C<Gtk2::Ex::ErrorTextDialog>. The "stock" icon and tooltip follow
the direction. The action is insensitive when the history is empty.
When the action is used on a toolbar button a mouse button-3 handler is
added to popup C<Gtk2::Ex::ErrorTextDialog::Menu>.
If you're not using UIManager and its actions system then see
L<Gtk2::Ex::ErrorTextDialog::Button> for similar button-3 behaviour.
There's no accelerator keys offered as yet. "B" and "F" would be natural,
but would depend what other things are in the UIManager and whether letters
should be reserved for text entry etc, or are available as accelerators.
Control-B and Control-F aren't good choices if using a text entry as they're
cursor movement in the Emacs style
F</usr/share/themes/Emacs/gtk-2.0-key/gtkrc>.
devel/max-chars.pl view on Meta::CPAN
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->signal_connect (destroy => sub {
print "$progname: quit\n";
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new (0, 0);
$toplevel->add ($vbox);
# Gtk2::Ex::ErrorTextDialog->popup;
{
my $button = Gtk2::Button->new_with_label ("add_message()");
$vbox->pack_start ($button, 0,0,0);
my $count = 0;
$button->signal_connect
(clicked => sub {
print "$progname: add_message()\n";
$count++;
Gtk2::Ex::ErrorTextDialog->add_message
devel/max-chars.pl view on Meta::CPAN
my $textbuf = $errtext->{'textbuf'};
print "$progname: char_count ",$textbuf->get_char_count,"\n";
});
}
{
my $button = Gtk2::Button->new_with_label ("big add_message()");
$button->signal_connect
(clicked => sub {
print "$progname: big add_message()\n";
Gtk2::Ex::ErrorTextDialog->popup_add_message
(join ("\n", 1 .. 50));
my $errtext = Gtk2::Ex::ErrorTextDialog->instance;
my $textbuf = $errtext->{'textbuf'};
print "$progname: char_count ",$textbuf->get_char_count,"\n";
});
$vbox->pack_start ($button, 0,0,0);
}
$toplevel->show_all;
Gtk2->main;
devel/run.pl view on Meta::CPAN
Gtk2->init;
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->signal_connect (destroy => sub {
print "$progname: quit\n";
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new (0, 0);
$toplevel->add ($vbox);
# Gtk2::Ex::ErrorTextDialog->popup;
{
my $button = Gtk2::Button->new_with_label ("add_message()");
$button->signal_connect (clicked => sub {
print "$progname: add\n";
require Gtk2::Ex::ErrorTextDialog;
Gtk2::Ex::ErrorTextDialog->popup_add_message("\
hello
fdjsk
fsdjkl
\x{C1}
fsdjk fkjsd kfj sdk
ksdjfksdksdjf s
");
# \x{2028}\x{2029}\x{2014}\x{204A}
});
devel/run.pl view on Meta::CPAN
});
$vbox->pack_start ($button, 0,0,0);
Glib::Log->set_handler ('My-Domain', ['warning','info'],
\&Gtk2::Ex::ErrorTextDialog::Handler::log_handler);
if (Glib::Log->can('set_default_handler')) {
Glib::Log->set_default_handler (\&Gtk2::Ex::ErrorTextDialog::Handler::log_handler);
}
}
{
my $n = 1;
my $button = Gtk2::Button->new_with_label ("popup_add_message()");
$button->signal_connect (clicked => sub {
Gtk2::Ex::ErrorTextDialog->popup_add_message ("hello world $n");
$n++;
});
$vbox->pack_start ($button, 0,0,0);
}
{
my $button = Gtk2::Button->new_with_label ("big add_message()");
$button->signal_connect
(clicked => sub {
Gtk2::Ex::ErrorTextDialog->popup_add_message
(join ("\n", 1 .. 50));
});
$vbox->pack_start ($button, 0,0,0);
}
{
my $button = Gtk2::Button->new_with_label ("present() dialog");
$button->signal_connect
(clicked => sub {
Gtk2::Ex::ErrorTextDialog->instance->present;
});
devel/run.pl view on Meta::CPAN
} else {
Glib->install_exception_handler
(sub {
print STDERR "Glib exception handler:\n";
goto \&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler;
});
}
# Glib::Log->set_default_handler (sub {
# my $dialog = Gtk2::Ex::ErrorTextDialog->popup;
# $dialog->glog_handler(@_);
# });
# sub glog_handler {
# my ($self, $log_domain, $log_level, $message) = @_;
# my $str = ((defined $log_domain ? "$log_domain-" : "** ")
# . "\U$log_level\E: "
# . (defined $message ? $message : "(no message)"));
# $self->add_message ($str);
# }
examples/keybindings.pl view on Meta::CPAN
# with Gtk2-Ex-ErrorTextDialog. If not, see <http://www.gnu.org/licenses/>.
# Usage: ./keybindings.pl
#
# Customized key bindings for the action signals in an ErrorTextDialog can
# be made in the usual way. It's as easy as putting a "binding" blob like
# below in your ~/.gtkrc-2.0 file, or programmatically with a Gtk2::Rc call
# as done here.
#
# Of course "clear" and "popup-save-dialog" aren't needed so often you'd
# really want extra key bindings for them, but the action signal + rc
# mechanism lets an application or user customize keys as desired.
#
use 5.008;
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::ErrorTextDialog;
Gtk2::Rc->parse_string (<<'HERE');
binding "my_error_keys" {
bind "F5" { "popup-save-dialog" () }
bind "F6" { "clear" () }
}
class "Gtk2__Ex__ErrorTextDialog" binding:application "my_error_keys"
HERE
my $errdialog = Gtk2::Ex::ErrorTextDialog->new;
$errdialog->signal_connect (destroy => sub { Gtk2->main_quit });
$errdialog->add_message ('This is an example of customized key bindings for action signals.');
$errdialog->add_message ('Press function key F5 for "popup-save-dialog".
Or press function key F6 to "clear" these messages!');
$errdialog->add_message ('These are in addition to the stock button mnemonics,
Alt-A for Save-As and Alt-C for Clear
(or whatever comes out in your locale).');
$errdialog->present;
Gtk2->main;
exit 0;
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
use Glib::Object::Subclass
'Gtk2::MessageDialog',
signals => { destroy => \&_do_destroy,
clear =>
{ param_types => [],
return_type => undef,
class_closure => \&_do_clear,
flags => ['run-last','action'] },
popup_save_dialog =>
{ param_types => [],
return_type => undef,
class_closure => \&_do_popup_save_dialog,
flags => ['run-last','action'] },
},
properties => [ Glib::ParamSpec->int
('max-chars',
__('Maximum characters'),
'Maximum number of characters to retain, or -1 for unlimited.',
-1, # minimum
POSIX::INT_MAX(), # maximum
200_000, # default
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
my $title = __('Errors');
if (defined (my $appname = Glib::get_application_name())) {
$title = "$appname: $title";
}
$self->set_title ($title);
}
$self->set (message_type => 'error',
resizable => 1);
{
my $check = $self->{'popup_checkbutton'}
= Gtk2::CheckButton->new_with_mnemonic (__('_Popup on Error'));
$check->set_active (1);
Glib::Ex::ObjectBits::set_property_maybe
($check,
# tooltip-text new in Gtk 2.12
tooltip_text => __('Whether to popup this dialog when an error occurs.
If errors are occurring repeatedly you might not want a popup every time.'));
$self->add_action_widget ($check, 'none');
}
{
my $button = $self->add_button ('gtk-save-as', $self->RESPONSE_SAVE);
Glib::Ex::ObjectBits::set_property_maybe
($button,
# tooltip-text new in Gtk 2.12
tooltip_text => __('Save the error messages to a file, perhaps to include in a bug report.
(Cut and paste works too, but saving may be better for very long messages.)'));
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
#-----------------------------------------------------------------------------
# button/response actions
sub _do_response {
my ($self, $response) = @_;
if ($response eq $self->RESPONSE_CLEAR) {
$self->clear;
} elsif ($response eq $self->RESPONSE_SAVE) {
$self->popup_save_dialog;
} elsif ($response eq 'close') {
# as per a keyboard close, defaults to raising 'delete-event', which in
# turn defaults to a destroy
$self->signal_emit ('close');
}
}
sub clear {
my ($self) = @_;
$self = $self->instance unless ref $self;
$self->signal_emit ('clear');
}
sub _do_clear {
my ($self) = @_;
my $textbuf = $self->{'textbuf'};
$textbuf->delete ($textbuf->get_start_iter, $textbuf->get_end_iter);
}
sub popup_save_dialog {
my ($self) = @_;
$self = $self->instance unless ref $self;
$self->signal_emit ('popup-save-dialog');
}
sub _do_popup_save_dialog {
my ($self) = @_;
$self->_save_dialog->present;
}
# create and return the save dialog -- might make this public one day
sub _save_dialog {
my ($self) = @_;
return ($self->{'save_dialog'} ||= do {
require Gtk2::Ex::ErrorTextDialog::SaveDialog;
my $save_dialog = Gtk2::Ex::ErrorTextDialog::SaveDialog->new;
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
# TRANSLATORS: The code currently assumes this string is 80 chars or less.
my $discard_message = __('[Older messages discarded]');
$textbuf->delete ($textbuf->get_start_iter,
$textbuf->get_iter_at_offset ($len - $max_chars));
$textbuf->insert ($textbuf->get_start_iter,
"$discard_message\n\n");
}
# not sure about this yet, an in particular which popup follows the
# popup-on-error checkbox and which is a programmatic always popup ...
#
# =item C<< Gtk2::Ex::ErrorTextDialog->popup_add_message ($str) >>
#
# =item C<< Gtk2::Ex::ErrorTextDialog->popup_add_message ($str, $parent) >>
#
# =item C<< $errordialog->popup_add_message ($str) >>
#
# =item C<< $errordialog->popup_add_message ($str, $parent) >>
#
# Add C<$str> to the error dialog with C<add_message> below, and popup the
# dialog so it's visible.
#
# Optional C<$parent> is a widget which the error relates to, or C<undef> for
# none. C<$parent> may help the window manager position the error dialog when
# first displayed, but is not used after that.
#
# not documented yet ...
sub popup_add_message {
my ($self, $msg, $parent) = @_;
$self = $self->instance unless ref $self;
if ($self->{'popup_checkbutton'}->get_active) {
$self->popup ($parent);
}
$self->add_message ($msg);
}
# not documented yet ...
sub popup {
my ($self, $parent) = @_;
$self = $self->instance unless ref $self;
if ($self->mapped) {
# too intrusive to raise every time
# $self->window->raise;
} else {
# allow for $parent a non-toplevel
if ($parent) { $parent = $parent->get_toplevel; }
$self->set_transient_for ($parent);
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
$log_level -= ['recursion','fatal'];
$log_level = join('-', @$log_level) || 'LOG';
return (($log_domain ? "$log_domain-" : "** ")
. "\U$log_level\E: "
. (defined $message ? $message : "(no message)"));
}
# probably not wanted ...
# sub popup_add_log {
# my ($class_or_self, $log_domain, $log_level, $message, $parent) = @_;
# $self->popup ($parent);
# $self->add_log ($log_domain, $log_level, $message);
# }
# sub add_log {
# my ($class_or_self, $log_domain, $log_level, $message) = @_;
# $class_or_self->add_message
# (_log_to_string ($log_domain, $log_level, $message));
# }
#-----------------------------------------------------------------------------
# generic helpers
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
The following are provided both as "action signals" for use from C<Gtk2::Rc>
key bindings and methods for use from program code.
=over 4
=item C<clear> action signal (no parameters)
Remove all messages from the dialog. This is the "Clear" button action.
=item C<popup-save-dialog> action signal (no parameters)
Popup the Save dialog, which asks the user for a filename to save the error
messages to. This is the "Save As" button action.
=item C<< Gtk2::Ex::ErrorTextDialog->clear() >>
=item C<< Gtk2::Ex::ErrorTextDialog->popup_save_dialog() >>
=item C<< $errordialog->clear() >>
=item C<< $errordialog->popup_save_dialog() >>
Emit the C<clear> or C<popup-save-dialog> signals, respectively. The
default handler in those signals does the actual work of clearing or showing
the save dialog and as usual for action signals that's the place to override
or specialize in a subclass.
=item C<< $id = Gtk2::Ex::ErrorTextDialog->RESPONSE_CLEAR >>
=item C<< $id = Gtk2::Ex::ErrorTextDialog->RESPONSE_SAVE >>
Return the dialog respond ID for the clear and save actions. These are the
responses raised by the clear and save buttons. The clear response could be
lib/Gtk2/Ex/ErrorTextDialog.pm view on Meta::CPAN
=back
=head2 Key Bindings
The stock Clear and Save-As button mnemonic keys invoke the clear and save
actions, but there's no further key bindings by default. You can add keys
in the usual way from the C<Gtk2::Rc> mechanism. The class is
C<Gtk2__Ex__ErrorTextDialog> so for example in your F<~/.gtkrc-2.0> file
binding "my_error_keys" {
bind "F5" { "popup-save-dialog" () }
}
class "Gtk2__Ex__ErrorTextDialog" binding:rc "my_error_keys"
See F<examples/keybindings.pl> in the sources for a complete program doing
this.
=head1 PROPERTIES
=over 4
lib/Gtk2/Ex/ErrorTextDialog/Handler.pm view on Meta::CPAN
$_idle_handler_id ||= Glib::Idle->add
(\&_idle_handler, undef, Glib::G_PRIORITY_HIGH);
}
if (DEBUG) { print STDERR "exception_handler() end\n"; }
return 1; # stay installed
}
# $_idle_handler_id is zapped at the start so exception_handler() will add
# another _idle_handler() for any further messages generated within the
# present _idle_handler() run. Anything before popup_add_message() will be
# covered by the present run, but anything after it needs another run.
#
# $_idle_recursions is incremented at the start as a worst case assumption
# that the code will die. Then if the code runs successfully to the end it
# can be cleared. It's cleared only if there were no further messages
# generated from within _idle_handler(). Further messages are noted by
# exception_handler() setting $_idle_another_message.
#
sub _idle_handler {
$_idle_recursions++;
$_idle_another_message = 0;
undef $_idle_handler_id;
if (DEBUG) { print STDERR "idle_handler() runs $_idle_recursions\n"; }
require Gtk2::Ex::ErrorTextDialog;
Gtk2::Ex::ErrorTextDialog->popup_add_message (undef);
if (! $_idle_another_message) {
$_idle_recursions = 0;
}
if (DEBUG) {
print STDERR "idle_handler() end, recursions now $_idle_recursions\n";
}
return 0; # Glib::SOURCE_REMOVE
}
po/Gtk2-Ex-ErrorTextDialog.pot view on Meta::CPAN
#: lib/Gtk2/Ex/ErrorTextDialog.pm:96
msgid "Errors"
msgstr ""
#: lib/Gtk2/Ex/ErrorTextDialog.pm:107
msgid "_Popup on Error"
msgstr ""
#: lib/Gtk2/Ex/ErrorTextDialog.pm:112
msgid ""
"Whether to popup this dialog when an error occurs.\n"
"If errors are occurring repeatedly you might not want a popup every time."
msgstr ""
#: lib/Gtk2/Ex/ErrorTextDialog.pm:122
msgid ""
"Save the error messages to a file, perhaps to include in a bug report.\n"
"(Cut and paste works too, but saving may be better for very long messages.)"
msgstr ""
#: lib/Gtk2/Ex/ErrorTextDialog.pm:177
msgid "An error has occurred"
t/ErrorTextDialog.t view on Meta::CPAN
$dialog->destroy;
}
#-----------------------------------------------------------------------------
# action signals
{
my $dialog = Gtk2::Ex::ErrorTextDialog->new;
my $textbuf = $dialog->{'textbuf'};
my ($find_popup) = grep {$_->{'signal_name'} eq 'popup-save-dialog'}
Glib::Type->list_signals ('Gtk2::Ex::ErrorTextDialog');
ok ($find_popup, 'have "popup-save-dialog" signal');
if ($find_popup) {
diag "$find_popup->{'signal_name'} $find_popup->{'signal_id'} $find_popup->{'itype'} $find_popup->{'signal_flags'}";
}
$dialog->add_message ('hello');
my $saw_popup = 0;
$dialog->signal_connect (popup_save_dialog => sub { $saw_popup = 1 });
{ local $SIG{'__WARN__'} = \&MyTestHelpers::warn_suppress_gtk_icon;
$dialog->popup_save_dialog;
}
is ($saw_popup, 1, 'popup_save_dialog() emits "popup-save-dialog"');
isnt ($textbuf->get_char_count, 0, 'popup - textbuf still has message');
$dialog->add_message ('hello');
my $saw_clear = 0;
$dialog->signal_connect (clear => sub { $saw_clear = 1 });
$dialog->clear;
is ($saw_clear, 1, 'clear() emits "clear"');
is ($textbuf->get_char_count, 0, 'clear - textbuf now empty');
$dialog->destroy;
}
#-----------------------------------------------------------------------------
# popup_add_message()
{
Gtk2::Ex::ErrorTextDialog->popup_add_message ('hello');
my $dialog = Gtk2::Ex::ErrorTextDialog->instance;
isa_ok ($dialog, 'Gtk2::Ex::ErrorTextDialog');
$dialog->popup_add_message ('hello');
}
exit 0;