From de040e80fc1f6aa0e6781525296c3ad6cb35686b Mon Sep 17 00:00:00 2001
From: kh1 <qt-info@nokia.com>
Date: Fri, 23 Jul 2010 16:36:08 +0200
Subject: [PATCH] Initial support for showing help in external window.

Task-number: QTCREATORBUG-1473
---
 src/plugins/help/externalhelpwindow.cpp  |  82 ++++++++++++++++++
 src/plugins/help/externalhelpwindow.h    |  54 ++++++++++++
 src/plugins/help/generalsettingspage.cpp |  32 +++++--
 src/plugins/help/generalsettingspage.h   |   7 ++
 src/plugins/help/generalsettingspage.ui  |  13 +++
 src/plugins/help/help.pro                |   8 +-
 src/plugins/help/helpplugin.cpp          | 101 +++++++++++++++++++++--
 src/plugins/help/helpplugin.h            |   7 ++
 8 files changed, 290 insertions(+), 14 deletions(-)
 create mode 100644 src/plugins/help/externalhelpwindow.cpp
 create mode 100644 src/plugins/help/externalhelpwindow.h

diff --git a/src/plugins/help/externalhelpwindow.cpp b/src/plugins/help/externalhelpwindow.cpp
new file mode 100644
index 00000000000..6ffd5b77169
--- /dev/null
+++ b/src/plugins/help/externalhelpwindow.cpp
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "externalhelpwindow.h"
+#include "helpconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QtGui/QKeyEvent>
+
+using namespace Help::Internal;
+
+ExternalHelpWindow::ExternalHelpWindow(QWidget *parent)
+    : QMainWindow(parent)
+{
+    QSettings *settings = Core::ICore::instance()->settings();
+    settings->beginGroup(Help::Constants::ID_MODE_HELP);
+
+    const QVariant geometry = settings->value(QLatin1String("geometry"));
+    if (geometry.isValid())
+        restoreGeometry(geometry.toByteArray());
+    else
+        resize(640, 480);
+
+    settings->endGroup();
+    installEventFilter(this);
+}
+
+ExternalHelpWindow::~ExternalHelpWindow()
+{
+}
+
+void ExternalHelpWindow::closeEvent(QCloseEvent *event)
+{
+    QSettings *settings = Core::ICore::instance()->settings();
+    settings->beginGroup(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 (QKeyEvent *keyEvent = static_cast<QKeyEvent*> (event)) {
+            switch (keyEvent->key()) {
+                case Qt::Key_Escape:
+                    Core::ICore::instance()->mainWindow()->activateWindow();
+                default:
+                    break;
+            }
+        }
+    }
+    return QMainWindow::eventFilter(obj, event);
+}
diff --git a/src/plugins/help/externalhelpwindow.h b/src/plugins/help/externalhelpwindow.h
new file mode 100644
index 00000000000..f96117f01fb
--- /dev/null
+++ b/src/plugins/help/externalhelpwindow.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef EXTERNALHELPWINDOW
+#define EXTERNALHELPWINDOW
+
+#include <QtGui/QMainWindow>
+
+QT_FORWARD_DECLARE_CLASS(QCloseEvent)
+
+namespace Help {
+    namespace Internal {
+
+class ExternalHelpWindow : public QMainWindow
+{
+public:
+    ExternalHelpWindow(QWidget *parent = 0);
+    virtual ~ExternalHelpWindow();
+
+protected:
+     void closeEvent(QCloseEvent *event);
+     bool eventFilter(QObject *obj, QEvent *event);
+};
+
+    }   // Internal
+}   // Help
+
+#endif  // EXTERNALHELPWINDOW
diff --git a/src/plugins/help/generalsettingspage.cpp b/src/plugins/help/generalsettingspage.cpp
index 9fc8b81141f..9c31af98a8a 100644
--- a/src/plugins/help/generalsettingspage.cpp
+++ b/src/plugins/help/generalsettingspage.cpp
@@ -37,8 +37,10 @@
 #include "xbelsupport.h"
 
 #include <coreplugin/coreconstants.h>
+#include <coreplugin/icore.h>
 
 #include <QtCore/QCoreApplication>
+#include <QtCore/QSettings>
 #include <QtCore/QTextStream>
 
 #include <QtGui/QApplication>
@@ -53,6 +55,7 @@
 using namespace Help::Internal;
 
 GeneralSettingsPage::GeneralSettingsPage()
