1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "searchresulttreeview.h"
27 #include "searchresulttreeitemroles.h"
28 #include "searchresulttreemodel.h"
29 #include "searchresulttreeitemdelegate.h"
30 
31 #include <utils/qtcassert.h>
32 
33 #include <QHeaderView>
34 #include <QKeyEvent>
35 #include <QVBoxLayout>
36 
37 namespace Core {
38 namespace Internal {
39 
40 class FilterWidget : public QWidget
41 {
42 public:
FilterWidget(QWidget * parent,QWidget * content)43     FilterWidget(QWidget *parent, QWidget *content) : QWidget(parent, Qt::Popup)
44     {
45         setAttribute(Qt::WA_DeleteOnClose);
46         const auto layout = new QVBoxLayout(this);
47         layout->setContentsMargins(2, 2, 2, 2);
48         layout->setSpacing(2);
49         layout->addWidget(content);
50         setLayout(layout);
51         move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
52     }
53 };
54 
SearchResultTreeView(QWidget * parent)55 SearchResultTreeView::SearchResultTreeView(QWidget *parent)
56     : Utils::TreeView(parent)
57     , m_model(new SearchResultFilterModel(this))
58     , m_autoExpandResults(false)
59 {
60     setModel(m_model);
61     connect(m_model, &SearchResultFilterModel::filterInvalidated,
62             this, &SearchResultTreeView::filterInvalidated);
63 
64     setItemDelegate(new SearchResultTreeItemDelegate(8, this));
65     setIndentation(14);
66     setUniformRowHeights(true);
67     setExpandsOnDoubleClick(true);
68     header()->setSectionResizeMode(QHeaderView::ResizeToContents);
69     header()->setStretchLastSection(false);
70     header()->hide();
71 
72     connect(this, &SearchResultTreeView::activated,
73             this, &SearchResultTreeView::emitJumpToSearchResult);
74 }
75 
setAutoExpandResults(bool expand)76 void SearchResultTreeView::setAutoExpandResults(bool expand)
77 {
78     m_autoExpandResults = expand;
79 }
80 
setTextEditorFont(const QFont & font,const SearchResultColors & colors)81 void SearchResultTreeView::setTextEditorFont(const QFont &font, const SearchResultColors &colors)
82 {
83     m_model->setTextEditorFont(font, colors);
84 
85     QPalette p;
86     p.setColor(QPalette::Base, colors.value(SearchResultColor::Style::Default).textBackground);
87     setPalette(p);
88 }
89 
clear()90 void SearchResultTreeView::clear()
91 {
92     m_model->clear();
93 }
94 
addResults(const QList<SearchResultItem> & items,SearchResult::AddMode mode)95 void SearchResultTreeView::addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode)
96 {
97     QList<QModelIndex> addedParents = m_model->addResults(items, mode);
98     if (m_autoExpandResults && !addedParents.isEmpty()) {
99         foreach (const QModelIndex &index, addedParents)
100             setExpanded(index, true);
101     }
102 }
103 
setFilter(SearchResultFilter * filter)104 void SearchResultTreeView::setFilter(SearchResultFilter *filter)
105 {
106     m_filter = filter;
107     if (m_filter)
108         m_filter->setParent(this);
109     m_model->setFilter(filter);
110     emit filterChanged();
111 }
112 
hasFilter() const113 bool SearchResultTreeView::hasFilter() const
114 {
115     return m_filter;
116 }
117 
showFilterWidget(QWidget * parent)118 void SearchResultTreeView::showFilterWidget(QWidget *parent)
119 {
120     QTC_ASSERT(hasFilter(), return);
121     const auto optionsWidget = new FilterWidget(parent, m_filter->createWidget());
122     optionsWidget->show();
123 }
124 
keyPressEvent(QKeyEvent * event)125 void SearchResultTreeView::keyPressEvent(QKeyEvent *event)
126 {
127     if ((event->key() == Qt::Key_Return
128             || event->key() == Qt::Key_Enter)
129             && event->modifiers() == 0
130             && currentIndex().isValid()
131             && state() != QAbstractItemView::EditingState) {
132         const SearchResultItem item
133             = model()->data(currentIndex(), ItemDataRoles::ResultItemRole).value<SearchResultItem>();
134         emit jumpToSearchResult(item);
135         return;
136     }
137     TreeView::keyPressEvent(event);
138 }
139 
event(QEvent * e)140 bool SearchResultTreeView::event(QEvent *e)
141 {
142     if (e->type() == QEvent::Resize)
143         header()->setMinimumSectionSize(width());
144     return TreeView::event(e);
145 }
146 
emitJumpToSearchResult(const QModelIndex & index)147 void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
148 {
149     if (model()->data(index, ItemDataRoles::IsGeneratedRole).toBool())
150         return;
151     SearchResultItem item = model()->data(index, ItemDataRoles::ResultItemRole).value<SearchResultItem>();
152 
153     emit jumpToSearchResult(item);
154 }
155 
setTabWidth(int tabWidth)156 void SearchResultTreeView::setTabWidth(int tabWidth)
157 {
158     auto delegate = static_cast<SearchResultTreeItemDelegate *>(itemDelegate());
159     delegate->setTabWidth(tabWidth);
160     doItemsLayout();
161 }
162 
model() const163 SearchResultFilterModel *SearchResultTreeView::model() const
164 {
165     return m_model;
166 }
167 
168 } // namespace Internal
169 } // namespace Core
170