File indexing completed on 2024-05-12 05:52:07
0001 /* 0002 SPDX-FileCopyrightText: 2018 Tomaz Canabrava <tcanabrava@kde.org> 0003 SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "katequickopenmodel.h" 0009 0010 #include "kateapp.h" 0011 #include "katemainwindow.h" 0012 0013 #include <KTextEditor/Document> 0014 #include <KTextEditor/View> 0015 0016 #include <QFileInfo> 0017 #include <QIcon> 0018 #include <QMimeDatabase> 0019 0020 #include <unordered_set> 0021 0022 KateQuickOpenModel::KateQuickOpenModel(QObject *parent) 0023 : QAbstractTableModel(parent) 0024 { 0025 } 0026 0027 int KateQuickOpenModel::rowCount(const QModelIndex &parent) const 0028 { 0029 if (parent.isValid()) { 0030 return 0; 0031 } 0032 return (int)m_modelEntries.size(); 0033 } 0034 0035 int KateQuickOpenModel::columnCount(const QModelIndex &parent) const 0036 { 0037 Q_UNUSED(parent); 0038 return 1; 0039 } 0040 0041 QVariant KateQuickOpenModel::data(const QModelIndex &idx, int role) const 0042 { 0043 if (!idx.isValid()) { 0044 return {}; 0045 } 0046 0047 const ModelEntry &entry = m_modelEntries.at(idx.row()); 0048 switch (role) { 0049 case Qt::DisplayRole: 0050 case Role::FileName: 0051 return entry.fileName; 0052 case Role::FilePath: { 0053 // no .remove since that might remove all occurrence in rare cases 0054 const auto &path = entry.filePath; 0055 return path.startsWith(m_projectBase) ? path.mid(m_projectBase.size()) : path; 0056 } 0057 case Qt::FontRole: { 0058 if (entry.document) { 0059 QFont font; 0060 font.setBold(true); 0061 return font; 0062 } 0063 return {}; 0064 } 0065 case Qt::DecorationRole: 0066 return QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(entry.fileName, QMimeDatabase::MatchExtension).iconName()); 0067 case Qt::UserRole: 0068 return !entry.document ? QUrl::fromLocalFile(entry.filePath) : entry.document->url(); 0069 case Role::Score: 0070 return entry.score; 0071 case Role::Document: 0072 return QVariant::fromValue(entry.document); 0073 default: 0074 return {}; 0075 } 0076 0077 return {}; 0078 } 0079 0080 void KateQuickOpenModel::refresh(KateMainWindow *mainWindow) 0081 { 0082 QObject *projectView = mainWindow->pluginView(QStringLiteral("kateprojectplugin")); 0083 const auto sortedViews = mainWindow->viewManager()->views(); 0084 const QList<KTextEditor::Document *> openDocs = KateApp::self()->documentManager()->documentList(); 0085 const QStringList projectDocs = projectView 0086 ? (m_listMode == CurrentProject ? projectView->property("projectFiles") : projectView->property("allProjectsFiles")).toStringList() 0087 : QStringList(); 0088 const QString projectBase = [projectView]() -> QString { 0089 if (!projectView) { 0090 return QString(); 0091 } 0092 QString ret; 0093 // open files are always included in the listing, even if list mode == CurrentProject 0094 // those open files may belong to another project than the current one 0095 // so we should always consistently strip the common base 0096 // otherwise it will be confusing and the opened files of anther project 0097 // end up with an unstripped complete file path 0098 ret = projectView->property("allProjectsCommonBaseDir").toString(); 0099 if (!ret.endsWith(QLatin1Char('/'))) { 0100 ret.append(QLatin1Char('/')); 0101 } 0102 // avoid strip of a single leading / 0103 if (ret == QStringLiteral("/")) { 0104 ret.clear(); 0105 } 0106 return ret; 0107 }(); 0108 0109 m_projectBase = projectBase; 0110 0111 std::vector<ModelEntry> allDocuments; 0112 allDocuments.reserve(sortedViews.size() + projectDocs.size()); 0113 0114 std::unordered_set<QString> openedDocUrls; 0115 std::unordered_set<KTextEditor::Document *> seenDocuments; 0116 openedDocUrls.reserve(sortedViews.size()); 0117 0118 const auto collectDoc = [&openedDocUrls, &seenDocuments, &allDocuments](KTextEditor::Document *doc) { 0119 // We don't want any duplicates, beside for untitled documents 0120 if (!seenDocuments.insert(doc).second) { 0121 return; 0122 } 0123 0124 // document with set url => use the url for displaying 0125 if (!doc->url().isEmpty()) { 0126 auto path = doc->url().toString(QUrl::NormalizePathSegments | QUrl::PreferLocalFile); 0127 openedDocUrls.insert(path); 0128 allDocuments.push_back({QFileInfo(path).fileName(), path, doc, -1}); 0129 return; 0130 } 0131 0132 // untitled document 0133 allDocuments.push_back({doc->documentName(), QString(), doc, -1}); 0134 }; 0135 0136 for (auto *view : sortedViews) { 0137 collectDoc(view->document()); 0138 } 0139 0140 for (auto *doc : openDocs) { 0141 collectDoc(doc); 0142 } 0143 0144 for (const auto &filePath : projectDocs) { 0145 // No duplicates 0146 if (openedDocUrls.count(filePath) != 0) { 0147 continue; 0148 } 0149 0150 // QFileInfo is too expensive just for fileName computation 0151 const int slashIndex = filePath.lastIndexOf(QLatin1Char('/')); 0152 QString fileName = filePath.mid(slashIndex + 1); 0153 allDocuments.push_back({std::move(fileName), filePath, nullptr, -1}); 0154 } 0155 0156 beginResetModel(); 0157 m_modelEntries = std::move(allDocuments); 0158 endResetModel(); 0159 } 0160 0161 #include "moc_katequickopenmodel.cpp"