diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index 73e945820b..1732169bba 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -130,6 +130,8 @@ set(PROJECT_SOURCES chartviewer.h codeeditor.cpp codeeditor.h + findandreplace.cpp + findandreplace.h helpers.cpp highlighter.cpp highlighter.h diff --git a/tools/lammps-gui/findandreplace.cpp b/tools/lammps-gui/findandreplace.cpp new file mode 100644 index 0000000000..d3ef6409b5 --- /dev/null +++ b/tools/lammps-gui/findandreplace.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +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(widget); + if (main) main->quit(); +} + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/findandreplace.h b/tools/lammps-gui/findandreplace.h new file mode 100644 index 0000000000..7c34c50543 --- /dev/null +++ b/tools/lammps-gui/findandreplace.h @@ -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 + +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: diff --git a/tools/lammps-gui/icons/search.png b/tools/lammps-gui/icons/search.png new file mode 100644 index 0000000000..1790200d49 Binary files /dev/null and b/tools/lammps-gui/icons/search.png differ diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index 8e72cea7bf..94632bde89 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -34,7 +34,8 @@ class ImageViewer : public QDialog { Q_OBJECT public: - explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent = nullptr); + explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, + QWidget *parent = nullptr); private slots: void saveAs(); diff --git a/tools/lammps-gui/lammps-gui.appdata.xml b/tools/lammps-gui/lammps-gui.appdata.xml index 46fcc86125..a6a384af1b 100644 --- a/tools/lammps-gui/lammps-gui.appdata.xml +++ b/tools/lammps-gui/lammps-gui.appdata.xml @@ -58,7 +58,7 @@ Added search and replace functionality. Converged command line argument parsing using Qt facilities - Dark mode compatible + Added dark mode adjustments diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index d4705645d2..362a8f00cb 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -15,6 +15,7 @@ #include "chartviewer.h" #include "fileviewer.h" +#include "findandreplace.h" #include "helpers.h" #include "highlighter.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->actionUndo, &QAction::triggered, this, &LammpsGui::undo); 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_File, &QAction::triggered, this, &LammpsGui::run_file); 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() { QSettings settings; diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 0cf6677149..9185b7a535 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -115,6 +115,7 @@ private slots: void paste(); void undo(); void redo(); + void findandreplace(); void run_buffer() { do_run(true); } void run_file() { do_run(false); } diff --git a/tools/lammps-gui/lammpsgui.qrc b/tools/lammps-gui/lammpsgui.qrc index cf9dd20dda..8111edd44b 100644 --- a/tools/lammps-gui/lammpsgui.qrc +++ b/tools/lammps-gui/lammpsgui.qrc @@ -58,6 +58,7 @@ icons/preferences-desktop.png icons/process-stop.png icons/run-file.png + icons/search.png icons/system-box.png icons/system-help.png icons/system-run.png diff --git a/tools/lammps-gui/lammpsgui.ui b/tools/lammps-gui/lammpsgui.ui index 1517168327..045e0f84a8 100644 --- a/tools/lammps-gui/lammpsgui.ui +++ b/tools/lammps-gui/lammpsgui.ui @@ -62,6 +62,8 @@ + + @@ -312,12 +314,23 @@ Ctrl+Shift+H + + + + + + &Find and Replace... + + + Ctrl+F + + - Pre&ferences... + P&references... Ctrl+P