Changeset View
Changeset View
Standalone View
Standalone View
src/completion/katecompletionmodel.cpp
Show First 20 Lines • Show All 189 Lines • ▼ Show 20 Line(s) | 183 | if (role == Qt::DecorationRole && index.column() == KTextEditor::CodeCompletionModel::Prefix && isExpandable(index)) { | |||
---|---|---|---|---|---|
190 | } | 190 | } | ||
191 | } | 191 | } | ||
192 | 192 | | |||
193 | //groupOfParent returns a group when the index is a member of that group, but not the group head/label. | 193 | //groupOfParent returns a group when the index is a member of that group, but not the group head/label. | ||
194 | if (!hasGroups() || groupOfParent(index)) { | 194 | if (!hasGroups() || groupOfParent(index)) { | ||
195 | if ( role == Qt::TextAlignmentRole ) { | 195 | if ( role == Qt::TextAlignmentRole ) { | ||
196 | if (isColumnMergingEnabled() && !m_columnMerges.isEmpty()) { | 196 | if (isColumnMergingEnabled() && !m_columnMerges.isEmpty()) { | ||
197 | int c = 0; | 197 | int c = 0; | ||
198 | foreach (const QList<int> &list, m_columnMerges) { | 198 | for (const QList<int> &list : qAsConst(m_columnMerges)) { | ||
199 | if (index.column() < c + list.size()) { | 199 | if (index.column() < c + list.size()) { | ||
200 | c += list.size(); | 200 | c += list.size(); | ||
201 | continue; | 201 | continue; | ||
202 | } | 202 | } | ||
203 | else if (list.count() == 1 && list.first() == CodeCompletionModel::Scope) { | 203 | else if (list.count() == 1 && list.first() == CodeCompletionModel::Scope) { | ||
204 | return Qt::AlignRight; | 204 | return Qt::AlignRight; | ||
205 | } | 205 | } | ||
206 | else { | 206 | else { | ||
207 | return QVariant(); | 207 | return QVariant(); | ||
208 | } | 208 | } | ||
209 | } | 209 | } | ||
210 | 210 | | |||
211 | } else if ((!isColumnMergingEnabled() || m_columnMerges.isEmpty()) && index.column() == CodeCompletionModel::Scope) { | 211 | } else if ((!isColumnMergingEnabled() || m_columnMerges.isEmpty()) && index.column() == CodeCompletionModel::Scope) { | ||
212 | return Qt::AlignRight; | 212 | return Qt::AlignRight; | ||
213 | } | 213 | } | ||
214 | } | 214 | } | ||
215 | 215 | | |||
216 | // Merge text for column merging | 216 | // Merge text for column merging | ||
217 | if (role == Qt::DisplayRole && !m_columnMerges.isEmpty() && isColumnMergingEnabled()) { | 217 | if (role == Qt::DisplayRole && !m_columnMerges.isEmpty() && isColumnMergingEnabled()) { | ||
218 | QString text; | 218 | QString text; | ||
219 | foreach (int column, m_columnMerges[index.column()]) { | 219 | for (int column : m_columnMerges[index.column()]) { | ||
220 | QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer())); | 220 | QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer())); | ||
221 | text.append(sourceIndex.data(role).toString()); | 221 | text.append(sourceIndex.data(role).toString()); | ||
222 | } | 222 | } | ||
223 | 223 | | |||
224 | return text; | 224 | return text; | ||
225 | } | 225 | } | ||
226 | 226 | | |||
227 | if (role == CodeCompletionModel::HighlightingMethod) { | 227 | if (role == CodeCompletionModel::HighlightingMethod) { | ||
228 | //Return that we are doing custom-highlighting of one of the sub-strings does it. Unfortunately internal highlighting does not work for the other substrings. | 228 | //Return that we are doing custom-highlighting of one of the sub-strings does it. Unfortunately internal highlighting does not work for the other substrings. | ||
229 | foreach (int column, m_columnMerges[index.column()]) { | 229 | for (int column : m_columnMerges[index.column()]) { | ||
230 | QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer())); | 230 | QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer())); | ||
231 | QVariant method = sourceIndex.data(CodeCompletionModel::HighlightingMethod); | 231 | QVariant method = sourceIndex.data(CodeCompletionModel::HighlightingMethod); | ||
232 | if (method.type() == QVariant::Int && method.toInt() == CodeCompletionModel::CustomHighlighting) { | 232 | if (method.type() == QVariant::Int && method.toInt() == CodeCompletionModel::CustomHighlighting) { | ||
233 | return QVariant(CodeCompletionModel::CustomHighlighting); | 233 | return QVariant(CodeCompletionModel::CustomHighlighting); | ||
234 | } | 234 | } | ||
235 | } | 235 | } | ||
236 | return QVariant(); | 236 | return QVariant(); | ||
237 | } | 237 | } | ||
238 | if (role == CodeCompletionModel::CustomHighlight) { | 238 | if (role == CodeCompletionModel::CustomHighlight) { | ||
239 | //Merge custom highlighting if multiple columns were merged | 239 | //Merge custom highlighting if multiple columns were merged | ||
240 | QStringList strings; | 240 | QStringList strings; | ||
241 | 241 | | |||
242 | //Collect strings | 242 | //Collect strings | ||
243 | foreach (int column, m_columnMerges[index.column()]) { | 243 | const auto& columns = m_columnMerges[index.column()]; | ||
244 | strings.reserve(columns.size()); | ||||
245 | for (int column : columns) { | ||||
244 | strings << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(Qt::DisplayRole).toString(); | 246 | strings << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(Qt::DisplayRole).toString(); | ||
245 | } | 247 | } | ||
246 | 248 | | |||
247 | QList<QVariantList> highlights; | 249 | QList<QVariantList> highlights; | ||
248 | 250 | | |||
249 | //Collect custom-highlightings | 251 | //Collect custom-highlightings | ||
250 | foreach (int column, m_columnMerges[index.column()]) { | 252 | highlights.reserve(columns.size()); | ||
253 | for (int column : columns) { | ||||
251 | highlights << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(CodeCompletionModel::CustomHighlight).toList(); | 254 | highlights << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(CodeCompletionModel::CustomHighlight).toList(); | ||
252 | } | 255 | } | ||
253 | 256 | | |||
254 | return mergeCustomHighlighting(strings, highlights, 0); | 257 | return mergeCustomHighlighting(strings, highlights, 0); | ||
255 | } | 258 | } | ||
256 | 259 | | |||
257 | QVariant v = mapToSource(index).data(role); | 260 | QVariant v = mapToSource(index).data(role); | ||
258 | if (v.isValid()) { | 261 | if (v.isValid()) { | ||
▲ Show 20 Lines • Show All 769 Lines • ▼ Show 20 Line(s) | |||||
1028 | QString KateCompletionModel::commonPrefixInternal(const QString &forcePrefix) const | 1031 | QString KateCompletionModel::commonPrefixInternal(const QString &forcePrefix) const | ||
1029 | { | 1032 | { | ||
1030 | QString commonPrefix; // isNull() = true | 1033 | QString commonPrefix; // isNull() = true | ||
1031 | 1034 | | |||
1032 | QList< Group * > groups = m_rowTable; | 1035 | QList< Group * > groups = m_rowTable; | ||
1033 | groups += m_ungrouped; | 1036 | groups += m_ungrouped; | ||
1034 | 1037 | | |||
1035 | for (Group *g : qAsConst(groups)) { | 1038 | for (Group *g : qAsConst(groups)) { | ||
1036 | foreach (const Item &item, g->filtered) { | 1039 | for (const Item &item : qAsConst(g->filtered)) { | ||
1037 | uint startPos = m_currentMatch[item.sourceRow().first].length(); | 1040 | uint startPos = m_currentMatch[item.sourceRow().first].length(); | ||
1038 | const QString candidate = item.name().mid(startPos); | 1041 | const QString candidate = item.name().mid(startPos); | ||
1039 | 1042 | | |||
1040 | if (!candidate.startsWith(forcePrefix)) { | 1043 | if (!candidate.startsWith(forcePrefix)) { | ||
1041 | continue; | 1044 | continue; | ||
1042 | } | 1045 | } | ||
1043 | 1046 | | |||
1044 | if (commonPrefix.isNull()) { | 1047 | if (commonPrefix.isNull()) { | ||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Line(s) | |||||
1239 | } | 1242 | } | ||
1240 | 1243 | | |||
1241 | void KateCompletionModel::debugStats() | 1244 | void KateCompletionModel::debugStats() | ||
1242 | { | 1245 | { | ||
1243 | if (!hasGroups()) { | 1246 | if (!hasGroups()) { | ||
1244 | qCDebug(LOG_KTE) << "Model groupless, " << m_ungrouped->filtered.count() << " items."; | 1247 | qCDebug(LOG_KTE) << "Model groupless, " << m_ungrouped->filtered.count() << " items."; | ||
1245 | } else { | 1248 | } else { | ||
1246 | qCDebug(LOG_KTE) << "Model grouped (" << m_rowTable.count() << " groups):"; | 1249 | qCDebug(LOG_KTE) << "Model grouped (" << m_rowTable.count() << " groups):"; | ||
1247 | foreach (Group *g, m_rowTable) { | 1250 | for (Group *g : qAsConst(m_rowTable)) { | ||
1248 | qCDebug(LOG_KTE) << "Group" << g << "count" << g->filtered.count(); | 1251 | qCDebug(LOG_KTE) << "Group" << g << "count" << g->filtered.count(); | ||
1249 | } | 1252 | } | ||
1250 | } | 1253 | } | ||
1251 | } | 1254 | } | ||
1252 | 1255 | | |||
1253 | bool KateCompletionModel::hasCompletionModel() const | 1256 | bool KateCompletionModel::hasCompletionModel() const | ||
1254 | { | 1257 | { | ||
1255 | return !m_completionModels.isEmpty(); | 1258 | return !m_completionModels.isEmpty(); | ||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Line(s) | |||||
1342 | { | 1345 | { | ||
1343 | if (m_columnMerges.isEmpty()) { | 1346 | if (m_columnMerges.isEmpty()) { | ||
1344 | return sourceColumn; | 1347 | return sourceColumn; | ||
1345 | } | 1348 | } | ||
1346 | 1349 | | |||
1347 | /* Debugging - dump column merge list | 1350 | /* Debugging - dump column merge list | ||
1348 | 1351 | | |||
1349 | QString columnMerge; | 1352 | QString columnMerge; | ||
1350 | foreach (const QList<int>& list, m_columnMerges) { | 1353 | for (const QList<int> &list : m_columnMerges) { | ||
1351 | columnMerge += '['; | 1354 | columnMerge += '['; | ||
1352 | foreach (int column, list) { | 1355 | for (int column : list) { | ||
1353 | columnMerge += QString::number(column) + QLatin1Char(' '); | 1356 | columnMerge += QString::number(column) + QLatin1Char(' '); | ||
1354 | } | 1357 | } | ||
1355 | columnMerge += "] "; | 1358 | columnMerge += "] "; | ||
1356 | } | 1359 | } | ||
1357 | 1360 | | |||
1358 | qCDebug(LOG_KTE) << k_funcinfo << columnMerge;*/ | 1361 | qCDebug(LOG_KTE) << k_funcinfo << columnMerge;*/ | ||
1359 | 1362 | | |||
1360 | int c = 0; | 1363 | int c = 0; | ||
1361 | foreach (const QList<int> &list, m_columnMerges) { | 1364 | for (const QList<int> &list : m_columnMerges) { | ||
1362 | foreach (int column, list) { | 1365 | for (int column : list) { | ||
1363 | if (column == sourceColumn) { | 1366 | if (column == sourceColumn) { | ||
1364 | return c; | 1367 | return c; | ||
1365 | } | 1368 | } | ||
1366 | } | 1369 | } | ||
1367 | c++; | 1370 | c++; | ||
1368 | } | 1371 | } | ||
1369 | return -1; | 1372 | return -1; | ||
1370 | } | 1373 | } | ||
▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Line(s) | 1783 | { | |||
1795 | 1798 | | |||
1796 | clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering. | 1799 | clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering. | ||
1797 | endResetModel(); | 1800 | endResetModel(); | ||
1798 | } | 1801 | } | ||
1799 | 1802 | | |||
1800 | void KateCompletionModel::Group::refilter() | 1803 | void KateCompletionModel::Group::refilter() | ||
1801 | { | 1804 | { | ||
1802 | filtered.clear(); | 1805 | filtered.clear(); | ||
1803 | foreach (const Item &i, prefilter) | 1806 | for (const Item &i : qAsConst(prefilter)) { | ||
1804 | if (!i.isFiltered()) { | 1807 | if (!i.isFiltered()) { | ||
1805 | filtered.append(i); | 1808 | filtered.append(i); | ||
1806 | } | 1809 | } | ||
1807 | } | 1810 | } | ||
1811 | } | ||||
1808 | 1812 | | |||
1809 | bool KateCompletionModel::Item::filter() | 1813 | bool KateCompletionModel::Item::filter() | ||
1810 | { | 1814 | { | ||
1811 | matchFilters = false; | 1815 | matchFilters = false; | ||
1812 | 1816 | | |||
1813 | if (model->isFilteringEnabled()) { | 1817 | if (model->isFilteringEnabled()) { | ||
1814 | QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name); | 1818 | QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name); | ||
1815 | 1819 | | |||
Show All 21 Lines | |||||
1837 | 1841 | | |||
1838 | matchFilters = true; | 1842 | matchFilters = true; | ||
1839 | return matchFilters; | 1843 | return matchFilters; | ||
1840 | } | 1844 | } | ||
1841 | 1845 | | |||
1842 | uint KateCompletionModel::filteredItemCount() const | 1846 | uint KateCompletionModel::filteredItemCount() const | ||
1843 | { | 1847 | { | ||
1844 | uint ret = 0; | 1848 | uint ret = 0; | ||
1845 | foreach (Group *group, m_rowTable) { | 1849 | for (Group *group : m_rowTable) { | ||
1846 | ret += group->filtered.size(); | 1850 | ret += group->filtered.size(); | ||
1847 | } | 1851 | } | ||
1848 | 1852 | | |||
1849 | return ret; | 1853 | return ret; | ||
1850 | } | 1854 | } | ||
1851 | 1855 | | |||
1852 | bool KateCompletionModel::shouldMatchHideCompletionList() const | 1856 | bool KateCompletionModel::shouldMatchHideCompletionList() const | ||
1853 | { | 1857 | { | ||
1854 | 1858 | | |||
1855 | // @todo Make this faster | 1859 | // @todo Make this faster | ||
1856 | 1860 | | |||
1857 | bool doHide = false; | 1861 | bool doHide = false; | ||
1858 | CodeCompletionModel *hideModel = nullptr; | 1862 | CodeCompletionModel *hideModel = nullptr; | ||
1859 | 1863 | | |||
1860 | foreach (Group *group, m_rowTable) | 1864 | for (Group *group : qAsConst(m_rowTable)) { | ||
1861 | foreach (const Item &item, group->filtered) | 1865 | for (const Item &item : qAsConst(group->filtered)) { | ||
1862 | if (item.haveExactMatch()) { | 1866 | if (item.haveExactMatch()) { | ||
1863 | KTextEditor::CodeCompletionModelControllerInterface *iface3 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface *>(item.sourceRow().first); | 1867 | KTextEditor::CodeCompletionModelControllerInterface *iface3 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface *>(item.sourceRow().first); | ||
1864 | bool hide = false; | 1868 | bool hide = false; | ||
1865 | if (!iface3) { | 1869 | if (!iface3) { | ||
1866 | hide = true; | 1870 | hide = true; | ||
1867 | } | 1871 | } | ||
1868 | if (iface3 && iface3->matchingItem(item.sourceRow().second) == KTextEditor::CodeCompletionModelControllerInterface::HideListIfAutomaticInvocation) { | 1872 | if (iface3 && iface3->matchingItem(item.sourceRow().second) == KTextEditor::CodeCompletionModelControllerInterface::HideListIfAutomaticInvocation) { | ||
1869 | hide = true; | 1873 | hide = true; | ||
1870 | } | 1874 | } | ||
1871 | if (hide) { | 1875 | if (hide) { | ||
1872 | doHide = true; | 1876 | doHide = true; | ||
1873 | hideModel = item.sourceRow().first; | 1877 | hideModel = item.sourceRow().first; | ||
1874 | } | 1878 | } | ||
1875 | } | 1879 | } | ||
1880 | } | ||||
1881 | } | ||||
1876 | 1882 | | |||
1877 | if (doHide) { | 1883 | if (doHide) { | ||
1878 | // Check if all other visible items are from the same model | 1884 | // Check if all other visible items are from the same model | ||
1879 | foreach (Group *group, m_rowTable) | 1885 | for (Group *group : qAsConst(m_rowTable)) { | ||
1880 | foreach (const Item &item, group->filtered) | 1886 | for (const Item &item : qAsConst(group->filtered)) { | ||
1881 | if (item.sourceRow().first != hideModel) { | 1887 | if (item.sourceRow().first != hideModel) { | ||
1882 | return false; | 1888 | return false; | ||
1883 | } | 1889 | } | ||
1884 | } | 1890 | } | ||
1891 | } | ||||
1892 | } | ||||
1885 | 1893 | | |||
1886 | return doHide; | 1894 | return doHide; | ||
1887 | } | 1895 | } | ||
1888 | 1896 | | |||
1889 | static inline QChar toLowerIfInsensitive(QChar c, Qt::CaseSensitivity caseSensitive) | 1897 | static inline QChar toLowerIfInsensitive(QChar c, Qt::CaseSensitivity caseSensitive) | ||
1890 | { | 1898 | { | ||
1891 | return (caseSensitive == Qt::CaseInsensitive) ? c.toLower() : c; | 1899 | return (caseSensitive == Qt::CaseInsensitive) ? c.toLower() : c; | ||
1892 | } | 1900 | } | ||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Line(s) | 1946 | { | |||
1939 | // A mismatch is very likely for random even for the first letter, | 1947 | // A mismatch is very likely for random even for the first letter, | ||
1940 | // thus this optimization makes sense. | 1948 | // thus this optimization makes sense. | ||
1941 | if (toLowerIfInsensitive(word.at(0), caseSensitive) != toLowerIfInsensitive(typed.at(0), caseSensitive)) { | 1949 | if (toLowerIfInsensitive(word.at(0), caseSensitive) != toLowerIfInsensitive(typed.at(0), caseSensitive)) { | ||
1942 | return false; | 1950 | return false; | ||
1943 | } | 1951 | } | ||
1944 | 1952 | | |||
1945 | // First, check if all letters are contained in the word in the right order. | 1953 | // First, check if all letters are contained in the word in the right order. | ||
1946 | int atLetter = 0; | 1954 | int atLetter = 0; | ||
1947 | foreach (const QChar c, typed) { | 1955 | for (const QChar c : typed) { | ||
1948 | while (toLowerIfInsensitive(c, caseSensitive) != toLowerIfInsensitive(word.at(atLetter), caseSensitive)) { | 1956 | while (toLowerIfInsensitive(c, caseSensitive) != toLowerIfInsensitive(word.at(atLetter), caseSensitive)) { | ||
1949 | atLetter += 1; | 1957 | atLetter += 1; | ||
1950 | if (atLetter >= word.size()) { | 1958 | if (atLetter >= word.size()) { | ||
1951 | return false; | 1959 | return false; | ||
1952 | } | 1960 | } | ||
1953 | } | 1961 | } | ||
1954 | } | 1962 | } | ||
1955 | 1963 | | |||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Line(s) | |||||
2172 | { | 2180 | { | ||
2173 | //if (m_completionModels == models) | 2181 | //if (m_completionModels == models) | ||
2174 | //return; | 2182 | //return; | ||
2175 | 2183 | | |||
2176 | clearCompletionModels(); | 2184 | clearCompletionModels(); | ||
2177 | 2185 | | |||
2178 | m_completionModels = models; | 2186 | m_completionModels = models; | ||
2179 | 2187 | | |||
2180 | foreach (KTextEditor::CodeCompletionModel *model, models) { | 2188 | for (KTextEditor::CodeCompletionModel *model : models) { | ||
2181 | connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int))); | 2189 | connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int))); | ||
2182 | connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int))); | 2190 | connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int))); | ||
2183 | connect(model, SIGNAL(modelReset()), SLOT(slotModelReset())); | 2191 | connect(model, SIGNAL(modelReset()), SLOT(slotModelReset())); | ||
2184 | } | 2192 | } | ||
2185 | 2193 | | |||
2186 | // This performs the reset | 2194 | // This performs the reset | ||
2187 | createGroups(); | 2195 | createGroups(); | ||
2188 | } | 2196 | } | ||
Show All 34 Lines | 2227 | struct FilterItems { | |||
2223 | 2231 | | |||
2224 | QHash<QString, CodeCompletionModel *> had; | 2232 | QHash<QString, CodeCompletionModel *> had; | ||
2225 | KateCompletionModel &m_model; | 2233 | KateCompletionModel &m_model; | ||
2226 | const QVector< KTextEditor::CodeCompletionModel * > m_needShadowing; | 2234 | const QVector< KTextEditor::CodeCompletionModel * > m_needShadowing; | ||
2227 | 2235 | | |||
2228 | void filter(QList<Item> &items) | 2236 | void filter(QList<Item> &items) | ||
2229 | { | 2237 | { | ||
2230 | QList<Item> temp; | 2238 | QList<Item> temp; | ||
2231 | foreach (const Item &item, items) { | 2239 | for (const Item &item : qAsConst(items)) { | ||
2232 | QHash<QString, CodeCompletionModel *>::const_iterator it = had.constFind(item.name()); | 2240 | QHash<QString, CodeCompletionModel *>::const_iterator it = had.constFind(item.name()); | ||
2233 | if (it != had.constEnd() && *it != item.sourceRow().first && m_needShadowing.contains(item.sourceRow().first)) { | 2241 | if (it != had.constEnd() && *it != item.sourceRow().first && m_needShadowing.contains(item.sourceRow().first)) { | ||
2234 | continue; | 2242 | continue; | ||
2235 | } | 2243 | } | ||
2236 | had.insert(item.name(), item.sourceRow().first); | 2244 | had.insert(item.name(), item.sourceRow().first); | ||
2237 | temp.push_back(item); | 2245 | temp.push_back(item); | ||
2238 | } | 2246 | } | ||
2239 | items = temp; | 2247 | items = temp; | ||
▲ Show 20 Lines • Show All 193 Lines • Show Last 20 Lines |