helpwidget.cpp 28 KB
Newer Older
1 2
/****************************************************************************
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5 6 7 8 9 10 11
**
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 24 25 26 27
**
****************************************************************************/

#include "helpwidget.h"

28
#include "bookmarkmanager.h"
29
#include "contentwindow.h"
30
#include "helpconstants.h"
31
#include "helpicons.h"
32 33
#include "helpplugin.h"
#include "helpviewer.h"
34
#include "indexwindow.h"
35
#include "localhelpmanager.h"
36
#include "openpagesmanager.h"
37
#include "searchwidget.h"
38
#include "topicchooser.h"
39 40 41

#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
42
#include <coreplugin/actionmanager/command.h>
43 44 45
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/findplaceholder.h>
46
#include <coreplugin/locator/locatormanager.h>
47 48
#include <coreplugin/minisplitter.h>
#include <coreplugin/sidebar.h>
49
#include <coreplugin/minisplitter.h>
50
#include <texteditor/texteditorconstants.h>
51
#include <utils/qtcassert.h>
52
#include <utils/styledbar.h>
53
#include <utils/utilsicons.h>
54

Sergey Belyashov's avatar
Sergey Belyashov committed
55
#include <QCoreApplication>
56 57
#include <QHBoxLayout>
#include <QMenu>
58 59 60
#include <QPrinter>
#include <QPrintDialog>
#include <QStackedWidget>
61
#include <QStatusBar>
62 63
#include <QToolButton>

64 65
static const char kWindowSideBarSettingsKey[] = "Help/WindowSideBar";
static const char kModeSideBarSettingsKey[] = "Help/ModeSideBar";
66 67 68 69

