- enhancement: prefer local headers over system headers when complete #include header path

This commit is contained in:
Roy Qu 2022-04-14 22:25:49 +08:00
parent 8c99d28307
commit 9d401cce42
7 changed files with 123 additions and 49 deletions

View File

@ -7,6 +7,7 @@ Red Panda C++ Version 1.0.4
- enhancement: if a project's unit encoding is the same with project's encoding, don't save its encoding - enhancement: if a project's unit encoding is the same with project's encoding, don't save its encoding
- fix: files will be saved to default encoding inspite of its original encoding - fix: files will be saved to default encoding inspite of its original encoding
- fix: parenthesis skip doesn't work when editing non-c/c++ files - fix: parenthesis skip doesn't work when editing non-c/c++ files
- enhancement: prefer local headers over system headers when complete #include header path
Red Panda C++ Version 1.0.3 Red Panda C++ Version 1.0.3
- fix: when oj problem grabbed by competitive companion received, - fix: when oj problem grabbed by competitive companion received,

View File

@ -3120,7 +3120,7 @@ void Editor::completionInsert(bool appendFunc)
void Editor::headerCompletionInsert() void Editor::headerCompletionInsert()
{ {
QString headerName = mHeaderCompletionPopup->selectedFilename(); QString headerName = mHeaderCompletionPopup->selectedFilename(true);
if (headerName.isEmpty()) if (headerName.isEmpty())
return; return;

View File

@ -570,9 +570,13 @@ void MainWindow::updateEditorColorSchemes()
QColor baseColor = palette().color(QPalette::Base); QColor baseColor = palette().color(QPalette::Base);
item = pColorManager->getItem(schemeName, SYNS_AttrPreprocessor); item = pColorManager->getItem(schemeName, SYNS_AttrPreprocessor);
if (item) { if (item) {
mHeaderCompletionPopup->setSuggestionColor(item->foreground()); mHeaderCompletionPopup->setSuggestionColor(item->foreground(),
item->foreground(),
item->foreground());
} else { } else {
mHeaderCompletionPopup->setSuggestionColor(palette().color(QPalette::Text)); mHeaderCompletionPopup->setSuggestionColor(palette().color(QPalette::Text),
palette().color(QPalette::Text),
palette().color(QPalette::Text));
} }
item = pColorManager->getItem(schemeName, COLOR_SCHEME_ERROR); item = pColorManager->getItem(schemeName, COLOR_SCHEME_ERROR);
if (item && haveGoodContrast(item->foreground(), baseColor)) { if (item && haveGoodContrast(item->foreground(), baseColor)) {

View File

@ -2763,7 +2763,7 @@ void Settings::CompilerSets::deleteSet(int index)
saveSets(); saveSets();
} }
int Settings::CompilerSets::size() const size_t Settings::CompilerSets::size() const
{ {
return mList.size(); return mList.size();
} }

View File

@ -1334,7 +1334,7 @@ public:
void saveDefaultIndex(); void saveDefaultIndex();
void deleteSet(int index); void deleteSet(int index);
void saveSet(int index); void saveSet(int index);
int size() const; size_t size() const;
int defaultIndex() const; int defaultIndex() const;
void setDefaultIndex(int value); void setDefaultIndex(int value);
PCompilerSet defaultSet(); PCompilerSet defaultSet();

View File

@ -17,9 +17,9 @@
#include "headercompletionpopup.h" #include "headercompletionpopup.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDebug>
HeaderCompletionPopup::HeaderCompletionPopup(QWidget* parent):QWidget(parent) HeaderCompletionPopup::HeaderCompletionPopup(QWidget* parent):QWidget(parent)
{ {
@ -86,7 +86,7 @@ bool HeaderCompletionPopup::search(const QString &phrase, bool autoHideOnSingleR
if (autoHideOnSingleResult) if (autoHideOnSingleResult)
return true; return true;
// if only one suggestion, and is exactly the symbol to search, hide the frame (the search is over) // if only one suggestion, and is exactly the symbol to search, hide the frame (the search is over)
if (symbol == mCompletionList.front()) if (symbol == mCompletionList[0]->filename)
return true; return true;
} }
} else { } else {
@ -100,43 +100,66 @@ void HeaderCompletionPopup::setKeypressedCallback(const KeyPressedCallback &newK
mListView->setKeypressedCallback(newKeypressedCallback); mListView->setKeypressedCallback(newKeypressedCallback);
} }
void HeaderCompletionPopup::setSuggestionColor(const QColor &color) void HeaderCompletionPopup::setSuggestionColor(const QColor& localColor,
const QColor& projectColor,
const QColor& systemColor)
{ {
mModel->setColor(color); mModel->setLocalColor(localColor);
mModel->setProjectColor(projectColor);
mModel->setSystemColor(systemColor);
} }
QString HeaderCompletionPopup::selectedFilename() QString HeaderCompletionPopup::selectedFilename(bool updateUsageCount)
{ {
if (!isEnabled()) if (!isEnabled())
return ""; return "";
int index = mListView->currentIndex().row(); int index = mListView->currentIndex().row();
PHeaderCompletionListItem item;
if (index>=0 && index<mCompletionList.count()) if (index>=0 && index<mCompletionList.count())
return mCompletionList[index]; item=mCompletionList[index];
else if (mCompletionList.count()>0) { else if (mCompletionList.count()>0) {
return mCompletionList.front(); item=mCompletionList.front();
} }
return ""; if (item) {
if (updateUsageCount) {
item->usageCount++;
mHeaderUsageCounts.insert(item->fullpath,item->usageCount);
}
return item->filename;
}
return "";
} }
static bool sortByUsage(const PHeaderCompletionListItem& item1,const PHeaderCompletionListItem& item2){
if (item1->usageCount != item2->usageCount)
return item1->usageCount > item2->usageCount;
if (item1->itemType != item2->itemType)
return item1->itemType<item2->itemType;
return item1->filename < item2->filename;
}
void HeaderCompletionPopup::filterList(const QString &member) void HeaderCompletionPopup::filterList(const QString &member)
{ {
Qt::CaseSensitivity caseSensitivity=mIgnoreCase?Qt::CaseInsensitive:Qt::CaseSensitive;
mCompletionList.clear(); mCompletionList.clear();
if (member.isEmpty()) { if (member.isEmpty()) {
foreach (const QString& s,mFullCompletionList) { foreach (const PHeaderCompletionListItem& item,mFullCompletionList.values()) {
mCompletionList.append(s); mCompletionList.append(item);
} }
} else { } else {
foreach (const QString& s,mFullCompletionList) { foreach (const PHeaderCompletionListItem& item,mFullCompletionList.values()) {
if (mIgnoreCase && s.startsWith(member, Qt::CaseInsensitive)) { if (item->filename.startsWith(member, caseSensitivity)) {
mCompletionList.append(s); mCompletionList.append(item);
} else if (s.startsWith(member, Qt::CaseSensitive)){
mCompletionList.append(s);
} }
} }
} }
std::sort(mCompletionList.begin(),mCompletionList.end()); std::sort(mCompletionList.begin(),mCompletionList.end(), sortByUsage);
} }
void HeaderCompletionPopup::getCompletionFor(const QString &phrase) void HeaderCompletionPopup::getCompletionFor(const QString &phrase)
{ {
int idx = phrase.lastIndexOf('\\'); int idx = phrase.lastIndexOf('\\');
@ -147,33 +170,33 @@ void HeaderCompletionPopup::getCompletionFor(const QString &phrase)
if (idx < 0) { // dont have basedir if (idx < 0) { // dont have basedir
if (mSearchLocal) { if (mSearchLocal) {
QFileInfo fileInfo(mCurrentFile); QFileInfo fileInfo(mCurrentFile);
addFilesInPath(fileInfo.absolutePath()); addFilesInPath(fileInfo.absolutePath(), HeaderCompletionListItemType::LocalHeader);
}; };
for (const QString& path: mParser->includePaths()) { for (const QString& path: mParser->includePaths()) {
addFilesInPath(path); addFilesInPath(path, HeaderCompletionListItemType::ProjectHeader);
} }
for (const QString& path: mParser->projectIncludePaths()) { for (const QString& path: mParser->projectIncludePaths()) {
addFilesInPath(path); addFilesInPath(path, HeaderCompletionListItemType::SystemHeader);
} }
} else { } else {
QString current = phrase.mid(0,idx); QString current = phrase.mid(0,idx);
if (mSearchLocal) { if (mSearchLocal) {
QFileInfo fileInfo(mCurrentFile); QFileInfo fileInfo(mCurrentFile);
addFilesInSubDir(fileInfo.absolutePath(),current); addFilesInSubDir(fileInfo.absolutePath(),current, HeaderCompletionListItemType::LocalHeader);
} }
for (const QString& path: mParser->includePaths()) { for (const QString& path: mParser->includePaths()) {
addFilesInSubDir(path,current); addFilesInSubDir(path,current, HeaderCompletionListItemType::ProjectHeader);
} }
for (const QString& path: mParser->projectIncludePaths()) { for (const QString& path: mParser->projectIncludePaths()) {
addFilesInSubDir(path,current); addFilesInSubDir(path,current, HeaderCompletionListItemType::SystemHeader);
} }
} }
} }
void HeaderCompletionPopup::addFilesInPath(const QString &path) void HeaderCompletionPopup::addFilesInPath(const QString &path, HeaderCompletionListItemType type)
{ {
QDir dir(path); QDir dir(path);
if (!dir.exists()) if (!dir.exists())
@ -183,25 +206,30 @@ void HeaderCompletionPopup::addFilesInPath(const QString &path)
continue; continue;
QString suffix = fileInfo.suffix().toLower(); QString suffix = fileInfo.suffix().toLower();
if (suffix == "h" || suffix == "hpp" || suffix == "") { if (suffix == "h" || suffix == "hpp" || suffix == "") {
addFile(fileInfo.fileName()); addFile(dir, fileInfo.fileName(), type);
} }
} }
} }
void HeaderCompletionPopup::addFile(const QString &fileName) void HeaderCompletionPopup::addFile(const QDir& dir, const QString &fileName, HeaderCompletionListItemType type)
{ {
if (fileName.isEmpty()) if (fileName.isEmpty())
return; return;
if (fileName.startsWith('.')) if (fileName.startsWith('.'))
return; return;
mFullCompletionList.insert(fileName); PHeaderCompletionListItem item = std::make_shared<HeaderCompletionListItem>();
item->filename = fileName;
item->itemType = type;
item->fullpath = dir.absoluteFilePath(fileName);
item->usageCount = mHeaderUsageCounts.value(item->fullpath,0);
mFullCompletionList.insert(fileName,item);
} }
void HeaderCompletionPopup::addFilesInSubDir(const QString &baseDirPath, const QString &subDirName) void HeaderCompletionPopup::addFilesInSubDir(const QString &baseDirPath, const QString &subDirName, HeaderCompletionListItemType type)
{ {
QDir baseDir(baseDirPath); QDir baseDir(baseDirPath);
QString subDirPath = baseDir.filePath(subDirName); QString subDirPath = baseDir.filePath(subDirName);
addFilesInPath(subDirPath); addFilesInPath(subDirPath, type);
} }
bool HeaderCompletionPopup::searchLocal() const bool HeaderCompletionPopup::searchLocal() const
@ -259,7 +287,7 @@ bool HeaderCompletionPopup::event(QEvent *event)
return result; return result;
} }
HeaderCompletionListModel::HeaderCompletionListModel(const QStringList *files, QObject *parent): HeaderCompletionListModel::HeaderCompletionListModel(const QList<PHeaderCompletionListItem> *files, QObject *parent):
QAbstractListModel(parent), QAbstractListModel(parent),
mFiles(files) mFiles(files)
{ {
@ -280,10 +308,18 @@ QVariant HeaderCompletionListModel::data(const QModelIndex &index, int role) con
switch(role) { switch(role) {
case Qt::DisplayRole: { case Qt::DisplayRole: {
return mFiles->at(index.row()); return mFiles->at(index.row())->filename;
} }
case Qt::ForegroundRole: case Qt::ForegroundRole:
return mColor; switch(mFiles->at(index.row())->itemType) {
case HeaderCompletionListItemType::LocalHeader:
return mLocalColor;
case HeaderCompletionListItemType::ProjectHeader:
return mProjectColor;
case HeaderCompletionListItemType::SystemHeader:
return mSystemColor;
}
break; break;
} }
return QVariant(); return QVariant();
@ -295,7 +331,17 @@ void HeaderCompletionListModel::notifyUpdated()
endResetModel(); endResetModel();
} }
void HeaderCompletionListModel::setColor(const QColor &newColor) void HeaderCompletionListModel::setSystemColor(const QColor &newColor)
{ {
mColor = newColor; mSystemColor = newColor;
}
void HeaderCompletionListModel::setProjectColor(const QColor &newColor)
{
mProjectColor = newColor;
}
void HeaderCompletionListModel::setLocalColor(const QColor &newColor)
{
mLocalColor = newColor;
} }

