1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "indexwindow.h"
5
6#include "centralwidget.h"
7#include "helpenginewrapper.h"
8#include "helpviewer.h"
9#include "openpagesmanager.h"
10#include "topicchooser.h"
11#include "tracer.h"
12
13#include <QtWidgets/QLayout>
14#include <QtWidgets/QLabel>
15#include <QtWidgets/QLineEdit>
16#include <QtGui/QKeyEvent>
17#include <QtWidgets/QMenu>
18#include <QtGui/QContextMenuEvent>
19#include <QtWidgets/QListWidgetItem>
20
21#include <QtHelp/QHelpIndexWidget>
22#include <QtHelp/QHelpEngineCore>
23#include <QtHelp/QHelpLink>
24
25QT_BEGIN_NAMESPACE
26
27IndexWindow::IndexWindow(QWidget *parent)
28 : QWidget(parent)
29 , m_searchLineEdit(new QLineEdit)
30 , m_indexWidget(HelpEngineWrapper::instance().indexWidget())
31{
32 TRACE_OBJ
33 QVBoxLayout *layout = new QVBoxLayout(this);
34 QLabel *l = new QLabel(tr(s: "&Look for:"));
35 layout->addWidget(l);
36
37 l->setBuddy(m_searchLineEdit);
38 m_searchLineEdit->setClearButtonEnabled(true);
39 connect(sender: m_searchLineEdit, signal: &QLineEdit::textChanged,
40 context: this, slot: &IndexWindow::filterIndices);
41 m_searchLineEdit->installEventFilter(filterObj: this);
42 layout->setContentsMargins(left: 4, top: 4, right: 4, bottom: 4);
43 layout->addWidget(m_searchLineEdit);
44
45 HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
46 m_indexWidget->installEventFilter(filterObj: this);
47 connect(sender: helpEngine.indexModel(), signal: &QHelpIndexModel::indexCreationStarted,
48 context: this, slot: &IndexWindow::disableSearchLineEdit);
49 connect(sender: helpEngine.indexModel(), signal: &QHelpIndexModel::indexCreated,
50 context: this, slot: &IndexWindow::enableSearchLineEdit);
51 connect(sender: m_indexWidget, signal: &QHelpIndexWidget::documentActivated,
52 context: this, slot: [this](const QHelpLink &link) {
53 emit linkActivated(link: link.url);
54 });
55 connect(sender: m_indexWidget, signal: &QHelpIndexWidget::documentsActivated,
56 context: this, slot: &IndexWindow::documentsActivated);
57 connect(sender: m_searchLineEdit, signal: &QLineEdit::returnPressed,
58 context: m_indexWidget, slot: &QHelpIndexWidget::activateCurrentItem);
59 layout->addWidget(m_indexWidget);
60
61 m_indexWidget->viewport()->installEventFilter(filterObj: this);
62}
63
64IndexWindow::~IndexWindow()
65{
66 TRACE_OBJ
67}
68
69void IndexWindow::filterIndices(const QString &filter)
70{
71 TRACE_OBJ
72 if (filter.contains(c: QLatin1Char('*')))
73 m_indexWidget->filterIndices(filter, wildcard: filter);
74 else
75 m_indexWidget->filterIndices(filter, wildcard: QString());
76}
77
78bool IndexWindow::eventFilter(QObject *obj, QEvent *e)
79{
80 TRACE_OBJ
81 if (obj == m_searchLineEdit && e->type() == QEvent::KeyPress) {
82 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
83 QModelIndex idx = m_indexWidget->currentIndex();
84 switch (ke->key()) {
85 case Qt::Key_Up:
86 idx = m_indexWidget->model()->index(row: idx.row()-1,
87 column: idx.column(), parent: idx.parent());
88 if (idx.isValid()) {
89 m_indexWidget->setCurrentIndex(idx);
90 return true;
91 }
92 break;
93 case Qt::Key_Down:
94 idx = m_indexWidget->model()->index(row: idx.row() + 1,
95 column: idx.column(), parent: idx.parent());
96 if (idx.isValid()) {
97 m_indexWidget->setCurrentIndex(idx);
98 return true;
99 }
100 break;
101 case Qt::Key_Escape:
102 emit escapePressed();
103 return true;
104 default: ; // stop complaining
105 }
106 } else if (obj == m_indexWidget && e->type() == QEvent::ContextMenu) {
107 QContextMenuEvent *ctxtEvent = static_cast<QContextMenuEvent*>(e);
108 QModelIndex idx = m_indexWidget->indexAt(p: ctxtEvent->pos());
109 if (idx.isValid()) {
110 QMenu menu;
111 QAction *curTab = menu.addAction(text: tr(s: "Open Link"));
112 QAction *newTab = menu.addAction(text: tr(s: "Open Link in New Tab"));
113 menu.move(m_indexWidget->mapToGlobal(ctxtEvent->pos()));
114
115 QAction *action = menu.exec();
116 if (curTab == action)
117 m_indexWidget->activateCurrentItem();
118 else if (newTab == action) {
119 open(indexWidget: m_indexWidget, index: idx);
120 }
121 }
122 } else if (m_indexWidget && obj == m_indexWidget->viewport()
123 && e->type() == QEvent::MouseButtonRelease) {
124 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
125 QModelIndex idx = m_indexWidget->indexAt(p: mouseEvent->pos());
126 if (idx.isValid()) {
127 Qt::MouseButtons button = mouseEvent->button();
128 if (((button == Qt::LeftButton) && (mouseEvent->modifiers() & Qt::ControlModifier))
129 || (button == Qt::MiddleButton)) {
130 open(indexWidget: m_indexWidget, index: idx);
131 }
132 }
133 }
134#ifdef Q_OS_MAC
135 else if (obj == m_indexWidget && e->type() == QEvent::KeyPress) {
136 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
137 if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
138 m_indexWidget->activateCurrentItem();
139 }
140#endif
141 return QWidget::eventFilter(watched: obj, event: e);
142}
143
144void IndexWindow::enableSearchLineEdit()
145{
146 TRACE_OBJ
147 m_searchLineEdit->setDisabled(false);
148 filterIndices(filter: m_searchLineEdit->text());
149}
150
151void IndexWindow::disableSearchLineEdit()
152{
153 TRACE_OBJ
154 m_searchLineEdit->setDisabled(true);
155}
156
157void IndexWindow::setSearchLineEditText(const QString &text)
158{
159 TRACE_OBJ
160 m_searchLineEdit->setText(text);
161}
162
163void IndexWindow::focusInEvent(QFocusEvent *e)
164{
165 TRACE_OBJ
166 if (e->reason() != Qt::MouseFocusReason) {
167 m_searchLineEdit->selectAll();
168 m_searchLineEdit->setFocus();
169 }
170}
171
172void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index)
173{
174 TRACE_OBJ
175 QHelpIndexModel *model = qobject_cast<QHelpIndexModel*>(object: indexWidget->model());
176 if (model) {
177 const QString keyword = model->data(index, role: Qt::DisplayRole).toString();
178 const QList<QHelpLink> docs = model->helpEngine()->documentsForKeyword(keyword);
179
180 QUrl url;
181 if (docs.size() > 1) {
182 TopicChooser tc(this, keyword, docs);
183 if (tc.exec() == QDialog::Accepted)
184 url = tc.link();
185 } else if (!docs.isEmpty()) {
186 url = docs.first().url;
187 } else {
188 return;
189 }
190
191 if (!HelpViewer::canOpenPage(url: url.path()))
192 CentralWidget::instance()->setSource(url);
193 else
194 OpenPagesManager::instance()->createPage(url);
195 }
196}
197
198QT_END_NAMESPACE
199

source code of qttools/src/assistant/assistant/indexwindow.cpp