File indexing completed on 2024-05-19 04:59:00

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "popupwindow.h"
0019 #include "popupwebview.h"
0020 #include "webpage.h"
0021 #include "popupstatusbarmessage.h"
0022 #include "progressbar.h"
0023 #include "searchtoolbar.h"
0024 #include "qzsettings.h"
0025 #include "popuplocationbar.h"
0026 #include "qztools.h"
0027 #include "mainapplication.h"
0028 #include "browserwindow.h"
0029 
0030 #include <QVBoxLayout>
0031 #include <QStatusBar>
0032 #include <QCloseEvent>
0033 #include <QMenuBar>
0034 
0035 PopupWindow::PopupWindow(PopupWebView* view)
0036     : QWidget()
0037     , m_view(view)
0038     , m_search(nullptr)
0039 {
0040     m_layout = new QVBoxLayout(this);
0041     m_layout->setContentsMargins(0, 0, 0, 0);
0042     m_layout->setSpacing(0);
0043 
0044     m_locationBar = new PopupLocationBar(this);
0045     m_locationBar->setView(m_view);
0046 
0047     auto *locationWidget = new QWidget(this);
0048     auto *llayout = new QVBoxLayout();
0049     llayout->setContentsMargins(3, 3, 3, 5);
0050     llayout->addWidget(m_locationBar);
0051     locationWidget->setLayout(llayout);
0052 
0053     m_statusBar = new QStatusBar(this);
0054     m_statusBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
0055 
0056     m_progressBar = new ProgressBar(m_statusBar);
0057     m_statusBar->addPermanentWidget(m_progressBar);
0058     m_progressBar->hide();
0059 
0060     m_view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0061     m_statusBarMessage = new PopupStatusBarMessage(this);
0062 
0063     m_notificationWidget = new QWidget(this);
0064     m_notificationWidget->setAutoFillBackground(true);
0065     QPalette pal = m_notificationWidget->palette();
0066     pal.setColor(QPalette::Window, pal.window().color().darker(110));
0067     m_notificationWidget->setPalette(pal);
0068 
0069     auto *nlayout = new QVBoxLayout(m_notificationWidget);
0070     nlayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
0071     nlayout->setContentsMargins(0, 0, 0, 0);
0072     nlayout->setSpacing(1);
0073 
0074     auto *viewSpacer = new QWidget(this);
0075     pal = viewSpacer->palette();
0076     pal.setColor(QPalette::Window, pal.window().color().darker(125));
0077     viewSpacer->setPalette(pal);
0078     viewSpacer->setFixedHeight(1);
0079     viewSpacer->setAutoFillBackground(true);
0080 
0081     m_menuBar = new QMenuBar(this);
0082 
0083     auto* menuFile = new QMenu(tr("File"));
0084     menuFile->addAction(QIcon::fromTheme(QSL("mail-message-new")), tr("Send Link..."), m_view, &WebView::sendPageByMail);
0085     menuFile->addAction(QIcon::fromTheme(QSL("document-print")), tr("&Print..."), m_view, &WebView::printPage)->setShortcut(QKeySequence(QSL("Ctrl+P")));
0086     menuFile->addSeparator();
0087     menuFile->addAction(QIcon::fromTheme(QSL("window-close")), tr("Close"), this, &QWidget::close)->setShortcut(QKeySequence(QSL("Ctrl+W")));
0088     m_menuBar->addMenu(menuFile);
0089 
0090     m_menuEdit = new QMenu(tr("Edit"));
0091     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Undo));
0092     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Redo));
0093     m_menuEdit->addSeparator();
0094     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Cut));
0095     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Copy));
0096     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Paste));
0097     m_menuEdit->addSeparator();
0098     m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::SelectAll));
0099     m_menuEdit->addAction(QIcon::fromTheme(QSL("edit-find")), tr("Find"), this, &PopupWindow::searchOnPage)->setShortcut(QKeySequence(QSL("Ctrl+F")));
0100     m_menuBar->addMenu(m_menuEdit);
0101 
0102     m_menuView = new QMenu(tr("View"));
0103     m_actionStop = m_menuView->addAction(QIcon::fromTheme(QSL("process-stop")), tr("&Stop"), m_view, &QWebEngineView::stop);
0104     m_actionStop->setShortcut(QKeySequence(QSL("Esc")));
0105     m_actionReload = m_menuView->addAction(QIcon::fromTheme(QSL("view-refresh")), tr("&Reload"), m_view, &QWebEngineView::reload);
0106     m_actionReload->setShortcut(QKeySequence(QSL("F5")));
0107     m_menuView->addSeparator();
0108     m_menuView->addAction(QIcon::fromTheme(QSL("zoom-in")), tr("Zoom &In"), m_view, &WebView::zoomIn)->setShortcut(QKeySequence(QSL("Ctrl++")));
0109     m_menuView->addAction(QIcon::fromTheme(QSL("zoom-out")), tr("Zoom &Out"), m_view, &WebView::zoomOut)->setShortcut(QKeySequence(QSL("Ctrl+-")));
0110     m_menuView->addAction(QIcon::fromTheme(QSL("zoom-original")), tr("Reset"), m_view, &WebView::zoomReset)->setShortcut(QKeySequence(QSL("Ctrl+0")));
0111     m_menuView->addSeparator();
0112     m_menuView->addAction(QIcon::fromTheme(QSL("text-html")), tr("&Page Source"), m_view, &WebView::showSource)->setShortcut(QKeySequence(QSL("Ctrl+U")));
0113     m_menuBar->addMenu(m_menuView);
0114 
0115     // Make shortcuts available even with hidden menubar
0116     QList<QAction*> actions = m_menuBar->actions();
0117     for (QAction* action : std::as_const(actions)) {
0118         if (action->menu()) {
0119             actions += action->menu()->actions();
0120         }
0121         addAction(action);
0122     }
0123 
0124     auto *l = new QVBoxLayout();
0125     l->setContentsMargins(0, 0, 0, 0);
0126     l->setSpacing(0);
0127     l->addWidget(m_view);
0128 
0129     auto *viewWidget = new QWidget(this);
0130     viewWidget->setLayout(l);
0131 
0132     m_layout->insertWidget(0, m_menuBar);
0133     m_layout->addWidget(locationWidget);
0134     m_layout->addWidget(viewSpacer);
0135     m_layout->addWidget(viewWidget);
0136     m_layout->addWidget(m_statusBar);
0137     setLayout(m_layout);
0138 
0139     connect(m_view, &WebView::showNotification, this, &PopupWindow::showNotification);
0140     connect(m_view, &WebView::titleChanged, this, &PopupWindow::titleChanged);
0141     connect(m_view, &WebView::urlChanged, m_locationBar, &PopupLocationBar::showUrl);
0142     connect(m_view, &WebView::iconChanged, m_locationBar, &PopupLocationBar::showSiteIcon);
0143     connect(m_view, &WebView::loadStarted, this, &PopupWindow::loadStarted);
0144     connect(m_view, &WebView::loadProgress, this, &PopupWindow::loadProgress);
0145     connect(m_view, &WebView::loadFinished, this, &PopupWindow::loadFinished);
0146     connect(m_view, &WebView::privacyChanged, m_locationBar, &PopupLocationBar::setPrivacyState);
0147 
0148     auto pageChanged = [this](WebPage *page) {
0149         connect(page, &WebPage::linkHovered, this, &PopupWindow::showStatusBarMessage);
0150         connect(page, &WebPage::geometryChangeRequested, this, &PopupWindow::setWindowGeometry);
0151     };
0152     pageChanged(m_view->page());
0153     connect(m_view, &WebView::pageChanged, this, pageChanged);
0154 
0155     m_view->setFocus();
0156     titleChanged();
0157 
0158     QUrl urlToShow = m_view->url();
0159     if (urlToShow.isEmpty()) {
0160         urlToShow = m_view->page()->requestedUrl();
0161     }
0162 
0163     m_locationBar->showUrl(urlToShow);
0164 
0165     if (mApp->getWindow()) {
0166         m_statusBar->setVisible(mApp->getWindow()->statusBar()->isVisible());
0167         m_menuBar->setVisible(mApp->getWindow()->menuBar()->isVisible());
0168 
0169         if (m_menuBar->isHidden())
0170             m_layout->setContentsMargins(0, 2, 0, 0);
0171     }
0172 
0173     // Ensuring correct sizes for widgets in layout are calculated even
0174     // before calling QWidget::show()
0175     m_layout->invalidate();
0176     m_layout->activate();
0177 }
0178 
0179 QStatusBar* PopupWindow::statusBar()
0180 {
0181     return m_statusBar;
0182 }
0183 
0184 PopupWebView* PopupWindow::webView()
0185 {
0186     return m_view;
0187 }
0188 
0189 void PopupWindow::showNotification(QWidget* notif)
0190 {
0191     m_notificationWidget->setParent(nullptr);
0192     m_notificationWidget->setParent(m_view->overlayWidget());
0193     m_notificationWidget->setFixedWidth(m_view->width());
0194     m_notificationWidget->layout()->addWidget(notif);
0195     m_notificationWidget->show();
0196     notif->show();
0197 }
0198 
0199 void PopupWindow::showStatusBarMessage(const QString &message)
0200 {
0201     if (message.isEmpty()) {
0202         m_statusBarMessage->clearMessage();
0203     }
0204     else {
0205         m_statusBarMessage->showMessage(message);
0206     }
0207 }
0208 
0209 void PopupWindow::loadStarted()
0210 {
0211     m_progressBar->setValue(0);
0212     m_progressBar->show();
0213 
0214     m_locationBar->startLoading();
0215 
0216     if (m_actionStop) {
0217         m_actionStop->setEnabled(true);
0218         m_actionReload->setEnabled(false);
0219     }
0220 }
0221 
0222 void PopupWindow::loadProgress(int value)
0223 {
0224     m_progressBar->setValue(value);
0225 }
0226 
0227 void PopupWindow::loadFinished()
0228 {
0229     m_progressBar->hide();
0230 
0231     m_locationBar->stopLoading();
0232 
0233     if (m_actionStop) {
0234         m_actionStop->setEnabled(false);
0235         m_actionReload->setEnabled(true);
0236     }
0237 }
0238 
0239 void PopupWindow::closeEvent(QCloseEvent* event)
0240 {
0241     if (m_view->page()->isRunningLoop()) {
0242         event->ignore();
0243         return;
0244     }
0245 
0246     m_view->deleteLater();
0247 
0248     event->accept();
0249 }
0250 
0251 void PopupWindow::resizeEvent(QResizeEvent *event)
0252 {
0253     QWidget::resizeEvent(event);
0254 
0255     m_notificationWidget->setFixedWidth(m_view->width());
0256 }
0257 
0258 void PopupWindow::searchOnPage()
0259 {
0260     if (!m_search) {
0261         m_search = new SearchToolBar(m_view, this);
0262         m_search.data()->showMinimalInPopupWindow();
0263         m_layout->insertWidget(m_layout->count() - 1, m_search);
0264     }
0265 
0266     m_search->focusSearchLine();
0267 }
0268 
0269 void PopupWindow::titleChanged()
0270 {
0271     setWindowTitle(tr("%1 - Falkon").arg(m_view->title()));
0272 }
0273 
0274 void PopupWindow::setWindowGeometry(QRect newRect)
0275 {
0276     if (!Settings().value(QSL("allowJavaScriptGeometryChange"), true).toBool())
0277         return;
0278 
0279     // left/top was set while width/height not
0280     if (!newRect.topLeft().isNull() && newRect.size().isNull()) {
0281         newRect.setSize(QSize(550, 585));
0282     }
0283 
0284     if (newRect.isValid()) {
0285         QRect oldRect = rect();
0286         move(newRect.topLeft());
0287 
0288         QSize newSize = newRect.size();
0289         int additionalHeight = height() - m_view->height();
0290         newSize.setHeight(newSize.height() + additionalHeight);
0291         resize(newSize);
0292 
0293         if (newRect.topLeft() == QPoint(0, 0) && oldRect.topLeft() == QPoint(0, 0)) {
0294             QzTools::centerWidgetOnScreen(this);
0295         }
0296     }
0297 }