Developer Documentation

helpWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43 #include "helpWidget.hh"
44
45 #include <OpenFlipper/common/GlobalOptions.hh>
46
47 //#define DEBUG_HELP_CONTENTS
48
49 HelpWidget::HelpWidget(QWidget* parent, const QString& _homeSite /*=""*/, const bool _loadHomeSite /*= true*/)
50 : QMainWindow(parent),
51 searchWidget_(0),
52 tabWidget_(0),
53 textWindow_(0),
54 helpEngine_(0),
55 searchEngine_(0) {
56
57 setupUi(this);
58
59 homeSite_ = _homeSite;
60
61 QString filename = QString( OpenFlipper::Options::configDirStr() );
62 filename += OpenFlipper::Options::dirSeparator();
63 filename += "Help.qhc";
64
65 QDir helpDir = QDir(OpenFlipper::Options::helpDirStr());
66
67 QString iconPath = QString(OpenFlipper::Options::iconDirStr())+QString(OpenFlipper::Options::dirSeparator());
68
69 // Set Buttons
70 backButton_->setIcon(QIcon(iconPath+"arrow-left.png"));
71 forwardButton_->setIcon(QIcon(iconPath+"arrow-right.png"));
72 homeButton_->setIcon(QIcon(iconPath+"go-home.png"));
73 searchButton_->setIcon(QIcon(iconPath+"edit-find.png"));
74
75 tabWidget_ = new QTabWidget(this);
76
77 // Generate the help engine. The filename is in the users home directory and
78 // contains all registered help resources.
79 helpEngine_ = new QHelpEngine(filename, this);
80
81 helpEngine_->setupData();
82
83 // Get all currently registered nameSpaces
84 QStringList registeredNamespaces =helpEngine_->registeredDocumentations();
85
86 QStringList documentationFiles;
87
88 // Get a list of all loaded documentation files from the namespaces
89 QStringList helpFiles = helpDir.entryList(QStringList("*.qch"),QDir::Files);
90
91 // Write absolute path into filenames
92 for (QStringList::iterator iter = helpFiles.begin(); iter != helpFiles.end(); ++iter)
93 *iter = helpDir.path()+ OpenFlipper::Options::dirSeparator() + *iter;
94
95 for ( int i = 0; i < registeredNamespaces.size() ; ++i)
96 {
97 QString registredFilename (helpEngine_->documentationFileName(registeredNamespaces[i]));
98
99 // re-register documentation if location changed
100 if (helpFiles.indexOf(registredFilename) != -1)
101 documentationFiles.push_back( registredFilename );
102 else
103 helpEngine_->unregisterDocumentation(registeredNamespaces[i]);
104 }
105
106 for ( int i = 0 ; i < helpFiles.size() ; ++i ) {
107 const QString filename = helpFiles[i];
108
109 // Don't register files twice (stored between multiple OpenFlipper executions)
110 if (documentationFiles.contains(filename))
111 continue;
112
113 // Try to register the file
114 if ( !helpEngine_->registerDocumentation( filename ) ) {
115 std::cerr << "Error when trying to register file " << filename.toStdString() << std::endl;
116 std::cerr << helpFiles[i].toStdString() << " :" << helpEngine_->error().toStdString() << std::endl;
117 }
118
119 }
120
121 searchEngine_ = new QHelpSearchEngine(helpEngine_, this);
122
123 textWindow_ = new HelpBrowser(helpEngine_, this);
124
125 homeIndex_ = tabWidget_->addTab(textWindow_, tr("Home"));
126
127 gridLayout_->addWidget(helpEngine_->contentWidget(), 1, 0);
128 gridLayout_->addWidget(tabWidget_, 1, 1);
129
130 gridLayout_->setColumnStretch(0, 1);
131 gridLayout_->setColumnStretch(1, 3);
132
133 // Search popup at bottom of window
134 searchWidget_ = new QDockWidget(tr("Search results"), this);
135 searchWidget_->setFeatures( QDockWidget::DockWidgetClosable );
136
137 searchWidget_->resize(this->size().width(), floor( double(this->size().height() / 3)) );
138
139 searchWidget_->setWidget(searchEngine_->queryWidget());
140 //searchWidget_->setWidget(results_);
141
142 searchWidget_->hide();
143 addDockWidget(Qt::BottomDockWidgetArea, searchWidget_);
144
145
146 // Entry in tree view has been clicked
147 connect(helpEngine_->contentWidget(), SIGNAL(linkActivated(const QUrl&)),
148 this, SLOT(linkActivated(const QUrl&)));
149
150 // Search button
151 connect(searchButton_, SIGNAL(clicked()), this, SLOT(showSearchWidget()));
152
153 // Search button
154 connect(searchEngine_->queryWidget(), SIGNAL(search()), this, SLOT(startSearch()));
155
156 // Show results if search is finished
157 connect(searchEngine_, SIGNAL(searchingFinished(int)), this, SLOT(showResults(int)));
158
159 // Show results if search is finished
160 connect(searchEngine_->resultWidget(), SIGNAL(requestShowLink(const QUrl&)),
161 this, SLOT(showFoundSite(const QUrl&)));
162
163 // Back button
164 connect(backButton_, SIGNAL(clicked()), this, SLOT(goBack()));
165
166 // Forward button
167 connect(forwardButton_, SIGNAL(clicked()), this, SLOT(goForward()));
168
169 // Forward button
170 connect(homeButton_, SIGNAL(clicked()), this, SLOT(goHome()));
171
172 // Source has been reloaded, so the buttons need an update and the modelview
173 connect(textWindow_, SIGNAL(sourceChanged(const QUrl&)), this, SLOT(update(const QUrl&)));
174
175 // the history has changed, so the buttons need an update
176 connect(textWindow_, SIGNAL(historyChanged(const QUrl&)), this, SLOT(updateButtons()));
177
178 // Register documentation
179 // Seems to be an unneeded call!
180 //helpEngine_->registerDocumentation(filename);
181
182 QStringList tmp = helpEngine_->registeredDocumentations ();
183
184 #ifdef DEBUG_HELP_CONTENTS
185 for ( int i = 0 ; i < tmp.size(); ++i) {
186 std::cerr << "=========================================================================================" << std::endl;
187 std::cerr << "Registered namespace: " << tmp[i].toStdString() << std::endl;
188 std::cerr << "From file : " << helpEngine_->documentationFileName(tmp[i]).toStdString() << std::endl;
189
190
191 QList<QStringList> filterAttribs = helpEngine_->filterAttributeSets (tmp[i]);
192 // std::cerr << "Filter attributes:" << std::endl;
193 // for ( int j = 0 ; j < filterAttribs.size(); ++j) {
194 // for ( int k = 0 ; k < filterAttribs[j].size(); ++k) {
195 // std::cerr << filterAttribs[j][k].toStdString() << std::endl;
196 // }
197 // }
198
199 // Print a list of all files included in this help file
200 if ( !filterAttribs.empty() ) {
201 QList<QUrl> list = helpEngine_->files ( tmp[i], filterAttribs[0]);
202 for ( int j = 0 ; j < list.size(); ++j) {
203 std::cerr << list[j].toString().toStdString() << std::endl;
204 }
205 } else {
206 std::cerr << "Error, empty filter! Unable to get list of included files." << std::endl;
207 }
208
209
210 }
211 #endif
212
213 if (_loadHomeSite)
214 {
215 // Load main page
216 textWindow_->open(QUrl(homeSite_));
217 }
218 }
219
220 void HelpWidget::activateLink(const QUrl& _url)
221 {
222 //open and show the url
223 linkActivated(_url);
224 }
225
226 void HelpWidget::linkActivated(const QUrl& _url) {
227
228 textWindow_->open(_url);
229 tabWidget_->setCurrentIndex(homeIndex_);
230 }
231
232 void HelpWidget::startSearch() {
233
234 searchEngine_->search(searchEngine_->queryWidget()->query());
235 }
236
237 void HelpWidget::setHomeSite(const QString& _homeSite) {
238
239 homeSite_ = _homeSite;
240 }
241
242 void HelpWidget::showFoundSite(const QUrl& _url) {
243
244 textWindow_->open(_url);
245 tabWidget_->setCurrentIndex(homeIndex_);
246 }
247
248 void HelpWidget::update(const QUrl& _url ) {
249
250 updateButtons();
251
252 //search for the entry and select the item in the contentWidget
253 //in our case, it is the treeView on the left side
254 QUrl newUrl = textWindow_->resolveUrl(_url);
255 //search for the selected url
256 QModelIndex modelIndex = helpEngine_->contentWidget()->indexOf(newUrl);
257
258 //select this url in content widget
259 if (modelIndex.isValid())
260 helpEngine_->contentWidget()->setCurrentIndex( modelIndex );
261 }
262
263 void HelpWidget::goForward() {
264
265 textWindow_->forward();
266
267 tabWidget_->setCurrentIndex(homeIndex_);
268
269 updateButtons();
270 }
271
272 void HelpWidget::goBack() {
273
274 textWindow_->backward();
275
276 tabWidget_->setCurrentIndex(homeIndex_);
277
278 updateButtons();
279 }
280
281 void HelpWidget::goHome() {
282
283 textWindow_->open(homeSite_);
284
285 tabWidget_->setCurrentIndex(homeIndex_);
286
287 updateButtons();
288 }
289
290 void HelpWidget::updateButtons() {
291
292 if(!textWindow_->isBackwardAvailable()) {
293 backButton_->setEnabled(false);
294 } else {
295 backButton_->setEnabled(true);
296 }
297
298 if(!textWindow_->isForwardAvailable()) {
299 forwardButton_->setEnabled(false);
300 } else {
301 forwardButton_->setEnabled(true);
302 }
303 }
304
305 void HelpWidget::showSearchWidget() {
306
307 searchWidget_->show();
308 }
309
310 void HelpWidget::showResults(int /*_hits*/) {
311
312 searchWidget_->hide();
313
314 int resultsTabIndex_ = tabWidget_->addTab(searchEngine_->resultWidget(), tr("Results") );
315 tabWidget_->setCurrentIndex(resultsTabIndex_);
316 }
317
318 void HelpWidget::openFoundSite(QListWidgetItem* /*_item*/) {
319
320 }
321
322 HelpWidget::~HelpWidget() {
323
324 delete searchWidget_;
325 delete textWindow_;
326 }
HelpBrowser::HelpBrowser
HelpBrowser(QHelpEngine *_helpEngine, QWidget *parent=0)
Constructor.
Definition: helpBrowser.cc:46
GlobalOptions.hh
HelpBrowser::helpEngine_
QHelpEngine * helpEngine_
The help engine the widget is working on.
Definition: helpBrowser.hh:162