KSeExpr  4.0.4.0
ExprControlCollection.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 Disney Enterprises, Inc.
2 // SPDX-License-Identifier: LicenseRef-Apache-2.0
3 // SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 /*
6 * @file ExprControlCollection.cpp
7 * @brief Manages/creates a bunch of ExprControls by using expression text
8 * @author aselle
9 */
10 
11 #include <QPushButton>
12 #include <KSeExpr/Utils.h>
13 
14 #include "Debug.h"
15 #include "Editable.h"
16 #include "ExprAddDialog.h"
17 #include "ExprControlCollection.h"
18 
19 ExprControlCollection::ExprControlCollection(QWidget* parent, bool showAddButton)
20  : QWidget(parent), showAddButton(showAddButton) {
21  controlLayout = new QVBoxLayout();
22  controlLayout->setMargin(0);
23  controlLayout->setSpacing(0);
24  controlLayout->insertStretch(-1, 100);
25 
26  if (showAddButton) {
27  auto* button = new QPushButton(tr("Add new variable"));
28  button->setFocusPolicy(Qt::NoFocus);
29  auto *buttonLayout = new QHBoxLayout();
30  buttonLayout->insertStretch(-1, 100);
31  buttonLayout->addWidget(button, 0);
32  controlLayout->addLayout(buttonLayout);
33  connect(button, SIGNAL(clicked()), SLOT(addControlDialog()));
34  }
35  setLayout(controlLayout);
36 }
37 
39 
41  auto *dialog = new ExprAddDialog(count, this);
42  if (dialog->exec()) {
43  QString s;
44  switch (dialog->tabWidget->currentIndex()) {
45  case 0:
46  s = QString::fromLatin1("%1 = curve(%2,0,0,4,1,1,4);\n")
47  .arg(dialog->variableName->text())
48  .arg(dialog->curveLookup->text());
49  break;
50  case 1:
51  s = QString::fromLatin1("%1 = ccurve(%2,0,[0,0,0],4,1,[1,1,1],4);\n")
52  .arg(dialog->variableName->text())
53  .arg(dialog->colorCurveLookup->text());
54  break;
55  case 2:
56  s = QString::fromLatin1("%1 = %2; # %3,%4\n")
57  .arg(dialog->variableName->text())
58  .arg(dialog->intDefault->text())
59  .arg(dialog->intMin->text())
60  .arg(dialog->intMax->text());
61  break;
62  case 3:
63  s = QString::fromLatin1("%1 = %2; # %3, %4\n")
64  .arg(dialog->variableName->text())
65  .arg(dialog->floatDefault->text())
66  .arg(KSeExpr::Utils::atof(dialog->floatMin->text().toStdString()), 0, 'f', 3)
67  .arg(KSeExpr::Utils::atof(dialog->floatMax->text().toStdString()), 0, 'f', 3);
68  break;
69  case 4:
70  s = QString::fromLatin1("%1 = [%2,%3,%4]; # %5, %6\n")
71  .arg(dialog->variableName->text())
72  .arg(dialog->vectorDefault0->text())
73  .arg(dialog->vectorDefault1->text())
74  .arg(dialog->vectorDefault2->text())
75  .arg(KSeExpr::Utils::atof(dialog->vectorMin->text().toStdString()), 0, 'f', 3)
76  .arg(KSeExpr::Utils::atof(dialog->vectorMax->text().toStdString()), 0, 'f', 3);
77  break;
78  case 5:
79  s = QString::fromLatin1("%1 = [%2,%3,%4];\n")
80  .arg(dialog->variableName->text())
81  .arg(dialog->color.redF())
82  .arg(dialog->color.greenF())
83  .arg(dialog->color.blueF());
84  break;
85  case 6:
86  s = QString::fromLatin1("%1 = swatch(%2,%3);\n")
87  .arg(dialog->variableName->text())
88  .arg(dialog->swatchLookup->text())
89  .arg(QString::fromLatin1(dialog->initSwatch()));
90  break;
91  case 7:
92  s = QString::fromLatin1("%1 = \"%2\"; #%3 %4\n")
93  .arg(dialog->variableName->text())
94  .arg(dialog->stringDefaultWidget->text())
95  .arg(dialog->stringTypeWidget->currentText())
96  .arg(dialog->stringNameWidget->text());
97  break;
98  }
99  emit insertString(s);
100  }
101 }
102 
103 bool ExprControlCollection::rebuildControls(const QString& expressionText, std::vector<QString>& variables) {
104  // parse a new editable expression so we can check if we need to make new controls
105  auto *newEditable = new EditableExpression;
106  newEditable->setExpr(expressionText.toStdString());
107 
108  // check for new variables
109 
110  bool newVariables = true;
111  if (editableExpression && editableExpression->getVariables() == newEditable->getVariables()) newVariables = false;
112  if (newVariables) {
113  const std::vector<std::string>& vars = newEditable->getVariables();
114  variables.clear();
115  for (const auto & var : vars) {
116  variables.push_back(QString::fromLatin1("$%1").arg(QString::fromStdString(var)));
117  }
118  }
119 
120  if (newEditable->size() == 0 && !editableExpression) return false;
121 
122  if (editableExpression && editableExpression->controlsMatch(*newEditable)) {
123  // controls match so we only need to update positions (i.e. if the user typed and shifted some controls)
124  editableExpression->updateString(*newEditable);
125  delete newEditable;
126  } else {
127  // controls did not match
128 
129  // delete old controls
130  for (auto & _control : _controls) {
131  controlLayout->removeWidget(_control);
132  delete _control;
133  }
134  _linkedId = -1;
135  _controls.clear();
136 
137  // swap to new editable expression
138  delete editableExpression;
139  editableExpression = newEditable;
140 
141  // build new controls
142  for (size_t i = 0; i < editableExpression->size(); i++) {
143  Editable* editable = (*editableExpression)[i];
144  ExprControl* widget = nullptr;
145  // Create control "factory" (but since its only used here...)
146  if (auto* x = dynamic_cast<NumberEditable*>(editable))
147  widget = new NumberControl(i, x);
148  else if (auto *x = dynamic_cast<VectorEditable *>(editable))
149  widget = new VectorControl(i, x);
150  else if (auto *x = dynamic_cast<StringEditable *>(editable))
151  widget = new StringControl(i, x);
152  else if (auto *x = dynamic_cast<CurveEditable *>(editable))
153  widget = new CurveControl(i, x);
154  else if (auto *x = dynamic_cast<ColorCurveEditable *>(editable))
155  widget = new CCurveControl(i, x);
156  else if (auto *x = dynamic_cast<ColorSwatchEditable *>(editable))
157  widget = new ColorSwatchControl(i, x);
158  else {
159  dbgSeExpr << "KSeExpr editor logic error, cannot find a widget for the given editable";
160  }
161  if (widget) {
162  // successfully made widget
163  int insertPoint = controlLayout->count() - 1;
164  if (showAddButton) insertPoint--;
165  controlLayout->insertWidget(insertPoint, widget);
166  _controls.push_back(widget);
167  connect(widget, SIGNAL(controlChanged(int)), SLOT(singleControlChanged(int)));
168  connect(widget, SIGNAL(linkColorEdited(int, QColor)), SLOT(linkColorEdited(int, QColor)));
169  connect(widget, SIGNAL(linkColorLink(int)), SLOT(linkColorLink(int)));
170  } else {
171  dbgSeExpr << "Expr Editor Logic ERROR did not make widget";
172  }
173  }
174  }
175  return newVariables;
176 }
177 
179 
180 }
181 
183  _linkedId = id;
184  for (auto & _control : _controls) {
185  _control->linkDisconnect(_linkedId);
186  }
187 }
188 
189 void ExprControlCollection::linkColorEdited(int id, QColor color) {
190  if (id == _linkedId) emit linkColorOutput(color);
191 }
192 
194  // TODO: fix
195  if (_linkedId < 0 || _linkedId >= (int)_controls.size()) return;
196  _controls[_linkedId]->setColor(color);
197 }
198 
199 void ExprControlCollection::updateText(const int, QString& text) {
200  if (editableExpression) text = QString::fromStdString(editableExpression->getEditedExpr());
201 }
202 
#define dbgSeExpr
Definition: Debug.h:17
Control for editing a color ramp curve.
Definition: ExprControl.h:264
A control for editing color swatches.
Definition: ExprControl.h:282
Control for editing a normal curve ramp.
Definition: ExprControl.h:248
Factors a SeExpr into an editable expression with controls (i.e. value boxes, curve boxes)
size_t size() const
Return the count of editable parameters.
void setExpr(const std::string &expr)
Set's expressions and parses it into "control editable form".
std::string getEditedExpr() const
Return a reconstructed expression using all the editable's current values.
bool controlsMatch(const EditableExpression &other) const
Check if the other editable expression has editables that all match i.e. the controls are same.
void updateString(const EditableExpression &other)
Update the string refered to into the controls (this is only valid if controlsmatch)
const std::vector< std::string > & getVariables() const
Get list of commentsø
This class is the UI for adding widgets.
Definition: ExprAddDialog.h:23
void controlChanged(int id)
Notification that a specific control was changed.
void updateText(int id, QString &text)
Request new text, given taking into account control id's new values.
bool rebuildControls(const QString &expressionText, std::vector< QString > &variables)
Rebuild the controls given the new expressionText. Return any local variables found.
void insertString(const QString &controlString)
void singleControlChanged(int id)
Notification when by a control whenever it is edited.
void linkColorOutput(QColor color)
Gives information about when a link color was changed.
ExprControlCollection(QWidget *parent=nullptr, bool showAddButton=true)
void addControlDialog()
When a user clicks "Add new variable" button.
std::vector< ExprControl * > _controls
void linkColorLink(int id)
Notification by a control that a new color link is desired.
void linkColorEdited(int id, QColor color)
Notification by a control that a color is edited (when it is linked)
EditableExpression * editableExpression
void linkColorInput(QColor color)
Base class for all controls for Expressions.
Definition: ExprControl.h:25
Number slider for either float or int data.
Definition: ExprControl.h:171
A control for editing strings, filenames, and directories.
Definition: ExprControl.h:227
A vector or color control (named vector because it edits a KSeExpr::Vec3d literal)
Definition: ExprControl.h:196
double_t atof(const char *num)
Definition: Utils.cpp:51