1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 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 "mainwindow.h" |
30 | |
31 | #include "aboutdialog.h" |
32 | #include "bookmarkmanager.h" |
33 | #include "centralwidget.h" |
34 | #include "cmdlineparser.h" |
35 | #include "contentwindow.h" |
36 | #include "globalactions.h" |
37 | #include "helpenginewrapper.h" |
38 | #include "indexwindow.h" |
39 | #include "openpagesmanager.h" |
40 | #include "preferencesdialog.h" |
41 | #include "qtdocinstaller.h" |
42 | #include "remotecontrol.h" |
43 | #include "searchwidget.h" |
44 | #include "topicchooser.h" |
45 | #include "tracer.h" |
46 | |
47 | #include <QtCore/QByteArray> |
48 | #include <QtCore/QDateTime> |
49 | #include <QtCore/QDebug> |
50 | #include <QtCore/QDir> |
51 | #include <QtCore/QPair> |
52 | #include <QtCore/QResource> |
53 | #include <QtCore/QStandardPaths> |
54 | #include <QtCore/QTextStream> |
55 | #include <QtCore/QTimer> |
56 | #include <QtCore/QBuffer> |
57 | #include <QtCore/QLibraryInfo> |
58 | #include <QtCore/QFileInfo> |
59 | #include <QtCore/QDir> |
60 | |
61 | #include <QtWidgets/QAction> |
62 | #include <QtWidgets/QComboBox> |
63 | #include <QtWidgets/QDockWidget> |
64 | #include <QtGui/QFontDatabase> |
65 | #include <QtGui/QImageReader> |
66 | #include <QtGui/QScreen> |
67 | #include <QtWidgets/QFileDialog> |
68 | #include <QtWidgets/QLabel> |
69 | #include <QtWidgets/QLayout> |
70 | #include <QtWidgets/QLineEdit> |
71 | #include <QtWidgets/QMenuBar> |
72 | #include <QtWidgets/QMessageBox> |
73 | #include <QtWidgets/QProgressBar> |
74 | #include <QtWidgets/QShortcut> |
75 | #include <QtWidgets/QStatusBar> |
76 | #include <QtWidgets/QToolBar> |
77 | #include <QtWidgets/QToolButton> |
78 | |
79 | #include <QtHelp/QHelpContentModel> |
80 | #include <QtHelp/QHelpEngineCore> |
81 | #include <QtHelp/QHelpIndexModel> |
82 | #include <QtHelp/QHelpSearchEngine> |
83 | #include <QtHelp/QHelpFilterEngine> |
84 | |
85 | #include <cstdlib> |
86 | |
87 | QT_BEGIN_NAMESPACE |
88 | |
89 | enum { warnAboutMissingModules = 0 }; |
90 | |
91 | MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) |
92 | : QMainWindow(parent) |
93 | , m_cmdLine(cmdLine) |
94 | { |
95 | TRACE_OBJ |
96 | |
97 | setToolButtonStyle(Qt::ToolButtonFollowStyle); |
98 | setDockOptions(dockOptions() | AllowNestedDocks); |
99 | |
100 | QString collectionFile; |
101 | if (usesDefaultCollection()) { |
102 | MainWindow::collectionFileDirectory(createDir: true); |
103 | collectionFile = MainWindow::defaultHelpCollectionFileName(); |
104 | } else { |
105 | collectionFile = cmdLine->collectionFile(); |
106 | } |
107 | HelpEngineWrapper &helpEngineWrapper = |
108 | HelpEngineWrapper::instance(collectionFile); |
109 | BookmarkManager *bookMarkManager = BookmarkManager::instance(); |
110 | |
111 | if (!initHelpDB(registerInternalDoc: !cmdLine->collectionFileGiven())) { |
112 | qDebug(msg: "Fatal error: Help engine initialization failed. " |
113 | "Error message was: %s\nAssistant will now exit." , |
114 | qPrintable(HelpEngineWrapper::instance().error())); |
115 | std::exit(status: 1); |
116 | } |
117 | |
118 | m_centralWidget = new CentralWidget(this); |
119 | setCentralWidget(m_centralWidget); |
120 | |
121 | m_indexWindow = new IndexWindow(this); |
122 | QDockWidget *indexDock = new QDockWidget(tr(s: "Index" ), this); |
123 | indexDock->setObjectName(QLatin1String("IndexWindow" )); |
124 | indexDock->setWidget(m_indexWindow); |
125 | addDockWidget(area: Qt::LeftDockWidgetArea, dockwidget: indexDock); |
126 | |
127 | m_contentWindow = new ContentWindow; |
128 | QDockWidget *contentDock = new QDockWidget(tr(s: "Contents" ), this); |
129 | contentDock->setObjectName(QLatin1String("ContentWindow" )); |
130 | contentDock->setWidget(m_contentWindow); |
131 | addDockWidget(area: Qt::LeftDockWidgetArea, dockwidget: contentDock); |
132 | |
133 | m_searchWindow = new SearchWidget(helpEngineWrapper.searchEngine()); |
134 | m_searchWindow->setFont(!helpEngineWrapper.usesBrowserFont() ? qApp->font() |
135 | : helpEngineWrapper.browserFont()); |
136 | QDockWidget *searchDock = new QDockWidget(tr(s: "Search" ), this); |
137 | searchDock->setObjectName(QLatin1String("SearchWindow" )); |
138 | searchDock->setWidget(m_searchWindow); |
139 | addDockWidget(area: Qt::LeftDockWidgetArea, dockwidget: searchDock); |
140 | |
141 | QDockWidget *bookmarkDock = new QDockWidget(tr(s: "Bookmarks" ), this); |
142 | bookmarkDock->setObjectName(QLatin1String("BookmarkWindow" )); |
143 | bookmarkDock->setWidget(m_bookmarkWidget |
144 | = bookMarkManager->bookmarkDockWidget()); |
145 | addDockWidget(area: Qt::LeftDockWidgetArea, dockwidget: bookmarkDock); |
146 | |
147 | QDockWidget *openPagesDock = new QDockWidget(tr(s: "Open Pages" ), this); |
148 | openPagesDock->setObjectName(QLatin1String("Open Pages" )); |
149 | OpenPagesManager *openPagesManager |
150 | = OpenPagesManager::createInstance(parent: this, defaultCollection: usesDefaultCollection(), cmdLineUrl: m_cmdLine->url()); |
151 | openPagesDock->setWidget(openPagesManager->openPagesWidget()); |
152 | addDockWidget(area: Qt::LeftDockWidgetArea, dockwidget: openPagesDock); |
153 | |
154 | connect(sender: m_centralWidget, signal: &CentralWidget::addBookmark, |
155 | receiver: bookMarkManager, slot: &BookmarkManager::addBookmark); |
156 | connect(sender: bookMarkManager, signal: &BookmarkManager::escapePressed, |
157 | receiver: this, slot: &MainWindow::activateCurrentCentralWidgetTab); |
158 | connect(sender: bookMarkManager, signal: &BookmarkManager::setSource, |
159 | receiver: m_centralWidget, slot: &CentralWidget::setSource); |
160 | connect(sender: bookMarkManager, signal: &BookmarkManager::setSourceInNewTab, |
161 | context: openPagesManager, slot: [openPagesManager](const QUrl &url){ openPagesManager->createPage(url); }); |
162 | |
163 | QHelpSearchEngine *searchEngine = helpEngineWrapper.searchEngine(); |
164 | connect(sender: searchEngine, signal: &QHelpSearchEngine::indexingStarted, |
165 | receiver: this, slot: &MainWindow::indexingStarted); |
166 | connect(sender: searchEngine, signal: &QHelpSearchEngine::indexingFinished, |
167 | receiver: this, slot: &MainWindow::indexingFinished); |
168 | |
169 | QString defWindowTitle = tr(s: "Qt Assistant" ); |
170 | setWindowTitle(defWindowTitle); |
171 | |
172 | setupActions(); |
173 | statusBar()->show(); |
174 | m_centralWidget->connectTabBar(); |
175 | |
176 | setupFilterToolbar(); |
177 | setupAddressToolbar(); |
178 | |
179 | const QString windowTitle = helpEngineWrapper.windowTitle(); |
180 | setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); |
181 | QByteArray iconArray = helpEngineWrapper.applicationIcon(); |
182 | if (iconArray.size() > 0) { |
183 | QBuffer buffer(&iconArray); |
184 | QImageReader reader(&buffer); |
185 | QIcon appIcon; |
186 | do { |
187 | QPixmap pix; |
188 | pix.convertFromImage(img: reader.read()); |
189 | appIcon.addPixmap(pixmap: pix); |
190 | } while (reader.jumpToNextImage()); |
191 | qApp->setWindowIcon(appIcon); |
192 | } |
193 | #if !defined(Q_OS_OSX) && !defined(Q_OS_WIN) |
194 | else { |
195 | QIcon appIcon(QLatin1String(":/qt-project.org/assistant/images/assistant-128.png" )); |
196 | qApp->setWindowIcon(appIcon); |
197 | } |
198 | #endif |
199 | |
200 | QToolBar *toolBar = addToolBar(title: tr(s: "Bookmark Toolbar" )); |
201 | toolBar->setObjectName(QLatin1String("Bookmark Toolbar" )); |
202 | bookMarkManager->setBookmarksToolbar(toolBar); |
203 | |
204 | toolBar->hide(); |
205 | toolBarMenu()->addAction(action: toolBar->toggleViewAction()); |
206 | |
207 | QByteArray ba(helpEngineWrapper.mainWindow()); |
208 | if (!ba.isEmpty()) |
209 | restoreState(state: ba); |
210 | |
211 | ba = helpEngineWrapper.mainWindowGeometry(); |
212 | if (!ba.isEmpty()) { |
213 | restoreGeometry(geometry: ba); |
214 | } else { |
215 | tabifyDockWidget(first: contentDock, second: indexDock); |
216 | tabifyDockWidget(first: indexDock, second: bookmarkDock); |
217 | tabifyDockWidget(first: bookmarkDock, second: searchDock); |
218 | contentDock->raise(); |
219 | const QRect screen = QGuiApplication::primaryScreen()->geometry(); |
220 | resize(w: 4*screen.width()/5, h: 4*screen.height()/5); |
221 | |
222 | adjustSize(); // make sure we won't start outside of the screen |
223 | move(screen.center() - rect().center()); |
224 | } |
225 | |
226 | if (!helpEngineWrapper.hasFontSettings()) { |
227 | helpEngineWrapper.setUseAppFont(false); |
228 | helpEngineWrapper.setUseBrowserFont(false); |
229 | helpEngineWrapper.setAppFont(qApp->font()); |
230 | helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin); |
231 | helpEngineWrapper.setBrowserFont(qApp->font()); |
232 | helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin); |
233 | } else { |
234 | updateApplicationFont(); |
235 | } |
236 | |
237 | updateAboutMenuText(); |
238 | |
239 | QTimer::singleShot(interval: 0, receiver: this, slot: &MainWindow::insertLastPages); |
240 | if (m_cmdLine->enableRemoteControl()) |
241 | (void)new RemoteControl(this); |
242 | |
243 | if (m_cmdLine->contents() == CmdLineParser::Show) |
244 | showContents(); |
245 | else if (m_cmdLine->contents() == CmdLineParser::Hide) |
246 | hideContents(); |
247 | |
248 | if (m_cmdLine->index() == CmdLineParser::Show) |
249 | showIndex(); |
250 | else if (m_cmdLine->index() == CmdLineParser::Hide) |
251 | hideIndex(); |
252 | |
253 | if (m_cmdLine->bookmarks() == CmdLineParser::Show) |
254 | showBookmarksDockWidget(); |
255 | else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) |
256 | hideBookmarksDockWidget(); |
257 | |
258 | if (m_cmdLine->search() == CmdLineParser::Show) |
259 | showSearch(); |
260 | else if (m_cmdLine->search() == CmdLineParser::Hide) |
261 | hideSearch(); |
262 | |
263 | if (m_cmdLine->contents() == CmdLineParser::Activate) |
264 | showContents(); |
265 | else if (m_cmdLine->index() == CmdLineParser::Activate) |
266 | showIndex(); |
267 | else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) |
268 | showBookmarksDockWidget(); |
269 | |
270 | if (!m_cmdLine->currentFilter().isEmpty()) { |
271 | const QString &curFilter = m_cmdLine->currentFilter(); |
272 | if (helpEngineWrapper.filterEngine()->filters().contains(str: curFilter)) |
273 | helpEngineWrapper.filterEngine()->setActiveFilter(curFilter); |
274 | } |
275 | |
276 | if (usesDefaultCollection()) |
277 | QTimer::singleShot(interval: 0, receiver: this, slot: &MainWindow::lookForNewQtDocumentation); |
278 | else |
279 | checkInitState(); |
280 | |
281 | connect(sender: &helpEngineWrapper, signal: &HelpEngineWrapper::documentationRemoved, |
282 | receiver: this, slot: &MainWindow::documentationRemoved); |
283 | connect(sender: &helpEngineWrapper, signal: &HelpEngineWrapper::documentationUpdated, |
284 | receiver: this, slot: &MainWindow::documentationUpdated); |
285 | |
286 | setTabPosition(areas: Qt::AllDockWidgetAreas, tabPosition: QTabWidget::North); |
287 | GlobalActions::instance()->updateActions(); |
288 | if (helpEngineWrapper.addressBarEnabled()) |
289 | showNewAddress(); |
290 | } |
291 | |
292 | MainWindow::~MainWindow() |
293 | { |
294 | TRACE_OBJ |
295 | delete m_qtDocInstaller; |
296 | } |
297 | |
298 | bool MainWindow::usesDefaultCollection() const |
299 | { |
300 | TRACE_OBJ |
301 | return m_cmdLine->collectionFile().isEmpty(); |
302 | } |
303 | |
304 | void MainWindow::closeEvent(QCloseEvent *e) |
305 | { |
306 | TRACE_OBJ |
307 | BookmarkManager::destroy(); |
308 | HelpEngineWrapper::instance().setMainWindow(saveState()); |
309 | HelpEngineWrapper::instance().setMainWindowGeometry(saveGeometry()); |
310 | QMainWindow::closeEvent(event: e); |
311 | } |
312 | |
313 | bool MainWindow::initHelpDB(bool registerInternalDoc) |
314 | { |
315 | TRACE_OBJ |
316 | HelpEngineWrapper &helpEngineWrapper = HelpEngineWrapper::instance(); |
317 | if (!helpEngineWrapper.setupData()) |
318 | return false; |
319 | |
320 | if (!registerInternalDoc) { |
321 | if (helpEngineWrapper.defaultHomePage() == QLatin1String("help" )) |
322 | helpEngineWrapper.setDefaultHomePage(QLatin1String("about:blank" )); |
323 | return true; |
324 | } |
325 | bool assistantInternalDocRegistered = false; |
326 | QString intern(QLatin1String("org.qt-project.assistantinternal-" )); |
327 | for (const QString &ns : helpEngineWrapper.registeredDocumentations()) { |
328 | if (ns.startsWith(s: intern)) { |
329 | intern = ns; |
330 | assistantInternalDocRegistered = true; |
331 | break; |
332 | } |
333 | } |
334 | |
335 | const QString &collectionFile = helpEngineWrapper.collectionFile(); |
336 | QFileInfo fi(collectionFile); |
337 | QString helpFile; |
338 | QTextStream(&helpFile) << fi.absolutePath() << QDir::separator() |
339 | << QLatin1String("assistant.qch." ) << (QT_VERSION >> 16) |
340 | << QLatin1Char('.') << ((QT_VERSION >> 8) & 0xFF); |
341 | |
342 | bool needsSetup = false; |
343 | if (!assistantInternalDocRegistered || !QFile::exists(fileName: helpFile)) { |
344 | QFile file(helpFile); |
345 | if (file.open(flags: QIODevice::WriteOnly)) { |
346 | QResource res(QLatin1String(":/qt-project.org/assistant/assistant.qch" )); |
347 | if (file.write(data: (const char*)res.data(), len: res.size()) != res.size()) |
348 | qDebug() << QLatin1String("could not write assistant.qch..." ); |
349 | |
350 | file.close(); |
351 | } |
352 | helpEngineWrapper.unregisterDocumentation(namespaceName: intern); |
353 | helpEngineWrapper.registerDocumentation(docFile: helpFile); |
354 | needsSetup = true; |
355 | } |
356 | |
357 | if (needsSetup) |
358 | helpEngineWrapper.setupData(); |
359 | return true; |
360 | } |
361 | |
362 | static const char *docs[] = { |
363 | "assistant" , "designer" , "linguist" , // Qt 4 |
364 | "qmake" , |
365 | "qt" , |
366 | "qtqmake" , |
367 | "activeqt" , |
368 | "qtandroidextras" , |
369 | "qtassistant" , |
370 | "qtbluetooth" , |
371 | "qtconcurrent" , |
372 | "qtconnectivity" , |
373 | "qtcore" , |
374 | "qtdbus" , |
375 | "qtdesigner" , |
376 | "qtdoc" , |
377 | "qtenginio" , |
378 | "qtgraphicaleffects" , |
379 | "qtgui" , |
380 | "qthelp" , |
381 | "qtimageformats" , |
382 | "qtlinguist" , |
383 | "qtlocation" , |
384 | "qtmacextras" , |
385 | "qtmultimedia" , |
386 | "qtmultimediawidgets" , |
387 | "qtnfc" , |
388 | "qtnetwork" , |
389 | "qtopengl" , |
390 | "qtpositioning" , |
391 | "qtprintsupport" , |
392 | "qtqml" , |
393 | "qtquick" , |
394 | "qtscript" , |
395 | "qtscripttools" , |
396 | "qtsensors" , |
397 | "qtsql" , |
398 | "qtsvg" , |
399 | "qttestlib" , |
400 | "qtuitools" , |
401 | "qtwebkit" , |
402 | "qtwebkitexamples" , |
403 | "qtwidgets" , |
404 | "qtxml" , |
405 | "qtxmlpatterns" , |
406 | "qdoc" , |
407 | "qtx11extras" , |
408 | "qtserialport" , |
409 | "qtquickcontrols" , |
410 | "qtquickcontrolsstyles" , |
411 | "qtquickdialogs" , |
412 | "qtquicklayouts" , |
413 | "qtwebsockets" , |
414 | "qtwinextras" |
415 | }; |
416 | |
417 | static QStringList newQtDocumentation() |
418 | { |
419 | QStringList result; |
420 | const QDir docDirectory(QLibraryInfo::location(QLibraryInfo::DocumentationPath)); |
421 | const QFileInfoList entries = docDirectory.entryInfoList(nameFilters: QStringList(QStringLiteral("*.qch" )), |
422 | filters: QDir::Files, sort: QDir::Name); |
423 | if (!entries.isEmpty()) { |
424 | result.reserve(alloc: entries.size()); |
425 | for (const QFileInfo &fi : entries) |
426 | result.append(t: fi.baseName()); |
427 | return result; |
428 | } |
429 | if (warnAboutMissingModules) |
430 | qWarning() << "No documentation found in " << QDir::toNativeSeparators(pathName: docDirectory.absolutePath()); |
431 | const int docCount = int(sizeof(docs) / sizeof(docs[0])); |
432 | result.reserve(alloc: docCount); |
433 | for (int d = 0; d < docCount; ++d) |
434 | result.append(t: QLatin1String(docs[d])); |
435 | return result; |
436 | } |
437 | |
438 | void MainWindow::lookForNewQtDocumentation() |
439 | { |
440 | TRACE_OBJ |
441 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
442 | |
443 | const QStringList &docs = newQtDocumentation(); |
444 | const int docCount = docs.size(); |
445 | QList<QtDocInstaller::DocInfo> qtDocInfos; |
446 | qtDocInfos.reserve(alloc: docCount); |
447 | for (const QString &doc : docs) { |
448 | const QtDocInstaller::DocInfo docInfo(doc, helpEngine.qtDocInfo(component: doc)); |
449 | qtDocInfos.append(t: docInfo); |
450 | if (warnAboutMissingModules && (docInfo.second.isEmpty() || docInfo.second.first().isEmpty())) |
451 | qWarning() << "No documentation found for " << doc; |
452 | } |
453 | |
454 | m_qtDocInstaller = new QtDocInstaller(qtDocInfos); |
455 | connect(sender: m_qtDocInstaller, signal: &QtDocInstaller::docsInstalled, |
456 | receiver: this, slot: &MainWindow::qtDocumentationInstalled); |
457 | connect(sender: m_qtDocInstaller, signal: &QtDocInstaller::qchFileNotFound, |
458 | receiver: this, slot: &MainWindow::resetQtDocInfo); |
459 | connect(sender: m_qtDocInstaller, signal: &QtDocInstaller::registerDocumentation, |
460 | receiver: this, slot: &MainWindow::registerDocumentation); |
461 | if (helpEngine.qtDocInfo(component: QLatin1String("qt" )).count() != 2) |
462 | statusBar()->showMessage(text: tr(s: "Looking for Qt Documentation..." )); |
463 | m_qtDocInstaller->installDocs(); |
464 | } |
465 | |
466 | void MainWindow::qtDocumentationInstalled() |
467 | { |
468 | TRACE_OBJ |
469 | statusBar()->clearMessage(); |
470 | checkInitState(); |
471 | } |
472 | |
473 | void MainWindow::checkInitState() |
474 | { |
475 | TRACE_OBJ |
476 | if (!m_cmdLine->enableRemoteControl()) { |
477 | HelpEngineWrapper::instance().initialDocSetupDone(); |
478 | return; |
479 | } |
480 | |
481 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
482 | if (helpEngine.contentModel()->isCreatingContents() |
483 | || helpEngine.indexModel()->isCreatingIndex()) { |
484 | if (!m_connectedInitSignals) { |
485 | connect(sender: helpEngine.contentModel(), signal: &QHelpContentModel::contentsCreated, |
486 | receiver: this, slot: &MainWindow::checkInitState); |
487 | connect(sender: helpEngine.indexModel(), signal: &QHelpIndexModel::indexCreated, |
488 | receiver: this, slot: &MainWindow::checkInitState); |
489 | m_connectedInitSignals = true; |
490 | } |
491 | } else { |
492 | if (m_connectedInitSignals) { |
493 | disconnect(sender: helpEngine.contentModel(), signal: nullptr, receiver: this, member: nullptr); |
494 | disconnect(sender: helpEngine.indexModel(), signal: nullptr, receiver: this, member: nullptr); |
495 | } |
496 | HelpEngineWrapper::instance().initialDocSetupDone(); |
497 | emit initDone(); |
498 | } |
499 | } |
500 | |
501 | void MainWindow::insertLastPages() |
502 | { |
503 | TRACE_OBJ |
504 | if (m_cmdLine->search() == CmdLineParser::Activate) |
505 | showSearch(); |
506 | } |
507 | |
508 | void MainWindow::setupActions() |
509 | { |
510 | TRACE_OBJ |
511 | QString resourcePath = QLatin1String(":/qt-project.org/assistant/images/" ); |
512 | #ifdef Q_OS_MAC |
513 | setUnifiedTitleAndToolBarOnMac(true); |
514 | resourcePath.append(QLatin1String("mac" )); |
515 | #else |
516 | resourcePath.append(s: QLatin1String("win" )); |
517 | #endif |
518 | |
519 | QMenu * = menuBar()->addMenu(title: tr(s: "&File" )); |
520 | OpenPagesManager *const openPages = OpenPagesManager::instance(); |
521 | m_newTabAction = menu->addAction(text: tr(s: "New &Tab" ), |
522 | object: openPages, slot: &OpenPagesManager::createBlankPage); |
523 | m_newTabAction->setShortcut(QKeySequence::AddTab); |
524 | m_closeTabAction = menu->addAction(text: tr(s: "&Close Tab" ), |
525 | object: openPages, slot: &OpenPagesManager::closeCurrentPage); |
526 | m_closeTabAction->setShortcuts(QKeySequence::Close); |
527 | m_closeTabAction->setEnabled(openPages->pageCount() > 1); |
528 | connect(sender: openPages, signal: &OpenPagesManager::pageClosed, |
529 | receiver: this, slot: &MainWindow::handlePageCountChanged); |
530 | connect(sender: openPages, signal: &OpenPagesManager::pageAdded, |
531 | receiver: this, slot: &MainWindow::handlePageCountChanged); |
532 | |
533 | menu->addSeparator(); |
534 | |
535 | m_pageSetupAction = menu->addAction(text: tr(s: "Page Set&up..." ), |
536 | object: m_centralWidget, slot: &CentralWidget::pageSetup); |
537 | m_printPreviewAction = menu->addAction(text: tr(s: "Print Preview..." ), |
538 | object: m_centralWidget, slot: &CentralWidget::printPreview); |
539 | |
540 | GlobalActions *globalActions = GlobalActions::instance(parent: this); |
541 | menu->addAction(action: globalActions->printAction()); |
542 | menu->addSeparator(); |
543 | |
544 | QIcon appExitIcon = QIcon::fromTheme(name: "application-exit" ); |
545 | QAction *tmp; |
546 | #ifdef Q_OS_WIN |
547 | tmp = menu->addAction(appExitIcon, tr("E&xit" ), |
548 | this, &QWidget::close); |
549 | tmp->setShortcut(QKeySequence(tr("CTRL+Q" ))); |
550 | #else |
551 | tmp = menu->addAction(actionIcon: appExitIcon, text: tr(s: "&Quit" ), |
552 | object: this, slot: &QWidget::close); |
553 | tmp->setShortcut(QKeySequence::Quit); |
554 | #endif |
555 | tmp->setMenuRole(QAction::QuitRole); |
556 | |
557 | menu = menuBar()->addMenu(title: tr(s: "&Edit" )); |
558 | #if QT_CONFIG(clipboard) |
559 | menu->addAction(action: globalActions->copyAction()); |
560 | #endif |
561 | menu->addAction(action: globalActions->findAction()); |
562 | |
563 | QAction *findNextAction = menu->addAction(text: tr(s: "Find &Next" ), |
564 | object: m_centralWidget, slot: &CentralWidget::findNext); |
565 | findNextAction->setShortcuts(QKeySequence::FindNext); |
566 | |
567 | QAction *findPreviousAction = menu->addAction(text: tr(s: "Find &Previous" ), |
568 | object: m_centralWidget, slot: &CentralWidget::findPrevious); |
569 | findPreviousAction->setShortcuts(QKeySequence::FindPrevious); |
570 | |
571 | menu->addSeparator(); |
572 | tmp = menu->addAction(text: tr(s: "Preferences..." ), |
573 | object: this, slot: &MainWindow::showPreferences); |
574 | tmp->setMenuRole(QAction::PreferencesRole); |
575 | |
576 | m_viewMenu = menuBar()->addMenu(title: tr(s: "&View" )); |
577 | m_viewMenu->addAction(action: globalActions->zoomInAction()); |
578 | m_viewMenu->addAction(action: globalActions->zoomOutAction()); |
579 | |
580 | m_resetZoomAction = m_viewMenu->addAction(text: tr(s: "Normal &Size" ), |
581 | object: m_centralWidget, slot: &CentralWidget::resetZoom); |
582 | m_resetZoomAction->setPriority(QAction::LowPriority); |
583 | m_resetZoomAction->setIcon(QIcon(resourcePath + QLatin1String("/resetzoom.png" ))); |
584 | m_resetZoomAction->setShortcut(tr(s: "Ctrl+0" )); |
585 | |
586 | m_viewMenu->addSeparator(); |
587 | |
588 | m_viewMenu->addAction(text: tr(s: "Contents" ), |
589 | object: this, slot: &MainWindow::showContents, shortcut: QKeySequence(tr(s: "ALT+C" ))); |
590 | m_viewMenu->addAction(text: tr(s: "Index" ), |
591 | object: this, slot: &MainWindow::showIndex, shortcut: QKeySequence(tr(s: "ALT+I" ))); |
592 | m_viewMenu->addAction(text: tr(s: "Bookmarks" ), |
593 | object: this, slot: &MainWindow::showBookmarksDockWidget, shortcut: QKeySequence(tr(s: "ALT+O" ))); |
594 | m_viewMenu->addAction(text: tr(s: "Search" ), |
595 | object: this, slot: &MainWindow::showSearch, shortcut: QKeySequence(tr(s: "ALT+S" ))); |
596 | m_viewMenu->addAction(text: tr(s: "Open Pages" ), |
597 | object: this, slot: &MainWindow::showOpenPages, shortcut: QKeySequence(tr(s: "ALT+P" ))); |
598 | |
599 | menu = menuBar()->addMenu(title: tr(s: "&Go" )); |
600 | menu->addAction(action: globalActions->homeAction()); |
601 | menu->addAction(action: globalActions->backAction()); |
602 | menu->addAction(action: globalActions->nextAction()); |
603 | |
604 | m_syncAction = menu->addAction(text: tr(s: "Sync with Table of Contents" ), |
605 | object: this, slot: &MainWindow::syncContents); |
606 | m_syncAction->setIconText(tr(s: "Sync" )); |
607 | m_syncAction->setIcon(QIcon(resourcePath + QLatin1String("/synctoc.png" ))); |
608 | |
609 | menu->addSeparator(); |
610 | |
611 | tmp = menu->addAction(text: tr(s: "Next Page" ), |
612 | object: openPages, slot: &OpenPagesManager::nextPage); |
613 | tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr(s: "Ctrl+Alt+Right" )) |
614 | << QKeySequence(Qt::CTRL | Qt::Key_PageDown)); |
615 | |
616 | tmp = menu->addAction(text: tr(s: "Previous Page" ), |
617 | object: openPages, slot: &OpenPagesManager::previousPage); |
618 | tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr(s: "Ctrl+Alt+Left" )) |
619 | << QKeySequence(Qt::CTRL | Qt::Key_PageUp)); |
620 | |
621 | const Qt::Modifier modifier = |
622 | #ifdef Q_OS_MAC |
623 | Qt::ALT; |
624 | #else |
625 | Qt::CTRL; |
626 | #endif |
627 | |
628 | QShortcut *sct = new QShortcut(QKeySequence(modifier | Qt::Key_Tab), this); |
629 | connect(sender: sct, signal: &QShortcut::activated, |
630 | receiver: openPages, slot: &OpenPagesManager::nextPageWithSwitcher); |
631 | sct = new QShortcut(QKeySequence(modifier | Qt::SHIFT | Qt::Key_Tab), this); |
632 | connect(sender: sct, signal: &QShortcut::activated, |
633 | receiver: openPages, slot: &OpenPagesManager::previousPageWithSwitcher); |
634 | |
635 | BookmarkManager::instance()->setBookmarksMenu(menuBar()->addMenu(title: tr(s: "&Bookmarks" ))); |
636 | |
637 | menu = menuBar()->addMenu(title: tr(s: "&Help" )); |
638 | m_aboutAction = menu->addAction(text: tr(s: "About..." ), |
639 | object: this, slot: &MainWindow::showAboutDialog); |
640 | m_aboutAction->setMenuRole(QAction::AboutRole); |
641 | |
642 | #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) |
643 | m_resetZoomAction->setIcon(QIcon::fromTheme(name: "zoom-original" , fallback: m_resetZoomAction->icon())); |
644 | m_syncAction->setIcon(QIcon::fromTheme(name: "view-refresh" , fallback: m_syncAction->icon())); |
645 | #endif |
646 | |
647 | QToolBar *navigationBar = addToolBar(title: tr(s: "Navigation Toolbar" )); |
648 | navigationBar->setObjectName(QLatin1String("NavigationToolBar" )); |
649 | navigationBar->addAction(action: globalActions->backAction()); |
650 | navigationBar->addAction(action: globalActions->nextAction()); |
651 | navigationBar->addAction(action: globalActions->homeAction()); |
652 | navigationBar->addAction(action: m_syncAction); |
653 | navigationBar->addSeparator(); |
654 | #if QT_CONFIG(clipboard) |
655 | navigationBar->addAction(action: globalActions->copyAction()); |
656 | #endif |
657 | navigationBar->addAction(action: globalActions->printAction()); |
658 | navigationBar->addAction(action: globalActions->findAction()); |
659 | navigationBar->addSeparator(); |
660 | navigationBar->addAction(action: globalActions->zoomInAction()); |
661 | navigationBar->addAction(action: globalActions->zoomOutAction()); |
662 | navigationBar->addAction(action: m_resetZoomAction); |
663 | |
664 | #if defined(Q_OS_MAC) |
665 | QMenu *windowMenu = new QMenu(tr("&Window" ), this); |
666 | menuBar()->insertMenu(menu->menuAction(), windowMenu); |
667 | windowMenu->addAction(tr("Zoom" ), |
668 | this, &QWidget::showMaximized); |
669 | windowMenu->addAction(tr("Minimize" ), |
670 | this, &QWidget::showMinimized, QKeySequence(tr("Ctrl+M" ))); |
671 | #endif |
672 | |
673 | // content viewer connections |
674 | #if QT_CONFIG(clipboard) |
675 | connect(sender: m_centralWidget, signal: &CentralWidget::copyAvailable, |
676 | receiver: globalActions, slot: &GlobalActions::setCopyAvailable); |
677 | #endif |
678 | connect(sender: m_centralWidget, signal: &CentralWidget::currentViewerChanged, |
679 | receiver: globalActions, slot: &GlobalActions::updateActions); |
680 | connect(sender: m_centralWidget, signal: &CentralWidget::forwardAvailable, |
681 | receiver: globalActions, slot: &GlobalActions::updateActions); |
682 | connect(sender: m_centralWidget, signal: &CentralWidget::backwardAvailable, |
683 | receiver: globalActions, slot: &GlobalActions::updateActions); |
684 | connect(sender: m_centralWidget, signal: &CentralWidget::highlighted, |
685 | context: this, slot: [this](const QUrl &link) { statusBar()->showMessage(text: link.toString());} ); |
686 | |
687 | // index window |
688 | connect(sender: m_indexWindow, signal: &IndexWindow::linkActivated, |
689 | receiver: m_centralWidget, slot: &CentralWidget::setSource); |
690 | connect(sender: m_indexWindow, signal: &IndexWindow::documentsActivated, |
691 | receiver: this, slot: &MainWindow::showTopicChooser); |
692 | connect(sender: m_indexWindow, signal: &IndexWindow::escapePressed, |
693 | receiver: this, slot: &MainWindow::activateCurrentCentralWidgetTab); |
694 | |
695 | // content window |
696 | connect(sender: m_contentWindow, signal: &ContentWindow::linkActivated, |
697 | receiver: m_centralWidget, slot: &CentralWidget::setSource); |
698 | connect(sender: m_contentWindow, signal: &ContentWindow::escapePressed, |
699 | receiver: this, slot: &MainWindow::activateCurrentCentralWidgetTab); |
700 | |
701 | // search window |
702 | connect(sender: m_searchWindow, signal: &SearchWidget::requestShowLink, |
703 | receiver: CentralWidget::instance(), slot: &CentralWidget::setSourceFromSearch); |
704 | connect(sender: m_searchWindow, signal: &SearchWidget::requestShowLinkInNewTab, |
705 | receiver: OpenPagesManager::instance(), slot: &OpenPagesManager::createNewPageFromSearch); |
706 | |
707 | #if defined(QT_NO_PRINTER) |
708 | m_pageSetupAction->setVisible(false); |
709 | m_printPreviewAction->setVisible(false); |
710 | globalActions->printAction()->setVisible(false); |
711 | #endif |
712 | } |
713 | |
714 | QMenu *MainWindow::toolBarMenu() |
715 | { |
716 | TRACE_OBJ |
717 | if (!m_toolBarMenu) { |
718 | m_viewMenu->addSeparator(); |
719 | m_toolBarMenu = m_viewMenu->addMenu(title: tr(s: "Toolbars" )); |
720 | } |
721 | return m_toolBarMenu; |
722 | } |
723 | |
724 | void MainWindow::setupFilterToolbar() |
725 | { |
726 | TRACE_OBJ |
727 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
728 | if (!helpEngine.filterFunctionalityEnabled()) |
729 | return; |
730 | |
731 | m_filterCombo = new QComboBox(this); |
732 | m_filterCombo->setMinimumWidth(QFontMetrics(QFont()). |
733 | horizontalAdvance(QLatin1String("MakeTheComboBoxWidthEnough" ))); |
734 | |
735 | QToolBar *filterToolBar = addToolBar(title: tr(s: "Filter Toolbar" )); |
736 | filterToolBar->setObjectName(QLatin1String("FilterToolBar" )); |
737 | filterToolBar->addWidget(widget: new QLabel(tr(s: "Filtered by:" ).append(c: QLatin1Char(' ')), |
738 | this)); |
739 | filterToolBar->addWidget(widget: m_filterCombo); |
740 | |
741 | if (!helpEngine.filterToolbarVisible()) |
742 | filterToolBar->hide(); |
743 | toolBarMenu()->addAction(action: filterToolBar->toggleViewAction()); |
744 | |
745 | connect(sender: &helpEngine, signal: &HelpEngineWrapper::setupFinished, |
746 | receiver: this, slot: &MainWindow::setupFilterCombo, type: Qt::QueuedConnection); |
747 | connect(sender: m_filterCombo, signal: QOverload<int>::of(ptr: &QComboBox::activated), |
748 | receiver: this, slot: &MainWindow::filterDocumentation); |
749 | connect(sender: helpEngine.filterEngine(), signal: &QHelpFilterEngine::filterActivated, |
750 | receiver: this, slot: &MainWindow::currentFilterChanged); |
751 | |
752 | setupFilterCombo(); |
753 | } |
754 | |
755 | void MainWindow::setupAddressToolbar() |
756 | { |
757 | TRACE_OBJ |
758 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
759 | if (!helpEngine.addressBarEnabled()) |
760 | return; |
761 | |
762 | m_addressLineEdit = new QLineEdit(this); |
763 | QToolBar *addressToolBar = addToolBar(title: tr(s: "Address Toolbar" )); |
764 | addressToolBar->setObjectName(QLatin1String("AddressToolBar" )); |
765 | insertToolBarBreak(before: addressToolBar); |
766 | |
767 | addressToolBar->addWidget(widget: new QLabel(tr(s: "Address:" ).append(c: QChar::Space), |
768 | this)); |
769 | addressToolBar->addWidget(widget: m_addressLineEdit); |
770 | |
771 | if (!helpEngine.addressBarVisible()) |
772 | addressToolBar->hide(); |
773 | toolBarMenu()->addAction(action: addressToolBar->toggleViewAction()); |
774 | |
775 | // address lineedit |
776 | connect(sender: m_addressLineEdit, signal: &QLineEdit::returnPressed, |
777 | receiver: this, slot: &MainWindow::gotoAddress); |
778 | connect(sender: m_centralWidget, signal: &CentralWidget::currentViewerChanged, |
779 | receiver: this, slot: QOverload<>::of(ptr: &MainWindow::showNewAddress)); |
780 | connect(sender: m_centralWidget, signal: &CentralWidget::sourceChanged, |
781 | receiver: this, slot: QOverload<>::of(ptr: &MainWindow::showNewAddress)); |
782 | } |
783 | |
784 | void MainWindow::updateAboutMenuText() |
785 | { |
786 | TRACE_OBJ |
787 | QByteArray ba = HelpEngineWrapper::instance().aboutMenuTexts(); |
788 | if (ba.size() > 0) { |
789 | QString lang; |
790 | QString str; |
791 | QString trStr; |
792 | QString currentLang = QLocale::system().name(); |
793 | int i = currentLang.indexOf(c: QLatin1Char('_')); |
794 | if (i > -1) |
795 | currentLang = currentLang.left(n: i); |
796 | QDataStream s(&ba, QIODevice::ReadOnly); |
797 | while (!s.atEnd()) { |
798 | s >> lang; |
799 | s >> str; |
800 | if (lang == QLatin1String("default" ) && trStr.isEmpty()) { |
801 | trStr = str; |
802 | } else if (lang == currentLang) { |
803 | trStr = str; |
804 | break; |
805 | } |
806 | } |
807 | if (!trStr.isEmpty()) |
808 | m_aboutAction->setText(trStr); |
809 | } |
810 | } |
811 | |
812 | void MainWindow::showNewAddress() |
813 | { |
814 | TRACE_OBJ |
815 | showNewAddress(url: m_centralWidget->currentSource()); |
816 | } |
817 | |
818 | void MainWindow::showNewAddress(const QUrl &url) |
819 | { |
820 | TRACE_OBJ |
821 | m_addressLineEdit->setText(url.toString()); |
822 | } |
823 | |
824 | void MainWindow::gotoAddress() |
825 | { |
826 | TRACE_OBJ |
827 | m_centralWidget->setSource(m_addressLineEdit->text()); |
828 | } |
829 | |
830 | void MainWindow::showTopicChooser(const QList<QHelpLink> &documents, |
831 | const QString &keyword) |
832 | { |
833 | TRACE_OBJ |
834 | TopicChooser tc(this, keyword, documents); |
835 | if (tc.exec() == QDialog::Accepted) { |
836 | m_centralWidget->setSource(tc.link()); |
837 | } |
838 | } |
839 | |
840 | void MainWindow::showPreferences() |
841 | { |
842 | TRACE_OBJ |
843 | PreferencesDialog dia(this); |
844 | connect(sender: &dia, signal: &PreferencesDialog::updateApplicationFont, |
845 | receiver: this, slot: &MainWindow::updateApplicationFont); |
846 | connect(sender: &dia, signal: &PreferencesDialog::updateBrowserFont, |
847 | receiver: m_centralWidget, slot: &CentralWidget::updateBrowserFont); |
848 | connect(sender: &dia, signal: &PreferencesDialog::updateUserInterface, |
849 | receiver: m_centralWidget, slot: &CentralWidget::updateUserInterface); |
850 | dia.exec(); |
851 | } |
852 | |
853 | void MainWindow::syncContents() |
854 | { |
855 | TRACE_OBJ |
856 | qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); |
857 | const QUrl url = m_centralWidget->currentSource(); |
858 | showContents(); |
859 | if (!m_contentWindow->syncToContent(url)) |
860 | statusBar()->showMessage( |
861 | text: tr(s: "Could not find the associated content item." ), timeout: 3000); |
862 | qApp->restoreOverrideCursor(); |
863 | } |
864 | |
865 | void MainWindow::showAboutDialog() |
866 | { |
867 | TRACE_OBJ |
868 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
869 | QByteArray contents; |
870 | QByteArray ba = helpEngine.aboutTexts(); |
871 | if (!ba.isEmpty()) { |
872 | QString lang; |
873 | QByteArray cba; |
874 | QString currentLang = QLocale::system().name(); |
875 | int i = currentLang.indexOf(c: QLatin1Char('_')); |
876 | if (i > -1) |
877 | currentLang = currentLang.left(n: i); |
878 | QDataStream s(&ba, QIODevice::ReadOnly); |
879 | while (!s.atEnd()) { |
880 | s >> lang; |
881 | s >> cba; |
882 | if (lang == QLatin1String("default" ) && contents.isEmpty()) { |
883 | contents = cba; |
884 | } else if (lang == currentLang) { |
885 | contents = cba; |
886 | break; |
887 | } |
888 | } |
889 | } |
890 | |
891 | AboutDialog aboutDia(this); |
892 | |
893 | QByteArray iconArray; |
894 | if (!contents.isEmpty()) { |
895 | iconArray = helpEngine.aboutIcon(); |
896 | QByteArray resources = helpEngine.aboutImages(); |
897 | QPixmap pix; |
898 | pix.loadFromData(buf: iconArray); |
899 | aboutDia.setText(text: QString::fromUtf8(str: contents), resources); |
900 | if (!pix.isNull()) |
901 | aboutDia.setPixmap(pix); |
902 | aboutDia.setWindowTitle(aboutDia.documentTitle()); |
903 | } else { |
904 | QByteArray resources; |
905 | #if defined(BROWSER_QTWEBKIT) |
906 | const QString browser = QStringLiteral("Qt WebKit" ); |
907 | #else |
908 | const QString browser = QStringLiteral("QTextBrowser" ); |
909 | #endif |
910 | aboutDia.setText(text: tr(s: "<center>" |
911 | "<h3>%1</h3>" |
912 | "<p>Version %2</p>" |
913 | "<p>Browser: %3</p></center>" |
914 | "<p>Copyright (C) %4 The Qt Company Ltd.</p>" ) |
915 | .arg(args: tr(s: "Qt Assistant" ), args: QLatin1String(QT_VERSION_STR), args: browser, QStringLiteral("2022" )), |
916 | resources); |
917 | QLatin1String path(":/qt-project.org/assistant/images/assistant-128.png" ); |
918 | aboutDia.setPixmap(QString(path)); |
919 | } |
920 | if (aboutDia.windowTitle().isEmpty()) |
921 | aboutDia.setWindowTitle(tr(s: "About %1" ).arg(a: windowTitle())); |
922 | aboutDia.exec(); |
923 | } |
924 | |
925 | void MainWindow::setContentsVisible(bool visible) |
926 | { |
927 | TRACE_OBJ |
928 | if (visible) |
929 | showContents(); |
930 | else |
931 | hideContents(); |
932 | } |
933 | |
934 | void MainWindow::showContents() |
935 | { |
936 | TRACE_OBJ |
937 | activateDockWidget(w: m_contentWindow); |
938 | } |
939 | |
940 | void MainWindow::hideContents() |
941 | { |
942 | TRACE_OBJ |
943 | m_contentWindow->parentWidget()->hide(); |
944 | } |
945 | |
946 | void MainWindow::setIndexVisible(bool visible) |
947 | { |
948 | TRACE_OBJ |
949 | if (visible) |
950 | showIndex(); |
951 | else |
952 | hideIndex(); |
953 | } |
954 | |
955 | void MainWindow::showIndex() |
956 | { |
957 | TRACE_OBJ |
958 | activateDockWidget(w: m_indexWindow); |
959 | } |
960 | |
961 | void MainWindow::hideIndex() |
962 | { |
963 | TRACE_OBJ |
964 | m_indexWindow->parentWidget()->hide(); |
965 | } |
966 | |
967 | void MainWindow::setBookmarksVisible(bool visible) |
968 | { |
969 | TRACE_OBJ |
970 | if (visible) |
971 | showBookmarksDockWidget(); |
972 | else |
973 | hideBookmarksDockWidget(); |
974 | } |
975 | |
976 | void MainWindow::showBookmarksDockWidget() |
977 | { |
978 | TRACE_OBJ |
979 | activateDockWidget(w: m_bookmarkWidget); |
980 | } |
981 | |
982 | void MainWindow::hideBookmarksDockWidget() |
983 | { |
984 | TRACE_OBJ |
985 | m_bookmarkWidget->parentWidget()->hide(); |
986 | } |
987 | |
988 | void MainWindow::setSearchVisible(bool visible) |
989 | { |
990 | TRACE_OBJ |
991 | if (visible) |
992 | showSearch(); |
993 | else |
994 | hideSearch(); |
995 | } |
996 | |
997 | void MainWindow::showSearch() |
998 | { |
999 | TRACE_OBJ |
1000 | activateDockWidget(w: m_searchWindow); |
1001 | } |
1002 | |
1003 | void MainWindow::showOpenPages() |
1004 | { |
1005 | TRACE_OBJ |
1006 | activateDockWidget(w: OpenPagesManager::instance()->openPagesWidget()); |
1007 | } |
1008 | |
1009 | void MainWindow::hideSearch() |
1010 | { |
1011 | TRACE_OBJ |
1012 | m_searchWindow->parentWidget()->hide(); |
1013 | } |
1014 | |
1015 | void MainWindow::activateDockWidget(QWidget *w) |
1016 | { |
1017 | TRACE_OBJ |
1018 | w->parentWidget()->show(); |
1019 | w->parentWidget()->raise(); |
1020 | w->setFocus(); |
1021 | } |
1022 | |
1023 | void MainWindow::setIndexString(const QString &str) |
1024 | { |
1025 | TRACE_OBJ |
1026 | m_indexWindow->setSearchLineEditText(str); |
1027 | } |
1028 | |
1029 | void MainWindow::activateCurrentBrowser() |
1030 | { |
1031 | TRACE_OBJ |
1032 | CentralWidget::instance()->activateTab(); |
1033 | } |
1034 | |
1035 | void MainWindow::activateCurrentCentralWidgetTab() |
1036 | { |
1037 | TRACE_OBJ |
1038 | m_centralWidget->activateTab(); |
1039 | } |
1040 | |
1041 | void MainWindow::updateApplicationFont() |
1042 | { |
1043 | TRACE_OBJ |
1044 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
1045 | QFont font = qApp->font(); |
1046 | if (helpEngine.usesAppFont()) |
1047 | font = helpEngine.appFont(); |
1048 | |
1049 | const QWidgetList &widgets = QApplication::allWidgets(); |
1050 | for (QWidget *widget : widgets) |
1051 | widget->setFont(font); |
1052 | } |
1053 | |
1054 | void MainWindow::setupFilterCombo() |
1055 | { |
1056 | TRACE_OBJ |
1057 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
1058 | const QString currentFilter = helpEngine.filterEngine()->activeFilter(); |
1059 | m_filterCombo->clear(); |
1060 | m_filterCombo->addItem(atext: tr(s: "Unfiltered" )); |
1061 | const QStringList allFilters = helpEngine.filterEngine()->filters(); |
1062 | if (!allFilters.isEmpty()) |
1063 | m_filterCombo->insertSeparator(index: 1); |
1064 | for (const QString &filter : allFilters) |
1065 | m_filterCombo->addItem(atext: filter, auserData: filter); |
1066 | |
1067 | int idx = m_filterCombo->findData(data: currentFilter); |
1068 | if (idx < 0) |
1069 | idx = 0; |
1070 | m_filterCombo->setCurrentIndex(idx); |
1071 | } |
1072 | |
1073 | void MainWindow::filterDocumentation(int filterIndex) |
1074 | { |
1075 | TRACE_OBJ |
1076 | |
1077 | const QString filter = m_filterCombo->itemData(index: filterIndex).toString(); |
1078 | HelpEngineWrapper::instance().filterEngine()->setActiveFilter(filter); |
1079 | } |
1080 | |
1081 | void MainWindow::expandTOC(int depth) |
1082 | { |
1083 | TRACE_OBJ |
1084 | Q_ASSERT(depth >= -1); |
1085 | m_contentWindow->expandToDepth(depth); |
1086 | } |
1087 | |
1088 | void MainWindow::indexingStarted() |
1089 | { |
1090 | TRACE_OBJ |
1091 | if (!m_progressWidget) { |
1092 | m_progressWidget = new QWidget(); |
1093 | QLayout* hlayout = new QHBoxLayout(m_progressWidget); |
1094 | |
1095 | QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); |
1096 | |
1097 | QLabel *label = new QLabel(tr(s: "Updating search index" )); |
1098 | label->setSizePolicy(sizePolicy); |
1099 | hlayout->addWidget(w: label); |
1100 | |
1101 | QProgressBar *progressBar = new QProgressBar(); |
1102 | progressBar->setRange(minimum: 0, maximum: 0); |
1103 | progressBar->setTextVisible(false); |
1104 | progressBar->setSizePolicy(sizePolicy); |
1105 | |
1106 | hlayout->setSpacing(6); |
1107 | hlayout->setContentsMargins(QMargins()); |
1108 | hlayout->addWidget(w: progressBar); |
1109 | |
1110 | statusBar()->addPermanentWidget(widget: m_progressWidget); |
1111 | } |
1112 | } |
1113 | |
1114 | void MainWindow::indexingFinished() |
1115 | { |
1116 | TRACE_OBJ |
1117 | statusBar()->removeWidget(widget: m_progressWidget); |
1118 | delete m_progressWidget; |
1119 | m_progressWidget = nullptr; |
1120 | } |
1121 | |
1122 | QString MainWindow::collectionFileDirectory(bool createDir, const QString &cacheDir) |
1123 | { |
1124 | TRACE_OBJ |
1125 | QString collectionPath = |
1126 | QStandardPaths::writableLocation(type: QStandardPaths::GenericDataLocation); |
1127 | if (collectionPath.isEmpty()) { |
1128 | if (cacheDir.isEmpty()) |
1129 | collectionPath = QDir::homePath() + QDir::separator() |
1130 | + QLatin1String(".assistant" ); |
1131 | else |
1132 | collectionPath = QDir::homePath() + QLatin1String("/." ) + cacheDir; |
1133 | } else { |
1134 | if (cacheDir.isEmpty()) |
1135 | collectionPath = collectionPath + QLatin1String("/QtProject/Assistant" ); |
1136 | else |
1137 | collectionPath = collectionPath + QDir::separator() + cacheDir; |
1138 | } |
1139 | if (createDir) { |
1140 | QDir dir; |
1141 | if (!dir.exists(name: collectionPath)) |
1142 | dir.mkpath(dirPath: collectionPath); |
1143 | } |
1144 | return collectionPath; |
1145 | } |
1146 | |
1147 | QString MainWindow::defaultHelpCollectionFileName() |
1148 | { |
1149 | TRACE_OBJ |
1150 | // forces creation of the default collection file path |
1151 | return collectionFileDirectory(createDir: true) + QDir::separator() + |
1152 | QString(QLatin1String("qthelpcollection_%1.qhc" )). |
1153 | arg(a: QLatin1String(QT_VERSION_STR)); |
1154 | } |
1155 | |
1156 | void MainWindow::currentFilterChanged(const QString &filter) |
1157 | { |
1158 | TRACE_OBJ |
1159 | int index = m_filterCombo->findData(data: filter); |
1160 | if (index < 0) |
1161 | index = 0; |
1162 | m_filterCombo->setCurrentIndex(index); |
1163 | } |
1164 | |
1165 | void MainWindow::documentationRemoved(const QString &namespaceName) |
1166 | { |
1167 | TRACE_OBJ |
1168 | OpenPagesManager::instance()->closePages(nameSpace: namespaceName); |
1169 | } |
1170 | |
1171 | void MainWindow::documentationUpdated(const QString &namespaceName) |
1172 | { |
1173 | TRACE_OBJ |
1174 | OpenPagesManager::instance()->reloadPages(nameSpace: namespaceName); |
1175 | } |
1176 | |
1177 | void MainWindow::resetQtDocInfo(const QString &component) |
1178 | { |
1179 | TRACE_OBJ |
1180 | HelpEngineWrapper::instance().setQtDocInfo(component, |
1181 | doc: QStringList(QDateTime().toString(format: Qt::ISODate))); |
1182 | } |
1183 | |
1184 | void MainWindow::registerDocumentation(const QString &component, |
1185 | const QString &absFileName) |
1186 | { |
1187 | TRACE_OBJ |
1188 | QString ns = QHelpEngineCore::namespaceName(documentationFileName: absFileName); |
1189 | if (ns.isEmpty()) |
1190 | return; |
1191 | |
1192 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
1193 | if (helpEngine.registeredDocumentations().contains(str: ns)) |
1194 | helpEngine.unregisterDocumentation(namespaceName: ns); |
1195 | if (!helpEngine.registerDocumentation(docFile: absFileName)) { |
1196 | QMessageBox::warning(parent: this, title: tr(s: "Qt Assistant" ), |
1197 | text: tr(s: "Could not register file '%1': %2" ). |
1198 | arg(a: absFileName).arg(a: helpEngine.error())); |
1199 | } else { |
1200 | QStringList docInfo; |
1201 | docInfo << QFileInfo(absFileName).lastModified().toString(format: Qt::ISODate) |
1202 | << absFileName; |
1203 | helpEngine.setQtDocInfo(component, doc: docInfo); |
1204 | } |
1205 | } |
1206 | |
1207 | void MainWindow::handlePageCountChanged() |
1208 | { |
1209 | m_closeTabAction->setEnabled(OpenPagesManager::instance()->pageCount() > 1); |
1210 | } |
1211 | |
1212 | QT_END_NAMESPACE |
1213 | |