work save

This commit is contained in:
royqh1979@gmail.com 2021-08-23 03:47:28 +08:00
parent 41b9c53146
commit 13b4b9804c
5 changed files with 360 additions and 1 deletions

View File

@ -25,6 +25,7 @@ SOURCES += \
qsynedit/SearchBase.cpp \
qsynedit/SearchRegex.cpp \
settingsdialog/debuggeneralwidget.cpp \
widgets/classbrowser.cpp \
widgets/cpudialog.cpp \
debugger.cpp \
editor.cpp \
@ -87,6 +88,7 @@ HEADERS += \
qsynedit/SearchBase.h \
qsynedit/SearchRegex.h \
settingsdialog/debuggeneralwidget.h \
widgets/classbrowser.h \
widgets/cpudialog.h \
debugger.h \
editor.h \

View File

@ -3517,6 +3517,11 @@ void CppParser::updateSerialId()
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
}
const QString &CppParser::serialId() const
{
return mSerialId;
}
int CppParser::parserId() const
{
return mParserId;

View File

@ -110,6 +110,8 @@ public:
int parserId() const;
const QString &serialId() const;
signals:
void onProgress(const QString& fileName, int total, int current);
void onBusy();
@ -346,5 +348,5 @@ private:
QRecursiveMutex mMutex;
GetFileStreamCallBack mOnGetFileStream;
};
using PCppParser = std::shared_ptr<CppParser>;
#endif // CPPPARSER_H

View File

@ -0,0 +1,297 @@
#include "classbrowser.h"
#include "../utils.h"
ClassBrowserModel::ClassBrowserModel(QObject *parent):QAbstractItemModel(parent)
{
mRoot = new ClassBrowserNode();
mRoot->parent = nullptr;
mRoot->statement = PStatement();
mRoot->childrenFetched = true;
mUpdating = false;
mUpdateCount = 0;
mShowInheritedMembers = false;
}
ClassBrowserModel::~ClassBrowserModel()
{
delete mRoot;
}
QModelIndex ClassBrowserModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row,column,parent))
return QModelIndex();
ClassBrowserNode *parentNode;
if (!parent.isValid()) { // top level
parentNode = mRoot;
} else {
parentNode = static_cast<ClassBrowserNode *>(parent.internalPointer());
}
return createIndex(row,column,parentNode->children[row]);
}
QModelIndex ClassBrowserModel::parent(const QModelIndex &child) const
{
if (child.isValid()) {
return QModelIndex();
}
ClassBrowserNode *childNode = static_cast<ClassBrowserNode *>(child.internalPointer());
ClassBrowserNode *parentNode = childNode->parent;
if (parentNode->parent == nullptr) //it's root node
return QModelIndex();
ClassBrowserNode *grandNode = parentNode->parent;
int row = grandNode->children.indexOf(parentNode);
return createIndex(row,0,parentNode);
}
int ClassBrowserModel::rowCount(const QModelIndex &parent) const
{
ClassBrowserNode *parentNode;
if (!parent.isValid()) { // top level
parentNode = mRoot;
} else {
parentNode = static_cast<ClassBrowserNode *>(parent.internalPointer());
}
return parentNode->children.count();
}
int ClassBrowserModel::columnCount(const QModelIndex&) const
{
return 1;
}
void ClassBrowserModel::fetchMore(const QModelIndex &parent)
{
if (!parent.isValid()) { // top level
return;
}
ClassBrowserNode *parentNode = static_cast<ClassBrowserNode *>(parent.internalPointer());
if (!parentNode->childrenFetched) {
parentNode->childrenFetched = true;
if (parentNode->statement && !parentNode->statement->children.isEmpty())
filterChildren(parentNode, parentNode->statement->children);
}
}
bool ClassBrowserModel::canFetchMore(const QModelIndex &parent) const
{
if (!parent.isValid()) { // top level
return false;
}
ClassBrowserNode *parentNode = static_cast<ClassBrowserNode *>(parent.internalPointer());
if (!parentNode->childrenFetched) {
if (parentNode->statement && !parentNode->statement->children.isEmpty())
return true;
else
parentNode->childrenFetched = true;
}
return false;
}
QVariant ClassBrowserModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()){
return QVariant();
}
ClassBrowserNode *node = static_cast<ClassBrowserNode *>(index.internalPointer());
if (!node)
return QVariant();
if (role == Qt::DisplayRole) {
if (node->statement) {
return node->statement->command;
}
}
return QVariant();
}
const PCppParser &ClassBrowserModel::cppParser() const
{
return mParser;
}
void ClassBrowserModel::setCppParser(const PCppParser &newCppParser)
{
if (mParser) {
disconnect(mParser.get(),
&CppParser::onEndParsing,
this,
&ClassBrowserModel::fillStatements);
}
mParser = newCppParser;
if (mParser) {
connect(mParser.get(),
&CppParser::onEndParsing,
this,
&ClassBrowserModel::fillStatements);
if (!mParser->parsing())
fillStatements();
}
}
void ClassBrowserModel::clear()
{
beginResetModel();
mRoot->children.clear();
mNodes.clear();
mDummyStatements.clear();
endResetModel();
}
void ClassBrowserModel::fillStatements()
{
QMutexLocker locker(&mMutex);
if (mUpdateCount!=0)
return;
mUpdating = true;
beginResetModel();
clear();
{
auto action = finally([this]{
endResetModel();
mUpdating = false;
});
if (!mParser)
return;
if (!mParser->enabled())
return;
if (!mParser->freeze())
return;
{
auto action2 = finally([this]{
mParser->unFreeze();
});
QString mParserSerialId = mParser->serialId();
if (!mCurrentFile.isEmpty()) {
QSet<QString> includedFiles = mParser->getFileIncludes(mCurrentFile);
addMembers(includedFiles);
// Remember selection
// if fLastSelection <> '' then
// ReSelect;
}
}
}
}
void ClassBrowserModel::calculateChildrenCounts(const QModelIndex &index)
{
ClassBrowserNode *parentNode;
if (!index.isValid()) { // top level
parentNode = mRoot;
} else {
parentNode = static_cast<ClassBrowserNode *>(index.internalPointer());
}
if (!parentNode->childrenFetched && parentNode->statement) {
parentNode->childrenFetched = true;
filterChildren(parentNode, parentNode->statement->children);
}
}
void ClassBrowserModel::addChild(ClassBrowserNode *node, PStatement statement)
{
PClassBrowserNode newNode = std::make_shared<ClassBrowserNode>();
newNode->parent = node;
newNode->statement = statement;
newNode->childrenInited = false;
node->children.append(newNode.get());
mNodes.append(newNode);
}
void ClassBrowserModel::addMembers(const QSet<QString> &includedFiles)
{
// show statements in the file
PFileIncludes p = mParser->findFileIncludes(mCurrentFile);
if (!p)
return;
filterChildren(mRoot,p->statements);
}
void ClassBrowserModel::filterChildren(ClassBrowserNode *node, const StatementMap &statements)
{
for (PStatement statement:statements) {
if (statement->kind == StatementKind::skBlock)
continue;
if (statement->isInherited && !mShowInheritedMembers)
continue;
if (statement == node->statement) // prevent infinite recursion
continue;
if (statement->scope == StatementScope::ssLocal)
continue;
// if (fStatementsType = cbstProject) then begin
// if not Statement^._InProject then
// Continue;
// if Statement^._Static and not SameText(Statement^._FileName,fCurrentFile)
// and not SameText(Statement^._FileName,fCurrentFile) then
// Continue;
// end;
// we only test and handle orphan statements in the top level (node->statement is null)
PStatement parentScope = statement->parentScope.lock();
if ((parentScope!=node->statement) && (!node->statement)) {
// // we only handle orphan statements when type is cbstFile
// if fStatementsType <> cbstFile then
// Continue;
// //should not happend, just in case of error
if (!parentScope)
continue;
// Processing the orphan statement
while (statement) {
//the statement's parent is in this file, so it's not a real orphan
if ((parentScope->fileName==mCurrentFile)
||(parentScope->definitionFileName==mCurrentFile))
break;
PStatement dummyParent = mDummyStatements.value(parentScope->fullName,PStatement());
if (dummyParent) {
dummyParent->children.insert(statement->command,statement);
break;
}
dummyParent = createDummy(parentScope);
dummyParent->children.insert(statement->command,statement);
//we are adding an orphan statement, just add it
statement = dummyParent;
parentScope = statement->parentScope.lock();
if (!parentScope) {
addChild(node,statement);
break;
}
}
} else if (statement->kind == StatementKind::skNamespace) {
PStatement dummy = mDummyStatements.value(statement->fullName,PStatement());
if (dummy) {
for (PStatement child: statement->children) {
dummy->children.insert(child->command,child);
}
continue;
}
dummy = createDummy(statement);
dummy->children = statement->children;
addChild(node,dummy);
} else {
addChild(node,statement);
}
}
// if sortAlphabetically and sortByType then begin
// filtered.Sort(@CompareByAlphaAndType);
// end else if sortAlphabetically then begin
// filtered.Sort(@CompareByAlpha);
// end else if sortByType then begin
// filtered.Sort(@CompareByType);
// end;
}

