From 1c3bf9000cb18c1e9b75f7ba2cc5475da9a81927 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sat, 5 Nov 2022 23:35:15 +0800 Subject: [PATCH] - enhancement: base class dropdown list in new class dialog now works --- NEWS.md | 3 +- RedPandaIDE/mainwindow.cpp | 11 ++- RedPandaIDE/parser/parserutils.h | 2 +- RedPandaIDE/widgets/bookmarkmodel.cpp | 12 ++-- RedPandaIDE/widgets/newclassdialog.cpp | 94 ++++++++++++++++++++++++-- RedPandaIDE/widgets/newclassdialog.h | 28 +++++++- RedPandaIDE/widgets/newclassdialog.ui | 6 +- tools/astyle/ASResource.cpp | 18 ++--- 8 files changed, 147 insertions(+), 27 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6842a4cb..12aef19c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,7 +5,8 @@ Red Panda C++ Version 2.2 - fix: Wrong charset name returned when saving file - fix: 'using =' / 'namespace =' not correctly handled - fix: Pressing '*' at begin of line will crash app - - enhancement: switch header/source + - enhancement: switch header/source in editor's context menu + - enhancement: base class dropdown list in new class dialog now works Red Panda C++ Version 2.1 diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index b8bbb802..e0cd08bc 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -7963,7 +7963,7 @@ void MainWindow::on_actionNew_Class_triggered() { if (!mProject) return; - NewClassDialog dialog; + NewClassDialog dialog(mProject->cppParser()); dialog.setPath(mProject->folder()); if (dialog.exec()==QDialog::Accepted) { QDir dir(dialog.path()); @@ -7997,7 +7997,14 @@ void MainWindow::on_actionNew_Class_triggered() header.append(QString("#ifndef %1").arg(header_macro)); header.append(QString("#define %1").arg(header_macro)); header.append(""); - header.append(QString("class %1 {").arg(dialog.className())); + if (dialog.baseClass()) { + header.append(QString("#include \"%1\"").arg(extractRelativePath(mProject->directory(), + dialog.baseClass()->fileName))); + header.append(""); + header.append(QString("class %1 : public %2 {").arg(dialog.className(), + dialog.baseClass()->fullName)); + } else + header.append(QString("class %1 {").arg(dialog.className())); header.append("public:"); header.append(""); header.append("private:"); diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index fd3bc1e4..ddce1ff2 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -149,7 +149,7 @@ using StatementMap = QMultiMap; struct Statement { // Statement(); // ~Statement(); - std::weak_ptr parentScope; // parent class/struct/namespace scope, don't use auto pointer to prevent circular reference + std::weak_ptr parentScope; // parent class/struct/namespace scope, use weak pointer to prevent circular reference QString type; // type "int" QString command; // identifier/name of statement "foo" QString args; // args "(int a,float b)" diff --git a/RedPandaIDE/widgets/bookmarkmodel.cpp b/RedPandaIDE/widgets/bookmarkmodel.cpp index 5ffe45f6..83f15a0a 100644 --- a/RedPandaIDE/widgets/bookmarkmodel.cpp +++ b/RedPandaIDE/widgets/bookmarkmodel.cpp @@ -431,13 +431,13 @@ void BookmarkModel::sort(int column, Qt::SortOrder order) case 0: if (order == Qt::SortOrder::AscendingOrder) { auto sorter=[](PBookmark b1,PBookmark b2) { - return QString::compare(b1->description,b2->description); + return b1->description < b2->description; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); } else { auto sorter=[](PBookmark b1,PBookmark b2) { - return QString::compare(b2->description,b1->description); + return b2->descriptiondescription; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); @@ -446,13 +446,13 @@ void BookmarkModel::sort(int column, Qt::SortOrder order) case 1: if (order == Qt::SortOrder::AscendingOrder) { auto sorter=[](PBookmark b1,PBookmark b2) { - return QString::compare(b1->filename,b2->filename); + return b1->filenamefilename; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); } else { auto sorter=[](PBookmark b1,PBookmark b2) { - return QString::compare(b2->filename,b1->filename); + return b2->filenamefilename; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); @@ -461,13 +461,13 @@ void BookmarkModel::sort(int column, Qt::SortOrder order) case 2: if (order == Qt::SortOrder::AscendingOrder) { auto sorter=[](PBookmark b1,PBookmark b2) { - return b1->line-b2->line; + return b1->lineline; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); } else { auto sorter=[](PBookmark b1,PBookmark b2) { - return b2->line-b1->line; + return b2->lineline; }; std::sort(mBookmarks.begin(),mBookmarks.end(),sorter); std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter); diff --git a/RedPandaIDE/widgets/newclassdialog.cpp b/RedPandaIDE/widgets/newclassdialog.cpp index f880baa2..6f110896 100644 --- a/RedPandaIDE/widgets/newclassdialog.cpp +++ b/RedPandaIDE/widgets/newclassdialog.cpp @@ -19,10 +19,12 @@ #include "../iconsmanager.h" #include "../settings.h" #include +#include -NewClassDialog::NewClassDialog(QWidget *parent) : +NewClassDialog::NewClassDialog(PCppParser parser, QWidget *parent) : QDialog(parent), - ui(new Ui::NewClassDialog) + ui(new Ui::NewClassDialog), + mModel(parser) { setWindowFlag(Qt::WindowContextHelpButtonHint,false); ui->setupUi(this); @@ -31,6 +33,7 @@ NewClassDialog::NewClassDialog(QWidget *parent) : connect(pIconsManager,&IconsManager::actionIconsUpdated, this, &NewClassDialog::onUpdateIcons); ui->txtClassName->setFocus(); + ui->cbBaseClass->setModel(&mModel); } NewClassDialog::~NewClassDialog() @@ -42,9 +45,9 @@ QString NewClassDialog::className() const return ui->txtClassName->text(); } -QString NewClassDialog::baseClass() const +PStatement NewClassDialog::baseClass() const { - return ui->cbBaseClass->currentText(); + return mModel.getCandidate(ui->cbBaseClass->currentIndex()); } QString NewClassDialog::headerName() const @@ -105,3 +108,86 @@ void NewClassDialog::on_txtClassName_textChanged(const QString &/* arg1 */) ui->txtSourceName->setText(ui->txtClassName->text().toLower()+".cpp"); } +NewClassCandidatesModel::NewClassCandidatesModel(PCppParser parser):QAbstractListModel(), + mParser(parser) +{ + fillClasses(); +} + +PStatement NewClassCandidatesModel::getCandidate(int row) const +{ + if (row<0) + return PStatement(); + if (row==0) + return PStatement(); + return mCandidates[row-1]; +} + + +void NewClassCandidatesModel::fillClasses() +{ + if (!mParser->enabled()) + return; + if (!mParser->freeze()) + return; + foreach( const PStatement& s, mParser->statementList().childrenStatements()) { + if (s->kind==StatementKind::skClass + && s->inProject + && !s->command.startsWith("_") + && !s->command.contains("<") + && !mClassNames.contains(s->fullName)) { + if (getFileType(s->fileName)==FileType::CHeader + || getFileType(s->fileName)==FileType::CppHeader) { + mCandidates.append(s); + mClassNames.insert(s->fullName); + } + } else if (s->kind == StatementKind::skNamespace + && !s->command.startsWith("_") + && !s->command.contains("<")) { + fillClassesInNamespace(s); + } + } + mParser->unFreeze(); + std::sort(mCandidates.begin(),mCandidates.end(),[](const PStatement& s1, const PStatement& s2){ + return s1->fullNamefullName; + }); + +} + +void NewClassCandidatesModel::fillClassesInNamespace(PStatement ns) +{ + foreach( const PStatement& s, mParser->statementList().childrenStatements(ns)) { + if (s->kind==StatementKind::skClass + && s->inProject + && !s->command.startsWith("_") + && !s->command.contains("<") + && !mClassNames.contains(s->fullName)) { + if (getFileType(s->fileName)==FileType::CHeader + || getFileType(s->fileName)==FileType::CppHeader) { + mCandidates.append(s); + mClassNames.insert(s->fullName); + } + } else if (s->kind == StatementKind::skNamespace + && !s->command.startsWith("_") + && !s->command.contains("<")) { + fillClassesInNamespace(s); + } + } +} + +int NewClassCandidatesModel::rowCount(const QModelIndex &/*parent*/) const +{ + return mCandidates.count()+1; +} + +QVariant NewClassCandidatesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (role==Qt::DisplayRole) { + if (index.row()==0) + return ""; + return mCandidates[index.row()-1]->fullName; + } + return QVariant(); +} diff --git a/RedPandaIDE/widgets/newclassdialog.h b/RedPandaIDE/widgets/newclassdialog.h index 6b14110b..6d6d3534 100644 --- a/RedPandaIDE/widgets/newclassdialog.h +++ b/RedPandaIDE/widgets/newclassdialog.h @@ -18,21 +18,42 @@ #define NEWCLASSDIALOG_H #include +#include "../parser/cppparser.h" +#include namespace Ui { class NewClassDialog; } +class NewClassCandidatesModel: public QAbstractListModel { + Q_OBJECT +public: + explicit NewClassCandidatesModel(PCppParser parser); + PStatement getCandidate(int row) const; +private: + void fillClasses(); + void fillClassesInNamespace(PStatement ns); +private: + PCppParser mParser; + QVector mCandidates; + QSet mClassNames; + + // QAbstractItemModel interface +public: + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; +}; + class NewClassDialog : public QDialog { Q_OBJECT public: - explicit NewClassDialog(QWidget *parent = nullptr); + explicit NewClassDialog(PCppParser parser, QWidget *parent = nullptr); ~NewClassDialog(); QString className() const; - QString baseClass() const; + PStatement baseClass() const; QString headerName() const; QString sourceName() const; QString path() const; @@ -49,7 +70,8 @@ private slots: private: Ui::NewClassDialog *ui; - + QList mClasses; + NewClassCandidatesModel mModel; private: void onUpdateIcons(); diff --git a/RedPandaIDE/widgets/newclassdialog.ui b/RedPandaIDE/widgets/newclassdialog.ui index 819a7e31..759f8b6a 100644 --- a/RedPandaIDE/widgets/newclassdialog.ui +++ b/RedPandaIDE/widgets/newclassdialog.ui @@ -48,7 +48,11 @@ - + + + false + + diff --git a/tools/astyle/ASResource.cpp b/tools/astyle/ASResource.cpp index 9c190cb0..4ad44f3f 100644 --- a/tools/astyle/ASResource.cpp +++ b/tools/astyle/ASResource.cpp @@ -208,7 +208,7 @@ void ASResource::buildAssignmentOperators(vector* assignmentOpera assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN); assert(assignmentOperators->size() < elements); - sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength); + sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength); } /** @@ -228,7 +228,7 @@ void ASResource::buildCastOperators(vector* castOperators) castOperators->emplace_back(&AS_STATIC_CAST); assert(castOperators->size() < elements); - sort(castOperators->begin(), castOperators->end(), sortOnName); + sort(castOperators->begin(), castOperators->end(), sortOnName); } /** @@ -295,7 +295,7 @@ void ASResource::buildHeaders(vector* headers, int fileType, bool } assert(headers->size() < elements); - sort(headers->begin(), headers->end(), sortOnName); + sort(headers->begin(), headers->end(), sortOnName); } /** @@ -369,7 +369,7 @@ void ASResource::buildNonAssignmentOperators(vector* nonAssignmen nonAssignmentOperators->emplace_back(&AS_LAMBDA); assert(nonAssignmentOperators->size() < elements); - sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength); + sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength); } /** @@ -425,7 +425,7 @@ void ASResource::buildNonParenHeaders(vector* nonParenHeaders, in } assert(nonParenHeaders->size() < elements); - sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName); + sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName); } /** @@ -489,7 +489,7 @@ void ASResource::buildOperators(vector* operators, int fileType) } assert(operators->size() < elements); - sort(operators->begin(), operators->end(), sortOnLength); + sort(operators->begin(), operators->end(), sortOnLength); } /** @@ -527,7 +527,7 @@ void ASResource::buildPreBlockStatements(vector* preBlockStatemen } assert(preBlockStatements->size() < elements); - sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName); + sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName); } /** @@ -567,7 +567,7 @@ void ASResource::buildPreCommandHeaders(vector* preCommandHeaders } assert(preCommandHeaders->size() < elements); - sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName); + sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName); } /** @@ -604,7 +604,7 @@ void ASResource::buildPreDefinitionHeaders(vector* preDefinitionH } assert(preDefinitionHeaders->size() < elements); - sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName); + sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *