work save: view models for "find in files"

This commit is contained in:
royqh1979@gmail.com 2021-08-04 13:16:15 +08:00
parent 2be69f0758
commit 579b36ff49
10 changed files with 230 additions and 16 deletions

View File

@ -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 \

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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());

View File

@ -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;

View File

@ -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);

View File

@ -260,7 +260,7 @@
<item>
<widget class="QRadioButton" name="rbCurrentFile">
<property name="text">
<string>current file</string>
<string>Current File</string>
</property>
<property name="checked">
<bool>true</bool>
@ -270,14 +270,14 @@
<item>
<widget class="QRadioButton" name="rbProject">
<property name="text">
<string>Files In project</string>
<string>Files In Project</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbOpenFiles">
<property name="text">
<string>Open files</string>
<string>Open Files</string>
</property>
</widget>
</item>

View File

@ -0,0 +1,120 @@
#include "searchresultview.h"
PSearchResults SearchResultModel::addSearchResults(const QString &keyword, SynSearchOptions options, SearchFileScope scope)
{
int index=-1;
for (int i=0;i<mSearchResults.size();i++) {
PSearchResults results = mSearchResults[i];
if (results->keyword == 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<SearchResults>();
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 && index<mSearchResults.size()) {
mCurrentIndex = index;
emit currentChanged(mCurrentIndex);
}
}
void SearchResultModel::clear()
{
mCurrentIndex = -1;
mSearchResults.clear();
emit modelChanged();
}
SearchResultTreeModel::SearchResultTreeModel(SearchResultModel *model, QObject *parent):
QAbstractItemModel(parent),
mSearchResultModel(model)
{
}
SearchResultListModel::SearchResultListModel(SearchResultModel *model, QObject *parent):
QAbstractListModel(parent),
mSearchResultModel(model)
{
connect(mSearchResultModel, &SearchResultModel::currentChanged,
this, &SearchResultListModel::onResultModelChanged);
connect(mSearchResultModel, &SearchResultModel::modelChanged,
this, &SearchResultListModel::onResultModelChanged);
}
int SearchResultListModel::rowCount(const QModelIndex &parent) const
{
return mSearchResultModel->resultsCount();
}
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();
}

View File

@ -0,0 +1,86 @@
#ifndef SEARCHRESULTVIEW_H
#define SEARCHRESULTVIEW_H
#include <QTreeView>
#include <QMap>
#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<SearchResult>;
using SearchResultList = QList<PSearchResult>;
using PSearchResultList = std::shared_ptr<SearchResultList>;
struct SearchResults{
SynSearchOptions options;
QString keyword;
SearchFileScope scope;
QMap<QString, PSearchResultList> results;
};
using PSearchResults = std::shared_ptr<SearchResults>;
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<PSearchResults> 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