[Kde-perl] Why isn't this easy? implementing File->New

Joe Carlson joe at fruitfly.org
Wed Aug 2 18:38:55 CEST 2006


Darrik and Ashley,

Thanks for the info. I appreciate the 'garbage collection done him
wrong' advice. This is definitely it.

But I have now a comment or two about these methods. It seems like all
of these are ways to create references to the newly created top-level
windows to keep the reference count from going to zero and getting
destroyed. But it seems to me that this needs to be done at a global (or
application) level. If I keep a list of the new windows I've created
within the first window, what happens when I close the first window? In
trying out different things, I'm seeing that the created windows also
close. (Of course maybe it's some quirk about how I've scoped
variables...) There are some cases where closing the creating window
also closes the created, but this isn't what I'm looking for. I was
trying out Darrik's hash-the-reference approach and seeing this
behavior. (In addition, it seemed to me that if I opened a third window
after opening one from from the first, the second window closed. Again,
maybe that was a scoping issue.)  

What I see as the simplest way to beat the garbage collection is to
simple put a self reference in the class

package MyView;
...
use Qt::attributes qw(selfReference ...);
...
sub NEW {
...
  selfReference = this;
...
and so on.

In my playing around, this gives me all the right behavior. But if
future collectors get more clever and see that this is a circular
reference all bets are off. The only iron clad way to keep the reference
is to make a list a global scope

push @main::windowList, $newWindow;

But now here's the thing: this now is reproducing the C++ behavior,
warts and all. The C++ code is simple, I just 'new' me up a main window
and call show on it. And we've manage to make it this simple in the perl
code. But we've just created a memory leak since we've made no
allowances for freeing memory after the created windows are closed.

If I use the self-reference trick, then I need to reset this before
calling close:

sub processFileMenu {
...
  if ($option == FILECLOSE) {
    selfReference = '';
    this->close();
  }
...

I've been testing this out with print's in the module's DESTROY method
and things seem to be cleaning up properly. I'm going to try this out.
The only other option I can think of is to use the application level
list and emit signal when there is a request to close the top level
window and have the application deal with removing the reference from
the list.

Thanks,

Joe

On Tue, 2006-08-01 at 23:12 -0700, Ashley Winters wrote:
> --- darrik <darrik at mythofbutterfly.com> wrote:
> 
> > Ashley Winters wrote:
> > > use strict;
> > > use Qt;     # use Qt in EVERY package! It declares 'this', and does
> > > other use-strict-happy things
> > > use MyView;
> > > sub processFileMenu {
> > > 	if ($option==FILENEW) {
> > > 		MyView(this)->show;
> > > 	}
> > > }
> > 
> > You're not storing a perl reference to the new window anywhere.  What
> > 
> > happens when you want to access that window from the parent later?
> 
> Ahh, in that case you want to store it as a member variable. If, for
> example, we wanted to populate the Window menu with the list of windows
> opened with File->New or something...
> 
> package YourClass;
> use strict;
> use Qt;
> use Qt::isa qw(Qt::Widget);
> use Qt::attributes qw(windows);    # declare a member variable
> use MyView;
> 
> sub NEW {
>     # standard preamble
> 
>     windows = [];    # initialize as an array
> }
> 
> sub processFileMenu {
> 	if ($option==FILENEW) {
> 		my $viewer = MyView(this);
> 		$viewer->show;
> 		push @{ windows }, $viewer;
> 	}
> }
> 
> > 
> > This is more evident when you subclass a container widget that has
> > child 
> > controls.  For instance:
> 
> I'll make the edits inline...
> 
> > 
> > use strict;
> > 
> > package MyWidget;
> > 
> > use Qt;
> > use Qt::isa qw( Qt::Widget );
> 
> use Qt::attributes qw( lbl );
> 
> > 
> > sub NEW {
> >    # irrelevant method arguments left out for brevity :P
> > 
> >    my $class=shift;
> >    my $parent=shift;
> >    shift->SUPER::NEW($parent);
> >    my $layout=Qt::HBoxLayout(this);
> #>    my $lbl=Qt::Label("label",this);
> #>    $layout->addWidget($lbl);
> 
>     # instead
>     lbl = Qt::Label("label",this);
>     $layout->addWidget(lbl);
> > }
> > 
> > sub changeChildLabel {
> >    # how do you access $lbl here?
>     lbl->setText("Qt::attributes");
> > }
> 
> 
> > This part has me confused.  Storing $lbl in a package variable
> > doesn't 
> > work if you instantiate several MyWidget's.  I've been using
> > workarounds 
> > that are inelegant, so a pointer to the *proper* way to do this would
> > be 
> > immensely appreciated.
> 
> Sure. Keep in mind that the 'this' function/variable/keyword thing is,
> in fact, a hash. You're free to store things in it, like so:
> 
> this->{'lbl'} = Qt::Label(...);
> 
> In fact, that's all the Qt::attributes pragma does, is setup that
> shortcut. It automatically creates a lbl() function which returns
> this->{'lbl'}, in a way that lets you assign to it (as an lvalue).
> 
> That's the technical side, at least. For more of a tutorial, read this:
> 
> http://perlqt.sourceforge.net/dist/current/doc/en/index.html#using_attributes
> 
> - Ashley Winters
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam protection around 
> http://mail.yahoo.com 
> _______________________________________________
> Kde-perl mailing list
> Kde-perl at kde.org
> https://mail.kde.org/mailman/listinfo/kde-perl
> 



More information about the Kde-perl mailing list