File indexing completed on 2024-05-12 04:57:59

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 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 "bookmarkstreeview.h"
0019 #include "bookmarksitemdelegate.h"
0020 #include "bookmarksmodel.h"
0021 #include "bookmarkitem.h"
0022 #include "bookmarks.h"
0023 #include "mainapplication.h"
0024 #include "iconprovider.h"
0025 
0026 #include <QHeaderView>
0027 #include <QMouseEvent>
0028 
0029 BookmarksTreeView::BookmarksTreeView(QWidget* parent)
0030     : QTreeView(parent)
0031     , m_bookmarks(mApp->bookmarks())
0032     , m_model(m_bookmarks->model())
0033     , m_filter(new BookmarksFilterModel(m_model))
0034     , m_type(BookmarksManagerViewType)
0035 {
0036     setModel(m_filter);
0037     setDragEnabled(true);
0038     setAcceptDrops(true);
0039     setUniformRowHeights(true);
0040     setDropIndicatorShown(true);
0041     setAllColumnsShowFocus(true);
0042     setItemDelegate(new BookmarksItemDelegate(this));
0043     header()->resizeSections(QHeaderView::ResizeToContents);
0044 
0045     connect(this, &QTreeView::expanded, this, &BookmarksTreeView::indexExpanded);
0046     connect(this, &QTreeView::collapsed, this, &BookmarksTreeView::indexCollapsed);
0047 }
0048 
0049 BookmarksTreeView::ViewType BookmarksTreeView::viewType() const
0050 {
0051     return m_type;
0052 }
0053 
0054 void BookmarksTreeView::setViewType(BookmarksTreeView::ViewType type)
0055 {
0056     m_type = type;
0057 
0058     switch (m_type) {
0059     case BookmarksManagerViewType:
0060         setColumnHidden(1, false);
0061         setHeaderHidden(false);
0062         setMouseTracking(false);
0063         setSelectionMode(QAbstractItemView::ExtendedSelection);
0064         break;
0065     case BookmarksSidebarViewType:
0066         setColumnHidden(1, true);
0067         setHeaderHidden(true);
0068         setMouseTracking(true);
0069         setSelectionMode(QAbstractItemView::SingleSelection);
0070         break;
0071     default:
0072         break;
0073     }
0074 
0075     restoreExpandedState(QModelIndex());
0076 }
0077 
0078 BookmarkItem* BookmarksTreeView::selectedBookmark() const
0079 {
0080     QList<BookmarkItem*> items = selectedBookmarks();
0081     return items.count() == 1 ? items.at(0) : nullptr;
0082 }
0083 
0084 QList<BookmarkItem*> BookmarksTreeView::selectedBookmarks() const
0085 {
0086     QList<BookmarkItem*> items;
0087 
0088     const auto indexes = selectionModel()->selectedRows();
0089     for (const QModelIndex &index : indexes) {
0090         BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0091         items.append(item);
0092     }
0093 
0094     return items;
0095 }
0096 
0097 void BookmarksTreeView::selectBookmark(BookmarkItem* item)
0098 {
0099     QModelIndex col0 = m_filter->mapFromSource(m_model->index(item, 0));
0100     QModelIndex col1 = m_filter->mapFromSource(m_model->index(item, 1));
0101 
0102     selectionModel()->clearSelection();
0103     selectionModel()->select(col0, QItemSelectionModel::Select);
0104     selectionModel()->select(col1, QItemSelectionModel::Select);
0105 }
0106 
0107 void BookmarksTreeView::ensureBookmarkVisible(BookmarkItem* item)
0108 {
0109     QModelIndex index = m_filter->mapFromSource(m_model->index(item));
0110     QModelIndex parent = m_filter->parent(index);
0111 
0112     while (parent.isValid()) {
0113         setExpanded(parent, true);
0114         parent = m_filter->parent(parent);
0115     }
0116 }
0117 
0118 void BookmarksTreeView::search(const QString &string)
0119 {
0120     m_filter->setFilterFixedString(string);
0121 }
0122 
0123 void BookmarksTreeView::indexExpanded(const QModelIndex &parent)
0124 {
0125     BookmarkItem* item = m_model->item(m_filter->mapToSource(parent));
0126 
0127     switch (m_type) {
0128     case BookmarksManagerViewType:
0129         item->setExpanded(true);
0130         break;
0131     case BookmarksSidebarViewType:
0132         item->setSidebarExpanded(true);
0133         break;
0134     default:
0135         break;
0136     }
0137 }
0138 
0139 void BookmarksTreeView::indexCollapsed(const QModelIndex &parent)
0140 {
0141     BookmarkItem* item = m_model->item(m_filter->mapToSource(parent));
0142 
0143     switch (m_type) {
0144     case BookmarksManagerViewType:
0145         item->setExpanded(false);
0146         break;
0147     case BookmarksSidebarViewType:
0148         item->setSidebarExpanded(false);
0149         break;
0150     default:
0151         break;
0152     }
0153 }
0154 
0155 void BookmarksTreeView::restoreExpandedState(const QModelIndex &parent)
0156 {
0157     for (int i = 0; i < m_filter->rowCount(parent); ++i) {
0158         QModelIndex index = m_filter->index(i, 0, parent);
0159         BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0160         setExpanded(index, m_type == BookmarksManagerViewType ? item->isExpanded() : item->isSidebarExpanded());
0161         restoreExpandedState(index);
0162     }
0163 }
0164 
0165 void BookmarksTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
0166 {
0167     restoreExpandedState(parent);
0168     QTreeView::rowsInserted(parent, start, end);
0169 }
0170 
0171 void BookmarksTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
0172 {
0173     Q_UNUSED(selected)
0174     Q_UNUSED(deselected)
0175 
0176     Q_EMIT bookmarksSelected(selectedBookmarks());
0177 }
0178 
0179 void BookmarksTreeView::contextMenuEvent(QContextMenuEvent* event)
0180 {
0181     Q_EMIT contextMenuRequested(viewport()->mapToGlobal(event->pos()));
0182 }
0183 
0184 void BookmarksTreeView::mouseMoveEvent(QMouseEvent* event)
0185 {
0186     QTreeView::mouseMoveEvent(event);
0187 
0188     if (m_type == BookmarksSidebarViewType) {
0189         QCursor cursor = Qt::ArrowCursor;
0190         if (event->buttons() == Qt::NoButton) {
0191             QModelIndex index = indexAt(event->position().toPoint());
0192             if (index.isValid() && index.data(BookmarksModel::TypeRole).toInt() == BookmarkItem::Url) {
0193                 cursor = Qt::PointingHandCursor;
0194             }
0195         }
0196         viewport()->setCursor(cursor);
0197     }
0198 }
0199 
0200 void BookmarksTreeView::mousePressEvent(QMouseEvent* event)
0201 {
0202     QTreeView::mousePressEvent(event);
0203 
0204     if (selectionModel()->selectedRows().count() == 1) {
0205         QModelIndex index = indexAt(event->position().toPoint());
0206         Qt::MouseButtons buttons = event->buttons();
0207         Qt::KeyboardModifiers modifiers = event->modifiers();
0208 
0209         if (index.isValid()) {
0210             BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0211 
0212             if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) {
0213                 Q_EMIT bookmarkShiftActivated(item);
0214             }
0215             else if (buttons == Qt::MiddleButton || (buttons == Qt::LeftButton && modifiers == Qt::ControlModifier)) {
0216                 Q_EMIT bookmarkCtrlActivated(item);
0217             }
0218         }
0219     }
0220 }
0221 
0222 void BookmarksTreeView::mouseReleaseEvent(QMouseEvent* event)
0223 {
0224     QTreeView::mouseReleaseEvent(event);
0225 
0226     if (selectionModel()->selectedRows().count() == 1) {
0227         QModelIndex index = indexAt(event->position().toPoint());
0228 
0229         if (index.isValid()) {
0230             BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0231 
0232             // Activate bookmarks with single mouse click in Sidebar
0233             if (m_type == BookmarksSidebarViewType && event->button() == Qt::LeftButton && event->modifiers() == Qt::NoModifier) {
0234                 Q_EMIT bookmarkActivated(item);
0235             }
0236         }
0237     }
0238 }
0239 
0240 void BookmarksTreeView::mouseDoubleClickEvent(QMouseEvent* event)
0241 {
0242     QTreeView::mouseDoubleClickEvent(event);
0243 
0244     if (selectionModel()->selectedRows().count() == 1) {
0245         QModelIndex index = indexAt(event->position().toPoint());
0246 
0247         if (index.isValid()) {
0248             BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0249             Qt::MouseButtons buttons = event->buttons();
0250             Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
0251 
0252             if (buttons == Qt::LeftButton && modifiers == Qt::NoModifier) {
0253                 Q_EMIT bookmarkActivated(item);
0254             }
0255             else if (buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) {
0256                 Q_EMIT bookmarkShiftActivated(item);
0257             }
0258         }
0259     }
0260 }
0261 
0262 void BookmarksTreeView::keyPressEvent(QKeyEvent* event)
0263 {
0264     QTreeView::keyPressEvent(event);
0265 
0266     if (selectionModel()->selectedRows().count() == 1) {
0267         QModelIndex index = selectionModel()->selectedRows().at(0);
0268         BookmarkItem* item = m_model->item(m_filter->mapToSource(index));
0269 
0270         switch (event->key()) {
0271         case Qt::Key_Return:
0272         case Qt::Key_Enter:
0273             if (item->isFolder() && (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::KeypadModifier)) {
0274                 setExpanded(index, !isExpanded(index));
0275             }
0276             else {
0277                 Qt::KeyboardModifiers modifiers = event->modifiers();
0278 
0279                 if (modifiers == Qt::NoModifier || modifiers == Qt::KeypadModifier) {
0280                     Q_EMIT bookmarkActivated(item);
0281                 }
0282                 else if (modifiers == Qt::ControlModifier) {
0283                     Q_EMIT bookmarkCtrlActivated(item);
0284                 }
0285                 else if (modifiers == Qt::ShiftModifier) {
0286                     Q_EMIT bookmarkShiftActivated(item);
0287                 }
0288             }
0289             break;
0290         }
0291     }
0292 }