helpwidget.cpp 26.8 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 47
#include <coreplugin/minisplitter.h>
#include <coreplugin/sidebar.h>
48
#include <texteditor/texteditorconstants.h>
49
#include <utils/qtcassert.h>
50
#include <utils/styledbar.h>
51
#include <utils/utilsicons.h>
52

Sergey Belyashov's avatar
Sergey Belyashov committed
53
#include <QCoreApplication>
54
#include <QHBoxLayout>
55 56 57
#include <QHelpEngine>
#include <QHelpSearchEngine>
#include <QHelpSearchQuery>
58
#include <QMenu>
59 60 61
#include <QPrinter>
#include <QPrintDialog>
#include <QStackedWidget>
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
HelpWidget::HelpWidget(const Core::Context &context, WidgetStyle style, QWidget *parent) :
    QWidget(parent),
80
    m_style(style)
81
{
82 83 84 85 86 87 88 89 90 91
    m_viewerStack = new QStackedWidget;

    auto hLayout = new QHBoxLayout(this);
    hLayout->setMargin(0);
    hLayout->setSpacing(0);

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

92
    Utils::StyledBar *toolBar = new Utils::StyledBar();
93 94 95
    QHBoxLayout *layout = new QHBoxLayout(toolBar);
    layout->setSpacing(0);
    layout->setMargin(0);
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

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

114
    Core::Command *cmd;
115 116 117 118 119 120 121 122
    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
123 124
    }
    if (style != SideBarWidget) {
Ulf Hermann's avatar
Ulf Hermann committed
125
        m_toggleSideBarAction = new QAction(Utils::Icons::TOGGLE_SIDEBAR_TOOLBAR.icon(),
Sergey Belyashov's avatar
Sergey Belyashov committed
126 127
                                            QCoreApplication::translate("Core", Core::Constants::TR_SHOW_SIDEBAR),
                                            toolBar);
128 129 130 131 132 133
        m_toggleSideBarAction->setCheckable(true);
        m_toggleSideBarAction->setChecked(false);
        cmd = Core::ActionManager::registerAction(m_toggleSideBarAction,
                                                  Core::Constants::TOGGLE_SIDEBAR, context);
        connect(m_toggleSideBarAction, &QAction::toggled, m_toggleSideBarAction,
                [this](bool checked) {
Sergey Belyashov's avatar
Sergey Belyashov committed
134 135 136 137
                    m_toggleSideBarAction->setText(
                        QCoreApplication::translate("Core",
                                                    checked ? Core::Constants::TR_HIDE_SIDEBAR
                                                            : Core::Constants::TR_SHOW_SIDEBAR));
138 139
                });
        addSideBar();
140
        m_toggleSideBarAction->setChecked(m_sideBar->isVisibleTo(this));
141 142 143 144 145
        connect(m_toggleSideBarAction, &QAction::triggered, m_sideBar, &Core::SideBar::setVisible);
        connect(m_sideBar, &Core::SideBar::sideBarClosed, m_toggleSideBarAction, [this]() {
            m_toggleSideBarAction->setChecked(false);
        });
    }
146 147
    if (style == ExternalWindow)
        layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_toggleSideBarAction, cmd));
148

149
    if (style != ModeWidget) {
150
        m_switchToHelp = new QAction(tr("Open in Help Mode"), toolBar);
151
        cmd = Core::ActionManager::registerAction(m_switchToHelp, Constants::CONTEXT_HELP, context);
Montel Laurent's avatar
Montel Laurent committed
152
        connect(m_switchToHelp, &QAction::triggered, this, &HelpWidget::helpModeButtonClicked);
153
        layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_switchToHelp, cmd));
154
    }
155

156
    m_homeAction = new QAction(Icons::HOME_TOOLBAR.icon(), tr("Home"), this);
157 158
    cmd = Core::ActionManager::registerAction(m_homeAction, Constants::HELP_HOME, context);
    connect(m_homeAction, &QAction::triggered, this, &HelpWidget::goHome);
159
    layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_homeAction, cmd));
160

161
    m_backAction = new QAction(Utils::Icons::PREV_TOOLBAR.icon(), tr("Back"), toolBar);
162
    connect(m_backAction, &QAction::triggered, this, &HelpWidget::backward);
163
    m_backMenu = new QMenu(toolBar);
