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
14using namespace KTextEditor;
15
16void KateArgumentHintModel::clear()
17{
18 m_rows.clear();
19}
20
21QModelIndex 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
42void KateArgumentHintModel::parentModelReset()
43{
44 clear();
45 buildRows();
46}
47
48void 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
75KateArgumentHintModel::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
83QVariant 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
153int KateArgumentHintModel::rowCount(const QModelIndex &) const
154{
155 return m_rows.size();
156}
157
158KateCompletionModel::Group *KateArgumentHintModel::group() const
159{
160 return m_parent->m_argumentHints;
161}
162
163void 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

source code of ktexteditor/src/completion/kateargumenthintmodel.cpp