File indexing completed on 2024-05-12 04:58:24
0001 /* ============================================================ 0002 * Falkon - Qt web browser 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 "tabmrumodel.h" 0019 #include "tabmodel.h" 0020 #include "webtab.h" 0021 #include "tabwidget.h" 0022 #include "browserwindow.h" 0023 0024 class TabMruModelItem 0025 { 0026 public: 0027 explicit TabMruModelItem(WebTab *tab = nullptr, const QModelIndex &index = QModelIndex()); 0028 ~TabMruModelItem(); 0029 0030 WebTab *tab = nullptr; 0031 QVector<TabMruModelItem*> children; 0032 QPersistentModelIndex sourceIndex; 0033 }; 0034 0035 TabMruModelItem::TabMruModelItem(WebTab *tab, const QModelIndex &index) 0036 : tab(tab) 0037 , sourceIndex(index) 0038 { 0039 } 0040 0041 TabMruModelItem::~TabMruModelItem() 0042 { 0043 qDeleteAll(children); 0044 } 0045 0046 TabMruModel::TabMruModel(BrowserWindow *window, QObject *parent) 0047 : QAbstractProxyModel(parent) 0048 , m_window(window) 0049 { 0050 connect(this, &QAbstractProxyModel::sourceModelChanged, this, &TabMruModel::init); 0051 } 0052 0053 TabMruModel::~TabMruModel() 0054 { 0055 delete m_root; 0056 } 0057 0058 QModelIndex TabMruModel::tabIndex(WebTab *tab) const 0059 { 0060 TabMruModelItem *item = m_items.value(tab); 0061 return item ? createIndex(m_root->children.indexOf(item), 0, item) : QModelIndex(); 0062 } 0063 0064 WebTab *TabMruModel::tab(const QModelIndex &index) const 0065 { 0066 TabMruModelItem *it = item(index); 0067 return it ? it->tab : nullptr; 0068 } 0069 0070 Qt::ItemFlags TabMruModel::flags(const QModelIndex &index) const 0071 { 0072 if (!index.isValid()) { 0073 return Qt::NoItemFlags; 0074 } 0075 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0076 } 0077 0078 int TabMruModel::rowCount(const QModelIndex &parent) const 0079 { 0080 if (parent.isValid()) { 0081 return 0; 0082 } 0083 return m_items.count(); 0084 } 0085 0086 int TabMruModel::columnCount(const QModelIndex &parent) const 0087 { 0088 if (parent.column() > 0) { 0089 return 0; 0090 } 0091 return 1; 0092 } 0093 0094 QModelIndex TabMruModel::parent(const QModelIndex &index) const 0095 { 0096 Q_UNUSED(index) 0097 return {}; 0098 } 0099 0100 QModelIndex TabMruModel::index(int row, int column, const QModelIndex &parent) const 0101 { 0102 if (!hasIndex(row, column, parent)) { 0103 return {}; 0104 } 0105 return createIndex(row, column, m_root->children.at(row)); 0106 } 0107 0108 QModelIndex TabMruModel::mapFromSource(const QModelIndex &sourceIndex) const 0109 { 0110 return tabIndex(sourceIndex.data(TabModel::WebTabRole).value<WebTab*>()); 0111 } 0112 0113 QModelIndex TabMruModel::mapToSource(const QModelIndex &proxyIndex) const 0114 { 0115 TabMruModelItem *it = item(proxyIndex); 0116 if (!it) { 0117 return {}; 0118 } 0119 return it->sourceIndex; 0120 } 0121 0122 void TabMruModel::init() 0123 { 0124 delete m_root; 0125 m_items.clear(); 0126 0127 m_root = new TabMruModelItem; 0128 sourceRowsInserted(QModelIndex(), 0, sourceModel()->rowCount()); 0129 currentTabChanged(m_window->tabWidget()->currentIndex()); 0130 0131 connect(m_window->tabWidget(), &TabWidget::currentChanged, this, &TabMruModel::currentTabChanged, Qt::UniqueConnection); 0132 connect(sourceModel(), &QAbstractItemModel::dataChanged, this, &TabMruModel::sourceDataChanged, Qt::UniqueConnection); 0133 connect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &TabMruModel::sourceRowsInserted, Qt::UniqueConnection); 0134 connect(sourceModel(), &QAbstractItemModel::rowsAboutToBeRemoved, this, &TabMruModel::sourceRowsAboutToBeRemoved, Qt::UniqueConnection); 0135 connect(sourceModel(), &QAbstractItemModel::modelReset, this, &TabMruModel::sourceReset, Qt::UniqueConnection); 0136 } 0137 0138 QModelIndex TabMruModel::index(TabMruModelItem *item) const 0139 { 0140 if (!item || item == m_root) { 0141 return {}; 0142 } 0143 return createIndex(m_root->children.indexOf(item), 0, item); 0144 } 0145 0146 TabMruModelItem *TabMruModel::item(const QModelIndex &index) const 0147 { 0148 return static_cast<TabMruModelItem*>(index.internalPointer()); 0149 } 0150 0151 void TabMruModel::currentTabChanged(int index) 0152 { 0153 TabMruModelItem *it = item(mapFromSource(sourceModel()->index(index, 0))); 0154 if (!it) { 0155 return; 0156 } 0157 const int from = m_root->children.indexOf(it); 0158 if (from == 0) { 0159 return; 0160 } 0161 if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), 0)) { 0162 qWarning() << "Invalid beginMoveRows" << from; 0163 return; 0164 } 0165 m_root->children.removeAt(from); 0166 m_root->children.insert(0, it); 0167 endMoveRows(); 0168 } 0169 0170 void TabMruModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) 0171 { 0172 Q_EMIT dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles); 0173 } 0174 0175 void TabMruModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) 0176 { 0177 for (int i = start; i <= end; ++i) { 0178 const QModelIndex index = sourceModel()->index(i, 0, parent); 0179 auto *tab = index.data(TabModel::WebTabRole).value<WebTab*>(); 0180 if (tab) { 0181 beginInsertRows(QModelIndex(), m_items.count(), m_items.count()); 0182 auto *item = new TabMruModelItem(tab, index); 0183 m_items[tab] = item; 0184 m_root->children.append(item); 0185 endInsertRows(); 0186 } 0187 } 0188 } 0189 0190 void TabMruModel::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0191 { 0192 for (int i = start; i <= end; ++i) { 0193 const QModelIndex index = sourceModel()->index(i, 0, parent); 0194 TabMruModelItem *it = item(mapFromSource(index)); 0195 if (it) { 0196 const int idx = m_root->children.indexOf(it); 0197 beginRemoveRows(QModelIndex(), idx, idx); 0198 m_items.remove(it->tab); 0199 m_root->children.removeAt(idx); 0200 delete it; 0201 endRemoveRows(); 0202 } 0203 } 0204 } 0205 0206 void TabMruModel::sourceReset() 0207 { 0208 beginResetModel(); 0209 init(); 0210 endResetModel(); 0211 }