View File

@ -17,22 +17,42 @@
#ifndef HEADERCOMPLETIONPOPUP_H #ifndef HEADERCOMPLETIONPOPUP_H
#define HEADERCOMPLETIONPOPUP_H #define HEADERCOMPLETIONPOPUP_H
#include <QDir>
#include <QWidget> #include <QWidget>
#include "codecompletionlistview.h" #include "codecompletionlistview.h"
#include "../parser/cppparser.h" #include "../parser/cppparser.h"
enum class HeaderCompletionListItemType {
LocalHeader,
ProjectHeader,
SystemHeader
};
struct HeaderCompletionListItem {
QString filename;
QString fullpath;
int usageCount;
HeaderCompletionListItemType itemType;
};
using PHeaderCompletionListItem=std::shared_ptr<HeaderCompletionListItem>;
class HeaderCompletionListModel: public QAbstractListModel { class HeaderCompletionListModel: public QAbstractListModel {
Q_OBJECT Q_OBJECT
public: public:
explicit HeaderCompletionListModel(const QStringList* files,QObject *parent = nullptr); explicit HeaderCompletionListModel(const QList<PHeaderCompletionListItem>* files,QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override; int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
void notifyUpdated(); void notifyUpdated();
void setColor(const QColor &newColor); void setLocalColor(const QColor &newColor);
void setSystemColor(const QColor &newColor);
void setProjectColor(const QColor &newColor);
private: private:
const QStringList* mFiles; const QList<PHeaderCompletionListItem>* mFiles;
QColor mColor; QColor mLocalColor;
QColor mSystemColor;
QColor mProjectColor;
}; };
class HeaderCompletionPopup : public QWidget class HeaderCompletionPopup : public QWidget
@ -44,21 +64,24 @@ public:
void prepareSearch(const QString& phrase, const QString& fileName); void prepareSearch(const QString& phrase, const QString& fileName);
bool search(const QString& phrase, bool autoHideOnSingleResult); bool search(const QString& phrase, bool autoHideOnSingleResult);
void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback);
void setSuggestionColor(const QColor& color); void setSuggestionColor(const QColor& localColor,
QString selectedFilename(); const QColor& projectColor,
const QColor& systemColor);
QString selectedFilename(bool updateUsageCount);
private: private:
void filterList(const QString& member); void filterList(const QString& member);
void getCompletionFor(const QString& phrase); void getCompletionFor(const QString& phrase);
void addFilesInPath(const QString& path); void addFilesInPath(const QString& path, HeaderCompletionListItemType type);
void addFile(const QString& fileName); void addFile(const QDir& dir, const QString& fileName, HeaderCompletionListItemType type);
void addFilesInSubDir(const QString& baseDirPath, const QString& subDirName); void addFilesInSubDir(const QString& baseDirPath, const QString& subDirName, HeaderCompletionListItemType type);
private: private:
CodeCompletionListView* mListView; CodeCompletionListView* mListView;
HeaderCompletionListModel* mModel; HeaderCompletionListModel* mModel;
QSet<QString> mFullCompletionList; QHash<QString, PHeaderCompletionListItem> mFullCompletionList;
QStringList mCompletionList; QList<PHeaderCompletionListItem> mCompletionList;
QHash<QString,int> mHeaderUsageCounts;
int mShowCount; int mShowCount;
QSet<QString> mAddedFileNames; QSet<QString> mAddedFileNames;