Merge branch 'develop' into next_release
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(lammps-gui VERSION 1.6.9 LANGUAGES CXX)
|
||||
project(lammps-gui VERSION 1.6.10 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
@ -130,6 +130,8 @@ set(PROJECT_SOURCES
|
||||
chartviewer.h
|
||||
codeeditor.cpp
|
||||
codeeditor.h
|
||||
findandreplace.cpp
|
||||
findandreplace.h
|
||||
helpers.cpp
|
||||
highlighter.cpp
|
||||
highlighter.h
|
||||
|
||||
@ -2,12 +2,21 @@ LAMMPS-GUI TODO list:
|
||||
|
||||
# Short term goals (v1.x)
|
||||
|
||||
- implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences.
|
||||
- add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped.
|
||||
- add a "Charts tab" to the preferences with the following (default) settings:
|
||||
- default filter data yes/no
|
||||
- default smooth parameters
|
||||
- default plot colors
|
||||
- enable "raw" or "smooth" or "both"
|
||||
- add QLineEdit field to enter plot title
|
||||
- add a "Colors" menu to the image viewer to adjust color settings for the
|
||||
current image (unlike the defaults in the perferences) including assigning
|
||||
colors to individual atom types.
|
||||
- Support color by property (e.g. scan computes or fixes with per-atom data), define colormaps etc.
|
||||
- Add a "Diameters" dialog where diamaters can by specified by atom type
|
||||
- figure out how widgets can be resized to fraction of available screen size.
|
||||
- figure out stacking order of frames and whether it can be more flexible
|
||||
- implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences.
|
||||
- add a "Colors" menu to the image viewer to adjust color settings for the
|
||||
current image (unlike the defaults in the perferences). Support color by
|
||||
property (e.g. scan computes or fixes with per-atom data), define colormaps etc.
|
||||
|
||||
- implement indenting regions for (nested) loops?
|
||||
- implement data file manager GUI with the following features:
|
||||
|
||||
@ -424,7 +424,7 @@ void ChartViewer::add_data(int step, double data)
|
||||
if (last_step < step) {
|
||||
last_step = step;
|
||||
|
||||
// do not add data that deviates by more than 5 sigma from the average
|
||||
// do not add data that deviates by more than 4 sigma from the average
|
||||
// over the last 5 to 20 data items. this is a hack to work around
|
||||
// getting corrupted data from lammps_get_last_thermo()
|
||||
const auto &points = series->points();
|
||||
|
||||
@ -218,7 +218,10 @@ CodeEditor::CodeEditor(QWidget *parent) :
|
||||
help_index.close();
|
||||
}
|
||||
|
||||
setBackgroundRole(QPalette::Light);
|
||||
lineNumberArea = new LineNumberArea(this);
|
||||
lineNumberArea->setBackgroundRole(QPalette::Dark);
|
||||
lineNumberArea->setAutoFillBackground(true);
|
||||
connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
|
||||
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
|
||||
updateLineNumberAreaWidth(0);
|
||||
@ -669,7 +672,7 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||
if (block.isVisible() && bottom >= event->rect().top()) {
|
||||
QString number = QString::number(blockNumber + 1) + " ";
|
||||
if ((highlight == NO_HIGHLIGHT) || (blockNumber != std::abs(highlight))) {
|
||||
painter.setPen(Qt::black);
|
||||
painter.setPen(palette().color(QPalette::WindowText));
|
||||
} else {
|
||||
number = QString(">") + QString::number(blockNumber + 1) + "<";
|
||||
if (highlight < 0)
|
||||
|
||||
148
tools/lammps-gui/findandreplace.cpp
Normal file
148
tools/lammps-gui/findandreplace.cpp
Normal 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:
|
||||
46
tools/lammps-gui/findandreplace.h
Normal file
46
tools/lammps-gui/findandreplace.h
Normal 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:
|
||||
@ -13,9 +13,12 @@
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QColor>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QPalette>
|
||||
#include <QProcess>
|
||||
#include <QStringList>
|
||||
|
||||
@ -84,6 +87,16 @@ void purge_directory(const QString &dir)
|
||||
}
|
||||
}
|
||||
|
||||
// compare black level of foreground and background color
|
||||
bool is_light_theme()
|
||||
{
|
||||
QPalette p;
|
||||
int fg = p.brush(QPalette::Active, QPalette::WindowText).color().black();
|
||||
int bg = p.brush(QPalette::Active, QPalette::Window).color().black();
|
||||
|
||||
return (fg > bg);
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// c-basic-offset: 4
|
||||
// End:
|
||||
|
||||
@ -28,6 +28,9 @@ extern bool has_exe(const QString &exe);
|
||||
// recursively purge a directory
|
||||
extern void purge_directory(const QString &dir);
|
||||
|
||||
// flag if light or dark theme
|
||||
extern bool is_light_theme();
|
||||
|
||||
#endif
|
||||
// Local Variables:
|
||||
// c-basic-offset: 4
|
||||
|
||||
@ -12,6 +12,28 @@
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "highlighter.h"
|
||||
#include "helpers.h"
|
||||
#include <QColor>
|
||||
|
||||
// workaround for Qt-5.12
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
namespace QColorConstants {
|
||||
const QColor Red = QColor::fromRgb(0xff, 0x00, 0x00);
|
||||
const QColor Green = QColor::fromRgb(0x00, 0xff, 0x00);
|
||||
const QColor Blue = QColor::fromRgb(0x00, 0x00, 0xff);
|
||||
const QColor Cyan = QColor::fromRgb(0x00, 0xff, 0xff);
|
||||
const QColor Magenta = QColor::fromRgb(0xff, 0x00, 0xff);
|
||||
const QColor Yellow = QColor::fromRgb(0xff, 0xff, 0x00);
|
||||
namespace Svg {
|
||||
const QColor dodgerblue = QColor::fromRgb(0x1e, 0x90, 0xff);
|
||||
const QColor indianred = QColor::fromRgb(0xcd, 0x5c, 0x5c);
|
||||
const QColor lightcoral = QColor::fromRgb(0xf0, 0x80, 0x80);
|
||||
const QColor lightgray = QColor::fromRgb(0xd3, 0xd3, 0xd3);
|
||||
const QColor lightgreen = QColor::fromRgb(0x90, 0xee, 0x90);
|
||||
const QColor lightskyblue = QColor::fromRgb(0x87, 0xce, 0xfa);
|
||||
} // namespace Svg
|
||||
} // namespace QColorConstants
|
||||
#endif
|
||||
|
||||
Highlighter::Highlighter(QTextDocument *parent) :
|
||||
QSyntaxHighlighter(parent),
|
||||
@ -54,27 +76,54 @@ Highlighter::Highlighter(QTextDocument *parent) :
|
||||
isTriple(QStringLiteral("[^\"]*\"\"\"[^\"]*")),
|
||||
isString(QStringLiteral("(\".+?\"|'.+?'|\"\"\".*\"\"\")")), in_triple(false)
|
||||
{
|
||||
formatNumber.setForeground(Qt::blue);
|
||||
formatString.setForeground(Qt::darkGreen);
|
||||
formatString.setFontWeight(QFont::Normal);
|
||||
formatComment.setForeground(Qt::red);
|
||||
formatSpecial.setForeground(Qt::darkMagenta);
|
||||
formatSpecial.setFontWeight(QFont::Bold);
|
||||
formatParticle.setForeground(Qt::darkRed);
|
||||
formatParticle.setFontWeight(QFont::Bold);
|
||||
formatRun.setForeground(Qt::darkBlue);
|
||||
formatRun.setFontWeight(QFont::Bold);
|
||||
formatVariable.setForeground(Qt::darkGray);
|
||||
formatVariable.setFontWeight(QFont::Bold);
|
||||
if (is_light_theme()) {
|
||||
// syntax colors for light themes
|
||||
formatNumber.setForeground(Qt::blue);
|
||||
formatString.setForeground(Qt::darkGreen);
|
||||
formatString.setFontWeight(QFont::Normal);
|
||||
formatComment.setForeground(Qt::red);
|
||||
formatSpecial.setForeground(Qt::darkMagenta);
|
||||
formatSpecial.setFontWeight(QFont::Bold);
|
||||
formatParticle.setForeground(Qt::darkRed);
|
||||
formatParticle.setFontWeight(QFont::Bold);
|
||||
formatRun.setForeground(Qt::darkBlue);
|
||||
formatRun.setFontWeight(QFont::Bold);
|
||||
formatVariable.setForeground(Qt::darkGray);
|
||||
formatVariable.setFontWeight(QFont::Bold);
|
||||
|
||||
formatOutput.setForeground(Qt::darkYellow);
|
||||
formatOutput.setFontWeight(QFont::Bold);
|
||||
formatRead.setForeground(Qt::magenta);
|
||||
formatRead.setFontWeight(QFont::Bold);
|
||||
formatLattice.setForeground(Qt::darkGreen);
|
||||
formatLattice.setFontWeight(QFont::Bold);
|
||||
formatSetup.setForeground(Qt::darkCyan);
|
||||
formatSetup.setFontWeight(QFont::Bold);
|
||||
formatOutput.setForeground(Qt::darkYellow);
|
||||
formatOutput.setFontWeight(QFont::Bold);
|
||||
formatRead.setForeground(Qt::magenta);
|
||||
formatRead.setFontWeight(QFont::Bold);
|
||||
formatLattice.setForeground(Qt::darkGreen);
|
||||
formatLattice.setFontWeight(QFont::Bold);
|
||||
formatSetup.setForeground(Qt::darkCyan);
|
||||
formatSetup.setFontWeight(QFont::Bold);
|
||||
} else {
|
||||
// syntax colors for dark themes
|
||||
formatNumber.setForeground(QColorConstants::Svg::dodgerblue);
|
||||
formatString.setForeground(QColorConstants::Green);
|
||||
formatString.setFontWeight(QFont::Normal);
|
||||
formatComment.setForeground(QColorConstants::Red);
|
||||
formatComment.setFontWeight(QFont::Bold);
|
||||
formatSpecial.setForeground(QColorConstants::Magenta);
|
||||
formatSpecial.setFontWeight(QFont::Bold);
|
||||
formatParticle.setForeground(QColorConstants::Svg::indianred);
|
||||
formatParticle.setFontWeight(QFont::Bold);
|
||||
formatRun.setForeground(QColorConstants::Svg::lightskyblue);
|
||||
formatRun.setFontWeight(QFont::Bold);
|
||||
formatVariable.setForeground(QColorConstants::Svg::lightgray);
|
||||
formatVariable.setFontWeight(QFont::Bold);
|
||||
|
||||
formatOutput.setForeground(QColorConstants::Yellow);
|
||||
formatOutput.setFontWeight(QFont::Bold);
|
||||
formatRead.setForeground(QColorConstants::Svg::lightcoral);
|
||||
formatRead.setFontWeight(QFont::Bold);
|
||||
formatLattice.setForeground(QColorConstants::Svg::lightgreen);
|
||||
formatLattice.setFontWeight(QFont::Bold);
|
||||
formatSetup.setForeground(QColorConstants::Cyan);
|
||||
formatSetup.setFontWeight(QFont::Bold);
|
||||
}
|
||||
}
|
||||
|
||||
void Highlighter::highlightBlock(const QString &text)
|
||||
|
||||
BIN
tools/lammps-gui/icons/search.png
Normal file
BIN
tools/lammps-gui/icons/search.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
@ -20,6 +20,7 @@
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QDir>
|
||||
#include <QDoubleValidator>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
@ -31,6 +32,7 @@
|
||||
#include <QImageReader>
|
||||
#include <QKeySequence>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QPalette>
|
||||
@ -135,9 +137,10 @@ static const QString blank(" ");
|
||||
|
||||
ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) :
|
||||
QDialog(parent), menuBar(new QMenuBar), imageLabel(new QLabel), scrollArea(new QScrollArea),
|
||||
saveAsAct(nullptr), copyAct(nullptr), cmdAct(nullptr), zoomInAct(nullptr), zoomOutAct(nullptr),
|
||||
normalSizeAct(nullptr), lammps(_lammps), group("all"), filename(fileName), useelements(false),
|
||||
usediameter(false), usesigma(false)
|
||||
buttonBox(nullptr), scaleFactor(1.0), atomSize(1.0), saveAsAct(nullptr), copyAct(nullptr),
|
||||
cmdAct(nullptr), zoomInAct(nullptr), zoomOutAct(nullptr), normalSizeAct(nullptr),
|
||||
lammps(_lammps), group("all"), filename(fileName), useelements(false), usediameter(false),
|
||||
usesigma(false)
|
||||
{
|
||||
imageLabel->setBackgroundRole(QPalette::Base);
|
||||
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
@ -163,6 +166,13 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
|
||||
renderstatus->setEnabled(false);
|
||||
renderstatus->setToolTip("Render status");
|
||||
renderstatus->setObjectName("renderstatus");
|
||||
auto *asize = new QLineEdit(QString::number(atomSize));
|
||||
auto *valid = new QDoubleValidator(1.0e-10, 1.0e10, 10, asize);
|
||||
asize->setValidator(valid);
|
||||
asize->setObjectName("atomSize");
|
||||
asize->setToolTip("Set Atom size");
|
||||
asize->setEnabled(false);
|
||||
asize->hide();
|
||||
settings.beginGroup("snapshot");
|
||||
auto *xval = new QSpinBox;
|
||||
xval->setRange(100, 10000);
|
||||
@ -179,6 +189,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
|
||||
yval->setToolTip("Set rendered image height");
|
||||
yval->setMinimumSize(bsize);
|
||||
settings.endGroup();
|
||||
connect(asize, &QLineEdit::editingFinished, this, &ImageViewer::set_atom_size);
|
||||
connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
|
||||
connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
|
||||
|
||||
@ -249,6 +260,11 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
|
||||
|
||||
menuLayout->addWidget(menuBar);
|
||||
menuLayout->addWidget(renderstatus);
|
||||
menuLayout->addWidget(new QLabel(" Atom Size: "));
|
||||
menuLayout->addWidget(asize);
|
||||
// hide item initially
|
||||
menuLayout->itemAt(2)->widget()->setObjectName("AtomLabel");
|
||||
menuLayout->itemAt(2)->widget()->hide();
|
||||
menuLayout->addWidget(new QLabel(" Width: "));
|
||||
menuLayout->addWidget(xval);
|
||||
menuLayout->addWidget(new QLabel(" Height: "));
|
||||
@ -307,7 +323,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
|
||||
doanti->setChecked(antialias);
|
||||
|
||||
scaleFactor = 1.0;
|
||||
resize(image.width() + 20, image.height() + 75);
|
||||
resize(image.width() + 25, image.height() + 80);
|
||||
|
||||
scrollArea->setVisible(true);
|
||||
updateActions();
|
||||
@ -356,6 +372,13 @@ void ImageViewer::reset_view()
|
||||
createImage();
|
||||
}
|
||||
|
||||
void ImageViewer::set_atom_size()
|
||||
{
|
||||
auto *field = qobject_cast<QLineEdit *>(sender());
|
||||
atomSize = field->text().toDouble();
|
||||
createImage();
|
||||
}
|
||||
|
||||
void ImageViewer::edit_size()
|
||||
{
|
||||
auto *field = qobject_cast<QSpinBox *>(sender());
|
||||
@ -560,10 +583,43 @@ void ImageViewer::createImage()
|
||||
if (useelements || usediameter || usesigma) {
|
||||
auto *button = findChild<QPushButton *>("vdw");
|
||||
if (button) button->setEnabled(true);
|
||||
auto *edit = findChild<QLineEdit *>("atomSize");
|
||||
if (edit) {
|
||||
edit->setEnabled(false);
|
||||
edit->hide();
|
||||
}
|
||||
auto *label = findChild<QLabel *>("AtomLabel");
|
||||
if (label) {
|
||||
label->setEnabled(false);
|
||||
label->hide();
|
||||
}
|
||||
|
||||
} else {
|
||||
adiams.clear();
|
||||
auto *button = findChild<QPushButton *>("vdw");
|
||||
if (button) button->setEnabled(false);
|
||||
|
||||
auto *label = findChild<QLabel *>("AtomLabel");
|
||||
if (label) {
|
||||
label->setEnabled(true);
|
||||
label->show();
|
||||
}
|
||||
auto *edit = findChild<QLineEdit *>("atomSize");
|
||||
if (edit) {
|
||||
if (!edit->isEnabled()) {
|
||||
edit->setEnabled(true);
|
||||
edit->show();
|
||||
// initialize with lattice spacing
|
||||
auto *xlattice = (const double *)lammps->extract_global("xlattice");
|
||||
if (xlattice) atomSize = *xlattice;
|
||||
edit->setText(QString::number(atomSize));
|
||||
}
|
||||
atomSize = edit->text().toDouble();
|
||||
}
|
||||
if (atomSize != 1.0) {
|
||||
for (int i = 1; i <= ntypes; ++i)
|
||||
adiams += QString("adiam %1 %2 ").arg(i).arg(atomSize);
|
||||
}
|
||||
}
|
||||
|
||||
// color
|
||||
@ -607,6 +663,7 @@ void ImageViewer::createImage()
|
||||
dumpcmd += " backcolor " + settings.value("background", "black").toString();
|
||||
if (useelements) dumpcmd += blank + elements + blank + adiams + blank;
|
||||
if (usesigma) dumpcmd += blank + adiams + blank;
|
||||
if (!useelements && !usesigma && (atomSize != 1.0)) dumpcmd += blank + adiams + blank;
|
||||
settings.endGroup();
|
||||
|
||||
last_dump_cmd = dumpcmd;
|
||||
@ -617,10 +674,10 @@ void ImageViewer::createImage()
|
||||
const QImage newImage = reader.read();
|
||||
dumpfile.remove();
|
||||
|
||||
// read of new image failed. Don't try to scale and load it.
|
||||
// read of new image failed. nothing left to do.
|
||||
if (newImage.isNull()) return;
|
||||
|
||||
// scale back to achieve antialiasing
|
||||
// show show image
|
||||
image = newImage;
|
||||
imageLabel->setPixmap(QPixmap::fromImage(image));
|
||||
imageLabel->adjustSize();
|
||||
|
||||
@ -34,13 +34,15 @@ 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();
|
||||
void copy();
|
||||
void quit();
|
||||
|
||||
void set_atom_size();
|
||||
void edit_size();
|
||||
void reset_view();
|
||||
void toggle_ssao();
|
||||
@ -75,7 +77,8 @@ private:
|
||||
QLabel *imageLabel;
|
||||
QScrollArea *scrollArea;
|
||||
QDialogButtonBox *buttonBox;
|
||||
double scaleFactor = 1.0;
|
||||
double scaleFactor;
|
||||
double atomSize;
|
||||
|
||||
QAction *saveAsAct;
|
||||
QAction *copyAct;
|
||||
|
||||
@ -54,8 +54,17 @@
|
||||
</provides>
|
||||
|
||||
<releases>
|
||||
<release version="1.6.10" timestamp="1724585189">
|
||||
<description>
|
||||
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.6.9" timestamp="1724308872">
|
||||
<description>
|
||||
Added search and replace functionality
|
||||
Converged command line argument parsing using Qt facilities
|
||||
Added dark mode adjustments to syntax highlighting
|
||||
Add field to enter Atom size, if not determined otherwise
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.6.8" timestamp="1723581926">
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
#include "chartviewer.h"
|
||||
#include "fileviewer.h"
|
||||
#include "findandreplace.h"
|
||||
#include "helpers.h"
|
||||
#include "highlighter.h"
|
||||
#include "imageviewer.h"
|
||||
@ -68,18 +69,13 @@
|
||||
static const QString blank(" ");
|
||||
static constexpr int BUFLEN = 256;
|
||||
|
||||
LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
|
||||
LammpsGui::LammpsGui(QWidget *parent, const QString &filename) :
|
||||
QMainWindow(parent), ui(new Ui::LammpsGui), highlighter(nullptr), capturer(nullptr),
|
||||
status(nullptr), logwindow(nullptr), imagewindow(nullptr), chartwindow(nullptr),
|
||||
slideshow(nullptr), logupdater(nullptr), dirstatus(nullptr), progress(nullptr),
|
||||
prefdialog(nullptr), lammpsstatus(nullptr), varwindow(nullptr), wizard(nullptr),
|
||||
runner(nullptr), is_running(false), run_counter(0)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
// register QList<QString> only needed for Qt5
|
||||
qRegisterMetaTypeStreamOperators<QList<QString>>("QList<QString>");
|
||||
#endif
|
||||
|
||||
docver = "";
|
||||
ui->setupUi(this);
|
||||
this->setCentralWidget(ui->textEdit);
|
||||
@ -90,27 +86,34 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
|
||||
// use $HOME if we get dropped to "/" like on macOS
|
||||
if (current_dir == "/") current_dir = QDir::homePath();
|
||||
inspectList.clear();
|
||||
setAutoFillBackground(true);
|
||||
|
||||
// restore and initialize settings
|
||||
QSettings settings;
|
||||
|
||||
#if defined(LAMMPS_GUI_USE_PLUGIN)
|
||||
plugin_path.clear();
|
||||
std::string deffile = settings.value("plugin_path", "liblammps.so").toString().toStdString();
|
||||
for (const char *libfile : {deffile.c_str(), "./liblammps.so", "liblammps.dylib",
|
||||
"./liblammps.dylib", "liblammps.dll"}) {
|
||||
if (lammps.load_lib(libfile)) {
|
||||
auto canonical = QFileInfo(libfile).canonicalFilePath();
|
||||
plugin_path = canonical.toStdString();
|
||||
settings.setValue("plugin_path", canonical);
|
||||
break;
|
||||
plugin_path =
|
||||
QFileInfo(settings.value("plugin_path", "liblammps.so").toString()).canonicalFilePath();
|
||||
if (!lammps.load_lib(plugin_path.toStdString().c_str())) {
|
||||
// fall back to defaults
|
||||
for (const char *libfile :
|
||||
{"./liblammps.so", "liblammps.dylib", "./liblammps.dylib", "liblammps.dll"}) {
|
||||
if (lammps.load_lib(libfile)) {
|
||||
plugin_path = QFileInfo(libfile).canonicalFilePath();
|
||||
settings.setValue("plugin_path", plugin_path);
|
||||
break;
|
||||
} else {
|
||||
plugin_path.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin_path.empty()) {
|
||||
if (plugin_path.isEmpty()) {
|
||||
// none of the plugin paths could load, remove key
|
||||
settings.remove("plugin_path");
|
||||
QMessageBox::critical(this, "Error", "Cannot open LAMMPS shared library file");
|
||||
QMessageBox::critical(this, "Error",
|
||||
"Cannot open LAMMPS shared library file.\n"
|
||||
"Use -p command line flag to specify a path to the library.");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
@ -205,6 +208,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);
|
||||
@ -278,7 +282,7 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
|
||||
dirstatus->show();
|
||||
ui->statusbar->addWidget(progress);
|
||||
|
||||
if (filename) {
|
||||
if (filename.size() > 0) {
|
||||
open_file(filename);
|
||||
} else {
|
||||
setWindowTitle("LAMMPS-GUI - Editor - *unknown*");
|
||||
@ -502,7 +506,7 @@ void LammpsGui::start_exe()
|
||||
void LammpsGui::update_recents(const QString &filename)
|
||||
{
|
||||
QSettings settings;
|
||||
recent = settings.value("recent").value<QList<QString>>();
|
||||
if (settings.contains("recent")) recent = settings.value("recent").value<QList<QString>>();
|
||||
|
||||
for (int i = 0; i < recent.size(); ++i) {
|
||||
QFileInfo fi(recent[i]);
|
||||
@ -514,7 +518,10 @@ void LammpsGui::update_recents(const QString &filename)
|
||||
|
||||
if (!filename.isEmpty() && !recent.contains(filename)) recent.prepend(filename);
|
||||
if (recent.size() > 5) recent.removeLast();
|
||||
settings.setValue("recent", QVariant::fromValue(recent));
|
||||
if (recent.size() > 0)
|
||||
settings.setValue("recent", QVariant::fromValue(recent));
|
||||
else
|
||||
settings.remove("recent");
|
||||
|
||||
ui->action_1->setVisible(false);
|
||||
if ((recent.size() > 0) && !recent[0].isEmpty()) {
|
||||
@ -1428,12 +1435,16 @@ void LammpsGui::setFont(const QFont &newfont)
|
||||
void LammpsGui::about()
|
||||
{
|
||||
std::string version = "This is LAMMPS-GUI version " LAMMPS_GUI_VERSION;
|
||||
version += " using Qt version " QT_VERSION_STR "\n";
|
||||
version += " using Qt version " QT_VERSION_STR;
|
||||
if (is_light_theme())
|
||||
version += " using light theme\n";
|
||||
else
|
||||
version += " using dark theme\n";
|
||||
if (lammps.has_plugin()) {
|
||||
version += "LAMMPS library loaded as plugin";
|
||||
if (!plugin_path.empty()) {
|
||||
if (!plugin_path.isEmpty()) {
|
||||
version += " from file ";
|
||||
version += plugin_path;
|
||||
version += plugin_path.toStdString();
|
||||
}
|
||||
} else {
|
||||
version += "LAMMPS library linked to executable";
|
||||
@ -1862,6 +1873,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;
|
||||
|
||||
@ -68,7 +68,7 @@ class LammpsGui : public QMainWindow {
|
||||
friend class Tutorial2Wizard;
|
||||
|
||||
public:
|
||||
LammpsGui(QWidget *parent = nullptr, const char *filename = nullptr);
|
||||
LammpsGui(QWidget *parent = nullptr, const QString &filename = QString());
|
||||
~LammpsGui() override;
|
||||
|
||||
protected:
|
||||
@ -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); }
|
||||
|
||||
@ -171,7 +172,7 @@ private:
|
||||
LammpsWrapper lammps;
|
||||
LammpsRunner *runner;
|
||||
QString docver;
|
||||
std::string plugin_path;
|
||||
QString plugin_path;
|
||||
bool is_running;
|
||||
int run_counter;
|
||||
std::vector<char *> lammps_args;
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
<file>icons/preferences-desktop.png</file>
|
||||
<file>icons/process-stop.png</file>
|
||||
<file>icons/run-file.png</file>
|
||||
<file>icons/search.png</file>
|
||||
<file>icons/system-box.png</file>
|
||||
<file>icons/system-help.png</file>
|
||||
<file>icons/system-run.png</file>
|
||||
|
||||
@ -62,6 +62,8 @@
|
||||
<addaction name="actionCut"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSearchAndReplace"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPreferences"/>
|
||||
<addaction name="actionDefaults"/>
|
||||
</widget>
|
||||
@ -312,12 +314,23 @@
|
||||
<string>Ctrl+Shift+H</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSearchAndReplace">
|
||||
<property name="icon">
|
||||
<iconset theme=":/icons/search.png"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Find and Replace...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+F</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPreferences">
|
||||
<property name="icon">
|
||||
<iconset theme=":/icons/preferences-desktop.png"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pre&ferences...</string>
|
||||
<string>P&references...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+P</string>
|
||||
|
||||
@ -115,7 +115,7 @@ double LammpsWrapper::extract_variable(const char *keyword)
|
||||
}
|
||||
double val = *((double *)ptr);
|
||||
#if defined(LAMMPS_GUI_USE_PLUGIN)
|
||||
ptr = ((liblammpsplugin_t *)plugin_handle)->free(ptr);
|
||||
((liblammpsplugin_t *)plugin_handle)->free(ptr);
|
||||
#else
|
||||
lammps_free(ptr);
|
||||
#endif
|
||||
|
||||
@ -17,6 +17,9 @@
|
||||
#include <QCommandLineOption>
|
||||
#include <QCommandLineParser>
|
||||
#include <QLocale>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -27,6 +30,11 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(lammpsgui);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
// register QList<QString> only needed for Qt5
|
||||
qRegisterMetaTypeStreamOperators<QList<QString>>("QList<QString>");
|
||||
#endif
|
||||
|
||||
QApplication app(argc, argv);
|
||||
// enforce using the plain ASCII C locale within the GUI.
|
||||
QLocale::setDefault(QLocale::c());
|
||||
@ -40,13 +48,32 @@ int main(int argc, char *argv[])
|
||||
"\nA graphical editor for LAMMPS input files with syntax highlighting and\n"
|
||||
"auto-completion that can run LAMMPS directly. It has built-in capabilities\n"
|
||||
"for monitoring, visualization, plotting, and capturing console output.");
|
||||
#if defined(LAMMPS_GUI_USE_PLUGIN)
|
||||
QCommandLineOption plugindir(QStringList() << "p"
|
||||
<< "pluginpath",
|
||||
"Path to LAMMPS shared library", "path");
|
||||
parser.addOption(plugindir);
|
||||
#endif
|
||||
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument("file", "The LAMMPS input file to open (optional).");
|
||||
parser.process(app); // this removes known arguments
|
||||
parser.process(app);
|
||||
|
||||
const char *infile = nullptr;
|
||||
if (argc > 1) infile = argv[1];
|
||||
#if defined(LAMMPS_GUI_USE_PLUGIN)
|
||||
if (parser.isSet(plugindir)) {
|
||||
QStringList pluginpath = parser.values(plugindir);
|
||||
if (pluginpath.length() > 0) {
|
||||
QSettings settings;
|
||||
settings.setValue("plugin_path", QString(pluginpath.at(0)));
|
||||
settings.sync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QString infile;
|
||||
QStringList args = parser.positionalArguments();
|
||||
if (args.size() > 0) infile = args[0];
|
||||
LammpsGui w(nullptr, infile);
|
||||
w.show();
|
||||
return app.exec();
|
||||
|
||||
Reference in New Issue
Block a user