Changeset View
Changeset View
Standalone View
Standalone View
plugins/qthelp/qthelpdocumentation.cpp
Show All 24 Lines | |||||
25 | #include <QUrl> | 25 | #include <QUrl> | ||
26 | #include <QTreeView> | 26 | #include <QTreeView> | ||
27 | #include <QHelpContentModel> | 27 | #include <QHelpContentModel> | ||
28 | #include <QHeaderView> | 28 | #include <QHeaderView> | ||
29 | #include <QMenu> | 29 | #include <QMenu> | ||
30 | #include <QTemporaryFile> | 30 | #include <QTemporaryFile> | ||
31 | #include <QRegularExpression> | 31 | #include <QRegularExpression> | ||
32 | 32 | | |||
33 | #ifdef USE_QTEXTBROWSER | ||||
34 | #include <QDesktopServices> | ||||
35 | #endif | ||||
36 | | ||||
33 | #include <KLocalizedString> | 37 | #include <KLocalizedString> | ||
34 | 38 | | |||
35 | #include <interfaces/icore.h> | 39 | #include <interfaces/icore.h> | ||
36 | #include <interfaces/idocumentationcontroller.h> | 40 | #include <interfaces/idocumentationcontroller.h> | ||
37 | #include <documentation/standarddocumentationview.h> | 41 | #include <documentation/standarddocumentationview.h> | ||
38 | #include "qthelpnetwork.h" | 42 | #include "qthelpnetwork.h" | ||
39 | #include "qthelpproviderabstract.h" | 43 | #include "qthelpproviderabstract.h" | ||
40 | 44 | | |||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Line(s) | 151 | if(pos != -1) { | |||
219 | return thisFragment; | 223 | return thisFragment; | ||
220 | } | 224 | } | ||
221 | 225 | | |||
222 | return QStringList(m_info.keys()).join(QStringLiteral(", ")); | 226 | return QStringList(m_info.keys()).join(QStringLiteral(", ")); | ||
223 | } | 227 | } | ||
224 | 228 | | |||
225 | void QtHelpDocumentation::setUserStyleSheet(StandardDocumentationView* view, const QUrl& url) | 229 | void QtHelpDocumentation::setUserStyleSheet(StandardDocumentationView* view, const QUrl& url) | ||
226 | { | 230 | { | ||
231 | #ifdef USE_QTEXTBROWSER | ||||
232 | QString css; | ||||
233 | QTextStream ts(&css); | ||||
234 | #else | ||||
227 | QTemporaryFile* file = new QTemporaryFile(view); | 235 | QTemporaryFile* file = new QTemporaryFile(view); | ||
228 | file->open(); | 236 | file->open(); | ||
229 | 237 | | |||
230 | QTextStream ts(file); | 238 | QTextStream ts(file); | ||
239 | #endif | ||||
240 | | ||||
231 | ts << "html { background: white !important; }\n"; | 241 | ts << "html { background: white !important; }\n"; | ||
232 | if (url.scheme() == QLatin1String("qthelp") && url.host().startsWith(QLatin1String("com.trolltech.qt."))) { | 242 | if (url.scheme() == QLatin1String("qthelp") && url.host().startsWith(QLatin1String("com.trolltech.qt."))) { | ||
233 | ts << ".content .toc + .title + p { clear:left; }\n" | 243 | ts << ".content .toc + .title + p { clear:left; }\n" | ||
234 | << "#qtdocheader .qtref { position: absolute !important; top: 5px !important; right: 0 !important; }\n"; | 244 | << "#qtdocheader .qtref { position: absolute !important; top: 5px !important; right: 0 !important; }\n"; | ||
235 | } | 245 | } | ||
246 | #ifdef USE_QTEXTBROWSER | ||||
247 | view->setHtml(css); | ||||
248 | #else | ||||
236 | file->close(); | 249 | file->close(); | ||
237 | view->setOverrideCss(QUrl::fromLocalFile(file->fileName())); | 250 | view->setOverrideCss(QUrl::fromLocalFile(file->fileName())); | ||
238 | 251 | | |||
239 | delete m_lastStyleSheet.data(); | 252 | delete m_lastStyleSheet.data(); | ||
240 | m_lastStyleSheet = file; | 253 | m_lastStyleSheet = file; | ||
254 | #endif | ||||
255 | } | ||||
256 | | ||||
257 | bool QtHelpDocumentation::loadResourceCallback(int type, QUrl& url, QVariant& content) | ||||
258 | { | ||||
259 | if (type < 4 && StandardDocumentationView::isUrlSchemeSupported(url)) { | ||||
260 | QByteArray ba; | ||||
261 | const auto resolvedUrl = m_provider->engine()->findFile(url); | ||||
262 | if (resolvedUrl.isEmpty() || !StandardDocumentationView::isUrlSchemeSupported(resolvedUrl)) { | ||||
263 | return false; | ||||
264 | } | ||||
265 | qCDebug(QTHELP) << "loadResourceCallback type" << type << "url" << url << "resolved=" << resolvedUrl; | ||||
266 | url = resolvedUrl; | ||||
267 | ba = m_provider->engine()->fileData(url); | ||||
268 | bool ret = true; | ||||
269 | if (url.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { | ||||
270 | QImage image; | ||||
271 | image.loadFromData(ba, "svg"); | ||||
272 | if (!image.isNull()) { | ||||
273 | content = ba; | ||||
274 | } else { | ||||
275 | ret = false; | ||||
276 | } | ||||
277 | } | ||||
278 | if (!content.isValid()) { | ||||
279 | content = ba; | ||||
280 | } | ||||
281 | return true; | ||||
282 | } | ||||
283 | return false; | ||||
284 | } | ||||
285 | | ||||
286 | bool QtHelpDocumentation::loadResourceCallback(QPointer<QObject> that, int type, QUrl& url, QVariant& content) | ||||
287 | { | ||||
288 | if (that.isNull() || !that.data()) { | ||||
289 | return false; | ||||
290 | } else { | ||||
291 | QtHelpDocumentation *q = qobject_cast<QtHelpDocumentation*>(that); | ||||
292 | return q ? q->loadResourceCallback(type, url, content) : false; | ||||
293 | } | ||||
241 | } | 294 | } | ||
242 | 295 | | |||
243 | QWidget* QtHelpDocumentation::documentationWidget(DocumentationFindWidget* findWidget, QWidget* parent) | 296 | QWidget* QtHelpDocumentation::documentationWidget(DocumentationFindWidget* findWidget, QWidget* parent) | ||
244 | { | 297 | { | ||
245 | if(m_info.isEmpty()) { //QtHelp sometimes has empty info maps. e.g. availableaudioeffects i 4.5.2 | 298 | if(m_info.isEmpty()) { //QtHelp sometimes has empty info maps. e.g. availableaudioeffects i 4.5.2 | ||
246 | return new QLabel(i18n("Could not find any documentation for '%1'", m_name), parent); | 299 | return new QLabel(i18n("Could not find any documentation for '%1'", m_name), parent); | ||
247 | } else { | 300 | } else { | ||
248 | StandardDocumentationView* view = new StandardDocumentationView(findWidget, parent); | 301 | StandardDocumentationView* view = new StandardDocumentationView(findWidget, parent); | ||
249 | view->initZoom(m_provider->name()); | 302 | view->initZoom(m_provider->name()); | ||
250 | view->setDelegateLinks(true); | 303 | view->setDelegateLinks(true); | ||
251 | view->setNetworkAccessManager(m_provider->networkAccess()); | 304 | view->setNetworkAccessManager(m_provider->networkAccess()); | ||
252 | view->setContextMenuPolicy(Qt::CustomContextMenu); | 305 | view->setContextMenuPolicy(Qt::CustomContextMenu); | ||
253 | QObject::connect(view, &StandardDocumentationView::linkClicked, this, &QtHelpDocumentation::jumpedTo); | | |||
254 | connect(view, &StandardDocumentationView::customContextMenuRequested, this, &QtHelpDocumentation::viewContextMenuRequested); | 306 | connect(view, &StandardDocumentationView::customContextMenuRequested, this, &QtHelpDocumentation::viewContextMenuRequested); | ||
255 | 307 | | |||
256 | setUserStyleSheet(view, m_current.value()); | 308 | setUserStyleSheet(view, m_current.value()); | ||
309 | #ifdef USE_QTEXTBROWSER | ||||
310 | view->registerLoadResourceCallback(this, &QtHelpDocumentation::loadResourceCallback); | ||||
311 | const auto url = m_current.value(); | ||||
312 | if (view->isUrlSchemeSupported(url)) { | ||||
313 | view->load(url, m_provider->engine()->fileData(url)); | ||||
314 | } else { | ||||
315 | // external link | ||||
316 | qCWarning(QTHELP) << "Opening url" << url << "in the registered web browser"; | ||||
317 | QDesktopServices::openUrl(url); | ||||
318 | } | ||||
319 | #else | ||||
257 | view->load(m_current.value()); | 320 | view->load(m_current.value()); | ||
321 | #endif | ||||
258 | lastView = view; | 322 | lastView = view; | ||
323 | // jumpedTo can only be called safely now. | ||||
324 | QObject::connect(view, &StandardDocumentationView::linkClicked, this, &QtHelpDocumentation::jumpedTo); | ||||
259 | return view; | 325 | return view; | ||
260 | } | 326 | } | ||
261 | } | 327 | } | ||
262 | 328 | | |||
263 | void QtHelpDocumentation::viewContextMenuRequested(const QPoint& pos) | 329 | void QtHelpDocumentation::viewContextMenuRequested(const QPoint& pos) | ||
264 | { | 330 | { | ||
265 | StandardDocumentationView* view = qobject_cast<StandardDocumentationView*>(sender()); | 331 | StandardDocumentationView* view = qobject_cast<StandardDocumentationView*>(sender()); | ||
266 | if (!view) | 332 | if (!view) | ||
Show All 20 Lines | |||||
287 | } | 353 | } | ||
288 | 354 | | |||
289 | 355 | | |||
290 | void QtHelpDocumentation::jumpedTo(const QUrl& newUrl) | 356 | void QtHelpDocumentation::jumpedTo(const QUrl& newUrl) | ||
291 | { | 357 | { | ||
292 | Q_ASSERT(lastView); | 358 | Q_ASSERT(lastView); | ||
293 | m_provider->jumpedTo(newUrl); | 359 | m_provider->jumpedTo(newUrl); | ||
294 | setUserStyleSheet(lastView, newUrl); | 360 | setUserStyleSheet(lastView, newUrl); | ||
361 | #ifdef USE_QTEXTBROWSER | ||||
362 | if (lastView->isUrlSchemeSupported(newUrl)) { | ||||
363 | QByteArray content = m_provider->engine()->fileData(newUrl); | ||||
364 | if (!content.isEmpty()) { | ||||
365 | lastView->load(newUrl, content); | ||||
366 | return; | ||||
367 | } else { | ||||
368 | qCWarning(QTHELP) << "cannot determine the content of the new url" << newUrl; | ||||
369 | } | ||||
370 | } else { | ||||
371 | // external link, use the user's webbrowser | ||||
372 | qCWarning(QTHELP) << "Opening new url" << newUrl << "in the registered web browser"; | ||||
373 | QDesktopServices::openUrl(newUrl); | ||||
374 | } | ||||
375 | // restore the current "internal" doc view. If we fail to do this | ||||
376 | // the next link we click that isn't fully specified will be completed | ||||
377 | // using <newUrl>. | ||||
378 | lastView->restore(); | ||||
379 | #else | ||||
295 | lastView->load(newUrl); | 380 | lastView->load(newUrl); | ||
381 | #endif | ||||
296 | } | 382 | } | ||
297 | 383 | | |||
298 | IDocumentationProvider* QtHelpDocumentation::provider() const | 384 | IDocumentationProvider* QtHelpDocumentation::provider() const | ||
299 | { | 385 | { | ||
300 | return m_provider; | 386 | return m_provider; | ||
301 | } | 387 | } | ||
302 | 388 | | |||
303 | QtHelpAlternativeLink::QtHelpAlternativeLink(const QString& name, const QtHelpDocumentation* doc, QObject* parent) | 389 | QtHelpAlternativeLink::QtHelpAlternativeLink(const QString& name, const QtHelpDocumentation* doc, QObject* parent) | ||
304 | : QAction(name, parent), mDoc(doc), mName(name) | 390 | : QAction(name, parent), mDoc(doc), mName(name) | ||
305 | { | 391 | { | ||
306 | connect(this, &QtHelpAlternativeLink::triggered, this, &QtHelpAlternativeLink::showUrl); | 392 | connect(this, &QtHelpAlternativeLink::triggered, this, &QtHelpAlternativeLink::showUrl); | ||
307 | } | 393 | } | ||
308 | 394 | | |||
309 | void QtHelpAlternativeLink::showUrl() | 395 | void QtHelpAlternativeLink::showUrl() | ||
310 | { | 396 | { | ||
311 | IDocumentation::Ptr newDoc(new QtHelpDocumentation(mName, mDoc->info(), mName)); | 397 | IDocumentation::Ptr newDoc(new QtHelpDocumentation(mName, mDoc->info(), mName)); | ||
398 | // probe, not to be committed. | ||||
399 | qInfo() << Q_FUNC_INFO << "name" << mName << ":" << mDoc->info(); | ||||
312 | ICore::self()->documentationController()->showDocumentation(newDoc); | 400 | ICore::self()->documentationController()->showDocumentation(newDoc); | ||
313 | } | 401 | } | ||
314 | 402 | | |||
315 | HomeDocumentation::HomeDocumentation() : m_provider(QtHelpDocumentation::s_provider) | 403 | HomeDocumentation::HomeDocumentation() : m_provider(QtHelpDocumentation::s_provider) | ||
316 | { | 404 | { | ||
317 | } | 405 | } | ||
318 | 406 | | |||
319 | QWidget* HomeDocumentation::documentationWidget(DocumentationFindWidget*, QWidget* parent) | 407 | QWidget* HomeDocumentation::documentationWidget(DocumentationFindWidget*, QWidget* parent) | ||
Show All 29 Lines |