Falkon Develop
Cross-platform Qt-based web browser
historytreeview.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "historytreeview.h"
19#include "historymodel.h"
20#include "historyitem.h"
21#include "headerview.h"
22#include "mainapplication.h"
23#include "iconprovider.h"
24
25#include <QClipboard>
26#include <QKeyEvent>
27#include <QLineEdit>
28#include <QMenu>
29
31 : QTreeView(parent)
32 , m_history(mApp->history())
33 , m_filter(new HistoryFilterModel(m_history->model()))
34 , m_type(HistoryManagerViewType)
35{
36 setModel(m_filter);
37 setUniformRowHeights(true);
38 setAllColumnsShowFocus(true);
39
40 m_header = new HeaderView(this);
41 m_header->setDefaultSectionSizes(QList<double>() << 0.4 << 0.35 << 0.10 << 0.08);
42 m_header->setSectionHidden(4, true);
43 setHeader(m_header);
44
45 connect(m_filter, &HistoryFilterModel::expandAllItems, this, &QTreeView::expandAll);
46 connect(m_filter, &HistoryFilterModel::collapseAllItems, this, &QTreeView::collapseAll);
47}
48
50{
51 return m_type;
52}
53
55{
56 m_type = type;
57
58 switch (m_type) {
60 setColumnHidden(1, false);
61 setColumnHidden(2, false);
62 setColumnHidden(3, false);
63 setHeaderHidden(false);
64 setMouseTracking(false);
65 setSelectionMode(QAbstractItemView::ExtendedSelection);
66 break;
68 setColumnHidden(1, true);
69 setColumnHidden(2, true);
70 setColumnHidden(3, true);
71 setHeaderHidden(true);
72 setMouseTracking(true);
73 setSelectionMode(QAbstractItemView::SingleSelection);
74 break;
75 default:
76 break;
77 }
78}
79
81{
82 const QList<QModelIndex> indexes = selectionModel()->selectedRows();
83
84 if (indexes.count() != 1)
85 return {};
86
87 // TopLevelItems have invalid (empty) UrlRole data
88 return indexes.at(0).data(HistoryModel::UrlRole).toUrl();
89}
90
92{
93 return m_header;
94}
95
96void HistoryTreeView::search(const QString &string)
97{
98 m_filter->setFilterFixedString(string);
99}
100
102{
103 QList<int> list;
104 QApplication::setOverrideCursor(Qt::WaitCursor);
105
106 QList<QPersistentModelIndex> topLevelIndexes;
107
108 const auto indexes = selectedIndexes();
109 for (const QModelIndex &index : indexes) {
110 if (index.column() > 0) {
111 continue;
112 }
113
114 if ((index.data(HistoryModel::IsTopLevelRole).toBool()) && (m_filter->isPatternEmpty())) {
115 qint64 start = index.data(HistoryModel::TimestampStartRole).toLongLong();
116 qint64 end = index.data(HistoryModel::TimestampEndRole).toLongLong();
117
118 list.append(m_history->indexesFromTimeRange(start, end));
119
120 topLevelIndexes.append(index);
121 }
122 else {
123 int id = index.data(HistoryModel::IdRole).toInt();
124 if (!list.contains(id)) {
125 list.append(id);
126 }
127 }
128 }
129
130 m_history->deleteHistoryEntry(list);
131 m_history->model()->removeTopLevelIndexes(topLevelIndexes);
132
133 QApplication::restoreOverrideCursor();
134}
135
136void HistoryTreeView::contextMenuEvent(QContextMenuEvent* event)
137{
138 Q_EMIT contextMenuRequested(viewport()->mapToGlobal(event->pos()));
139}
140
141void HistoryTreeView::mouseMoveEvent(QMouseEvent* event)
142{
143 QTreeView::mouseMoveEvent(event);
144
145 if (m_type == HistorySidebarViewType) {
146 QCursor cursor = Qt::ArrowCursor;
147 if (event->buttons() == Qt::NoButton) {
148 QModelIndex index = indexAt(event->position().toPoint());
149 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) {
150 cursor = Qt::PointingHandCursor;
151 }
152 }
153 viewport()->setCursor(cursor);
154 }
155}
156
157void HistoryTreeView::mousePressEvent(QMouseEvent* event)
158{
159 QTreeView::mousePressEvent(event);
160
161 if (selectionModel()->selectedRows().count() == 1) {
162 QModelIndex index = indexAt(event->position().toPoint());
163 Qt::MouseButtons buttons = event->buttons();
164 Qt::KeyboardModifiers modifiers = event->modifiers();
165
166 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) {
167 const QUrl url = index.data(HistoryModel::UrlRole).toUrl();
168
169 if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) {
170 Q_EMIT urlShiftActivated(url);
171 }
172 else if (buttons == Qt::MiddleButton || (buttons == Qt::LeftButton && modifiers == Qt::ControlModifier)) {
173 Q_EMIT urlCtrlActivated(url);
174 }
175 }
176 }
177}
178
180{
181 QTreeView::mouseReleaseEvent(event);
182
183 if (selectionModel()->selectedRows().count() == 1) {
184 QModelIndex index = indexAt(event->position().toPoint());
185
186 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) {
187 const QUrl url = index.data(HistoryModel::UrlRole).toUrl();
188
189 // Activate urls with single mouse click in Sidebar
190 if (m_type == HistorySidebarViewType && event->button() == Qt::LeftButton && event->modifiers() == Qt::NoModifier) {
191 Q_EMIT urlActivated(url);
192 }
193 }
194 }
195}
196
198{
199 QTreeView::mouseDoubleClickEvent(event);
200
201 if (selectionModel()->selectedRows().count() == 1) {
202 QModelIndex index = indexAt(event->position().toPoint());
203
204 if (index.isValid() && !index.data(HistoryModel::IsTopLevelRole).toBool()) {
205 const QUrl url = index.data(HistoryModel::UrlRole).toUrl();
206 Qt::MouseButtons buttons = event->buttons();
207 Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
208
209 if (buttons == Qt::LeftButton && modifiers == Qt::NoModifier) {
210 Q_EMIT urlActivated(url);
211 }
212 else if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) {
213 Q_EMIT urlShiftActivated(url);
214 }
215 }
216 }
217}
218
219void HistoryTreeView::keyPressEvent(QKeyEvent* event)
220{
221 QTreeView::keyPressEvent(event);
222
223 if (selectionModel()->selectedRows().count() == 1) {
224 QModelIndex index = selectionModel()->selectedRows().at(0);
225 const QUrl url = index.data(HistoryModel::UrlRole).toUrl();
226 const bool isTopLevel = index.data(HistoryModel::IsTopLevelRole).toBool();
227
228 switch (event->key()) {
229 case Qt::Key_Return:
230 case Qt::Key_Enter:
231 if (isTopLevel && (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::KeypadModifier)) {
232 setExpanded(index, !isExpanded(index));
233 }
234 else {
235 Qt::KeyboardModifiers modifiers = event->modifiers();
236
237 if (modifiers == Qt::NoModifier || modifiers == Qt::KeypadModifier) {
238 Q_EMIT urlActivated(url);
239 }
240 else if (modifiers == Qt::ControlModifier) {
241 Q_EMIT urlCtrlActivated(url);
242 }
243 else if (modifiers == Qt::ShiftModifier) {
244 Q_EMIT urlShiftActivated(url);
245 }
246 }
247 break;
248
249 case Qt::Key_Delete:
251 break;
252 }
253 }
254}
255
256void HistoryTreeView::drawRow(QPainter* painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
257{
258 bool itemTopLevel = index.data(HistoryModel::IsTopLevelRole).toBool();
259 bool iconLoaded = !index.data(HistoryModel::IconRole).value<QIcon>().isNull();
260
261 if (index.isValid() && !itemTopLevel && !iconLoaded) {
262 const QPersistentModelIndex idx = index;
263 model()->setData(idx, IconProvider::iconForUrl(index.data(HistoryModel::UrlRole).toUrl()), HistoryModel::IconRole);
264 }
265
266 QTreeView::drawRow(painter, options, index);
267}
void setDefaultSectionSizes(const QList< double > &sizes)
Definition: headerview.cpp:34
bool isPatternEmpty() const
void setFilterFixedString(const QString &pattern)
QList< int > indexesFromTimeRange(qint64 start, qint64 end)
Definition: history.cpp:209
void deleteHistoryEntry(int index)
Definition: history.cpp:139
HistoryModel * model()
Definition: history.cpp:38
void removeTopLevelIndexes(const QList< QPersistentModelIndex > &indexes)
QUrl selectedUrl() const
void setViewType(ViewType type)
void mousePressEvent(QMouseEvent *event) override
void urlCtrlActivated(const QUrl &url)
void mouseReleaseEvent(QMouseEvent *event) override
void urlShiftActivated(const QUrl &url)
HeaderView * header() const
HistoryTreeView(QWidget *parent=nullptr)
void contextMenuRequested(const QPoint &point)
void keyPressEvent(QKeyEvent *event) override
void drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const override
ViewType viewType() const
void urlActivated(const QUrl &url)
void search(const QString &string)
void contextMenuEvent(QContextMenuEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void mouseDoubleClickEvent(QMouseEvent *event) override
static QIcon iconForUrl(const QUrl &url, bool allowNull=false)
#define mApp