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 Assistant module 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 "openpagesmanager.h"
30
31#include "centralwidget.h"
32#include "helpenginewrapper.h"
33#include "helpviewer.h"
34#include "openpagesmodel.h"
35#include "openpagesswitcher.h"
36#include "openpageswidget.h"
37#include "tracer.h"
38#include "../shared/collectionconfiguration.h"
39
40#include <QtWidgets/QApplication>
41#include <QtWidgets/QTreeView>
42
43QT_BEGIN_NAMESPACE
44
45OpenPagesManager *OpenPagesManager::m_instance = nullptr;
46
47OpenPagesManager *OpenPagesManager::createInstance(QObject *parent,
48 bool defaultCollection, const QUrl &cmdLineUrl)
49{
50 TRACE_OBJ
51 Q_ASSERT(!m_instance);
52 m_instance = new OpenPagesManager(parent, defaultCollection, cmdLineUrl);
53 return m_instance;
54}
55
56OpenPagesManager *OpenPagesManager::instance()
57{
58 TRACE_OBJ
59 Q_ASSERT(m_instance);
60 return m_instance;
61}
62
63OpenPagesManager::OpenPagesManager(QObject *parent, bool defaultCollection,
64 const QUrl &cmdLineUrl)
65 : QObject(parent)
66 , m_model(new OpenPagesModel(this))
67{
68 TRACE_OBJ
69 m_openPagesWidget = new OpenPagesWidget(m_model);
70 m_openPagesWidget->setFrameStyle(QFrame::NoFrame);
71 connect(sender: m_openPagesWidget, signal: &OpenPagesWidget::setCurrentPage,
72 receiver: this, slot: QOverload<const QModelIndex &>::of(ptr: &OpenPagesManager::setCurrentPage));
73 connect(sender: m_openPagesWidget, signal: &OpenPagesWidget::closePage,
74 receiver: this, slot: QOverload<const QModelIndex &>::of(ptr: &OpenPagesManager::closePage));
75 connect(sender: m_openPagesWidget, signal: &OpenPagesWidget::closePagesExcept,
76 receiver: this, slot: &OpenPagesManager::closePagesExcept);
77
78 m_openPagesSwitcher = new OpenPagesSwitcher(m_model);
79 connect(sender: m_openPagesSwitcher, signal: &OpenPagesSwitcher::closePage,
80 receiver: this, slot: QOverload<const QModelIndex &>::of(ptr: &OpenPagesManager::closePage));
81 connect(sender: m_openPagesSwitcher, signal: &OpenPagesSwitcher::setCurrentPage,
82 receiver: this, slot: QOverload<const QModelIndex &>::of(ptr: &OpenPagesManager::setCurrentPage));
83
84 setupInitialPages(defaultCollection, cmdLineUrl);
85}
86
87OpenPagesManager ::~OpenPagesManager()
88{
89 TRACE_OBJ
90 m_instance = nullptr;
91 delete m_openPagesSwitcher;
92}
93
94int OpenPagesManager::pageCount() const
95{
96 TRACE_OBJ
97 return m_model->rowCount();
98}
99
100void OpenPagesManager::setupInitialPages(bool defaultCollection,
101 const QUrl &cmdLineUrl)
102{
103 TRACE_OBJ
104 if (cmdLineUrl.isValid()) {
105 createPage(url: cmdLineUrl);
106 return;
107 }
108
109 HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
110 int initialPage = 0;
111 switch (helpEngine.startOption()) {
112 case ShowHomePage:
113 m_model->addPage(url: helpEngine.homePage());
114 break;
115 case ShowBlankPage:
116 m_model->addPage(url: QUrl(QLatin1String("about:blank")));
117 break;
118 case ShowLastPages: {
119 const QStringList &lastShownPageList = helpEngine.lastShownPages();
120 const int pageCount = lastShownPageList.count();
121 if (pageCount == 0) {
122 if (defaultCollection)
123 m_model->addPage(url: QUrl(QLatin1String("help")));
124 else
125 m_model->addPage(url: QUrl(QLatin1String("about:blank")));
126 } else {
127 QStringList zoomFactors = helpEngine.lastZoomFactors();
128 while (zoomFactors.count() < pageCount)
129 zoomFactors.append(t: CollectionConfiguration::DefaultZoomFactor);
130 initialPage = helpEngine.lastTabPage();
131 if (initialPage >= pageCount) {
132 qWarning(msg: "Initial page set to %d, maximum possible value is %d",
133 initialPage, pageCount - 1);
134 initialPage = 0;
135 }
136 for (int curPage = 0; curPage < pageCount; ++curPage) {
137 const QString &curFile = lastShownPageList.at(i: curPage);
138 if (helpEngine.findFile(url: curFile).isValid()
139 || curFile == QLatin1String("about:blank")) {
140 m_model->addPage(url: curFile, zoom: zoomFactors.at(i: curPage).toFloat());
141 } else if (curPage <= initialPage && initialPage > 0)
142 --initialPage;
143 }
144 }
145 break;
146 }
147 default:
148 Q_ASSERT(0);
149 }
150
151 if (m_model->rowCount() == 0)
152 m_model->addPage(url: helpEngine.homePage());
153 for (int i = 0; i < m_model->rowCount(); ++i)
154 CentralWidget::instance()->addPage(page: m_model->pageAt(index: i));
155 setCurrentPage((initialPage >= m_model->rowCount())
156 ? m_model->rowCount() - 1 : initialPage);
157 m_openPagesSwitcher->selectCurrentPage();
158}
159
160HelpViewer *OpenPagesManager::createBlankPage()
161{
162 TRACE_OBJ
163 return createPage(url: QUrl(QLatin1String("about:blank")));
164}
165
166void OpenPagesManager::closeCurrentPage()
167{
168 TRACE_OBJ
169 Q_ASSERT(m_model->rowCount() > 1);
170 const QModelIndexList selectedIndexes
171 = m_openPagesWidget->selectionModel()->selectedRows();
172 if (selectedIndexes.isEmpty())
173 return;
174 Q_ASSERT(selectedIndexes.count() == 1);
175 removePage(index: selectedIndexes.first().row());
176}
177
178HelpViewer *OpenPagesManager::createPage(const QUrl &url, bool fromSearch)
179{
180 TRACE_OBJ
181 if (HelpViewer::launchWithExternalApp(url))
182 return nullptr;
183
184 emit aboutToAddPage();
185
186 m_model->addPage(url);
187 const int index = m_model->rowCount() - 1;
188 HelpViewer * const page = m_model->pageAt(index);
189 CentralWidget::instance()->addPage(page, fromSearch);
190 setCurrentPage(index);
191
192 emit pageAdded(index);
193 return page;
194}
195
196HelpViewer *OpenPagesManager::createNewPageFromSearch(const QUrl &url)
197{
198 TRACE_OBJ
199 return createPage(url, fromSearch: true);
200}
201
202void OpenPagesManager::closePage(HelpViewer *viewer)
203{
204 TRACE_OBJ
205 for (int i = 0; i < m_model->rowCount(); ++i) {
206 if (m_model->pageAt(index: i) == viewer) {
207 removePage(index: i);
208 break;
209 }
210 }
211}
212
213void OpenPagesManager::closePage(const QModelIndex &index)
214{
215 TRACE_OBJ
216 if (index.isValid())
217 removePage(index: index.row());
218}
219
220void OpenPagesManager::closePages(const QString &nameSpace)
221{
222 TRACE_OBJ
223 closeOrReloadPages(nameSpace, tryReload: false);
224}
225
226void OpenPagesManager::reloadPages(const QString &nameSpace)
227{
228 TRACE_OBJ
229 closeOrReloadPages(nameSpace, tryReload: true);
230 m_openPagesWidget->selectCurrentPage();
231}
232
233void OpenPagesManager::closeOrReloadPages(const QString &nameSpace, bool tryReload)
234{
235 TRACE_OBJ
236 for (int i = m_model->rowCount() - 1; i >= 0; --i) {
237 HelpViewer *page = m_model->pageAt(index: i);
238 if (page->source().host() != nameSpace)
239 continue;
240 if (tryReload && HelpEngineWrapper::instance().findFile(url: page->source()).isValid())
241 page->reload();
242 else if (m_model->rowCount() == 1)
243 page->setSource(QUrl(QLatin1String("about:blank")));
244 else
245 removePage(index: i);
246 }
247}
248
249bool OpenPagesManager::pagesOpenForNamespace(const QString &nameSpace) const
250{
251 TRACE_OBJ
252 for (int i = 0; i < m_model->rowCount(); ++i)
253 if (m_model->pageAt(index: i)->source().host() == nameSpace)
254 return true;
255 return false;
256}
257
258void OpenPagesManager::setCurrentPage(const QModelIndex &index)
259{
260 TRACE_OBJ
261 if (index.isValid())
262 setCurrentPage(index.row());
263}
264
265void OpenPagesManager::setCurrentPage(int index)
266{
267 TRACE_OBJ
268 setCurrentPage(m_model->pageAt(index));
269}
270
271void OpenPagesManager::setCurrentPage(HelpViewer *page)
272{
273 TRACE_OBJ
274 CentralWidget::instance()->setCurrentPage(page);
275 m_openPagesWidget->selectCurrentPage();
276}
277
278void OpenPagesManager::removePage(int index)
279{
280 TRACE_OBJ
281 emit aboutToClosePage(index);
282
283 CentralWidget::instance()->removePage(index);
284 m_model->removePage(index);
285 m_openPagesWidget->selectCurrentPage();
286
287 emit pageClosed();
288}
289
290
291void OpenPagesManager::closePagesExcept(const QModelIndex &index)
292{
293 TRACE_OBJ
294 if (!index.isValid())
295 return;
296
297 int i = 0;
298 HelpViewer *viewer = m_model->pageAt(index: index.row());
299 while (m_model->rowCount() > 1) {
300 if (m_model->pageAt(index: i) != viewer)
301 removePage(index: i);
302 else
303 ++i;
304 }
305}
306
307QAbstractItemView *OpenPagesManager::openPagesWidget() const
308{
309 TRACE_OBJ
310 return m_openPagesWidget;
311}
312
313void OpenPagesManager::nextPage()
314{
315 TRACE_OBJ
316 nextOrPreviousPage(offset: 1);
317}
318
319void OpenPagesManager::nextPageWithSwitcher()
320{
321 TRACE_OBJ
322 if (!m_openPagesSwitcher->isVisible()) {
323 m_openPagesSwitcher->selectCurrentPage();
324 m_openPagesSwitcher->gotoNextPage();
325 showSwitcherOrSelectPage();
326 } else {
327 m_openPagesSwitcher->gotoNextPage();
328 }
329}
330
331void OpenPagesManager::previousPage()
332{
333 TRACE_OBJ
334 nextOrPreviousPage(offset: -1);
335}
336
337void OpenPagesManager::previousPageWithSwitcher()
338{
339 TRACE_OBJ
340 if (!m_openPagesSwitcher->isVisible()) {
341 m_openPagesSwitcher->selectCurrentPage();
342 m_openPagesSwitcher->gotoPreviousPage();
343 showSwitcherOrSelectPage();
344 } else {
345 m_openPagesSwitcher->gotoPreviousPage();
346 }
347}
348
349void OpenPagesManager::nextOrPreviousPage(int offset)
350{
351 TRACE_OBJ
352 setCurrentPage((CentralWidget::instance()->currentIndex() + offset
353 + m_model->rowCount()) % m_model->rowCount());
354}
355
356void OpenPagesManager::showSwitcherOrSelectPage() const
357{
358 TRACE_OBJ
359 if (QApplication::keyboardModifiers() != Qt::NoModifier) {
360 const int width = CentralWidget::instance()->width();
361 const int height = CentralWidget::instance()->height();
362 const QPoint p(CentralWidget::instance()->mapToGlobal(QPoint(0, 0)));
363 m_openPagesSwitcher->move(ax: (width - m_openPagesSwitcher->width()) / 2 + p.x(),
364 ay: (height - m_openPagesSwitcher->height()) / 2 + p.y());
365 m_openPagesSwitcher->setVisible(true);
366 } else {
367 m_openPagesSwitcher->selectAndHide();
368 }
369}
370
371QT_END_NAMESPACE
372

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