diff --git a/tools/lammps-gui/icons/tutorial2-logo.png b/tools/lammps-gui/icons/tutorial2-logo.png new file mode 100644 index 0000000000..dc661decb3 Binary files /dev/null and b/tools/lammps-gui/icons/tutorial2-logo.png differ diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index 36f22abb5f..89597ec7fe 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -1668,19 +1668,56 @@ QWizardPage *LammpsGui::tutorial1_finish() void LammpsGui::start_tutorial2() { if (wizard) delete wizard; - wizard = new QWizard; + wizard = new Tutorial2Wizard; wizard->addPage(tutorial2_intro()); + wizard->addPage(tutorial2_info()); wizard->addPage(tutorial2_directory()); + wizard->addPage(tutorial2_finish()); wizard->setWindowTitle("Tutorial 2 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); wizard->show(); } QWizardPage *LammpsGui::tutorial2_intro() { auto *page = new QWizardPage; - page->setTitle("Starting Tutorial 2"); - auto *label = new QLabel("This wizard will guide you to get set up for working " - "through the Tutorial 2 from lammpstutorials.github.io."); + page->setTitle("Getting Started With Tutorial 2"); + page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + + // XXX TODO: update URL to published tutorial DOI + auto *label = + new QLabel("

This wizard will help you to select and populate a folder with " + "materials required to work through tutorial 2 from a fourthcoming " + "LAMMPS tutorial using LAMMPS-GUI by Simon Gravelle, Jake Gissinger, " + "and Axel Kohlmeyer.

\n" + "The work-in-progress materials for this tutorial are available at: " + "github.com/lammpstutorials/lammpstutorials-article


\n" + "
\n" + "

Click on the \"Next\" button to begin.

"); + label->setWordWrap(true); + + auto *layout = new QVBoxLayout; + layout->addWidget(label); + page->setLayout(layout); + return page; +} + +QWizardPage *LammpsGui::tutorial2_info() +{ + auto *page = new QWizardPage; + page->setTitle("Contents of Tutorial 2"); + page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + + auto *label = + new QLabel("

In tutorial 2 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the " + "response to it. Since bonds are represented by a harmonic potential, they " + "cannot break. This is then compared to simulating the same system with a " + "reactive force field (AIREBO) where bonds may be broken and formed.

" + "
\n" + "

Click on the \"Next\" button to select a folder.

"); label->setWordWrap(true); auto *layout = new QVBoxLayout; @@ -1693,11 +1730,79 @@ QWizardPage *LammpsGui::tutorial2_directory() { auto *page = new QWizardPage; page->setTitle("Select Directory for Tutorial 2"); - auto *label = new QLabel("Please select a directory to store the files for tutorial 2"); + page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + + auto *frame = new QFrame; + auto *label = new QLabel( + "

Select a directory to store the files for tutorial 2. The directory will be " + "created if necessary and LAMMPS-GUI will download the files required for the " + "tutorial.

\n" + "

If selected, an existing directory may be cleared.

\n" + "

Also, available files of the tutorial solution may be downloaded to a " + "folder \"solution\", if requested.

\n" + "
\n"); + label->setWordWrap(true); + + auto *dirlayout = new QHBoxLayout; + auto *directory = new QLineEdit; + // if we are already in the tutorial folder, stay there + if (!current_dir.endsWith("tutorial2")) { + // if current dir is home, or application folder, switch to desktop path + if ((current_dir == QDir::homePath()) || current_dir.contains("AppData") || + current_dir.contains("Program Files")) { + current_dir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + } + current_dir += "/tutorial2"; + } + directory->setText(current_dir); + + auto *dirbutton = new QPushButton("&Choose"); + dirlayout->addWidget(directory); + dirlayout->addWidget(dirbutton); + directory->setObjectName("t2_directory"); + connect(dirbutton, &QPushButton::released, this, &LammpsGui::get_directory); + + auto *grid = new QGridLayout; + auto *purgeval = new QCheckBox; + auto *solval = new QCheckBox; + auto *purgelabel = new QLabel("Remove existing files from directory"); + auto *sollabel = new QLabel("Download solutions"); + purgeval->setCheckState(Qt::Unchecked); + purgeval->setObjectName("t2_dirpurge"); + solval->setCheckState(Qt::Unchecked); + solval->setObjectName("t2_getsolution"); + grid->addWidget(purgeval, 0, 0, Qt::AlignVCenter); + grid->addWidget(purgelabel, 0, 1, Qt::AlignVCenter); + grid->addWidget(solval, 1, 0, Qt::AlignVCenter); + grid->addWidget(sollabel, 1, 1, Qt::AlignVCenter); + grid->setColumnStretch(0, 0); + grid->setColumnStretch(1, 100); + + auto *layout = new QVBoxLayout(frame); + layout->addWidget(label); + layout->addLayout(dirlayout); + layout->addLayout(grid); + + page->setLayout(layout); + return page; +} + +QWizardPage *LammpsGui::tutorial2_finish() +{ + auto *page = new QWizardPage; + page->setTitle("Start Tutorial 2"); + page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + + auto *label = new QLabel("

You are now ready to start tutorial 2.

\n" + "
\n" + "

Click on the \"Finish\" button to " + "complete the setup.

"); label->setWordWrap(true); auto *layout = new QVBoxLayout; layout->addWidget(label); + layout->setStretch(0, 100); + page->setLayout(layout); return page; } @@ -1881,7 +1986,7 @@ void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, boo lammps.command(QString("shell cd " + dir).toLocal8Bit()); // read and process manifest - lammps.command(geturl.arg(1).arg(".manifest").toLocal8Bit()); + lammps.command(geturl.arg(tutno).arg(".manifest").toLocal8Bit()); QFile manifest(".manifest"); QString line, first; if (manifest.open(QIODevice::ReadOnly)) { @@ -1895,12 +2000,12 @@ void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, boo // file in subfolder if (line.contains('/')) { if (getsolution && line.startsWith("solution")) { - lammps.command(geturl.arg(1).arg(line).toLocal8Bit()); + lammps.command(geturl.arg(tutno).arg(line).toLocal8Bit()); } } else { // first file is the initial template if (first.isEmpty()) first = line; - lammps.command(geturl.arg(1).arg(line).toLocal8Bit()); + lammps.command(geturl.arg(tutno).arg(line).toLocal8Bit()); } } manifest.close(); @@ -1948,6 +2053,45 @@ void Tutorial1Wizard::accept() QDialog::accept(); } +Tutorial2Wizard::Tutorial2Wizard(QWidget *parent) : QWizard(parent) +{ + setWindowIcon(QIcon(":/icons/tutorial-logo.png")); +} + +// actions to perform when the wizard for tutorial 2 is complete +// and the user has clicked on "Finish" + +void Tutorial2Wizard::accept() +{ + // get pointers to the widgets with the information we need + auto *dirname = findChild("t2_directory"); + auto *dirpurge = findChild("t2_dirpurge"); + auto *getsol = findChild("t2_getsolution"); + + // create and populate directory. + if (dirname) { + QDir directory; + auto curdir = dirname->text().trimmed(); + if (!directory.mkpath(curdir)) { + QMessageBox::warning(this, "Warning", + "Cannot create tutorial 2 working directory " + curdir + + ".\n\nGoing back to directory selection."); + back(); + return; + } + + bool purgedir = dirpurge && (dirpurge->checkState() == Qt::Checked); + bool getsolution = getsol && (getsol->checkState() == Qt::Checked); + + // get hold of LAMMPS-GUI main widget + LammpsGui *main = nullptr; + for (QWidget *widget : QApplication::topLevelWidgets()) + if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); + if (main) main->setup_tutorial(2, curdir, purgedir, getsolution); + } + QDialog::accept(); +} + // Local Variables: // c-basic-offset: 4 // End: diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 255df4e150..ce89d23998 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -64,6 +64,7 @@ class LammpsGui : public QMainWindow { friend class CodeEditor; friend class GeneralTab; friend class Tutorial1Wizard; + friend class Tutorial2Wizard; public: LammpsGui(QWidget *parent = nullptr, const char *filename = nullptr); @@ -86,7 +87,9 @@ protected: QWizardPage *tutorial1_directory(); QWizardPage *tutorial1_finish(); QWizardPage *tutorial2_intro(); + QWizardPage *tutorial2_info(); QWizardPage *tutorial2_directory(); + QWizardPage *tutorial2_finish(); void setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution); void purge_inspect_list(); bool eventFilter(QObject *watched, QEvent *event) override; @@ -180,6 +183,13 @@ public: void accept() override; }; +class Tutorial2Wizard : public QWizard { + Q_OBJECT + +public: + Tutorial2Wizard(QWidget *parent = nullptr); + void accept() override; +}; #endif // LAMMPSGUI_H // Local Variables: diff --git a/tools/lammps-gui/lammpsgui.qrc b/tools/lammps-gui/lammpsgui.qrc index c6be49a40b..5de1a5efba 100644 --- a/tools/lammps-gui/lammpsgui.qrc +++ b/tools/lammps-gui/lammpsgui.qrc @@ -3,6 +3,7 @@ icons/lammps-icon-128x128.png icons/tutorial1-logo.png + icons/tutorial2-logo.png help_index.table lammps_internal_commands.txt