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