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
static void openUrlInWindow(const QUrl &url)
{
    HelpViewer *viewer = HelpPlugin::viewerForHelpViewerLocation(Core::HelpManager::ExternalHelpAlways);
73
    HelpPlugin::showInHelpViewer(url, viewer);
74 75
}

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

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

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

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

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

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

    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);

123
    Core::Command *cmd;
124 125 126 127 128 129 130 131
    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
132 133
    }
    if (style != SideBarWidget) {
Serhii Moroz's avatar
Serhii Moroz committed
134 135
        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
136
                                            toolBar);
137 138 139
        m_toggleSideBarAction->setCheckable(true);
        m_toggleSideBarAction->setChecked(false);
        cmd = Core::ActionManager::registerAction(m_toggleSideBarAction,
Serhii Moroz's avatar
Serhii Moroz committed
140
                                                  Core::Constants::TOGGLE_LEFT_SIDEBAR, context);
141 142
        connect(m_toggleSideBarAction, &QAction::toggled, m_toggleSideBarAction,
                [this](bool checked) {
Sergey Belyashov's avatar
Sergey Belyashov committed
143 144
                    m_toggleSideBarAction->setText(
                        QCoreApplication::translate("Core",
Serhii Moroz's avatar
Serhii Moroz committed
145 146
                                                    checked ? Core::Constants::TR_HIDE_LEFT_SIDEBAR
                                                            : Core::Constants::TR_SHOW_LEFT_SIDEBAR));
147 148
                });
        addSideBar();
149
        m_toggleSideBarAction->setChecked(m_sideBar->isVisibleTo(this));
150 151 152 153
        connect(m_toggleSideBarAction, &QAction::triggered, m_sideBar, &Core::SideBar::setVisible);
        connect(m_sideBar, &Core::SideBar::sideBarClosed, m_toggleSideBarAction, [this]() {
            m_toggleSideBarAction->setChecked(false);
        });
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
        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);
        }
170
    }
171

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

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

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

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

206
    m_addBookmarkAction = new QAction(Utils::Icons::BOOKMARK_TOOLBAR.icon(), tr("Add Bookmark"), this);
Eike Ziller's avatar
Eike Ziller committed
207
    cmd = Core::ActionManager::registerAction(m_addBookmarkAction, Constants::HELP_ADDBOOKMARK, context);
208 209 210
    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));
211
    layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_addBookmarkAction, cmd));
212

213 214 215
    if (style == ModeWidget) {
        layout->addWidget(new Utils::StyledSeparator(toolBar));
        layout->addWidget(OpenPagesManager::instance().openPagesComboBox(), 10);
216 217 218 219
    } else {
        layout->addWidget(new QLabel(), 10);
    }
    if (style != SideBarWidget) {
220 221 222
        m_filterComboBox = new QComboBox;
        m_filterComboBox->setMinimumContentsLength(15);
        m_filterComboBox->setModel(LocalHelpManager::filterModel());
223
        m_filterComboBox->setCurrentIndex(LocalHelpManager::filterIndex());
224 225 226 227 228 229 230
        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);
    }

231 232
    layout->addStretch();

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

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

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

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

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

263
    if (style != ExternalWindow) {
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
        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);

289 290 291
        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
292
        connect(m_closeAction, &QAction::triggered, this, &HelpWidget::closeButtonClicked);
293 294 295
        button = new QToolButton;
        button->setDefaultAction(m_closeAction);
        layout->addWidget(button);
296 297 298 299 300 301
    }

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

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

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

341
    auto contentWindow = new ContentWindow;
342
    auto contentItem = new Core::SideBarItem(contentWindow, Constants::HELP_CONTENTS);
343
    contentWindow->setOpenInNewPageActionVisible(supportsNewPages);
344
    contentWindow->setWindowTitle(HelpPlugin::tr(Constants::SB_CONTENTS));
345 346
    connect(contentWindow, &ContentWindow::linkActivated,
            this, &HelpWidget::open);
Takumi ASAKI's avatar
Takumi ASAKI committed
347
    m_contentsAction = new QAction(HelpPlugin::tr(Constants::SB_CONTENTS), this);
348 349 350
    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")));
351
    shortcutMap.insert(Constants::HELP_CONTENTS, cmd);
