Commit e7ac9fac authored by Eike Ziller's avatar Eike Ziller
Browse files

Help: Implement a real external help window



With this patch it is just used with the context help "always show in
external window" option.

Change-Id: I4bc6ba8e0e241500f6970d4cb72f66ba02075ef5
Reviewed-by: default avatarKarsten Heimrich <karsten.heimrich@digia.com>
parent b2a2a893
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "externalhelpwindow.h"
#include "centralwidget.h"
#include "helpconstants.h"
#include "openpagesmanager.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <utils/hostosinfo.h>
#include <QAction>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QStatusBar>
#include <QToolButton>
using namespace Help::Internal;
ExternalHelpWindow::ExternalHelpWindow(QWidget *parent)
: QMainWindow(parent)
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Help::Constants::ID_MODE_HELP));
const QVariant geometry = settings->value(QLatin1String("geometry"));
if (geometry.isValid())
restoreGeometry(geometry.toByteArray());
else
resize(640, 480);
settings->endGroup();
QAction *action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I));
connect(action, SIGNAL(triggered()), this, SIGNAL(activateIndex()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C));
connect(action, SIGNAL(triggered()), this, SIGNAL(activateContents()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Slash));
connect(action, SIGNAL(triggered()), this, SIGNAL(activateSearch()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B));
connect(action, SIGNAL(triggered()), this, SIGNAL(activateBookmarks()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_O));
connect(action, SIGNAL(triggered()), this, SIGNAL(activateOpenPages()));
addAction(action);
CentralWidget *centralWidget = CentralWidget::instance();
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Plus));
connect(action, SIGNAL(triggered()), centralWidget, SLOT(zoomIn()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Minus));
connect(action, SIGNAL(triggered()), centralWidget, SLOT(zoomOut()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
connect(action, SIGNAL(triggered()), this, SIGNAL(addBookmark()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));
connect(action, SIGNAL(triggered()), centralWidget, SLOT(copy()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P));
connect(action, SIGNAL(triggered()), centralWidget, SLOT(print()));
addAction(action);
action = new QAction(this);
action->setShortcut(QKeySequence::Back);
action->setEnabled(centralWidget->isBackwardAvailable());
connect(action, SIGNAL(triggered()), centralWidget, SLOT(backward()));
connect(centralWidget, SIGNAL(backwardAvailable(bool)), action,
SLOT(setEnabled(bool)));
action = new QAction(this);
action->setShortcut(QKeySequence::Forward);
action->setEnabled(centralWidget->isForwardAvailable());
connect(action, SIGNAL(triggered()), centralWidget, SLOT(forward()));
connect(centralWidget, SIGNAL(forwardAvailable(bool)), action,
SLOT(setEnabled(bool)));
QAction *reset = new QAction(this);
connect(reset, SIGNAL(triggered()), centralWidget, SLOT(resetZoom()));
addAction(reset);
QAction *ctrlTab = new QAction(this);
connect(ctrlTab, SIGNAL(triggered()), &OpenPagesManager::instance(),
SLOT(gotoPreviousPage()));
addAction(ctrlTab);
QAction *ctrlShiftTab = new QAction(this);
connect(ctrlShiftTab, SIGNAL(triggered()), &OpenPagesManager::instance(),
SLOT(gotoNextPage()));
addAction(ctrlShiftTab);
action = new QAction(QIcon(QLatin1String(Core::Constants::ICON_TOGGLE_SIDEBAR)),
tr("Show Sidebar"), this);
connect(action, SIGNAL(triggered()), this, SIGNAL(showHideSidebar()));
if (Utils::HostOsInfo::isMacHost()) {
reset->setShortcut(QKeySequence(Qt::ALT + Qt::Key_0));
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0));
ctrlTab->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Tab));
ctrlShiftTab->setShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Tab));
} else {
reset->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0));
action->setShortcut(QKeySequence(Qt::ALT + Qt::Key_0));
ctrlTab->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Tab));
ctrlShiftTab->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab));
}
QToolButton *button = new QToolButton;
button->setDefaultAction(action);
QStatusBar *statusbar = statusBar();
statusbar->show();
statusbar->setProperty("p_styled", true);
statusbar->addPermanentWidget(button);
QWidget *w = new QWidget;
QHBoxLayout *layout = new QHBoxLayout(w);
layout->addStretch(1);
statusbar->insertWidget(1, w, 1);
installEventFilter(this);
setWindowTitle(tr("Qt Creator Offline Help"));
}
ExternalHelpWindow::~ExternalHelpWindow()
{
}
void ExternalHelpWindow::closeEvent(QCloseEvent *event)
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Help::Constants::ID_MODE_HELP));
settings->setValue(QLatin1String("geometry"), saveGeometry());
settings->endGroup();
QMainWindow::closeEvent(event);
}
bool ExternalHelpWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*> (event);
switch (keyEvent->key()) {
case Qt::Key_Escape:
Core::ICore::raiseWindow(Core::ICore::mainWindow());
default:
break;
}
}
}
return QMainWindow::eventFilter(obj, event);
}
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef EXTERNALHELPWINDOW
#define EXTERNALHELPWINDOW
#include <QMainWindow>
QT_FORWARD_DECLARE_CLASS(QCloseEvent)
QT_FORWARD_DECLARE_CLASS(QToolButton)
namespace Help {
namespace Internal {
class ExternalHelpWindow : public QMainWindow
{
Q_OBJECT
public:
ExternalHelpWindow(QWidget *parent = 0);
virtual ~ExternalHelpWindow();
signals:
void activateIndex();
void activateContents();
void activateSearch();
void activateBookmarks();
void activateOpenPages();
void addBookmark();
void showHideSidebar();
protected:
void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
};
} // Internal
} // Help
#endif // EXTERNALHELPWINDOW
......@@ -185,8 +185,6 @@ void GeneralSettingsPage::apply()
settings->beginGroup(QLatin1String(Help::Constants::ID_MODE_HELP));
settings->setValue(QLatin1String("ContextHelpOption"), helpOption);
settings->endGroup();
emit contextHelpOptionChanged();
}
const bool close = m_ui->m_returnOnClose->isChecked();
......
......@@ -55,7 +55,6 @@ signals:
void fontChanged();
void startOptionChanged();
void returnOnCloseChanged();
void contextHelpOptionChanged();
private slots:
void setCurrentPage();
......
......@@ -196,7 +196,7 @@
</item>
<item>
<property name="text">
<string>Always Show Help in External Window</string>
<string>Always Show in External Window</string>
</property>
</item>
</widget>
......
......@@ -35,7 +35,6 @@ HEADERS += \
remotehelpfilter.h \
searchwidget.h \
xbelsupport.h \
externalhelpwindow.h \
searchtaskhandler.h \
qtwebkithelpviewer.h \
textbrowserhelpviewer.h \
......@@ -59,7 +58,6 @@ SOURCES += \
remotehelpfilter.cpp \
searchwidget.cpp \
xbelsupport.cpp \
externalhelpwindow.cpp \
searchtaskhandler.cpp \
qtwebkithelpviewer.cpp \
textbrowserhelpviewer.cpp \
......
......@@ -42,7 +42,6 @@ QtcPlugin {
files: [
"centralwidget.cpp", "centralwidget.h",
"docsettingspage.cpp", "docsettingspage.h", "docsettingspage.ui",
"externalhelpwindow.cpp", "externalhelpwindow.h",
"filtersettingspage.cpp", "filtersettingspage.h", "filtersettingspage.ui",
"generalsettingspage.cpp", "generalsettingspage.h", "generalsettingspage.ui",
"help.qrc",
......
......@@ -64,6 +64,9 @@ const char HELP_TR_CATEGORY[] = QT_TRANSLATE_NOOP("Help", "Help");
const char C_MODE_HELP [] = "Help Mode";
const char C_HELP_SIDEBAR[] = "Help Sidebar";
const char C_HELP_EXTERNAL[] = "Help.ExternalWindow";
const char CONTEXT_HELP[] = "Help.Context";
} // Constants
} // Help
......
......@@ -31,7 +31,6 @@
#include "centralwidget.h"
#include "docsettingspage.h"
#include "externalhelpwindow.h"
#include "filtersettingspage.h"
#include "generalsettingspage.h"
#include "helpconstants.h"
......@@ -39,7 +38,6 @@
#include "helpindexfilter.h"
#include "helpmode.h"
#include "helpviewer.h"
#include "helpwidget.h"
#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include "openpagesmodel.h"
......@@ -104,6 +102,8 @@ const char SB_BOOKMARKS[] = QT_TRANSLATE_NOOP("Help::Internal::HelpPlugin", "Boo
const char SB_OPENPAGES[] = "OpenPages";
static const char kExternalWindowStateKey[] = "Help/ExternalWindowState";
#define IMAGEPATH ":/help/images/"
using namespace Core;
......@@ -128,9 +128,6 @@ HelpPlugin::HelpPlugin()
m_firstModeChange(true),
m_helpManager(0),
m_openPagesManager(0),
m_oldMode(0),
m_connectWindow(true),
m_externalWindow(0),
m_backMenu(0),
m_nextMenu(0),
m_isSidebarVisible(true)
......@@ -177,8 +174,6 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
connect(m_generalSettingsPage, SIGNAL(fontChanged()), this,
SLOT(fontChanged()));
connect(m_generalSettingsPage, SIGNAL(contextHelpOptionChanged()), this,
SLOT(contextHelpOptionChanged()));
connect(m_generalSettingsPage, SIGNAL(returnOnCloseChanged()), this,
SLOT(updateCloseButton()));
connect(HelpManager::instance(), SIGNAL(helpRequested(QUrl)), this,
......@@ -241,7 +236,7 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
connect(action, SIGNAL(triggered()), this, SLOT(activateIndex()));
action = new QAction(tr("Context Help"), this);
cmd = ActionManager::registerAction(action, "Help.Context", globalcontext);
cmd = ActionManager::registerAction(action, Help::Constants::CONTEXT_HELP, globalcontext);
ActionManager::actionContainer(Core::Constants::M_HELP)->addAction(cmd, Core::Constants::G_HELP_HELP);
cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F1));
connect(action, SIGNAL(triggered()), this, SLOT(activateContext()));
......@@ -340,18 +335,9 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*,Core::IMode*)),
this, SLOT(modeChanged(Core::IMode*,Core::IMode*)));
m_externalWindow = new ExternalHelpWindow;
m_mode = new HelpMode;
if (contextHelpOption() == Help::Constants::ExternalHelpAlways) {
m_mode->setWidget(new QWidget);
m_mode->setEnabled(false);
m_externalHelpBar->setVisible(true);
m_externalWindow->setCentralWidget(m_splitter);
QTimer::singleShot(0, this, SLOT(showExternalWindow()));
} else {
m_mode->setWidget(m_splitter);
m_internalHelpBar->setVisible(true);
}
m_mode->setWidget(m_splitter);
m_internalHelpBar->setVisible(true);
addAutoReleasedObject(m_mode);
return true;
......@@ -375,12 +361,6 @@ ExtensionSystem::IPlugin::ShutdownFlag HelpPlugin::aboutToShutdown()
settings->setValue(QLatin1String("HelpSideBar/") + QLatin1String("Visible"), m_isSidebarVisible);
}
if (m_externalWindow) {
delete m_externalWindow;
m_centralWidget = 0; // Running the external window will take down the central widget as well, cause
// calling m_externalWindow->setCentralWidget(m_centralWidget) will pass ownership to the window.
}
return SynchronousShutdown;
}
......@@ -524,23 +504,58 @@ void HelpPlugin::resetFilter()
connect(engine, SIGNAL(setupFinished()), this, SLOT(updateFilterComboBox()));
}
void HelpPlugin::createRightPaneContextViewer()
void HelpPlugin::saveExternalWindowSettings()
{
if (m_rightPaneSideBarWidget)
if (!m_externalWindow)
return;
m_externalWindowState = m_externalWindow->geometry();
QSettings *settings = Core::ICore::settings();
settings->setValue(QLatin1String(kExternalWindowStateKey),
qVariantFromValue(m_externalWindowState));
}
m_rightPaneSideBarWidget = new HelpWidget(Core::Context(Constants::C_HELP_SIDEBAR));
HelpWidget *HelpPlugin::createHelpWidget(const Context &context, HelpWidget::WidgetStyle style)
{
HelpWidget *widget = new HelpWidget(context, style);
connect(m_rightPaneSideBarWidget->currentViewer(), SIGNAL(loadFinished()),
connect(widget->currentViewer(), SIGNAL(loadFinished()),
this, SLOT(highlightSearchTermsInContextHelp()));
connect(m_rightPaneSideBarWidget, SIGNAL(openHelpMode(QUrl)),
connect(widget, SIGNAL(openHelpMode(QUrl)),
this, SLOT(switchToHelpMode(QUrl)));
connect(m_rightPaneSideBarWidget, SIGNAL(close()),
connect(widget, SIGNAL(closeButtonClicked()),
this, SLOT(slotHideRightPane()));
connect(widget, SIGNAL(aboutToClose()),
this, SLOT(saveExternalWindowSettings()));
// force setup, as we might have never switched to full help mode
// thus the help engine might still run without collection file setup
m_helpManager->setupGuiHelpEngine();
return widget;
}
void HelpPlugin::createRightPaneContextViewer()
{
if (m_rightPaneSideBarWidget)
return;
m_rightPaneSideBarWidget = createHelpWidget(Core::Context(Constants::C_HELP_SIDEBAR),
HelpWidget::SideBarWidget);
}
HelpViewer *HelpPlugin::externalHelpViewer()
{
if (m_externalWindow)
return m_externalWindow->currentViewer();
m_externalWindow = createHelpWidget(Core::Context(Constants::C_HELP_EXTERNAL),
HelpWidget::ExternalWindow);
if (m_externalWindowState.isNull()) {
QSettings *settings = Core::ICore::settings();
m_externalWindowState = settings->value(QLatin1String(kExternalWindowStateKey)).toRect();
}
if (!m_externalWindowState.isNull())
m_externalWindow->setGeometry(m_externalWindowState);
m_externalWindow->show();
return m_externalWindow->currentViewer();
}
HelpViewer *HelpPlugin::createHelpViewer(qreal zoom)
......@@ -576,15 +591,13 @@ HelpViewer *HelpPlugin::createHelpViewer(qreal zoom)
void HelpPlugin::activateHelpMode()
{
if (contextHelpOption() != Help::Constants::ExternalHelpAlways)
ModeManager::activateMode(Id(Constants::ID_MODE_HELP));
else
showExternalWindow();
ModeManager::activateMode(Id(Constants::ID_MODE_HELP));
}
void HelpPlugin::switchToHelpMode(const QUrl &source)
{
activateHelpMode();
Core::ICore::raiseWindow(m_mode->widget());
m_centralWidget->setSource(source);
m_centralWidget->setFocus();
}
......@@ -600,22 +613,10 @@ void HelpPlugin::showHideSidebar()
onSideBarVisibilityChanged();
}
void HelpPlugin::showExternalWindow()
{
bool firstTime = m_firstModeChange;
doSetupIfNeeded();
m_externalWindow->show();
connectExternalHelpWindow();
if (firstTime)
ICore::raiseWindow(ICore::mainWindow());
else
ICore::raiseWindow(m_externalWindow);
}
void HelpPlugin::modeChanged(IMode *mode, IMode *old)
{
Q_UNUSED(old)
if (mode == m_mode) {
m_oldMode = old;
qApp->setOverrideCursor(Qt::WaitCursor);
doSetupIfNeeded();
qApp->restoreOverrideCursor();
......@@ -673,55 +674,6 @@ QStackedLayout * layoutForWidget(QWidget *parent, QWidget *widget)
return 0;
}
void HelpPlugin::contextHelpOptionChanged()
{
doSetupIfNeeded();
QWidget *modeWidget = m_mode->widget();
if (modeWidget == m_splitter
&& contextHelpOption() == Help::Constants::ExternalHelpAlways) {
if (QWidget *widget = m_splitter->parentWidget()) {
if (QStackedLayout *layout = layoutForWidget(widget, m_splitter)) {
const int index = layout->indexOf(m_splitter);
layout->removeWidget(m_splitter);
m_mode->setWidget(new QWidget);
layout->insertWidget(index, m_mode->widget());
m_externalWindow->setCentralWidget(m_splitter);
m_splitter->show();
slotHideRightPane();
m_mode->setEnabled(false);
m_externalHelpBar->setVisible(true);
m_internalHelpBar->setVisible(false);
m_externalWindow->show();
connectExternalHelpWindow();
if (m_oldMode && m_mode == ModeManager::currentMode())
ModeManager::activateMode(m_oldMode->id());
}
}
} else if (modeWidget != m_splitter
&& contextHelpOption() != Help::Constants::ExternalHelpAlways) {
QStackedLayout *wLayout = layoutForWidget(modeWidget->parentWidget(),
modeWidget);
if (wLayout && m_splitter->parentWidget()->layout()) {
const int index = wLayout->indexOf(modeWidget);
QWidget *tmp = wLayout->widget(index);
wLayout->removeWidget(modeWidget);
delete tmp;
m_splitter->parentWidget()->layout()->removeWidget(m_splitter);
m_mode->setWidget(m_splitter);
wLayout->insertWidget(index, m_splitter);
m_mode->setEnabled(true);
m_externalWindow->close();
m_sideBar->setVisible(true);
m_internalHelpBar->setVisible(true);
m_externalHelpBar->setVisible(false);
}
}
}
void HelpPlugin::setupHelpEngineIfNeeded()
{
m_helpManager->setEngineNeedsUpdate();
......@@ -732,6 +684,7 @@ void HelpPlugin::setupHelpEngineIfNeeded()
HelpViewer *HelpPlugin::viewerForContextMode()
{
// TODO this is a hack for opening examples
if (ModeManager::currentMode()->id() == Core::Constants::MODE_WELCOME)
ModeManager::activateMode(Core::Constants::MODE_EDIT);
......@@ -755,7 +708,8 @@ HelpViewer *HelpPlugin::viewerForContextMode()
// side by side
showSideBySide = true;
} break;
case Help::Constants::ExternalHelpAlways:
return externalHelpViewer();
default: // help mode
break;
}
......@@ -804,14 +758,6 @@ static QUrl findBestLink(const QMap<QString, QUrl> &links, QString *highlightId)
void HelpPlugin::activateContext()
{
createRightPaneContextViewer();
RightPanePlaceHolder *placeHolder = RightPanePlaceHolder::current();
if (placeHolder && qApp->focusWidget()