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

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