namespace Help {
namespace Internal {

70 71 72 73 74 75 76 77
static void openUrlInWindow(const QUrl &url)
{
    HelpViewer *viewer = HelpPlugin::viewerForHelpViewerLocation(Core::HelpManager::ExternalHelpAlways);
    if (QTC_GUARD(viewer))
        viewer->setSource(url);
    Core::ICore::raiseWindow(viewer);
}

78 79 80 81 82
static bool isBookmarkable(const QUrl &url)
{
    return !url.isEmpty() && url != QUrl(Help::Constants::AboutBlank);
}

83 84
HelpWidget::HelpWidget(const Core::Context &context, WidgetStyle style, QWidget *parent) :
    QWidget(parent),
85
    m_style(style)
86
{
87 88
    m_viewerStack = new QStackedWidget;

89 90 91 92 93 94
    auto topLayout = new QVBoxLayout;
    topLayout->setMargin(0);
    topLayout->setSpacing(0);
    setLayout(topLayout);

    auto hLayout = new QHBoxLayout;
95 96
    hLayout->setMargin(0);
    hLayout->setSpacing(0);
97
    topLayout->addLayout(hLayout, 10);
98 99 100 101 102

    m_sideBarSplitter = new Core::MiniSplitter(this);
    m_sideBarSplitter->setOpaqueResize(false);
    hLayout->addWidget(m_sideBarSplitter);

103
    Utils::StyledBar *toolBar = new Utils::StyledBar();
104 105 106
    QHBoxLayout *layout = new QHBoxLayout(toolBar);
    layout->setSpacing(0);
    layout->setMargin(0);
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

    auto rightSide = new QWidget(this);
    m_sideBarSplitter->insertWidget(1, rightSide);
    QVBoxLayout *vLayout = new QVBoxLayout(rightSide);
    vLayout->setMargin(0);
    vLayout->setSpacing(0);
    vLayout->addWidget(toolBar);
    vLayout->addWidget(m_viewerStack);
    Core::FindToolBarPlaceHolder *fth = new Core::FindToolBarPlaceHolder(this);
    vLayout->addWidget(fth);

    setFocusProxy(m_viewerStack);

    m_context = new Core::IContext(this);
    m_context->setContext(context);
    m_context->setWidget(m_sideBarSplitter);
    Core::ICore::addContextObject(m_context);

125
    Core::Command *cmd;
126 127 128 129 130 131 132 133
    QToolButton *button;

    if (style == ExternalWindow) {
        static int windowId = 0;
        Core::ICore::registerWindow(this,
                                    Core::Context(Core::Id("Help.Window.").withSuffix(++windowId)));
        setAttribute(Qt::WA_DeleteOnClose);
        setAttribute(Qt::WA_QuitOnClose, false); // don't prevent Qt Creator from closing
134 135
    }
    if (style != SideBarWidget) {
Serhii Moroz's avatar
Serhii Moroz committed
136 137
        m_toggleSideBarAction = new QAction(Utils::Icons::TOGGLE_LEFT_SIDEBAR_TOOLBAR.icon(),
                                            QCoreApplication::translate("Core", Core::Constants::TR_SHOW_LEFT_SIDEBAR),
Sergey Belyashov's avatar
Sergey Belyashov committed
138
                                            toolBar);
139 140 141
        m_toggleSideBarAction->setCheckable(true);
        m_toggleSideBarAction->setChecked(false);
        cmd = Core::ActionManager::registerAction(m_toggleSideBarAction,
Serhii Moroz's avatar
Serhii Moroz committed
142
                                                  Core::Constants::TOGGLE_LEFT_SIDEBAR, context);
143 144
        connect(m_toggleSideBarAction, &QAction::toggled, m_toggleSideBarAction,
                [this](bool checked) {
Sergey Belyashov's avatar
Sergey Belyashov committed
145 146
                    m_toggleSideBarAction->setText(
                        QCoreApplication::translate("Core",
Serhii Moroz's avatar
Serhii Moroz committed
147 148
                                                    checked ? Core::Constants::TR_HIDE_LEFT_SIDEBAR
                                                            : Core::Constants::TR_SHOW_LEFT_SIDEBAR));
149 150
                });
        addSideBar();
151
        m_toggleSideBarAction->setChecked(m_sideBar->isVisibleTo(this));
152 153 154 155
        connect(m_toggleSideBarAction, &QAction::triggered, m_sideBar, &Core::SideBar::setVisible);
        connect(m_sideBar, &Core::SideBar::sideBarClosed, m_toggleSideBarAction, [this]() {
            m_toggleSideBarAction->setChecked(false);
        });
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
        if (style == ExternalWindow) {
            auto statusBar = new QStatusBar;
            topLayout->addWidget(statusBar);
            auto splitter = new Core::NonResizingSplitter(statusBar);
            statusBar->addPermanentWidget(splitter, 10);
            auto statusBarWidget = new QWidget;
            auto statusBarWidgetLayout = new QHBoxLayout;
            statusBarWidgetLayout->setContentsMargins(0, 0, 3, 0);
            statusBarWidget->setLayout(statusBarWidgetLayout);
            splitter->addWidget(statusBarWidget);
            splitter->addWidget(new QWidget);
            auto locatorWidget = Core::LocatorManager::createLocatorInputWidget(window());
            statusBarWidgetLayout->addWidget(Core::Command::toolButtonWithAppendedShortcut(
                                                 m_toggleSideBarAction, cmd));
            statusBarWidgetLayout->addWidget(locatorWidget);
        }
172
    }
173

174
    if (style != ModeWidget) {
175
        m_switchToHelp = new QAction(tr("Open in Help Mode"), toolBar);
176
        cmd = Core::ActionManager::registerAction(m_switchToHelp, Constants::CONTEXT_HELP, context);
Montel Laurent's avatar
Montel Laurent committed
177
        connect(m_switchToHelp, &QAction::triggered, this, &HelpWidget::helpModeButtonClicked);
178
        layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_switchToHelp, cmd));
179
    }
180

181
    m_homeAction = new QAction(Icons::HOME_TOOLBAR.icon(), tr("Home"), this);
182 183
    cmd = Core::ActionManager::registerAction(m_homeAction, Constants::HELP_HOME, context);
    connect(m_homeAction, &QAction::triggered, this, &HelpWidget::goHome);
184
    layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_homeAction, cmd));
185

186
    m_backAction = new QAction(Utils::Icons::PREV_TOOLBAR.icon(), tr("Back"), toolBar);
187
    connect(m_backAction, &QAction::triggered, this, &HelpWidget::backward);
