Commit a56432b3 authored by Eike Ziller's avatar Eike Ziller

Share code between "central" and other help viewers.

This removes a lot of duplication of actions and interaction.
It's also a preparation step into making the external help
window behave more like the full-fledged help mode.

Change-Id: I318d831f229b0a75bb8702a5f163c96cce6a668c
Reviewed-by: default avatarEike Ziller <eike.ziller@digia.com>
parent 85ac9651
......@@ -31,22 +31,11 @@
#include "helpviewer.h"
#include "localhelpmanager.h"
#include "topicchooser.h"
#include <topicchooser.h>
#include <QEvent>
#include <QTimer>
#include <QKeyEvent>
#include <QLayout>
#include <QPageSetupDialog>
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QStackedWidget>
#include <utils/qtcassert.h>
#include <QHelpEngine>
#include <QHelpSearchEngine>
using namespace Help::Internal;
......@@ -54,29 +43,19 @@ CentralWidget *gStaticCentralWidget = 0;
// -- CentralWidget
CentralWidget::CentralWidget(QWidget *parent)
: QWidget(parent)
, printer(0)
, m_stackedWidget(0)
CentralWidget::CentralWidget(const Core::Context &context, QWidget *parent)
: HelpWidget(context, HelpWidget::ModeWidget, parent)
{
Q_ASSERT(!gStaticCentralWidget);
QTC_CHECK(!gStaticCentralWidget);
gStaticCentralWidget = this;
QVBoxLayout *vboxLayout = new QVBoxLayout(this);
vboxLayout->setMargin(0);
m_stackedWidget = new QStackedWidget(this);
vboxLayout->addWidget(m_stackedWidget);
}
CentralWidget::~CentralWidget()
{
#ifndef QT_NO_PRINTER
delete printer;
#endif
// TODO: this shouldn't be done here
QString zoomFactors;
QString currentPages;
for (int i = 0; i < m_stackedWidget->count(); ++i) {
for (int i = 0; i < viewerCount(); ++i) {
const HelpViewer * const viewer = viewerAt(i);
const QUrl &source = viewer->source();
if (source.isValid()) {
......@@ -97,171 +76,6 @@ CentralWidget *CentralWidget::instance()
return gStaticCentralWidget;
}
bool CentralWidget::isForwardAvailable() const
{
const HelpViewer* viewer = currentHelpViewer();
if (viewer)
return viewer->isForwardAvailable();
return false;
}
bool CentralWidget::isBackwardAvailable() const
{
const HelpViewer* viewer = currentHelpViewer();
if (viewer)
return viewer->isBackwardAvailable();
return false;
}
HelpViewer* CentralWidget::viewerAt(int index) const
{
return qobject_cast<HelpViewer*> (m_stackedWidget->widget(index));
}
HelpViewer* CentralWidget::currentHelpViewer() const
{
return qobject_cast<HelpViewer*> (m_stackedWidget->currentWidget());
}
void CentralWidget::addPage(HelpViewer *page, bool fromSearch)
{
page->installEventFilter(this);
page->setFocus(Qt::OtherFocusReason);
connectSignals(page);
m_stackedWidget->addWidget(page);
if (fromSearch) {
connect(currentHelpViewer(), SIGNAL(loadFinished()), this,
SLOT(highlightSearchTerms()));
}
}
void CentralWidget::removePage(int index)
{
m_stackedWidget->removeWidget(m_stackedWidget->widget(index));
}
int CentralWidget::currentIndex() const
{
return m_stackedWidget->currentIndex();
}
void CentralWidget::setCurrentPage(HelpViewer *page)
{
m_stackedWidget->setCurrentWidget(page);
}
bool CentralWidget::find(const QString &txt, Core::FindFlags flags,
bool incremental, bool *wrapped)
{
return currentHelpViewer()->findText(txt, flags, incremental, false, wrapped);
}
// -- public slots
void CentralWidget::copy()
{
if (HelpViewer* viewer = currentHelpViewer())
viewer->copy();
}
void CentralWidget::home()
{
if (HelpViewer* viewer = currentHelpViewer())
viewer->home();
}
void CentralWidget::zoomIn()
{
HelpViewer* viewer = currentHelpViewer();
if (viewer)
viewer->scaleUp();
}
void CentralWidget::zoomOut()
{
HelpViewer* viewer = currentHelpViewer();
if (viewer)
viewer->scaleDown();
}
void CentralWidget::resetZoom()
{
HelpViewer* viewer = currentHelpViewer();
if (viewer)
viewer->resetScale();
}
void CentralWidget::forward()
{
if (HelpViewer* viewer = currentHelpViewer())
viewer->forward();
}
void CentralWidget::backward()
{
if (HelpViewer* viewer = currentHelpViewer())
viewer->backward();
}
void CentralWidget::print()
{
#ifndef QT_NO_PRINTER
if (HelpViewer* viewer = currentHelpViewer()) {
initPrinter();
QPrintDialog dlg(printer, this);
dlg.setWindowTitle(tr("Print Document"));
if (!viewer->selectedText().isEmpty())
dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange);
dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies);
if (dlg.exec() == QDialog::Accepted)
viewer->print(printer);
}
#endif
}
void CentralWidget::pageSetup()
{
#ifndef QT_NO_PRINTER
initPrinter();
QPageSetupDialog dlg(printer);
dlg.exec();
#endif
}
void CentralWidget::printPreview()
{
#ifndef QT_NO_PRINTER
initPrinter();
QPrintPreviewDialog preview(printer, this);
connect(&preview, SIGNAL(paintRequested(QPrinter*)),
SLOT(printPreview(QPrinter*)));
preview.exec();
#endif
}
void CentralWidget::setSource(const QUrl &url)
{
if (HelpViewer* viewer = currentHelpViewer()) {
viewer->setSource(url);
viewer->setFocus(Qt::OtherFocusReason);
}
}
void CentralWidget::setSourceFromSearch(const QUrl &url)
{
if (HelpViewer* viewer = currentHelpViewer()) {
connect(viewer, SIGNAL(loadFinished()), this,
SLOT(highlightSearchTerms()));
viewer->setSource(url);
viewer->setFocus(Qt::OtherFocusReason);
}
}
void CentralWidget::showTopicChooser(const QMap<QString, QUrl> &links,
const QString &keyword)
{
......@@ -269,99 +83,3 @@ void CentralWidget::showTopicChooser(const QMap<QString, QUrl> &links,
if (tc.exec() == QDialog::Accepted)
setSource(tc.link());
}
// -- protected
void CentralWidget::focusInEvent(QFocusEvent * /* event */)
{
// If we have a current help viewer then this is the 'focus proxy',
// otherwise it's the central widget. This is needed, so an embedding
// program can just set the focus to the central widget and it does
// The Right Thing(TM)
QObject *receiver = m_stackedWidget;
if (HelpViewer *viewer = currentHelpViewer())
receiver = viewer;
QTimer::singleShot(1, receiver, SLOT(setFocus()));
}
// -- private slots
void CentralWidget::highlightSearchTerms()
{
if (HelpViewer *viewer = currentHelpViewer()) {
QHelpSearchEngine *searchEngine =
LocalHelpManager::helpEngine().searchEngine();
QList<QHelpSearchQuery> queryList = searchEngine->query();
QStringList terms;
foreach (const QHelpSearchQuery &query, queryList) {
switch (query.fieldName) {
default: break;
case QHelpSearchQuery::ALL: {
case QHelpSearchQuery::PHRASE:
case QHelpSearchQuery::DEFAULT:
case QHelpSearchQuery::ATLEAST:
foreach (QString term, query.wordList)
terms.append(term.remove(QLatin1Char('"')));
}
}
}
foreach (const QString& term, terms)
viewer->findText(term, 0, false, true);
disconnect(viewer, SIGNAL(loadFinished()), this,
SLOT(highlightSearchTerms()));
}
}
void CentralWidget::printPreview(QPrinter *p)
{
#ifndef QT_NO_PRINTER
HelpViewer *viewer = currentHelpViewer();
if (viewer)
viewer->print(p);
#else
Q_UNUSED(p)
#endif
}
void CentralWidget::handleSourceChanged(const QUrl &url)
{
if (sender() == currentHelpViewer())
emit sourceChanged(url);
}
// -- private
void CentralWidget::initPrinter()
{
#ifndef QT_NO_PRINTER
if (!printer)
printer = new QPrinter(QPrinter::HighResolution);
#endif
}
void CentralWidget::connectSignals(HelpViewer *page)
{
connect(page, SIGNAL(sourceChanged(QUrl)), this, SLOT(handleSourceChanged(QUrl)));
connect(page, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool)));
connect(page, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool)));
connect(page, SIGNAL(printRequested()), this, SLOT(print()));
}
bool CentralWidget::eventFilter(QObject *object, QEvent *e)
{
if (e->type() != QEvent::KeyPress)
return QWidget::eventFilter(object, e);
HelpViewer *viewer = currentHelpViewer();
QKeyEvent *keyEvent = static_cast<QKeyEvent*> (e);
if (viewer == object && keyEvent->key() == Qt::Key_Backspace) {
if (viewer->isBackwardAvailable()) {
// this helps in case there is an html <input> field
if (!viewer->hasFocus())
viewer->backward();
}
}
return QWidget::eventFilter(object, e);
}
......@@ -30,90 +30,32 @@
#ifndef CENTRALWIDGET_H
#define CENTRALWIDGET_H
#include <coreplugin/find/ifindsupport.h>
#include <QWidget>
#include "helpwidget.h"
QT_FORWARD_DECLARE_CLASS(QEvent)
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
QT_FORWARD_DECLARE_CLASS(QFocusEvent)
QT_FORWARD_DECLARE_CLASS(QPrinter)
#include <coreplugin/find/ifindsupport.h>
namespace Help {
namespace Internal {
namespace Internal {
class HelpViewer;
class PrintHelper;
class CentralWidget : public QWidget
class CentralWidget : public HelpWidget
{
Q_OBJECT
public:
CentralWidget(QWidget *parent = 0);
CentralWidget(const Core::Context &context, QWidget *parent = 0);
~CentralWidget();
static CentralWidget *instance();
bool isForwardAvailable() const;
bool isBackwardAvailable() const;
HelpViewer *viewerAt(int index) const;
HelpViewer *currentHelpViewer() const;
void addPage(HelpViewer *page, bool fromSearch = false);
void removePage(int index);
int currentIndex() const;
void setCurrentPage(HelpViewer *page);
bool find(const QString &txt, Core::FindFlags findFlags,
bool incremental, bool *wrapped = 0);
public slots:
void copy();
void home();
void zoomIn();
void zoomOut();
void resetZoom();
void forward();
void backward();
void print();
void pageSetup();
void printPreview();
void setSource(const QUrl &url);
void setSourceFromSearch(const QUrl &url);
void showTopicChooser(const QMap<QString, QUrl> &links, const QString &key);
protected:
void focusInEvent(QFocusEvent *event);
signals:
void sourceChanged(const QUrl &url);
void forwardAvailable(bool available);
void backwardAvailable(bool available);
private slots:
void highlightSearchTerms();
void printPreview(QPrinter *printer);
void handleSourceChanged(const QUrl &url);
private:
void initPrinter();
void connectSignals(HelpViewer *page);
bool eventFilter(QObject *object, QEvent *e);
private:
QPrinter *printer;
QStackedWidget *m_stackedWidget;
};
} // namespace Internal
} // namespace Internal
} // namespace Help
#endif // CENTRALWIDGET_H
......@@ -110,7 +110,7 @@ QWidget *GeneralSettingsPage::widget()
connect(m_ui->blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage()));
connect(m_ui->defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage()));
HelpViewer *viewer = CentralWidget::instance()->currentHelpViewer();
HelpViewer *viewer = CentralWidget::instance()->currentViewer();
if (!viewer)
m_ui->currentPageButton->setEnabled(false);
......@@ -197,7 +197,7 @@ void GeneralSettingsPage::apply()
void GeneralSettingsPage::setCurrentPage()
{
HelpViewer *viewer = CentralWidget::instance()->currentHelpViewer();
HelpViewer *viewer = CentralWidget::instance()->currentViewer();
if (viewer)
m_ui->homePageLineEdit->setText(viewer->source().toString());
}
......
......@@ -107,18 +107,6 @@ static const char kExternalWindowStateKey[] = "Help/ExternalWindowState";
using namespace Core;
static QToolButton *toolButton(Core::Command *cmd, QAction *action)
{
QToolButton *button = new QToolButton;
button->setDefaultAction(action);
button->setPopupMode(QToolButton::DelayedPopup);
action->setToolTip(cmd->stringWithAppendedShortcut(action->text()));
QObject::connect(cmd, &Core::Command::keySequenceChanged, action, [cmd, action]() {
action->setToolTip(cmd->stringWithAppendedShortcut(action->text()));
});
return button;
}
HelpPlugin::HelpPlugin()
: m_mode(0),
m_centralWidget(0),
......@@ -131,8 +119,6 @@ HelpPlugin::HelpPlugin()
m_firstModeChange(true),
m_helpManager(0),
m_openPagesManager(0),
m_backMenu(0),
m_nextMenu(0),
m_isSidebarVisible(true)
{
}
......@@ -175,9 +161,15 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
addAutoReleasedObject(m_generalSettingsPage = new GeneralSettingsPage());
addAutoReleasedObject(m_searchTaskHandler = new SearchTaskHandler);
m_centralWidget = new Help::Internal::CentralWidget(modecontext);
connect(m_centralWidget, SIGNAL(sourceChanged(QUrl)), this,
SLOT(updateSideBarSource(QUrl)));
connect(m_centralWidget, &CentralWidget::closeButtonClicked,
&OpenPagesManager::instance(), &OpenPagesManager::closeCurrentPage);
connect(m_generalSettingsPage, SIGNAL(fontChanged()), this,
SLOT(fontChanged()));
connect(m_generalSettingsPage, SIGNAL(returnOnCloseChanged()), this,
connect(m_generalSettingsPage, SIGNAL(returnOnCloseChanged()), m_centralWidget,
SLOT(updateCloseButton()));
connect(HelpManager::instance(), SIGNAL(helpRequested(QUrl,Core::HelpManager::HelpViewerLocation)),
this, SLOT(handleHelpRequest(QUrl,Core::HelpManager::HelpViewerLocation)));
......@@ -193,52 +185,9 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
connect(HelpManager::instance(), SIGNAL(setupFinished()), this,
SLOT(unregisterOldQtCreatorDocumentation()));
auto helpButtonBar = new Utils::StyledBar;
auto helpButtonLayout = new QHBoxLayout(helpButtonBar);
helpButtonLayout->setMargin(0);
helpButtonLayout->setSpacing(0);
m_splitter = new MiniSplitter;
Command *cmd;
m_centralWidget = new Help::Internal::CentralWidget();
connect(m_centralWidget, SIGNAL(sourceChanged(QUrl)), this,
SLOT(updateSideBarSource(QUrl)));
// Add Home, Previous and Next actions (used in the toolbar)
QAction *action = new QAction(QIcon(QLatin1String(IMAGEPATH "home.png")),
tr("Home"), this);
cmd = ActionManager::registerAction(action, Constants::HELP_HOME, globalcontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(home()));
helpButtonLayout->addWidget(toolButton(cmd, action));
QAction *back = new QAction(QIcon(QLatin1String(IMAGEPATH "previous.png")),
tr("Previous Page"), this);
cmd = ActionManager::registerAction(back, Constants::HELP_PREVIOUS, modecontext);
cmd->setDefaultKeySequence(QKeySequence::Back);
back->setEnabled(m_centralWidget->isBackwardAvailable());
connect(back, SIGNAL(triggered()), m_centralWidget, SLOT(backward()));
connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), back,
SLOT(setEnabled(bool)));
helpButtonLayout->addWidget(toolButton(cmd, back));
QAction *next = new QAction(QIcon(QLatin1String(IMAGEPATH "next.png")), tr("Next Page"), this);
cmd = ActionManager::registerAction(next, Constants::HELP_NEXT, modecontext);
cmd->setDefaultKeySequence(QKeySequence::Forward);
next->setEnabled(m_centralWidget->isForwardAvailable());
connect(next, SIGNAL(triggered()), m_centralWidget, SLOT(forward()));
connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), next,
SLOT(setEnabled(bool)));
helpButtonLayout->addWidget(toolButton(cmd, next));
helpButtonLayout->addWidget(new Utils::StyledSeparator(helpButtonBar));
setupNavigationMenus(back, next, helpButtonBar);
action = new QAction(QIcon(QLatin1String(IMAGEPATH "bookmark.png")),
tr("Add Bookmark"), this);
cmd = ActionManager::registerAction(action, Constants::HELP_BOOKMARK, modecontext);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+M") : tr("Ctrl+M")));
connect(action, SIGNAL(triggered()), this, SLOT(addBookmark()));
helpButtonLayout->addWidget(toolButton(cmd, action));
helpButtonLayout->addWidget(new Utils::StyledSeparator(helpButtonBar));
QAction *action;
// Add Contents, Index, and Context menu items
action = new QAction(QIcon::fromTheme(QLatin1String("help-contents")),
......@@ -268,34 +217,6 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
ActionManager::actionContainer(Core::Constants::M_HELP)->addAction(cmd, Core::Constants::G_HELP_SUPPORT);
connect(action, SIGNAL(triggered()), this, SLOT(slotReportBug()));
action = new QAction(this);
ActionManager::registerAction(action, Core::Constants::PRINT, modecontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(print()));
action = new QAction(this);
cmd = ActionManager::registerAction(action, Core::Constants::COPY, modecontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(copy()));
action->setText(cmd->action()->text());
action->setIcon(cmd->action()->icon());
if (ActionContainer *advancedMenu = ActionManager::actionContainer(Core::Constants::M_EDIT_ADVANCED)) {
// reuse TextEditor constants to avoid a second pair of menu actions
action = new QAction(tr("Increase Font Size"), this);
cmd = ActionManager::registerAction(action, TextEditor::Constants::INCREASE_FONT_SIZE, modecontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(zoomIn()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
action = new QAction(tr("Decrease Font Size"), this);
cmd = ActionManager::registerAction(action, TextEditor::Constants::DECREASE_FONT_SIZE, modecontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(zoomOut()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
action = new QAction(tr("Reset Font Size"), this);
cmd = ActionManager::registerAction(action, TextEditor::Constants::RESET_FONT_SIZE, modecontext);
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(resetZoom()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
}
if (ActionContainer *windowMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW)) {
// reuse EditorManager constants to avoid a second pair of menu actions
// Goto Previous In History Action
......@@ -315,27 +236,7 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
SLOT(gotoNextPage()));
}
QWidget *toolBarWidget = new QWidget;
QHBoxLayout *toolBarLayout = new QHBoxLayout(toolBarWidget);
toolBarLayout->setMargin(0);
toolBarLayout->setSpacing(0);
toolBarLayout->addWidget(helpButtonBar);
toolBarLayout->addWidget(createWidgetToolBar());
QWidget *mainWidget = new QWidget;
m_splitter->addWidget(mainWidget);
QVBoxLayout *mainWidgetLayout = new QVBoxLayout(mainWidget);
mainWidgetLayout->setMargin(0);
mainWidgetLayout->setSpacing(0);
mainWidgetLayout->addWidget(toolBarWidget);
mainWidgetLayout->addWidget(m_centralWidget);
if (QLayout *layout = m_centralWidget->layout()) {
layout->setSpacing(0);
FindToolBarPlaceHolder *fth = new FindToolBarPlaceHolder(m_centralWidget);
fth->setObjectName(QLatin1String("HelpFindToolBarPlaceHolder"));
mainWidgetLayout->addWidget(fth);
}
m_splitter->addWidget(m_centralWidget);