Fixes: - wrong font settings for helpviewer, cleanup
[qt-creator-color-themes.git] / src / plugins / help / centralwidget.cpp
bloba944efa29b3af5a28c0f1f8306d7360f22e8f68f
1 /***************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Qt Software Information (qt-info@nokia.com)
8 **
9 **
10 ** Non-Open Source Usage
12 ** Licensees may use this file in accordance with the Qt Beta Version
13 ** License Agreement, Agreement version 2.2 provided with the Software or,
14 ** alternatively, in accordance with the terms contained in a written
15 ** agreement between you and Nokia.
17 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU General
20 ** Public License versions 2.0 or 3.0 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.GPL included in the packaging
22 ** of this file. Please review the following information to ensure GNU
23 ** General Public Licensing requirements will be met:
25 ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
26 ** http://www.gnu.org/copyleft/gpl.html.
28 ** In addition, as a special exception, Nokia gives you certain additional
29 ** rights. These rights are described in the Nokia Qt GPL Exception
30 ** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
32 ***************************************************************************/
34 #include "centralwidget.h"
35 #include "helpviewer.h"
36 #include "topicchooser.h"
38 #include <QtCore/QDir>
39 #include <QtCore/QEvent>
40 #include <QtCore/QTimer>
42 #include <QtGui/QMenu>
43 #include <QtGui/QLabel>
44 #include <QtGui/QLayout>
45 #include <QtGui/QPrinter>
46 #include <QtGui/QLineEdit>
47 #include <QtGui/QCheckBox>
48 #include <QtGui/QTabBar>
49 #include <QtGui/QTabWidget>
50 #include <QtGui/QToolButton>
51 #include <QtGui/QMouseEvent>
52 #include <QtGui/QFocusEvent>
53 #include <QtGui/QMainWindow>
54 #include <QtGui/QSpacerItem>
55 #include <QtGui/QTextCursor>
56 #include <QtGui/QPrintDialog>
57 #include <QtGui/QApplication>
58 #include <QtGui/QTextDocumentFragment>
59 #include <QtGui/QPrintPreviewDialog>
60 #include <QtGui/QPageSetupDialog>
62 #include <QtHelp/QHelpEngine>
64 #include <coreplugin/coreconstants.h>
66 using namespace Help::Internal;
68 namespace {
69 HelpViewer* helpViewerFromTabPosition(const QTabWidget *widget, const QPoint &point)
71 QTabBar *tabBar = qFindChild<QTabBar*>(widget);
72 for (int i = 0; i < tabBar->count(); ++i) {
73 if (tabBar->tabRect(i).contains(point))
74 return qobject_cast<HelpViewer*>(widget->widget(i));
76 return 0;
78 CentralWidget *staticCentralWidget = 0;
81 CentralWidget::CentralWidget(QHelpEngine *engine, QWidget *parent)
82 : QWidget(parent)
83 , findBar(0)
84 , tabWidget(0)
85 , helpEngine(engine)
86 , printer(0)
88 lastTabPage = 0;
89 globalActionList.clear();
90 collectionFile = helpEngine->collectionFile();
92 QString system = QLatin1String("win");
94 #ifdef Q_OS_MAC
95 system = QLatin1String("mac");
96 #endif
98 tabWidget = new QTabWidget;
99 tabWidget->setDocumentMode(true);
100 tabWidget->setMovable(true);
101 connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
102 connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentPageChanged(int)));
104 QToolButton *newTabButton = new QToolButton(this);
105 newTabButton->setAutoRaise(true);
106 newTabButton->setToolTip(tr("Add new page"));
107 newTabButton->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/addtab.png").arg(system)));
109 tabWidget->setCornerWidget(newTabButton, Qt::TopLeftCorner);
110 connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab()));
112 QVBoxLayout *vboxLayout = new QVBoxLayout(this);
113 vboxLayout->setMargin(0);
114 vboxLayout->addWidget(tabWidget);
116 QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
117 if (tabBar) {
118 tabBar->installEventFilter(this);
119 tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
120 connect(tabBar, SIGNAL(customContextMenuRequested(const QPoint&)),
121 this, SLOT(showTabBarContextMenu(const QPoint&)));
124 staticCentralWidget = this;
127 CentralWidget::~CentralWidget()
129 QDir dir;
130 QString currentPages;
131 QHelpEngineCore engine(collectionFile, 0);
133 if (engine.setupData()) {
134 for (int i = 0; i < tabWidget->count(); ++i) {
135 HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i));
136 if (viewer && viewer->source().isValid())
137 currentPages.append(viewer->source().toString()).append(QLatin1Char('|'));
139 engine.setCustomValue(QLatin1String("LastTabPage"), lastTabPage);
140 engine.setCustomValue(QLatin1String("LastShownPages"), currentPages);
144 CentralWidget *CentralWidget::instance()
146 return staticCentralWidget;
149 void CentralWidget::newTab()
151 HelpViewer* viewer = currentHelpViewer();
152 if (viewer)
153 setSourceInNewTab(viewer->source());
156 void CentralWidget::zoomIn()
158 HelpViewer* viewer = currentHelpViewer();
159 if (viewer)
160 viewer->zoomIn();
163 void CentralWidget::zoomOut()
165 HelpViewer* viewer = currentHelpViewer();
166 if (viewer)
167 viewer->zoomOut();
170 void CentralWidget::nextPage()
172 if (tabWidget->currentIndex() < tabWidget->count() -1)
173 tabWidget->setCurrentIndex(tabWidget->currentIndex() +1);
174 else
175 tabWidget->setCurrentIndex(0);
178 void CentralWidget::resetZoom()
180 HelpViewer* viewer = currentHelpViewer();
181 if (viewer)
182 viewer->resetZoom();
185 void CentralWidget::previousPage()
187 int index = tabWidget->currentIndex() -1;
188 if (index >= 0)
189 tabWidget->setCurrentIndex(index);
190 else
191 tabWidget->setCurrentIndex(tabWidget->count() -1);
194 void CentralWidget::closeTab()
196 closeTab(tabWidget->currentIndex());
199 void CentralWidget::closeTab(int index)
201 HelpViewer* viewer = helpViewerAtIndex(index);
202 if (!viewer || tabWidget->count() == 1)
203 return;
205 tabWidget->removeTab(index);
206 QTimer::singleShot(0, viewer, SLOT(deleteLater()));
209 void CentralWidget::setSource(const QUrl &url)
211 HelpViewer* viewer = currentHelpViewer();
212 HelpViewer* lastViewer = qobject_cast<HelpViewer*>(tabWidget->widget(lastTabPage));
214 if (!viewer && !lastViewer) {
215 viewer = new HelpViewer(helpEngine, this);
216 viewer->installEventFilter(this);
217 lastTabPage = tabWidget->addTab(viewer, QString());
218 tabWidget->setCurrentIndex(lastTabPage);
219 connectSignals();
220 qApp->processEvents();
221 } else
222 viewer = lastViewer;
224 viewer->setSource(url);
225 currentPageChanged(lastTabPage);
226 viewer->setFocus(Qt::OtherFocusReason);
227 tabWidget->setCurrentIndex(lastTabPage);
228 tabWidget->setTabText(lastTabPage, quoteTabTitle(viewer->documentTitle()));
231 void CentralWidget::setLastShownPages()
233 const QStringList lastShownPageList =
234 helpEngine->customValue(QLatin1String("LastShownPages")). toString().
235 split(QLatin1Char('|'), QString::SkipEmptyParts);
237 if (!lastShownPageList.isEmpty()) {
238 foreach (const QString& page, lastShownPageList)
239 setSourceInNewTab(page);
241 tabWidget->setCurrentIndex(helpEngine->
242 customValue(QLatin1String("LastTabPage"), 0).toInt());
243 } else {
244 QUrl url(helpEngine->findFile(QUrl("qthelp://com.trolltech.qt.440/qdoc/index.html")));
245 if (!url.isValid()) {
246 url.setUrl(QString("qthelp://com.nokia.qtcreator.%1%2/doc/index.html").
247 arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR));
249 setSource(url);
252 updateBrowserFont();
255 bool CentralWidget::hasSelection() const
257 const HelpViewer* viewer = currentHelpViewer();
258 return viewer ? viewer->hasSelection() : false;
261 QUrl CentralWidget::currentSource() const
263 const HelpViewer* viewer = currentHelpViewer();
264 if (viewer)
265 return viewer->source();
267 return QUrl();
270 QString CentralWidget::currentTitle() const
272 const HelpViewer* viewer = currentHelpViewer();
273 if (viewer)
274 return viewer->documentTitle();
276 return QString();
279 void CentralWidget::copySelection()
281 HelpViewer* viewer = currentHelpViewer();
282 if (viewer)
283 viewer->copy();
286 void CentralWidget::initPrinter()
288 #ifndef QT_NO_PRINTER
289 if (!printer)
290 printer = new QPrinter(QPrinter::HighResolution);
291 #endif
294 void CentralWidget::print()
296 #ifndef QT_NO_PRINTER
297 HelpViewer* viewer = currentHelpViewer();
298 if (!viewer)
299 return;
301 initPrinter();
303 QPrintDialog *dlg = new QPrintDialog(printer, this);
304 #if defined(QT_NO_WEBKIT)
305 if (viewer->textCursor().hasSelection())
306 dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
307 #endif
308 dlg->addEnabledOption(QAbstractPrintDialog::PrintPageRange);
309 dlg->addEnabledOption(QAbstractPrintDialog::PrintCollateCopies);
310 dlg->setWindowTitle(tr("Print Document"));
311 if (dlg->exec() == QDialog::Accepted) {
312 viewer->print(printer);
314 delete dlg;
315 #endif
318 void CentralWidget::printPreview()
320 #ifndef QT_NO_PRINTER
321 initPrinter();
322 QPrintPreviewDialog preview(printer, this);
323 connect(&preview, SIGNAL(paintRequested(QPrinter *)), SLOT(printPreview(QPrinter *)));
324 preview.exec();
325 #endif
328 void CentralWidget::printPreview(QPrinter *p)
330 #ifndef QT_NO_PRINTER
331 HelpViewer *viewer = currentHelpViewer();
332 if (viewer)
333 viewer->print(p);
334 #endif
337 void CentralWidget::pageSetup()
339 #ifndef QT_NO_PRINTER
340 initPrinter();
341 QPageSetupDialog dlg(printer);
342 dlg.exec();
343 #endif
346 bool CentralWidget::isHomeAvailable() const
348 return currentHelpViewer() ? true : false;
351 void CentralWidget::home()
353 HelpViewer* viewer = currentHelpViewer();
354 if (viewer)
355 viewer->home();
358 bool CentralWidget::isForwardAvailable() const
360 const HelpViewer* viewer = currentHelpViewer();
361 if (viewer)
362 return viewer->isForwardAvailable();
364 return false;
367 void CentralWidget::forward()
369 HelpViewer* viewer = currentHelpViewer();
370 if (viewer)
371 viewer->forward();
374 bool CentralWidget::isBackwardAvailable() const
376 const HelpViewer* viewer = currentHelpViewer();
377 if (viewer)
378 return viewer->isBackwardAvailable();
380 return false;
383 void CentralWidget::backward()
385 HelpViewer* viewer = currentHelpViewer();
386 if (viewer)
387 viewer->backward();
391 QList<QAction*> CentralWidget::globalActions() const
393 return globalActionList;
396 void CentralWidget::setGlobalActions(const QList<QAction*> &actions)
398 globalActionList = actions;
401 void CentralWidget::setSourceInNewTab(const QUrl &url)
403 HelpViewer* viewer = new HelpViewer(helpEngine, this);
404 viewer->installEventFilter(this);
405 viewer->setSource(url);
406 viewer->setFocus(Qt::OtherFocusReason);
407 tabWidget->setCurrentIndex(tabWidget->addTab(viewer,
408 quoteTabTitle(viewer->documentTitle())));
410 #if defined(QT_NO_WEBIT)
411 QFont font = qApp->font();
412 if (helpEngine->customValue(QLatin1String("useBrowserFont")).toBool())
413 font = qVariantValue<QFont>(helpEngine->customValue(QLatin1String("browserFont")));
414 viewer->setFont(font);
415 #else
416 QWebView* view = qobject_cast<QWebView*> (viewer);
417 if (view) {
418 QWebSettings* settings = QWebSettings::globalSettings();
419 int fontSize = settings->fontSize(QWebSettings::DefaultFontSize);
420 QString fontFamily = settings->fontFamily(QWebSettings::StandardFont);
422 settings = view->settings();
423 settings->setFontSize(QWebSettings::DefaultFontSize, fontSize);
424 settings->setFontFamily(QWebSettings::StandardFont, fontFamily);
426 #endif
428 connectSignals();
431 HelpViewer *CentralWidget::newEmptyTab()
433 HelpViewer* viewer = new HelpViewer(helpEngine, this);
434 viewer->installEventFilter(this);
435 viewer->setFocus(Qt::OtherFocusReason);
436 #if defined(QT_NO_WEBKIT)
437 viewer->setDocumentTitle(tr("unknown"));
438 #endif
439 tabWidget->setCurrentIndex(tabWidget->addTab(viewer, tr("unknown")));
441 connectSignals();
442 return viewer;
445 void CentralWidget::connectSignals()
447 const HelpViewer* viewer = currentHelpViewer();
448 if (viewer) {
449 connect(viewer, SIGNAL(copyAvailable(bool)), this, SIGNAL(copyAvailable(bool)));
450 connect(viewer, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool)));
451 connect(viewer, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool)));
452 connect(viewer, SIGNAL(sourceChanged(const QUrl&)), this, SIGNAL(sourceChanged(const QUrl&)));
453 connect(viewer, SIGNAL(highlighted(const QString&)), this, SIGNAL(highlighted(const QString&)));
455 connect(viewer, SIGNAL(sourceChanged(const QUrl&)), this, SLOT(setTabTitle(const QUrl&)));
459 HelpViewer *CentralWidget::helpViewerAtIndex(int index) const
461 return qobject_cast<HelpViewer*>(tabWidget->widget(index));
464 HelpViewer *CentralWidget::currentHelpViewer() const
466 return qobject_cast<HelpViewer*>(tabWidget->currentWidget());
469 void CentralWidget::activateTab(bool onlyHelpViewer)
471 if (currentHelpViewer()) {
472 currentHelpViewer()->setFocus();
473 } else {
474 int idx = 0;
475 if (onlyHelpViewer)
476 idx = lastTabPage;
477 tabWidget->setCurrentIndex(idx);
478 tabWidget->currentWidget()->setFocus();
482 void CentralWidget::setTabTitle(const QUrl& url)
484 int tab = lastTabPage;
485 HelpViewer* viewer = currentHelpViewer();
487 #if !defined(QT_NO_WEBKIT)
488 if (!viewer || viewer->source() != url) {
489 QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
490 for (tab = 0; tab < tabBar->count(); ++tab) {
491 viewer = qobject_cast<HelpViewer*>(tabWidget->widget(tab));
492 if (viewer && viewer->source() == url)
493 break;
496 #endif
498 if (viewer) {
499 tabWidget->setTabText(tab,
500 quoteTabTitle(viewer->documentTitle().trimmed()));
504 void CentralWidget::currentPageChanged(int index)
506 const HelpViewer *viewer = currentHelpViewer();
508 if (viewer || tabWidget->count() == 1)
509 lastTabPage = index;
511 bool enabled = false;
512 if (viewer)
513 enabled = tabWidget->count() > 1;
515 tabWidget->setTabsClosable(enabled);
516 tabWidget->cornerWidget(Qt::TopLeftCorner)->setEnabled(true);
518 emit currentViewerChanged();
521 void CentralWidget::showTabBarContextMenu(const QPoint &point)
523 HelpViewer* viewer = helpViewerFromTabPosition(tabWidget, point);
524 if (!viewer)
525 return;
527 QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
529 QMenu menu(QLatin1String(""), tabBar);
530 QAction *new_page = menu.addAction(tr("Add New Page"));
531 QAction *close_page = menu.addAction(tr("Close This Page"));
532 QAction *close_pages = menu.addAction(tr("Close Other Pages"));
533 menu.addSeparator();
534 QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page..."));
536 if (tabBar->count() == 1) {
537 close_page->setEnabled(false);
538 close_pages->setEnabled(false);
541 QAction *picked_action = menu.exec(tabBar->mapToGlobal(point));
542 if (!picked_action)
543 return;
545 if (picked_action == new_page)
546 setSourceInNewTab(viewer->source());
548 if (picked_action == close_page) {
549 tabWidget->removeTab(tabWidget->indexOf(viewer));
550 QTimer::singleShot(0, viewer, SLOT(deleteLater()));
553 if (picked_action == close_pages) {
554 int currentPage = tabWidget->indexOf(viewer);
555 for (int i = tabBar->count() -1; i >= 0; --i) {
556 viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i));
557 if (i != currentPage && viewer) {
558 tabWidget->removeTab(i);
559 QTimer::singleShot(0, viewer, SLOT(deleteLater()));
561 if (i < currentPage)
562 --currentPage;
567 if (picked_action == newBookmark)
568 emit addNewBookmark(viewer->documentTitle(), viewer->source().toString());
571 // if we have a current help viewer then this is the 'focus proxy', otherwise
572 // it's the tab widget itself
573 // this is needed, so an embedding program can just set the focus to the central widget
574 // and it does TheRightThing
575 void CentralWidget::focusInEvent(QFocusEvent * /* event */)
577 if (currentHelpViewer())
578 QTimer::singleShot(1, currentHelpViewer(), SLOT(setFocus()));
579 else
580 QTimer::singleShot(1, tabWidget, SLOT(setFocus()));
583 bool CentralWidget::eventFilter(QObject *object, QEvent *e)
585 if (currentHelpViewer() == object && e->type() == QEvent::KeyPress){
586 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
587 if (ke->key() == Qt::Key_Backspace) {
588 HelpViewer *viewer = currentHelpViewer();
589 if (viewer && viewer->isBackwardAvailable())
590 viewer->backward();
591 return true;
595 QTabBar *tabBar = qobject_cast<QTabBar*>(object);
596 bool mousRel = e->type() == QEvent::MouseButtonRelease;
597 bool dblClick = e->type() == QEvent::MouseButtonDblClick;
599 if (tabBar && (mousRel || dblClick)) {
600 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e);
601 HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, mouseEvent->pos());
602 if (tabWidget->count() <= 1)
603 return QWidget::eventFilter(object, e);
605 if (viewer && (mouseEvent->button() == Qt::MidButton || dblClick)) {
606 tabWidget->removeTab(tabWidget->indexOf(viewer));
607 QTimer::singleShot(0, viewer, SLOT(deleteLater()));
608 currentPageChanged(tabWidget->currentIndex());
609 return true;
612 return QWidget::eventFilter(object, e);
615 void CentralWidget::updateBrowserFont()
617 #if defined(QT_NO_WEBKIT)
618 QFont font = qApp->font();
619 if (helpEngine->customValue(QLatin1String("useBrowserFont")).toBool())
620 font = qVariantValue<QFont>(helpEngine->customValue(QLatin1String("browserFont")));
622 QWidget* widget = 0;
623 for (int i = 0; i < tabWidget->count(); ++i) {
624 widget = tabWidget->widget(i);
625 if (widget->font() != font)
626 widget->setFont(font);
628 #else
629 QWebSettings* settings = QWebSettings::globalSettings();
630 int fontSize = settings->fontSize(QWebSettings::DefaultFontSize);
631 QString fontFamily = settings->fontFamily(QWebSettings::StandardFont);
633 QWebView* widget = 0;
634 for (int i = 0; i < tabWidget->count(); ++i) {
635 widget = qobject_cast<QWebView*> (tabWidget->widget(i));
636 if (widget) {
637 settings = widget->settings();
638 settings->setFontSize(QWebSettings::DefaultFontSize, fontSize);
639 settings->setFontFamily(QWebSettings::StandardFont, fontFamily);
642 #endif
645 bool CentralWidget::find(const QString &txt, QTextDocument::FindFlags findFlags,
646 bool incremental)
648 HelpViewer* viewer = currentHelpViewer();
650 #if !defined(QT_NO_WEBKIT)
651 Q_UNUSED(incremental);
652 if (viewer) {
653 QWebPage::FindFlags options = QWebPage::FindWrapsAroundDocument;
654 if (findFlags & QTextDocument::FindBackward)
655 options |= QWebPage::FindBackward;
656 if (findFlags & QTextDocument::FindCaseSensitively)
657 options |= QWebPage::FindCaseSensitively;
659 return viewer->findText(txt, options);
661 return false;
662 #else
663 QTextCursor cursor;
664 QTextDocument *doc = 0;
665 QTextBrowser *browser = 0;
667 if (viewer) {
668 doc = viewer->document();
669 cursor = viewer->textCursor();
670 browser = qobject_cast<QTextBrowser*>(viewer);
673 if (tabWidget->currentWidget() == m_searchWidget) {
674 QTextBrowser* browser = qFindChild<QTextBrowser*>(m_searchWidget);
675 if (browser) {
676 doc = browser->document();
677 cursor = browser->textCursor();
681 if (!browser || !doc || cursor.isNull())
682 return false;
683 if (incremental)
684 cursor.setPosition(cursor.selectionStart());
686 QTextCursor found = doc->find(txt, cursor, findFlags);
687 if (found.isNull()) {
688 if ((findFlags&QTextDocument::FindBackward) == 0)
689 cursor.movePosition(QTextCursor::Start);
690 else
691 cursor.movePosition(QTextCursor::End);
692 found = doc->find(txt, cursor, findFlags);
693 if (found.isNull()) {
694 return false;
697 if (!found.isNull()) {
698 viewer->setTextCursor(found);
700 return true;
701 #endif
704 void CentralWidget::showTopicChooser(const QMap<QString, QUrl> &links,
705 const QString &keyword)
707 TopicChooser tc(this, keyword, links);
708 if (tc.exec() == QDialog::Accepted)
709 setSource(tc.link());
712 void CentralWidget::copy()
714 HelpViewer* viewer = currentHelpViewer();
715 if (viewer)
716 viewer->copy();
719 QString CentralWidget::quoteTabTitle(const QString &title) const
721 QString s = title;
722 return s.replace(QLatin1Char('&'), QLatin1String("&&"));