implement text search and replace functionality

This commit is contained in:
Axel Kohlmeyer
2024-08-24 11:39:54 -04:00
parent 72873b0dca
commit 1b3652583b
10 changed files with 225 additions and 3 deletions

View File

@ -130,6 +130,8 @@ set(PROJECT_SOURCES
chartviewer.h chartviewer.h
codeeditor.cpp codeeditor.cpp
codeeditor.h codeeditor.h
findandreplace.cpp
findandreplace.h
helpers.cpp helpers.cpp
highlighter.cpp highlighter.cpp
highlighter.h highlighter.h

View File

@ -0,0 +1,148 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "findandreplace.h"
#include "codeeditor.h"
#include "lammpsgui.h"
#include <QApplication>
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QShortcut>
#include <QSizePolicy>
#include <QTextCursor>
/* ---------------------------------------------------------------------- */
FindAndReplace::FindAndReplace(CodeEditor *_editor, QWidget *parent) :
QDialog(parent), editor(_editor), search(nullptr), replace(nullptr), withcase(nullptr),
wrap(nullptr), whole(nullptr)
{
auto *layout = new QGridLayout;
search = new QLineEdit;
replace = new QLineEdit;
withcase = new QCheckBox("Match case");
wrap = new QCheckBox("Wrap around");
whole = new QCheckBox("Whole word");
auto *next = new QPushButton("Next");
auto *replone = new QPushButton("Replace");
auto *replall = new QPushButton("Replace All");
auto *done = new QPushButton("Done");
layout->addWidget(new QLabel("Find:"), 0, 0, Qt::AlignRight);
layout->addWidget(search, 0, 1, 1, 2, Qt::AlignLeft);
layout->addWidget(new QLabel("Replace with:"), 1, 0, Qt::AlignRight);
layout->addWidget(replace, 1, 1, 1, 2, Qt::AlignLeft);
layout->addWidget(withcase, 2, 0, Qt::AlignLeft);
layout->addWidget(wrap, 2, 1, Qt::AlignLeft);
layout->addWidget(whole, 2, 2, Qt::AlignLeft);
wrap->setChecked(true);
auto *buttons = new QHBoxLayout;
buttons->addWidget(next);
buttons->addWidget(replone);
buttons->addWidget(replall);
buttons->addWidget(done);
layout->addLayout(buttons, 3, 0, 1, 3, Qt::AlignHCenter);
connect(next, &QPushButton::released, this, &FindAndReplace::find_next);
connect(replone, &QPushButton::released, this, &FindAndReplace::replace_next);
connect(replall, &QPushButton::released, this, &FindAndReplace::replace_all);
connect(done, &QPushButton::released, this, &QDialog::accept);
auto action = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this);
connect(action, &QShortcut::activated, this, &FindAndReplace::quit);
setLayout(layout);
setWindowIcon(QIcon(":/icons/lammps-icon-128x128.png"));
setWindowTitle("LAMMPS-GUI - Find and Replace");
}
/* ---------------------------------------------------------------------- */
void FindAndReplace::find_next()
{
auto text = search->text();
int find_flags = 0;
if (withcase->isChecked()) find_flags |= QTextDocument::FindCaseSensitively;
if (whole->isChecked()) find_flags |= QTextDocument::FindWholeWords;
if (!text.isEmpty()) {
if (!editor->find(text, (QTextDocument::FindFlag)find_flags) && wrap->isChecked()) {
// nothing found from the current position to the end, reposition cursor and beginning
editor->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
editor->find(text, (QTextDocument::FindFlag)find_flags);
}
}
}
/* ---------------------------------------------------------------------- */
void FindAndReplace::replace_next()
{
auto text = search->text();
if (text.isEmpty()) return;
auto cursor = editor->textCursor();
auto flag = withcase->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
// if selected text at cursor location matches search text, replace
if (QString::compare(cursor.selectedText(), search->text(), flag) == 0)
cursor.insertText(replace->text());
find_next();
}
/* ---------------------------------------------------------------------- */
void FindAndReplace::replace_all()
{
auto text = search->text();
if (text.isEmpty()) return;
// drop selection if we have one
auto cursor = editor->textCursor();
if (cursor.hasSelection()) cursor.movePosition(QTextCursor::Left);
find_next();
cursor = editor->textCursor();
// keep replacing until find_next() does not find anything anymore
while (cursor.hasSelection()) {
cursor.insertText(replace->text());
find_next();
cursor = editor->textCursor();
}
}
/* ---------------------------------------------------------------------- */
void FindAndReplace::quit()
{
LammpsGui *main = nullptr;
for (QWidget *widget : QApplication::topLevelWidgets())
if (widget->objectName() == "LammpsGui") main = dynamic_cast<LammpsGui *>(widget);
if (main) main->quit();
}
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -0,0 +1,46 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef FIND_AND_REPLACE_H
#define FIND_AND_REPLACE_H
#include "codeeditor.h"
#include <QDialog>
class QLineEdit;
class QCheckBox;
class FindAndReplace : public QDialog {
Q_OBJECT
public:
explicit FindAndReplace(CodeEditor *_editor, QWidget *parent = nullptr);
~FindAndReplace() = default;
private slots:
void find_next();
void replace_next();
void replace_all();
void quit();
private:
CodeEditor *editor;
QLineEdit *search, *replace;
QCheckBox *withcase, *wrap, *whole;
};
#endif
// Local Variables:
// c-basic-offset: 4
// End:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -34,7 +34,8 @@ class ImageViewer : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent = nullptr); explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps,
QWidget *parent = nullptr);
private slots: private slots:
void saveAs(); void saveAs();

