Developer Documentation
Loading...
Searching...
No Matches
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
46
47//#define DEBUG_HELP_CONTENTS
48
49HelpWidget::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 currentFilename = helpFiles[i];
108
109 // Don't register files twice (stored between multiple OpenFlipper executions)
110 if (documentationFiles.contains(currentFilename))
111 continue;
112
113 // Try to register the file
114 if ( !helpEngine_->registerDocumentation( currentFilename ) ) {
115 std::cerr << "Error when trying to register file " << currentFilename.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 #ifdef DEBUG_HELP_CONTENTS
183
184 QStringList tmp = helpEngine_->registeredDocumentations ();
185
186 for ( int i = 0 ; i < tmp.size(); ++i) {
187 std::cerr << "=========================================================================================" << std::endl;
188 std::cerr << "Registered namespace: " << tmp[i].toStdString() << std::endl;
189 std::cerr << "From file : " << helpEngine_->documentationFileName(tmp[i]).toStdString() << std::endl;
190
191
192 QList<QStringList> filterAttribs = helpEngine_->filterAttributeSets (tmp[i]);
193// std::cerr << "Filter attributes:" << std::endl;
194// for ( int j = 0 ; j < filterAttribs.size(); ++j) {
195// for ( int k = 0 ; k < filterAttribs[j].size(); ++k) {
196// std::cerr << filterAttribs[j][k].toStdString() << std::endl;
197// }
198// }
199
200 // Print a list of all files included in this help file
201 if ( !filterAttribs.empty() ) {
202 QList<QUrl> list = helpEngine_->files ( tmp[i], filterAttribs[0]);
203 for ( int j = 0 ; j < list.size(); ++j) {
204 std::cerr << list[j].toString().toStdString() << std::endl;
205 }
206 } else {
207 std::cerr << "Error, empty filter! Unable to get list of included files." << std::endl;
208 }
209
210
211 }
212 #endif
213
214 if (_loadHomeSite)
215 {
216 // Load main page
217 textWindow_->open(QUrl(homeSite_));
218 }
219}
220
221void HelpWidget::activateLink(const QUrl& _url)
222{
223 //open and show the url
224 linkActivated(_url);
225}
226
227void HelpWidget::linkActivated(const QUrl& _url) {
228
229 textWindow_->open(_url);
230 tabWidget_->setCurrentIndex(homeIndex_);
231}
232
233void HelpWidget::startSearch() {
234
235 searchEngine_->search(searchEngine_->queryWidget()->searchInput());
236}
237
238void HelpWidget::setHomeSite(const QString& _homeSite) {
239
240 homeSite_ = _homeSite;
241}
242
243void HelpWidget::showFoundSite(const QUrl& _url) {
244
245 textWindow_->open(_url);
246 tabWidget_->setCurrentIndex(homeIndex_);
247}
248
249void HelpWidget::update(const QUrl& _url ) {
250
251 updateButtons();
252
253 //search for the entry and select the item in the contentWidget
254 //in our case, it is the treeView on the left side
255 QUrl newUrl = textWindow_->resolveUrl(_url);
256 //search for the selected url
257 QModelIndex modelIndex = helpEngine_->contentWidget()->indexOf(newUrl);
258
259 //select this url in content widget
260 if (modelIndex.isValid())
261 helpEngine_->contentWidget()->setCurrentIndex( modelIndex );
262}
263
264void HelpWidget::goForward() {
265
266 textWindow_->forward();
267
268 tabWidget_->setCurrentIndex(homeIndex_);
269
270 updateButtons();
271}
272
273void HelpWidget::goBack() {
274
275 textWindow_->backward();
276
277 tabWidget_->setCurrentIndex(homeIndex_);
278
279 updateButtons();
280}
281
282void HelpWidget::goHome() {
283
284 textWindow_->open(homeSite_);
285
286 tabWidget_->setCurrentIndex(homeIndex_);
287
288 updateButtons();
289}
290
291void HelpWidget::updateButtons() {
292
293 if(!textWindow_->isBackwardAvailable()) {
294 backButton_->setEnabled(false);
295 } else {
296 backButton_->setEnabled(true);
297 }
298
299 if(!textWindow_->isForwardAvailable()) {
300 forwardButton_->setEnabled(false);
301 } else {
302 forwardButton_->setEnabled(true);
303 }
304}
305
306void HelpWidget::showSearchWidget() {
307
308 searchWidget_->show();
309}
310
311void HelpWidget::showResults(int /*_hits*/) {
312
313 searchWidget_->hide();
314
315 int resultsTabIndex_ = tabWidget_->addTab(searchEngine_->resultWidget(), tr("Results") );
316 tabWidget_->setCurrentIndex(resultsTabIndex_);
317}
318
319void HelpWidget::openFoundSite(QListWidgetItem* /*_item*/) {
320
321}
322
323HelpWidget::~HelpWidget() {
324
325 delete searchWidget_;
326 delete textWindow_;
327}
void forward()
Show next page stored in the history.
QUrl resolveUrl(const QUrl &_url)
resolves relative urls to absolute
void backward()
Show last page stored in the history.
bool isForwardAvailable()
Checks if the back button was pressed and we can go forward to the next page.
bool isBackwardAvailable()
Checks if we visited other pages before.