352

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

Eike Ziller's avatar
Eike Ziller committed
365
    auto bookmarkWidget = new BookmarkWidget(&LocalHelpManager::bookmarkManager());
366
    bookmarkWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_BOOKMARKS));
367
    bookmarkWidget->setOpenInNewPageActionVisible(supportsNewPages);
368
    auto bookmarkItem = new Core::SideBarItem(bookmarkWidget, Constants::HELP_BOOKMARKS);
Eike Ziller's avatar
Eike Ziller committed
369 370 371 372
    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());
373
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Alt+Meta+M")
Eike Ziller's avatar
Eike Ziller committed
374
                                                                  : tr("Ctrl+Shift+B")));
375
    shortcutMap.insert(Constants::HELP_BOOKMARKS, cmd);
Eike Ziller's avatar
Eike Ziller committed
376

377 378 379 380 381 382 383
    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+/")));
384
    shortcutMap.insert(Constants::HELP_SEARCH, cmd);
385

386 387 388
    Core::SideBarItem *openPagesItem = 0;
    if (m_style == ModeWidget) {
        QWidget *openPagesWidget = OpenPagesManager::instance().openPagesWidget();
389
        openPagesWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_OPENPAGES));
390
        openPagesItem = new Core::SideBarItem(openPagesWidget, Constants::HELP_OPENPAGES);
391 392 393 394 395
        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")));
396
        shortcutMap.insert(Constants::HELP_OPENPAGES, cmd);
397 398
    }

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

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

QString HelpWidget::sideBarSettingsKey() const
{
    switch (m_style) {
    case ModeWidget:
440
        return QString(kModeSideBarSettingsKey);
441
    case ExternalWindow:
442
        return QString(kWindowSideBarSettingsKey);
443 444 445 446 447
    case SideBarWidget:
        QTC_CHECK(false);
        break;
    }
    return QString();
448 449
}

450 451
HelpViewer *HelpWidget::currentViewer() const
{
452 453 454 455 456 457 458 459
    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());
460
    m_addBookmarkAction->setEnabled(isBookmarkable(viewer->source()));
461 462 463 464 465 466 467 468 469 470
    if (m_style == ExternalWindow)
        updateWindowTitle();
    emit sourceChanged(viewer->source());
}

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

471
void HelpWidget::addViewer(HelpViewer *viewer)
472 473 474
{
    m_viewerStack->addWidget(viewer);
    viewer->setFocus(Qt::OtherFocusReason);
475 476
    viewer->setActionVisible(HelpViewer::Action::NewPage, m_style == ModeWidget);
    viewer->setActionVisible(HelpViewer::Action::ExternalWindow, m_style != ExternalWindow);
477
    connect(viewer, &HelpViewer::sourceChanged, this, [viewer, this](const QUrl &url) {
478 479
        if (currentViewer() == viewer) {
            m_addBookmarkAction->setEnabled(isBookmarkable(url));
480
            emit sourceChanged(url);
481
        }
482 483 484 485 486 487 488 489 490 491 492 493 494
    });
    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
495
        connect(viewer, &HelpViewer::titleChanged, this, &HelpWidget::updateWindowTitle);
496

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

    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));
}

528 529 530 531 532 533 534 535
void HelpWidget::open(const QUrl &url, bool newPage)
{
    if (newPage)
        OpenPagesManager::instance().createPage(url);
    else
        setSource(url);
}

536
void HelpWidget::showLinks(const QMap<QString, QUrl> &links,
537 538
    const QString &keyword, bool newPage)
{
539 540 541 542 543 544 545 546 547
    if (links.size() < 1)
        return;
    if (links.size() == 1) {
        open(links.first(), newPage);
    } else {
        TopicChooser tc(this, keyword, links);
        if (tc.exec() == QDialog::Accepted)
            open(tc.link(), newPage);
    }
548 549
}

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

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

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

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

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

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

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

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

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

622 623 624 625 626 627 628 629 630 631 632 633
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();
634
    if (!isBookmarkable(url))
635 636 637 638 639 640
        return;

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

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 693 694
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()
{
695 696 697 698 699 700 701
    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();
702 703
}

704 705
} // Internal
} // Help