From 579b36ff496f4b6cf582da3cb0dbf85c10111f5c Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 4 Aug 2021 13:16:15 +0800 Subject: [PATCH] work save: view models for "find in files" --- RedPandaIDE/RedPandaIDE.pro | 6 +- RedPandaIDE/qsynedit/Search.cpp | 12 +-- RedPandaIDE/qsynedit/Search.h | 2 +- RedPandaIDE/qsynedit/SearchBase.h | 2 +- RedPandaIDE/qsynedit/SearchRegex.cpp | 4 +- RedPandaIDE/qsynedit/SearchRegex.h | 2 +- RedPandaIDE/utils.h | 6 ++ RedPandaIDE/widgets/searchdialog.ui | 6 +- RedPandaIDE/widgets/searchresultview.cpp | 120 +++++++++++++++++++++++ RedPandaIDE/widgets/searchresultview.h | 86 ++++++++++++++++ 10 files changed, 230 insertions(+), 16 deletions(-) create mode 100644 RedPandaIDE/widgets/searchresultview.cpp create mode 100644 RedPandaIDE/widgets/searchresultview.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index b3f21bac..28cf0aa0 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -62,7 +62,8 @@ SOURCES += \ widgets/issuestable.cpp \ widgets/qconsole.cpp \ widgets/qpatchedcombobox.cpp \ - widgets/searchdialog.cpp + widgets/searchdialog.cpp \ + widgets/searchresultview.cpp HEADERS += \ HighlighterManager.h \ @@ -119,7 +120,8 @@ HEADERS += \ widgets/issuestable.h \ widgets/qconsole.h \ widgets/qpatchedcombobox.h \ - widgets/searchdialog.h + widgets/searchdialog.h \ + widgets/searchresultview.h FORMS += \ settingsdialog/debuggeneralwidget.ui \ diff --git a/RedPandaIDE/qsynedit/Search.cpp b/RedPandaIDE/qsynedit/Search.cpp index 5f66fb8f..b94cd790 100644 --- a/RedPandaIDE/qsynedit/Search.cpp +++ b/RedPandaIDE/qsynedit/Search.cpp @@ -24,7 +24,7 @@ int SynSearch::resultCount() return mResults.count(); } -int SynSearch::findAll(const QString &newText) +int SynSearch::findAll(const QString &keyword) { mResults.clear(); if (pattern().isEmpty()) @@ -33,18 +33,18 @@ int SynSearch::findAll(const QString &newText) int next=-1; while (true) { if (options().testFlag(ssoMatchCase)) { - next = newText.indexOf(pattern(),start,Qt::CaseSensitive); + next = keyword.indexOf(pattern(),start,Qt::CaseSensitive); } else { - next = newText.indexOf(pattern(),start,Qt::CaseInsensitive); + next = keyword.indexOf(pattern(),start,Qt::CaseInsensitive); } if (next<0) { break; } - start = next + newText.length(); + start = next + keyword.length(); if (options().testFlag(ssoWholeWord)) { - if (((next<=0) || isDelimitChar(newText[next-1])) + if (((next<=0) || isDelimitChar(keyword[next-1])) && - ( (start>=newText.length()) || isDelimitChar(newText[start]) ) + ( (start>=keyword.length()) || isDelimitChar(keyword[start]) ) ) { mResults.append(next); } diff --git a/RedPandaIDE/qsynedit/Search.h b/RedPandaIDE/qsynedit/Search.h index c6ab316c..3032c8ed 100644 --- a/RedPandaIDE/qsynedit/Search.h +++ b/RedPandaIDE/qsynedit/Search.h @@ -14,7 +14,7 @@ public: int length(int aIndex) override; int result(int aIndex) override; int resultCount() override; - int findAll(const QString &newText) override; + int findAll(const QString &keyword) override; QString replace(const QString &aOccurrence, const QString &aReplacement) override; private: bool isDelimitChar(QChar ch); diff --git a/RedPandaIDE/qsynedit/SearchBase.h b/RedPandaIDE/qsynedit/SearchBase.h index 62a41160..9e3adacb 100644 --- a/RedPandaIDE/qsynedit/SearchBase.h +++ b/RedPandaIDE/qsynedit/SearchBase.h @@ -26,7 +26,7 @@ public: virtual int length(int aIndex) = 0; virtual int result(int aIndex) = 0; virtual int resultCount() = 0; - virtual int findAll(const QString& newText) = 0; + virtual int findAll(const QString& keyword) = 0; virtual QString replace(const QString& aOccurrence, const QString& aReplacement) = 0; SynSearchOptions options() const; virtual void setOptions(const SynSearchOptions &options); diff --git a/RedPandaIDE/qsynedit/SearchRegex.cpp b/RedPandaIDE/qsynedit/SearchRegex.cpp index 49c7dbab..aed1da7e 100644 --- a/RedPandaIDE/qsynedit/SearchRegex.cpp +++ b/RedPandaIDE/qsynedit/SearchRegex.cpp @@ -26,13 +26,13 @@ int SynSearchRegex::resultCount() return mResults.size(); } -int SynSearchRegex::findAll(const QString &newText) +int SynSearchRegex::findAll(const QString &keyword) { if (pattern().isEmpty()) return 0; mResults.clear(); mLengths.clear(); - QRegularExpressionMatchIterator it = mRegex.globalMatch(newText); + QRegularExpressionMatchIterator it = mRegex.globalMatch(keyword); while (it.hasNext()) { QRegularExpressionMatch match = it.next(); mLengths.append(match.capturedLength()); diff --git a/RedPandaIDE/qsynedit/SearchRegex.h b/RedPandaIDE/qsynedit/SearchRegex.h index 2fc9255f..b85f43f9 100644 --- a/RedPandaIDE/qsynedit/SearchRegex.h +++ b/RedPandaIDE/qsynedit/SearchRegex.h @@ -15,7 +15,7 @@ public: int length(int aIndex) override; int result(int aIndex) override; int resultCount() override; - int findAll(const QString &newText) override; + int findAll(const QString &keyword) override; QString replace(const QString &aOccurrence, const QString &aReplacement) override; void setPattern(const QString &value) override; void setOptions(const SynSearchOptions &options) override; diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index 346f53f5..8803c706 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -34,6 +34,12 @@ enum class FileEndingType { Mac };// Windows: CRLF, UNIX: LF, Mac: CR +enum class SearchFileScope { + currentFile, + wholeProject, + openedFiles +}; + class BaseError{ public: explicit BaseError(const QString& reason); diff --git a/RedPandaIDE/widgets/searchdialog.ui b/RedPandaIDE/widgets/searchdialog.ui index c29a52a1..b6880e60 100644 --- a/RedPandaIDE/widgets/searchdialog.ui +++ b/RedPandaIDE/widgets/searchdialog.ui @@ -260,7 +260,7 @@ - current file + Current File true @@ -270,14 +270,14 @@ - Files In project + Files In Project - Open files + Open Files diff --git a/RedPandaIDE/widgets/searchresultview.cpp b/RedPandaIDE/widgets/searchresultview.cpp new file mode 100644 index 00000000..4f76aaad --- /dev/null +++ b/RedPandaIDE/widgets/searchresultview.cpp @@ -0,0 +1,120 @@ +#include "searchresultview.h" + +PSearchResults SearchResultModel::addSearchResults(const QString &keyword, SynSearchOptions options, SearchFileScope scope) +{ + int index=-1; + for (int i=0;ikeyword == keyword && results->scope == scope) { + index=i; + break; + } + } + if (index>0) { + mSearchResults.removeAt(index); + } + if (mSearchResults.size()>=MAX_SEARCH_RESULTS) { + mSearchResults.pop_back(); + } + PSearchResults results = std::make_shared(); + results->keyword = keyword; + results->options = options; + results->scope = scope; + mSearchResults.push_front(results); + emit modelChanged(); + return results; +} + +PSearchResults SearchResultModel::results(int index) +{ + if (index<0 || index>=mSearchResults.size()) { + return PSearchResults(); + } + return mSearchResults[index]; +} + +SearchResultModel::SearchResultModel(QObject* parent): + QObject(parent), + mCurrentIndex(-1) +{ + +} + +int SearchResultModel::currentIndex() const +{ + return mCurrentIndex; +} + +int SearchResultModel::resultsCount() const +{ + return mSearchResults.count(); +} + +PSearchResults SearchResultModel::currentResults() +{ + return results(mCurrentIndex); +} + +void SearchResultModel::setCurrentIndex(int index) +{ + if (index!=mCurrentIndex && + index>=0 && indexresultsCount(); +} + +QVariant SearchResultListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (role == Qt::DisplayRole) { + PSearchResults results = mSearchResultModel->results(index.row()); + if (!results) + return QVariant(); + switch (results->scope) { + case SearchFileScope::currentFile: + return tr("Current File") + QString(" \"%1\"").arg(results->keyword); + case SearchFileScope::wholeProject: + return tr("Files In Project") + QString(" \"%1\"").arg(results->keyword); + case SearchFileScope::openedFiles: + return tr("Open Files") + QString(" \"%1\"").arg(results->keyword); + } + } + return QVariant(); +} + +void SearchResultListModel::onResultModelChanged() +{ + beginResetModel(); + endResetModel(); +} diff --git a/RedPandaIDE/widgets/searchresultview.h b/RedPandaIDE/widgets/searchresultview.h new file mode 100644 index 00000000..02d1cc03 --- /dev/null +++ b/RedPandaIDE/widgets/searchresultview.h @@ -0,0 +1,86 @@ +#ifndef SEARCHRESULTVIEW_H +#define SEARCHRESULTVIEW_H + +#include +#include +#include "../qsynedit/SearchBase.h" +#include "utils.h" + +#define MAX_SEARCH_RESULTS 20 + +struct SearchResult { + QString filename; + int line; + int start; + int len; +}; + +using PSearchResult = std::shared_ptr; +using SearchResultList = QList; +using PSearchResultList = std::shared_ptr; + +struct SearchResults{ + SynSearchOptions options; + QString keyword; + SearchFileScope scope; + QMap results; +}; + +using PSearchResults = std::shared_ptr; + +class SearchResultModel : QObject { + Q_OBJECT +public: + explicit SearchResultModel(QObject* parent=nullptr); + PSearchResults addSearchResults(const QString& keyword,SynSearchOptions options, + SearchFileScope scope); + PSearchResults results(int index); + int currentIndex() const; + int resultsCount() const; + PSearchResults currentResults(); + void setCurrentIndex(int index); + void clear(); +signals: + void modelChanged(); + void currentChanged(int index); +private: + QList mSearchResults; + int mCurrentIndex; + +}; + +class SearchResultListModel: public QAbstractListModel { +Q_OBJECT + // QAbstractItemModel interface +public: + explicit SearchResultListModel(SearchResultModel* model,QObject* parent=nullptr); + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; +public slots: + void onResultModelChanged(); +private: + SearchResultModel *mSearchResultModel; +}; + +class SearchResultTreeModel : public QAbstractItemModel { +Q_OBJECT + // QAbstractItemModel interface +public: + explicit SearchResultTreeModel(SearchResultModel* model,QObject* parent=nullptr); + 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; + QVariant data(const QModelIndex &index, int role) const override; +private: + SearchResultModel *mSearchResultModel; +}; + +class SearchResultView : public QTreeView +{ + Q_OBJECT +public: + explicit SearchResultView(QWidget* parent=nullptr); +}; + +#endif // SEARCHRESULTVIEW_H