diff --git a/src/lib/app/browserwindow.cpp b/src/lib/app/browserwindow.cpp index 33979dc3..05135c2c 100644 --- a/src/lib/app/browserwindow.cpp +++ b/src/lib/app/browserwindow.cpp @@ -1,1623 +1,1622 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "browserwindow.h" #include "tabwidget.h" #include "tabbar.h" #include "webpage.h" #include "tabbedwebview.h" #include "lineedit.h" #include "history.h" #include "locationbar.h" #include "websearchbar.h" #include "pluginproxy.h" #include "sidebar.h" #include "downloadmanager.h" #include "cookiejar.h" #include "cookiemanager.h" #include "bookmarkstoolbar.h" #include "clearprivatedata.h" #include "autofill.h" #include "mainapplication.h" #include "checkboxdialog.h" -#include "adblockmanager.h" #include "clickablelabel.h" #include "docktitlebarwidget.h" #include "iconprovider.h" #include "progressbar.h" #include "adblockicon.h" #include "closedwindowsmanager.h" #include "statusbarmessage.h" #include "browsinglibrary.h" #include "navigationbar.h" #include "bookmarksimport/bookmarksimportdialog.h" #include "qztools.h" #include "reloadstopbutton.h" #include "enhancedmenu.h" #include "navigationcontainer.h" #include "settings.h" #include "qzsettings.h" #include "speeddial.h" #include "menubar.h" #include "bookmarkstools.h" #include "bookmarksmenu.h" #include "historymenu.h" #include "mainmenu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef QZ_WS_X11 #include #include #include #endif static const int savedWindowVersion = 2; BrowserWindow::SavedWindow::SavedWindow() { } BrowserWindow::SavedWindow::SavedWindow(BrowserWindow *window) { windowState = window->isFullScreen() ? QByteArray() : window->saveState(); windowGeometry = window->saveGeometry(); windowUiState = window->saveUiState(); #ifdef QZ_WS_X11 virtualDesktop = window->getCurrentVirtualDesktop(); #endif const int tabsCount = window->tabCount(); tabs.reserve(tabsCount); for (int i = 0; i < tabsCount; ++i) { TabbedWebView *webView = window->weView(i); if (!webView) { continue; } WebTab* webTab = webView->webTab(); if (!webTab) { continue; } WebTab::SavedTab tab(webTab); if (!tab.isValid()) { continue; } if (webTab->isCurrentTab()) { currentTab = tabs.size(); } tabs.append(tab); } } bool BrowserWindow::SavedWindow::isValid() const { return currentTab > -1; } void BrowserWindow::SavedWindow::clear() { windowState.clear(); windowGeometry.clear(); virtualDesktop = -1; currentTab = -1; tabs.clear(); } QDataStream &operator<<(QDataStream &stream, const BrowserWindow::SavedWindow &window) { stream << savedWindowVersion; stream << window.windowState; stream << window.windowGeometry; stream << window.virtualDesktop; stream << window.currentTab; stream << window.tabs.count(); for (int i = 0; i < window.tabs.count(); ++i) { stream << window.tabs.at(i); } stream << window.windowUiState; return stream; } QDataStream &operator>>(QDataStream &stream, BrowserWindow::SavedWindow &window) { int version; stream >> version; if (version < 1) { return stream; } stream >> window.windowState; stream >> window.windowGeometry; stream >> window.virtualDesktop; stream >> window.currentTab; int tabsCount = -1; stream >> tabsCount; window.tabs.reserve(tabsCount); for (int i = 0; i < tabsCount; ++i) { WebTab::SavedTab tab; stream >> tab; window.tabs.append(tab); } if (version >= 2) { stream >> window.windowUiState; } return stream; } BrowserWindow::BrowserWindow(Qz::BrowserWindowType type, const QUrl &startUrl) : QMainWindow(0) , m_startUrl(startUrl) , m_windowType(type) , m_startTab(0) , m_startPage(0) , m_sideBarManager(new SideBarManager(this)) , m_statusBarMessage(new StatusBarMessage(this)) , m_isHtmlFullScreen(false) , m_hideNavigationTimer(0) { setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DontCreateNativeAncestors); setObjectName("mainwindow"); setWindowTitle(tr("Falkon")); setProperty("private", mApp->isPrivate()); setupUi(); setupMenu(); m_hideNavigationTimer = new QTimer(this); m_hideNavigationTimer->setInterval(1000); m_hideNavigationTimer->setSingleShot(true); connect(m_hideNavigationTimer, SIGNAL(timeout()), this, SLOT(hideNavigationSlot())); connect(mApp, SIGNAL(settingsReloaded()), this, SLOT(loadSettings())); QTimer::singleShot(0, this, SLOT(postLaunch())); if (mApp->isPrivate()) { QzTools::setWmClass("Falkon Browser (Private Window)", this); } else { QzTools::setWmClass("Falkon Browser", this); } } BrowserWindow::~BrowserWindow() { mApp->plugins()->emitMainWindowDeleted(this); foreach (const QPointer &pointer, m_deleteOnCloseWidgets) { if (pointer) { pointer->deleteLater(); } } } void BrowserWindow::setStartTab(WebTab* tab) { m_startTab = tab; } void BrowserWindow::setStartPage(WebPage *page) { m_startPage = page; } void BrowserWindow::postLaunch() { loadSettings(); bool addTab = true; QUrl startUrl; switch (mApp->afterLaunch()) { case MainApplication::OpenBlankPage: startUrl = QUrl(); break; case MainApplication::OpenSpeedDial: startUrl = QUrl("falkon:speeddial"); break; case MainApplication::OpenHomePage: case MainApplication::RestoreSession: case MainApplication::SelectSession: startUrl = m_homepage; break; default: break; } show(); switch (m_windowType) { case Qz::BW_FirstAppWindow: if (mApp->isStartingAfterCrash()) { addTab = false; startUrl.clear(); // qupzilla:restore needs JavaScript enabled // correct value is then restored in MainApplication::destroyRestoreManager mApp->webSettings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true); m_tabWidget->addView(QUrl("falkon:restore"), Qz::NT_CleanSelectedTabAtTheEnd); } else if (mApp->afterLaunch() == MainApplication::SelectSession || mApp->afterLaunch() == MainApplication::RestoreSession) { addTab = m_tabWidget->count() <= 0; } break; case Qz::BW_NewWindow: case Qz::BW_MacFirstWindow: addTab = true; break; case Qz::BW_OtherRestoredWindow: addTab = false; break; } if (!m_startUrl.isEmpty()) { startUrl = m_startUrl; addTab = true; } if (m_startTab) { addTab = false; m_tabWidget->addView(m_startTab, Qz::NT_SelectedTab); } if (m_startPage) { addTab = false; m_tabWidget->addView(QUrl()); weView()->setPage(m_startPage); } if (addTab) { m_tabWidget->addView(startUrl, Qz::NT_CleanSelectedTabAtTheEnd); if (startUrl.isEmpty() || startUrl.toString() == QLatin1String("falkon:speeddial")) { locationBar()->setFocus(); } } // Something went really wrong .. add one tab if (m_tabWidget->count() <= 0) { m_tabWidget->addView(m_homepage, Qz::NT_SelectedTabAtTheEnd); } mApp->plugins()->emitMainWindowCreated(this); emit startingCompleted(); raise(); activateWindow(); updateStartupFocus(); } void BrowserWindow::setupUi() { Settings settings; settings.beginGroup("Browser-View-Settings"); const QByteArray windowGeometry = settings.value(QSL("WindowGeometry")).toByteArray(); const QStringList keys = { QSL("LocationBarWidth"), QSL("WebSearchBarWidth"), QSL("SideBarWidth"), QSL("WebViewWidth"), QSL("SideBar") }; QHash uiState; for (const QString &key : keys) { if (settings.contains(key)) { uiState[key] = settings.value(key); } } settings.endGroup(); QWidget* widget = new QWidget(this); widget->setCursor(Qt::ArrowCursor); setCentralWidget(widget); m_mainLayout = new QVBoxLayout(widget); m_mainLayout->setContentsMargins(0, 0, 0, 0); m_mainLayout->setSpacing(0); m_mainSplitter = new QSplitter(this); m_mainSplitter->setObjectName("sidebar-splitter"); m_tabWidget = new TabWidget(this); m_superMenu = new QMenu(this); m_navigationToolbar = new NavigationBar(this); m_bookmarksToolbar = new BookmarksToolbar(this); m_navigationContainer = new NavigationContainer(this); m_navigationContainer->addWidget(m_navigationToolbar); m_navigationContainer->addWidget(m_bookmarksToolbar); m_navigationContainer->setTabBar(m_tabWidget->tabBar()); m_mainSplitter->addWidget(m_tabWidget); m_mainSplitter->setCollapsible(0, false); m_mainLayout->addWidget(m_navigationContainer); m_mainLayout->addWidget(m_mainSplitter); statusBar()->setObjectName("mainwindow-statusbar"); statusBar()->setCursor(Qt::ArrowCursor); m_progressBar = new ProgressBar(statusBar()); m_ipLabel = new QLabel(this); m_ipLabel->setObjectName("statusbar-ip-label"); m_ipLabel->setToolTip(tr("IP Address of current page")); statusBar()->addPermanentWidget(m_progressBar); statusBar()->addPermanentWidget(m_ipLabel); m_navigationToolbar->addToolButton(new AdBlockIcon(this)); QDesktopWidget* desktop = mApp->desktop(); int windowWidth = desktop->availableGeometry().width() / 1.3; int windowHeight = desktop->availableGeometry().height() / 1.3; // Let the WM decides where to put new browser window if (m_windowType != Qz::BW_FirstAppWindow && m_windowType != Qz::BW_MacFirstWindow && mApp->getWindow()) { #ifdef Q_WS_WIN // Windows WM places every new window in the middle of screen .. for some reason QPoint p = mApp->getWindow()->geometry().topLeft(); p.setX(p.x() + 30); p.setY(p.y() + 30); if (!desktop->availableGeometry(mApp->getWindow()).contains(p)) { p.setX(desktop->availableGeometry(mApp->getWindow()).x() + 30); p.setY(desktop->availableGeometry(mApp->getWindow()).y() + 30); } setGeometry(QRect(p, mApp->getWindow()->size())); #else resize(mApp->getWindow()->size()); #endif } else if (!restoreGeometry(windowGeometry)) { #ifdef Q_WS_WIN setGeometry(QRect(desktop->availableGeometry(mApp->getWindow()).x() + 30, desktop->availableGeometry(mApp->getWindow()).y() + 30, windowWidth, windowHeight)); #else resize(windowWidth, windowHeight); #endif } // Workaround for Oxygen tooltips not having transparent background QPalette pal = QToolTip::palette(); QColor col = pal.window().color(); col.setAlpha(0); pal.setColor(QPalette::Window, col); QToolTip::setPalette(pal); restoreUiState(uiState); // Set some sane minimum width setMinimumWidth(300); } void BrowserWindow::setupMenu() { #ifdef Q_OS_MACOS static MainMenu* macMainMenu = 0; if (!macMainMenu) { macMainMenu = new MainMenu(this, 0); macMainMenu->initMenuBar(new QMenuBar(0)); connect(mApp, SIGNAL(activeWindowChanged(BrowserWindow*)), macMainMenu, SLOT(setWindow(BrowserWindow*))); } else { macMainMenu->setWindow(this); } m_mainMenu = macMainMenu; #else setMenuBar(new MenuBar(this)); m_mainMenu = new MainMenu(this, this); m_mainMenu->initMenuBar(menuBar()); #endif m_mainMenu->initSuperMenu(m_superMenu); // Setup other shortcuts QShortcut* reloadBypassCacheAction = new QShortcut(QKeySequence(QSL("Ctrl+F5")), this); QShortcut* reloadBypassCacheAction2 = new QShortcut(QKeySequence(QSL("Ctrl+Shift+R")), this); connect(reloadBypassCacheAction, SIGNAL(activated()), this, SLOT(reloadBypassCache())); connect(reloadBypassCacheAction2, SIGNAL(activated()), this, SLOT(reloadBypassCache())); QShortcut* closeTabAction = new QShortcut(QKeySequence(QSL("Ctrl+W")), this); QShortcut* closeTabAction2 = new QShortcut(QKeySequence(QSL("Ctrl+F4")), this); connect(closeTabAction, SIGNAL(activated()), this, SLOT(closeTab())); connect(closeTabAction2, SIGNAL(activated()), this, SLOT(closeTab())); QShortcut* reloadAction = new QShortcut(QKeySequence("Ctrl+R"), this); connect(reloadAction, SIGNAL(activated()), this, SLOT(reload())); QShortcut* openLocationAction = new QShortcut(QKeySequence("Alt+D"), this); connect(openLocationAction, SIGNAL(activated()), this, SLOT(openLocation())); QShortcut* inspectorAction = new QShortcut(QKeySequence(QSL("F12")), this); connect(inspectorAction, SIGNAL(activated()), this, SLOT(toggleWebInspector())); QShortcut* restoreClosedWindow = new QShortcut(QKeySequence(QSL("Ctrl+Shift+N")), this); connect(restoreClosedWindow, &QShortcut::activated, mApp->closedWindowsManager(), &ClosedWindowsManager::restoreClosedWindow); } void BrowserWindow::updateStartupFocus() { QTimer::singleShot(500, this, [this]() { // Scroll to current tab tabWidget()->tabBar()->ensureVisible(); // Update focus if (!m_startPage && LocationBar::convertUrlToText(weView()->page()->requestedUrl()).isEmpty()) locationBar()->setFocus(); else weView()->setFocus(); }); } QAction* BrowserWindow::createEncodingAction(const QString &codecName, const QString &activeCodecName, QMenu* menu) { QAction* action = new QAction(codecName, menu); action->setData(codecName); action->setCheckable(true); connect(action, SIGNAL(triggered()), this, SLOT(changeEncoding())); if (activeCodecName.compare(codecName, Qt::CaseInsensitive) == 0) { action->setChecked(true); } return action; } void BrowserWindow::createEncodingSubMenu(const QString &name, QStringList &codecNames, QMenu* menu) { if (codecNames.isEmpty()) { return; } QCollator collator; collator.setNumericMode(true); std::sort(codecNames.begin(), codecNames.end(), [collator](const QString &a, const QString &b) { return collator.compare(a, b) < 0; }); QMenu* subMenu = new QMenu(name, menu); const QString activeCodecName = mApp->webSettings()->defaultTextEncoding(); QActionGroup *group = new QActionGroup(subMenu); foreach (const QString &codecName, codecNames) { QAction *act = createEncodingAction(codecName, activeCodecName, subMenu); group->addAction(act); subMenu->addAction(act); } menu->addMenu(subMenu); } QHash BrowserWindow::saveUiState() { saveSideBarSettings(); QHash state; state[QSL("LocationBarWidth")] = m_navigationToolbar->splitter()->sizes().at(0); state[QSL("WebSearchBarWidth")] = m_navigationToolbar->splitter()->sizes().at(1); state[QSL("SideBarWidth")] = m_sideBarWidth; state[QSL("WebViewWidth")] = m_webViewWidth; state[QSL("SideBar")] = m_sideBarManager->activeSideBar(); return state; } void BrowserWindow::restoreUiState(const QHash &state) { const int locationBarWidth = state.value(QSL("LocationBarWidth"), 480).toInt(); const int websearchBarWidth = state.value(QSL("WebSearchBarWidth"), 140).toInt(); m_navigationToolbar->setSplitterSizes(locationBarWidth, websearchBarWidth); m_sideBarWidth = state.value(QSL("SideBarWidth"), 250).toInt(); m_webViewWidth = state.value(QSL("WebViewWidth"), 2000).toInt(); if (m_sideBar) { m_mainSplitter->setSizes({m_sideBarWidth, m_webViewWidth}); } const QString activeSideBar = state.value(QSL("SideBar")).toString(); if (activeSideBar.isEmpty() && m_sideBar) { m_sideBar->close(); } else { m_sideBarManager->showSideBar(activeSideBar, false); } } void BrowserWindow::loadSettings() { Settings settings; //Url settings settings.beginGroup("Web-URL-Settings"); m_homepage = settings.value("homepage", "falkon:start").toUrl(); settings.endGroup(); //Browser Window settings settings.beginGroup("Browser-View-Settings"); bool showStatusBar = settings.value("showStatusBar", false).toBool(); bool showBookmarksToolbar = settings.value("showBookmarksToolbar", true).toBool(); bool showNavigationToolbar = settings.value("showNavigationToolbar", true).toBool(); bool showMenuBar = settings.value("showMenubar", false).toBool(); // Make sure both menubar and navigationbar are not hidden // Fixes #781 if (!showNavigationToolbar) { showMenuBar = true; settings.setValue("showMenubar", true); } settings.endGroup(); settings.beginGroup("Shortcuts"); m_useTabNumberShortcuts = settings.value("useTabNumberShortcuts", true).toBool(); m_useSpeedDialNumberShortcuts = settings.value("useSpeedDialNumberShortcuts", true).toBool(); m_useSingleKeyShortcuts = settings.value("useSingleKeyShortcuts", false).toBool(); settings.endGroup(); settings.beginGroup("Web-Browser-Settings"); QAction *quitAction = m_mainMenu->action(QSL("Standard/Quit")); if (settings.value("closeAppWithCtrlQ", true).toBool()) { quitAction->setShortcut(QzTools::actionShortcut(QKeySequence::Quit, QKeySequence(QSL("Ctrl+Q")))); } else { quitAction->setShortcut(QKeySequence()); } settings.endGroup(); statusBar()->setVisible(!isFullScreen() && showStatusBar); m_bookmarksToolbar->setVisible(showBookmarksToolbar); m_navigationToolbar->setVisible(showNavigationToolbar); #ifndef Q_OS_MACOS menuBar()->setVisible(!isFullScreen() && showMenuBar); #endif m_navigationToolbar->setSuperMenuVisible(!showMenuBar); } void BrowserWindow::goForward() { weView()->forward(); } void BrowserWindow::reload() { weView()->reload(); } void BrowserWindow::reloadBypassCache() { weView()->reloadBypassCache(); } void BrowserWindow::goBack() { weView()->back(); } int BrowserWindow::tabCount() const { return m_tabWidget->count(); } TabbedWebView* BrowserWindow::weView() const { return weView(m_tabWidget->currentIndex()); } TabbedWebView* BrowserWindow::weView(int index) const { WebTab* webTab = qobject_cast(m_tabWidget->widget(index)); if (!webTab) { return 0; } return webTab->webView(); } LocationBar* BrowserWindow::locationBar() const { return qobject_cast(m_tabWidget->locationBars()->currentWidget()); } TabWidget* BrowserWindow::tabWidget() const { return m_tabWidget; } BookmarksToolbar* BrowserWindow::bookmarksToolbar() const { return m_bookmarksToolbar; } StatusBarMessage* BrowserWindow::statusBarMessage() const { return m_statusBarMessage; } NavigationBar* BrowserWindow::navigationBar() const { return m_navigationToolbar; } SideBarManager* BrowserWindow::sideBarManager() const { return m_sideBarManager; } QLabel* BrowserWindow::ipLabel() const { return m_ipLabel; } QMenu* BrowserWindow::superMenu() const { return m_superMenu; } QUrl BrowserWindow::homepageUrl() const { return m_homepage; } Qz::BrowserWindowType BrowserWindow::windowType() const { return m_windowType; } QAction* BrowserWindow::action(const QString &name) const { return m_mainMenu->action(name); } void BrowserWindow::setWindowTitle(const QString &t) { QString title = t; if (mApp->isPrivate()) { title.append(tr(" (Private Browsing)")); } QMainWindow::setWindowTitle(title); } void BrowserWindow::changeEncoding() { if (QAction* action = qobject_cast(sender())) { const QString encoding = action->data().toString(); mApp->webSettings()->setDefaultTextEncoding(encoding); Settings settings; settings.setValue("Web-Browser-Settings/DefaultEncoding", encoding); weView()->reload(); } } void BrowserWindow::printPage() { weView()->printPage(); } void BrowserWindow::bookmarkPage() { TabbedWebView* view = weView(); BookmarksTools::addBookmarkDialog(this, view->url(), view->title()); } void BrowserWindow::bookmarkAllTabs() { BookmarksTools::bookmarkAllTabsDialog(this, m_tabWidget); } void BrowserWindow::addBookmark(const QUrl &url, const QString &title) { BookmarksTools::addBookmarkDialog(this, url, title); } void BrowserWindow::goHome() { loadAddress(m_homepage); } void BrowserWindow::goHomeInNewTab() { m_tabWidget->addView(m_homepage, Qz::NT_SelectedTab); } void BrowserWindow::loadActionUrl(QObject* obj) { if (!obj) { obj = sender(); } if (QAction* action = qobject_cast(obj)) { loadAddress(action->data().toUrl()); } } void BrowserWindow::loadActionUrlInNewTab(QObject* obj) { if (!obj) { obj = sender(); } if (QAction* action = qobject_cast(obj)) { m_tabWidget->addView(action->data().toUrl(), Qz::NT_SelectedTabAtTheEnd); } } void BrowserWindow::loadAddress(const QUrl &url) { if (weView()->webTab()->isPinned()) { int index = m_tabWidget->addView(url, qzSettings->newTabPosition); weView(index)->setFocus(); } else { weView()->load(url); weView()->setFocus(); } } void BrowserWindow::showHistoryManager() { mApp->browsingLibrary()->showHistory(this); } void BrowserWindow::showSource(WebView *view) { if (!view) view = weView(); view->showSource(); } void BrowserWindow::showNormal() { if (m_normalWindowState & Qt::WindowMaximized) { QMainWindow::showMaximized(); } else { QMainWindow::showNormal(); } } SideBar* BrowserWindow::addSideBar() { if (m_sideBar) { return m_sideBar.data(); } m_sideBar = new SideBar(m_sideBarManager, this); m_mainSplitter->insertWidget(0, m_sideBar.data()); m_mainSplitter->setCollapsible(0, false); m_mainSplitter->setSizes({m_sideBarWidth, m_webViewWidth}); return m_sideBar.data(); } void BrowserWindow::saveSideBarSettings() { if (m_sideBar) { // That +1 is important here, without it, the sidebar width would // decrease by 1 pixel every close m_sideBarWidth = m_mainSplitter->sizes().at(0) + 1; m_webViewWidth = width() - m_sideBarWidth; } Settings().setValue(QSL("Browser-View-Settings/SideBar"), m_sideBarManager->activeSideBar()); } void BrowserWindow::toggleShowMenubar() { #ifdef Q_OS_MACOS // We use one shared global menubar on Mac that can't be hidden return; #endif setUpdatesEnabled(false); menuBar()->setVisible(!menuBar()->isVisible()); m_navigationToolbar->setSuperMenuVisible(!menuBar()->isVisible()); setUpdatesEnabled(true); Settings().setValue("Browser-View-Settings/showMenubar", menuBar()->isVisible()); // Make sure we show Navigation Toolbar when Menu Bar is hidden if (!m_navigationToolbar->isVisible() && !menuBar()->isVisible()) { toggleShowNavigationToolbar(); } } void BrowserWindow::toggleShowStatusBar() { setUpdatesEnabled(false); statusBar()->setVisible(!statusBar()->isVisible()); setUpdatesEnabled(true); Settings().setValue("Browser-View-Settings/showStatusBar", statusBar()->isVisible()); } void BrowserWindow::toggleShowBookmarksToolbar() { setUpdatesEnabled(false); m_bookmarksToolbar->setVisible(!m_bookmarksToolbar->isVisible()); setUpdatesEnabled(true); Settings().setValue("Browser-View-Settings/showBookmarksToolbar", m_bookmarksToolbar->isVisible()); Settings().setValue("Browser-View-Settings/instantBookmarksToolbar", false); } void BrowserWindow::toggleShowNavigationToolbar() { setUpdatesEnabled(false); m_navigationToolbar->setVisible(!m_navigationToolbar->isVisible()); setUpdatesEnabled(true); Settings().setValue("Browser-View-Settings/showNavigationToolbar", m_navigationToolbar->isVisible()); #ifndef Q_OS_MACOS // Make sure we show Menu Bar when Navigation Toolbar is hidden if (!m_navigationToolbar->isVisible() && !menuBar()->isVisible()) { toggleShowMenubar(); } #endif } void BrowserWindow::toggleTabsOnTop(bool enable) { qzSettings->tabsOnTop = enable; m_navigationContainer->toggleTabsOnTop(enable); } void BrowserWindow::toggleFullScreen() { if (m_isHtmlFullScreen) { weView()->triggerPageAction(QWebEnginePage::ExitFullScreen); return; } if (isFullScreen()) showNormal(); else showFullScreen(); } void BrowserWindow::toggleHtmlFullScreen(bool enable) { if (enable) showFullScreen(); else showNormal(); if (m_sideBar) m_sideBar.data()->setHidden(enable); m_isHtmlFullScreen = enable; } void BrowserWindow::showWebInspector() { if (weView() && weView()->webTab()) { weView()->webTab()->showWebInspector(); } } void BrowserWindow::toggleWebInspector() { if (weView() && weView()->webTab()) { weView()->webTab()->toggleWebInspector(); } } void BrowserWindow::refreshHistory() { m_navigationToolbar->refreshHistory(); } void BrowserWindow::currentTabChanged() { TabbedWebView* view = weView(); if (!view) { return; } setWindowTitle(tr("%1 - Falkon").arg(view->webTab()->title())); m_ipLabel->setText(view->getIp()); view->setFocus(); m_navigationToolbar->setCurrentView(view); updateLoadingActions(); // Setting correct tab order (LocationBar -> WebSearchBar -> WebView) setTabOrder(locationBar(), m_navigationToolbar->webSearchBar()); setTabOrder(m_navigationToolbar->webSearchBar(), view); } void BrowserWindow::updateLoadingActions() { TabbedWebView* view = weView(); if (!view) { return; } bool isLoading = view->isLoading(); m_ipLabel->setVisible(!isLoading); m_progressBar->setVisible(isLoading); action(QSL("View/Stop"))->setEnabled(isLoading); action(QSL("View/Reload"))->setEnabled(!isLoading); if (isLoading) { m_progressBar->setValue(view->loadingProgress()); m_navigationToolbar->showStopButton(); } else { m_navigationToolbar->showReloadButton(); } } void BrowserWindow::addDeleteOnCloseWidget(QWidget* widget) { if (!m_deleteOnCloseWidgets.contains(widget)) { m_deleteOnCloseWidgets.append(widget); } } void BrowserWindow::restoreWindow(const SavedWindow &window) { restoreState(window.windowState); restoreGeometry(window.windowGeometry); restoreUiState(window.windowUiState); #ifdef QZ_WS_X11 moveToVirtualDesktop(window.virtualDesktop); #endif show(); // Window has to be visible before adding QWebEngineView's m_tabWidget->restoreState(window.tabs, window.currentTab); updateStartupFocus(); } void BrowserWindow::createToolbarsMenu(QMenu* menu) { removeActions(menu->actions()); menu->clear(); QAction* action; #ifndef Q_OS_MACOS action = menu->addAction(tr("&Menu Bar"), this, SLOT(toggleShowMenubar())); action->setCheckable(true); action->setChecked(menuBar()->isVisible()); #endif action = menu->addAction(tr("&Navigation Toolbar"), this, SLOT(toggleShowNavigationToolbar())); action->setCheckable(true); action->setChecked(m_navigationToolbar->isVisible()); action = menu->addAction(tr("&Bookmarks Toolbar"), this, SLOT(toggleShowBookmarksToolbar())); action->setCheckable(true); action->setChecked(Settings().value("Browser-View-Settings/showBookmarksToolbar").toBool()); menu->addSeparator(); action = menu->addAction(tr("&Tabs on Top"), this, SLOT(toggleTabsOnTop(bool))); action->setCheckable(true); action->setChecked(qzSettings->tabsOnTop); addActions(menu->actions()); } void BrowserWindow::createSidebarsMenu(QMenu* menu) { m_sideBarManager->createMenu(menu); } void BrowserWindow::createEncodingMenu(QMenu* menu) { const QString activeCodecName = mApp->webSettings()->defaultTextEncoding(); QStringList isoCodecs; QStringList utfCodecs; QStringList windowsCodecs; QStringList isciiCodecs; QStringList ibmCodecs; QStringList otherCodecs; QStringList allCodecs; foreach (const int mib, QTextCodec::availableMibs()) { const QString codecName = QString::fromUtf8(QTextCodec::codecForMib(mib)->name()); if (!allCodecs.contains(codecName)) allCodecs.append(codecName); else continue; if (codecName.startsWith(QLatin1String("ISO"))) isoCodecs.append(codecName); else if (codecName.startsWith(QLatin1String("UTF"))) utfCodecs.append(codecName); else if (codecName.startsWith(QLatin1String("windows"))) windowsCodecs.append(codecName); else if (codecName.startsWith(QLatin1String("Iscii"))) isciiCodecs.append(codecName); else if (codecName.startsWith(QLatin1String("IBM"))) ibmCodecs.append(codecName); else otherCodecs.append(codecName); } if (!menu->isEmpty()) menu->addSeparator(); createEncodingSubMenu("ISO", isoCodecs, menu); createEncodingSubMenu("UTF", utfCodecs, menu); createEncodingSubMenu("Windows", windowsCodecs, menu); createEncodingSubMenu("Iscii", isciiCodecs, menu); createEncodingSubMenu("IBM", ibmCodecs, menu); createEncodingSubMenu(tr("Other"), otherCodecs, menu); } void BrowserWindow::removeActions(const QList &actions) { foreach (QAction *action, actions) { removeAction(action); } } void BrowserWindow::addTab() { m_tabWidget->addView(QUrl(), Qz::NT_SelectedNewEmptyTab, true); m_tabWidget->setCurrentTabFresh(true); if (isFullScreen()) showNavigationWithFullScreen(); } void BrowserWindow::webSearch() { m_navigationToolbar->webSearchBar()->setFocus(); m_navigationToolbar->webSearchBar()->selectAll(); } void BrowserWindow::searchOnPage() { if (weView() && weView()->webTab()) { weView()->webTab()->showSearchToolBar(); } } void BrowserWindow::openFile() { const QString fileTypes = QString("%1(*.html *.htm *.shtml *.shtm *.xhtml);;" "%2(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff);;" "%3(*.txt);;" "%4(*.*)").arg(tr("HTML files"), tr("Image files"), tr("Text files"), tr("All files")); const QString filePath = QzTools::getOpenFileName("MainWindow-openFile", this, tr("Open file..."), QDir::homePath(), fileTypes); if (!filePath.isEmpty()) { loadAddress(QUrl::fromLocalFile(filePath)); } } void BrowserWindow::openLocation() { if (isFullScreen()) { showNavigationWithFullScreen(); } locationBar()->setFocus(); locationBar()->selectAll(); } bool BrowserWindow::fullScreenNavigationVisible() const { return m_navigationContainer->isVisible(); } void BrowserWindow::showNavigationWithFullScreen() { if (m_isHtmlFullScreen) return; if (m_hideNavigationTimer->isActive()) { m_hideNavigationTimer->stop(); } m_navigationContainer->show(); } void BrowserWindow::hideNavigationWithFullScreen() { if (m_tabWidget->isCurrentTabFresh()) return; if (!m_hideNavigationTimer->isActive()) { m_hideNavigationTimer->start(); } } void BrowserWindow::hideNavigationSlot() { TabbedWebView* view = weView(); bool mouseInView = view && view->underMouse(); if (isFullScreen() && mouseInView) { m_navigationContainer->hide(); } } bool BrowserWindow::event(QEvent* event) { switch (event->type()) { case QEvent::WindowStateChange: if (!(m_oldWindowState & Qt::WindowFullScreen) && windowState() & Qt::WindowFullScreen) { // Enter fullscreen m_normalWindowState = m_oldWindowState; m_statusBarVisible = statusBar()->isVisible(); #ifndef Q_OS_MACOS m_menuBarVisible = menuBar()->isVisible(); menuBar()->hide(); #endif statusBar()->hide(); m_navigationContainer->hide(); } else if (m_oldWindowState & Qt::WindowFullScreen && !(windowState() & Qt::WindowFullScreen)) { // Leave fullscreen statusBar()->setVisible(m_statusBarVisible); #ifndef Q_OS_MACOS menuBar()->setVisible(m_menuBarVisible); #endif m_navigationContainer->show(); m_navigationToolbar->setSuperMenuVisible(!m_menuBarVisible); m_isHtmlFullScreen = false; } if (m_hideNavigationTimer) { m_hideNavigationTimer->stop(); } m_oldWindowState = windowState(); break; default: break; } return QMainWindow::event(event); } void BrowserWindow::resizeEvent(QResizeEvent* event) { m_bookmarksToolbar->setMaximumWidth(width()); QMainWindow::resizeEvent(event); } void BrowserWindow::keyPressEvent(QKeyEvent* event) { if (mApp->plugins()->processKeyPress(Qz::ON_BrowserWindow, this, event)) { return; } int number = -1; TabbedWebView* view = weView(); switch (event->key()) { case Qt::Key_Back: if (view) { view->back(); event->accept(); } break; case Qt::Key_Forward: if (view) { view->forward(); event->accept(); } break; case Qt::Key_Stop: if (view) { view->stop(); event->accept(); } break; case Qt::Key_Reload: case Qt::Key_Refresh: if (view) { view->reload(); event->accept(); } break; case Qt::Key_HomePage: goHome(); event->accept(); break; case Qt::Key_Favorites: mApp->browsingLibrary()->showBookmarks(this); event->accept(); break; case Qt::Key_Search: searchOnPage(); event->accept(); break; case Qt::Key_F6: case Qt::Key_OpenUrl: openLocation(); event->accept(); break; case Qt::Key_History: showHistoryManager(); event->accept(); break; case Qt::Key_AddFavorite: bookmarkPage(); event->accept(); break; case Qt::Key_News: action(QSL("Tools/RssReader"))->trigger(); event->accept(); break; case Qt::Key_Tools: action(QSL("Standard/Preferences"))->trigger(); event->accept(); break; case Qt::Key_Tab: if (event->modifiers() == Qt::ControlModifier) { m_tabWidget->nextTab(); event->accept(); } break; case Qt::Key_Backtab: if (event->modifiers() == (Qt::ControlModifier + Qt::ShiftModifier)) { m_tabWidget->previousTab(); event->accept(); } break; case Qt::Key_PageDown: if (event->modifiers() == Qt::ControlModifier) { m_tabWidget->nextTab(); event->accept(); } break; case Qt::Key_PageUp: if (event->modifiers() == Qt::ControlModifier) { m_tabWidget->previousTab(); event->accept(); } break; case Qt::Key_Equal: if (view && event->modifiers() == Qt::ControlModifier) { view->zoomIn(); event->accept(); } break; case Qt::Key_I: if (event->modifiers() == Qt::ControlModifier) { action(QSL("Tools/SiteInfo"))->trigger(); event->accept(); } break; case Qt::Key_U: if (event->modifiers() == Qt::ControlModifier) { action(QSL("View/PageSource"))->trigger(); event->accept(); } break; case Qt::Key_F: if (event->modifiers() == Qt::ControlModifier) { action(QSL("Edit/Find"))->trigger(); event->accept(); } break; case Qt::Key_Slash: if (m_useSingleKeyShortcuts) { action(QSL("Edit/Find"))->trigger(); event->accept(); } break; case Qt::Key_1: number = 1; break; case Qt::Key_2: number = 2; break; case Qt::Key_3: number = 3; break; case Qt::Key_4: number = 4; break; case Qt::Key_5: number = 5; break; case Qt::Key_6: number = 6; break; case Qt::Key_7: number = 7; break; case Qt::Key_8: number = 8; break; case Qt::Key_9: number = 9; break; default: break; } if (number != -1) { if (event->modifiers() & Qt::AltModifier && m_useTabNumberShortcuts) { if (number == 9) { number = m_tabWidget->count(); } m_tabWidget->setCurrentIndex(number - 1); event->accept(); return; } if (event->modifiers() & Qt::ControlModifier && m_useSpeedDialNumberShortcuts) { const QUrl url = mApp->plugins()->speedDial()->urlForShortcut(number - 1); if (url.isValid()) { loadAddress(url); event->accept(); return; } } if (event->modifiers() == Qt::NoModifier && m_useSingleKeyShortcuts) { if (number == 1) m_tabWidget->previousTab(); if (number == 2) m_tabWidget->nextTab(); } } QMainWindow::keyPressEvent(event); } void BrowserWindow::keyReleaseEvent(QKeyEvent* event) { if (mApp->plugins()->processKeyRelease(Qz::ON_BrowserWindow, this, event)) { return; } switch (event->key()) { case Qt::Key_F: if (event->modifiers() == Qt::ControlModifier) { action(QSL("Edit/Find"))->trigger(); event->accept(); } break; default: break; } QMainWindow::keyReleaseEvent(event); } void BrowserWindow::closeEvent(QCloseEvent* event) { if (mApp->isClosing()) { saveSettings(); return; } Settings settings; bool askOnClose = settings.value("Browser-Tabs-Settings/AskOnClosing", true).toBool(); if ((mApp->afterLaunch() == MainApplication::SelectSession || mApp->afterLaunch() == MainApplication::RestoreSession) && mApp->windowCount() == 1) { askOnClose = false; } if (askOnClose && m_tabWidget->normalTabsCount() > 1) { CheckBoxDialog dialog(QMessageBox::Yes | QMessageBox::No, this); dialog.setDefaultButton(QMessageBox::No); //~ singular There is still %n open tab and your session won't be stored.\nAre you sure you want to close this window? //~ plural There are still %n open tabs and your session won't be stored.\nAre you sure you want to close this window? dialog.setText(tr("There are still %n open tabs and your session won't be stored.\nAre you sure you want to close this window?", "", m_tabWidget->count())); dialog.setCheckBoxText(tr("Don't ask again")); dialog.setWindowTitle(tr("There are still open tabs")); dialog.setIcon(QMessageBox::Warning); if (dialog.exec() != QMessageBox::Yes) { event->ignore(); return; } if (dialog.isChecked()) { settings.setValue("Browser-Tabs-Settings/AskOnClosing", false); } } saveSettings(); mApp->closedWindowsManager()->saveWindow(this); #ifndef Q_OS_MACOS if (mApp->windowCount() == 1) mApp->quitApplication(); #endif event->accept(); } void BrowserWindow::closeWindow() { #ifdef Q_OS_MACOS close(); return; #endif if (mApp->windowCount() > 1) { close(); } } void BrowserWindow::saveSettings() { if (mApp->isPrivate()) { return; } Settings settings; settings.beginGroup("Browser-View-Settings"); settings.setValue("WindowGeometry", saveGeometry()); const auto state = saveUiState(); for (auto it = state.constBegin(); it != state.constEnd(); ++it) { settings.setValue(it.key(), it.value()); } settings.endGroup(); } void BrowserWindow::closeTab() { // Don't close pinned tabs with keyboard shortcuts (Ctrl+W, Ctrl+F4) if (weView() && !weView()->webTab()->isPinned()) { m_tabWidget->requestCloseTab(); } } #ifdef QZ_WS_X11 int BrowserWindow::getCurrentVirtualDesktop() const { if (QGuiApplication::platformName() != QL1S("xcb")) return 0; xcb_intern_atom_cookie_t intern_atom; xcb_intern_atom_reply_t *atom_reply = 0; xcb_atom_t atom; xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *reply = 0; uint32_t value; intern_atom = xcb_intern_atom(QX11Info::connection(), false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP"); atom_reply = xcb_intern_atom_reply(QX11Info::connection(), intern_atom, 0); if (!atom_reply) goto error; atom = atom_reply->atom; cookie = xcb_get_property(QX11Info::connection(), false, winId(), atom, XCB_ATOM_CARDINAL, 0, 1); reply = xcb_get_property_reply(QX11Info::connection(), cookie, 0); if (!reply || reply->type != XCB_ATOM_CARDINAL || reply->value_len != 1 || reply->format != sizeof(uint32_t) * 8) goto error; value = *reinterpret_cast(xcb_get_property_value(reply)); free(reply); free(atom_reply); return value; error: free(reply); free(atom_reply); return 0; } void BrowserWindow::moveToVirtualDesktop(int desktopId) { if (QGuiApplication::platformName() != QL1S("xcb")) return; // Don't move when window is already visible or it is first app window if (desktopId < 0 || isVisible() || m_windowType == Qz::BW_FirstAppWindow) return; xcb_intern_atom_cookie_t intern_atom; xcb_intern_atom_reply_t *atom_reply = 0; xcb_atom_t atom; intern_atom = xcb_intern_atom(QX11Info::connection(), false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP"); atom_reply = xcb_intern_atom_reply(QX11Info::connection(), intern_atom, 0); if (!atom_reply) goto error; atom = atom_reply->atom; xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, winId(), atom, XCB_ATOM_CARDINAL, 32, 1, (const void*) &desktopId); error: free(atom_reply); } #endif diff --git a/src/lib/app/mainmenu.cpp b/src/lib/app/mainmenu.cpp index 63ae39cd..1a5d59dc 100644 --- a/src/lib/app/mainmenu.cpp +++ b/src/lib/app/mainmenu.cpp @@ -1,679 +1,672 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2014-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "mainmenu.h" #include "siteinfo.h" #include "tabwidget.h" #include "historymenu.h" #include "aboutdialog.h" #include "preferences.h" #include "iconprovider.h" #include "cookiemanager.h" #include "bookmarksmenu.h" #include "tabbedwebview.h" #include "browserwindow.h" -#include "adblockmanager.h" #include "downloadmanager.h" #include "mainapplication.h" #include "clearprivatedata.h" #include "qzsettings.h" #include "pluginproxy.h" #include "webinspector.h" #include "sessionmanager.h" #include #include #include #include #include #include #ifdef Q_OS_MACOS extern void qt_mac_set_dock_menu(QMenu* menu); #endif MainMenu::MainMenu(BrowserWindow* window, QWidget* parent) : QMenu(parent) , m_window(window) { Q_ASSERT(m_window); init(); } void MainMenu::setWindow(BrowserWindow* window) { Q_ASSERT(window); m_window = window; addActionsToWindow(); } void MainMenu::initMenuBar(QMenuBar* menuBar) const { menuBar->addMenu(m_menuFile); menuBar->addMenu(m_menuEdit); menuBar->addMenu(m_menuView); menuBar->addMenu(m_menuHistory); menuBar->addMenu(m_menuBookmarks); menuBar->addMenu(m_menuTools); menuBar->addMenu(m_menuHelp); } void MainMenu::initSuperMenu(QMenu* superMenu) const { superMenu->addAction(m_actions[QSL("File/NewTab")]); superMenu->addAction(m_actions[QSL("File/NewWindow")]); superMenu->addAction(m_actions[QSL("File/NewPrivateWindow")]); superMenu->addAction(m_actions[QSL("File/OpenFile")]); if (!mApp->isPrivate()) { superMenu->addSeparator(); QMenu* sessionsSubmenu = new QMenu(tr("Sessions")); connect(sessionsSubmenu, SIGNAL(aboutToShow()), mApp->sessionManager(), SLOT(aboutToShowSessionsMenu())); superMenu->addMenu(sessionsSubmenu); superMenu->addAction(m_actions[QSL("File/SessionManager")]); } superMenu->addSeparator(); superMenu->addAction(m_actions[QSL("File/SendLink")]); superMenu->addAction(m_actions[QSL("File/Print")]); superMenu->addSeparator(); superMenu->addAction(m_actions[QSL("Edit/SelectAll")]); superMenu->addAction(m_actions[QSL("Edit/Find")]); superMenu->addSeparator(); superMenu->addAction(m_menuHistory->actions().at(3)); superMenu->addAction(m_menuBookmarks->actions().at(2)); superMenu->addSeparator(); superMenu->addMenu(m_menuView); superMenu->addMenu(m_menuHistory); superMenu->addMenu(m_menuBookmarks); superMenu->addMenu(m_menuTools); superMenu->addMenu(m_menuHelp); superMenu->addSeparator(); superMenu->addAction(m_actions[QSL("Standard/Preferences")]); superMenu->addAction(m_actions[QSL("Standard/About")]); superMenu->addSeparator(); superMenu->addAction(m_actions[QSL("Standard/Quit")]); connect(superMenu, &QMenu::aboutToShow, this, &MainMenu::aboutToShowSuperMenu); } QAction* MainMenu::action(const QString &name) const { Q_ASSERT(m_actions.value(name)); return m_actions.value(name); } void MainMenu::showAboutDialog() { AboutDialog* dialog = new AboutDialog(m_window); dialog->open(); } void MainMenu::showPreferences() { if (!m_preferences) m_preferences = new Preferences(m_window); m_preferences->show(); m_preferences->raise(); m_preferences->activateWindow(); } void MainMenu::quitApplication() { mApp->quitApplication(); } void MainMenu::newTab() { callSlot("addTab"); } void MainMenu::newWindow() { mApp->createWindow(Qz::BW_NewWindow); } void MainMenu::newPrivateWindow() { mApp->startPrivateBrowsing(); } void MainMenu::openLocation() { callSlot("openLocation"); } void MainMenu::openFile() { callSlot("openFile"); } void MainMenu::closeWindow() { callSlot("closeWindow"); } void MainMenu::savePageAs() { if (m_window) { QMetaObject::invokeMethod(m_window->weView(), "savePageAs"); } } void MainMenu::sendLink() { const QUrl mailUrl = QUrl::fromEncoded("mailto:%20?body=" + QUrl::toPercentEncoding(m_window->weView()->url().toEncoded()) + "&subject=" + QUrl::toPercentEncoding(m_window->weView()->title())); QDesktopServices::openUrl(mailUrl); } void MainMenu::printPage() { callSlot("printPage"); } void MainMenu::editUndo() { if (m_window) { m_window->weView()->editUndo(); } } void MainMenu::editRedo() { if (m_window) { m_window->weView()->editRedo(); } } void MainMenu::editCut() { if (m_window) { m_window->weView()->editCut(); } } void MainMenu::editCopy() { if (m_window) { m_window->weView()->editCopy(); } } void MainMenu::editPaste() { if (m_window) { m_window->weView()->editPaste(); } } void MainMenu::editSelectAll() { if (m_window) { m_window->weView()->editSelectAll(); } } void MainMenu::editFind() { callSlot("searchOnPage"); } void MainMenu::showStatusBar() { if (m_window) { m_window->toggleShowStatusBar(); } } void MainMenu::stop() { if (m_window) { m_window->weView()->stop(); } } void MainMenu::reload() { if (m_window) { m_window->weView()->reload(); } } void MainMenu::zoomIn() { if (m_window) { m_window->weView()->zoomIn(); } } void MainMenu::zoomOut() { if (m_window) { m_window->weView()->zoomOut(); } } void MainMenu::zoomReset() { if (m_window) { m_window->weView()->zoomReset(); } } void MainMenu::showPageSource() { callSlot("showSource"); } void MainMenu::showFullScreen() { if (m_window) { m_window->toggleFullScreen(); } } void MainMenu::webSearch() { callSlot("webSearch"); } void MainMenu::showSiteInfo() { if (m_window && SiteInfo::canShowSiteInfo(m_window->weView()->url())) { SiteInfo* info = new SiteInfo(m_window->weView()); info->show(); } } void MainMenu::showDownloadManager() { DownloadManager* m = mApp->downloadManager(); m->show(); m->raise(); } void MainMenu::showCookieManager() { CookieManager* m = new CookieManager(); m->show(); m->raise(); } -void MainMenu::showAdBlockDialog() -{ - AdBlockManager::instance()->showDialog(); -} - void MainMenu::toggleWebInspector() { callSlot("toggleWebInspector"); } void MainMenu::showClearRecentHistoryDialog() { ClearPrivateData* dialog = new ClearPrivateData(m_window); dialog->open(); } void MainMenu::aboutQt() { QApplication::aboutQt(); } void MainMenu::showInfoAboutApp() { if (m_window) { m_window->tabWidget()->addView(QUrl(QSL("falkon:about")), Qz::NT_CleanSelectedTab); } } void MainMenu::showConfigInfo() { if (m_window) { m_window->tabWidget()->addView(QUrl(QSL("falkon:config")), Qz::NT_CleanSelectedTab); } } void MainMenu::reportIssue() { if (m_window) { m_window->tabWidget()->addView(QUrl(QSL("falkon:reportbug")), Qz::NT_CleanSelectedTab); } } void MainMenu::restoreClosedTab() { if (m_window) { m_window->tabWidget()->restoreClosedTab(); } } void MainMenu::aboutToShowFileMenu() { #ifndef Q_OS_MACOS m_actions[QSL("File/CloseWindow")]->setEnabled(mApp->windowCount() > 1); #endif } void MainMenu::aboutToShowViewMenu() { if (!m_window) { return; } m_actions[QSL("View/ShowStatusBar")]->setChecked(m_window->statusBar()->isVisible()); m_actions[QSL("View/FullScreen")]->setChecked(m_window->isFullScreen()); } void MainMenu::aboutToShowEditMenu() { if (!m_window) { return; } WebView* view = m_window->weView(); m_actions[QSL("Edit/Undo")]->setEnabled(view->pageAction(QWebEnginePage::Undo)->isEnabled()); m_actions[QSL("Edit/Redo")]->setEnabled(view->pageAction(QWebEnginePage::Redo)->isEnabled()); m_actions[QSL("Edit/Cut")]->setEnabled(view->pageAction(QWebEnginePage::Cut)->isEnabled()); m_actions[QSL("Edit/Copy")]->setEnabled(view->pageAction(QWebEnginePage::Copy)->isEnabled()); m_actions[QSL("Edit/Paste")]->setEnabled(view->pageAction(QWebEnginePage::Paste)->isEnabled()); m_actions[QSL("Edit/SelectAll")]->setEnabled(view->pageAction(QWebEnginePage::SelectAll)->isEnabled()); } void MainMenu::aboutToShowToolsMenu() { if (!m_window) return; m_actions[QSL("Tools/SiteInfo")]->setEnabled(SiteInfo::canShowSiteInfo(m_window->weView()->url())); m_submenuExtensions->clear(); mApp->plugins()->populateExtensionsMenu(m_submenuExtensions); m_submenuExtensions->menuAction()->setVisible(!m_submenuExtensions->actions().isEmpty()); } void MainMenu::aboutToShowSuperMenu() { if (!m_window) { return; } WebView* view = m_window->weView(); m_actions[QSL("Edit/Find")]->setEnabled(true); m_actions[QSL("Edit/SelectAll")]->setEnabled(view->pageAction(QWebEnginePage::SelectAll)->isEnabled()); } void MainMenu::aboutToShowToolbarsMenu() { QMenu* menu = qobject_cast(sender()); Q_ASSERT(menu); if (m_window) { menu->clear(); m_window->createToolbarsMenu(menu); } } void MainMenu::aboutToShowSidebarsMenu() { QMenu* menu = qobject_cast(sender()); Q_ASSERT(menu); if (m_window) { m_window->createSidebarsMenu(menu); } } void MainMenu::aboutToShowEncodingMenu() { QMenu* menu = qobject_cast(sender()); Q_ASSERT(menu); if (m_window) { menu->clear(); m_window->createEncodingMenu(menu); } } void MainMenu::init() { #define ADD_ACTION(name, menu, icon, trName, slot, shortcut) \ action = menu->addAction(icon, trName); \ action->setShortcut(QKeySequence(QSL(shortcut))); \ connect(action, SIGNAL(triggered()), this, slot); \ m_actions[QSL(name)] = action #define ADD_CHECKABLE_ACTION(name, menu, icon, trName, slot, shortcut) \ action = menu->addAction(icon, trName); \ action->setShortcut(QKeySequence(QSL(shortcut))); \ action->setCheckable(true); \ connect(action, SIGNAL(triggered(bool)), this, slot); \ m_actions[QSL(name)] = action // Standard actions - needed on Mac to be placed correctly in "application" menu QAction* action = new QAction(QIcon::fromTheme(QSL("help-about")), tr("&About Falkon"), this); action->setMenuRole(QAction::AboutRole); connect(action, SIGNAL(triggered()), this, SLOT(showAboutDialog())); m_actions[QSL("Standard/About")] = action; action = new QAction(IconProvider::settingsIcon(), tr("Pr&eferences"), this); action->setMenuRole(QAction::PreferencesRole); action->setShortcut(QKeySequence(QKeySequence::Preferences)); connect(action, SIGNAL(triggered()), this, SLOT(showPreferences())); m_actions[QSL("Standard/Preferences")] = action; action = new QAction(QIcon::fromTheme(QSL("application-exit")), tr("Quit"), this); action->setMenuRole(QAction::QuitRole); // shortcut set from browserwindow connect(action, SIGNAL(triggered()), this, SLOT(quitApplication())); m_actions[QSL("Standard/Quit")] = action; // File menu m_menuFile = new QMenu(tr("&File")); connect(m_menuFile, SIGNAL(aboutToShow()), this, SLOT(aboutToShowFileMenu())); ADD_ACTION("File/NewTab", m_menuFile, IconProvider::newTabIcon(), tr("New Tab"), SLOT(newTab()), "Ctrl+T"); ADD_ACTION("File/NewWindow", m_menuFile, IconProvider::newWindowIcon(), tr("&New Window"), SLOT(newWindow()), "Ctrl+N"); ADD_ACTION("File/NewPrivateWindow", m_menuFile, IconProvider::privateBrowsingIcon(), tr("New &Private Window"), SLOT(newPrivateWindow()), "Ctrl+Shift+P"); ADD_ACTION("File/OpenLocation", m_menuFile, QIcon::fromTheme(QSL("document-open-remote")), tr("Open Location"), SLOT(openLocation()), "Ctrl+L"); ADD_ACTION("File/OpenFile", m_menuFile, QIcon::fromTheme(QSL("document-open")), tr("Open &File..."), SLOT(openFile()), "Ctrl+O"); ADD_ACTION("File/CloseWindow", m_menuFile, QIcon::fromTheme(QSL("window-close")), tr("Close Window"), SLOT(closeWindow()), "Ctrl+Shift+W"); m_menuFile->addSeparator(); if (!mApp->isPrivate()) { QMenu* sessionsSubmenu = new QMenu(tr("Sessions")); connect(sessionsSubmenu, SIGNAL(aboutToShow()), mApp->sessionManager(), SLOT(aboutToShowSessionsMenu())); m_menuFile->addMenu(sessionsSubmenu); action = new QAction(tr("Session Manager"), this); connect(action, SIGNAL(triggered()), mApp->sessionManager(), SLOT(openSessionManagerDialog())); m_actions[QSL("File/SessionManager")] = action; m_menuFile->addAction(action); m_menuFile->addSeparator(); } ADD_ACTION("File/SavePageAs", m_menuFile, QIcon::fromTheme(QSL("document-save")), tr("&Save Page As..."), SLOT(savePageAs()), "Ctrl+S"); ADD_ACTION("File/SendLink", m_menuFile, QIcon::fromTheme(QSL("mail-message-new")), tr("Send Link..."), SLOT(sendLink()), ""); ADD_ACTION("File/Print", m_menuFile, QIcon::fromTheme(QSL("document-print")), tr("&Print..."), SLOT(printPage()), "Ctrl+P"); m_menuFile->addSeparator(); m_menuFile->addAction(m_actions[QSL("Standard/Quit")]); // Edit menu m_menuEdit = new QMenu(tr("&Edit")); connect(m_menuEdit, SIGNAL(aboutToShow()), this, SLOT(aboutToShowEditMenu())); ADD_ACTION("Edit/Undo", m_menuEdit, QIcon::fromTheme(QSL("edit-undo")), tr("&Undo"), SLOT(editUndo()), "Ctrl+Z"); action->setShortcutContext(Qt::WidgetShortcut); ADD_ACTION("Edit/Redo", m_menuEdit, QIcon::fromTheme(QSL("edit-redo")), tr("&Redo"), SLOT(editRedo()), "Ctrl+Shift+Z"); action->setShortcutContext(Qt::WidgetShortcut); m_menuEdit->addSeparator(); ADD_ACTION("Edit/Cut", m_menuEdit, QIcon::fromTheme(QSL("edit-cut")), tr("&Cut"), SLOT(editCut()), "Ctrl+X"); action->setShortcutContext(Qt::WidgetShortcut); ADD_ACTION("Edit/Copy", m_menuEdit, QIcon::fromTheme(QSL("edit-copy")), tr("C&opy"), SLOT(editCopy()), "Ctrl+C"); action->setShortcutContext(Qt::WidgetShortcut); ADD_ACTION("Edit/Paste", m_menuEdit, QIcon::fromTheme(QSL("edit-paste")), tr("&Paste"), SLOT(editPaste()), "Ctrl+V"); action->setShortcutContext(Qt::WidgetShortcut); m_menuEdit->addSeparator(); ADD_ACTION("Edit/SelectAll", m_menuEdit, QIcon::fromTheme(QSL("edit-select-all")), tr("Select &All"), SLOT(editSelectAll()), "Ctrl+A"); action->setShortcutContext(Qt::WidgetShortcut); ADD_ACTION("Edit/Find", m_menuEdit, QIcon::fromTheme(QSL("edit-find")), tr("&Find"), SLOT(editFind()), "Ctrl+F"); action->setShortcutContext(Qt::WidgetShortcut); m_menuEdit->addSeparator(); // View menu m_menuView = new QMenu(tr("&View")); connect(m_menuView, SIGNAL(aboutToShow()), this, SLOT(aboutToShowViewMenu())); QMenu* toolbarsMenu = new QMenu(tr("Toolbars")); connect(toolbarsMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowToolbarsMenu())); QMenu* sidebarMenu = new QMenu(tr("Sidebars")); connect(sidebarMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSidebarsMenu())); QMenu* encodingMenu = new QMenu(tr("Character &Encoding")); connect(encodingMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowEncodingMenu())); // Create menus to make shortcuts available even before first showing the menu m_window->createToolbarsMenu(toolbarsMenu); m_window->createSidebarsMenu(sidebarMenu); m_menuView->addMenu(toolbarsMenu); m_menuView->addMenu(sidebarMenu); ADD_CHECKABLE_ACTION("View/ShowStatusBar", m_menuView, QIcon(), tr("Sta&tus Bar"), SLOT(showStatusBar()), ""); m_menuView->addSeparator(); ADD_ACTION("View/Stop", m_menuView, QIcon::fromTheme(QSL("process-stop")), tr("&Stop"), SLOT(stop()), "Esc"); ADD_ACTION("View/Reload", m_menuView, QIcon::fromTheme(QSL("view-refresh")), tr("&Reload"), SLOT(reload()), "F5"); m_menuView->addSeparator(); ADD_ACTION("View/ZoomIn", m_menuView, QIcon::fromTheme(QSL("zoom-in")), tr("Zoom &In"), SLOT(zoomIn()), "Ctrl++"); ADD_ACTION("View/ZoomOut", m_menuView, QIcon::fromTheme(QSL("zoom-out")), tr("Zoom &Out"), SLOT(zoomOut()), "Ctrl+-"); ADD_ACTION("View/ZoomReset", m_menuView, QIcon::fromTheme(QSL("zoom-original")), tr("Reset"), SLOT(zoomReset()), "Ctrl+0"); m_menuView->addSeparator(); m_menuView->addMenu(encodingMenu); m_menuView->addSeparator(); ADD_ACTION("View/PageSource", m_menuView, QIcon::fromTheme(QSL("text-html")), tr("&Page Source"), SLOT(showPageSource()), "Ctrl+U"); action->setShortcutContext(Qt::WidgetShortcut); ADD_CHECKABLE_ACTION("View/FullScreen", m_menuView, QIcon(), tr("&FullScreen"), SLOT(showFullScreen()), "F11"); // Tools menu m_menuTools = new QMenu(tr("&Tools")); connect(m_menuTools, SIGNAL(aboutToShow()), this, SLOT(aboutToShowToolsMenu())); ADD_ACTION("Tools/WebSearch", m_menuTools, QIcon(), tr("&Web Search"), SLOT(webSearch()), "Ctrl+K"); ADD_ACTION("Tools/SiteInfo", m_menuTools, QIcon::fromTheme(QSL("dialog-information")), tr("Site &Info"), SLOT(showSiteInfo()), "Ctrl+I"); action->setShortcutContext(Qt::WidgetShortcut); m_menuTools->addSeparator(); ADD_ACTION("Tools/DownloadManager", m_menuTools, QIcon(), tr("&Download Manager"), SLOT(showDownloadManager()), "Ctrl+Y"); ADD_ACTION("Tools/CookiesManager", m_menuTools, QIcon(), tr("&Cookies Manager"), SLOT(showCookieManager()), ""); - ADD_ACTION("Tools/AdBlock", m_menuTools, QIcon(), tr("&AdBlock"), SLOT(showAdBlockDialog()), ""); ADD_ACTION("Tools/WebInspector", m_menuTools, QIcon(), tr("Web In&spector"), SLOT(toggleWebInspector()), "Ctrl+Shift+I"); ADD_ACTION("Tools/ClearRecentHistory", m_menuTools, QIcon::fromTheme(QSL("edit-clear")), tr("Clear Recent &History"), SLOT(showClearRecentHistoryDialog()), "Ctrl+Shift+Del"); if (!WebInspector::isEnabled()) m_actions.value(QSL("Tools/WebInspector"))->setVisible(false); m_submenuExtensions = new QMenu(tr("&Extensions")); m_submenuExtensions->menuAction()->setVisible(false); m_menuTools->addMenu(m_submenuExtensions); m_menuTools->addSeparator(); // Help menu m_menuHelp = new QMenu(tr("&Help")); #ifndef Q_OS_MACOS ADD_ACTION("Help/AboutQt", m_menuHelp, QIcon(), tr("About &Qt"), SLOT(aboutQt()), ""); m_menuHelp->addAction(m_actions[QSL("Standard/About")]); m_menuHelp->addSeparator(); #endif ADD_ACTION("Help/InfoAboutApp", m_menuHelp, QIcon::fromTheme(QSL("help-contents")), tr("Information about application"), SLOT(showInfoAboutApp()), ""); ADD_ACTION("Help/ConfigInfo", m_menuHelp, QIcon(), tr("Configuration Information"), SLOT(showConfigInfo()), ""); ADD_ACTION("Help/ReportIssue", m_menuHelp, QIcon(), tr("Report &Issue"), SLOT(reportIssue()), ""); m_actions[QSL("Help/InfoAboutApp")]->setShortcut(QKeySequence(QKeySequence::HelpContents)); // History menu m_menuHistory = new HistoryMenu(); m_menuHistory->setMainWindow(m_window); // Bookmarks menu m_menuBookmarks = new BookmarksMenu(); m_menuBookmarks->setMainWindow(m_window); // Other actions action = new QAction(QIcon::fromTheme(QSL("user-trash")), tr("Restore &Closed Tab"), this); action->setShortcut(QKeySequence(QSL("Ctrl+Shift+T"))); connect(action, SIGNAL(triggered()), this, SLOT(restoreClosedTab())); m_actions[QSL("Other/RestoreClosedTab")] = action; #ifdef Q_OS_MACOS m_actions[QSL("View/FullScreen")]->setShortcut(QKeySequence(QSL("Ctrl+Meta+F"))); // Add standard actions to File Menu (as it won't be ever cleared) and Mac menubar should move them to "Application" menu m_menuFile->addAction(m_actions[QSL("Standard/About")]); m_menuFile->addAction(m_actions[QSL("Standard/Preferences")]); // Prevent ConfigInfo action to be detected as "Preferences..." action in Mac menubar m_actions[QSL("Help/ConfigInfo")]->setMenuRole(QAction::NoRole); // Create Dock menu QMenu* dockMenu = new QMenu(0); dockMenu->addAction(m_actions[QSL("File/NewTab")]); dockMenu->addAction(m_actions[QSL("File/NewWindow")]); dockMenu->addAction(m_actions[QSL("File/NewPrivateWindow")]); qt_mac_set_dock_menu(dockMenu); #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) m_menuEdit->addAction(m_actions[QSL("Standard/Preferences")]); #elif !defined(Q_OS_MACOS) m_menuTools->addAction(m_actions[QSL("Standard/Preferences")]); #endif addActionsToWindow(); } void MainMenu::addActionsToWindow() { // Make shortcuts available even in fullscreen (hidden menu) QList actions; actions << m_menuFile->actions(); actions << m_menuEdit->actions(); actions << m_menuView->actions(); actions << m_menuTools->actions(); actions << m_menuHelp->actions(); actions << m_menuHistory->actions(); actions << m_menuBookmarks->actions(); actions << m_actions[QSL("Other/RestoreClosedTab")]; for (int i = 0; i < actions.size(); ++i) { QAction* action = actions.at(i); if (action->menu()) { actions += action->menu()->actions(); } m_window->addAction(action); } } void MainMenu::callSlot(const char* slot) { if (m_window) { QMetaObject::invokeMethod(m_window, slot); } } diff --git a/src/lib/app/mainmenu.h b/src/lib/app/mainmenu.h index a5dc7f7f..eed2e7b3 100644 --- a/src/lib/app/mainmenu.h +++ b/src/lib/app/mainmenu.h @@ -1,133 +1,132 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2014-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #ifndef MAINMENU_H #define MAINMENU_H #include #include #include #include "qzcommon.h" class QMenuBar; class Preferences; class HistoryMenu; class BookmarksMenu; class BrowserWindow; class FALKON_EXPORT MainMenu : public QMenu { Q_OBJECT public: explicit MainMenu(BrowserWindow* window, QWidget* parent = 0); void initMenuBar(QMenuBar* menuBar) const; void initSuperMenu(QMenu* superMenu) const; QAction* action(const QString &name) const; public slots: void setWindow(BrowserWindow* window); private slots: // Standard actions void showAboutDialog(); void showPreferences(); void quitApplication(); // File menu void newTab(); void newWindow(); void newPrivateWindow(); void openLocation(); void openFile(); void closeWindow(); void savePageAs(); void sendLink(); void printPage(); // Edit menu void editUndo(); void editRedo(); void editCut(); void editCopy(); void editPaste(); void editSelectAll(); void editFind(); // View menu void showStatusBar(); void stop(); void reload(); void zoomIn(); void zoomOut(); void zoomReset(); void showPageSource(); void showFullScreen(); // Tools menu void webSearch(); void showSiteInfo(); void showDownloadManager(); void showCookieManager(); - void showAdBlockDialog(); void toggleWebInspector(); void showClearRecentHistoryDialog(); // Help menu void aboutQt(); void showInfoAboutApp(); void showConfigInfo(); void reportIssue(); // Other actions void restoreClosedTab(); void aboutToShowFileMenu(); void aboutToShowViewMenu(); void aboutToShowEditMenu(); void aboutToShowToolsMenu(); void aboutToShowSuperMenu(); void aboutToShowToolbarsMenu(); void aboutToShowSidebarsMenu(); void aboutToShowEncodingMenu(); private: void init(); void addActionsToWindow(); void callSlot(const char* slot); QHash m_actions; QPointer m_window; QPointer m_preferences; QMenu* m_menuFile; QMenu* m_menuEdit; QMenu* m_menuView; QMenu* m_menuTools; QMenu* m_menuHelp; QMenu* m_submenuExtensions; HistoryMenu* m_menuHistory; BookmarksMenu* m_menuBookmarks; }; #endif // MAINMENU_H