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

Andrew Snyder asnyder at ariasystems.net
Wed Aug 2 20:05:57 CEST 2006


I'd go with a package scoped variable. Any reason why this wouldn't work?

package MyView;
our %window_list;
...
...
sub NEW {
...
  $window_list{$self}++;
...
}

sub DESTROY
{
   my $self = shift;
   if (defined $window_list{$self})
   {
      delete $window_list{$self};
   }
...
}




On Wednesday 02 August 2006 12:38, Joe Carlson wrote:
> 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_attrib
> >utes
> >
> > - 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
>
> _______________________________________________
> Kde-perl mailing list
> Kde-perl at kde.org
> https://mail.kde.org/mailman/listinfo/kde-perl

-- 
Andrew Snyder



More information about the Kde-perl mailing list