188
    m_backMenu = new QMenu(toolBar);
Montel Laurent's avatar
Montel Laurent committed
189
    connect(m_backMenu, &QMenu::aboutToShow, this, &HelpWidget::updateBackMenu);
190 191 192
    m_backAction->setMenu(m_backMenu);
    cmd = Core::ActionManager::registerAction(m_backAction, Constants::HELP_PREVIOUS, context);
    cmd->setDefaultKeySequence(QKeySequence::Back);
193 194 195
    button = Core::Command::toolButtonWithAppendedShortcut(m_backAction, cmd);
    button->setPopupMode(QToolButton::DelayedPopup);
    layout->addWidget(button);
196

197
    m_forwardAction = new QAction(Utils::Icons::NEXT_TOOLBAR.icon(), tr("Forward"), toolBar);
198
    connect(m_forwardAction, &QAction::triggered, this, &HelpWidget::forward);
199
    m_forwardMenu = new QMenu(toolBar);
Montel Laurent's avatar
Montel Laurent committed
200
    connect(m_forwardMenu, &QMenu::aboutToShow, this, &HelpWidget::updateForwardMenu);
201 202 203
    m_forwardAction->setMenu(m_forwardMenu);
    cmd = Core::ActionManager::registerAction(m_forwardAction, Constants::HELP_NEXT, context);
    cmd->setDefaultKeySequence(QKeySequence::Forward);
204 205 206
    button = Core::Command::toolButtonWithAppendedShortcut(m_forwardAction, cmd);
    button->setPopupMode(QToolButton::DelayedPopup);
    layout->addWidget(button);
207

208
    m_addBookmarkAction = new QAction(Utils::Icons::BOOKMARK_TOOLBAR.icon(), tr("Add Bookmark"), this);
Eike Ziller's avatar
Eike Ziller committed
209
    cmd = Core::ActionManager::registerAction(m_addBookmarkAction, Constants::HELP_ADDBOOKMARK, context);
210 211 212
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+M") : tr("Ctrl+M")));
    connect(m_addBookmarkAction, &QAction::triggered, this, &HelpWidget::addBookmark);
    layout->addWidget(new Utils::StyledSeparator(toolBar));
213
    layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_addBookmarkAction, cmd));
214

215 216 217
    if (style == ModeWidget) {
        layout->addWidget(new Utils::StyledSeparator(toolBar));
        layout->addWidget(OpenPagesManager::instance().openPagesComboBox(), 10);
218 219 220 221
    } else {
        layout->addWidget(new QLabel(), 10);
    }
    if (style != SideBarWidget) {
222 223 224
        m_filterComboBox = new QComboBox;
        m_filterComboBox->setMinimumContentsLength(15);
        m_filterComboBox->setModel(LocalHelpManager::filterModel());
225
        m_filterComboBox->setCurrentIndex(LocalHelpManager::filterIndex());
226 227 228 229 230 231 232
        layout->addWidget(m_filterComboBox);
        connect(m_filterComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
                LocalHelpManager::instance(), &LocalHelpManager::setFilterIndex);
        connect(LocalHelpManager::instance(), &LocalHelpManager::filterIndexChanged,
                m_filterComboBox, &QComboBox::setCurrentIndex);
    }

233 234
    layout->addStretch();

235 236 237
    m_printAction = new QAction(this);
    Core::ActionManager::registerAction(m_printAction, Core::Constants::PRINT, context);
    connect(m_printAction, &QAction::triggered, this, [this]() { print(currentViewer()); });
238

239
    m_copy = new QAction(this);
240
    Core::ActionManager::registerAction(m_copy, Core::Constants::COPY, context);
241
    connect(m_copy, &QAction::triggered, this, &HelpWidget::copy);
242 243

    Core::ActionContainer *advancedMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT_ADVANCED);
