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 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 /*
52  * helpWidget.cc
53  *
54  * Created on: Apr 7, 2009
55  * Author: kremer
56  */
57 
58 #include "helpWidget.hh"
59 
61 
62 //#define DEBUG_HELP_CONTENTS
63 
64 HelpWidget::HelpWidget(QWidget* parent, const QString& _homeSite /*=""*/, const bool _loadHomeSite /*= true*/)
65  : QMainWindow(parent),
66  searchWidget_(0),
67  tabWidget_(0),
68  textWindow_(0),
69  helpEngine_(0),
70  searchEngine_(0) {
71 
72  setupUi(this);
73 
74  homeSite_ = _homeSite;
75 
76  QString filename = QString( OpenFlipper::Options::configDirStr() );
77  filename += OpenFlipper::Options::dirSeparator();
78  filename += "Help.qhc";
79 
80  QDir helpDir = QDir(OpenFlipper::Options::helpDirStr());
81 
82  QString iconPath = QString(OpenFlipper::Options::iconDirStr())+QString(OpenFlipper::Options::dirSeparator());
83 
84  // Set Buttons
85  backButton_->setIcon(QIcon(iconPath+"arrow-left.png"));
86  forwardButton_->setIcon(QIcon(iconPath+"arrow-right.png"));
87  homeButton_->setIcon(QIcon(iconPath+"go-home.png"));
88  searchButton_->setIcon(QIcon(iconPath+"edit-find.png"));
89 
90  tabWidget_ = new QTabWidget(this);
91 
92  // Generate the help engine. The filename is in the users home directory and
93  // contains all registered help resources.
94  helpEngine_ = new QHelpEngine(filename, this);
95 
96  helpEngine_->setupData();
97 
98  // Get all currently registered nameSpaces
99  QStringList registeredNamespaces =helpEngine_->registeredDocumentations();
100 
101  QStringList documentationFiles;
102 
103  // Get a list of all loaded documentation files from the namespaces
104  QStringList helpFiles = helpDir.entryList(QStringList("*.qch"),QDir::Files);
105 
106  // Write absolute path into filenames
107  for (QStringList::iterator iter = helpFiles.begin(); iter != helpFiles.end(); ++iter)
108  *iter = helpDir.path()+ OpenFlipper::Options::dirSeparator() + *iter;
109 
110  for ( int i = 0; i < registeredNamespaces.size() ; ++i)
111  {
112  QString registredFilename (helpEngine_->documentationFileName(registeredNamespaces[i]));
113 
114  // re-register documentation if location changed
115  if (helpFiles.indexOf(registredFilename) != -1)
116  documentationFiles.push_back( registredFilename );
117  else
118  helpEngine_->unregisterDocumentation(registeredNamespaces[i]);
119  }
120 
121  for ( int i = 0 ; i < helpFiles.size() ; ++i ) {
122  const QString filename = helpFiles[i];
123 
124  // Don't register files twice (stored between multiple OpenFlipper executions)
125  if (documentationFiles.contains(filename))
126  continue;
127 
128  // Try to register the file
129  if ( !helpEngine_->registerDocumentation( filename ) ) {
130  std::cerr << "Error when trying to register file " << filename.toStdString() << std::endl;
131  std::cerr << helpFiles[i].toStdString() << " :" << helpEngine_->error().toStdString() << std::endl;
132  }
133 
134  }
135 
136  searchEngine_ = new QHelpSearchEngine(helpEngine_, this);
137 
138  textWindow_ = new HelpBrowser(helpEngine_, this);
139 
140  homeIndex_ = tabWidget_->addTab(textWindow_, tr("Home"));
141 
142  gridLayout_->addWidget(helpEngine_->contentWidget(), 1, 0);
143  gridLayout_->addWidget(tabWidget_, 1, 1);
144 
145  gridLayout_->setColumnStretch(0, 1);
146  gridLayout_->setColumnStretch(1, 3);
147 
148  // Search popup at bottom of window
149  searchWidget_ = new QDockWidget(tr("Search results"), this);
150  searchWidget_->setFeatures( QDockWidget::DockWidgetClosable );
151 
152  searchWidget_->resize(this->size().width(), floor( double(this->size().height() / 3)) );
153 
154  searchWidget_->setWidget(searchEngine_->queryWidget());
155  //searchWidget_->setWidget(results_);
156 
157  searchWidget_->hide();
158  addDockWidget(Qt::BottomDockWidgetArea, searchWidget_);
159 
160 
161  // Entry in tree view has been clicked
162  connect(helpEngine_->contentWidget(), SIGNAL(linkActivated(const QUrl&)),
163  this, SLOT(linkActivated(const QUrl&)));
164 
165  // Search button
166  connect(searchButton_, SIGNAL(clicked()), this, SLOT(showSearchWidget()));
167 
168  // Search button
169  connect(searchEngine_->queryWidget(), SIGNAL(search()), this, SLOT(startSearch()));
170 
171  // Show results if search is finished
172  connect(searchEngine_, SIGNAL(searchingFinished(int)), this, SLOT(showResults(int)));
173 
174  // Show results if search is finished
175  connect(searchEngine_->resultWidget(), SIGNAL(requestShowLink(const QUrl&)),
176  this, SLOT(showFoundSite(const QUrl&)));
177 
178  // Back button
179  connect(backButton_, SIGNAL(clicked()), this, SLOT(goBack()));
180 
181  // Forward button
182  connect(forwardButton_, SIGNAL(clicked()), this, SLOT(goForward()));
183 
184  // Forward button
185  connect(homeButton_, SIGNAL(clicked()), this, SLOT(goHome()));
186 
187  // Source has been reloaded, so the buttons need an update and the modelview
188  connect(textWindow_, SIGNAL(sourceChanged(const QUrl&)), this, SLOT(update(const QUrl&)));
189 
190  // the history has changed, so the buttons need an update
191  connect(textWindow_, SIGNAL(historyChanged(const QUrl&)), this, SLOT(updateButtons()));
192 
193  // Register documentation
194  // Seems to be an unneeded call!
195  //helpEngine_->registerDocumentation(filename);
196 
197  QStringList tmp = helpEngine_->registeredDocumentations ();
198 
199  #ifdef DEBUG_HELP_CONTENTS
200  for ( int i = 0 ; i < tmp.size(); ++i) {
201  std::cerr << "=========================================================================================" << std::endl;
202  std::cerr << "Registered namespace: " << tmp[i].toStdString() << std::endl;
203  std::cerr << "From file : " << helpEngine_->documentationFileName(tmp[i]).toStdString() << std::endl;
204 
205 
206  QList<QStringList> filterAttribs = helpEngine_->filterAttributeSets (tmp[i]);
207 // std::cerr << "Filter attributes:" << std::endl;
208 // for ( int j = 0 ; j < filterAttribs.size(); ++j) {
209 // for ( int k = 0 ; k < filterAttribs[j].size(); ++k) {
210 // std::cerr << filterAttribs[j][k].toStdString() << std::endl;
211 // }
212 // }
213 
214  // Print a list of all files included in this help file
215  if ( !filterAttribs.empty() ) {
216  QList<QUrl> list = helpEngine_->files ( tmp[i], filterAttribs[0]);
217  for ( int j = 0 ; j < list.size(); ++j) {
218  std::cerr << list[j].toString().toStdString() << std::endl;
219  }
220  } else {
221  std::cerr << "Error, empty filter! Unable to get list of included files." << std::endl;
222  }
223 
224 
225  }
226  #endif
227 
228  if (_loadHomeSite)
229  {
230  // Load main page
231  textWindow_->open(QUrl(homeSite_));
232  }
233 }
234 
235 void HelpWidget::activateLink(const QUrl& _url)
236 {
237  //open and show the url
238  linkActivated(_url);
239 }
240 
241 void HelpWidget::linkActivated(const QUrl& _url) {
242 
243  textWindow_->open(_url);
244  tabWidget_->setCurrentIndex(homeIndex_);
245 }
246 
247 void HelpWidget::startSearch() {
248 
249  searchEngine_->search(searchEngine_->queryWidget()->query());
250 }
251 
252 void HelpWidget::setHomeSite(const QString& _homeSite) {
253 
254  homeSite_ = _homeSite;
255 }
256 
257 void HelpWidget::showFoundSite(const QUrl& _url) {
258 
259  textWindow_->open(_url);
260  tabWidget_->setCurrentIndex(homeIndex_);
261 }
262 
263 void HelpWidget::update(const QUrl& _url ) {
264 
265  updateButtons();
266 
267  //search for the entry and select the item in the contentWidget
268  //in our case, it is the treeView on the left side
269  QUrl newUrl = textWindow_->resolveUrl(_url);
270  //search for the selected url
271  QModelIndex modelIndex = helpEngine_->contentWidget()->indexOf(newUrl);
272 
273  //select this url in content widget
274  if (modelIndex.isValid())
275  helpEngine_->contentWidget()->setCurrentIndex( modelIndex );
276 }
277 
278 void HelpWidget::goForward() {
279 
280  textWindow_->forward();
281 
282  tabWidget_->setCurrentIndex(homeIndex_);
283 
284  updateButtons();
285 }
286 
287 void HelpWidget::goBack() {
288 
289  textWindow_->backward();
290 
291  tabWidget_->setCurrentIndex(homeIndex_);
292 
293  updateButtons();
294 }
295 
296 void HelpWidget::goHome() {
297 
298  textWindow_->open(homeSite_);
299 
300  tabWidget_->setCurrentIndex(homeIndex_);
301 
302  updateButtons();
303 }
304 
305 void HelpWidget::updateButtons() {
306 
307  if(!textWindow_->isBackwardAvailable()) {
308  backButton_->setEnabled(false);
309  } else {
310  backButton_->setEnabled(true);
311  }
312 
313  if(!textWindow_->isForwardAvailable()) {
314  forwardButton_->setEnabled(false);
315  } else {
316  forwardButton_->setEnabled(true);
317  }
318 }
319 
320 void HelpWidget::showSearchWidget() {
321 
322  searchWidget_->show();
323 }
324 
325 void HelpWidget::showResults(int /*_hits*/) {
326 
327  searchWidget_->hide();
328 
329  int resultsTabIndex_ = tabWidget_->addTab(searchEngine_->resultWidget(), tr("Results") );
330  tabWidget_->setCurrentIndex(resultsTabIndex_);
331 }
332 
333 void HelpWidget::openFoundSite(QListWidgetItem* /*_item*/) {
334 
335 }
336 
337 HelpWidget::~HelpWidget() {
338 
339  delete searchWidget_;
340  delete textWindow_;
341 }
QHelpEngine * helpEngine_
The help engine the widget is working on.
Definition: helpBrowser.hh:183
HelpBrowser(QHelpEngine *_helpEngine, QWidget *parent=0)
Constructor.
Definition: helpBrowser.cc:61