Merge pull request #3910 from akohlmey/add-slideshow

Add slideshow feature to LAMMPS GUI
This commit is contained in:
Axel Kohlmeyer
2023-08-31 21:35:45 -04:00
committed by GitHub
40 changed files with 824 additions and 444 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -17,7 +17,7 @@
<key>CFBundleLongVersionString</key> <key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string> <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>LAMMPS</string> <string>LAMMPS_GUI</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>

View File

@ -9,7 +9,7 @@ of the available packages.
The following individual commands are included: The following individual commands are included:
binary2txt lammps-gui lmp msi2lmp phana stl_bin2txt binary2txt lammps-gui lmp msi2lmp phana stl_bin2txt
After copying the lammps-gui folder into your Applications folder, please follow After copying the LAMMPS_GUI folder into your Applications folder, please follow
these steps: these steps:
1. Open the Terminal app 1. Open the Terminal app
@ -23,7 +23,7 @@ these steps:
3. Add the following lines to the end of the file, save it, and close the editor 3. Add the following lines to the end of the file, save it, and close the editor
LAMMPS_INSTALL_DIR=/Applications/LAMMPS.app/Contents LAMMPS_INSTALL_DIR=/Applications/LAMMPS_GUI.app/Contents
LAMMPS_POTENTIALS=${LAMMPS_INSTALL_DIR}/share/lammps/potentials LAMMPS_POTENTIALS=${LAMMPS_INSTALL_DIR}/share/lammps/potentials
LAMMPS_BENCH_DIR=${LAMMPS_INSTALL_DIR}/share/lammps/bench LAMMPS_BENCH_DIR=${LAMMPS_INSTALL_DIR}/share/lammps/bench
MSI2LMP_LIBRARY=${LAMMPS_INSTALL_DIR}/share/lammps/frc_files MSI2LMP_LIBRARY=${LAMMPS_INSTALL_DIR}/share/lammps/frc_files
@ -38,9 +38,9 @@ these steps:
the changes from .zprofile automatically. the changes from .zprofile automatically.
Note: the above assumes you use the default shell (zsh) that comes with Note: the above assumes you use the default shell (zsh) that comes with
MacOS. If you customized MacOS to use a different shell, you'll need to modify MacOS. If you customized MacOS to use a different shell, you'll need to
that shell's init file (.cshrc, .bashrc, etc.) instead with appropiate commands modify that shell's init file (.cshrc, .bashrc, etc.) instead with
to modify the same environment variables. appropiate commands to modify the same environment variables.
5. Try running LAMMPS (which might fail, see step 7) 5. Try running LAMMPS (which might fail, see step 7)
@ -50,10 +50,10 @@ these steps:
lammps-gui ${LAMMPS_BENCH_DIR}/in.rhodo lammps-gui ${LAMMPS_BENCH_DIR}/in.rhodo
Depending on the size and resolution of your screen, the fonts may Depending on the size and resolution of your screen, the fonts may be too
be too small to read. This can be adjusted by setting the environment small to read. This can be adjusted by setting the environment variable
variable QT_FONT_DPI. The default value would be 72, so to increase QT_FONT_DPI. The default value would be 72, so to increase the fonts by a
the fonts by a third one can add to the .zprofile file the line third, one can add to the .zprofile file the line
export QT_FONT_DPI=96 export QT_FONT_DPI=96
@ -61,9 +61,9 @@ these steps:
7. Give permission to execute the commands (lmp, lammps-gui, msi2lmp, binary2txt, phana, stl_bin2txt) 7. Give permission to execute the commands (lmp, lammps-gui, msi2lmp, binary2txt, phana, stl_bin2txt)
MacOS will likely block the initial run of the executables, since they MacOS will likely block the initial run of the executables, since they were
were downloaded from the internet and are missing a known signature from an downloaded from the internet and are missing a known signature from an
identified developer. Go to "Settings" and search for "Security settings". It identified developer. Go to "Settings" and search for "Security settings".
should display a message that an executable like "lmp" was blocked. Press It should display a message that an executable like "lmp" was blocked. Press
"Open anyway", which might prompt you for your admin credentials. Afterwards "Open anyway", which might prompt you for your admin credentials. Afterwards
"lmp" and the other executables should work as expected. "lmp" and the other executables should work as expected.

View File

@ -4,7 +4,7 @@ APP_NAME=lammps-gui
DESTDIR=${PWD}/../LAMMPS_GUI DESTDIR=${PWD}/../LAMMPS_GUI
echo "Delete old files, if they exist" echo "Delete old files, if they exist"
rm -rf ${DESTDIR} ../LAMMPS-Linux-amd64.tar.gz rm -rf ${DESTDIR} ../LAMMPS_GUI-Linux-amd64.tar.gz
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 "/"
@ -69,7 +69,7 @@ do \
done done
pushd .. pushd ..
tar -czvvf LAMMPS-Linux-amd64.tar.gz LAMMPS_GUI tar -czvvf LAMMPS_GUI-Linux-amd64.tar.gz LAMMPS_GUI
popd popd
echo "Cleanup dir" echo "Cleanup dir"

View File

@ -3,7 +3,7 @@
APP_NAME=lammps-gui APP_NAME=lammps-gui
echo "Delete old files, if they exist" echo "Delete old files, if they exist"
rm -f ${APP_NAME}.dmg ${APP_NAME}-rw.dmg LAMMPS-macOS-multiarch.dmg rm -f ${APP_NAME}.dmg ${APP_NAME}-rw.dmg LAMMPS_GUI-macOS-multiarch.dmg
echo "Create initial dmg file with macdeployqt" echo "Create initial dmg file with macdeployqt"
macdeployqt lammps-gui.app -dmg macdeployqt lammps-gui.app -dmg
@ -22,8 +22,8 @@ ln -s /Applications .
mv ${APP_NAME}.app/Contents/Resources/README.txt . mv ${APP_NAME}.app/Contents/Resources/README.txt .
mkdir .background mkdir .background
mv ${APP_NAME}.app/Contents/Resources/LAMMPS_DMG_Background.png .background/background.png mv ${APP_NAME}.app/Contents/Resources/LAMMPS_DMG_Background.png .background/background.png
mv ${APP_NAME}.app LAMMPS.app mv ${APP_NAME}.app LAMMPS_GUI.app
cd LAMMPS.app/Contents cd LAMMPS_GUI.app/Contents
echo "Attach icons to LAMMPS console and GUI executables" echo "Attach icons to LAMMPS console and GUI executables"
echo "read 'icns' (-16455) \"Resources/lammps.icns\";" > icon.rsrc echo "read 'icns' (-16455) \"Resources/lammps.icns\";" > icon.rsrc
@ -75,7 +75,7 @@ echo '
set statusbar visible to false set statusbar visible to false
set toolbar visible to false set toolbar visible to false
set the bounds to { 100, 40, 868, 640 } set the bounds to { 100, 40, 868, 640 }
set position of item "'LAMMPS'.app" to { 190, 216 } set position of item "'LAMMPS_GUI'.app" to { 190, 216 }
set position of item "Applications" to { 576, 216 } set position of item "Applications" to { 576, 216 }
set position of item "README.txt" to { 190, 400 } set position of item "README.txt" to { 190, 400 }
end tell end tell
@ -96,12 +96,12 @@ sync
echo "Unmount modified disk image and convert to compressed read-only image" echo "Unmount modified disk image and convert to compressed read-only image"
hdiutil detach "${DEVICE}" hdiutil detach "${DEVICE}"
hdiutil convert "${APP_NAME}-rw.dmg" -format UDZO -o "LAMMPS-macOS-multiarch.dmg" hdiutil convert "${APP_NAME}-rw.dmg" -format UDZO -o "LAMMPS_GUI-macOS-multiarch.dmg"
echo "Attach icon to .dmg file" echo "Attach icon to .dmg file"
echo "read 'icns' (-16455) \"lammps-gui.app/Contents/Resources/lammps.icns\";" > icon.rsrc echo "read 'icns' (-16455) \"lammps-gui.app/Contents/Resources/lammps.icns\";" > icon.rsrc
Rez -a icon.rsrc -o LAMMPS-macOS-multiarch.dmg Rez -a icon.rsrc -o LAMMPS_GUI-macOS-multiarch.dmg
SetFile -a C LAMMPS-macOS-multiarch.dmg SetFile -a C LAMMPS_GUI-macOS-multiarch.dmg
rm icon.rsrc rm icon.rsrc
echo "Delete temporary disk images" echo "Delete temporary disk images"

View File

@ -1,7 +1,7 @@
# CMake script to be run post installation to build zipped package # CMake script to be run post installation to build zipped package
# clean up old zipfile and deployment tree # clean up old zipfile and deployment tree
file(REMOVE LAMMPS-Win10-amd64.zip) file(REMOVE LAMMPS_GUI-Win10-amd64.zip)
file(REMOVE_RECURSE LAMMPS_GUI) file(REMOVE_RECURSE LAMMPS_GUI)
file(RENAME ${INSTNAME} LAMMPS_GUI) file(RENAME ${INSTNAME} LAMMPS_GUI)
@ -22,7 +22,7 @@ execute_process(COMMAND cmd.exe /c qtdeploy.bat COMMAND_ECHO STDERR)
file(REMOVE qtdeploy.bat) file(REMOVE qtdeploy.bat)
# create zip archive # create zip archive
file(WRITE makearchive.ps1 "Compress-Archive -Path LAMMPS_GUI -CompressionLevel Optimal -DestinationPath LAMMPS-Win10-amd64.zip") file(WRITE makearchive.ps1 "Compress-Archive -Path LAMMPS_GUI -CompressionLevel Optimal -DestinationPath LAMMPS_GUI-Win10-amd64.zip")
execute_process(COMMAND powershell -ExecutionPolicy Bypass -File makearchive.ps1) execute_process(COMMAND powershell -ExecutionPolicy Bypass -File makearchive.ps1)
file(REMOVE makearchive.ps1) file(REMOVE makearchive.ps1)
file(REMOVE_RECURSE LAMMPS_GUI) file(REMOVE_RECURSE LAMMPS_GUI)

View File

