/******************************************************************************* ** ** 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 "forms/aboutdialog.h" #include #include #include #include #include #include #include #include MainWindow::MainWindow(std::shared_ptr config, 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)) { Q_ASSERT(config); m_config = config; // delete this window when it closes setAttribute(Qt::WA_DeleteOnClose, true); // set up UI ui->setupUi(this); QAction *fullscreenAction = new QAction(this); fullscreenAction->setShortcut(QKeySequence(QString::fromStdString(m_config->value("browser.shortcuts.fullscreen").value()))); connect(fullscreenAction, &QAction::triggered, this, &MainWindow::toggleFullscreen); addAction(fullscreenAction); // Dockable widget styling setDockOptions(dockOptions() | AllowTabbedDocks | ForceTabbedDocks); setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North); // Main menu menuBar = new MainWindowMenuBar(config, this); menuBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); connect(menuBar->printAction(), &QAction::triggered, this, [&]() { const 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(m_config->value("browser.ui.tabtoolbarMovable").value()); tabToolBar->addWidget(menuBar); //tabToolBar->addWidget(tabBar); this->addToolBar(Qt::TopToolBarArea, tabToolBar); this->addToolBarBreak(Qt::TopToolBarArea); // navigationToolBar: address bar navigationToolBar->setMovable(m_config->value("browser.ui.navtoolbarMovable").value()); // page actions m_backButton = new NavigationButton(NavigationButton::BackButton, this); m_forwardButton = new NavigationButton(NavigationButton::ForwardButton, this); m_reloadButton = new NavigationButton(NavigationButton::ReloadButton, this); QToolButton *homepageButton = new QToolButton(this); homepageButton->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); connect(homepageButton, &QToolButton::clicked, this, [&]() { tabBar->currentView()->load(tabBar->profile()->homepage()); }); navigationToolBar->addWidget(m_backButton); navigationToolBar->addWidget(m_forwardButton); navigationToolBar->addWidget(m_reloadButton); navigationToolBar->addWidget(homepageButton); navigationToolBar->addWidget(m_addressBar); this->addToolBar(Qt::TopToolBarArea, navigationToolBar); // connect signals connect(m_addressBar, &AddressBar::addressEntered, this, [&](const QUrl &url) { tabBar->currentView()->load(url); }); connect(m_addressBar, &AddressBar::searchTermEntered, this, [&](const QString &string) { QString term = string.mid(1); term.replace(' ', '+'); //tabBar->currentView()->load(QUrl::fromUserInput(browser->settings()->value("general.search").toString().replace("$term", term))); }); connect(tabBar, SIGNAL(currentTabChanged(WebView*)), this, SLOT(handleTabChanged(WebView*))); // loading bar ui->statusBar->addPermanentWidget(m_progressBar); // shortcuts QAction *focusAddressAction = new QAction(this); //focusAddressAction->setShortcut(QKeySequence::fromString(browser->settings()->value("window.shortcuts.focusAddress").toString())); connect(focusAddressAction, SIGNAL(triggered(bool)), this, SLOT(focusAddress())); addAction(focusAddressAction); resize(m_config->value("browser.window.width").value(), m_config->value("browser.window.height").value()); if(m_config->value("browser.window.maximized").value()) { showMaximized(); } } MainWindow::~MainWindow() { // Release all dock widgets before deleting so we don't accidentally delete them // Also fixes that annoying crash when closing QList allDockWidgets = findChildren(); for(QDockWidget *w : allDockWidgets) { if(w->widget()) { w->widget()->setParent(nullptr); } } delete ui; } void MainWindow::addTabbedDock(Qt::DockWidgetArea area, QWidget *widget) { // get all dock widgets QList allDockWidgets = findChildren(); // check if the widget we're adding is there already for(QDockWidget *w : allDockWidgets) { if(w->widget() == widget) { // widget is already shown --> return w->show(); return; } } // we haven't shown this widget, so let's make a list of widgets in the area we want QVector areaDockWidgets; for(QDockWidget *w : allDockWidgets) { if(dockWidgetArea(w) == area) { areaDockWidgets.append(w); } } // create a dock widget // this dock widget will be destroyed with the MainWindow QDockWidget *dock = new QDockWidget(widget->windowTitle(), this); dock->setWidget(widget); if(areaDockWidgets.empty()) { // no other widgets addDockWidget(area, dock); } else { // there are other widgets, so put it after the last one tabifyDockWidget(areaDockWidgets.last(), dock); } } void MainWindow::newTab(const QUrl &url) { if(!m_tabBarAdded) { m_tabBarAdded = true; tabToolBar->addWidget(tabBar); } tabBar->addTab(url); } 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::setBookmarksWidget(std::shared_ptr &widget) { Q_ASSERT(widget); m_bookmarksWidget = widget; connect(menuBar->bookmarksAction(), &QAction::triggered, this, [this]() { addTabbedDock(Qt::RightDockWidgetArea, m_bookmarksWidget.get()); }); connect(m_bookmarksWidget.get(), &BookmarksWidget::openUrl, this, [this](const QUrl &url) { if(isActiveWindow()) { newTab(url); } }); } void MainWindow::setDownloadsWidget(std::shared_ptr &widget) { Q_ASSERT(widget); m_downloadsWidget = widget; connect(menuBar->downloadsAction(), &QAction::triggered, this, [this]() { addTabbedDock(Qt::RightDockWidgetArea, m_downloadsWidget.get()); }); } void MainWindow::toggleFullscreen() { if(isFullScreen()) { setWindowState(Qt::WindowMaximized | Qt::WindowActive); } else { setWindowState(Qt::WindowFullScreen | Qt::WindowActive); } } void MainWindow::newWindow(const QUrl &url) { QHash options; options.insert("urls", url); //browser->createWindow(options); } 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(nullptr); // disconnect signals disconnect(centralWidget()); } // set new central widget setCentralWidget(view); // connect signals m_backButton->setView(view); m_forwardButton->setView(view); m_reloadButton->setView(view); 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) { QString t = QString::fromStdString(m_config->value("browser.window.title").value()); t.replace("title", title); t.replace("profile", tabBar->profile()->name()); setWindowTitle(t); //setWindowTitle(browser->settings()->value("window.title").toString().replace("title", title).replace("profile", tabBar->profile()->name())); }