File indexing completed on 2024-05-19 04:59:22
0001 /* ============================================================ 0002 * VerticalTabs plugin for Falkon 0003 * Copyright (C) 2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "verticaltabswidget.h" 0019 #include "tabtreeview.h" 0020 #include "tablistview.h" 0021 #include "tabfiltermodel.h" 0022 0023 #include "webtab.h" 0024 #include "tabmodel.h" 0025 #include "tabwidget.h" 0026 #include "toolbutton.h" 0027 #include "tabtreemodel.h" 0028 #include "browserwindow.h" 0029 0030 #include <QListView> 0031 #include <QScrollBar> 0032 #include <QVBoxLayout> 0033 #include <QWheelEvent> 0034 0035 VerticalTabsWidget::VerticalTabsWidget(BrowserWindow *window) 0036 : QWidget() 0037 , m_window(window) 0038 { 0039 auto *layout = new QVBoxLayout(this); 0040 layout->setSpacing(0); 0041 layout->setContentsMargins(0, 0, 0, 0); 0042 0043 m_pinnedView = new TabListView(m_window, this); 0044 auto *model = new TabFilterModel(m_pinnedView); 0045 model->setFilterPinnedTabs(false); 0046 model->setRejectDropOnLastIndex(true); 0047 model->setSourceModel(m_window->tabModel()); 0048 m_pinnedView->setModel(model); 0049 m_pinnedView->setHideWhenEmpty(true); 0050 0051 m_normalView = new TabTreeView(m_window, this); 0052 m_pinnedView->setFocusProxy(m_normalView); 0053 0054 auto *buttonAddTab = new ToolButton(this); 0055 buttonAddTab->setObjectName(QSL("verticaltabs-button-addtab")); 0056 buttonAddTab->setAutoRaise(true); 0057 buttonAddTab->setFocusPolicy(Qt::NoFocus); 0058 buttonAddTab->setToolTip(tr("New Tab")); 0059 buttonAddTab->setIcon(QIcon::fromTheme(QSL("list-add"))); 0060 buttonAddTab->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 0061 connect(buttonAddTab, &QAbstractButton::clicked, m_window, &BrowserWindow::addTab); 0062 connect(buttonAddTab, &ToolButton::middleMouseClicked, this, &VerticalTabsWidget::addChildTab); 0063 0064 m_groupMenu = new QMenu(this); 0065 buttonAddTab->setMenu(m_groupMenu); 0066 connect(m_groupMenu, &QMenu::aboutToShow, this, &VerticalTabsWidget::updateGroupMenu); 0067 0068 layout->addWidget(m_pinnedView); 0069 layout->addWidget(m_normalView); 0070 layout->addWidget(buttonAddTab); 0071 } 0072 0073 void VerticalTabsWidget::setViewType(VerticalTabsPlugin::ViewType type) 0074 { 0075 auto *model = new TabFilterModel(m_normalView); 0076 model->setFilterPinnedTabs(true); 0077 0078 delete m_normalView->model(); 0079 0080 switch (type) { 0081 case VerticalTabsPlugin::TabListView: 0082 model->setSourceModel(m_window->tabModel()); 0083 m_normalView->setModel(model); 0084 m_normalView->setTabsInOrder(true); 0085 m_normalView->setHaveTreeModel(false); 0086 break; 0087 0088 case VerticalTabsPlugin::TabTreeView: 0089 m_treeModel = new TabTreeModel(m_window, model); 0090 m_treeModel->setSourceModel(m_window->tabModel()); 0091 model->setSourceModel(m_treeModel); 0092 m_normalView->setModel(model); 0093 m_normalView->setTabsInOrder(false); 0094 m_normalView->setHaveTreeModel(true); 0095 break; 0096 0097 default: 0098 break; 0099 }; 0100 } 0101 0102 void VerticalTabsWidget::switchToNextTab() 0103 { 0104 WebTab *tab = nextTab(); 0105 if (tab) { 0106 tab->makeCurrentTab(); 0107 } 0108 } 0109 0110 void VerticalTabsWidget::switchToPreviousTab() 0111 { 0112 WebTab *tab = previousTab(); 0113 if (tab) { 0114 tab->makeCurrentTab(); 0115 } 0116 } 0117 0118 WebTab *VerticalTabsWidget::nextTab() const 0119 { 0120 QModelIndex next; 0121 if (m_window->tabWidget()->webTab()->isPinned()) { 0122 next = m_pinnedView->indexAfter(m_pinnedView->currentIndex()); 0123 if (!next.isValid()) { 0124 next = m_normalView->model()->index(0, 0); 0125 } 0126 } else { 0127 next = m_normalView->indexBelow(m_normalView->currentIndex()); 0128 if (!next.isValid()) { 0129 next = m_pinnedView->model()->index(0, 0); 0130 } 0131 } 0132 return next.data(TabModel::WebTabRole).value<WebTab*>(); 0133 } 0134 0135 WebTab *VerticalTabsWidget::previousTab() const 0136 { 0137 QModelIndex previous; 0138 if (m_window->tabWidget()->webTab()->isPinned()) { 0139 previous = m_pinnedView->indexBefore(m_pinnedView->currentIndex()); 0140 if (!previous.isValid()) { 0141 previous = m_normalView->model()->index(m_normalView->model()->rowCount() - 1, 0); 0142 while (previous.isValid()) { 0143 const QModelIndex below = m_normalView->indexBelow(previous); 0144 if (below.isValid()) { 0145 previous = below; 0146 } else { 0147 break; 0148 } 0149 } 0150 } 0151 } else { 0152 previous = m_normalView->indexAbove(m_normalView->currentIndex()); 0153 if (!previous.isValid()) { 0154 previous = m_pinnedView->model()->index(m_pinnedView->model()->rowCount() - 1, 0); 0155 } 0156 } 0157 return previous.data(TabModel::WebTabRole).value<WebTab*>(); 0158 } 0159 0160 void VerticalTabsWidget::wheelEvent(QWheelEvent *event) 0161 { 0162 if (m_normalView->verticalScrollBar()->isVisible()) { 0163 return; 0164 } 0165 0166 m_wheelHelper.processEvent(event); 0167 while (WheelHelper::Direction direction = m_wheelHelper.takeDirection()) { 0168 switch (direction) { 0169 case WheelHelper::WheelUp: 0170 case WheelHelper::WheelLeft: 0171 switchToPreviousTab(); 0172 break; 0173 0174 case WheelHelper::WheelDown: 0175 case WheelHelper::WheelRight: 0176 switchToNextTab(); 0177 break; 0178 0179 default: 0180 break; 0181 } 0182 } 0183 event->accept(); 0184 } 0185 0186 void VerticalTabsWidget::updateGroupMenu() 0187 { 0188 m_groupMenu->clear(); 0189 0190 for (int i = 0; i < m_window->tabWidget()->count(); ++i) { 0191 WebTab *tab = m_window->tabWidget()->webTab(i); 0192 if (tab->url().toString(QUrl::RemoveFragment) == QL1S("extension://verticaltabs/group")) { 0193 m_groupMenu->addAction(tab->url().fragment(), this, [=]() { 0194 QMetaObject::invokeMethod(m_window, "addTab"); 0195 m_window->tabWidget()->webTab()->setParentTab(tab); 0196 }); 0197 } 0198 } 0199 0200 m_groupMenu->addSeparator(); 0201 m_groupMenu->addAction(tr("Add New Group..."), this, [this]() { 0202 m_window->tabWidget()->addView(QUrl(QSL("extension://verticaltabs/group")), Qz::NT_SelectedTab); 0203 }); 0204 } 0205 0206 void VerticalTabsWidget::addChildTab() 0207 { 0208 WebTab *tab = m_window->tabWidget()->webTab(); 0209 m_window->addTab(); 0210 m_window->tabWidget()->webTab()->setParentTab(tab); 0211 }