Montel Laurent's avatar
Montel Laurent committed
164
    connect(m_backMenu, &QMenu::aboutToShow, this, &HelpWidget::updateBackMenu);
165 166 167
    m_backAction->setMenu(m_backMenu);
    cmd = Core::ActionManager::registerAction(m_backAction, Constants::HELP_PREVIOUS, context);
    cmd->setDefaultKeySequence(QKeySequence::Back);
168 169 170
    button = Core::Command::toolButtonWithAppendedShortcut(m_backAction, cmd);
    button->setPopupMode(QToolButton::DelayedPopup);
    layout->addWidget(button);
171

172
    m_forwardAction = new QAction(Utils::Icons::NEXT_TOOLBAR.icon(), tr("Forward"), toolBar);
173
    connect(m_forwardAction, &QAction::triggered, this, &HelpWidget::forward);
174
    m_forwardMenu = new QMenu(toolBar);
Montel Laurent's avatar
Montel Laurent committed
175
    connect(m_forwardMenu, &QMenu::aboutToShow, this, &HelpWidget::updateForwardMenu);
176 177 178
    m_forwardAction->setMenu(m_forwardMenu);
    cmd = Core::ActionManager::registerAction(m_forwardAction, Constants::HELP_NEXT, context);
    cmd->setDefaultKeySequence(QKeySequence::Forward);
179 180 181
    button = Core::Command::toolButtonWithAppendedShortcut(m_forwardAction, cmd);
    button->setPopupMode(QToolButton::DelayedPopup);
    layout->addWidget(button);
182

183
    m_addBookmarkAction = new QAction(Icons::BOOKMARK_TOOLBAR.icon(), tr("Add Bookmark"), this);
Eike Ziller's avatar
Eike Ziller committed
184
    cmd = Core::ActionManager::registerAction(m_addBookmarkAction, Constants::HELP_ADDBOOKMARK, context);
185 186 187
    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));
188
    layout->addWidget(Core::Command::toolButtonWithAppendedShortcut(m_addBookmarkAction, cmd));
189

190 191 192
    if (style == ModeWidget) {
        layout->addWidget(new Utils::StyledSeparator(toolBar));
        layout->addWidget(OpenPagesManager::instance().openPagesComboBox(), 10);
193 194 195 196
    } else {
        layout->addWidget(new QLabel(), 10);
    }
    if (style != SideBarWidget) {
197 198 199
        m_filterComboBox = new QComboBox;
        m_filterComboBox->setMinimumContentsLength(15);
        m_filterComboBox->setModel(LocalHelpManager::filterModel());
200
        m_filterComboBox->setCurrentIndex(LocalHelpManager::filterIndex());
201 202 203 204 205 206 207
        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);
    }

208 209
    layout->addStretch();

210 211 212
    m_printAction = new QAction(this);
    Core::ActionManager::registerAction(m_printAction, Core::Constants::PRINT, context);
    connect(m_printAction, &QAction::triggered, this, [this]() { print(currentViewer()); });
213

214
    m_copy = new QAction(this);
215
    Core::ActionManager::registerAction(m_copy, Core::Constants::COPY, context);
216
    connect(m_copy, &QAction::triggered, this, &HelpWidget::copy);
217 218

    Core::ActionContainer *advancedMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT_ADVANCED);
Eike Ziller's avatar
Eike Ziller committed
219
    if (QTC_GUARD(advancedMenu)) {
220
        // reuse TextEditor constants to avoid a second pair of menu actions
221 222
        m_scaleUp = new QAction(tr("Increase Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_scaleUp, TextEditor::Constants::INCREASE_FONT_SIZE,
223
                                                  context);
224
        connect(m_scaleUp, &QAction::triggered, this, &HelpWidget::scaleUp);
225 226
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);

227 228
        m_scaleDown = new QAction(tr("Decrease Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_scaleDown, TextEditor::Constants::DECREASE_FONT_SIZE,
229
                                                  context);
230
        connect(m_scaleDown, &QAction::triggered, this, &HelpWidget::scaleDown);
231 232
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);

233 234
        m_resetScale = new QAction(tr("Reset Font Size"), this);
        cmd = Core::ActionManager::registerAction(m_resetScale, TextEditor::Constants::RESET_FONT_SIZE,
235
                                                  context);
236
        connect(m_resetScale, &QAction::triggered, this, &HelpWidget::resetScale);
237 238
        advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
    }
