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
50 QT_BEGIN_NAMESPACE
51
IndexWindow(QWidget * parent)52 IndexWindow::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("&Look for:"));
60 layout->addWidget(l);
61
62 l->setBuddy(m_searchLineEdit);
63 m_searchLineEdit->setClearButtonEnabled(true);
64 connect(m_searchLineEdit, &QLineEdit::textChanged,
65 this, &IndexWindow::filterIndices);
66 m_searchLineEdit->installEventFilter(this);
67 layout->setContentsMargins(4, 4, 4, 4);
68 layout->addWidget(m_searchLineEdit);
69
70 HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
71 m_indexWidget->installEventFilter(this);
72 connect(helpEngine.indexModel(), &QHelpIndexModel::indexCreationStarted,
73 this, &IndexWindow::disableSearchLineEdit);
74 connect(helpEngine.indexModel(), &QHelpIndexModel::indexCreated,
75 this, &IndexWindow::enableSearchLineEdit);
76 connect(m_indexWidget, &QHelpIndexWidget::documentActivated,
77 this, [this](const QHelpLink &link) {
78 emit linkActivated(link.url);
79 });
80 connect(m_indexWidget, &QHelpIndexWidget::documentsActivated,
81 this, &IndexWindow::documentsActivated);
82 connect(m_searchLineEdit, &QLineEdit::returnPressed,
83 m_indexWidget, &QHelpIndexWidget::activateCurrentItem);
84 layout->addWidget(m_indexWidget);
85
86 m_indexWidget->viewport()->installEventFilter(this);
87 }
88
~IndexWindow()89 IndexWindow::~IndexWindow()
90 {
91 TRACE_OBJ
92 }
93
filterIndices(const QString & filter)94 void IndexWindow::filterIndices(const QString &filter)
95 {
96 TRACE_OBJ
97 if (filter.contains(QLatin1Char('*')))
98 m_indexWidget->filterIndices(filter, filter);
99 else
100 m_indexWidget->filterIndices(filter, QString());
101 }
102
eventFilter(QObject * obj,QEvent * e)103 bool 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(idx.row()-1,
112 idx.column(), 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(idx.row() + 1,
120 idx.column(), 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(ctxtEvent->pos());
134 if (idx.isValid()) {
135 QMenu menu;
136 QAction *curTab = menu.addAction(tr("Open Link"));
137 QAction *newTab = menu.addAction(tr("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(m_indexWidget, 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(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(m_indexWidget, 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(obj, e);
167 }
168
enableSearchLineEdit()169 void IndexWindow::enableSearchLineEdit()
170 {
171 TRACE_OBJ
172 m_searchLineEdit->setDisabled(false);
173 filterIndices(m_searchLineEdit->text());
174 }
175
disableSearchLineEdit()176 void IndexWindow::disableSearchLineEdit()
177 {
178 TRACE_OBJ
179 m_searchLineEdit->setDisabled(true);
180 }
181
setSearchLineEditText(const QString & text)182 void IndexWindow::setSearchLineEditText(const QString &text)
183 {
184 TRACE_OBJ
185 m_searchLineEdit->setText(text);
186 }
187
focusInEvent(QFocusEvent * e)188 void 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
open(QHelpIndexWidget * indexWidget,const QModelIndex & index)197 void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index)
198 {
199 TRACE_OBJ
200 QHelpIndexModel *model = qobject_cast<QHelpIndexModel*>(indexWidget->model());
201 if (model) {
202 const QString keyword = model->data(index, 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.path()))
217 CentralWidget::instance()->setSource(url);
218 else
219 OpenPagesManager::instance()->createPage(url);
220 }
221 }
222
223 QT_END_NAMESPACE
224