/*******************************************************************************
**
** 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
#include
#include
#include "browser.h"
#include
#include
#include
#include "forms/aboutdialog.h"
#include
#include
MainWindow::MainWindow(QUrl defaultUrl, QWidget *parent) :
QMainWindow(parent),
blocklistManager(new BlockerManager(this)),
ui(new Ui::MainWindow),
navigationToolBar(new QToolBar(tr("Navigation"), this)),
tabToolBar(new QToolBar(tr("Tab bar"), this)),
tabBar(new WebViewTabBar(this)),
urlLineEdit(new UrlLineEdit(navigationToolBar)),
progressBar(new LoadingBar(this))
{
// set up UI
ui->setupUi(this);
// Dockable widget styling
setDockOptions(dockOptions() | AllowTabbedDocks | ForceTabbedDocks);
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North);
// Main menu
QMenuBar *menuBar = new QMenuBar(this);
menuBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
// Browser menu
QMenu *browserMenu = new QMenu(qApp->applicationName(), menuBar);
menuBar->addMenu(browserMenu);
browserMenu->addAction(tr("New Window"), this, SLOT(handleNewWindow()), QKeySequence::fromString(sSettings->value("window.shortcuts.windowNew").toString()));
browserMenu->addAction(tr("New Tab"), this, SLOT(addNewTab()), QKeySequence::fromString(sSettings->value("window.shortcuts.tabNew").toString()));
browserMenu->addSeparator();
browserMenu->addAction(tr("About"), this, SLOT(about()), QKeySequence(tr("F1")));
browserMenu->addAction(tr("About Qt"), qApp, SLOT(aboutQt()));
browserMenu->addAction(tr("Quit"), qApp, SLOT(quit()), QKeySequence::fromString(sSettings->value("window.shortcuts.windowClose").toString()));
// Tools menu
QMenu *toolsMenu = new QMenu(tr("Tools"), menuBar);
menuBar->addMenu(toolsMenu);
QAction *downloadsAction = toolsMenu->addAction(tr("Downloads"), Browser::instance()->downloads(), SLOT(show()));
downloadsAction->setParent(this);
downloadsAction->setShortcut(QKeySequence::fromString(sSettings->value("downloads.dialogShortcut").toString()));
QAction *bookmarksAction = toolsMenu->addAction(tr("Bookmarks"), Browser::instance()->bookmarks(), SLOT(show()));
bookmarksAction->setParent(this);
bookmarksAction->setShortcut(QKeySequence(sSettings->value("bookmarks.dialogShortcut").toString()));
toolsMenu->addSeparator();
toolsMenu->addAction(tr("Blocker"), blocklistManager, SLOT(show()), QKeySequence::fromString(sSettings->value("blocker.shortcut").toString()));
// Profile menu
QMenu *profileMenu = new QMenu(tr("Profile"), menuBar);
menuBar->addMenu(profileMenu);
profileMenu->addAction(tr("View profile"), this, SLOT(profileAction()));
profileMenu->addAction(tr("Load profile"), this, SLOT(loadProfile()));
//profileMenu->addAction(tr("Settings"));
profileMenu->addAction(tr("Cookies"), this, SLOT(cookiesAction()));
// Add the toolbars
// tabToolBar: main menu and tab list
tabToolBar->setMovable(sSettings->value("window.ui.tabtoolbarMovable", true).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", true).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, QWebEnginePage::Back);
QToolButton *forwardButton = new QToolButton(this);
forwardButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward));
connect(forwardButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(forwardButton, QWebEnginePage::Forward);
QToolButton *reloadButton = new QToolButton(this);
reloadButton->setIcon(style()->standardIcon(QStyle::SP_BrowserReload));
connect(reloadButton, SIGNAL(clicked()), tabBar->signalMapper(), SLOT(map()));
tabBar->signalMapper()->setMapping(reloadButton, QWebEnginePage::Reload);
navigationToolBar->addWidget(backButton);
navigationToolBar->addWidget(forwardButton);
navigationToolBar->addWidget(reloadButton);
navigationToolBar->addWidget(urlLineEdit);
this->addToolBar(Qt::TopToolBarArea, navigationToolBar);
// connect signals
connect(urlLineEdit, SIGNAL(returnPressed()), this, SLOT(handleUrlChanged()));
connect(tabBar, SIGNAL(currentTabChanged(WebView*)), this, SLOT(handleTabChanged(WebView*)));
// Load profile
m_profile = qApp->profile(sSettings->value("browser.profile.default").toString());
// loading bar
ui->statusBar->addPermanentWidget(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()) {
addNewTab(defaultUrl);
} else {
addNewTab(sSettings->value("general.homepage", QUrl("about:blank")).toUrl());
}
resize(sSettings->value("window.width", 800).toInt(), sSettings->value("window.height", 600).toInt());
if(sSettings->value("window.maximized", false).toBool()) {
showMaximized();
}
}
MainWindow::MainWindow(const QStringList urlList, QWidget *parent) :
MainWindow(QUrl(""), parent)
{
for(QString url : urlList) {
addNewTab(QUrl::fromUserInput(url));
}
}
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::addNewTab(const QUrl &url)
{
if(!url.isEmpty()) {
tabBar->addTab(m_profile, url);
} else {
tabBar->addTab(m_profile, sSettings->value("general.newtab").toUrl());
}
}
void MainWindow::focusAddress()
{
urlLineEdit->setFocus();
urlLineEdit->selectAll();
}
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::loadProfile(const QString name)
{
if(name.isEmpty()) {
bool ok;
QString _name = QInputDialog::getText(this, tr("Load Profile"), tr("Enter Profile name"), QLineEdit::Normal, QString(""), &ok);
if(ok) {
m_profile = qApp->profile(_name);
} else {
return;
}
} else {
m_profile = qApp->profile(name);
}
tabBar->setProfile(m_profile);
}
void MainWindow::handleNewWindow(const QUrl &url)
{
Browser::instance()->addWindow(new MainWindow(url));
}
void MainWindow::handleTabChanged(WebView *view)
{
Q_ASSERT(view);
// 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
connect(view, SIGNAL(urlChanged(QUrl)), urlLineEdit, SLOT(setUrl(QUrl)));
connect(view, SIGNAL(titleChanged(QString)), this, SLOT(handleTitleUpdated(QString)));
connect(view, SIGNAL(linkHovered(QString)), ui->statusBar, SLOT(showMessage(QString)));
progressBar->connectWebView(view);
// update UI
urlLineEdit->setUrl(view->url());
this->handleTitleUpdated(view->title());
centralWidget()->setFocus();
}
void MainWindow::handleUrlChanged()
{
tabBar->currentView()->load(urlLineEdit->url());
}
void MainWindow::handleTitleUpdated(const QString &title)
{
setWindowTitle(sSettings->value("window.title").toString().replace("title", title).replace("profile", m_profile->storageName()));
}
void MainWindow::profileAction()
{
m_profile->dialog()->showProfile();
}
void MainWindow::cookiesAction()
{
m_profile->dialog()->showCookies();
}