+    : m_helpManager(0)
 {
     m_font = qApp->font();
 #if !defined(QT_NO_WEBKIT)
@@ -94,6 +97,7 @@ QWidget *GeneralSettingsPage::createPage(QWidget *parent)
     m_ui.sizeComboBox->setEditable(false);
     m_ui.styleComboBox->setEditable(false);
 
+    m_helpManager->setupGuiHelpEngine();
     const QHelpEngineCore &engine = LocalHelpManager::helpEngine();
     m_font = qVariantValue<QFont>(engine.customValue(QLatin1String("font"), m_font));
 
@@ -112,9 +116,9 @@ QWidget *GeneralSettingsPage::createPage(QWidget *parent)
         Help::Constants::ShowLastPages).toInt();
     m_ui.helpStartComboBox->setCurrentIndex(startOption);
 
-    const int helpOption = engine.customValue(QLatin1String("ContextHelpOption"),
+    m_contextOption = engine.customValue(QLatin1String("ContextHelpOption"),
         Help::Constants::SideBySideIfPossible).toInt();
-    m_ui.contextHelpComboBox->setCurrentIndex(helpOption);
+    m_ui.contextHelpComboBox->setCurrentIndex(m_contextOption);
 
     connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage()));
     connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage()));
@@ -166,10 +170,11 @@ void GeneralSettingsPage::apply()
         newFont.setWeight(weight);
 
     QHelpEngineCore *engine = &LocalHelpManager::helpEngine();
-    engine->setCustomValue(QLatin1String("font"), newFont);
-
-    if (newFont != m_font)
+    if (newFont != m_font) {
+        m_font = newFont;
+        engine->setCustomValue(QLatin1String("font"), newFont);
         emit fontChanged();
+    }
 
     QString homePage = m_ui.homePageLineEdit->text();
     if (homePage.isEmpty())
@@ -180,7 +185,17 @@ void GeneralSettingsPage::apply()
     engine->setCustomValue(QLatin1String("StartOption"), startOption);
 
     const int helpOption = m_ui.contextHelpComboBox->currentIndex();
-    engine->setCustomValue(QLatin1String("ContextHelpOption"), helpOption);
+    if (m_contextOption != helpOption) {
+        m_contextOption = helpOption;
+        engine->setCustomValue(QLatin1String("ContextHelpOption"), helpOption);
+
+        QSettings *settings = Core::ICore::instance()->settings();
+        settings->beginGroup(Help::Constants::ID_MODE_HELP);
+        settings->setValue(QLatin1String("ContextHelpOption"), helpOption);
+        settings->endGroup();
+
+        emit contextHelpOptionChanged();
+    }
 }
 
 void GeneralSettingsPage::setCurrentPage()
@@ -327,3 +342,8 @@ bool GeneralSettingsPage::matches(const QString &s) const
 {
     return m_searchKeywords.contains(s, Qt::CaseInsensitive);
 }
