- fix: Escape suquences like \uxxxx and \Uxxxxxxxx in strings are not correctly highlighted.
- enhancement: Search / replace dialogs redesigned. - fix: inline functions are not correctly parsed; - fix: &operator= functions are not correctly parsed; - fix: Code Formatter's "add indent to continueous lines" option is not correctly saved.
This commit is contained in:
parent
1dbc0972ab
commit
b085560743
8
NEWS.md
8
NEWS.md
|
@ -20,6 +20,11 @@ Red Panda C++ Version 2.4
|
||||||
- fix: modifitions in the project options dialogs's dll host page is not correctly saved.
|
- fix: modifitions in the project options dialogs's dll host page is not correctly saved.
|
||||||
- enhancement: In the project options dialog, autoset the default folder in the openning dialog when choosing file/directory paths.
|
- enhancement: In the project options dialog, autoset the default folder in the openning dialog when choosing file/directory paths.
|
||||||
- fix: Escape suquences like \uxxxx and \Uxxxxxxxx in strings are not correctly highlighted.
|
- fix: Escape suquences like \uxxxx and \Uxxxxxxxx in strings are not correctly highlighted.
|
||||||
|
- enhancement: Search / replace dialogs redesigned.
|
||||||
|
- fix: inline functions are not correctly parsed;
|
||||||
|
- fix: &operator= functions are not correctly parsed;
|
||||||
|
- fix: Code Formatter's "add indent to continueous lines" option is not correctly saved.
|
||||||
|
|
||||||
|
|
||||||
Red Panda C++ Version 2.3
|
Red Panda C++ Version 2.3
|
||||||
|
|
||||||
|
@ -46,7 +51,8 @@ Red Panda C++ Version 2.2
|
||||||
- fix: Set max undo memory usage to 0 don't really remove the limit for undo
|
- fix: Set max undo memory usage to 0 don't really remove the limit for undo
|
||||||
- fix: Set max undo times to 0 don't really remove the limit for undo
|
- fix: Set max undo times to 0 don't really remove the limit for undo
|
||||||
- fix: Keep the newest undo info regardless of undo memory usage
|
- fix: Keep the newest undo info regardless of undo memory usage
|
||||||
|
- fix: inline functions not correctly handled by parser
|
||||||
|
- fix: &operator= not correctly handled by parser
|
||||||
|
|
||||||
Red Panda C++ Version 2.1
|
Red Panda C++ Version 2.1
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,9 @@ SOURCES += \
|
||||||
widgets/projectalreadyopendialog.cpp \
|
widgets/projectalreadyopendialog.cpp \
|
||||||
widgets/qconsole.cpp \
|
widgets/qconsole.cpp \
|
||||||
widgets/qpatchedcombobox.cpp \
|
widgets/qpatchedcombobox.cpp \
|
||||||
|
widgets/replacedialog.cpp \
|
||||||
widgets/searchdialog.cpp \
|
widgets/searchdialog.cpp \
|
||||||
|
widgets/searchinfiledialog.cpp \
|
||||||
widgets/searchresultview.cpp \
|
widgets/searchresultview.cpp \
|
||||||
widgets/shortcutinputedit.cpp \
|
widgets/shortcutinputedit.cpp \
|
||||||
widgets/shrinkabletabwidget.cpp \
|
widgets/shrinkabletabwidget.cpp \
|
||||||
|
@ -331,7 +333,9 @@ HEADERS += \
|
||||||
widgets/projectalreadyopendialog.h \
|
widgets/projectalreadyopendialog.h \
|
||||||
widgets/qconsole.h \
|
widgets/qconsole.h \
|
||||||
widgets/qpatchedcombobox.h \
|
widgets/qpatchedcombobox.h \
|
||||||
|
widgets/replacedialog.h \
|
||||||
widgets/searchdialog.h \
|
widgets/searchdialog.h \
|
||||||
|
widgets/searchinfiledialog.h \
|
||||||
widgets/searchresultview.h \
|
widgets/searchresultview.h \
|
||||||
widgets/shortcutinputedit.h \
|
widgets/shortcutinputedit.h \
|
||||||
widgets/shrinkabletabwidget.h \
|
widgets/shrinkabletabwidget.h \
|
||||||
|
@ -395,7 +399,9 @@ FORMS += \
|
||||||
widgets/newtemplatedialog.ui \
|
widgets/newtemplatedialog.ui \
|
||||||
widgets/ojproblempropertywidget.ui \
|
widgets/ojproblempropertywidget.ui \
|
||||||
widgets/projectalreadyopendialog.ui \
|
widgets/projectalreadyopendialog.ui \
|
||||||
|
widgets/replacedialog.ui \
|
||||||
widgets/searchdialog.ui \
|
widgets/searchdialog.ui \
|
||||||
|
widgets/searchinfiledialog.ui \
|
||||||
widgets/signalmessagedialog.ui
|
widgets/signalmessagedialog.ui
|
||||||
|
|
||||||
win32: {
|
win32: {
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
#include "widgets/newtemplatedialog.h"
|
#include "widgets/newtemplatedialog.h"
|
||||||
#include "visithistorymanager.h"
|
#include "visithistorymanager.h"
|
||||||
#include "widgets/projectalreadyopendialog.h"
|
#include "widgets/projectalreadyopendialog.h"
|
||||||
|
#include "widgets/searchdialog.h"
|
||||||
|
#include "widgets/replacedialog.h"
|
||||||
|
|
||||||
|
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
@ -85,7 +88,7 @@
|
||||||
#include "cpprefacter.h"
|
#include "cpprefacter.h"
|
||||||
|
|
||||||
#include "widgets/newprojectunitdialog.h"
|
#include "widgets/newprojectunitdialog.h"
|
||||||
#include "widgets/searchdialog.h"
|
#include "widgets/searchinfiledialog.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
|
@ -107,7 +110,9 @@ MainWindow* pMainWindow;
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent),
|
: QMainWindow(parent),
|
||||||
ui(new Ui::MainWindow),
|
ui(new Ui::MainWindow),
|
||||||
|
mSearchInFilesDialog(nullptr),
|
||||||
mSearchDialog(nullptr),
|
mSearchDialog(nullptr),
|
||||||
|
mReplaceDialog(nullptr),
|
||||||
mQuitting(false),
|
mQuitting(false),
|
||||||
mClosingProject(false),
|
mClosingProject(false),
|
||||||
mCheckSyntaxInBack(false),
|
mCheckSyntaxInBack(false),
|
||||||
|
@ -965,6 +970,18 @@ void MainWindow::onFileSaved(const QString &path, bool inProject)
|
||||||
//updateForEncodingInfo();
|
//updateForEncodingInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::prepareSearchDialog()
|
||||||
|
{
|
||||||
|
if (!mSearchDialog)
|
||||||
|
mSearchDialog = new SearchDialog(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::prepareReplaceDialog()
|
||||||
|
{
|
||||||
|
if (!mReplaceDialog)
|
||||||
|
mReplaceDialog = new ReplaceDialog(this);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateAppTitle()
|
void MainWindow::updateAppTitle()
|
||||||
{
|
{
|
||||||
Editor *e = mEditorList->getEditor();
|
Editor *e = mEditorList->getEditor();
|
||||||
|
@ -4783,9 +4800,9 @@ const std::shared_ptr<CodeCompletionPopup> &MainWindow::completionPopup() const
|
||||||
return mCompletionPopup;
|
return mCompletionPopup;
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchDialog *MainWindow::searchDialog() const
|
SearchInFileDialog *MainWindow::searchInFilesDialog() const
|
||||||
{
|
{
|
||||||
return mSearchDialog;
|
return mSearchInFilesDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchResultModel *MainWindow::searchResultModel()
|
SearchResultModel *MainWindow::searchResultModel()
|
||||||
|
@ -5771,24 +5788,22 @@ void MainWindow::on_actionFind_triggered()
|
||||||
Editor *e = mEditorList->getEditor();
|
Editor *e = mEditorList->getEditor();
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
if (mSearchDialog==nullptr) {
|
|
||||||
mSearchDialog = new SearchDialog(this);
|
|
||||||
}
|
|
||||||
QString s = e->wordAtCursor();
|
QString s = e->wordAtCursor();
|
||||||
|
prepareSearchDialog();
|
||||||
mSearchDialog->find(s);
|
mSearchDialog->find(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionFind_in_files_triggered()
|
void MainWindow::on_actionFind_in_files_triggered()
|
||||||
{
|
{
|
||||||
if (mSearchDialog==nullptr) {
|
if (mSearchInFilesDialog==nullptr) {
|
||||||
mSearchDialog = new SearchDialog(this);
|
mSearchInFilesDialog = new SearchInFileDialog(this);
|
||||||
}
|
}
|
||||||
Editor *e = mEditorList->getEditor();
|
Editor *e = mEditorList->getEditor();
|
||||||
if (e) {
|
if (e) {
|
||||||
QString s = e->wordAtCursor();
|
QString s = e->wordAtCursor();
|
||||||
mSearchDialog->findInFiles(s);
|
mSearchInFilesDialog->findInFiles(s);
|
||||||
} else {
|
} else {
|
||||||
mSearchDialog->findInFiles("");
|
mSearchInFilesDialog->findInFiles("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5797,11 +5812,10 @@ void MainWindow::on_actionReplace_triggered()
|
||||||
Editor *e = mEditorList->getEditor();
|
Editor *e = mEditorList->getEditor();
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
if (mSearchDialog==nullptr) {
|
|
||||||
mSearchDialog = new SearchDialog(this);
|
|
||||||
}
|
|
||||||
QString s = e->wordAtCursor();
|
QString s = e->wordAtCursor();
|
||||||
mSearchDialog->replace(s,s);
|
prepareReplaceDialog();
|
||||||
|
mReplaceDialog->replace(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionFind_Next_triggered()
|
void MainWindow::on_actionFind_Next_triggered()
|
||||||
|
@ -5841,14 +5855,14 @@ void MainWindow::on_cbSearchHistory_currentIndexChanged(int index)
|
||||||
|
|
||||||
void MainWindow::on_btnSearchAgain_clicked()
|
void MainWindow::on_btnSearchAgain_clicked()
|
||||||
{
|
{
|
||||||
if (mSearchDialog==nullptr) {
|
if (mSearchInFilesDialog==nullptr) {
|
||||||
mSearchDialog = new SearchDialog(this);
|
mSearchInFilesDialog = new SearchInFileDialog(this);
|
||||||
}
|
}
|
||||||
PSearchResults results=mSearchResultModel.currentResults();
|
PSearchResults results=mSearchResultModel.currentResults();
|
||||||
if (!results)
|
if (!results)
|
||||||
return;
|
return;
|
||||||
if (results->searchType == SearchType::Search){
|
if (results->searchType == SearchType::Search){
|
||||||
mSearchDialog->findInFiles(results->keyword,
|
mSearchInFilesDialog->findInFiles(results->keyword,
|
||||||
results->scope,
|
results->scope,
|
||||||
results->options);
|
results->options);
|
||||||
} else if (results->searchType == SearchType::FindOccurences) {
|
} else if (results->searchType == SearchType::FindOccurences) {
|
||||||
|
@ -8785,3 +8799,8 @@ void MainWindow::on_actionSwitchHeaderSource_triggered()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchDialog *MainWindow::searchDialog() const
|
||||||
|
{
|
||||||
|
return mSearchDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,9 @@ class Editor;
|
||||||
class Debugger;
|
class Debugger;
|
||||||
class CPUDialog;
|
class CPUDialog;
|
||||||
class QPlainTextEdit;
|
class QPlainTextEdit;
|
||||||
|
class SearchInFileDialog;
|
||||||
class SearchDialog;
|
class SearchDialog;
|
||||||
|
class ReplaceDialog;
|
||||||
class Project;
|
class Project;
|
||||||
struct ProjectModelNode;
|
struct ProjectModelNode;
|
||||||
class ProjectUnit;
|
class ProjectUnit;
|
||||||
|
@ -173,6 +175,8 @@ public:
|
||||||
|
|
||||||
EditorList *editorList() const;
|
EditorList *editorList() const;
|
||||||
|
|
||||||
|
SearchInFileDialog *searchInFilesDialog() const;
|
||||||
|
|
||||||
SearchDialog *searchDialog() const;
|
SearchDialog *searchDialog() const;
|
||||||
|
|
||||||
SearchResultModel* searchResultModel();
|
SearchResultModel* searchResultModel();
|
||||||
|
@ -252,6 +256,8 @@ public slots:
|
||||||
void onFileSaved(const QString& path, bool inProject);
|
void onFileSaved(const QString& path, bool inProject);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void prepareSearchDialog();
|
||||||
|
void prepareReplaceDialog();
|
||||||
void prepareProjectForCompile();
|
void prepareProjectForCompile();
|
||||||
void closeProject(bool refreshEditor);
|
void closeProject(bool refreshEditor);
|
||||||
void updateProjectView();
|
void updateProjectView();
|
||||||
|
@ -756,7 +762,9 @@ private:
|
||||||
std::shared_ptr<CompilerManager> mCompilerManager;
|
std::shared_ptr<CompilerManager> mCompilerManager;
|
||||||
std::shared_ptr<Debugger> mDebugger;
|
std::shared_ptr<Debugger> mDebugger;
|
||||||
CPUDialog *mCPUDialog;
|
CPUDialog *mCPUDialog;
|
||||||
|
SearchInFileDialog *mSearchInFilesDialog;
|
||||||
SearchDialog *mSearchDialog;
|
SearchDialog *mSearchDialog;
|
||||||
|
ReplaceDialog *mReplaceDialog;
|
||||||
bool mQuitting;
|
bool mQuitting;
|
||||||
bool mClosingProject;
|
bool mClosingProject;
|
||||||
QElapsedTimer mParserTimer;
|
QElapsedTimer mParserTimer;
|
||||||
|
|
|
@ -1456,8 +1456,10 @@ void CppParser::addSoloScopeLevel(PStatement& statement, int line, bool shouldRe
|
||||||
else
|
else
|
||||||
mClassScope = StatementClassScope::Public; // structs are public by default
|
mClassScope = StatementClassScope::Public; // structs are public by default
|
||||||
mCurrentClassScope.append(mClassScope);
|
mCurrentClassScope.append(mClassScope);
|
||||||
//if (mCurrentClassScope.count()==2)
|
#ifdef QT_DEBUG
|
||||||
|
//if (mCurrentClassScope.count()==1)
|
||||||
// qDebug()<<"++add scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
// qDebug()<<"++add scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppParser::removeScopeLevel(int line)
|
void CppParser::removeScopeLevel(int line)
|
||||||
|
@ -1465,8 +1467,10 @@ void CppParser::removeScopeLevel(int line)
|
||||||
// Remove class list
|
// Remove class list
|
||||||
if (mCurrentScope.isEmpty())
|
if (mCurrentScope.isEmpty())
|
||||||
return; // TODO: should be an exception
|
return; // TODO: should be an exception
|
||||||
//if (mCurrentClassScope.count()==2)
|
#ifdef QT_DEBUG
|
||||||
|
//if (mCurrentClassScope.count()==1)
|
||||||
// qDebug()<<"--remove scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
// qDebug()<<"--remove scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
||||||
|
#endif
|
||||||
PStatement currentScope = getCurrentScope();
|
PStatement currentScope = getCurrentScope();
|
||||||
PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile);
|
PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile);
|
||||||
if (currentScope) {
|
if (currentScope) {
|
||||||
|
@ -1867,8 +1871,8 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType)
|
||||||
&& !isIdentChar(currentText[8])) {
|
&& !isIdentChar(currentText[8])) {
|
||||||
// operator overloading
|
// operator overloading
|
||||||
handleMethod(StatementKind::skFunction,"",
|
handleMethod(StatementKind::skFunction,"",
|
||||||
mergeArgs(mIndex+1,mTokenizer[mIndex]->matchIndex-1),
|
currentText,
|
||||||
indexAfterParentheis,false,false);
|
mIndex,false,false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//check for constructor like Foo::Foo()
|
//check for constructor like Foo::Foo()
|
||||||
|
@ -1996,7 +2000,7 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType)
|
||||||
||mTokenizer[mIndex + 1]->text == ';'
|
||mTokenizer[mIndex + 1]->text == ';'
|
||||||
||mTokenizer[mIndex + 1]->text == ':'
|
||mTokenizer[mIndex + 1]->text == ':'
|
||||||
||mTokenizer[mIndex + 1]->text == '{'
|
||mTokenizer[mIndex + 1]->text == '{'
|
||||||
||mTokenizer[mIndex + 1]->text == '=') {
|
|| mTokenizer[mIndex + 1]->text == '=') {
|
||||||
handleVar(sType,isExtern,isStatic);
|
handleVar(sType,isExtern,isStatic);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3027,6 +3031,11 @@ void CppParser::handleScope(KeywordType keywordType)
|
||||||
mIndex+=2; // the scope is followed by a ':'
|
mIndex+=2; // the scope is followed by a ':'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
static int lastIndex=-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool CppParser::handleStatement()
|
bool CppParser::handleStatement()
|
||||||
{
|
{
|
||||||
QString funcType,funcName;
|
QString funcType,funcName;
|
||||||
|
@ -3034,6 +3043,11 @@ bool CppParser::handleStatement()
|
||||||
int idx2=getCurrentBlockBeginSkip();
|
int idx2=getCurrentBlockBeginSkip();
|
||||||
int idx3=getCurrentInlineNamespaceEndSkip();
|
int idx3=getCurrentInlineNamespaceEndSkip();
|
||||||
KeywordType keywordType;
|
KeywordType keywordType;
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
// qDebug()<<lastIndex<<mIndex;
|
||||||
|
Q_ASSERT(mIndex>=lastIndex);
|
||||||
|
lastIndex=mIndex;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mIndex >= idx2) {
|
if (mIndex >= idx2) {
|
||||||
//skip (previous handled) block begin
|
//skip (previous handled) block begin
|
||||||
|
@ -3080,7 +3094,7 @@ bool CppParser::handleStatement()
|
||||||
// } else if (checkForLambda()) { // is lambda
|
// } else if (checkForLambda()) { // is lambda
|
||||||
// handleLambda();
|
// handleLambda();
|
||||||
} else if (mTokenizer[mIndex]->text=='(') {
|
} else if (mTokenizer[mIndex]->text=='(') {
|
||||||
if (mTokenizer[mIndex]->text=="operator") {
|
if (mIndex+1<mTokenizer.tokenCount() && mTokenizer[mIndex+1]->text=="operator") {
|
||||||
// things like (operator int)
|
// things like (operator int)
|
||||||
mIndex++; //just skip '('
|
mIndex++; //just skip '('
|
||||||
} else
|
} else
|
||||||
|
@ -3131,11 +3145,13 @@ bool CppParser::handleStatement()
|
||||||
handleUsing();
|
handleUsing();
|
||||||
} else if (checkForStructs(keywordType)) {
|
} else if (checkForStructs(keywordType)) {
|
||||||
handleStructs(false);
|
handleStructs(false);
|
||||||
} else {
|
} else if (keywordType == KeywordType::Inline) {
|
||||||
|
mIndex++;
|
||||||
|
}else {
|
||||||
// it should be method/constructor/var
|
// it should be method/constructor/var
|
||||||
checkAndHandleMethodOrVar(keywordType);
|
checkAndHandleMethodOrVar(keywordType);
|
||||||
}
|
}
|
||||||
Q_ASSERT(mIndex<999999);
|
//Q_ASSERT(mIndex<999999);
|
||||||
|
|
||||||
// while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
|
// while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
|
||||||
// handleLambda(mTokenizer.indexOfFirstLambda());
|
// handleLambda(mTokenizer.indexOfFirstLambda());
|
||||||
|
@ -3723,6 +3739,9 @@ void CppParser::internalParse(const QString &fileName)
|
||||||
return;
|
return;
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||||
|
#endif
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
lastIndex = -1;
|
||||||
#endif
|
#endif
|
||||||
// Process the token list
|
// Process the token list
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
|
@ -418,6 +418,7 @@ QString CppTokenizer::getWord(bool bSkipParenthesis, bool bSkipArray, bool bSkip
|
||||||
}
|
}
|
||||||
// Append the operator characters and argument list to the operator word
|
// Append the operator characters and argument list to the operator word
|
||||||
if ((currentWord == "operator") ||
|
if ((currentWord == "operator") ||
|
||||||
|
(currentWord == "&operator") ||
|
||||||
(currentWord == "operator*") ||
|
(currentWord == "operator*") ||
|
||||||
(currentWord == "operator&")) {
|
(currentWord == "operator&")) {
|
||||||
// Spaces between 'operator' and the operator itself are allowed
|
// Spaces between 'operator' and the operator itself are allowed
|
||||||
|
|
|
@ -4793,7 +4793,7 @@ void Settings::CodeFormatter::doLoad()
|
||||||
mIndentCases = boolValue("indent_cases",false);
|
mIndentCases = boolValue("indent_cases",false);
|
||||||
mIndentNamespaces = boolValue("indent_namespaces",true);
|
mIndentNamespaces = boolValue("indent_namespaces",true);
|
||||||
mIndentAfterParens = boolValue("indent_after_parents",false);
|
mIndentAfterParens = boolValue("indent_after_parents",false);
|
||||||
mIndentContinuation = boolValue("indent_continuation",false);
|
mIndentContinuation = intValue("indent_continuation",1);
|
||||||
mIndentLabels = boolValue("indent_labels",false);
|
mIndentLabels = boolValue("indent_labels",false);
|
||||||
mIndentPreprocBlock = boolValue("indent_preproc_block",true);
|
mIndentPreprocBlock = boolValue("indent_preproc_block",true);
|
||||||
mIndentPreprocCond = boolValue("indent_preproc_cond",false);
|
mIndentPreprocCond = boolValue("indent_preproc_cond",false);
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
@ -337,7 +337,11 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="spinMaxContinuationIndent"/>
|
<widget class="QSpinBox" name="spinMaxContinuationIndent">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>40</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_5">
|
<spacer name="horizontalSpacer_5">
|
||||||
|
@ -883,7 +887,7 @@
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="referenceBtnGroup"/>
|
|
||||||
<buttongroup name="pointerBtnGroup"/>
|
<buttongroup name="pointerBtnGroup"/>
|
||||||
|
<buttongroup name="referenceBtnGroup"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -6171,6 +6171,105 @@
|
||||||
<translation>Valor</translation>
|
<translation>Valor</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>ReplaceDialog</name>
|
||||||
|
<message>
|
||||||
|
<source>Replace</source>
|
||||||
|
<translation type="unfinished">Substituir</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Text to Find:</source>
|
||||||
|
<translation type="unfinished">Texto a procurar:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace with:</source>
|
||||||
|
<translation type="unfinished">Substituir por:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Scope:</source>
|
||||||
|
<translation type="unfinished">Escopo:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Global</source>
|
||||||
|
<translation type="unfinished">Global</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Selection</source>
|
||||||
|
<translation type="unfinished">Seleção</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Origin:</source>
|
||||||
|
<translation type="unfinished">Origem:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>From cursor</source>
|
||||||
|
<translation type="unfinished">A partir do cursor</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Entire scope</source>
|
||||||
|
<translation type="unfinished">Escopo inteiro</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Options:</source>
|
||||||
|
<translation type="unfinished">Opções:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Whole words only</source>
|
||||||
|
<translation type="unfinished">Apenas palavras inteiras</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Wrap Around</source>
|
||||||
|
<translation type="unfinished">Wrap Around</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Regular Expression</source>
|
||||||
|
<translation type="unfinished">Expressão regular</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Prompt on replace</source>
|
||||||
|
<translation type="unfinished">Perguntar ao substituir</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Case Sensitive</source>
|
||||||
|
<translation type="unfinished">Sensibilidade a maiúsculas/minúsculas</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Previous</source>
|
||||||
|
<translation type="unfinished">Procurar anterior</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Next</source>
|
||||||
|
<translation type="unfinished">Procurar outro</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace All</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Close</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Beginning of file has been reached. </source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's end?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>End of file has been reached. </source>
|
||||||
|
<translation type="unfinished">Encontrado fim de arquivo.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's beginning?</source>
|
||||||
|
<translation type="unfinished">Quer continuar a partir do início do arquivo?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Continue Search</source>
|
||||||
|
<translation type="unfinished">Continuar a procura</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SearchDialog</name>
|
<name>SearchDialog</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6271,15 +6370,15 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Replace</source>
|
<source>Replace</source>
|
||||||
<translation>Substituir</translation>
|
<translation type="vanished">Substituir</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Find in files</source>
|
<source>Find in files</source>
|
||||||
<translation>Procurar em arquivos</translation>
|
<translation type="vanished">Procurar em arquivos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Replace in files</source>
|
<source>Replace in files</source>
|
||||||
<translation>Substituir em arquivos</translation>
|
<translation type="vanished">Substituir em arquivos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Continue Search</source>
|
<source>Continue Search</source>
|
||||||
|
@ -6295,11 +6394,74 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Replace this occurrence of ''%1''?</source>
|
<source>Replace this occurrence of ''%1''?</source>
|
||||||
<translation>Substituir essa ocorrência de ''%1''?</translation>
|
<translation type="vanished">Substituir essa ocorrência de ''%1''?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Continue Replace</source>
|
<source>Continue Replace</source>
|
||||||
<translation>Continuar a substituir</translation>
|
<translation type="vanished">Continuar a substituir</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Close after search</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Previous</source>
|
||||||
|
<translation type="unfinished">Procurar anterior</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Next</source>
|
||||||
|
<translation type="unfinished">Procurar outro</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Close</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Beginning of file has been reached. </source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's end?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>SearchInFileDialog</name>
|
||||||
|
<message>
|
||||||
|
<source>Find</source>
|
||||||
|
<translation type="obsolete">Procurar</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace</source>
|
||||||
|
<translation type="obsolete">Substituir</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find in files</source>
|
||||||
|
<translation type="obsolete">Procurar em arquivos</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace in files</source>
|
||||||
|
<translation type="obsolete">Substituir em arquivos</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Continue Search</source>
|
||||||
|
<translation type="obsolete">Continuar a procura</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>End of file has been reached. </source>
|
||||||
|
<translation type="obsolete">Encontrado fim de arquivo.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's beginning?</source>
|
||||||
|
<translation type="obsolete">Quer continuar a partir do início do arquivo?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace this occurrence of ''%1''?</source>
|
||||||
|
<translation type="obsolete">Substituir essa ocorrência de ''%1''?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Continue Replace</source>
|
||||||
|
<translation type="obsolete">Continuar a substituir</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5908,6 +5908,105 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>ReplaceDialog</name>
|
||||||
|
<message>
|
||||||
|
<source>Replace</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Text to Find:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace with:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Scope:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Global</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Selection</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Origin:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>From cursor</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Entire scope</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Options:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Whole words only</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Wrap Around</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Regular Expression</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Prompt on replace</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Case Sensitive</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Previous</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Next</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Replace All</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Close</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Beginning of file has been reached. </source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's end?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>End of file has been reached. </source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's beginning?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Continue Search</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SearchDialog</name>
|
<name>SearchDialog</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6006,18 +6105,6 @@
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>Replace</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Find in files</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Replace in files</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Continue Search</source>
|
<source>Continue Search</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -6031,11 +6118,27 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Replace this occurrence of ''%1''?</source>
|
<source>Close after search</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Continue Replace</source>
|
<source>Find Previous</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Find Next</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Close</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Beginning of file has been reached. </source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do you want to continue from file's end?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "compiler/executablerunner.h"
|
#include "compiler/executablerunner.h"
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QComboBox>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -526,3 +527,15 @@ QString getSizeString(int size)
|
||||||
return QString("%1 ").arg(size / 1024.0 / 1024.0 / 1024.0)+QObject::tr("GB");
|
return QString("%1 ").arg(size / 1024.0 / 1024.0 / 1024.0)+QObject::tr("GB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveComboHistory(QComboBox* cb,const QString& text) {
|
||||||
|
QString s = text.trimmed();
|
||||||
|
if (s.isEmpty())
|
||||||
|
return;
|
||||||
|
int i = cb->findText(s);
|
||||||
|
if (i>=0) {
|
||||||
|
cb->removeItem(i);
|
||||||
|
}
|
||||||
|
cb->insertItem(0,s);
|
||||||
|
cb->setCurrentText(s);
|
||||||
|
}
|
||||||
|
|
|
@ -143,4 +143,8 @@ QByteArray getHTTPBody(const QByteArray& content);
|
||||||
|
|
||||||
QString getSizeString(int size);
|
QString getSizeString(int size);
|
||||||
|
|
||||||
|
class QComboBox;
|
||||||
|
void saveComboHistory(QComboBox* cb,const QString& text);
|
||||||
|
|
||||||
|
|
||||||
#endif // UTILS_H
|
#endif // UTILS_H
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
#include "replacedialog.h"
|
||||||
|
#include "ui_replacedialog.h"
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <memory>
|
||||||
|
#include <qsynedit/Search.h>
|
||||||
|
#include <qsynedit/SearchRegex.h>
|
||||||
|
#include "../utils.h"
|
||||||
|
#include "../editor.h"
|
||||||
|
#include "../editorlist.h"
|
||||||
|
#include "../mainwindow.h"
|
||||||
|
|
||||||
|
ReplaceDialog::ReplaceDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ReplaceDialog),
|
||||||
|
mSearchOptions()
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
mBasicSearchEngine= std::make_shared<QSynedit::BasicSearcher>();
|
||||||
|
mRegexSearchEngine= std::make_shared<QSynedit::RegexSearcher>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplaceDialog::~ReplaceDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::replace(const QString &text)
|
||||||
|
{
|
||||||
|
ui->cbFind->setCurrentText(text);
|
||||||
|
ui->cbFind->setFocus();
|
||||||
|
//ui->cbReplace->setCurrentText("");
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::doSearch(bool backward)
|
||||||
|
{
|
||||||
|
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
||||||
|
prepareOptions(backward);
|
||||||
|
|
||||||
|
Editor *editor = pMainWindow->editorList()->getEditor();
|
||||||
|
if (editor) {
|
||||||
|
// Modify the caret when using 'from cursor' and when the selection is ignored
|
||||||
|
if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
||||||
|
&& editor->selAvail()) {
|
||||||
|
// start at end of selection
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
||||||
|
editor->setCaretXY(editor->blockBegin());
|
||||||
|
} else {
|
||||||
|
editor->setCaretXY(editor->blockEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QSynedit::PSynSearchBase searchEngine;
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
||||||
|
searchEngine = mRegexSearchEngine;
|
||||||
|
} else {
|
||||||
|
searchEngine = mBasicSearchEngine;
|
||||||
|
}
|
||||||
|
editor->searchReplace(
|
||||||
|
ui->cbFind->currentText(),
|
||||||
|
"",
|
||||||
|
mSearchOptions,
|
||||||
|
searchEngine, nullptr, [this,backward](){
|
||||||
|
QString msg;
|
||||||
|
if (backward) {
|
||||||
|
msg = tr("Beginning of file has been reached. ")
|
||||||
|
+tr("Do you want to continue from file's end?");
|
||||||
|
} else {
|
||||||
|
msg = tr("End of file has been reached. ")
|
||||||
|
+tr("Do you want to continue from file's beginning?");
|
||||||
|
}
|
||||||
|
QWidget *p;
|
||||||
|
if (isVisible()) {
|
||||||
|
p=this;
|
||||||
|
} else {
|
||||||
|
p=pMainWindow;
|
||||||
|
}
|
||||||
|
return QMessageBox::question(p,
|
||||||
|
tr("Continue Search"),
|
||||||
|
msg,
|
||||||
|
QMessageBox::Yes|QMessageBox::No,
|
||||||
|
QMessageBox::Yes) == QMessageBox::Yes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::doReplace(bool replaceAll)
|
||||||
|
{
|
||||||
|
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
||||||
|
saveComboHistory(ui->cbReplace,ui->cbReplace->currentText());
|
||||||
|
prepareOptions(false);
|
||||||
|
Editor *editor = pMainWindow->editorList()->getEditor();
|
||||||
|
if (editor) {
|
||||||
|
// // Modify the caret when using 'from cursor' and when the selection is ignored
|
||||||
|
// if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
||||||
|
// && editor->selAvail()) {
|
||||||
|
// // start at end of selection
|
||||||
|
// if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
||||||
|
// editor->setCaretXY(editor->blockBegin());
|
||||||
|
// } else {
|
||||||
|
// editor->setCaretXY(editor->blockEnd());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
QSynedit::PSynSearchBase searchEngine;
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
||||||
|
searchEngine = mRegexSearchEngine;
|
||||||
|
} else {
|
||||||
|
searchEngine = mBasicSearchEngine;
|
||||||
|
}
|
||||||
|
editor->searchReplace(
|
||||||
|
ui->cbFind->currentText(),
|
||||||
|
ui->cbReplace->currentText(),
|
||||||
|
mSearchOptions,
|
||||||
|
searchEngine,
|
||||||
|
[&replaceAll](const QString& /*sSearch*/,
|
||||||
|
const QString& /*sReplace*/, int /*Line*/, int /*ch*/, int /*wordLen*/){
|
||||||
|
if (replaceAll) {
|
||||||
|
return QSynedit::SearchAction::ReplaceAll;
|
||||||
|
} else {
|
||||||
|
return QSynedit::SearchAction::ReplaceAndExit;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this](){
|
||||||
|
QString msg = tr("End of file has been reached. ")
|
||||||
|
+tr("Do you want to continue from file's beginning?");
|
||||||
|
QWidget *p;
|
||||||
|
if (isVisible()) {
|
||||||
|
p=this;
|
||||||
|
} else {
|
||||||
|
p=pMainWindow;
|
||||||
|
}
|
||||||
|
return QMessageBox::question(p,
|
||||||
|
tr("Continue Search"),
|
||||||
|
msg,
|
||||||
|
QMessageBox::Yes|QMessageBox::No,
|
||||||
|
QMessageBox::Yes) == QMessageBox::Yes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::prepareOptions(bool backward)
|
||||||
|
{
|
||||||
|
mSearchOptions&=0;
|
||||||
|
|
||||||
|
// Apply options
|
||||||
|
if (backward) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoBackwards);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->chkRegExp->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoRegExp);
|
||||||
|
}
|
||||||
|
if (ui->chkCaseSensetive->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoMatchCase);
|
||||||
|
}
|
||||||
|
if (ui->chkWholeWord->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoWholeWord);
|
||||||
|
}
|
||||||
|
if (ui->chkWrapAround->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoWrapAround);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply scope, when enabled
|
||||||
|
if (ui->grpScope->isEnabled()) {
|
||||||
|
if (ui->rbSelection->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoSelectedOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply origin, when enabled
|
||||||
|
if (ui->grpOrigin->isEnabled()) {
|
||||||
|
if (ui->rbEntireScope->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoEntireScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::on_cbFind_currentTextChanged(const QString &value)
|
||||||
|
{
|
||||||
|
ui->btnNext->setEnabled(!value.isEmpty());
|
||||||
|
ui->btnPrevious->setEnabled(!value.isEmpty());
|
||||||
|
ui->btnReplace->setEnabled(!value.isEmpty());
|
||||||
|
ui->btnReplaceAll->setEnabled(!value.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::on_btnClose_clicked()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::on_btnNext_clicked()
|
||||||
|
{
|
||||||
|
doSearch(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::on_btnPrevious_clicked()
|
||||||
|
{
|
||||||
|
doSearch(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceDialog::on_btnReplace_clicked()
|
||||||
|
{
|
||||||
|
doReplace(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ReplaceDialog::on_btnReplaceAll_clicked()
|
||||||
|
{
|
||||||
|
doReplace(true);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef REPLACEDIALOG_H
|
||||||
|
#define REPLACEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <qsynedit/SearchBase.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ReplaceDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReplaceDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ReplaceDialog(QWidget *parent = nullptr);
|
||||||
|
~ReplaceDialog();
|
||||||
|
void replace(const QString& text);
|
||||||
|
private:
|
||||||
|
void doSearch(bool backward);
|
||||||
|
void doReplace(bool replaceAll);
|
||||||
|
void prepareOptions(bool backward);
|
||||||
|
private slots:
|
||||||
|
void on_cbFind_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
|
void on_btnClose_clicked();
|
||||||
|
|
||||||
|
void on_btnNext_clicked();
|
||||||
|
|
||||||
|
void on_btnPrevious_clicked();
|
||||||
|
void on_btnReplace_clicked();
|
||||||
|
|
||||||
|
void on_btnReplaceAll_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ReplaceDialog *ui;
|
||||||
|
QSynedit::SearchOptions mSearchOptions;
|
||||||
|
QSynedit::PSynSearchBase mBasicSearchEngine;
|
||||||
|
QSynedit::PSynSearchBase mRegexSearchEngine;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPLACEDIALOG_H
|
|
@ -0,0 +1,386 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ReplaceDialog</class>
|
||||||
|
<widget class="QDialog" name="ReplaceDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>512</width>
|
||||||
|
<height>242</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Replace</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_4" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="lblFind">
|
||||||
|
<property name="text">
|
||||||
|
<string>Text to Find:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="cbFind">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="insertPolicy">
|
||||||
|
<enum>QComboBox::InsertAtTop</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace with:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="cbReplace">
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="insertPolicy">
|
||||||
|
<enum>QComboBox::InsertAtTop</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QGroupBox" name="grpScope">
|
||||||
|
<property name="title">
|
||||||
|
<string>Scope:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbGlobal">
|
||||||
|
<property name="text">
|
||||||
|
<string>Global</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbSelection">
|
||||||
|
<property name="text">
|
||||||
|
<string>Selection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QGroupBox" name="grpOrigin">
|
||||||
|
<property name="title">
|
||||||
|
<string>Origin:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbFromCursor">
|
||||||
|
<property name="text">
|
||||||
|
<string>From cursor</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbEntireScope">
|
||||||
|
<property name="text">
|
||||||
|
<string>Entire scope</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" rowspan="2">
|
||||||
|
<widget class="QGroupBox" name="grpOptions">
|
||||||
|
<property name="title">
|
||||||
|
<string>Options:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkWholeWord">
|
||||||
|
<property name="text">
|
||||||
|
<string>Whole words only</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkWrapAround">
|
||||||
|
<property name="text">
|
||||||
|
<string>Wrap Around</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="txtRegExpHelp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><html><head/><body><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"><span style=" text-decoration: underline; color:#0000ff;">(?)</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkRegExp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Regular Expression</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkPrompt">
|
||||||
|
<property name="text">
|
||||||
|
<string>Prompt on replace</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkCaseSensetive">
|
||||||
|
<property name="text">
|
||||||
|
<string>Case Sensitive</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<spacer name="verticalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_3" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPrevious">
|
||||||
|
<property name="text">
|
||||||
|
<string>Find Previous</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNext">
|
||||||
|
<property name="text">
|
||||||
|
<string>Find Next</string>
|
||||||
|
</property>
|
||||||
|
<property name="default">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnReplace">
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnReplaceAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>15</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClose">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -1,51 +1,23 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include "searchdialog.h"
|
#include "searchdialog.h"
|
||||||
#include "ui_searchdialog.h"
|
#include "ui_searchdialog.h"
|
||||||
#include <QTabBar>
|
|
||||||
#include "../editor.h"
|
#include <QMessageBox>
|
||||||
#include "../mainwindow.h"
|
#include <memory>
|
||||||
#include "../editorlist.h"
|
|
||||||
#include <qsynedit/Search.h>
|
#include <qsynedit/Search.h>
|
||||||
#include <qsynedit/SearchRegex.h>
|
#include <qsynedit/SearchRegex.h>
|
||||||
#include "../project.h"
|
#include "../utils.h"
|
||||||
#include "../settings.h"
|
#include "../editor.h"
|
||||||
#include <QMessageBox>
|
#include "../editorlist.h"
|
||||||
#include <QDebug>
|
#include "../mainwindow.h"
|
||||||
|
|
||||||
|
|
||||||
SearchDialog::SearchDialog(QWidget *parent) :
|
SearchDialog::SearchDialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::SearchDialog),
|
ui(new Ui::SearchDialog),
|
||||||
mSearchEngine()
|
mSearchOptions()
|
||||||
{
|
{
|
||||||
setWindowFlag(Qt::WindowContextHelpButtonHint,false);
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
mTabBar = new QTabBar();
|
mBasicSearchEngine= std::make_shared<QSynedit::BasicSearcher>();
|
||||||
mTabBar->addTab(tr("Find"));
|
mRegexSearchEngine= std::make_shared<QSynedit::RegexSearcher>();
|
||||||
mTabBar->addTab(tr("Replace"));
|
|
||||||
mTabBar->addTab(tr("Find in files"));
|
|
||||||
mTabBar->addTab(tr("Replace in files"));
|
|
||||||
mTabBar->setExpanding(false);
|
|
||||||
ui->dialogLayout->insertWidget(0,mTabBar);
|
|
||||||
connect(mTabBar,&QTabBar::currentChanged,this, &SearchDialog::onTabChanged);
|
|
||||||
mSearchOptions&=0;
|
|
||||||
mBasicSearchEngine= QSynedit::PSynSearchBase(new QSynedit::BasicSearcher());
|
|
||||||
mRegexSearchEngine= QSynedit::PSynSearchBase(new QSynedit::RegexSearcher());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchDialog::~SearchDialog()
|
SearchDialog::~SearchDialog()
|
||||||
|
@ -55,11 +27,6 @@ SearchDialog::~SearchDialog()
|
||||||
|
|
||||||
void SearchDialog::find(const QString &text)
|
void SearchDialog::find(const QString &text)
|
||||||
{
|
{
|
||||||
if (mTabBar->currentIndex()==0) {
|
|
||||||
this->onTabChanged();
|
|
||||||
} else {
|
|
||||||
mTabBar->setCurrentIndex(0);
|
|
||||||
}
|
|
||||||
ui->cbFind->setCurrentText(text);
|
ui->cbFind->setCurrentText(text);
|
||||||
ui->cbFind->setFocus();
|
ui->cbFind->setFocus();
|
||||||
show();
|
show();
|
||||||
|
@ -67,153 +34,29 @@ void SearchDialog::find(const QString &text)
|
||||||
|
|
||||||
void SearchDialog::findNext()
|
void SearchDialog::findNext()
|
||||||
{
|
{
|
||||||
if (mTabBar->currentIndex()==0) { // it's a find action
|
doSearch(false);
|
||||||
|
if (ui->chkCloseAfterSearch)
|
||||||
// Disable entire scope searching
|
close();
|
||||||
ui->rbEntireScope->setChecked(false);
|
|
||||||
|
|
||||||
// Always search forwards
|
|
||||||
ui->rbForward->setChecked(true);
|
|
||||||
|
|
||||||
ui->btnExecute->click();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchDialog::findInFiles(const QString &text)
|
void SearchDialog::findPrevious()
|
||||||
{
|
{
|
||||||
mTabBar->setCurrentIndex(2);
|
doSearch(true);
|
||||||
ui->cbFind->setCurrentText(text);
|
if (ui->chkCloseAfterSearch)
|
||||||
ui->cbFind->setFocus();
|
close();
|
||||||
show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchDialog::findInFiles(const QString &keyword, SearchFileScope scope, QSynedit::SearchOptions options)
|
void SearchDialog::doSearch(bool backward)
|
||||||
{
|
{
|
||||||
mTabBar->setCurrentIndex(2);
|
|
||||||
|
|
||||||
ui->cbFind->setCurrentText(keyword);
|
|
||||||
ui->cbFind->setFocus();
|
|
||||||
|
|
||||||
switch(scope) {
|
|
||||||
case SearchFileScope::currentFile:
|
|
||||||
ui->rbCurrentFile->setChecked(true);
|
|
||||||
break;
|
|
||||||
case SearchFileScope::openedFiles:
|
|
||||||
ui->rbOpenFiles->setChecked(true);
|
|
||||||
break;
|
|
||||||
case SearchFileScope::wholeProject:
|
|
||||||
ui->rbProject->setChecked(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Apply options
|
|
||||||
ui->chkRegExp->setChecked(options.testFlag(QSynedit::ssoRegExp));
|
|
||||||
ui->chkCaseSensetive->setChecked(options.testFlag(QSynedit::ssoMatchCase));
|
|
||||||
ui->chkWholeWord->setChecked(options.testFlag(QSynedit::ssoWholeWord));
|
|
||||||
ui->chkWrapAround->setChecked(options.testFlag(QSynedit::ssoWholeWord));
|
|
||||||
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::replace(const QString &sFind, const QString &sReplace)
|
|
||||||
{
|
|
||||||
mTabBar->setCurrentIndex(1);
|
|
||||||
ui->cbFind->setCurrentText(sFind);
|
|
||||||
ui->cbReplace->setCurrentText(sReplace);
|
|
||||||
ui->cbFind->setFocus();
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::onTabChanged()
|
|
||||||
{
|
|
||||||
bool isfind = (mTabBar->currentIndex() == 0);
|
|
||||||
bool isfindfiles = (mTabBar->currentIndex() == 2 || mTabBar->currentIndex() == 3 );
|
|
||||||
bool isreplace = (mTabBar->currentIndex() == 1);
|
|
||||||
|
|
||||||
ui->lblReplace->setVisible(isreplace);
|
|
||||||
ui->cbReplace->setVisible(isreplace);
|
|
||||||
|
|
||||||
ui->grpOrigin->setVisible(isfind || isreplace);
|
|
||||||
ui->grpOrigin->setEnabled(isfind || isreplace);
|
|
||||||
|
|
||||||
ui->grpScope->setVisible(isfind || isreplace);
|
|
||||||
ui->grpScope->setEnabled(isreplace);
|
|
||||||
ui->grpWhere->setVisible(isfindfiles);
|
|
||||||
ui->grpWhere->setEnabled(isfindfiles);
|
|
||||||
ui->grpDirection->setVisible(isfind || isreplace);
|
|
||||||
ui->grpDirection->setEnabled(isfind || isreplace);
|
|
||||||
|
|
||||||
// grpOption is always visible
|
|
||||||
|
|
||||||
// Disable project search option when none is open
|
|
||||||
// rbProjectFiles.Enabled := Assigned(MainForm.Project);
|
|
||||||
ui->rbProject->setEnabled(pMainWindow->project()!=nullptr);
|
|
||||||
ui->rbOpenFiles->setEnabled(pMainWindow->editorList()->pageCount()>0);
|
|
||||||
// if not Assigned(MainForm.Project) then
|
|
||||||
// rbOpenFiles.Checked := true;
|
|
||||||
|
|
||||||
// Disable prompt when doing finds
|
|
||||||
ui->chkPrompt->setEnabled(isreplace);
|
|
||||||
ui->chkPrompt->setVisible(isreplace);
|
|
||||||
ui->chkWrapAround->setEnabled(!isfindfiles);
|
|
||||||
ui->chkWrapAround->setVisible(!isfindfiles);
|
|
||||||
|
|
||||||
if (isfind || isfindfiles) {
|
|
||||||
ui->btnExecute->setText(tr("Find"));
|
|
||||||
} else {
|
|
||||||
ui->btnExecute->setText(tr("Replace"));
|
|
||||||
}
|
|
||||||
setWindowTitle(mTabBar->tabText(mTabBar->currentIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::on_cbFind_currentTextChanged(const QString &)
|
|
||||||
{
|
|
||||||
ui->btnExecute->setEnabled(!ui->cbFind->currentText().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::on_btnCancel_clicked()
|
|
||||||
{
|
|
||||||
this->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void saveComboHistory(QComboBox* cb,const QString& text) {
|
|
||||||
QString s = text.trimmed();
|
|
||||||
if (s.isEmpty())
|
|
||||||
return;
|
|
||||||
int i = cb->findText(s);
|
|
||||||
if (i>=0) {
|
|
||||||
cb->removeItem(i);
|
|
||||||
}
|
|
||||||
cb->insertItem(0,s);
|
|
||||||
cb->setCurrentText(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::on_btnExecute_clicked()
|
|
||||||
{
|
|
||||||
int findCount = 0;
|
|
||||||
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
||||||
saveComboHistory(ui->cbReplace,ui->cbReplace->currentText());
|
|
||||||
|
|
||||||
SearchAction actionType;
|
|
||||||
switch (mTabBar->currentIndex()) {
|
|
||||||
case 0:
|
|
||||||
actionType = SearchAction::Find;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
actionType = SearchAction::Replace;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
actionType = SearchAction::FindFiles;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
actionType = SearchAction::ReplaceFiles;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSearchOptions&=0;
|
mSearchOptions&=0;
|
||||||
|
|
||||||
// Apply options
|
// Apply options
|
||||||
|
if (backward) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoBackwards);
|
||||||
|
}
|
||||||
|
|
||||||
if (ui->chkRegExp->isChecked()) {
|
if (ui->chkRegExp->isChecked()) {
|
||||||
mSearchOptions.setFlag(QSynedit::ssoRegExp);
|
mSearchOptions.setFlag(QSynedit::ssoRegExp);
|
||||||
}
|
}
|
||||||
|
@ -234,13 +77,6 @@ void SearchDialog::on_btnExecute_clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply direction, when enabled
|
|
||||||
if (ui->grpDirection->isEnabled()) {
|
|
||||||
if (ui->rbBackward->isChecked()) {
|
|
||||||
mSearchOptions.setFlag(QSynedit::ssoBackwards);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply origin, when enabled
|
// Apply origin, when enabled
|
||||||
if (ui->grpOrigin->isEnabled()) {
|
if (ui->grpOrigin->isEnabled()) {
|
||||||
if (ui->rbEntireScope->isChecked()) {
|
if (ui->rbEntireScope->isChecked()) {
|
||||||
|
@ -248,259 +84,69 @@ void SearchDialog::on_btnExecute_clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use entire scope for file finding/replacing
|
Editor *editor = pMainWindow->editorList()->getEditor();
|
||||||
if (actionType == SearchAction::FindFiles || actionType == SearchAction::ReplaceFiles) {
|
if (editor) {
|
||||||
mSearchOptions.setFlag(QSynedit::ssoEntireScope);
|
// Modify the caret when using 'from cursor' and when the selection is ignored
|
||||||
}
|
if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
||||||
|
&& editor->selAvail()) {
|
||||||
this->close();
|
// start at end of selection
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
||||||
// Find the first one, then quit
|
editor->setCaretXY(editor->blockBegin());
|
||||||
if (actionType == SearchAction::Find) {
|
} else {
|
||||||
Editor *e = pMainWindow->editorList()->getEditor();
|
editor->setCaretXY(editor->blockEnd());
|
||||||
if (e!=nullptr) {
|
|
||||||
findCount+=execute(e,ui->cbFind->currentText(),"",nullptr,
|
|
||||||
[](){
|
|
||||||
return QMessageBox::question(pMainWindow,
|
|
||||||
tr("Continue Search"),
|
|
||||||
tr("End of file has been reached. ")
|
|
||||||
+tr("Do you want to continue from file's beginning?"),
|
|
||||||
QMessageBox::Yes|QMessageBox::No,
|
|
||||||
QMessageBox::Yes) == QMessageBox::Yes;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (actionType == SearchAction::Replace) {
|
|
||||||
Editor *e = pMainWindow->editorList()->getEditor();
|
|
||||||
if (e!=nullptr) {
|
|
||||||
bool doPrompt = ui->chkPrompt->isChecked();
|
|
||||||
findCount+=execute(e,ui->cbFind->currentText(),ui->cbReplace->currentText(),
|
|
||||||
[&doPrompt](const QString& sSearch,
|
|
||||||
const QString& /*sReplace*/, int /*Line*/, int /*ch*/, int /*wordLen*/){
|
|
||||||
if (doPrompt) {
|
|
||||||
switch(QMessageBox::question(pMainWindow,
|
|
||||||
tr("Replace"),
|
|
||||||
tr("Replace this occurrence of ''%1''?").arg(sSearch),
|
|
||||||
QMessageBox::Yes|QMessageBox::YesAll|QMessageBox::No|QMessageBox::Cancel,
|
|
||||||
QMessageBox::Yes)) {
|
|
||||||
case QMessageBox::Yes:
|
|
||||||
return QSynedit::SearchAction::Replace;
|
|
||||||
case QMessageBox::YesAll:
|
|
||||||
return QSynedit::SearchAction::ReplaceAll;
|
|
||||||
case QMessageBox::No:
|
|
||||||
return QSynedit::SearchAction::Skip;
|
|
||||||
case QMessageBox::Cancel:
|
|
||||||
return QSynedit::SearchAction::Exit;
|
|
||||||
default:
|
|
||||||
return QSynedit::SearchAction::Exit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return QSynedit::SearchAction::ReplaceAll;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[](){
|
|
||||||
return QMessageBox::question(pMainWindow,
|
|
||||||
tr("Continue Replace"),
|
|
||||||
tr("End of file has been reached. ")
|
|
||||||
+tr("Do you want to continue from file's beginning?"),
|
|
||||||
QMessageBox::Yes|QMessageBox::No,
|
|
||||||
QMessageBox::Yes) == QMessageBox::Yes;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (actionType == SearchAction::FindFiles || actionType == SearchAction::ReplaceFiles) {
|
|
||||||
int fileSearched = 0;
|
|
||||||
int fileHitted = 0;
|
|
||||||
QString keyword = ui->cbFind->currentText();
|
|
||||||
if (ui->rbOpenFiles->isChecked()) {
|
|
||||||
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
|
||||||
keyword,
|
|
||||||
mSearchOptions,
|
|
||||||
SearchFileScope::openedFiles
|
|
||||||
);
|
|
||||||
// loop through editors, add results to message control
|
|
||||||
for (int i=0;i<pMainWindow->editorList()->pageCount();i++) {
|
|
||||||
Editor * e=pMainWindow->editorList()->operator[](i);
|
|
||||||
if (e!=nullptr) {
|
|
||||||
fileSearched++;
|
|
||||||
PSearchResultTreeItem parentItem = batchFindInEditor(
|
|
||||||
e,
|
|
||||||
e->filename(),
|
|
||||||
keyword);
|
|
||||||
int t = parentItem->results.size();
|
|
||||||
findCount+=t;
|
|
||||||
if (t>0) {
|
|
||||||
fileHitted++;
|
|
||||||
results->results.append(parentItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
|
||||||
} else if (ui->rbCurrentFile->isChecked()) {
|
|
||||||
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
|
||||||
keyword,
|
|
||||||
mSearchOptions,
|
|
||||||
SearchFileScope::currentFile
|
|
||||||
);
|
|
||||||
Editor * e= pMainWindow->editorList()->getEditor();
|
|
||||||
if (e!=nullptr) {
|
|
||||||
fileSearched++;
|
|
||||||
PSearchResultTreeItem parentItem = batchFindInEditor(
|
|
||||||
e,
|
|
||||||
e->filename(),
|
|
||||||
keyword);
|
|
||||||
int t = parentItem->results.size();
|
|
||||||
findCount+=t;
|
|
||||||
if (t>0) {
|
|
||||||
fileHitted++;
|
|
||||||
results->results.append(parentItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
|
||||||
} else if (ui->rbProject->isChecked()) {
|
|
||||||
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
|
||||||
keyword,
|
|
||||||
mSearchOptions,
|
|
||||||
SearchFileScope::wholeProject
|
|
||||||
);
|
|
||||||
foreach (PProjectUnit unit, pMainWindow->project()->unitList()) {
|
|
||||||
Editor * e = pMainWindow->project()->unitEditor(unit);
|
|
||||||
QString curFilename = unit->fileName();
|
|
||||||
if (e) {
|
|
||||||
fileSearched++;
|
|
||||||
PSearchResultTreeItem parentItem = batchFindInEditor(
|
|
||||||
e,
|
|
||||||
e->filename(),
|
|
||||||
keyword);
|
|
||||||
int t = parentItem->results.size();
|
|
||||||
findCount+=t;
|
|
||||||
if (t>0) {
|
|
||||||
fileHitted++;
|
|
||||||
results->results.append(parentItem);
|
|
||||||
}
|
|
||||||
} else if (fileExists(curFilename)) {
|
|
||||||
QSynedit::SynEdit editor;
|
|
||||||
QByteArray realEncoding;
|
|
||||||
editor.document()->loadFromFile(curFilename,ENCODING_AUTO_DETECT, realEncoding);
|
|
||||||
fileSearched++;
|
|
||||||
PSearchResultTreeItem parentItem = batchFindInEditor(
|
|
||||||
&editor,
|
|
||||||
curFilename,
|
|
||||||
keyword);
|
|
||||||
int t = parentItem->results.size();
|
|
||||||
findCount+=t;
|
|
||||||
if (t>0) {
|
|
||||||
fileHitted++;
|
|
||||||
results->results.append(parentItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
|
||||||
}
|
}
|
||||||
pMainWindow->showSearchPanel(actionType == SearchAction::ReplaceFiles);
|
QSynedit::PSynSearchBase searchEngine;
|
||||||
}
|
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
||||||
}
|
searchEngine = mRegexSearchEngine;
|
||||||
|
|
||||||
int SearchDialog::execute(QSynedit::SynEdit *editor, const QString &sSearch, const QString &sReplace,
|
|
||||||
QSynedit::SearchMathedProc matchCallback,
|
|
||||||
QSynedit::SearchConfirmAroundProc confirmAroundCallback)
|
|
||||||
{
|
|
||||||
if (editor==nullptr)
|
|
||||||
return 0;
|
|
||||||
// Modify the caret when using 'from cursor' and when the selection is ignored
|
|
||||||
if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
|
||||||
&& editor->selAvail()) {
|
|
||||||
// start at end of selection
|
|
||||||
if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
|
||||||
editor->setCaretXY(editor->blockBegin());
|
|
||||||
} else {
|
} else {
|
||||||
editor->setCaretXY(editor->blockEnd());
|
searchEngine = mBasicSearchEngine;
|
||||||
}
|
}
|
||||||
}
|
editor->searchReplace(
|
||||||
|
ui->cbFind->currentText(),
|
||||||
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
"",
|
||||||
mSearchEngine = mRegexSearchEngine;
|
mSearchOptions,
|
||||||
} else {
|
searchEngine, nullptr, [this,backward](){
|
||||||
mSearchEngine = mBasicSearchEngine;
|
QString msg;
|
||||||
}
|
if (backward) {
|
||||||
|
msg = tr("Beginning of file has been reached. ")
|
||||||
return editor->searchReplace(sSearch, sReplace, mSearchOptions,
|
+tr("Do you want to continue from file's end?");
|
||||||
mSearchEngine, matchCallback, confirmAroundCallback);
|
} else {
|
||||||
}
|
msg = tr("End of file has been reached. ")
|
||||||
|
+tr("Do you want to continue from file's beginning?");
|
||||||
std::shared_ptr<SearchResultTreeItem> SearchDialog::batchFindInEditor(QSynedit::SynEdit *e, const QString& filename,const QString &keyword)
|
}
|
||||||
{
|
QWidget *p;
|
||||||
//backup
|
if (isVisible()) {
|
||||||
QSynedit::BufferCoord caretBackup = e->caretXY();
|
p=this;
|
||||||
QSynedit::BufferCoord blockBeginBackup = e->blockBegin();
|
} else {
|
||||||
QSynedit::BufferCoord blockEndBackup = e->blockEnd();
|
p=pMainWindow;
|
||||||
int toplineBackup = e->topLine();
|
}
|
||||||
int leftCharBackup = e->leftChar();
|
return QMessageBox::question(p,
|
||||||
|
tr("Continue Search"),
|
||||||
PSearchResultTreeItem parentItem = std::make_shared<SearchResultTreeItem>();
|
msg,
|
||||||
parentItem->filename = filename;
|
QMessageBox::Yes|QMessageBox::No,
|
||||||
parentItem->parent = nullptr;
|
QMessageBox::Yes) == QMessageBox::Yes;
|
||||||
execute(e,keyword,"",
|
});
|
||||||
[e,&parentItem, filename](const QString&,
|
|
||||||
const QString&, int Line, int ch, int wordLen){
|
|
||||||
PSearchResultTreeItem item = std::make_shared<SearchResultTreeItem>();
|
|
||||||
item->filename = filename;
|
|
||||||
item->line = Line;
|
|
||||||
item->start = ch;
|
|
||||||
item->len = wordLen;
|
|
||||||
item->parent = parentItem.get();
|
|
||||||
item->text = e->document()->getString(Line-1);
|
|
||||||
item->text.replace('\t',' ');
|
|
||||||
parentItem->results.append(item);
|
|
||||||
return QSynedit::SearchAction::Skip;
|
|
||||||
});
|
|
||||||
|
|
||||||
// restore
|
|
||||||
e->setCaretXY(caretBackup);
|
|
||||||
e->setTopLine(toplineBackup);
|
|
||||||
e->setLeftChar(leftCharBackup);
|
|
||||||
e->setCaretAndSelection(
|
|
||||||
caretBackup,
|
|
||||||
blockBeginBackup,
|
|
||||||
blockEndBackup
|
|
||||||
);
|
|
||||||
return parentItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchDialog::showEvent(QShowEvent *event)
|
|
||||||
{
|
|
||||||
QDialog::showEvent(event);
|
|
||||||
if (pSettings->environment().language()=="zh_CN") {
|
|
||||||
ui->txtRegExpHelp->setText(
|
|
||||||
QString("<html><head/><body><p><a href=\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">(?)</span></a></p></body></html>")
|
|
||||||
.arg("https://www.runoob.com/regexp/regexp-tutorial.html"));
|
|
||||||
} else {
|
|
||||||
ui->txtRegExpHelp->setText(
|
|
||||||
QString("<html><head/><body><p><a href=\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">(?)</span></a></p></body></html>")
|
|
||||||
.arg("https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTabBar *SearchDialog::tabBar() const
|
void SearchDialog::on_cbFind_currentTextChanged(const QString &value)
|
||||||
{
|
{
|
||||||
return mTabBar;
|
ui->btnNext->setEnabled(!value.isEmpty());
|
||||||
|
ui->btnPrevious->setEnabled(!value.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
QSynedit::PSynSearchBase SearchDialog::searchEngine() const
|
void SearchDialog::on_btnClose_clicked()
|
||||||
{
|
{
|
||||||
return mSearchEngine;
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchDialog::findPrevious()
|
void SearchDialog::on_btnNext_clicked()
|
||||||
{
|
{
|
||||||
if (mTabBar->currentIndex()==0) { // it's a find action
|
doSearch(false);
|
||||||
|
}
|
||||||
// Disable entire scope searching
|
|
||||||
ui->rbEntireScope->setChecked(false);
|
void SearchDialog::on_btnPrevious_clicked()
|
||||||
|
{
|
||||||
// Always search backward
|
doSearch(true);
|
||||||
ui->rbBackward->setChecked(true);
|
|
||||||
|
|
||||||
ui->btnExecute->click();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,81 +1,40 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef SEARCHDIALOG_H
|
#ifndef SEARCHDIALOG_H
|
||||||
#define SEARCHDIALOG_H
|
#define SEARCHDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <qsynedit/SynEdit.h>
|
#include <qsynedit/SearchBase.h>
|
||||||
#include "../utils.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SearchDialog;
|
class SearchDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SearchResultTreeItem;
|
|
||||||
class QTabBar;
|
|
||||||
class Editor;
|
|
||||||
class SearchDialog : public QDialog
|
class SearchDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
enum class SearchAction {
|
|
||||||
Find,
|
|
||||||
FindFiles,
|
|
||||||
Replace,
|
|
||||||
ReplaceFiles
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SearchDialog(QWidget *parent = nullptr);
|
explicit SearchDialog(QWidget *parent = nullptr);
|
||||||
~SearchDialog();
|
~SearchDialog();
|
||||||
void find(const QString& text);
|
void find(const QString& text);
|
||||||
void findNext();
|
void findNext();
|
||||||
void findPrevious();
|
void findPrevious();
|
||||||
void findInFiles(const QString& text);
|
|
||||||
void findInFiles(const QString& keyword, SearchFileScope scope, QSynedit::SearchOptions options);
|
|
||||||
void replace(const QString& sFind, const QString& sReplace);
|
|
||||||
QSynedit::PSynSearchBase searchEngine() const;
|
|
||||||
|
|
||||||
QTabBar *tabBar() const;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTabChanged();
|
|
||||||
void on_cbFind_currentTextChanged(const QString &arg1);
|
|
||||||
|
|
||||||
void on_btnCancel_clicked();
|
|
||||||
|
|
||||||
void on_btnExecute_clicked();
|
|
||||||
private:
|
private:
|
||||||
int execute(QSynedit::SynEdit* editor, const QString& sSearch,
|
void doSearch(bool backward);
|
||||||
const QString& sReplace,
|
private slots:
|
||||||
QSynedit::SearchMathedProc matchCallback = nullptr,
|
void on_cbFind_currentTextChanged(const QString &arg1);
|
||||||
QSynedit::SearchConfirmAroundProc confirmAroundCallback = nullptr);
|
|
||||||
std::shared_ptr<SearchResultTreeItem> batchFindInEditor(QSynedit::SynEdit * editor,const QString& filename, const QString& keyword);
|
void on_btnClose_clicked();
|
||||||
|
|
||||||
|
void on_btnNext_clicked();
|
||||||
|
|
||||||
|
|
||||||
|
void on_btnPrevious_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::SearchDialog *ui;
|
Ui::SearchDialog *ui;
|
||||||
QTabBar *mTabBar;
|
|
||||||
QSynedit::SearchOptions mSearchOptions;
|
QSynedit::SearchOptions mSearchOptions;
|
||||||
QSynedit::PSynSearchBase mSearchEngine;
|
|
||||||
QSynedit::PSynSearchBase mBasicSearchEngine;
|
QSynedit::PSynSearchBase mBasicSearchEngine;
|
||||||
QSynedit::PSynSearchBase mRegexSearchEngine;
|
QSynedit::PSynSearchBase mRegexSearchEngine;
|
||||||
|
|
||||||
// QWidget interface
|
|
||||||
protected:
|
|
||||||
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SEARCHDIALOG_H
|
#endif // SEARCHDIALOG_H
|
||||||
|
|
|
@ -6,41 +6,35 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>684</width>
|
<width>609</width>
|
||||||
<height>548</height>
|
<height>242</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>Find</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="dialogLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame">
|
<widget class="QWidget" name="widget_4" native="true">
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget_2" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -53,14 +47,14 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item>
|
||||||
<widget class="QLabel" name="lblFind">
|
<widget class="QLabel" name="lblFind">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Text to Find:</string>
|
<string>Text to Find:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="QComboBox" name="cbFind">
|
<widget class="QComboBox" name="cbFind">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -76,131 +70,42 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="cbReplace">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="editable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="insertPolicy">
|
|
||||||
<enum>QComboBox::InsertAtTop</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="lblReplace">
|
|
||||||
<property name="text">
|
|
||||||
<string>Replace with:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget_3" native="true">
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<property name="leftMargin">
|
||||||
<widget class="QGroupBox" name="grpOptions">
|
<number>0</number>
|
||||||
<property name="title">
|
</property>
|
||||||
<string>Options:</string>
|
<property name="topMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
</property>
|
||||||
<item>
|
<property name="rightMargin">
|
||||||
<widget class="QCheckBox" name="chkCaseSensetive">
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Case Sensitive</string>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<item row="1" column="1">
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="chkWholeWord">
|
|
||||||
<property name="text">
|
|
||||||
<string>Whole words only</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="widget_31" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="chkRegExp">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Regular Expression</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="txtRegExpHelp">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string notr="true"><html><head/><body><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"><span style=" text-decoration: underline; color:#0000ff;">(?)</span></a></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="openExternalLinks">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="chkWrapAround">
|
|
||||||
<property name="text">
|
|
||||||
<string>Wrap Around</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="chkPrompt">
|
|
||||||
<property name="text">
|
|
||||||
<string>Prompt on replace</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QGroupBox" name="grpScope">
|
<widget class="QGroupBox" name="grpScope">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Scope:</string>
|
<string>Scope:</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="rbGlobal">
|
<widget class="QRadioButton" name="rbGlobal">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -218,12 +123,24 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QGroupBox" name="grpOrigin">
|
<widget class="QGroupBox" name="grpOrigin">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Origin:</string>
|
<string>Origin:</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="rbFromCursor">
|
<widget class="QRadioButton" name="rbFromCursor">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -244,107 +161,92 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="0" rowspan="2">
|
||||||
<widget class="QWidget" name="widget_4" native="true">
|
<widget class="QGroupBox" name="grpOptions">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<property name="title">
|
||||||
<property name="spacing">
|
<string>Options:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
<number>7</number>
|
<number>7</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>0</number>
|
<number>7</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>0</number>
|
<number>7</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>7</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item row="0" column="0">
|
||||||
<widget class="QGroupBox" name="grpDirection">
|
<widget class="QCheckBox" name="chkCaseSensetive">
|
||||||
<property name="title">
|
<property name="text">
|
||||||
<string>Direction:</string>
|
<string>Case Sensitive</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbForward">
|
|
||||||
<property name="text">
|
|
||||||
<string>Forward</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbBackward">
|
|
||||||
<property name="text">
|
|
||||||
<string>Backward</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="3" column="0">
|
||||||
<widget class="QGroupBox" name="grpWhere">
|
<widget class="QCheckBox" name="chkWrapAround">
|
||||||
<property name="title">
|
<property name="text">
|
||||||
<string>Where:</string>
|
<string>Wrap Around</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkPrompt">
|
||||||
|
<property name="text">
|
||||||
|
<string>Prompt on replace</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkRegExp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Regular Expression</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkWholeWord">
|
||||||
|
<property name="text">
|
||||||
|
<string>Whole words only</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="txtRegExpHelp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><html><head/><body><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"><span style=" text-decoration: underline; color:#0000ff;">(?)</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkCloseAfterSearch">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close after search</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbCurrentFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>Current File</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbProject">
|
|
||||||
<property name="text">
|
|
||||||
<string>Files In Project</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbOpenFiles">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open Files</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -353,6 +255,77 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_3" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPrevious">
|
||||||
|
<property name="text">
|
||||||
|
<string>Find Previous</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNext">
|
||||||
|
<property name="text">
|
||||||
|
<string>Find Next</string>
|
||||||
|
</property>
|
||||||
|
<property name="default">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>15</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClose">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -361,7 +334,7 @@
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>20</width>
|
||||||
<height>134</height>
|
<height>40</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
|
@ -369,45 +342,6 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>455</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnExecute">
|
|
||||||
<property name="text">
|
|
||||||
<string>Find</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnCancel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cancel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "searchinfiledialog.h"
|
||||||
|
#include "ui_searchinfiledialog.h"
|
||||||
|
#include <QTabBar>
|
||||||
|
#include "../editor.h"
|
||||||
|
#include "../mainwindow.h"
|
||||||
|
#include "../editorlist.h"
|
||||||
|
#include <qsynedit/Search.h>
|
||||||
|
#include <qsynedit/SearchRegex.h>
|
||||||
|
#include "../project.h"
|
||||||
|
#include "../settings.h"
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
SearchInFileDialog::SearchInFileDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::SearchInFileDialog)
|
||||||
|
{
|
||||||
|
setWindowFlag(Qt::WindowContextHelpButtonHint,false);
|
||||||
|
ui->setupUi(this);
|
||||||
|
mSearchOptions&=0;
|
||||||
|
mBasicSearchEngine= QSynedit::PSynSearchBase(new QSynedit::BasicSearcher());
|
||||||
|
mRegexSearchEngine= QSynedit::PSynSearchBase(new QSynedit::RegexSearcher());
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchInFileDialog::~SearchInFileDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SearchInFileDialog::findInFiles(const QString &text)
|
||||||
|
{
|
||||||
|
ui->cbFind->setCurrentText(text);
|
||||||
|
ui->cbFind->setFocus();
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::findInFiles(const QString &keyword, SearchFileScope scope, QSynedit::SearchOptions options)
|
||||||
|
{
|
||||||
|
ui->cbFind->setCurrentText(keyword);
|
||||||
|
ui->cbFind->setFocus();
|
||||||
|
|
||||||
|
switch(scope) {
|
||||||
|
case SearchFileScope::currentFile:
|
||||||
|
ui->rbCurrentFile->setChecked(true);
|
||||||
|
break;
|
||||||
|
case SearchFileScope::openedFiles:
|
||||||
|
ui->rbOpenFiles->setChecked(true);
|
||||||
|
break;
|
||||||
|
case SearchFileScope::wholeProject:
|
||||||
|
ui->rbProject->setChecked(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Apply options
|
||||||
|
ui->chkRegExp->setChecked(options.testFlag(QSynedit::ssoRegExp));
|
||||||
|
ui->chkCaseSensetive->setChecked(options.testFlag(QSynedit::ssoMatchCase));
|
||||||
|
ui->chkWholeWord->setChecked(options.testFlag(QSynedit::ssoWholeWord));
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::on_cbFind_currentTextChanged(const QString &value)
|
||||||
|
{
|
||||||
|
ui->btnExecute->setEnabled(!value.isEmpty());
|
||||||
|
ui->btnReplace->setEnabled(!value.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::on_btnCancel_clicked()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::on_btnExecute_clicked()
|
||||||
|
{
|
||||||
|
doSearch(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::doSearch(bool replace)
|
||||||
|
{
|
||||||
|
int findCount = 0;
|
||||||
|
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
||||||
|
|
||||||
|
mSearchOptions&=0;
|
||||||
|
|
||||||
|
// Apply options
|
||||||
|
if (ui->chkRegExp->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoRegExp);
|
||||||
|
}
|
||||||
|
if (ui->chkCaseSensetive->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoMatchCase);
|
||||||
|
}
|
||||||
|
if (ui->chkWholeWord->isChecked()) {
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoWholeWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSearchOptions.setFlag(QSynedit::ssoEntireScope);
|
||||||
|
|
||||||
|
close();
|
||||||
|
|
||||||
|
// Find the first one, then quit
|
||||||
|
int fileSearched = 0;
|
||||||
|
int fileHitted = 0;
|
||||||
|
QString keyword = ui->cbFind->currentText();
|
||||||
|
if (ui->rbOpenFiles->isChecked()) {
|
||||||
|
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
||||||
|
keyword,
|
||||||
|
mSearchOptions,
|
||||||
|
SearchFileScope::openedFiles
|
||||||
|
);
|
||||||
|
// loop through editors, add results to message control
|
||||||
|
for (int i=0;i<pMainWindow->editorList()->pageCount();i++) {
|
||||||
|
Editor * e=pMainWindow->editorList()->operator[](i);
|
||||||
|
if (e!=nullptr) {
|
||||||
|
fileSearched++;
|
||||||
|
PSearchResultTreeItem parentItem = batchFindInEditor(
|
||||||
|
e,
|
||||||
|
e->filename(),
|
||||||
|
keyword);
|
||||||
|
int t = parentItem->results.size();
|
||||||
|
findCount+=t;
|
||||||
|
if (t>0) {
|
||||||
|
fileHitted++;
|
||||||
|
results->results.append(parentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
||||||
|
} else if (ui->rbCurrentFile->isChecked()) {
|
||||||
|
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
||||||
|
keyword,
|
||||||
|
mSearchOptions,
|
||||||
|
SearchFileScope::currentFile
|
||||||
|
);
|
||||||
|
Editor * e= pMainWindow->editorList()->getEditor();
|
||||||
|
if (e!=nullptr) {
|
||||||
|
fileSearched++;
|
||||||
|
PSearchResultTreeItem parentItem = batchFindInEditor(
|
||||||
|
e,
|
||||||
|
e->filename(),
|
||||||
|
keyword);
|
||||||
|
int t = parentItem->results.size();
|
||||||
|
findCount+=t;
|
||||||
|
if (t>0) {
|
||||||
|
fileHitted++;
|
||||||
|
results->results.append(parentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
||||||
|
} else if (ui->rbProject->isChecked()) {
|
||||||
|
PSearchResults results = pMainWindow->searchResultModel()->addSearchResults(
|
||||||
|
keyword,
|
||||||
|
mSearchOptions,
|
||||||
|
SearchFileScope::wholeProject
|
||||||
|
);
|
||||||
|
foreach (PProjectUnit unit, pMainWindow->project()->unitList()) {
|
||||||
|
Editor * e = pMainWindow->project()->unitEditor(unit);
|
||||||
|
QString curFilename = unit->fileName();
|
||||||
|
if (e) {
|
||||||
|
fileSearched++;
|
||||||
|
PSearchResultTreeItem parentItem = batchFindInEditor(
|
||||||
|
e,
|
||||||
|
e->filename(),
|
||||||
|
keyword);
|
||||||
|
int t = parentItem->results.size();
|
||||||
|
findCount+=t;
|
||||||
|
if (t>0) {
|
||||||
|
fileHitted++;
|
||||||
|
results->results.append(parentItem);
|
||||||
|
}
|
||||||
|
} else if (fileExists(curFilename)) {
|
||||||
|
QSynedit::SynEdit editor;
|
||||||
|
QByteArray realEncoding;
|
||||||
|
editor.document()->loadFromFile(curFilename,ENCODING_AUTO_DETECT, realEncoding);
|
||||||
|
fileSearched++;
|
||||||
|
PSearchResultTreeItem parentItem = batchFindInEditor(
|
||||||
|
&editor,
|
||||||
|
curFilename,
|
||||||
|
keyword);
|
||||||
|
int t = parentItem->results.size();
|
||||||
|
findCount+=t;
|
||||||
|
if (t>0) {
|
||||||
|
fileHitted++;
|
||||||
|
results->results.append(parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMainWindow->searchResultModel()->notifySearchResultsUpdated();
|
||||||
|
}
|
||||||
|
pMainWindow->showSearchPanel(replace);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SearchInFileDialog::execute(QSynedit::SynEdit *editor, const QString &sSearch, const QString &sReplace,
|
||||||
|
QSynedit::SearchMathedProc matchCallback,
|
||||||
|
QSynedit::SearchConfirmAroundProc confirmAroundCallback)
|
||||||
|
{
|
||||||
|
if (editor==nullptr)
|
||||||
|
return 0;
|
||||||
|
// Modify the caret when using 'from cursor' and when the selection is ignored
|
||||||
|
if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
||||||
|
&& editor->selAvail()) {
|
||||||
|
// start at end of selection
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
||||||
|
editor->setCaretXY(editor->blockBegin());
|
||||||
|
} else {
|
||||||
|
editor->setCaretXY(editor->blockEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSynedit::PSynSearchBase searchEngine;
|
||||||
|
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
||||||
|
searchEngine = mRegexSearchEngine;
|
||||||
|
} else {
|
||||||
|
searchEngine = mBasicSearchEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return editor->searchReplace(sSearch, sReplace, mSearchOptions,
|
||||||
|
searchEngine, matchCallback, confirmAroundCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SearchResultTreeItem> SearchInFileDialog::batchFindInEditor(QSynedit::SynEdit *e, const QString& filename,const QString &keyword)
|
||||||
|
{
|
||||||
|
//backup
|
||||||
|
QSynedit::BufferCoord caretBackup = e->caretXY();
|
||||||
|
QSynedit::BufferCoord blockBeginBackup = e->blockBegin();
|
||||||
|
QSynedit::BufferCoord blockEndBackup = e->blockEnd();
|
||||||
|
int toplineBackup = e->topLine();
|
||||||
|
int leftCharBackup = e->leftChar();
|
||||||
|
|
||||||
|
PSearchResultTreeItem parentItem = std::make_shared<SearchResultTreeItem>();
|
||||||
|
parentItem->filename = filename;
|
||||||
|
parentItem->parent = nullptr;
|
||||||
|
execute(e,keyword,"",
|
||||||
|
[e,&parentItem, filename](const QString&,
|
||||||
|
const QString&, int Line, int ch, int wordLen){
|
||||||
|
PSearchResultTreeItem item = std::make_shared<SearchResultTreeItem>();
|
||||||
|
item->filename = filename;
|
||||||
|
item->line = Line;
|
||||||
|
item->start = ch;
|
||||||
|
item->len = wordLen;
|
||||||
|
item->parent = parentItem.get();
|
||||||
|
item->text = e->document()->getString(Line-1);
|
||||||
|
item->text.replace('\t',' ');
|
||||||
|
parentItem->results.append(item);
|
||||||
|
return QSynedit::SearchAction::Skip;
|
||||||
|
});
|
||||||
|
|
||||||
|
// restore
|
||||||
|
e->setCaretXY(caretBackup);
|
||||||
|
e->setTopLine(toplineBackup);
|
||||||
|
e->setLeftChar(leftCharBackup);
|
||||||
|
e->setCaretAndSelection(
|
||||||
|
caretBackup,
|
||||||
|
blockBeginBackup,
|
||||||
|
blockEndBackup
|
||||||
|
);
|
||||||
|
return parentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QDialog::showEvent(event);
|
||||||
|
if (pSettings->environment().language()=="zh_CN") {
|
||||||
|
ui->txtRegExpHelp->setText(
|
||||||
|
QString("<html><head/><body><p><a href=\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">(?)</span></a></p></body></html>")
|
||||||
|
.arg("https://www.runoob.com/regexp/regexp-tutorial.html"));
|
||||||
|
} else {
|
||||||
|
ui->txtRegExpHelp->setText(
|
||||||
|
QString("<html><head/><body><p><a href=\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">(?)</span></a></p></body></html>")
|
||||||
|
.arg("https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchInFileDialog::on_btnReplace_clicked()
|
||||||
|
{
|
||||||
|
doSearch(true);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SEARCHINFILEDIALOG_H
|
||||||
|
#define SEARCHINFILEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <qsynedit/SynEdit.h>
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class SearchInFileDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SearchResultTreeItem;
|
||||||
|
class QTabBar;
|
||||||
|
class Editor;
|
||||||
|
class SearchInFileDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SearchInFileDialog(QWidget *parent = nullptr);
|
||||||
|
~SearchInFileDialog();
|
||||||
|
void findInFiles(const QString& text);
|
||||||
|
void findInFiles(const QString& keyword, SearchFileScope scope, QSynedit::SearchOptions options);
|
||||||
|
QSynedit::PSynSearchBase searchEngine() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_cbFind_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
|
void on_btnCancel_clicked();
|
||||||
|
|
||||||
|
void on_btnExecute_clicked();
|
||||||
|
void on_btnReplace_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void doSearch(bool replace);
|
||||||
|
int execute(QSynedit::SynEdit* editor, const QString& sSearch,
|
||||||
|
const QString& sReplace,
|
||||||
|
QSynedit::SearchMathedProc matchCallback = nullptr,
|
||||||
|
QSynedit::SearchConfirmAroundProc confirmAroundCallback = nullptr);
|
||||||
|
std::shared_ptr<SearchResultTreeItem> batchFindInEditor(QSynedit::SynEdit * editor,const QString& filename, const QString& keyword);
|
||||||
|
private:
|
||||||
|
Ui::SearchInFileDialog *ui;
|
||||||
|
QSynedit::SearchOptions mSearchOptions;
|
||||||
|
QSynedit::PSynSearchBase mBasicSearchEngine;
|
||||||
|
QSynedit::PSynSearchBase mRegexSearchEngine;
|
||||||
|
|
||||||
|
// QWidget interface
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEARCHINFILEDIALOG_H
|
|
@ -0,0 +1,278 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SearchInFileDialog</class>
|
||||||
|
<widget class="QDialog" name="SearchInFileDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>684</width>
|
||||||
|
<height>548</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="dialogLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="lblFind">
|
||||||
|
<property name="text">
|
||||||
|
<string>Text to Find:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="cbFind">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="insertPolicy">
|
||||||
|
<enum>QComboBox::InsertAtTop</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_3" native="true">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QWidget" name="widget_4" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="grpWhere">
|
||||||
|
<property name="title">
|
||||||
|
<string>Where:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbCurrentFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>Current File</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbProject">
|
||||||
|
<property name="text">
|
||||||
|
<string>Files In Project</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbOpenFiles">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open Files</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="grpOptions">
|
||||||
|
<property name="title">
|
||||||
|
<string>Options:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkWholeWord">
|
||||||
|
<property name="text">
|
||||||
|
<string>Whole words only</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkCaseSensetive">
|
||||||
|
<property name="text">
|
||||||
|
<string>Case Sensitive</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QWidget" name="widget_31" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="chkRegExp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Regular Expression</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="txtRegExpHelp">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><html><head/><body><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference"><span style=" text-decoration: underline; color:#0000ff;">(?)</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>134</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>455</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnExecute">
|
||||||
|
<property name="text">
|
||||||
|
<string>Find</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnReplace">
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -5241,6 +5241,7 @@ int SynEdit::searchReplace(const QString &sSearch, const QString &sReplace, Sear
|
||||||
else
|
else
|
||||||
i = 0;
|
i = 0;
|
||||||
// Operate on all results in this line.
|
// Operate on all results in this line.
|
||||||
|
bool needRefresh = (nInLine>0);
|
||||||
while (nInLine > 0) {
|
while (nInLine > 0) {
|
||||||
// An occurrence may have been replaced with a text of different length
|
// An occurrence may have been replaced with a text of different length
|
||||||
int nFound = searchEngine->result(i) + 1 + iResultOffset;
|
int nFound = searchEngine->result(i) + 1 + iResultOffset;
|
||||||
|
@ -5274,26 +5275,25 @@ int SynEdit::searchReplace(const QString &sSearch, const QString &sReplace, Sear
|
||||||
setBlockBegin(ptCurrent);
|
setBlockBegin(ptCurrent);
|
||||||
|
|
||||||
//Be sure to use the Ex version of CursorPos so that it appears in the middle if necessary
|
//Be sure to use the Ex version of CursorPos so that it appears in the middle if necessary
|
||||||
setCaretXYEx(false, BufferCoord{1, ptCurrent.line});
|
setCaretXYEx(false, BufferCoord{ptCurrent.ch, ptCurrent.line});
|
||||||
ensureCursorPosVisibleEx(true);
|
ensureCursorPosVisibleEx(true);
|
||||||
ptCurrent.ch += nSearchLen;
|
ptCurrent.ch += nSearchLen;
|
||||||
setBlockEnd(ptCurrent);
|
setBlockEnd(ptCurrent);
|
||||||
//internalSetCaretXY(ptCurrent);
|
|
||||||
if (bBackward)
|
|
||||||
internalSetCaretXY(blockBegin());
|
|
||||||
else
|
|
||||||
internalSetCaretXY(ptCurrent);
|
|
||||||
|
|
||||||
QString replaceText = searchEngine->replace(selText(), sReplace);
|
QString replaceText = searchEngine->replace(selText(), sReplace);
|
||||||
if (matchedCallback && !dobatchReplace) {
|
if (searchAction==SearchAction::ReplaceAndExit) {
|
||||||
|
searchAction=SearchAction::Exit;
|
||||||
|
} else if (matchedCallback && !dobatchReplace) {
|
||||||
searchAction = matchedCallback(sSearch,replaceText,ptCurrent.line,
|
searchAction = matchedCallback(sSearch,replaceText,ptCurrent.line,
|
||||||
nFound,nSearchLen);
|
nFound,nSearchLen);
|
||||||
}
|
}
|
||||||
if (searchAction==SearchAction::Exit) {
|
if (searchAction==SearchAction::Exit) {
|
||||||
|
invalidateLine(ptCurrent.line);
|
||||||
return result;
|
return result;
|
||||||
} else if (searchAction == SearchAction::Skip) {
|
} else if (searchAction == SearchAction::Skip) {
|
||||||
continue;
|
continue;
|
||||||
} else if (searchAction == SearchAction::Replace
|
} else if (searchAction == SearchAction::Replace
|
||||||
|
|| searchAction == SearchAction::ReplaceAndExit
|
||||||
|| searchAction == SearchAction::ReplaceAll) {
|
|| searchAction == SearchAction::ReplaceAll) {
|
||||||
if (!dobatchReplace &&
|
if (!dobatchReplace &&
|
||||||
(searchAction == SearchAction::ReplaceAll) ){
|
(searchAction == SearchAction::ReplaceAll) ){
|
||||||
|
@ -5319,14 +5319,17 @@ int SynEdit::searchReplace(const QString &sSearch, const QString &sReplace, Sear
|
||||||
mOptions.setFlag(EditorOption::eoAutoIndent,oldAutoIndent);
|
mOptions.setFlag(EditorOption::eoAutoIndent,oldAutoIndent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (needRefresh)
|
||||||
|
invalidateLine(ptCurrent.line);
|
||||||
|
|
||||||
// search next / previous line
|
// search next / previous line
|
||||||
if (bBackward)
|
if (bBackward)
|
||||||
ptCurrent.line--;
|
ptCurrent.line--;
|
||||||
else
|
else
|
||||||
ptCurrent.line++;
|
ptCurrent.line++;
|
||||||
if (((ptCurrent.line < ptStart.line) || (ptCurrent.line > ptEnd.line))
|
if (((ptCurrent.line < ptStart.line) || (ptCurrent.line > ptEnd.line))
|
||||||
&& bFromCursor && sOptions.testFlag(ssoWrapAround)){
|
&& bFromCursor ){
|
||||||
if (confirmAroundCallback && !confirmAroundCallback())
|
if (!sOptions.testFlag(ssoWrapAround) && confirmAroundCallback && !confirmAroundCallback())
|
||||||
break;
|
break;
|
||||||
//search start from cursor, search has finished but no result founds
|
//search start from cursor, search has finished but no result founds
|
||||||
bFromCursor = false;
|
bFromCursor = false;
|
||||||
|
|
|
@ -113,6 +113,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(EditorOptions)
|
||||||
enum class SearchAction {
|
enum class SearchAction {
|
||||||
Replace,
|
Replace,
|
||||||
ReplaceAll,
|
ReplaceAll,
|
||||||
|
ReplaceAndExit,
|
||||||
Skip,
|
Skip,
|
||||||
Exit
|
Exit
|
||||||
};
|
};
|
||||||
|
|
|
@ -252,64 +252,62 @@ void SynEditTextPainter::computeSelectionInfo()
|
||||||
BufferCoord vEnd{0,0};
|
BufferCoord vEnd{0,0};
|
||||||
bAnySelection = false;
|
bAnySelection = false;
|
||||||
// Only if selection is visible anyway.
|
// Only if selection is visible anyway.
|
||||||
if (edit->hasFocus()) {
|
bAnySelection = true;
|
||||||
bAnySelection = true;
|
// Get the *real* start of the selected area.
|
||||||
// Get the *real* start of the selected area.
|
if (edit->mBlockBegin.line < edit->mBlockEnd.line) {
|
||||||
if (edit->mBlockBegin.line < edit->mBlockEnd.line) {
|
vStart = edit->mBlockBegin;
|
||||||
vStart = edit->mBlockBegin;
|
vEnd = edit->mBlockEnd;
|
||||||
vEnd = edit->mBlockEnd;
|
} else if (edit->mBlockBegin.line > edit->mBlockEnd.line) {
|
||||||
} else if (edit->mBlockBegin.line > edit->mBlockEnd.line) {
|
vEnd = edit->mBlockBegin;
|
||||||
vEnd = edit->mBlockBegin;
|
vStart = edit->mBlockEnd;
|
||||||
vStart = edit->mBlockEnd;
|
} else if (edit->mBlockBegin.ch != edit->mBlockEnd.ch) {
|
||||||
} else if (edit->mBlockBegin.ch != edit->mBlockEnd.ch) {
|
// it is only on this line.
|
||||||
// it is only on this line.
|
vStart.line = edit->mBlockBegin.line;
|
||||||
vStart.line = edit->mBlockBegin.line;
|
vEnd.line = vStart.line;
|
||||||
vEnd.line = vStart.line;
|
if (edit->mBlockBegin.ch < edit->mBlockEnd.ch) {
|
||||||
if (edit->mBlockBegin.ch < edit->mBlockEnd.ch) {
|
vStart.ch = edit->mBlockBegin.ch;
|
||||||
vStart.ch = edit->mBlockBegin.ch;
|
vEnd.ch = edit->mBlockEnd.ch;
|
||||||
vEnd.ch = edit->mBlockEnd.ch;
|
} else {
|
||||||
} else {
|
vStart.ch = edit->mBlockEnd.ch;
|
||||||
vStart.ch = edit->mBlockEnd.ch;
|
vEnd.ch = edit->mBlockBegin.ch;
|
||||||
vEnd.ch = edit->mBlockBegin.ch;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
bAnySelection = false;
|
|
||||||
if (edit->mInputPreeditString.length()>0) {
|
|
||||||
if (vStart.line == edit->mCaretY && vStart.ch >=edit->mCaretX) {
|
|
||||||
vStart.ch+=edit->mInputPreeditString.length();
|
|
||||||
}
|
|
||||||
if (vEnd.line == edit->mCaretY && vEnd.ch >edit->mCaretX) {
|
|
||||||
vEnd.ch+=edit->mInputPreeditString.length();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If there is any visible selection so far, then test if there is an
|
} else
|
||||||
// intersection with the area to be painted.
|
bAnySelection = false;
|
||||||
|
if (edit->mInputPreeditString.length()>0) {
|
||||||
|
if (vStart.line == edit->mCaretY && vStart.ch >=edit->mCaretX) {
|
||||||
|
vStart.ch+=edit->mInputPreeditString.length();
|
||||||
|
}
|
||||||
|
if (vEnd.line == edit->mCaretY && vEnd.ch >edit->mCaretX) {
|
||||||
|
vEnd.ch+=edit->mInputPreeditString.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there is any visible selection so far, then test if there is an
|
||||||
|
// intersection with the area to be painted.
|
||||||
|
if (bAnySelection) {
|
||||||
|
// Don't care if the selection is not visible.
|
||||||
|
bAnySelection = (vEnd.line >= vFirstLine) && (vStart.line <= vLastLine);
|
||||||
if (bAnySelection) {
|
if (bAnySelection) {
|
||||||
// Don't care if the selection is not visible.
|
// Transform the selection from text space into screen space
|
||||||
bAnySelection = (vEnd.line >= vFirstLine) && (vStart.line <= vLastLine);
|
vSelStart = edit->bufferToDisplayPos(vStart);
|
||||||
if (bAnySelection) {
|
vSelEnd = edit->bufferToDisplayPos(vEnd);
|
||||||
// Transform the selection from text space into screen space
|
if (edit->mInputPreeditString.length()
|
||||||
vSelStart = edit->bufferToDisplayPos(vStart);
|
&& vStart.line == edit->mCaretY) {
|
||||||
vSelEnd = edit->bufferToDisplayPos(vEnd);
|
QString sLine = edit->lineText().left(edit->mCaretX-1)
|
||||||
if (edit->mInputPreeditString.length()
|
+ edit->mInputPreeditString
|
||||||
&& vStart.line == edit->mCaretY) {
|
+ edit->lineText().mid(edit->mCaretX-1);
|
||||||
QString sLine = edit->lineText().left(edit->mCaretX-1)
|
vSelStart.Column = edit->charToColumn(sLine,vStart.ch);
|
||||||
+ edit->mInputPreeditString
|
|
||||||
+ edit->lineText().mid(edit->mCaretX-1);
|
|
||||||
vSelStart.Column = edit->charToColumn(sLine,vStart.ch);
|
|
||||||
}
|
|
||||||
if (edit->mInputPreeditString.length()
|
|
||||||
&& vEnd.line == edit->mCaretY) {
|
|
||||||
QString sLine = edit->lineText().left(edit->mCaretX-1)
|
|
||||||
+ edit->mInputPreeditString
|
|
||||||
+ edit->lineText().mid(edit->mCaretX-1);
|
|
||||||
vSelEnd.Column = edit->charToColumn(sLine,vEnd.ch);
|
|
||||||
}
|
|
||||||
// In the column selection mode sort the begin and end of the selection,
|
|
||||||
// this makes the painting code simpler.
|
|
||||||
if (edit->mActiveSelectionMode == SelectionMode::Column && vSelStart.Column > vSelEnd.Column)
|
|
||||||
std::swap(vSelStart.Column, vSelEnd.Column);
|
|
||||||
}
|
}
|
||||||
|
if (edit->mInputPreeditString.length()
|
||||||
|
&& vEnd.line == edit->mCaretY) {
|
||||||
|
QString sLine = edit->lineText().left(edit->mCaretX-1)
|
||||||
|
+ edit->mInputPreeditString
|
||||||
|
+ edit->lineText().mid(edit->mCaretX-1);
|
||||||
|
vSelEnd.Column = edit->charToColumn(sLine,vEnd.ch);
|
||||||
|
}
|
||||||
|
// In the column selection mode sort the begin and end of the selection,
|
||||||
|
// this makes the painting code simpler.
|
||||||
|
if (edit->mActiveSelectionMode == SelectionMode::Column && vSelStart.Column > vSelEnd.Column)
|
||||||
|
std::swap(vSelStart.Column, vSelEnd.Column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue