/*******************************************************************************
**
** smolbote: yet another qute browser
** Copyright (C) 2017 Xian Nox
**
** 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 "mainwindow.h"
#include "ui_mainwindow.h"
#include "widgets/mainwindowmenubar.h"
#include
#include "browser.h"
#include
#include
#include "forms/aboutdialog.h"
#include
#include
#include
#include
MainWindow::MainWindow(QUrl defaultUrl, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
navigationToolBar(new QToolBar(tr("Navigation"), this)),
tabToolBar(new QToolBar(tr("Tab bar"), this)),
tabBar(new WebViewTabBar(nullptr, this)),
m_addressBar(new AddressBar(navigationToolBar)),
m_progressBar(new LoadingBar(this))
{
// set up UI
ui->setupUi(this);
QAction *fullscreenAction = new QAction(this);
fullscreenAction->setShortcut(QKeySequence::fromString(sSettings->value("window.shortcuts.fullscreen").toString()));
connect(fullscreenAction, SIGNAL(triggered(bool)), this, SLOT(toggleFullscreen()));
addAction(fullscreenAction);
// Dockable widget styling
setDockOptions(dockOptions() | AllowTabbedDocks | ForceTabbedDocks);
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North);
// Main menu
MainWindowMenuBar *menuBar = new MainWindowMenuBar(this);
menuBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
connect(menuBar->printAction(), &QAction::triggered, [this]() {
QString path = QFileDialog::getSaveFileName(this, tr("Print to PDF"), QDir::homePath(), tr("PDF files (*.pdf)"));
m_currentView->page()->printToPdf(path);
});
// Add the toolbars
// tabToolBar: main menu and tab list
tabToolBar->setMovable(sSettings->value("window.ui.tabtoolbarMovable").toBool());
tabToolBar->addWidget(menuBar);
tabToolBar->addWidget(tabBar);
this->addToolBar(Qt::TopToolBarArea, tabToolBar);
this->addToolBarBreak(Qt::TopToolBarArea);
// navigationToolBar: address bar
navigationToolBar->setMovable(sSettings->value("window.ui.navtoolbarMovable").toBool());
// page actions
QToolButton *backButton = new QToolButton(this);
backButton->setIcon(style()->standardIcon(QStyle::SP_ArrowBack));
connect(backButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(backButton, WebViewTabBar::Back);
QMenu *backMenu = new QMenu(this);
connect(backMenu, &QMenu::aboutToShow, [backMenu, this]() {
backMenu->clear();
for(QWebEngineHistoryItem i : m_currentView->history()->backItems(10)) {
QAction *a = backMenu->addAction(i.title());
connect(a, &QAction::triggered, [i, this]() {
m_currentView->history()->goToItem(i);
});
}
});
backButton->setMenu(backMenu);
QToolButton *forwardButton = new QToolButton(this);
forwardButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward));
connect(forwardButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(forwardButton, WebViewTabBar::Forward);
QMenu *forwardMenu = new QMenu(this);
connect(forwardMenu, &QMenu::aboutToShow, [forwardMenu, this]() {
forwardMenu->clear();
for(QWebEngineHistoryItem i : m_currentView->history()->forwardItems(10)) {
QAction *a = forwardMenu->addAction(i.title());
connect(a, &QAction::triggered, [i, this]() {
m_currentView->history()->goToItem(i);
});
}
});
forwardButton->setMenu(forwardMenu);
QToolButton *reloadButton = new QToolButton(this);
reloadButton->setIcon(style()->standardIcon(QStyle::SP_BrowserReload));
connect(reloadButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(reloadButton, WebViewTabBar::Reload);
QToolButton *homepageButton = new QToolButton(this);
homepageButton->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon));
connect(homepageButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(homepageButton, WebViewTabBar::Homepage);
navigationToolBar->addWidget(backButton);
navigationToolBar->addWidget(forwardButton);
navigationToolBar->addWidget(reloadButton);
navigationToolBar->addWidget(homepageButton);
navigationToolBar->addWidget(m_addressBar);
this->addToolBar(Qt::TopToolBarArea, navigationToolBar);
// connect signals
connect(m_addressBar, &AddressBar::addressEntered, [&](const QUrl &url) {
tabBar->currentView()->load(url);
});
connect(m_addressBar, &AddressBar::searchTermEntered, [&](const QString &string) {
QString term = string.mid(1);
term.replace(' ', '+');
tabBar->currentView()->load(QUrl::fromUserInput(qApp->settings()->value("general.search").toString().replace("$term", term)));
});
connect(tabBar, SIGNAL(currentTabChanged(WebView*)), this, SLOT(handleTabChanged(WebView*)));
connect(qApp->bookmarks(), &BookmarksWidget::openUrl, [this](const QUrl &url) {
if(this->isActiveWindow()) {
this->newTab(url);
}
});
// Load profile
tabBar->setProfile(qApp->profile(sSettings->value("browser.profile.default").toString()));
// loading bar
ui->statusBar->addPermanentWidget(m_progressBar);
// shortcuts
QAction *focusAddressAction = new QAction(this);
focusAddressAction->setShortcut(QKeySequence::fromString(sSettings->value("window.shortcuts.focusAddress").toString()));
connect(focusAddressAction, SIGNAL(triggered(bool)), this, SLOT(focusAddress()));
addAction(focusAddressAction);
if(!defaultUrl.isEmpty()) {
newTab(defaultUrl);
} else {
newTab(tabBar->profile()->homepage());
}
resize(sSettings->value("window.width").toInt(), sSettings->value("window.height").toInt());
if(sSettings->value("window.maximized").toBool()) {
showMaximized();
}
}
MainWindow::MainWindow(const QStringList urlList, QWidget *parent) :
MainWindow(QUrl(""), parent)
{
QStringList::const_iterator i;
for(i = urlList.constBegin(); i != urlList.constEnd(); ++i) {
newTab(QUrl::fromUserInput(*i));
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::addTabbedDock(Qt::DockWidgetArea area, QDockWidget *widget)
{
QList allDockWidgets = findChildren();
QVector areaDockWidgets;
for(QDockWidget *w : allDockWidgets) {
if(dockWidgetArea(w) == area) {
areaDockWidgets.append(w);
}
}
if(areaDockWidgets.empty()) {
// no other widgets
addDockWidget(area, widget);
} else {
tabifyDockWidget(areaDockWidgets.last(), widget);
}
}
void MainWindow::newTab(const QUrl &url)
{
if(!url.isEmpty()) {
tabBar->addTab(url);
} else {
tabBar->addTab(tabBar->profile()->newtab());
}
}
void MainWindow::focusAddress()
{
m_addressBar->setFocus();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(tabBar->count() > 1) {
int ret = QMessageBox::warning(this, tr("Close window?"), tr("Close multiple tabs?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if(ret == QMessageBox::No) {
event->ignore();
return;
}
}
QMainWindow::closeEvent(event);
}
void MainWindow::about()
{
AboutDialog *dlg = new AboutDialog(this);
dlg->exec();
}
void MainWindow::setProfile(WebEngineProfile *profile)
{
Q_ASSERT(profile != nullptr);
tabBar->setProfile(profile);
}
void MainWindow::toggleFullscreen()
{
if(isFullScreen()) {
setWindowState(Qt::WindowMaximized | Qt::WindowActive);
} else {
setWindowState(Qt::WindowFullScreen | Qt::WindowActive);
}
}
void MainWindow::newWindow(const QUrl &url)
{
Browser::instance()->addWindow(new MainWindow(url));
}
void MainWindow::handleTabChanged(WebView *view)
{
Q_ASSERT(view != nullptr);
m_currentView = view;
// centralWidget can be a nullptr
if(centralWidget()) {
// clear the parent of the central widget so it doesn't get deleted
centralWidget()->setParent(0);
// disconnect signals
disconnect(centralWidget());
}
// set new central widget
setCentralWidget(view);
// connect signals
m_addressBar->setWebView(view);
connect(view, SIGNAL(titleChanged(QString)), this, SLOT(handleTitleUpdated(QString)));
connect(view, SIGNAL(linkHovered(QString)), ui->statusBar, SLOT(showMessage(QString)));
m_progressBar->connectWebView(view);
// update UI
this->handleTitleUpdated(view->title());
centralWidget()->setFocus();
}
void MainWindow::handleTitleUpdated(const QString &title)
{
setWindowTitle(sSettings->value("window.title").toString().replace("title", title).replace("profile", tabBar->profile()->name()));
}