@ -1,7 +1,7 @@
Using the LAMMPS GUI Using the LAMMPS GUI
==================== ====================
This document describes **LAMMPS GUI version 1.3**. This document describes **LAMMPS GUI version 1.4**.
----- -----
@ -168,7 +168,7 @@ Chart Window
------------ ------------
By default, when starting a run, a "Chart Window" will open that displays charts By default, when starting a run, a "Chart Window" will open that displays charts
of thermodynamic output of the LAMMPS calculation as shown below. of the thermodynamic output of the LAMMPS calculation as shown below.
.. image:: JPG/lammps-gui-chart.png .. image:: JPG/lammps-gui-chart.png
:align: center :align: center
@ -191,6 +191,22 @@ unless the format, number, or names of output columns are changed or the
current time step is reset with :doc:`reset_timestep <reset_timestep>` current time step is reset with :doc:`reset_timestep <reset_timestep>`
or a :doc:`clear <clear>` command is issued. or a :doc:`clear <clear>` command is issued.
Image Slide Show
----------------
By default, in case the LAMMPS input contains a :doc:`dump image
<dump_image>` command, a "Slide Show" window will open which loads and
displays the images created by LAMMPS as they are written.
.. image:: JPG/lammps-gui-slideshow.png
:align: center
:scale: 50%
The various buttons at the bottom right of the window allow to either
single step through the list of images or play an animation (as a
continuous loop or once from first to last). It is also possible to
zoom in or zoom out.
Variable Info Variable Info
------------- -------------
@ -213,7 +229,7 @@ via the "Set Variables..." dialog from the ``Run`` menu.
Viewing Snapshot Images Viewing Snapshot Images
----------------------- -----------------------
By selecting the ``View Image`` entry in the ``Run`` menu, by hitting By selecting the ``Create Image`` entry in the ``Run`` menu, by hitting
the `Ctrl-I` (`Command-I` on macOS) hotkey, or by clicking on the the `Ctrl-I` (`Command-I` on macOS) hotkey, or by clicking on the
"palette" button in the status bar, LAMMPS GUI will issue a "palette" button in the status bar, LAMMPS GUI will issue a
:doc:`write_dump image <dump_image>` command and read the resulting :doc:`write_dump image <dump_image>` command and read the resulting
@ -347,7 +363,7 @@ not defined as far as the built-in parser can detect them. New rows for
additional variables can be added through the ``Add Row`` button and additional variables can be added through the ``Add Row`` button and
existing rows may be deleted by clicking on the ``X`` icons on the right. existing rows may be deleted by clicking on the ``X`` icons on the right.
The ``View Image`` entry will send a :doc:`dump image <dump_image>` The ``Create Image`` entry will send a :doc:`dump image <dump_image>`
command to the LAMMPS instance, read the resulting file, and show it in command to the LAMMPS instance, read the resulting file, and show it in
an ``Image Viewer`` window. an ``Image Viewer`` window.
@ -389,13 +405,13 @@ and looks of the LAMMPS GUI application. The settings are grouped
and each group is displayed within a tab. and each group is displayed within a tab.
.. |guiprefs1| image:: JPG/lammps-gui-prefs-general.png .. |guiprefs1| image:: JPG/lammps-gui-prefs-general.png
:width: 25% :width: 32%
.. |guiprefs2| image:: JPG/lammps-gui-prefs-accel.png .. |guiprefs2| image:: JPG/lammps-gui-prefs-accel.png
:width: 25% :width: 32%
.. |guiprefs3| image:: JPG/lammps-gui-prefs-image.png .. |guiprefs3| image:: JPG/lammps-gui-prefs-image.png
:width: 25% :width: 32%
|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs1| |guiprefs2| |guiprefs3|
@ -405,7 +421,7 @@ General Settings:
- *Echo input to log:* when checked, all input commands, including - *Echo input to log:* when checked, all input commands, including
variable expansions, will be echoed to the log window. This is variable expansions, will be echoed to the log window. This is
equivalent to using `-echo screen` at the command line. There is no equivalent to using `-echo screen` at the command line. There is no
log *file* produced since it always uses `-log none`. log *file* produced by default, since LAMMPS GUI uses `-log none`.
- *Include citation details:* when checked full citation info will be - *Include citation details:* when checked full citation info will be
included to the log window. This is equivalent to using `-cite included to the log window. This is equivalent to using `-cite
screen` on the command line. screen` on the command line.
@ -414,6 +430,9 @@ General Settings:
- *Show chart window by default:* when checked, the thermodynamic - *Show chart window by default:* when checked, the thermodynamic
output of a LAMMPS run will be collected and displayed in a chart output of a LAMMPS run will be collected and displayed in a chart
window as line graphs. window as line graphs.
- *Show slide show window by default:* when checked, a slide show
window will be shown with images from a dump image command, if
present, in the LAMMPS input.
- *Replace log window on new run:* when checked, an existing log - *Replace log window on new run:* when checked, an existing log
window will be replaced on a new LAMMPS run, otherwise each run will window will be replaced on a new LAMMPS run, otherwise each run will
create a new log window. create a new log window.
@ -481,54 +500,52 @@ instead of Ctrl/Control).
- Function - Function
- Hotkey - Hotkey
- Function - Function
- Hotkey
- Function
* - Ctrl+N * - Ctrl+N
- New File - New File
- Ctrl+Z - Ctrl+Z
- Undo edit - Undo edit
- Ctrl+Enter - Ctrl+Enter
- Run LAMMPS - Run LAMMPS
- Ctrl+Shift+A
- About LAMMPS
* - Ctrl+O * - Ctrl+O
- Open File - Open File
- Ctrl+Shift+Z - Ctrl+Shift+Z
- Redo edit - Redo edit
- Ctrl+/ - Ctrl+/
- Stop Active Run - Stop Active Run
- Ctrl+Shift+H
- Quick Help
* - CTRL+S * - CTRL+S
- Save File - Save File
- Ctrl+C - Ctrl+C
- Copy text - Copy text
- Ctrl+Shift+V - Ctrl+Shift+V
- Set Variables - Set Variables
- Ctrl+Shift+G
- LAMMPS GUI Howto
* - Ctrl+Shift+S * - Ctrl+Shift+S
- Save File As - Save File As
- Ctrl+X - Ctrl+X
- Cut text - Cut text
- Ctrl+I - Ctrl+I
- Snapshot Image - Snapshot Image
- Ctrl+Shift+M
- LAMMPS Manual
* - Ctrl+Q * - Ctrl+Q
- Quit - Quit
- Ctrl+V - Ctrl+V
- Paste text - Paste text
- Ctrl+P - Ctrl-L
- Preferences - Slide Show
- Ctrl+?
- Context Help
* - Ctrl-W * - Ctrl-W
- Close Window - Close Window
- Ctrl-A - Ctrl-A
- Select All - Select All
- Ctrl-Shift-Enter - Ctrl+P
- Run Current File - Preferences
* - Ctrl+Shift+A
- About LAMMPS
- Ctrl+Shift+H
- Quick Help
- Ctrl+Shift+G
- LAMMPS GUI Howto
* - Ctrl+Shift+M
- LAMMPS Manual
- Ctrl+?
- Context Help
- Ctrl-Shift-W - Ctrl-Shift-W
- Show Variables - Show Variables

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1506,6 +1506,7 @@ Im
imageint imageint
Imageint Imageint
Imagemagick Imagemagick
imagename
imd imd
Impey Impey
impl impl

View File

@ -36,6 +36,8 @@
#include "memory.h" #include "memory.h"
#include "modify.h" #include "modify.h"
#include "molecule.h" #include "molecule.h"
#include "output.h"
#include "thermo.h"
#include "tokenizer.h" #include "tokenizer.h"
#include "update.h" #include "update.h"
#include "variable.h" #include "variable.h"
@ -77,18 +79,10 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
// set filetype based on filename suffix // set filetype based on filename suffix
int n = strlen(filename); if (utils::strmatch(filename, "\\.jpg$") || utils::strmatch(filename, "\\.JPG$")
if (strlen(filename) > 4 && strcmp(&filename[n-4],".jpg") == 0) || utils::strmatch(filename, "\\.jpeg$") || utils::strmatch(filename, "\\.JPEG$"))
filetype = JPG; filetype = JPG;
else if (strlen(filename) > 4 && strcmp(&filename[n-4],".JPG") == 0) else if (utils::strmatch(filename, "\\.png$") || utils::strmatch(filename, "\\.PNG$"))
filetype = JPG;
else if (strlen(filename) > 5 && strcmp(&filename[n-5],".jpeg") == 0)
filetype = JPG;
else if (strlen(filename) > 5 && strcmp(&filename[n-5],".JPEG") == 0)
filetype = JPG;
else if (strlen(filename) > 4 && strcmp(&filename[n-4],".png") == 0)
filetype = PNG;
else if (strlen(filename) > 4 && strcmp(&filename[n-4],".PNG") == 0)
filetype = PNG; filetype = PNG;
else filetype = PPM; else filetype = PPM;
@ -481,6 +475,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
DumpImage::~DumpImage() DumpImage::~DumpImage()
{ {
delete image; delete image;
output->thermo->set_image_fname("");
delete[] diamtype; delete[] diamtype;
delete[] diamelement; delete[] diamelement;
@ -792,6 +787,12 @@ void DumpImage::write()
if (multifile) { if (multifile) {
fclose(fp); fclose(fp);
fp = nullptr; fp = nullptr;
// cache last dump image filename for access through library interface.
// update only *after* the file has been written so there will be no invalid read.
// have to recreate the substitution done within openfile().
output->thermo->set_image_fname(utils::star_subst(filename, update->ntimestep, padflag));
} }
} }
} }

View File

