Falkon Develop
Cross-platform Qt-based web browser
popupwindow.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "popupwindow.h"
19#include "popupwebview.h"
20#include "webpage.h"
22#include "progressbar.h"
23#include "searchtoolbar.h"
24#include "qzsettings.h"
25#include "popuplocationbar.h"
26#include "qztools.h"
27#include "mainapplication.h"
28#include "browserwindow.h"
29
30#include <QVBoxLayout>
31#include <QStatusBar>
32#include <QCloseEvent>
33#include <QMenuBar>
34
36 : QWidget()
37 , m_view(view)
38 , m_search(nullptr)
39{
40 m_layout = new QVBoxLayout(this);
41 m_layout->setContentsMargins(0, 0, 0, 0);
42 m_layout->setSpacing(0);
43
44 m_locationBar = new PopupLocationBar(this);
45 m_locationBar->setView(m_view);
46
47 auto *locationWidget = new QWidget(this);
48 auto *llayout = new QVBoxLayout();
49 llayout->setContentsMargins(3, 3, 3, 5);
50 llayout->addWidget(m_locationBar);
51 locationWidget->setLayout(llayout);
52
53 m_statusBar = new QStatusBar(this);
54 m_statusBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
55
56 m_progressBar = new ProgressBar(m_statusBar);
57 m_statusBar->addPermanentWidget(m_progressBar);
58 m_progressBar->hide();
59
60 m_view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
61 m_statusBarMessage = new PopupStatusBarMessage(this);
62
63 m_notificationWidget = new QWidget(this);
64 m_notificationWidget->setAutoFillBackground(true);
65 QPalette pal = m_notificationWidget->palette();
66 pal.setColor(QPalette::Window, pal.window().color().darker(110));
67 m_notificationWidget->setPalette(pal);
68
69 auto *nlayout = new QVBoxLayout(m_notificationWidget);
70 nlayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
71 nlayout->setContentsMargins(0, 0, 0, 0);
72 nlayout->setSpacing(1);
73
74 auto *viewSpacer = new QWidget(this);
75 pal = viewSpacer->palette();
76 pal.setColor(QPalette::Window, pal.window().color().darker(125));
77 viewSpacer->setPalette(pal);
78 viewSpacer->setFixedHeight(1);
79 viewSpacer->setAutoFillBackground(true);
80
81 m_menuBar = new QMenuBar(this);
82
83 auto* menuFile = new QMenu(tr("File"));
84 menuFile->addAction(QIcon::fromTheme(QSL("mail-message-new")), tr("Send Link..."), m_view, &WebView::sendPageByMail);
85 menuFile->addAction(QIcon::fromTheme(QSL("document-print")), tr("&Print..."), m_view, &WebView::printPage)->setShortcut(QKeySequence(QSL("Ctrl+P")));
86 menuFile->addSeparator();
87 menuFile->addAction(QIcon::fromTheme(QSL("window-close")), tr("Close"), this, &QWidget::close)->setShortcut(QKeySequence(QSL("Ctrl+W")));
88 m_menuBar->addMenu(menuFile);
89
90 m_menuEdit = new QMenu(tr("Edit"));
91 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Undo));
92 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Redo));
93 m_menuEdit->addSeparator();
94 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Cut));
95 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Copy));
96 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::Paste));
97 m_menuEdit->addSeparator();
98 m_menuEdit->addAction(m_view->pageAction(QWebEnginePage::SelectAll));
99 m_menuEdit->addAction(QIcon::fromTheme(QSL("edit-find")), tr("Find"), this, &PopupWindow::searchOnPage)->setShortcut(QKeySequence(QSL("Ctrl+F")));
100 m_menuBar->addMenu(m_menuEdit);
101
102 m_menuView = new QMenu(tr("View"));
103 m_actionStop = m_menuView->addAction(QIcon::fromTheme(QSL("process-stop")), tr("&Stop"), m_view, &QWebEngineView::stop);
104 m_actionStop->setShortcut(QKeySequence(QSL("Esc")));
105 m_actionReload = m_menuView->addAction(QIcon::fromTheme(QSL("view-refresh")), tr("&Reload"), m_view, &QWebEngineView::reload);
106 m_actionReload->setShortcut(QKeySequence(QSL("F5")));
107 m_menuView->addSeparator();
108 m_menuView->addAction(QIcon::fromTheme(QSL("zoom-in")), tr("Zoom &In"), m_view, &WebView::zoomIn)->setShortcut(QKeySequence(QSL("Ctrl++")));
109 m_menuView->addAction(QIcon::fromTheme(QSL("zoom-out")), tr("Zoom &Out"), m_view, &WebView::zoomOut)->setShortcut(QKeySequence(QSL("Ctrl+-")));
110 m_menuView->addAction(QIcon::fromTheme(QSL("zoom-original")), tr("Reset"), m_view, &WebView::zoomReset)->setShortcut(QKeySequence(QSL("Ctrl+0")));
111 m_menuView->addSeparator();
112 m_menuView->addAction(QIcon::fromTheme(QSL("text-html")), tr("&Page Source"), m_view, &WebView::showSource)->setShortcut(QKeySequence(QSL("Ctrl+U")));
113 m_menuBar->addMenu(m_menuView);
114
115 // Make shortcuts available even with hidden menubar
116 QList<QAction*> actions = m_menuBar->actions();
117 for (QAction* action : std::as_const(actions)) {
118 if (action->menu()) {
119 actions += action->menu()->actions();
120 }
121 addAction(action);
122 }
123
124 auto *l = new QVBoxLayout();
125 l->setContentsMargins(0, 0, 0, 0);
126 l->setSpacing(0);
127 l->addWidget(m_view);
128
129 auto *viewWidget = new QWidget(this);
130 viewWidget->setLayout(l);
131
132 m_layout->insertWidget(0, m_menuBar);
133 m_layout->addWidget(locationWidget);
134 m_layout->addWidget(viewSpacer);
135 m_layout->addWidget(viewWidget);
136 m_layout->addWidget(m_statusBar);
137 setLayout(m_layout);
138
139 connect(m_view, &WebView::showNotification, this, &PopupWindow::showNotification);
140 connect(m_view, &WebView::titleChanged, this, &PopupWindow::titleChanged);
141 connect(m_view, &WebView::urlChanged, m_locationBar, &PopupLocationBar::showUrl);
142 connect(m_view, &WebView::iconChanged, m_locationBar, &PopupLocationBar::showSiteIcon);
143 connect(m_view, &WebView::loadStarted, this, &PopupWindow::loadStarted);
144 connect(m_view, &WebView::loadProgress, this, &PopupWindow::loadProgress);
145 connect(m_view, &WebView::loadFinished, this, &PopupWindow::loadFinished);
146 connect(m_view, &WebView::privacyChanged, m_locationBar, &PopupLocationBar::setPrivacyState);
147
148 auto pageChanged = [this](WebPage *page) {
149 connect(page, &WebPage::linkHovered, this, &PopupWindow::showStatusBarMessage);
150 connect(page, &WebPage::geometryChangeRequested, this, &PopupWindow::setWindowGeometry);
151 };
152 pageChanged(m_view->page());
153 connect(m_view, &WebView::pageChanged, this, pageChanged);
154
155 m_view->setFocus();
156 titleChanged();
157
158 QUrl urlToShow = m_view->url();
159 if (urlToShow.isEmpty()) {
160 urlToShow = m_view->page()->requestedUrl();
161 }
162
163 m_locationBar->showUrl(urlToShow);
164
165 if (mApp->getWindow()) {
166 m_statusBar->setVisible(mApp->getWindow()->statusBar()->isVisible());
167 m_menuBar->setVisible(mApp->getWindow()->menuBar()->isVisible());
168
169 if (m_menuBar->isHidden())
170 m_layout->setContentsMargins(0, 2, 0, 0);
171 }
172
173 // Ensuring correct sizes for widgets in layout are calculated even
174 // before calling QWidget::show()
175 m_layout->invalidate();
176 m_layout->activate();
177}
178
180{
181 return m_statusBar;
182}
183
185{
186 return m_view;
187}
188
189void PopupWindow::showNotification(QWidget* notif)
190{
191 m_notificationWidget->setParent(nullptr);
192 m_notificationWidget->setParent(m_view->overlayWidget());
193 m_notificationWidget->setFixedWidth(m_view->width());
194 m_notificationWidget->layout()->addWidget(notif);
195 m_notificationWidget->show();
196 notif->show();
197}
198
199void PopupWindow::showStatusBarMessage(const QString &message)
200{
201 if (message.isEmpty()) {
202 m_statusBarMessage->clearMessage();
203 }
204 else {
205 m_statusBarMessage->showMessage(message);
206 }
207}
208
209void PopupWindow::loadStarted()
210{
211 m_progressBar->setValue(0);
212 m_progressBar->show();
213
214 m_locationBar->startLoading();
215
216 if (m_actionStop) {
217 m_actionStop->setEnabled(true);
218 m_actionReload->setEnabled(false);
219 }
220}
221
222void PopupWindow::loadProgress(int value)
223{
224 m_progressBar->setValue(value);
225}
226
227void PopupWindow::loadFinished()
228{
229 m_progressBar->hide();
230
231 m_locationBar->stopLoading();
232
233 if (m_actionStop) {
234 m_actionStop->setEnabled(false);
235 m_actionReload->setEnabled(true);
236 }
237}
238
239void PopupWindow::closeEvent(QCloseEvent* event)
240{
241 if (m_view->page()->isRunningLoop()) {
242 event->ignore();
243 return;
244 }
245
246 m_view->deleteLater();
247
248 event->accept();
249}
250
251void PopupWindow::resizeEvent(QResizeEvent *event)
252{
253 QWidget::resizeEvent(event);
254
255 m_notificationWidget->setFixedWidth(m_view->width());
256}
257
258void PopupWindow::searchOnPage()
259{
260 if (!m_search) {
261 m_search = new SearchToolBar(m_view, this);
262 m_search.data()->showMinimalInPopupWindow();
263 m_layout->insertWidget(m_layout->count() - 1, m_search);
264 }
265
266 m_search->focusSearchLine();
267}
268
269void PopupWindow::titleChanged()
270{
271 setWindowTitle(tr("%1 - Falkon").arg(m_view->title()));
272}
273
275{
276 if (!Settings().value(QSL("allowJavaScriptGeometryChange"), true).toBool())
277 return;
278
279 // left/top was set while width/height not
280 if (!newRect.topLeft().isNull() && newRect.size().isNull()) {
281 newRect.setSize(QSize(550, 585));
282 }
283
284 if (newRect.isValid()) {
285 QRect oldRect = rect();
286 move(newRect.topLeft());
287
288 QSize newSize = newRect.size();
289 int additionalHeight = height() - m_view->height();
290 newSize.setHeight(newSize.height() + additionalHeight);
291 resize(newSize);
292
293 if (newRect.topLeft() == QPoint(0, 0) && oldRect.topLeft() == QPoint(0, 0)) {
295 }
296 }
297}
void showUrl(const QUrl &url)
void setPrivacyState(bool state)
void setView(PopupWebView *view)
void showMessage(const QString &message)
QWidget * overlayWidget() override
void setWindowGeometry(QRect newRect)
PopupWindow(PopupWebView *view)
Definition: popupwindow.cpp:35
QStatusBar * statusBar()
PopupWebView * webView()
void setValue(int value)
Definition: progressbar.cpp:32
static void centerWidgetOnScreen(QWidget *w)
Definition: qztools.cpp:116
bool isRunningLoop()
Definition: webpage.cpp:205
void showNotification(QWidget *)
WebPage * page() const
Definition: webview.cpp:132
void printPage()
Definition: webview.cpp:385
void zoomReset()
Definition: webview.cpp:314
void sendPageByMail()
Definition: webview.cpp:485
void zoomIn()
Definition: webview.cpp:298
void pageChanged(WebPage *page)
void privacyChanged(bool)
void zoomOut()
Definition: webview.cpp:306
QString title(bool allowEmpty=false) const
Definition: webview.cpp:107
void showSource()
Definition: webview.cpp:548
#define mApp
int value(const QColor &c)
Definition: colors.cpp:238
#define QSL(x)
Definition: qzcommon.h:40