View File

@ -58,7 +58,7 @@
<description> <description>
Added search and replace functionality. Added search and replace functionality.
Converged command line argument parsing using Qt facilities Converged command line argument parsing using Qt facilities
Dark mode compatible Added dark mode adjustments
</description> </description>
</release> </release>
<release version="1.6.8" timestamp="1723581926"> <release version="1.6.8" timestamp="1723581926">

View File

@ -15,6 +15,7 @@
#include "chartviewer.h" #include "chartviewer.h"
#include "fileviewer.h" #include "fileviewer.h"
#include "findandreplace.h"
#include "helpers.h" #include "helpers.h"
#include "highlighter.h" #include "highlighter.h"
#include "imageviewer.h" #include "imageviewer.h"
@ -206,6 +207,7 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
connect(ui->actionPaste, &QAction::triggered, this, &LammpsGui::paste); connect(ui->actionPaste, &QAction::triggered, this, &LammpsGui::paste);
connect(ui->actionUndo, &QAction::triggered, this, &LammpsGui::undo); connect(ui->actionUndo, &QAction::triggered, this, &LammpsGui::undo);
connect(ui->actionRedo, &QAction::triggered, this, &LammpsGui::redo); connect(ui->actionRedo, &QAction::triggered, this, &LammpsGui::redo);
connect(ui->actionSearchAndReplace, &QAction::triggered, this, &LammpsGui::findandreplace);
connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer); connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer);
connect(ui->actionRun_File, &QAction::triggered, this, &LammpsGui::run_file); connect(ui->actionRun_File, &QAction::triggered, this, &LammpsGui::run_file);
connect(ui->actionStop_LAMMPS, &QAction::triggered, this, &LammpsGui::stop_run); connect(ui->actionStop_LAMMPS, &QAction::triggered, this, &LammpsGui::stop_run);
@ -1863,6 +1865,14 @@ void LammpsGui::edit_variables()
} }
} }
void LammpsGui::findandreplace()
{
FindAndReplace find(ui->textEdit, this);
find.setFont(font());
find.setObjectName("find");
find.exec();
}
void LammpsGui::preferences() void LammpsGui::preferences()
{ {
QSettings settings; QSettings settings;

View File

@ -115,6 +115,7 @@ private slots:
void paste(); void paste();
void undo(); void undo();
void redo(); void redo();
void findandreplace();
void run_buffer() { do_run(true); } void run_buffer() { do_run(true); }
void run_file() { do_run(false); } void run_file() { do_run(false); }

View File

@ -58,6 +58,7 @@
<file>icons/preferences-desktop.png</file> <file>icons/preferences-desktop.png</file>
<file>icons/process-stop.png</file> <file>icons/process-stop.png</file>
<file>icons/run-file.png</file> <file>icons/run-file.png</file>
<file>icons/search.png</file>
<file>icons/system-box.png</file> <file>icons/system-box.png</file>
<file>icons/system-help.png</file> <file>icons/system-help.png</file>
<file>icons/system-run.png</file> <file>icons/system-run.png</file>

View File

@ -62,6 +62,8 @@
<addaction name="actionCut"/> <addaction name="actionCut"/>
<addaction name="actionPaste"/> <addaction name="actionPaste"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSearchAndReplace"/>
<addaction name="separator"/>
<addaction name="actionPreferences"/> <addaction name="actionPreferences"/>
<addaction name="actionDefaults"/> <addaction name="actionDefaults"/>
</widget> </widget>
@ -312,12 +314,23 @@
<string>Ctrl+Shift+H</string> <string>Ctrl+Shift+H</string>
</property> </property>
</action> </action>
<action name="actionSearchAndReplace">
<property name="icon">
<iconset theme=":/icons/search.png"/>
</property>
<property name="text">
<string>&amp;Find and Replace...</string>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
</property>
</action>
<action name="actionPreferences"> <action name="actionPreferences">
<property name="icon"> <property name="icon">
<iconset theme=":/icons/preferences-desktop.png"/> <iconset theme=":/icons/preferences-desktop.png"/>
</property> </property>
<property name="text"> <property name="text">
<string>Pre&amp;ferences...</string> <string>P&amp;references...</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+P</string> <string>Ctrl+P</string>