[PyQt] PyQt.QtHelp - QFSFileEngine::open: No file name specified

Hans-Peter Jansen hpj at urpla.net
Wed Nov 24 14:43:08 GMT 2010

On Wednesday 24 November 2010, 13:54:50 romain wrote:
> Hans-Peter Jansen wrote:
>  > On Tuesday 23 November 2010, 14:28:16 romain wrote:
>  >> Hi everybody,
>  >>
>  >> I am facing an issue when I use the PyQt.QtHelp module. I have
>  >> generated a .qhc file containing the documentation I want to
>  >> embed into my soft so users can access it directly. It is made up
>  >> with .html pages.
>  >>
>  >> I have joined the code in attachment. I simplified it so it can
>  >> be used in a "stand-alone" software, but it is in fact part of a
>  >> bigger program. My problem is the same in both cases anyway.
>  >>
>  >> (This code is more or less the same as in the QtHelp example from
>  >> Qt
>  >>
>  >> : http://doc.trolltech.com/qq/qq28-qthelp.html and
>  >>
>  >> http://doc.trolltech.com/qq/qq28-qthelp.zip for the example
>  >> code).
>  >>
>  >> When I launch my soft, and click on one of the link of the table
>  >> of content, the error message "QFSFileEngine::open: No file name
>  >> specified" is displayed, and consequently the documentation is
>  >> not displayed. The HelpBrowser.loadResources() method is called
>  >> by HelpBrowser.setSource() when a link of the table of content is
>  >> double-clicked.
>  >
>  > No, a method named HelpBrowser.loadResource() is called.
>  >
>  > Btw, you are covering a few python keywords in your code (type,
>  > help).
>  >
>  > It's usually a good practice to call parent methods with super
>  > (will save you from editing every method invocation, if you rebase
>  > your class one day, which usually results in _nasty_ behavior),
>  > and you and your typing fingers _really_ want to use PyQt's new
>  > style signals, I sure.
> Thanks for your answer. I changed that and added a few documentation
> in the code.
> The class QHelpEngine is used to embed documentation in a program (as
> Qt assistant does). It provides widgets for the search, index and
> table of content (I only use the TOC in the example).
> The documentation itself is generated from html files and results in
> .qhc and .qch files. The generation is done by using the
> qhelpgenerator and the qcollectiongenerator tools provided by Qt.
> These files are a kind of compressed documentation, including the
> table of content.
> Then, to access the content of these files a QHelpEngine musts be
> used, and more precisely the method QHelpEngine.fileData(QUrl url).
> The URL musts be something like
> "qthelp://namespace/virtual_folder/resource.html". `namespace` and
> `virtual_folder` are defined when the documentation is generated.
> `resource.html` is the page we want to display. The method fileData
> of the QHelpEngine extracts the html contained in the resource.
> To summarize, I generate the doc, load it with a QHelpEngine and
> display the TOC. A click on a link in the TOC emits the signal
> `linkActivated(QUrl)`, which in my case is connected to
> `HelpBrowser.setSource(QUrl)` slot.
> But the documentation is not displayed due to the fact that the error
> "QFSFileEngine::open: No file name specified" occurs. I do not
> understand why. The method HelpBrowser.loadResources should be called
> for each style sheets and images of the page.

Romain, did you read my answer? Anyway, here is the cruical part again:

No, a method named HelpBrowser.loadResource() is called. Yours is named:

Hopefully, you you're able to spot the difference now. Btw, you still 
cover "help", "type", and missed the super calls in the c'tors. For 
that reason, your argument shuffle is suboptimal, better would be:

class HelpBrowser(QTextBrowser):
        def __init__(self, helpEngine, parent = None):
           super(HelpBrowser, self).__init__(parent)
           self.__helpEngine = helpEngine

        def loadResource(self, type_, url):
            if url.scheme() == "qthelp":
                return self.__helpEngine.fileData(url)
            return super(HelpBrowser, self).loadResources(type_, url)

Check the parent arg.
This might need something like before the very first PyQt4 import:

import sip
sip.setapi('QVariant', 2)

and is a good idea for new code anyway (similar to QString elimination).


More information about the PyQt mailing list