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