239

240
    if (style != ExternalWindow) {
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
        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);

266 267 268
        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
269
        connect(m_closeAction, &QAction::triggered, this, &HelpWidget::closeButtonClicked);
270 271 272
        button = new QToolButton;
        button->setDefaultAction(m_closeAction);
        layout->addWidget(button);
273 274 275 276 277 278
    }

    if (style != ModeWidget) {
        HelpViewer *viewer = HelpPlugin::createHelpViewer(qreal(0.0));
        addViewer(viewer);
        setCurrentViewer(viewer);
279 280 281 282 283
    }
}

HelpWidget::~HelpWidget()
{
284
    if (m_sideBar) {
285
        m_sideBar->saveSettings(Core::ICore::settings(), sideBarSettingsKey());
286
        Core::ActionManager::unregisterAction(m_contentsAction, Constants::HELP_CONTENTS);
287
        Core::ActionManager::unregisterAction(m_indexAction, Constants::HELP_INDEX);
Eike Ziller's avatar
Eike Ziller committed
288
        Core::ActionManager::unregisterAction(m_bookmarkAction, Constants::HELP_BOOKMARKS);
289
        Core::ActionManager::unregisterAction(m_searchAction, Constants::HELP_SEARCH);
290 291
        if (m_openPagesAction)
            Core::ActionManager::unregisterAction(m_openPagesAction, Constants::HELP_OPENPAGES);
292
    }
293
    Core::ICore::removeContextObject(m_context);
294
    Core::ActionManager::unregisterAction(m_copy, Core::Constants::COPY);
295
    Core::ActionManager::unregisterAction(m_printAction, Core::Constants::PRINT);
296 297
    if (m_toggleSideBarAction)
        Core::ActionManager::unregisterAction(m_toggleSideBarAction, Core::Constants::TOGGLE_SIDEBAR);
298 299
    if (m_switchToHelp)
        Core::ActionManager::unregisterAction(m_switchToHelp, Constants::CONTEXT_HELP);
300
    Core::ActionManager::unregisterAction(m_homeAction, Constants::HELP_HOME);
301 302
    Core::ActionManager::unregisterAction(m_forwardAction, Constants::HELP_NEXT);
    Core::ActionManager::unregisterAction(m_backAction, Constants::HELP_PREVIOUS);
Eike Ziller's avatar
Eike Ziller committed
303
    Core::ActionManager::unregisterAction(m_addBookmarkAction, Constants::HELP_ADDBOOKMARK);
304 305 306 307 308 309
    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);
310 311
}

312 313 314 315
void HelpWidget::addSideBar()
{
    QMap<QString, Core::Command *> shortcutMap;
    Core::Command *cmd;
316
    bool supportsNewPages = (m_style == ModeWidget);
317

318
    auto contentWindow = new ContentWindow;
319
    auto contentItem = new Core::SideBarItem(contentWindow, Constants::HELP_CONTENTS);
320
    contentWindow->setOpenInNewPageActionVisible(supportsNewPages);
321
    contentWindow->setWindowTitle(HelpPlugin::tr(Constants::SB_CONTENTS));
322 323
    connect(contentWindow, &ContentWindow::linkActivated,
            this, &HelpWidget::open);
Takumi ASAKI's avatar
Takumi ASAKI committed
324
    m_contentsAction = new QAction(HelpPlugin::tr(Constants::SB_CONTENTS), this);
325 326 327
    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")));
328
    shortcutMap.insert(Constants::HELP_CONTENTS, cmd);
329

330
    auto indexWindow = new IndexWindow();
331
    auto indexItem = new Core::SideBarItem(indexWindow, Constants::HELP_INDEX);
332
    indexWindow->setOpenInNewPageActionVisible(supportsNewPages);
333
    indexWindow->setWindowTitle(HelpPlugin::tr(Constants::SB_INDEX));
334 335 336 337
    connect(indexWindow, &IndexWindow::linkActivated,
            this, &HelpWidget::open);
    connect(indexWindow, &IndexWindow::linksActivated,
        this, &HelpWidget::showTopicChooser);
Takumi ASAKI's avatar
Takumi ASAKI committed
338
    m_indexAction = new QAction(HelpPlugin::tr(Constants::SB_INDEX), this);
339 340 341
    cmd = Core::ActionManager::registerAction(m_indexAction, Constants::HELP_INDEX, m_context->context());
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+I")
                                                                  : tr("Ctrl+Shift+I")));