View File

@ -0,0 +1,53 @@
#ifndef CLASSBROWSER_H
#define CLASSBROWSER_H
#include <QAbstractItemModel>
#include "parser/cppparser.h"
struct ClassBrowserNode {
ClassBrowserNode* parent;
PStatement statement;
QVector<ClassBrowserNode *> children;
bool childrenFetched;
};
using PClassBrowserNode = std::shared_ptr<ClassBrowserNode>;
class ClassBrowserModel : public QAbstractItemModel{
Q_OBJECT
// QAbstractItemModel interface
public:
explicit ClassBrowserModel(QObject* parent=nullptr);
~ClassBrowserModel();
ClassBrowserModel& operator=(const ClassBrowserModel& model) = delete;
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
bool canFetchMore(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
const PCppParser &cppParser() const;
void setCppParser(const PCppParser &newCppParser);
void clear();
public slots:
void fillStatements();
private:
void addChild(ClassBrowserNode* node, PStatement statement);
void addMembers(const QSet<QString>& includedFiles);
void filterChildren(ClassBrowserNode * node, const StatementMap& statements);
private:
ClassBrowserNode * mRoot;
QHash<QString,PStatement> mDummyStatements;
QVector<PClassBrowserNode> mNodes;
PCppParser mParser;
bool mUpdating;
int mUpdateCount;
QRecursiveMutex mMutex;
QString mCurrentFile;
bool mShowInheritedMembers;
};
#endif // CLASSBROWSER_H