Eike Ziller's avatar
Eike Ziller committed
244
    if (QTC_GUARD(advancedMenu)) {
245
        // reuse TextEditor constants to avoid a second pair of menu actions
246 247
        m_scaleUp = new QAction(tr("Increase Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_scaleUp, TextEditor::Constants::INCREASE_FONT_SIZE,
248
                                                  context);
249
        connect(m_scaleUp, &QAction::triggered, this, &HelpWidget::scaleUp);
250 251
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);

252 253
        m_scaleDown = new QAction(tr("Decrease Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_scaleDown, TextEditor::Constants::DECREASE_FONT_SIZE,
254
                                                  context);
255
        connect(m_scaleDown, &QAction::triggered, this, &HelpWidget::scaleDown);
256 257
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);

258 259
        m_resetScale = new QAction(tr("Reset Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_resetScale, TextEditor::Constants::RESET_FONT_SIZE,
260
                                                  context);
261
        connect(m_resetScale, &QAction::triggered, this, &HelpWidget::resetScale);
262 263
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
    }
264

265
    if (style != ExternalWindow) {
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        auto openButton = new QToolButton;
        openButton->setIcon(Utils::Icons::SPLIT_HORIZONTAL_TOOLBAR.icon());
        openButton->setPopupMode(QToolButton::InstantPopup);
        openButton->setProperty("noArrow", true);
        layout->addWidget(openButton);
        QMenu *openMenu = new QMenu(openButton);
        if (m_switchToHelp)
            openMenu->addAction(m_switchToHelp);
        if (style == ModeWidget) {
            QAction *openPage = openMenu->addAction(tr("Open in New Page"));
            connect(openPage, &QAction::triggered, this, [this]() {
                if (HelpViewer *viewer = currentViewer())
                    OpenPagesManager::instance().createPage(viewer->source());
            });
        }
        QAction *openExternal = openMenu->addAction(tr("Open in Window"));
        connect(openExternal, &QAction::triggered, this, [this]() {
            if (HelpViewer *viewer = currentViewer()) {
                openUrlInWindow(viewer->source());
                if (m_style == SideBarWidget)
                    emit closeButtonClicked();
            }
        });
        openButton->setMenu(openMenu);

291 292 293
        const Utils::Icon &icon = style == ModeWidget ? Utils::Icons::CLOSE_TOOLBAR
                                                      : Utils::Icons::CLOSE_SPLIT_RIGHT;
        m_closeAction = new QAction(icon.icon(), QString(), toolBar);
Orgad Shaneh's avatar
Orgad Shaneh committed
294
        connect(m_closeAction, &QAction::triggered, this, &HelpWidget::closeButtonClicked);
295 296 297
        button = new QToolButton;
        button->setDefaultAction(m_closeAction);
        layout->addWidget(button);
298 299 300 301 302 303
    }

    if (style != ModeWidget) {
        HelpViewer *viewer = HelpPlugin::createHelpViewer(qreal(0.0));
        addViewer(viewer);
        setCurrentViewer(viewer);
304 305 306 307 308
    }
}

HelpWidget::~HelpWidget()
{
309
    if (m_sideBar) {
310
        m_sideBar->saveSettings(Core::ICore::settings(), sideBarSettingsKey());
311
        Core::ActionManager::unregisterAction(m_contentsAction, Constants::HELP_CONTENTS);
312
        Core::ActionManager::unregisterAction(m_indexAction, Constants::HELP_INDEX);
Eike Ziller's avatar
Eike Ziller committed
313
        Core::ActionManager::unregisterAction(m_bookmarkAction, Constants::HELP_BOOKMARKS);
314
        Core::ActionManager::unregisterAction(m_searchAction, Constants::HELP_SEARCH);
315 316
        if (m_openPagesAction)
            Core::ActionManager::unregisterAction(m_openPagesAction, Constants::HELP_OPENPAGES);
317
    }
318
    Core::ICore::removeContextObject(m_context);
319
    Core::ActionManager::unregisterAction(m_copy, Core::Constants::COPY);
320
    Core::ActionManager::unregisterAction(m_printAction, Core::Constants::PRINT);
321
    if (m_toggleSideBarAction)
Serhii Moroz's avatar
Serhii Moroz committed
322
        Core::ActionManager::unregisterAction(m_toggleSideBarAction, Core::Constants::TOGGLE_LEFT_SIDEBAR);
323 324
    if (m_switchToHelp)
        Core::ActionManager::unregisterAction(m_switchToHelp, Constants::CONTEXT_HELP);
325
    Core::ActionManager::unregisterAction(m_homeAction, Constants::HELP_HOME);
326 327
    Core::ActionManager::unregisterAction(m_forwardAction, Constants::HELP_NEXT);
    Core::ActionManager::unregisterAction(m_backAction, Constants::HELP_PREVIOUS);
Eike Ziller's avatar
Eike Ziller committed
328
    Core::ActionManager::unregisterAction(m_addBookmarkAction, Constants::HELP_ADDBOOKMARK);
329 330 331 332 333 334
    if (m_scaleUp)
        Core::ActionManager::unregisterAction(m_scaleUp, TextEditor::Constants::INCREASE_FONT_SIZE);
    if (m_scaleDown)
        Core::ActionManager::unregisterAction(m_scaleDown, TextEditor::Constants::DECREASE_FONT_SIZE);
    if (m_resetScale)
        Core::ActionManager::unregisterAction(m_resetScale, TextEditor::Constants::RESET_FONT_SIZE);
335 336
}