342
    shortcutMap.insert(Constants::HELP_INDEX, cmd);
343

Eike Ziller's avatar
Eike Ziller committed
344
    auto bookmarkWidget = new BookmarkWidget(&LocalHelpManager::bookmarkManager());
345
    bookmarkWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_BOOKMARKS));
346
    bookmarkWidget->setOpenInNewPageActionVisible(supportsNewPages);
347
    auto bookmarkItem = new Core::SideBarItem(bookmarkWidget, Constants::HELP_BOOKMARKS);
Eike Ziller's avatar
Eike Ziller committed
348 349 350 351
    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());
352
    cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Alt+Meta+M")
Eike Ziller's avatar
Eike Ziller committed
353
                                                                  : tr("Ctrl+Shift+B")));
354
    shortcutMap.insert(Constants::HELP_BOOKMARKS, cmd);
Eike Ziller's avatar
Eike Ziller committed
355

356 357 358 359 360 361 362
    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+/")));
363
    shortcutMap.insert(Constants::HELP_SEARCH, cmd);
364

365 366 367
    Core::SideBarItem *openPagesItem = 0;
    if (m_style == ModeWidget) {
        QWidget *openPagesWidget = OpenPagesManager::instance().openPagesWidget();
368
        openPagesWidget->setWindowTitle(HelpPlugin::tr(Constants::SB_OPENPAGES));
369
        openPagesItem = new Core::SideBarItem(openPagesWidget, Constants::HELP_OPENPAGES);
370 371 372 373 374
        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")));
375
        shortcutMap.insert(Constants::HELP_OPENPAGES, cmd);
376 377
    }

378
    QList<Core::SideBarItem *> itemList;
379
    itemList << contentItem << indexItem << bookmarkItem << searchItem;
380 381
    if (openPagesItem)
         itemList << openPagesItem;
382
    m_sideBar = new Core::SideBar(itemList,
383 384
                                  QList<Core::SideBarItem *>() << contentItem
                                  << (openPagesItem ? openPagesItem : indexItem));
385 386 387 388 389
    m_sideBar->setShortcutMap(shortcutMap);
    m_sideBar->setCloseWhenEmpty(true);
    m_sideBarSplitter->insertWidget(0, m_sideBar);
    m_sideBarSplitter->setStretchFactor(0, 0);
    m_sideBarSplitter->setStretchFactor(1, 1);
390 391
    if (m_style != ModeWidget)
        m_sideBar->setVisible(false);
392
    m_sideBar->resize(250, size().height());
393
    m_sideBar->readSettings(Core::ICore::settings(), sideBarSettingsKey());
394 395
    m_sideBarSplitter->setSizes(QList<int>() << m_sideBar->size().width() << 300);

396
    connect(m_contentsAction, &QAction::triggered, m_sideBar, [this]() {
397
        m_sideBar->activateItem(Constants::HELP_CONTENTS);
398
    });
Eike Ziller's avatar
Eike Ziller committed
399
    connect(m_indexAction, &QAction::triggered, m_sideBar, [this]() {
400
        m_sideBar->activateItem(Constants::HELP_INDEX);
401
    });
Eike Ziller's avatar
Eike Ziller committed
402
    connect(m_bookmarkAction, &QAction::triggered, m_sideBar, [this]() {
403
        m_sideBar->activateItem(Constants::HELP_BOOKMARKS);
Eike Ziller's avatar
Eike Ziller committed
404
    });
405
    connect(m_searchAction, &QAction::triggered, m_sideBar, [this]() {
406
        m_sideBar->activateItem(Constants::HELP_SEARCH);
407
    });
408 409
    if (m_openPagesAction) {
        connect(m_openPagesAction, &QAction::triggered, m_sideBar, [this]() {
410
            m_sideBar->activateItem(Constants::HELP_OPENPAGES);
411 412 413 414 415 416 417 418
        });
    }
}

