1 | /* |
2 | SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #include "kateargumenthintmodel.h" |
8 | #include "katecompletionmodel.h" |
9 | #include "katepartdebug.h" |
10 | #include <ktexteditor/codecompletionmodel.h> |
11 | |
12 | #include <QTextFormat> |
13 | |
14 | using namespace KTextEditor; |
15 | |
16 | void KateArgumentHintModel::clear() |
17 | { |
18 | m_rows.clear(); |
19 | } |
20 | |
21 | QModelIndex KateArgumentHintModel::mapToSource(const QModelIndex &index) const |
22 | { |
23 | if (size_t(index.row()) >= m_rows.size()) { |
24 | return QModelIndex(); |
25 | } |
26 | |
27 | if (m_rows[index.row()] < 0 || m_rows[index.row()] >= (int)group()->filtered.size()) { |
28 | return QModelIndex(); |
29 | } |
30 | |
31 | KateCompletionModel::ModelRow source = group()->filtered[m_rows[index.row()]].sourceRow(); |
32 | if (!source.first) { |
33 | qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Row does not exist in source" ; |
34 | return QModelIndex(); |
35 | } |
36 | |
37 | QModelIndex sourceIndex = source.second.sibling(arow: source.second.row(), acolumn: index.column()); |
38 | |
39 | return sourceIndex; |
40 | } |
41 | |
42 | void KateArgumentHintModel::parentModelReset() |
43 | { |
44 | clear(); |
45 | buildRows(); |
46 | } |
47 | |
48 | void KateArgumentHintModel::buildRows() |
49 | { |
50 | beginResetModel(); |
51 | |
52 | m_rows.clear(); |
53 | std::map<int, std::vector<int>> m_depths; // Map each hint-depth to a list of functions of that depth |
54 | for (int a = 0; a < (int)group()->filtered.size(); a++) { |
55 | KateCompletionModel::ModelRow source = group()->filtered[a].sourceRow(); |
56 | QModelIndex sourceIndex = source.second.sibling(arow: source.second.row(), acolumn: 0); |
57 | QVariant v = sourceIndex.data(arole: CodeCompletionModel::ArgumentHintDepth); |
58 | if (v.userType() == QMetaType::Int) { |
59 | std::vector<int> &lst(m_depths[v.toInt()]); |
60 | lst.push_back(x: a); |
61 | } |
62 | } |
63 | |
64 | for (const auto &[key, value] : m_depths) { |
65 | for (int row : value) { |
66 | m_rows.insert(position: m_rows.begin(), x: row); // Insert filtered in reversed order |
67 | } |
68 | } |
69 | |
70 | endResetModel(); |
71 | |
72 | Q_EMIT contentStateChanged(hasContent: !m_rows.empty()); |
73 | } |
74 | |
75 | KateArgumentHintModel::KateArgumentHintModel(KateCompletionModel *parent) |
76 | : QAbstractListModel(parent) |
77 | , m_parent(parent) |
78 | { |
79 | connect(sender: parent, signal: &KateCompletionModel::modelReset, context: this, slot: &KateArgumentHintModel::parentModelReset); |
80 | connect(sender: parent, signal: &KateCompletionModel::argumentHintsChanged, context: this, slot: &KateArgumentHintModel::parentModelReset); |
81 | } |
82 | |
83 | QVariant KateArgumentHintModel::data(const QModelIndex &index, int role) const |
84 | { |
85 | if (size_t(index.row()) >= m_rows.size()) { |
86 | // qCDebug(LOG_KTE) << "KateArgumentHintModel::data: index out of bound: " << index.row() << " total filtered: " << m_rows.count(); |
87 | return QVariant(); |
88 | } |
89 | |
90 | if (m_rows[index.row()] < 0 || m_rows[index.row()] >= (int)group()->filtered.size()) { |
91 | qCDebug(LOG_KTE) << "KateArgumentHintModel::data: index out of bound: " << m_rows[index.row()] << " total filtered: " << (int)group()->filtered.size(); |
92 | return QVariant(); |
93 | } |
94 | |
95 | KateCompletionModel::ModelRow source = group()->filtered[m_rows[index.row()]].sourceRow(); |
96 | if (!source.first) { |
97 | qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Row does not exist in source" ; |
98 | return QVariant(); |
99 | } |
100 | |
101 | QModelIndex sourceIndex = source.second.sibling(arow: source.second.row(), acolumn: index.column()); |
102 | |
103 | if (!sourceIndex.isValid()) { |
104 | qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Source-index is not valid" ; |
105 | return QVariant(); |
106 | } |
107 | |
108 | switch (role) { |
109 | case Qt::DisplayRole: { |
110 | // Construct the text |
111 | QString totalText; |
112 | for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) { |
113 | if (a != CodeCompletionModel::Scope) { // Skip the scope |
114 | totalText += source.second.sibling(arow: source.second.row(), acolumn: a).data(arole: Qt::DisplayRole).toString() + QLatin1Char(' '); |
115 | } |
116 | } |
117 | |
118 | return QVariant(totalText); |
119 | } |
120 | case CodeCompletionModel::HighlightingMethod: { |
121 | // Return that we are doing custom-highlighting of one of the sub-strings does it |
122 | for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) { |
123 | QVariant method = source.second.sibling(arow: source.second.row(), acolumn: a).data(arole: CodeCompletionModel::HighlightingMethod); |
124 | if (method.userType() == QMetaType::Int && method.toInt() == CodeCompletionModel::CustomHighlighting) { |
125 | return QVariant(CodeCompletionModel::CustomHighlighting); |
126 | } |
127 | } |
128 | |
129 | return QVariant(); |
130 | } |
131 | case CodeCompletionModel::CustomHighlight: { |
132 | QStringList strings; |
133 | |
134 | // Collect strings |
135 | for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) { |
136 | strings << source.second.sibling(arow: source.second.row(), acolumn: a).data(arole: Qt::DisplayRole).toString(); |
137 | } |
138 | |
139 | QList<QVariantList> highlights; |
140 | |
141 | // Collect custom-highlightings |
142 | for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) { |
143 | highlights << source.second.sibling(arow: source.second.row(), acolumn: a).data(arole: CodeCompletionModel::CustomHighlight).toList(); |
144 | } |
145 | |
146 | return mergeCustomHighlighting(strings, highlights, gapBetweenStrings: 1); |
147 | } |
148 | } |
149 | |
150 | return {}; |
151 | } |
152 | |
153 | int KateArgumentHintModel::rowCount(const QModelIndex &) const |
154 | { |
155 | return m_rows.size(); |
156 | } |
157 | |
158 | KateCompletionModel::Group *KateArgumentHintModel::group() const |
159 | { |
160 | return m_parent->m_argumentHints; |
161 | } |
162 | |
163 | void KateArgumentHintModel::emitDataChanged(const QModelIndex &start, const QModelIndex &end) |
164 | { |
165 | Q_EMIT dataChanged(topLeft: start, bottomRight: end); |
166 | } |
167 | |
168 | #include "moc_kateargumenthintmodel.cpp" |
169 | |