diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2018-01-19 02:10:31 +0100 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2018-01-19 02:10:31 +0100 |
commit | 49ee5ed6e80b8f06337f92d14e2cab1c1512c1e3 (patch) | |
tree | e35d5472c2a3ed129f5a6a6826f9999b033cc548 /src/mainwindow/mainwindow.cpp | |
parent | Configuration creates missing items based on defaults (diff) | |
download | smolbote-49ee5ed6e80b8f06337f92d14e2cab1c1512c1e3.tar.xz |
Refactoring MainWindow
- Added NavigationBar object that manages the navigation buttons
- Removed NavigationButton class that it obsoleted
Diffstat (limited to 'src/mainwindow/mainwindow.cpp')
-rw-r--r-- | src/mainwindow/mainwindow.cpp | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp new file mode 100644 index 0000000..018ff64 --- /dev/null +++ b/src/mainwindow/mainwindow.cpp @@ -0,0 +1,316 @@ +/* + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: git://neueland.iserlohn-fortress.net/smolbote.git + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "mainwindow.h" +#include "forms/aboutdialog.h" +#include "forms/searchform.h" +#include "ui_mainwindow.h" +#include "widgets/mainwindowmenubar.h" +#include <QDockWidget> +#include <QMessageBox> +#include <bookmarks/bookmarkswidget.h> +#include <downloads/downloadswidget.h> +#include <navigation/urllineedit.h> +#include <settings/settingsdialog.h> + +MainWindow::MainWindow(std::shared_ptr<Configuration> config, QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) + , tabBar(new MainWindowTabBar(config, this)) + , menuBar(new MainWindowMenuBar(config, this)) + , m_addressBar(new UrlLineEdit(this)) + , 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<std::string>("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); + + // Add the toolbars + // tabToolBar: main menu and tab list + ui->mainToolBar->setMovable(m_config->value<bool>("browser.ui.tabtoolbarMovable").value()); + ui->mainToolBar->addWidget(menuBar); + //tabToolBar->addWidget(tabBar); + + // navigationToolBar: address bar + ui->navigationToolBar->setMovable(m_config->value<bool>("browser.ui.navtoolbarMovable").value()); + insertToolBarBreak(ui->navigationToolBar); + + // page actions + m_navigationBar = new NavigationBar(this); + m_navigationBar->addWidgetsTo(ui->navigationToolBar); + + ui->navigationToolBar->addWidget(m_addressBar); + + // connect signals + connect(m_addressBar, &UrlLineEdit::addressEntered, this, [&](const QUrl &url) { + tabBar->currentView()->load(url); + }); + connect(m_addressBar, &UrlLineEdit::searchTermEntered, this, [&](const QString &term) { + QString t = term; + t.replace(' ', '+'); + QString url = QString::fromStdString(m_config->value<std::string>("profile.search").value()); + url.replace("$term", t); + tabBar->currentView()->load(QUrl::fromUserInput(url)); + }); + connect(tabBar, &MainWindowTabBar::currentTabChanged, this, &MainWindow::handleTabChanged); + //connect(tabBar, SIGNAL(currentTabChanged(WebView *)), this, SLOT(handleTabChanged(WebView *))); + + // loading bar + ui->statusBar->addPermanentWidget(m_progressBar); + + // search box + m_searchBox = new SearchForm(this); + ui->statusBar->addWidget(m_searchBox); + m_searchBox->setVisible(false); + + // shortcuts + QAction *focusAddressAction = new QAction(this); + focusAddressAction->setShortcut(QKeySequence(QString::fromStdString(m_config->value<std::string>("browser.shortcuts.focusAddress").value()))); + //focusAddressAction->setShortcut(QKeySequence::fromString(browser->settings()->value("window.shortcuts.focusAddress").toString())); + //connect(focusAddressAction, SIGNAL(triggered(bool)), this, SLOT(focusAddress())); + connect(focusAddressAction, &QAction::triggered, this, [this]() { + m_addressBar->setFocus(); + m_addressBar->selectAll(); + }); + addAction(focusAddressAction); + + resize(m_config->value<int>("browser.window.width").value(), m_config->value<int>("browser.window.height").value()); + if(m_config->value<bool>("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<QDockWidget *> allDockWidgets = findChildren<QDockWidget *>(); + for(QDockWidget *w : allDockWidgets) { + if(w->widget()) { + w->widget()->setParent(nullptr); + } + } + + delete ui; +} + +void MainWindow::addTabbedDock(Qt::DockWidgetArea area, QWidget *widget) +{ + // make a list of widgets in the area we want + // this way we can append the new dock widget to the last one + QVector<QDockWidget *> areaDockWidgets; + for(QDockWidget *w : findChildren<QDockWidget *>()) { + // check if widget is already shown + if(w->widget() == widget) { + // in this case, close the dock and return + w->close(); + return; + } + + if(dockWidgetArea(w) == area) { + areaDockWidgets.append(w); + } + } + + // create a dock widget + QDockWidget *dock = new QDockWidget(widget->windowTitle(), this); + dock->setAttribute(Qt::WA_DeleteOnClose, true); + + // when the dock widget becomes invisble, release the docked widget + // setting the widget makes the dock its parent; setting parent back to nullptr + // makes the dock not show the widget any more + connect(dock, &QDockWidget::visibilityChanged, [dock](bool visible) { + if(!visible && dock->widget()) { + dock->widget()->setParent(nullptr); + } + }); + dock->setWidget(widget); + + // the same widget may be shown by docks in other windows + // in that case, they grab ownership and the current dock won't be showing anything + // so the current widget needs to be closed + auto *w = dynamic_cast<BookmarksWidget *>(widget); + w->closeOthers(); + if(w) { + connect(w, &BookmarksWidget::closeOthersSignal, dock, [dock]() { + dock->close(); + }); + } + + 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; + ui->mainToolBar->addWidget(tabBar); + } + tabBar->addTab(createWebView(url, m_profile.get(), this)); +} + +MainWindow *MainWindow::newWindow(const QUrl &url) +{ + Browser *instance = static_cast<Browser *>(qApp->instance()); + return instance->createSession(m_profile->storageName(), true, QStringList(url.toString())); +} + +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::showSettingsDialog() +{ + SettingsDialog *dlg = new SettingsDialog(m_config, this); + dlg->exec(); +} + +void MainWindow::setProfile(std::shared_ptr<WebEngineProfile> profile) +{ + Q_ASSERT(profile); + m_profile = profile; + tabBar->setProfile(profile.get()); + menuBar->setProfileName(profile->name()); +} + +WebEngineProfile *MainWindow::profile() +{ + Q_ASSERT(m_profile); + return m_profile.get(); +} + +void MainWindow::setBookmarksWidget(std::shared_ptr<BookmarksWidget> &widget) +{ + Q_ASSERT(widget); + m_bookmarksWidget = widget; + m_addressBar->setCompleterModel(m_bookmarksWidget->model()); + 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<DownloadsWidget> &widget) +{ + Q_ASSERT(widget); + m_downloadsWidget = widget; +} + +void MainWindow::toggleFullscreen() +{ + if(isFullScreen()) { + setWindowState(Qt::WindowMaximized | Qt::WindowActive); + } else { + setWindowState(Qt::WindowFullScreen | Qt::WindowActive); + } +} + +void MainWindow::handleTabChanged(WebView *view) +{ + Q_CHECK_PTR(view); + + 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_navigationBar->connectWebView(view); + + connect(view, &WebView::urlChanged, m_addressBar, &UrlLineEdit::setUrl); + m_addressBar->setUrl(view->url()); + m_addressBar->pageAction()->setMenu(view->pageMenu()); + + connect(view, &WebView::titleChanged, this, &MainWindow::handleTitleUpdated); + + 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<std::string>("browser.window.title").value()); + t.replace("title", title); + t.replace("profile", m_profile->name()); + setWindowTitle(t); + //setWindowTitle(browser->settings()->value("window.title").toString().replace("title", title).replace("profile", tabBar->profile()->name())); +} + +void MainWindow::addPlugins(const QVector<Browser::Plugin> &plugins) +{ + for(const Browser::Plugin &plugin : plugins) { + ProfileInterface *iProfilePlugin = qobject_cast<ProfileInterface *>(plugin.pointer); + if(iProfilePlugin) { + QWidget *w = iProfilePlugin->createWidget(m_profile.get(), this); + + auto *profileAction = new QAction(tr("Profile Action"), this); + ui->navigationToolBar->addAction(profileAction); + connect(profileAction, &QAction::triggered, this, [this, w]() { + w->setVisible(!w->isVisible()); + if(w->isVisible()) { + QPoint pos = ui->navigationToolBar->pos(); + pos.setX(pos.x() + ui->navigationToolBar->width() - w->width()); + pos.setY(pos.y() + ui->navigationToolBar->height()); + w->move(mapToGlobal(pos)); + w->show(); + } + }); + } + } +} |