qpdfview %1
qpdfview is a tabbed document viewer using Qt.
" "This version includes:" "
See launchpad.net/qpdfview for more information.
" "© %1 The qpdfview developers
").arg("2012-2018"))); } void MainWindow::on_focusCurrentPage_activated() { m_currentPageSpinBox->setFocus(); m_currentPageSpinBox->selectAll(); } void MainWindow::on_focusScaleFactor_activated() { m_scaleFactorComboBox->setFocus(); m_scaleFactorComboBox->lineEdit()->selectAll(); } void MainWindow::on_toggleToolBars_triggered(bool checked) { if(checked) { m_tabWidget->setTabBarPolicy(static_cast< TabWidget::TabBarPolicy >(m_tabBarHadPolicy)); m_fileToolBar->setVisible(m_fileToolBarWasVisible); m_editToolBar->setVisible(m_editToolBarWasVisible); m_viewToolBar->setVisible(m_viewToolBarWasVisible); } else { m_tabBarHadPolicy = static_cast< int >(m_tabWidget->tabBarPolicy()); m_fileToolBarWasVisible = m_fileToolBar->isVisible(); m_editToolBarWasVisible = m_editToolBar->isVisible(); m_viewToolBarWasVisible = m_viewToolBar->isVisible(); m_tabWidget->setTabBarPolicy(TabWidget::TabBarAlwaysOff); m_fileToolBar->setVisible(false); m_editToolBar->setVisible(false); m_viewToolBar->setVisible(false); } } void MainWindow::on_toggleMenuBar_triggered(bool checked) { menuBar()->setVisible(checked); } void MainWindow::on_searchInitiated(const QString& text, bool modified) { if(text.isEmpty()) { return; } const bool forAllTabs = s_settings->mainWindow().extendedSearchDock() ? !modified : modified; const bool matchCase = m_matchCaseCheckBox->isChecked(); const bool wholeWords = m_wholeWordsCheckBox->isChecked(); if(forAllTabs) { foreach(DocumentView* tab, allTabs()) { tab->startSearch(text, matchCase, wholeWords); } } else { DocumentView* const tab = currentTab(); if(tab->searchText() != text || tab->searchWasCanceled()) { tab->startSearch(text, matchCase, wholeWords); } else { tab->findNext(); } } } void MainWindow::on_highlightAll_clicked(bool checked) { currentTab()->setHighlightAll(checked); } void MainWindow::on_dock_dockLocationChanged(Qt::DockWidgetArea area) { QDockWidget* dock = qobject_cast< QDockWidget* >(sender()); if(dock == 0) { return; } QDockWidget::DockWidgetFeatures features = dock->features(); if(area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) { features |= QDockWidget::DockWidgetVerticalTitleBar; } else { features &= ~QDockWidget::DockWidgetVerticalTitleBar; } dock->setFeatures(features); } void MainWindow::on_outline_sectionCountChanged() { setSectionResizeMode(m_outlineView->header(), 0, QHeaderView::Stretch); setSectionResizeMode(m_outlineView->header(), 1, QHeaderView::ResizeToContents); m_outlineView->header()->setMinimumSectionSize(0); m_outlineView->header()->setStretchLastSection(false); m_outlineView->header()->setVisible(false); } void MainWindow::on_outline_clicked(const QModelIndex& index) { bool ok = false; const int page = index.data(Model::Document::PageRole).toInt(&ok); if(!ok) { return; } const qreal left = index.data(Model::Document::LeftRole).toReal(); const qreal top = index.data(Model::Document::TopRole).toReal(); const QString fileName = index.data(Model::Document::FileNameRole).toString(); if(fileName.isEmpty()) { currentTab()->jumpToPage(page, true, left, top); } else { jumpToPageOrOpenInNewTab(currentTab()->resolveFileName(fileName), page, true); } } void MainWindow::on_properties_sectionCountChanged() { setSectionResizeMode(m_propertiesView->horizontalHeader(), 0, QHeaderView::Stretch); setSectionResizeMode(m_propertiesView->horizontalHeader(), 1, QHeaderView::Stretch); m_propertiesView->horizontalHeader()->setVisible(false); setSectionResizeMode(m_propertiesView->verticalHeader(), QHeaderView::ResizeToContents); m_propertiesView->verticalHeader()->setVisible(false); } void MainWindow::on_thumbnails_dockLocationChanged(Qt::DockWidgetArea area) { foreach(DocumentView* tab, allTabs()) { tab->setThumbnailsOrientation(area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea ? Qt::Horizontal : Qt::Vertical); } } void MainWindow::on_thumbnails_verticalScrollBar_valueChanged(int value) { Q_UNUSED(value); if(m_thumbnailsView->scene() != 0) { const QRectF visibleRect = m_thumbnailsView->mapToScene(m_thumbnailsView->viewport()->rect()).boundingRect(); foreach(ThumbnailItem* page, currentTab()->thumbnailItems()) { if(!page->boundingRect().translated(page->pos()).intersects(visibleRect)) { page->cancelRender(); } } } } void MainWindow::on_bookmarks_sectionCountChanged() { setSectionResizeMode(m_bookmarksView->horizontalHeader(), 0, QHeaderView::Stretch); setSectionResizeMode(m_bookmarksView->horizontalHeader(), 1, QHeaderView::ResizeToContents); m_bookmarksView->horizontalHeader()->setMinimumSectionSize(0); m_bookmarksView->horizontalHeader()->setStretchLastSection(false); m_bookmarksView->horizontalHeader()->setVisible(false); setSectionResizeMode(m_bookmarksView->verticalHeader(), QHeaderView::ResizeToContents); m_bookmarksView->verticalHeader()->setVisible(false); } void MainWindow::on_bookmarks_clicked(const QModelIndex& index) { bool ok = false; const int page = index.data(BookmarkModel::PageRole).toInt(&ok); if(ok) { currentTab()->jumpToPage(page); } } void MainWindow::on_bookmarks_contextMenuRequested(QPoint pos) { QMenu menu; menu.addActions(QList< QAction* >() << m_previousBookmarkAction << m_nextBookmarkAction); menu.addSeparator(); menu.addAction(m_addBookmarkAction); QAction* removeBookmarkAction = menu.addAction(tr("&Remove bookmark")); QAction* editBookmarkAction = menu.addAction(tr("&Edit bookmark")); const QModelIndex index = m_bookmarksView->indexAt(pos); removeBookmarkAction->setVisible(index.isValid()); editBookmarkAction->setVisible(index.isValid()); const QAction* action = menu.exec(m_bookmarksView->mapToGlobal(pos)); if(action == removeBookmarkAction) { BookmarkModel* model = qobject_cast< BookmarkModel* >(m_bookmarksView->model()); if(model != 0) { model->removeBookmark(BookmarkItem(index.data(BookmarkModel::PageRole).toInt())); if(model->isEmpty()) { m_bookmarksView->setModel(0); BookmarkModel::removePath(currentTab()->fileInfo().absoluteFilePath()); } m_bookmarksMenuIsDirty = true; scheduleSaveBookmarks(); } } else if(action == editBookmarkAction) { BookmarkModel* model = qobject_cast< BookmarkModel* >(m_bookmarksView->model()); if(model != 0) { BookmarkItem bookmark(index.data(BookmarkModel::PageRole).toInt()); model->findBookmark(bookmark); QScopedPointer< BookmarkDialog > dialog(new BookmarkDialog(bookmark, this)); if(dialog->exec() == QDialog::Accepted) { model->addBookmark(bookmark); m_bookmarksMenuIsDirty = true; scheduleSaveBookmarks(); } } } } void MainWindow::on_search_sectionCountChanged() { setSectionResizeMode(m_searchView->header(), 0, QHeaderView::Stretch); setSectionResizeMode(m_searchView->header(), 1, QHeaderView::ResizeToContents); m_searchView->header()->setMinimumSectionSize(0); m_searchView->header()->setStretchLastSection(false); m_searchView->header()->setVisible(false); } void MainWindow::on_search_dockLocationChanged(Qt::DockWidgetArea area) { delete m_searchWidget->layout(); QGridLayout* searchLayout = new QGridLayout(m_searchWidget); if(area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) { searchLayout->setRowStretch(2, 1); searchLayout->setColumnStretch(3, 1); searchLayout->addWidget(m_searchLineEdit, 0, 0, 1, 7); searchLayout->addWidget(m_matchCaseCheckBox, 1, 0); searchLayout->addWidget(m_wholeWordsCheckBox, 1, 1); searchLayout->addWidget(m_highlightAllCheckBox, 1, 2); searchLayout->addWidget(m_findPreviousButton, 1, 4, Qt::AlignRight); searchLayout->addWidget(m_findNextButton, 1, 5, Qt::AlignRight); searchLayout->addWidget(m_cancelSearchButton, 1, 6, Qt::AlignRight); if(s_settings->mainWindow().extendedSearchDock()) { searchLayout->addWidget(m_searchView, 2, 0, 1, 7); } } else { searchLayout->setRowStretch(4, 1); searchLayout->setColumnStretch(1, 1); searchLayout->addWidget(m_searchLineEdit, 0, 0, 1, 5); searchLayout->addWidget(m_matchCaseCheckBox, 1, 0); searchLayout->addWidget(m_wholeWordsCheckBox, 2, 0); searchLayout->addWidget(m_highlightAllCheckBox, 3, 0); searchLayout->addWidget(m_findPreviousButton, 1, 2, 3, 1, Qt::AlignTop); searchLayout->addWidget(m_findNextButton, 1, 3, 3, 1, Qt::AlignTop); searchLayout->addWidget(m_cancelSearchButton, 1, 4, 3, 1, Qt::AlignTop); if(s_settings->mainWindow().extendedSearchDock()) { searchLayout->addWidget(m_searchView, 4, 0, 1, 5); } } } void MainWindow::on_search_visibilityChanged(bool visible) { if(!visible) { m_searchLineEdit->stopTimer(); m_searchLineEdit->setProgress(0); foreach(DocumentView* tab, allTabs()) { tab->cancelSearch(); tab->clearResults(); } if(DocumentView* tab = currentTab()) { tab->setFocus(); } } } void MainWindow::on_search_clicked(const QModelIndex& clickedIndex) { DocumentView* const clickedTab = SearchModel::instance()->viewForIndex(clickedIndex); for(int index = 0, count = m_tabWidget->count(); index < count; ++index) { foreach(DocumentView* tab, allTabs(index)) { if(tab == clickedTab) { m_tabWidget->setCurrentIndex(index); tab->setFocus(); clickedTab->findResult(clickedIndex); return; } } } } void MainWindow::on_search_rowsInserted(const QModelIndex& parent, int first, int last) { if(parent.isValid()) { return; } for(int row = first; row <= last; ++row) { const QModelIndex index = s_searchModel->index(row, 0, parent); if(!m_searchView->isExpanded(index) && s_searchModel->viewForIndex(index) == currentTab()) { m_searchView->expand(index); } } } void MainWindow::on_saveDatabase_timeout() { if(s_settings->mainWindow().restoreTabs()) { s_database->saveTabs(allTabs()); s_settings->mainWindow().setCurrentTabIndex(m_tabWidget->currentIndex()); } if(s_settings->mainWindow().restoreBookmarks()) { s_database->saveBookmarks(); } if(s_settings->mainWindow().restorePerFileSettings()) { foreach(DocumentView* tab, allTabs()) { s_database->savePerFileSettings(tab); } } } bool MainWindow::eventFilter(QObject* target, QEvent* event) { // This event filter is used to override any keyboard shortcuts if the outline widget has the focus. if(target == m_outlineView && event->type() == QEvent::ShortcutOverride) { QKeyEvent* keyEvent = static_cast< QKeyEvent* >(event); const bool modifiers = keyEvent->modifiers().testFlag(Qt::ControlModifier) || keyEvent->modifiers().testFlag(Qt::ShiftModifier); const bool keys = keyEvent->key() == Qt::Key_Right || keyEvent->key() == Qt::Key_Left || keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down; if(modifiers && keys) { keyEvent->accept(); return true; } } // This event filter is used to fit the thumbnails into the thumbnails view if this is enabled in the settings. else if(target == m_thumbnailsView && (event->type() == QEvent::Resize || event->type() == QEvent::Show)) { if(DocumentView* tab = currentTab()) { tab->setThumbnailsViewportSize(m_thumbnailsView->viewport()->size()); } } return QMainWindow::eventFilter(target, event); } void MainWindow::closeEvent(QCloseEvent* event) { m_searchDock->setVisible(false); for(int index = 0, count = m_tabWidget->count(); index < count; ++index) { foreach(DocumentView* tab, allTabs(index)) { if(!saveModifications(tab)) { m_tabWidget->setCurrentIndex(index); tab->setFocus(); event->setAccepted(false); return; } } } if(s_settings->mainWindow().restoreTabs()) { s_database->saveTabs(allTabs()); s_settings->mainWindow().setCurrentTabIndex(m_tabWidget->currentIndex()); } else { s_database->clearTabs(); } if(s_settings->mainWindow().restoreBookmarks()) { s_database->saveBookmarks(); } else { s_database->clearBookmarks(); } s_settings->mainWindow().setRecentlyUsed(s_settings->mainWindow().trackRecentlyUsed() ? m_recentlyUsedMenu->filePaths() : QStringList()); s_settings->documentView().setMatchCase(m_matchCaseCheckBox->isChecked()); s_settings->documentView().setWholeWords(m_wholeWordsCheckBox->isChecked()); s_settings->mainWindow().setGeometry(m_fullscreenAction->isChecked() ? m_fullscreenAction->data().toByteArray() : saveGeometry()); s_settings->mainWindow().setState(saveState()); QMainWindow::closeEvent(event); } void MainWindow::dragEnterEvent(QDragEnterEvent* event) { if(event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } void MainWindow::dropEvent(QDropEvent* event) { if(event->mimeData()->hasUrls()) { event->acceptProposedAction(); CurrentTabChangeBlocker currentTabChangeBlocker(this); foreach(const QUrl& url, event->mimeData()->urls()) { #if QT_VERSION >= QT_VERSION_CHECK(4,8,0) if(url.isLocalFile()) #else if(url.scheme() == "file") #endif // QT_VERSION { openInNewTab(url.toLocalFile()); } } } } void MainWindow::prepareStyle() { if(s_settings->mainWindow().hasIconTheme()) { QIcon::setThemeName(s_settings->mainWindow().iconTheme()); } if(s_settings->mainWindow().hasStyleSheet()) { qApp->setStyleSheet(s_settings->mainWindow().styleSheet()); } ProxyStyle* style = new ProxyStyle(); style->setScrollableMenus(s_settings->mainWindow().scrollableMenus()); qApp->setStyle(style); } inline DocumentView* MainWindow::currentTab() const { return findCurrentTab(m_tabWidget->currentWidget()); } inline DocumentView* MainWindow::currentTab(int index) const { return findCurrentTab(m_tabWidget->widget(index)); } inline QVector< DocumentView* > MainWindow::allTabs(int index) const { return findAllTabs(m_tabWidget->widget(index)); } QVector< DocumentView* > MainWindow::allTabs() const { QVector< DocumentView* > tabs; for(int index = 0, count = m_tabWidget->count(); index < count; ++index) { tabs += allTabs(index); } return tabs; } bool MainWindow::senderIsCurrentTab() const { return sender() == currentTab() || qobject_cast< DocumentView* >(sender()) == 0; } void MainWindow::addTab(DocumentView* tab) { m_tabWidget->addTab(tab, s_settings->mainWindow().newTabNextToCurrentTab(), tab->title(), tab->fileInfo().absoluteFilePath()); } void MainWindow::addTabAction(DocumentView* tab) { QAction* tabAction = new QAction(tab->title(), tab); tabAction->setToolTip(tab->fileInfo().absoluteFilePath()); tabAction->setData(true); // Flag action for search-as-you-type connect(tabAction, SIGNAL(triggered()), SLOT(on_tabAction_triggered())); m_tabsMenu->addAction(tabAction); } void MainWindow::connectTab(DocumentView* tab) { connect(tab, SIGNAL(documentChanged()), SLOT(on_currentTab_documentChanged())); connect(tab, SIGNAL(documentModified()), SLOT(on_currentTab_documentModified())); connect(tab, SIGNAL(numberOfPagesChanged(int)), SLOT(on_currentTab_numberOfPagesChaned(int))); connect(tab, SIGNAL(currentPageChanged(int)), SLOT(on_currentTab_currentPageChanged(int))); connect(tab, SIGNAL(canJumpChanged(bool,bool)), SLOT(on_currentTab_canJumpChanged(bool,bool))); connect(tab, SIGNAL(continuousModeChanged(bool)), SLOT(on_currentTab_continuousModeChanged(bool))); connect(tab, SIGNAL(layoutModeChanged(LayoutMode)), SLOT(on_currentTab_layoutModeChanged(LayoutMode))); connect(tab, SIGNAL(rightToLeftModeChanged(bool)), SLOT(on_currentTab_rightToLeftModeChanged(bool))); connect(tab, SIGNAL(scaleModeChanged(ScaleMode)), SLOT(on_currentTab_scaleModeChanged(ScaleMode))); connect(tab, SIGNAL(scaleFactorChanged(qreal)), SLOT(on_currentTab_scaleFactorChanged(qreal))); connect(tab, SIGNAL(rotationChanged(Rotation)), SLOT(on_currentTab_rotationChanged(Rotation))); connect(tab, SIGNAL(linkClicked(int)), SLOT(on_currentTab_linkClicked(int))); connect(tab, SIGNAL(linkClicked(bool,QString,int)), SLOT(on_currentTab_linkClicked(bool,QString,int))); connect(tab, SIGNAL(renderFlagsChanged(qpdfview::RenderFlags)), SLOT(on_currentTab_renderFlagsChanged(qpdfview::RenderFlags))); connect(tab, SIGNAL(invertColorsChanged(bool)), SLOT(on_currentTab_invertColorsChanged(bool))); connect(tab, SIGNAL(convertToGrayscaleChanged(bool)), SLOT(on_currentTab_convertToGrayscaleChanged(bool))); connect(tab, SIGNAL(trimMarginsChanged(bool)), SLOT(on_currentTab_trimMarginsChanged(bool))); connect(tab, SIGNAL(compositionModeChanged(CompositionMode)), SLOT(on_currentTab_compositionModeChanged(CompositionMode))); connect(tab, SIGNAL(highlightAllChanged(bool)), SLOT(on_currentTab_highlightAllChanged(bool))); connect(tab, SIGNAL(rubberBandModeChanged(RubberBandMode)), SLOT(on_currentTab_rubberBandModeChanged(RubberBandMode))); connect(tab, SIGNAL(searchFinished()), SLOT(on_currentTab_searchFinished())); connect(tab, SIGNAL(searchProgressChanged(int)), SLOT(on_currentTab_searchProgressChanged(int))); connect(tab, SIGNAL(customContextMenuRequested(QPoint)), SLOT(on_currentTab_customContextMenuRequested(QPoint))); } void MainWindow::restorePerFileSettings(DocumentView* tab) { s_database->restorePerFileSettings(tab); if(m_outlineView->model() == tab->outlineModel()) { m_outlineView->restoreExpansion(); } } bool MainWindow::saveModifications(DocumentView* tab) { s_database->savePerFileSettings(tab); scheduleSaveTabs(); if(tab->wasModified()) { const int button = QMessageBox::warning(this, tr("Warning"), tr("The document '%1' has been modified. Do you want to save your changes?").arg(tab->fileInfo().filePath()), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); if(button == QMessageBox::Save) { if(tab->save(tab->fileInfo().filePath(), true)) { return true; } else { QMessageBox::warning(this, tr("Warning"), tr("Could not save as '%1'.").arg(tab->fileInfo().filePath())); } } else if(button == QMessageBox::Discard) { return true; } return false; } return true; } void MainWindow::closeTab(DocumentView* tab) { const int tabIndex = m_tabWidget->indexOf(tab); if(s_settings->mainWindow().keepRecentlyClosed() && tabIndex != -1) { foreach(QAction* tabAction, m_tabsMenu->actions()) { if(tabAction->parent() == tab) { m_tabsMenu->removeAction(tabAction); m_tabWidget->removeTab(tabIndex); tab->setParent(this); tab->setVisible(false); tab->clearResults(); m_recentlyClosedMenu->addTabAction(tabAction); break; } } } else { Splitter* const splitter = qobject_cast< Splitter* >(tab->parentWidget()); delete tab; if(splitter != 0) { if(splitter->count() > 0) { splitter->widget(0)->setFocus(); } else { delete splitter; } } if(s_settings->mainWindow().exitAfterLastTab() && m_tabWidget->count() == 0) { close(); } } } void MainWindow::setWindowTitleForCurrentTab() { QString tabText; QString instanceText; if(DocumentView* tab = currentTab()) { QString currentPage; if(s_settings->mainWindow().currentPageInWindowTitle()) { currentPage = QString(" (%1 / %2)").arg(tab->currentPage()).arg(tab->numberOfPages()); } tabText = m_tabWidget->currentTabText() + currentPage + QLatin1String("[*] - "); } const QString instanceName = qApp->objectName(); if(s_settings->mainWindow().instanceNameInWindowTitle() && !instanceName.isEmpty()) { instanceText = QLatin1String(" (") + instanceName + QLatin1String(")"); } setWindowTitle(tabText + QLatin1String("qpdfview") + instanceText); } void MainWindow::setCurrentPageSuffixForCurrentTab() { QString suffix; if(DocumentView* tab = currentTab()) { const int currentPage = tab->currentPage(); const int numberOfPages = tab->numberOfPages(); const QString& defaultPageLabel = tab->defaultPageLabelFromNumber(currentPage); const QString& pageLabel = tab->pageLabelFromNumber(currentPage); const QString& lastDefaultPageLabel = tab->defaultPageLabelFromNumber(numberOfPages); if((s_settings->mainWindow().usePageLabel() || tab->hasFrontMatter()) && defaultPageLabel != pageLabel) { suffix = QString(" (%1 / %2)").arg(defaultPageLabel, lastDefaultPageLabel); } else { suffix = QString(" / %1").arg(lastDefaultPageLabel); } } else { suffix = QLatin1String(" / 1"); } m_currentPageSpinBox->setSuffix(suffix); } BookmarkModel* MainWindow::bookmarkModelForCurrentTab(bool create) { return BookmarkModel::fromPath(currentTab()->fileInfo().absoluteFilePath(), create); } QAction* MainWindow::sourceLinkActionForCurrentTab(QObject* parent, QPoint pos) { QAction* action = createTemporaryAction(parent, QString(), QLatin1String("openSourceLink")); if(const DocumentView::SourceLink sourceLink = currentTab()->sourceLink(pos)) { const QString fileName = QFileInfo(sourceLink.name).fileName(); action->setText(tr("Edit '%1' at %2,%3...").arg(fileName).arg(sourceLink.line).arg(sourceLink.column)); action->setData(QVariant::fromValue(sourceLink)); } else { action->setVisible(false); } return action; } void MainWindow::prepareDatabase() { if(s_database == 0) { s_database = Database::instance(); } m_saveDatabaseTimer = new QTimer(this); m_saveDatabaseTimer->setSingleShot(true); connect(m_saveDatabaseTimer, SIGNAL(timeout()), SLOT(on_saveDatabase_timeout())); } void MainWindow::scheduleSaveDatabase() { const int interval = s_settings->mainWindow().saveDatabaseInterval(); if(!m_saveDatabaseTimer->isActive() && interval >= 0) { m_saveDatabaseTimer->start(interval); } } void MainWindow::scheduleSaveTabs() { if(s_settings->mainWindow().restoreTabs()) { scheduleSaveDatabase(); } } void MainWindow::scheduleSaveBookmarks() { if(s_settings->mainWindow().restoreBookmarks()) { scheduleSaveDatabase(); } } void MainWindow::scheduleSavePerFileSettings() { if(s_settings->mainWindow().restorePerFileSettings()) { scheduleSaveDatabase(); } } void MainWindow::createWidgets() { m_tabWidget = new TabWidget(this); m_tabWidget->setDocumentMode(true); m_tabWidget->setMovable(true); m_tabWidget->setTabsClosable(true); m_tabWidget->setElideMode(Qt::ElideRight); m_tabWidget->setTabPosition(static_cast< QTabWidget::TabPosition >(s_settings->mainWindow().tabPosition())); m_tabWidget->setTabBarPolicy(static_cast< TabWidget::TabBarPolicy >(s_settings->mainWindow().tabVisibility())); m_tabWidget->setSpreadTabs(s_settings->mainWindow().spreadTabs()); setCentralWidget(m_tabWidget); m_currentTabChangedBlocked = false; connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(on_tabWidget_currentChanged())); connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(on_tabWidget_tabCloseRequested(int))); connect(m_tabWidget, SIGNAL(tabDragRequested(int)), SLOT(on_tabWidget_tabDragRequested(int))); connect(m_tabWidget, SIGNAL(tabContextMenuRequested(QPoint,int)), SLOT(on_tabWidget_tabContextMenuRequested(QPoint,int))); // current page m_currentPageSpinBox = new MappingSpinBox(new TextValueMapper(this), this); m_currentPageSpinBox->setAlignment(Qt::AlignCenter); m_currentPageSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); m_currentPageSpinBox->setKeyboardTracking(false); connect(m_currentPageSpinBox, SIGNAL(editingFinished()), SLOT(on_currentPage_editingFinished())); connect(m_currentPageSpinBox, SIGNAL(returnPressed()), SLOT(on_currentPage_returnPressed())); m_currentPageAction = new QWidgetAction(this); m_currentPageAction->setObjectName(QLatin1String("currentPage")); m_currentPageAction->setDefaultWidget(m_currentPageSpinBox); // scale factor m_scaleFactorComboBox = new ComboBox(this); m_scaleFactorComboBox->setEditable(true); m_scaleFactorComboBox->setInsertPolicy(QComboBox::NoInsert); m_scaleFactorComboBox->addItem(tr("Page width")); m_scaleFactorComboBox->addItem(tr("Page size")); m_scaleFactorComboBox->addItem("50 %", 0.5); m_scaleFactorComboBox->addItem("75 %", 0.75); m_scaleFactorComboBox->addItem("100 %", 1.0); m_scaleFactorComboBox->addItem("125 %", 1.25); m_scaleFactorComboBox->addItem("150 %", 1.5); m_scaleFactorComboBox->addItem("200 %", 2.0); m_scaleFactorComboBox->addItem("300 %", 3.0); m_scaleFactorComboBox->addItem("400 %", 4.0); m_scaleFactorComboBox->addItem("500 %", 5.0); connect(m_scaleFactorComboBox, SIGNAL(activated(int)), SLOT(on_scaleFactor_activated(int))); connect(m_scaleFactorComboBox->lineEdit(), SIGNAL(editingFinished()), SLOT(on_scaleFactor_editingFinished())); connect(m_scaleFactorComboBox->lineEdit(), SIGNAL(returnPressed()), SLOT(on_scaleFactor_returnPressed())); m_scaleFactorAction = new QWidgetAction(this); m_scaleFactorAction->setObjectName(QLatin1String("scaleFactor")); m_scaleFactorAction->setDefaultWidget(m_scaleFactorComboBox); // search m_searchLineEdit = new SearchLineEdit(this); m_matchCaseCheckBox = new QCheckBox(tr("Match &case"), this); m_wholeWordsCheckBox = new QCheckBox(tr("Whole &words"), this); m_highlightAllCheckBox = new QCheckBox(tr("Highlight &all"), this); connect(m_searchLineEdit, SIGNAL(searchInitiated(QString,bool)), SLOT(on_searchInitiated(QString,bool))); connect(m_matchCaseCheckBox, SIGNAL(clicked()), m_searchLineEdit, SLOT(startTimer())); connect(m_wholeWordsCheckBox, SIGNAL(clicked()), m_searchLineEdit, SLOT(startTimer())); connect(m_highlightAllCheckBox, SIGNAL(clicked(bool)), SLOT(on_highlightAll_clicked(bool))); m_matchCaseCheckBox->setChecked(s_settings->documentView().matchCase()); m_wholeWordsCheckBox->setChecked(s_settings->documentView().wholeWords()); } QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QIcon& icon, const QList< QKeySequence >& shortcuts, const char* member, bool checkable, bool checked) { QAction* action = new QAction(text, this); action->setObjectName(objectName); action->setIcon(icon); action->setShortcuts(shortcuts); if(!objectName.isEmpty()) { s_shortcutHandler->registerAction(action); } if(checkable) { action->setCheckable(true); action->setChecked(checked); connect(action, SIGNAL(triggered(bool)), member); } else { action->setIconVisibleInMenu(true); connect(action, SIGNAL(triggered()), member); } addAction(action); return action; } inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QIcon& icon, const QKeySequence& shortcut, const char* member, bool checkable, bool checked) { return createAction(text, objectName, icon, QList< QKeySequence >() << shortcut, member, checkable, checked); } inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QString& iconName, const QList< QKeySequence >& shortcuts, const char* member, bool checkable, bool checked) { return createAction(text, objectName, loadIconWithFallback(iconName), shortcuts, member, checkable, checked); } inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QString& iconName, const QKeySequence& shortcut, const char* member, bool checkable, bool checked) { return createAction(text, objectName, iconName, QList< QKeySequence >() << shortcut, member, checkable, checked); } void MainWindow::createActions() { // file m_openAction = createAction(tr("&Open..."), QLatin1String("open"), QLatin1String("document-open"), QKeySequence::Open, SLOT(on_open_triggered())); m_openInNewTabAction = createAction(tr("Open in new &tab..."), QLatin1String("openInNewTab"), QLatin1String("tab-new"), QKeySequence::AddTab, SLOT(on_openInNewTab_triggered())); m_refreshAction = createAction(tr("&Refresh"), QLatin1String("refresh"), QLatin1String("view-refresh"), QKeySequence::Refresh, SLOT(on_refresh_triggered())); m_saveAction = createAction(tr("&Save"), QLatin1String("save"), QLatin1String("document-save"), QKeySequence::Save, SLOT(on_save_triggered())); m_saveAsAction = createAction(tr("Save &as..."), QLatin1String("saveAs"), QLatin1String("document-save-as"), QKeySequence::SaveAs, SLOT(on_saveAs_triggered())); m_saveCopyAction = createAction(tr("Save ©..."), QLatin1String("saveCopy"), QIcon(), QKeySequence(), SLOT(on_saveCopy_triggered())); m_printAction = createAction(tr("&Print..."), QLatin1String("print"), QLatin1String("document-print"), QKeySequence::Print, SLOT(on_print_triggered())); m_exitAction = createAction(tr("E&xit"), QLatin1String("exit"), QIcon::fromTheme("application-exit"), QKeySequence::Quit, SLOT(close())); // edit m_previousPageAction = createAction(tr("&Previous page"), QLatin1String("previousPage"), QLatin1String("go-previous"), QKeySequence(Qt::Key_Backspace), SLOT(on_previousPage_triggered())); m_nextPageAction = createAction(tr("&Next page"), QLatin1String("nextPage"), QLatin1String("go-next"), QKeySequence(Qt::Key_Space), SLOT(on_nextPage_triggered())); const QList< QKeySequence > firstPageShortcuts = QList< QKeySequence >() << QKeySequence(Qt::Key_Home) << QKeySequence(Qt::KeypadModifier + Qt::Key_Home) << QKeySequence(Qt::ControlModifier + Qt::Key_Home) << QKeySequence(Qt::ControlModifier + Qt::KeypadModifier + Qt::Key_Home); m_firstPageAction = createAction(tr("&First page"), QLatin1String("firstPage"), QLatin1String("go-first"), firstPageShortcuts, SLOT(on_firstPage_triggered())); const QList< QKeySequence > lastPageShortcuts = QList< QKeySequence >() << QKeySequence(Qt::Key_End) << QKeySequence(Qt::KeypadModifier + Qt::Key_End) << QKeySequence(Qt::ControlModifier + Qt::Key_End) << QKeySequence(Qt::ControlModifier + Qt::KeypadModifier + Qt::Key_End); m_lastPageAction = createAction(tr("&Last page"), QLatin1String("lastPage"), QLatin1String("go-last"), lastPageShortcuts, SLOT(on_lastPage_triggered())); m_setFirstPageAction = createAction(tr("&Set first page..."), QLatin1String("setFirstPage"), QIcon(), QKeySequence(), SLOT(on_setFirstPage_triggered())); m_jumpToPageAction = createAction(tr("&Jump to page..."), QLatin1String("jumpToPage"), QLatin1String("go-jump"), QKeySequence(Qt::CTRL + Qt::Key_J), SLOT(on_jumpToPage_triggered())); m_jumpBackwardAction = createAction(tr("Jump &backward"), QLatin1String("jumpBackward"), QLatin1String("media-seek-backward"), QKeySequence(Qt::CTRL + Qt::Key_Return), SLOT(on_jumpBackward_triggered())); m_jumpForwardAction = createAction(tr("Jump for&ward"), QLatin1String("jumpForward"), QLatin1String("media-seek-forward"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Return), SLOT(on_jumpForward_triggered())); m_searchAction = createAction(tr("&Search..."), QLatin1String("search"), QLatin1String("edit-find"), QKeySequence::Find, SLOT(on_search_triggered())); m_findPreviousAction = createAction(tr("Find previous"), QLatin1String("findPrevious"), QLatin1String("go-up"), QKeySequence::FindPrevious, SLOT(on_findPrevious_triggered())); m_findNextAction = createAction(tr("Find next"), QLatin1String("findNext"), QLatin1String("go-down"), QKeySequence::FindNext, SLOT(on_findNext_triggered())); m_cancelSearchAction = createAction(tr("Cancel search"), QLatin1String("cancelSearch"), QLatin1String("process-stop"), QKeySequence(Qt::Key_Escape), SLOT(on_cancelSearch_triggered())); m_copyToClipboardModeAction = createAction(tr("&Copy to clipboard"), QLatin1String("copyToClipboardMode"), QLatin1String("edit-copy"), QKeySequence(Qt::CTRL + Qt::Key_C), SLOT(on_copyToClipboardMode_triggered(bool)), true); m_addAnnotationModeAction = createAction(tr("&Add annotation"), QLatin1String("addAnnotationMode"), QLatin1String("mail-attachment"), QKeySequence(Qt::CTRL + Qt::Key_A), SLOT(on_addAnnotationMode_triggered(bool)), true); m_settingsAction = createAction(tr("Settings..."), QString(), QIcon(), QKeySequence(), SLOT(on_settings_triggered())); // view m_continuousModeAction = createAction(tr("&Continuous"), QLatin1String("continuousMode"), QIcon(QLatin1String(":icons/continuous")), QKeySequence(Qt::CTRL + Qt::Key_7), SLOT(on_continuousMode_triggered(bool)), true); m_twoPagesModeAction = createAction(tr("&Two pages"), QLatin1String("twoPagesMode"), QIcon(QLatin1String(":icons/two-pages")), QKeySequence(Qt::CTRL + Qt::Key_6), SLOT(on_twoPagesMode_triggered(bool)), true); m_twoPagesWithCoverPageModeAction = createAction(tr("Two pages &with cover page"), QLatin1String("twoPagesWithCoverPageMode"), QIcon(QLatin1String(":icons/two-pages-with-cover-page")), QKeySequence(Qt::CTRL + Qt::Key_5), SLOT(on_twoPagesWithCoverPageMode_triggered(bool)), true); m_multiplePagesModeAction = createAction(tr("&Multiple pages"), QLatin1String("multiplePagesMode"), QIcon(QLatin1String(":icons/multiple-pages")), QKeySequence(Qt::CTRL + Qt::Key_4), SLOT(on_multiplePagesMode_triggered(bool)), true); m_rightToLeftModeAction = createAction(tr("Right to left"), QLatin1String("rightToLeftMode"), QIcon(QLatin1String(":icons/right-to-left")), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R), SLOT(on_rightToLeftMode_triggered(bool)), true); m_zoomInAction = createAction(tr("Zoom &in"), QLatin1String("zoomIn"), QLatin1String("zoom-in"), QKeySequence(Qt::CTRL + Qt::Key_Up), SLOT(on_zoomIn_triggered())); m_zoomOutAction = createAction(tr("Zoom &out"), QLatin1String("zoomOut"), QLatin1String("zoom-out"), QKeySequence(Qt::CTRL + Qt::Key_Down), SLOT(on_zoomOut_triggered())); m_originalSizeAction = createAction(tr("Original &size"), QLatin1String("originalSize"), QLatin1String("zoom-original"), QKeySequence(Qt::CTRL + Qt::Key_0), SLOT(on_originalSize_triggered())); m_fitToPageWidthModeAction = createAction(tr("Fit to page width"), QLatin1String("fitToPageWidthMode"), QIcon(QLatin1String(":icons/fit-to-page-width")), QKeySequence(Qt::CTRL + Qt::Key_9), SLOT(on_fitToPageWidthMode_triggered(bool)), true); m_fitToPageSizeModeAction = createAction(tr("Fit to page size"), QLatin1String("fitToPageSizeMode"), QIcon(QLatin1String(":icons/fit-to-page-size")), QKeySequence(Qt::CTRL + Qt::Key_8), SLOT(on_fitToPageSizeMode_triggered(bool)), true); m_rotateLeftAction = createAction(tr("Rotate &left"), QLatin1String("rotateLeft"), QLatin1String("object-rotate-left"), QKeySequence(Qt::CTRL + Qt::Key_Left), SLOT(on_rotateLeft_triggered())); m_rotateRightAction = createAction(tr("Rotate &right"), QLatin1String("rotateRight"), QLatin1String("object-rotate-right"), QKeySequence(Qt::CTRL + Qt::Key_Right), SLOT(on_rotateRight_triggered())); m_invertColorsAction = createAction(tr("Invert colors"), QLatin1String("invertColors"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_I), SLOT(on_invertColors_triggered(bool)), true); m_convertToGrayscaleAction = createAction(tr("Convert to grayscale"), QLatin1String("convertToGrayscale"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_U), SLOT(on_convertToGrayscale_triggered(bool)), true); m_trimMarginsAction = createAction(tr("Trim margins"), QLatin1String("trimMargins"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U), SLOT(on_trimMargins_triggered(bool)), true); m_darkenWithPaperColorAction = createAction(tr("Darken with paper color"), QLatin1String("darkenWithPaperColor"), QIcon(), QKeySequence(), SLOT(on_darkenWithPaperColor_triggered(bool)), true); m_lightenWithPaperColorAction = createAction(tr("Lighten with paper color"), QLatin1String("lightenWithPaperColor"), QIcon(), QKeySequence(), SLOT(on_lightenWithPaperColor_triggered(bool)), true); m_fontsAction = createAction(tr("Fonts..."), QString(), QIcon(), QKeySequence(), SLOT(on_fonts_triggered())); m_fullscreenAction = createAction(tr("&Fullscreen"), QLatin1String("fullscreen"), QLatin1String("view-fullscreen"), QKeySequence(Qt::Key_F11), SLOT(on_fullscreen_triggered(bool)), true); m_presentationAction = createAction(tr("&Presentation..."), QLatin1String("presentation"), QLatin1String("x-office-presentation"), QKeySequence(Qt::Key_F12), SLOT(on_presentation_triggered())); // tabs m_previousTabAction = createAction(tr("&Previous tab"), QLatin1String("previousTab"), QIcon(), QKeySequence::PreviousChild, SLOT(on_previousTab_triggered())); m_nextTabAction = createAction(tr("&Next tab"), QLatin1String("nextTab"), QIcon(), QKeySequence::NextChild, SLOT(on_nextTab_triggered())); m_closeTabAction = createAction(tr("&Close tab"), QLatin1String("closeTab"), QIcon::fromTheme("window-close"), QKeySequence(Qt::CTRL + Qt::Key_W), SLOT(on_closeTab_triggered())); m_closeAllTabsAction = createAction(tr("Close &all tabs"), QLatin1String("closeAllTabs"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W), SLOT(on_closeAllTabs_triggered())); m_closeAllTabsButCurrentTabAction = createAction(tr("Close all tabs &but current tab"), QLatin1String("closeAllTabsButCurrent"), QIcon(), QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_W), SLOT(on_closeAllTabsButCurrentTab_triggered())); m_restoreMostRecentlyClosedTabAction = createAction(tr("Restore &most recently closed tab"), QLatin1String("restoreMostRecentlyClosedTab"), QIcon(), QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_W), SLOT(on_restoreMostRecentlyClosedTab_triggered())); // tab shortcuts for(int index = 0; index < 9; ++index) { m_tabShortcuts[index] = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_1 + index), this, SLOT(on_tabShortcut_activated())); } // bookmarks m_previousBookmarkAction = createAction(tr("&Previous bookmark"), QLatin1String("previousBookmarkAction"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_PageUp), SLOT(on_previousBookmark_triggered())); m_nextBookmarkAction = createAction(tr("&Next bookmark"), QLatin1String("nextBookmarkAction"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_PageDown), SLOT(on_nextBookmark_triggered())); m_addBookmarkAction = createAction(tr("&Add bookmark"), QLatin1String("addBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_B), SLOT(on_addBookmark_triggered())); m_removeBookmarkAction = createAction(tr("&Remove bookmark"), QLatin1String("removeBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B), SLOT(on_removeBookmark_triggered())); m_removeAllBookmarksAction = createAction(tr("Remove all bookmarks"), QLatin1String("removeAllBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_B), SLOT(on_removeAllBookmarks_triggered())); // help m_contentsAction = createAction(tr("&Contents"), QLatin1String("contents"), QIcon::fromTheme("help-contents"), QKeySequence::HelpContents, SLOT(on_contents_triggered())); m_aboutAction = createAction(tr("&About"), QString(), QIcon::fromTheme("help-about"), QKeySequence(), SLOT(on_about_triggered())); // context m_openCopyInNewTabAction = createAction(tr("Open © in new tab"), QLatin1String("openCopyInNewTab"), QLatin1String("tab-new"), QKeySequence(), SLOT(on_openCopyInNewTab_triggered())); m_openCopyInNewWindowAction = createAction(tr("Open copy in new &window"), QLatin1String("openCopyInNewWindow"), QLatin1String("window-new"), QKeySequence(), SLOT(on_openCopyInNewWindow_triggered())); m_openContainingFolderAction = createAction(tr("Open containing &folder"), QLatin1String("openContainingFolder"), QLatin1String("folder"), QKeySequence(), SLOT(on_openContainingFolder_triggered())); m_moveToInstanceAction = createAction(tr("Move to &instance..."), QLatin1String("moveToInstance"), QIcon(), QKeySequence(), SLOT(on_moveToInstance_triggered())); m_splitViewHorizontallyAction = createAction(tr("Split view horizontally..."), QLatin1String("splitViewHorizontally"), QIcon(), QKeySequence(), SLOT(on_splitView_splitHorizontally_triggered())); m_splitViewVerticallyAction = createAction(tr("Split view vertically..."), QLatin1String("splitViewVertically"), QIcon(), QKeySequence(), SLOT(on_splitView_splitVertically_triggered())); m_closeCurrentViewAction = createAction(tr("Close current view"), QLatin1String("closeCurrentView"), QIcon(), QKeySequence(), SLOT(on_splitView_closeCurrent_triggered())); // tool bars and menu bar m_toggleToolBarsAction = createAction(tr("Toggle tool bars"), QLatin1String("toggleToolBars"), QIcon(), QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_T), SLOT(on_toggleToolBars_triggered(bool)), true, true); m_toggleMenuBarAction = createAction(tr("Toggle menu bar"), QLatin1String("toggleMenuBar"), QIcon(), QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_M), SLOT(on_toggleMenuBar_triggered(bool)), true, true); // progress and error icons s_settings->pageItem().setProgressIcon(loadIconWithFallback(QLatin1String("image-loading"))); s_settings->pageItem().setErrorIcon(loadIconWithFallback(QLatin1String("image-missing"))); } QToolBar* MainWindow::createToolBar(const QString& text, const QString& objectName, const QStringList& actionNames, const QList< QAction* >& actions) { QToolBar* toolBar = addToolBar(text); toolBar->setObjectName(objectName); addWidgetActions(toolBar, actionNames, actions); toolBar->toggleViewAction()->setObjectName(objectName + QLatin1String("ToggleView")); s_shortcutHandler->registerAction(toolBar->toggleViewAction()); return toolBar; } void MainWindow::createToolBars() { m_fileToolBar = createToolBar(tr("&File"), QLatin1String("fileToolBar"), s_settings->mainWindow().fileToolBar(), QList< QAction* >() << m_openAction << m_openInNewTabAction << m_openContainingFolderAction << m_refreshAction << m_saveAction << m_saveAsAction << m_printAction); m_editToolBar = createToolBar(tr("&Edit"), QLatin1String("editToolBar"), s_settings->mainWindow().editToolBar(), QList< QAction* >() << m_currentPageAction << m_previousPageAction << m_nextPageAction << m_firstPageAction << m_lastPageAction << m_jumpToPageAction << m_searchAction << m_jumpBackwardAction << m_jumpForwardAction << m_copyToClipboardModeAction << m_addAnnotationModeAction); m_viewToolBar = createToolBar(tr("&View"), QLatin1String("viewToolBar"), s_settings->mainWindow().viewToolBar(), QList< QAction* >() << m_scaleFactorAction << m_continuousModeAction << m_twoPagesModeAction << m_twoPagesWithCoverPageModeAction << m_multiplePagesModeAction << m_rightToLeftModeAction << m_zoomInAction << m_zoomOutAction << m_originalSizeAction << m_fitToPageWidthModeAction << m_fitToPageSizeModeAction << m_rotateLeftAction << m_rotateRightAction << m_fullscreenAction << m_presentationAction); m_focusCurrentPageShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_K), this, SLOT(on_focusCurrentPage_activated())); m_focusScaleFactorShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this, SLOT(on_focusScaleFactor_activated())); } QDockWidget* MainWindow::createDock(const QString& text, const QString& objectName, const QKeySequence& toggleViewShortcut) { QDockWidget* dock = new QDockWidget(text, this); dock->setObjectName(objectName); dock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); #ifdef Q_OS_WIN dock->setWindowTitle(dock->windowTitle().remove(QLatin1Char('&'))); #endif // Q_OS_WIN addDockWidget(Qt::LeftDockWidgetArea, dock); connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_dock_dockLocationChanged(Qt::DockWidgetArea))); dock->toggleViewAction()->setObjectName(objectName + QLatin1String("ToggleView")); dock->toggleViewAction()->setShortcut(toggleViewShortcut); s_shortcutHandler->registerAction(dock->toggleViewAction()); dock->hide(); return dock; } void MainWindow::createSearchDock() { m_searchDock = new QDockWidget(tr("&Search"), this); m_searchDock->setObjectName(QLatin1String("searchDock")); m_searchDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetVerticalTitleBar); #ifdef Q_OS_WIN m_searchDock->setWindowTitle(m_searchDock->windowTitle().remove(QLatin1Char('&'))); #endif // Q_OS_WIN addDockWidget(Qt::BottomDockWidgetArea, m_searchDock); connect(m_searchDock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_dock_dockLocationChanged(Qt::DockWidgetArea))); connect(m_searchDock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_search_dockLocationChanged(Qt::DockWidgetArea))); connect(m_searchDock, SIGNAL(visibilityChanged(bool)), SLOT(on_search_visibilityChanged(bool))); m_searchWidget = new QWidget(this); m_searchDock->setWidget(m_searchWidget); m_findPreviousButton = new QToolButton(m_searchWidget); m_findPreviousButton->setAutoRaise(true); m_findPreviousButton->setDefaultAction(m_findPreviousAction); m_findNextButton = new QToolButton(m_searchWidget); m_findNextButton->setAutoRaise(true); m_findNextButton->setDefaultAction(m_findNextAction); m_cancelSearchButton = new QToolButton(m_searchWidget); m_cancelSearchButton->setAutoRaise(true); m_cancelSearchButton->setDefaultAction(m_cancelSearchAction); connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_findPreviousAction, SLOT(setEnabled(bool))); connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_findNextAction, SLOT(setEnabled(bool))); connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_cancelSearchAction, SLOT(setEnabled(bool))); m_searchDock->setVisible(false); m_findPreviousAction->setEnabled(false); m_findNextAction->setEnabled(false); m_cancelSearchAction->setEnabled(false); if(s_settings->mainWindow().extendedSearchDock()) { m_searchDock->setFeatures(m_searchDock->features() | QDockWidget::DockWidgetClosable); m_searchDock->toggleViewAction()->setObjectName(QLatin1String("searchDockToggleView")); m_searchDock->toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F10)); s_shortcutHandler->registerAction(m_searchDock->toggleViewAction()); m_searchView = new QTreeView(m_searchWidget); m_searchView->setAlternatingRowColors(true); m_searchView->setUniformRowHeights(true); m_searchView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_searchView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_searchView->setSelectionMode(QAbstractItemView::SingleSelection); m_searchView->setSelectionBehavior(QAbstractItemView::SelectRows); m_searchView->setItemDelegate(new SearchItemDelegate(m_searchView)); connect(m_searchView->header(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_search_sectionCountChanged())); connect(m_searchView, SIGNAL(clicked(QModelIndex)), SLOT(on_search_clicked(QModelIndex))); connect(m_searchView, SIGNAL(activated(QModelIndex)), SLOT(on_search_clicked(QModelIndex))); m_searchView->setModel(s_searchModel); connect(s_searchModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(on_search_rowsInserted(QModelIndex,int,int))); } else { m_searchView = 0; } on_search_dockLocationChanged(Qt::BottomDockWidgetArea); } void MainWindow::createDocks() { // outline m_outlineDock = createDock(tr("&Outline"), QLatin1String("outlineDock"), QKeySequence(Qt::Key_F6)); m_outlineView = new TreeView(Model::Document::ExpansionRole, this); m_outlineView->setAlternatingRowColors(true); m_outlineView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_outlineView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_outlineView->setSelectionMode(QAbstractItemView::SingleSelection); m_outlineView->setSelectionBehavior(QAbstractItemView::SelectRows); m_outlineView->installEventFilter(this); connect(m_outlineView->header(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_outline_sectionCountChanged())); connect(m_outlineView, SIGNAL(clicked(QModelIndex)), SLOT(on_outline_clicked(QModelIndex))); connect(m_outlineView, SIGNAL(activated(QModelIndex)), SLOT(on_outline_clicked(QModelIndex))); m_outlineDock->setWidget(m_outlineView); // properties m_propertiesDock = createDock(tr("&Properties"), QLatin1String("propertiesDock"), QKeySequence(Qt::Key_F7)); m_propertiesView = new QTableView(this); m_propertiesView->setAlternatingRowColors(true); m_propertiesView->setTabKeyNavigation(false); m_propertiesView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_propertiesView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); connect(m_propertiesView->horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_properties_sectionCountChanged())); m_propertiesDock->setWidget(m_propertiesView); // thumbnails m_thumbnailsDock = createDock(tr("Thumb&nails"), QLatin1String("thumbnailsDock"), QKeySequence(Qt::Key_F8)); connect(m_thumbnailsDock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_thumbnails_dockLocationChanged(Qt::DockWidgetArea))); m_thumbnailsView = new QGraphicsView(this); m_thumbnailsView->installEventFilter(this); connect(m_thumbnailsView->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(on_thumbnails_verticalScrollBar_valueChanged(int))); m_thumbnailsDock->setWidget(m_thumbnailsView); // bookmarks m_bookmarksDock = createDock(tr("Book&marks"), QLatin1String("bookmarksDock"), QKeySequence(Qt::Key_F9)); m_bookmarksView = new QTableView(this); m_bookmarksView->setShowGrid(false); m_bookmarksView->setAlternatingRowColors(true); m_bookmarksView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_bookmarksView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_bookmarksView->setSelectionMode(QAbstractItemView::SingleSelection); m_bookmarksView->setSelectionBehavior(QAbstractItemView::SelectRows); m_bookmarksView->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_bookmarksView->horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_bookmarks_sectionCountChanged())); connect(m_bookmarksView, SIGNAL(clicked(QModelIndex)), SLOT(on_bookmarks_clicked(QModelIndex))); connect(m_bookmarksView, SIGNAL(activated(QModelIndex)), SLOT(on_bookmarks_clicked(QModelIndex))); connect(m_bookmarksView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(on_bookmarks_contextMenuRequested(QPoint))); m_bookmarksDock->setWidget(m_bookmarksView); // search createSearchDock(); } void MainWindow::createMenus() { // file m_fileMenu = menuBar()->addMenu(tr("&File")); m_fileMenu->addActions(QList< QAction* >() << m_openAction << m_openInNewTabAction); m_recentlyUsedMenu = new RecentlyUsedMenu(s_settings->mainWindow().recentlyUsed(), s_settings->mainWindow().recentlyUsedCount(), this); connect(m_recentlyUsedMenu, SIGNAL(openTriggered(QString)), SLOT(on_recentlyUsed_openTriggered(QString))); if(s_settings->mainWindow().trackRecentlyUsed()) { m_fileMenu->addMenu(m_recentlyUsedMenu); setToolButtonMenu(m_fileToolBar, m_openAction, m_recentlyUsedMenu); setToolButtonMenu(m_fileToolBar, m_openInNewTabAction, m_recentlyUsedMenu); } m_fileMenu->addActions(QList< QAction* >() << m_refreshAction << m_saveAction << m_saveAsAction << m_saveCopyAction << m_printAction); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_exitAction); // edit m_editMenu = menuBar()->addMenu(tr("&Edit")); m_editMenu->addActions(QList< QAction* >() << m_previousPageAction << m_nextPageAction << m_firstPageAction << m_lastPageAction << m_jumpToPageAction); m_editMenu->addSeparator(); m_editMenu->addActions(QList< QAction* >() << m_jumpBackwardAction << m_jumpForwardAction); m_editMenu->addSeparator(); m_editMenu->addActions(QList< QAction* >() << m_searchAction << m_findPreviousAction << m_findNextAction << m_cancelSearchAction); m_editMenu->addSeparator(); m_editMenu->addActions(QList< QAction* >() << m_copyToClipboardModeAction << m_addAnnotationModeAction); m_editMenu->addSeparator(); m_editMenu->addAction(m_settingsAction); // view m_viewMenu = menuBar()->addMenu(tr("&View")); m_viewMenu->addActions(QList< QAction* >() << m_continuousModeAction << m_twoPagesModeAction << m_twoPagesWithCoverPageModeAction << m_multiplePagesModeAction); m_viewMenu->addSeparator(); m_viewMenu->addAction(m_rightToLeftModeAction); m_viewMenu->addSeparator(); m_viewMenu->addActions(QList< QAction* >() << m_zoomInAction << m_zoomOutAction << m_originalSizeAction << m_fitToPageWidthModeAction << m_fitToPageSizeModeAction); m_viewMenu->addSeparator(); m_viewMenu->addActions(QList< QAction* >() << m_rotateLeftAction << m_rotateRightAction); m_viewMenu->addSeparator(); m_viewMenu->addActions(QList< QAction* >() << m_invertColorsAction << m_convertToGrayscaleAction << m_trimMarginsAction); m_compositionModeMenu = m_viewMenu->addMenu(tr("Composition")); m_compositionModeMenu->addAction(m_darkenWithPaperColorAction); m_compositionModeMenu->addAction(m_lightenWithPaperColorAction); m_viewMenu->addSeparator(); QMenu* toolBarsMenu = m_viewMenu->addMenu(tr("&Tool bars")); toolBarsMenu->addActions(QList< QAction* >() << m_fileToolBar->toggleViewAction() << m_editToolBar->toggleViewAction() << m_viewToolBar->toggleViewAction()); QMenu* docksMenu = m_viewMenu->addMenu(tr("&Docks")); docksMenu->addActions(QList< QAction* >() << m_outlineDock->toggleViewAction() << m_propertiesDock->toggleViewAction() << m_thumbnailsDock->toggleViewAction() << m_bookmarksDock->toggleViewAction()); if(s_settings->mainWindow().extendedSearchDock()) { docksMenu->addAction(m_searchDock->toggleViewAction()); } m_viewMenu->addAction(m_fontsAction); m_viewMenu->addSeparator(); m_viewMenu->addActions(QList< QAction* >() << m_fullscreenAction << m_presentationAction); // tabs m_tabsMenu = new SearchableMenu(tr("&Tabs"), this); menuBar()->addMenu(m_tabsMenu); m_tabsMenu->setSearchable(s_settings->mainWindow().searchableMenus()); m_tabsMenu->addActions(QList< QAction* >() << m_previousTabAction << m_nextTabAction); m_tabsMenu->addSeparator(); m_tabsMenu->addActions(QList< QAction* >() << m_closeTabAction << m_closeAllTabsAction << m_closeAllTabsButCurrentTabAction); m_recentlyClosedMenu = new RecentlyClosedMenu(s_settings->mainWindow().recentlyClosedCount(), this); connect(m_recentlyClosedMenu, SIGNAL(tabActionTriggered(QAction*)), SLOT(on_recentlyClosed_tabActionTriggered(QAction*))); if(s_settings->mainWindow().keepRecentlyClosed()) { m_tabsMenu->addMenu(m_recentlyClosedMenu); m_tabsMenu->addAction(m_restoreMostRecentlyClosedTabAction); } m_tabsMenu->addSeparator(); // bookmarks m_bookmarksMenu = new SearchableMenu(tr("&Bookmarks"), this); menuBar()->addMenu(m_bookmarksMenu); m_bookmarksMenu->setSearchable(s_settings->mainWindow().searchableMenus()); connect(m_bookmarksMenu, SIGNAL(aboutToShow()), this, SLOT(on_bookmarksMenu_aboutToShow())); m_bookmarksMenuIsDirty = true; // help m_helpMenu = menuBar()->addMenu(tr("&Help")); m_helpMenu->addActions(QList< QAction* >() << m_contentsAction << m_aboutAction); } #ifdef WITH_DBUS MainWindowAdaptor::MainWindowAdaptor(MainWindow* mainWindow) : QDBusAbstractAdaptor(mainWindow) { } QDBusInterface* MainWindowAdaptor::createInterface(const QString& instanceName) { return new QDBusInterface(serviceName(instanceName), QLatin1String("/MainWindow"), QLatin1String("local.qpdfview.MainWindow"), QDBusConnection::sessionBus()); } MainWindowAdaptor* MainWindowAdaptor::createAdaptor(MainWindow* mainWindow) { QScopedPointer< MainWindowAdaptor > adaptor(new MainWindowAdaptor(mainWindow)); if(!QDBusConnection::sessionBus().registerService(serviceName())) { return 0; } if(!QDBusConnection::sessionBus().registerObject(QLatin1String("/MainWindow"), mainWindow)) { return 0; } return adaptor.take(); } void MainWindowAdaptor::raiseAndActivate() { mainWindow()->raise(); mainWindow()->activateWindow(); } bool MainWindowAdaptor::open(const QString& absoluteFilePath, int page, const QRectF& highlight, bool quiet) { return mainWindow()->open(absoluteFilePath, page, highlight, quiet); } bool MainWindowAdaptor::openInNewTab(const QString& absoluteFilePath, int page, const QRectF& highlight, bool quiet) { return mainWindow()->openInNewTab(absoluteFilePath, page, highlight, quiet); } bool MainWindowAdaptor::jumpToPageOrOpenInNewTab(const QString& absoluteFilePath, int page, bool refreshBeforeJump, const QRectF& highlight, bool quiet) { return mainWindow()->jumpToPageOrOpenInNewTab(absoluteFilePath, page, refreshBeforeJump, highlight, quiet); } void MainWindowAdaptor::startSearch(const QString& text) { mainWindow()->startSearch(text); } void MainWindowAdaptor::saveDatabase() { mainWindow()->saveDatabase(); } int MainWindowAdaptor::currentPage() const { if(DocumentView* tab = mainWindow()->currentTab()) { return tab->currentPage(); } else { return -1; } } void MainWindowAdaptor::jumpToPage(int page) { if(DocumentView* tab = mainWindow()->currentTab()) { tab->jumpToPage(page); } } #define ONLY_IF_CURRENT_TAB if(mainWindow()->m_tabWidget->currentIndex() == -1) { return; } void MainWindowAdaptor::previousPage() { ONLY_IF_CURRENT_TAB mainWindow()->on_previousPage_triggered(); } void MainWindowAdaptor::nextPage() { ONLY_IF_CURRENT_TAB mainWindow()->on_nextPage_triggered(); } void MainWindowAdaptor::firstPage() { ONLY_IF_CURRENT_TAB mainWindow()->on_firstPage_triggered(); } void MainWindowAdaptor::lastPage() { ONLY_IF_CURRENT_TAB mainWindow()->on_lastPage_triggered(); } void MainWindowAdaptor::previousBookmark() { ONLY_IF_CURRENT_TAB mainWindow()->on_previousBookmark_triggered(); } void MainWindowAdaptor::nextBookmark() { ONLY_IF_CURRENT_TAB mainWindow()->on_nextBookmark_triggered(); } bool MainWindowAdaptor::jumpToBookmark(const QString& label) { if(mainWindow()->m_tabWidget->currentIndex() == -1) { return false; } const BookmarkModel* model = mainWindow()->bookmarkModelForCurrentTab(); if(model != 0) { for(int row = 0, rowCount = model->rowCount(); row < rowCount; ++row) { const QModelIndex index = model->index(row); if(label == index.data(BookmarkModel::LabelRole).toString()) { mainWindow()->currentTab()->jumpToPage(index.data(BookmarkModel::PageRole).toInt()); return true; } } } return false; } void MainWindowAdaptor::continuousMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_continuousMode_triggered(checked); } void MainWindowAdaptor::twoPagesMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_twoPagesMode_triggered(checked); } void MainWindowAdaptor::twoPagesWithCoverPageMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_twoPagesWithCoverPageMode_triggered(checked); } void MainWindowAdaptor::multiplePagesMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_multiplePagesMode_triggered(checked); } void MainWindowAdaptor::fitToPageWidthMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_fitToPageWidthMode_triggered(checked); } void MainWindowAdaptor::fitToPageSizeMode(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_fitToPageSizeMode_triggered(checked); } void MainWindowAdaptor::invertColors(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_invertColors_triggered(checked); } void MainWindowAdaptor::convertToGrayscale(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_convertToGrayscale_triggered(checked); } void MainWindowAdaptor::trimMargins(bool checked) { ONLY_IF_CURRENT_TAB mainWindow()->on_trimMargins_triggered(checked); } void MainWindowAdaptor::fullscreen(bool checked) { if(mainWindow()->m_fullscreenAction->isChecked() != checked) { mainWindow()->m_fullscreenAction->trigger(); } } void MainWindowAdaptor::presentation() { ONLY_IF_CURRENT_TAB mainWindow()->on_presentation_triggered(); } void MainWindowAdaptor::closeTab() { ONLY_IF_CURRENT_TAB mainWindow()->on_closeTab_triggered(); } void MainWindowAdaptor::closeAllTabs() { mainWindow()->on_closeAllTabs_triggered(); } void MainWindowAdaptor::closeAllTabsButCurrentTab() { mainWindow()->on_closeAllTabsButCurrentTab_triggered(); } bool MainWindowAdaptor::closeTab(const QString& absoluteFilePath) { if(mainWindow()->m_tabWidget->currentIndex() == -1) { return false; } const QFileInfo fileInfo(absoluteFilePath); foreach(DocumentView* tab, mainWindow()->allTabs()) { if(tab->fileInfo() == fileInfo) { if(mainWindow()->saveModifications(tab)) { mainWindow()->closeTab(tab); } return true; } } return false; } #undef ONLY_IF_CURRENT_TAB inline MainWindow* MainWindowAdaptor::mainWindow() const { return qobject_cast< MainWindow* >(parent()); } QString MainWindowAdaptor::serviceName(QString instanceName) { QString serviceName = QApplication::organizationDomain(); if(instanceName.isNull()) { instanceName = qApp->objectName(); } if(!instanceName.isEmpty()) { serviceName.append('.'); serviceName.append(instanceName); } return serviceName; } # endif // WITH_DBUS } // qpdfview