helpwidget.cpp 27.9 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(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 358 359 360
    connect(indexWindow, &IndexWindow::linkActivated,
            this, &HelpWidget::open);
    connect(indexWindow, &IndexWindow::linksActivated,
        this, &HelpWidget::showTopicChooser);
Takumi ASAKI's avatar
Takumi ASAKI committed
361
    m_indexAction = new QAction(HelpPlugin::tr(Constants::SB_INDEX), this);
362 363 364
    cmd = Core::ActionManager::registerAction(m_indexAction, Constants::HELP_INDEX, m_context->context());
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+I")
                                                                  : tr("Ctrl+Shift+I")));
365
    shortcutMap.insert(Constants::HELP_INDEX, cmd);
366

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

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

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

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

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

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

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

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

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

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

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

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
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);
}

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

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

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

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

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

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

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

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

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

618 619 620 621 622 623 624 625 626 627 628 629
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();
630
    if (!isBookmarkable(url))
631 632 633 634 635 636
        return;

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

637 638 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
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()
{
691 692 693 694 695 696 697
    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();
698 699
}

700 701
} // Internal
} // Help