There are three common ways to provide an online help system. One approach is to provide the help in the form of HTML files, and to launch a Web browser set to the relevant page. Another is to use the Qt Assistant application provided with Qt. The third approach is to provide a help form, again using HTML, but with the images and HTML files as resources.
Image Changer Help
Image Changer Help
The first approach can be achieved by launching a Web browser as a separate process, using either Python's subprocess module, or PyQt's QProcess class. Qt 4.2 introduced a new class, QDesktopServices, that makes it really easy to launch a browser in a platform-independent way with its openUrl() static convenience method.
The second approach is trickier, since it requires us to create an XML file in a special format and to distribute Qt Assistant with our application. The advantage of using Qt Assistant is that it provides automatic indexing.
The third approach, using a custom help form and with HTML files and images Re- as resources, is the one that we will use. We saw back in Chapter 6 when we looked at resource files, that we could include arbitrary files, including HTML files, and we incorporated some demo help files in our resources.qrc file. Here is the code for the Image Changer's MainWindow.helpHelp() method:
def helpHelp(self):
form = helpform.HelpForm("index.html", self) form.show()
source files
Using our help form is easy: We just give it one of the HTML files, and self (over which the form will center itself). Notice that we use show() rather than exec_(); this almost always means that the form shown will have the delete on close attribute set.
The screenshot in Figure 17.1 may give the misleading impression that keyboard users are not catered to, but in fact, the class used to show the HTML files, QTextBrowser, provides good keyboard support. For example, users can press Tab to move the focus from hyperlink to hyperlink, and Enter to follow a hyperlink. They can go back by pressing Alt+Left Arrow, and they can go to the first page by pressing Home. And because the form is a QDialog subclass, they can close the window by pressing Esc.
By now we are very familiar with creating PyQt dialogs, so we will confine ourselves to showing just those extracts that are relevant to creating the online help system—specifically, a couple of extracts from the HelpForm's initializer, and one of its methods. (The code is in chap17/helpform.py.)
class HelpForm(QDialog):
def_init_(self, page, parent=None):
super(HelpForm, self)._init_(parent)
self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_GroupLeader)
The Qt.WA_GroupLeader attribute ensures that if the help form is invoked from a modal dialog, the user will be able to interact with both the modal dialog and the help form, something that would not be possible otherwise. If the help form is invoked from a modeless dialog or main window, the attribute has no effect, and the user can interact with both as usual.
self.textBrowser.setSearchPaths([":/"]) self.textBrowser.setSource(QUrl(page))
The QTextBrowser class is a subclass of QTextEdit that can be used to display a large subset of HTML tags, including images, lists, and tables. We have set its search path to the resource file's root directory, and set its initial page to be the page that was passed in. Because we have set a search path we are able to pass a page without a path (e.g., simply index.html or filemenu.html). The QTextBrowser understands resource paths, and is therefore able to find image resources in <img> tags such as <img src=":/filenew.png">.
self.connect(backAction, SIGNAL("triggered()"), self.textBrowser, SLOT("backward()")) self.connect(homeAction, SIGNAL("triggered()"), self.textBrowser, SLOT("home()")) self.connect(self.textBrowser, SIGNAL("sourceChanged(QUrl)"), self.updatePageTitle)
Navigating from page to page is handled automatically by the QTextBrowser. Nonetheless, we have provided two toolbar buttons, Back and Home, and connected them to the appropriate QTextBrowser slots to get the behavior we want. If the HTML document is changed—for example, due to the user clicking a hyperlink—we call a custom updatePageTitle() slot.
def updatePageTitle(self):
self.pageLabel.setText(self.textBrowser.documentTitleO)
This slot simply puts the HTML page's <title> text in a QLabel that is in the toolbar, to the right of the toolbar buttons.
Once we have a HelpForm class, we can implement our online help system entirely in HTML, either including the files as resources, or installing them in the filesystem and finding them using code like this:
helppath = os.path.join(os.path.dirname(_file_), "help")
This assumes that the help files are in a help directory that resides in the directory where the application's .pyw file is located.
Writing the code to provide an online help system is straightforward; but designing a system that is easy to navigate, and that is understandable, can be quite a challenge..