$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2012: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "HelpViewer.h" 00022 00023 #include <QtHelp/QHelpContentWidget> 00024 #include <QCoreApplication> 00025 #include <QDir> 00026 #include <QHBoxLayout> 00027 #include <QVBoxLayout> 00028 #include <QSplitter> 00029 #include <QFile> 00030 #include <QIODevice> 00031 #include <QUrl> 00032 #include <QVariant> 00033 #include <QSettings> 00034 #include <QDesktopServices> 00035 #include <QMessageBox> 00036 00037 #include <QDebug> 00038 00039 #include <HelpViewer.moc> 00040 00041 namespace Aseba 00042 { 00043 const QString HelpViewer::DEFAULT_LANGUAGE = "en"; 00044 00045 HelpViewer::HelpViewer(QWidget* parent): 00046 QWidget(parent), 00047 tmpHelpSubDir(QString("aseba-studio-%1").arg(QCoreApplication::applicationPid())), 00048 tmpHelpFileNameHC(QDir::temp().filePath(tmpHelpSubDir + "/aseba-doc.qhc")), 00049 tmpHelpFileNameCH(QDir::temp().filePath(tmpHelpSubDir + "/aseba-doc.qch")) 00050 { 00051 // expanding help files into tmp 00052 QDir::temp().mkdir(tmpHelpSubDir); 00053 QFile(":aseba-doc.qhc").copy(tmpHelpFileNameHC); 00054 QFile(":aseba-doc.qch").copy(tmpHelpFileNameCH); 00055 00056 // open files from tmp 00057 helpEngine = new QHelpEngine(tmpHelpFileNameHC, this); 00058 if (helpEngine->setupData() == false) 00059 { 00060 helpFound = false; 00061 QString message = tr("The help file %0 was not loaded successfully. " \ 00062 "The error was: %1." \ 00063 "The help file should be available in the temporary directory of your system. " \ 00064 "Please check your installation, or report a bug.").arg(tmpHelpFileNameHC).arg(helpEngine->error()); 00065 QMessageBox::warning(this, tr("Help file not found"), message); 00066 } 00067 else 00068 helpFound = true; 00069 00070 // navigation buttons 00071 previous = new QPushButton(tr("Previous")); 00072 previous->setEnabled(false); 00073 next = new QPushButton(tr("Next")); 00074 next->setEnabled(false); 00075 home = new QPushButton(tr("Home")); 00076 QHBoxLayout* buttonLayout = new QHBoxLayout(); 00077 buttonLayout->addWidget(previous); 00078 buttonLayout->addWidget(home); 00079 buttonLayout->addWidget(next); 00080 buttonLayout->addStretch(); 00081 00082 // QTextBrower 00083 viewer = new HelpBrowser(helpEngine); 00084 00085 // set default language 00086 setLanguage(); 00087 00088 // help layout 00089 QSplitter *helpSplitter = new QSplitter(Qt::Horizontal); 00090 helpSplitter->addWidget(helpEngine->contentWidget()); 00091 helpSplitter->addWidget(viewer); 00092 helpSplitter->setStretchFactor(helpSplitter->indexOf(viewer), 1); 00093 00094 // main layout 00095 QVBoxLayout* mainLayout = new QVBoxLayout(); 00096 mainLayout->addLayout(buttonLayout); 00097 //mainLayout->addWidget(viewer); 00098 mainLayout->addWidget(helpSplitter); 00099 00100 setLayout(mainLayout); 00101 00102 // connect 00103 connect(previous, SIGNAL(clicked()), this, SLOT(previousClicked())); 00104 connect(next, SIGNAL(clicked()), this, SLOT(nextClicked())); 00105 connect(home, SIGNAL(clicked()), this, SLOT(homeClicked())); 00106 connect(viewer, SIGNAL(backwardAvailable(bool)), this, SLOT(backwardAvailable(bool))); 00107 connect(viewer, SIGNAL(forwardAvailable(bool)), this, SLOT(forwardAvailable(bool))); 00108 connect(helpEngine->contentWidget(), SIGNAL(linkActivated(const QUrl&)), viewer, SLOT(setSource(const QUrl&))); 00109 00110 // restore window state, if available 00111 if (readSettings() == false) 00112 resize(800, 500); 00113 00114 setWindowTitle(tr("Aseba Studio Help")); 00115 } 00116 00117 HelpViewer::~HelpViewer() 00118 { 00119 writeSettings(); 00120 // remove help files from tmp 00121 QFile(tmpHelpFileNameHC).remove(); 00122 QFile(tmpHelpFileNameCH).remove(); 00123 QDir::temp().rmdir(tmpHelpSubDir); 00124 } 00125 00126 void HelpViewer::setLanguage(const QString& lang) 00127 { 00128 if (!helpFound) 00129 return; 00130 00131 // check if the language is part of the existing filters 00132 if (selectLanguage(lang) == false) 00133 { 00134 // rollback to default language 00135 QString message = tr("The help filter for the langauge \"%0\" has not been found. " \ 00136 "Falling back to the default language (%1). " \ 00137 "This is probably a bug, please report it.").arg(lang).arg(DEFAULT_LANGUAGE); 00138 QMessageBox::warning(this, tr("Help filter not found"), message); 00139 helpEngine->setCurrentFilter(DEFAULT_LANGUAGE); 00140 this->language = DEFAULT_LANGUAGE; 00141 } 00142 } 00143 00144 bool HelpViewer::selectLanguage(const QString& reqLang) 00145 { 00146 const QStringList& langList(helpEngine->customFilters()); 00147 for (QStringList::const_iterator it = langList.constBegin(); it != langList.constEnd(); ++it) 00148 { 00149 const QString& availableLang(*it); 00150 if (reqLang.startsWith(availableLang)) 00151 { 00152 helpEngine->setCurrentFilter(availableLang); 00153 this->language = availableLang; 00154 return true; 00155 } 00156 } 00157 return false; 00158 } 00159 00160 void HelpViewer::showHelp(helpType type) 00161 { 00162 if (!helpFound) 00163 { 00164 this->show(); // show anyway, but will be blank 00165 return; 00166 } 00167 00168 QString filename = "qthelp:///doc/doc/" + this->language + "_"; 00169 switch (type) 00170 { 00171 // help files generated by the wikidot parser 00172 case HelpViewer::USERMANUAL: 00173 filename += "asebausermanual.html"; 00174 break; 00175 case HelpViewer::STUDIO: 00176 filename += "asebastudio.html"; 00177 break; 00178 case HelpViewer::LANGUAGE: 00179 filename += "asebalanguage.html"; 00180 break; 00181 } 00182 00183 QUrl result = helpEngine->findFile(QUrl(filename)); 00184 viewer->setSource(result); 00185 viewer->setWindowTitle(tr("Aseba Studio Help")); 00186 this->show(); 00187 } 00188 00189 bool HelpViewer::readSettings() 00190 { 00191 bool result; 00192 00193 QSettings settings; 00194 result = restoreGeometry(settings.value("HelpViewer/geometry").toByteArray()); 00195 move(settings.value("HelpViewer/position").toPoint()); 00196 return result; 00197 } 00198 00199 void HelpViewer::writeSettings() 00200 { 00201 QSettings settings; 00202 settings.setValue("HelpViewer/geometry", saveGeometry()); 00203 settings.setValue("HelpViewer/position", pos()); 00204 } 00205 00206 00207 void HelpViewer::previousClicked() 00208 { 00209 viewer->backward(); 00210 } 00211 00212 void HelpViewer::backwardAvailable(bool state) 00213 { 00214 previous->setEnabled(state); 00215 } 00216 00217 void HelpViewer::nextClicked() 00218 { 00219 viewer->forward(); 00220 } 00221 00222 void HelpViewer::forwardAvailable(bool state) 00223 { 00224 next->setEnabled(state); 00225 } 00226 00227 void HelpViewer::homeClicked() 00228 { 00229 showHelp(HelpViewer::USERMANUAL); 00230 } 00231 00232 00233 HelpBrowser::HelpBrowser(QHelpEngine* helpEngine, QWidget* parent): 00234 QTextBrowser(parent), helpEngine(helpEngine) 00235 { 00236 setReadOnly(true); 00237 } 00238 00239 void HelpBrowser::setSource(const QUrl &url) 00240 { 00241 if (url.scheme() == "http") 00242 { 00243 QDesktopServices::openUrl(url); 00244 } 00245 else 00246 QTextBrowser::setSource(url); 00247 } 00248 00249 QVariant HelpBrowser::loadResource(int type, const QUrl& url) 00250 { 00251 //qDebug() << "Loading " << url; 00252 00253 // from Qt Quarterly 28: 00254 // "Using QtHelp to Lend a Helping Hand" 00255 if (url.scheme() == "qthelp") 00256 return QVariant(helpEngine->fileData(url)); 00257 else 00258 return QTextBrowser::loadResource(type, url); 00259 } 00260 } 00261