+
+void GeneralSettingsPage::setHelpManager(LocalHelpManager *manager)
+{
+    m_helpManager = manager;
+}
diff --git a/src/plugins/help/generalsettingspage.h b/src/plugins/help/generalsettingspage.h
index 9d8370b5813..12afb0d63c3 100644
--- a/src/plugins/help/generalsettingspage.h
+++ b/src/plugins/help/generalsettingspage.h
@@ -37,6 +37,7 @@ namespace Help {
 namespace Internal {
 
 class CentralWidget;
+class LocalHelpManager;
 
 class GeneralSettingsPage : public Core::IOptionsPage
 {
@@ -56,8 +57,11 @@ public:
     void finish() {}
     virtual bool matches(const QString &s) const;
 
+    void setHelpManager(LocalHelpManager *manager);
+
 signals:
     void fontChanged();
+    void contextHelpOptionChanged();
 
 private slots:
     void setCurrentPage();
@@ -77,9 +81,12 @@ private:
     QFontDatabase m_fontDatabase;
 
     QString m_homePage;
+    int m_contextOption;
 
     QString m_searchKeywords;
     Ui::GeneralSettingsPage m_ui;
+
+    LocalHelpManager *m_helpManager;
 };
 
     }   // Internal
diff --git a/src/plugins/help/generalsettingspage.ui b/src/plugins/help/generalsettingspage.ui
index 7a99e243453..40c9c707038 100644
--- a/src/plugins/help/generalsettingspage.ui
+++ b/src/plugins/help/generalsettingspage.ui
@@ -2,6 +2,14 @@
 <ui version="4.0">
  <class>GeneralSettingsPage</class>
  <widget class="QWidget" name="GeneralSettingsPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>498</width>
+    <height>304</height>
+   </rect>
+  </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
@@ -169,6 +177,11 @@
             <string>Always Start Full Help</string>
            </property>
           </item>
+          <item>
+           <property name="text">
+            <string>Always Show Help in External Window</string>
+           </property>
+          </item>
          </widget>
         </item>
         <item row="1" column="0">
diff --git a/src/plugins/help/help.pro b/src/plugins/help/help.pro
index 890779e9b0e..451fc5d3d36 100644
--- a/src/plugins/help/help.pro
+++ b/src/plugins/help/help.pro
@@ -28,7 +28,8 @@ HEADERS += \
     openpageswidget.h \
     remotehelpfilter.h \
     searchwidget.h \
-    xbelsupport.h
+    xbelsupport.h \
+    externalhelpwindow.h
 
 SOURCES += \
     centralwidget.cpp \
@@ -49,8 +50,9 @@ SOURCES += \
     openpageswidget.cpp \
     remotehelpfilter.cpp \
     searchwidget.cpp \
-    xbelsupport.cpp
-
+    xbelsupport.cpp \
+    externalhelpwindow.cpp
+    
 FORMS += docsettingspage.ui \
     filtersettingspage.ui \
     generalsettingspage.ui \
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index f009ba5bfc1..eb4cd404800 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -33,6 +33,7 @@
 #include "centralwidget.h"
 #include "contentwindow.h"
 #include "docsettingspage.h"
+#include "externalhelpwindow.h"
 #include "filtersettingspage.h"
 #include "generalsettingspage.h"
 #include "helpconstants.h"
@@ -68,6 +69,7 @@
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
 #include <QtCore/QLibraryInfo>
+#include <QtCore/QTimer>
 #include <QtCore/QTranslator>
 #include <QtCore/qplugin.h>
 
@@ -75,6 +77,7 @@
 #include <QtGui/QComboBox>
 #include <QtGui/QDesktopServices>
 #include <QtGui/QShortcut>
+#include <QtGui/QStackedLayout>
 #include <QtGui/QSplitter>
 #include <QtGui/QToolBar>
 
@@ -113,7 +116,9 @@ HelpPlugin::HelpPlugin()
     m_searchItem(0),
     m_bookmarkItem(0),
     m_sideBar(0),
-    m_firstModeChange(true)
+    m_firstModeChange(true),
+    m_oldMode(0),
+    m_externalWindow(new ExternalHelpWindow(0))
 {
 }
 
@@ -150,8 +155,11 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
     addAutoReleasedObject(m_filterSettingsPage = new FilterSettingsPage());
     addAutoReleasedObject(m_generalSettingsPage = new GeneralSettingsPage());
 
+    m_generalSettingsPage->setHelpManager(m_helpManager);
     connect(m_generalSettingsPage, SIGNAL(fontChanged()), this,
         SLOT(fontChanged()));
+    connect(m_generalSettingsPage, SIGNAL(contextHelpOptionChanged()), this,
+        SLOT(contextHelpOptionChanged()));
     connect(Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl)), this,
         SLOT(handleHelpRequest(QUrl)));
     m_filterSettingsPage->setHelpManager(m_helpManager);
@@ -315,8 +323,19 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
     connect(m_core->modeManager(), SIGNAL(currentModeChanged(Core::IMode*,
         Core::IMode*)), this, SLOT(modeChanged(Core::IMode*, Core::IMode*)));
 
-    addAutoReleasedObject(m_mode = new HelpMode(m_splitter));
+    if (contextHelpOption() == Help::Constants::ExternalHelpAlways) {
+        m_mode = new HelpMode(new QWidget);
+        m_mode->setEnabled(false);
+        m_externalWindow->setCentralWidget(m_splitter);
+        QTimer::singleShot(0, this, SLOT(showExternalWindow()));
+    } else {
+        m_mode = new HelpMode(m_splitter);
+    }
+    addAutoReleasedObject(m_mode);
     m_mode->setContext(modecontext);
+    
+    connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()),
+        m_externalWindow, SLOT(close()));
 
     return true;
 }
