diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 88b7ec422e..604339f345 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -192,6 +192,7 @@ option(BUILD_SHARED_LIBS "Build shared library" OFF) option(CMAKE_POSITION_INDEPENDENT_CODE "Create object compatible with shared libraries" ON) option(BUILD_TOOLS "Build and install LAMMPS tools (msi2lmp, binary2txt, chain)" OFF) option(BUILD_LAMMPS_SHELL "Build and install the LAMMPS shell" OFF) +option(BUILD_LAMMPS_GUI "Build and install the LAMMPS GUI" OFF) # Support using clang-tidy for C++ files with selected options set(ENABLE_CLANG_TIDY OFF CACHE BOOL "Include clang-tidy processing when compiling") diff --git a/cmake/Modules/Tools.cmake b/cmake/Modules/Tools.cmake index 285c5f2405..44d9a5a1db 100644 --- a/cmake/Modules/Tools.cmake +++ b/cmake/Modules/Tools.cmake @@ -67,4 +67,8 @@ if(BUILD_LAMMPS_SHELL) install(FILES ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) endif() - +if(BUILD_LAMMPS_GUI) + get_filename_component(LAMMPS_GUI_DIR ${LAMMPS_SOURCE_DIR}/../tools/lammps-gui ABSOLUTE) + get_filename_component(LAMMPS_GUI_BIN ${CMAKE_BINARY_DIR}/lammps-gui-build ABSOLUTE) + add_subdirectory(${LAMMPS_GUI_DIR} ${LAMMPS_GUI_BIN}) +endif() diff --git a/tools/lammps-gui/.gitignore b/tools/lammps-gui/.gitignore new file mode 100644 index 0000000000..fab7372d79 --- /dev/null +++ b/tools/lammps-gui/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt new file mode 100644 index 0000000000..85c07abc57 --- /dev/null +++ b/tools/lammps-gui/CMakeLists.txt @@ -0,0 +1,98 @@ +cmake_minimum_required(VERSION 3.10) + +project(lammps-gui VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# when this file is included as subdirectory in the LAMMPS build, many settings are directly imported +if(LAMMPS_DIR) + set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR}) + set(LAMMPS_LIBRARY lammps) +else() + # NOTE: the next line should be commented out when used outside of the LAMMPS package + get_filename_component(LAMMPS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src ABSOLUTE) + set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR} CACHE PATH "Location of LAMMPS headers") + if(NOT LAMMPS_HEADER_DIR) + message(FATAL_ERROR "Must set LAMMPS_HEADER_DIR") + endif() + # find LAMMPS library + find_library(LAMMPS_LIBRARY + NAMES lammps lammps_serial + HINTS ${LAMMPS_HEADER_DIR}/../build ${LAMMPS_HEADER_DIR}/../build-clang ${LAMMPS_HEADER_DIR}/../build-test ${LAMMPS_HEADER_DIR} + REQUIRED + ) + # by default, install into $HOME/.local (not /usr/local), + # so that no root access (and sudo) is needed + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE) + endif() + # ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro + # and prints lots of pointless warnings about "unsafe" functions + if(MSVC) + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + add_compile_options(/Zc:__cplusplus) + add_compile_options(/wd4244) + add_compile_options(/wd4267) + if(LAMMPS_EXCEPTIONS) + add_compile_options(/EHsc) + endif() + endif() + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + endif() +endif() + +find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) + +set(PROJECT_SOURCES + main.cpp + lammpsgui.cpp + lammpsgui.h + lammpsgui.ui +) + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(lammps-gui + MANUAL_FINALIZATION + ${PROJECT_SOURCES} + ) +# Define target properties for Android with Qt 6 as: +# set_property(TARGET lammps-gui APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR +# ${CMAKE_CURRENT_SOURCE_DIR}/android) +# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation +else() + if(ANDROID) + add_library(lammps-gui SHARED + ${PROJECT_SOURCES} + ) +# Define properties for Android with Qt 5 after find_package() calls as: +# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") + else() + add_executable(lammps-gui + ${PROJECT_SOURCES} + ) + endif() +endif() + +target_include_directories(lammps-gui PRIVATE ${LAMMPS_HEADER_DIR}) +target_link_libraries(lammps-gui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) +target_link_libraries(lammps-gui PRIVATE ${LAMMPS_LIBRARY}) + +set_target_properties(lammps-gui PROPERTIES + MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_finalize_executable(lammps-gui) +endif() diff --git a/tools/lammps-gui/CMakeLists.txt.user b/tools/lammps-gui/CMakeLists.txt.user new file mode 100644 index 0000000000..eaa7cf2ae6 --- /dev/null +++ b/tools/lammps-gui/CMakeLists.txt.user @@ -0,0 +1,322 @@ + + + + + + EnvironmentId + {ed0d4570-2589-4771-8b12-00999b3e43be} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + Builtin.BuildSystem + + true + true + Builtin.DefaultTidyAndClazy + 2 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {287695d9-d112-4f65-92b5-675d1d6bc655} + 0 + 0 + 0 + + Debug + -DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{IDE:ResourcePath}/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + /home/akohlmey/compile/lammps/tools/build-lammps-gui-Desktop-Debug + + + + all + + true + Build + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + Build + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + Release + -DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{IDE:ResourcePath}/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + /home/akohlmey/compile/lammps/tools/build-lammps-gui-Desktop-Release + + + + all + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + CMakeProjectManager.CMakeBuildConfiguration + + + RelWithDebInfo + -DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{IDE:ResourcePath}/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + /home/akohlmey/compile/lammps/tools/build-lammps-gui-Desktop-RelWithDebInfo + + + + all + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + MinSizeRel + -DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=MinSizeRel +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{IDE:ResourcePath}/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + /home/akohlmey/compile/lammps/tools/build-lammps-gui-Desktop-MinSizeRel + + + + all + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 4 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + lammps-gui + CMakeProjectManager.CMakeRunConfiguration.lammps-gui + lammps-gui + false + true + true + false + true + /home/akohlmey/compile/lammps/tools/build-lammps-gui-Desktop-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp new file mode 100644 index 0000000000..b0fbd74b68 --- /dev/null +++ b/tools/lammps-gui/lammpsgui.cpp @@ -0,0 +1,183 @@ +#include "lammpsgui.h" +#include "./ui_lammpsgui.h" +#include "library.h" + +#include +#include +#include +#include +#include +#include + +LammpsGui::LammpsGui(QWidget *parent) + : QMainWindow(parent), ui(new Ui::LammpsGui), lammps_handle(nullptr) +{ + ui->setupUi(this); + this->setCentralWidget(ui->textEdit); + current_file.clear(); + current_line = 0; + text_font.setFamily("monospace"); + text_font.setFixedPitch(true); + text_font.setStyleHint(QFont::TypeWriter); + ui->textEdit->setCurrentFont(text_font); + + connect(ui->actionNew, &QAction::triggered, this, &LammpsGui::new_document); + connect(ui->actionOpen, &QAction::triggered, this, &LammpsGui::open); + connect(ui->actionSave, &QAction::triggered, this, &LammpsGui::save); + connect(ui->actionSave_As, &QAction::triggered, this, &LammpsGui::save_as); + connect(ui->actionQuit, &QAction::triggered, this, &LammpsGui::quit); + connect(ui->actionCopy, &QAction::triggered, this, &LammpsGui::copy); + connect(ui->actionCut, &QAction::triggered, this, &LammpsGui::cut); + connect(ui->actionPaste, &QAction::triggered, this, &LammpsGui::paste); + connect(ui->actionUndo, &QAction::triggered, this, &LammpsGui::undo); + connect(ui->actionRedo, &QAction::triggered, this, &LammpsGui::redo); + connect(ui->actionClear, &QAction::triggered, this, &LammpsGui::clear); + connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer); + connect(ui->actionExecute_Line, &QAction::triggered, this, &LammpsGui::run_line); +// connect(ui->actionAbout, &QAction::triggered, this, &LammpsGui::about); + +#if !QT_CONFIG(clipboard) + ui->actionCut->setEnabled(false); + ui->actionCopy->setEnabled(false); + ui->actionPaste->setEnabled(false); +#endif +} + +LammpsGui::~LammpsGui() +{ + delete ui; +} + +void LammpsGui::new_document() +{ + current_file.clear(); + current_line = 0; + ui->textEdit->setText(QString()); + if (lammps_handle) lammps_close(lammps_handle); + lammps_handle = nullptr; +} + +void LammpsGui::open() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Open the file"); + QFile file(fileName); + current_file = fileName; + current_line = 0; + if (!file.open(QIODevice::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, "Warning", "Cannot open file: " + file.errorString()); + return; + } + setWindowTitle(fileName); + QTextStream in(&file); + QString text = in.readAll(); + ui->textEdit->setText(text); + file.close(); +} + +void LammpsGui::save() +{ + QString fileName; + // If we don't have a filename from before, get one. + if (current_file.isEmpty()) { + fileName = QFileDialog::getSaveFileName(this, "Save"); + current_file = fileName; + } else { + fileName = current_file; + } + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString()); + return; + } + setWindowTitle(fileName); + QTextStream out(&file); + QString text = ui->textEdit->toPlainText(); + out << text; + file.close(); +} + +void LammpsGui::save_as() +{ + QString fileName = QFileDialog::getSaveFileName(this, "Save as"); + QFile file(fileName); + + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString()); + return; + } + current_file = fileName; + setWindowTitle(fileName); + QTextStream out(&file); + QString text = ui->textEdit->toPlainText(); + out << text; + file.close(); +} + +void LammpsGui::quit() +{ + if (lammps_handle) { + lammps_close(lammps_handle); + lammps_mpi_finalize(); + lammps_kokkos_finalize(); + lammps_python_finalize(); + } + QCoreApplication::quit(); +} + +void LammpsGui::copy() +{ +#if QT_CONFIG(clipboard) + ui->textEdit->copy(); +#endif +} + +void LammpsGui::cut() +{ +#if QT_CONFIG(clipboard) + ui->textEdit->cut(); +#endif +} + +void LammpsGui::paste() +{ +#if QT_CONFIG(clipboard) + ui->textEdit->paste(); +#endif +} + +void LammpsGui::undo() +{ + ui->textEdit->undo(); +} + +void LammpsGui::redo() +{ + ui->textEdit->redo(); +} + +void LammpsGui::run_buffer() +{ + clear(); + if (!lammps_handle) lammps_handle = lammps_open_no_mpi(0, nullptr, nullptr); + if (!lammps_handle) return; + std::string buffer = ui->textEdit->toPlainText().toStdString(); + lammps_commands_string(lammps_handle, buffer.c_str()); +} + +void LammpsGui::run_line() +{ + // dummy +} + +void LammpsGui::clear() +{ + if (lammps_handle) { + lammps_command(lammps_handle, "clear"); + current_line = 0; + } +} + +void LammpsGui::about() +{ + // dummy +} diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h new file mode 100644 index 0000000000..d56a981ddf --- /dev/null +++ b/tools/lammps-gui/lammpsgui.h @@ -0,0 +1,43 @@ +#ifndef LAMMPSGUI_H +#define LAMMPSGUI_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class LammpsGui; } +QT_END_NAMESPACE + +class LammpsGui : public QMainWindow +{ + Q_OBJECT + +public: + LammpsGui(QWidget *parent = nullptr); + ~LammpsGui(); + +private slots: + void new_document(); + void open(); + void save(); + void save_as(); + void quit(); + void copy(); + void cut(); + void paste(); + void undo(); + void redo(); + void clear(); + void run_buffer(); + void run_line(); + void about(); + +private: + Ui::LammpsGui *ui; + QString current_file; + QFont text_font; + int current_line; + void *lammps_handle; +}; +#endif // LAMMPSGUI_H diff --git a/tools/lammps-gui/lammpsgui.ui b/tools/lammps-gui/lammpsgui.ui new file mode 100644 index 0000000000..6ea0351cce --- /dev/null +++ b/tools/lammps-gui/lammpsgui.ui @@ -0,0 +1,152 @@ + + + LammpsGui + + + + 0 + 0 + 800 + 600 + + + + LammpsGui + + + + + + 0 + 40 + 741 + 381 + + + + + + + + + + + + + 0 + 0 + 800 + 23 + + + + + File + + + + + + + + + + + + Edit + + + + + + + + + + + Run + + + + + + + + About + + + + + + + + + + + New + + + + + Open + + + + + Save + + + + + Save As + + + + + Quit + + + + + Cut + + + + + Copy + + + + + Paste + + + + + Undo + + + + + Redo + + + + + Clear + + + + + Execute Buffer + + + + + Execute Line + + + + + + diff --git a/tools/lammps-gui/main.cpp b/tools/lammps-gui/main.cpp new file mode 100644 index 0000000000..7ee8f9150f --- /dev/null +++ b/tools/lammps-gui/main.cpp @@ -0,0 +1,11 @@ +#include "lammpsgui.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + LammpsGui w; + w.show(); + return a.exec(); +}