File indexing completed on 2024-05-12 04:58:06
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2010-2014 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 "historytreeview.h" 0019 #include "historymodel.h" 0020 #include "historyitem.h" 0021 #include "headerview.h" 0022 #include "mainapplication.h" 0023 #include "iconprovider.h" 0024 0025 #include <QClipboard> 0026 #include <QKeyEvent> 0027 #include <QLineEdit> 0028 #include <QMenu> 0029 0030 HistoryTreeView::HistoryTreeView(QWidget* parent) 0031 : QTreeView(parent) 0032 , m_history(mApp->history()) 0033 , m_filter(new HistoryFilterModel(m_history->model())) 0034 , m_type(HistoryManagerViewType) 0035 { 0036 setModel(m_filter); 0037 setUniformRowHeights(true); 0038 setAllColumnsShowFocus(true); 0039 0040 m_header = new HeaderView(this); 0041 m_header->setDefaultSectionSizes(QList<double>() << 0.4 << 0.35 << 0.10 << 0.08); 0042 m_header->setSectionHidden(4, true); 0043 setHeader(m_header); 0044 0045 connect(m_filter, &HistoryFilterModel::expandAllItems, this, &QTreeView::expandAll); 0046 connect(m_filter, &HistoryFilterModel::collapseAllItems, this, &QTreeView::collapseAll); 0047 } 0048 0049 HistoryTreeView::ViewType HistoryTreeView::viewType() const 0050 { 0051 return m_type; 0052 } 0053 0054 void HistoryTreeView::setViewType(HistoryTreeView::ViewType type) 0055 { 0056 m_type = type; 0057 0058 switch (m_type) { 0059 case HistoryManagerViewType: 0060 setColumnHidden(1, false); 0061 setColumnHidden(2, false); 0062 setColumnHidden(3, false); 0063 setHeaderHidden(false); 0064 setMouseTracking(false); 0065 setSelectionMode(QAbstractItemView::ExtendedSelection); 0066 break; 0067 case HistorySidebarViewType: 0068 setColumnHidden(1, true); 0069 setColumnHidden(2, true); 0070 setColumnHidden(3, true); 0071 setHeaderHidden(true); 0072 setMouseTracking(true); 0073 setSelectionMode(QAbstractItemView::SingleSelection); 0074 break; 0075 default: 0076 break; 0077 } 0078 } 0079 0080 QUrl HistoryTreeView::selectedUrl() const 0081 { 0082 const QList<QModelIndex> indexes = selectionModel()->selectedRows(); 0083 0084 if (indexes.count() != 1) 0085 return {}; 0086 0087 // TopLevelItems have invalid (empty) UrlRole data 0088 return indexes.at(0).data(HistoryModel::UrlRole).toUrl(); 0089 } 0090 0091 HeaderView* HistoryTreeView::header() const 0092 { 0093 return m_header; 0094 } 0095 0096 void HistoryTreeView::search(const QString &string) 0097 { 0098 m_filter->setFilterFixedString(string); 0099 } 0100 0101 void HistoryTreeView::removeSelectedItems() 0102 { 0103 QList<int> list; 0104 QApplication::setOverrideCursor(Qt::WaitCursor); 0105 0106 QList<QPersistentModelIndex> topLevelIndexes; 0107 0108 const auto indexes = selectedIndexes(); 0109 for (const QModelIndex &index : indexes) { 0110 if (index.column() > 0) { 0111 continue; 0112 } 0113 0114 if ((index.data(HistoryModel::IsTopLevelRole).toBool()) && (m_filter->isPatternEmpty())) { 0115 qint64 start = index.data(HistoryModel::TimestampStartRole).toLongLong(); 0116 qint64 end = index.data(HistoryModel::TimestampEndRole).toLongLong(); 0117 0118 list.append(m_history->indexesFromTimeRange(start, end)); 0119 0120 topLevelIndexes.append(index); 0121 } 0122 else { 0123 int id = index.data(HistoryModel::IdRole).toInt(); 0124 if (!list.contains(id)) { 0125 list.append(id); 0126 } 0127 } 0128 } 0129 0130 m_history->deleteHistoryEntry(list); 0131 m_history->model()->removeTopLevelIndexes(topLevelIndexes); 0132 0133 QApplication::restoreOverrideCursor(); 0134 } 0135 0136 void HistoryTreeView::contextMenuEvent(QContextMenuEvent* event) 0137 { 0138 Q_EMIT contextMenuRequested(viewport()->mapToGlobal(event->pos())); 0139 } 0140 0141 void HistoryTreeView::mouseMoveEvent(QMouseEvent* event) 0142 { 0143 QTreeView::mouseMoveEvent(event); 0144 0145 if (m_type == HistorySidebarViewType) { 0146 QCursor cursor = Qt::ArrowCursor; 0147 if (event->buttons() == Qt::NoButton) { 0148 QModelIndex index = indexAt(event->position().toPoint()); 0149 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) { 0150 cursor = Qt::PointingHandCursor; 0151 } 0152 } 0153 viewport()->setCursor(cursor); 0154 } 0155 } 0156 0157 void HistoryTreeView::mousePressEvent(QMouseEvent* event) 0158 { 0159 QTreeView::mousePressEvent(event); 0160 0161 if (selectionModel()->selectedRows().count() == 1) { 0162 QModelIndex index = indexAt(event->position().toPoint()); 0163 Qt::MouseButtons buttons = event->buttons(); 0164 Qt::KeyboardModifiers modifiers = event->modifiers(); 0165 0166 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) { 0167 const QUrl url = index.data(HistoryModel::UrlRole).toUrl(); 0168 0169 if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) { 0170 Q_EMIT urlShiftActivated(url); 0171 } 0172 else if (buttons == Qt::MiddleButton || (buttons == Qt::LeftButton && modifiers == Qt::ControlModifier)) { 0173 Q_EMIT urlCtrlActivated(url); 0174 } 0175 } 0176 } 0177 } 0178 0179 void HistoryTreeView::mouseReleaseEvent(QMouseEvent* event) 0180 { 0181 QTreeView::mouseReleaseEvent(event); 0182 0183 if (selectionModel()->selectedRows().count() == 1) { 0184 QModelIndex index = indexAt(event->position().toPoint()); 0185 0186 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) { 0187 const QUrl url = index.data(HistoryModel::UrlRole).toUrl(); 0188 0189 // Activate urls with single mouse click in Sidebar 0190 if (m_type == HistorySidebarViewType && event->button() == Qt::LeftButton && event->modifiers() == Qt::NoModifier) { 0191 Q_EMIT urlActivated(url); 0192 } 0193 } 0194 } 0195 } 0196 0197 void HistoryTreeView::mouseDoubleClickEvent(QMouseEvent* event) 0198 { 0199 QTreeView::mouseDoubleClickEvent(event); 0200 0201 if (selectionModel()->selectedRows().count() == 1) { 0202 QModelIndex index = indexAt(event->position().toPoint()); 0203 0204 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) { 0205 const QUrl url = index.data(HistoryModel::UrlRole).toUrl(); 0206 Qt::MouseButtons buttons = event->buttons(); 0207 Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); 0208 0209 if (buttons == Qt::LeftButton && modifiers == Qt::NoModifier) { 0210 Q_EMIT urlActivated(url); 0211 } 0212 else if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) { 0213 Q_EMIT urlShiftActivated(url); 0214 } 0215 } 0216 } 0217 } 0218 0219 void HistoryTreeView::keyPressEvent(QKeyEvent* event) 0220 { 0221 QTreeView::keyPressEvent(event); 0222 0223 if (selectionModel()->selectedRows().count() == 1) { 0224 QModelIndex index = selectionModel()->selectedRows().at(0); 0225 const QUrl url = index.data(HistoryModel::UrlRole).toUrl(); 0226 const bool isTopLevel = index.data(HistoryModel::IsTopLevelRole).toBool(); 0227 0228 switch (event->key()) { 0229 case Qt::Key_Return: 0230 case Qt::Key_Enter: 0231 if (isTopLevel && (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::KeypadModifier)) { 0232 setExpanded(index, !isExpanded(index)); 0233 } 0234 else { 0235 Qt::KeyboardModifiers modifiers = event->modifiers(); 0236 0237 if (modifiers == Qt::NoModifier || modifiers == Qt::KeypadModifier) { 0238 Q_EMIT urlActivated(url); 0239 } 0240 else if (modifiers == Qt::ControlModifier) { 0241 Q_EMIT urlCtrlActivated(url); 0242 } 0243 else if (modifiers == Qt::ShiftModifier) { 0244 Q_EMIT urlShiftActivated(url); 0245 } 0246 } 0247 break; 0248 0249 case Qt::Key_Delete: 0250 removeSelectedItems(); 0251 break; 0252 } 0253 } 0254 } 0255 0256 void HistoryTreeView::drawRow(QPainter* painter, const QStyleOptionViewItem &options, const QModelIndex &index) const 0257 { 0258 bool itemTopLevel = index.data(HistoryModel::IsTopLevelRole).toBool(); 0259 bool iconLoaded = !index.data(HistoryModel::IconRole).value<QIcon>().isNull(); 0260 0261 if (index.isValid() && !itemTopLevel && !iconLoaded) { 0262 const QPersistentModelIndex idx = index; 0263 model()->setData(idx, IconProvider::iconForUrl(index.data(HistoryModel::UrlRole).toUrl()), HistoryModel::IconRole); 0264 } 0265 0266 QTreeView::drawRow(painter, options, index); 0267 }