@@ -351,6 +370,8 @@ ExtensionSystem::IPlugin::ShutdownFlag HelpPlugin::aboutToShutdown()
 {
     if (m_sideBar)
         m_sideBar->saveSettings(m_core->settings(), QLatin1String("HelpSideBar"));
+    delete m_externalWindow;
+
     return SynchronousShutdown;
 }
 
@@ -555,7 +576,10 @@ void HelpPlugin::createRightPaneContextViewer()
 
 void HelpPlugin::activateHelpMode()
 {
-    m_core->modeManager()->activateMode(QLatin1String(Constants::ID_MODE_HELP));
+    if (contextHelpOption() != Help::Constants::ExternalHelpAlways)
+        m_core->modeManager()->activateMode(QLatin1String(Constants::ID_MODE_HELP));
+    else
+        showExternalWindow();
 }
 
 void HelpPlugin::switchToHelpMode()
@@ -575,10 +599,17 @@ void HelpPlugin::slotHideRightPane()
     Core::RightPaneWidget::instance()->setShown(false);
 }
 
+void HelpPlugin::showExternalWindow()
+{
+    setup();
+    m_externalWindow->show();
+    m_externalWindow->activateWindow();
+}
+
 void HelpPlugin::modeChanged(Core::IMode *mode, Core::IMode *old)
 {
-    Q_UNUSED(old)
     if (mode == m_mode) {
+        m_oldMode = old;
         qApp->setOverrideCursor(Qt::WaitCursor);
         setup();
         qApp->restoreOverrideCursor();
@@ -622,10 +653,65 @@ void HelpPlugin::fontChanged()
     }
 }
 
+QStackedLayout * layoutForWidget(QWidget *parent, QWidget *widget)
+{
+    QList<QStackedLayout*> list = parent->findChildren<QStackedLayout*>();
+    foreach (QStackedLayout *layout, list) {
+        const int index = layout->indexOf(widget);
+        if (index >= 0)
+            return layout;
+    }
+    return 0;
+}
+
+void HelpPlugin::contextHelpOptionChanged()
+{
+    setup();
+    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_externalWindow->show();
+                
+                if (m_oldMode && m_mode == m_core->modeManager()->currentMode())
+                    m_core->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();
+        }
+    }
+}
+
 void HelpPlugin::setupHelpEngineIfNeeded()
 {
     m_helpManager->setEngineNeedsUpdate();
-    if (Core::ModeManager::instance()->currentMode() == m_mode)
+    if (Core::ModeManager::instance()->currentMode() == m_mode
+        || contextHelpOption() == Help::Constants::ExternalHelpAlways)
         m_helpManager->setupGuiHelpEngine();
 }
 
@@ -905,6 +991,11 @@ void HelpPlugin::setup()
 
 int HelpPlugin::contextHelpOption() const
 {
+    QSettings *settings = Core::ICore::instance()->settings();
+    const QString key = Help::Constants::ID_MODE_HELP + QLatin1String("/ContextHelpOption");
+    if (settings->contains(key))
+        return settings->value(key, Help::Constants::SideBySideIfPossible).toInt();
+
     const QHelpEngineCore &engine = LocalHelpManager::helpEngine();
     return engine.customValue(QLatin1String("ContextHelpOption"),
         Help::Constants::SideBySideIfPossible).toInt();
diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h
index a56adbbc573..73f68ba4f99 100644
--- a/src/plugins/help/helpplugin.h
+++ b/src/plugins/help/helpplugin.h
@@ -52,6 +52,7 @@ namespace Help {
 namespace Internal {
 class CentralWidget;
 class DocSettingsPage;
+class ExternalHelpWindow;
 class FilterSettingsPage;
 class GeneralSettingsPage;
 class HelpMode;
@@ -73,6 +74,7 @@ public:
     ShutdownFlag aboutToShutdown();
 
 private slots:
+    void showExternalWindow();
     void modeChanged(Core::IMode *mode, Core::IMode *old);
 
     void activateContext();
@@ -94,6 +96,8 @@ private slots:
     void updateSideBarSource(const QUrl &newUrl);
 
     void fontChanged();
+    void contextHelpOptionChanged();
+
     void updateCloseButton();
     void setupHelpEngineIfNeeded();
 
@@ -141,6 +145,9 @@ private:
     QString m_oldAttrValue;
     QString m_styleProperty;
     QString m_idFromContext;
+
+    Core::IMode* m_oldMode;
+    ExternalHelpWindow *m_externalWindow;
 };
 
 } // namespace Internal
-- 
GitLab