aboutsummaryrefslogtreecommitdiff
path: root/src/mainwindow/mainwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwindow/mainwindow.cpp')
-rw-r--r--src/mainwindow/mainwindow.cpp362
1 files changed, 115 insertions, 247 deletions
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp
index 99a80b8..c039c8e 100644
--- a/src/mainwindow/mainwindow.cpp
+++ b/src/mainwindow/mainwindow.cpp
@@ -7,301 +7,169 @@
*/
#include "mainwindow.h"
-#include "addressbar/urllineedit.h"
-#include "configuration/configuration.h"
-#include "forms/aboutdialog.h"
-#include "mainwindow/widgets/searchform.h"
-#include "ui_mainwindow.h"
-#include "widgets/mainwindowmenubar.h"
-#include "mainwindow/widgets/tabbar.h"
+#include "webengine/webview.h"
+#include "widgets/navigationbar.h"
+#include "window.h"
+#include <QApplication>
+#include <QCloseEvent>
#include <QDockWidget>
+#include <QLineEdit>
+#include <QMdiArea>
+#include <QMdiSubWindow>
+#include <QMenuBar>
#include <QMessageBox>
-#include <bookmarks/bookmarksview.h>
-#include <bookmarks/bookmarkswidget.h>
-#include <downloads/downloadswidget.h>
+#include <QShortcut>
+#include <QToolBar>
+#include <QUrl>
+#include <about/aboutdialog.h>
+#include <configuration/configuration.h>
-MainWindow::MainWindow(std::shared_ptr<Configuration> config, QWidget *parent)
+MainWindow::MainWindow(std::shared_ptr<Configuration> &config, QWidget *parent)
: QMainWindow(parent)
- , ui(new Ui::MainWindow)
- , tabBar(new TabBar(config->section("tabbar"), this))
- , m_addressBar(new UrlLineEdit(config->section("addressbar"), this))
- , m_progressBar(new LoadingBar(this))
- , menuBar(new MainWindowMenuBar(config, this))
+ , mdiArea(new QMdiArea(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);
+ // create UI
+ resize(config->value<int>("mainwindow.width").value(), config->value<int>("mainwindow.height").value());
+ titleSuffix = QString::fromStdString(config->value<std::string>("mainwindow.title").value());
+ setWindowTitle(tr("smolbote"));
+ if(config->value<bool>("mainwindow.maximized").value())
+ showMaximized();
+ else
+ show();
+
+ createMenuBar();
+ auto *navigationToolBar = new NavigationBar(config->section("navigation"), this);
+ navigationToolBar->setMovable(config->value<bool>("navigation.movable").value());
+ addToolBar(Qt::TopToolBarArea, navigationToolBar);
+ navigationToolBar->connectWebView(nullptr);
+
+ setCentralWidget(mdiArea);
+ mdiArea->setFocus();
+
+ connect(mdiArea, &QMdiArea::subWindowActivated, this, [this, navigationToolBar](QMdiSubWindow *window) {
+ disconnect(titleChangedConnection);
+ disconnect(navigationBarConnection);
+
+ auto *w = qobject_cast<Window *>(window);
+ if(w != nullptr) {
+ setWindowTitle(w->windowTitle() + titleSuffix);
+ titleChangedConnection = connect(w, &Window::windowTitleChanged, this, [this](const QString &title) {
+ this->setWindowTitle(title + titleSuffix);
+ });
- // 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));
+ navigationToolBar->connectWebView(w->currentView());
+ navigationBarConnection = connect(w, &Window::currentViewChanged, navigationToolBar, &NavigationBar::connectWebView);
+ }
});
- connect(tabBar, &TabBar::currentTabChanged, this, &MainWindow::handleTabChanged);
- // loading bar
- ui->statusBar->addPermanentWidget(m_progressBar);
-
- // search box
- m_searchBox = new SearchForm(this);
- ui->statusBar->addWidget(m_searchBox);
- m_searchBox->setVisible(false);
-
- 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();
- }
+ auto *tileShortcut = new QShortcut(QKeySequence(config->value<std::string>("mainwindow.shortcuts.tileWindows").value().c_str()), this);
+ connect(tileShortcut, &QShortcut::activated, this, [this]() {
+ mdiArea->tileSubWindows();
+ });
}
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;
+ disconnect(titleChangedConnection);
+ disconnect(navigationBarConnection);
}
-void MainWindow::addTabbedDock(Qt::DockWidgetArea area, QWidget *widget)
+void MainWindow::createMenuBar()
{
- // 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;
- }
+ auto *smolboteMenu = menuBar()->addMenu(qApp->applicationDisplayName());
+ smolboteMenu->addAction(tr("New tab"), this, [this]() {
+ createTab(QUrl::fromUserInput("about:blank"));
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.newTab").value().c_str()));
- if(dockWidgetArea(w) == area) {
- areaDockWidgets.append(w);
- }
- }
+ smolboteMenu->addAction(tr("New tab group"), this, [this]() {
+ createSubWindow(QUrl::fromUserInput("about:blank"));
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.newGroup").value().c_str()));
+ smolboteMenu->addAction(tr("New window"))->setEnabled(false);
- // create a dock widget
- QDockWidget *dock = new QDockWidget(widget->windowTitle(), this);
- dock->setAttribute(Qt::WA_DeleteOnClose, true);
+ smolboteMenu->addSeparator();
- // 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);
+ smolboteMenu->addAction(tr("About"), this, [this]() {
+ auto *dlg = new AboutDialog(this);
+ dlg->exec();
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.about").value().c_str()));
+ smolboteMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt);
- // 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);
- }
-}
+ smolboteMenu->addSeparator();
-void MainWindow::newTab(const QUrl &url)
-{
- if(!m_tabBarAdded) {
- m_tabBarAdded = true;
- ui->mainToolBar->addWidget(tabBar);
- }
- tabBar->addTab(createWebView(url, m_profile.get(), this));
-}
+ smolboteMenu->addAction(tr("Quit"), qApp, &QApplication::quit,
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.quit").value().c_str()));
-MainWindow *MainWindow::newWindow(const QUrl &url)
-{
- auto *instance = dynamic_cast<Browser *>(QApplication::instance());
- return instance->createSession(m_profile->storageName(), true, QStringList(url.toString()));
+ toolsMenu = menuBar()->addMenu(tr("Tools"));
}
-void MainWindow::closeEvent(QCloseEvent *event)
+void MainWindow::addAction(ActionLocation where, QAction *action)
{
- 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;
- }
+ switch(where) {
+ case ToolsMenu:
+ toolsMenu->addAction(action);
+ break;
+ default:
+ QMainWindow::addAction(action);
+ break;
}
- QMainWindow::closeEvent(event);
-}
-
-void MainWindow::about()
-{
- auto *dlg = new AboutDialog(this);
- dlg->exec();
}
-void MainWindow::setProfile(std::shared_ptr<WebEngineProfile> profile)
+void MainWindow::addDockWidget(Qt::DockWidgetArea area, QWidget *widget)
{
- Q_ASSERT(profile);
- m_profile = profile;
- tabBar->setProfile(profile.get());
- menuBar->profileAction()->setText(tr("Current profile: %1").arg(profile->name()));
-}
-
-WebEngineProfile *MainWindow::profile()
-{
- Q_ASSERT(m_profile);
- return m_profile.get();
-}
+ QDockWidget *dock = new QDockWidget(widget->windowTitle(), this);
+ dock->setAttribute(Qt::WA_DeleteOnClose, true);
+ dock->setWidget(widget);
-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);
+ connect(dock, &QDockWidget::visibilityChanged, [dock](bool visible) {
+ if(!visible && dock->widget()) {
+ dock->widget()->setParent(nullptr);
}
});
-}
-void MainWindow::setDownloadsWidget(std::shared_ptr<DownloadsWidget> &widget)
-{
- Q_ASSERT(widget);
- m_downloadsWidget = widget;
+ QMainWindow::addDockWidget(area, dock);
}
-void MainWindow::toggleFullscreen()
+void MainWindow::createTab(const QUrl &url)
{
- if(isFullScreen()) {
- setWindowState(Qt::WindowMaximized | Qt::WindowActive);
+ auto *w = qobject_cast<Window *>(mdiArea->currentSubWindow());
+ if(w == nullptr) {
+ w = createSubWindow(url);
} else {
- setWindowState(Qt::WindowFullScreen | Qt::WindowActive);
+ w->addTab(url);
}
}
-void MainWindow::handleTabChanged(WebView *view)
+Window *MainWindow::createSubWindow(const QUrl &url)
{
- Q_CHECK_PTR(view);
+ auto *w = new Window(this);
+ mdiArea->addSubWindow(w);
+ w->showMaximized();
+ w->setFocus();
- disconnect(titleChangedConnection);
- disconnect(newBookmarkConnection);
+ w->addTab(url);
- 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);
-
- m_addressBar->connectWebView(view);
-
- titleChangedConnection = connect(view, &WebView::titleChanged, this, &MainWindow::handleTitleUpdated);
- newBookmarkConnection = connect(view, &WebView::newBookmark, this, [this](const QString &title, const QUrl &url) {
- if(m_bookmarksWidget) {
- auto *bookmark = m_bookmarksWidget->model()->createBookmark(nullptr);
- bookmark->setText(0, title);
- bookmark->setText(1, url.toString());
- }
- });
-
- m_progressBar->connectWebView(view);
-
- // update UI
- this->handleTitleUpdated(view->title());
- centralWidget()->setFocus();
+ return w;
}
-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)
+void MainWindow::closeEvent(QCloseEvent *event)
{
- for(const Browser::Plugin &plugin : plugins) {
- ProfileInterface *iProfilePlugin = qobject_cast<ProfileInterface *>(plugin.pointer);
- if(iProfilePlugin) {
- QWidget *w = iProfilePlugin->createWidget(m_profile.get(), this);
-
- menuBar->profileAction()->setEnabled(true);
- connect(menuBar->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();
- }
- });
+ if(mdiArea->subWindowList().count() > 1) {
+ int choice = QMessageBox::question(this, tr("Close multiple subwindows?"), tr("Do you want to close all subwindows?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ if(choice == QMessageBox::No) {
+ event->ignore();
+ return;
}
}
+
+ mdiArea->closeAllSubWindows();
+ if(mdiArea->currentSubWindow())
+ event->ignore();
+ else
+ event->accept();
}