@ -69,9 +69,8 @@ void DumpMovie::init_style()
{ {
// initialize image style circumventing multifile check // initialize image style circumventing multifile check
multifile = 1; multifile_override = 1;
DumpImage::init_style(); DumpImage::init_style();
multifile = 0;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */

View File

@ -822,6 +822,10 @@ argument string.
- line number (0-based) of current line in current file or buffer - line number (0-based) of current line in current file or buffer
- pointer to int - pointer to int
- no - no
* - imagename
- file name of the last :doc:`dump image <dump_image>` file written
- pointer to 0-terminated const char array
- no
* - step * - step
- timestep when the last thermo output was generated or -1 - timestep when the last thermo output was generated or -1
- pointer to bigint - pointer to bigint
@ -866,6 +870,9 @@ void *lammps_last_thermo(void *handle, const char *what, int index)
} else if (strcmp(what, "line") == 0) { } else if (strcmp(what, "line") == 0) {
val = (void *) th->get_line(); val = (void *) th->get_line();
} else if (strcmp(what, "imagename") == 0) {
val = (void *) th->get_image_fname();
} else if (strcmp(what, "step") == 0) { } else if (strcmp(what, "step") == 0) {
val = (void *) th->get_timestep(); val = (void *) th->get_timestep();
@ -2489,9 +2496,9 @@ string, otherwise 1.
int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) { int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) {
auto lmp = (LAMMPS *) handle; auto lmp = (LAMMPS *) handle;
Info info(lmp); Info info(lmp);
auto varinfo = info.get_variable_info(idx);
if ((idx >= 0) && (idx < lmp->input->variable->nvar)) { if ((idx >= 0) && (idx < lmp->input->variable->nvar)) {
auto varinfo = info.get_variable_info(idx);
strncpy(buffer, varinfo.c_str(), buf_size); strncpy(buffer, varinfo.c_str(), buf_size);
return 1; return 1;
} }

View File

@ -796,9 +796,12 @@ void ReadRestart::header()
} else if (flag == ATOM_ID) { } else if (flag == ATOM_ID) {
atom->tag_enable = read_int(); atom->tag_enable = read_int();
} else if (flag == ATOM_MAP_STYLE) { } else if (flag == ATOM_MAP_STYLE) {
atom->map_style = read_int(); // we should be able to enable an atom map, even
// if the simulation in the restart didn't use one
int itmp = read_int();
if (atom->map_user == Atom::MAP_NONE) atom->map_style = itmp;
} else if (flag == ATOM_MAP_USER) { } else if (flag == ATOM_MAP_USER) {
atom->map_user = read_int(); int itmp = read_int(); // ignored
} else if (flag == ATOM_SORTFREQ) { } else if (flag == ATOM_SORTFREQ) {
atom->sortfreq = read_int(); atom->sortfreq = read_int();
} else if (flag == ATOM_SORTBIN) { } else if (flag == ATOM_SORTBIN) {

View File

@ -113,6 +113,7 @@ Thermo::Thermo(LAMMPS *_lmp, int narg, char **arg) :
flushflag = 0; flushflag = 0;
ntimestep = -1; ntimestep = -1;
nline = -1; nline = -1;
image_fname.clear();
// set style and corresponding lineflag // set style and corresponding lineflag
// custom style builds its own line of keywords, including wildcard expansion // custom style builds its own line of keywords, including wildcard expansion

View File

@ -42,14 +42,17 @@ class Thermo : protected Pointers {
void compute(int); void compute(int);
int evaluate_keyword(const std::string &, double *); int evaluate_keyword(const std::string &, double *);
// for accessing cached thermo data // for accessing cached thermo and related data
const int *get_nfield() const { return &nfield; }
const int *get_line() const { return &nline; } const int *get_line() const { return &nline; }
const char *get_image_fname() const { return image_fname.c_str(); }
const int *get_nfield() const { return &nfield; }
const bigint *get_timestep() const { return &ntimestep; } const bigint *get_timestep() const { return &ntimestep; }
const std::vector<multitype> &get_fields() const { return field_data; } const std::vector<multitype> &get_fields() const { return field_data; }
const std::vector<std::string> &get_keywords() const { return keyword; } const std::vector<std::string> &get_keywords() const { return keyword; }
void set_line(int _nline) { nline = _nline; } void set_line(int _nline) { nline = _nline; }
void set_image_fname(const std::string &fname) { image_fname = fname; }
private: private:
int nfield, nfield_initial; int nfield, nfield_initial;
@ -75,6 +78,7 @@ class Thermo : protected Pointers {
bigint natoms; bigint natoms;
bigint ntimestep; bigint ntimestep;
int nline; int nline;
std::string image_fname;
// data used by routines that compute single values // data used by routines that compute single values
int ivalue; // integer value to print int ivalue; // integer value to print

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(lammps-gui VERSION 1.3.1 LANGUAGES CXX) project(lammps-gui VERSION 1.4.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@ -72,17 +72,17 @@ find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets Charts)
set(PROJECT_SOURCES set(PROJECT_SOURCES
main.cpp main.cpp
lammpsgui.cpp
lammpsgui.h
lammpsgui.ui
chartviewer.cpp
chartviewer.h
codeeditor.cpp codeeditor.cpp
codeeditor.h codeeditor.h
highlighter.cpp highlighter.cpp
highlighter.h highlighter.h
imageviewer.cpp imageviewer.cpp
imageviewer.h imageviewer.h
chartviewer.cpp
chartviewer.h
lammpsgui.cpp
lammpsgui.h
lammpsgui.ui
lammpsrunner.h lammpsrunner.h
lammpswrapper.cpp lammpswrapper.cpp
lammpswrapper.h lammpswrapper.h
@ -93,6 +93,8 @@ set(PROJECT_SOURCES
preferences.h preferences.h
setvariables.cpp setvariables.cpp
setvariables.h setvariables.h
slideshow.h
slideshow.cpp
stdcapture.cpp stdcapture.cpp
${PLUGIN_LOADER_SRC} ${PLUGIN_LOADER_SRC}
${ICON_RC_FILE} ${ICON_RC_FILE}

View File

@ -2,12 +2,8 @@ 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 "syntax check" with enabled "-skiprun" flag - add "syntax check" with enabled "-skiprun" flag
- switch input file editor to read-only while loop is running - switch input file editor to read-only while loop is running
- add slideshow of images from dump image commands in the input
# Long term ideas # Long term ideas
- rewrite entire application to build the App and its layout manually - rewrite entire application to build the App and its layout manually

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -13,242 +13,220 @@
#include "highlighter.h" #include "highlighter.h"
Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) Highlighter::Highlighter(QTextDocument *parent) :
QSyntaxHighlighter(parent),
isLattice1(QStringLiteral("^\\s*(units|atom_style|change_box|dielectric|dimension)\\s+(\\S+)")),
isLattice2(QStringLiteral("^\\s*(lattice|region|create_box|create_atoms|delete_atoms|displace_"
"atoms)\\s+(\\S+)\\s+(\\S+)")),
isLattice3(QStringLiteral("^\\s*(boundary|replicate)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)")),
isOutput1(QStringLiteral("^\\s*(echo|log|write_data|write_coeff|write_restart|restart|info|"
"thermo|print|thermo_style|"
"timer|pair_write|bond_write|angle_write|dihedral_write)\\s+(\\S+)")),
isOutput2(QStringLiteral("^\\s*(write_dump|shell|thermo_modify)\\s+(\\S+)\\s+(\\S+)")),
isRead(QStringLiteral("^\\s*(include|read_restart|read_data|read_dump|molecule)")),
isStyle(QStringLiteral("^\\s*(fix|compute|dump)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)")),
isForce(QStringLiteral(
"^\\s*(pair_style|bond_style|angle_style|dihedral_style|improper_style|kspace_style|pair_"
"coeff|angle_coeff|bond_coeff|dihedral_coeff|improper_coeff)\\s+(\\S+)")),
isDefine(QStringLiteral("^\\s*(group|variable|python|set|group2ndx|ndx2group|kim|kim_query|mdi)"
"\\s+(\\S+)\\s+(\\S+)")),
isUndo(QStringLiteral("^\\s*(unfix|uncompute|undump|label|jump|next)\\s+(\\S+)")),
isParticle(QStringLiteral("^\\s*(pair_modify|mass|velocity|create_bonds|delete_"
"bonds|kspace_modify|labelmap|atom_modify)\\s+(\\S+)")),
isSetup(QStringLiteral(
"^\\s*(min_style|min_modify|run_style|timestep|neighbor|neigh_modify|suffix|special_bonds|"
"balance|box|clear|plugin|quit|comm_modify|comm_style|newton|package|partition|processors|"
"reset_atoms|reset_ids|reset_timestep|dump_modify|fix_modify|compute_modify)")),
isRun(QStringLiteral("^\\s*(minimize|minimize/kk|run|rerun|tad|neb|neb/spin|prd|server|temper/"
"npt|temper/grem|temper|message|hyper|dynamical_matrix|dynamical_matrix/"
"kk|third_order|third_order/kk|fitpod)")),
isVariable(QStringLiteral("\\s+(\\$[a-z]|\\${[^} ]+}|\\$\\(\\S+\\))")),
isReference(
QStringLiteral("\\s+(c_\\S+|C_\\S+|f_\\S+|F_\\S+|i_\\S+|i2_\\S+|d_\\S+|d2_\\S+|v_\\S+)")),
isNumber1(QStringLiteral("(^|\\s+)[0-9:*]+")), // integer and integer ranges
isNumber2(QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*")), // floating point 1
isNumber3(QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*")), // floating point 2
isNumber4(QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?")), // floating point 3
isSpecial(
QStringLiteral("(\\s\\+?-?INF|\\sEDGE|\\sNULL|\\sSELF|if\\s|then\\s|else\\s|elif\\s)")),
isContinue(QStringLiteral("&$")), isComment(QStringLiteral("#.*")),
isQuotedComment(QStringLiteral("(\".*#.*\"|'.*#.*')")),
isTriple(QStringLiteral("[^\"]*\"\"\"[^\"]*")),
isString(QStringLiteral("(\".+?\"|'.+?'|\"\"\".*\"\"\")")), in_triple(false)
{ {
HighlightingRule rule; formatNumber.setForeground(Qt::blue);
formatString.setForeground(Qt::darkGreen);
formatString.setFontWeight(QFont::Normal);
formatComment.setForeground(Qt::red);
formatSpecial.setForeground(Qt::darkMagenta);
formatSpecial.setFontWeight(QFont::Bold);
formatParticle.setForeground(Qt::darkRed);
formatParticle.setFontWeight(QFont::Bold);
formatRun.setForeground(Qt::darkBlue);
formatRun.setFontWeight(QFont::Bold);
formatVariable.setForeground(Qt::darkGray);
formatVariable.setFontWeight(QFont::Bold);
outputFormat.setForeground(Qt::darkYellow); formatOutput.setForeground(Qt::darkYellow);
outputFormat.setFontWeight(QFont::Bold); formatOutput.setFontWeight(QFont::Bold);
readFormat.setForeground(Qt::magenta); formatRead.setForeground(Qt::magenta);
readFormat.setFontWeight(QFont::Bold); formatRead.setFontWeight(QFont::Bold);
latticeFormat.setForeground(Qt::darkGreen); formatLattice.setForeground(Qt::darkGreen);
latticeFormat.setFontWeight(QFont::Bold); formatLattice.setFontWeight(QFont::Bold);
particleFormat.setForeground(Qt::darkRed); formatSetup.setForeground(Qt::darkCyan);
particleFormat.setFontWeight(QFont::Bold); formatSetup.setFontWeight(QFont::Bold);
setupFormat.setForeground(Qt::darkCyan);
setupFormat.setFontWeight(QFont::Bold);
runFormat.setForeground(Qt::darkBlue);
runFormat.setFontWeight(QFont::Bold);
defineFormat.setForeground(Qt::darkMagenta);
defineFormat.setFontWeight(QFont::Bold);
numberFormat.setForeground(Qt::blue);
commentFormat.setForeground(Qt::red);
stringFormat.setForeground(Qt::darkGreen);
stringFormat.setFontWeight(QFont::Normal);
const QString output_keywords[] = {
QStringLiteral("^\\s*log\\W"), QStringLiteral("^\\s*write_data\\W"),
QStringLiteral("^\\s*write_dump\\W"), QStringLiteral("^\\s*write_coeff\\W"),
QStringLiteral("^\\s*info\\W"), QStringLiteral("^\\s*shell\\W"),
QStringLiteral("^\\s*write_restart\\W"), QStringLiteral("^\\s*restart\\W"),
QStringLiteral("^\\s*dump\\W"), QStringLiteral("^\\s*undump\\W"),
QStringLiteral("^\\s*thermo\\W"), QStringLiteral("^\\s*thermo_modify\\W"),
QStringLiteral("^\\s*thermo_style\\W"), QStringLiteral("^\\s*print\\W"),
QStringLiteral("^\\s*timer\\W")};
for (const QString &pattern : output_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = outputFormat;
highlightingRules.append(rule);
}
const QString read_keywords[] = {
QStringLiteral("^\\s*include\\W"), QStringLiteral("^\\s*read_restart\\W"),
QStringLiteral("^\\s*read_data\\W"), QStringLiteral("^\\s*read_dump\\W"),
QStringLiteral("^\\s*molecule\\W")};
for (const QString &pattern : read_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = readFormat;
highlightingRules.append(rule);
}
const QString lattice_keywords[] = {
QStringLiteral("^\\s*boundary\\W"), QStringLiteral("^\\s*units\\W"),
QStringLiteral("^\\s*atom_style\\W"), QStringLiteral("^\\s*lattice\\W"),
QStringLiteral("^\\s*region\\W"), QStringLiteral("^\\s*create_box\\W"),
QStringLiteral("^\\s*create_atoms\\W"), QStringLiteral("^\\s*dielectric\\W"),
QStringLiteral("^\\s*delete_atoms\\W"), QStringLiteral("^\\s*displace_atoms\\W"),
QStringLiteral("^\\s*change_box\\W"), QStringLiteral("^\\s*dimension\\W"),
QStringLiteral("^\\s*replicate\\W")};
for (const QString &pattern : lattice_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = latticeFormat;
highlightingRules.append(rule);
}
const QString particle_keywords[] = {
QStringLiteral("^\\s*pair_coeff\\W"), QStringLiteral("^\\s*pair_style\\W"),
QStringLiteral("^\\s*pair_modify\\W"), QStringLiteral("^\\s*pair_write\\W"),
QStringLiteral("^\\s*mass\\W"), QStringLiteral("^\\s*velocity\\W"),
QStringLiteral("^\\s*angle_coeff\\W"), QStringLiteral("^\\s*angle_style\\W"),
QStringLiteral("^\\s*angle_write\\W"), QStringLiteral("^\\s*atom_modify\\W"),
QStringLiteral("^\\s*atom_style\\W"), QStringLiteral("^\\s*bond_coeff\\W"),
QStringLiteral("^\\s*bond_style\\W"), QStringLiteral("^\\s*bond_write\\W"),
QStringLiteral("^\\s*create_bonds\\W"), QStringLiteral("^\\s*delete_bonds\\W"),
QStringLiteral("^\\s*kspace_style\\W"), QStringLiteral("^\\s*kspace_modify\\W"),
QStringLiteral("^\\s*dihedral_style\\W"), QStringLiteral("^\\s*dihedral_coeff\\W"),
QStringLiteral("^\\s*dihedral_write\\W"), QStringLiteral("^\\s*improper_style\\W"),
QStringLiteral("^\\s*improper_coeff\\W"), QStringLiteral("^\\s*labelmap\\W")};
for (const QString &pattern : particle_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = particleFormat;
highlightingRules.append(rule);
}
const QString setup_keywords[] = {QStringLiteral("^\\s*min_style\\W"),
QStringLiteral("^\\s*min_modify\\W"),
QStringLiteral("^\\s*run_style\\W"),
QStringLiteral("^\\s*timestep\\W"),
QStringLiteral("^\\s*neighbor\\W"),
QStringLiteral("^\\s*neigh_modify\\W"),
QStringLiteral("^\\s*suffix\\W"),
QStringLiteral("^\\s*special_bonds\\W"),
QStringLiteral("^\\s*balance\\W"),
QStringLiteral("^\\s*box\\W"),
QStringLiteral("^\\s*clear\\W"),
QStringLiteral("^\\s*comm_modify\\W"),
QStringLiteral("^\\s*comm_style\\W"),
QStringLiteral("^\\s*newton\\W"),
QStringLiteral("^\\s*package\\W"),
QStringLiteral("^\\s*processors\\W"),
QStringLiteral("^\\s*reset_atoms\\W"),
QStringLiteral("^\\s*dump_modify\\W"),
QStringLiteral("^\\s*reset_ids\\W"),
QStringLiteral("^\\s*reset_timestep\\W"),
QStringLiteral("^\\s*label\\W"),
QStringLiteral("^\\s*jump\\W"),
QStringLiteral("^\\s*next\\W"),
QStringLiteral("^\\s*loop\\W")
};
for (const QString &pattern : setup_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = setupFormat;
highlightingRules.append(rule);
}
const QString run_keywords[] = {QStringLiteral("^\\s*minimize\\W"),
QStringLiteral("^\\s*minimize/kk\\W"),
QStringLiteral("^\\s*run\\W"),
QStringLiteral("^\\s*rerun\\W"),
QStringLiteral("^\\s*tad\\W"),
QStringLiteral("^\\s*neb\\W"),
QStringLiteral("^\\s*neb/spin\\W"),
QStringLiteral("^\\s*prd\\W"),
QStringLiteral("^\\s*quit\\W"),
QStringLiteral("^\\s*server\\W"),
QStringLiteral("^\\s*temper/npt\\W"),
QStringLiteral("^\\s*temper/grem\\W"),
QStringLiteral("^\\s*temper\\W"),
QStringLiteral("^\\s*message\\W"),
QStringLiteral("^\\s*hyper\\W"),
QStringLiteral("^\\s*dynamical_matrix\\W"),
QStringLiteral("^\\s*dynamical_matrix/kk\\W"),
QStringLiteral("^\\s*third_order\\W"),
QStringLiteral("^\\s*third_order/kk\\W"),
QStringLiteral("^\\s*fitpod\\W"),
QStringLiteral("^\\s*if\\W"),
QStringLiteral("^\\s*then\\W"),
QStringLiteral("^\\s*elif\\W"),
QStringLiteral("^\\s*else\\W")};
for (const QString &pattern : run_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = runFormat;
highlightingRules.append(rule);
}
const QString define_keywords[] = {QStringLiteral("^\\s*variable\\W"),
QStringLiteral("^\\s*group\\W"),
QStringLiteral("^\\s*compute\\W"),
QStringLiteral("^\\s*python\\W"),
QStringLiteral("^\\s*set\\W"),
QStringLiteral("^\\s*uncompute\\W"),
QStringLiteral("^\\s*kim_query\\W"),
QStringLiteral("^\\s*kim\\W"),
QStringLiteral("^\\s*group2ndx\\W"),
QStringLiteral("^\\s*ndx2group\\W"),
QStringLiteral("^\\s*compute_modify\\W"),
QStringLiteral("^\\s*fix_modify\\W"),
QStringLiteral("^\\s*fix\\W"),
QStringLiteral("^\\s*unfix\\W"),
QStringLiteral("^\\s*INF\\W"),
QStringLiteral("^\\s*EDGE\\W"),
QStringLiteral("^\\s*NULL\\W"),
QStringLiteral("^\\s*&\\s*$"),
QStringLiteral("^\\s*mdi\\W")};
for (const QString &pattern : define_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = defineFormat;
highlightingRules.append(rule);
}
const QString number_keywords[] = {
QStringLiteral("(^|\\s+)[0-9:*]+"), // integer and integer ranges
QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*"), // floating point 1
QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*"), // floating point 2
QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?") // floating point 3
};
for (const QString &pattern : number_keywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = numberFormat;
highlightingRules.append(rule);
}
// comments, must come before strings but after other keywords.
rule.pattern = QRegularExpression("#.*");
rule.format = commentFormat;
highlightingRules.append(rule);
// strings, must come last so it overwrites other formatting
rule.pattern = QRegularExpression("(\".*\"|'.*')");
rule.format = stringFormat;
highlightingRules.append(rule);
} }
void Highlighter::highlightBlock(const QString &text) void Highlighter::highlightBlock(const QString &text)
{ {
// clang-format off // nothing to do for empty lines
auto style = QRegularExpression("^(fix|compute|dump|set)\\s+(\\w+)\\s+(\\S+)\\s+(\\S+)").match(text); if (text.isEmpty()) return;
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 match = isLattice1.match(text);
auto undo = QRegularExpression("^(unfix|uncompute|undump)\\s+(\\w+)").match(text); if (match.hasMatch()) {
// clang-format on setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice);
bool do_style = true; setFormat(match.capturedStart(2), match.capturedLength(2), formatRun);
bool do_force = true; }
bool do_defs = true;
bool do_undo = true; match = isLattice2.match(text);
for (const HighlightingRule &rule : qAsConst(highlightingRules)) { if (match.hasMatch()) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice);
while (matchIterator.hasNext()) { setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(3), match.capturedLength(3), formatRun);
// special treatment for fix/compute/dump styles etc. }
if (style.hasMatch() && do_style) {
setFormat(style.capturedStart(1), style.capturedLength(1), defineFormat); match = isLattice3.match(text);
setFormat(style.capturedStart(2), style.capturedLength(2), numberFormat); if (match.hasMatch()) {
setFormat(style.capturedStart(3), style.capturedLength(3), stringFormat); setFormat(match.capturedStart(1), match.capturedLength(1), formatLattice);
setFormat(style.capturedStart(4), style.capturedLength(4), runFormat); setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
do_style = false; setFormat(match.capturedStart(3), match.capturedLength(3), formatString);
// special treatment for force styles styles setFormat(match.capturedStart(4), match.capturedLength(4), formatString);
} else if (force.hasMatch() && do_force) { }
setFormat(force.capturedStart(1), force.capturedLength(1), particleFormat);
setFormat(force.capturedStart(2), force.capturedLength(2), runFormat); match = isOutput1.match(text);
do_force = false; if (match.hasMatch()) {
// special treatment for undo commands setFormat(match.capturedStart(1), match.capturedLength(1), formatOutput);
} else if (undo.hasMatch() && do_undo) { setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
setFormat(undo.capturedStart(1), undo.capturedLength(1), defineFormat); }
setFormat(undo.capturedStart(2), undo.capturedLength(2), stringFormat);
do_undo = false; match = isOutput2.match(text);
// special treatment for some definitions if (match.hasMatch()) {
} else if (defs.hasMatch() && do_defs) { setFormat(match.capturedStart(1), match.capturedLength(1), formatOutput);
setFormat(defs.capturedStart(1), defs.capturedLength(1), particleFormat); setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
setFormat(defs.capturedStart(2), defs.capturedLength(2), stringFormat); setFormat(match.capturedStart(3), match.capturedLength(3), formatRun);
setFormat(defs.capturedStart(3), defs.capturedLength(3), runFormat); }
do_defs = false;
} else { match = isRead.match(text);
setFormat(match.capturedStart(), match.capturedLength(), rule.format); if (match.hasMatch()) {
} setFormat(match.capturedStart(1), match.capturedLength(1), formatRead);
setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
}
match = isStyle.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle);
setFormat(match.capturedStart(2), match.capturedLength(2), formatNumber);
setFormat(match.capturedStart(3), match.capturedLength(3), formatString);
setFormat(match.capturedStart(4), match.capturedLength(4), formatRun);
}
match = isForce.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle);
setFormat(match.capturedStart(2), match.capturedLength(2), formatRun);
}
match = isUndo.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatSpecial);
setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
}
match = isDefine.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle);
setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
setFormat(match.capturedStart(3), match.capturedLength(3), formatRun);
}
match = isParticle.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatParticle);
setFormat(match.capturedStart(2), match.capturedLength(2), formatString);
}
match = isSetup.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatSetup);
}
match = isRun.match(text);
if (match.hasMatch()) {
setFormat(match.capturedStart(1), match.capturedLength(1), formatRun);
}
// numbers
QRegularExpression numbers[] = {isNumber1, isNumber2, isNumber3, isNumber4};
for (auto &number : numbers) {
auto num = number.globalMatch(text);
while (num.hasNext()) {
auto match = num.next();
setFormat(match.capturedStart(), match.capturedLength(), formatNumber);
} }
} }
// variables
auto vars = isVariable.globalMatch(text);
while (vars.hasNext()) {
auto match = vars.next();
setFormat(match.capturedStart(), match.capturedLength(), formatVariable);
}
// references
auto refs = isReference.globalMatch(text);
while (refs.hasNext()) {
auto match = refs.next();
setFormat(match.capturedStart(), match.capturedLength(), formatVariable);
}
// continuation character
auto multiline = isContinue.match(text);
if (multiline.hasMatch())
setFormat(multiline.capturedStart(0), multiline.capturedLength(0), formatSpecial);
// special keywords
auto special = isSpecial.globalMatch(text);
while (special.hasNext()) {
auto match = special.next();
setFormat(match.capturedStart(), match.capturedLength(), formatSpecial);
}
// comments, must come before strings but after other keywords.
auto comment = isComment.match(text);
if (comment.hasMatch() && !isQuotedComment.match(text).hasMatch() && !in_triple) {
setFormat(comment.capturedStart(0), comment.capturedLength(0), formatComment);
return;
}
// strings, must come last so they can overwrite other formatting
auto string = isString.globalMatch(text);
while (string.hasNext()) {
auto match = string.next();
setFormat(match.capturedStart(), match.capturedLength(), formatString);
}
auto triple = isTriple.match(text);
if (triple.hasMatch()) {
if (in_triple) {
in_triple = false;
setFormat(0, triple.capturedStart(0) + triple.capturedLength(0), formatString);
} else {
in_triple = true;
setFormat(triple.capturedStart(0), -1, formatString);
}
} else {
if (in_triple) setFormat(0, text.size(), formatString);
}
} }
// Local Variables: // Local Variables:
// c-basic-offset: 4 // c-basic-offset: 4

