Re: Converting from Gtk2 -> Gtk3 Notes



On 24.09.2013 01:08, Terence Ferraro wrote:
I have included below various changes, gotchas, and general notes I
accrued in converting our application from perl Gtk2 to perl Gtk3.

Thanks a lot, this is really useful.  I started a similar list in Gtk3's
POD: <https://metacpan.org/module/Gtk3#Porting-from-Gtk2-to-Gtk3>.  I
welcome any extensions and improvements.

Near the bottom, you'll also notice some changes I made directly to
Gtk3.pm. I suppose I could have created a diff as these changes were
made to produce backward-compatible functionality but, they essentially
break the "new" Gtk3 style for those widgets. However, if anyone else
needs to convert a major project over, these changes will shave a *lot*
of time off of said conversion.

Gtk3 is not promising API-stability yet, so any changes that make
porting from Gtk2 easier can in principal be applied even if they change
API.

Some specific comments on your notes follow.

Was: $widget->isa(Gtk2::Window)
Now: ? (Started calling $widget->get_toplevel for similar functionality
with respect to our system)

$widget->isa('Gtk3::Window') should work.

Was: ComboBoxEntry->get_child;
Now: Gtk3::Bin::get_child($combo)

$combo->get_child should work.

Was: my $loader = Gtk2::Gdk::PixbufLoader->new; $loader->write($img);
Now: my $loader = Gtk3::Gdk::PixbufLoader->new; $loader->write([unpack
'C*', $imgdata]);

We could add an override for this similar to
Gtk3::Gdk::Pixbuf::new_from_inline.  Patches welcome.

Was: Gtk2::RadioButton->new
Now: Gtk3::RadioButton->new_with_label
Was: Gtk2::CheckButton->new
Now: Gtk3::CheckButton->new_with_label

Could add overrides similar to the one for Gtk3::RadioMenuItem.  Patches
welcome.

Was: $group = $radio->get_group; $radio1 =
Gtk2::RadioButton->new($group,'Label');
Now: $radio1 = Gtk2::RadioButton->new($radio,'Label');

There are still some problems with the group-based radio API.  You might
have better luck with the widget-based API.

Can't use: $store->get_value($iter,0,1,2,3,4);
Must use: $store->get($iter,0,1,2,3,4);

I didn't keep this alias because the name "get_value" and multiple
column indices don't make sense together.  You can still use get_value
to fetch the value of a single column.

Lazy loading gtk3 doesn't seem to work, can't use "require", must use "use"

That's due to the INIT block in Glib::Object::Introspection.  I'm open
to suggestions on how to implement this differently.

Both Frame and Labels must be passed a blank string '' instead of no value

Could add overrides.  Patches welcome.

Can't use $button->set_image(undef) needs to be
$button0->set_image(Gtk3::Image::new);

Looks like gtk_button_set_image is missing an "allow none" annotation.
So, gtk+ needs to be patched.

drag_source_set and drag_dest_set used to require a target_table array
defined purely in perl. Also, the argument order has changed slightly.
Used to be: $widget->drag_source_set(['button1_mask', 'button3_mask'],
['copy', 'move'], @targets); Now, requires an array of Gtk3::TargetEntry
and must be called as such:
    @targets=
    (
        Gtk3::TargetEntry->new('STRING',0,ID_ICONVIEW),
        Gtk3::TargetEntry->new('text/uri-list',0,ID_URI),
        Gtk3::TargetEntry->new('text/plain',0,ID_LABEL),
    );
$widget->drag_source_set (['button1_mask', 'button3_mask'],
\ main::target_table, ['copy','move']);
$widget->drag_dest_set('all', \ main::target_table, ['copy', 'move']);

Could add an override, at least for converting pure-Perl target entry
arrays.  I'd prefer the order to stay consistent with the C API.
Patches welcome.