QString HelpWidget::sideBarSettingsKey() const
{
    switch (m_style) {
    case ModeWidget:
419
        return QString(kModeSideBarSettingsKey);
420
    case ExternalWindow:
421
        return QString(kWindowSideBarSettingsKey);
422 423 424 425 426
    case SideBarWidget:
        QTC_CHECK(false);
        break;
    }
    return QString();
427 428
}

429 430
HelpViewer *HelpWidget::currentViewer() const
{
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
    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());
    if (m_style == ExternalWindow)
        updateWindowTitle();
    emit sourceChanged(viewer->source());
}

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

449
void HelpWidget::addViewer(HelpViewer *viewer)
450 451 452
{
    m_viewerStack->addWidget(viewer);
    viewer->setFocus(Qt::OtherFocusReason);
453 454
    viewer->setActionVisible(HelpViewer::Action::NewPage, m_style == ModeWidget);
    viewer->setActionVisible(HelpViewer::Action::ExternalWindow, m_style != ExternalWindow);
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
    connect(viewer, &HelpViewer::sourceChanged, this, [viewer, this](const QUrl &url) {
        if (currentViewer() == viewer)
            emit sourceChanged(url);
    });
    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
471
        connect(viewer, &HelpViewer::titleChanged, this, &HelpWidget::updateWindowTitle);
472

473
    connect(viewer, &HelpViewer::loadFinished, this, &HelpWidget::highlightSearchTerms);
474 475 476
    connect(viewer, &HelpViewer::newPageRequested, [](const QUrl &url) {
        OpenPagesManager::instance().createPage(url);
    });
477
    connect(viewer, &HelpViewer::externalPageRequested, this, &openUrlInWindow);
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503

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

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
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);
}

520 521 522 523 524 525
void HelpWidget::activateSideBarItem(const QString &id)
{
    QTC_ASSERT(m_sideBar, return);
    m_sideBar->activateItem(id);
}

526 527 528 529 530 531 532 533
void HelpWidget::setSource(const QUrl &url)
{
    HelpViewer* viewer = currentViewer();
    QTC_ASSERT(viewer, return);
    viewer->setSource(url);
    viewer->setFocus(Qt::OtherFocusReason);
}

534
void HelpWidget::openFromSearch(const QUrl &url, const QStringList &searchTerms, bool newPage)
535
{
536
    m_searchTerms = searchTerms;
537
    if (newPage)
538
        OpenPagesManager::instance().createPage(url);
539 540 541 542 543 544
    else {
        HelpViewer* viewer = currentViewer();
        QTC_ASSERT(viewer, return);
        viewer->setSource(url);
        viewer->setFocus(Qt::OtherFocusReason);
    }
545 546
}

547 548 549 550 551
void HelpWidget::closeEvent(QCloseEvent *)
{
    emit aboutToClose();
}

552 553 554
void HelpWidget::updateBackMenu()
{
    m_backMenu->clear();
555 556
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->addBackHistoryItems(m_backMenu);
557 558 559 560 561
}

void HelpWidget::updateForwardMenu()
{
    m_forwardMenu->clear();
562 563
    QTC_ASSERT(currentViewer(), return);
    currentViewer()->addForwardHistoryItems(m_forwardMenu);
564 565
}

566 567
void HelpWidget::updateWindowTitle()
{
568 569
    QTC_ASSERT(currentViewer(), return);
    const QString pageTitle = currentViewer()->title();
570 571 572 573 574 575
    if (pageTitle.isEmpty())
        setWindowTitle(tr("Help"));
    else
        setWindowTitle(tr("Help - %1").arg(pageTitle));
}

576
void HelpWidget::helpModeButtonClicked()
577
{
578 579
    QTC_ASSERT(currentViewer(), return);
    emit openHelpMode(currentViewer()->source());
580 581
    if (m_style == ExternalWindow)
        close();
582 583
}

584 585 586
void HelpWidget::updateCloseButton()
{
    if (m_style == ModeWidget) {
587
        const bool closeOnReturn = LocalHelpManager::returnOnClose();
588 589 590 591
        m_closeAction->setEnabled(closeOnReturn || m_viewerStack->count() > 1);
    }
}

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
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();
    if (url.isEmpty() || url == Help::Constants::AboutBlank)
        return;

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

611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 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
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()
{
665 666 667 668 669 670 671
    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();
672 673
}

674 675
} // Internal
} // Help