337 338 339 340
void HelpWidget::addSideBar()
{
    QMap<QString, Core::Command *> shortcutMap;
    Core::Command *cmd;
341
    bool supportsNewPages = (m_style == ModeWidget);
342

343
    auto contentWindow = new ContentWindow;
344
    auto contentItem = new Core::SideBarItem(contentWindow, Constants::HELP_CONTENTS);
345
    contentWindow->setOpenInNewPageActionVisible(supportsNewPages);
346
    contentWindow->setWindowTitle(HelpPlugin::tr(Constants::SB_CONTENTS));
347 348
    connect(contentWindow, &ContentWindow::linkActivated,
            this, &HelpWidget::open);
Takumi ASAKI's avatar
Takumi ASAKI committed
349
    m_contentsAction = new QAction(HelpPlugin::tr(Constants::SB_CONTENTS), this);
350 351 352
    cmd = Core::ActionManager::registerAction(m_contentsAction, Constants::HELP_CONTENTS, m_context->context());
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+C")
                                                                  : tr("Ctrl+Shift+C")));
353
    shortcutMap.insert(Constants::HELP_CONTENTS, cmd);
354

355
    auto indexWindow = new IndexWindow();
356
    auto indexItem = new Core::SideBarItem(indexWindow, Constants::HELP_INDEX);
357
    indexWindow->setOpenInNewPageActionVisible(supportsNewPages);
358
    indexWindow->setWindowTitle(HelpPlugin::tr(Constants::SB_INDEX));
359 360 361 362
    connect(indexWindow, &IndexWindow::linkActivated,
            this, &HelpWidget::open);
    connect(indexWindow, &IndexWindow::linksActivated,
        this, &HelpWidget::showTopicChooser);
Takumi ASAKI's avatar
Takumi ASAKI committed
363
    m_indexAction = new QAction(HelpPlugin::tr(Constants::SB_INDEX), this);
364 365 366
    cmd = Core::ActionManager::registerAction(m_indexAction, Constants::HELP_INDEX, m_context->context());
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+I")
                                                                  : tr("Ctrl+Shift+I")));
367
    shortcutMap.insert(Constants::HELP_INDEX, cmd);
368

Eike Ziller's avatar
Eike Ziller committed
369
    auto bookmarkWidget = new BookmarkWidget(&LocalHelpManager::bookmarkManager());
370
    bookmarkWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_BOOKMARKS));
371
    bookmarkWidget->setOpenInNewPageActionVisible(supportsNewPages);
372
    auto bookmarkItem = new Core::SideBarItem(bookmarkWidget, Constants::HELP_BOOKMARKS);
Eike Ziller's avatar
Eike Ziller committed
373 374 375 376
    connect(bookmarkWidget, &BookmarkWidget::linkActivated, this, &HelpWidget::setSource);
    m_bookmarkAction = new QAction(tr("Activate Help Bookmarks View"), this);
    cmd = Core::ActionManager::registerAction(m_bookmarkAction, Constants::HELP_BOOKMARKS,
                                              m_context->context());
