Mantid
Loading...
Searching...
No Matches
EditLocalParameterDialog.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
11
12#include <QClipboard>
13#include <QMenu>
14#include <QMessageBox>
15#include <limits>
16#include <utility>
17
18namespace {
19QString makeNumber(double d) { return QString::number(d, 'g', 16); }
20const int valueColumn = 0;
21const int roleColumn = 1;
22} // namespace
23
25
37EditLocalParameterDialog::EditLocalParameterDialog(QWidget *parent, const QString &parName,
38 const QStringList &datasetNames,
39 const QStringList &datasetDomainNames, const QList<double> &values,
40 const QList<bool> &fixes, const QStringList &ties,
41 const QStringList &constraints)
42 : MantidDialog(parent), m_parName(parName), m_values(values), m_fixes(fixes), m_ties(std::move(ties)),
43 m_constraints(std::move(constraints)) {
44 assert(values.size() == datasetDomainNames.size());
45 assert(fixes.size() == datasetDomainNames.size());
46 assert(ties.size() == datasetDomainNames.size());
47 assert(constraints.size() == datasetDomainNames.size());
48 m_uiForm.setupUi(this);
49 setAttribute(Qt::WA_DeleteOnClose);
50 doSetup(parName, datasetNames, datasetDomainNames);
51}
52
61void EditLocalParameterDialog::doSetup(const QString &parName, const QStringList &datasetNames,
62 const QStringList &datasetDomainNames) {
63 m_logFinder = std::make_unique<LogValueFinder>(datasetNames);
64 // Populate list of logs
65 auto *logCombo = m_uiForm.logValueSelector->getLogComboBox();
66 for (const auto &logName : m_logFinder->getLogNames()) {
67 logCombo->addItem(QString::fromStdString(logName));
68 }
69
70 m_uiForm.logValueSelector->setCheckboxShown(true);
71 connect(m_uiForm.logValueSelector, SIGNAL(logOptionsEnabled(bool)), this, SIGNAL(logOptionsChecked(bool)));
72 QHeaderView *header = m_uiForm.tableWidget->horizontalHeader();
73 header->setSectionResizeMode(QHeaderView::Stretch);
74 connect(m_uiForm.tableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(valueChanged(int, int)));
75 m_uiForm.lblParameterName->setText("Parameter: " + parName);
76
77 for (int i = 0; i < datasetDomainNames.size(); i++) {
78 m_uiForm.tableWidget->insertRow(i);
79 auto cell = new QTableWidgetItem(makeNumber(m_values[i]));
80 m_uiForm.tableWidget->setItem(i, valueColumn, cell);
81 auto headerItem = new QTableWidgetItem(datasetDomainNames[i]);
82 m_uiForm.tableWidget->setVerticalHeaderItem(i, headerItem);
83 cell = new QTableWidgetItem("");
84 auto flags = cell->flags();
85 flags ^= Qt::ItemIsEditable;
86 flags ^= Qt::ItemIsSelectable;
87 flags ^= Qt::ItemIsEnabled;
88 cell->setFlags(flags);
89 m_uiForm.tableWidget->setItem(i, roleColumn, cell);
91 }
92 auto deleg = new LocalParameterItemDelegate(this);
93 m_uiForm.tableWidget->setItemDelegateForColumn(valueColumn, deleg);
94 connect(deleg, SIGNAL(setAllValues(double)), this, SLOT(setAllValues(double)));
95 connect(deleg, SIGNAL(fixParameter(int, bool)), this, SLOT(fixParameter(int, bool)));
96 connect(deleg, SIGNAL(setAllFixed(bool)), this, SLOT(setAllFixed(bool)));
97 connect(deleg, SIGNAL(setTie(int, QString)), this, SLOT(setTie(int, QString)));
98 connect(deleg, SIGNAL(setTieAll(QString)), this, SLOT(setTieAll(QString)));
99 connect(deleg, SIGNAL(setConstraint(int, QString)), this, SLOT(setConstraint(int, QString)));
100 connect(deleg, SIGNAL(setConstraintAll(QString)), this, SLOT(setConstraintAll(QString)));
101 connect(deleg, SIGNAL(setValueToLog(int)), this, SLOT(setValueToLog(int)));
102 connect(deleg, SIGNAL(setAllValuesToLog()), this, SLOT(setAllValuesToLog()));
103
104 m_uiForm.tableWidget->installEventFilter(this);
105}
106
111 if (col == valueColumn) {
112 QString text = m_uiForm.tableWidget->item(row, col)->text();
113 try {
114 bool ok = false;
115 double value = text.toDouble(&ok);
116 if (ok) {
117 m_values[row] = value;
118 } else {
119 m_ties[row] = text;
120 }
121 } catch (std::exception &) {
122 // restore old value
123 m_uiForm.tableWidget->item(row, col)->setText(makeNumber(m_values[row]));
124 }
125 }
126}
127
131 int n = m_values.size();
132 for (int i = 0; i < n; ++i) {
133 m_values[i] = value;
134 m_uiForm.tableWidget->item(i, valueColumn)->setText(makeNumber(value));
136 }
137}
138
141
144
146QStringList EditLocalParameterDialog::getTies() const { return m_ties; }
147
150
155 m_fixes[index] = fix;
156 m_ties[index] = "";
158}
159
164 m_ties[index] = std::move(tie);
165 m_fixes[index] = false;
167}
168
171void EditLocalParameterDialog::setTieAll(const QString &tie) {
172 for (int i = 0; i < m_ties.size(); ++i) {
173 m_ties[i] = tie;
174 m_fixes[i] = false;
176 }
177 redrawCells();
178}
179
180void EditLocalParameterDialog::setConstraint(int index, QString constraint) {
181 m_constraints[index] = std::move(constraint);
183}
184
185void EditLocalParameterDialog::setConstraintAll(const QString &constraint) {
186 for (int i = 0; i < m_constraints.size(); ++i) {
187 m_constraints[i] = constraint;
189 }
190 redrawCells();
191}
192
196 if (m_fixes.empty())
197 return;
198 for (int i = 0; i < m_fixes.size(); ++i) {
199 m_fixes[i] = fix;
200 m_ties[i] = "";
202 }
203 redrawCells();
204}
205
207bool EditLocalParameterDialog::eventFilter(QObject *obj, QEvent *ev) {
208 if (obj == m_uiForm.tableWidget && ev->type() == QEvent::ContextMenu) {
210 }
211 return QDialog::eventFilter(obj, ev);
212}
213
216 auto selection = m_uiForm.tableWidget->selectionModel()->selectedColumns();
217
218 bool hasSelection = false;
219
220 for (auto &index : selection) {
221 if (index.column() == valueColumn)
222 hasSelection = true;
223 }
224
225 if (!hasSelection)
226 return;
227
228 QMenu *menu = new QMenu(this);
229 {
230 QAction *action = new QAction("Copy", this);
231 action->setToolTip("Copy data to clipboard.");
232 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
233 menu->addAction(action);
234 }
235 {
236 QAction *action = new QAction("Paste", this);
237 action->setToolTip("Paste data from clipboard.");
238 connect(action, SIGNAL(triggered()), this, SLOT(paste()));
239 auto text = QApplication::clipboard()->text();
240 action->setEnabled(!text.isEmpty());
241 menu->addAction(action);
242 }
243
244 menu->exec(QCursor::pos());
245}
246
250 QStringList text;
251 auto n = m_values.size();
252 for (int i = 0; i < n; ++i) {
253 text << makeNumber(m_values[i]);
254 }
255 QApplication::clipboard()->setText(text.join("\n"));
256}
257
260 auto text = QApplication::clipboard()->text();
261 auto vec = text.split(QRegExp("\\s|,"), Qt::SkipEmptyParts);
262 auto n = qMin(vec.size(), m_uiForm.tableWidget->rowCount());
263 // prepare for pasting data
264 auto deleg = static_cast<LocalParameterItemDelegate *>(m_uiForm.tableWidget->itemDelegateForColumn(valueColumn));
265 deleg->prepareForPastedData();
266 // insert data into table
267 for (int i = 0; i < n; ++i) {
268 auto str = vec[i];
269 bool ok;
270 m_values[i] = str.toDouble(&ok);
271 if (!ok)
272 str = "0";
273 m_uiForm.tableWidget->item(i, valueColumn)->setText(str);
274 }
275}
276
279 for (int i = 0; i < m_values.size(); ++i) {
280 // it's the only way I am able to make the table to repaint itself
281 auto text = makeNumber(m_values[i]);
282 m_uiForm.tableWidget->item(i, valueColumn)->setText(text + " ");
283 m_uiForm.tableWidget->item(i, valueColumn)->setText(text);
284 }
285}
286
289 auto cell = m_uiForm.tableWidget->item(index, roleColumn);
290 QString text;
291 if (m_fixes[index]) {
292 text = "fixed";
293 cell->setForeground(QBrush(Qt::red));
294 } else if (!m_ties[index].isEmpty()) {
295 text = "tied";
296 cell->setForeground(QBrush(Qt::blue));
297 } else {
298 text = "fitted";
299 cell->setForeground(QBrush(Qt::darkGreen));
300 }
301 if (!m_constraints[index].isEmpty()) {
302 text += ", " + m_constraints[index];
303 }
304 cell->setText(text);
305}
306
309 for (int j = 0; j < m_fixes.size(); ++j) {
310 if (j != i && m_fixes[j])
311 return true;
312 }
313 return false;
314}
315
318 for (int j = 0; j < m_fixes.size(); ++j) {
319 if (j != i && !m_fixes[j])
320 return false;
321 }
322 return true;
323}
324
327 for (int j = 0; j < m_fixes.size(); ++j) {
328 if (j != i && !m_ties[j].isEmpty())
329 return true;
330 }
331 return false;
332}
333
337 assert(i < m_values.size());
338
339 const auto &logName = m_uiForm.logValueSelector->getLog();
340 const auto &function = m_uiForm.logValueSelector->getFunction();
341
342 double value = std::numeric_limits<double>::quiet_NaN();
343 try {
344 value = m_logFinder->getLogValue(logName, function, i);
345 } catch (const std::invalid_argument &err) {
346 const auto &message = QString("Failed to get log value:\n\n %1").arg(err.what());
347 QMessageBox::critical(this, "Mantid - Error", message);
348 }
349 m_values[i] = value;
350 m_uiForm.tableWidget->item(i, valueColumn)->setText(makeNumber(value));
352}
353
356 const int nValues = m_values.size();
357 for (int i = 0; i < nValues; ++i) {
358 setValueToLog(i);
359 }
360}
361
364bool EditLocalParameterDialog::isLogCheckboxTicked() const { return m_uiForm.logValueSelector->isCheckboxTicked(); }
365
366} // namespace MantidQt::MantidWidgets
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
double obj
the value of the quadratic function
std::unique_ptr< LogValueFinder > m_logFinder
Log value finder.
void setTieAll(const QString &)
Set the same tie to all parameters.
QList< bool > m_fixes
Cache for the "fixed" attribute.
void copy()
Copy all parameter values to the clipboard.
bool areAllOthersFixed(int i) const
Check if all other parameters are fixed.
QList< double > getValues() const
Get the list of new parameter values.
void updateRoleColumn(int index)
Update the text in the role column.
void fixParameter(int, bool)
Fix/unfix a single parameter.
QStringList m_constraints
Cache for the constraints.
void doSetup(const QString &parName, const QStringList &datasetDomains, const QStringList &datasetDomainNames)
Common setup method used by both constructors Prerequisite: one of the constructors must have filled ...
QStringList getConstraints() const
Get a list of the constraints.
QList< double > m_values
Cache for new values. size() == number of spectra.
EditLocalParameterDialog(QWidget *parent, const QString &parName, const QStringList &datasetNames, const QStringList &datasetDomainNames, const QList< double > &values, const QList< bool > &fixes, const QStringList &ties, const QStringList &constraints)
Constructor for EditLocalParameterDialog used in FunctionBrowser.
bool areOthersTied(int i) const
Check if there are any other tied parameters.
bool eventFilter(QObject *obj, QEvent *ev) override
Event filter for managing the context menu.
void paste()
Paste a list of values from the clipboard.
bool isLogCheckboxTicked() const
Returns whether log checkbox is ticked or not.
void redrawCells()
Force the table to redraw its cells.
QStringList getTies() const
Get a list of the ties.
void setTie(int, QString)
Set a new tie for a parameter.
QList< bool > getFixes() const
Get a list with the "fixed" attribute.
bool areOthersFixed(int i) const
Check if there are any other fixed parameters.
void setAllValues(double)
Set all parameters to the same value.
void setAllValuesToLog()
Set value of each parameter to log value from respective workspace.
A custom item delegate - an object controlling display and editing of a cell in a table widget.
void prepareForPastedData()
Data is about to be pasted into the table.
STL namespace.