1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "indexwindow.h"
30
31#include "centralwidget.h"
32#include "helpenginewrapper.h"
33#include "helpviewer.h"
34#include "openpagesmanager.h"
35#include "topicchooser.h"
36#include "tracer.h"
37
38#include <QtWidgets/QLayout>
39#include <QtWidgets/QLabel>
40#include <QtWidgets/QLineEdit>
41#include <QtGui/QKeyEvent>
42#include <QtWidgets/QMenu>
43#include <QtGui/QContextMenuEvent>
44#include <QtWidgets/QListWidgetItem>
45
46#include <QtHelp/QHelpIndexWidget>
47#include <QtHelp/QHelpEngineCore>
48#include <QtHelp/QHelpLink>
49
50QT_BEGIN_NAMESPACE
51
52IndexWindow::IndexWindow(QWidget *parent)
53 : QWidget(parent)
54 , m_searchLineEdit(new QLineEdit)
55 , m_indexWidget(HelpEngineWrapper::instance().indexWidget())
56{
57 TRACE_OBJ
58 QVBoxLayout *layout = new QVBoxLayout(this);
59 QLabel *l = new QLabel(tr(s: "&Look for:"));
60 layout->addWidget(l);
61
62 l->setBuddy(m_searchLineEdit);
63 m_searchLineEdit->setClearButtonEnabled(true);
64 connect(sender: m_searchLineEdit, signal: &QLineEdit::textChanged,
65 receiver: this, slot: &IndexWindow::filterIndices);
66 m_searchLineEdit->installEventFilter(filterObj: this);
67 layout->setContentsMargins(left: 4, top: 4, right: 4, bottom: 4);
68 layout->addWidget(m_searchLineEdit);
69
70 HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
71 m_indexWidget->installEventFilter(filterObj: this);
72 connect(sender: helpEngine.indexModel(), signal: &QHelpIndexModel::indexCreationStarted,
73 receiver: this, slot: &IndexWindow::disableSearchLineEdit);
74 connect(sender: helpEngine.indexModel(), signal: &QHelpIndexModel::indexCreated,
75 receiver: this, slot: &IndexWindow::enableSearchLineEdit);
76 connect(sender: m_indexWidget, signal: &QHelpIndexWidget::documentActivated,
77 context: this, slot: [this](const QHelpLink &link) {
78 emit linkActivated(link: link.url);
79 });
80 connect(sender: m_indexWidget, signal: &QHelpIndexWidget::documentsActivated,
81 receiver: this, slot: &IndexWindow::documentsActivated);
82 connect(sender: m_searchLineEdit, signal: &QLineEdit::returnPressed,
83 receiver: m_indexWidget, slot: &QHelpIndexWidget::activateCurrentItem);
84 layout->addWidget(m_indexWidget);
85
86 m_indexWidget->viewport()->installEventFilter(filterObj: this);
87}
88
89IndexWindow::~IndexWindow()
90{
91 TRACE_OBJ
92}
93
94void IndexWindow::filterIndices(const QString &filter)
95{
96 TRACE_OBJ
97 if (filter.contains(c: QLatin1Char('*')))
98 m_indexWidget->filterIndices(filter, wildcard: filter);
99 else
100 m_indexWidget->filterIndices(filter, wildcard: QString());
101}
102
103bool IndexWindow::eventFilter(QObject *obj, QEvent *e)
104{
105 TRACE_OBJ
106 if (obj == m_searchLineEdit && e->type() == QEvent::KeyPress) {
107 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
108 QModelIndex idx = m_indexWidget->currentIndex();
109 switch (ke->key()) {
110 case Qt::Key_Up:
111 idx = m_indexWidget->model()->index(row: idx.row()-1,
112 column: idx.column(), parent: idx.parent());
113 if (idx.isValid()) {
114 m_indexWidget->setCurrentIndex(idx);
115 return true;
116 }
117 break;
118 case Qt::Key_Down:
119 idx = m_indexWidget->model()->index(row: idx.row() + 1,
120 column: idx.column(), parent: idx.parent());
121 if (idx.isValid()) {
122 m_indexWidget->setCurrentIndex(idx);
123 return true;
124 }
125 break;
126 case Qt::Key_Escape:
127 emit escapePressed();
128 return true;
129 default: ; // stop complaining
130 }
131 } else if (obj == m_indexWidget && e->type() == QEvent::ContextMenu) {
132 QContextMenuEvent *ctxtEvent = static_cast<QContextMenuEvent*>(e);
133 QModelIndex idx = m_indexWidget->indexAt(p: ctxtEvent->pos());
134 if (idx.isValid()) {
135 QMenu menu;
136 QAction *curTab = menu.addAction(text: tr(s: "Open Link"));
137 QAction *newTab = menu.addAction(text: tr(s: "Open Link in New Tab"));
138 menu.move(m_indexWidget->mapToGlobal(ctxtEvent->pos()));
139
140 QAction *action = menu.exec();
141 if (curTab == action)
142 m_indexWidget->activateCurrentItem();
143 else if (newTab == action) {
144 open(indexWidget: m_indexWidget, index: idx);
145 }
146 }
147 } else if (m_indexWidget && obj == m_indexWidget->viewport()
148 && e->type() == QEvent::MouseButtonRelease) {
149 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
150 QModelIndex idx = m_indexWidget->indexAt(p: mouseEvent->pos());
151 if (idx.isValid()) {
152 Qt::MouseButtons button = mouseEvent->button();
153 if (((button == Qt::LeftButton) && (mouseEvent->modifiers() & Qt::ControlModifier))
154 || (button == Qt::MiddleButton)) {
155 open(indexWidget: m_indexWidget, index: idx);
156 }
157 }
158 }
159#ifdef Q_OS_MAC
160 else if (obj == m_indexWidget && e->type() == QEvent::KeyPress) {
161 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
162 if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
163 m_indexWidget->activateCurrentItem();
164 }
165#endif
166 return QWidget::eventFilter(watched: obj, event: e);
167}
168
169void IndexWindow::enableSearchLineEdit()
170{
171 TRACE_OBJ
172 m_searchLineEdit->setDisabled(false);
173 filterIndices(filter: m_searchLineEdit->text());
174}
175
176void IndexWindow::disableSearchLineEdit()
177{
178 TRACE_OBJ
179 m_searchLineEdit->setDisabled(true);
180}
181
182void IndexWindow::setSearchLineEditText(const QString &text)
183{
184 TRACE_OBJ
185 m_searchLineEdit->setText(text);
186}
187
188void IndexWindow::focusInEvent(QFocusEvent *e)
189{
190 TRACE_OBJ
191 if (e->reason() != Qt::MouseFocusReason) {
192 m_searchLineEdit->selectAll();
193 m_searchLineEdit->setFocus();
194 }
195}
196
197void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index)
198{
199 TRACE_OBJ
200 QHelpIndexModel *model = qobject_cast<QHelpIndexModel*>(object: indexWidget->model());
201 if (model) {
202 const QString keyword = model->data(index, role: Qt::DisplayRole).toString();
203 const QList<QHelpLink> docs = model->helpEngine()->documentsForKeyword(keyword);
204
205 QUrl url;
206 if (docs.count() > 1) {
207 TopicChooser tc(this, keyword, docs);
208 if (tc.exec() == QDialog::Accepted)
209 url = tc.link();
210 } else if (!docs.isEmpty()) {
211 url = docs.first().url;
212 } else {
213 return;
214 }
215
216 if (!HelpViewer::canOpenPage(url: url.path()))
217 CentralWidget::instance()->setSource(url);
218 else
219 OpenPagesManager::instance()->createPage(url);
220 }
221}
222
223QT_END_NAMESPACE
224

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