377
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Alt+Meta+M")
Eike Ziller's avatar
Eike Ziller committed
378
                                                                  : tr("Ctrl+Shift+B")));
379
    shortcutMap.insert(Constants::HELP_BOOKMARKS, cmd);
Eike Ziller's avatar
Eike Ziller committed
380

381 382 383 384 385 386 387
    auto searchItem = new SearchSideBarItem;
    connect(searchItem, &SearchSideBarItem::linkActivated, this, &HelpWidget::openFromSearch);
    m_searchAction = new QAction(tr("Activate Help Search View"), this);
    cmd = Core::ActionManager::registerAction(m_searchAction, Constants::HELP_SEARCH,
                                              m_context->context());
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+/")
                                                                  : tr("Ctrl+Shift+/")));
388
    shortcutMap.insert(Constants::HELP_SEARCH, cmd);
389

390 391 392
    Core::SideBarItem *openPagesItem = 0;
    if (m_style == ModeWidget) {
        QWidget *openPagesWidget = OpenPagesManager::instance().openPagesWidget();
393
        openPagesWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_OPENPAGES));
394
        openPagesItem = new Core::SideBarItem(openPagesWidget, Constants::HELP_OPENPAGES);
395 396 397 398 399
        m_openPagesAction = new QAction(tr("Activate Open Help Pages View"), this);
        cmd = Core::ActionManager::registerAction(m_openPagesAction, Constants::HELP_OPENPAGES,
                                                  m_context->context());
        cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+O")
                                                                      : tr("Ctrl+Shift+O")));
400
        shortcutMap.insert(Constants::HELP_OPENPAGES, cmd);
401 402
    }

403
    QList<Core::SideBarItem *> itemList;
404
    itemList << contentItem << indexItem << bookmarkItem << searchItem;
405 406
    if (openPagesItem)
         itemList << openPagesItem;
407
    m_sideBar = new Core::SideBar(itemList,
408 409
                                  QList<Core::SideBarItem *>() << contentItem
                                  << (openPagesItem ? openPagesItem : indexItem));
410 411 412 413 414
    m_sideBar->setShortcutMap(shortcutMap);
    m_sideBar->setCloseWhenEmpty(true);
    m_sideBarSplitter->insertWidget(0, m_sideBar);
    m_sideBarSplitter->setStretchFactor(0, 0);
    m_sideBarSplitter->setStretchFactor(1, 1);
415 416
    if (m_style != ModeWidget)
        m_sideBar->setVisible(false);
417
    m_sideBar->resize(250, size().height());
418
    m_sideBar->readSettings(Core::ICore::settings(), sideBarSettingsKey());
419 420
    m_sideBarSplitter->setSizes(QList<int>() << m_sideBar->size().width() << 300);

421
    connect(m_contentsAction, &QAction::triggered, m_sideBar, [this]() {
422
        m_sideBar->activateItem(Constants::HELP_CONTENTS);
423
    });
Eike Ziller's avatar
Eike Ziller committed
424
    connect(m_indexAction, &QAction::triggered, m_sideBar, [this]() {
425
        m_sideBar->activateItem(Constants::HELP_INDEX);
426
    });
Eike Ziller's avatar
Eike Ziller committed
427
    connect(m_bookmarkAction, &QAction::triggered, m_sideBar, [this]() {
428
        m_sideBar->activateItem(Constants::HELP_BOOKMARKS);
Eike Ziller's avatar
Eike Ziller committed
429
    });
430
    connect(m_searchAction, &QAction::triggered, m_sideBar, [this]() {
431
        m_sideBar->activateItem(Constants::HELP_SEARCH);
432
    });
433 434
    if (m_openPagesAction) {
        connect(m_openPagesAction, &QAction::triggered, m_sideBar, [this]() {
435
            m_sideBar->activateItem(Constants::HELP_OPENPAGES);
436 437 438 439 440 441 442 443
        });
    }
}

QString HelpWidget::sideBarSettingsKey() const
{
    switch (m_style) {
    case ModeWidget:
444
        return QString(kModeSideBarSettingsKey);
445
    case ExternalWindow:
446
        return QString(kWindowSideBarSettingsKey);
447 448 449 450 451
    case SideBarWidget:
        QTC_CHECK(false);
        break;
    }
    return QString();
452 453
}