View File

@ -28,23 +28,27 @@ protected:
void highlightBlock(const QString &text) override; void highlightBlock(const QString &text) override;
private: private:
struct HighlightingRule { QRegularExpression isLattice1, isLattice2, isLattice3;
QRegularExpression pattern; QRegularExpression isOutput1, isOutput2, isRead;
QTextCharFormat format; QTextCharFormat formatOutput, formatRead, formatLattice, formatSetup;
}; QRegularExpression isStyle, isForce, isDefine, isUndo;
QVector<HighlightingRule> highlightingRules; QRegularExpression isParticle, isSetup, isRun;
QTextCharFormat formatParticle, formatRun, formatDefine;
QRegularExpression isVariable, isReference;
QTextCharFormat formatVariable;
QRegularExpression isNumber1, isNumber2, isNumber3, isNumber4;
QTextCharFormat formatNumber;
QRegularExpression isSpecial, isContinue;
QTextCharFormat formatSpecial;
QRegularExpression isComment;
QRegularExpression isQuotedComment;
QTextCharFormat formatComment;
QRegularExpression isTriple;
QRegularExpression isString;
QTextCharFormat formatString;
QTextCharFormat outputFormat; int in_triple;
QTextCharFormat readFormat; int startIndex;
QTextCharFormat latticeFormat;
QTextCharFormat particleFormat;
QTextCharFormat setupFormat;
QTextCharFormat runFormat;
QTextCharFormat defineFormat;
QTextCharFormat numberFormat;
QTextCharFormat stringFormat;
QTextCharFormat commentFormat;
}; };
#endif #endif
// Local Variables: // Local Variables:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -103,8 +103,10 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
// workaround for incorrect highlight bug on macOS
auto *dummy = new QPushButton(QIcon(), ""); auto *dummy = new QPushButton(QIcon(), "");
dummy->hide(); dummy->hide();
auto *dossao = new QPushButton(QIcon(":/hd-img.png"), ""); auto *dossao = new QPushButton(QIcon(":/hd-img.png"), "");
dossao->setCheckable(true); dossao->setCheckable(true);
dossao->setToolTip("Toggle SSAO rendering"); dossao->setToolTip("Toggle SSAO rendering");
@ -190,6 +192,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
mainLayout->addLayout(menuLayout); mainLayout->addLayout(menuLayout);
mainLayout->addWidget(scrollArea); mainLayout->addWidget(scrollArea);
mainLayout->addWidget(buttonBox); mainLayout->addWidget(buttonBox);
setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).fileName()); setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).fileName());
createActions(); createActions();
@ -207,9 +210,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
resize(image.width() + 20, image.height() + 50); resize(image.width() + 20, image.height() + 50);
scrollArea->setVisible(true); scrollArea->setVisible(true);
fitToWindowAct->setEnabled(true);
updateActions(); updateActions();
if (!fitToWindowAct->isChecked()) imageLabel->adjustSize();
setLayout(mainLayout); setLayout(mainLayout);
} }
@ -464,30 +465,6 @@ void ImageViewer::saveAs()
void ImageViewer::copy() {} void ImageViewer::copy() {}
void ImageViewer::zoomIn()
{
scaleImage(1.25);
}
void ImageViewer::zoomOut()
{
scaleImage(0.8);
}
void ImageViewer::normalSize()
{
imageLabel->adjustSize();
scaleFactor = 1.0;
}
void ImageViewer::fitToWindow()
{
bool fitToWindow = fitToWindowAct->isChecked();
scrollArea->setWidgetResizable(fitToWindow);
if (!fitToWindow) normalSize();
updateActions();
}
void ImageViewer::saveFile(const QString &fileName) void ImageViewer::saveFile(const QString &fileName)
{ {
if (!fileName.isEmpty()) image.save(fileName); if (!fileName.isEmpty()) image.save(fileName);
@ -509,39 +486,12 @@ void ImageViewer::createActions()
QAction *exitAct = fileMenu->addAction("&Close", this, &QWidget::close); QAction *exitAct = fileMenu->addAction("&Close", this, &QWidget::close);
exitAct->setIcon(QIcon(":/window-close.png")); exitAct->setIcon(QIcon(":/window-close.png"));
exitAct->setShortcut(QKeySequence::fromString("Ctrl+W")); exitAct->setShortcut(QKeySequence::fromString("Ctrl+W"));
QMenu *viewMenu = menuBar->addMenu("&View");
zoomInAct = viewMenu->addAction("Image Zoom &In (25%)", this, &ImageViewer::zoomIn);
zoomInAct->setShortcut(QKeySequence::ZoomIn);
zoomInAct->setIcon(QIcon(":/gtk-zoom-in.png"));
zoomInAct->setEnabled(false);
zoomOutAct = viewMenu->addAction("Image Zoom &Out (25%)", this, &ImageViewer::zoomOut);
zoomOutAct->setShortcut(QKeySequence::ZoomOut);
zoomOutAct->setIcon(QIcon(":/gtk-zoom-out.png"));
zoomOutAct->setEnabled(false);
normalSizeAct = viewMenu->addAction("&Reset Image Size", this, &ImageViewer::normalSize);
normalSizeAct->setShortcut(QKeySequence::fromString("Ctrl+0"));
normalSizeAct->setIcon(QIcon(":/gtk-zoom-fit.png"));
normalSizeAct->setEnabled(false);
viewMenu->addSeparator();
fitToWindowAct = viewMenu->addAction("&Fit to Window", this, &ImageViewer::fitToWindow);
fitToWindowAct->setEnabled(false);
fitToWindowAct->setCheckable(true);
fitToWindowAct->setShortcut(QKeySequence::fromString("Ctrl+="));
} }
void ImageViewer::updateActions() void ImageViewer::updateActions()
{ {
saveAsAct->setEnabled(!image.isNull()); saveAsAct->setEnabled(!image.isNull());
copyAct->setEnabled(!image.isNull()); copyAct->setEnabled(!image.isNull());
zoomInAct->setEnabled(!fitToWindowAct->isChecked());
zoomOutAct->setEnabled(!fitToWindowAct->isChecked());
normalSizeAct->setEnabled(!fitToWindowAct->isChecked());
} }
void ImageViewer::scaleImage(double factor) void ImageViewer::scaleImage(double factor)
@ -555,8 +505,6 @@ void ImageViewer::scaleImage(double factor)
adjustScrollBar(scrollArea->horizontalScrollBar(), factor); adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
adjustScrollBar(scrollArea->verticalScrollBar(), factor); adjustScrollBar(scrollArea->verticalScrollBar(), factor);
zoomInAct->setEnabled(scaleFactor < 3.0);
zoomOutAct->setEnabled(scaleFactor > 0.333);
} }
void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor) void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)

