/* * 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: https://neueland.iserlohn-fortress.net/smolbote.hg * * SPDX-License-Identifier: GPL-3.0 */ #include "subwindow.h" #include "browser.h" #include #include "webengine/webview.h" #include "widgets/tabwidget.h" #include #include #include #include #include #include #include #include SubWindow::SubWindow(const QHash &config, QWidget *parent, Qt::WindowFlags flags) : QMdiSubWindow(parent, flags) , tabWidget(new TabWidget(this)) { // delete this window when it closes setAttribute(Qt::WA_DeleteOnClose, true); resize(800, 600); setWidget(tabWidget); profile = WebProfile::defaultProfile(); // system menu { auto *menu = systemMenu(); menu->addSeparator(); auto *profileName_action = menu->addAction(tr("Profile: %1").arg(profile->name())); profileName_action->setEnabled(false); auto *loadProfile_menu = menu->addMenu(tr("Load profile")); Browser *browser = qobject_cast(qApp); Q_CHECK_PTR(browser); for(const QString &name : browser->profiles()) { auto *loadAction = loadProfile_menu->addAction(name); connect(loadAction, &QAction::triggered, this, [name, browser, profileName_action, this]() { auto *profile = browser->profile(name); this->setProfile(profile); profileName_action->setText(tr("Profile: %1").arg(name)); }); } #ifdef QT_DEBUG menu->addSeparator(); menu->addAction(tr("Debug menu"))->setEnabled(false); auto *saveSession_action = menu->addAction(tr("Save session")); menu->addAction(tr("Load session"))->setEnabled(false); setSystemMenu(menu); connect(saveSession_action, &QAction::triggered, [this]() { QJsonDocument doc(session()); qDebug("%s", qUtf8Printable(doc.toJson())); }); #endif } // new tab button auto *newTab_button = new QToolButton(this); newTab_button->setIcon(style()->standardIcon(QStyle::SP_FileIcon)); newTab_button->setToolTip(tr("Add tab")); newTab_button->setShortcut(QKeySequence(config.value("window.shortcuts.new"))); connect(newTab_button, &QToolButton::clicked, this, [=]() { auto index = addTab(WebProfile::defaultProfile()->newtab()); tabWidget->setCurrentIndex(index); }); tabWidget->setCornerWidget(newTab_button, Qt::TopRightCorner); // general actions auto *closeTab_shortcut = new QShortcut(QKeySequence(config.value("window.shortcuts.close")), this); connect(closeTab_shortcut, &QShortcut::activated, this, [=]() { tabWidget->deleteTab(tabWidget->currentIndex()); }); auto *leftTab_shortcut = new QShortcut(QKeySequence(config.value("window.shortcuts.left")), this); connect(leftTab_shortcut, &QShortcut::activated, this, [=]() { tabWidget->setCurrentIndex(qMax(0, tabWidget->currentIndex() - 1)); }); auto *rightTab_shortcut = new QShortcut(QKeySequence(config.value("window.shortcuts.right")), this); connect(rightTab_shortcut, &QShortcut::activated, this, [=]() { tabWidget->setCurrentIndex(qMin(tabWidget->currentIndex() + 1, tabWidget->count() - 1)); }); connect(tabWidget, &TabWidget::currentChanged, [this](int index) { if(index < 0) { // last tab has been closed close(); } else { auto *view = dynamic_cast(tabWidget->widget(index)); Q_CHECK_PTR(view); disconnect(titleConnection); disconnect(linkHoveredConnection); titleConnection = connect(view, &WebView::titleChanged, this, [this](const QString &title) { auto *v = qobject_cast(sender()); this->setWindowTitle(QString("%1 :%2").arg(title, v->profile()->name())); }); setWindowTitle(QString("%1 :%2").arg(view->title(), view->profile()->name())); linkHoveredConnection = connect(view->page(), &WebPage::linkHovered, this, [this](const QString &url) { if(!url.isEmpty()) emit showStatusMessage(url, 3000); }); emit currentViewChanged(view); } }); } SubWindow::~SubWindow() { delete tabWidget; } WebView *SubWindow::currentView() { return qobject_cast(tabWidget->currentWidget()); } WebView *SubWindow::view(int index) const { return qobject_cast(tabWidget->widget(index)); } void SubWindow::setProfile(WebProfile *profile) { Q_CHECK_PTR(profile); this->profile = profile; for(int i = 0; i < tabWidget->count(); ++i) { auto *view = qobject_cast(tabWidget->widget(i)); view->setProfile(profile); } } int SubWindow::addTab(const QUrl &url) { auto *view = new WebView(profile, this); if(!url.isEmpty()) view->load(url); return tabWidget->addTab(view); } void SubWindow::setCurrentTab(int index) { tabWidget->setCurrentIndex(index); } QJsonObject SubWindow::session() const { QJsonObject obj; obj.insert("profile", QJsonValue("")); QJsonArray tabs; for(int i = 0; i < tabWidget->count(); ++i) { auto *view = qobject_cast(tabWidget->widget(i)); if(view) { tabs.append(view->url().toString()); } } obj.insert("tabs", tabs); return obj; } void SubWindow::restoreSession(const QJsonObject &sessionData) { auto *browser = qobject_cast(qApp); Q_CHECK_PTR(browser); Q_ASSERT_X(sessionData.value("profile") != QJsonValue::Undefined, "Window::restoreSession", "no profile in json"); if(browser->profiles().contains(sessionData.value("profile").toString())) profile = browser->profile(sessionData.value("profile").toString()); Q_ASSERT_X(sessionData.value("tabs") != QJsonValue::Undefined, "Window::restoreSession", "no tabs in json"); const QJsonArray tabs = sessionData.value("tabs").toArray(); if(tabs.count() == 0) { // open a newtab auto *view = new WebView(profile, this); view->load(profile->newtab()); tabWidget->addTab(view); return; } for(const auto &tab : tabs) { auto *view = new WebView(profile, this); view->load(QUrl::fromUserInput(tab.toString())); tabWidget->addTab(view); } }