454 455
HelpViewer *HelpWidget::currentViewer() const
{
456 457 458 459 460 461 462 463
    return qobject_cast<HelpViewer *>(m_viewerStack->currentWidget());
}

void HelpWidget::setCurrentViewer(HelpViewer *viewer)
{
    m_viewerStack->setCurrentWidget(viewer);
    m_backAction->setEnabled(viewer->isBackwardAvailable());
    m_forwardAction->setEnabled(viewer->isForwardAvailable());
464
    m_addBookmarkAction->setEnabled(isBookmarkable(viewer->source()));
465 466 467 468 469 470 471 472 473 474
    if (m_style == ExternalWindow)
        updateWindowTitle();
    emit sourceChanged(viewer->source());
}

int HelpWidget::currentIndex() const
{
    return m_viewerStack->currentIndex();
}

475
void HelpWidget::addViewer(HelpViewer *viewer)
476 477 478
{
    m_viewerStack->addWidget(viewer);
    viewer->setFocus(Qt::OtherFocusReason);
479 480
    viewer->setActionVisible(HelpViewer::Action::NewPage, m_style == ModeWidget);
    viewer->setActionVisible(HelpViewer::Action::ExternalWindow, m_style != ExternalWindow);
481
    connect(viewer, &HelpViewer::sourceChanged, this, [viewer, this](const QUrl &url) {
482 483
        if (currentViewer() == viewer) {
            m_addBookmarkAction->setEnabled(isBookmarkable(url));
484
            emit sourceChanged(url);
485
        }
486 487 488 489 490 491 492 493 494 495 496 497 498
    });
    connect(viewer, &HelpViewer::forwardAvailable, this, [viewer, this](bool available) {
        if (currentViewer() == viewer)
            m_forwardAction->setEnabled(available);
    });
    connect(viewer, &HelpViewer::backwardAvailable, this, [viewer, this](bool available) {
        if (currentViewer() == viewer)
            m_backAction->setEnabled(available);
    });
    connect(viewer, &HelpViewer::printRequested, this, [viewer, this]() {
        print(viewer);
    });
    if (m_style == ExternalWindow)
Montel Laurent's avatar
Montel Laurent committed
499
        connect(viewer, &HelpViewer::titleChanged, this, &HelpWidget::updateWindowTitle);
500

501
    connect(viewer, &HelpViewer::loadFinished, this, &HelpWidget::highlightSearchTerms);
502 503 504
    connect(viewer, &HelpViewer::newPageRequested, [](const QUrl &url) {
        OpenPagesManager::instance().createPage(url);
    });
505
    connect(viewer, &HelpViewer::externalPageRequested, this, &openUrlInWindow);
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531

    updateCloseButton();
}

void HelpWidget::removeViewerAt(int index)
{
    QWidget *viewerWidget = m_viewerStack->widget(index);
    QTC_ASSERT(viewerWidget, return);
    m_viewerStack->removeWidget(viewerWidget);
    // do not delete, that is done in the model
    // delete viewerWidget;
    if (m_viewerStack->currentWidget())
        setCurrentViewer(qobject_cast<HelpViewer *>(m_viewerStack->currentWidget()));
    updateCloseButton();
}

int HelpWidget::viewerCount() const
{
    return m_viewerStack->count();
}

HelpViewer *HelpWidget::viewerAt(int index) const
{
    return qobject_cast<HelpViewer *>(m_viewerStack->widget(index));
}

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
void HelpWidget::open(const QUrl &url, bool newPage)
{
    if (newPage)
        OpenPagesManager::instance().createPage(url);
    else
        setSource(url);
}

void HelpWidget::showTopicChooser(const QMap<QString, QUrl> &links,
    const QString &keyword, bool newPage)
{
    TopicChooser tc(this, keyword, links);
    if (tc.exec() == QDialog::Accepted)
        open(tc.link(), newPage);
}

548 549 550 551 552 553
void HelpWidget::activateSideBarItem(const QString &id)
{
    QTC_ASSERT(m_sideBar, return);
    m_sideBar->activateItem(id);
}

