BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
SampleListModel.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/SampleDesigner/SampleListModel.cpp
6 //! @brief Implements class SampleListModel
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2021
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "Base/Util/Assert.h"
21 #include "GUI/Util/String.h"
25 #include "Sample/Multilayer/MultiLayer.h"
26 #include <QIcon>
27 
29  : QAbstractListModel(parent)
30  , m_sampleItems(model)
31 {
32 }
33 
34 int SampleListModel::rowCount(const QModelIndex& parent) const
35 {
36  if (parent.isValid())
37  return 0;
38 
39  return m_sampleItems->sampleItems().size();
40 }
41 
42 QVariant SampleListModel::data(const QModelIndex& index, int role) const
43 {
44  auto* const item = itemForIndex(index);
45 
46  if (role == Qt::ToolTipRole)
47  return item->description();
48 
49  if (role == Qt::DisplayRole) {
50  auto descr = item->description();
51  if (!descr.isEmpty()) {
52  descr.prepend("<br><br>");
53  const int maxDescriptionLines = 8;
54  while (descr.count("\n") >= maxDescriptionLines) {
55  descr.truncate(descr.lastIndexOf("\n"));
56  descr += " [...]";
57  }
58  descr.replace("\n", "<br>");
59  }
60  return "<b>" + item->sampleName() + "</b>" + descr;
61  }
62 
63  if (role == Qt::EditRole)
64  return item->sampleName();
65 
66  return QVariant();
67 }
68 
69 Qt::ItemFlags SampleListModel::flags(const QModelIndex& index) const
70 {
71  auto f = QAbstractItemModel::flags(index);
72  f |= Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
73 
74  return f;
75 }
76 
77 bool SampleListModel::setData(const QModelIndex& index, const QVariant& value, int role)
78 {
79  if (!index.isValid())
80  return false;
81 
82  if (role == Qt::EditRole && index.column() == 0) {
83  itemForIndex(index)->setSampleName(value.toString());
84  emit dataChanged(index, index);
85  return true;
86  }
87 
88  if (role == Qt::ToolTipRole && index.column() == 0) {
89  itemForIndex(index)->setDescription(value.toString());
90  emit dataChanged(index, index);
91  return true;
92  }
93 
94  return false;
95 }
96 
97 MultiLayerItem* SampleListModel::itemForIndex(const QModelIndex& index) const
98 {
99  if (!index.isValid())
100  return nullptr;
101 
102  return m_sampleItems->sampleItems()[index.row()];
103 }
104 
106 {
107  if (auto row = m_sampleItems->sampleItems().indexOf(item); row >= 0)
108  return index(row, 0);
109 
110  return QModelIndex();
111 }
112 
114 {
115  QModelIndex index = indexForItem(item);
116  if (!index.isValid())
117  return;
118 
119  beginRemoveRows(index.parent(), index.row(), index.row());
121  endRemoveRows();
122 }
123 
125 {
126  const QStringList existingNames = m_sampleItems->sampleNames();
127 
128  const int row = m_sampleItems->sampleItems().size();
129  beginInsertRows(QModelIndex(), row, row);
130  auto* sample_item = m_sampleItems->addMultiLayer();
131  sample_item->setSampleName(GUI::Util::String::suggestName(existingNames, "Sample"));
132  sample_item->addStandardMaterials();
133  endInsertRows();
134  return indexForItem(sample_item);
135 }
136 
137 QModelIndex SampleListModel::createSampleFromExamples(const QString& className,
138  const QString& title,
139  const QString& description)
140 {
141  try {
142  auto* sample =
143  dynamic_cast<MultiLayerItem*>(GUI::ExamplesFactory::itemizeSample(className));
144  if (!sample)
145  return {};
146  sample->setSampleName(title);
147  sample->setDescription(description);
148 
149  const int row = m_sampleItems->sampleItems().size();
150  beginInsertRows(QModelIndex(), row, row);
151  m_sampleItems->addMultiLayer(sample);
152  endInsertRows();
153  return indexForItem(sample);
154  } catch (const std::exception& ex) {
155  QString message("Exception thrown while trying to build GUI models.\n");
156  QString details = QString::fromStdString(ex.what());
157  DetailedMessageBox(GUI::Global::mainWindow, "Example builder failure", message, details)
158  .exec();
159  return {};
160  }
161 }
162 
163 #ifdef BORNAGAIN_PYTHON
165 {
166  auto sample = PyImportAssistant::importMultiLayer();
167  if (!sample)
168  return {}; // any messages already shown to user; no dlg necessary anymore
169 
170 
171  auto* sampleItem = PyImportAssistant::itemizeSample(*sample);
172  if (!sampleItem)
173  return {}; // any messages already shown to user; no dlg necessary anymore
174 
175  sampleItem->setDescription("Imported from python code");
176 
177  const int row = m_sampleItems->sampleItems().size();
178  beginInsertRows(QModelIndex(), row, row);
179  m_sampleItems->addMultiLayer(sampleItem);
180  endInsertRows();
181  return indexForItem(sampleItem);
182 }
183 #endif
Defines class DetailedMessageBox.
Defines class GUI::ExamplesFactory.
Defines global pointers.
Defines class GUISampleBuilder.
Defines class MultiLayerItem.
Defines class MultiLayerItems.
Implements class PyImportAssistant.
Defines class SampleListModel.
Defines functions from namespace GUI::Util::String.
A dialog similar to standard QMessageBox intended for detailed warning messages. On the contrary to Q...
void setDescription(const QString &description)
void setSampleName(const QString &name)
Main model to hold sample items.
void removeMultiLayer(MultiLayerItem *sample)
QStringList sampleNames() const
QVector< MultiLayerItem * > sampleItems() const
MultiLayerItem * addMultiLayer()
Adds a sample and returns the new item.
QModelIndex createSample()
Create a new sample (sample) and return the index of it.
Qt::ItemFlags flags(const QModelIndex &index) const override
SampleListModel(QObject *parent, MultiLayerItems *model)
QModelIndex createSampleFromPython()
Create sample from an imported python code.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void removeSample(MultiLayerItem *item)
Remove the given sample. nullptr is allowed.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
MultiLayerItem * itemForIndex(const QModelIndex &index) const
bool setData(const QModelIndex &index, const QVariant &value, int role) override
MultiLayerItems * m_sampleItems
QModelIndex createSampleFromExamples(const QString &className, const QString &title, const QString &description)
Create sample from list of built-in examples.
QModelIndex indexForItem(MultiLayerItem *item) const
MultiLayerItem * itemizeSample(const QString &name)
Create a sample item of the built-in example with the given internal name.
static QMainWindow * mainWindow
Definition: Globals.h:22
QString suggestName(const QStringList &existingNames, const QString &name)
Returns a name suggestion based on the given name.
Definition: String.cpp:26
MultiLayerItem * itemizeSample(const MultiLayer &sample)
Populates GUI sample with domain sample.
std::unique_ptr< MultiLayer > importMultiLayer()
Show select-file dialog, try to import via python, return created sample.