- enhancement: prefer local headers over system headers when complete #include header path
This commit is contained in:
parent
8c99d28307
commit
9d401cce42
1
NEWS.md
1
NEWS.md
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue