File indexing completed on 2024-04-28 05:49:07
0001 /* This file is part of the Kate project. 0002 * 0003 * SPDX-FileCopyrightText: 2012 Christoph Cullmann <cullmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kateprojectinfoviewindex.h" 0009 #include "kateproject.h" 0010 #include "kateprojectindex.h" 0011 #include "kateprojectplugin.h" 0012 #include "kateprojectpluginview.h" 0013 #include "ktexteditor_utils.h" 0014 0015 #include <KLocalizedString> 0016 #include <KMessageWidget> 0017 #include <QAction> 0018 #include <QVBoxLayout> 0019 0020 KateProjectInfoViewIndex::KateProjectInfoViewIndex(KateProjectPluginView *pluginView, KateProject *project, QWidget *parent) 0021 : QWidget(parent) 0022 , m_pluginView(pluginView) 0023 , m_project(project) 0024 , m_messageWidget(nullptr) 0025 , m_lineEdit(new QLineEdit()) 0026 , m_treeView(new QTreeView()) 0027 , m_model(new QStandardItemModel(m_treeView)) 0028 { 0029 /** 0030 * default style 0031 */ 0032 m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); 0033 m_treeView->setUniformRowHeights(true); 0034 m_treeView->setRootIsDecorated(false); 0035 m_model->setHorizontalHeaderLabels(QStringList() << i18n("Name") << i18n("Kind") << i18n("File") << i18n("Line")); 0036 m_lineEdit->setPlaceholderText(i18n("Search")); 0037 m_lineEdit->setClearButtonEnabled(true); 0038 0039 /** 0040 * attach model 0041 * kill selection model 0042 */ 0043 QItemSelectionModel *m = m_treeView->selectionModel(); 0044 m_treeView->setModel(m_model); 0045 delete m; 0046 0047 /** 0048 * layout widget 0049 */ 0050 QVBoxLayout *layout = new QVBoxLayout; 0051 layout->setSpacing(0); 0052 layout->setContentsMargins(0, 0, 0, 0); 0053 layout->addWidget(m_lineEdit); 0054 layout->addWidget(m_treeView); 0055 setLayout(layout); 0056 setFocusProxy(m_lineEdit); 0057 0058 /** 0059 * connect needed signals 0060 */ 0061 connect(m_pluginView, &KateProjectPluginView::projectLookupWord, m_lineEdit, &QLineEdit::setText); 0062 connect(m_lineEdit, &QLineEdit::textChanged, this, &KateProjectInfoViewIndex::slotTextChanged); 0063 connect(m_treeView, &QTreeView::clicked, this, &KateProjectInfoViewIndex::slotClicked); 0064 if (m_project) { 0065 connect(m_project, &KateProject::indexChanged, this, &KateProjectInfoViewIndex::indexAvailable); 0066 } else { 0067 connect(m_pluginView, &KateProjectPluginView::gotoSymbol, this, &KateProjectInfoViewIndex::slotGotoSymbol); 0068 enableWidgets(true); 0069 } 0070 0071 /** 0072 * trigger once search with nothing 0073 */ 0074 slotTextChanged(QString()); 0075 } 0076 0077 KateProjectInfoViewIndex::~KateProjectInfoViewIndex() 0078 { 0079 } 0080 0081 void KateProjectInfoViewIndex::slotGotoSymbol(const QString &text, int &results) 0082 { 0083 // trigger fill model 0084 m_lineEdit->setText(text); 0085 results = m_model->rowCount(); 0086 // immediately goto if only a single option 0087 if (results == 1) { 0088 slotClicked(m_model->index(0, 0)); 0089 } 0090 } 0091 0092 void KateProjectInfoViewIndex::slotTextChanged(const QString &text) 0093 { 0094 /** 0095 * init 0096 */ 0097 m_treeView->setSortingEnabled(false); 0098 m_model->setRowCount(0); 0099 0100 /** 0101 * get results 0102 */ 0103 if (m_project && m_project->projectIndex() && !text.isEmpty()) { 0104 m_project->projectIndex()->findMatches(*m_model, text, KateProjectIndex::FindMatches); 0105 } else if (!text.isEmpty()) { 0106 const auto projects = m_pluginView->plugin()->projects(); 0107 for (const auto project : projects) { 0108 if (project->projectIndex()) { 0109 project->projectIndex()->findMatches(*m_model, text, KateProjectIndex::FindMatches, TAG_FULLMATCH | TAG_OBSERVECASE); 0110 } 0111 } 0112 } 0113 0114 /** 0115 * tree view polish ;) 0116 */ 0117 m_treeView->setSortingEnabled(true); 0118 m_treeView->resizeColumnToContents(2); 0119 m_treeView->resizeColumnToContents(1); 0120 m_treeView->resizeColumnToContents(0); 0121 } 0122 0123 void KateProjectInfoViewIndex::slotClicked(const QModelIndex &index) 0124 { 0125 /** 0126 * get path 0127 */ 0128 QString filePath = m_model->item(index.row(), 2)->text(); 0129 if (filePath.isEmpty()) { 0130 return; 0131 } 0132 0133 /** Save current position before jumping **/ 0134 auto currentView = m_pluginView->mainWindow()->activeView(); 0135 QUrl url; 0136 KTextEditor::Cursor pos; 0137 if (currentView) { 0138 url = currentView->document()->url(); 0139 pos = currentView->cursorPosition(); 0140 } 0141 0142 /** 0143 * create view 0144 */ 0145 KTextEditor::View *view = m_pluginView->mainWindow()->openUrl(QUrl::fromLocalFile(filePath)); 0146 if (!view) { 0147 return; 0148 } 0149 0150 /** save current position in location history */ 0151 Utils::addPositionToHistory(url, pos, m_pluginView->mainWindow()); 0152 0153 /** 0154 * set cursor, if possible 0155 */ 0156 int line = m_model->item(index.row(), 3)->text().toInt(); 0157 if (line >= 1) { 0158 view->setCursorPosition(KTextEditor::Cursor(line - 1, 0)); 0159 0160 /** save the jump position in location history */ 0161 Utils::addPositionToHistory(view->document()->url(), {line - 1, 0}, m_pluginView->mainWindow()); 0162 } 0163 } 0164 0165 void KateProjectInfoViewIndex::indexAvailable() 0166 { 0167 const bool valid = m_project->projectIndex() && m_project->projectIndex()->isValid(); 0168 enableWidgets(valid); 0169 } 0170 0171 void KateProjectInfoViewIndex::enableWidgets(bool valid) 0172 { 0173 /** 0174 * update enabled state of widgets 0175 */ 0176 m_lineEdit->setEnabled(valid); 0177 m_treeView->setEnabled(valid); 0178 0179 /** 0180 * if index exists, hide possible message widget, else create it 0181 */ 0182 if (valid) { 0183 if (m_messageWidget && m_messageWidget->isVisible()) { 0184 m_messageWidget->animatedHide(); 0185 } 0186 } else if (!m_messageWidget) { 0187 m_messageWidget = new KMessageWidget(); 0188 m_messageWidget->setPosition(KMessageWidget::Header); 0189 m_messageWidget->setCloseButtonVisible(true); 0190 m_messageWidget->setMessageType(KMessageWidget::Warning); 0191 m_messageWidget->setWordWrap(false); 0192 static_cast<QVBoxLayout *>(layout())->insertWidget(0, m_messageWidget); 0193 m_messageWidget->animatedShow(); 0194 } 0195 0196 // disabled or failed to create? 0197 if (!valid && m_project->projectIndex()) { 0198 m_messageWidget->setText(i18n("The index could not be created. Please install 'ctags'.")); 0199 // Make sure we remove the action 0200 const QList<QAction *> actions = m_messageWidget->actions(); 0201 if (actions.size() == 1) { 0202 m_messageWidget->removeAction(actions.first()); 0203 } 0204 } else if (!valid) { 0205 if (!m_messageWidget->text().isEmpty()) { 0206 return; 0207 } 0208 m_messageWidget->setText(i18n("Indexing is not enabled")); 0209 auto enableIndexing = new QAction(i18n("Enable indexing"), m_messageWidget); 0210 connect(enableIndexing, &QAction::triggered, m_messageWidget, [this]() { 0211 m_project->plugin()->setIndex(true, QUrl()); 0212 m_project->reload(true); 0213 }); 0214 m_messageWidget->addAction(enableIndexing); 0215 } 0216 } 0217 0218 #include "moc_kateprojectinfoviewindex.cpp"