PDF Viewing Support (poppler-qt4)

Gunnar Sletta gunnar at trolltech.com
Fri Feb 15 10:17:33 CET 2008


Adam Batkin wrote:

> Pages get constructed on-the-fly by (for example) calling 
> Document->page(n). You can then do various useful things, in my case 
> just page->renderToImage() is enough, and out pops a nice QImage. But: 
> my PdfDocument could get garbage collected (and the underlying Document 
> deleted) while there are still outstanding PdfPage (and Page) objects 
> lying about.
> 
> I'm thinking that I'll solve this by replacing my bare pointer to the 
> Document (in my PdfDocument class) with a reference counted proxy, then 
> make sure that each PdfPage also keeps a copy of its underlying 
> Document. Does this sound reasonable? Are there other common patterns to 
> solving patterns like this? I know that in the C++ world this type of 
> solution is common, but I was kind-of hoping that the generator would 
> have some magic to make that all go away.

We cover this exact case because it doesn't appear in Qt. It does, but 
in that case the objects are QObjects and then they are covered by other 
rules ;-)

We have the <reference-count> attribute which is documented here:
http://doc.trolltech.com/qtjambi-4.3.3_01/com/trolltech/qt/qtjambi-typesystem.html#reference-count
which can do a lot with ownership handling. For instance when you have

   lineEdit.setCompleter(completer)

we have a reference-count node where the lineEdit java object gets a 
private completer member and thus keeps a java reference to it. When the 
lineedit is collected this reference goes away and the completer can be 
collected on the next pass. Of course doing:

   lineEdit.setCompleter(null)

will in turn reset the private reference to null allowing the original 
completer to be deleted.


I would suggest that you do a similar approach with your page object, 
namely let the java Page object keep hold of a private member to the 
document assuring you that it will be alive. The way we normally do this 
is by "hiding the original page() function" and replacing it with one 
that does the right thing. In pseudo code:

// Insert a Document member into the page object.
<object-type name="Page">
   <inject-code class="java">
     Document theDocument;
   </inject-code>
</object-type>

// hide the original Document.page() function and replace it
// with one that sets the "theDocument" ref on the returned page
<object-type name="Document">
   <modify-function signature="page()const"
                    access="private"
                    rename="page_helper" />
   <inject-code class="java">
     public Page page() {
         Page page = page_helper();
         page.theDocument = this;
         return page;
     }
   </inject-code>
</object-type>

So, when the page() function gets called it you'll call you own version 
of it which sets up the reference. As long as the Page object is alive 
there will be a reference to the Document object and it cannot be 
collected. I hope this helps you a little bit.

best regards,
Gunnar



More information about the Qt-jambi-interest mailing list