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);
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->setShortcut(QKeySequence::fromString(sSettings->value("downloads.dialogShortcut").toString()));
QAction *bookmarksAction = toolsMenu->addAction(tr("Bookmarks"), Browser::instance()->bookmarks(), SLOT(show()));
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(execProfileEditor()));
profileMenu->addAction(tr("Load profile"), this, SLOT(loadProfileGUI()));
//profileMenu->addAction(tr("Settings"));
//profileMenu->addAction(tr("Cookies"));
// 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());
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
loadProfile(sSettings->value("general.profile").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::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()
{
QMessageBox::about(this, tr("About"), tr("smolbote %1
"
"yet another Qute browser
"
"Copyright (C) 2017 Xian Nox
"
"This program comes with ABSOLUTELY NO WARRANTY. "
"This is free software, and you are welcome to redistribute it under the conditions set by the GNU GPLv3.
"
"Configuration lives in: %2
")
.arg(qApp->applicationVersion()).arg(sSettings->filePath()));
}
void MainWindow::loadProfile(const QString &name)
{
if(m_profile) {
m_profile->deleteLater();
}
if(name.isEmpty()) {
//profileName = tr("Off the record");
m_profile = new WebEngineProfile(this);
qDebug("Creating off-the-record profile");
} else {
//profileName = name;
m_profile = new WebEngineProfile(name, this);
qDebug("Using profile: %s", qUtf8Printable(m_profile->storageName()));
}
UrlRequestInterceptor *interceptor = new UrlRequestInterceptor(this);
interceptor->setSubscription(blocklistManager);
m_profile->setRequestInterceptor(interceptor);
connect(m_profile, SIGNAL(downloadRequested(QWebEngineDownloadItem*)), Browser::instance()->downloads(), SLOT(addDownload(QWebEngineDownloadItem*)));
}
void MainWindow::loadProfileGUI()
{
bool ok;
QString name = QInputDialog::getText(this, tr("Load Profile"), tr("Enter Profile name"), QLineEdit::Normal, QString(""), &ok);
if(ok) {
loadProfile(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::execProfileEditor()
{
ProfileDialog *dialog = new ProfileDialog(m_profile, this);
dialog->exec();
}