update LAMMPS GUI to version 1.2

This commit is contained in:
Axel Kohlmeyer
2023-08-16 02:33:18 -04:00
parent e32ae65aa1
commit 088ff4ad27
80 changed files with 3779 additions and 538 deletions

View File

@ -1,3 +1,4 @@
# -*- CMake -*- master configuration file for building LAMMPS
######################################## ########################################
# CMake build system # CMake build system
# This file is part of LAMMPS # This file is part of LAMMPS
@ -888,8 +889,15 @@ else()
endif() endif()
include(FeatureSummary) include(FeatureSummary)
feature_summary(DESCRIPTION "The following tools and libraries have been found and configured:" WHAT PACKAGES_FOUND) feature_summary(DESCRIPTION "The following tools and libraries have been found and configured:" WHAT PACKAGES_FOUND)
if(GIT_FOUND AND EXISTS ${LAMMPS_DIR}/.git)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --dirty=-modified --always
OUTPUT_VARIABLE GIT_DESCRIBE
ERROR_QUIET
WORKING_DIRECTORY ${LAMMPS_DIR}
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
message(STATUS "<<< Build configuration >>> message(STATUS "<<< Build configuration >>>
LAMMPS Version: ${PROJECT_VERSION} LAMMPS Version: ${PROJECT_VERSION} ${GIT_DESCRIBE}
Operating System: ${CMAKE_SYSTEM_NAME} ${CMAKE_LINUX_DISTRO} ${CMAKE_DISTRO_VERSION} Operating System: ${CMAKE_SYSTEM_NAME} ${CMAKE_LINUX_DISTRO} ${CMAKE_DISTRO_VERSION}
CMake Version: ${CMAKE_VERSION} CMake Version: ${CMAKE_VERSION}
Build type: ${LAMMPS_BUILD_TYPE} Build type: ${LAMMPS_BUILD_TYPE}
@ -1026,6 +1034,14 @@ endif()
if(BUILD_LAMMPS_SHELL) if(BUILD_LAMMPS_SHELL)
message(STATUS "<<< Building LAMMPS Shell >>>") message(STATUS "<<< Building LAMMPS Shell >>>")
endif() endif()
if(BUILD_LAMMPS_GUI)
message(STATUS "<<< Building LAMMPS GUI >>>")
if(LAMMPS_GUI_USE_PLUGIN)
message(STATUS "Loading LAMMPS library as plugin at run time")
else()
message(STATUS "Linking LAMMPS library at compile time")
endif()
endif()
if(ENABLE_TESTING) if(ENABLE_TESTING)
message(STATUS "<<< Building Unit Tests >>>") message(STATUS "<<< Building Unit Tests >>>")
if(ENABLE_COVERAGE) if(ENABLE_COVERAGE)

View File

@ -1,26 +1,64 @@
#!/bin/bash -vx #!/bin/bash
APP_NAME=lammps-gui APP_NAME=lammps-gui
DESTDIR=${PWD}/../LAMMPS_GUI DESTDIR=${PWD}/LAMMPS_GUI
SYSROOT="$1"
echo "Delete old files, if they exist" echo "Delete old files, if they exist"
rm -rvf ${DESTDIR} LAMMPS-Win10-amd64.zip rm -rvf ${DESTDIR}/LAMMPS_GUI ${DESTDIR}/LAMMPS-Win10-amd64.zip
echo "Create staging area for deployment and populate" echo "Create staging area for deployment and populate"
DESTDIR=${DESTDIR} cmake --install . --prefix "/" DESTDIR=${DESTDIR} cmake --install . --prefix "/"
echo "Add required dependencies for Qt" # no static libs needed
for dll in Qt5Core.dll Qt5Gui.dll Qt5Widgets.dll rm -rvf ${DESTDIR}/lib
# but the LAMMPS lib
echo "Copying required DLL files"
for dll in $(objdump -p *.exe *.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq)
do \ do \
cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/${dll} ${DESTDIR}/bin/ doskip=0
done for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32
for dir in styles platforms imageformats do \
do \ test ${dll} = ${skip}.dll && doskip=1
mkdir -p ${DESTDIR}/${dir} done
cp -r /usr/x86_64-w64-mingw32/sys-root/mingw/lib/qt5/plugins/${dir}/*.dll ${DESTDIR}/${dir} test ${doskip} -eq 1 && continue
test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin
done done
pushd .. echo "Copy required Qt plugins"
zip -9rv LAMMPS-Win10-amd64.zip LAMMPS_GUI mkdir -p ${DESTDIR}/qt5plugins
popd for plugin in imageformats platforms styles
exit 0 do \
cp -r ${SYSROOT}/lib/qt5/plugins/${plugin} ${DESTDIR}/qt5plugins/
done
echo "Check dependencies of DLL files"
for dll in $(objdump -p ${DESTDIR}/bin/*.dll ${DESTDIR}/qt5plugins/*/*.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq)
do \
doskip=0
for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32
do \
test ${dll} = ${skip}.dll && doskip=1
done
test ${doskip} -eq 1 && continue
test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin
done
for dll in $(objdump -p ${DESTDIR}/bin/*.dll ${DESTDIR}/qt5plugins/*/*.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq)
do \
doskip=0
for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32
do \
test ${dll} = ${skip}.dll && doskip=1
done
test ${doskip} -eq 1 && continue
test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin
done
cat > ${DESTDIR}/bin/qt.conf <<EOF
[Paths]
Plugins = ../qt5plugins
EOF
zip -9rvD LAMMPS-Win10-amd64.zip LAMMPS_GUI

View File