554 555 556 557 558 559 560 561
void HelpWidget::setSource(const QUrl &url)
{
    HelpViewer* viewer = currentViewer();
    QTC_ASSERT(viewer, return);
    viewer->setSource(url);
    viewer->setFocus(Qt::OtherFocusReason);
}

562
void HelpWidget::openFromSearch(const QUrl &url, const QStringList &searchTerms, bool newPage)
563
{
564
    m_searchTerms = searchTerms;
565
    if (newPage)
566
        OpenPagesManager::instance().createPage(url);
567 568 569 570 571 572
    else {
        HelpViewer* viewer = currentViewer();
        QTC_ASSERT(viewer, return);
        viewer->setSource(url);
        viewer->setFocus(Qt::OtherFocusReason);
    }
573 574
}

575 576 577 578 579
void HelpWidget::closeEvent(QCloseEvent *)
{
    emit aboutToClose();
}

580 581 582
void HelpWidget::updateBackMenu()
{
    m_backMenu->clear();
583 584
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->addBackHistoryItems(m_backMenu);
585 586 587 588 589
}

void HelpWidget::updateForwardMenu()
{
    m_forwardMenu->clear();
590 591
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->addForwardHistoryItems(m_forwardMenu);
592 593
}

594 595
void HelpWidget::updateWindowTitle()
{
596 597
    QTC_ASSERT(currentViewer(), return);
    const QString pageTitle = currentViewer()->title();
598 599 600 601 602 603
    if (pageTitle.isEmpty())
        setWindowTitle(tr("Help"));
    else
        setWindowTitle(tr("Help - %1").arg(pageTitle));
}

604
void HelpWidget::helpModeButtonClicked()
605
{
606 607
    QTC_ASSERT(currentViewer(), return);
    emit openHelpMode(currentViewer()->source());
608 609
    if (m_style == ExternalWindow)
        close();
610 611
}

612 613 614
void HelpWidget::updateCloseButton()
{
    if (m_style == ModeWidget) {
615
        const bool closeOnReturn = LocalHelpManager::returnOnClose();
616 617 618 619
        m_closeAction->setEnabled(closeOnReturn || m_viewerStack->count() > 1);
    }
}

620 621 622 623 624 625 626 627 628 629 630 631
void HelpWidget::goHome()
{
    if (HelpViewer *viewer = currentViewer())
        viewer->home();
}

void HelpWidget::addBookmark()
{
    HelpViewer *viewer = currentViewer();
    QTC_ASSERT(viewer, return);

    const QString &url = viewer->source().toString();
632
    if (!isBookmarkable(url))
633 634 635 636 637 638
        return;

    BookmarkManager *manager = &LocalHelpManager::bookmarkManager();
    manager->showBookmarkDialog(this, viewer->title(), url);
}

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
void HelpWidget::copy()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->copy();
}

void HelpWidget::forward()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->forward();
}

void HelpWidget::backward()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->backward();
}

void HelpWidget::scaleUp()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->scaleUp();
}

void HelpWidget::scaleDown()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->scaleDown();
}

void HelpWidget::resetScale()
{
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->resetScale();
}

void HelpWidget::print(HelpViewer *viewer)
{
    QTC_ASSERT(viewer, return);
    if (!m_printer)
        m_printer = new QPrinter(QPrinter::HighResolution);
    QPrintDialog dlg(m_printer, this);
    dlg.setWindowTitle(tr("Print Documentation"));
    if (!viewer->selectedText().isEmpty())
        dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
    dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange);
    dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies);

    if (dlg.exec() == QDialog::Accepted)
        viewer->print(m_printer);
}

void HelpWidget::highlightSearchTerms()
{
693 694 695 696 697 698 699
    if (m_searchTerms.isEmpty())
        return;
    HelpViewer *viewer = qobject_cast<HelpViewer *>(sender());
    QTC_ASSERT(viewer, return);
    foreach (const QString& term, m_searchTerms)
        viewer->findText(term, 0, false, true);
    m_searchTerms.clear();
700 701
}

702 703
} // Internal
} // Help