BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
PythonScriptWidget.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Script/PythonScriptWidget.cpp
6 //! @brief Implements class PythonScriptWidget
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
23 #include "Sim/Export/ExportToPython.h"
24 #include "Sim/Simulation/ScatteringSimulation.h"
25 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QPushButton>
28 #include <QStandardPaths>
29 #include <QStyle>
30 #include <QTextEdit>
31 #include <QTextStream>
32 #include <QToolBar>
33 #include <QVBoxLayout>
34 #include <memory>
35 
37  : QDialog(parent)
38  , m_textEdit(new QTextEdit)
39  , m_cautionSign(new CautionSign(m_textEdit))
40 {
41  setObjectName("PythonScriptWidget");
42  setWindowTitle("Python Script");
43  setMinimumSize(128, 128);
44  resize(512, 400);
45  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
46 
47  auto* toolbar = new StyledToolbar;
48  toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
49 
50  auto* exportAction = new QAction(this);
51  exportAction->setIcon(QIcon(":/images/content-save-outline.svg"));
52  exportAction->setText("Save to file");
53  exportAction->setToolTip("Opens dialog to save given script into the file");
54  connect(exportAction, &QAction::triggered, this, &PythonScriptWidget::onExportToFileButton);
55 
56  toolbar->addAction(exportAction);
57 
58  m_textEdit->setReadOnly(true);
59  QFont textFont("Monospace");
60  m_textEdit->setFont(textFont);
62  m_textEdit->setLineWrapMode(QTextEdit::NoWrap);
63  auto* highlighter = new PythonSyntaxHighlighter(m_textEdit->document());
64  Q_UNUSED(highlighter);
65 
66  auto* mainLayout = new QVBoxLayout;
67  mainLayout->setContentsMargins(0, 0, 0, 0);
68  mainLayout->setMargin(0);
69  mainLayout->setSpacing(0);
70  mainLayout->addWidget(toolbar);
71  mainLayout->addWidget(m_textEdit);
72 
73  setLayout(mainLayout);
74 
75  setAttribute(Qt::WA_DeleteOnClose, true);
78 }
79 
80 
82 {
84 }
85 
87  const InstrumentItem* instrumentItem,
88  const SimulationOptionsItem& optionItem,
89  const QString& outputDir)
90 {
91  m_outputDir = outputDir;
93 
94  try {
95  const auto simulation =
96  GUI::Transform::ToCore::itemsToSimulation(sampleItem, instrumentItem, optionItem);
97 
98  QString code = QString::fromStdString(Py::Export::simulationPlotCode(*simulation));
99  m_textEdit->clear();
100  m_textEdit->setText(code);
101  } catch (const std::exception& ex) {
102  QString message =
103  QString(
104  "Generation of Python Script failed. Code is not complete.\n\n"
105  "It can happen if sample requires further assembling or some of sample parameters "
106  "are not valid. See details below.\n\n%1")
107  .arg(QString::fromStdString(ex.what()));
108 
110  }
111 }
112 
114 {
115  QString dirname(m_outputDir);
116  if (dirname.isEmpty())
117  dirname = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
118 
119  QString filters("Python scripts (*.py)");
120  QString defaultFilter("Python scripts (*.py)");
121  QString defaultName = dirname + "/untitled";
122 
123  QString fileName = QFileDialog::getSaveFileName(
124  nullptr, "Save file", defaultName, filters, &defaultFilter,
125  appSettings->useNativeFileDialog() ? QFileDialog::Options()
126  : QFileDialog::DontUseNativeDialog);
127 
128  if (fileName.isEmpty())
129  return;
130 
131  if (!fileName.endsWith(".py"))
132  fileName += ".py";
133 
134  QFile file(fileName);
135  if (!file.open(QIODevice::WriteOnly)) {
136  QMessageBox::warning(this, "Save Python file", "File could not be opened for writing!");
137  return;
138  }
139  QTextStream out(&file);
140  out << m_textEdit->toPlainText();
141  file.close();
142  raise();
143 }
ApplicationSettings * appSettings
global pointer to the instance
Defines class ApplicationSettings.
Defines class CautionSign.
Defines class DesignerHelper.
Defines class PythonScriptWidget.
Defines class PythonSyntaxHighlighter.
Defines namespace GUI::Transform::ToCore.
Defines GUI::StyleUtils namespace.
Defines class StyledToolbar.
void loadWindowSizeAndPos(QWidget *w)
void saveWindowSizeAndPos(const QWidget *w)
bool useNativeFileDialog() const
The CautionSign controls appearance of CautionSignWidget on top of parent widget.
Definition: CautionSign.h:25
void clear()
Clears caution message;.
Definition: CautionSign.cpp:42
void setCautionMessage(const QString &cautionMessage)
Shows caution sign on the screen. If clear of previous caution sign had happened just few msec ago,...
Definition: CautionSign.cpp:60
static int getPythonEditorFontSize()
Abstract base class for instrument-specific item classes.
PythonScriptWidget(QWidget *parent=nullptr)
CautionSign * m_cautionSign
void generatePythonScript(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const SimulationOptionsItem &optionItem, const QString &outputDir="")
Implementation of highlighting for Python code.
The SimulationOptionsItem class holds simulation status (run policy, number of threads,...
The StyledToolbar class represents our standard narrow toolbar with the height 24 pixels.
Definition: StyledToolbar.h:22
std::unique_ptr< ISimulation > itemsToSimulation(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const SimulationOptionsItem &optionsItem)
Creates domain simulation from sample and instrument items.
void setResizable(QDialog *dialog)
Make modal dialog resizable.
Definition: StyleUtils.cpp:100
void warning(QWidget *parent, const QString &title, const QString &text, const QString &detailedText)
Definition: MessageBox.cpp:37