File indexing completed on 2024-05-05 05:52:18
0001 /* This file is part of the Kate project. 0002 * Based on the snippet plugin from KDevelop 4. 0003 * 0004 * SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de> 0005 * SPDX-FileCopyrightText: 2012 Christoph Cullmann <cullmann@kde.org> 0006 * 0007 * SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "snippetcompletionmodel.h" 0011 0012 #include <ktexteditor/document.h> 0013 #include <ktexteditor/view.h> 0014 0015 #include "snippet.h" 0016 #include "snippetcompletionitem.h" 0017 #include "snippetrepository.h" 0018 #include "snippetstore.h" 0019 0020 #include <KLocalizedString> 0021 0022 SnippetCompletionModel::SnippetCompletionModel() 0023 : KTextEditor::CodeCompletionModel(nullptr) 0024 { 0025 setHasGroups(false); 0026 } 0027 0028 SnippetCompletionModel::~SnippetCompletionModel() 0029 { 0030 qDeleteAll(m_snippets); 0031 m_snippets.clear(); 0032 } 0033 0034 QVariant SnippetCompletionModel::data(const QModelIndex &idx, int role) const 0035 { 0036 if (role == KTextEditor::CodeCompletionModel::InheritanceDepth) { 0037 return 11000; 0038 } 0039 0040 // grouping of snippets 0041 if (!idx.parent().isValid()) { 0042 if (role == Qt::DisplayRole) { 0043 return i18n("Snippets"); 0044 } 0045 if (role == KTextEditor::CodeCompletionModel::GroupRole) { 0046 return Qt::DisplayRole; 0047 } 0048 return QVariant(); 0049 } 0050 // snippets 0051 if (!idx.isValid() || idx.row() < 0 || idx.row() >= m_snippets.count()) { 0052 return QVariant(); 0053 } else { 0054 return m_snippets.at(idx.row())->data(idx, role, nullptr); 0055 } 0056 } 0057 0058 void SnippetCompletionModel::executeCompletionItem(KTextEditor::View *view, const KTextEditor::Range &word, const QModelIndex &index) const 0059 { 0060 if (index.parent().isValid()) { 0061 m_snippets[index.row()]->execute(view, word); 0062 } 0063 } 0064 0065 void SnippetCompletionModel::completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType) 0066 { 0067 Q_UNUSED(range); 0068 Q_UNUSED(invocationType); 0069 initData(view); 0070 } 0071 0072 void SnippetCompletionModel::initData(KTextEditor::View *view) 0073 { 0074 QString posMode = view->document()->highlightingModeAt(view->cursorPosition()); 0075 QString docMode = view->document()->highlightingMode(); 0076 if (docMode.isEmpty() && posMode.isEmpty()) { 0077 qWarning() << Q_FUNC_INFO << "Unexpected empty modes"; 0078 return; 0079 } 0080 0081 beginResetModel(); 0082 0083 qDeleteAll(m_snippets); 0084 m_snippets.clear(); 0085 SnippetStore *store = SnippetStore::self(); 0086 for (int i = 0; i < store->rowCount(); i++) { 0087 if (store->item(i, 0)->checkState() != Qt::Checked) { 0088 continue; 0089 } 0090 SnippetRepository *repo = SnippetRepository::fromItem(store->item(i, 0)); 0091 if (!repo) { 0092 continue; 0093 } 0094 const QStringList fileTypes = repo->fileTypes(); 0095 if (fileTypes.isEmpty() || fileTypes.contains(docMode) || fileTypes.contains(posMode)) { 0096 for (int j = 0; j < repo->rowCount(); ++j) { 0097 if (Snippet *snippet = Snippet::fromItem(repo->child(j))) { 0098 m_snippets << new SnippetCompletionItem(snippet, repo); 0099 } 0100 } 0101 } 0102 } 0103 0104 endResetModel(); 0105 } 0106 0107 QModelIndex SnippetCompletionModel::parent(const QModelIndex &index) const 0108 { 0109 if (index.internalId()) { 0110 return createIndex(0, 0, quintptr(0)); 0111 } else { 0112 return QModelIndex(); 0113 } 0114 } 0115 0116 QModelIndex SnippetCompletionModel::index(int row, int column, const QModelIndex &parent) const 0117 { 0118 if (!parent.isValid()) { 0119 if (row == 0) { 0120 return createIndex(row, column, quintptr(0)); // header index 0121 } else { 0122 return QModelIndex(); 0123 } 0124 } else if (parent.parent().isValid()) { // we only have header and children, no subheaders 0125 return QModelIndex(); 0126 } 0127 0128 if (row < 0 || row >= m_snippets.count() || column < 0 || column >= ColumnCount) { 0129 return QModelIndex(); 0130 } 0131 0132 return createIndex(row, column, 1); // normal item index 0133 } 0134 0135 int SnippetCompletionModel::rowCount(const QModelIndex &parent) const 0136 { 0137 if (!parent.isValid() && !m_snippets.isEmpty()) { 0138 return 1; // one toplevel node (group header) 0139 } else if (parent.parent().isValid()) { 0140 return 0; // we don't have sub children 0141 } else { 0142 return m_snippets.count(); // only the children 0143 } 0144 } 0145 0146 bool SnippetCompletionModel::shouldStartCompletion(KTextEditor::View *view, 0147 const QString &insertedText, 0148 bool userInsertion, 0149 const KTextEditor::Cursor &position) 0150 { 0151 Q_UNUSED(view); 0152 Q_UNUSED(insertedText); 0153 Q_UNUSED(userInsertion); 0154 Q_UNUSED(position); 0155 return false; 0156 } 0157 0158 bool SnippetCompletionModel::shouldAbortCompletion(KTextEditor::View *view, const KTextEditor::Range &range, const QString ¤tCompletion) 0159 { 0160 if (view->cursorPosition() < range.start() || view->cursorPosition() > range.end()) { 0161 return true; // Always abort when the completion-range has been left 0162 } 0163 0164 for (const auto token : currentCompletion) { 0165 if (token.isSpace()) { 0166 return true; 0167 } 0168 } 0169 // else it's valid 0170 return false; 0171 } 0172 0173 #include "moc_snippetcompletionmodel.cpp"