@ -1,6 +1,9 @@
#!/bin/sh #!/bin/sh
# wrapper for bundled executables # wrapper for bundled executables
# reset locale to avoid problems with decimal numbers
export LC_ALL=C
BASEDIR=$(dirname "$0") BASEDIR=$(dirname "$0")
EXENAME=$(basename "$0") EXENAME=$(basename "$0")

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(lammps-gui VERSION 1.0.0 LANGUAGES CXX) project(lammps-gui VERSION 1.2.0 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@ -16,10 +16,6 @@ mark_as_advanced(LAMMPS_GUI_USE_PLUGIN)
if(NOT LAMMPS_EXCEPTIONS) if(NOT LAMMPS_EXCEPTIONS)
message(FATAL_ERROR "Must enable LAMMPS_EXCEPTIONS for building the LAMMPS GUI") message(FATAL_ERROR "Must enable LAMMPS_EXCEPTIONS for building the LAMMPS GUI")
endif() endif()
if(BUILD_MPI)
message(FATAL_ERROR "Must disable BUILD_MPI for building the LAMMPS GUI")
endif()
# when this file is included as subdirectory in the LAMMPS build, many settings are directly imported # when this file is included as subdirectory in the LAMMPS build, many settings are directly imported
if(LAMMPS_DIR) if(LAMMPS_DIR)
set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR}) set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR})
@ -60,12 +56,21 @@ endif()
set(LAMMPS_PLUGINLIB_DIR ${LAMMPS_DIR}/examples/COUPLE/plugin) set(LAMMPS_PLUGINLIB_DIR ${LAMMPS_DIR}/examples/COUPLE/plugin)
if(LAMMPS_GUI_USE_PLUGIN) if(LAMMPS_GUI_USE_PLUGIN)
if(APPLE)
message(FATAL_ERROR "Dynamic loading of the LAMMPS library currently not supported on this platform")
endif()
enable_language(C) enable_language(C)
set(PLUGIN_LOADER_SRC ${LAMMPS_PLUGINLIB_DIR}/liblammpsplugin.c) set(PLUGIN_LOADER_SRC ${LAMMPS_PLUGINLIB_DIR}/liblammpsplugin.c)
endif() endif()
# include resource compiler to embed icons into the executable on Windows
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
enable_language(RC)
set(ICON_RC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/lmpicons.rc)
endif()
# we require Qt 5 and at least version 5.12 at that. # we require Qt 5 and at least version 5.12 at that.
find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets) find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets Charts)
set(PROJECT_SOURCES set(PROJECT_SOURCES
main.cpp main.cpp
@ -75,6 +80,8 @@ set(PROJECT_SOURCES
highlighter.h highlighter.h
imageviewer.cpp imageviewer.cpp
imageviewer.h imageviewer.h
chartviewer.cpp
chartviewer.h
lammpsgui.cpp lammpsgui.cpp
lammpsgui.h lammpsgui.h
lammpsgui.ui lammpsgui.ui
@ -82,10 +89,15 @@ set(PROJECT_SOURCES
lammpswrapper.cpp lammpswrapper.cpp
lammpswrapper.h lammpswrapper.h
linenumberarea.h linenumberarea.h
logwindow.cpp
logwindow.h
preferences.cpp preferences.cpp
preferences.h preferences.h
setvariables.cpp
setvariables.h
stdcapture.cpp stdcapture.cpp
${PLUGIN_LOADER_SRC} ${PLUGIN_LOADER_SRC}
${ICON_RC_FILE}
) )
qt5_add_resources(PROJECT_SOURCES lammpsgui.qrc) qt5_add_resources(PROJECT_SOURCES lammpsgui.qrc)
@ -110,7 +122,7 @@ else()
endif() endif()
target_include_directories(lammps-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(lammps-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(lammps-gui PRIVATE LAMMPS_GUI_VERSION="${PROJECT_VERSION}") target_compile_definitions(lammps-gui PRIVATE LAMMPS_GUI_VERSION="${PROJECT_VERSION}")
target_link_libraries(lammps-gui PRIVATE Qt5::Widgets) target_link_libraries(lammps-gui PRIVATE Qt5::Widgets Qt5::Charts)
if(BUILD_OMP) if(BUILD_OMP)
find_package(OpenMP COMPONENTS CXX REQUIRED) find_package(OpenMP COMPONENTS CXX REQUIRED)
target_link_libraries(lammps-gui PRIVATE OpenMP::OpenMP_CXX) target_link_libraries(lammps-gui PRIVATE OpenMP::OpenMP_CXX)
@ -172,8 +184,23 @@ elseif(MSVC)
get_filename_component(QT5_BIN_DIR "${Qt5Core_DIR}/../../../bin" ABSOLUTE) get_filename_component(QT5_BIN_DIR "${Qt5Core_DIR}/../../../bin" ABSOLUTE)
get_filename_component(INSTNAME ${CMAKE_INSTALL_PREFIX} NAME) get_filename_component(INSTNAME ${CMAKE_INSTALL_PREFIX} NAME)
install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -D INSTNAME=${INSTNAME} -D VC_INIT=\"${VC_INIT}\" -D QT5_BIN_DIR=\"${QT5_BIN_DIR}\" -P \"${CMAKE_SOURCE_DIR}/packaging/build_windows_vs.cmake\" WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}/..\" COMMAND_ECHO STDOUT)") install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -D INSTNAME=${INSTNAME} -D VC_INIT=\"${VC_INIT}\" -D QT5_BIN_DIR=\"${QT5_BIN_DIR}\" -P \"${CMAKE_SOURCE_DIR}/packaging/build_windows_vs.cmake\" WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}/..\" COMMAND_ECHO STDOUT)")
elseif((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING)
install(TARGETS lammps-gui DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES $<TARGET_RUNTIME_DLLS:lammps-gui> TYPE BIN)
install(FILES $<TARGET_RUNTIME_DLLS:lammps> TYPE BIN)
install(FILES $<TARGET_RUNTIME_DLLS:lmp> TYPE BIN)
add_custom_target(zip
COMMAND sh -vx ${LAMMPS_DIR}/cmake/packaging/build_windows_cross_zip.sh ${CMAKE_INSTALL_PREFIX}
DEPENDS lmp lammps-gui
COMMENT "Create zip file with windows binaries"
BYPRODUCT LAMMPS-Win10-amd64.zip
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
install(TARGETS lammps-gui DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS lammps-gui DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-gui.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-input.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages/)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-input.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/text/x-application-lammps.xml)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/icons/hicolor DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/)
install(CODE [[ install(CODE [[
file(GET_RUNTIME_DEPENDENCIES file(GET_RUNTIME_DEPENDENCIES
LIBRARIES $<TARGET_FILE:lammps> LIBRARIES $<TARGET_FILE:lammps>

View File

@ -1,104 +1,14 @@
LAMMPS GUI LAMMPS GUI
# Overview
LAMMPS GUI is essentially a small graphical text editor that is linked LAMMPS GUI is essentially a small graphical text editor that is linked
to the LAMMPS library and thus can run LAMMPS using the contents of the to the LAMMPS library and thus can run LAMMPS using the contents of the
text buffer as input. This is similar to what people usually would do text buffer as input directly without requiring an additional LAMMPS
using a text editor to edit the input and then a command line terminal executable. It can also capture and show the screen output, a line graph
window to run the input commands. The main benefit is that this of thermodynamic data and snapshot images in separate windows.
integrates very well with graphical desktop environments and that it is
easier to use for beginners in running computations and thus very
suitable for tutorials on LAMMPS.
# Features Detailed documentation about installing and using LAMMPS GUI is in
the LAMMPS manual.
The main window of the LAMMPS GUI is a text editor window with syntax
highlighting set up for LAMMPS input files. It can be used to edit any
kind of text file, but then trying to run those files will cause errors.
The output of a run is captured and displayed in a separate window
dialog. The log window is updated during the run and a progress bar for
each run command shown in the main window. Starting a new run will open
another log windows. After the simulation is finished, an image of the
simulated system can be created and shown in another window. Ongoing
runs can be stopped at the next iteration via triggering a timeout.
When opening a file, the editor will determine the directory where the
file resides and switch its current working directory to that folder.
Many LAMMPS inputs contain commands that read other files, typically
from the folder with the input file. The GUI will show the current
working directory. The editor window can also receive (entire) files
via drag-n-drop from a file manager GUI or a desktop environment.
Almost all commands are accessible via hotkeys. Which those hotkeys are,
is shown next to the entries in the menu. Log and image viewer windows
can be closed with CTRL-W (or Command-W on macOS). The "About LAMMPS"
dialog will show the LAMMPS version and the features included into the
LAMMPS library linked to the LAMMPS GUI.
Due to its nature as a graphical application, it is not possible to use
the LAMMPS GUI in parallel with MPI, but OpenMP multi-threading is
available.
# Prerequisites and portability
LAMMPS GUI is programmed using the Qt cross-platform GUI toolkit,
currently using Qt version 5.15LTS for better compatibility with older
compilers. It has been successfully compiled and tested on:
- Fedora Linux 38 x86\_64 using GCC 13 and Clang 16
- Apple macOS 12 (Monterey) and macOS 13 (Ventura) with Xcode on arm64 and x86\_64
- Windows 10 and 11 x86_64 with Visual Studio 2022 and Visual C++ 14.36
# Compilation
The source for the LAMMPS GUI is included with the LAMMPS source code
distribution in the folder `tools/lammps-gui` and thus it can be can be
built as part of a regular LAMMPS compilation. Using CMake is required.
To enable its compilation the CMake variable `-D BUILD_LAMMPS_GUI=on`
must be set when creating the CMake configuration. All other settings
(compiler, flags, compile type) for LAMMPS GUI are then inherited from
the regular LAMMPS build. If the Qt library is packaged for Linux
distributions, then its location is typically auto-detected since the
required CMake configuration files are stored in a location where CMake
can find them without additional help. Otherwise, the location of the
Qt library installation must be indicated by setting `-D
Qt5_DIR=/path/to/qt5/lib/cmake/Qt5`, which is a path to a folder inside
the Qt installation that contains the file `Qt5Config.cmake`.
It is also possible to build the LAMMPS GUI as a standalone executable
(e.g. when LAMMPS has been compiled with traditional make), then the
CMake configuration needs to be told where to find the LAMMPS headers
and the LAMMPS library, via `-D LAMMPS_SOURCE_DIR=/path/to/lammps/src`.
CMake will try to guess a build folder with the LAMMPS library from that
path, but it can also be set with `-D LAMMPS_LIB_DIR=/path/to/lammps/lib`.
Rather than linking to the LAMMPS library during compilation, it is also
possible to compile the GUI with a plugin loader library that will load
the LAMMPS library at runtime during startup of the GUI from a shared
library; e.g. `liblammps.so` or `liblammps.dylib` or `liblammps.dll`
depending on the operating system. This has the advantage that the
LAMMPS library can be updated LAMMPS without having to recompile the
GUI. The ABI of the LAMMPS C-library interface is very stable and
generally backward compatible. This feature is enabled by setting
`-D LAMMPS_GUI_USE_PLUGIN=on` and then
`-D LAMMPS_PLUGINLIB_DIR=/path/to/lammps/plugin/loader`. Typically, this
would be the `examples/COUPLE/plugin` folder of the LAMMPS distribution.
# Platform notes
## macOS
When building on macOS, the build procedure will try to manufacture a
drag-n-drop installer, LAMMPS-macOS-multiarch.dmg. To build multi-arch
executables that will run on both, arm64 and x86_64 architectures
natively, it is necessary to set the CMake variable
`-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64`. To achieve wide compatibility
with different macOS versions, you can also set
`-D CMAKE_OSX_DEPLOYMENT_TARGET=11.0` which will set compatibility to macOS
11 (Big Sur) and later, even if you are compiling on a more recent macOS
version.
-------- --------
updated by Axel Kohlmeyer, 08/1023 updated by Axel Kohlmeyer, 2023-08-12

View File

@ -2,18 +2,26 @@ LAMMPS-GUI TODO list:
# Short term goals # Short term goals
- rewrite syntax highlighting to be line oriented instead of word oriented.
handle first part of line based on regular expressions, then advance and only highlight strings and numbers.
handle "&" continuation and multiline strings with """ like C style comments in Qt docs example
- add CTRL-q hotkey to log windows so you can exit the entire application (add do you really want to? dialog to this) - add CTRL-q hotkey to log windows so you can exit the entire application (add do you really want to? dialog to this)
- add "syntax check" with enabled "-skiprun" flag - add "syntax check" with enabled "-skiprun" flag
- add multi-tab settings dialog where certain properties can be set through customizing the LAMMPS command line - need to handle "label" and "jump" commands from within ?
+ select Font - switch processing of input to line based commands or?
- add list of 5(?) most recently opened/saved files to file dialog (and also write to settings state on exit) (note: must store full path!) - switch input file editor to read-only while loop is running
# Long term ideas # Long term ideas
- add feature to LAMMPS (to the LAMMPS class) to store current file name and line number, update while reading/parsing
use in error messages
add API to library interface to query this info and use it for highlighting in text editor
- rewrite entire application to either use QtCreator for everything or just build the App and its layout manually
- port to Qt6
- also a rewrite should establish consistent naming conventions. now we have a mix of LAMMPS style, Qt style, and others.
- add option to attach a debugger to the running program (highly non-portable, need customization support in preferences)
- write a "wizard" dialog that can be used for beginners to create an input file template for a few typical use scenarios - write a "wizard" dialog that can be used for beginners to create an input file template for a few typical use scenarios
- use the "lammps_get_last_thermo" function to get access to thermodynamic data during a run and add plot/graph dialog that can plot one or more of those graphs while the simulation is still running
- possibly also implement a callback interface, so that external programs can be called after thermo data is updated.
- support single stepping, i.e. process input line by line (need to detect continuation chars!) with highlighting active line(s) - support single stepping, i.e. process input line by line (need to detect continuation chars!) with highlighting active line(s)
- have command text input file in/above status bar where individual commands can be tested. have insert button to copy line into file at the current point - have command text input file in/above status bar where individual commands can be tested. have insert button to copy line into file at the current point
- support text completion as done with lammps-shell - support text completion as done with lammps-shell
- have context menu for known commands to offer retrieving help by dispatching URL to webbrowser (process index from sphinx for that purpose) - add a "python" mode, where instead of launching LAMMPS, python is loaded where the LAMMPS python module is made available.
- add a "python" mode, where instead of launching LAMMPS, python is loaded that the LAMMPS python module is made available. - support multiple tabs and multiple LAMMPS instances?

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,248 @@
/* ----------------------------------------------------------------------
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 "chartviewer.h"
#include <QHBoxLayout>
#include <QLineSeries>
#include <QSettings>
#include <QVBoxLayout>
using namespace QtCharts;
ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), active_chart(-1),
filename(_filename)
{
auto *top = new QHBoxLayout;
menu->addMenu(file);
menu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
columns = new QComboBox;
top->addWidget(menu);
top->addWidget(columns);
saveAsAct = file->addAction("&Save Graph As...", this, &ChartWindow::saveAs);
saveAsAct->setIcon(QIcon(":/document-save-as.png"));
exportCsvAct = file->addAction("&Export data to CSV...", this, &ChartWindow::exportCsv);
exportCsvAct->setIcon(QIcon(":/application-calc.png"));
exportDatAct = file->addAction("Export data to &Gnuplot...", this, &ChartWindow::exportDat);
exportDatAct->setIcon(QIcon(":/application-plot.png"));
file->addSeparator();
closeAct = file->addAction("&Close", this, &QWidget::close);
closeAct->setIcon(QIcon(":/window-close.png"));
auto *layout = new QVBoxLayout;
layout->addLayout(top);
setLayout(layout);
connect(columns, SIGNAL(currentIndexChanged(int)), this, SLOT(change_chart(int)));
QSettings settings;
resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt());
}
int ChartWindow::get_step() const
{
if (charts.size() > 0) {
auto *v = charts[0];
return (int)v->get_step(v->get_count() - 1);
} else {
return -1;
}
}
void ChartWindow::reset_charts()
{
while (layout()->count() > 1) {
auto *item = layout()->takeAt(1);
if (item) {
layout()->removeItem(item);
delete item->widget();
delete item;
}
}
charts.clear();
columns->clear();
active_chart = 0;
}
void ChartWindow::add_chart(const QString &title, int index)
{
auto *chart = new ChartViewer(title, index);
layout()->addWidget(chart);
columns->addItem(title, index);
columns->show();
// hide all but the first chart added
if (charts.size() > 0) chart->hide();
charts.append(chart);
active_chart = 0;
}
void ChartWindow::add_data(int step, double data, int index)
{
for (auto &c : charts)
if (c->get_index() == index) c->add_data(step, data);
}
void ChartWindow::saveAs()
{
if (charts.empty() || (active_chart < 0)) return;
QString defaultname = filename + "." + columns->currentText() + ".png";
if (filename.isEmpty()) defaultname = columns->currentText() + ".png";
QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as Image", defaultname,
"Image Files (*.jpg *.png *.bmp *.ppm)");
if (!fileName.isEmpty()) {
charts[active_chart]->grab().save(fileName);
}
}
void ChartWindow::exportDat()
{
if (charts.empty() || (active_chart < 0)) return;
QString defaultname = filename + ".dat";
if (filename.isEmpty()) defaultname = "lammpsdata.dat";
QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as Gnuplot data", defaultname,
"Image Files (*.dat)");
if (!fileName.isEmpty()) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write("# Thermodynamic data from ");
file.write(filename.toLocal8Bit());
file.write("\n# Columns:");
for (auto &c : charts) {
file.write(" ");
file.write(c->get_title());
}
file.write("\n");
int lines = charts[0]->get_count();
for (int i = 0; i < lines; ++i) {
// timestep
file.write(QString::number(charts[0]->get_step(i)).toLocal8Bit());
for (auto &c : charts) {
file.write(" ");
file.write(QString::number(c->get_data(i)).toLocal8Bit());
}
file.write("\n");
}
file.close();
}
}
}
void ChartWindow::exportCsv()
{
if (charts.empty() || (active_chart < 0)) return;
QString defaultname = filename + ".csv";
if (filename.isEmpty()) defaultname = "lammpsdata.csv";
QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as CSV data", defaultname,
"Image Files (*.csv)");
if (!fileName.isEmpty()) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write("Step");
for (auto &c : charts) {
file.write(",");
file.write(c->get_title());
}
file.write("\n");
int lines = charts[0]->get_count();
for (int i = 0; i < lines; ++i) {
// timestep
file.write(QString::number(charts[0]->get_step(i)).toLocal8Bit());
for (auto &c : charts) {
file.write(",");
file.write(QString::number(c->get_data(i)).toLocal8Bit());
}
file.write("\n");
}
file.close();
}
}
}
void ChartWindow::change_chart(int index)
{
int choice = columns->currentData().toInt();
for (auto &c : charts) {
if (choice == c->get_index())
c->show();
else
c->hide();
}
}
void ChartWindow::closeEvent(QCloseEvent *event)
{
QSettings settings;
if (!isMaximized()) {
settings.setValue("chartx", width());
settings.setValue("charty", height());
}
QWidget::closeEvent(event);
}
/* -------------------------------------------------------------------- */
ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) :
QChartView(parent), last_step(-1), index(_index), chart(new QChart), series(new QLineSeries),
xaxis(new QValueAxis), yaxis(new QValueAxis)
{
chart->legend()->hide();
chart->addAxis(xaxis, Qt::AlignBottom);
chart->addAxis(yaxis, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(xaxis);
series->attachAxis(yaxis);
xaxis->setTitleText("Time step");
xaxis->setTickCount(5);
xaxis->setLabelFormat("%d");
yaxis->setTickCount(5);
xaxis->setMinorTickCount(5);
yaxis->setMinorTickCount(5);
yaxis->setTitleText(title);
series->setName(title);
setRenderHint(QPainter::Antialiasing);
setChart(chart);
setRubberBand(QChartView::RectangleRubberBand);
}
/* -------------------------------------------------------------------- */
void ChartViewer::add_data(int step, double data)
{
if (last_step < step) {
last_step = step;
series->append(step, data);
auto points = series->pointsVector();
qreal xmin = 1.0e100;
qreal xmax = -1.0e100;
qreal ymin = 1.0e100;
qreal ymax = -1.0e100;
for (auto &p : points) {
xmin = qMin(xmin, p.x());
xmax = qMax(xmax, p.x());
ymin = qMin(ymin, p.y());
ymax = qMax(ymax, p.y());
}
xaxis->setRange(xmin, xmax);
yaxis->setRange(ymin, ymax);
}
}
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -0,0 +1,94 @@
/* -*- 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 CHARTVIEWER_H
#define CHARTVIEWER_H
#include <QList>
#include <QString>
#include <QWidget>
#include <QtCharts>
class QAction;
class QMenuBar;
class QMenu;
class QComboBox;
class ChartViewer;
class ChartWindow : public QWidget {
Q_OBJECT
public:
ChartWindow(const QString &filename, QWidget *parent = nullptr);
int num_charts() const { return charts.size(); }
bool has_title(const QString &title, int index) const
{
return (columns->itemText(index) == title);
}
int get_step() const;
void reset_charts();
void add_chart(const QString &title, int index);
void add_data(int step, double data, int index);
private slots:
void saveAs();
void exportDat();
void exportCsv();
void change_chart(int index);
protected:
void closeEvent(QCloseEvent *event) override;
private:
QMenuBar *menu;
QMenu *file;
QComboBox *columns;
QAction *saveAsAct;
QAction *exportCsvAct;
QAction *exportDatAct;
QAction *closeAct;
QString filename;
int active_chart;
QList<ChartViewer *> charts;
};
/* -------------------------------------------------------------------- */
class ChartViewer : public QtCharts::QChartView {
Q_OBJECT
public:
explicit ChartViewer(const QString &title, int index, QWidget *parent = nullptr);
void add_data(int step, double data);
int get_index() const { return index; };
int get_count() const { return series->count(); }
const char *get_title() const { return series->name().toLocal8Bit(); }
double get_step(int index) const { return series->at(index).x(); }
double get_data(int index) const { return series->at(index).y(); }
private:
int last_step, index;
QtCharts::QChart *chart;
QtCharts::QLineSeries *series;
QtCharts::QValueAxis *xaxis;
QtCharts::QValueAxis *yaxis;
};
#endif
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -15,19 +15,61 @@
#include "lammpsgui.h" #include "lammpsgui.h"
#include "linenumberarea.h" #include "linenumberarea.h"
#include <QAction>
#include <QDesktopServices>
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QIcon>
#include <QKeySequence>
#include <QMenu>
#include <QMimeData> #include <QMimeData>
#include <QPainter> #include <QPainter>
#include <QRegularExpression>
#include <QTextBlock> #include <QTextBlock>
#include <QUrl>
CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
{ {
lineNumberArea = new LineNumberArea(this); help_action = new QShortcut(QKeySequence::fromString("Ctrl+?"), parent);
connect(help_action, &QShortcut::activated, this, &CodeEditor::get_help);
// initialize help system
QFile help_index(":/help_index.table");
if (help_index.open(QIODevice::ReadOnly | QIODevice::Text)) {
while (!help_index.atEnd()) {
auto line = QString(help_index.readLine());
auto words = line.trimmed().split(' ');
if (words.size() > 2) {
if (words.at(1) == "pair_style") {
pair_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "bond_style") {
bond_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "angle_style") {
angle_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "dihedral_style") {
dihedral_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "improper_style") {
improper_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "fix") {
fix_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "compute") {
compute_map[words.at(2)] = words.at(0);
} else if (words.at(1) == "kspace_style") {
cmd_map["kspace_style"] = "kspace_style.html";
}
// ignoring: dump, fix_modify ATC
} else if (words.size() == 2) {
cmd_map[words.at(1)] = words.at(0);
} else {
fprintf(stderr, "unhandled: %s", line.toStdString().c_str());
}
}
help_index.close();
}
lineNumberArea = new LineNumberArea(this);
connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth); connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea); connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
updateLineNumberAreaWidth(0); updateLineNumberAreaWidth(0);
} }
@ -138,6 +180,102 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
} }
} }
void CodeEditor::contextMenuEvent(QContextMenuEvent *event)
{
// reposition the cursor here?
QString page, help;
find_help(page, help);
// print augmented context menu if an entry was found
auto *menu = createStandardContextMenu();
if (!page.isEmpty()) {
menu->addSeparator();
auto action = menu->addAction(QString("View Documentation for '%1'").arg(help));
action->setIcon(QIcon(":/system-help.png"));
action->setData(page);
connect(action, &QAction::triggered, this, &CodeEditor::open_help);
// if we link to help with specific styles (fix, compute, pair, bond, ...)
// also link to the docs for the primary command
auto words = help.split(' ');
if (words.size() > 1) {
help = words.at(0);
page = words.at(0);
page += ".html";
auto action2 = menu->addAction(QString("View Documentation for '%1'").arg(help));
action2->setIcon(QIcon(":/system-help.png"));
action2->setData(page);
connect(action2, &QAction::triggered, this, &CodeEditor::open_help);
}
}
auto action3 = menu->addAction(QString("LAMMPS Manual"));
action3->setIcon(QIcon(":/help-browser.png"));
action3->setData(QString());
connect(action3, &QAction::triggered, this, &CodeEditor::open_help);
menu->exec(event->globalPos());
delete menu;
}
void CodeEditor::get_help()
{
QString page, help;
find_help(page, help);
if (!page.isEmpty())
QDesktopServices::openUrl(QUrl(QString("https://docs.lammps.org/%1").arg(page)));
}
void CodeEditor::find_help(QString &page, QString &help)
{
// process line of text where the cursor is
auto text = textCursor().block().text().replace('\t', ' ').trimmed();
auto style =
QRegularExpression("^(pair|bond|angle|dihedral|improper)_style\\s+(\\S+)").match(text);
help.clear();
page.clear();
if (style.hasMatch()) {
if (style.captured(1) == "pair") {
page = pair_map.value(style.captured(2), QString());
help = QString("pair_style %1").arg(style.captured(2));
} else if (style.captured(1) == "bond") {
page = bond_map.value(style.captured(2), QString());
help = QString("bond_style %1").arg(style.captured(2));
} else if (style.captured(1) == "angle") {
page = angle_map.value(style.captured(2), QString());
help = QString("angle_style %1").arg(style.captured(2));
} else if (style.captured(1) == "dihedral") {
page = dihedral_map.value(style.captured(2), QString());
help = QString("dihedral_style %1").arg(style.captured(2));
} else if (style.captured(1) == "improper") {
page = improper_map.value(style.captured(2), QString());
help = QString("improper_style %1").arg(style.captured(2));
}
}
style = QRegularExpression("^(fix|compute)\\s+\\w+\\s+\\w+\\s+(\\S+)").match(text);
if (style.hasMatch()) {
help = QString("%1 %2").arg(style.captured(1), style.captured(2));
if (style.captured(1) == "fix") {
page = fix_map.value(style.captured(2), QString());
} else if (style.captured(1) == "compute") {
page = compute_map.value(style.captured(2), QString());
}
}
// could not find a matching "style", now try the plain command
if (page.isEmpty() && !text.isEmpty()) {
auto cmd = text.split(' ').at(0);
help = cmd;
page = cmd_map.value(cmd, QString());
}
}
void CodeEditor::open_help()
{
QAction *act = qobject_cast<QAction *>(sender());
QDesktopServices::openUrl(
QUrl(QString("https://docs.lammps.org/%1").arg(act->data().toString())));
}
// Local Variables: // Local Variables:
// c-basic-offset: 4 // c-basic-offset: 4
// End: // End:

View File

@ -14,7 +14,10 @@
#ifndef CODEEDITOR_H #ifndef CODEEDITOR_H
#define CODEEDITOR_H #define CODEEDITOR_H
#include <QMap>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QShortcut>
#include <QString>
class CodeEditor : public QPlainTextEdit { class CodeEditor : public QPlainTextEdit {
Q_OBJECT Q_OBJECT
@ -30,14 +33,29 @@ protected:
void dragEnterEvent(QDragEnterEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override;
bool canInsertFromMimeData(const QMimeData *source) const override; bool canInsertFromMimeData(const QMimeData *source) const override;
void dropEvent(QDropEvent *event) override; void dropEvent(QDropEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private slots: private slots:
void updateLineNumberAreaWidth(int newBlockCount); void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine(); void highlightCurrentLine();
void updateLineNumberArea(const QRect &rect, int dy); void updateLineNumberArea(const QRect &rect, int dy);
void get_help();
void find_help(QString &page, QString &help);
void open_help();
private: private:
QWidget *lineNumberArea; QWidget *lineNumberArea;
QShortcut *help_action;
QMap<QString, QString> cmd_map;
QMap<QString, QString> fix_map;
QMap<QString, QString> compute_map;
QMap<QString, QString> pair_map;
QMap<QString, QString> bond_map;
QMap<QString, QString> angle_map;
QMap<QString, QString> dihedral_map;
QMap<QString, QString> improper_map;
QMap<QString, QString> dump_map;
}; };
#endif #endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
tools/lammps-gui/hd-img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because it is too large Load Diff

View File

@ -18,18 +18,23 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
HighlightingRule rule; HighlightingRule rule;
outputFormat.setForeground(Qt::darkYellow); outputFormat.setForeground(Qt::darkYellow);
outputFormat.setFontWeight(QFont::Bold);
readFormat.setForeground(Qt::magenta); readFormat.setForeground(Qt::magenta);
readFormat.setFontWeight(QFont::Bold);
latticeFormat.setForeground(Qt::darkGreen); latticeFormat.setForeground(Qt::darkGreen);
latticeFormat.setFontWeight(QFont::Bold);
particleFormat.setForeground(Qt::darkRed); particleFormat.setForeground(Qt::darkRed);
particleFormat.setFontWeight(QFont::Bold);
setupFormat.setForeground(Qt::darkCyan); setupFormat.setForeground(Qt::darkCyan);
runFormat.setForeground(Qt::green); setupFormat.setFontWeight(QFont::Bold);
runFormat.setForeground(Qt::darkBlue);
runFormat.setFontWeight(QFont::Bold); runFormat.setFontWeight(QFont::Bold);
defineFormat.setForeground(Qt::darkMagenta); defineFormat.setForeground(Qt::darkMagenta);
defineFormat.setFontWeight(QFont::Bold); defineFormat.setFontWeight(QFont::Bold);
numberFormat.setForeground(Qt::blue); numberFormat.setForeground(Qt::blue);
commentFormat.setForeground(Qt::red); commentFormat.setForeground(Qt::red);
stringFormat.setForeground(Qt::cyan); stringFormat.setForeground(Qt::darkGreen);
stringFormat.setFontWeight(QFont::Normal); stringFormat.setFontWeight(QFont::Normal);
const QString output_keywords[] = { const QString output_keywords[] = {
@ -202,11 +207,44 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
void Highlighter::highlightBlock(const QString &text) void Highlighter::highlightBlock(const QString &text)
{ {
auto style = QRegularExpression("^(fix|compute|dump|set)\\s+(\\w+)\\s+(\\S+)\\s+(\\S+)").match(text);
auto force = QRegularExpression("^(atom_style|pair_style|bond_style|angle_style|dihedral_style|improper_style|kspace_style)\\s+(\\S+)").match(text);
auto defs = QRegularExpression("^(group|variable)\\s+(\\S+)\\s+(\\S+)").match(text);
auto undo = QRegularExpression("^(unfix|uncompute|undump)\\s+(\\w+)").match(text);
bool do_style = true;
bool do_force = true;
bool do_defs = true;
bool do_undo = true;
for (const HighlightingRule &rule : qAsConst(highlightingRules)) { for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) { while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next(); QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format); // special treatment for fix/compute/dump styles etc.
if (style.hasMatch() && do_style) {
setFormat(style.capturedStart(1), style.capturedLength(1), defineFormat);
setFormat(style.capturedStart(2), style.capturedLength(2), numberFormat);
setFormat(style.capturedStart(3), style.capturedLength(3), stringFormat);
setFormat(style.capturedStart(4), style.capturedLength(4), runFormat);
do_style = false;
// special treatment for force styles styles
} else if (force.hasMatch() && do_force) {
setFormat(force.capturedStart(1), force.capturedLength(1), particleFormat);
setFormat(force.capturedStart(2), force.capturedLength(2), runFormat);
do_force = false;
// special treatment for undo commands
} else if (undo.hasMatch() && do_undo) {
setFormat(undo.capturedStart(1), undo.capturedLength(1), defineFormat);
setFormat(undo.capturedStart(2), undo.capturedLength(2), stringFormat);
do_undo = false;
// special treatment for some definitions
} else if (defs.hasMatch() && do_defs) {
setFormat(defs.capturedStart(1), defs.capturedLength(1), particleFormat);
setFormat(defs.capturedStart(2), defs.capturedLength(2), stringFormat);
setFormat(defs.capturedStart(3), defs.capturedLength(3), runFormat);
do_defs = false;
} else {
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

View File

@ -12,6 +12,7 @@
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#include "imageviewer.h" #include "imageviewer.h"
#include "lammpswrapper.h"
#include <QAction> #include <QAction>
#include <QDialogButtonBox> #include <QDialogButtonBox>
@ -25,15 +26,21 @@
#include <QMessageBox> #include <QMessageBox>
#include <QPalette> #include <QPalette>
#include <QPoint> #include <QPoint>
#include <QPushButton>
#include <QScreen> #include <QScreen>
#include <QScrollArea> #include <QScrollArea>
#include <QScrollBar> #include <QScrollBar>
#include <QSettings>
#include <QStatusBar> #include <QStatusBar>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWheelEvent> #include <QWheelEvent>
#include <QWidgetAction>
ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) : static const QString blank(" ");
QDialog(parent), imageLabel(new QLabel), scrollArea(new QScrollArea), menuBar(new QMenuBar)
ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) :
QDialog(parent), imageLabel(new QLabel), scrollArea(new QScrollArea), menuBar(new QMenuBar),
lammps(_lammps), group("all"), filename(fileName)
{ {
imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
@ -42,8 +49,6 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) :
scrollArea->setBackgroundRole(QPalette::Dark); scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setWidget(imageLabel); scrollArea->setWidget(imageLabel);
scrollArea->setMouseTracking(true);
scrollArea->installEventFilter(this);
scrollArea->setVisible(false); scrollArea->setVisible(false);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
@ -52,23 +57,72 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) :
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(menuBar);
auto *dossao = new QPushButton(QIcon(":/hd-img.png"), "");
dossao->setCheckable(true);
auto *doanti = new QPushButton(QIcon(":/antialias.png"), "");
doanti->setCheckable(true);
auto *dobox = new QPushButton(QIcon(":/system-box.png"), "");
dobox->setCheckable(true);
auto *doaxes = new QPushButton(QIcon(":/axes-img.png"), "");
doaxes->setCheckable(true);
auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), "");
auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), "");
auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), "");
auto *rotright = new QPushButton(QIcon(":/object-rotate-right.png"), "");
auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), "");
auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), "");
auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), "");
auto *combo = new QComboBox;
combo->setObjectName("group");
int ngroup = lammps->id_count("group");
char gname[64];
for (int i = 0; i < ngroup; ++i) {
lammps->id_name("group", i, gname, 64);
combo->addItem(gname);
}
QHBoxLayout *menuLayout = new QHBoxLayout;
menuLayout->addWidget(menuBar);
menuLayout->addWidget(dossao);
menuLayout->addWidget(doanti);
menuLayout->addWidget(dobox);
menuLayout->addWidget(doaxes);
menuLayout->addWidget(zoomin);
menuLayout->addWidget(zoomout);
menuLayout->addWidget(rotleft);
menuLayout->addWidget(rotright);
menuLayout->addWidget(rotup);
menuLayout->addWidget(rotdown);
menuLayout->addWidget(reset);
menuLayout->addWidget(new QLabel(" Group: "));
menuLayout->addWidget(combo);
connect(dossao, &QPushButton::released, this, &ImageViewer::toggle_ssao);
connect(doanti, &QPushButton::released, this, &ImageViewer::toggle_anti);
connect(dobox, &QPushButton::released, this, &ImageViewer::toggle_box);
connect(doaxes, &QPushButton::released, this, &ImageViewer::toggle_axes);
connect(zoomin, &QPushButton::released, this, &ImageViewer::do_zoom_in);
connect(zoomout, &QPushButton::released, this, &ImageViewer::do_zoom_out);
connect(rotleft, &QPushButton::released, this, &ImageViewer::do_rot_left);
connect(rotright, &QPushButton::released, this, &ImageViewer::do_rot_right);
connect(rotup, &QPushButton::released, this, &ImageViewer::do_rot_up);
connect(rotdown, &QPushButton::released, this, &ImageViewer::do_rot_down);
connect(reset, &QPushButton::released, this, &ImageViewer::reset_view);
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(change_group(int)));
mainLayout->addLayout(menuLayout);
mainLayout->addWidget(scrollArea); mainLayout->addWidget(scrollArea);
mainLayout->addWidget(buttonBox); mainLayout->addWidget(buttonBox);
setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).completeBaseName()); setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).fileName());
createActions(); createActions();
QImageReader reader(fileName); reset_view();
reader.setAutoTransform(true); dobox->setChecked(showbox);
const QImage newImage = reader.read(); doaxes->setChecked(showaxes);
if (newImage.isNull()) { dossao->setChecked(usessao);
QMessageBox::warning(this, QGuiApplication::applicationDisplayName(), doanti->setChecked(antialias);
tr("Cannot load %1: %2").arg(fileName, reader.errorString()));
return;
}
image = newImage;
imageLabel->setPixmap(QPixmap::fromImage(image));
scaleFactor = 1.0; scaleFactor = 1.0;
resize(image.width() + 20, image.height() + 50); resize(image.width() + 20, image.height() + 50);
@ -79,6 +133,181 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) :
setLayout(mainLayout); setLayout(mainLayout);
} }
void ImageViewer::reset_view()
{
QSettings settings;
settings.beginGroup("snapshot");
zoom = settings.value("zoom", 1.0).toDouble();
hrot = settings.value("hrot", 60).toInt();
vrot = settings.value("vrot", 30).toInt();
showbox = settings.value("box", true).toBool();
showaxes = settings.value("axes", false).toBool();
usessao = settings.value("ssao", false).toBool();
antialias = settings.value("antialias", false).toBool();
settings.endGroup();
// reset state of checkable push buttons and combo box (after main layout is set up)
auto *lo = layout();
if (lo) {
// grab layout manager for the top bar
lo = lo->itemAt(0)->layout();
// grab the first 4 buttons after the menu bar
auto *button = qobject_cast<QPushButton *>(lo->itemAt(1)->widget());
button->setChecked(usessao);
button = qobject_cast<QPushButton *>(lo->itemAt(2)->widget());
button->setChecked(antialias);
button = qobject_cast<QPushButton *>(lo->itemAt(3)->widget());
button->setChecked(showbox);
button = qobject_cast<QPushButton *>(lo->itemAt(4)->widget());
button->setChecked(showaxes);
// grab the last entry -> group selector
auto *cb = qobject_cast<QComboBox *>(lo->itemAt(lo->count() - 1)->widget());
cb->setCurrentText("all");
}
createImage();
}
void ImageViewer::toggle_ssao()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
usessao = !usessao;
button->setChecked(usessao);
createImage();
}
void ImageViewer::toggle_anti()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
antialias = !antialias;
button->setChecked(antialias);
createImage();
}
void ImageViewer::toggle_box()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
showbox = !showbox;
button->setChecked(showbox);
createImage();
}
void ImageViewer::toggle_axes()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
showaxes = !showaxes;
button->setChecked(showaxes);
createImage();
}
void ImageViewer::do_zoom_in()
{
zoom = zoom * 1.1;
if (zoom > 5.0) zoom = 5.0;
createImage();
}
void ImageViewer::do_zoom_out()
{
zoom = zoom / 1.1;
if (zoom < 0.5) zoom = 0.5;
createImage();
}
void ImageViewer::do_rot_left()
{
vrot -= 15;
if (vrot < -180) vrot += 360;
createImage();
}
void ImageViewer::do_rot_right()
{
vrot += 15;
if (vrot > 180) vrot -= 360;
createImage();
}
void ImageViewer::do_rot_down()
{
hrot -= 15;
if (hrot < 0) hrot += 360;
createImage();
}
void ImageViewer::do_rot_up()
{
hrot += 15;
if (hrot > 360) hrot -= 360;
createImage();
}
void ImageViewer::change_group(int idx)
{
QComboBox *box = findChild<QComboBox *>("group");
if (box) group = box->currentText();
createImage();
}
void ImageViewer::createImage()
{
QSettings settings;
QString dumpcmd = QString("write_dump ") + group + " image ";
QDir dumpdir(QDir::tempPath());
QFile dumpfile(dumpdir.absoluteFilePath(filename + ".ppm"));
dumpcmd += dumpfile.fileName();
settings.beginGroup("snapshot");
int aa = antialias ? 2 : 1;
int xsize = settings.value("xsize", 800).toInt() * aa;
int ysize = settings.value("ysize", 600).toInt() * aa;
int hhrot = (hrot > 180) ? 360 - hrot : hrot;
dumpcmd += blank + settings.value("color", "type").toString();
dumpcmd += blank + settings.value("diameter", "type").toString();
dumpcmd += QString(" size ") + QString::number(xsize) + blank + QString::number(ysize);
dumpcmd += QString(" zoom ") + QString::number(zoom);
lammps->command(dumpcmd.toLocal8Bit());
if (lammps->extract_setting("dimension") == 3) {
dumpcmd += QString(" view ") + QString::number(hhrot) + blank + QString::number(vrot);
}
if (usessao) dumpcmd += QString(" ssao yes 453983 0.75");
if (showbox)
dumpcmd += QString(" box yes 0.025");
else
dumpcmd += QString(" box no 0.0");
if (showaxes)
dumpcmd += QString(" axes yes 0.2 0.025");
else
dumpcmd += QString(" axes no 0.0 0.0");
dumpcmd += " modify boxcolor " + settings.value("boxcolor", "yellow").toString();
dumpcmd += " backcolor " + settings.value("background", "black").toString();
settings.endGroup();
lammps->command(dumpcmd.toLocal8Bit());
QImageReader reader(dumpfile.fileName());
reader.setAutoTransform(true);
const QImage newImage = reader.read();
if (newImage.isNull()) {
QMessageBox::warning(
this, QGuiApplication::applicationDisplayName(),
QString("Cannot load %1: %2").arg(dumpfile.fileName(), reader.errorString()));
return;
}
dumpfile.remove();
settings.beginGroup("snapshot");
xsize = settings.value("xsize", 800).toInt();
ysize = settings.value("ysize", 600).toInt();
settings.endGroup();
// scale back to achieve antialiasing
image = newImage.scaled(xsize, ysize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
imageLabel->setPixmap(QPixmap::fromImage(image));
}
void ImageViewer::saveAs() void ImageViewer::saveAs()
{ {
QString fileName = QFileDialog::getSaveFileName(this, "Save Image File As", QString(), QString fileName = QFileDialog::getSaveFileName(this, "Save Image File As", QString(),
@ -90,12 +319,12 @@ void ImageViewer::copy() {}
void ImageViewer::zoomIn() void ImageViewer::zoomIn()
{ {
scaleImage(1.1); scaleImage(1.25);
} }
void ImageViewer::zoomOut() void ImageViewer::zoomOut()
{ {
scaleImage(0.9); scaleImage(0.8);
} }
void ImageViewer::normalSize() void ImageViewer::normalSize()
@ -119,38 +348,44 @@ void ImageViewer::saveFile(const QString &fileName)
void ImageViewer::createActions() void ImageViewer::createActions()
{ {
QMenu *fileMenu = menuBar->addMenu(tr("&File")); QMenu *fileMenu = menuBar->addMenu("&File");
saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &ImageViewer::saveAs); saveAsAct = fileMenu->addAction("&Save As...", this, &ImageViewer::saveAs);
saveAsAct->setIcon(QIcon(":/document-save-as.png"));
saveAsAct->setEnabled(false); saveAsAct->setEnabled(false);
fileMenu->addSeparator(); fileMenu->addSeparator();
copyAct = fileMenu->addAction(tr("&Copy"), this, &ImageViewer::copy); copyAct = fileMenu->addAction("&Copy", this, &ImageViewer::copy);
copyAct->setIcon(QIcon(":/edit-copy.png"));
copyAct->setShortcut(QKeySequence::Copy); copyAct->setShortcut(QKeySequence::Copy);
copyAct->setEnabled(false); copyAct->setEnabled(false);
fileMenu->addSeparator(); fileMenu->addSeparator();
QAction *exitAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close); QAction *exitAct = fileMenu->addAction("&Close", this, &QWidget::close);
exitAct->setShortcut(tr("Ctrl+W")); exitAct->setIcon(QIcon(":/window-close.png"));
exitAct->setShortcut(QKeySequence::fromString("Ctrl+W"));
QMenu *viewMenu = menuBar->addMenu(tr("&View")); QMenu *viewMenu = menuBar->addMenu("&View");
zoomInAct = viewMenu->addAction(tr("Zoom &In (10%)"), this, &ImageViewer::zoomIn); zoomInAct = viewMenu->addAction("Image Zoom &In (25%)", this, &ImageViewer::zoomIn);
zoomInAct->setShortcut(QKeySequence::ZoomIn); zoomInAct->setShortcut(QKeySequence::ZoomIn);
zoomInAct->setIcon(QIcon(":/gtk-zoom-in.png"));
zoomInAct->setEnabled(false); zoomInAct->setEnabled(false);
zoomOutAct = viewMenu->addAction(tr("Zoom &Out (10%)"), this, &ImageViewer::zoomOut); zoomOutAct = viewMenu->addAction("Image Zoom &Out (25%)", this, &ImageViewer::zoomOut);
zoomOutAct->setShortcut(QKeySequence::ZoomOut); zoomOutAct->setShortcut(QKeySequence::ZoomOut);
zoomOutAct->setIcon(QIcon(":/gtk-zoom-out.png"));
zoomOutAct->setEnabled(false); zoomOutAct->setEnabled(false);
normalSizeAct = viewMenu->addAction(tr("&Normal Size"), this, &ImageViewer::normalSize); normalSizeAct = viewMenu->addAction("&Reset Image Size", this, &ImageViewer::normalSize);
normalSizeAct->setShortcut(tr("Ctrl+S")); normalSizeAct->setShortcut(QKeySequence::fromString("Ctrl+0"));
normalSizeAct->setIcon(QIcon(":/gtk-zoom-fit.png"));
normalSizeAct->setEnabled(false); normalSizeAct->setEnabled(false);
viewMenu->addSeparator(); viewMenu->addSeparator();
fitToWindowAct = viewMenu->addAction(tr("&Fit to Window"), this, &ImageViewer::fitToWindow); fitToWindowAct = viewMenu->addAction("&Fit to Window", this, &ImageViewer::fitToWindow);
fitToWindowAct->setEnabled(false); fitToWindowAct->setEnabled(false);
fitToWindowAct->setCheckable(true); fitToWindowAct->setCheckable(true);
fitToWindowAct->setShortcut(tr("Ctrl+F")); fitToWindowAct->setShortcut(QKeySequence::fromString("Ctrl+="));
} }
void ImageViewer::updateActions() void ImageViewer::updateActions()
@ -183,27 +418,6 @@ void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep() / 2))); int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep() / 2)));
} }
bool ImageViewer::eventFilter(QObject *, QEvent *event)
{
if (event->type() == QEvent::Wheel) {
wheelEvent((QWheelEvent *)event);
return true;
}
return false;
}
void ImageViewer::wheelEvent(QWheelEvent *event)
{
QPoint num = event->angleDelta();
if (!num.isNull()) {
if (num.y() > 0)
zoomIn();
else
zoomOut();
}
event->accept();
}
// Local Variables: // Local Variables:
// c-basic-offset: 4 // c-basic-offset: 4
// End: // End:

View File

@ -14,8 +14,10 @@
#ifndef IMAGEVIEWER_H #ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H #define IMAGEVIEWER_H
#include <QComboBox>
#include <QDialog> #include <QDialog>
#include <QImage> #include <QImage>
#include <QString>
class QAction; class QAction;
class QMenuBar; class QMenuBar;
@ -25,13 +27,15 @@ class QObject;
class QScrollArea; class QScrollArea;
class QScrollBar; class QScrollBar;
class QStatusBar; class QStatusBar;
class QWheelEvent; class LammpsWrapper;
class QComboBox;
class ImageViewer : public QDialog { class ImageViewer : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ImageViewer(const QString &fileName, QWidget *parent = nullptr); explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps,
QWidget *parent = nullptr);
private slots: private slots:
void saveAs(); void saveAs();
@ -41,14 +45,28 @@ private slots:
void normalSize(); void normalSize();
void fitToWindow(); void fitToWindow();
void reset_view();
void toggle_ssao();
void toggle_anti();
void toggle_box();
void toggle_axes();
void do_zoom_in();
void do_zoom_out();
void do_rot_left();
void do_rot_right();
void do_rot_up();
void do_rot_down();
void change_group(int);
public:
void createImage();
private: private:
void createActions(); void createActions();
void updateActions(); void updateActions();
void saveFile(const QString &fileName); void saveFile(const QString &fileName);
void scaleImage(double factor); void scaleImage(double factor);
void adjustScrollBar(QScrollBar *scrollBar, double factor); void adjustScrollBar(QScrollBar *scrollBar, double factor);
bool eventFilter(QObject *object, QEvent *event);
void wheelEvent(QWheelEvent *event);
private: private:
QImage image; QImage image;
@ -64,6 +82,13 @@ private:
QAction *zoomOutAct; QAction *zoomOutAct;
QAction *normalSizeAct; QAction *normalSizeAct;
QAction *fitToWindowAct; QAction *fitToWindowAct;
LammpsWrapper *lammps;
QString group;
QString filename;
int hrot, vrot;
double zoom;
bool showbox, showaxes, antialias, usessao;
}; };
#endif #endif

View File

@ -0,0 +1,11 @@
[Desktop Entry]
Version=1.0
Type=Application
Categories=Education;Science
MimeType=text/x-application-lammps
Exec=lammps-gui %f
Name=The LAMMPS GUI
Terminal=false
GenericName=LAMMPS MD Simulator GUI
Keywords=MD Simulation;LAMMPS;Molecular Dynamics;N-Body
Icon=lammps

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/x-application-lammps">
<comment>LAMMPS input file</comment>
<glob pattern="*.lmp"/>
<glob pattern="in.*"/>
</mime-type>
</mime-info>

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QList> #include <QList>
#include <QPair>
#include <QString> #include <QString>
#include <vector> #include <vector>
@ -24,6 +25,8 @@
// forward declarations // forward declarations
class GeneralTab;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { namespace Ui {
class LammpsGui; class LammpsGui;
@ -39,11 +42,13 @@ class Highlighter;
class StdCapture; class StdCapture;
class Preferences; class Preferences;
class ImageViewer; class ImageViewer;
class ChartWindow;
class LammpsGui : public QMainWindow { class LammpsGui : public QMainWindow {
Q_OBJECT Q_OBJECT
friend class CodeEditor; friend class CodeEditor;
friend class GeneralTab;
public: public:
LammpsGui(QWidget *parent = nullptr, const char *filename = nullptr); LammpsGui(QWidget *parent = nullptr, const char *filename = nullptr);
@ -52,12 +57,16 @@ public:
protected: protected:
void open_file(const QString &filename); void open_file(const QString &filename);
void write_file(const QString &filename); void write_file(const QString &filename);
void update_recents(const QString &filename = "");
void update_variables();
void start_lammps(); void start_lammps();
void run_done(); void run_done();
private slots: private slots:
void new_document(); void new_document();
void open(); void open();
void open_recent();
void start_exe();
void save(); void save();
void save_as(); void save_as();
void quit(); void quit();
@ -69,33 +78,44 @@ private slots:
void clear(); void clear();
void run_buffer(); void run_buffer();
void stop_run(); void stop_run();
void edit_variables();
void render_image();
void view_image(); void view_image();
void view_chart();
void view_log();
void about(); void about();
void help(); void help();
void manual(); void manual();
void howto();
void logupdate(); void logupdate();
void modified(); void modified();
void preferences(); void preferences();
void defaults(); void defaults();
private: protected:
Ui::LammpsGui *ui; Ui::LammpsGui *ui;
private:
Highlighter *highlighter; Highlighter *highlighter;
StdCapture *capturer; StdCapture *capturer;
QLabel *status; QLabel *status;
QPlainTextEdit *logwindow; QPlainTextEdit *logwindow;
ImageViewer *imagewindow; ImageViewer *imagewindow;
ChartWindow *chartwindow;
QTimer *logupdater; QTimer *logupdater;
QLabel *dirstatus; QLabel *dirstatus;
QProgressBar *progress; QProgressBar *progress;
Preferences *prefdialog; Preferences *prefdialog;
QLabel *lammpsstatus;
QString current_file; QString current_file;
QString current_dir; QString current_dir;
QList<QString> recent;
QList<QPair<QString, QString>> variables;
LammpsWrapper lammps; LammpsWrapper lammps;
std::string plugin_path; std::string plugin_path;
bool is_running; bool is_running;
QList<QString> recent_files;
std::vector<char *> lammps_args; std::vector<char *> lammps_args;
}; };
#endif // LAMMPSGUI_H #endif // LAMMPSGUI_H

View File

@ -1,6 +1,47 @@
<!DOCTYPE RCC><RCC version="1.0"> <RCC>
<qresource> <qresource prefix="/">
<file alias="Monospace.ttf">DejaVuSansMono.ttf</file> <file>lammps-icon-128x128.png</file>
<file>lammps-icon-128x128.png</file> <file>help_index.table</file>
</qresource> <file>system-help.png</file>
<file>help-browser.png</file>
<file>gtk-zoom-in.png</file>
<file>gtk-zoom-out.png</file>
<file>gtk-zoom-fit.png</file>
<file>edit-delete.png</file>
<file>object-rotate-right.png</file>
<file>object-rotate-left.png</file>
<file>gtk-go-up.png</file>
<file>gtk-go-down.png</file>
<file>document-save-as.png</file>
<file>document-open-recent.png</file>
<file>document-open.png</file>
<file>document-new.png</file>
<file>edit-undo.png</file>
<file>edit-redo.png</file>
<file>edit-paste.png</file>
<file>edit-cut.png</file>
<file>edit-copy.png</file>
<file>application-exit.png</file>
<file>utilities-terminal.png</file>
<file>x-office-drawing.png</file>
<file>document-save.png</file>
<file>document-revert.png</file>
<file>preferences-desktop.png</file>
<file>preferences-desktop-personal.png</file>
<file>preferences-desktop-font.png</file>
<file>help-faq.png</file>
<file>help-about.png</file>
<file>emblem-photos.png</file>
<file>process-stop.png</file>
<file>emblem-default.png</file>
<file>window-close.png</file>
<file>application-plot.png</file>
<file>application-calc.png</file>
<file>system-box.png</file>
<file>axes-img.png</file>
<file>hd-img.png</file>
<file>antialias.png</file>
<file>ovito.png</file>
<file>vmd.png</file>
</qresource>
</RCC> </RCC>

View File

@ -13,19 +13,13 @@
<property name="windowTitle"> <property name="windowTitle">
<string>LammpsGui</string> <string>LammpsGui</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="CodeEditor" name="textEdit">
<layout class="QHBoxLayout" name="horizontalLayout"> <property name="enabled">
<item> <bool>true</bool>
<widget class="CodeEditor" name="textEdit"> </property>
<property name="enabled"> <property name="acceptDrops">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="acceptDrops">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">
@ -33,7 +27,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>600</width>
<height>23</height> <height>24</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -41,8 +35,15 @@
<string>&amp;File</string> <string>&amp;File</string>
</property> </property>
<addaction name="actionNew"/> <addaction name="actionNew"/>
<addaction name="separator"/>
<addaction name="actionOpen"/> <addaction name="actionOpen"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="action_1"/>
<addaction name="action_2"/>
<addaction name="action_3"/>
<addaction name="action_4"/>
<addaction name="action_5"/>
<addaction name="separator"/>
<addaction name="actionSave"/> <addaction name="actionSave"/>
<addaction name="actionSave_As"/> <addaction name="actionSave_As"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -69,7 +70,11 @@
<addaction name="actionRun_Buffer"/> <addaction name="actionRun_Buffer"/>
<addaction name="actionStop_LAMMPS"/> <addaction name="actionStop_LAMMPS"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSet_Variables"/>
<addaction name="separator"/>
<addaction name="actionImage"/> <addaction name="actionImage"/>
<addaction name="actionView_in_OVITO"/>
<addaction name="actionView_in_VMD"/>
</widget> </widget>
<widget class="QMenu" name="menuAbout"> <widget class="QMenu" name="menuAbout">
<property name="title"> <property name="title">
@ -77,219 +82,162 @@
</property> </property>
<addaction name="actionAbout_LAMMPS_GUI"/> <addaction name="actionAbout_LAMMPS_GUI"/>
<addaction name="action_Help"/> <addaction name="action_Help"/>
<addaction name="actionLAMMPS_GUI_Howto"/>
<addaction name="actionLAMMPS_Manual"/> <addaction name="actionLAMMPS_Manual"/>
</widget> </widget>
<widget class="QMenu" name="menu_View">
<property name="title">
<string>&amp;View</string>
</property>
<addaction name="actionView_Log_Window"/>
<addaction name="actionView_Graph_Window"/>
<addaction name="actionView_Image_Window"/>
</widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuEdit"/> <addaction name="menuEdit"/>
<addaction name="menu_Run"/> <addaction name="menu_Run"/>
<addaction name="menu_View"/>
<addaction name="menuAbout"/> <addaction name="menuAbout"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
<action name="actionNew"> <action name="actionNew">
<property name="icon"> <property name="icon">
<iconset theme="document-new"> <iconset theme=":/document-new.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;New</string> <string>&amp;New</string>
</property> </property>
<property name="toolTip">
<string>Start a New Input File</string>
</property>
<property name="statusTip">
<string>Start a New Input File</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+N</string> <string>Ctrl+N</string>
</property> </property>
</action> </action>
<action name="actionOpen"> <action name="actionOpen">
<property name="icon"> <property name="icon">
<iconset theme="document-open"> <iconset theme=":/document-open.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Open</string> <string>&amp;Open</string>
</property> </property>
<property name="toolTip">
<string>Open an Input File</string>
</property>
<property name="statusTip">
<string>Open an Input File</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+O</string> <string>Ctrl+O</string>
</property> </property>
</action> </action>
<action name="actionSave"> <action name="actionSave">
<property name="icon"> <property name="icon">
<iconset theme="document-save"> <iconset theme=":/document-save.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Save</string> <string>&amp;Save</string>
</property> </property>
<property name="toolTip">
<string>Save Input File</string>
</property>
<property name="statusTip">
<string>Save Input File</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+S</string> <string>Ctrl+S</string>
</property> </property>
</action> </action>
<action name="actionSave_As"> <action name="actionSave_As">
<property name="icon"> <property name="icon">
<iconset theme="document-save-as"> <iconset theme=":/document-save-as.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Save &amp;As</string> <string>Save &amp;As</string>
</property> </property>
<property name="toolTip">
<string>Save Input File As...</string>
</property>
<property name="statusTip">
<string>Save Input File As...</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Shift+S</string> <string>Ctrl+Shift+S</string>
</property> </property>
</action> </action>
<action name="actionQuit"> <action name="actionQuit">
<property name="icon"> <property name="icon">
<iconset theme="application-exit"> <iconset theme=":/application-exit.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Quit</string> <string>&amp;Quit</string>
</property> </property>
<property name="toolTip">
<string>Quit LAMMPS-GUI</string>
</property>
<property name="statusTip">
<string>Quit LAMMPS-GUI</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Q</string> <string>Ctrl+Q</string>
</property> </property>
</action> </action>
<action name="actionCut"> <action name="actionCut">
<property name="icon"> <property name="icon">
<iconset theme="edit-cut"> <iconset theme=":/edit-cut.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Cu&amp;t</string> <string>Cu&amp;t</string>
</property> </property>
<property name="statusTip">
<string>Cut Selected Text to Clipboard</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+X</string> <string>Ctrl+X</string>
</property> </property>
</action> </action>
<action name="actionCopy"> <action name="actionCopy">
<property name="icon"> <property name="icon">
<iconset theme="edit-copy"> <iconset theme=":/edit-copy.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Copy</string> <string>&amp;Copy</string>
</property> </property>
<property name="statusTip">
<string>Copy Selected Text to Clipboard</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+C</string> <string>Ctrl+C</string>
</property> </property>
</action> </action>
<action name="actionPaste"> <action name="actionPaste">
<property name="icon"> <property name="icon">
<iconset theme="edit-paste"> <iconset theme=":/edit-paste.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Paste</string> <string>&amp;Paste</string>
</property> </property>
<property name="statusTip">
<string>Paste Text from Clipboard</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+V</string> <string>Ctrl+V</string>
</property> </property>
</action> </action>
<action name="actionUndo"> <action name="actionUndo">
<property name="icon"> <property name="icon">
<iconset theme="edit-undo"> <iconset theme=":/edit-undo.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Undo</string> <string>&amp;Undo</string>
</property> </property>
<property name="statusTip">
<string>Undo Edit</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Z</string> <string>Ctrl+Z</string>
</property> </property>
</action> </action>
<action name="actionRedo"> <action name="actionRedo">
<property name="icon"> <property name="icon">
<iconset theme="edit-redo"> <iconset theme=":/edit-redo.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Redo</string> <string>&amp;Redo</string>
</property> </property>
<property name="statusTip">
<string>Redo Edit</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Shift+Z</string> <string>Ctrl+Shift+Z</string>
</property> </property>
</action> </action>
<action name="actionRun_Buffer"> <action name="actionRun_Buffer">
<property name="icon"> <property name="icon">
<iconset theme="emblem-default"> <iconset theme=":/emblem-default.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Run LAMMPS</string> <string>&amp;Run LAMMPS</string>
</property> </property>
<property name="toolTip">
<string>Run LAMMPS with Input</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Return</string> <string>Ctrl+Return</string>
</property> </property>
</action> </action>
<action name="actionStop_LAMMPS"> <action name="actionStop_LAMMPS">
<property name="icon"> <property name="icon">
<iconset theme="process-stop"> <iconset theme=":/process-stop.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Stop LAMMPS</string> <string>&amp;Stop LAMMPS</string>
</property> </property>
<property name="toolTip">
<string>Stop LAMMPS Process</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+/</string> <string>Ctrl+/</string>
</property> </property>
</action> </action>
<action name="actionImage"> <action name="actionImage">
<property name="icon"> <property name="icon">
<iconset theme="emblem-photos"> <iconset theme=":/emblem-photos.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;View Snapshot</string> <string>View &amp;Image</string>
</property>
<property name="toolTip">
<string>View Snapshot of current LAMMPS state</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+I</string> <string>Ctrl+I</string>
@ -297,35 +245,29 @@
</action> </action>
<action name="actionAbout_LAMMPS_GUI"> <action name="actionAbout_LAMMPS_GUI">
<property name="icon"> <property name="icon">
<iconset theme="help-about"> <iconset theme=":/help-about.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;About LAMMPS-GUI</string> <string>&amp;About LAMMPS</string>
</property> </property>
<property name="toolTip"> <property name="shortcut">
<string>About LAMMPS-GUI</string> <string>Ctrl+Shift+A</string>
</property> </property>
</action> </action>
<action name="action_Help"> <action name="action_Help">
<property name="icon"> <property name="icon">
<iconset theme="help-faq"> <iconset theme=":/help-faq.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Quick &amp;Help</string> <string>Quick &amp;Help</string>
</property> </property>
<property name="toolTip">
<string>Quick Help</string>
</property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Shift+/</string> <string>Ctrl+Shift+H</string>
</property> </property>
</action> </action>
<action name="actionPreferences"> <action name="actionPreferences">
<property name="icon"> <property name="icon">
<iconset theme="preferences-desktop"> <iconset theme=":/preferences-desktop.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Pre&amp;ferences...</string> <string>Pre&amp;ferences...</string>
@ -336,21 +278,140 @@
</action> </action>
<action name="actionLAMMPS_Manual"> <action name="actionLAMMPS_Manual">
<property name="icon"> <property name="icon">
<iconset theme="help-browser"> <iconset theme=":/help-browser.png"/>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>LAMMPS &amp;Manual</string> <string>LAMMPS &amp;Manual</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+Shift+M</string>
</property>
</action> </action>
<action name="actionDefaults"> <action name="actionDefaults">
<property name="icon"> <property name="icon">
<iconset theme="document-revert"/> <iconset theme=":/document-revert.png"/>
</property> </property>
<property name="text"> <property name="text">
<string>Reset to &amp;Defaults</string> <string>Reset to &amp;Defaults</string>
</property> </property>
</action> </action>
<action name="actionView_in_OVITO">
<property name="icon">
<iconset theme=":/ovito.png"/>
</property>
<property name="text">
<string>View in &amp;OVITO</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+O</string>
</property>
</action>
<action name="actionView_in_VMD">
<property name="icon">
<iconset theme=":/vmd.png"/>
</property>
<property name="text">
<string>View in VM&amp;D</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+D</string>
</property>
</action>
<action name="actionView_Log_Window">
<property name="icon">
<iconset theme=":/utilities-terminal.png"/>
</property>
<property name="text">
<string>&amp;Log Window</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+L</string>
</property>
</action>
<action name="actionView_Graph_Window">
<property name="icon">
<iconset theme=":/x-office-drawing.png"/>
</property>
<property name="text">
<string>&amp;Chart Window</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+C</string>
</property>
</action>
<action name="action_1">
<property name="icon">
<iconset theme=":/document-open-recent.png"/>
</property>
<property name="text">
<string>&amp;1.</string>
</property>
</action>
<action name="action_2">
<property name="icon">
<iconset theme=":/document-open-recent.png"/>
</property>
<property name="text">
<string>&amp;2.</string>
</property>
</action>
<action name="action_3">
<property name="icon">
<iconset theme=":/document-open-recent.png"/>
</property>
<property name="text">
<string>&amp;3.</string>
</property>
</action>
<action name="action_4">
<property name="icon">
<iconset theme=":/document-open-recent.png"/>
</property>
<property name="text">
<string>&amp;4.</string>
</property>
</action>
<action name="action_5">
<property name="icon">
<iconset theme=":/document-open-recent.png"/>
</property>
<property name="text">
<string>&amp;5.</string>
</property>
</action>
<action name="actionView_Image_Window">
<property name="icon">
<iconset theme=":/emblem-photos.png"/>
</property>
<property name="text">
<string>&amp;Image Window</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+I</string>
</property>
</action>
<action name="actionSet_Variables">
<property name="icon">
<iconset theme=":/preferences-desktop-personal.png"/>
</property>
<property name="text">
<string>Set &amp;Variables...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+V</string>
</property>
</action>
<action name="actionLAMMPS_GUI_Howto">
<property name="icon">
<iconset theme=":/system-help.png"/>
</property>
<property name="text">
<string>LAMMPS GUI Howto</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+G</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -27,17 +27,17 @@ public:
// execute LAMMPS in runner thread // execute LAMMPS in runner thread
void run() override void run() override
{ {
lammps->command("clear");
lammps->commands_string(input); lammps->commands_string(input);
delete[] input; delete[] input;
emit resultReady(); emit resultReady();
} }
// transfer info to worker thread // transfer info to worker thread and reset LAMMPS instance
void setup_run(LammpsWrapper *_lammps, const char *_input) void setup_run(LammpsWrapper *_lammps, const char *_input)
{ {
lammps = _lammps; lammps = _lammps;
input = _input; input = _input;
lammps->command("clear");
} }
signals: signals:

View File

@ -23,13 +23,13 @@ LammpsWrapper::LammpsWrapper() : lammps_handle(nullptr), plugin_handle(nullptr)
void LammpsWrapper::open(int narg, char **args) void LammpsWrapper::open(int narg, char **args)
{ {
if (!lammps_handle) { // since there may only be one LAMMPS instance in LAMMPS GUI we don't open a second
if (lammps_handle) return;
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
lammps_handle = ((liblammpsplugin_t *)plugin_handle)->open_no_mpi(narg, args, nullptr); lammps_handle = ((liblammpsplugin_t *)plugin_handle)->open_no_mpi(narg, args, nullptr);
#else #else
lammps_handle = lammps_open_no_mpi(narg, args, nullptr); lammps_handle = lammps_open_no_mpi(narg, args, nullptr);
#endif #endif
}
} }
int LammpsWrapper::extract_setting(const char *keyword) int LammpsWrapper::extract_setting(const char *keyword)
@ -39,7 +39,33 @@ int LammpsWrapper::extract_setting(const char *keyword)
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->extract_setting(lammps_handle, keyword); val = ((liblammpsplugin_t *)plugin_handle)->extract_setting(lammps_handle, keyword);
#else #else
val = lammps_extract_setting(lammps_handle, keyword); val = lammps_extract_setting(lammps_handle, keyword);
#endif
}
return val;
}
int LammpsWrapper::id_count(const char *keyword)
{
int val = 0;
if (lammps_handle) {
#if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->id_count(lammps_handle, keyword);
#else
val = lammps_id_count(lammps_handle, keyword);
#endif
}
return val;
}
int LammpsWrapper::id_name(const char *keyword, int idx, char *buf, int len)
{
int val = 0;
if (lammps_handle) {
#if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->id_name(lammps_handle, keyword, idx, buf, len);
#else
val = lammps_id_name(lammps_handle, keyword, idx, buf, len);
#endif #endif
} }
return val; return val;
@ -52,12 +78,25 @@ double LammpsWrapper::get_thermo(const char *keyword)
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->get_thermo(lammps_handle, keyword); val = ((liblammpsplugin_t *)plugin_handle)->get_thermo(lammps_handle, keyword);
#else #else
val = lammps_get_thermo(lammps_handle, keyword); val = lammps_get_thermo(lammps_handle, keyword);
#endif #endif
} }
return val; return val;
} }
void *LammpsWrapper::last_thermo(const char *keyword, int index)
{
void *ptr = nullptr;
if (lammps_handle) {
#if defined(LAMMPS_GUI_USE_PLUGIN)
ptr = ((liblammpsplugin_t *)plugin_handle)->last_thermo(lammps_handle, keyword, index);
#else
ptr = lammps_last_thermo(lammps_handle, keyword, index);
#endif
}
return ptr;
}
bool LammpsWrapper::is_running() bool LammpsWrapper::is_running()
{ {
int val = 0; int val = 0;
@ -65,7 +104,7 @@ bool LammpsWrapper::is_running()
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->is_running(lammps_handle); val = ((liblammpsplugin_t *)plugin_handle)->is_running(lammps_handle);
#else #else
val = lammps_is_running(lammps_handle); val = lammps_is_running(lammps_handle);
#endif #endif
} }
return val != 0; return val != 0;
@ -103,6 +142,7 @@ bool LammpsWrapper::has_error() const
#endif #endif
} }
// may be called with null handle. returns global error then.
int LammpsWrapper::get_last_error_message(char *buf, int buflen) int LammpsWrapper::get_last_error_message(char *buf, int buflen)
{ {
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
@ -115,9 +155,9 @@ int LammpsWrapper::get_last_error_message(char *buf, int buflen)
void LammpsWrapper::force_timeout() void LammpsWrapper::force_timeout()
{ {
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
((liblammpsplugin_t *)plugin_handle)->force_timeout(lammps_handle); if (lammps_handle) ((liblammpsplugin_t *)plugin_handle)->force_timeout(lammps_handle);
#else #else
lammps_force_timeout(lammps_handle); if (lammps_handle) lammps_force_timeout(lammps_handle);
#endif #endif
} }
@ -188,7 +228,10 @@ bool LammpsWrapper::has_plugin() const
bool LammpsWrapper::load_lib(const char *libfile) bool LammpsWrapper::load_lib(const char *libfile)
{ {
if (plugin_handle) liblammpsplugin_release((liblammpsplugin_t *)plugin_handle); if (plugin_handle) {
close();
liblammpsplugin_release((liblammpsplugin_t *)plugin_handle);
}
plugin_handle = liblammpsplugin_load(libfile); plugin_handle = liblammpsplugin_load(libfile);
if (!plugin_handle) return false; if (!plugin_handle) return false;
if (((liblammpsplugin_t *)plugin_handle)->abiversion != LAMMPSPLUGIN_ABI_VERSION) { if (((liblammpsplugin_t *)plugin_handle)->abiversion != LAMMPSPLUGIN_ABI_VERSION) {

View File

@ -29,7 +29,11 @@ public:
void force_timeout(); void force_timeout();
int extract_setting(const char *keyword); int extract_setting(const char *keyword);
int id_count(const char *idtype);
int id_name(const char *idtype, int idx, char *buf, int buflen);
double get_thermo(const char *keyword); double get_thermo(const char *keyword);
void *last_thermo(const char *keyword, int idx);
bool is_open() const { return lammps_handle != nullptr; } bool is_open() const { return lammps_handle != nullptr; }
bool is_running(); bool is_running();
bool has_error() const; bool has_error() const;

View File

@ -0,0 +1,35 @@
/* ----------------------------------------------------------------------
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 "logwindow.h"
#include <QSettings>
LogWindow::LogWindow(QWidget *parent) : QPlainTextEdit(parent)
{
QSettings settings;
resize(settings.value("logx", 500).toInt(), settings.value("logy", 320).toInt());
}
void LogWindow::closeEvent(QCloseEvent *event)
{
QSettings settings;
if (!isMaximized()) {
settings.setValue("logx", width());
settings.setValue("logy", height());
}
QPlainTextEdit::closeEvent(event);
}
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -0,0 +1,32 @@
/* -*- 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 LOGWINDOW_H
#define LOGWINDOW_H
#include <QPlainTextEdit>
class LogWindow : public QPlainTextEdit {
Q_OBJECT
public:
LogWindow(QWidget *parent = nullptr);
protected:
void closeEvent(QCloseEvent *event) override;
};
#endif
// Local Variables:
// c-basic-offset: 4
// End:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
tools/lammps-gui/ovito.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -13,16 +13,22 @@
#include "preferences.h" #include "preferences.h"
#include "lammpsgui.h"
#include "lammpswrapper.h" #include "lammpswrapper.h"
#include "ui_lammpsgui.h"
#include <QApplication>
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDir> #include <QDir>
#include <QDoubleValidator> #include <QDoubleValidator>
#include <QFileDialog> #include <QFileDialog>
#include <QFontDialog>
#include <QGroupBox> #include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QIcon>
#include <QIntValidator> #include <QIntValidator>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
@ -38,10 +44,28 @@
#include <omp.h> #include <omp.h>
#endif #endif
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <process.h>
#define execl(exe, arg0, arg1) _execl(exe, arg0, arg1)
#else
#include <unistd.h>
#endif
// duplicate string
static char *mystrdup(const std::string &text)
{
auto tmp = new char[text.size() + 1];
memcpy(tmp, text.c_str(), text.size() + 1);
return tmp;
}
Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) : Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) :
QDialog(parent), tabWidget(new QTabWidget), QDialog(parent), tabWidget(new QTabWidget),
buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)), buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)),
settings(new QSettings), lammps(_lammps) settings(new QSettings), lammps(_lammps), need_relaunch(false)
{ {
tabWidget->addTab(new GeneralTab(settings, lammps), "&General Settings"); tabWidget->addTab(new GeneralTab(settings, lammps), "&General Settings");
tabWidget->addTab(new AcceleratorTab(settings, lammps), "&Accelerators"); tabWidget->addTab(new AcceleratorTab(settings, lammps), "&Accelerators");
@ -94,7 +118,7 @@ void Preferences::accept()
if (field) if (field)
if (field->hasAcceptableInput()) settings->setValue("nthreads", field->text()); if (field->hasAcceptableInput()) settings->setValue("nthreads", field->text());
// store image width, height, and zoom // store image width, height, zoom, and rendering settings
settings->beginGroup("snapshot"); settings->beginGroup("snapshot");
field = tabWidget->findChild<QLineEdit *>("xsize"); field = tabWidget->findChild<QLineEdit *>("xsize");
@ -106,14 +130,46 @@ void Preferences::accept()
field = tabWidget->findChild<QLineEdit *>("zoom"); field = tabWidget->findChild<QLineEdit *>("zoom");
if (field) if (field)
if (field->hasAcceptableInput()) settings->setValue("zoom", field->text()); if (field->hasAcceptableInput()) settings->setValue("zoom", field->text());
QCheckBox *box = tabWidget->findChild<QCheckBox *>("anti");
if (box) settings->setValue("antialias", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("ssao");
if (box) settings->setValue("ssao", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("box");
if (box) settings->setValue("box", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("axes");
if (box) settings->setValue("axes", box->isChecked());
QComboBox *combo = tabWidget->findChild<QComboBox *>("background");
if (combo) settings->setValue("background", combo->currentText());
combo = tabWidget->findChild<QComboBox *>("boxcolor");
if (combo) settings->setValue("boxcolor", combo->currentText());
settings->endGroup(); settings->endGroup();
// general settings // general settings
QCheckBox *box = tabWidget->findChild<QCheckBox *>("echo"); box = tabWidget->findChild<QCheckBox *>("echo");
if (box) settings->setValue("echo", box->isChecked() ? "1" : "0"); if (box) settings->setValue("echo", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("cite"); box = tabWidget->findChild<QCheckBox *>("cite");
if (box) settings->setValue("cite", box->isChecked() ? "1" : "0"); if (box) settings->setValue("cite", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("logreplace");
if (box) settings->setValue("logreplace", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("chartreplace");
if (box) settings->setValue("chartreplace", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("imagereplace");
if (box) settings->setValue("imagereplace", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("viewlog");
if (box) settings->setValue("viewlog", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("viewchart");
if (box) settings->setValue("viewchart", box->isChecked());
if (need_relaunch) {
QMessageBox msg(QMessageBox::Information, QString("Relaunching LAMMPS-GUI"),
QString("LAMMPS library plugin path was changed.\n"
"LAMMPS-GUI must be relaunched."),
QMessageBox::Ok);
msg.exec();
const char *path = mystrdup(QCoreApplication::applicationFilePath().toStdString());
const char *arg0 = mystrdup(QCoreApplication::arguments().at(0).toStdString());
execl(path, arg0, (char *)NULL);
}
QDialog::accept(); QDialog::accept();
} }
@ -123,21 +179,29 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa
auto *layout = new QVBoxLayout; auto *layout = new QVBoxLayout;
auto *echo = new QCheckBox("Echo input to log"); auto *echo = new QCheckBox("Echo input to log");
echo->setCheckState(settings->value("echo", "0").toInt() ? Qt::Checked : Qt::Unchecked);
echo->setObjectName("echo"); echo->setObjectName("echo");
auto *cite = new QCheckBox("Include Citations"); echo->setCheckState(settings->value("echo", false).toBool() ? Qt::Checked : Qt::Unchecked);
cite->setCheckState(settings->value("cite", "0").toInt() ? Qt::Checked : Qt::Unchecked); auto *cite = new QCheckBox("Include citation details");
cite->setObjectName("cite"); cite->setObjectName("cite");
#if !defined(__APPLE__) cite->setCheckState(settings->value("cite", false).toBool() ? Qt::Checked : Qt::Unchecked);
auto *tmplabel = new QLabel("Scratch Folder:"); auto *logv = new QCheckBox("Show log window by default");
auto *tmpedit = new QLineEdit(settings->value("tempdir", ".").toString()); logv->setObjectName("viewlog");
auto *tmpbrowse = new QPushButton("Browse..."); logv->setCheckState(settings->value("viewlog", true).toBool() ? Qt::Checked : Qt::Unchecked);
auto *tmplayout = new QHBoxLayout; auto *pltv = new QCheckBox("Show chart window by default");
tmpedit->setObjectName("tmpedit"); pltv->setObjectName("viewchart");
tmplayout->addWidget(tmplabel); pltv->setCheckState(settings->value("viewchart", true).toBool() ? Qt::Checked : Qt::Unchecked);
tmplayout->addWidget(tmpedit); auto *logr = new QCheckBox("Replace log window on new run");
tmplayout->addWidget(tmpbrowse); logr->setObjectName("logreplace");
#endif logr->setCheckState(settings->value("logreplace", false).toBool() ? Qt::Checked
: Qt::Unchecked);
auto *imgr = new QCheckBox("Replace image window on new render");
imgr->setObjectName("imagereplace");
imgr->setCheckState(settings->value("imagereplace", false).toBool() ? Qt::Checked
: Qt::Unchecked);
auto *pltr = new QCheckBox("Replace chart window on new run");
pltr->setObjectName("chartreplace");
pltr->setCheckState(settings->value("chartreplace", false).toBool() ? Qt::Checked
: Qt::Unchecked);
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
auto *pluginlabel = new QLabel("Path to LAMMPS Shared Library File:"); auto *pluginlabel = new QLabel("Path to LAMMPS Shared Library File:");
@ -151,25 +215,69 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa
connect(pluginbrowse, &QPushButton::released, this, &GeneralTab::pluginpath); connect(pluginbrowse, &QPushButton::released, this, &GeneralTab::pluginpath);
#endif #endif
auto *fontlayout = new QHBoxLayout;
auto *getallfont =
new QPushButton(QIcon(":/preferences-desktop-font.png"), "Select Default Font...");
auto *gettextfont =
new QPushButton(QIcon(":/preferences-desktop-font.png"), "Select Text Font...");
fontlayout->addWidget(getallfont);
fontlayout->addWidget(gettextfont);
connect(getallfont, &QPushButton::released, this, &GeneralTab::newallfont);
connect(gettextfont, &QPushButton::released, this, &GeneralTab::newtextfont);
layout->addWidget(echo); layout->addWidget(echo);
layout->addWidget(cite); layout->addWidget(cite);
#if !defined(__APPLE__) layout->addWidget(logv);
layout->addLayout(tmplayout); layout->addWidget(pltv);
#endif layout->addWidget(logr);
layout->addWidget(pltr);
layout->addWidget(imgr);
#if defined(LAMMPS_GUI_USE_PLUGIN) #if defined(LAMMPS_GUI_USE_PLUGIN)
layout->addWidget(pluginlabel); layout->addWidget(pluginlabel);
layout->addLayout(pluginlayout); layout->addLayout(pluginlayout);
#endif #endif
layout->addLayout(fontlayout);
layout->addStretch(1); layout->addStretch(1);
setLayout(layout); setLayout(layout);
} }
void GeneralTab::newtmpfolder() void GeneralTab::updatefonts(const QFont &all, const QFont &text)
{ {
QLineEdit *field = findChild<QLineEdit *>("tmpedit"); LammpsGui *main;
QString tmpdir = for (QWidget *widget : QApplication::topLevelWidgets())
QFileDialog::getExistingDirectory(this, "Find Folder for Temporary Files", field->text()); if (widget->objectName() == "LammpsGui") main = dynamic_cast<LammpsGui *>(widget);
if (!tmpdir.isEmpty()) field->setText(tmpdir);
QApplication::setFont(all);
main->ui->textEdit->document()->setDefaultFont(text);
}
void GeneralTab::newallfont()
{
QSettings settings;
QFont all, text;
all.fromString(settings.value("allfont", "").toString());
text.fromString(settings.value("textfont", "").toString());
bool ok = false;
QFont font = QFontDialog::getFont(&ok, all, this, QString("Select Default Font"));
if (ok) updatefonts(font, text);
settings.setValue("allfont", font.toString());
}
void GeneralTab::newtextfont()
{
QSettings settings;
QFont all, text;
all.fromString(settings.value("allfont", "").toString());
text.fromString(settings.value("textfont", "").toString());
bool ok = false;
QFont font = QFontDialog::getFont(&ok, text, this, QString("Select Text Font"));
if (ok) updatefonts(all, font);
settings.setValue("textfont", font.toString());
} }
void GeneralTab::pluginpath() void GeneralTab::pluginpath()
@ -179,16 +287,11 @@ void GeneralTab::pluginpath()
QFileDialog::getOpenFileName(this, "Select Shared LAMMPS Library to Load", field->text(), QFileDialog::getOpenFileName(this, "Select Shared LAMMPS Library to Load", field->text(),
"Shared Objects (*.so *.dll *.dylib)"); "Shared Objects (*.so *.dll *.dylib)");
if (!pluginfile.isEmpty() && pluginfile.contains("liblammps", Qt::CaseSensitive)) { if (!pluginfile.isEmpty() && pluginfile.contains("liblammps", Qt::CaseSensitive)) {
if (lammps->load_lib(pluginfile.toStdString().c_str())) { auto canonical = QFileInfo(pluginfile).canonicalFilePath();
auto canonical = QFileInfo(pluginfile).canonicalFilePath(); field->setText(pluginfile);
field->setText(pluginfile); settings->setValue("plugin_path", canonical);
settings->setValue("plugin_path", canonical); // ugly hack
} else { qobject_cast<Preferences *>(parent()->parent()->parent())->need_relaunch = true;
// plugin did not load cannot continue
settings->remove("plugin_path");
QMessageBox::critical(this, "Error", "Cannot open LAMMPS shared library file");
QCoreApplication::quit();
}
} }
} }
@ -288,11 +391,28 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
auto *xsize = new QLabel("Image width:"); auto *xsize = new QLabel("Image width:");
auto *ysize = new QLabel("Image height:"); auto *ysize = new QLabel("Image height:");
auto *zoom = new QLabel("Zoom factor:"); auto *zoom = new QLabel("Zoom factor:");
auto *anti = new QLabel("Antialias:");
auto *ssao = new QLabel("HQ Image mode:");
auto *bbox = new QLabel("Show Box:");
auto *axes = new QLabel("Show Axes:");
auto *cback = new QLabel("Background Color:");
auto *cbox = new QLabel("Box Color:");
settings->beginGroup("snapshot"); settings->beginGroup("snapshot");
auto *xval = new QLineEdit(settings->value("xsize", "800").toString()); auto *xval = new QLineEdit(settings->value("xsize", "800").toString());
auto *yval = new QLineEdit(settings->value("ysize", "600").toString()); auto *yval = new QLineEdit(settings->value("ysize", "600").toString());
auto *zval = new QLineEdit(settings->value("zoom", "1.0").toString()); auto *zval = new QLineEdit(settings->value("zoom", "1.0").toString());
settings->endGroup(); auto *aval = new QCheckBox;
auto *sval = new QCheckBox;
auto *bval = new QCheckBox;
auto *eval = new QCheckBox;
sval->setCheckState(settings->value("ssao", false).toBool() ? Qt::Checked : Qt::Unchecked);
sval->setObjectName("ssao");
aval->setCheckState(settings->value("antialias", false).toBool() ? Qt::Checked : Qt::Unchecked);
aval->setObjectName("anti");
bval->setCheckState(settings->value("box", true).toBool() ? Qt::Checked : Qt::Unchecked);
bval->setObjectName("box");
eval->setCheckState(settings->value("axes", false).toBool() ? Qt::Checked : Qt::Unchecked);
eval->setObjectName("axes");
auto *intval = new QIntValidator(100, 100000, this); auto *intval = new QIntValidator(100, 100000, this);
xval->setValidator(intval); xval->setValidator(intval);
@ -302,15 +422,48 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
zval->setValidator(new QDoubleValidator(0.01, 100.0, 100, this)); zval->setValidator(new QDoubleValidator(0.01, 100.0, 100, this));
zval->setObjectName("zoom"); zval->setObjectName("zoom");
auto *background = new QComboBox;
background->setObjectName("background");
background->addItem("black");
background->addItem("darkgray");
background->addItem("gray");
background->addItem("silver");
background->addItem("white");
background->setCurrentText(settings->value("background", "black").toString());
auto *boxcolor = new QComboBox;
boxcolor->setObjectName("boxcolor");
boxcolor->addItem("yellow");
boxcolor->addItem("silver");
boxcolor->addItem("gray");
boxcolor->addItem("darkred");
boxcolor->addItem("darkgreen");
boxcolor->addItem("darkblue");
boxcolor->setCurrentText(settings->value("boxcolor", "yellow").toString());
settings->endGroup();
grid->addWidget(xsize, 0, 0, Qt::AlignTop); grid->addWidget(xsize, 0, 0, Qt::AlignTop);
grid->addWidget(ysize, 1, 0, Qt::AlignTop); grid->addWidget(ysize, 1, 0, Qt::AlignTop);
grid->addWidget(zoom, 2, 0, Qt::AlignTop); grid->addWidget(zoom, 2, 0, Qt::AlignTop);
grid->addWidget(anti, 3, 0, Qt::AlignTop);
grid->addWidget(ssao, 4, 0, Qt::AlignTop);
grid->addWidget(bbox, 5, 0, Qt::AlignTop);
grid->addWidget(axes, 6, 0, Qt::AlignTop);
grid->addWidget(cback, 7, 0, Qt::AlignTop);
grid->addWidget(cbox, 8, 0, Qt::AlignTop);
grid->addWidget(xval, 0, 1, Qt::AlignTop); grid->addWidget(xval, 0, 1, Qt::AlignTop);
grid->addWidget(yval, 1, 1, Qt::AlignTop); grid->addWidget(yval, 1, 1, Qt::AlignTop);
grid->addWidget(zval, 2, 1, Qt::AlignTop); grid->addWidget(zval, 2, 1, Qt::AlignTop);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 0); grid->addWidget(aval, 3, 1, Qt::AlignTop);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 1); grid->addWidget(sval, 4, 1, Qt::AlignVCenter);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 3, 2); grid->addWidget(bval, 5, 1, Qt::AlignVCenter);
grid->addWidget(eval, 6, 1, Qt::AlignVCenter);
grid->addWidget(background, 7, 1, Qt::AlignVCenter);
grid->addWidget(boxcolor, 8, 1, Qt::AlignVCenter);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 0);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 1);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 9, 2);
setLayout(grid); setLayout(grid);
} }

View File

@ -17,6 +17,7 @@
#include <QDialog> #include <QDialog>
class QDialogButtonBox; class QDialogButtonBox;
class QFont;
class QSettings; class QSettings;
class QTabWidget; class QTabWidget;
class LammpsWrapper; class LammpsWrapper;
@ -31,6 +32,8 @@ public:
private slots: private slots:
void accept() override; void accept() override;
public:
bool need_relaunch;
private: private:
QTabWidget *tabWidget; QTabWidget *tabWidget;
QDialogButtonBox *buttonBox; QDialogButtonBox *buttonBox;
@ -48,9 +51,11 @@ public:
private slots: private slots:
void pluginpath(); void pluginpath();
void newtmpfolder(); void newallfont();
void newtextfont();
private: private:
void updatefonts(const QFont &all, const QFont &text);
QSettings *settings; QSettings *settings;
LammpsWrapper *lammps; LammpsWrapper *lammps;
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,124 @@
/* ----------------------------------------------------------------------
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 "setvariables.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSizePolicy>
SetVariables::SetVariables(QList<QPair<QString, QString>> &_vars, QWidget *parent) :
QDialog(parent), vars(_vars), layout(new QVBoxLayout)
{
auto *top = new QLabel("Set Variables:");
layout->addWidget(top, 0, Qt::AlignHCenter);
int i = 1;
for (const auto &v : vars) {
auto *row = new QHBoxLayout;
auto *name = new QLineEdit(v.first);
auto *val = new QLineEdit(v.second);
auto *del = new QPushButton(QIcon(":/edit-delete.png"), "");
name->setObjectName("varname");
val->setObjectName("varval");
del->setObjectName(QString::number(i));
connect(del, &QPushButton::released, this, &SetVariables::del_row);
row->addWidget(name);
row->addWidget(val);
row->addWidget(del);
layout->addLayout(row);
++i;
}
layout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding));
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *add = new QPushButton("&Add Row");
add->setObjectName("add_row");
buttonBox->addButton(add, QDialogButtonBox::ActionRole);
connect(add, &QPushButton::released, this, &SetVariables::add_row);
connect(buttonBox, &QDialogButtonBox::accepted, this, &SetVariables::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(buttonBox);
setLayout(layout);
setWindowTitle("LAMMPS-GUI - Set Variables");
resize(300, 200);
}
void SetVariables::accept()
{
// store all data in variables class and then confirm accepting
vars.clear();
int nrows = layout->count() - 2;
for (int i = 1; i < nrows; ++i) {
auto *row = layout->itemAt(i)->layout();
auto *var = dynamic_cast<QLineEdit *>(row->itemAt(0)->widget());
auto *val = dynamic_cast<QLineEdit *>(row->itemAt(1)->widget());
if (var && val) vars.append(qMakePair(var->text(), val->text()));
}
QDialog::accept();
}
void SetVariables::add_row()
{
int nrows = layout->count();
auto *row = new QHBoxLayout;
auto *name = new QLineEdit(QString());
auto *val = new QLineEdit(QString());
auto *del = new QPushButton(QIcon(":/edit-delete.png"), "");
name->setObjectName("varname");
val->setObjectName("varval");
del->setObjectName(QString::number(nrows - 2));
connect(del, &QPushButton::released, this, &SetVariables::del_row);
row->addWidget(name);
row->addWidget(val);
row->addWidget(del);
layout->insertLayout(nrows - 2, row);
}
void SetVariables::del_row()
{
int nrows = layout->count();
auto *who = sender();
if (who) {
// figure out which row was deleted and delete its layout and widgets
int delrow = who->objectName().toInt();
auto *row = layout->takeAt(delrow);
while (row->layout()->count() > 0) {
auto *item = row->layout()->takeAt(0);
if (item) {
row->layout()->removeItem(item);
delete item->widget();
delete item;
}
}
layout->removeItem(row);
delete row->layout();
// renumber the delete pushbutton names
for (int i = delrow; i < nrows - 3; ++i) {
auto *row = layout->itemAt(i)->layout();
auto *widget = row->itemAt(2)->widget();
widget->setObjectName(QString::number(i));
}
}
}
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -0,0 +1,43 @@
/* -*- 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 SET_VARIABLES_H
#define SET_VARIABLES_H
#include <QDialog>
#include <QList>
#include <QPair>
#include <QString>
class SetVariables : public QDialog {
Q_OBJECT
public:
explicit SetVariables(QList<QPair<QString, QString>> &vars, QWidget *parent = nullptr);
~SetVariables() = default;
private slots:
void accept() override;
void add_row();
void del_row();
private:
QList<QPair<QString, QString>> &vars;
class QVBoxLayout *layout;
};
#endif
// Local Variables:
// c-basic-offset: 4
// End:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,4 @@
#!/bin/sh
# this updates the help index table
grep '\.\. index::' ../../doc/src/*.rst | sort | sed -e 's/^.*src\/\([^/]\+\)\.rst:/\1.html /' -e 's/\.\. \+index:: \+//' > help_index.table

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
tools/lammps-gui/vmd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB