1#!/usr/bin/env python3
2
3#****************************************************************************
4# helpview.py, provides a window for viewing an html help file
5#
6# Copyright (C) 2017, Douglas W. Bell
7#
8# This is free software; you can redistribute it and/or modify it under the
9# terms of the GNU General Public License, either Version 2 or any later
10# version.  This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY.  See the included LICENSE file for details.
12#*****************************************************************************
13
14from PyQt5.QtCore import QUrl, Qt
15from PyQt5.QtGui import QTextDocument
16from PyQt5.QtWidgets import (QAction, QLabel, QLineEdit, QMainWindow, QMenu,
17                             QStatusBar, QTextBrowser)
18import dataeditors
19
20
21class HelpView(QMainWindow):
22    """Main window for viewing an html help file.
23    """
24    def __init__(self, pathObj, caption, icons, parent=None):
25        """Helpview initialize with text.
26
27        Arguments:
28            pathObj -- a path object for the help file
29            caption -- the window caption
30            icons -- dict of view icons
31        """
32        QMainWindow.__init__(self, parent)
33        self.setAttribute(Qt.WA_QuitOnClose, False)
34        self.setWindowFlags(Qt.Window)
35        self.setStatusBar(QStatusBar())
36        self.textView = HelpViewer(self)
37        self.setCentralWidget(self.textView)
38        self.textView.setSearchPaths([str(pathObj.parent)])
39        self.textView.setSource(QUrl(pathObj.as_uri()))
40        self.resize(520, 440)
41        self.setWindowTitle(caption)
42        tools = self.addToolBar(_('Tools'))
43        self.menu = QMenu(self.textView)
44        self.textView.highlighted[str].connect(self.showLink)
45
46        backAct = QAction(_('&Back'), self)
47        backAct.setIcon(icons['helpback'])
48        tools.addAction(backAct)
49        self.menu.addAction(backAct)
50        backAct.triggered.connect(self.textView.backward)
51        backAct.setEnabled(False)
52        self.textView.backwardAvailable.connect(backAct.setEnabled)
53
54        forwardAct = QAction(_('&Forward'), self)
55        forwardAct.setIcon(icons['helpforward'])
56        tools.addAction(forwardAct)
57        self.menu.addAction(forwardAct)
58        forwardAct.triggered.connect(self.textView.forward)
59        forwardAct.setEnabled(False)
60        self.textView.forwardAvailable.connect(forwardAct.setEnabled)
61
62        homeAct = QAction(_('&Home'), self)
63        homeAct.setIcon(icons['helphome'])
64        tools.addAction(homeAct)
65        self.menu.addAction(homeAct)
66        homeAct.triggered.connect(self.textView.home)
67
68        tools.addSeparator()
69        tools.addSeparator()
70        findLabel = QLabel(_(' Find: '), self)
71        tools.addWidget(findLabel)
72        self.findEdit = QLineEdit(self)
73        tools.addWidget(self.findEdit)
74        self.findEdit.textEdited.connect(self.findTextChanged)
75        self.findEdit.returnPressed.connect(self.findNext)
76
77        self.findPreviousAct = QAction(_('Find &Previous'), self)
78        self.findPreviousAct.setIcon(icons['helpprevious'])
79        tools.addAction(self.findPreviousAct)
80        self.menu.addAction(self.findPreviousAct)
81        self.findPreviousAct.triggered.connect(self.findPrevious)
82        self.findPreviousAct.setEnabled(False)
83
84        self.findNextAct = QAction(_('Find &Next'), self)
85        self.findNextAct.setIcon(icons['helpnext'])
86        tools.addAction(self.findNextAct)
87        self.menu.addAction(self.findNextAct)
88        self.findNextAct.triggered.connect(self.findNext)
89        self.findNextAct.setEnabled(False)
90
91    def showLink(self, text):
92        """Send link text to the statusbar.
93
94        Arguments:
95            text -- link text to show
96        """
97        self.statusBar().showMessage(text)
98
99    def findTextChanged(self, text):
100        """Update find controls based on text in text edit.
101
102        Arguments:
103            text -- the search text
104        """
105        self.findPreviousAct.setEnabled(len(text) > 0)
106        self.findNextAct.setEnabled(len(text) > 0)
107
108    def findPrevious(self):
109        """Command to find the previous string.
110        """
111        if self.textView.find(self.findEdit.text(),
112                              QTextDocument.FindBackward):
113            self.statusBar().clearMessage()
114        else:
115            self.statusBar().showMessage(_('Text string not found'))
116
117    def findNext(self):
118        """Command to find the next string.
119        """
120        if self.textView.find(self.findEdit.text()):
121            self.statusBar().clearMessage()
122        else:
123            self.statusBar().showMessage(_('Text string not found'))
124
125
126class HelpViewer(QTextBrowser):
127    """Shows an html help file.
128    """
129    def __init__(self, parent=None):
130        """Initialize the viewer.
131
132        Arguments:
133            parent -- the parent widget, if given
134        """
135        QTextBrowser.__init__(self, parent)
136
137    def setSource(self, url):
138        """Called when user clicks on a URL.
139
140        Arguments:
141            url -- the clicked on QUrl
142        """
143        name = url.toString()
144        if name.startswith('http'):
145            dataeditors.openExtUrl(name)
146        else:
147            QTextBrowser.setSource(self, QUrl(name))
148
149    def contextMenuEvent(self, event):
150        """Init popup menu on right click"".
151
152        Arguments:
153            event -- the menu event
154        """
155        self.parentWidget().menu.exec_(event.globalPos())
156