my $oldcolor = $widget->get_style->bg('normal'); had to replaced with:
sub getbackgroundcolorfrombutton
{
    my ($button) = @_;
   
    my $style = $button->get_style;
    my $stylecontext = $style->get_property('context');
    my $bgcolor = $stylecontext->get_property('background-color','normal');
    my $bgstring = $bgcolor->to_string;
    my @a = split(/\(/, $bgstring);
    my @b = split(/,/, $a[1]);
    my $one = uc(sprintf("%x",$b[0]));
    my $two = uc(sprintf("%x",$b[1]));
    my $three = uc(sprintf("%x",$b[2]));
    if(length($one) == 1) { $one = '0' . $one; }
    if(length($two) == 1) { $two = '0' . $two; }
    if(length($three) == 1) { $three = '0' . $three; }
   
    my $oldcolor = [Gtk3::Gdk::Color::parse('#' . $one . $two .
$three)]->[1];
    return($oldcolor);
}

This should work:

  my $style_context = $button->get_style_context;
  my $bg_rgba = $style_context->get_property ("background-color", "normal");
  my $bg_rgb = Gtk3::Gdk::Color::parse ($bg_rgba->to_string);

But note that there should be an RGBA alternative form of whatever API
you pass an RGB color to.

$button->set_always_show_image(1); should be called if set_image and
set_label are both used. This was not necessary in Gtk2.

I think in gtk+ 3 this is a user or theme setting that should not be
altered by a program without a very good reason.

need to replace all instances of Gtk3::Gdk::Color::parse('#EEEEEE') with
[Gtk3::Gdk::Color::parse('#EEEEEE')]->[1]

Could add an override similar to Gtk3::Gdk::RGBA::parse.  Patches welcome.

Allocation can no longer be pulled as $draw->allocation. Is now: my
$allocation = Gtk3::Widget::get_allocation($docdraw); Must then be
referenced as a hash as noted above

$widget->get_allocation should work.

Instead of
Gtk2::Gdk::Cairo::Context::set_source_pixbuf($cairocontext,0,0) should
not be dealing with pixbuf anymore when rendering, instead take png
images and convert to image surfaces:
    my $fh = new IO::Scalar \$png;
    my $tempsurface = Cairo::ImageSurface->create_from_png_stream(sub {
my ($fh, $length) = @_; my $tempdata; my $nread =
sysread($fh,$tempdata,$length) or print "Couldn't read\n";
return($tempdata); },$fh);
    close($fh);
    $context->set_source_surface($tempsurface,0,0);

I haven't looked at the gdk<->cairo stuff yet, but does this work perhaps?

  Gtk3::Gdk::cairo_set_source_pixbuf ($cr, $pixbuf, $x, $y)

We definitely need some overrides here.

$treeview->set_cursor($path) should now be
$treeview->set_cursor($path,undef,0);

Could add an override.  Patches welcome.

my $keyval = "Gtk3::Gdk::KEY_$char"; my $key = eval($keyval);

What's wrong with simple string interpolation?

my @selection =
$main::plantinventorytree->get_selection->get_selected_rows; now returns
a two-dimensional array instead of one.

That's intentional, and it's documented in the POD.

Modified Gtk3.pm to include the following in both:
Gtk3::TreeStore::insert_with_values and Gtk3::ListStore::insert_with_values
if(length($position) == 0) { $position = 0; }

Why?  $position is supposed to be an integer.  Are you passing in an
empty string?

Modified Gtk3.pm to include the following override method as to not
break 90% of my program:
sub Gtk3::Entry::set_text {
if(!defined($_[1])) { $_[1] = ''; }
  return Glib::Object::Introspection->invoke (
    $_GTK_BASENAME, 'Entry', 'set_text',($_[0],$_[1]));
}

The C API doesn't accept NULL, so I don't think the Perl API should
accept undef.

Added the following override due to random breakage returning valid
(unintialized) iters causing all sorts of issues with previous assuming
definedness was a valid check
sub Gtk3::ComboBox::get_active_iter
{
    my ($combo) = @_;
   
    my ($bool,$iter) = Glib::Object::Introspection->invoke (
    $_GTK_BASENAME, 'ComboBox', 'get_active_iter', $combo);

    if($bool == 1) { return($iter); }
    else { return(undef); }
}

"Gtk3::ComboBox::get_active_iter" needs to be added to
@_GTK_HANDLE_SENTINEL_BOOLEAN_FOR.  Patches welcome.

sub Gtk3::Frame::new {
    my $frame = Glib::Object::Introspection->invoke ( $_GTK_BASENAME,
'Frame', 'new', ('',''));
    $frame->set_label(undef);
    return($frame);
}

gtk+ is missing an "allow none" annotation for gtk_frame_new.

sub Gtk3::TextBuffer::set_text {
if(!defined($_[1])) { $_[1] = ''; }
  return Glib::Object::Introspection->invoke (
    $_GTK_BASENAME, 'TextBuffer', 'set_text',
    @_ == 3 ? @_ : (@_[0,1], -1)); # wants length in bytes
}

See my comment about Gtk3::Entry::set_text above.

Can't use: for($iter = $store->get_iter_first;$iter;$iter = 
$store->iter_next($iter))
Tried using this initially: my $valid = 1; for($iter =
$store->get_iter_first;$valid;$valid = $store->iter_next($iter))
However, direct modification of iters *severely* broke a ton of code, so
added this to Gtk3.pm:

Do you have a short example that demonstrates this breakage?


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]