Mantid
Loading...
Searching...
No Matches
MantidHelpWindow.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10#include "MantidKernel/Logger.h"
15#include <Poco/File.h>
16#include <Poco/Path.h>
17#include <QApplication>
18#include <QDir>
19#include <QFileInfo>
20#include <QHelpEngine>
21#include <QLatin1Char>
22#include <QLatin1String>
23#include <QResource>
24#include <QStandardPaths>
25#include <QString>
26#include <QTemporaryFile>
27#include <QTextStream>
28#include <QUrl>
29#include <QWidget>
30#include <boost/lexical_cast.hpp>
31#include <memory>
32#include <stdexcept>
33
35
36using std::string;
37using namespace MantidQt::API;
38
39REGISTER_HELPWINDOW(MantidHelpWindow)
40
41namespace {
43Mantid::Kernel::Logger g_log("MantidHelpWindow");
44} // namespace
45
46// initialise the help window
47QPointer<pqHelpWindow> MantidHelpWindow::g_helpWindow;
48
50const QString BASE_URL("qthelp://org.mantidproject/doc/");
52const QString DEFAULT_URL(BASE_URL + "index.html");
53
55const QString WIKI_BASE_URL("https://www.mantidproject.org/");
57const QString WIKI_DEFAULT_URL(WIKI_BASE_URL + "MantidPlot");
58
60const QString COLLECTION_FILE("MantidProject.qhc");
61
65MantidHelpWindow::MantidHelpWindow(const Qt::WindowFlags &flags)
66 : MantidHelpInterface(), m_collectionFile(""), m_cacheFile(""), m_firstRun(true) {
67 // find the collection and delete the cache file if this is the first run
68 if (!helpWindowExists()) {
69 this->determineFileLocs();
70
71 // see if chache file exists and remove it - shouldn't be necessary, but it
72 // is
73 if (!m_cacheFile.empty()) {
74 if (Poco::File(m_cacheFile).exists()) {
75 g_log.debug() << "Removing help cache file \"" << m_cacheFile << "\"\n";
76 Poco::File(m_cacheFile).remove();
77 } else {
78 Poco::Path direcPath = Poco::Path(m_cacheFile).parent(); // drop off the filename
79 Poco::File direcFile(direcPath.absolute().toString());
80 if (!direcFile.exists()) {
81 direcFile.createDirectories();
82 }
83 }
84 }
85
86 // create the help engine with the found location
87 g_log.debug() << "Loading " << m_collectionFile << "\n";
88 auto helpEngine = new QHelpEngine(QString(m_collectionFile.c_str()));
89 QObject::connect(helpEngine, SIGNAL(warning(QString)), this, SLOT(warning(QString)));
90 g_log.debug() << "Making local cache copy for saving information at " << m_cacheFile << "\n";
91
92 if (helpEngine->copyCollectionFile(QString(m_cacheFile.c_str()))) {
93 helpEngine->setCollectionFile(QString(m_cacheFile.c_str()));
94 } else {
95 g_log.warning("Failed to copy collection file");
96 g_log.debug(helpEngine->error().toStdString());
97 }
98 g_log.debug() << "helpengine.setupData() returned " << helpEngine->setupData() << "\n";
99
100 // create a new help window
101 g_helpWindow = new pqHelpWindow(helpEngine, this, flags);
102 g_helpWindow->setWindowTitle(QString("Mantid - Help"));
103 g_helpWindow->setWindowIcon(QIcon(":/images/MantidIcon.ico"));
104
105 // show the home page on startup
106 auto registeredDocs = helpEngine->registeredDocumentations();
107 if (registeredDocs.size() > 0) {
108 g_helpWindow->showHomePage(registeredDocs[0]);
109 }
110 g_helpWindow->show();
111 g_helpWindow->raise();
112 }
113}
114
115void MantidHelpWindow::showHelp(const QString &url) {
116 g_log.debug() << "open help window for \"" << url.toStdString() << "\"\n";
117 // bring up the help window if it is showing
118 g_helpWindow->show();
119 g_helpWindow->raise();
120 if (!url.isEmpty()) {
121 g_helpWindow->showPage(url);
122 }
123}
124
125void MantidHelpWindow::openWebpage(const QUrl &url) {
126 g_log.debug() << "open url \"" << url.toString().toStdString() << "\"\n";
128}
129
130void MantidHelpWindow::showPage(const QString &url) { this->showPage(QUrl(url)); }
131
132void MantidHelpWindow::showPage(const QUrl &url) {
133 if (helpWindowExists()) {
134 if (url.isEmpty())
135 this->showHelp(DEFAULT_URL);
136 else
137 this->showHelp(url.toString());
138 } else // qt-assistant disabled
139 {
140 if (url.isEmpty())
142 else
143 this->openWebpage(url);
144 }
145}
146
154void MantidHelpWindow::showPage(const string &url) { this->showPage(QUrl(QString(url.c_str()))); }
155
156void MantidHelpWindow::showWikiPage(const string &page) {
157 if (page.empty())
159 else
160 this->openWebpage(WIKI_BASE_URL + page.c_str());
161}
162
169void MantidHelpWindow::showWikiPage(const QString &page) { this->showWikiPage(page.toStdString()); }
170
180void MantidHelpWindow::showAlgorithm(const string &name, const int version) {
181 auto versionStr("-v" + boost::lexical_cast<string>(version));
182 if (version <= 0) {
183 versionStr = ""; // let the redirect do its thing
184 }
185
186 QString help_url("");
187 if (!name.empty()) {
188 auto alg = Mantid::API::AlgorithmManager::Instance().createUnmanaged(name);
189 help_url = QString::fromStdString(alg->helpURL());
190 }
191 if (helpWindowExists()) {
192 if (help_url.isEmpty()) {
193 QString url(BASE_URL);
194 url += "algorithms/";
195 if (name.empty()) {
196 url += "index.html";
197 } else {
198 url += QString(name.c_str()) + QString(versionStr.c_str()) + ".html";
199 }
200 this->showHelp(url);
201 } else {
202 this->showHelp(help_url);
203 }
204 } else { // qt-assistant disabled
205 if (help_url.isEmpty()) {
206 if (name.empty()) {
207 this->showWikiPage(std::string("Category:Algorithms"));
208 } else {
209 this->showWikiPage(name);
210 }
211 } else {
212 this->openWebpage(help_url);
213 }
214 }
215}
216
226void MantidHelpWindow::showAlgorithm(const QString &name, const int version) {
227 this->showAlgorithm(name.toStdString(), version);
228}
229
236void MantidHelpWindow::showConcept(const string &name) {
237 if (helpWindowExists()) {
238 QString url(BASE_URL);
239 url += "concepts/";
240 if (name.empty())
241 url += "index.html";
242 else
243 url += QString(name.c_str()) + ".html";
244 this->showHelp(url);
245 } else // qt-assistant disabled
246 {
247 if (name.empty())
248 this->showWikiPage(std::string("Category:Concepts"));
249 else
250 this->showWikiPage(name);
251 }
252}
253
260void MantidHelpWindow::showConcept(const QString &name) { this->showConcept(name.toStdString()); }
261
269void MantidHelpWindow::showFitFunction(const std::string &name) {
270 if (helpWindowExists()) {
271 QString url(BASE_URL);
272 url += "fitting/fitfunctions/";
273 auto functionUrl = url + QString(name.c_str()) + ".html";
274 if (name.empty() || !g_helpWindow->isExistingPage(functionUrl))
275 url += "index.html";
276 else
277 url = functionUrl;
278
279 this->showHelp(url);
280 } else // qt-assistant disabled
281 {
282 if (name.empty())
283 this->showWikiPage(std::string("Category:Fit_functions"));
284 else
285 this->showWikiPage(name);
286 }
287}
288
296void MantidHelpWindow::showFitFunction(const QString &name) { this->showFitFunction(name.toStdString()); }
297
305void MantidHelpWindow::showCustomInterface(const QString &name, const QString &area, const QString &section) {
306 this->showCustomInterface(name.toStdString(), area.toStdString(), section.toStdString());
307}
308
316void MantidHelpWindow::showCustomInterface(const std::string &name, const std::string &area,
317 const std::string &section) {
318 if (helpWindowExists()) {
319 QString url(BASE_URL);
320 url += "interfaces/";
321 if (!area.empty()) {
322 url += QString::fromStdString(area) + "/";
323 }
324 if (name.empty()) {
325 url += "index.html";
326 } else {
327 url += QString::fromStdString(name) + ".html";
328 if (!section.empty()) {
329 url += "#" + QString::fromStdString(section);
330 }
331 }
332 this->showHelp(url);
333 }
334}
335
341 // close the window and delete the object
342 // Deleting the object ensures the help engine's destructor is called and
343 // avoids a segfault when workbench is closed
344 g_helpWindow->setAttribute(Qt::WA_DeleteOnClose);
345 g_helpWindow->close();
346}
347
356void MantidHelpWindow::findCollectionFile(std::string &binDir) {
357 // this being empty notes the feature being disabled
358 m_collectionFile = "";
359
360 QDir searchDir(QString::fromStdString(binDir));
361
362 // try next to the executable
363 QString path = searchDir.absoluteFilePath(COLLECTION_FILE);
364 g_log.debug() << "Trying \"" << path.toStdString() << "\"\n";
365 if (searchDir.exists(COLLECTION_FILE)) {
366 m_collectionFile = path.toStdString();
367 return;
368 } else {
369 g_log.debug() << "QHelp Collection file " << path.toStdString() << " not found\n";
370 }
371
372 // try where the builds will put it for a single configuration build
373 searchDir.cdUp();
374 if (searchDir.cd("docs")) {
375 searchDir.cd("qthelp");
376 path = searchDir.absoluteFilePath(COLLECTION_FILE);
377 g_log.debug() << "Trying \"" << path.toStdString() << "\"\n";
378 if (searchDir.exists(COLLECTION_FILE)) {
379 m_collectionFile = path.toStdString();
380 return;
381 }
382 }
383 // try where the builds will put it for a multi-configuration build
384 searchDir.cdUp();
385 if (searchDir.cd("docs")) {
386 searchDir.cd("qthelp");
387 path = searchDir.absoluteFilePath(COLLECTION_FILE);
388 g_log.debug() << "Trying \"" << path.toStdString() << "\"\n";
389 if (searchDir.exists(COLLECTION_FILE)) {
390 m_collectionFile = path.toStdString();
391 return;
392 }
393 }
394
395 // try in windows/linux install location
396 searchDir = QDir(QString::fromStdString(binDir));
397 searchDir.cdUp();
398 searchDir.cd("share");
399 searchDir.cd("doc");
400 path = searchDir.absoluteFilePath(COLLECTION_FILE);
401 g_log.debug() << "Trying \"" << path.toStdString() << "\"\n";
402 if (searchDir.exists(COLLECTION_FILE)) {
403 m_collectionFile = path.toStdString();
404 return;
405 }
406
407 // try a special place for mac/osx
408 searchDir = QDir(QString::fromStdString(binDir));
409 searchDir.cdUp();
410 searchDir.cdUp();
411 searchDir.cd("share");
412 searchDir.cd("doc");
413 path = searchDir.absoluteFilePath(COLLECTION_FILE);
414 g_log.debug() << "Trying \"" << path.toStdString() << "\"\n";
415 if (searchDir.exists(COLLECTION_FILE)) {
416 m_collectionFile = path.toStdString();
417 return;
418 }
419
420 // all tries have failed
421 g_log.information("Failed to find help system collection file \"" + COLLECTION_FILE.toStdString() + "\"");
422}
423
428 // determine collection file location
429 string binDir = Mantid::Kernel::ConfigService::Instance().getPropertiesDir();
430
431 this->findCollectionFile(binDir);
432 if (m_collectionFile.empty()) {
433 // clear out the other filenames
434 m_cacheFile = "";
435 return;
436 }
437 g_log.debug() << "Using collection file \"" << m_collectionFile << "\"\n";
438
439 // determine cache file location
440 m_cacheFile = COLLECTION_FILE.toStdString();
441
442 QString dataLoc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/data";
443
444 if (dataLoc.endsWith("mantidproject")) {
445 Poco::Path path(dataLoc.toStdString(), m_cacheFile);
446 m_cacheFile = path.absolute().toString();
447 } else if (dataLoc.endsWith("MantidPlot")) // understood to end in "Mantid/MantidPlot"
448 {
449 Poco::Path path(dataLoc.toStdString());
450 path = path.parent(); // drop off "MantidPlot"
451 path = path.parent(); // drop off "Mantid"
452 path = Poco::Path(path, "mantidproject");
453 path = Poco::Path(path, m_cacheFile);
454 m_cacheFile = path.absolute().toString();
455 } else {
456 g_log.debug() << "Failed to determine help cache file location\n"; // REMOVE
457 Poco::Path path(dataLoc.toStdString(), "mantidproject");
458 path = Poco::Path(path, COLLECTION_FILE.toStdString());
459 m_cacheFile = path.absolute().toString();
460 }
461}
462
463void MantidHelpWindow::warning(const QString &msg) { g_log.warning(msg.toStdString()); }
464
465} // namespace MantidQt::MantidWidgets
#define REGISTER_HELPWINDOW(TYPE)
Used to register help window.
static bool openUrl(const QUrl &url)
Opens a url in the appropriate web browser.
MantidHelpWindow(const Qt::WindowFlags &flags=Qt::WindowFlags())
Default constructor shows the DEFAULT_URL.
std::string m_collectionFile
The full path of the collection file.
void showConcept(const std::string &name) override
Show the help page for a particular concept.
void findCollectionFile(std::string &binDir)
Determine the location of the collection file, "mantid.qhc".
void showPage(const std::string &url=std::string()) override
Have the help window show a specific url.
void showAlgorithm(const std::string &name=std::string(), const int version=-1) override
Show the help page for a particular algorithm.
void showWikiPage(const std::string &page=std::string()) override
void determineFileLocs()
Determine the location of the collection and cache files.
void shutdown() override
Perform any clean up on main window shutdown.
void showFitFunction(const std::string &name=std::string()) override
Show the help page for a particular fit function.
static QPointer< pqHelpWindow > g_helpWindow
The window that renders the help information.
std::string m_cacheFile
The full path of the cache file.
void showCustomInterface(const std::string &name=std::string(), const std::string &area=std::string(), const std::string &section=std::string()) override
Show the help page for a given custom interface.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
pqHelpWindow provides an assistant-like window for showing help provided by a QHelpEngine.
Definition: pqHelpWindow.h:73
const QString COLLECTION_FILE("MantidProject.qhc")
name of the collection file itself
const QString WIKI_DEFAULT_URL(WIKI_BASE_URL+"MantidPlot")
Url to display if nothing else is suggested.
const QString DEFAULT_URL(BASE_URL+"index.html")
Url to display if nothing else is suggested.
const QString BASE_URL("qthelp://org.mantidproject/doc/")
Base url for all of the files in the project.
const QString WIKI_BASE_URL("https://www.mantidproject.org/")
Base url for all of the wiki links.
Kernel::Logger g_log("ExperimentInfo")
static logger object