BornAgain  1.19.0
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/coregui/Views/SimulationWidgets/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 
24 #include <QFileDialog>
25 #include <QMessageBox>
26 #include <QPushButton>
27 #include <QStandardPaths>
28 #include <QStyle>
29 #include <QTextEdit>
30 #include <QTextStream>
31 #include <QToolBar>
32 #include <QVBoxLayout>
33 #include <memory>
34 
36  : QDialog(parent)
37  , m_toolBar(nullptr)
38  , m_textEdit(new QTextEdit)
39  , m_warningSign(new WarningSign(m_textEdit))
40 {
41  setWindowTitle("Python Script View");
42  setMinimumSize(128, 128);
43  resize(512, 400);
44  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
45 
46  m_toolBar = new QToolBar;
47  m_toolBar->setFixedHeight(28);
48  m_toolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
49  const int size = style()->pixelMetric(QStyle::PM_SmallIconSize);
50  m_toolBar->setIconSize(QSize(size, size));
51  m_toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
52 
53  QPushButton* exportToFileButton = new QPushButton;
54  exportToFileButton->setText("Save to file");
55  exportToFileButton->setToolTip("Opens dialog to save given script into the file");
56  connect(exportToFileButton, &QPushButton::clicked, this,
58  exportToFileButton->setAutoDefault(false);
59  m_toolBar->addWidget(exportToFileButton);
60 
61  m_textEdit->setReadOnly(true);
62  QFont textFont("Monospace");
63  m_textEdit->setFont(textFont);
65  m_textEdit->setLineWrapMode(QTextEdit::NoWrap);
66  PythonSyntaxHighlighter* highlighter = new PythonSyntaxHighlighter(m_textEdit->document());
67  Q_UNUSED(highlighter);
68 
69  QVBoxLayout* mainLayout = new QVBoxLayout;
70  mainLayout->setContentsMargins(0, 0, 0, 0);
71  mainLayout->setMargin(0);
72  mainLayout->setSpacing(0);
73  mainLayout->addWidget(m_toolBar);
74  mainLayout->addWidget(m_textEdit);
75 
76  setLayout(mainLayout);
77 
78  setAttribute(Qt::WA_DeleteOnClose, true);
80 }
81 
83  const InstrumentItem* instrumentItem,
84  const SimulationOptionsItem* optionItem,
85  const QString& outputDir)
86 {
87  m_outputDir = outputDir;
89 
90  try {
91  const auto simulation =
92  DomainSimulationBuilder::createSimulation(sampleItem, instrumentItem, optionItem);
93 
94  QString code = QString::fromStdString(ExportToPython::simulationPlotCode(*simulation));
95  m_textEdit->clear();
96  m_textEdit->setText(code);
97 
98  } catch (const std::exception& ex) {
99  QString message =
100  QString(
101  "Generation of Python Script failed. Code is not complete.\n\n"
102  "It can happen if sample requires further assembling or some of sample parameters "
103  "are not valid. See details below.\n\n%1")
104  .arg(QString::fromStdString(ex.what()));
105 
107  }
108 }
109 
111 {
112  QString dirname(m_outputDir);
113  if (dirname.isEmpty())
114  dirname = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
115 
116  QString filters("Python scripts (*.py)");
117  QString defaultFilter("Python scripts (*.py)");
118  QString defaultName = dirname + "/untitled";
119 
120  QString fileName =
121  QFileDialog::getSaveFileName(nullptr, "Save file", defaultName, filters, &defaultFilter);
122 
123  if (fileName.isEmpty())
124  return;
125 
126  if (!fileName.endsWith(".py"))
127  fileName += ".py";
128 
129  QFile file(fileName);
130  if (!file.open(QIODevice::WriteOnly)) {
131  QMessageBox warning_dialog(this);
132  warning_dialog.setIcon(QMessageBox::Warning);
133  warning_dialog.setText("File could not be opened for writing!");
134  warning_dialog.exec();
135  return;
136  }
137  QTextStream out(&file);
138  out << m_textEdit->toPlainText();
139  file.close();
140  raise();
141 }
Defines class DesignerHelper.
Defines class DomainSimulationBuilder.
Defines ExportToPython namespace.
Defines class GISASSimulation.
Defines InstrumentItems classes.
Defines class PythonScriptWidget.
Defines class PythonSyntaxHighlighter.
DefinesStyleUtils namespace.
Defines class WarningSign.
static int getPythonEditorFontSize()
PythonScriptWidget(QWidget *parent=0)
WarningSign * m_warningSign
void generatePythonScript(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const SimulationOptionsItem *optionItem=0, const QString &outputDir="")
Implementation of highlighting for Python code.
The SimulationOptionsItem class holds simulation status (run policy, number of threads,...
The WarningSign controls appearance of WarningSignWidget on top of parent widget.
Definition: WarningSign.h:25
void clear()
Clears warning message;.
Definition: WarningSign.cpp:40
void setWarningMessage(const QString &warningMessage)
Shows warning sign on the screen.
Definition: WarningSign.cpp:58
std::unique_ptr< ISimulation > createSimulation(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const SimulationOptionsItem *optionsItem=nullptr)
Creates domain simulation from sample and instrument items.
std::string simulationPlotCode(const ISimulation &simulation)
void setResizable(QDialog *dialog)
Make modal dialog resizable.
Definition: StyleUtils.cpp:87