File indexing completed on 2024-04-14 03:55:01

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "kateargumenthintmodel.h"
0008 #include "katecompletionmodel.h"
0009 #include "katepartdebug.h"
0010 #include <ktexteditor/codecompletionmodel.h>
0011 
0012 #include <QTextFormat>
0013 
0014 using namespace KTextEditor;
0015 
0016 void KateArgumentHintModel::clear()
0017 {
0018     m_rows.clear();
0019 }
0020 
0021 QModelIndex KateArgumentHintModel::mapToSource(const QModelIndex &index) const
0022 {
0023     if (size_t(index.row()) >= m_rows.size()) {
0024         return QModelIndex();
0025     }
0026 
0027     if (m_rows[index.row()] < 0 || m_rows[index.row()] >= (int)group()->filtered.size()) {
0028         return QModelIndex();
0029     }
0030 
0031     KateCompletionModel::ModelRow source = group()->filtered[m_rows[index.row()]].sourceRow();
0032     if (!source.first) {
0033         qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Row does not exist in source";
0034         return QModelIndex();
0035     }
0036 
0037     QModelIndex sourceIndex = source.second.sibling(source.second.row(), index.column());
0038 
0039     return sourceIndex;
0040 }
0041 
0042 void KateArgumentHintModel::parentModelReset()
0043 {
0044     clear();
0045     buildRows();
0046 }
0047 
0048 void KateArgumentHintModel::buildRows()
0049 {
0050     beginResetModel();
0051 
0052     m_rows.clear();
0053     std::map<int, std::vector<int>> m_depths; // Map each hint-depth to a list of functions of that depth
0054     for (int a = 0; a < (int)group()->filtered.size(); a++) {
0055         KateCompletionModel::ModelRow source = group()->filtered[a].sourceRow();
0056         QModelIndex sourceIndex = source.second.sibling(source.second.row(), 0);
0057         QVariant v = sourceIndex.data(CodeCompletionModel::ArgumentHintDepth);
0058         if (v.userType() == QMetaType::Int) {
0059             std::vector<int> &lst(m_depths[v.toInt()]);
0060             lst.push_back(a);
0061         }
0062     }
0063 
0064     for (const auto &[key, value] : m_depths) {
0065         for (int row : value) {
0066             m_rows.insert(m_rows.begin(), row); // Insert filtered in reversed order
0067         }
0068     }
0069 
0070     endResetModel();
0071 
0072     Q_EMIT contentStateChanged(!m_rows.empty());
0073 }
0074 
0075 KateArgumentHintModel::KateArgumentHintModel(KateCompletionModel *parent)
0076     : QAbstractListModel(parent)
0077     , m_parent(parent)
0078 {
0079     connect(parent, &KateCompletionModel::modelReset, this, &KateArgumentHintModel::parentModelReset);
0080     connect(parent, &KateCompletionModel::argumentHintsChanged, this, &KateArgumentHintModel::parentModelReset);
0081 }
0082 
0083 QVariant KateArgumentHintModel::data(const QModelIndex &index, int role) const
0084 {
0085     if (size_t(index.row()) >= m_rows.size()) {
0086         // qCDebug(LOG_KTE) << "KateArgumentHintModel::data: index out of bound: " << index.row() << " total filtered: " << m_rows.count();
0087         return QVariant();
0088     }
0089 
0090     if (m_rows[index.row()] < 0 || m_rows[index.row()] >= (int)group()->filtered.size()) {
0091         qCDebug(LOG_KTE) << "KateArgumentHintModel::data: index out of bound: " << m_rows[index.row()] << " total filtered: " << (int)group()->filtered.size();
0092         return QVariant();
0093     }
0094 
0095     KateCompletionModel::ModelRow source = group()->filtered[m_rows[index.row()]].sourceRow();
0096     if (!source.first) {
0097         qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Row does not exist in source";
0098         return QVariant();
0099     }
0100 
0101     QModelIndex sourceIndex = source.second.sibling(source.second.row(), index.column());
0102 
0103     if (!sourceIndex.isValid()) {
0104         qCDebug(LOG_KTE) << "KateArgumentHintModel::data: Source-index is not valid";
0105         return QVariant();
0106     }
0107 
0108     switch (role) {
0109     case Qt::DisplayRole: {
0110         // Construct the text
0111         QString totalText;
0112         for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) {
0113             if (a != CodeCompletionModel::Scope) { // Skip the scope
0114                 totalText += source.second.sibling(source.second.row(), a).data(Qt::DisplayRole).toString() + QLatin1Char(' ');
0115             }
0116         }
0117 
0118         return QVariant(totalText);
0119     }
0120     case CodeCompletionModel::HighlightingMethod: {
0121         // Return that we are doing custom-highlighting of one of the sub-strings does it
0122         for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) {
0123             QVariant method = source.second.sibling(source.second.row(), a).data(CodeCompletionModel::HighlightingMethod);
0124             if (method.userType() == QMetaType::Int && method.toInt() == CodeCompletionModel::CustomHighlighting) {
0125                 return QVariant(CodeCompletionModel::CustomHighlighting);
0126             }
0127         }
0128 
0129         return QVariant();
0130     }
0131     case CodeCompletionModel::CustomHighlight: {
0132         QStringList strings;
0133 
0134         // Collect strings
0135         for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) {
0136             strings << source.second.sibling(source.second.row(), a).data(Qt::DisplayRole).toString();
0137         }
0138 
0139         QList<QVariantList> highlights;
0140 
0141         // Collect custom-highlightings
0142         for (int a = CodeCompletionModel::Prefix; a <= CodeCompletionModel::Postfix; a++) {
0143             highlights << source.second.sibling(source.second.row(), a).data(CodeCompletionModel::CustomHighlight).toList();
0144         }
0145 
0146         return mergeCustomHighlighting(strings, highlights, 1);
0147     }
0148     }
0149 
0150     return {};
0151 }
0152 
0153 int KateArgumentHintModel::rowCount(const QModelIndex &) const
0154 {
0155     return m_rows.size();
0156 }
0157 
0158 KateCompletionModel::Group *KateArgumentHintModel::group() const
0159 {
0160     return m_parent->m_argumentHints;
0161 }
0162 
0163 void KateArgumentHintModel::emitDataChanged(const QModelIndex &start, const QModelIndex &end)
0164 {
0165     Q_EMIT dataChanged(start, end);
0166 }
0167 
0168 #include "moc_kateargumenthintmodel.cpp"