/* * 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/gitea/aqua/smolbote * * SPDX-License-Identifier: GPL-3.0 */ #include "tabwidget.h" #include "browser.h" #include "webengine/webview.h" #include #include #include #include #include "webengine/webprofile.h" #include #include "subwindow.h" inline WebView *createViewFromInfo(TabWidget::TabInformation &tab, QWidget *parent) { auto *view = new WebView(tab.profile, parent); QDataStream stream(&tab.historyBuffer, QIODevice::ReadOnly); stream >> *view->history(); view->history()->goToItem(view->history()->itemAt(tab.historyIndex)); return view; } TabWidget::TabWidget(QWidget *parent) : QTabWidget(parent) { setStyleSheet("QTabBar::tab { width: 200px; }"); setTabsClosable(true); setTabBarAutoHide(true); setElideMode(Qt::ElideRight); setMovable(true); connect(this, &TabWidget::tabCloseRequested, this, &TabWidget::removeTab); // when changing tabs, give focus to the widget // otherwise when closing tabs, the tabwidget will retain focus connect(this, &TabWidget::currentChanged, this, [this](int index) { if(widget(index)) widget(index)->setFocus(); }); // context menu tabContextMenu = new QMenu(this); auto *closeTab = tabContextMenu->addAction(tr("Close Tab")); connect(closeTab, &QAction::triggered, this, [this]() { removeTab(this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos()))); }); auto *closeTabsLeft = tabContextMenu->addAction(tr("Close Tabs left")); connect(closeTabsLeft, &QAction::triggered, this, [this]() { int idx = this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos())); for(int i = idx - 1; i >= 0; --i) { removeTab(i); } }); auto *closeTabsRight = tabContextMenu->addAction(tr("Close Tabs right")); connect(closeTabsRight, &QAction::triggered, this, [this]() { int idx = this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos())); for(int i = count() - 1; i > idx; --i) { removeTab(i); } }); // connect(this, &TabWidget::currentChanged, this, [this](int index) { previous = current; current = index; }); } TabWidget::~TabWidget() { for(int i = count() - 1; i >= 0; i--) { delete widget(i); } } int TabWidget::addTab(WebView *view) { Q_ASSERT_X(view != nullptr, "TabWidget::addTab", "Tried to add null view"); int idx = QTabWidget::addTab(view, view->title()); connect(view, &WebView::titleChanged, [this, view](const QString &title) { int idx = this->indexOf(view); Q_ASSERT(idx != -1); this->setTabText(idx, title); }); connect(view, &WebView::iconChanged, [this, view](const QIcon &icon) { int idx = this->indexOf(view); Q_ASSERT(idx != -1); this->setTabIcon(idx, icon); }); SubWindow::TabData data; tabBar()->setTabData(idx, QVariant::fromValue(data)); return idx; } void TabWidget::removeTab(int index) { // deleting the widget automatically removes the tab? WebView *w = qobject_cast(widget(index)); TabInformation tab; tab.profile = w->profile(); tab.title = w->title(); tab.historyIndex = w->history()->currentItemIndex(); QDataStream stream(&tab.historyBuffer, QIODevice::WriteOnly); stream << *w->history(); m_closedTabs.enqueue(tab); while(m_closedTabs.length() > 5) { m_closedTabs.dequeue(); } setCurrentIndex(previous); QTabWidget::removeTab(index); delete w; } int TabWidget::restoreLastTab() { if(!m_closedTabs.isEmpty()) { TabInformation tab = m_closedTabs.takeLast(); return addTab(createViewFromInfo(tab, this)); } return -1; } void TabWidget::restoreTabMenu(QMenu *menu) { if(m_closedTabs.isEmpty()) return; for(int i = 0; i < m_closedTabs.count(); ++i) { auto *openAction = menu->addAction(m_closedTabs.at(i).title); connect(openAction, &QAction::triggered, this, [this, i]() { TabInformation tab = m_closedTabs.takeAt(i); addTab(createViewFromInfo(tab, this)); }); } menu->addSeparator(); auto *clearTabHistory = menu->addAction(tr("Clear")); connect(clearTabHistory, &QAction::triggered, this, [this]() { m_closedTabs.clear(); }); } void TabWidget::contextMenuEvent(QContextMenuEvent *event) { // check if the context menu was called on a tab int tabIndex = tabBar()->tabAt(event->pos()); if(tabIndex < 0) { return; } tabContextMenu->exec(event->globalPos()); } void TabWidget::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::MiddleButton) { int index = tabBar()->tabAt(event->pos()); if(index >= 0) { removeTab(index); } event->accept(); return; } QTabWidget::mousePressEvent(event); }