View File

@ -40,10 +40,6 @@ public:
private slots: private slots:
void saveAs(); void saveAs();
void copy(); void copy();
void zoomIn();
void zoomOut();
void normalSize();
void fitToWindow();
void edit_size(); void edit_size();
void reset_view(); void reset_view();

View File

@ -20,6 +20,7 @@
#include "logwindow.h" #include "logwindow.h"
#include "preferences.h" #include "preferences.h"
#include "setvariables.h" #include "setvariables.h"
#include "slideshow.h"
#include "stdcapture.h" #include "stdcapture.h"
#include "ui_lammpsgui.h" #include "ui_lammpsgui.h"
@ -96,8 +97,8 @@ static bool has_exe(const QString &exe)
LammpsGui::LammpsGui(QWidget *parent, const char *filename) : LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
QMainWindow(parent), ui(new Ui::LammpsGui), highlighter(nullptr), capturer(nullptr), QMainWindow(parent), ui(new Ui::LammpsGui), highlighter(nullptr), capturer(nullptr),
status(nullptr), logwindow(nullptr), imagewindow(nullptr), chartwindow(nullptr), status(nullptr), logwindow(nullptr), imagewindow(nullptr), chartwindow(nullptr),
logupdater(nullptr), dirstatus(nullptr), progress(nullptr), prefdialog(nullptr), slideshow(nullptr), logupdater(nullptr), dirstatus(nullptr), progress(nullptr),
lammpsstatus(nullptr), varwindow(nullptr) prefdialog(nullptr), lammpsstatus(nullptr), varwindow(nullptr)
{ {
// enforce using the plain ASCII C locale within the GUI. // enforce using the plain ASCII C locale within the GUI.
QLocale::setDefault(QLocale("C")); QLocale::setDefault(QLocale("C"));
@ -239,6 +240,7 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
connect(ui->actionView_Log_Window, &QAction::triggered, this, &LammpsGui::view_log); connect(ui->actionView_Log_Window, &QAction::triggered, this, &LammpsGui::view_log);
connect(ui->actionView_Graph_Window, &QAction::triggered, this, &LammpsGui::view_chart); connect(ui->actionView_Graph_Window, &QAction::triggered, this, &LammpsGui::view_chart);
connect(ui->actionView_Image_Window, &QAction::triggered, this, &LammpsGui::view_image); connect(ui->actionView_Image_Window, &QAction::triggered, this, &LammpsGui::view_image);
connect(ui->actionView_Slide_Show, &QAction::triggered, this, &LammpsGui::view_slides);
connect(ui->actionView_Variable_Window, &QAction::triggered, this, &LammpsGui::view_variables); connect(ui->actionView_Variable_Window, &QAction::triggered, this, &LammpsGui::view_variables);
connect(ui->action_1, &QAction::triggered, this, &LammpsGui::open_recent); connect(ui->action_1, &QAction::triggered, this, &LammpsGui::open_recent);
connect(ui->action_2, &QAction::triggered, this, &LammpsGui::open_recent); connect(ui->action_2, &QAction::triggered, this, &LammpsGui::open_recent);
@ -307,6 +309,7 @@ LammpsGui::~LammpsGui()
delete chartwindow; delete chartwindow;
delete dirstatus; delete dirstatus;
delete varwindow; delete varwindow;
delete slideshow;
} }
void LammpsGui::new_document() void LammpsGui::new_document()
@ -545,6 +548,10 @@ void LammpsGui::open_file(const QString &fileName)
dirstatus->setText(QString(" Directory: ") + current_dir); dirstatus->setText(QString(" Directory: ") + current_dir);
status->setText("Ready."); status->setText("Ready.");
if (slideshow) {
delete slideshow;
slideshow = nullptr;
}
update_variables(); update_variables();
} }
@ -710,20 +717,25 @@ void LammpsGui::logupdate()
} }
} }
// get timestep
int step = 0;
void *ptr = lammps.last_thermo("step", 0);
if (ptr) {
if (lammps.extract_setting("bigint") == 4)
step = *(int *)ptr;
else
step = (int)*(int64_t *)ptr;
}
// extract cached thermo data // extract cached thermo data
if (chartwindow) { if (chartwindow) {
// thermo data is not yet valid during setup // thermo data is not yet valid during setup
void *ptr = lammps.last_thermo("setup", 0); void *ptr = lammps.last_thermo("setup", 0);
if (ptr && *(int *)ptr) return; if (ptr && *(int *)ptr) return;
ptr = lammps.last_thermo("step", 0); ptr = lammps.last_thermo("num", 0);
if (ptr) { if (ptr) {
int step = 0; int ncols = *(int *)ptr;
if (lammps.extract_setting("bigint") == 4)
step = *(int *)ptr;
else
step = (int)*(int64_t *)ptr;
int ncols = *(int *)lammps.last_thermo("num", 0);
// check if the column assignment has changed // check if the column assignment has changed
// if yes, delete charts and start over // if yes, delete charts and start over
@ -768,6 +780,22 @@ void LammpsGui::logupdate()
} }
} }
} }
// update list of available image file names
QString imagefile = (const char *)lammps.last_thermo("imagename", 0);
if (!imagefile.isEmpty()) {
if (!slideshow) {
slideshow = new SlideShow(current_file);
if (QSettings().value("viewslide", true).toBool())
slideshow->show();
else
slideshow->hide();
} else {
slideshow->setWindowTitle(QString("LAMMPS-GUI - Slide Show: ") + current_file);
}
slideshow->add_image(imagefile);
}
} }
void LammpsGui::modified() void LammpsGui::modified()
@ -956,6 +984,12 @@ void LammpsGui::do_run(bool use_buffer)
else else
chartwindow->hide(); chartwindow->hide();
if (slideshow) {
slideshow->setWindowTitle("LAMMPS-GUI - Slide Show");
slideshow->clear();
slideshow->hide();
}
logupdater = new QTimer(this); logupdater = new QTimer(this);
connect(logupdater, &QTimer::timeout, this, &LammpsGui::logupdate); connect(logupdater, &QTimer::timeout, this, &LammpsGui::logupdate);
logupdater->start(100); logupdater->start(100);
@ -982,6 +1016,15 @@ void LammpsGui::render_image()
imagewindow->show(); imagewindow->show();
} }
void LammpsGui::view_slides()
{
if (!slideshow) slideshow = new SlideShow(current_file);
if (slideshow->isVisible())
slideshow->hide();
else
slideshow->show();
}
void LammpsGui::view_chart() void LammpsGui::view_chart()
{ {
QSettings settings; QSettings settings;
@ -1068,6 +1111,7 @@ void LammpsGui::about()
QMessageBox msg; QMessageBox msg;
msg.setWindowTitle("About LAMMPS"); msg.setWindowTitle("About LAMMPS");
msg.setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
msg.setText(version.c_str()); msg.setText(version.c_str());
msg.setInformativeText(info.c_str()); msg.setInformativeText(info.c_str());
msg.setIconPixmap(QPixmap(":/lammps-icon-128x128.png").scaled(64, 64)); msg.setIconPixmap(QPixmap(":/lammps-icon-128x128.png").scaled(64, 64));
@ -1087,6 +1131,7 @@ void LammpsGui::help()
{ {
QMessageBox msg; QMessageBox msg;
msg.setWindowTitle("LAMMPS-GUI Quick Help"); msg.setWindowTitle("LAMMPS-GUI Quick Help");
msg.setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
msg.setText("<div>This is LAMMPS-GUI version " LAMMPS_GUI_VERSION "</div>"); msg.setText("<div>This is LAMMPS-GUI version " LAMMPS_GUI_VERSION "</div>");
msg.setInformativeText("<p>LAMMPS GUI is a graphical text editor that is linked to the LAMMPS " msg.setInformativeText("<p>LAMMPS GUI is a graphical text editor that is linked to the LAMMPS "
"library and thus can run LAMMPS directly using the contents of the " "library and thus can run LAMMPS directly using the contents of the "

View File

@ -45,6 +45,7 @@ class StdCapture;
class Preferences; class Preferences;
class ImageViewer; class ImageViewer;
class ChartWindow; class ChartWindow;
class SlideShow;
class LammpsGui : public QMainWindow { class LammpsGui : public QMainWindow {
Q_OBJECT Q_OBJECT
@ -84,6 +85,7 @@ private slots:
void stop_run(); void stop_run();
void edit_variables(); void edit_variables();
void render_image(); void render_image();
void view_slides();
void view_image(); void view_image();
void view_chart(); void view_chart();
void view_log(); void view_log();
@ -107,6 +109,7 @@ private:
LogWindow *logwindow; LogWindow *logwindow;
ImageViewer *imagewindow; ImageViewer *imagewindow;
ChartWindow *chartwindow; ChartWindow *chartwindow;
SlideShow *slideshow;
QTimer *logupdater; QTimer *logupdater;
QLabel *dirstatus; QLabel *dirstatus;
QProgressBar *progress; QProgressBar *progress;

View File

@ -1,49 +1,57 @@
<!-- -*- xml -*- -->
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>lammps-icon-128x128.png</file> <file>lammps-icon-128x128.png</file>
<file>antialias.png</file> <file>antialias.png</file>
<file>application-calc.png</file> <file>application-calc.png</file>
<file>application-exit.png</file> <file>application-exit.png</file>
<file>application-plot.png</file> <file>application-plot.png</file>
<file>axes-img.png</file> <file>axes-img.png</file>
<file>document-new.png</file> <file>document-new.png</file>
<file>document-open-recent.png</file> <file>document-open-recent.png</file>
<file>document-open.png</file> <file>document-open.png</file>
<file>document-revert.png</file> <file>document-revert.png</file>
<file>document-save-as.png</file> <file>document-save-as.png</file>
<file>document-save.png</file> <file>document-save.png</file>
<file>edit-copy.png</file> <file>edit-copy.png</file>
<file>edit-cut.png</file> <file>edit-cut.png</file>
<file>edit-delete.png</file> <file>edit-delete.png</file>
<file>edit-paste.png</file> <file>edit-paste.png</file>
<file>edit-redo.png</file> <file>edit-redo.png</file>
<file>edit-undo.png</file> <file>edit-undo.png</file>
<file>emblem-photos.png</file> <file>emblem-photos.png</file>
<file>gtk-go-down.png</file> <file>go-first.png</file>
<file>gtk-go-up.png</file> <file>go-last.png</file>
<file>gtk-zoom-fit.png</file> <file>go-next-2.png</file>
<file>gtk-zoom-in.png</file> <file>go-previous-2.png</file>
<file>gtk-zoom-out.png</file> <file>gtk-go-down.png</file>
<file>hd-img.png</file> <file>gtk-go-up.png</file>
<file>help-about.png</file> <file>gtk-zoom-fit.png</file>
<file>help-browser.png</file> <file>gtk-zoom-in.png</file>
<file>help-faq.png</file> <file>gtk-zoom-out.png</file>
<file>help_index.table</file> <file>hd-img.png</file>
<file>object-rotate-left.png</file> <file>help-about.png</file>
<file>object-rotate-right.png</file> <file>help-browser.png</file>
<file>ovito.png</file> <file>help-faq.png</file>
<file>preferences-desktop-font.png</file> <file>help_index.table</file>
<file>preferences-desktop-personal.png</file> <file>image-x-generic.png</file>
<file>preferences-desktop.png</file> <file>media-playback-start-2.png</file>
<file>process-stop.png</file> <file>media-playlist-repeat.png</file>
<file>run-file.png</file> <file>object-rotate-left.png</file>
<file>system-box.png</file> <file>object-rotate-right.png</file>
<file>system-help.png</file> <file>ovito.png</file>
<file>system-run.png</file> <file>preferences-desktop-font.png</file>
<file>utilities-terminal.png</file> <file>preferences-desktop-personal.png</file>
<file>vdw-style.png</file> <file>preferences-desktop.png</file>
<file>vmd.png</file> <file>process-stop.png</file>
<file>window-close.png</file> <file>run-file.png</file>
<file>x-office-drawing.png</file> <file>system-box.png</file>
</qresource> <file>system-help.png</file>
<file>system-run.png</file>
<file>utilities-terminal.png</file>
<file>vdw-style.png</file>
<file>vmd.png</file>
<file>window-close.png</file>
<file>x-office-drawing.png</file>
</qresource>
</RCC> </RCC>

View File

@ -93,6 +93,7 @@
<addaction name="actionView_Log_Window"/> <addaction name="actionView_Log_Window"/>
<addaction name="actionView_Graph_Window"/> <addaction name="actionView_Graph_Window"/>
<addaction name="actionView_Image_Window"/> <addaction name="actionView_Image_Window"/>
<addaction name="actionView_Slide_Show"/>
<addaction name="actionView_Variable_Window"/> <addaction name="actionView_Variable_Window"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
@ -250,7 +251,7 @@
<iconset theme=":/emblem-photos.png"/> <iconset theme=":/emblem-photos.png"/>
</property> </property>
<property name="text"> <property name="text">
<string>View &amp;Image</string> <string>Create &amp;Image</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+I</string> <string>Ctrl+I</string>
@ -352,6 +353,17 @@
<string>Ctrl+Shift+C</string> <string>Ctrl+Shift+C</string>
</property> </property>
</action> </action>
<action name="actionView_Slide_Show">
<property name="icon">
<iconset theme=":/image-x-generic.png"/>
</property>
<property name="text">
<string>&amp;Slide Show Window</string>
</property>
<property name="shortcut">
<string>Ctrl+L</string>
</property>
</action>
<action name="action_1"> <action name="action_1">
<property name="icon"> <property name="icon">
<iconset theme=":/document-open-recent.png"/> <iconset theme=":/document-open-recent.png"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -78,6 +78,7 @@ Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) :
layout->addWidget(tabWidget); layout->addWidget(tabWidget);
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
setLayout(layout); setLayout(layout);
setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
setWindowTitle("LAMMPS-GUI - Preferences"); setWindowTitle("LAMMPS-GUI - Preferences");
resize(500, 400); resize(500, 400);
} }
@ -161,6 +162,8 @@ void Preferences::accept()
if (box) settings->setValue("viewlog", box->isChecked()); if (box) settings->setValue("viewlog", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("viewchart"); box = tabWidget->findChild<QCheckBox *>("viewchart");
if (box) settings->setValue("viewchart", box->isChecked()); if (box) settings->setValue("viewchart", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("viewslide");
if (box) settings->setValue("viewslide", box->isChecked());
if (need_relaunch) { if (need_relaunch) {
QMessageBox msg(QMessageBox::Information, QString("Relaunching LAMMPS-GUI"), QMessageBox msg(QMessageBox::Information, QString("Relaunching LAMMPS-GUI"),
@ -192,6 +195,9 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa
auto *pltv = new QCheckBox("Show chart window by default"); auto *pltv = new QCheckBox("Show chart window by default");
pltv->setObjectName("viewchart"); pltv->setObjectName("viewchart");
pltv->setCheckState(settings->value("viewchart", true).toBool() ? Qt::Checked : Qt::Unchecked); pltv->setCheckState(settings->value("viewchart", true).toBool() ? Qt::Checked : Qt::Unchecked);
auto *sldv = new QCheckBox("Show slide show window by default");
sldv->setObjectName("viewslide");
sldv->setCheckState(settings->value("viewslide", true).toBool() ? Qt::Checked : Qt::Unchecked);
auto *logr = new QCheckBox("Replace log window on new run"); auto *logr = new QCheckBox("Replace log window on new run");
logr->setObjectName("logreplace"); logr->setObjectName("logreplace");
logr->setCheckState(settings->value("logreplace", false).toBool() ? Qt::Checked logr->setCheckState(settings->value("logreplace", false).toBool() ? Qt::Checked
@ -232,6 +238,7 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa
layout->addWidget(cite); layout->addWidget(cite);
layout->addWidget(logv); layout->addWidget(logv);
layout->addWidget(pltv); layout->addWidget(pltv);
layout->addWidget(sldv);
layout->addWidget(logr); layout->addWidget(logr);
layout->addWidget(pltr); layout->addWidget(pltr);
layout->addWidget(imgr); layout->addWidget(imgr);

View File

@ -55,6 +55,7 @@ SetVariables::SetVariables(QList<QPair<QString, QString>> &_vars, QWidget *paren
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
setLayout(layout); setLayout(layout);
setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
setWindowTitle("LAMMPS-GUI - Set Variables"); setWindowTitle("LAMMPS-GUI - Set Variables");
resize(300, 200); resize(300, 200);
} }

View File

@ -0,0 +1,280 @@
/* ----------------------------------------------------------------------
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 "slideshow.h"
#include <QDialogButtonBox>
#include <QFileInfo>
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QImage>
#include <QImageReader>
#include <QLabel>
#include <QPalette>
#include <QPushButton>
#include <QScreen>
#include <QSettings>
#include <QShortcut>
#include <QSpacerItem>
#include <QTimer>
#include <QVBoxLayout>
SlideShow::SlideShow(const QString &fileName, QWidget *parent) :
QDialog(parent), playtimer(nullptr), imageLabel(new QLabel), imageName(new QLabel("(none)")),
do_loop(true)
{
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setScaledContents(false);
imageLabel->setMinimumSize(100, 100);
imageName->setFrameStyle(QFrame::Raised);
imageName->setFrameShape(QFrame::Panel);
imageName->setAlignment(Qt::AlignCenter);
imageName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this);
QObject::connect(shortcut, &QShortcut::activated, this, &SlideShow::close);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto *mainLayout = new QVBoxLayout;
auto *navLayout = new QHBoxLayout;
auto *botLayout = new QHBoxLayout;
// workaround for incorrect highlight bug on macOS
auto *dummy = new QPushButton(QIcon(), "");
dummy->hide();
auto *gofirst = new QPushButton(QIcon(":/go-first.png"), "");
gofirst->setToolTip("Go to first Image");
auto *goprev = new QPushButton(QIcon(":/go-previous-2.png"), "");
goprev->setToolTip("Go to previous Image");
auto *goplay = new QPushButton(QIcon(":/media-playback-start-2.png"), "");
goplay->setToolTip("Play animation");
goplay->setCheckable(true);
goplay->setChecked(playtimer);
goplay->setObjectName("play");
auto *gonext = new QPushButton(QIcon(":/go-next-2.png"), "");
gonext->setToolTip("Go to next Image");
auto *golast = new QPushButton(QIcon(":/go-last.png"), "");
golast->setToolTip("Go to last Image");
auto *goloop = new QPushButton(QIcon(":/media-playlist-repeat.png"), "");
goloop->setToolTip("Loop animation");
goloop->setCheckable(true);
goloop->setChecked(do_loop);
auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), "");
zoomin->setToolTip("Zoom in by 10 percent");
auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), "");
zoomout->setToolTip("Zoom out by 10 percent");
auto *normal = new QPushButton(QIcon(":/gtk-zoom-fit.png"), "");
normal->setToolTip("Reset zoom to normal");
connect(gofirst, &QPushButton::released, this, &SlideShow::first);
connect(goprev, &QPushButton::released, this, &SlideShow::prev);
connect(goplay, &QPushButton::released, this, &SlideShow::play);
connect(gonext, &QPushButton::released, this, &SlideShow::next);
connect(golast, &QPushButton::released, this, &SlideShow::last);
connect(goloop, &QPushButton::released, this, &SlideShow::loop);
connect(zoomin, &QPushButton::released, this, &SlideShow::zoomIn);
connect(zoomout, &QPushButton::released, this, &SlideShow::zoomOut);
connect(gofirst, &QPushButton::released, this, &SlideShow::first);
connect(normal, &QPushButton::released, this, &SlideShow::normalSize);
navLayout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
navLayout->addWidget(dummy);
navLayout->addWidget(gofirst);
navLayout->addWidget(goprev);
navLayout->addWidget(goplay);
navLayout->addWidget(gonext);
navLayout->addWidget(golast);
navLayout->addWidget(goloop);
navLayout->addWidget(zoomin);
navLayout->addWidget(zoomout);
navLayout->addWidget(normal);
mainLayout->addWidget(imageLabel);
mainLayout->addLayout(navLayout);
botLayout->addWidget(imageName);
botLayout->addWidget(buttonBox);
botLayout->setStretch(0, 3);
mainLayout->addLayout(botLayout);
setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
setWindowTitle(QString("LAMMPS-GUI - Slide Show: ") + QFileInfo(fileName).fileName());
imagefiles.clear();
scaleFactor = 1.0;
current = 0;
auto maxsize = QGuiApplication::primaryScreen()->availableSize() * 4 / 5;
maxheight = maxsize.height();
maxwidth = maxsize.width();
setLayout(mainLayout);
}
void SlideShow::add_image(const QString &filename)
{
if (!imagefiles.contains(filename)) {
int lastidx = imagefiles.size();
imagefiles.append(filename);
loadImage(lastidx);
}
}
void SlideShow::clear()
{
imagefiles.clear();
image.fill(Qt::black);
imageLabel->setPixmap(QPixmap::fromImage(image));
imageLabel->adjustSize();
imageName->setText("(none)");
repaint();
}
void SlideShow::loadImage(int idx)
{
if ((idx < 0) || (idx >= imagefiles.size())) return;
do {
QImageReader reader(imagefiles[idx]);
reader.setAutoTransform(true);
const QImage newImage = reader.read();
// There was an error reading the image file. Try reading the previous image instead.
if (newImage.isNull()) {
--idx;
} else {
int newheight = (int)newImage.height() * scaleFactor;
int newwidth = (int)newImage.width() * scaleFactor;
image = newImage.scaled(newwidth, newheight, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
imageLabel->setPixmap(QPixmap::fromImage(image));
imageLabel->setMinimumSize(newwidth, newheight);
imageName->setText(QString(" Image %1 / %2 : %3 ")
.arg(idx + 1)
.arg(imagefiles.size())
.arg(imagefiles[idx]));
adjustSize();
current = idx;
break;
}
} while (idx >= 0);
}
void SlideShow::first()
{
current = 0;
loadImage(current);
}
void SlideShow::last()
{
current = imagefiles.size() - 1;
loadImage(current);
}
void SlideShow::play()
{
// if we do not loop, start animation from beginning
if (!do_loop) current = 0;
if (playtimer) {
playtimer->stop();
delete playtimer;
playtimer = nullptr;
} else {
playtimer = new QTimer(this);
connect(playtimer, &QTimer::timeout, this, &SlideShow::next);
playtimer->start(100);
}
// reset push button state. use findChild() if not triggered from button.
QPushButton *button = qobject_cast<QPushButton *>(sender());
if (!button) button = findChild<QPushButton *>("play");
if (button) button->setChecked(playtimer);
}
void SlideShow::next()
{
++current;
if (current >= imagefiles.size()) {
if (do_loop) {
current = 0;
} else {
// stop animation
if (playtimer) play();
--current;
}
}
loadImage(current);
}
void SlideShow::prev()
{
--current;
if (current < 0) {
if (do_loop)
current = imagefiles.size() - 1;
else
current = 0;
}
loadImage(current);
}
void SlideShow::loop()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
do_loop = !do_loop;
button->setChecked(do_loop);
}
void SlideShow::zoomIn()
{
scaleImage(1.1);
}
void SlideShow::zoomOut()
{
scaleImage(0.9);
}
void SlideShow::normalSize()
{
scaleFactor = 1.0;
scaleImage(1.0);
}
void SlideShow::scaleImage(double factor)
{
// compute maxfactor so the image is not scaled beyond 80 of width or height of screen
double maxfactor = 10.0;
maxfactor = qMin((double)maxheight / (double)image.height(), maxfactor);
maxfactor = qMin((double)maxwidth / (double)image.width(), maxfactor);
if (factor > maxfactor) factor = maxfactor;
scaleFactor *= factor;
if (scaleFactor < 0.25) scaleFactor = 0.25;
loadImage(current);
}
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -0,0 +1,65 @@
/* -*- 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 SLIDESHOW_H
#define SLIDESHOW_H
#include <QDialog>
#include <QImage>
#include <QString>
#include <QStringList>
class QDialogButtonBox;
class QLabel;
class QTimer;
class SlideShow : public QDialog {
Q_OBJECT
public:
explicit SlideShow(const QString &fileName, QWidget *parent = nullptr);
void add_image(const QString &filename);
void clear();
private slots:
void first();
void last();
void next();
void prev();
void play();
void loop();
void zoomIn();
void zoomOut();
void normalSize();
private:
void scaleImage(double factor);
void loadImage(int idx);
private:
QImage image;
QTimer *playtimer;
QLabel *imageLabel, *imageName;
QDialogButtonBox *buttonBox;
double scaleFactor = 1.0;
int current;
int maxwidth, maxheight;
bool do_loop;
QStringList imagefiles;
};
#endif
// Local Variables:
// c-basic-offset: 4
// End:

View File

@ -533,7 +533,7 @@ TEST_F(AtomStyleTest, atomic)
ASSERT_NE(lmp->atom->mass_setflag, nullptr); ASSERT_NE(lmp->atom->mass_setflag, nullptr);
ASSERT_NE(lmp->atom->sametag, nullptr); ASSERT_NE(lmp->atom->sametag, nullptr);
ASSERT_EQ(lmp->atom->map_style, Atom::MAP_HASH); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_HASH);
ASSERT_EQ(lmp->atom->map_user, 2); ASSERT_EQ(lmp->atom->map_user, Atom::MAP_HASH);
ASSERT_EQ(lmp->atom->map_tag_max, 4); ASSERT_EQ(lmp->atom->map_tag_max, 4);
BEGIN_HIDE_OUTPUT(); BEGIN_HIDE_OUTPUT();
command("pair_coeff * *"); command("pair_coeff * *");
@ -587,7 +587,7 @@ TEST_F(AtomStyleTest, atomic)
ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[1], 1);
ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1);
ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY);
ASSERT_EQ(lmp->atom->map_user, 1); ASSERT_EQ(lmp->atom->map_user, Atom::MAP_ARRAY);
ASSERT_EQ(lmp->atom->map_tag_max, 4); ASSERT_EQ(lmp->atom->map_tag_max, 4);
ASSERT_EQ(lmp->atom->tag_consecutive(), 1); ASSERT_EQ(lmp->atom->tag_consecutive(), 1);
@ -597,6 +597,7 @@ TEST_F(AtomStyleTest, atomic)
command("delete_atoms group two compress no"); command("delete_atoms group two compress no");
command("write_restart test_atom_styles.restart"); command("write_restart test_atom_styles.restart");
command("clear"); command("clear");
command("atom_modify map hash");
command("read_restart test_atom_styles.restart"); command("read_restart test_atom_styles.restart");
END_HIDE_OUTPUT(); END_HIDE_OUTPUT();
ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic"));
@ -629,8 +630,8 @@ TEST_F(AtomStyleTest, atomic)
EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON);
ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[1], 1);
ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1);
ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_HASH);
ASSERT_EQ(lmp->atom->map_user, 1); ASSERT_EQ(lmp->atom->map_user, Atom::MAP_HASH);
ASSERT_EQ(lmp->atom->map_tag_max, 3); ASSERT_EQ(lmp->atom->map_tag_max, 3);
BEGIN_HIDE_OUTPUT(); BEGIN_HIDE_OUTPUT();
command("reset_atom_ids"); command("reset_atom_ids");
@ -4561,8 +4562,8 @@ TEST_F(AtomStyleTest, property_atom)
expected.atom_style = "atomic"; expected.atom_style = "atomic";
expected.molecular = Atom::ATOMIC; expected.molecular = Atom::ATOMIC;
expected.tag_enable = 1; expected.tag_enable = 1;
expected.map_style = 1; expected.map_style = Atom::MAP_ARRAY;
expected.map_user = 1; expected.map_user = Atom::MAP_ARRAY;
expected.has_type = true; expected.has_type = true;
expected.has_image = true; expected.has_image = true;
expected.has_mask = true; expected.has_mask = true;
@ -4663,7 +4664,7 @@ TEST_F(AtomStyleTest, property_atom)
ASSERT_NE(lmp->atom->sametag, nullptr); ASSERT_NE(lmp->atom->sametag, nullptr);
ASSERT_EQ(lmp->atom->tag_consecutive(), 1); ASSERT_EQ(lmp->atom->tag_consecutive(), 1);
ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY);
ASSERT_EQ(lmp->atom->map_user, 1); ASSERT_EQ(lmp->atom->map_user, Atom::MAP_ARRAY);
ASSERT_EQ(lmp->atom->map_tag_max, 4); ASSERT_EQ(lmp->atom->map_tag_max, 4);
auto x = lmp->atom->x; auto x = lmp->atom->x;
@ -4751,6 +4752,7 @@ TEST_F(AtomStyleTest, property_atom)
expected.has_ianame = true; expected.has_ianame = true;
expected.has_daname = true; expected.has_daname = true;
expected.nextra_store = 12; expected.nextra_store = 12;
expected.map_user = Atom::MAP_NONE;
ASSERT_ATOM_STATE_EQ(lmp->atom, expected); ASSERT_ATOM_STATE_EQ(lmp->atom, expected);
ASSERT_NE(lmp->atom->avec, nullptr); ASSERT_NE(lmp->atom->avec, nullptr);