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 }