Falkon Develop
Cross-platform Qt-based web browser
browserwindow.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 "browserwindow.h"
19#include "tabwidget.h"
20#include "tabbar.h"
21#include "webpage.h"
22#include "tabbedwebview.h"
23#include "lineedit.h"
24#include "history.h"
25#include "locationbar.h"
26#include "websearchbar.h"
27#include "pluginproxy.h"
28#include "sidebar.h"
29#include "cookiejar.h"
30#include "cookiemanager.h"
31#include "bookmarkstoolbar.h"
32#include "clearprivatedata.h"
33#include "autofill.h"
34#include "mainapplication.h"
35#include "checkboxdialog.h"
36#include "clickablelabel.h"
37#include "docktitlebarwidget.h"
38#include "iconprovider.h"
39#include "progressbar.h"
41#include "statusbar.h"
42#include "browsinglibrary.h"
43#include "navigationbar.h"
45#include "qztools.h"
46#include "reloadstopbutton.h"
47#include "enhancedmenu.h"
48#include "navigationcontainer.h"
49#include "settings.h"
50#include "qzsettings.h"
51#include "speeddial.h"
52#include "menubar.h"
53#include "bookmarkstools.h"
54#include "bookmarksmenu.h"
55#include "historymenu.h"
56#include "mainmenu.h"
57#include "downloadsbutton.h"
58#include "tabmodel.h"
59#include "tabmrumodel.h"
60
61#include <algorithm>
62
63#include <QKeyEvent>
64#include <QSplitter>
65#include <QMenuBar>
66#include <QTimer>
67#include <QShortcut>
68#include <QStackedWidget>
69#include <QTextCodec>
70#include <QFileDialog>
71#include <QDesktopServices>
72#include <QWebEngineHistory>
73#include <QWebEngineSettings>
74#include <QMessageBox>
75#include <QToolTip>
76#include <QScrollArea>
77#include <QCollator>
78#include <QTemporaryFile>
79#include <QActionGroup>
80
81#ifdef QZ_WS_X11
82#include <xcb/xcb.h>
83#include <xcb/xcb_atom.h>
84#endif
85
86static const int savedWindowVersion = 2;
87
89= default;
90
92{
93 windowState = window->isFullScreen() ? QByteArray() : window->saveState();
94 windowGeometry = window->saveGeometry();
95 windowUiState = window->saveUiState();
96#ifdef QZ_WS_X11
97 virtualDesktop = window->getCurrentVirtualDesktop();
98#endif
99
100 const int tabsCount = window->tabCount();
101 tabs.reserve(tabsCount);
102 for (int i = 0; i < tabsCount; ++i) {
103 TabbedWebView *webView = window->weView(i);
104 if (!webView) {
105 continue;
106 }
107 WebTab* webTab = webView->webTab();
108 if (!webTab) {
109 continue;
110 }
111 WebTab::SavedTab tab(webTab);
112 if (!tab.isValid()) {
113 continue;
114 }
115 if (webTab->isCurrentTab()) {
116 currentTab = tabs.size();
117 }
118 tabs.append(tab);
119 }
120}
121
123{
124 for (const WebTab::SavedTab &tab : std::as_const(tabs)) {
125 if (!tab.isValid()) {
126 return false;
127 }
128 }
129 return currentTab > -1;
130}
131
133{
134 windowState.clear();
135 windowGeometry.clear();
136 virtualDesktop = -1;
137 currentTab = -1;
138 tabs.clear();
139}
140
141QDataStream &operator<<(QDataStream &stream, const BrowserWindow::SavedWindow &window)
142{
143 stream << savedWindowVersion;
144 stream << window.windowState;
145 stream << window.windowGeometry;
146 stream << window.virtualDesktop;
147 stream << window.currentTab;
148 stream << static_cast<int>(window.tabs.count());
149
150 for (int i = 0; i < window.tabs.count(); ++i) {
151 stream << window.tabs.at(i);
152 }
153
154 stream << window.windowUiState;
155
156 return stream;
157}
158
159QDataStream &operator>>(QDataStream &stream, BrowserWindow::SavedWindow &window)
160{
161 int version;
162 stream >> version;
163
164 if (version < 1) {
165 return stream;
166 }
167
168 stream >> window.windowState;
169 stream >> window.windowGeometry;
170 stream >> window.virtualDesktop;
171 stream >> window.currentTab;
172
173 int tabsCount = -1;
174 stream >> tabsCount;
175 window.tabs.reserve(tabsCount);
176
177 for (int i = 0; i < tabsCount; ++i) {
179 stream >> tab;
180 window.tabs.append(tab);
181 }
182
183 if (version >= 2) {
184 stream >> window.windowUiState;
185 }
186
187 return stream;
188}
189
191 : QMainWindow(nullptr)
192 , m_startUrl(startUrl)
193 , m_windowType(type)
194 , m_startTab(nullptr)
195 , m_startPage(nullptr)
196 , m_sideBarManager(new SideBarManager(this))
197 , m_hideNavigationTimer(nullptr)
198{
199 setAttribute(Qt::WA_DeleteOnClose);
200 setAttribute(Qt::WA_DontCreateNativeAncestors);
201
202 setObjectName(QSL("mainwindow"));
203 setWindowTitle(tr("Falkon"));
204 setProperty("private", mApp->isPrivate());
205
206 setupUi();
207 setupMenu();
208
209 m_hideNavigationTimer = new QTimer(this);
210 m_hideNavigationTimer->setInterval(1000);
211 m_hideNavigationTimer->setSingleShot(true);
212 connect(m_hideNavigationTimer, &QTimer::timeout, this, &BrowserWindow::hideNavigationSlot);
213
214 connect(mApp, &MainApplication::settingsReloaded, this, &BrowserWindow::loadSettings);
215
216 QTimer::singleShot(0, this, &BrowserWindow::postLaunch);
217
218 if (mApp->isPrivate()) {
219 QzTools::setWmClass(QSL("Falkon Browser (Private Window)"), this);
220 }
221 else {
222 QzTools::setWmClass(QSL("Falkon Browser"), this);
223 }
224}
225
227{
228 mApp->plugins()->emitMainWindowDeleted(this);
229
230 for (const QPointer<QWidget> &pointer : std::as_const(m_deleteOnCloseWidgets)) {
231 if (pointer) {
232 pointer->deleteLater();
233 }
234 }
235}
236
238{
239 m_startTab = tab;
240}
241
243{
244 m_startPage = page;
245}
246
247void BrowserWindow::postLaunch()
248{
249 loadSettings();
250
251 bool addTab = true;
252 QUrl startUrl;
253
254 switch (mApp->afterLaunch()) {
256 startUrl = QUrl();
257 break;
258
260 startUrl = QUrl(QSL("falkon:speeddial"));
261 break;
262
266 startUrl = m_homepage;
267 break;
268
269 default:
270 break;
271 }
272
273 if (!mApp->isTestModeEnabled()) {
274 show();
275 }
276
277 switch (m_windowType) {
279 if (mApp->isStartingAfterCrash()) {
280 addTab = false;
281 startUrl.clear();
282 m_tabWidget->addView(QUrl(QSL("falkon:restore")), Qz::NT_CleanSelectedTabAtTheEnd);
283 }
284 else if (mApp->afterLaunch() == MainApplication::SelectSession || mApp->afterLaunch() == MainApplication::RestoreSession) {
285 addTab = m_tabWidget->count() <= 0;
286 }
287 break;
288
289 case Qz::BW_NewWindow:
291 addTab = true;
292 break;
293
295 addTab = false;
296 break;
297 }
298
299 if (!m_startUrl.isEmpty()) {
300 startUrl = m_startUrl;
301 addTab = true;
302 }
303
304 if (m_startTab) {
305 addTab = false;
306 m_tabWidget->addView(m_startTab, Qz::NT_SelectedTab);
307 }
308
309 if (m_startPage) {
310 addTab = false;
311 m_tabWidget->addView(QUrl());
312 weView()->setPage(m_startPage);
313 }
314
315 if (addTab) {
316 m_tabWidget->addView(startUrl, Qz::NT_CleanSelectedTabAtTheEnd);
317
318 if (startUrl.isEmpty() || startUrl.toString() == QLatin1String("falkon:speeddial")) {
319 locationBar()->setFocus();
320 }
321 }
322
323 // Something went really wrong .. add one tab
324 if (m_tabWidget->count() <= 0) {
325 m_tabWidget->addView(m_homepage, Qz::NT_SelectedTabAtTheEnd);
326 }
327
328 mApp->plugins()->emitMainWindowCreated(this);
329 Q_EMIT startingCompleted();
330
331 raise();
332 activateWindow();
333 updateStartupFocus();
334}
335
336void BrowserWindow::setupUi()
337{
338 Settings settings;
339 settings.beginGroup(QSL("Browser-View-Settings"));
340 const QByteArray windowGeometry = settings.value(QSL("WindowGeometry")).toByteArray();
341
342 const QStringList keys = {
343 QSL("LocationBarWidth"),
344 QSL("WebSearchBarWidth"),
345 QSL("SideBarWidth"),
346 QSL("WebViewWidth"),
347 QSL("SideBar")
348 };
349 QHash<QString, QVariant> uiState;
350 for (const QString &key : keys) {
351 if (settings.contains(key)) {
352 uiState[key] = settings.value(key);
353 }
354 }
355 settings.endGroup();
356
357 auto* widget = new QWidget(this);
358 widget->setCursor(Qt::ArrowCursor);
359 setCentralWidget(widget);
360
361 m_mainLayout = new QVBoxLayout(widget);
362 m_mainLayout->setContentsMargins(0, 0, 0, 0);
363 m_mainLayout->setSpacing(0);
364 m_mainSplitter = new QSplitter(this);
365 m_mainSplitter->setObjectName(QSL("sidebar-splitter"));
366 m_tabWidget = new TabWidget(this);
367 m_superMenu = new QMenu(this);
368 m_navigationToolbar = new NavigationBar(this);
369 m_bookmarksToolbar = new BookmarksToolbar(this);
370
371 m_tabModel = new TabModel(this, this);
372 m_tabMruModel = new TabMruModel(this, this);
373 m_tabMruModel->setSourceModel(m_tabModel);
374
375 m_navigationContainer = new NavigationContainer(this);
376 m_navigationContainer->addWidget(m_navigationToolbar);
377 m_navigationContainer->addWidget(m_bookmarksToolbar);
378 m_navigationContainer->setTabBar(m_tabWidget->tabBar());
379
380 m_mainSplitter->addWidget(m_tabWidget);
381 m_mainSplitter->setCollapsible(0, false);
382
383 m_mainLayout->addWidget(m_navigationContainer);
384 m_mainLayout->addWidget(m_mainSplitter);
385
386 m_statusBar = new StatusBar(this);
387 m_statusBar->setObjectName(QSL("mainwindow-statusbar"));
388 m_statusBar->setCursor(Qt::ArrowCursor);
389 setStatusBar(m_statusBar);
390 m_progressBar = new ProgressBar(m_statusBar);
391 m_ipLabel = new QLabel(this);
392 m_ipLabel->setObjectName(QSL("statusbar-ip-label"));
393 m_ipLabel->setToolTip(tr("IP Address of current page"));
394
395 m_statusBar->addPermanentWidget(m_progressBar);
396 m_statusBar->addPermanentWidget(m_ipLabel);
397
398 auto *downloadsButton = new DownloadsButton(this);
399 m_statusBar->addButton(downloadsButton);
400 m_navigationToolbar->addToolButton(downloadsButton);
401
402 auto desktop = QGuiApplication::primaryScreen();
403 int windowWidth = desktop->availableGeometry().width() / 1.3;
404 int windowHeight = desktop->availableGeometry().height() / 1.3;
405
406 // Let the WM decides where to put new browser window
407 if (m_windowType != Qz::BW_FirstAppWindow && m_windowType != Qz::BW_MacFirstWindow && mApp->getWindow()) {
408#ifdef Q_WS_WIN
409 // Windows WM places every new window in the middle of screen .. for some reason
410 QPoint p = mApp->getWindow()->geometry().topLeft();
411 p.setX(p.x() + 30);
412 p.setY(p.y() + 30);
413
414 if (!desktop->availableGeometry(mApp->getWindow()).contains(p)) {
415 p.setX(desktop->availableGeometry(mApp->getWindow()).x() + 30);
416 p.setY(desktop->availableGeometry(mApp->getWindow()).y() + 30);
417 }
418
419 setGeometry(QRect(p, mApp->getWindow()->size()));
420#else
421 resize(mApp->getWindow()->size());
422#endif
423 } else if (!restoreGeometry(windowGeometry)) {
424#ifdef Q_WS_WIN
425 setGeometry(QRect(desktop->availableGeometry(mApp->getWindow()).x() + 30,
426 desktop->availableGeometry(mApp->getWindow()).y() + 30, windowWidth, windowHeight));
427#else
428 resize(windowWidth, windowHeight);
429#endif
430 }
431
432 restoreUiState(uiState);
433
434 // Set some sane minimum width
435 setMinimumWidth(300);
436}
437
438void BrowserWindow::setupMenu()
439{
440#ifdef Q_OS_MACOS
441 static MainMenu* macMainMenu = 0;
442
443 if (!macMainMenu) {
444 macMainMenu = new MainMenu(this, 0);
445 macMainMenu->initMenuBar(new QMenuBar(0));
446 connect(mApp, SIGNAL(activeWindowChanged(BrowserWindow*)), macMainMenu, SLOT(setWindow(BrowserWindow*)));
447 }
448 else {
449 macMainMenu->setWindow(this);
450 }
451
452 m_mainMenu = macMainMenu;
453#else
454 setMenuBar(new MenuBar(this));
455
456 m_mainMenu = new MainMenu(this, this);
457 m_mainMenu->initMenuBar(menuBar());
458#endif
459 m_mainMenu->initSuperMenu(m_superMenu);
460
461 // Setup other shortcuts
462 auto* reloadBypassCacheAction = new QShortcut(QKeySequence(QSL("Ctrl+F5")), this);
463 auto* reloadBypassCacheAction2 = new QShortcut(QKeySequence(QSL("Ctrl+Shift+R")), this);
464 connect(reloadBypassCacheAction, &QShortcut::activated, this, &BrowserWindow::reloadBypassCache);
465 connect(reloadBypassCacheAction2, &QShortcut::activated, this, &BrowserWindow::reloadBypassCache);
466
467 auto* closeTabAction = new QShortcut(QKeySequence(QSL("Ctrl+W")), this);
468 auto* closeTabAction2 = new QShortcut(QKeySequence(QSL("Ctrl+F4")), this);
469 connect(closeTabAction, &QShortcut::activated, this, &BrowserWindow::closeTab);
470 connect(closeTabAction2, &QShortcut::activated, this, &BrowserWindow::closeTab);
471
472 auto* reloadAction = new QShortcut(QKeySequence(QSL("Ctrl+R")), this);
473 connect(reloadAction, &QShortcut::activated, this, &BrowserWindow::reload);
474
475 auto* openLocationAction = new QShortcut(QKeySequence(QSL("Alt+D")), this);
476 connect(openLocationAction, &QShortcut::activated, this, &BrowserWindow::openLocation);
477
478 auto* inspectorAction = new QShortcut(QKeySequence(QSL("F12")), this);
479 connect(inspectorAction, &QShortcut::activated, this, &BrowserWindow::toggleWebInspector);
480
481 auto* restoreClosedWindow = new QShortcut(QKeySequence(QSL("Ctrl+Shift+N")), this);
482 connect(restoreClosedWindow, &QShortcut::activated, mApp->closedWindowsManager(), &ClosedWindowsManager::restoreClosedWindow);
483}
484
485void BrowserWindow::updateStartupFocus()
486{
487 QTimer::singleShot(500, this, [this]() {
488 // Scroll to current tab
490 // Update focus
491 if (!m_startPage && LocationBar::convertUrlToText(weView()->page()->requestedUrl()).isEmpty())
492 locationBar()->setFocus();
493 else
494 weView()->setFocus();
495 });
496}
497
498QAction* BrowserWindow::createEncodingAction(const QString &codecName,
499 const QString &activeCodecName, QMenu* menu)
500{
501 auto* action = new QAction(codecName, menu);
502 action->setData(codecName);
503 action->setCheckable(true);
504 connect(action, &QAction::triggered, this, &BrowserWindow::changeEncoding);
505 if (activeCodecName.compare(codecName, Qt::CaseInsensitive) == 0) {
506 action->setChecked(true);
507 }
508 return action;
509}
510
511void BrowserWindow::createEncodingSubMenu(const QString &name, QStringList &codecNames, QMenu* menu)
512{
513 if (codecNames.isEmpty()) {
514 return;
515 }
516
517 QCollator collator;
518 collator.setNumericMode(true);
519 std::sort(codecNames.begin(), codecNames.end(), [collator](const QString &a, const QString &b) {
520 return collator.compare(a, b) < 0;
521 });
522
523 auto* subMenu = new QMenu(name, menu);
524 const QString activeCodecName = mApp->webSettings()->defaultTextEncoding();
525
526 auto *group = new QActionGroup(subMenu);
527
528 for (const QString &codecName : std::as_const(codecNames)) {
529 QAction *act = createEncodingAction(codecName, activeCodecName, subMenu);
530 group->addAction(act);
531 subMenu->addAction(act);
532 }
533
534 menu->addMenu(subMenu);
535}
536
537QHash<QString, QVariant> BrowserWindow::saveUiState()
538{
540
541 QHash<QString, QVariant> state;
542 state[QSL("LocationBarWidth")] = m_navigationToolbar->splitter()->sizes().at(0);
543 state[QSL("WebSearchBarWidth")] = m_navigationToolbar->splitter()->sizes().at(1);
544 state[QSL("SideBarWidth")] = m_sideBarWidth;
545 state[QSL("WebViewWidth")] = m_webViewWidth;
546 state[QSL("SideBar")] = m_sideBarManager->activeSideBar();
547 return state;
548}
549
550void BrowserWindow::restoreUiState(const QHash<QString, QVariant> &state)
551{
552 const int locationBarWidth = state.value(QSL("LocationBarWidth"), 480).toInt();
553 const int websearchBarWidth = state.value(QSL("WebSearchBarWidth"), 140).toInt();
554 m_navigationToolbar->setSplitterSizes(locationBarWidth, websearchBarWidth);
555
556 m_sideBarWidth = state.value(QSL("SideBarWidth"), 250).toInt();
557 m_webViewWidth = state.value(QSL("WebViewWidth"), 2000).toInt();
558 if (m_sideBar) {
559 m_mainSplitter->setSizes({m_sideBarWidth, m_webViewWidth});
560 }
561
562 const QString activeSideBar = state.value(QSL("SideBar")).toString();
563 if (activeSideBar.isEmpty() && m_sideBar) {
564 m_sideBar->close();
565 } else {
566 m_sideBarManager->showSideBar(activeSideBar, false);
567 }
568}
569
570void BrowserWindow::loadSettings()
571{
572 Settings settings;
573
574 //Url settings
575 settings.beginGroup(QSL("Web-URL-Settings"));
576 m_homepage = settings.value(QSL("homepage"), QSL("falkon:start")).toUrl();
577 settings.endGroup();
578
579 //Browser Window settings
580 settings.beginGroup(QSL("Browser-View-Settings"));
581 bool showStatusBar = settings.value(QSL("showStatusBar"), false).toBool();
582 bool showBookmarksToolbar = settings.value(QSL("showBookmarksToolbar"), false).toBool();
583 bool showNavigationToolbar = settings.value(QSL("showNavigationToolbar"), true).toBool();
584 bool showMenuBar = settings.value(QSL("showMenubar"), false).toBool();
585
586 // Make sure both menubar and navigationbar are not hidden
587 // Fixes #781
588 if (!showNavigationToolbar) {
589 showMenuBar = true;
590 settings.setValue(QSL("showMenubar"), true);
591 }
592
593 settings.endGroup();
594
595 settings.beginGroup(QSL("Shortcuts"));
596 m_useTabNumberShortcuts = settings.value(QSL("useTabNumberShortcuts"), true).toBool();
597 m_useSpeedDialNumberShortcuts = settings.value(QSL("useSpeedDialNumberShortcuts"), true).toBool();
598 m_useSingleKeyShortcuts = settings.value(QSL("useSingleKeyShortcuts"), false).toBool();
599 settings.endGroup();
600
601 settings.beginGroup(QSL("Web-Browser-Settings"));
602 QAction *quitAction = m_mainMenu->action(QSL("Standard/Quit"));
603 if (settings.value(QSL("closeAppWithCtrlQ"), true).toBool()) {
604 quitAction->setShortcut(QzTools::actionShortcut(QKeySequence::Quit, QKeySequence(QSL("Ctrl+Q"))));
605 } else {
606 quitAction->setShortcut(QKeySequence());
607 }
608 settings.endGroup();
609
610 m_statusBarVisible = showStatusBar;
611 statusBar()->setVisible(!isFullScreen() && showStatusBar);
612 m_bookmarksToolbar->setVisible(showBookmarksToolbar);
613 m_navigationToolbar->setVisible(showNavigationToolbar);
614
615#ifndef Q_OS_MACOS
616 m_menuBarVisible = showMenuBar;
617 menuBar()->setVisible(!isFullScreen() && showMenuBar);
618#endif
619
620 m_navigationToolbar->setSuperMenuVisible(isFullScreen() || !showMenuBar);
621}
622
624{
625 weView()->forward();
626}
627
629{
630 weView()->reload();
631}
632
634{
636}
637
639{
640 weView()->back();
641}
642
644{
645 return m_tabWidget->count();
646}
647
649{
650 return weView(m_tabWidget->currentIndex());
651}
652
654{
655 auto* webTab = qobject_cast<WebTab*>(m_tabWidget->widget(index));
656 if (!webTab) {
657 return nullptr;
658 }
659
660 return webTab->webView();
661}
662
664{
665 return qobject_cast<LocationBar*>(m_tabWidget->locationBars()->currentWidget());
666}
667
669{
670 return m_tabWidget;
671}
672
674{
675 return m_bookmarksToolbar;
676}
677
679{
680 return m_statusBar;
681}
682
684{
685 return m_navigationToolbar;
686}
687
689{
690 return m_sideBarManager;
691}
692
694{
695 return m_ipLabel;
696}
697
699{
700 return m_superMenu;
701}
702
704{
705 return m_homepage;
706}
707
709{
710 return m_windowType;
711}
712
713QAction* BrowserWindow::action(const QString &name) const
714{
715 return m_mainMenu->action(name);
716}
717
719{
720 return m_tabModel;
721}
722
724{
725 return m_tabMruModel;
726}
727
729{
730 QString title = t;
731
732 if (mApp->isPrivate()) {
733 title.append(tr(" (Private Browsing)"));
734 }
735
736 QMainWindow::setWindowTitle(title);
737}
738
739void BrowserWindow::changeEncoding()
740{
741 if (auto* action = qobject_cast<QAction*>(sender())) {
742 const QString encoding = action->data().toString();
743 mApp->webSettings()->setDefaultTextEncoding(encoding);
744
745 Settings settings;
746 settings.setValue(QSL("Web-Browser-Settings/DefaultEncoding"), encoding);
747
748 weView()->reload();
749 }
750}
751
752void BrowserWindow::printPage()
753{
754 weView()->printPage();
755}
756
758{
759 TabbedWebView* view = weView();
760 BookmarksTools::addBookmarkDialog(this, view->url(), view->title());
761}
762
764{
765 BookmarksTools::bookmarkAllTabsDialog(this, m_tabWidget);
766}
767
768void BrowserWindow::addBookmark(const QUrl &url, const QString &title)
769{
770 BookmarksTools::addBookmarkDialog(this, url, title);
771}
772
774{
775 loadAddress(m_homepage);
776}
777
779{
780 m_tabWidget->addView(m_homepage, Qz::NT_SelectedTab);
781}
782
784{
785 if (!obj) {
786 obj = sender();
787 }
788
789 if (auto* action = qobject_cast<QAction*>(obj)) {
790 loadAddress(action->data().toUrl());
791 }
792}
793
795{
796 if (!obj) {
797 obj = sender();
798 }
799
800 if (auto* action = qobject_cast<QAction*>(obj)) {
801 m_tabWidget->addView(action->data().toUrl(), Qz::NT_SelectedTabAtTheEnd);
802 }
803}
804
805void BrowserWindow::loadAddress(const QUrl &url)
806{
807 if (weView()->webTab()->isPinned()) {
808 int index = m_tabWidget->addView(url, qzSettings->newTabPosition);
809 weView(index)->setFocus();
810 } else {
811 weView()->setFocus();
812 weView()->load(LoadRequest(url));
813 }
814}
815
817{
818 mApp->browsingLibrary()->showHistory(this);
819}
820
822{
823 if (!view)
824 view = weView();
825 view->showSource();
826}
827
829{
830 if (m_sideBar) {
831 return m_sideBar.data();
832 }
833
834 m_sideBar = new SideBar(m_sideBarManager, this);
835
836 m_mainSplitter->insertWidget(0, m_sideBar.data());
837 m_mainSplitter->setCollapsible(0, false);
838 m_mainSplitter->setSizes({m_sideBarWidth, m_webViewWidth});
839
840 return m_sideBar.data();
841}
842
844{
845 if (m_sideBar) {
846 // That +1 is important here, without it, the sidebar width would
847 // decrease by 1 pixel every close
848 m_sideBarWidth = m_mainSplitter->sizes().at(0) + 1;
849 m_webViewWidth = width() - m_sideBarWidth;
850 }
851
852 Settings().setValue(QSL("Browser-View-Settings/SideBar"), m_sideBarManager->activeSideBar());
853}
854
856{
857#ifdef Q_OS_MACOS
858 // We use one shared global menubar on Mac that can't be hidden
859 return;
860#endif
861
862 setUpdatesEnabled(false);
863
864 menuBar()->setVisible(!menuBar()->isVisible());
865 m_navigationToolbar->setSuperMenuVisible(!menuBar()->isVisible());
866
867 setUpdatesEnabled(true);
868
869 Settings().setValue(QSL("Browser-View-Settings/showMenubar"), menuBar()->isVisible());
870
871 // Make sure we show Navigation Toolbar when Menu Bar is hidden
872 if (!m_navigationToolbar->isVisible() && !menuBar()->isVisible()) {
874 }
875}
876
878{
879 setUpdatesEnabled(false);
880
881 m_statusBar->setVisible(!m_statusBar->isVisible());
882
883 setUpdatesEnabled(true);
884
885 Settings().setValue(QSL("Browser-View-Settings/showStatusBar"), m_statusBar->isVisible());
886
887}
888
890{
891 setUpdatesEnabled(false);
892
893 m_bookmarksToolbar->setVisible(!m_bookmarksToolbar->isVisible());
894
895 setUpdatesEnabled(true);
896
897 Settings().setValue(QSL("Browser-View-Settings/showBookmarksToolbar"), m_bookmarksToolbar->isVisible());
898 Settings().setValue(QSL("Browser-View-Settings/instantBookmarksToolbar"), false);
899}
900
902{
903 setUpdatesEnabled(false);
904
905 m_navigationToolbar->setVisible(!m_navigationToolbar->isVisible());
906
907 setUpdatesEnabled(true);
908
909 Settings().setValue(QSL("Browser-View-Settings/showNavigationToolbar"), m_navigationToolbar->isVisible());
910
911#ifndef Q_OS_MACOS
912 // Make sure we show Menu Bar when Navigation Toolbar is hidden
913 if (!m_navigationToolbar->isVisible() && !menuBar()->isVisible()) {
915 }
916#endif
917}
918
920{
921 qzSettings->tabsOnTop = enable;
922 m_navigationContainer->toggleTabsOnTop(enable);
923}
924
926{
927 if (m_htmlFullScreenView) {
928 weView()->triggerPageAction(QWebEnginePage::ExitFullScreen);
929 return;
930 }
931
932 if (isFullScreen()) {
933 setWindowState(windowState() & ~Qt::WindowFullScreen);
934 } else {
935 setWindowState(windowState() | Qt::WindowFullScreen);
936 }
937}
938
940{
941 if (enable) {
942 setWindowState(windowState() | Qt::WindowFullScreen);
943 } else {
944 setWindowState(windowState() & ~Qt::WindowFullScreen);
945 }
946
947 if (m_sideBar)
948 m_sideBar.data()->setHidden(enable);
949
950 m_htmlFullScreenView = enable ? view : nullptr;
951}
952
954{
955 if (weView() && weView()->webTab()) {
957 }
958}
959
961{
962 if (weView() && weView()->webTab()) {
964 }
965}
966
968{
969 TabbedWebView* view = weView();
970 m_navigationToolbar->setCurrentView(view);
971
972 if (!view) {
973 return;
974 }
975
976 const QString title = view->webTab()->title(/*allowEmpty*/true);
977 if (title.isEmpty()) {
978 setWindowTitle(tr("Falkon"));
979 } else {
980 setWindowTitle(tr("%1 - Falkon").arg(title));
981 }
982 m_ipLabel->setText(view->getIp());
983 view->setFocus();
984
986
987 // Setting correct tab order (LocationBar -> WebSearchBar -> WebView)
988 setTabOrder(locationBar(), m_navigationToolbar->webSearchBar());
989 setTabOrder(m_navigationToolbar->webSearchBar(), view);
990}
991
993{
994 TabbedWebView* view = weView();
995 if (!view) {
996 return;
997 }
998
999 bool isLoading = view->isLoading();
1000
1001 m_ipLabel->setVisible(!isLoading);
1002 m_progressBar->setVisible(isLoading);
1003
1004 action(QSL("View/Stop"))->setEnabled(isLoading);
1005 action(QSL("View/Reload"))->setEnabled(!isLoading);
1006
1007 if (isLoading) {
1008 m_progressBar->setValue(view->loadingProgress());
1009 m_navigationToolbar->showStopButton();
1010 }
1011 else {
1012 m_navigationToolbar->showReloadButton();
1013 }
1014}
1015
1017{
1018 if (!m_deleteOnCloseWidgets.contains(widget)) {
1019 m_deleteOnCloseWidgets.append(widget);
1020 }
1021}
1022
1024{
1025 restoreState(window.windowState);
1026 restoreGeometry(window.windowGeometry);
1027 restoreUiState(window.windowUiState);
1028#ifdef QZ_WS_X11
1029 moveToVirtualDesktop(window.virtualDesktop);
1030#endif
1031 if (!mApp->isTestModeEnabled()) {
1032 show(); // Window has to be visible before adding QWebEngineView's
1033 }
1034 m_tabWidget->restoreState(window.tabs, window.currentTab);
1035 updateStartupFocus();
1036}
1037
1039{
1040 removeActions(menu->actions());
1041 menu->clear();
1042
1043 QAction* action;
1044
1045#ifndef Q_OS_MACOS
1046 action = menu->addAction(tr("&Menu Bar"), this, &BrowserWindow::toggleShowMenubar);
1047 action->setCheckable(true);
1048 action->setChecked(menuBar()->isVisible());
1049#endif
1050
1051 action = menu->addAction(tr("&Navigation Toolbar"), this, &BrowserWindow::toggleShowNavigationToolbar);
1052 action->setCheckable(true);
1053 action->setChecked(m_navigationToolbar->isVisible());
1054
1055 action = menu->addAction(tr("&Bookmarks Toolbar"), this, &BrowserWindow::toggleShowBookmarksToolbar);
1056 action->setCheckable(true);
1057 action->setChecked(Settings().value(QSL("Browser-View-Settings/showBookmarksToolbar")).toBool());
1058
1059 menu->addSeparator();
1060
1061 action = menu->addAction(tr("&Tabs on Top"), this, SLOT(toggleTabsOnTop(bool)));
1062 action->setCheckable(true);
1063 action->setChecked(qzSettings->tabsOnTop);
1064
1065 addActions(menu->actions());
1066}
1067
1069{
1070 m_sideBarManager->createMenu(menu);
1071}
1072
1074{
1075 const QString activeCodecName = mApp->webSettings()->defaultTextEncoding();
1076
1077 QStringList isoCodecs;
1078 QStringList utfCodecs;
1079 QStringList windowsCodecs;
1080 QStringList isciiCodecs;
1081 QStringList ibmCodecs;
1082 QStringList otherCodecs;
1083 QStringList allCodecs;
1084
1085 const auto mibs = QTextCodec::availableMibs();
1086 for (const int mib : mibs) {
1087 const QString codecName = QString::fromUtf8(QTextCodec::codecForMib(mib)->name());
1088
1089 if (!allCodecs.contains(codecName))
1090 allCodecs.append(codecName);
1091 else
1092 continue;
1093
1094 if (codecName.startsWith(QLatin1String("ISO")))
1095 isoCodecs.append(codecName);
1096 else if (codecName.startsWith(QLatin1String("UTF")))
1097 utfCodecs.append(codecName);
1098 else if (codecName.startsWith(QLatin1String("windows")))
1099 windowsCodecs.append(codecName);
1100 else if (codecName.startsWith(QLatin1String("Iscii")))
1101 isciiCodecs.append(codecName);
1102 else if (codecName.startsWith(QLatin1String("IBM")))
1103 ibmCodecs.append(codecName);
1104 else
1105 otherCodecs.append(codecName);
1106 }
1107
1108 if (!menu->isEmpty())
1109 menu->addSeparator();
1110
1111 createEncodingSubMenu(QSL("ISO"), isoCodecs, menu);
1112 createEncodingSubMenu(QSL("UTF"), utfCodecs, menu);
1113 createEncodingSubMenu(QSL("Windows"), windowsCodecs, menu);
1114 createEncodingSubMenu(QSL("Iscii"), isciiCodecs, menu);
1115 createEncodingSubMenu(QSL("IBM"), ibmCodecs, menu);
1116 createEncodingSubMenu(tr("Other"), otherCodecs, menu);
1117}
1118
1119void BrowserWindow::removeActions(const QList<QAction *> &actions)
1120{
1121 for (QAction *action : actions) {
1122 removeAction(action);
1123 }
1124}
1125
1127{
1128 m_tabWidget->addView(QUrl(), Qz::NT_SelectedNewEmptyTab, true);
1129 m_tabWidget->setCurrentTabFresh(true);
1130
1131 if (isFullScreen())
1133}
1134
1135void BrowserWindow::webSearch()
1136{
1137 m_navigationToolbar->webSearchBar()->setFocus();
1138 m_navigationToolbar->webSearchBar()->selectAll();
1139}
1140
1141void BrowserWindow::searchOnPage()
1142{
1143 if (weView() && weView()->webTab()) {
1144 const QString searchText = weView()->page()->selectedText();
1145 if (!searchText.contains(QL1C('\n'))) {
1146 weView()->webTab()->showSearchToolBar(searchText);
1147 } else {
1149 }
1150 }
1151}
1152
1153void BrowserWindow::openFile()
1154{
1155 const QString fileTypes = QSL("%1(*.html *.htm *.shtml *.shtm *.xhtml);;"
1156 "%2(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff);;"
1157 "%3(*.txt);;"
1158 "%4(*.*)").arg(tr("HTML files"), tr("Image files"), tr("Text files"), tr("All files"));
1159
1160 const QString filePath = QzTools::getOpenFileName(QSL("MainWindow-openFile"), this, tr("Open file..."), QDir::homePath(), fileTypes);
1161
1162 if (!filePath.isEmpty()) {
1163 loadAddress(QUrl::fromLocalFile(filePath));
1164 }
1165}
1166
1167void BrowserWindow::openLocation()
1168{
1169 if (isFullScreen()) {
1171 }
1172
1173 locationBar()->setFocus();
1174 locationBar()->selectAll();
1175}
1176
1178{
1179 return m_navigationContainer->isVisible();
1180}
1181
1183{
1184 if (m_htmlFullScreenView)
1185 return;
1186
1187 if (m_hideNavigationTimer->isActive()) {
1188 m_hideNavigationTimer->stop();
1189 }
1190
1191 m_navigationContainer->show();
1192}
1193
1195{
1196 if (m_tabWidget->isCurrentTabFresh())
1197 return;
1198
1199 if (!m_hideNavigationTimer->isActive()) {
1200 m_hideNavigationTimer->start();
1201 }
1202}
1203
1204void BrowserWindow::hideNavigationSlot()
1205{
1206 TabbedWebView* view = weView();
1207 bool mouseInView = view && view->underMouse();
1208
1209 if (isFullScreen() && mouseInView) {
1210 m_navigationContainer->hide();
1211 }
1212}
1213
1214bool BrowserWindow::event(QEvent *event)
1215{
1216 if (event->type() == QEvent::WindowStateChange) {
1217 auto *e = static_cast<QWindowStateChangeEvent*>(event);
1218 if (!(e->oldState() & Qt::WindowFullScreen) && windowState() & Qt::WindowFullScreen) {
1219 // Enter fullscreen
1220 m_statusBarVisible = m_statusBar->isVisible();
1221#ifndef Q_OS_MACOS
1222 m_menuBarVisible = menuBar()->isVisible();
1223 menuBar()->hide();
1224#endif
1225 m_statusBar->hide();
1226
1227 m_navigationContainer->hide();
1228 m_navigationToolbar->enterFullScreen();
1229
1230 // Show main menu button since menubar is hidden
1231 m_navigationToolbar->setSuperMenuVisible(true);
1232 }
1233 else if (e->oldState() & Qt::WindowFullScreen && !(windowState() & Qt::WindowFullScreen)) {
1234 // Leave fullscreen
1235 m_statusBar->setVisible(m_statusBarVisible);
1236#ifndef Q_OS_MACOS
1237 menuBar()->setVisible(m_menuBarVisible);
1238#endif
1239
1240 m_navigationContainer->show();
1241 m_navigationToolbar->setSuperMenuVisible(!m_menuBarVisible);
1242 m_navigationToolbar->leaveFullScreen();
1243 m_htmlFullScreenView = nullptr;
1244 }
1245
1246 if (m_hideNavigationTimer) {
1247 m_hideNavigationTimer->stop();
1248 }
1249 }
1250
1251 return QMainWindow::event(event);
1252}
1253
1254void BrowserWindow::resizeEvent(QResizeEvent* event)
1255{
1256 m_bookmarksToolbar->setMaximumWidth(width());
1257
1258 QMainWindow::resizeEvent(event);
1259}
1260
1261void BrowserWindow::keyPressEvent(QKeyEvent* event)
1262{
1263 if (mApp->plugins()->processKeyPress(Qz::ON_BrowserWindow, this, event)) {
1264 return;
1265 }
1266
1267 int number = -1;
1268 TabbedWebView* view = weView();
1269
1270 switch (event->key()) {
1271 case Qt::Key_Back:
1272 if (view) {
1273 view->back();
1274 event->accept();
1275 }
1276 break;
1277
1278 case Qt::Key_Forward:
1279 if (view) {
1280 view->forward();
1281 event->accept();
1282 }
1283 break;
1284
1285 case Qt::Key_Stop:
1286 if (view) {
1287 view->stop();
1288 event->accept();
1289 }
1290 break;
1291
1292 case Qt::Key_Reload:
1293 case Qt::Key_Refresh:
1294 if (view) {
1295 view->reload();
1296 event->accept();
1297 }
1298 break;
1299
1300 case Qt::Key_HomePage:
1301 goHome();
1302 event->accept();
1303 break;
1304
1305 case Qt::Key_Favorites:
1306 mApp->browsingLibrary()->showBookmarks(this);
1307 event->accept();
1308 break;
1309
1310 case Qt::Key_Search:
1311 searchOnPage();
1312 event->accept();
1313 break;
1314
1315 case Qt::Key_F6:
1316 case Qt::Key_OpenUrl:
1317 openLocation();
1318 event->accept();
1319 break;
1320
1321 case Qt::Key_History:
1323 event->accept();
1324 break;
1325
1326 case Qt::Key_AddFavorite:
1327 bookmarkPage();
1328 event->accept();
1329 break;
1330
1331 case Qt::Key_Tools:
1332 action(QSL("Standard/Preferences"))->trigger();
1333 event->accept();
1334 break;
1335
1336 case Qt::Key_Tab:
1337 if (event->modifiers() == Qt::ControlModifier) {
1338 static_cast<QObject*>(m_tabWidget)->event(event);
1339 }
1340 break;
1341
1342 case Qt::Key_Backtab:
1343 if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
1344 static_cast<QObject*>(m_tabWidget)->event(event);
1345 }
1346 break;
1347
1348 case Qt::Key_PageDown:
1349 if (event->modifiers() == Qt::ControlModifier) {
1350 m_tabWidget->nextTab();
1351 event->accept();
1352 }
1353 break;
1354
1355 case Qt::Key_PageUp:
1356 if (event->modifiers() == Qt::ControlModifier) {
1357 m_tabWidget->previousTab();
1358 event->accept();
1359 }
1360 break;
1361
1362 case Qt::Key_Equal:
1363 if (view && event->modifiers() == Qt::ControlModifier) {
1364 view->zoomIn();
1365 event->accept();
1366 }
1367 break;
1368
1369 case Qt::Key_I:
1370 if (event->modifiers() == Qt::ControlModifier) {
1371 action(QSL("Tools/SiteInfo"))->trigger();
1372 event->accept();
1373 }
1374 break;
1375
1376 case Qt::Key_U:
1377 if (event->modifiers() == Qt::ControlModifier) {
1378 action(QSL("View/PageSource"))->trigger();
1379 event->accept();
1380 }
1381 break;
1382
1383 case Qt::Key_F:
1384 if (event->modifiers() == Qt::ControlModifier) {
1385 action(QSL("Edit/Find"))->trigger();
1386 event->accept();
1387 }
1388 break;
1389
1390 case Qt::Key_Slash:
1391 if (m_useSingleKeyShortcuts) {
1392 action(QSL("Edit/Find"))->trigger();
1393 event->accept();
1394 }
1395 break;
1396
1397 case Qt::Key_1:
1398 number = 1;
1399 break;
1400 case Qt::Key_2:
1401 number = 2;
1402 break;
1403 case Qt::Key_3:
1404 number = 3;
1405 break;
1406 case Qt::Key_4:
1407 number = 4;
1408 break;
1409 case Qt::Key_5:
1410 number = 5;
1411 break;
1412 case Qt::Key_6:
1413 number = 6;
1414 break;
1415 case Qt::Key_7:
1416 number = 7;
1417 break;
1418 case Qt::Key_8:
1419 number = 8;
1420 break;
1421 case Qt::Key_9:
1422 number = 9;
1423 break;
1424
1425 default:
1426 break;
1427 }
1428
1429 if (number != -1) {
1430 if (event->modifiers() & Qt::AltModifier && m_useTabNumberShortcuts) {
1431 if (number == 9) {
1432 number = m_tabWidget->count();
1433 }
1434 m_tabWidget->setCurrentIndex(number - 1);
1435 event->accept();
1436 return;
1437 }
1438 if (event->modifiers() & Qt::ControlModifier && m_useSpeedDialNumberShortcuts) {
1439 const QUrl url = mApp->plugins()->speedDial()->urlForShortcut(number - 1);
1440 if (url.isValid()) {
1441 loadAddress(url);
1442 event->accept();
1443 return;
1444 }
1445 }
1446 if (event->modifiers() == Qt::NoModifier && m_useSingleKeyShortcuts) {
1447 if (number == 1)
1448 m_tabWidget->previousTab();
1449 if (number == 2)
1450 m_tabWidget->nextTab();
1451 }
1452 }
1453
1454 QMainWindow::keyPressEvent(event);
1455}
1456
1457void BrowserWindow::keyReleaseEvent(QKeyEvent* event)
1458{
1459 if (mApp->plugins()->processKeyRelease(Qz::ON_BrowserWindow, this, event)) {
1460 return;
1461 }
1462
1463 switch (event->key()) {
1464 case Qt::Key_F:
1465 if (event->modifiers() == Qt::ControlModifier) {
1466 action(QSL("Edit/Find"))->trigger();
1467 event->accept();
1468 }
1469 break;
1470
1471 default:
1472 break;
1473 }
1474
1475 QMainWindow::keyReleaseEvent(event);
1476}
1477
1478void BrowserWindow::closeEvent(QCloseEvent* event)
1479{
1480 if (mApp->isClosing()) {
1481 saveSettings();
1482 return;
1483 }
1484
1485 Settings settings;
1486 bool askOnClose = settings.value(QSL("Browser-Tabs-Settings/AskOnClosing"), true).toBool();
1487
1488 if ((mApp->afterLaunch() == MainApplication::SelectSession || mApp->afterLaunch() == MainApplication::RestoreSession) && mApp->windowCount() == 1) {
1489 askOnClose = false;
1490 }
1491
1492 if (askOnClose && m_tabWidget->normalTabsCount() > 1) {
1493 CheckBoxDialog dialog(QMessageBox::Yes | QMessageBox::No, this);
1494 dialog.setDefaultButton(QMessageBox::No);
1495 //~ singular There is still %n open tab and your session won't be stored.\nAre you sure you want to close this window?
1496 //~ plural There are still %n open tabs and your session won't be stored.\nAre you sure you want to close this window?
1497 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()));
1498 dialog.setCheckBoxText(tr("Don't ask again"));
1499 dialog.setWindowTitle(tr("There are still open tabs"));
1500 dialog.setIcon(QMessageBox::Warning);
1501
1502 if (dialog.exec() != QMessageBox::Yes) {
1503 event->ignore();
1504 return;
1505 }
1506
1507 if (dialog.isChecked()) {
1508 settings.setValue(QSL("Browser-Tabs-Settings/AskOnClosing"), false);
1509 }
1510 }
1511
1512 Q_EMIT aboutToClose();
1513
1514 saveSettings();
1515 mApp->closedWindowsManager()->saveWindow(this);
1516
1517 #ifndef Q_OS_MACOS
1518 if (mApp->windowCount() == 1)
1519 mApp->quitApplication();
1520 #endif
1521
1522 event->accept();
1523}
1524
1525void BrowserWindow::closeWindow()
1526{
1527#ifdef Q_OS_MACOS
1528 close();
1529 return;
1530#endif
1531
1532 if (mApp->windowCount() > 1) {
1533 close();
1534 }
1535}
1536
1537void BrowserWindow::saveSettings()
1538{
1539 if (mApp->isPrivate()) {
1540 return;
1541 }
1542
1543 Settings settings;
1544 settings.beginGroup(QSL("Browser-View-Settings"));
1545 settings.setValue(QSL("WindowGeometry"), saveGeometry());
1546
1547 const auto state = saveUiState();
1548 for (auto it = state.constBegin(); it != state.constEnd(); ++it) {
1549 settings.setValue(it.key(), it.value());
1550 }
1551
1552 settings.endGroup();
1553}
1554
1555void BrowserWindow::closeTab()
1556{
1557 // Don't close pinned tabs with keyboard shortcuts (Ctrl+W, Ctrl+F4)
1558 if (weView() && !weView()->webTab()->isPinned()) {
1559 m_tabWidget->requestCloseTab();
1560 }
1561}
1562
1563#ifdef QZ_WS_X11
1564static xcb_connection_t *getXcbConnection()
1565{
1566 const QNativeInterface::QX11Application *x11App = qApp->nativeInterface<QNativeInterface::QX11Application>();
1567 if (x11App == nullptr)
1568 return nullptr;
1569 return x11App->connection();
1570}
1571
1572int BrowserWindow::getCurrentVirtualDesktop() const
1573{
1574 if (QGuiApplication::platformName() != QL1S("xcb"))
1575 return 0;
1576
1577 xcb_connection_t *connection = getXcbConnection();
1578 if (connection == nullptr)
1579 return 0;
1580
1581 xcb_intern_atom_cookie_t intern_atom;
1582 xcb_intern_atom_reply_t *atom_reply = nullptr;
1583 xcb_atom_t atom;
1584 xcb_get_property_cookie_t cookie;
1585 xcb_get_property_reply_t *reply = nullptr;
1586 uint32_t value;
1587
1588 intern_atom = xcb_intern_atom(connection, false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP");
1589 atom_reply = xcb_intern_atom_reply(connection, intern_atom, nullptr);
1590
1591 if (!atom_reply)
1592 goto error;
1593
1594 atom = atom_reply->atom;
1595
1596 cookie = xcb_get_property(connection, false, winId(), atom, XCB_ATOM_CARDINAL, 0, 1);
1597 reply = xcb_get_property_reply(connection, cookie, nullptr);
1598
1599 if (!reply || reply->type != XCB_ATOM_CARDINAL || reply->value_len != 1 || reply->format != sizeof(uint32_t) * 8)
1600 goto error;
1601
1602 value = *reinterpret_cast<uint32_t*>(xcb_get_property_value(reply));
1603
1604 free(reply);
1605 free(atom_reply);
1606 return value;
1607
1608error:
1609 free(reply);
1610 free(atom_reply);
1611 return 0;
1612}
1613
1614void BrowserWindow::moveToVirtualDesktop(int desktopId)
1615{
1616 if (QGuiApplication::platformName() != QL1S("xcb"))
1617 return;
1618
1619 // Don't move when window is already visible or it is first app window
1620 if (desktopId < 0 || isVisible() || m_windowType == Qz::BW_FirstAppWindow)
1621 return;
1622
1623 xcb_connection_t *connection = getXcbConnection();
1624 if (connection == nullptr)
1625 return;
1626
1627 xcb_intern_atom_cookie_t intern_atom;
1628 xcb_intern_atom_reply_t *atom_reply = nullptr;
1629 xcb_atom_t atom;
1630
1631 intern_atom = xcb_intern_atom(connection, false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP");
1632 atom_reply = xcb_intern_atom_reply(connection, intern_atom, nullptr);
1633
1634 if (!atom_reply)
1635 goto error;
1636
1637 atom = atom_reply->atom;
1638
1639 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, winId(), atom,
1640 XCB_ATOM_CARDINAL, 32, 1, (const void*) &desktopId);
1641
1642error:
1643 free(atom_reply);
1644}
1645#endif
QDataStream & operator>>(QDataStream &stream, BrowserWindow::SavedWindow &window)
QDataStream & operator<<(QDataStream &stream, const BrowserWindow::SavedWindow &window)
static bool bookmarkAllTabsDialog(QWidget *parent, TabWidget *tabWidget, BookmarkItem *folder=nullptr)
static bool addBookmarkDialog(QWidget *parent, const QUrl &url, const QString &title, BookmarkItem *folder=nullptr)
void toggleShowMenubar()
Qz::BrowserWindowType windowType() const
void toggleShowBookmarksToolbar()
void aboutToClose()
void setStartPage(WebPage *page)
QAction * action(const QString &name) const
TabMruModel * tabMruModel() const
void removeActions(const QList< QAction * > &actions)
bool fullScreenNavigationVisible() const
void toggleTabsOnTop(bool enable)
TabWidget * tabWidget() const
void setStartTab(WebTab *tab)
void updateLoadingActions()
void showSource(WebView *view=nullptr)
int tabCount() const
void showWebInspector()
void createSidebarsMenu(QMenu *menu)
void toggleShowStatusBar()
void showNavigationWithFullScreen()
void bookmarkAllTabs()
LocationBar * locationBar() const
void startingCompleted()
void requestHtmlFullScreen(TabbedWebView *view, bool enable)
void showHistoryManager()
void addDeleteOnCloseWidget(QWidget *widget)
NavigationBar * navigationBar() const
~BrowserWindow() override
void reloadBypassCache()
void toggleFullScreen()
void addBookmark(const QUrl &url, const QString &title)
void toggleWebInspector()
QLabel * ipLabel() const
void currentTabChanged()
SideBarManager * sideBarManager() const
QMenu * superMenu() const
TabModel * tabModel() const
void loadAddress(const QUrl &url)
void toggleShowNavigationToolbar()
void saveSideBarSettings()
void loadActionUrl(QObject *obj=nullptr)
StatusBar * statusBar() const
SideBar * addSideBar()
void createEncodingMenu(QMenu *menu)
TabbedWebView * weView() const
void createToolbarsMenu(QMenu *menu)
void loadActionUrlInNewTab(QObject *obj=nullptr)
BookmarksToolbar * bookmarksToolbar() const
QUrl homepageUrl() const
void setWindowTitle(const QString &t)
void hideNavigationWithFullScreen()
BrowserWindow(Qz::BrowserWindowType type, const QUrl &url=QUrl())
void restoreWindow(const SavedWindow &window)
void ensureVisible(int index=-1, int xmargin=-1)
static QString convertUrlToText(const QUrl &url)
void settingsReloaded()
QAction * action(const QString &name) const
Definition: mainmenu.cpp:113
void initSuperMenu(QMenu *superMenu) const
Definition: mainmenu.cpp:76
void setWindow(BrowserWindow *window)
Definition: mainmenu.cpp:57
void initMenuBar(QMenuBar *menuBar) const
Definition: mainmenu.cpp:65
void showReloadButton()
WebSearchBar * webSearchBar()
Definition: navigationbar.h:58
void setSplitterSizes(int locationBar, int websearchBar)
void enterFullScreen()
void leaveFullScreen()
void setSuperMenuVisible(bool visible)
void setCurrentView(TabbedWebView *view)
void addToolButton(AbstractButtonInterface *button)
QSplitter * splitter()
Definition: navigationbar.h:59
void addWidget(QWidget *widget)
void toggleTabsOnTop(bool enable)
void setTabBar(TabBar *tabBar)
void setValue(int value)
Definition: progressbar.cpp:32
static void setWmClass(const QString &name, const QWidget *widget)
Definition: qztools.cpp:874
static QKeySequence actionShortcut(const QKeySequence &shortcut, const QKeySequence &fallBack, const QKeySequence &shortcutRtl=QKeySequence(), const QKeySequence &fallbackRtl=QKeySequence())
Definition: qztools.cpp:752
static QString getOpenFileName(const QString &name, QWidget *parent=nullptr, const QString &caption=QString(), const QString &dir=QString(), const QString &filter=QString(), QString *selectedFilter=nullptr, QFileDialog::Options options=QFileDialog::Options())
Definition: qztools.cpp:659
void beginGroup(const QString &prefix)
Definition: settings.cpp:79
void endGroup()
Definition: settings.cpp:84
bool contains(const QString &key) const
Definition: settings.cpp:59
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:74
void setValue(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:69
QString activeSideBar() const
Definition: sidebar.cpp:96
void createMenu(QMenu *menu)
Definition: sidebar.cpp:101
void showSideBar(const QString &id, bool toggle=true)
Definition: sidebar.cpp:163
void addButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:217
int currentIndex() const
QWidget * widget(int index) const
void requestCloseTab(int index=-1)
Definition: tabwidget.cpp:471
void setCurrentIndex(int index)
Definition: tabwidget.cpp:536
void previousTab()
Definition: tabwidget.cpp:546
TabBar * tabBar() const
Definition: tabwidget.cpp:580
void nextTab()
Definition: tabwidget.cpp:541
bool restoreState(const QVector< WebTab::SavedTab > &tabs, int currentTab)
Definition: tabwidget.cpp:848
bool isCurrentTabFresh() const
Definition: tabwidget.cpp:219
int addView(const LoadRequest &req, const Qz::NewTabPositionFlags &openFlags, bool selectLine=false, bool pinned=false)
Definition: tabwidget.cpp:314
int normalTabsCount() const
Definition: tabwidget.cpp:551
QStackedWidget * locationBars() const
Definition: tabwidget.cpp:818
void setCurrentTabFresh(bool currentTabFresh)
Definition: tabwidget.cpp:224
QString getIp() const
void setPage(WebPage *page)
WebTab * webTab() const
Definition: webtab.h:40
void showWebInspector(bool inspectElement=false)
Definition: webtab.cpp:219
bool isCurrentTab() const
Definition: webtab.cpp:684
void toggleWebInspector()
Definition: webtab.cpp:234
QString title(bool allowEmpty=false) const
Definition: webtab.cpp:276
void showSearchToolBar(const QString &searchText=QString())
Definition: webtab.cpp:242
int loadingProgress() const
Definition: webview.cpp:219
WebPage * page() const
Definition: webview.cpp:132
void printPage()
Definition: webview.cpp:385
void zoomIn()
Definition: webview.cpp:298
void reloadBypassCache()
Definition: webview.cpp:358
bool isLoading() const
Definition: webview.cpp:214
void load(const QUrl &url)
Definition: webview.cpp:177
QString title(bool allowEmpty=false) const
Definition: webview.cpp:107
void forward()
Definition: webview.cpp:374
void back()
Definition: webview.cpp:363
void showSource()
Definition: webview.cpp:548
#define mApp
int value(const QColor &c)
Definition: colors.cpp:238
@ ON_BrowserWindow
Definition: qzcommon.h:93
BrowserWindowType
Definition: qzcommon.h:64
@ BW_NewWindow
Definition: qzcommon.h:67
@ BW_OtherRestoredWindow
Definition: qzcommon.h:66
@ BW_FirstAppWindow
Definition: qzcommon.h:65
@ BW_MacFirstWindow
Definition: qzcommon.h:68
@ NT_SelectedTabAtTheEnd
Definition: qzcommon.h:104
@ NT_SelectedTab
Definition: qzcommon.h:97
@ NT_SelectedNewEmptyTab
Definition: qzcommon.h:103
@ NT_CleanSelectedTabAtTheEnd
Definition: qzcommon.h:106
t
Definition: i18n.py:27
i
Definition: i18n.py:23
State state
#define QL1S(x)
Definition: qzcommon.h:44
#define QL1C(x)
Definition: qzcommon.h:48
#define QSL(x)
Definition: qzcommon.h:40
#define qzSettings
Definition: qzsettings.h:69
QVector< WebTab::SavedTab > tabs
Definition: browserwindow.h:68
QHash< QString, QVariant > windowUiState
Definition: browserwindow.h:65
bool isValid() const
Definition: webtab.cpp:67