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 "contentwindow.h"
30 
31 #include "centralwidget.h"
32 #include "helpenginewrapper.h"
33 #include "helpviewer.h"
34 #include "openpagesmanager.h"
35 #include "tracer.h"
36 
37 #include <QtWidgets/QLayout>
38 #include <QtGui/QFocusEvent>
39 #include <QtWidgets/QMenu>
40 
41 #include <QtHelp/QHelpContentWidget>
42 
43 QT_BEGIN_NAMESPACE
44 
ContentWindow()45 ContentWindow::ContentWindow()
46     : m_contentWidget(HelpEngineWrapper::instance().contentWidget())
47     , m_expandDepth(-2)
48 {
49     TRACE_OBJ
50     m_contentWidget->viewport()->installEventFilter(this);
51     m_contentWidget->setContextMenuPolicy(Qt::CustomContextMenu);
52 
53     QVBoxLayout *layout = new QVBoxLayout(this);
54     layout->setContentsMargins(4, 4, 4, 4);
55     layout->addWidget(m_contentWidget);
56 
57     connect(m_contentWidget, &QWidget::customContextMenuRequested,
58             this, &ContentWindow::showContextMenu);
59     connect(m_contentWidget, &QHelpContentWidget::linkActivated,
60             this, &ContentWindow::linkActivated);
61 
62     QHelpContentModel *contentModel =
63         qobject_cast<QHelpContentModel*>(m_contentWidget->model());
64     connect(contentModel, &QHelpContentModel::contentsCreated,
65             this, &ContentWindow::expandTOC);
66 }
67 
~ContentWindow()68 ContentWindow::~ContentWindow()
69 {
70     TRACE_OBJ
71 }
72 
syncToContent(const QUrl & url)73 bool ContentWindow::syncToContent(const QUrl& url)
74 {
75     TRACE_OBJ
76     QModelIndex idx = m_contentWidget->indexOf(url);
77     if (!idx.isValid())
78         return false;
79     m_contentWidget->setCurrentIndex(idx);
80     return true;
81 }
82 
expandTOC()83 void ContentWindow::expandTOC()
84 {
85     TRACE_OBJ
86     Q_ASSERT(m_expandDepth >= -2);
87     if (m_expandDepth > -2) {
88         expandToDepth(m_expandDepth);
89         m_expandDepth = -2;
90     }
91 }
92 
expandToDepth(int depth)93 void ContentWindow::expandToDepth(int depth)
94 {
95     TRACE_OBJ
96     Q_ASSERT(depth >= -2);
97     m_expandDepth = depth;
98     if (depth == -1)
99         m_contentWidget->expandAll();
100     else if (depth == 0)
101         m_contentWidget->collapseAll();
102     else
103         m_contentWidget->expandToDepth(depth - 1);
104 }
105 
focusInEvent(QFocusEvent * e)106 void ContentWindow::focusInEvent(QFocusEvent *e)
107 {
108     TRACE_OBJ
109     if (e->reason() != Qt::MouseFocusReason)
110         m_contentWidget->setFocus();
111 }
112 
keyPressEvent(QKeyEvent * e)113 void ContentWindow::keyPressEvent(QKeyEvent *e)
114 {
115     TRACE_OBJ
116     if (e->key() == Qt::Key_Escape)
117         emit escapePressed();
118 }
119 
eventFilter(QObject * o,QEvent * e)120 bool ContentWindow::eventFilter(QObject *o, QEvent *e)
121 {
122     TRACE_OBJ
123     if (m_contentWidget && o == m_contentWidget->viewport()
124         && e->type() == QEvent::MouseButtonRelease) {
125         QMouseEvent *me = static_cast<QMouseEvent*>(e);
126         const QModelIndex &index = m_contentWidget->indexAt(me->pos());
127         if (!index.isValid())
128             return QWidget::eventFilter(o, e);
129 
130         const Qt::MouseButtons button = me->button();
131         QItemSelectionModel *sm = m_contentWidget->selectionModel();
132         if (sm->isSelected(index)) {
133             if ((button == Qt::LeftButton && (me->modifiers() & Qt::ControlModifier))
134                 || (button == Qt::MiddleButton)) {
135                 QHelpContentModel *contentModel =
136                     qobject_cast<QHelpContentModel*>(m_contentWidget->model());
137                 if (contentModel) {
138                     QHelpContentItem *itm = contentModel->contentItemAt(index);
139                     if (itm && HelpViewer::canOpenPage(itm->url().path()))
140                         OpenPagesManager::instance()->createPage(itm->url());
141                 }
142             } else if (button == Qt::LeftButton) {
143                 itemClicked(index);
144             }
145         }
146     }
147     return QWidget::eventFilter(o, e);
148 }
149 
150 
showContextMenu(const QPoint & pos)151 void ContentWindow::showContextMenu(const QPoint &pos)
152 {
153     TRACE_OBJ
154     if (!m_contentWidget->indexAt(pos).isValid())
155         return;
156 
157     QHelpContentModel *contentModel =
158         qobject_cast<QHelpContentModel*>(m_contentWidget->model());
159     QHelpContentItem *itm =
160         contentModel->contentItemAt(m_contentWidget->currentIndex());
161 
162     QMenu menu;
163     QAction *curTab = menu.addAction(tr("Open Link"));
164     QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
165     if (!HelpViewer::canOpenPage(itm->url().path()))
166         newTab->setEnabled(false);
167 
168     menu.move(m_contentWidget->mapToGlobal(pos));
169 
170     QAction *action = menu.exec();
171     if (curTab == action)
172         emit linkActivated(itm->url());
173     else if (newTab == action)
174         OpenPagesManager::instance()->createPage(itm->url());
175 }
176 
itemClicked(const QModelIndex & index)177 void ContentWindow::itemClicked(const QModelIndex &index)
178 {
179     TRACE_OBJ
180     QHelpContentModel *contentModel =
181         qobject_cast<QHelpContentModel*>(m_contentWidget->model());
182 
183     if (contentModel) {
184         if (QHelpContentItem *itm = contentModel->contentItemAt(index)) {
185             const QUrl &url = itm->url();
186             if (url != CentralWidget::instance()->currentSource())
187                 emit linkActivated(url);
188         }
189     }
190 }
191 
192 QT_END_NAMESPACE
193