Vuo  2.0.1
VuoInputEditorMathExpressionList.cc
Go to the documentation of this file.
1 
11 #include "VuoInputEditorIcon.hh"
12 
13 extern "C"
14 {
15  #include "VuoHeap.h"
16  #include "VuoMathExpressionList.h"
17  #include "VuoMathExpressionParser.h"
18 }
19 
24 {
26 }
27 
32  : VuoInputEditorWithLineEditList(false, 200)
33 {
34  hasError = false;
35  errorMessage = NULL;
36  originalValue = NULL;
37 
38  QString validCharacters = QString(" _0-9a-zA-Z=&|<>!+*/^%?:()");
39  validCharacters.append( getDecimalPointInUserLocale() ); // . or ,
40  validCharacters.append( getListSeparatorInUserLocale() ); // , or ;
41  QString validCharactersEscaped = QRegExp::escape(validCharacters);
42  validCharactersEscaped.append("\\-"); // not escaped by QRegExp::escape()
43  QRegExp regExp( QString("([%1])*").arg(validCharactersEscaped) );
44  validator = new QRegExpValidator(regExp, this);
45 }
46 
50 void VuoInputEditorMathExpressionList::setUpDialog(QDialog &dialog, json_object *originalValue, json_object *details)
51 {
52  VuoInputEditorWithLineEditList::setUpDialog(dialog, originalValue, details);
53 
54  this->originalValue = originalValue;
55 
56  dialog.installEventFilter(this);
57 }
58 
62 QLayout * VuoInputEditorMathExpressionList::setUpRow(QDialog &dialog, QLineEdit *lineEdit)
63 {
64  QLayout *rowLayout = VuoInputEditorWithLineEditList::setUpRow(dialog, lineEdit);
65 
66  QPixmap *errorPixmap = VuoInputEditorIcon::renderErrorPixmap(isDark);
67  QLabel *errorLabel = new QLabel(lineEdit);
68  errorLabel->setPixmap(*errorPixmap);
69  errorLabel->adjustSize();
70  errorLabel->move(lineEdit->width() - errorLabel->width() - rowLayout->spacing(),
71  (lineEdit->height() - errorLabel->height()) / 2.);
72  errorLabel->setVisible(false);
73  errorSymbols.insert(rowLayout, errorLabel);
74  delete errorPixmap;
75 
76  lineEdit->setValidator(validator);
77  connect(lineEdit, &QLineEdit::editingFinished, this, &VuoInputEditorMathExpressionList::validate);
78 
79  return rowLayout;
80 }
81 
85 void VuoInputEditorMathExpressionList::tearDownRow(QLayout *rowLayout)
86 {
87  errorSymbols.remove(rowLayout);
88 }
89 
94 json_object * VuoInputEditorMathExpressionList::getAcceptedValue(void)
95 {
96  if (! isMathExpressionListValid())
97  return originalValue; // ... in case the user closed the input editor by clicking away from it.
98 
100 }
101 
105 QList<QString> VuoInputEditorMathExpressionList::convertToLineEditListFormat(json_object *value)
106 {
107  QList<QString> lineEditTexts;
108 
110  unsigned long expressionCount = VuoListGetCount_VuoText(expressionList.expressions);
111  for (unsigned long i = 1; i <= expressionCount; ++i)
112  {
113  VuoText expression = VuoListGetValue_VuoText(expressionList.expressions, i);
114  QString expressionString = convertToUserLocale(expression);
115  lineEditTexts.append(expressionString);
116  }
117 
118  return lineEditTexts;
119 }
120 
124 json_object * VuoInputEditorMathExpressionList::convertFromLineEditListFormat(const QList<QString> &lineEditTexts)
125 {
126  VuoList_VuoText expressions = getExpressionsFromLineEditTexts(lineEditTexts);
127 
128  VuoMathExpressionList expressionList = VuoMathExpressionList_make(expressions);
129  json_object *value = VuoMathExpressionList_getJson(expressionList);
130 
131  VuoMathExpressionList_retain(expressionList);
132  VuoMathExpressionList_release(expressionList);
133 
134  return value;
135 }
136 
140 VuoList_VuoText VuoInputEditorMathExpressionList::getExpressionsFromLineEditTexts(const QList<QString> &lineEditTexts)
141 {
142  VuoList_VuoText expressions = VuoListCreate_VuoText();
143 
144  foreach (QString lineEditText, lineEditTexts)
145  {
146  if (! lineEditText.isEmpty())
147  {
148  QString expressionString = convertFromUserLocale(lineEditText);
149  VuoText expression = VuoText_make(expressionString.toUtf8().constData());
150  VuoListAppendValue_VuoText(expressions, expression);
151  }
152  }
153 
154  return expressions;
155 }
156 
160 QString VuoInputEditorMathExpressionList::convertToUserLocale(QString valueInStandardLocale)
161 {
162  return valueInStandardLocale
163  .replace(',', getListSeparatorInUserLocale())
164  .replace('.', getDecimalPointInUserLocale());
165 }
166 
170 QString VuoInputEditorMathExpressionList::convertFromUserLocale(QString valueInUserLocale)
171 {
172  return valueInUserLocale
173  .replace(getDecimalPointInUserLocale(), '.')
174  .replace(getListSeparatorInUserLocale(), ',');
175 }
176 
180 QChar VuoInputEditorMathExpressionList::getDecimalPointInUserLocale(void)
181 {
182  return QLocale().decimalPoint();
183 }
184 
188 QChar VuoInputEditorMathExpressionList::getListSeparatorInUserLocale(void)
189 {
190  return getDecimalPointInUserLocale() == '.' ? ',' : ';';
191 }
192 
196 void VuoInputEditorMathExpressionList::validate()
197 {
198  validateMathExpressionList(false);
199 }
200 
204 void VuoInputEditorMathExpressionList::validateMathExpressionList(bool shouldCheckForAtLeastOneExpression)
205 {
206  QString errorMessageString;
207  VuoList_VuoInteger errorExpressions = NULL;
208 
209  QList<QString> lineEditTexts = getLineEditTexts();
210  VuoList_VuoText expressions = getExpressionsFromLineEditTexts(lineEditTexts);
211  bool hasNoExpressions = (VuoListGetCount_VuoText(expressions) == 0);
212 
213  if (hasNoExpressions)
214  {
215  if (shouldCheckForAtLeastOneExpression)
216  errorMessageString = "There must be at least one math expression.";
217  }
218  else
219  {
220  VuoMathExpressionError error = NULL;
222  hasError = (error != NULL);
223 
224  if (error)
225  {
226  errorMessageString = VuoMathExpressionError_getMessage(error);
227  errorExpressions = VuoMathExpressionError_getExpressionIndices(error);
229  }
230  }
231 
232  VuoRetain(expressions);
233  VuoRelease(expressions);
234 
235  if (errorMessage)
236  {
237  removeWidgetFromDialog(errorMessage);
238  delete errorMessage;
239  errorMessage = NULL;
240  }
241 
242  foreach (QLabel *errorSymbol, errorSymbols.values())
243  errorSymbol->setVisible(false);
244 
245  if (! errorMessageString.isEmpty())
246  {
247  errorMessage = new QLabel(errorMessageString);
248  errorMessage->setWordWrap(true);
249  addWidgetToDialog(errorMessage);
250 
251  if (errorExpressions)
252  {
253  unsigned long count = VuoListGetCount_VuoInteger(errorExpressions);
254  for (unsigned long i = 1; i <= count; ++i)
255  {
256  int indexIgnoringEmptyStrings = VuoListGetValue_VuoInteger(errorExpressions, i) - 1;
257 
258  int index;
259  int nonEmptyStringIndex = 0;
260  for (index = 0; index < lineEditTexts.size(); ++index)
261  if (! lineEditTexts.at(index).isEmpty())
262  if (nonEmptyStringIndex++ == indexIgnoringEmptyStrings)
263  break;
264 
265  QLayout *rowLayout = getRowAtIndex(index);
266  QLabel *errorSymbol = errorSymbols.value(rowLayout);
267  errorSymbol->setVisible(true);
268  }
269 
270  VuoRetain(errorExpressions);
271  VuoRelease(errorExpressions);
272  }
273  }
274 }
275 
279 bool VuoInputEditorMathExpressionList::isMathExpressionListValid(void)
280 {
281  VuoList_VuoText expressions = getExpressionsFromLineEditTexts( getLineEditTexts() );
282  bool hasNoExpressions = (VuoListGetCount_VuoText(expressions) == 0);
283  VuoRetain(expressions);
284  VuoRelease(expressions);
285  return ! hasError && ! hasNoExpressions;
286 }
287 
292 bool VuoInputEditorMathExpressionList::eventFilter(QObject *o, QEvent *event)
293 {
294  if (event->type() == QEvent::KeyPress)
295  {
296  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
297  if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
298  {
299  validateMathExpressionList(true);
300  if (! isMathExpressionListValid())
301  return true;
302  }
303  }
304 
306 }